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