최종완료보고 버전
This commit is contained in:
@@ -0,0 +1,551 @@
|
||||
|
||||
#include "stringex.h"
|
||||
#include "hsparser.h"
|
||||
#include <time.h>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
|
||||
static char * SliceHeader(char * pszBuffer)
|
||||
{
|
||||
for (unsigned int i = 0; pszBuffer[i]; i++)
|
||||
{
|
||||
if (pszBuffer[i] == '\r' && pszBuffer[i + 1] == '\n')
|
||||
{
|
||||
pszBuffer[i] = '\0';
|
||||
return (pszBuffer + i + 2);
|
||||
}
|
||||
else if (pszBuffer[i] == '\n')
|
||||
{
|
||||
pszBuffer[i] = '\0';
|
||||
return (pszBuffer + i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char * SliceToken(char * pszLine, char cDelimiter)
|
||||
{
|
||||
for (unsigned int i = 0; pszLine[i]; i++)
|
||||
{
|
||||
if (pszLine[i] == cDelimiter)
|
||||
{
|
||||
pszLine[i] = '\0';
|
||||
return (pszLine + i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char * HHsParser::SearchBodyPtr(char * pData, unsigned int nSize)
|
||||
{
|
||||
for (unsigned int i = 0; i < nSize; i++)
|
||||
{
|
||||
if (pData[i] == '\r' && pData[i + 1] == '\n' && pData[i + 2] == '\r' && pData[i + 3] == '\n')
|
||||
return (pData + i + 4);
|
||||
else if (pData[i] == '\n' && pData[i + 1] == '\n')
|
||||
return (pData + i + 2);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HHsHeaderElement::HHsHeaderElement(const char * pszName, bool bNameMewMemory, const char * pszValue, bool bValueNewMemory)
|
||||
{
|
||||
m_bNameNewMemory = bNameMewMemory;
|
||||
m_bValueNewMemory = bValueNewMemory;
|
||||
m_nNameLength = strlen(pszName);
|
||||
m_nValueLength = strlen(pszValue);
|
||||
|
||||
if (bNameMewMemory)
|
||||
{
|
||||
m_pszName = (char *)malloc(m_nNameLength + 1);
|
||||
strcpy(m_pszName, pszName);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pszName = (char *)pszName;
|
||||
}
|
||||
|
||||
if (bValueNewMemory)
|
||||
{
|
||||
m_pszValue = (char *)malloc(m_nValueLength + 1);
|
||||
strcpy(m_pszValue, pszValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pszValue = (char *)pszValue;
|
||||
}
|
||||
|
||||
m_pNext = NULL;
|
||||
}
|
||||
|
||||
HHsHeaderElement::~HHsHeaderElement()
|
||||
{
|
||||
if (m_bNameNewMemory)
|
||||
free(m_pszName);
|
||||
|
||||
if (m_bValueNewMemory)
|
||||
free(m_pszValue);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HHsParser::HHsParser(const char * pszProtocolName)
|
||||
{
|
||||
strcpy(m_szProtocolName, pszProtocolName);
|
||||
m_nProtocolNameLength = strlen(pszProtocolName);
|
||||
|
||||
m_pszMethod = NULL;
|
||||
|
||||
m_pszRequestUri = NULL;
|
||||
m_bRequestUriNewMemory = false;
|
||||
|
||||
m_pszVersion = NULL;
|
||||
m_nStatusCode = -1;
|
||||
|
||||
m_pszReasonPhrase = NULL;
|
||||
m_bReasonPhraseNewMemory = false;
|
||||
|
||||
m_pElementHead = NULL;
|
||||
m_pElementRear = NULL;
|
||||
|
||||
m_nHeaderSize = 0;
|
||||
m_nContentLength = 0;
|
||||
|
||||
m_pBody = NULL;
|
||||
m_bBodyNewMemory = false;
|
||||
m_nBodySize = 0;
|
||||
}
|
||||
|
||||
HHsParser::~HHsParser()
|
||||
{
|
||||
if (m_bRequestUriNewMemory)
|
||||
free(m_pszRequestUri);
|
||||
|
||||
if (m_bReasonPhraseNewMemory)
|
||||
free(m_pszReasonPhrase);
|
||||
|
||||
if (m_pElementHead)
|
||||
{
|
||||
HHsHeaderElement * pTemp;
|
||||
HHsHeaderElement * pNext = m_pElementHead;
|
||||
|
||||
do
|
||||
{
|
||||
pTemp = pNext;
|
||||
pNext = pNext->m_pNext;
|
||||
|
||||
delete pTemp;
|
||||
} while (pNext != NULL);
|
||||
}
|
||||
|
||||
if (m_bBodyNewMemory)
|
||||
free(m_pBody);
|
||||
}
|
||||
|
||||
void HHsParser::SetRequestUri(const char * pszRequestUri)
|
||||
{
|
||||
size_t oldLen = strlen(m_pszRequestUri);
|
||||
size_t newLen = strlen(pszRequestUri);
|
||||
|
||||
if (newLen > oldLen)
|
||||
{
|
||||
if (m_bRequestUriNewMemory)
|
||||
free(m_pszRequestUri);
|
||||
else
|
||||
m_bRequestUriNewMemory = true;
|
||||
|
||||
m_pszRequestUri = (char *)malloc(newLen + 1);
|
||||
}
|
||||
|
||||
strcpy(m_pszRequestUri, pszRequestUri);
|
||||
|
||||
m_nHeaderSize += (newLen - oldLen);
|
||||
}
|
||||
|
||||
void HHsParser::SetVersion(const char * pszVersion)
|
||||
{
|
||||
strcpy(m_pszVersion, pszVersion); //...
|
||||
}
|
||||
|
||||
void HHsParser::SetReasonPhrase(const char * pszReasonPhrase)
|
||||
{
|
||||
size_t oldLen = strlen(m_pszReasonPhrase);
|
||||
size_t newLen = strlen(pszReasonPhrase);
|
||||
|
||||
if (newLen > oldLen)
|
||||
{
|
||||
if (m_bReasonPhraseNewMemory)
|
||||
free(m_pszReasonPhrase);
|
||||
else
|
||||
m_bReasonPhraseNewMemory = true;
|
||||
|
||||
m_pszReasonPhrase = (char *)malloc(newLen + 1);
|
||||
}
|
||||
|
||||
strcpy(m_pszReasonPhrase, pszReasonPhrase);
|
||||
|
||||
m_nHeaderSize += (newLen - oldLen);
|
||||
}
|
||||
|
||||
void HHsParser::SetBody(char * pData, unsigned int nSize)
|
||||
{
|
||||
if (nSize > m_nBodySize)
|
||||
{
|
||||
if (m_bBodyNewMemory)
|
||||
free(m_pBody);
|
||||
else
|
||||
m_bBodyNewMemory = true;
|
||||
|
||||
m_pBody = (char *)malloc(nSize + 1);
|
||||
}
|
||||
|
||||
memcpy(m_pBody, pData, nSize);
|
||||
m_pBody[nSize] = '\0';
|
||||
m_nBodySize = nSize;
|
||||
}
|
||||
|
||||
HHsHeaderElement * HHsParser::GetHeaderElement(const char * pszHeaderName, int nIndex)
|
||||
{
|
||||
int i = 0;
|
||||
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
|
||||
{
|
||||
if (stricmp(pszHeaderName, pNext->m_pszName) == 0)
|
||||
{
|
||||
if (nIndex != i++)
|
||||
continue;
|
||||
|
||||
return pNext;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * HHsParser::GetHeaderValue(const char * pszHeaderName, int nIndex)
|
||||
{
|
||||
int i = 0;
|
||||
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
|
||||
{
|
||||
if (stricmp(pszHeaderName, pNext->m_pszName) == 0)
|
||||
{
|
||||
if (nIndex != i++)
|
||||
continue;
|
||||
|
||||
return pNext->m_pszValue;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool HHsParser::AddHeader(const char * pszHeaderName, const char * pszHeaderValue)
|
||||
{
|
||||
HHsHeaderElement * pElement = new HHsHeaderElement(pszHeaderName, true, pszHeaderValue, true);
|
||||
|
||||
if (m_pElementHead == NULL)
|
||||
m_pElementHead = pElement;
|
||||
|
||||
if (m_pElementRear)
|
||||
m_pElementRear->m_pNext = pElement;
|
||||
|
||||
m_pElementRear = pElement;
|
||||
|
||||
m_nHeaderSize += (pElement->m_nNameLength + pElement->m_nValueLength + 4); // 4 = ": " + "\r\n"
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HHsParser::SetHeader(const char * pszHeaderName, const char * pszHeaderValue, int nIndex)
|
||||
{
|
||||
HHsHeaderElement * pFindElement = GetHeaderElement(pszHeaderName, nIndex);
|
||||
if (pFindElement)
|
||||
{
|
||||
size_t newLen = strlen(pszHeaderValue);
|
||||
|
||||
if (newLen > pFindElement->m_nValueLength)
|
||||
{
|
||||
if (pFindElement->m_bValueNewMemory)
|
||||
free(pFindElement->m_pszValue);
|
||||
else
|
||||
pFindElement->m_bValueNewMemory = true;
|
||||
|
||||
pFindElement->m_pszValue = (char *)malloc(newLen + 1);
|
||||
}
|
||||
|
||||
strcpy(pFindElement->m_pszValue, pszHeaderValue);
|
||||
|
||||
m_nHeaderSize += (newLen - pFindElement->m_nValueLength);
|
||||
pFindElement->m_nValueLength = newLen;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return AddHeader(pszHeaderName, pszHeaderValue);
|
||||
}
|
||||
|
||||
bool HHsParser::OrganizeHeader(char * pszHeaderName, char * pszHeaderValue)
|
||||
{
|
||||
HHsHeaderElement * pElement = new HHsHeaderElement(pszHeaderName, false, pszHeaderValue, false);
|
||||
|
||||
if (m_pElementHead == NULL)
|
||||
m_pElementHead = pElement;
|
||||
|
||||
if (m_pElementRear)
|
||||
m_pElementRear->m_pNext = pElement;
|
||||
|
||||
m_pElementRear = pElement;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HHsParser::RemoveHeader(const char * pszHeaderName, const char * pszHeaderValue, int nIndex)
|
||||
{
|
||||
int i = 0;
|
||||
HHsHeaderElement * pPrevNext = m_pElementHead;
|
||||
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
|
||||
{
|
||||
if (stricmp(pszHeaderName, pNext->m_pszName) == 0)
|
||||
{
|
||||
if (nIndex != i++)
|
||||
continue;
|
||||
|
||||
if (pszHeaderValue && stricmp(pszHeaderValue, pNext->m_pszValue) != 0)
|
||||
{
|
||||
pPrevNext = pNext;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pNext == m_pElementHead)
|
||||
{
|
||||
m_pElementHead = pNext->m_pNext;
|
||||
|
||||
if (pNext == m_pElementRear)
|
||||
m_pElementRear = m_pElementHead;
|
||||
}
|
||||
else if (pNext == m_pElementRear)
|
||||
{
|
||||
m_pElementRear = pPrevNext;
|
||||
m_pElementRear->m_pNext = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPrevNext->m_pNext = pNext->m_pNext;
|
||||
}
|
||||
|
||||
m_nHeaderSize -= (pNext->m_nNameLength + pNext->m_nValueLength + 4); // 4 = ": " + "\rn"
|
||||
delete pNext;
|
||||
break;
|
||||
}
|
||||
|
||||
pPrevNext = pNext;
|
||||
}
|
||||
}
|
||||
|
||||
size_t HHsParser::RefleshHeaderSize()
|
||||
{
|
||||
size_t nHeaderSize = 0;
|
||||
|
||||
if (m_pszMethod && m_pszRequestUri && m_pszVersion)
|
||||
{
|
||||
nHeaderSize += strlen(m_pszMethod) + 1;
|
||||
nHeaderSize += strlen(m_pszRequestUri) + 1;
|
||||
nHeaderSize += m_nProtocolNameLength + strlen(m_pszVersion) + 3; // GET / HTTP/1.1\r\n
|
||||
}
|
||||
else if (m_pszVersion && m_nStatusCode > 0 && m_pszReasonPhrase)
|
||||
{
|
||||
nHeaderSize += m_nProtocolNameLength + strlen(m_pszVersion) + 2; // HTTP/1.1 200 OK
|
||||
|
||||
int nNum = m_nStatusCode;
|
||||
int nFigure = 0;
|
||||
for (; nNum != 0; nFigure++)
|
||||
nNum = nNum / 10;
|
||||
|
||||
nHeaderSize += nFigure + 1;
|
||||
nHeaderSize += strlen(m_pszReasonPhrase) + 2;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (m_pElementHead == 0)
|
||||
return 0;
|
||||
|
||||
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
|
||||
{
|
||||
nHeaderSize += pNext->m_nNameLength + 2;
|
||||
nHeaderSize += pNext->m_nValueLength + 2;
|
||||
}
|
||||
|
||||
nHeaderSize += 2; // + \r\n
|
||||
m_nHeaderSize = nHeaderSize;
|
||||
|
||||
return nHeaderSize;
|
||||
}
|
||||
|
||||
int HHsParser::Parse(char * pData, unsigned int nSize, char * pBodyPtr)
|
||||
{
|
||||
if (pData == NULL || pData[0] == '\0')
|
||||
return HP_PARAMETER_ERROR;
|
||||
|
||||
if (pBodyPtr == NULL)
|
||||
{
|
||||
pBodyPtr = SearchBodyPtr(pData, nSize);
|
||||
if (pBodyPtr == NULL)
|
||||
return HP_HEADER_REMAIN_PACKET;
|
||||
}
|
||||
m_nHeaderSize = pBodyPtr - pData;
|
||||
|
||||
char * pNextToken;
|
||||
char * pNextLine = SliceHeader(pData);
|
||||
if (strncmp(pData, m_szProtocolName, m_nProtocolNameLength) == 0)
|
||||
{
|
||||
// Response Start-Line (ex: HTTP/1.1 200 OK)
|
||||
m_pszVersion = pData + m_nProtocolNameLength + 1;
|
||||
if ((pNextToken = SliceToken(m_pszVersion, ' ')) == NULL)
|
||||
return HP_NOT_HTTP_PACKET;
|
||||
|
||||
char * pszStatusCode = pNextToken;
|
||||
if ((pNextToken = SliceToken(pszStatusCode, ' ')) == NULL)
|
||||
return HP_NOT_HTTP_PACKET;
|
||||
m_nStatusCode = atoi(pszStatusCode);
|
||||
|
||||
m_pszReasonPhrase = pNextToken;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Request Start-Line
|
||||
m_pszMethod = pData;
|
||||
if ((pNextToken = SliceToken(m_pszMethod, ' ')) == NULL)
|
||||
return HP_NOT_HTTP_PACKET;
|
||||
|
||||
//... check method name
|
||||
|
||||
m_pszRequestUri = pNextToken;
|
||||
if ((pNextToken = SliceToken(m_pszRequestUri, ' ')) == NULL)
|
||||
return HP_NOT_HTTP_PACKET;
|
||||
|
||||
m_pszVersion = pNextToken + m_nProtocolNameLength + 1;
|
||||
}
|
||||
|
||||
bool bHasContentLength = false;
|
||||
bool bIsChunkded = false;
|
||||
bool bIsConnectionClose = false;
|
||||
bool bHasContentType = false;
|
||||
|
||||
char * pOneLine;
|
||||
char * pszHeaderName;
|
||||
do
|
||||
{
|
||||
pOneLine = pNextLine;
|
||||
if ((pNextLine = SliceHeader(pOneLine)) == NULL)
|
||||
break;
|
||||
|
||||
pszHeaderName = pOneLine;
|
||||
if ((pNextToken = SliceToken(pszHeaderName, ':')) == NULL)
|
||||
return HP_NOT_HTTP_PACKET;
|
||||
|
||||
for (int i = 0; ; i++) // front trim
|
||||
{
|
||||
if (*pNextToken == ' ') pNextToken++;
|
||||
else break;
|
||||
}
|
||||
|
||||
if (stricmp(pszHeaderName, "Content-Length") == 0)
|
||||
{
|
||||
m_nContentLength = atol(pNextToken);
|
||||
bHasContentLength = true;
|
||||
}
|
||||
else if (stricmp(pszHeaderName, "Transfer-Encoding") == 0)
|
||||
{
|
||||
if (stricmp(pNextToken, "chunked") == 0)
|
||||
bIsChunkded = true;
|
||||
}
|
||||
else if (stricmp(pszHeaderName, "Connection") == 0)
|
||||
{
|
||||
if (stricmp(pNextToken, "close") == 0)
|
||||
bIsConnectionClose = true;
|
||||
}
|
||||
else if (stricmp(pszHeaderName, "Content-Type") == 0)
|
||||
bHasContentType = true;
|
||||
|
||||
OrganizeHeader(pszHeaderName, pNextToken);
|
||||
} while (*pNextLine != '\r' && *pNextLine != '\n'); // header end
|
||||
|
||||
if (m_nHeaderSize == nSize && m_nContentLength == 0)
|
||||
{
|
||||
if (bIsChunkded || (bHasContentType && m_pszMethod == NULL && bHasContentLength == false && bIsConnectionClose))
|
||||
return HP_BODYSIZE_UNKNOWN_PACKET;
|
||||
else
|
||||
return HP_COMPLETE_PACKET;
|
||||
}
|
||||
|
||||
unsigned int nRemainSize = nSize - m_nHeaderSize;
|
||||
if (m_nContentLength == 0 || m_nContentLength >= nRemainSize)
|
||||
m_nBodySize = nRemainSize;
|
||||
else
|
||||
m_nBodySize = m_nContentLength;
|
||||
|
||||
if (m_nBodySize > 0)
|
||||
{
|
||||
m_pBody = pBodyPtr;
|
||||
m_pBody[m_nBodySize] = '\0';
|
||||
}
|
||||
|
||||
if (m_nContentLength == 0)
|
||||
return HP_BODYSIZE_UNKNOWN_PACKET;
|
||||
else if (m_nContentLength == m_nBodySize)
|
||||
return HP_COMPLETE_PACKET;
|
||||
else if (m_nContentLength > m_nBodySize)
|
||||
return HP_BODY_REMAIN_PACKET;
|
||||
|
||||
return HP_BODYSIZE_UNKNOWN_PACKET;
|
||||
}
|
||||
|
||||
bool HHsParser::ToString(char * pBuffer, bool bOnlyHeader)
|
||||
{
|
||||
if (m_pszVersion == NULL || m_pElementHead == NULL)
|
||||
{
|
||||
pBuffer[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_pszMethod)
|
||||
sprintf(pBuffer, "%s %s %s/%s\r\n", m_pszMethod, m_pszRequestUri, m_szProtocolName, m_pszVersion);
|
||||
else
|
||||
sprintf(pBuffer, "%s/%s %d %s\r\n", m_szProtocolName, m_pszVersion, m_nStatusCode, m_pszReasonPhrase);
|
||||
|
||||
size_t nTempSize = strlen(pBuffer);
|
||||
|
||||
char * pBufferOffset = pBuffer + nTempSize;
|
||||
for (HHsHeaderElement * pNext = m_pElementHead; pNext != NULL; pNext = pNext->m_pNext)
|
||||
{
|
||||
strcpy(pBufferOffset, pNext->m_pszName);
|
||||
pBufferOffset += pNext->m_nNameLength;
|
||||
|
||||
strcpy(pBufferOffset, ": ");
|
||||
pBufferOffset += 2;
|
||||
|
||||
strcpy(pBufferOffset, pNext->m_pszValue);
|
||||
pBufferOffset += pNext->m_nValueLength;
|
||||
|
||||
strcpy(pBufferOffset, "\r\n");
|
||||
pBufferOffset += 2;
|
||||
}
|
||||
|
||||
strcpy(pBufferOffset, "\r\n");
|
||||
|
||||
if (bOnlyHeader == false && m_pBody)
|
||||
{
|
||||
pBufferOffset += 2;
|
||||
memcpy(pBufferOffset, m_pBody, m_nBodySize);
|
||||
pBufferOffset[m_nBodySize] = '\0';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user