aboutsummaryrefslogtreecommitdiffstats
path: root/src/headerField.cpp
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2005-03-12 16:58:59 +0000
committerVincent Richard <[email protected]>2005-03-12 16:58:59 +0000
commit836c80565f76f5d7b1470ea3341ae939a9846262 (patch)
treeda24a4f57b572cadeb514a52c7a99958c13cbb0c /src/headerField.cpp
parentChanged first argument of copy_vector() to 'const', to avoid mistakes. (diff)
downloadvmime-836c80565f76f5d7b1470ea3341ae939a9846262.tar.gz
vmime-836c80565f76f5d7b1470ea3341ae939a9846262.zip
Moved header field parsing to 'headerField::parseNext()'.
Diffstat (limited to 'src/headerField.cpp')
-rw-r--r--src/headerField.cpp162
1 files changed, 160 insertions, 2 deletions
diff --git a/src/headerField.cpp b/src/headerField.cpp
index 627c63eb..7c8562da 100644
--- a/src/headerField.cpp
+++ b/src/headerField.cpp
@@ -20,6 +20,8 @@
#include "vmime/headerField.hpp"
#include "vmime/headerFieldFactory.hpp"
+#include "vmime/parserHelpers.hpp"
+
namespace vmime
{
@@ -67,12 +69,168 @@ headerField& headerField::operator=(const headerField& other)
}
+headerField* headerField::parseNext(const string& buffer, const string::size_type position,
+ const string::size_type end, string::size_type* newPosition)
+{
+ string::size_type pos = position;
+
+ while (pos < end)
+ {
+ char_t c = buffer[pos];
+
+ // Check for end of headers (empty line): although RFC-822 recommends
+ // to use CRLF for header/body separator (see 4.1 SYNTAX), here, we
+ // also check for LF for compatibility with broken implementations...
+ if (c == '\n')
+ {
+ if (newPosition)
+ *newPosition = pos + 1; // LF: illegal
+
+ return (NULL);
+ }
+ else if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n')
+ {
+ if (newPosition)
+ *newPosition = pos + 2; // CR+LF
+
+ return (NULL);
+ }
+
+ // This line may be a field description
+ if (!parserHelpers::isspace(c))
+ {
+ const string::size_type nameStart = pos; // remember the start position of the line
+
+ while (pos < end && (buffer[pos] != ':' && !parserHelpers::isspace(buffer[pos])))
+ ++pos;
+
+ const string::size_type nameEnd = pos;
+
+ while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t'))
+ ++pos;
+
+ if (buffer[pos] != ':')
+ {
+ // Humm...does not seem to be a valid header line.
+ // Skip this error and advance to the next line
+ pos = nameStart;
+
+ while (pos < end && buffer[pos] != '\n')
+ ++pos;
+
+ if (pos < end && buffer[pos] == '\n')
+ ++pos;
+ }
+ else
+ {
+ // Extract the field name
+ const string name(buffer.begin() + nameStart,
+ buffer.begin() + nameEnd);
+
+ // Skip ':' character
+ ++pos;
+
+ // Skip spaces between ':' and the field contents
+ while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t'))
+ ++pos;
+
+ // Extract the field value
+ string contents;
+
+ while (pos < end)
+ {
+ c = buffer[pos];
+
+ // Check for end of contents
+ if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n')
+ {
+ pos += 2;
+ break;
+ }
+ else if (c == '\n')
+ {
+ ++pos;
+ break;
+ }
+
+ const string::size_type ctsStart = pos;
+ string::size_type ctsEnd = pos;
+
+ while (pos < end)
+ {
+ c = buffer[pos];
+
+ // Check for end of line
+ if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n')
+ {
+ ctsEnd = pos;
+ pos += 2;
+ break;
+ }
+ else if (c == '\n')
+ {
+ ctsEnd = pos;
+ ++pos;
+ break;
+ }
+
+ ++pos;
+ }
+
+ if (ctsEnd != ctsStart)
+ {
+ // Append this line to contents
+ contents.append(buffer.begin() + ctsStart,
+ buffer.begin() + ctsEnd);
+ }
+
+ // 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...
+ }
+ else
+ {
+ // End of this field
+ break;
+ }
+ }
+
+ // Return a new field
+ headerField* field = headerFieldFactory::getInstance()->create(name);
+
+ field->parse(contents); // TODO: fix incorrect parsed bounds...
+ field->setParsedBounds(nameStart, pos);
+
+ if (newPosition)
+ *newPosition = pos;
+
+ return (field);
+ }
+ }
+ else
+ {
+ // Skip this error and advance to the next line
+ while (pos < end && buffer[pos] != '\n')
+ ++pos;
+
+ if (buffer[pos] == '\n')
+ ++pos;
+ }
+ }
+
+ if (newPosition)
+ *newPosition = pos;
+
+ return (NULL);
+}
+
+
void headerField::parse(const string& buffer, const string::size_type position, const string::size_type end,
string::size_type* newPosition)
{
getValue().parse(buffer, position, end, newPosition);
-
- setParsedBounds(position, end);
}