aboutsummaryrefslogtreecommitdiff
path: root/src/cgi.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2006-05-01 17:11:04 +0000
committerMike Buland <eichlan@xagasoft.com>2006-05-01 17:11:04 +0000
commitf7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54 (patch)
tree53cec4864776e07950e3c72f2a990a1017d08045 /src/cgi.cpp
downloadlibbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.tar.gz
libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.tar.bz2
libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.tar.xz
libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.zip
libbu++ is finally laid out the way it should be, trunk, branches, and tags.
Diffstat (limited to 'src/cgi.cpp')
-rw-r--r--src/cgi.cpp644
1 files changed, 644 insertions, 0 deletions
diff --git a/src/cgi.cpp b/src/cgi.cpp
new file mode 100644
index 0000000..1fecbbe
--- /dev/null
+++ b/src/cgi.cpp
@@ -0,0 +1,644 @@
1#include <string.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <stdarg.h>
5#include <sys/stat.h>
6
7#include "cgi.h"
8
9Cgi::Cgi( const char *strSource ) :
10 aContent( new HashFunctionString(), 151, true )
11{
12 int length, j, k, mode = 0, slen = 0;
13 char hexbuf[3] = { 0, 0, 0 };
14 char *buf, chr;
15 Item *cur = NULL;
16 int nCur = 0;
17
18 if( strSource != NULL )
19 {
20 loadContent( strSource );
21 }
22
23 if( ( getenv( "CONTENT_LENGTH" ) ) )
24 {
25 if( !strcmp
26 ( getenv( "CONTENT_TYPE" ),
27 "application/x-www-form-urlencoded" ) )
28 {
29 length = atoi( getenv( "CONTENT_LENGTH" ) );
30 buf = new char[length + 1];
31 fread( buf, 1, length, stdin );
32 cur = new Item( );
33 aVars.append( cur );
34 cur->type = VAR_STDINPUT;
35 for( j = 0; j < length; j++ )
36 {
37 switch ( buf[j] )
38 {
39 case '=':
40 cur->name = new char[slen + 1];
41 slen = 0;
42 break;
43
44 case '&':
45 cur->value = new char[slen + 1];
46 cur->len = slen;
47 slen = 0;
48 cur = new Item( );
49 aVars.append( cur );
50 cur->type = VAR_STDINPUT;
51 break;
52
53 default:
54 switch ( buf[j] )
55 {
56 case '%': /* per-cents mean a hex-code for an ASCII char */
57 j += 2;
58 slen++;
59 break;
60
61 default: /* Nothing special, move along, folks... */
62 slen++;
63 break;
64 }
65 break;
66 }
67 }
68 cur->value = new char[slen + 1];
69 cur->len = slen;
70 slen = 0;
71 mode = 0;
72 cur = ( Item * ) aVars.getAt( 0 );
73 k = 0;
74 nCur = 0;
75 for( j = 0; j < length; j++ )
76 {
77 switch ( buf[j] )
78 {
79 case '=':
80 mode = 1;
81 k = 0;
82 break;
83
84 case '&':
85 mode = 0;
86 k = 0;
87 nCur++;
88 cur = ( Item * ) aVars.getAt( nCur );
89 break;
90
91 default:
92 switch ( buf[j] )
93 {
94 case '%': /* per-cents mean a hex-code for an ASCII char */
95 hexbuf[0] = buf[++j];
96 hexbuf[1] = buf[++j];
97 chr = ( char ) ( strtol( hexbuf, NULL, 16 ) );
98 break;
99
100 case '+': /* Pluses mean spaces, odd, I know... */
101 chr = ' ';
102 break;
103
104 default: /* Nothing special, move along, folks... */
105 chr = buf[j];
106 break;
107 }
108 if( mode == 0 )
109 {
110 cur->name[k] = chr;
111 cur->name[++k] = '\0';
112 }
113 else
114 {
115 cur->value[k] = chr;
116 cur->value[++k] = '\0';
117 }
118 break;
119 }
120 }
121 delete buf;
122 }
123 else if( !strncmp
124 ( getenv( "CONTENT_TYPE" ), "multipart/form-data;", 20 ) )
125 {
126 char *boundary, *oname;
127 int blen, j, k, olen;
128
129 length = atoi( getenv( "CONTENT_LENGTH" ) );
130 buf = new char[length + 1];
131 fread( buf, 1, length, stdin );
132 for( blen = 0; buf[blen + 1] != '\n'; blen++ );
133 boundary = new char[blen + 1];
134 memcpy( boundary, buf, blen );
135 boundary[blen] = '\0';
136 j = blen + 2;
137 for( ;; )
138 {
139 cur = new Item( );
140 aVars.append( cur );
141 cur->type = VAR_STDINPUT;
142 if( !strncmp
143 ( buf + j, "Content-Disposition: form-data; name=\"",
144 38 ) )
145 {
146 j += 38;
147 for( k = 0; buf[j + k] != '\"'; k++ );
148 oname = cur->name = new char[k + 1];
149 memcpy( cur->name, buf + j, k );
150 olen = k;
151 cur->name[k] = '\0';
152 j += k + 1;
153 if( !strncmp( buf + j, "; filename=\"", 12 ) ) /* Must be a file */
154 {
155 /* Acquire file name */
156 j += 12;
157 for( k = 0; buf[j + k] != '\"'; k++ );
158 cur->value = new char[k + 1];
159 memcpy( cur->value, buf + j, k );
160 cur->value[k] = '\0';
161 cur->len = k;
162 j += k + 3;
163
164 /* Acquire content type */
165 if( !strncmp( "Content-Type: ", buf + j, 14 ) )
166 {
167 j += 14;
168 cur = new Item( );
169 aVars.append( cur );
170 cur->type = VAR_STDINPUT;
171 cur->name = new char[olen + 1];
172 memcpy( cur->name, oname, olen + 1 );
173 for( k = 0; buf[j + k + 1] != '\n'; k++ );
174 cur->value = new char[k + 1];
175 memcpy( cur->value, buf + j, k );
176 cur->value[k] = '\0';
177 cur->len = k;
178 j += k;
179 }
180 else
181 {
182 cur = new Item( );
183 aVars.append( cur );
184 cur->type = VAR_STDINPUT;
185 cur->name = new char[olen + 1];
186 memcpy( cur->name, oname, olen + 1 );
187 cur->value = new char[1];
188 cur->value[0] = '\0';
189 cur->len = 0;
190 }
191 j += 4;
192
193 /* Acquire content */
194 cur = new Item( );
195 aVars.append( cur );
196 cur->type = VAR_STDINPUT;
197 cur->name = new char[olen + 1];
198 memcpy( cur->name, oname, olen + 1 );
199 if( !strncmp( buf + j + k, boundary, blen ) )
200 {
201 cur->value = new char[1];
202 cur->value[0] = '\0';
203 j += blen + 4;
204 }
205 else if( !strncmp( buf + j + k + 1, boundary, blen ) )
206 {
207 cur->value = new char[1];
208 cur->value[0] = '\0';
209 j += blen + 5;
210 }
211 else
212 {
213 for( k = 0;
214 strncmp( buf + j + k + 2, boundary, blen );
215 k++ );
216 cur->value = new char[k + 1];
217 memcpy( cur->value, buf + j, k );
218 cur->value[k] = '\0';
219 cur->len = k;
220 j += k + blen + 4;
221 }
222 }
223 else
224 {
225 j += 4;
226 for( k = 0;
227 strncmp( buf + j + k + 2, boundary, blen );
228 k++ );
229 cur->value = new char[k + 1];
230 memcpy( cur->value, buf + j, k );
231 cur->value[k] = '\0';
232 cur->len = k;
233 j += k + blen + 4;
234 }
235 if( buf[j + 1] == '\n' )
236 j += 2;
237 if( j >= length )
238 break;
239 }
240 else
241 {
242 cur->name = ( char * ) "ERROR";
243 cur->value = ( char * ) "Error here";
244 }
245 }
246 }
247 delete buf;
248 }
249
250 if( ( buf = getenv( "HTTP_COOKIE" ) ) )
251 {
252 int lbase = aVars.getSize( );
253 length = strlen( buf );
254 cur = new Item( );
255 aVars.append( cur );
256 cur->type = VAR_COOKIE;
257 for( j = 0; j < length; j++ )
258 {
259 switch ( buf[j] )
260 {
261 case '=':
262 cur->name = new char[slen + 1];
263 slen = 0;
264 break;
265
266 case ';':
267 cur->value = new char[slen + 1];
268 cur->len = slen;
269 slen = 0;
270 cur = new Item( );
271 aVars.append( cur );
272 cur->type = VAR_COOKIE;
273 break;
274
275 default:
276 switch ( buf[j] )
277 {
278 case '%': /* per-cents mean a hex-code for an ASCII char */
279 j += 2;
280 slen++;
281 break;
282
283 default: /* Nothing special, move along, folks... */
284 slen++;
285 break;
286 }
287 break;
288 }
289 }
290 cur->value = new char[slen + 1];
291 cur->len = slen;
292 slen = 0;
293 cur = ( Item * ) aVars.getAt( lbase );
294 mode = 0;
295 k = 0;
296 nCur = lbase;
297 for( j = 0; j < length; j++ )
298 {
299 switch ( buf[j] )
300 {
301 case '=':
302 mode = 1;
303 k = 0;
304 break;
305
306 case ';':
307 mode = 0;
308 k = 0;
309 nCur++;
310 cur = ( Item * ) aVars.getAt( nCur );
311 break;
312
313 default:
314 switch ( buf[j] )
315 {
316 case '%': /* per-cents mean a hex-code for an ASCII char */
317 hexbuf[0] = buf[++j];
318 hexbuf[1] = buf[++j];
319 chr = ( char ) ( strtol( hexbuf, NULL, 16 ) );
320 break;
321
322 case '+': /* Pluses mean spaces, odd, I know... */
323 chr = ' ';
324 break;
325
326 case ' ':
327 continue;
328 break;
329
330 default: /* Nothing special, move along, folks... */
331 chr = buf[j];
332 break;
333 }
334 if( mode == 0 )
335 {
336 cur->name[k] = chr;
337 cur->name[++k] = '\0';
338 }
339 else
340 {
341 cur->value[k] = chr;
342 cur->value[++k] = '\0';
343 }
344 break;
345 }
346 }
347 }
348
349 if( ( buf = getenv( "QUERY_STRING" ) ) )
350 {
351 if( strlen( buf ) > 0 )
352 {
353 int lbase = aVars.getSize( );
354 length = strlen( buf );
355 cur = new Item( );
356 aVars.append( cur );
357 cur->type = VAR_CMDLINE;
358 for( j = 0; j < length; j++ )
359 {
360 switch ( buf[j] )
361 {
362 case '=':
363 cur->name = new char[slen + 1];
364 slen = 0;
365 break;
366
367 case '&':
368 cur->value = new char[slen + 1];
369 cur->len = slen;
370 slen = 0;
371 cur = new Item( );
372 aVars.append( cur );
373 cur->type = VAR_CMDLINE;
374 break;
375
376 default:
377 switch ( buf[j] )
378 {
379 case '%': /* per-cents mean a hex-code for an ASCII char */
380 j += 2;
381 slen++;
382 break;
383
384 default: /* Nothing special, move along, folks... */
385 slen++;
386 break;
387 }
388 break;
389 }
390 }
391 cur->value = new char[slen + 1];
392 cur->len = slen;
393 slen = 0;
394 cur = ( Item * ) aVars.getAt( lbase );
395 nCur = lbase;
396 mode = 0;
397 k = 0;
398 for( j = 0; j < length; j++ )
399 {
400 switch ( buf[j] )
401 {
402 case '=':
403 mode = 1;
404 k = 0;
405 break;
406
407 case '&':
408 mode = 0;
409 k = 0;
410 nCur++;
411 cur = ( Item * ) aVars.getAt( nCur );
412 break;
413
414 default:
415 switch ( buf[j] )
416 {
417 case '%': /* per-cents mean a hex-code for an ASCII char */
418 hexbuf[0] = buf[++j];
419 hexbuf[1] = buf[++j];
420 chr = ( char ) ( strtol( hexbuf, NULL, 16 ) );
421 break;
422
423 case '+': /* Pluses mean spaces, odd, I know... */
424 chr = ' ';
425 break;
426
427 default: /* Nothing special, move along, folks... */
428 chr = buf[j];
429 break;
430 }
431 if( mode == 0 )
432 {
433 cur->name[k] = chr;
434 cur->name[++k] = '\0';
435 }
436 else
437 {
438 cur->value[k] = chr;
439 cur->value[++k] = '\0';
440 }
441 break;
442 }
443 }
444 }
445 }
446}
447
448Cgi::~Cgi( )
449{
450}
451
452char *Cgi::getVarValue( const char *name, int skip, unsigned char type )
453{
454 for( int j = 0; j < aVars.getSize( ); j++ )
455 {
456 Item *cur = ( Item * ) aVars.getAt( j );
457 if( !strcmp( cur->name, name ) )
458 {
459 if( ( cur->type & type ) )
460 {
461 if( skip <= 0 )
462 {
463 return cur->value;
464 }
465 else
466 {
467 skip--;
468 }
469 }
470 }
471 }
472 return NULL;
473}
474
475int Cgi::getVarLength( const char *name, int skip, unsigned char type )
476{
477 for( int j = 0; j < aVars.getSize( ); j++ )
478 {
479 Item *cur = ( Item * ) aVars.getAt( j );
480 if( !strcmp( cur->name, name ) )
481 {
482 if( ( cur->type & type ) )
483 {
484 if( skip <= 0 )
485 {
486 return cur->len;
487 }
488 else
489 {
490 skip--;
491 }
492 }
493 }
494 }
495 return -1;
496}
497
498void Cgi::writeDebugInfo()
499{
500 printf( "<pre>\n" );
501 printf( "0x%02X - stdInput | 0x%02X - cookie | 0x%02X - cmdLine\n\n",
502 VAR_STDINPUT, VAR_COOKIE, VAR_CMDLINE );
503 for( int j = 0; j < aVars.getSize( ); j++ )
504 {
505 Item *item = ( Item * ) aVars.getAt( j );
506 printf("[%s] = \"%s\" [0x%02X]\n", item->name,
507 item->value, item->type );
508 }
509 printf( "</pre>\n" );
510}
511
512void Cgi::writeContentHeader( int type )
513{
514 switch( type )
515 {
516 case headerHTML:
517 printf("Content-type: text/html\n\n");
518 break;
519 }
520}
521
522void Cgi::writeContent( const char *name, ...)
523{
524 char *templ = (char *)aContent.get(name);
525
526 if( templ )
527 {
528 va_list ap;
529
530 va_start (ap, name);
531 vprintf (templ, ap);
532 va_end (ap);
533 }
534 else
535 {
536 printf("Error finding content labeled \"%s\"\n", name );
537 }
538}
539
540void Cgi::loadContent( const char *strSource )
541{
542 FILE *fh = NULL;
543 if( strSource == NULL )
544 {
545 extern char *program_invocation_short_name;
546 char *tmpName = new char[strlen(program_invocation_short_name)+10];
547 memset( tmpName, 0, strlen(program_invocation_short_name)+10 );
548 strcpy( tmpName, program_invocation_short_name );
549 strcat( tmpName, ".content" );
550 fh = fopen( tmpName, "rt" );
551 delete tmpName;
552 }
553 else
554 {
555 fh = fopen( strSource, "rt" );
556 }
557
558 if( fh == NULL ) return;
559
560 struct stat xStats;
561
562 fstat( fileno( fh ), &xStats );
563
564 char *bigBuf = new char[xStats.st_size+1];
565 memset( bigBuf, 0, xStats.st_size+1 );
566 fread( bigBuf, 1, xStats.st_size, fh );
567 fclose( fh );
568
569 // Now we can actually load stuff from the file, first we need to make us up a format...
570 int lSize=0;
571 struct Content
572 {
573 char *name;
574 char *value;
575 } xCont;
576 int j = 0;
577 while( j < xStats.st_size )
578 {
579 // We're looking for a content-block init statement
580 for( ; j < xStats.st_size; j++ )
581 {
582 if( bigBuf[j] == '#' )
583 {
584 if( bigBuf[j+1] == '{' )
585 {
586 break;
587 }
588 }
589 }
590 j=j+2;
591 if( j >= xStats.st_size ) break;
592 for( ; bigBuf[j] == ' ' || bigBuf[j] == '\t'; j++ );
593 for( lSize = 0; lSize+j < xStats.st_size && bigBuf[lSize+j] != '\n' && bigBuf[lSize+j] != '\r'; lSize++ );
594 xCont.name = new char[lSize+1];
595 memset( xCont.name, 0, lSize+1 );
596 memcpy( xCont.name, &bigBuf[j], lSize );
597 j += lSize+1;
598
599 for( lSize = 0; lSize+j < xStats.st_size; lSize++ )
600 {
601 if( bigBuf[lSize+j] == '#' )
602 {
603 if( bigBuf[lSize+j+1] == '}' )
604 {
605 break;
606 }
607 }
608 }
609 xCont.value = new char[lSize+1];
610 memset( xCont.value, 0, lSize+1 );
611 memcpy( xCont.value, &bigBuf[j], lSize );
612
613 aContent.insert( xCont.name, xCont.value );
614
615 j += lSize + 2;
616 }
617}
618
619void Cgi::writeCookie( char const *name, char const *value, char const *expires, char const *path, char const *domain, bool secure )
620{
621 printf("Set-Cookie: %s=%s", name, value );
622
623 if( expires != NULL )
624 {
625 printf("; expires=%s", expires );
626 }
627
628 if( path != NULL )
629 {
630 printf("; path=%s", path );
631 }
632
633 if( domain != NULL )
634 {
635 printf("; domain=%s", domain );
636 }
637
638 if( secure )
639 {
640 printf("; secure");
641 }
642
643 printf("\n");
644}