aboutsummaryrefslogtreecommitdiff
path: root/src/http.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/http.cpp')
-rw-r--r--src/http.cpp371
1 files changed, 371 insertions, 0 deletions
diff --git a/src/http.cpp b/src/http.cpp
new file mode 100644
index 0000000..11950b7
--- /dev/null
+++ b/src/http.cpp
@@ -0,0 +1,371 @@
1#include <string.h>
2#include <stdlib.h>
3#include "http.h"
4#include "hashfunctionstring.h"
5
6Http::Http( Connection *pConnection ) : hReqHeader( new HashFunctionString(), 100 )
7{
8 pCon = pConnection;
9 nParseState = parseInit;
10}
11
12Http::~Http()
13{
14 for( int j = 0; j < lStrings.getSize(); j++ )
15 {
16 delete (std::string *)lStrings[j];
17 }
18}
19
20bool Http::parseRequest()
21{
22 for(;;)
23 {
24 pCon->readInput();
25 switch( nParseState )
26 {
27 case parseInit:
28 {
29 int nLen = pCon->scanInputFor( CR );
30 if( nLen == -1 )
31 {
32 return false;
33 }
34 else
35 {
36 nReqType = getRequestType( pCon->getInput() );
37 pCon->usedInput( pCon->scanInputFor(' ')+1 );
38
39 nLen = pCon->scanInputFor(' ');
40 sReqURI.append( pCon->getInput(), nLen );
41 pCon->usedInput( nLen+1 );
42
43 if( !strncmp( pCon->getInput(), "HTTP/", 5 ) )
44 {
45 char mbuf[2]={'\0','\0'};
46 unsigned char major, minor;
47
48 pCon->usedInput( 5 );
49 mbuf[0] = pCon->getInput()[0];
50 major = (unsigned char)atoi(mbuf);
51 mbuf[0] = pCon->getInput()[2];
52 minor = (unsigned char)atoi(mbuf);
53 setRequestVersion( major, minor );
54 if( checkRequestVer() )
55 {
56 nParseState = parseHeader;
57 }
58 else
59 {
60 setResponseStatus( statusHTTPVersionNotSupported );
61 printf("Verson not supported.\n");
62 return true;
63 }
64
65 pCon->usedInput( 5 );
66 }
67 else
68 {
69 setResponseStatus( statusBadRequest );
70 }
71
72 //return false;
73 }
74 }
75 break;
76
77 case parseHeader:
78 {
79 int nLen = pCon->scanInputFor( CR );
80 if( nLen == -1 )
81 {
82 return false;
83 }
84 else if( nLen == 0 )
85 {
86 // We've got our double-newline, time for content.
87 pCon->usedInput( 2 );
88 setResponseStatus( statusOK );
89 return true;
90 }
91 else
92 {
93 nLen = pCon->scanInputFor(':');
94 if( nLen == -1 )
95 {
96 printf("No colon? what are you trying to pull?\n");
97 }
98 else
99 {
100 std::string *pName = new std::string( pCon->getInput(), nLen );
101 lStrings.append( pName );
102 pCon->usedInput( nLen+1 );
103
104 nLen = pCon->scanInputFor( CR );
105 std::string *pValue = convSpaceString( pCon->getInput(), nLen );
106 lStrings.append( pValue );
107 pCon->usedInput( nLen+2 );
108
109 hReqHeader.insert(
110 pName->c_str(),
111 pValue->c_str()
112 );
113
114 printf("::%s = \"%s\"\n",
115 pName->c_str(),
116 pValue->c_str()
117 );
118 }
119 }
120 }
121 break;
122
123 case parseFinished:
124 break;
125 }
126 }
127}
128
129bool Http::buildResponse( short nResponseCode, const char *sResponse )
130{
131 if( nResponseCode > 0 )
132 {
133 nResStatus = nResponseCode;
134 }
135
136 if( sResponse == NULL )
137 {
138 sResStatusStr = "uh yeah";
139 }
140 else
141 {
142 sResStatusStr = sResponse;
143 }
144
145 time_t curTime;
146 time( &curTime );
147 gmtime_r( &curTime, &tResTime );
148
149 sServerStr = "YFHttp/0.0.1";
150 bResPersistant = false;
151
152 //char buf[30];
153 //strftime( buf, 30, "%a, %d %b %Y %H:%M:%S GMT", &tResponseTime );
154
155 return true;
156}
157
158bool Http::sendResponse()
159{
160 char buf[256];
161
162 sprintf( buf, "HTTP/1.1 %d %s\r\n", nResStatus, sResStatusStr.c_str() );
163 pCon->appendOutput( buf );
164
165 strftime( buf, 256, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", &tResTime );
166 pCon->appendOutput( buf );
167
168 sprintf( buf, "Server: %s\r\n", sServerStr.c_str() );
169 pCon->appendOutput( buf );
170
171 if( bResPersistant )
172 {
173 }
174 else
175 {
176 pCon->appendOutput("Connection: close\r\n");
177 }
178
179 sprintf( buf, "Content-Type: %s\r\n", sResMime.c_str() );
180 pCon->appendOutput( buf );
181
182 sprintf( buf, "Content-Length: %d\r\n", sResContent.size() );
183 pCon->appendOutput( buf );
184
185 pCon->appendOutput("\r\n");
186
187 pCon->appendOutput( sResContent.c_str(), sResContent.size() );
188
189 return true;
190}
191
192void Http::setResponsePersistant( bool bPersistant )
193{
194 bResPersistant = bPersistant;
195}
196
197void Http::setResponseContent( const char *sMime, const char *sContent, int nLen )
198{
199 sResMime = sMime;
200 sResContent.erase();
201 sResContent.append( sContent, nLen );
202}
203
204std::string *Http::convSpaceString( const char *sStr, int nLen )
205{
206 int nNewLen = 0;
207 bool bStart = true;
208 bool bSpace = false;
209
210 for( int j = 0; j < nLen; j++ )
211 {
212 if( sStr[j] == ' ' || sStr[j] == '\t' )
213 {
214 if( bStart )
215 {
216 }
217 else if( bSpace == false )
218 {
219 bSpace = true;
220 nNewLen++;
221 }
222 }
223 else
224 {
225 bStart = false;
226 bSpace = false;
227 nNewLen++;
228 }
229 }
230 if( bSpace )
231 {
232 nNewLen--;
233 }
234
235 std::string *pSStr = new std::string;
236 //char *pStr = pSStr->c_str();
237 nNewLen = 0;
238 bStart = true;
239 bSpace = false;
240
241 for( int j = 0; j < nLen; j++ )
242 {
243 if( sStr[j] == ' ' || sStr[j] == '\t' )
244 {
245 if( bStart )
246 {
247 }
248 else if( bSpace == false )
249 {
250 bSpace = true;
251 *pSStr += ' ';
252 //pStr[nNewLen++] = ' ';
253 }
254 }
255 else
256 {
257 bStart = false;
258 bSpace = false;
259 *pSStr += sStr[j];
260 //pStr[nNewLen++] = sStr[j];
261 }
262 }
263 if( bSpace == true )
264 {
265 nNewLen--;
266// pStr[nNewLen] = '\0';
267 }
268
269 return pSStr;
270}
271
272const char *Http::getRequestURI()
273{
274 return sReqURI.c_str();
275}
276
277short Http::getRequestType( const char *sType )
278{
279 if( !strncmp( sType, "OPTIONS", 7 ) )
280 {
281 return reqOptions;
282 }
283 else if( !strncmp( sType, "GET", 3 ) )
284 {
285 return reqGet;
286 }
287 else if( !strncmp( sType, "HEAD", 4 ) )
288 {
289 return reqHead;
290 }
291 else if( !strncmp( sType, "POST", 4 ) )
292 {
293 return reqPost;
294 }
295 else if( !strncmp( sType, "PUT", 3 ) )
296 {
297 return reqPut;
298 }
299 else if( !strncmp( sType, "DELETE", 6 ) )
300 {
301 return reqDelete;
302 }
303 else if( !strncmp( sType, "TRACE", 5 ) )
304 {
305 return reqTrace;
306 }
307 else if( !strncmp( sType, "CONNECT", 7 ) )
308 {
309 return reqConnect;
310 }
311 else
312 {
313 printf(" Uh oh, extension!\n");
314 return reqExtension;
315 }
316}
317
318const char *Http::getRequestType( short nType )
319{
320 switch( nType )
321 {
322 case reqOptions: return "OPTIONS";
323 case reqGet: return "GET";
324 case reqHead: return "HEAD";
325 case reqPost: return "POST";
326 case reqPut: return "PUT";
327 case reqDelete: return "DELETE";
328 case reqTrace: return "TRACE";
329 case reqConnect: return "CONNECT";
330 case reqExtension: return "EXTENSION";
331 default: return "INVALID VALUE";
332 }
333}
334
335short Http::getRequestType()
336{
337 return nReqType;
338}
339
340const char *Http::getRequestTypeStr()
341{
342 return getRequestType( nReqType );
343}
344
345void Http::setResponseStatus( short nStatus )
346{
347 nResStatus = nStatus;
348}
349
350void Http::setRequestVersion( unsigned char nMajor, unsigned char nMinor )
351{
352 cReqVersion = (nMajor<<4)|nMinor;
353}
354
355unsigned char Http::getRequestMinorVer()
356{
357 return cReqVersion&0x0F;
358}
359
360unsigned char Http::getRequestMajorVer()
361{
362 return cReqVersion>>4;
363}
364
365bool Http::checkRequestVer()
366{
367 if( cReqVersion == HTTP11 )
368 return true;
369 return false;
370}
371