Moved header field parsing to 'headerField::parseNext()'.
This commit is contained in:
parent
d18af13418
commit
836c80565f
148
src/header.cpp
148
src/header.cpp
@ -64,152 +64,10 @@ void header::parse(const string& buffer, const string::size_type position,
|
|||||||
|
|
||||||
while (pos < end)
|
while (pos < end)
|
||||||
{
|
{
|
||||||
char_t c = buffer[pos];
|
headerField* field = headerField::parseNext(buffer, pos, end, &pos);
|
||||||
|
if (field == NULL) break;
|
||||||
|
|
||||||
// Check for end of headers (empty line): although RFC-822 recommends
|
m_fields.push_back(field);
|
||||||
// to use CRLF for header/body separator (see 4.1 SYNTAX), here, we
|
|
||||||
// also check for LF just in case...
|
|
||||||
if (c == '\n')
|
|
||||||
{
|
|
||||||
++pos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n')
|
|
||||||
{
|
|
||||||
pos += 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 && parserHelpers::isspace(buffer[pos]))
|
|
||||||
++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 (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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a new field to list
|
|
||||||
m_fields.push_back(headerFieldFactory::getInstance()->
|
|
||||||
create(name, contents));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Skip this error and advance to the next line
|
|
||||||
while (pos < end && buffer[pos] != '\n')
|
|
||||||
++pos;
|
|
||||||
|
|
||||||
if (buffer[pos] == '\n')
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have found the header/body separator, skip it
|
|
||||||
if (pos < end)
|
|
||||||
{
|
|
||||||
if (buffer[pos] == '\n')
|
|
||||||
{
|
|
||||||
// This is a LF (illegal but...)
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
else if (buffer[pos] == '\r' && pos + 1 < end)
|
|
||||||
{
|
|
||||||
// This is a CRLF
|
|
||||||
pos += 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setParsedBounds(position, pos);
|
setParsedBounds(position, pos);
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include "vmime/headerField.hpp"
|
#include "vmime/headerField.hpp"
|
||||||
#include "vmime/headerFieldFactory.hpp"
|
#include "vmime/headerFieldFactory.hpp"
|
||||||
|
|
||||||
|
#include "vmime/parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace vmime
|
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,
|
void headerField::parse(const string& buffer, const string::size_type position, const string::size_type end,
|
||||||
string::size_type* newPosition)
|
string::size_type* newPosition)
|
||||||
{
|
{
|
||||||
getValue().parse(buffer, position, end, newPosition);
|
getValue().parse(buffer, position, end, newPosition);
|
||||||
|
|
||||||
setParsedBounds(position, end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,6 +97,8 @@ public:
|
|||||||
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
|
||||||
|
static headerField* parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
string m_name;
|
string m_name;
|
||||||
|
Loading…
Reference in New Issue
Block a user