aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2014-06-01 18:46:17 +0000
committerVincent Richard <[email protected]>2014-06-01 18:46:17 +0000
commit30ea54f269efa673a1eb5bc07e71715b67607dbc (patch)
tree456f9152fa4a341891c083313af952ae5a1250bc /src
parentFixed segfault in POP3 test. (diff)
downloadvmime-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.cpp75
-rw-r--r--src/vmime/parserHelpers.hpp39
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;
+ }
};