ReactOS  0.4.14-dev-1007-g90d795b
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 
19 CHAR MethodTable[NUMMETHODS][8] = {"OPTIONS", "GET", "HEAD", "POST", "PUT",
20  "DELETE", "TRACE"};
21 
22 CHAR GenerelTable[NUMGENERELS][18] = {"Cache-Control", "Connection", "Date", "Pragma",
23  "Transfer-Encoding", "Upgrade", "Via"};
24 
25 CHAR 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 
30 CHAR 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 }
BOOL ReadString(LPSTR lpsStr, UINT nLength)
Definition: http.cpp:116
#define TRUE
Definition: types.h:120
CHAR sHeader[63]
Definition: http.h:33
BOOL Complete()
Definition: http.cpp:49
char CHAR
Definition: xmlstorage.h:175
_In_ DWORD nLength
Definition: wincon.h:476
CHAR sMethod[63]
Definition: http.h:34
CHAR sVersion[15]
Definition: http.h:32
BOOL GenerelHeader()
Definition: http.cpp:253
BOOL bUnknownMethod
Definition: http.h:36
char * LPSTR
Definition: xmlstorage.h:182
int32_t INT
Definition: typedefs.h:57
CHAR EntityTable[NUMENTITIES][17]
Definition: http.cpp:30
BOOL ExpectCRLF()
Definition: http.cpp:184
CHttpParser()
Definition: http.cpp:37
BOOL RequestHeader()
Definition: http.cpp:285
UINT nTail
Definition: http.h:30
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 GenerelTable[NUMGENERELS][18]
Definition: http.cpp:22
BOOL Expect(CHAR sStr)
Definition: http.cpp:170
unsigned int BOOL
Definition: ntddk_ex.h:94
CHAR MethodTable[NUMMETHODS][8]
Definition: http.cpp:19
#define NUMREQUESTS
Definition: http.h:14
BOOL ReadSpecial(LPSTR lpStr, UINT nLength)
Definition: http.cpp:142
BOOL PeekChar(LPSTR lpsStr)
Definition: http.cpp:98
CHAR RequestTable[NUMREQUESTS][20]
Definition: http.cpp:25
#define NUMMETHODS
Definition: http.h:12
CHAR sUri[255]
Definition: http.h:31
BOOL MessageBody()
Definition: http.cpp:374
BOOL RequestLine()
Definition: http.cpp:213
BOOL EntityHeader()
Definition: http.cpp:350
#define NUMENTITIES
Definition: http.h:15
#define NUMGENERELS
Definition: http.h:13
unsigned int UINT
Definition: ndis.h:50
UINT nHead
Definition: http.h:29
BOOL Parse()
Definition: http.cpp:191
UINT nMethodNo
Definition: http.h:35
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
BOOL ReadChar(LPSTR lpsStr)
Definition: http.cpp:72
VOID Skip(CHAR sStr)
Definition: http.cpp:161
CHAR sBuffer[2048]
Definition: http.h:28
~CHttpParser()
Definition: http.cpp:44