최종완료보고 버전

This commit is contained in:
CodeTempla
2026-05-20 03:08:08 +09:00
commit 10d255ed51
548 changed files with 435582 additions and 0 deletions
+551
View File
@@ -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;
}