#include "huslib.h" #include "huslibex.h" #define ARRAYCOUNT(array) ((unsigned)(sizeof(array)/sizeof(array[0]))) static struct { const char * pszExtention; const char * pszContentType; } ContentTypeTab[] = { { ".htm", "text/html" }, { ".html", "text/html" }, { ".asp", "text/html" }, { ".php", "text/html" }, { ".jsp", "text/html" }, { ".css", "text/css" }, { ".js", "application/x-javascript" }, { ".txt", "text/plain" }, { ".ini", "text/plain" }, { ".gif", "image/gif" }, { ".jpg", "image/jpeg" }, { ".png", "image/png" }, { ".bmp", "image/bmp" }, { ".swf", "application/x-shockwave-flash" }, { ".zip", "application/zip" } }; HWebServer::HWebServer() { m_pszResponse = (char *)malloc(g_nMaxHsHeaderSize); m_pszResponseOffset = m_pszResponse; m_nResponseRemainSize = 0; m_pFileBuffer = (char *)malloc(WS_READ_BYTES + 1); m_pFileBufferOffset = m_pFileBuffer; m_nRemainBufferSize = 0; } HWebServer::~HWebServer() { free(m_pszResponse); free(m_pFileBuffer); } const char * HWebServer::GetContentType(const char * pszRequestUri) { for (unsigned i = 0; i < ARRAYCOUNT(ContentTypeTab); i++) { if (stristr(pszRequestUri, ContentTypeTab[i].pszExtention)) return ContentTypeTab[i].pszContentType; } return "application/octet-stream"; } void HWebServer::AddStaticDir(const char * pszDir) { m_listStaticDir.push_back(pszDir); } int HWebServer::SendResponse() { int nSentSize = SendToTransport(m_pszResponseOffset, m_nResponseRemainSize); if (nSentSize <= 0) return nSentSize; // -1 : shutdown, 0 : buffering because of wouldblock else if (nSentSize < m_nResponseRemainSize) { m_pszResponseOffset += nSentSize; m_nResponseRemainSize -= nSentSize; return 0; // buffering because of wouldblock } return -1; // shutdown } int HWebServer::SendFileHeader() { int nSentSize = SendToTransport(m_pFileBufferOffset, m_nRemainBufferSize); if (nSentSize <= 0) return nSentSize; // -1 : shutdown, 0 : buffering because of wouldblock else if (nSentSize < m_nRemainBufferSize) { m_pFileBufferOffset += nSentSize; m_nRemainBufferSize -= nSentSize; return 0; // buffering because of wouldblock } return 1; // continue } int HWebServer::SendOpenedFile() { int nSendSize; int nSentSize; int nReadSize = WS_READ_BYTES; while (m_nFileSize > 0) { while (m_nRemainBufferSize) { if (m_nRemainBufferSize > (long)g_nSocketSendingBlockSize) nSendSize = g_nSocketSendingBlockSize; else nSendSize = m_nRemainBufferSize; nSentSize = SendToTransport(m_pFileBufferOffset, nSendSize); if (nSentSize <= 0) return nSentSize; // -1 : shutdown, 0 : buffering because of wouldblock m_pFileBufferOffset += nSentSize; m_nRemainBufferSize -= nSentSize; if (nSentSize < nSendSize) return 0; } if (nReadSize < WS_READ_BYTES) break; if ((nReadSize = m_file.Read(m_pFileBuffer, WS_READ_BYTES)) <= 0) break; m_pFileBufferOffset = m_pFileBuffer; m_nRemainBufferSize = nReadSize; } m_file.Close(); m_pFileBufferOffset = m_pFileBuffer; m_nRemainBufferSize = 0; return -1; } int HWebServer::OnSendRetryToTransport() { if (m_nResponseRemainSize > 0) return SendResponse(); return SendOpenedFile(); } int HWebServer::OnPacketProcessing(const char * pBodyData, int nBodySize) { int nResult = OnPrepareRequest(pBodyData, nBodySize); if (nResult <= 0) return nResult; nResult = OnReceivedRequest(pBodyData, nBodySize); if (nResult <= 0) return nResult; HDynamicArray darrNewPath(strlen(m_pHttpParser->GetRequestUri()) + 1); RealignPathDepth(m_pHttpParser->GetRequestUri(), darrNewPath.m_p); int nCopySize = 0; const char * pOffset = strchr(darrNewPath.m_p, '?'); if (pOffset) nCopySize = pOffset - darrNewPath.m_p; else nCopySize = strlen(darrNewPath.m_p); size_t nPathLength = m_strHomeDir.GetLength() + nCopySize; if (nPathLength > (size_t)g_nMaxPathNameLength) { m_nResponseRemainSize = MakeResponse(m_pszResponse, "400 Bad Request", "400 Bad Request"); return SendResponse(); } HString strCopyPath = darrNewPath.m_p; HString strLastPath = strCopyPath.SubStr(0, nCopySize); if (strLastPath == "/") strLastPath = "/index.htm"; HString strPathName = m_strHomeDir; strPathName += strLastPath; if (m_file.Open(strPathName, HFile::FMODE_RDONLY)) { m_nFileSize = HFile::GetSize(strPathName); m_nRemainBufferSize = Make200Header(m_pFileBufferOffset, GetContentType(strPathName), m_nFileSize); int nResult = SendFileHeader(); if (nResult <= 0) return nResult; m_nRemainBufferSize = 0; return SendOpenedFile(); } // 404 Not found m_nResponseRemainSize = MakeResponse(m_pszResponse, "404 Not found", "404 Not found"); return SendResponse(); } bool HWebServer::IsStaticRequest() { for (HStrList::iterator iter = m_listStaticDir.begin(); iter != m_listStaticDir.end(); iter++) { if (iter->StrNICmp(m_pHttpParser->GetRequestUri(), iter->GetLength()) == 0) return true; } return false; }