[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [trojita] /: Crypto: gracefully handle unavailable data
From: Thomas_Lübking <thomas.luebking () gmail ! com>
Date: 2016-06-20 18:53:56
Message-ID: E1bF4Ka-0008Q5-FY () code ! kde ! org
[Download RAW message or body]
Git commit a80757e6e55bbdfd1617462636ff851a47c3c801 by Thomas Lübking, on behalf of \
Jan Kundrát. Committed on 18/06/2016 at 08:05.
Pushed by gerrit into branch 'master'.
Crypto: gracefully handle unavailable data
The crypto code should be transparent for network failures, that is, it
should act as if the signature/encryption was not available for some
reason, and should just use the underlying data in whatever form it's
currently available.
Change-Id: I61816d306b17fbcbfc63d04188cd563426606ffb
M +14 -0 src/Cryptography/GpgMe++.cpp
M +94 -0 tests/Cryptography/test_Cryptography_PGP.cpp
M +2 -0 tests/Cryptography/test_Cryptography_PGP.h
http://commits.kde.org/trojita/a80757e6e55bbdfd1617462636ff851a47c3c801
diff --git a/src/Cryptography/GpgMe++.cpp b/src/Cryptography/GpgMe++.cpp
index 414dcb6..4285799 100644
--- a/src/Cryptography/GpgMe++.cpp
+++ b/src/Cryptography/GpgMe++.cpp
@@ -630,6 +630,13 @@ void GpgMeSigned::handleDataChanged(const QModelIndex &topLeft, \
const QModelInde Q_ASSERT(m_plaintextPart.isValid());
Q_ASSERT(m_plaintextMimePart.isValid());
Q_ASSERT(m_signaturePart.isValid());
+ if (m_plaintextPart.data(RoleIsUnavailable).toBool() || \
m_plaintextMimePart.data(RoleIsUnavailable).toBool() + || \
m_signaturePart.data(RoleIsUnavailable).toBool() || \
m_enclosingMessage.data(RoleIsUnavailable).toBool()) { + \
forwardFailure(tr("Data Unavailable"), + tr("Some data are not \
available, perhaps due to an offline network connection"), + \
QStringLiteral("state-offline")); + return;
+ }
if (!m_plaintextPart.data(RoleIsFetched).toBool() || \
!m_plaintextMimePart.data(RoleIsFetched).toBool() ||
!m_signaturePart.data(RoleIsFetched).toBool() || \
!m_enclosingMessage.data(RoleMessageEnvelope).isValid()) { return;
@@ -766,6 +773,13 @@ void GpgMeEncrypted::handleDataChanged(const QModelIndex \
&topLeft, const QModelI }
Q_ASSERT(m_versionPart.isValid());
Q_ASSERT(m_encPart.isValid());
+ if (m_versionPart.data(RoleIsUnavailable).toBool() || \
m_encPart.data(RoleIsUnavailable).toBool() + || \
m_enclosingMessage.data(RoleIsUnavailable).toBool()) { + \
forwardFailure(tr("Data Unavailable"), + tr("Cannot decrypt. \
Some data are not available, perhaps due to an offline network connection."), + \
QStringLiteral("state-offline")); + return;
+ }
if (!m_versionPart.data(RoleIsFetched).toBool() || \
!m_encPart.data(RoleIsFetched).toBool() || \
!m_enclosingMessage.data(RoleMessageEnvelope).isValid()) { return;
diff --git a/tests/Cryptography/test_Cryptography_PGP.cpp \
b/tests/Cryptography/test_Cryptography_PGP.cpp index 99694c5..c2b4eb7 100644
--- a/tests/Cryptography/test_Cryptography_PGP.cpp
+++ b/tests/Cryptography/test_Cryptography_PGP.cpp
@@ -478,4 +478,98 @@ void CryptographyPGPTest::testMalformed_data()
}
+/** @short Check operation when some data are not available */
+void CryptographyPGPTest::testOffline()
+{
+ QFETCH(QByteArray, bodystructure);
+ QFETCH(QByteArray, fetchRegex);
+
+ model->setProperty("trojita-imap-delayed-fetch-part", 0);
+ helperSyncBNoMessages();
+ cServer("* 1 EXISTS\r\n");
+ cClient(t.mk("UID FETCH 1:* (FLAGS)\r\n"));
+ cServer("* 1 FETCH (UID 333 FLAGS ())\r\n" + t.last("OK fetched\r\n"));
+ QCOMPARE(model->rowCount(msgListB), 1);
+ QModelIndex msg = msgListB.child(0, 0);
+ QVERIFY(msg.isValid());
+ QCOMPARE(model->rowCount(msg), 0);
+ cClient(t.mk("UID FETCH 333 (" FETCH_METADATA_ITEMS ")\r\n"));
+ cServer(helperCreateTrivialEnvelope(1, 333, QStringLiteral("subj"), \
QStringLiteral("foo@example.org"), bodystructure) + + t.last("OK \
fetched\r\n")); + cEmpty();
+ QVERIFY(model->rowCount(msg) > 0);
+ Cryptography::MessageModel msgModel(0, msg);
+#ifdef TROJITA_HAVE_CRYPTO_MESSAGES
+# ifdef TROJITA_HAVE_GPGMEPP
+ msgModel.registerPartHandler(std::make_shared<Cryptography::GpgMeReplacer>());
+# endif
+#endif
+ QModelIndex mappedMsg = msgModel.index(0,0);
+ QVERIFY(mappedMsg.isValid());
+ QVERIFY(msgModel.rowCount(mappedMsg) > 0);
+
+ QModelIndex data = mappedMsg.child(0, 0);
+ QVERIFY(data.isValid());
+#ifdef TROJITA_HAVE_CRYPTO_MESSAGES
+ QCOMPARE(msgModel.rowCount(mappedMsg), 1);
+ QCOMPARE(msgModel.rowCount(data), 0);
+ QCOMPARE(data.data(Imap::Mailbox::RoleIsFetched).toBool(), false);
+
+ cClientRegExp(t.mk(fetchRegex));
+ auto fetchResp = t.last("NO offline\r\n");
+ LibMailboxSync::setModelNetworkPolicy(model, Imap::Mailbox::NETWORK_OFFLINE);
+ cClient(t.mk("LOGOUT\r\n"));
+ cServer(fetchResp + t.last("OK logout\r\n"));
+
+ QSignalSpy qcaErrorSpy(&msgModel, SIGNAL(error(const QModelIndex \
&,QString,QString))); +
+ int i = 0;
+ while (data.isValid() && \
data.data(Imap::Mailbox::RolePartCryptoNotFinishedYet).toBool() && \
qcaErrorSpy.empty() && i++ < 1000) { + QTest::qWait(10);
+ }
+ // allow for event processing, so that the model can retrieve the results
+ QCoreApplication::processEvents();
+
+ QCOMPARE(data.data(Imap::Mailbox::RolePartCryptoNotFinishedYet), \
QVariant(false)); + QCOMPARE(data.data(Imap::Mailbox::RolePartCryptoTLDR), \
QVariant(QStringLiteral("Data Unavailable"))); + QCOMPARE(msgModel.rowCount(data), \
2); +
+ if (!qcaErrorSpy.isEmpty()) {
+ qDebug() << "Unexpected failure in crypto";
+ for (int i = 0; i < qcaErrorSpy.size(); ++i) {
+ qDebug() << qcaErrorSpy[i][1].toString();
+ qDebug() << qcaErrorSpy[i][2].toString();
+ }
+ }
+
+ // We're offline, we cannot call cEmpty(), that would assert-crash due to no \
active parsers + //cEmpty();
+
+ QVERIFY(errorSpy->empty());
+#else
+ QCOMPARE(msgModel.rowCount(data), 2);
+ QCOMPARE(data.data(Imap::Mailbox::RoleIsFetched).toBool(), true);
+ cEmpty();
+
+ QSKIP("Some tests were skipped because this build doesn't have GpgME++ \
support"); +#endif
+}
+
+void CryptographyPGPTest::testOffline_data()
+{
+ QTest::addColumn<QByteArray>("bodystructure");
+ QTest::addColumn<QByteArray>("fetchRegex");
+
+ QTest::newRow("signed")
+ << QByteArray("(\"text\" \"plain\" (\"charset\" \"us-ascii\") NIL NIL \
\"7bit\" 423 14 NIL NIL NIL NIL)" + "(\"application\" \"pgp-signature\" \
NIL NIL NIL \"7bit\" 851 NIL NIL NIL NIL)" + " \"signed\" (\"boundary\" \
\"=-=-=\" \"micalg\" \"pgp-sha256\" \"protocol\" \"application/pgp-signature\")" + \
" NIL NIL NIL") + << QByteArray("UID FETCH 333 \
\\((BODY\\.PEEK\\[(2|1|1\\.MIME)\\] ?){3}\\)"); +
+ QTest::newRow("encrypted")
+ << bsEncrypted
+ << QByteArray("UID FETCH 333 \\((BODY\\.PEEK\\[(1|2)\\] ?){2}\\)");
+}
+
QTEST_GUILESS_MAIN(CryptographyPGPTest)
diff --git a/tests/Cryptography/test_Cryptography_PGP.h \
b/tests/Cryptography/test_Cryptography_PGP.h index 9cf3946..5eff0d5 100644
--- a/tests/Cryptography/test_Cryptography_PGP.h
+++ b/tests/Cryptography/test_Cryptography_PGP.h
@@ -40,6 +40,8 @@ private Q_SLOTS:
void testVerification_data();
void testMalformed();
void testMalformed_data();
+ void testOffline();
+ void testOffline_data();
};
Q_DECLARE_METATYPE(CryptographyPGPTest::pathList)
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic