Moved source to src
This commit is contained in:
132
src/HTTPServer/EnvelopeParser.cpp
Normal file
132
src/HTTPServer/EnvelopeParser.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
|
||||
// EnvelopeParser.cpp
|
||||
|
||||
// Implements the cEnvelopeParser class representing a parser for RFC-822 envelope headers, used both in HTTP and in MIME
|
||||
|
||||
#include "Globals.h"
|
||||
#include "EnvelopeParser.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cEnvelopeParser::cEnvelopeParser(cCallbacks & a_Callbacks) :
|
||||
m_Callbacks(a_Callbacks),
|
||||
m_IsInHeaders(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cEnvelopeParser::Parse(const char * a_Data, int a_Size)
|
||||
{
|
||||
if (!m_IsInHeaders)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start searching 1 char from the end of the already received data, if available:
|
||||
size_t SearchStart = m_IncomingData.size();
|
||||
SearchStart = (SearchStart > 1) ? SearchStart - 1 : 0;
|
||||
|
||||
m_IncomingData.append(a_Data, a_Size);
|
||||
|
||||
size_t idxCRLF = m_IncomingData.find("\r\n", SearchStart);
|
||||
if (idxCRLF == AString::npos)
|
||||
{
|
||||
// Not a complete line yet, all input consumed:
|
||||
return a_Size;
|
||||
}
|
||||
|
||||
// Parse as many lines as found:
|
||||
size_t Last = 0;
|
||||
do
|
||||
{
|
||||
if (idxCRLF == Last)
|
||||
{
|
||||
// This was the last line of the data. Finish whatever value has been cached and return:
|
||||
NotifyLast();
|
||||
m_IsInHeaders = false;
|
||||
return a_Size - (m_IncomingData.size() - idxCRLF) + 2;
|
||||
}
|
||||
if (!ParseLine(m_IncomingData.c_str() + Last, idxCRLF - Last))
|
||||
{
|
||||
// An error has occurred
|
||||
m_IsInHeaders = false;
|
||||
return -1;
|
||||
}
|
||||
Last = idxCRLF + 2;
|
||||
idxCRLF = m_IncomingData.find("\r\n", idxCRLF + 2);
|
||||
} while (idxCRLF != AString::npos);
|
||||
m_IncomingData.erase(0, Last);
|
||||
|
||||
// Parsed all lines and still expecting more
|
||||
return a_Size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEnvelopeParser::Reset(void)
|
||||
{
|
||||
m_IsInHeaders = true;
|
||||
m_IncomingData.clear();
|
||||
m_LastKey.clear();
|
||||
m_LastValue.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEnvelopeParser::NotifyLast(void)
|
||||
{
|
||||
if (!m_LastKey.empty())
|
||||
{
|
||||
m_Callbacks.OnHeaderLine(m_LastKey, m_LastValue);
|
||||
m_LastKey.clear();
|
||||
}
|
||||
m_LastValue.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cEnvelopeParser::ParseLine(const char * a_Data, size_t a_Size)
|
||||
{
|
||||
ASSERT(a_Size > 0);
|
||||
if (a_Data[0] <= ' ')
|
||||
{
|
||||
// This line is a continuation for the previous line
|
||||
if (m_LastKey.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Append, including the whitespace in a_Data[0]
|
||||
m_LastValue.append(a_Data, a_Size);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is a line with a new key:
|
||||
NotifyLast();
|
||||
for (size_t i = 0; i < a_Size; i++)
|
||||
{
|
||||
if (a_Data[i] == ':')
|
||||
{
|
||||
m_LastKey.assign(a_Data, i);
|
||||
m_LastValue.assign(a_Data + i + 2, a_Size - i - 2);
|
||||
return true;
|
||||
}
|
||||
} // for i - a_Data[]
|
||||
|
||||
// No colon was found, key-less header??
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user