최종완료보고 버전
This commit is contained in:
@@ -0,0 +1,550 @@
|
||||
|
||||
#include "huslib.h"
|
||||
#include "huslibex.h"
|
||||
|
||||
|
||||
bool HHttpHandler::UriCmp(const char * pszRequestUri, const char * pszPrefix)
|
||||
{
|
||||
const char * p1 = pszRequestUri;
|
||||
const char * p2 = pszPrefix;
|
||||
for (;;)
|
||||
{
|
||||
if (*p1 == '?' && *p2 == '\0')
|
||||
break;
|
||||
else if (strcmp(p1, "/") == 0 && *p2 == '\0')
|
||||
break;
|
||||
else if (*p1 != '\0' && *p2 == '*')
|
||||
break;
|
||||
else if (*p1 != *p2)
|
||||
return false;
|
||||
else if (*p1 == '\0' && *p2 == '\0')
|
||||
break;
|
||||
else if (*p1 == '\0' || *p2 == '\0')
|
||||
return false;
|
||||
|
||||
p1++;
|
||||
p2++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HHttpHandler::GetParamValue(const char * pszString, const char * pszKey, char * pszValue)
|
||||
{
|
||||
pszValue[0] = '\0';
|
||||
|
||||
char * pszKeyString = (char *)malloc(strlen(pszKey) + 2);
|
||||
strcpy(pszKeyString, pszKey);
|
||||
strcat(pszKeyString, "=");
|
||||
|
||||
const char * pszSearch = strstr(pszString, pszKeyString);
|
||||
free(pszKeyString);
|
||||
|
||||
if (pszSearch == NULL)
|
||||
return false;
|
||||
|
||||
int nIndex = (int)(pszSearch - pszString);
|
||||
if (nIndex > 0 &&
|
||||
pszString[nIndex - 1] != '?' &&
|
||||
pszString[nIndex - 1] != '&' &&
|
||||
#if 0
|
||||
pszString[nIndex - 1] != ' ' && pszString[nIndex - 1] != '\\' &&
|
||||
pszString[nIndex - 1] != '/' && pszString[nIndex - 1] != ':' &&
|
||||
pszString[nIndex - 1] != '\"' && pszString[nIndex - 1] != '\'' &&
|
||||
#endif
|
||||
pszString[nIndex - 1] != ';')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int nStart = strlen(pszKey) + 1;
|
||||
int nCount = strlen(pszSearch);
|
||||
int i;
|
||||
for (i = nStart; i < nCount; i++)
|
||||
{
|
||||
if (pszSearch[i] == '?' ||
|
||||
pszSearch[i] == '&' ||
|
||||
#if 0
|
||||
pszSearch[i] == ' ' || pszSearch[i] == '\\' ||
|
||||
pszSearch[i] == '/' || pszSearch[i] == ':' ||
|
||||
pszSearch[i] == '\"' || pszSearch[i] == '\'' ||
|
||||
#endif
|
||||
pszSearch[i] == ';')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nStart == i)
|
||||
{
|
||||
pszValue[0] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
strncpy(pszValue, pszSearch + nStart, i - nStart);
|
||||
pszValue[i - nStart] = '\0';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HHttpHandler::GetCookieValue(const char * pszCookie, const char * pszKeyName, char * pszValue)
|
||||
{
|
||||
*pszValue = '\0';
|
||||
|
||||
const char * pszOffset = stristr(pszCookie, pszKeyName);
|
||||
if (pszOffset == NULL)
|
||||
return false;
|
||||
|
||||
pszOffset += strlen(pszKeyName);
|
||||
|
||||
while (*pszOffset)
|
||||
{
|
||||
if (*pszOffset == '=')
|
||||
{
|
||||
pszOffset++;
|
||||
break;
|
||||
}
|
||||
else if (*pszOffset == ' ' || *pszOffset == '\t')
|
||||
;
|
||||
else if (*pszOffset == '\0')
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
pszOffset++;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (*pszOffset)
|
||||
{
|
||||
if (*pszOffset == ';' || *pszOffset == '\r' || *pszOffset == '\n' || *pszOffset == '\0')
|
||||
{
|
||||
pszValue[i] = '\0';
|
||||
return true;
|
||||
}
|
||||
else if (*pszOffset == '\t' || *pszOffset == ' ')
|
||||
;
|
||||
else
|
||||
pszValue[i++] = *pszOffset;
|
||||
|
||||
pszOffset++;
|
||||
}
|
||||
|
||||
pszValue[i] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HHttpHandler::SetCookieValue(char * pszNewCookie, const char * pszCookie, const char * pszKeyName, const char * pszValue)
|
||||
{
|
||||
*pszNewCookie = '\0';
|
||||
bool bIsSearch = false;
|
||||
const char * pFirst = NULL;
|
||||
const char * pSecond = NULL;
|
||||
|
||||
const char * pszOffset = pszCookie;
|
||||
for (;;)
|
||||
{
|
||||
pszOffset = stristr(pszOffset, pszKeyName);
|
||||
if (pszOffset == NULL)
|
||||
break;
|
||||
|
||||
if (pszOffset != pszCookie)
|
||||
{
|
||||
const char * pTemp = pszOffset - 1;
|
||||
if (*pTemp != ' ' && *pTemp != ';' && *pTemp != '\t')
|
||||
{
|
||||
pszOffset += strlen(pszKeyName);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
pszOffset += strlen(pszKeyName);
|
||||
|
||||
for (; *pszOffset; pszOffset++)
|
||||
{
|
||||
if (bIsSearch == false)
|
||||
{
|
||||
if (*pszOffset == '=')
|
||||
{
|
||||
bIsSearch = true;
|
||||
pFirst = pszOffset + 1;
|
||||
}
|
||||
else if (*pszOffset != ' ' && *pszOffset != '\t' && *pszOffset != '\r' && *pszOffset != '\n')
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*pszOffset == ';')
|
||||
{
|
||||
pSecond = pszOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bIsSearch == true)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bIsSearch == true)
|
||||
{
|
||||
int nCopySize = pFirst - pszCookie;
|
||||
strncpy(pszNewCookie, pszCookie, nCopySize);
|
||||
pszNewCookie[nCopySize] = '\0';
|
||||
strcat(pszNewCookie, pszValue);
|
||||
|
||||
if (pSecond)
|
||||
strcat(pszNewCookie, pSecond);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bAddSemiColon = true;
|
||||
|
||||
int nTotalLength = strlen(pszCookie);
|
||||
for (int i = nTotalLength; i > 0; i--)
|
||||
{
|
||||
if (pszCookie[i - 1] == ';')
|
||||
{
|
||||
bAddSemiColon = false;
|
||||
break;
|
||||
}
|
||||
else if (pszCookie[i - 1] == ' ' || pszCookie[i - 1] == '\t' ||
|
||||
pszCookie[i - 1] == '\r' || pszCookie[i - 1] == '\n')
|
||||
{
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(pszNewCookie, pszCookie);
|
||||
|
||||
if (bAddSemiColon == true)
|
||||
strcat(pszNewCookie, "; ");
|
||||
|
||||
strcat(pszNewCookie, pszKeyName);
|
||||
strcat(pszNewCookie, "=");
|
||||
strcat(pszNewCookie, pszValue);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int HHttpHandler::RemoveCookieValue(char * pszCookie, const char * pszKeyName, int nIndex)
|
||||
{
|
||||
const char * pszOffset = pszCookie;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
pszOffset = stristr(pszOffset, pszKeyName);
|
||||
if (pszOffset == NULL || pszOffset[strlen(pszKeyName)] != '=')
|
||||
return 0;
|
||||
|
||||
if (nIndex-- > 0)
|
||||
{
|
||||
pszOffset += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
char * pszFront = (char *)pszOffset;
|
||||
while (*pszOffset)
|
||||
{
|
||||
if (*pszOffset == ';' || *pszOffset == '\r' || *pszOffset == '\n' || *pszOffset == '\0')
|
||||
break;
|
||||
|
||||
pszOffset++;
|
||||
}
|
||||
|
||||
if (*pszOffset == ';')
|
||||
pszOffset++;
|
||||
|
||||
if (*pszOffset == '\r' || *pszOffset == '\n' || *pszOffset == '\0')
|
||||
{
|
||||
if (pszCookie == pszFront) // empty cookie
|
||||
{
|
||||
*pszFront = '\0';
|
||||
return 2;
|
||||
}
|
||||
|
||||
*pszFront = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*pszOffset == ' ')
|
||||
pszOffset++;
|
||||
|
||||
char * pszTemp = (char *)malloc(strlen(pszOffset) + 1);
|
||||
strcpy(pszTemp, pszOffset);
|
||||
strcpy(pszFront, pszTemp);
|
||||
free(pszTemp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int HHttpHandler::MakeCookie(char * pszSetCookie, const char * pszKeyName,
|
||||
const char * pszKeyValue, const char * pszDomain, const char * pszPath, long nExpireMinute)
|
||||
{
|
||||
if (nExpireMinute < 0)
|
||||
{
|
||||
return sprintf(pszSetCookie, "%s=%s; expires=Thu, 01 Jan 1970 23:59:59 GMT%s%s%s%s",
|
||||
pszKeyName, pszKeyValue,
|
||||
pszDomain ? "; domain=" : "", pszDomain ? pszDomain : "",
|
||||
pszPath ? "; path=" : "", pszPath ? pszPath : "");
|
||||
}
|
||||
else if (nExpireMinute == 0)
|
||||
{
|
||||
return sprintf(pszSetCookie, "%s=%s%s%s%s%s",
|
||||
pszKeyName, pszKeyValue,
|
||||
pszDomain ? "; domain=" : "", pszDomain ? pszDomain : "",
|
||||
pszPath ? "; path=" : "", pszPath ? pszPath : "");
|
||||
}
|
||||
|
||||
char szDateTime[32];
|
||||
struct tm * tmTmp;
|
||||
timeb tTimeb;
|
||||
|
||||
ftime(&tTimeb);
|
||||
tTimeb.time += nExpireMinute;
|
||||
tmTmp = localtime(&tTimeb.time);
|
||||
strftime(szDateTime, 32, "%a, %d-%b-%Y %H:%M:%S", tmTmp);
|
||||
|
||||
return sprintf(pszSetCookie, "%s=%s; expires=%s GMT%s%s%s%s",
|
||||
pszKeyName, pszKeyValue, szDateTime,
|
||||
pszDomain ? "; domain=" : "", pszDomain ? pszDomain : "",
|
||||
pszPath ? "; path=" : "", pszPath ? pszPath : "");
|
||||
}
|
||||
|
||||
const char * HHttpHandler::EnumExtractCookie(const char * pszCookie, char ** ppName, char ** ppValue)
|
||||
{
|
||||
*ppName = NULL;
|
||||
*ppValue = NULL;
|
||||
|
||||
if (pszCookie == NULL || pszCookie[0] == '\0')
|
||||
return NULL;
|
||||
|
||||
const char * pOffset1 = strchr(pszCookie, ';');
|
||||
const char * pOffset2 = strchr(pszCookie, '=');
|
||||
if (pOffset1 == NULL && pOffset2 == NULL)
|
||||
return NULL;
|
||||
else if (pOffset2 == NULL || (pOffset1 && pOffset1 <= pOffset2 + 1))
|
||||
return pOffset1 + 1;
|
||||
|
||||
int nNameSize = pOffset2 - pszCookie;
|
||||
*ppName = (char *)malloc(nNameSize + 1);
|
||||
StrNTrimCpy(*ppName, pszCookie, nNameSize);
|
||||
|
||||
int nValueSize;
|
||||
if (pOffset1)
|
||||
nValueSize = pOffset1 - (pOffset2 + 1);
|
||||
else
|
||||
nValueSize = strlen(pOffset2 + 1);
|
||||
|
||||
*ppValue = (char *)malloc(nValueSize + 1);
|
||||
StrNTrimCpy(*ppValue, pOffset2 + 1, nValueSize);
|
||||
|
||||
if (pOffset1)
|
||||
return pOffset1 + 1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int HHttpHandler::MakeResponse(char * pszResponse, const char * pszResponseType, const char * pszHtml)
|
||||
{
|
||||
HString strRear;
|
||||
if (pszHtml)
|
||||
{
|
||||
strRear = "Content-Length: ";
|
||||
strRear += strlen(pszHtml);
|
||||
strRear += "\r\n\r\n";
|
||||
strRear += pszHtml;
|
||||
}
|
||||
|
||||
size_t nSize = sprintf(pszResponse, "HTTP/1.1 %s\n"
|
||||
"Server: HUSS/2.0\r\n"
|
||||
"X-UA-Compatible: IE=Edge\r\n"
|
||||
"Content-Security-Policy: script-src 'self' 'unsafe-inline'; object-src 'self';\r\n"
|
||||
"X-Content-Type-Options: nosniff\r\n"
|
||||
"X-XSS-Protection: 1; mode=block\r\n"
|
||||
"Connection: close\r\n"
|
||||
"%s", pszResponseType, pszHtml ? strRear.psz() : "\r\n");
|
||||
|
||||
return nSize;
|
||||
}
|
||||
|
||||
int HHttpHandler::Make200Header(char * pszResponse, const char * pszContentType, unsigned long nBodySize, const char * pszAddtionalHeaders)
|
||||
{
|
||||
size_t nSize = sprintf(pszResponse, "HTTP/1.1 200 OK\r\n"
|
||||
"Server: HUSS/2.0\r\n"
|
||||
"X-UA-Compatible: IE=Edge\r\n"
|
||||
"Content-Security-Policy: script-src 'self' 'unsafe-inline'; object-src 'self';\r\n"
|
||||
"X-Content-Type-Options: nosniff\r\n"
|
||||
"X-XSS-Protection: 1; mode=block\r\n"
|
||||
"%s%s"
|
||||
"Content-Type: %s\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Length: %ld\r\n"
|
||||
"\r\n", pszAddtionalHeaders && pszAddtionalHeaders[0] != '\0' ? pszAddtionalHeaders : "",
|
||||
pszAddtionalHeaders && pszAddtionalHeaders[0] != '\0' ? "\r\n" : "",
|
||||
pszContentType, nBodySize);
|
||||
|
||||
return nSize;
|
||||
}
|
||||
|
||||
int HHttpHandler::Make302Response(char * pszResponse, const char * pszLocation, const char * pszSetCookie)
|
||||
{
|
||||
size_t nSize = sprintf(pszResponse, "HTTP/1.1 302 Moved Temporarily\r\n"
|
||||
"Server: HUSS/2.0\r\n"
|
||||
"Location: %s\r\n"
|
||||
"Connection: close\r\n"
|
||||
"%s%s%s"
|
||||
"\r\n", pszLocation, pszSetCookie ? "Set-Cookie: " : "",
|
||||
pszSetCookie ? pszSetCookie : "", pszSetCookie ? "\r\n" : "");
|
||||
|
||||
return nSize;
|
||||
}
|
||||
|
||||
int HHttpHandler::Make307Response(char * pszResponse, const char * pszLocation, const char * pszSetCookie)
|
||||
{
|
||||
size_t nSize = sprintf(pszResponse, "HTTP/1.1 307 Temporary Redirect\r\n"
|
||||
"Server: HUSS/2.0\r\n"
|
||||
"Location: %s\r\n"
|
||||
"Connection: close\r\n"
|
||||
"%s%s%s"
|
||||
"\r\n", pszLocation, pszSetCookie ? "Set-Cookie: " : "",
|
||||
pszSetCookie ? pszSetCookie : "", pszSetCookie ? "\r\n" : "");
|
||||
|
||||
return nSize;
|
||||
}
|
||||
|
||||
void HHttpHandler::MakeRedirectBody(HString * pstrBody, const char * pszUrl)
|
||||
{
|
||||
*pstrBody = "<html><head><META HTTP-EQUIV=Refresh CONTENT=\"0; URL='";
|
||||
*pstrBody += pszUrl;
|
||||
*pstrBody += "'\"></head></html>";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HHttpHandler::HHttpHandler()
|
||||
{
|
||||
m_pRecvStreamBuffer = new HStreamBuffer(g_nMaxHsHeaderSize + g_nSocketReceiveBlockSize);
|
||||
m_pHttpParser = NULL;
|
||||
m_nProtocolStatus = HHsParser::HP_NOT_HTTP_PACKET;
|
||||
|
||||
m_nRemainBodySize = 0;
|
||||
}
|
||||
|
||||
HHttpHandler::~HHttpHandler()
|
||||
{
|
||||
if (m_pHttpParser)
|
||||
delete m_pHttpParser;
|
||||
|
||||
delete m_pRecvStreamBuffer;
|
||||
}
|
||||
|
||||
void HHttpHandler::InitParser()
|
||||
{
|
||||
if (m_pHttpParser)
|
||||
{
|
||||
m_pRecvStreamBuffer->Reset();
|
||||
m_nProtocolStatus = HHsParser::HP_NOT_HTTP_PACKET;
|
||||
delete m_pHttpParser;
|
||||
m_pHttpParser = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void HHttpHandler::WriteStreamPacket(const char * pszDir, const char * pszPrefix)
|
||||
{
|
||||
HString strFileName = pszDir;
|
||||
strFileName += pszPrefix;
|
||||
char szDateTime[32];
|
||||
GetDateTimeNum(szDateTime);
|
||||
strFileName += szDateTime;
|
||||
|
||||
HFile file;
|
||||
if (file.Open(strFileName, HFile::FMODE_CREATE | HFile::FMODE_WRONLY) == false)
|
||||
return;
|
||||
file.Write(m_pRecvStreamBuffer->Head(), m_pRecvStreamBuffer->StoredSize());
|
||||
}
|
||||
|
||||
int HHttpHandler::OnReceivedFromTransport(const char * pData, int nSize)
|
||||
{
|
||||
//HLOGF(HLOG_WARNING, "TestLog, HttpHdler, inst = 0x%x, recv size = %d\n", this, nSize);
|
||||
//HLOGD(HLOG_WARNING, pData, 40, true);
|
||||
|
||||
if (m_nProtocolStatus == HHsParser::HP_BODY_REMAIN_PACKET)
|
||||
{
|
||||
m_nRemainBodySize -= nSize;
|
||||
|
||||
int nResult = OnReceivedBodyStream(pData, nSize);
|
||||
|
||||
if (m_nRemainBodySize <= 0)
|
||||
{
|
||||
m_pRecvStreamBuffer->Reset();
|
||||
m_nProtocolStatus = HHsParser::HP_NOT_HTTP_PACKET;
|
||||
delete m_pHttpParser;
|
||||
m_pHttpParser = NULL;
|
||||
}
|
||||
|
||||
return nResult;
|
||||
}
|
||||
else if (m_nProtocolStatus == HHsParser::HP_BODYSIZE_UNKNOWN_PACKET)
|
||||
{
|
||||
return OnReceivedBodyStream(pData, nSize);
|
||||
}
|
||||
|
||||
if (m_pRecvStreamBuffer->Store(pData, nSize) == false)
|
||||
{
|
||||
HLOGF(HLOG_ERROR, "[ERROR], HttpHdler, Failed to insert data, inst = 0x%x, buffer = %d, stored = %d, recv size = %d\n", this, m_pRecvStreamBuffer->Size(), m_pRecvStreamBuffer->StoredSize(), nSize);
|
||||
return -1; // disconnect
|
||||
}
|
||||
|
||||
// simply verify header
|
||||
if (isalnum(m_pRecvStreamBuffer->Head()[0]) == 0)
|
||||
{
|
||||
HLOGF(HLOG_WARNING, "[WARN], HttpHdler, Invalid http protocol 1, inst = 0x%x, buffer = %d, stored = %d, recv size = %d\n", this, m_pRecvStreamBuffer->Size(), m_pRecvStreamBuffer->StoredSize(), nSize);
|
||||
HLOGD(HLOG_WARNING, m_pRecvStreamBuffer->Head(), 20, false);
|
||||
return -1; // disconnect
|
||||
}
|
||||
|
||||
m_pRecvStreamBuffer->Head()[m_pRecvStreamBuffer->StoredSize()] = '\0'; // for using string operation
|
||||
|
||||
char * pszBodyPtr = HHsParser::SearchBodyPtr((char *)pData, nSize); //... search "\r\n\r\n" or "\n\n"
|
||||
if (pszBodyPtr == NULL)
|
||||
return 0; // continue received (remain header)
|
||||
|
||||
m_pHttpParser = new HHsParser("HTTP");
|
||||
m_nProtocolStatus = m_pHttpParser->Parse(m_pRecvStreamBuffer->Head(), m_pRecvStreamBuffer->StoredSize());
|
||||
|
||||
if (m_nProtocolStatus == HHsParser::HP_NOT_HTTP_PACKET ||
|
||||
m_nProtocolStatus == HHsParser::HP_PARAMETER_ERROR)
|
||||
{
|
||||
HLOGF(HLOG_WARNING, "[WARN], HttpHdler, Invalid http protocol 2, inst = 0x%x, buffer = %d, stored = %d, recv size = %d\n", this, m_pRecvStreamBuffer->Size(), m_pRecvStreamBuffer->StoredSize(), nSize);
|
||||
HLOGD(HLOG_WARNING, m_pRecvStreamBuffer->Head(), 20, false);
|
||||
return -1; // disconnect
|
||||
}
|
||||
else if (m_nProtocolStatus == HHsParser::HP_BODY_REMAIN_PACKET)
|
||||
{
|
||||
m_nRemainBodySize = m_pHttpParser->GetContentLength() - m_pHttpParser->GetBodySize();
|
||||
return OnPacketProcessing(m_pHttpParser->GetBodyPtr(), m_pHttpParser->GetBodySize());
|
||||
}
|
||||
else if (m_nProtocolStatus == HHsParser::HP_BODYSIZE_UNKNOWN_PACKET)
|
||||
{
|
||||
return OnPacketProcessing(m_pHttpParser->GetBodyPtr(), m_pHttpParser->GetBodySize());
|
||||
}
|
||||
else if (m_nProtocolStatus == HHsParser::HP_COMPLETE_PACKET)
|
||||
{
|
||||
int nResult = OnPacketProcessing(m_pHttpParser->GetBodyPtr(), m_pHttpParser->GetBodySize());
|
||||
|
||||
m_pRecvStreamBuffer->Reset();
|
||||
m_nProtocolStatus = HHsParser::HP_NOT_HTTP_PACKET;
|
||||
delete m_pHttpParser;
|
||||
m_pHttpParser = NULL;
|
||||
|
||||
return nResult;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user