Page MenuHomePhorge

D196.1774888390.diff
No OneTemporary

Authored By
Unknown
Size
13 KB
Referenced Files
None
Subscribers
None

D196.1774888390.diff

Index: framework/domain/mimetreeparser/interface.h
===================================================================
--- /dev/null
+++ framework/domain/mimetreeparser/interface.h
@@ -0,0 +1,327 @@
+/*
+ Copyright (c) 2016 Sandro Knauß <knauss@kolabsystems.com>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#pragma once
+
+#include <QUrl>
+#include <QMimeType>
+
+class Part;
+class EncryptionPart;
+class SignaturePart;
+
+class MimePart;
+class MimePartPrivate;
+
+class ContentPart;
+class ContentPartPrivate;
+
+class EncryptionErrorPart;
+class EncryptionErrorPartPrivate;
+
+class AttachmentPart;
+class AttachmentPartPrivate;
+
+class EncapsulatedPart;
+class EncapsulatedPart;
+
+class CertPart;
+class CertPart;
+
+class Key;
+class Signature;
+class Encryption;
+
+class Parser;
+class ParserPrivate;
+
+class Parser
+{
+public:
+ Parser(const QByteArray &mimeMessage);
+
+ std::shared_ptr<Part> getPart(QUrl url);
+
+ QVector<std::shared_ptr<AttachmentPart>> collect<AttachmentPart>() const;
+ QVector<std::shared_ptr<ContentPart>> collect<ContentPart>() const;
+ QVector<std::shared_ptr<T>> collect<T>(Part start, std::function<bool(const Part &)> select, std::function<bool(const std::shared_ptr<T> &)> filter) const;
+
+private:
+ std::unique_ptr<ParserPrivate> d;
+};
+
+class Part
+{
+public:
+ virtual QByteArray type() const = 0;
+
+ bool hasSubParts() const;
+ QList<Part> subParts() const;
+ Part partent() const;
+};
+
+/*
+ * A MessagePart that is based on a KMime::Content
+ */
+class MimePart : public Part
+{
+public:
+ /**
+ * Various possible values for the "Content-Disposition" header.
+ */
+ enum Disposition {
+ Invalid, ///< Default, invalid value
+ Inline, ///< inline
+ Attachment, ///< attachment
+ Parallel ///< parallel (invalid, do not use)
+ };
+
+ // interessting header parts of a KMime::Content
+ QByteArray content() const;
+ QMimeType mimetype() const;
+ Disposition dispossition() const
+ QUrl label() const;
+ QByteArray cid() const;
+ QByteArray charset() const;
+
+ // we wanna overrwrite the charset of the content, because some clients set the charset wrong
+ void setCharset(QByteArray charset);
+
+ // Unique identifier to ecactly this KMime::Content
+ QByteArray link() const;
+
+
+ QByteArray type() const Q_DECL_OVERRIDE;
+private:
+ std::unique_ptr<MimePartPrivate> d;
+};
+
+/*
+ * The main ContentPart
+ * is MimePart a good parent class?
+ * do we wanna need parts of the header of the connected KMime::Contents
+ * usecases:
+ * -
+ * for htmlonly it is representating only one MimePart (ok)
+ * for plaintext only also only one MimePart (ok)
+ * for alternative, we are represating three messageparts
+ * - "headers" do we return?, we can use setType to make it possible to select and than return these headers
+ */
+class ContentPart : public MimePart
+{
+public:
+ enum Types {
+ PlainText,
+ Html
+ };
+ Q_DECLARE_FLAGS(Types, Type)
+
+ QByteArray content(Content::Type ct) const;
+
+ // convert content with charset
+ QString content(Content::Type ct) const;
+
+ Content::Types availableContent() const;
+ QVector<Signature> signature() const;
+ QVector<Encryption> encryption() const;
+
+ QByteArray type() const Q_DECL_OVERRIDE;
+
+private:
+ std::unique_ptr<ContentPartPrivate> d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(ContentPart::Type)
+
+class AttachmentPart : public MimePart
+{
+public:
+ QByteArray type() const Q_DECL_OVERRIDE;
+
+private:
+ std::unique_ptr<AttachmentPartPrivate> d;
+};
+
+/*
+ * Faild to decrypt part
+ * thigs liks this can happen:
+ * decryption in progress
+ * have not tried at all to decrypt
+ * wrong passphrase
+ * no private key
+ * cryptobackend is not configured correctly (no gpg available)
+ * -> S/Mime and PGP have different meaning in their errors
+ *
+ * Open Questions:
+ * - How to make the string translateable for multiple clients, so that multiple clients can show same error messages,
+ * that helps users to understand what is going on ?
+ * - Does openpgp have translations already?
+ */
+class EncryptionErrorPart : public Part
+{
+public:
+ Error errorId() const;
+
+ CryptoBackend cryptoBackend();
+
+ QByteArray type() const Q_DECL_OVERRIDE;
+
+private:
+ std::unique_ptr<EncryptionErrorPartPrivate> d;
+};
+
+/*
+ * we want to request complete headers like:
+ * from/to...
+ */
+
+class EncapsulatedPart :: public AttachmentPart
+{
+public:
+ QByteArray type() const Q_DECL_OVERRIDE;
+
+ QByteArray header<Type>();
+private:
+ std::unique_ptr<EncryptionErrorPartPrivate> d;
+};
+
+/*
+ * importing a cert GpgMe::ImportResult
+ * checking a cert (if it is a valid cert)
+ */
+
+class CertPart :: public AttachmentPart
+{
+public:
+ QByteArray type() const Q_DECL_OVERRIDE;
+
+ bool checkCert() const;
+ Status importCert() const;
+
+private:
+ std::unique_ptr<CertPartPrivate> d;
+};
+
+/*
+the ggme error class
+
+// class GPGMEPP_EXPORT ErrorImportResult
+{
+public:
+ Error() : mErr(0), mMessage() {}
+ explicit Error(unsigned int e) : mErr(e), mMessage() {}
+
+ const char *source() const;
+ const char *asString() const;
+
+ int code() const;
+ int sourceID() const;
+
+ bool isCanceled() const;
+
+ unsigned int encodedError() const
+ {
+ return mErr;
+ }
+ int toErrno() const;
+
+ static bool hasSystemError();
+ static Error fromSystemError(unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT);
+ static void setSystemError(gpg_err_code_t err);
+ static void setErrno(int err);
+ static Error fromErrno(int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT);
+ static Error fromCode(unsigned int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT);
+
+ GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(mErr &&!isCanceled())
+private:
+ unsigned int mErr;
+ mutable std::string mMessage;
+};
+*/
+
+/*
+ * a used smime/PGP key
+ * in the end we also need things like:
+ bool isRevokation() const;
+ bool isInvalid() const;
+ bool isExpired() const;
+
+ -> so we end up wrapping GpgME::Key
+ */
+class Key
+{
+ QString keyid() const;
+ QString name() const;
+ QString email() const;
+ QString comment() const;
+ QVector<QString> emails() const;
+ KeyTrust keyTrust() const;
+ CryptoBackend cryptoBackend() const;
+
+ std::vector<Key> subkeys();
+ Key parentkey() const;
+};
+
+class Signature
+{
+ Key key() const;
+ QDateTime creationDateTime() const;
+ QDateTime expirationTime() const;
+ bool neverExpires() const;
+
+ bool inProgress(); //if the verfication is inProgress
+
+ enum Validity {
+ Unknown, Undefined, Never, Marginal, Full, Ultimate
+ };
+ Validity validity() const;
+
+ // to determine if we need this in our usecase (email)
+ // GpgME::VerificationResult
+ enum Summary {
+ None = 0x000,
+ Valid = 0x001,
+ Green = 0x002,
+ Red = 0x004,
+ KeyRevoked = 0x008,
+ KeyExpired = 0x010,
+ SigExpired = 0x020,
+ KeyMissing = 0x040,
+ CrlMissing = 0x080,
+ CrlTooOld = 0x100,
+ BadPolicy = 0x200,
+ SysError = 0x400
+ };
+ Summary summary() const;
+
+ const char *policyURL() const;
+ GpgME::Notation notation(unsigned int index) const;
+ std::vector<GpgME::Notation> notations() const;
+
+};
+
+/*
+ * Normally the Keys for encryption are subkeys
+ * for clients the parentkeys are "more interessting", because they store the name, email etc.
+ * but a client may also wants show to what subkey the mail is really encrypted, an if this subkey isRevoked or something else
+ */
+class Encryption
+{
+ std::vector<Key> recipients() const;
+};
\ No newline at end of file
Index: framework/domain/mimetreeparser/test.cpp
===================================================================
--- /dev/null
+++ framework/domain/mimetreeparser/test.cpp
@@ -0,0 +1,146 @@
+Usecases:
+
+# plaintext msg + attachment
+* ContentPart => cp1
+* AttachmentPart => ap1
+
+(cp1) == collect<ContentPart>(select=NoEncapsulatedMessages)
+(ap1) == collect<AttachmentParts>(select=NoEncapsulatedMessages)
+
+(PlainText) == cp1.availableContent()
+
+# html msg + related attachment + normal attachment
+* ContentPart => cp1
+* AttachmentPart(mimetype="*/related", cid="12345678") => ap1
+* AttachmentPart => ap2
+
+(cp1) == collect<ContentPart>(select=NoEncapsulatedMessages)
+(ap1, ap2) == collect<AttachmentParts>(select=NoEncapsulatedMessages)
+(ap2) == collect<AttachmentParts>(select=NoEncapsulatedMessages, filter=filterelated)
+
+ap1 == getPart("cid:12345678")
+
+(Html) == cp1.availableContent()
+
+# alternative msg + attachment
+* ContentPart(html="HTML", plaintext="Text") => cp1
+* AttachmentPart => ap1
+
+(cp1) == collect<ContentPart>(select=NoEncapsulatedMessages)
+(ap1) == collect<AttachmentParts>(select=NoEncapsulatedMessages)
+
+(Html, PlainText) == cp1.availableContent()
+"HTML" == cp1.content(Html)
+"text" == cp1.content(Plaintext)
+
+# alternative msg with GPGInline
+* ContentPart(html="HTML", plaintext="Text cypted<foo>") => cp1
+ * TextPart(text="Text")
+ * TextPart(text=foo, encryption=(enc1)
+
+(Html, PlainText) == cp1.availableContent()
+
+TODO: but how to get plaintext/html content?
+
+# encrypted msg (not encrypted/error) with unencrypted attachment
+* EncryptionErrorPart => cp1
+* AttachmentPart => ap1
+
+(cp1) == collect<ContentPart>(select=NoEncapsulatedMessages)
+(ap1) == collect<AttachmentParts>(select=NoEncapsulatedMessages)
+
+#encrypted msg (decrypted with attachment) + unencrypted attachment
+* encrytion=(rec1,rec2) => enc1
+ * ContentPart(encrytion = (enc1,)) => cp1
+ * AttachmentPart(encryption = (enc1,)) => ap1
+* AttachmentPart => ap2
+
+(cp1) == collect<ContentPart>(select=NoEncapsulatedMessages)
+(ap1, ap2) == collect<AttachmentParts>(select=NoEncapsulatedMessages)
+
+#INLINE GPG encrypted msg + attachment
+* ContentPart => cp1
+ * TextPart
+ * TextPart(encrytion = (enc1(rec1,rec2),))
+ * TextPart(signed = (sig1,))
+ * TextPart
+* AttachmentPart => ap1
+
+(cp1) == collect<ContentPart>(select=NoEncapsulatedMessages)
+(ap1) == collect<AttachmentParts>(select=NoEncapsulatedMessages)
+
+#forwared encrypted msg + attachments
+* ContentPart => cp1
+* EncapsulatedPart => ep1
+ * Encrytion=(rec1,rec2) => enc1
+ * Signature => sig1
+ * ContentPart(encrytion = (enc1,), signature = (sig1,)) => cp2
+ * TextPart(encrytion = (enc1,), signature = (sig1,))
+ * TextPart(encrytion = (enc1, enc2(rec3,rec4),), signature = (sig1,))
+ * AttachmentPart(encrytion = (enc1,), signature = (sig1,)) => ap1
+* AttachmentPart => ap2
+
+(cp1) = collect<ContentPart>(select=NoEncapsulatedMessages)
+(ap2) = collect<AttachmentParts>(select=NoEncapsulatedMessages)
+
+(cp2) = collect<ContentPart>(ep1, select=NoEncapsulatedMessages)
+(ap1) = collect<AttachmentParts>(ep1, select=NoEncapsulatedMessages)
+
+(cp1, cp2) == collect<ContentPart>()
+(ap1, ap2) == collect<AttachmentParts>()
+
+
+# plaintext msg + attachment + cert
+* ContentPart => cp1
+* AttachmentPart => ap1
+* CertPart => cep1
+
+(cp1) == collect<ContentPart>(select=NoEncapsulatedMessages)
+(ap1, cep1) == collect<AttachmentPart>(select=NoEncapsulatedMessages)
+(ap1) == collect<AttachmentPart>(select=NoEncapsulatedMessages, filter=filterSubAttachmentParts)
+
+(cep1) == collect<CertPart>(select=NoEncapsulatedMessages)
+
+
+collect function:
+
+bool noEncapsulatedMessages(Part part)
+{
+ if (is<EncapsulatedPart>(part)) {
+ return false;
+ }
+ return true;
+}
+
+bool filterRelated(T part)
+{
+ if (part.mimetype == related && !part.cid.isEmpty()) {
+ return false; //filter out related parts
+ }
+ return true;
+}
+
+bool filterSubAttachmentParts(AttachmentPart part)
+{
+ if (isSubPart<AttachmentPart>(part)) {
+ return false; // filter out CertPart f.ex.
+ }
+ return true;
+}
+
+List<T> collect<T>(Part start, std::function<bool(const Part &)> select, std::function<bool(const std::shared_ptr<T> &)> filter) {
+ List<T> col;
+ if (!select(start)) {
+ return col;
+ }
+
+ if(isOrSubTypeIs<T>(start) && filter(start.staticCast<T>)){
+ col.append(p);
+ }
+ foreach(childs as child) {
+ if (select(child)) {
+ col.expand(collect(child,select,filter);
+ }
+ }
+ return col;
+}
\ No newline at end of file

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 30, 4:33 PM (3 d, 1 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18775719
Default Alt Text
D196.1774888390.diff (13 KB)

Event Timeline