Hello community,

here is the log from the commit of package kmime for openSUSE:Factory checked 
in at 2017-12-18 08:51:31
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kmime (Old)
 and      /work/SRC/openSUSE:Factory/.kmime.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kmime"

Mon Dec 18 08:51:31 2017 rev:28 rq:556216 version:17.12.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kmime/kmime.changes      2017-11-16 
14:26:43.489747410 +0100
+++ /work/SRC/openSUSE:Factory/.kmime.new/kmime.changes 2017-12-18 
08:51:34.877758029 +0100
@@ -1,0 +2,45 @@
+Sat Dec 09 14:59:07 CET 2017 - lbeltr...@kde.org
+
+- Update to 17.12.0
+  * New feature release
+  * For more details please see:
+  * https://www.kde.org/announcements/announce-applications-17.12.0.php
+- Changes since 17.11.90:
+  * None
+
+-------------------------------------------------------------------
+Sat Dec 02 10:12:37 CET 2017 - lbeltr...@kde.org
+
+- Update to 17.11.90
+  * New feature release
+  * For more details please see:
+  * https://www.kde.org/announcements/announce-applications-17.12-rc.php
+- Changes since 17.11.80:
+  * None
+
+-------------------------------------------------------------------
+Mon Nov 20 06:59:17 CET 2017 - lbeltr...@kde.org
+
+- Update to 17.11.80
+  * New feature release
+  * For more details please see:
+  * https://www.kde.org/announcements/announce-applications-17.12-beta.php
+- Changes since 17.08.3:
+  * Do not clear parameters when changing the mimetype of a Content-Type header
+  * Fix clazy warning
+  * Remove more memory allocations during header parsing
+  * Optimize parsing headers
+  * Port UUEncode parsing to QRegularExpression
+  * Preallocate space when unfolding headers
+  * Remove unused variables
+  * Use variable
+  * Add Q_FALLTHROUGH() to supress compiler warning
+  * Fix some warning found by cppcheck
+  * Add KMime::Ident::fromIdent
+  * Relax token parsing when parsing header parameter values
+  * Use nullptr
+  * Allow to run test without install it
+  * Remove qt check
+  * Introduce KMime::Content::headers()
+
+-------------------------------------------------------------------

Old:
----
  kmime-17.08.3.tar.xz

New:
----
  kmime-17.12.0.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kmime.spec ++++++
--- /var/tmp/diff_new_pack.ikvIXt/_old  2017-12-18 08:51:36.793665540 +0100
+++ /var/tmp/diff_new_pack.ikvIXt/_new  2017-12-18 08:51:36.797665347 +0100
@@ -20,7 +20,7 @@
 
 %define kf5_version 5.19.0
 Name:           kmime
-Version:        17.08.3
+Version:        17.12.0
 Release:        0
 %define kf5_version 5.26.0
 # Latest stable Applications (e.g. 17.08 in KA, but 17.11.80 in KUA)

++++++ kmime-17.08.3.tar.xz -> kmime-17.12.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/.reviewboardrc 
new/kmime-17.12.0/.reviewboardrc
--- old/kmime-17.08.3/.reviewboardrc    2017-10-13 07:14:04.000000000 +0200
+++ new/kmime-17.12.0/.reviewboardrc    1970-01-01 01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-REVIEWBOARD_URL = "https://git.reviewboard.kde.org";
-REPOSITORY = "git://anongit.kde.org/kmime"
-BRANCH = "master"
-TARGET_GROUPS = "kdepimlibs"
-TARGET_PEOPLE = "mlaurent"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/CMakeLists.txt 
new/kmime-17.12.0/CMakeLists.txt
--- old/kmime-17.08.3/CMakeLists.txt    2017-11-07 02:26:06.000000000 +0100
+++ new/kmime-17.12.0/CMakeLists.txt    2017-12-08 02:01:51.000000000 +0100
@@ -1,10 +1,11 @@
 cmake_minimum_required(VERSION 3.0)
-set(PIM_VERSION "5.6.3")
+set(PIM_VERSION "5.7.0")
 
 project(KMime VERSION ${PIM_VERSION})
 
 # ECM setup
-set(KF5_VERSION "5.35.0")
+set(KF5_VERSION "5.39.0")
+
 find_package(ECM ${KF5_VERSION} CONFIG REQUIRED)
 set(CMAKE_MODULE_PATH ${KMime_SOURCE_DIR}/cmake ${ECM_MODULE_PATH})
 
@@ -21,7 +22,7 @@
 
 
 set(KMIME_LIB_VERSION ${PIM_VERSION})
