mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 22:13:06 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
377
modules/rosapps/applications/net/roshttpd/http.cpp
Normal file
377
modules/rosapps/applications/net/roshttpd/http.cpp
Normal file
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS HTTP Daemon
|
||||
* FILE: http.cpp
|
||||
* PURPOSE: HTTP 1.1 parser engine
|
||||
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||
* REVISIONS:
|
||||
* CSH 01/09/2000 Created
|
||||
* TODO: - Implement message-body
|
||||
* - Implement more generel-header entries
|
||||
* - Implement more request-header entries
|
||||
* - Implement more entity-header entries
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <http.h>
|
||||
|
||||
CHAR MethodTable[NUMMETHODS][8] = {"OPTIONS", "GET", "HEAD", "POST", "PUT",
|
||||
"DELETE", "TRACE"};
|
||||
|
||||
CHAR GenerelTable[NUMGENERELS][18] = {"Cache-Control", "Connection", "Date", "Pragma",
|
||||
"Transfer-Encoding", "Upgrade", "Via"};
|
||||
|
||||
CHAR RequestTable[NUMREQUESTS][20] = {"Accept", "Accept-Charset", "Accept-Encoding",
|
||||
"Accept-Language", "Authorization", "From", "Host", "If-Modified-Since", "If-Match",
|
||||
"If-None-Match", "If-Range", "If-Unmodified-Since", "Max-Forwards",
|
||||
"Proxy-Authorization", "Range", "Referer", "User-Agent"};
|
||||
|
||||
CHAR EntityTable[NUMENTITIES][17] = {"Allow", "Content-Base", "Content-Encoding",
|
||||
"Content-Language", "Content-Length", "Content-Location", "Content-MD5",
|
||||
"Content-Range", "Content-Type", "ETag", "Expires", "Last-Modified"};
|
||||
|
||||
// *************************** CHttpParser ***************************
|
||||
|
||||
// Default constructor
|
||||
CHttpParser::CHttpParser()
|
||||
{
|
||||
nHead = 0;
|
||||
nTail = 0;
|
||||
}
|
||||
|
||||
// Default destructor
|
||||
CHttpParser::~CHttpParser()
|
||||
{
|
||||
}
|
||||
|
||||
// Returns TRUE if a complete HTTP message is in buffer
|
||||
BOOL CHttpParser::Complete()
|
||||
{
|
||||
UINT nTmp;
|
||||
|
||||
/*DPRINT("--1:-%d---\n", sBuffer[nHead-2]);
|
||||
DPRINT("--2:-%d---\n", sBuffer[nHead-1]);
|
||||
|
||||
sBuffer[nHead] = '!';
|
||||
sBuffer[nHead+1] = 0;
|
||||
DPRINT("Examining buffer: (Head: %d, Tail: %d)\n", nHead, nTail);
|
||||
DPRINT("%s\n", (LPSTR)&sBuffer[nTail]);*/
|
||||
|
||||
nTmp = nTail;
|
||||
if (!Parse()) {
|
||||
if (!bUnknownMethod)
|
||||
nTail = nTmp;
|
||||
return FALSE;
|
||||
} else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Read a character from buffer
|
||||
BOOL CHttpParser::ReadChar(LPSTR lpsStr)
|
||||
{
|
||||
if (nTail <= nHead) {
|
||||
if (nTail != nHead) {
|
||||
lpsStr[0] = sBuffer[nTail];
|
||||
nTail++;
|
||||
return TRUE;
|
||||
} else {
|
||||
lpsStr[0] = 0;
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
if (nTail == sizeof(sBuffer))
|
||||
nTail = 0;
|
||||
if (nTail != nHead) {
|
||||
lpsStr[0] = sBuffer[nTail];
|
||||
nTail++;
|
||||
return TRUE;
|
||||
} else {
|
||||
lpsStr[0] = 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Peek at a character in the buffer
|
||||
BOOL CHttpParser::PeekChar(LPSTR lpsStr)
|
||||
{
|
||||
UINT nFakeTail;
|
||||
|
||||
if (nTail == sizeof(sBuffer))
|
||||
nFakeTail = 0;
|
||||
else
|
||||
nFakeTail = nTail;
|
||||
if (nFakeTail != nHead) {
|
||||
lpsStr[0] = sBuffer[nFakeTail];
|
||||
return TRUE;
|
||||
} else {
|
||||
lpsStr[0] = 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Read a string from buffer. Only A-Z, a-z, 0-9 and '-' are valid characters
|
||||
BOOL CHttpParser::ReadString(LPSTR lpsStr, UINT nLength)
|
||||
{
|
||||
UINT i = 0;
|
||||
CHAR sTmp;
|
||||
|
||||
while (PeekChar(&sTmp)) {
|
||||
if (((sTmp >= 'A') && (sTmp <= 'Z')) || ((sTmp >= 'a') && (sTmp <= 'z')) ||
|
||||
((sTmp >= '0') && (sTmp <= '9')) || (sTmp == '-')) {
|
||||
if (i >= (nLength - 1)) {
|
||||
lpsStr[0] = 0;
|
||||
return FALSE;
|
||||
}
|
||||
ReadChar(&sTmp);
|
||||
lpsStr[i] = sTmp;
|
||||
i++;
|
||||
} else {
|
||||
lpsStr[i] = 0;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
lpsStr[0] = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Read a string from buffer. Stop if SP or CR is found or when there are no more
|
||||
// characters
|
||||
BOOL CHttpParser::ReadSpecial(LPSTR lpsStr, UINT nLength)
|
||||
{
|
||||
UINT i = 0;
|
||||
CHAR sTmp;
|
||||
|
||||
while (PeekChar(&sTmp) && (sTmp != ' ') && (sTmp != 13)) {
|
||||
if (i >= (nLength - 1)) {
|
||||
lpsStr[nLength - 1] = 0;
|
||||
return FALSE;
|
||||
}
|
||||
ReadChar(&sTmp);
|
||||
lpsStr[i] = sTmp;
|
||||
i++;
|
||||
}
|
||||
lpsStr[i] = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Skip until "sCh" is found
|
||||
VOID CHttpParser::Skip(CHAR sCh)
|
||||
{
|
||||
CHAR sTmp;
|
||||
|
||||
while (PeekChar(&sTmp) && (sTmp != sCh))
|
||||
ReadChar(&sTmp);
|
||||
}
|
||||
|
||||
// Return TRUE if sCh is the next character
|
||||
BOOL CHttpParser::Expect(CHAR sCh)
|
||||
{
|
||||
CHAR sTmp;
|
||||
|
||||
if (PeekChar(&sTmp)) {
|
||||
if (sTmp == sCh) {
|
||||
ReadChar(&sTmp);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Return TRUE if CRLF are the next characters
|
||||
BOOL CHttpParser::ExpectCRLF()
|
||||
{
|
||||
return (Expect(13) && Expect(10));
|
||||
}
|
||||
|
||||
// Request = RequestLine | *( GenerelHeader | RequestHeader | EntityHeader )
|
||||
// CRLF [ MessageBody ]
|
||||
BOOL CHttpParser::Parse()
|
||||
{
|
||||
BOOL bStatus;
|
||||
|
||||
if (RequestLine()) {
|
||||
do {
|
||||
if (!ReadString(sHeader, sizeof(sHeader)))
|
||||
break;
|
||||
bStatus = (GenerelHeader());
|
||||
bStatus = (RequestHeader() || bStatus);
|
||||
bStatus = (EntityHeader() || bStatus);
|
||||
} while (bStatus);
|
||||
// CRLF
|
||||
if (!ExpectCRLF())
|
||||
return FALSE;
|
||||
MessageBody();
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// RequestLine = Method SP RequestURI SP HTTP-Version CRLF
|
||||
BOOL CHttpParser::RequestLine()
|
||||
{
|
||||
CHAR sCh;
|
||||
UINT i;
|
||||
|
||||
bUnknownMethod = FALSE;
|
||||
|
||||
// RFC 2068 states that servers SHOULD ignore any empty nine(s) received where a
|
||||
// Request-Line is expected
|
||||
while (PeekChar(&sCh) && ((sCh == 13) || (sCh == 10)));
|
||||
|
||||
if (!ReadString(sMethod, sizeof(sMethod)))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < NUMMETHODS; i++) {
|
||||
if (strcmp(MethodTable[i], sMethod) == 0) {
|
||||
nMethodNo = i;
|
||||
if (!Expect(' '))
|
||||
return FALSE;
|
||||
// URI (ie. host/directory/resource)
|
||||
if (!ReadSpecial(sUri, sizeof(sUri)))
|
||||
return FALSE;
|
||||
if (!Expect(' '))
|
||||
return FALSE;
|
||||
// HTTP version (eg. HTTP/1.1)
|
||||
if (!ReadSpecial(sVersion, sizeof(sVersion)))
|
||||
return FALSE;
|
||||
// CRLF
|
||||
if (!ExpectCRLF())
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
bUnknownMethod = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// GenerelHeader = Cache-Control | Connection | Date | Pragma | Transfer-Encoding |
|
||||
// Upgrade | Via
|
||||
BOOL CHttpParser::GenerelHeader()
|
||||
{
|
||||
INT i;
|
||||
|
||||
for (i = 0; i < NUMGENERELS; i++) {
|
||||
if (strcmp(GenerelTable[i], sHeader) == 0) {
|
||||
switch (i) {
|
||||
case 1: {
|
||||
//Connection
|
||||
Expect(':');
|
||||
Expect(' ');
|
||||
Skip(13);
|
||||
ExpectCRLF();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Expect(':');
|
||||
Expect(' ');
|
||||
Skip(13);
|
||||
ExpectCRLF();
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// RequestHeader = Accept | Accept-Charset | Accept-Encoding | Accept-Language |
|
||||
// Authorization | From | Host | If-Modified-Since | If-Match |
|
||||
// If-None-Match | If-Range | If-Unmodified-Since | Max-Forwards |
|
||||
// Proxy-Authorization | Range | Referer | User-Agent
|
||||
BOOL CHttpParser::RequestHeader()
|
||||
{
|
||||
INT i;
|
||||
|
||||
for (i = 0; i < NUMREQUESTS; i++) {
|
||||
if (strcmp(RequestTable[i], sHeader) == 0) {
|
||||
switch (i) {
|
||||
case 0: {
|
||||
//Accept
|
||||
Expect(':');
|
||||
Expect(' ');
|
||||
Skip(13);
|
||||
ExpectCRLF();
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
//Accept-Encoding
|
||||
Expect(':');
|
||||
Expect(' ');
|
||||
Skip(13);
|
||||
ExpectCRLF();
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
//Accept-Language
|
||||
Expect(':');
|
||||
Expect(' ');
|
||||
Skip(13);
|
||||
ExpectCRLF();
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
//Host
|
||||
Expect(':');
|
||||
Expect(' ');
|
||||
Skip(13);
|
||||
ExpectCRLF();
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
//User-Agent
|
||||
Expect(':');
|
||||
Expect(' ');
|
||||
Skip(13);
|
||||
ExpectCRLF();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Expect(':');
|
||||
Expect(' ');
|
||||
Skip(13);
|
||||
ExpectCRLF();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// EntityHeader = Allow | Content-Base | Content-Encoding | Content-Language |
|
||||
// Content-Length | Content-Location | Content-MD5 |
|
||||
// Content-Range | Content-Type | ETag | Expires |
|
||||
// Last-Modified | extension-header
|
||||
BOOL CHttpParser::EntityHeader()
|
||||
{
|
||||
INT i;
|
||||
|
||||
for (i = 0; i < NUMENTITIES; i++) {
|
||||
if (strcmp(EntityTable[i], sHeader) == 0) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
default: {
|
||||
//cout << "<Entity-Header>: #" << i << endl;
|
||||
Expect(':');
|
||||
Expect(' ');
|
||||
Skip(13);
|
||||
ExpectCRLF();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// MessageBody = *OCTET
|
||||
BOOL CHttpParser::MessageBody()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue