diff --git a/src/kmime_header_parsing.cpp b/src/kmime_header_parsing.cpp --- a/src/kmime_header_parsing.cpp +++ b/src/kmime_header_parsing.cpp @@ -2023,39 +2023,52 @@ return true; } -Headers::Base *extractFirstHeader(QByteArray &head) +namespace { + +Headers::Base *extractHeader(const QByteArray &head, const int headerStart, int &endOfFieldBody) { + Headers::Base *header = {}; + + int startOfFieldBody = head.indexOf(':', headerStart); + if (startOfFieldBody < 0) { + return nullptr; + } + + const QByteArray rawType = QByteArray::fromRawData(head.constData() + headerStart, 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); + // rawFieldBody references actual data from 'head' + QByteArray rawFieldBody = QByteArray::fromRawData(head.constData() + startOfFieldBody, endOfFieldBody - startOfFieldBody); + if (folded) { + rawFieldBody = unfoldHeader(rawFieldBody); + } - int startOfFieldBody = head.indexOf(':'); + // 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(), rawType.size()); + } + header->from7BitString(rawFieldBody); - 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); + return header; +} - startOfFieldBody++; //skip the ':' - if (head[startOfFieldBody] == ' ') { // skip the space after the ':', if there - startOfFieldBody++; - } - int 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(); @@ -2090,11 +2103,17 @@ QVector parseHeaders(const QByteArray &head) { QVector 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 --git a/src/kmime_headerfactory.cpp b/src/kmime_headerfactory.cpp --- a/src/kmime_headerfactory.cpp +++ b/src/kmime_headerfactory.cpp @@ -38,7 +38,7 @@ using namespace KMime::Headers; #define mk_header(hdr) \ - if (qstricmp(type.constData(), hdr ::staticType()) == 0) \ + if (qstrnicmp(type.constData(), hdr ::staticType(), type.size()) == 0) \ return new hdr Headers::Base *HeaderFactory::createHeader(const QByteArray &type) diff --git a/src/kmime_headers.h b/src/kmime_headers.h --- a/src/kmime_headers.h +++ b/src/kmime_headers.h @@ -1207,16 +1207,16 @@ { public: Generic(); - Generic(const char *t); + Generic(const char *t, int len = -1); ~Generic(); void clear() override; bool isEmpty() const override; const char *type() const override; - void setType(const char *type); + void setType(const char *type, int len = -1); private: Q_DECLARE_PRIVATE(Generic) diff --git a/src/kmime_headers.cpp b/src/kmime_headers.cpp --- a/src/kmime_headers.cpp +++ b/src/kmime_headers.cpp @@ -1167,9 +1167,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() @@ -1197,15 +1197,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; }