-set(QT_REQUIRED_VERSION "5.7.0")
+set(QT_REQUIRED_VERSION "5.8.0")
 find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Core)
 
 ecm_setup_version(PROJECT VARIABLE_PREFIX KMIME
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/autotests/CMakeLists.txt 
new/kmime-17.12.0/autotests/CMakeLists.txt
--- old/kmime-17.08.3/autotests/CMakeLists.txt  2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/autotests/CMakeLists.txt  2017-12-02 08:23:33.000000000 
+0100
@@ -1,6 +1,6 @@
 include(ECMMarkAsTest)
 
-set(QT_REQUIRED_VERSION "5.7.0")
+set(QT_REQUIRED_VERSION "5.8.0")
 find_package(Qt5Test ${QT_REQUIRED_VERSION} CONFIG REQUIRED)
 
 # Turn exceptions on
@@ -9,7 +9,7 @@
 macro(ADD_KMIME_TEST)
   foreach(_testName ${ARGN})
     add_executable(${_testName} ${_testName}.cpp)
-    add_test(kmime-${_testName} ${_testName})
+    add_test(NAME kmime-${_testName} COMMAND ${_testName})
     target_link_libraries(${_testName}
       KF5Mime
       Qt5::Test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/autotests/contenttest.cpp 
new/kmime-17.12.0/autotests/contenttest.cpp
--- old/kmime-17.08.3/autotests/contenttest.cpp 2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/autotests/contenttest.cpp 2017-12-02 08:23:33.000000000 
+0100
@@ -263,7 +263,7 @@
     msg->parse();
 
     // Test that multiple calls do not corrupt anything.
-    QByteArray encc = msg->encodedContent();
+    //QByteArray encc = msg->encodedContent();
     //qDebug() << "original data" << data;
     //qDebug() << "encodedContent" << encc;
     QCOMPARE(msg->encodedContent(), data);
@@ -486,7 +486,7 @@
     QCOMPARE(c->body(), part2);
 
     msg->assemble();
-    QByteArray encc = msg->encodedContent();
+    //QByteArray encc = msg->encodedContent();
     //qDebug() << "expected assembled content" << assembled;
     //qDebug() << "actual encoded content" << encc;
     QCOMPARE(msg->encodedContent(), assembled);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/autotests/headertest.cpp 
new/kmime-17.12.0/autotests/headertest.cpp
--- old/kmime-17.08.3/autotests/headertest.cpp  2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/autotests/headertest.cpp  2017-12-02 08:23:33.000000000 
+0100
@@ -1006,6 +1006,19 @@
     QVERIFY(!parseEncodedWord(start, end, result, language, usedCS));
 }
 
+void HeaderTest::testMissingQuotes()
+{
+    QByteArray str = "multipart/signed; boundary=nextPart22807781.u8zn2zYrSU; 
micalg=pgp-sha1; protocol=application/pgp-signature";
+
+    Headers::ContentType ct;
+    ct.from7BitString(str);
+    QCOMPARE(ct.mimeType(), QByteArray{ "multipart/signed" });
+    QCOMPARE(ct.boundary(), QByteArray{ "nextPart22807781.u8zn2zYrSU" });
+    QCOMPARE(ct.parameter(QStringLiteral("micalg")), 
QStringLiteral("pgp-sha1"));
+    QCOMPARE(ct.parameter(QStringLiteral("protocol")), 
QStringLiteral("application/pgp-signature"));
+
+}
+
 void HeaderTest::testBug271192()
 {
     QFETCH(QString, displayName);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/autotests/headertest.h 
new/kmime-17.12.0/autotests/headertest.h
--- old/kmime-17.08.3/autotests/headertest.h    2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/autotests/headertest.h    2017-12-02 08:23:33.000000000 
+0100
@@ -48,6 +48,7 @@
     void testInvalidQEncoding_data();
     void testBug271192();
     void testBug271192_data();
+    void testMissingQuotes();
 
     // makes sure we don't accidently have an abstract header class that's not
     // meant to be abstract
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/po/gl/libkmime5.po 
new/kmime-17.12.0/po/gl/libkmime5.po
--- old/kmime-17.08.3/po/gl/libkmime5.po        2017-11-07 02:26:05.000000000 
+0100
+++ new/kmime-17.12.0/po/gl/libkmime5.po        2017-12-08 02:01:50.000000000 
+0100
@@ -59,7 +59,7 @@
 "deleted unseen. This is no guarantee that the message will not be \"undeleted"
 "\" and nonetheless read later on."
 msgstr ""
-"A mensaxe enviada o ${date} a ${to} co asunto «${subject}» foi borrada sen "
+"A mensaxe enviada o ${date} a ${to} co asunto «${subject}» foi eliminada sen "
 "se chegar a ler. Isto non garante que a mensaxe non fose recuperada e lida "
 "con posterioridade."
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/po/zh_CN/libkmime5.po 
new/kmime-17.12.0/po/zh_CN/libkmime5.po
--- old/kmime-17.08.3/po/zh_CN/libkmime5.po     2017-11-07 02:26:06.000000000 
+0100
+++ new/kmime-17.12.0/po/zh_CN/libkmime5.po     2017-12-08 02:01:51.000000000 
+0100
@@ -7,7 +7,7 @@
 "Project-Id-Version: kdeorg\n"
 "Report-Msgid-Bugs-To: http://bugs.kde.org\n";
 "POT-Creation-Date: 2017-05-25 03:04+0200\n"
-"PO-Revision-Date: 2017-10-19 10:51-0400\n"
+"PO-Revision-Date: 2017-11-09 08:21-0500\n"
 "Last-Translator: guoyunhebrave <guoyunhebr...@gmail.com>\n"
 "Language-Team: Chinese Simplified\n"
 "Language: zh_CN\n"
@@ -18,7 +18,7 @@
 "X-Generator: crowdin.com\n"
 "X-Crowdin-Project: kdeorg\n"
 "X-Crowdin-Language: zh-CN\n"
-"X-Crowdin-File: /kf5-stable/messages/pim/libkmime5.pot\n"
+"X-Crowdin-File: /kf5-trunk/messages/pim/libkmime5.pot\n"
 
 #: kmime_dateformatter.cpp:268
 #, kde-format
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_codecs.cpp 
new/kmime-17.12.0/src/kmime_codecs.cpp
--- old/kmime-17.08.3/src/kmime_codecs.cpp      2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/src/kmime_codecs.cpp      2017-12-02 08:23:33.000000000 
+0100
@@ -283,7 +283,6 @@
         p++;
     }
     qDebug() << "Got pre-decoded:" << st;
-    QString result;
     const QTextCodec *charsetcodec = 
KCharsets::charsets()->codecForName(QString::fromLatin1(charset));
     if (!charsetcodec || forceCS) {
         charsetcodec = 
KCharsets::charsets()->codecForName(QString::fromLatin1(defaultCS));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_content.cpp 
new/kmime-17.12.0/src/kmime_content.cpp
--- old/kmime-17.08.3/src/kmime_content.cpp     2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/src/kmime_content.cpp     2017-12-02 08:23:33.000000000 
+0100
@@ -456,7 +456,9 @@
 
     auto ct = contentType(false);
     if (ct && ct->isMultipart() && !ct->isSubtype("related") && 
!ct->isSubtype("alternative")) {
-        Q_FOREACH (Content *child, contents()) {
+        const QVector<Content*> contentsList = contents();
+        result.reserve(contentsList.count());
+        Q_FOREACH (Content *child, contentsList) {
             if (isAttachment(child))
                 result.push_back(child);
             else
@@ -615,6 +617,11 @@
     }
 }
 
+QVector<Headers::Base*> Content::headers() const
+{
+    return d_ptr->headers;
+}
+
 Headers::Base *Content::headerByType(const char *type) const
 {
     Q_ASSERT(type  && *type);
@@ -1033,8 +1040,8 @@
     // Create a sub-Content for every part.
     Q_ASSERT(multipartContents.isEmpty());
     body.clear();
-    auto parts = mpp.parts();
-    foreach (const QByteArray &part, mpp.parts()) {
+    const auto parts = mpp.parts();
+    foreach (const QByteArray &part, parts) {
         Content *c = new Content(q);
         c->setContent(part);
         c->setFrozen(frozen);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_content.h 
new/kmime-17.12.0/src/kmime_content.h
--- old/kmime-17.08.3/src/kmime_content.h       2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/src/kmime_content.h       2017-12-02 08:23:33.000000000 
+0100
@@ -248,6 +248,12 @@
     void setHead(const QByteArray &head);
 
     /**
+     * Returns all headers.
+     * @since 5.7
+     */
+    QVector<Headers::Base*> headers() const;
+
+    /**
       Returns the first header of type @p type, if it exists.  Otherwise 
returns 0.
       Note that the returned header may be empty.
       @param type the header type to find
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_content_p.h 
new/kmime-17.12.0/src/kmime_content_p.h
--- old/kmime-17.08.3/src/kmime_content_p.h     2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/src/kmime_content_p.h     2017-12-02 08:23:33.000000000 
+0100
@@ -37,7 +37,6 @@
 {
 public:
     explicit ContentPrivate() :
-        parent(0),
         frozen(false)
     {
     }
@@ -65,7 +64,7 @@
     QByteArray frozenBody;
     QByteArray preamble;
     QByteArray epilogue;
-    Content *parent;
+    Content *parent = nullptr;
 
     QVector<Content*> multipartContents;
     MessagePtr bodyAsMessage;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_header_parsing.cpp 
new/kmime-17.12.0/src/kmime_header_parsing.cpp
--- old/kmime-17.08.3/src/kmime_header_parsing.cpp      2017-10-13 
07:14:04.000000000 +0200
+++ new/kmime-17.12.0/src/kmime_header_parsing.cpp      2017-12-02 
08:23:33.000000000 +0100
@@ -289,11 +289,11 @@
 // FIXME: Remove this and the other parseToken() method. add a new one where 
"result" is a
 //        QByteArray.
 bool parseToken(const char*&scursor, const char *const send,
-                QString &result, bool allow8Bit)
+                QString &result, ParseTokenFlags flags)
 {
     QPair<const char *, int> maybeResult;
 
-    if (parseToken(scursor, send, maybeResult, allow8Bit)) {
+    if (parseToken(scursor, send, maybeResult, flags)) {
         result = QString::fromLatin1(maybeResult.first, maybeResult.second);
         return true;
     }
@@ -302,7 +302,7 @@
 }
 
 bool parseToken(const char*&scursor, const char *const send,
-                QPair<const char *, int> &result, bool allow8Bit)
+                QPair<const char *, int> &result, ParseTokenFlags flags)
 {
     bool success = false;
     const char *start = scursor;
@@ -312,10 +312,12 @@
         if (ch > 0 && isTText(ch)) {
             // TText: OK
             success = true;
-        } else if (allow8Bit && ch < 0) {
+        } else if ((flags & ParseTokenAllow8Bit) && ch < 0) {
             // 8bit char: not OK, but be tolerant.
             KMIME_WARN_8BIT(ch);
             success = true;
+        } else if ((flags & ParseTokenRelaxedTText) && ch == '/') {
+            success = true;
         } else {
             // CTL or tspecial - marking the end of the atom:
             // re-set sursor to point to the offending
@@ -346,7 +348,6 @@
                               QString &result, bool isCRLF,
                               const char openChar, const char closeChar)
 {
-    char ch;
     // We are in a quoted-string or domain-literal or comment and the
     // cursor points to the first char after the openChar.
     // We will apply unfolding and quoted-pair removal.
@@ -356,7 +357,7 @@
     assert(*(scursor - 1) == openChar || *(scursor - 1) == closeChar);
 
     while (scursor != send) {
-        ch = *scursor++;
+        char ch = *scursor++;
 
         if (ch == closeChar || ch == openChar) {
             // end of quoted-string or another opening char:
@@ -451,9 +452,7 @@
                 scursor = oldscursor;
             }
             // fall through
-#if QT_VERSION >= QT_VERSION_CHECK(5,8,0)
-        Q_FALLTHROUGH();
-#endif
+            Q_FALLTHROUGH();
         }
         default:
             KMIME_WARN_IF_8BIT(ch);
@@ -637,10 +636,8 @@
                 // parse as atom:
                 scursor = oldscursor;
             }
-#if QT_VERSION >= QT_VERSION_CHECK(5,8,0)
-        Q_FALLTHROUGH();
-#endif
-        // fall though...
+            Q_FALLTHROUGH();
+            // fall though...
 
         default: //atom
             tmp.clear();
@@ -1233,7 +1230,7 @@
     //
     // FIXME: maybeAttribute should be a QByteArray
     QString maybeAttribute;
-    if (!parseToken(scursor, send, maybeAttribute, false /* no 8bit */)) {
+    if (!parseToken(scursor, send, maybeAttribute, ParseTokenNoFlag)) {
         return false;
     }
 
@@ -1281,7 +1278,7 @@
         }
     } else {
         // value is a token:
-        if (!parseToken(scursor, send, maybeValue.qpair, false /* no 8bit */)) 
{
+        if (!parseToken(scursor, send, maybeValue.qpair, 
ParseTokenRelaxedTText)) {
             scursor = oldscursor;
             result = qMakePair(maybeAttribute.toLower(), QStringOrQPair());
             return false; // this case needs further processing by upper 
layers!!
@@ -1714,7 +1711,7 @@
     }
 
     QPair<const char *, int> maybeTimeZone(nullptr, 0);
-    if (!parseToken(scursor, send, maybeTimeZone, false /*no 8bit*/)) {
+    if (!parseToken(scursor, send, maybeTimeZone, ParseTokenNoFlag)) {
         return false;
     }
     for (int i = 0 ; i < timeZonesLen ; ++i) {
@@ -2026,40 +2023,53 @@
     return true;
 }
 
-Headers::Base *extractFirstHeader(QByteArray &head)
+namespace {
+
+Headers::Base *extractHeader(const QByteArray &head, const int headerStart, 
int &endOfFieldBody)
 {
-    int endOfFieldBody = 0;
+    Headers::Base *header = {};
+
+    int startOfFieldBody = head.indexOf(':', headerStart);
+    if (startOfFieldBody < 0) {
+        return nullptr;
+    }
+
+    const char *rawType = head.constData() + headerStart;
+    const size_t rawTypeLen = startOfFieldBody - headerStart;
+
+    startOfFieldBody++; //skip the ':'
+    if (startOfFieldBody < head.size() - 1 &&  head[startOfFieldBody] == ' ') 
{ // skip the space after the ':', if there's any
+        startOfFieldBody++;
+    }
+
     bool folded = false;
-    Headers::Base *header = nullptr;
+    endOfFieldBody = findHeaderLineEnd(head, startOfFieldBody, &folded);
+
+    // We might get an invalid mail without a field name, don't crash on that.
+    if (rawTypeLen > 0) {
+        header = HeaderFactory::createHeader(rawType, rawTypeLen);
+    }
+    if (!header) {
+        //qWarning() << "Returning Generic header of type" << rawType;
+        header = new Headers::Generic(rawType, rawTypeLen);
+    }
+    if (folded) {
+        const auto unfoldedBody = unfoldHeader(head.constData() + 
startOfFieldBody, endOfFieldBody - startOfFieldBody);
+        header->from7BitString(unfoldedBody);
+    } else {
+        header->from7BitString(head.constData() + startOfFieldBody, 
endOfFieldBody - startOfFieldBody);
+    }
 
-    int startOfFieldBody = head.indexOf(':');
+    return header;
+}
 
-    if (startOfFieldBody > -1) {      //there is another header
-        // Split the original data
-        head[startOfFieldBody] = '\0';
-        // rawType references the actual data from 'head'
-        QByteArray rawType = QByteArray::fromRawData(head.constData(), 
startOfFieldBody);
-
-        startOfFieldBody++; //skip the ':'
-        if (head[startOfFieldBody] == ' ') {   // skip the space after the 
':', if there
-            startOfFieldBody++;
-        }
-        endOfFieldBody = findHeaderLineEnd(head, startOfFieldBody, &folded);
-        // rawFieldBody references actual data from 'heaed'
-        QByteArray rawFieldBody = QByteArray::fromRawData(head.constData() + 
startOfFieldBody, endOfFieldBody - startOfFieldBody);
-        if (folded) {
-            rawFieldBody = unfoldHeader(rawFieldBody);
-        }
-        // We might get an invalid mail without a field name, don't crash on 
that.
-        if (!rawType.isEmpty()) {
-            header = HeaderFactory::createHeader(rawType);
-        }
-        if (!header) {
-            //qWarning() << "Returning Generic header of type" << rawType;
-            header = new Headers::Generic(rawType.constData());
-        }
-        header->from7BitString(rawFieldBody);
+}
 
+Headers::Base *extractFirstHeader(QByteArray &head)
+{
+    int endOfFieldBody = 0;
+    auto header = extractHeader(head, 0, endOfFieldBody);
+    if (header) {
         head.remove(0, endOfFieldBody + 1);
     } else {
         head.clear();
@@ -2094,11 +2104,17 @@
 QVector<Headers::Base*> parseHeaders(const QByteArray &head)
 {
     QVector<Headers::Base*> ret;
-    Headers::Base *h;
 
-    QByteArray copy = head;
-    while ((h = extractFirstHeader(copy))) {
-        ret << h;
+    int cursor = 0;
+    while (cursor < head.size()) {
+        const int headerStart = cursor;
+        int endOfFieldBody;
+        if (auto header = extractHeader(head, headerStart, endOfFieldBody)) {
+            ret << header;
+            cursor = endOfFieldBody + 1;
+        } else {
+            break;
+        }
     }
 
     return ret;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_header_parsing.h 
new/kmime-17.12.0/src/kmime_header_parsing.h
--- old/kmime-17.08.3/src/kmime_header_parsing.h        2017-10-13 
07:14:04.000000000 +0200
+++ new/kmime-17.12.0/src/kmime_header_parsing.h        2017-12-02 
08:23:33.000000000 +0100
@@ -29,6 +29,7 @@
 #include <QString>
 #include <QPair>
 #include <QVector>
+#include <QFlags>
 
 #include <qdatetime.h>
 
@@ -97,12 +98,19 @@
 
 /** You may or may not have already started parsing into the
     token. This function will go on where you left off. */
+enum ParseTokenFlag {
+    ParseTokenNoFlag = 0,
+    ParseTokenAllow8Bit = 1,
+    ParseTokenRelaxedTText = 2
+};
+Q_DECLARE_FLAGS(ParseTokenFlags, ParseTokenFlag)
+
 KMIME_EXPORT bool parseToken(const char *&scursor, const char *const send,
-                             QString &result, bool allow8Bit = false);
+                             QString &result, ParseTokenFlags flags = 
ParseTokenNoFlag);
 
 KMIME_EXPORT bool parseToken(const char *&scursor, const char *const send,
                              QPair<const char *, int> &result,
-                             bool allow8Bit = false);
+                             ParseTokenFlags flags = ParseTokenNoFlag);
 
 /** @p scursor must be positioned after the opening openChar. */
 KMIME_EXPORT bool parseGenericQuotedString(const char *&scursor,
@@ -275,5 +283,7 @@
 
 } // namespace KMime
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(KMime::HeaderParsing::ParseTokenFlags)
+
 #endif // __KMIME_HEADER_PARSING_H__
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_headerfactory.cpp 
new/kmime-17.12.0/src/kmime_headerfactory.cpp
--- old/kmime-17.08.3/src/kmime_headerfactory.cpp       2017-10-13 
07:14:04.000000000 +0200
+++ new/kmime-17.12.0/src/kmime_headerfactory.cpp       2017-12-02 
08:23:33.000000000 +0100
@@ -38,13 +38,13 @@
 using namespace KMime::Headers;
 
 #define mk_header(hdr) \
-    if (qstricmp(type.constData(), hdr ::staticType()) == 0) \
+    if (qstrnicmp(type, hdr ::staticType(), typeLen) == 0) \
         return new hdr
 
-Headers::Base *HeaderFactory::createHeader(const QByteArray &type)
+Headers::Base *HeaderFactory::createHeader(const char *type, size_t typeLen)
 {
-    Q_ASSERT(!type.isEmpty());
-    switch (type.at(0)) {
+    Q_ASSERT(type && *type);
+    switch (*type) {
         case 'b':
         case 'B':
             mk_header(Bcc);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_headerfactory_p.h 
new/kmime-17.12.0/src/kmime_headerfactory_p.h
--- old/kmime-17.08.3/src/kmime_headerfactory_p.h       2017-10-13 
07:14:04.000000000 +0200
+++ new/kmime-17.12.0/src/kmime_headerfactory_p.h       2017-12-02 
08:23:33.000000000 +0100
@@ -35,7 +35,7 @@
 
 #include "kmime_export.h"
 
-class QByteArray;
+#include <QByteArray>
 
 namespace KMime
 {
@@ -47,7 +47,12 @@
 
 namespace HeaderFactory
 {
-    Headers::Base *createHeader(const QByteArray &type);
+    Headers::Base *createHeader(const char *type, size_t typeLen);
+    inline Headers::Base *createHeader(const QByteArray &type)
+    {
+        return createHeader(type.constData(), type.size());
+    }
+
 }
 
 } // namespace KMime
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_headers.cpp 
new/kmime-17.12.0/src/kmime_headers.cpp
--- old/kmime-17.08.3/src/kmime_headers.cpp     2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/src/kmime_headers.cpp     2017-12-02 08:23:33.000000000 
+0100
@@ -124,6 +124,11 @@
     d_ptr = nullptr;
 }
 
+void Base::from7BitString(const char *s, size_t len)
+{
+    from7BitString(QByteArray::fromRawData(s, len));
+}
+
 QByteArray Base::rfc2047Charset() const
 {
     if (d_ptr->encCS.isEmpty()) {
@@ -238,14 +243,19 @@
     d_ptr = nullptr;
 }
 
-void Structured::from7BitString(const QByteArray &s)
+
+void Structured::from7BitString(const char *s, size_t len)
 {
     Q_D(Structured);
     if (d->encCS.isEmpty()) {
         d->encCS = Content::defaultCharset();
     }
-    const char *cursor = s.constData();
-    parse(cursor, cursor + s.length());
+    parse(s, s + len);
+}
+
+void Structured::from7BitString(const QByteArray &s)
+{
+    from7BitString(s.constData(), s.length());
 }
 
 QString Structured::asUnicodeString() const
@@ -640,7 +650,7 @@
     }
 
     QPair<const char *, int> maybeToken;
-    if (!parseToken(scursor, send, maybeToken, false /* no 8bit chars */)) {
+    if (!parseToken(scursor, send, maybeToken, ParseTokenNoFlag)) {
         return false;
     }
     d->token = QByteArray(maybeToken.first, maybeToken.second);
@@ -996,6 +1006,13 @@
     return rv;
 }
 
+void Ident::fromIdent(const Ident* ident)
+{
+    d_func()->encCS = ident->d_func()->encCS;
+    d_func()->msgIdList = ident->d_func()->msgIdList;
+    d_func()->cachedIdentifier = ident->d_func()->cachedIdentifier;
+}
+
 void Ident::appendIdentifier(const QByteArray &id)
 {
     Q_D(Ident);
@@ -1160,9 +1177,9 @@
 {
 }
 
-Generic::Generic(const char *t) : Generics::Unstructured(new GenericPrivate)
+Generic::Generic(const char *t, int len) : Generics::Unstructured(new 
GenericPrivate)
 {
-    setType(t);
+    setType(t, len);
 }
 
 Generic::~Generic()
@@ -1190,15 +1207,16 @@
     return d_func()->type;
 }
 
-void Generic::setType(const char *type)
+void Generic::setType(const char *type, int len)
 {
     Q_D(Generic);
     if (d->type) {
         delete[] d->type;
     }
     if (type) {
-        d->type = new char[strlen(type) + 1];
-        strcpy(d->type, type);
+        const int l = (len < 0 ? strlen(type) : len) + 1;
+        d->type = new char[l];
+        qstrncpy(d->type, type, l);
     } else {
         d->type = nullptr;
     }
@@ -1662,7 +1680,6 @@
 void ContentType::setMimeType(const QByteArray & mimeType) {
     Q_D(ContentType);
     d->mimeType = mimeType;
-    Parametrized::clear();
 
     if (isMultipart()) {
         d->category = CCcontainer;
@@ -1794,7 +1811,6 @@
                         bool isCRLF) {
     Q_D(ContentType);
     // content-type: type "/" subtype *(";" parameter)
-
     clear();
     eatCFWS(scursor, send, isCRLF);
     if (scursor == send) {
@@ -1803,7 +1819,7 @@
 
     // type
     QPair<const char *, int> maybeMimeType;
-    if (!parseToken(scursor, send, maybeMimeType, false /* no 8Bit */)) {
+    if (!parseToken(scursor, send, maybeMimeType, ParseTokenNoFlag)) {
         return false;
     }
 
@@ -1819,7 +1835,7 @@
     }
 
     QPair<const char *, int> maybeSubType;
-    if (!parseToken(scursor, send, maybeSubType, false /* no 8bit */)) {
+    if (!parseToken(scursor, send, maybeSubType, ParseTokenNoFlag)) {
         return false;
     }
 
@@ -2080,7 +2096,7 @@
     }
 
     QPair<const char *, int> maybeToken;
-    if (!parseToken(scursor, send, maybeToken, false /* no 8Bit */)) {
+    if (!parseToken(scursor, send, maybeToken, ParseTokenNoFlag)) {
         return false;
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_headers.h 
new/kmime-17.12.0/src/kmime_headers.h
--- old/kmime-17.08.3/src/kmime_headers.h       2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/src/kmime_headers.h       2017-12-02 08:23:33.000000000 
+0100
@@ -137,6 +137,7 @@
       Parses the given string. Take care of RFC2047-encoded strings.
       @param s The encoded header data.
     */
+    virtual void from7BitString(const char *s, size_t len);
     virtual void from7BitString(const QByteArray &s) = 0;
 
     /**
@@ -246,6 +247,7 @@
     Unstructured();
     ~Unstructured();
 
+    using Base::from7BitString;
     void from7BitString(const QByteArray &s) override;
     QByteArray as7BitString(bool withHeaderType = true) const override;
 
@@ -298,6 +300,7 @@
     Structured();
     ~Structured();
 
+    void from7BitString(const char *s, size_t len) override;
     void from7BitString(const QByteArray &s) override;
     QString asUnicodeString() const override;
     void fromUnicodeString(const QString &s, const QByteArray &b) override;
@@ -515,6 +518,11 @@
     bool isEmpty() const override;
 
     /**
+      Initialize this identifier Copy the data from
+     */
+    void fromIdent(const Ident* ident);
+
+    /**
       Returns the list of identifiers contained in this header.
       Note:
       - Identifiers are not enclosed in angle-brackets.
@@ -1013,7 +1021,7 @@
     QByteArray subType() const;
 
     /**
-      Sets the mimetype and clears already existing parameters.
+      Sets the mimetype.
       @param mimeType The new mimetype.
     */
     void setMimeType(const QByteArray &mimeType);
@@ -1202,7 +1210,7 @@
 {
 public:
     Generic();
-    Generic(const char *t);
+    Generic(const char *t, int len = -1);
     ~Generic();
 
     void clear() override;
@@ -1211,7 +1219,7 @@
 
     const char *type() const override;
 
-    void setType(const char *type);
+    void setType(const char *type, int len = -1);
 
 private:
     Q_DECLARE_PRIVATE(Generic)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_headers_p.h 
new/kmime-17.12.0/src/kmime_headers_p.h
--- old/kmime-17.08.3/src/kmime_headers_p.h     2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/src/kmime_headers_p.h     2017-12-02 08:23:33.000000000 
+0100
@@ -158,15 +158,14 @@
 {
 public:
     GenericPrivate() :
-        Generics::UnstructuredPrivate(),
-        type(0)
+        Generics::UnstructuredPrivate()
     {}
     ~GenericPrivate()
     {
         delete[] type;
     }
 
-    char *type;
+    char *type = nullptr;
 };
 
 class ControlPrivate : public Generics::StructuredPrivate
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_parsers.cpp 
new/kmime-17.12.0/src/kmime_parsers.cpp
--- old/kmime-17.08.3/src/kmime_parsers.cpp     2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/src/kmime_parsers.cpp     2017-12-02 08:23:33.000000000 
+0100
@@ -22,7 +22,7 @@
 */
 #include "kmime_parsers.h"
 
-#include <QRegExp>
+#include <QRegularExpression>
 #include <QByteArray>
 
 using namespace KMime::Parser;
@@ -124,10 +124,9 @@
 QByteArray NonMimeParser::guessMimeType(const QByteArray &fileName)
 {
     QByteArray tmp, mimeType;
-    int pos;
 
     if (!fileName.isEmpty()) {
-        pos = fileName.lastIndexOf('.');
+        int pos = fileName.lastIndexOf('.');
         if (pos++ != -1) {
             tmp = fileName.mid(pos, fileName.length() - pos).toUpper();
             if (tmp == "JPG" || tmp == "JPEG") {
@@ -177,13 +176,16 @@
     int currentPos = 0;
     bool success = true, firstIteration = true;
 
+    const auto srcStr = QString::fromLatin1(m_src);
+    const QRegularExpression beginRegex(QStringLiteral("begin 
[0-9][0-9][0-9]"));
+    const QRegularExpression subjectRegex(QStringLiteral("[0-9]+/[0-9]+"));
+
     while (success) {
         int beginPos = currentPos, uuStart = currentPos, endPos = 0, lineCount 
= 0, MCount = 0, pos = 0, len = 0;
         bool containsBegin = false, containsEnd = false;
         QByteArray tmp, fileName;
 
-        if ((beginPos = 
QString::fromLatin1(m_src).indexOf(QRegExp(QStringLiteral("begin 
[0-9][0-9][0-9]")),
-                        currentPos)) > -1 &&
+        if ((beginPos = srcStr.indexOf(beginRegex, currentPos)) > -1 &&
                 (beginPos == 0 || m_src.at(beginPos - 1) == '\n')) {
             containsBegin = true;
             uuStart = m_src.indexOf('\n', beginPos);
@@ -227,9 +229,9 @@
 
             if ((!containsBegin || !containsEnd) && !m_subject.isNull()) {
                 // message may be split up => parse subject
-                QRegExp rx(QStringLiteral("[0-9]+/[0-9]+"));
-                pos = rx.indexIn(QLatin1String(m_subject), 0);
-                len = rx.matchedLength();
+                const auto match = 
subjectRegex.match(QLatin1String(m_subject));
+                pos = match.capturedStart(0);
+                len = match.capturedLength(0);
                 if (pos != -1) {
                     tmp = m_subject.mid(pos, len);
                     pos = tmp.indexOf('/');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_util.cpp 
new/kmime-17.12.0/src/kmime_util.cpp
--- old/kmime-17.08.3/src/kmime_util.cpp        2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/src/kmime_util.cpp        2017-12-02 08:23:33.000000000 
+0100
@@ -98,8 +98,10 @@
     switch (cf.type()) {
     case CharFreq::SevenBitText:
         allowed << Headers::CE7Bit;
+        Q_FALLTHROUGH();
     case CharFreq::EightBitText:
         allowed << Headers::CE8Bit;
+        Q_FALLTHROUGH();
     case CharFreq::SevenBitData:
         if (cf.printableRatio() > 5.0 / 6.0) {
             // let n the length of data and p the number of printable chars.
@@ -154,7 +156,7 @@
     static const char chars[] = 
"0123456789abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
     time_t now;
     char p[11];
-    int pos, ran;
+    int ran;
     unsigned int timeval;
 
     p[10] = '\0';
@@ -163,7 +165,7 @@
     timeval = (now / ran) + QCoreApplication::applicationPid();
 
     for (int i = 0; i < 10; i++) {
-        pos = (int)(61.0 * rand() / (RAND_MAX + 1.0));
+        int pos = (int)(61.0 * rand() / (RAND_MAX + 1.0));
         //qDebug() << pos;
         p[i] = chars[pos];
     }
@@ -181,33 +183,37 @@
     return "nextPart" + uniqueString();
 }
 
-QByteArray unfoldHeader(const QByteArray &header)
+QByteArray unfoldHeader(const char *header, size_t headerSize)
 {
     QByteArray result;
-    if (header.isEmpty()) {
+    if (headerSize == 0) {
         return result;
     }
 
-    int pos = 0, foldBegin = 0, foldMid = 0, foldEnd = 0;
-    while ((foldMid = header.indexOf('\n', pos)) >= 0) {
+    // unfolding skips characters so result will be at worst headerSize long
+    result.reserve(headerSize);
+
+    const char *end = header + headerSize;
+    const char *pos = header, *foldBegin = nullptr, *foldMid = nullptr, 
*foldEnd = nullptr;
+    while ((foldMid = strchr(pos, '\n')) && foldMid < end) {
         foldBegin = foldEnd = foldMid;
         // find the first space before the line-break
-        while (foldBegin > 0) {
-            if (!QChar::fromLatin1(header[foldBegin - 1]).isSpace()) {
+        while (foldBegin) {
+            if (!QChar::isSpace(*(foldBegin - 1))) {
                 break;
             }
             --foldBegin;
         }
         // find the first non-space after the line-break
-        while (foldEnd <= header.length() - 1) {
-            if (QChar::fromLatin1(header[foldEnd]).isSpace()) {
+        while (foldEnd <= end - 1) {
+            if (QChar::isSpace(*foldEnd)) {
                 ++foldEnd;
-            } else if (foldEnd > 0 && header[foldEnd - 1] == '\n' &&
-                       header[foldEnd] == '=' && foldEnd + 2 < header.length() 
&&
-                       ((header[foldEnd + 1] == '0' &&
-                         header[foldEnd + 2] == '9') ||
-                        (header[foldEnd + 1] == '2' &&
-                         header[foldEnd + 2] == '0'))) {
+            } else if (foldEnd && *(foldEnd - 1) == '\n' &&
+                       *foldEnd == '=' && foldEnd + 2 < (header + headerSize - 
1) &&
+                       ((*(foldEnd + 1) == '0' &&
+                         *(foldEnd + 2) == '9') ||
+                        (*(foldEnd + 1) == '2' &&
+                         *(foldEnd + 2) == '0'))) {
                 // bug #86302: malformed header continuation starting with 
=09/=20
                 foldEnd += 3;
             } else {
@@ -215,19 +221,23 @@
             }
         }
 
-        result.append(header.constData() + pos, foldBegin - pos);
-        if (foldEnd < header.length() - 1) {
+        result.append(pos, foldBegin - pos);
+        if (foldEnd < end - 1) {
             result += ' ';
         }
         pos = foldEnd;
     }
-    const int len = header.length();
-    if (len > pos) {
-        result.append(header.constData() + pos, len - pos);
+    if (end > pos) {
+        result.append(pos, end - pos);
     }
     return result;
 }
 
+QByteArray unfoldHeader(const QByteArray &header)
+{
+    return unfoldHeader(header.constData(), header.size());
+}
+
 int findHeaderLineEnd(const QByteArray &src, int &dataBegin, bool *folded)
 {
     int end = dataBegin;
@@ -353,8 +363,7 @@
             result = src.mid(begin, end - begin);
         } else {
             if (end > begin) {
-                QByteArray hdrValue = src.mid(begin, end - begin);
-                result = unfoldHeader(hdrValue);
+                result = unfoldHeader(src.constData() + begin, end - begin);
             }
         }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/src/kmime_util.h 
new/kmime-17.12.0/src/kmime_util.h
--- old/kmime-17.08.3/src/kmime_util.h  2017-10-13 07:14:04.000000000 +0200
+++ new/kmime-17.12.0/src/kmime_util.h  2017-12-02 08:23:33.000000000 +0100
@@ -89,7 +89,9 @@
   Unfolds the given header if necessary.
   @param header The header to unfold.
 */
+
 KMIME_EXPORT extern QByteArray unfoldHeader(const QByteArray &header);
+KMIME_EXPORT extern QByteArray unfoldHeader(const char *header, size_t 
headerSize);
 
 /**
   Tries to extract the header with name @p name from the string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/tests/CMakeLists.txt 
new/kmime-17.12.0/tests/CMakeLists.txt
--- old/kmime-17.08.3/tests/CMakeLists.txt      2017-10-13 07:14:04.000000000 
+0200
+++ new/kmime-17.12.0/tests/CMakeLists.txt      2017-12-02 08:23:33.000000000 
+0100
@@ -11,7 +11,7 @@
 ########### next target ###############
 
   add_executable(test_mdn test_mdn.cpp)
-  add_test(test_mdn test_mdn)
+  add_test(NAME test_mdn COMMAND test_mdn)
   target_link_libraries(test_mdn KF5Mime)
 
 endif()
@@ -19,11 +19,11 @@
 ########### next target ###############
 
 add_executable(test_charfreq test_charfreq.cpp)
-add_test(test_charfreq test_charfreq)
+add_test(NAME test_charfreq COMMAND test_charfreq)
 target_link_libraries(test_charfreq KF5Mime)
 
 ########### next target ###############
 
 add_executable(test_dates test_dates.cpp)
-add_test(test_dates test_dates)
+add_test(NAME test_dates COMMAND test_dates)
 target_link_libraries(test_dates KF5Mime)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kmime-17.08.3/tests/test_kmime_header_parsing.cpp 
new/kmime-17.12.0/tests/test_kmime_header_parsing.cpp
--- old/kmime-17.08.3/tests/test_kmime_header_parsing.cpp       2017-10-13 
07:14:04.000000000 +0200
+++ new/kmime-17.12.0/tests/test_kmime_header_parsing.cpp       2017-12-02 
08:23:33.000000000 +0100
@@ -184,7 +184,7 @@
     case 2: {
         // token
         QString result = QStringLiteral("with 8bit: ");
-        bool ok = parseToken(iit, iend, result, true);
+        bool ok = parseToken(iit, iend, result, ParseTokenAllow8Bit);
 
         cout << (ok ? "OK" : "BAD") << endl
              << "result:\n" << result
@@ -192,10 +192,10 @@
 
         result = QStringLiteral("without 8bit: ");
 #ifdef COMPILE_FAIL
-        ok = parseToken(indata.begin(), iend, result, false);
+        ok = parseToken(indata.begin(), iend, result, ParseTokenNoFlag);
 #else
         iit = indata.begin();
-        ok = parseToken(iit, iend, result, false);
+        ok = parseToken(iit, iend, result, ParseTokenNoFlag);
 #endif
 
         cout << (ok ? "OK" : "BAD") << endl


Reply via email to