Mercurial > urweb
comparison src/c/urweb.c @ 737:d049d31a1966
Initial support for blobs and upload
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sat, 25 Apr 2009 13:59:11 -0400 |
parents | 796e42c93c48 |
children | 4bb7e1c0550a |
comparison
equal
deleted
inserted
replaced
736:796e42c93c48 | 737:d049d31a1966 |
---|---|
280 typedef struct { | 280 typedef struct { |
281 unsigned client; | 281 unsigned client; |
282 buf msgs; | 282 buf msgs; |
283 } delta; | 283 } delta; |
284 | 284 |
285 typedef enum { | |
286 UNSET, NORMAL, FILES | |
287 } input_kind; | |
288 | |
289 typedef struct { | |
290 input_kind kind; | |
291 union { | |
292 char *normal; | |
293 uw_Basis_files files; | |
294 } data; | |
295 } input; | |
296 | |
285 struct uw_context { | 297 struct uw_context { |
286 char *headers, *headers_end; | 298 char *headers, *headers_end; |
287 | 299 |
288 buf outHeaders, page, heap, script; | 300 buf outHeaders, page, heap, script; |
289 char **inputs; | 301 input *inputs; |
290 | 302 |
291 int source_count; | 303 int source_count; |
292 | 304 |
293 void *db; | 305 void *db; |
294 | 306 |
323 buf_init(&ctx->page, 0); | 335 buf_init(&ctx->page, 0); |
324 buf_init(&ctx->heap, 0); | 336 buf_init(&ctx->heap, 0); |
325 buf_init(&ctx->script, 1); | 337 buf_init(&ctx->script, 1); |
326 ctx->script.start[0] = 0; | 338 ctx->script.start[0] = 0; |
327 | 339 |
328 ctx->inputs = calloc(uw_inputs_len, sizeof(char *)); | 340 ctx->inputs = calloc(uw_inputs_len, sizeof(input)); |
329 | 341 |
330 ctx->db = NULL; | 342 ctx->db = NULL; |
331 | 343 |
332 ctx->regions = NULL; | 344 ctx->regions = NULL; |
333 | 345 |
396 ctx->error_message[0] = 0; | 408 ctx->error_message[0] = 0; |
397 } | 409 } |
398 | 410 |
399 void uw_reset(uw_context ctx) { | 411 void uw_reset(uw_context ctx) { |
400 uw_reset_keep_request(ctx); | 412 uw_reset_keep_request(ctx); |
401 memset(ctx->inputs, 0, uw_inputs_len * sizeof(char *)); | 413 memset(ctx->inputs, 0, uw_inputs_len * sizeof(input)); |
402 } | 414 } |
403 | 415 |
404 void uw_db_init(uw_context); | 416 void uw_db_init(uw_context); |
405 void uw_handle(uw_context, char *); | 417 void uw_handle(uw_context, char *); |
406 | 418 |
542 | 554 |
543 char *uw_error_message(uw_context ctx) { | 555 char *uw_error_message(uw_context ctx) { |
544 return ctx->error_message; | 556 return ctx->error_message; |
545 } | 557 } |
546 | 558 |
547 int uw_input_num(char*); | 559 extern int uw_input_num(const char*); |
548 | 560 |
549 void uw_set_input(uw_context ctx, char *name, char *value) { | 561 void uw_set_input(uw_context ctx, const char *name, char *value) { |
550 int n = uw_input_num(name); | 562 int n = uw_input_num(name); |
551 | 563 |
552 if (n < 0) | 564 if (n < 0) |
553 uw_error(ctx, FATAL, "Bad input name %s", name); | 565 uw_error(ctx, FATAL, "Bad input name %s", name); |
554 | 566 |
555 if (n >= uw_inputs_len) | 567 if (n >= uw_inputs_len) |
556 uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n); | 568 uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n); |
557 | 569 |
558 ctx->inputs[n] = value; | 570 ctx->inputs[n].kind = NORMAL; |
559 | 571 ctx->inputs[n].data.normal = value; |
560 //printf("[%d] %s = %s\n", n, name, value); | |
561 } | 572 } |
562 | 573 |
563 char *uw_get_input(uw_context ctx, int n) { | 574 char *uw_get_input(uw_context ctx, int n) { |
564 if (n < 0) | 575 if (n < 0) |
565 uw_error(ctx, FATAL, "Negative input index %d", n); | 576 uw_error(ctx, FATAL, "Negative input index %d", n); |
566 if (n >= uw_inputs_len) | 577 if (n >= uw_inputs_len) |
567 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); | 578 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); |
568 //printf("[%d] = %s\n", n, ctx->inputs[n]); | 579 |
569 return ctx->inputs[n]; | 580 switch (ctx->inputs[n].kind) { |
581 case UNSET: | |
582 return NULL; | |
583 case FILES: | |
584 uw_error(ctx, FATAL, "Tried to read a files form input as normal"); | |
585 case NORMAL: | |
586 return ctx->inputs[n].data.normal; | |
587 default: | |
588 uw_error(ctx, FATAL, "Impossible input kind"); | |
589 } | |
570 } | 590 } |
571 | 591 |
572 char *uw_get_optional_input(uw_context ctx, int n) { | 592 char *uw_get_optional_input(uw_context ctx, int n) { |
573 if (n < 0) | 593 if (n < 0) |
574 uw_error(ctx, FATAL, "Negative input index %d", n); | 594 uw_error(ctx, FATAL, "Negative input index %d", n); |
575 if (n >= uw_inputs_len) | 595 if (n >= uw_inputs_len) |
576 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); | 596 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); |
577 //printf("[%d] = %s\n", n, ctx->inputs[n]); | 597 |
578 return (ctx->inputs[n] == NULL ? "" : ctx->inputs[n]); | 598 switch (ctx->inputs[n].kind) { |
599 case UNSET: | |
600 return ""; | |
601 case FILES: | |
602 uw_error(ctx, FATAL, "Tried to read a files form input as normal"); | |
603 case NORMAL: | |
604 return ctx->inputs[n].data.normal; | |
605 default: | |
606 uw_error(ctx, FATAL, "Impossible input kind"); | |
607 } | |
608 } | |
609 | |
610 void uw_set_file_input(uw_context ctx, const char *name, uw_Basis_files fs) { | |
611 int n = uw_input_num(name); | |
612 | |
613 if (n < 0) | |
614 uw_error(ctx, FATAL, "Bad file input name %s", name); | |
615 | |
616 if (n >= uw_inputs_len) | |
617 uw_error(ctx, FATAL, "For file input name %s, index %d is out of range", name, n); | |
618 | |
619 ctx->inputs[n].kind = FILES; | |
620 ctx->inputs[n].data.files = fs; | |
621 } | |
622 | |
623 uw_Basis_files uw_get_file_input(uw_context ctx, int n) { | |
624 if (n < 0) | |
625 uw_error(ctx, FATAL, "Negative file input index %d", n); | |
626 if (n >= uw_inputs_len) | |
627 uw_error(ctx, FATAL, "Out-of-bounds file input index %d", n); | |
628 | |
629 switch (ctx->inputs[n].kind) { | |
630 case UNSET: | |
631 { | |
632 uw_Basis_files fs = {}; | |
633 return fs; | |
634 } | |
635 case FILES: | |
636 return ctx->inputs[n].data.files; | |
637 case NORMAL: | |
638 uw_error(ctx, FATAL, "Tried to read a normal form input as files"); | |
639 default: | |
640 uw_error(ctx, FATAL, "Impossible input kind"); | |
641 } | |
579 } | 642 } |
580 | 643 |
581 void uw_set_script_header(uw_context ctx, const char *s) { | 644 void uw_set_script_header(uw_context ctx, const char *s) { |
582 ctx->script_header = s; | 645 ctx->script_header = s; |
583 } | 646 } |
1391 ctx->heap.front += len; | 1454 ctx->heap.front += len; |
1392 | 1455 |
1393 return s; | 1456 return s; |
1394 } | 1457 } |
1395 | 1458 |
1396 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) { | 1459 uw_Basis_string uw_strdup(uw_context ctx, uw_Basis_string s1) { |
1397 int len = strlen(s1) + 1; | 1460 int len = strlen(s1) + 1; |
1398 char *s; | 1461 char *s; |
1399 | 1462 |
1400 uw_check_heap(ctx, len); | 1463 uw_check_heap(ctx, len); |
1401 | 1464 |
1405 ctx->heap.front += len; | 1468 ctx->heap.front += len; |
1406 | 1469 |
1407 return s; | 1470 return s; |
1408 } | 1471 } |
1409 | 1472 |
1410 uw_Basis_string uw_Basis_maybe_strdup(uw_context ctx, uw_Basis_string s1) { | 1473 uw_Basis_string uw_maybe_strdup(uw_context ctx, uw_Basis_string s1) { |
1411 if (s1) | 1474 if (s1) |
1412 return uw_Basis_strdup(ctx, s1); | 1475 return uw_strdup(ctx, s1); |
1413 else | 1476 else |
1414 return NULL; | 1477 return NULL; |
1415 } | 1478 } |
1416 | 1479 |
1417 | 1480 |
1475 break; | 1538 break; |
1476 default: | 1539 default: |
1477 if (isprint(c)) | 1540 if (isprint(c)) |
1478 *s2++ = c; | 1541 *s2++ = c; |
1479 else { | 1542 else { |
1480 sprintf(s2, "\\%3o", c); | 1543 sprintf(s2, "\\%03o", c); |
1481 s2 += 4; | 1544 s2 += 4; |
1482 } | 1545 } |
1483 } | 1546 } |
1484 } | 1547 } |
1485 | 1548 |
1486 strcpy(s2, "'::text"); | 1549 strcpy(s2, "'::text"); |
1487 ctx->heap.front = s2 + 8; | 1550 ctx->heap.front = s2 + 8; |
1551 return r; | |
1552 } | |
1553 | |
1554 uw_Basis_string uw_Basis_sqlifyBlob(uw_context ctx, uw_Basis_blob b) { | |
1555 char *r, *s2; | |
1556 size_t i; | |
1557 | |
1558 uw_check_heap(ctx, b.size * 5 + 11); | |
1559 | |
1560 r = s2 = ctx->heap.front; | |
1561 *s2++ = 'E'; | |
1562 *s2++ = '\''; | |
1563 | |
1564 for (i = 0; i < b.size; ++i) { | |
1565 char c = b.data[i]; | |
1566 | |
1567 switch (c) { | |
1568 case '\'': | |
1569 strcpy(s2, "\\'"); | |
1570 s2 += 2; | |
1571 break; | |
1572 case '\\': | |
1573 strcpy(s2, "\\\\\\\\"); | |
1574 s2 += 4; | |
1575 break; | |
1576 default: | |
1577 if (isprint(c)) | |
1578 *s2++ = c; | |
1579 else { | |
1580 sprintf(s2, "\\\\%03o", c); | |
1581 s2 += 5; | |
1582 } | |
1583 } | |
1584 } | |
1585 | |
1586 strcpy(s2, "'::bytea"); | |
1587 ctx->heap.front = s2 + 9; | |
1488 return r; | 1588 return r; |
1489 } | 1589 } |
1490 | 1590 |
1491 char *uw_Basis_sqlifyChannel(uw_context ctx, uw_Basis_channel chn) { | 1591 char *uw_Basis_sqlifyChannel(uw_context ctx, uw_Basis_channel chn) { |
1492 int len; | 1592 int len; |
2018 } | 2118 } |
2019 | 2119 |
2020 uw_Basis_string uw_Basis_sigString(uw_context ctx, uw_unit u) { | 2120 uw_Basis_string uw_Basis_sigString(uw_context ctx, uw_unit u) { |
2021 return uw_cookie_sig(ctx); | 2121 return uw_cookie_sig(ctx); |
2022 } | 2122 } |
2123 | |
2124 uw_Basis_string uw_Basis_fileName(uw_context ctx, uw_Basis_file f) { | |
2125 return f.name; | |
2126 } | |
2127 | |
2128 uw_Basis_blob uw_Basis_fileData(uw_context ctx, uw_Basis_file f) { | |
2129 return f.data; | |
2130 } | |
2131 | |
2132 uw_Basis_int uw_Basis_numFiles(uw_context ctx, uw_Basis_files fs) { | |
2133 return fs.size; | |
2134 } | |
2135 | |
2136 uw_Basis_file uw_Basis_fileNum(uw_context ctx, uw_Basis_files fs, uw_Basis_int n) { | |
2137 if (n < 0 || n >= fs.size) | |
2138 uw_error(ctx, FATAL, "Files index out of bounds"); | |
2139 else | |
2140 return fs.files[n]; | |
2141 } |