src/server/safs/cgi.c

changeset 415
d938228c382e
parent 359
79b28ae7bfbd
child 430
83560f32e7d5
equal deleted inserted replaced
414:99a34860c105 415:d938228c382e
34 34
35 #include <sys/types.h> 35 #include <sys/types.h>
36 #include <signal.h> 36 #include <signal.h>
37 #include <sys/wait.h> 37 #include <sys/wait.h>
38 38
39 #include <ucx/string.h> 39 #include <cx/string.h>
40 40
41 #include "../util/util.h" 41 #include "../util/util.h"
42 #include "../util/pblock.h" 42 #include "../util/pblock.h"
43 #include "../daemon/netsite.h" 43 #include "../daemon/netsite.h"
44 #include "../util/io.h" 44 #include "../util/io.h"
214 p->pid = fork(); 214 p->pid = fork();
215 if(p->pid == 0) { 215 if(p->pid == 0) {
216 // child 216 // child
217 217
218 // get script directory and script name 218 // get script directory and script name
219 sstr_t script = sstr(path); 219 cxstring script = cx_str(path);
220 sstr_t parent; 220 cxmutstr parent;
221 int len = strlen(path); 221 int len = strlen(path);
222 for(int i=len-1;i>=0;i--) { 222 for(int i=len-1;i>=0;i--) {
223 if(path[i] == '/') { 223 if(path[i] == '/') {
224 script = sstrn(path + i + 1, len - i); 224 script = cx_strn(path + i + 1, len - i);
225 parent = sstrdup(sstrn(path, i)); 225 parent = cx_strdup(cx_strn(path, i));
226 if(chdir(parent.ptr)) { 226 if(chdir(parent.ptr)) {
227 perror("cgi_start: chdir"); 227 perror("cgi_start: chdir");
228 free(parent.ptr); 228 free(parent.ptr);
229 exit(-1); 229 exit(-1);
230 } 230 }
279 279
280 CGIResponseParser* cgi_parser_new(Session *sn, Request *rq) { 280 CGIResponseParser* cgi_parser_new(Session *sn, Request *rq) {
281 CGIResponseParser* parser = pool_malloc(sn->pool, sizeof(CGIResponseParser)); 281 CGIResponseParser* parser = pool_malloc(sn->pool, sizeof(CGIResponseParser));
282 parser->sn = sn; 282 parser->sn = sn;
283 parser->rq = rq; 283 parser->rq = rq;
284 parser->tmp = ucx_buffer_new(NULL, 64, UCX_BUFFER_AUTOEXTEND);
285 parser->status = 0; 284 parser->status = 0;
286 parser->msg = NULL; 285 parser->msg = NULL;
286 cxBufferInit(&parser->tmp, NULL, 64, pool_allocator(sn->pool), CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
287 return parser; 287 return parser;
288 } 288 }
289 289
290 void cgi_parser_free(CGIResponseParser *parser) { 290 void cgi_parser_free(CGIResponseParser *parser) {
291 if(parser->tmp) { 291 if(parser->tmp.space) {
292 ucx_buffer_free(parser->tmp); 292 cxBufferDestroy(&parser->tmp);
293 } 293 }
294 pool_free(parser->sn->pool, parser); 294 pool_free(parser->sn->pool, parser);
295 } 295 }
296 296
297 /* 297 /*
300 * 1: successfully parsed lines 300 * 1: successfully parsed lines
301 * 2: cgi response header complete (empty line) 301 * 2: cgi response header complete (empty line)
302 * -1: error 302 * -1: error
303 */ 303 */
304 static int parse_lines(CGIResponseParser *parser, char *buf, size_t len, int *pos) { 304 static int parse_lines(CGIResponseParser *parser, char *buf, size_t len, int *pos) {
305 UcxAllocator a = util_pool_allocator(parser->sn->pool); 305 CxAllocator *a = pool_allocator(parser->sn->pool);
306 sstr_t name; 306 cxmutstr name;
307 sstr_t value; 307 cxmutstr value;
308 WSBool space = TRUE; 308 WSBool space = TRUE;
309 int i; 309 int i;
310 310
311 int line_begin = 0; 311 int line_begin = 0;
312 int value_begin = 0; 312 int value_begin = 0;
313 for(i=0;i<len;i++) { 313 for(i=0;i<len;i++) {
314 char c = buf[i]; 314 char c = buf[i];
315 if(value_begin == line_begin && c == ':') { 315 if(value_begin == line_begin && c == ':') {
316 name = sstrn(buf + line_begin, i - line_begin); 316 name = cx_mutstrn(buf + line_begin, i - line_begin);
317 value_begin = i + 1; 317 value_begin = i + 1;
318 } else if(c == '\n') { 318 } else if(c == '\n') {
319 if(value_begin == line_begin) { 319 if(value_begin == line_begin) {
320 if(space) { 320 if(space) {
321 *pos = i + 1; 321 *pos = i + 1;
323 } else { 323 } else {
324 // line ends with content but without ':' -> error 324 // line ends with content but without ':' -> error
325 return -1; 325 return -1;
326 } 326 }
327 } 327 }
328 value = sstrn(buf + value_begin, i - value_begin); 328 value = cx_mutstrn(buf + value_begin, i - value_begin);
329 329
330 name = sstrlower_a(&a, sstrtrim(name)); 330 cx_strlower(name);
331 value = sstrtrim(value); 331 name = cx_strdup_a(a, cx_strtrim((cxstring){name.ptr, name.length}));
332 value = cx_strtrim_m(value);
332 333
333 if(name.length == 0 || value.length == 0) { 334 if(name.length == 0 || value.length == 0) {
334 return -1; 335 return -1;
335 } 336 }
336 337
337 if(!sstrcmp(name, S("status"))) { 338 if(!cx_strcmp((cxstring){name.ptr, name.length}, (cxstring)CX_STR("status"))) {
338 sstr_t codestr = value; 339 cxmutstr codestr = value;
339 int j; 340 int j;
340 for(j=0;j<codestr.length;j++) { 341 for(j=0;j<codestr.length;j++) {
341 if(!isdigit(codestr.ptr[j])) { 342 if(!isdigit(codestr.ptr[j])) {
342 break; 343 break;
343 } 344 }
349 350
350 int64_t s = 0; 351 int64_t s = 0;
351 util_strtoint(codestr.ptr, &s); 352 util_strtoint(codestr.ptr, &s);
352 parser->status = (int)s; 353 parser->status = (int)s;
353 354
354 sstr_t msg = sstrtrim(sstrsubs(value, j + 1)); 355 cxmutstr msg = cx_strtrim_m(cx_strsubs_m(value, j + 1));
355 356
356 if(msg.length > 0) { 357 if(msg.length > 0) {
357 parser->msg = sstrdup_pool(parser->sn->pool, msg).ptr; 358 parser->msg = cx_strdup_pool(parser->sn->pool, msg).ptr;
358 } 359 }
359 } else { 360 } else {
360 pblock_nvlinsert( 361 pblock_nvlinsert(
361 name.ptr, 362 name.ptr,
362 name.length, 363 name.length,
386 * 1: complete 387 * 1: complete
387 */ 388 */
388 int cgi_parse_response(CGIResponseParser *parser, char *buf, size_t len, size_t *bpos) { 389 int cgi_parse_response(CGIResponseParser *parser, char *buf, size_t len, size_t *bpos) {
389 *bpos = 0; 390 *bpos = 0;
390 int pos = 0; 391 int pos = 0;
391 if(parser->tmp->pos > 0) { 392 if(parser->tmp.pos > 0) {
392 // the tmp buffer contains an unfinished line 393 // the tmp buffer contains an unfinished line
393 // fill up the buffer until the line is complete 394 // fill up the buffer until the line is complete
394 WSBool nb = FALSE; 395 WSBool nb = FALSE;
395 for(pos=0;pos<len;pos++) { 396 for(pos=0;pos<len;pos++) {
396 if(buf[pos] == '\n') { 397 if(buf[pos] == '\n') {
397 nb = TRUE; 398 nb = TRUE;
398 break; 399 break;
399 } 400 }
400 } 401 }
401 ucx_buffer_write(buf, 1, pos, parser->tmp); 402 cxBufferWrite(buf, 1, pos, &parser->tmp);
402 403
403 if(nb) { 404 if(nb) {
404 // line complete 405 // line complete
405 int npos; 406 int npos;
406 int r = parse_lines(parser, parser->tmp->space, parser->tmp->pos, &npos); 407 int r = parse_lines(parser, parser->tmp.space, parser->tmp.pos, &npos);
407 switch(r) { 408 switch(r) {
408 case -1: return -1; 409 case -1: return -1;
409 case 0: return -1; 410 case 0: return -1;
410 case 1: break; 411 case 1: break;
411 case 2: { 412 case 2: {
412 *bpos = pos + 1; 413 *bpos = pos + 1;
413 return 1; 414 return 1;
414 } 415 }
415 } 416 }
416 // reset tmp buffer 417 // reset tmp buffer
417 parser->tmp->pos = 0; 418 parser->tmp.pos = 0;
418 } else { 419 } else {
419 if(parser->tmp->pos > CGI_RESPONSE_MAX_LINE_LENGTH) { 420 if(parser->tmp.pos > CGI_RESPONSE_MAX_LINE_LENGTH) {
420 return -1; 421 return -1;
421 } 422 }
422 } 423 }
423 } 424 }
424 425
428 default: return -1; 429 default: return -1;
429 case 0: 430 case 0:
430 case 1: { 431 case 1: {
431 int newlen = len - npos; 432 int newlen = len - npos;
432 if(npos > 0) { 433 if(npos > 0) {
433 ucx_buffer_write(buf + npos, 1, newlen, parser->tmp); 434 cxBufferWrite(buf + npos, 1, newlen, &parser->tmp);
434 } 435 }
435 return 0; 436 return 0;
436 } 437 }
437 case 2: { 438 case 2: {
438 *bpos = pos + npos; 439 *bpos = pos + npos;

mercurial