Mercurial > urweb
diff 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 |
line wrap: on
line diff
--- a/src/c/urweb.c Thu Apr 23 16:13:02 2009 -0400 +++ b/src/c/urweb.c Sat Apr 25 13:59:11 2009 -0400 @@ -282,11 +282,23 @@ buf msgs; } delta; +typedef enum { + UNSET, NORMAL, FILES +} input_kind; + +typedef struct { + input_kind kind; + union { + char *normal; + uw_Basis_files files; + } data; +} input; + struct uw_context { char *headers, *headers_end; buf outHeaders, page, heap, script; - char **inputs; + input *inputs; int source_count; @@ -325,7 +337,7 @@ buf_init(&ctx->script, 1); ctx->script.start[0] = 0; - ctx->inputs = calloc(uw_inputs_len, sizeof(char *)); + ctx->inputs = calloc(uw_inputs_len, sizeof(input)); ctx->db = NULL; @@ -398,7 +410,7 @@ void uw_reset(uw_context ctx) { uw_reset_keep_request(ctx); - memset(ctx->inputs, 0, uw_inputs_len * sizeof(char *)); + memset(ctx->inputs, 0, uw_inputs_len * sizeof(input)); } void uw_db_init(uw_context); @@ -544,9 +556,9 @@ return ctx->error_message; } -int uw_input_num(char*); +extern int uw_input_num(const char*); -void uw_set_input(uw_context ctx, char *name, char *value) { +void uw_set_input(uw_context ctx, const char *name, char *value) { int n = uw_input_num(name); if (n < 0) @@ -555,9 +567,8 @@ if (n >= uw_inputs_len) uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n); - ctx->inputs[n] = value; - - //printf("[%d] %s = %s\n", n, name, value); + ctx->inputs[n].kind = NORMAL; + ctx->inputs[n].data.normal = value; } char *uw_get_input(uw_context ctx, int n) { @@ -565,8 +576,17 @@ uw_error(ctx, FATAL, "Negative input index %d", n); if (n >= uw_inputs_len) uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); - //printf("[%d] = %s\n", n, ctx->inputs[n]); - return ctx->inputs[n]; + + switch (ctx->inputs[n].kind) { + case UNSET: + return NULL; + case FILES: + uw_error(ctx, FATAL, "Tried to read a files form input as normal"); + case NORMAL: + return ctx->inputs[n].data.normal; + default: + uw_error(ctx, FATAL, "Impossible input kind"); + } } char *uw_get_optional_input(uw_context ctx, int n) { @@ -574,8 +594,51 @@ uw_error(ctx, FATAL, "Negative input index %d", n); if (n >= uw_inputs_len) uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); - //printf("[%d] = %s\n", n, ctx->inputs[n]); - return (ctx->inputs[n] == NULL ? "" : ctx->inputs[n]); + + switch (ctx->inputs[n].kind) { + case UNSET: + return ""; + case FILES: + uw_error(ctx, FATAL, "Tried to read a files form input as normal"); + case NORMAL: + return ctx->inputs[n].data.normal; + default: + uw_error(ctx, FATAL, "Impossible input kind"); + } +} + +void uw_set_file_input(uw_context ctx, const char *name, uw_Basis_files fs) { + int n = uw_input_num(name); + + if (n < 0) + uw_error(ctx, FATAL, "Bad file input name %s", name); + + if (n >= uw_inputs_len) + uw_error(ctx, FATAL, "For file input name %s, index %d is out of range", name, n); + + ctx->inputs[n].kind = FILES; + ctx->inputs[n].data.files = fs; +} + +uw_Basis_files uw_get_file_input(uw_context ctx, int n) { + if (n < 0) + uw_error(ctx, FATAL, "Negative file input index %d", n); + if (n >= uw_inputs_len) + uw_error(ctx, FATAL, "Out-of-bounds file input index %d", n); + + switch (ctx->inputs[n].kind) { + case UNSET: + { + uw_Basis_files fs = {}; + return fs; + } + case FILES: + return ctx->inputs[n].data.files; + case NORMAL: + uw_error(ctx, FATAL, "Tried to read a normal form input as files"); + default: + uw_error(ctx, FATAL, "Impossible input kind"); + } } void uw_set_script_header(uw_context ctx, const char *s) { @@ -1393,7 +1456,7 @@ return s; } -uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) { +uw_Basis_string uw_strdup(uw_context ctx, uw_Basis_string s1) { int len = strlen(s1) + 1; char *s; @@ -1407,9 +1470,9 @@ return s; } -uw_Basis_string uw_Basis_maybe_strdup(uw_context ctx, uw_Basis_string s1) { +uw_Basis_string uw_maybe_strdup(uw_context ctx, uw_Basis_string s1) { if (s1) - return uw_Basis_strdup(ctx, s1); + return uw_strdup(ctx, s1); else return NULL; } @@ -1477,7 +1540,7 @@ if (isprint(c)) *s2++ = c; else { - sprintf(s2, "\\%3o", c); + sprintf(s2, "\\%03o", c); s2 += 4; } } @@ -1488,6 +1551,43 @@ return r; } +uw_Basis_string uw_Basis_sqlifyBlob(uw_context ctx, uw_Basis_blob b) { + char *r, *s2; + size_t i; + + uw_check_heap(ctx, b.size * 5 + 11); + + r = s2 = ctx->heap.front; + *s2++ = 'E'; + *s2++ = '\''; + + for (i = 0; i < b.size; ++i) { + char c = b.data[i]; + + switch (c) { + case '\'': + strcpy(s2, "\\'"); + s2 += 2; + break; + case '\\': + strcpy(s2, "\\\\\\\\"); + s2 += 4; + break; + default: + if (isprint(c)) + *s2++ = c; + else { + sprintf(s2, "\\\\%03o", c); + s2 += 5; + } + } + } + + strcpy(s2, "'::bytea"); + ctx->heap.front = s2 + 9; + return r; +} + char *uw_Basis_sqlifyChannel(uw_context ctx, uw_Basis_channel chn) { int len; char *r; @@ -2020,3 +2120,22 @@ uw_Basis_string uw_Basis_sigString(uw_context ctx, uw_unit u) { return uw_cookie_sig(ctx); } + +uw_Basis_string uw_Basis_fileName(uw_context ctx, uw_Basis_file f) { + return f.name; +} + +uw_Basis_blob uw_Basis_fileData(uw_context ctx, uw_Basis_file f) { + return f.data; +} + +uw_Basis_int uw_Basis_numFiles(uw_context ctx, uw_Basis_files fs) { + return fs.size; +} + +uw_Basis_file uw_Basis_fileNum(uw_context ctx, uw_Basis_files fs, uw_Basis_int n) { + if (n < 0 || n >= fs.size) + uw_error(ctx, FATAL, "Files index out of bounds"); + else + return fs.files[n]; +}