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 }