diff options
| author | Vincent Richard <[email protected]> | 2014-06-01 18:46:17 +0000 |
|---|---|---|
| committer | Vincent Richard <[email protected]> | 2014-06-01 18:46:17 +0000 |
| commit | 30ea54f269efa673a1eb5bc07e71715b67607dbc (patch) | |
| tree | 456f9152fa4a341891c083313af952ae5a1250bc /src | |
| parent | Fixed segfault in POP3 test. (diff) | |
| download | vmime-30ea54f269efa673a1eb5bc07e71715b67607dbc.tar.gz vmime-30ea54f269efa673a1eb5bc07e71715b67607dbc.zip | |
Fixed parsing of empty lines in header field value.
Diffstat (limited to 'src')
| -rw-r--r-- | src/vmime/headerField.cpp | 75 | ||||
| -rw-r--r-- | src/vmime/parserHelpers.hpp | 39 |
2 files changed, 48 insertions, 66 deletions
diff --git a/src/vmime/headerField.cpp b/src/vmime/headerField.cpp index f4c6187e..b88a5cd2 100644 --- a/src/vmime/headerField.cpp +++ b/src/vmime/headerField.cpp @@ -144,75 +144,18 @@ shared_ptr <headerField> headerField::parseNext const size_t contentsStart = pos; size_t contentsEnd = 0; - // Extract the field value - while (pos < end) - { - c = buffer[pos]; + bool firstLine = true; - // Check for folded line - if (c == '\r' && pos + 2 < end && buffer[pos + 1] == '\n' && - (buffer[pos + 2] == ' ' || buffer[pos + 2] == '\t')) - { - pos += 3; - } - // Check for end of contents - if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') - { - contentsEnd = pos; - pos += 2; - break; - } - else if (c == '\n') - { - contentsEnd = pos; - ++pos; + // Parse field value, taking care of line folding (value on multiple lines) + for (size_t eol = 0 ; parserHelpers::findEOL(buffer, pos, end, &eol) ; pos = eol) + { + // If the line does not start with a folding indicator (SPACE or TAB), + // and this is not the first line, then stop parsing lines + if (!firstLine && !(buffer[pos] == ' ' || buffer[pos] == '\t')) break; - } - - while (pos < end) - { - c = buffer[pos]; - - // Check for end of line - if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') - { - contentsEnd = pos; - pos += 2; - break; - } - else if (c == '\n') - { - contentsEnd = pos; - ++pos; - break; - } - ++pos; - } - - // Handle the case of folded lines - if (buffer[pos] == ' ' || buffer[pos] == '\t') - { - // This is a folding white-space: we keep it as is and - // we continue with contents parsing... - - // If the line contains only space characters, we assume it is - // the end of the headers. This is not strictly standard-compliant - // but, hey, we can't fail when parsing some malformed mails... - while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) - ++pos; - - if ((pos < end && buffer[pos] == '\n') || - (pos + 1 < end && buffer[pos] == '\r' && buffer[pos + 1] == '\n')) - { - break; - } - } - else - { - // End of this field - break; - } + contentsEnd = eol; + firstLine = false; } if (pos == end && contentsEnd == 0) diff --git a/src/vmime/parserHelpers.hpp b/src/vmime/parserHelpers.hpp index ce3f422a..430487b4 100644 --- a/src/vmime/parserHelpers.hpp +++ b/src/vmime/parserHelpers.hpp @@ -87,6 +87,45 @@ public: const unsigned int x = static_cast <unsigned int>(c); return (x >= 0x20 && x <= 0x7E); } + + + /** Finds the next EOL sequence in the specified buffer. + * An EOL sequence may be a CR+LF sequence, or a LF sequence. + * + * @param buffer search buffer + * @param currentPos start searching from this position + * @param end stop searching at this position + * @param eol will receive the position after the EOL sequence + * @return true if an EOL sequence has been found, or false if + * no EOL sequence was found before the end of the buffer + */ + static bool findEOL(const string& buffer, const size_t currentPos, const size_t end, size_t* eol) + { + size_t pos = currentPos; + + if (pos == end) + return false; + + while (pos < end) + { + if (buffer[pos] == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') + { + *eol = pos + 2; + return true; + } + else if (buffer[pos] == '\n') + { + *eol = pos + 1; + return true; + } + + ++pos; + } + + *eol = end; + + return true; + } }; |
