ReactOS 0.4.15-dev-7918-g2a2556c
http.cpp
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS HTTP Daemon
4 * FILE: http.cpp
5 * PURPOSE: HTTP 1.1 parser engine
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09/2000 Created
9 * TODO: - Implement message-body
10 * - Implement more generel-header entries
11 * - Implement more request-header entries
12 * - Implement more entity-header entries
13 */
14#include <debug.h>
15#include <iostream>
16#include <string.h>
17#include <http.h>
18
19CHAR MethodTable[NUMMETHODS][8] = {"OPTIONS", "GET", "HEAD", "POST", "PUT",
20 "DELETE", "TRACE"};
21
22CHAR GenerelTable[NUMGENERELS][18] = {"Cache-Control", "Connection", "Date", "Pragma",
23 "Transfer-Encoding", "Upgrade", "Via"};
24
25CHAR RequestTable[NUMREQUESTS][20] = {"Accept", "Accept-Charset", "Accept-Encoding",
26 "Accept-Language", "Authorization", "From", "Host", "If-Modified-Since", "If-Match",
27 "If-None-Match", "If-Range", "If-Unmodified-Since", "Max-Forwards",
28 "Proxy-Authorization", "Range", "Referer", "User-Agent"};
29
30CHAR EntityTable[NUMENTITIES][17] = {"Allow", "Content-Base", "Content-Encoding",
31 "Content-Language", "Content-Length", "Content-Location", "Content-MD5",
32 "Content-Range", "Content-Type", "ETag", "Expires", "Last-Modified"};
33
34// *************************** CHttpParser ***************************
35
36// Default constructor
38{
39 nHead = 0;
40 nTail = 0;
41}
42
43// Default destructor
45{
46}
47
48// Returns TRUE if a complete HTTP message is in buffer
50{
51 UINT nTmp;
52
53 /*DPRINT("--1:-%d---\n", sBuffer[nHead-2]);
54 DPRINT("--2:-%d---\n", sBuffer[nHead-1]);
55
56 sBuffer[nHead] = '!';
57 sBuffer[nHead+1] = 0;
58 DPRINT("Examining buffer: (Head: %d, Tail: %d)\n", nHead, nTail);
59 DPRINT("%s\n", (LPSTR)&sBuffer[nTail]);*/
60
61 nTmp = nTail;
62 if (!Parse()) {
63 if (!bUnknownMethod)
64 nTail = nTmp;
65 return FALSE;
66 } else
67 return TRUE;
68}
69
70
71// Read a character from buffer
73{
74 if (nTail <= nHead) {
75 if (nTail != nHead) {
76 lpsStr[0] = sBuffer[nTail];
77 nTail++;
78 return TRUE;
79 } else {
80 lpsStr[0] = 0;
81 return FALSE;
82 }
83 } else {
84 if (nTail == sizeof(sBuffer))
85 nTail = 0;
86 if (nTail != nHead) {
87 lpsStr[0] = sBuffer[nTail];
88 nTail++;
89 return TRUE;
90 } else {
91 lpsStr[0] = 0;
92 return FALSE;
93 }
94 }
95}
96
97// Peek at a character in the buffer
99{
100 UINT nFakeTail;
101
102 if (nTail == sizeof(sBuffer))
103 nFakeTail = 0;
104 else
105 nFakeTail = nTail;
106 if (nFakeTail != nHead) {
107 lpsStr[0] = sBuffer[nFakeTail];
108 return TRUE;
109 } else {
110 lpsStr[0] = 0;
111 return FALSE;
112 }
113}
114
115// Read a string from buffer. Only A-Z, a-z, 0-9 and '-' are valid characters
117{
118 UINT i = 0;
119 CHAR sTmp;
120
121 while (PeekChar(&sTmp)) {
122 if (((sTmp >= 'A') && (sTmp <= 'Z')) || ((sTmp >= 'a') && (sTmp <= 'z')) ||
123 ((sTmp >= '0') && (sTmp <= '9')) || (sTmp == '-')) {
124 if (i >= (nLength - 1)) {
125 lpsStr[0] = 0;
126 return FALSE;
127 }
128 ReadChar(&sTmp);
129 lpsStr[i] = sTmp;
130 i++;
131 } else {
132 lpsStr[i] = 0;
133 return TRUE;
134 }
135 }
136 lpsStr[0] = 0;
137 return FALSE;
138}
139
140// Read a string from buffer. Stop if SP or CR is found or when there are no more
141// characters
143{
144 UINT i = 0;
145 CHAR sTmp;
146
147 while (PeekChar(&sTmp) && (sTmp != ' ') && (sTmp != 13)) {
148 if (i >= (nLength - 1)) {
149 lpsStr[nLength - 1] = 0;
150 return FALSE;
151 }
152 ReadChar(&sTmp);
153 lpsStr[i] = sTmp;
154 i++;
155 }
156 lpsStr[i] = 0;
157 return TRUE;
158}
159
160// Skip until "sCh" is found
162{
163 CHAR sTmp;
164
165 while (PeekChar(&sTmp) && (sTmp != sCh))
166 ReadChar(&sTmp);
167}
168
169// Return TRUE if sCh is the next character
171{
172 CHAR sTmp;
173
174 if (PeekChar(&sTmp)) {
175 if (sTmp == sCh) {
176 ReadChar(&sTmp);
177 return TRUE;
178 }
179 }
180 return FALSE;
181}
182
183// Return TRUE if CRLF are the next characters
185{
186 return (Expect(13) && Expect(10));
187}
188
189// Request = RequestLine | *( GenerelHeader | RequestHeader | EntityHeader )
190// CRLF [ MessageBody ]
192{
193 BOOL bStatus;
194
195 if (RequestLine()) {
196 do {
197 if (!ReadString(sHeader, sizeof(sHeader)))
198 break;
199 bStatus = (GenerelHeader());
200 bStatus = (RequestHeader() || bStatus);
201 bStatus = (EntityHeader() || bStatus);
202 } while (bStatus);
203 // CRLF
204 if (!ExpectCRLF())
205 return FALSE;
206 MessageBody();
207 return TRUE;
208 }
209 return FALSE;
210}
211
212// RequestLine = Method SP RequestURI SP HTTP-Version CRLF
214{
215 CHAR sCh;
216 UINT i;
217
219
220 // RFC 2068 states that servers SHOULD ignore any empty nine(s) received where a
221 // Request-Line is expected
222 while (PeekChar(&sCh) && ((sCh == 13) || (sCh == 10)));
223
224 if (!ReadString(sMethod, sizeof(sMethod)))
225 return FALSE;
226
227 for (i = 0; i < NUMMETHODS; i++) {
228 if (strcmp(MethodTable[i], sMethod) == 0) {
229 nMethodNo = i;
230 if (!Expect(' '))
231 return FALSE;
232 // URI (ie. host/directory/resource)
233 if (!ReadSpecial(sUri, sizeof(sUri)))
234 return FALSE;
235 if (!Expect(' '))
236 return FALSE;
237 // HTTP version (eg. HTTP/1.1)
238 if (!ReadSpecial(sVersion, sizeof(sVersion)))
239 return FALSE;
240 // CRLF
241 if (!ExpectCRLF())
242 return FALSE;
243
244 return TRUE;
245 }
246 }
248 return FALSE;
249}
250
251// GenerelHeader = Cache-Control | Connection | Date | Pragma | Transfer-Encoding |
252// Upgrade | Via
254{
255 INT i;
256
257 for (i = 0; i < NUMGENERELS; i++) {
258 if (strcmp(GenerelTable[i], sHeader) == 0) {
259 switch (i) {
260 case 1: {
261 //Connection
262 Expect(':');
263 Expect(' ');
264 Skip(13);
265 ExpectCRLF();
266 break;
267 }
268 default: {
269 Expect(':');
270 Expect(' ');
271 Skip(13);
272 ExpectCRLF();
273 }
274 }
275 return TRUE;
276 }
277 }
278 return FALSE;
279}
280
281// RequestHeader = Accept | Accept-Charset | Accept-Encoding | Accept-Language |
282// Authorization | From | Host | If-Modified-Since | If-Match |
283// If-None-Match | If-Range | If-Unmodified-Since | Max-Forwards |
284// Proxy-Authorization | Range | Referer | User-Agent
286{
287 INT i;
288
289 for (i = 0; i < NUMREQUESTS; i++) {
290 if (strcmp(RequestTable[i], sHeader) == 0) {
291 switch (i) {
292 case 0: {
293 //Accept
294 Expect(':');
295 Expect(' ');
296 Skip(13);
297 ExpectCRLF();
298 break;
299 }
300 case 2: {
301 //Accept-Encoding
302 Expect(':');
303 Expect(' ');
304 Skip(13);
305 ExpectCRLF();
306 break;
307 }
308 case 3: {
309 //Accept-Language
310 Expect(':');
311 Expect(' ');
312 Skip(13);
313 ExpectCRLF();
314 break;
315 }
316 case 6: {
317 //Host
318 Expect(':');
319 Expect(' ');
320 Skip(13);
321 ExpectCRLF();
322 break;
323 }
324 case 16: {
325 //User-Agent
326 Expect(':');
327 Expect(' ');
328 Skip(13);
329 ExpectCRLF();
330 break;
331 }
332 default: {
333 Expect(':');
334 Expect(' ');
335 Skip(13);
336 ExpectCRLF();
337 return TRUE;
338 }
339 }
340 return TRUE;
341 }
342 }
343 return FALSE;
344}
345
346// EntityHeader = Allow | Content-Base | Content-Encoding | Content-Language |
347// Content-Length | Content-Location | Content-MD5 |
348// Content-Range | Content-Type | ETag | Expires |
349// Last-Modified | extension-header
351{
352 INT i;
353
354 for (i = 0; i < NUMENTITIES; i++) {
355 if (strcmp(EntityTable[i], sHeader) == 0) {
356 switch (i) {
357 case 0:
358 default: {
359 //cout << "<Entity-Header>: #" << i << endl;
360 Expect(':');
361 Expect(' ');
362 Skip(13);
363 ExpectCRLF();
364 return TRUE;
365 }
366 }
367 return FALSE;
368 }
369 }
370 return FALSE;
371}
372
373// MessageBody = *OCTET
375{
376 return FALSE;
377}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
BOOL Parse()
Definition: http.cpp:191
CHAR sMethod[63]
Definition: http.h:34
BOOL GenerelHeader()
Definition: http.cpp:253
BOOL MessageBody()
Definition: http.cpp:374
BOOL RequestHeader()
Definition: http.cpp:285
CHttpParser()
Definition: http.cpp:37
CHAR sVersion[15]
Definition: http.h:32
~CHttpParser()
Definition: http.cpp:44
BOOL Expect(CHAR sStr)
Definition: http.cpp:170
BOOL RequestLine()
Definition: http.cpp:213
BOOL PeekChar(LPSTR lpsStr)
Definition: http.cpp:98
BOOL ReadString(LPSTR lpsStr, UINT nLength)
Definition: http.cpp:116
BOOL ReadChar(LPSTR lpsStr)
Definition: http.cpp:72
BOOL ExpectCRLF()
Definition: http.cpp:184
UINT nTail
Definition: http.h:30
CHAR sBuffer[2048]
Definition: http.h:28
BOOL ReadSpecial(LPSTR lpStr, UINT nLength)
Definition: http.cpp:142
UINT nHead
Definition: http.h:29
CHAR sUri[255]
Definition: http.h:31
CHAR sHeader[63]
Definition: http.h:33
BOOL EntityHeader()
Definition: http.cpp:350
UINT nMethodNo
Definition: http.h:35
VOID Skip(CHAR sStr)
Definition: http.cpp:161
BOOL Complete()
Definition: http.cpp:49
BOOL bUnknownMethod
Definition: http.h:36
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
CHAR RequestTable[NUMREQUESTS][20]
Definition: http.cpp:25
CHAR MethodTable[NUMMETHODS][8]
Definition: http.cpp:19
CHAR EntityTable[NUMENTITIES][17]
Definition: http.cpp:30
CHAR GenerelTable[NUMGENERELS][18]
Definition: http.cpp:22
#define NUMMETHODS
Definition: http.h:12
#define NUMGENERELS
Definition: http.h:13
#define NUMENTITIES
Definition: http.h:15
#define NUMREQUESTS
Definition: http.h:14
unsigned int UINT
Definition: ndis.h:50
int32_t INT
Definition: typedefs.h:58
_In_ DWORD nLength
Definition: wincon.h:473
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175