annotate src/c/urweb.c @ 463:bb27c7efcd90

Reading cookies works
author Adam Chlipala <adamc@hcoop.net>
date Thu, 06 Nov 2008 12:08:41 -0500
parents 21bb5bbba2e9
children 91914c15a85b
rev   line source
adamc@436 1 #define _XOPEN_SOURCE
adamc@436 2
adamc@117 3 #include <stdlib.h>
adamc@102 4 #include <stdio.h>
adamc@117 5 #include <string.h>
adamc@457 6 #include <strings.h>
adamc@106 7 #include <ctype.h>
adamc@167 8 #include <setjmp.h>
adamc@167 9 #include <stdarg.h>
adamc@102 10
adamc@102 11 #include "types.h"
adamc@102 12
adamc@311 13 uw_unit uw_unit_v = {};
adamc@102 14
adamc@167 15 #define ERROR_BUF_LEN 1024
adamc@167 16
adamc@323 17 typedef struct regions {
adamc@323 18 struct regions *next;
adamc@323 19 } regions;
adamc@323 20
adamc@425 21 typedef struct {
adamc@425 22 void (*func)(void*);
adamc@425 23 void *arg;
adamc@425 24 } cleanup;
adamc@425 25
adamc@311 26 struct uw_context {
adamc@458 27 char *headers, *headers_end;
adamc@457 28
adamc@462 29 char *outHeaders, *outHeaders_front, *outHeaders_back;
adamc@117 30 char *page, *page_front, *page_back;
adamc@136 31 char *heap, *heap_front, *heap_back;
adamc@144 32 char **inputs;
adamc@167 33
adamc@272 34 void *db;
adamc@272 35
adamc@167 36 jmp_buf jmp_buf;
adamc@167 37
adamc@323 38 regions *regions;
adamc@323 39
adamc@425 40 cleanup *cleanup, *cleanup_front, *cleanup_back;
adamc@425 41
adamc@167 42 char error_message[ERROR_BUF_LEN];
adamc@117 43 };
adamc@117 44
adamc@311 45 extern int uw_inputs_len;
adamc@144 46
adamc@462 47 uw_context uw_init(size_t outHeaders_len, size_t page_len, size_t heap_len) {
adamc@311 48 uw_context ctx = malloc(sizeof(struct uw_context));
adamc@136 49
adamc@458 50 ctx->headers = ctx->headers_end = NULL;
adamc@457 51
adamc@462 52 ctx->outHeaders_front = ctx->outHeaders = malloc(outHeaders_len);
adamc@462 53 ctx->outHeaders_back = ctx->outHeaders_front + outHeaders_len;
adamc@462 54
adamc@462 55 ctx->heap_front = ctx->heap = malloc(heap_len);
adamc@462 56
adamc@117 57 ctx->page_front = ctx->page = malloc(page_len);
adamc@117 58 ctx->page_back = ctx->page_front + page_len;
adamc@136 59
adamc@136 60 ctx->heap_front = ctx->heap = malloc(heap_len);
adamc@136 61 ctx->heap_back = ctx->heap_front + heap_len;
adamc@136 62
adamc@311 63 ctx->inputs = calloc(uw_inputs_len, sizeof(char *));
adamc@144 64
adamc@272 65 ctx->db = NULL;
adamc@272 66
adamc@323 67 ctx->regions = NULL;
adamc@323 68
adamc@425 69 ctx->cleanup_front = ctx->cleanup_back = ctx->cleanup = malloc(0);
adamc@425 70
adamc@167 71 ctx->error_message[0] = 0;
adamc@167 72
adamc@117 73 return ctx;
adamc@106 74 }
adamc@106 75
adamc@311 76 void uw_set_db(uw_context ctx, void *db) {
adamc@272 77 ctx->db = db;
adamc@272 78 }
adamc@272 79
adamc@311 80 void *uw_get_db(uw_context ctx) {
adamc@272 81 return ctx->db;
adamc@272 82 }
adamc@272 83
adamc@311 84 void uw_free(uw_context ctx) {
adamc@462 85 free(ctx->outHeaders);
adamc@117 86 free(ctx->page);
adamc@136 87 free(ctx->heap);
adamc@144 88 free(ctx->inputs);
adamc@425 89 free(ctx->cleanup);
adamc@136 90 free(ctx);
adamc@136 91 }
adamc@136 92
adamc@311 93 void uw_reset_keep_request(uw_context ctx) {
adamc@462 94 ctx->outHeaders_front = ctx->outHeaders;
adamc@138 95 ctx->page_front = ctx->page;
adamc@138 96 ctx->heap_front = ctx->heap;
adamc@323 97 ctx->regions = NULL;
adamc@425 98 ctx->cleanup_front = ctx->cleanup;
adamc@167 99
adamc@167 100 ctx->error_message[0] = 0;
adamc@167 101 }
adamc@167 102
adamc@311 103 void uw_reset_keep_error_message(uw_context ctx) {
adamc@462 104 ctx->outHeaders_front = ctx->outHeaders;
adamc@167 105 ctx->page_front = ctx->page;
adamc@167 106 ctx->heap_front = ctx->heap;
adamc@323 107 ctx->regions = NULL;
adamc@425 108 ctx->cleanup_front = ctx->cleanup;
adamc@167 109 }
adamc@167 110
adamc@311 111 void uw_reset(uw_context ctx) {
adamc@311 112 uw_reset_keep_request(ctx);
adamc@311 113 memset(ctx->inputs, 0, uw_inputs_len * sizeof(char *));
adamc@144 114 }
adamc@144 115
adamc@311 116 void uw_db_init(uw_context);
adamc@311 117 void uw_handle(uw_context, char *);
adamc@167 118
adamc@311 119 failure_kind uw_begin_init(uw_context ctx) {
adamc@272 120 int r = setjmp(ctx->jmp_buf);
adamc@272 121
adamc@272 122 if (r == 0)
adamc@311 123 uw_db_init(ctx);
adamc@272 124
adamc@272 125 return r;
adamc@272 126 }
adamc@272 127
adamc@458 128 void uw_set_headers(uw_context ctx, char *headers) {
adamc@458 129 char *s = headers, *s2;
adamc@458 130 ctx->headers = headers;
adamc@458 131
adamc@458 132 while (s2 = strchr(s, '\r')) {
adamc@458 133 s = s2;
adamc@458 134
adamc@458 135 if (s[1] == 0)
adamc@458 136 break;
adamc@458 137
adamc@458 138 *s = 0;
adamc@458 139 s += 2;
adamc@458 140 }
adamc@458 141
adamc@458 142 ctx->headers_end = s;
adamc@458 143 }
adamc@458 144
adamc@458 145 failure_kind uw_begin(uw_context ctx, char *path) {
adamc@190 146 int r = setjmp(ctx->jmp_buf);
adamc@190 147
adamc@190 148 if (r == 0)
adamc@311 149 uw_handle(ctx, path);
adamc@167 150
adamc@190 151 return r;
adamc@167 152 }
adamc@167 153
adamc@311 154 __attribute__((noreturn)) void uw_error(uw_context ctx, failure_kind fk, const char *fmt, ...) {
adamc@425 155 cleanup *cl;
adamc@425 156
adamc@167 157 va_list ap;
adamc@167 158 va_start(ap, fmt);
adamc@167 159
adamc@167 160 vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap);
adamc@167 161
adamc@425 162 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
adamc@425 163 cl->func(cl->arg);
adamc@425 164
adamc@425 165 ctx->cleanup_front = ctx->cleanup;
adamc@425 166
adamc@190 167 longjmp(ctx->jmp_buf, fk);
adamc@167 168 }
adamc@167 169
adamc@425 170 void uw_push_cleanup(uw_context ctx, void (*func)(void *), void *arg) {
adamc@425 171 if (ctx->cleanup_front >= ctx->cleanup_back) {
adamc@425 172 int len = ctx->cleanup_back - ctx->cleanup, newLen;
adamc@425 173 if (len == 0)
adamc@425 174 newLen = 1;
adamc@425 175 else
adamc@428 176 newLen = len * 2;
adamc@425 177 ctx->cleanup = realloc(ctx->cleanup, newLen);
adamc@425 178 ctx->cleanup_front = ctx->cleanup + len;
adamc@425 179 ctx->cleanup_back = ctx->cleanup + newLen;
adamc@425 180 }
adamc@425 181
adamc@425 182 ctx->cleanup_front->func = func;
adamc@425 183 ctx->cleanup_front->arg = arg;
adamc@425 184 ++ctx->cleanup_front;
adamc@425 185 }
adamc@425 186
adamc@425 187 void uw_pop_cleanup(uw_context ctx) {
adamc@425 188 if (ctx->cleanup_front == ctx->cleanup)
adamc@425 189 uw_error(ctx, FATAL, "Attempt to pop from empty cleanup action stack");
adamc@425 190
adamc@425 191 --ctx->cleanup_front;
adamc@425 192 ctx->cleanup_front->func(ctx->cleanup_front->arg);
adamc@425 193 }
adamc@425 194
adamc@311 195 char *uw_error_message(uw_context ctx) {
adamc@167 196 return ctx->error_message;
adamc@167 197 }
adamc@167 198
adamc@311 199 int uw_input_num(char*);
adamc@144 200
adamc@311 201 void uw_set_input(uw_context ctx, char *name, char *value) {
adamc@311 202 int n = uw_input_num(name);
adamc@144 203
adamc@169 204 if (n < 0)
adamc@311 205 uw_error(ctx, FATAL, "Bad input name %s", name);
adamc@144 206
adamc@311 207 if (n >= uw_inputs_len)
adamc@311 208 uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n);
adamc@169 209
adamc@144 210 ctx->inputs[n] = value;
adamc@144 211
adamc@282 212 //printf("[%d] %s = %s\n", n, name, value);
adamc@144 213 }
adamc@144 214
adamc@311 215 char *uw_get_input(uw_context ctx, int n) {
adamc@169 216 if (n < 0)
adamc@311 217 uw_error(ctx, FATAL, "Negative input index %d", n);
adamc@311 218 if (n >= uw_inputs_len)
adamc@311 219 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
adamc@282 220 //printf("[%d] = %s\n", n, ctx->inputs[n]);
adamc@144 221 return ctx->inputs[n];
adamc@138 222 }
adamc@138 223
adamc@311 224 char *uw_get_optional_input(uw_context ctx, int n) {
adamc@190 225 if (n < 0)
adamc@311 226 uw_error(ctx, FATAL, "Negative input index %d", n);
adamc@311 227 if (n >= uw_inputs_len)
adamc@311 228 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
adamc@426 229 //printf("[%d] = %s\n", n, ctx->inputs[n]);
adamc@190 230 return (ctx->inputs[n] == NULL ? "" : ctx->inputs[n]);
adamc@190 231 }
adamc@190 232
adamc@311 233 static void uw_check_heap(uw_context ctx, size_t extra) {
adamc@136 234 if (ctx->heap_back - ctx->heap_front < extra) {
adamc@321 235 size_t desired = ctx->heap_front - ctx->heap + extra, next;
adamc@136 236 char *new_heap;
adamc@136 237
adamc@317 238 next = ctx->heap_back - ctx->heap;
adamc@317 239 if (next == 0)
adamc@317 240 next = 1;
adamc@317 241 for (; next < desired; next *= 2);
adamc@136 242
adamc@136 243 new_heap = realloc(ctx->heap, next);
adamc@321 244 ctx->heap_front = new_heap + (ctx->heap_front - ctx->heap);
adamc@169 245 ctx->heap_back = new_heap + next;
adamc@136 246
adamc@136 247 if (new_heap != ctx->heap) {
adamc@136 248 ctx->heap = new_heap;
adamc@311 249 uw_error(ctx, UNLIMITED_RETRY, "Couldn't allocate new heap chunk contiguously");
adamc@136 250 }
adamc@136 251
adamc@169 252 ctx->heap = new_heap;
adamc@136 253 }
adamc@136 254 }
adamc@136 255
adamc@311 256 void *uw_malloc(uw_context ctx, size_t len) {
adamc@136 257 void *result;
adamc@136 258
adamc@311 259 uw_check_heap(ctx, len);
adamc@136 260
adamc@136 261 result = ctx->heap_front;
adamc@136 262 ctx->heap_front += len;
adamc@136 263 return result;
adamc@117 264 }
adamc@117 265
adamc@323 266 void uw_begin_region(uw_context ctx) {
adamc@323 267 regions *r = (regions *) ctx->heap_front;
adamc@323 268
adamc@323 269 uw_check_heap(ctx, sizeof(regions));
adamc@323 270
adamc@323 271 ctx->heap_front += sizeof(regions);
adamc@323 272
adamc@323 273 r->next = ctx->regions;
adamc@323 274 ctx->regions = r;
adamc@323 275 }
adamc@323 276
adamc@323 277 void uw_end_region(uw_context ctx) {
adamc@323 278 regions *r = ctx->regions;
adamc@323 279
adamc@323 280 if (r == NULL)
adamc@323 281 uw_error(ctx, FATAL, "Region stack underflow");
adamc@323 282
adamc@323 283 ctx->heap_front = (char *) r;
adamc@323 284 ctx->regions = r->next;
adamc@323 285 }
adamc@323 286
adamc@324 287 void uw_memstats(uw_context ctx) {
adamc@462 288 printf("Headers: %d/%d\n", ctx->outHeaders_front - ctx->outHeaders, ctx->outHeaders_back - ctx->outHeaders);
adamc@324 289 printf("Page: %d/%d\n", ctx->page_front - ctx->page, ctx->page_back - ctx->page);
adamc@324 290 printf("Heap: %d/%d\n", ctx->heap_front - ctx->heap, ctx->heap_back - ctx->heap);
adamc@324 291 }
adamc@324 292
adamc@436 293 int uw_really_send(int sock, const void *buf, size_t len) {
adamc@117 294 while (len > 0) {
adamc@436 295 size_t n = send(sock, buf, len, 0);
adamc@117 296
adamc@117 297 if (n < 0)
adamc@117 298 return n;
adamc@117 299
adamc@117 300 buf += n;
adamc@117 301 len -= n;
adamc@117 302 }
adamc@117 303
adamc@117 304 return 0;
adamc@117 305 }
adamc@117 306
adamc@311 307 int uw_send(uw_context ctx, int sock) {
adamc@462 308 int n = uw_really_send(sock, ctx->outHeaders, ctx->outHeaders_front - ctx->outHeaders);
adamc@462 309
adamc@462 310 if (n < 0)
adamc@462 311 return n;
adamc@462 312
adamc@462 313 n = uw_really_send(sock, "\r\n", 2);
adamc@462 314
adamc@462 315 if (n < 0)
adamc@462 316 return n;
adamc@462 317
adamc@462 318 n = uw_really_send(sock, "<html>", 6);
adamc@462 319
adamc@462 320 if (n < 0)
adamc@462 321 return n;
adamc@462 322
adamc@462 323 n = uw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
adamc@462 324
adamc@462 325 if (n < 0)
adamc@462 326 return n;
adamc@462 327
adamc@462 328 return uw_really_send(sock, "</html>", 7);
adamc@462 329 }
adamc@462 330
adamc@462 331 static void uw_check_headers(uw_context ctx, size_t extra) {
adamc@462 332 size_t desired = ctx->outHeaders_front - ctx->outHeaders + extra, next;
adamc@462 333 char *new_outHeaders;
adamc@462 334
adamc@462 335 next = ctx->outHeaders_back - ctx->outHeaders;
adamc@462 336 if (next < desired) {
adamc@462 337 if (next == 0)
adamc@462 338 next = 1;
adamc@462 339 for (; next < desired; next *= 2);
adamc@462 340
adamc@462 341 new_outHeaders = realloc(ctx->outHeaders, next);
adamc@462 342 ctx->outHeaders_front = new_outHeaders + (ctx->outHeaders_front - ctx->outHeaders);
adamc@462 343 ctx->outHeaders_back = new_outHeaders + next;
adamc@462 344 ctx->outHeaders = new_outHeaders;
adamc@462 345 }
adamc@462 346 }
adamc@462 347
adamc@462 348 void uw_write_header(uw_context ctx, uw_Basis_string s) {
adamc@462 349 int len = strlen(s);
adamc@462 350
adamc@462 351 uw_check_headers(ctx, len + 1);
adamc@462 352 strcpy(ctx->outHeaders_front, s);
adamc@462 353 ctx->outHeaders_front += len;
adamc@117 354 }
adamc@117 355
adamc@311 356 static void uw_check(uw_context ctx, size_t extra) {
adamc@321 357 size_t desired = ctx->page_front - ctx->page + extra, next;
adamc@117 358 char *new_page;
adamc@117 359
adamc@317 360 next = ctx->page_back - ctx->page;
adamc@428 361 if (next < desired) {
adamc@428 362 if (next == 0)
adamc@428 363 next = 1;
adamc@428 364 for (; next < desired; next *= 2);
adamc@117 365
adamc@428 366 new_page = realloc(ctx->page, next);
adamc@428 367 ctx->page_front = new_page + (ctx->page_front - ctx->page);
adamc@428 368 ctx->page_back = new_page + next;
adamc@428 369 ctx->page = new_page;
adamc@428 370 }
adamc@117 371 }
adamc@117 372
adamc@311 373 static void uw_writec_unsafe(uw_context ctx, char c) {
adamc@117 374 *(ctx->page_front)++ = c;
adamc@117 375 }
adamc@117 376
adamc@311 377 void uw_writec(uw_context ctx, char c) {
adamc@311 378 uw_check(ctx, 1);
adamc@311 379 uw_writec_unsafe(ctx, c);
adamc@117 380 }
adamc@117 381
adamc@311 382 static void uw_write_unsafe(uw_context ctx, const char* s) {
adamc@117 383 int len = strlen(s);
adamc@117 384 memcpy(ctx->page_front, s, len);
adamc@117 385 ctx->page_front += len;
adamc@117 386 }
adamc@117 387
adamc@311 388 void uw_write(uw_context ctx, const char* s) {
adamc@311 389 uw_check(ctx, strlen(s) + 1);
adamc@311 390 uw_write_unsafe(ctx, s);
adamc@183 391 *ctx->page_front = 0;
adamc@102 392 }
adamc@106 393
adamc@135 394
adamc@311 395 char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) {
adamc@136 396 char *result;
adamc@136 397 int len;
adamc@311 398 uw_check_heap(ctx, INTS_MAX);
adamc@136 399 result = ctx->heap_front;
adamc@276 400 sprintf(result, "%lld%n", n, &len);
adamc@137 401 ctx->heap_front += len+1;
adamc@136 402 return result;
adamc@106 403 }
adamc@106 404
adamc@311 405 char *uw_Basis_attrifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@136 406 char *result;
adamc@136 407 int len;
adamc@311 408 uw_check_heap(ctx, FLOATS_MAX);
adamc@136 409 result = ctx->heap_front;
adamc@136 410 sprintf(result, "%g%n", n, &len);
adamc@137 411 ctx->heap_front += len+1;
adamc@136 412 return result;
adamc@106 413 }
adamc@106 414
adamc@311 415 char *uw_Basis_attrifyString(uw_context ctx, uw_Basis_string s) {
adamc@136 416 int len = strlen(s);
adamc@136 417 char *result, *p;
adamc@311 418 uw_check_heap(ctx, len * 6 + 1);
adamc@136 419
adamc@136 420 result = p = ctx->heap_front;
adamc@136 421
adamc@136 422 for (; *s; s++) {
adamc@136 423 char c = *s;
adamc@136 424
adamc@136 425 if (c == '"') {
adamc@136 426 strcpy(p, "&quot;");
adamc@136 427 p += 6;
adamc@136 428 } else if (c == '&') {
adamc@136 429 strcpy(p, "&amp;");
adamc@136 430 p += 5;
adamc@136 431 }
adamc@136 432 else if (isprint(c))
adamc@136 433 *p++ = c;
adamc@136 434 else {
adamc@136 435 int len2;
adamc@136 436 sprintf(p, "&#%d;%n", c, &len2);
adamc@136 437 p += len2;
adamc@136 438 }
adamc@136 439 }
adamc@136 440
adamc@137 441 *p++ = 0;
adamc@136 442 ctx->heap_front = p;
adamc@136 443 return result;
adamc@106 444 }
adamc@106 445
adamc@311 446 static void uw_Basis_attrifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@117 447 int len;
adamc@117 448
adamc@276 449 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@117 450 ctx->page_front += len;
adamc@106 451 }
adamc@106 452
adamc@428 453 uw_unit uw_Basis_attrifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 454 uw_check(ctx, INTS_MAX);
adamc@311 455 uw_Basis_attrifyInt_w_unsafe(ctx, n);
adamc@428 456
adamc@428 457 return uw_unit_v;
adamc@106 458 }
adamc@106 459
adamc@428 460 uw_unit uw_Basis_attrifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@117 461 int len;
adamc@117 462
adamc@311 463 uw_check(ctx, FLOATS_MAX);
adamc@117 464 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@117 465 ctx->page_front += len;
adamc@428 466
adamc@428 467 return uw_unit_v;
adamc@117 468 }
adamc@117 469
adamc@428 470 uw_unit uw_Basis_attrifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 471 uw_check(ctx, strlen(s) * 6);
adamc@117 472
adamc@106 473 for (; *s; s++) {
adamc@106 474 char c = *s;
adamc@106 475
adamc@106 476 if (c == '"')
adamc@311 477 uw_write_unsafe(ctx, "&quot;");
adamc@136 478 else if (c == '&')
adamc@311 479 uw_write_unsafe(ctx, "&amp;");
adamc@106 480 else if (isprint(c))
adamc@311 481 uw_writec_unsafe(ctx, c);
adamc@106 482 else {
adamc@311 483 uw_write_unsafe(ctx, "&#");
adamc@311 484 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 485 uw_writec_unsafe(ctx, ';');
adamc@106 486 }
adamc@106 487 }
adamc@428 488
adamc@428 489 return uw_unit_v;
adamc@106 490 }
adamc@120 491
adamc@120 492
adamc@311 493 char *uw_Basis_urlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@137 494 int len;
adamc@137 495 char *r;
adamc@137 496
adamc@311 497 uw_check_heap(ctx, INTS_MAX);
adamc@137 498 r = ctx->heap_front;
adamc@276 499 sprintf(r, "%lld%n", n, &len);
adamc@137 500 ctx->heap_front += len+1;
adamc@137 501 return r;
adamc@120 502 }
adamc@120 503
adamc@311 504 char *uw_Basis_urlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@137 505 int len;
adamc@137 506 char *r;
adamc@137 507
adamc@311 508 uw_check_heap(ctx, FLOATS_MAX);
adamc@137 509 r = ctx->heap_front;
adamc@137 510 sprintf(r, "%g%n", n, &len);
adamc@137 511 ctx->heap_front += len+1;
adamc@137 512 return r;
adamc@120 513 }
adamc@120 514
adamc@311 515 char *uw_Basis_urlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 516 char *r, *p;
adamc@137 517
adamc@311 518 uw_check_heap(ctx, strlen(s) * 3 + 1);
adamc@137 519
adamc@137 520 for (r = p = ctx->heap_front; *s; s++) {
adamc@137 521 char c = *s;
adamc@137 522
adamc@137 523 if (c == ' ')
adamc@137 524 *p++ = '+';
adamc@137 525 else if (isalnum(c))
adamc@137 526 *p++ = c;
adamc@137 527 else {
adamc@137 528 sprintf(p, "%%%02X", c);
adamc@137 529 p += 3;
adamc@137 530 }
adamc@137 531 }
adamc@137 532
adamc@137 533 *p++ = 0;
adamc@137 534 ctx->heap_front = p;
adamc@137 535 return r;
adamc@120 536 }
adamc@120 537
adamc@311 538 char *uw_Basis_urlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 539 if (b == uw_Basis_False)
adamc@186 540 return "0";
adamc@186 541 else
adamc@186 542 return "1";
adamc@186 543 }
adamc@186 544
adamc@311 545 static void uw_Basis_urlifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
adamc@120 546 int len;
adamc@120 547
adamc@276 548 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@120 549 ctx->page_front += len;
adamc@120 550 }
adamc@120 551
adamc@428 552 uw_unit uw_Basis_urlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@311 553 uw_check(ctx, INTS_MAX);
adamc@311 554 uw_Basis_urlifyInt_w_unsafe(ctx, n);
adamc@428 555
adamc@428 556 return uw_unit_v;
adamc@120 557 }
adamc@120 558
adamc@428 559 uw_unit uw_Basis_urlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@120 560 int len;
adamc@120 561
adamc@311 562 uw_check(ctx, FLOATS_MAX);
adamc@120 563 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@120 564 ctx->page_front += len;
adamc@428 565
adamc@428 566 return uw_unit_v;
adamc@120 567 }
adamc@120 568
adamc@428 569 uw_unit uw_Basis_urlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@311 570 uw_check(ctx, strlen(s) * 3);
adamc@120 571
adamc@120 572 for (; *s; s++) {
adamc@120 573 char c = *s;
adamc@120 574
adamc@120 575 if (c == ' ')
adamc@311 576 uw_writec_unsafe(ctx, '+');
adamc@120 577 else if (isalnum(c))
adamc@311 578 uw_writec_unsafe(ctx, c);
adamc@120 579 else {
adamc@120 580 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 581 ctx->page_front += 3;
adamc@120 582 }
adamc@120 583 }
adamc@428 584
adamc@428 585 return uw_unit_v;
adamc@120 586 }
adamc@120 587
adamc@428 588 uw_unit uw_Basis_urlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 589 if (b == uw_Basis_False)
adamc@311 590 uw_writec(ctx, '0');
adamc@186 591 else
adamc@311 592 uw_writec(ctx, '1');
adamc@428 593
adamc@428 594 return uw_unit_v;
adamc@186 595 }
adamc@186 596
adamc@120 597
adamc@311 598 static char *uw_unurlify_advance(char *s) {
adamc@144 599 char *new_s = strchr(s, '/');
adamc@120 600
adamc@120 601 if (new_s)
adamc@120 602 *new_s++ = 0;
adamc@120 603 else
adamc@144 604 new_s = strchr(s, 0);
adamc@144 605
adamc@144 606 return new_s;
adamc@144 607 }
adamc@144 608
adamc@311 609 uw_Basis_int uw_Basis_unurlifyInt(uw_context ctx, char **s) {
adamc@311 610 char *new_s = uw_unurlify_advance(*s);
adamc@311 611 uw_Basis_int r;
adamc@120 612
adamc@276 613 r = atoll(*s);
adamc@120 614 *s = new_s;
adamc@120 615 return r;
adamc@120 616 }
adamc@120 617
adamc@311 618 uw_Basis_float uw_Basis_unurlifyFloat(uw_context ctx, char **s) {
adamc@311 619 char *new_s = uw_unurlify_advance(*s);
adamc@311 620 uw_Basis_float r;
adamc@120 621
adamc@120 622 r = atof(*s);
adamc@120 623 *s = new_s;
adamc@120 624 return r;
adamc@120 625 }
adamc@120 626
adamc@311 627 static uw_Basis_string uw_unurlifyString_to(uw_context ctx, char *r, char *s) {
adamc@144 628 char *s1, *s2;
adamc@144 629 int n;
adamc@136 630
adamc@144 631 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
adamc@136 632 char c = *s2;
adamc@136 633
adamc@136 634 switch (c) {
adamc@136 635 case '+':
adamc@136 636 *s1 = ' ';
adamc@136 637 break;
adamc@136 638 case '%':
adamc@169 639 if (s2[1] == 0)
adamc@311 640 uw_error(ctx, FATAL, "Missing first character of escaped URL byte");
adamc@169 641 if (s2[2] == 0)
adamc@311 642 uw_error(ctx, FATAL, "Missing second character of escaped URL byte");
adamc@169 643 if (sscanf(s2+1, "%02X", &n) != 1)
adamc@311 644 uw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
adamc@136 645 *s1 = n;
adamc@136 646 s2 += 2;
adamc@136 647 break;
adamc@136 648 default:
adamc@136 649 *s1 = c;
adamc@136 650 }
adamc@136 651 }
adamc@136 652 *s1++ = 0;
adamc@144 653 return s1;
adamc@144 654 }
adamc@144 655
adamc@311 656 uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) {
adamc@311 657 char *new_s = uw_unurlify_advance(*s);
adamc@311 658 uw_Basis_bool r;
adamc@186 659
adamc@186 660 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
adamc@311 661 r = uw_Basis_False;
adamc@186 662 else
adamc@311 663 r = uw_Basis_True;
adamc@186 664
adamc@186 665 *s = new_s;
adamc@186 666 return r;
adamc@186 667 }
adamc@186 668
adamc@311 669 uw_Basis_string uw_Basis_unurlifyString(uw_context ctx, char **s) {
adamc@311 670 char *new_s = uw_unurlify_advance(*s);
adamc@144 671 char *r, *s1, *s2;
adamc@144 672 int len, n;
adamc@144 673
adamc@200 674 len = strlen(*s);
adamc@311 675 uw_check_heap(ctx, len + 1);
adamc@144 676
adamc@144 677 r = ctx->heap_front;
adamc@311 678 ctx->heap_front = uw_unurlifyString_to(ctx, ctx->heap_front, *s);
adamc@136 679 *s = new_s;
adamc@136 680 return r;
adamc@120 681 }
adamc@135 682
adamc@135 683
adamc@311 684 char *uw_Basis_htmlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@286 685 int len;
adamc@286 686 char *r;
adamc@286 687
adamc@311 688 uw_check_heap(ctx, INTS_MAX);
adamc@286 689 r = ctx->heap_front;
adamc@286 690 sprintf(r, "%lld%n", n, &len);
adamc@286 691 ctx->heap_front += len+1;
adamc@286 692 return r;
adamc@286 693 }
adamc@286 694
adamc@428 695 uw_unit uw_Basis_htmlifyInt_w(uw_context ctx, uw_Basis_int n) {
adamc@286 696 int len;
adamc@286 697
adamc@311 698 uw_check(ctx, INTS_MAX);
adamc@286 699 sprintf(ctx->page_front, "%lld%n", n, &len);
adamc@286 700 ctx->page_front += len;
adamc@428 701
adamc@428 702 return uw_unit_v;
adamc@286 703 }
adamc@286 704
adamc@311 705 char *uw_Basis_htmlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@286 706 int len;
adamc@286 707 char *r;
adamc@286 708
adamc@311 709 uw_check_heap(ctx, FLOATS_MAX);
adamc@286 710 r = ctx->heap_front;
adamc@286 711 sprintf(r, "%g%n", n, &len);
adamc@286 712 ctx->heap_front += len+1;
adamc@286 713 return r;
adamc@286 714 }
adamc@286 715
adamc@428 716 uw_unit uw_Basis_htmlifyFloat_w(uw_context ctx, uw_Basis_float n) {
adamc@286 717 int len;
adamc@286 718
adamc@311 719 uw_check(ctx, FLOATS_MAX);
adamc@286 720 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@286 721 ctx->page_front += len;
adamc@428 722
adamc@428 723 return uw_unit_v;
adamc@286 724 }
adamc@286 725
adamc@311 726 char *uw_Basis_htmlifyString(uw_context ctx, uw_Basis_string s) {
adamc@137 727 char *r, *s2;
adamc@137 728
adamc@311 729 uw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 730
adamc@137 731 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 732 char c = *s;
adamc@137 733
adamc@137 734 switch (c) {
adamc@137 735 case '<':
adamc@137 736 strcpy(s2, "&lt;");
adamc@137 737 s2 += 4;
adamc@137 738 break;
adamc@137 739 case '&':
adamc@137 740 strcpy(s2, "&amp;");
adamc@137 741 s2 += 5;
adamc@137 742 break;
adamc@137 743 default:
adamc@137 744 if (isprint(c))
adamc@137 745 *s2++ = c;
adamc@137 746 else {
adamc@137 747 int len2;
adamc@137 748 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 749 s2 += len2;
adamc@137 750 }
adamc@137 751 }
adamc@137 752 }
adamc@137 753
adamc@137 754 *s2++ = 0;
adamc@137 755 ctx->heap_front = s2;
adamc@137 756 return r;
adamc@135 757 }
adamc@135 758
adamc@428 759 uw_unit uw_Basis_htmlifyString_w(uw_context ctx, uw_Basis_string s) {
adamc@321 760 uw_check(ctx, strlen(s) * 6);
adamc@135 761
adamc@135 762 for (; *s; s++) {
adamc@135 763 char c = *s;
adamc@135 764
adamc@135 765 switch (c) {
adamc@135 766 case '<':
adamc@311 767 uw_write_unsafe(ctx, "&lt;");
adamc@135 768 break;
adamc@135 769 case '&':
adamc@311 770 uw_write_unsafe(ctx, "&amp;");
adamc@135 771 break;
adamc@135 772 default:
adamc@135 773 if (isprint(c))
adamc@311 774 uw_writec_unsafe(ctx, c);
adamc@135 775 else {
adamc@311 776 uw_write_unsafe(ctx, "&#");
adamc@311 777 uw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@311 778 uw_writec_unsafe(ctx, ';');
adamc@135 779 }
adamc@135 780 }
adamc@135 781 }
adamc@428 782
adamc@428 783 return uw_unit_v;
adamc@135 784 }
adamc@180 785
adamc@311 786 uw_Basis_string uw_Basis_htmlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 787 if (b == uw_Basis_False)
adamc@286 788 return "False";
adamc@286 789 else
adamc@286 790 return "True";
adamc@286 791 }
adamc@286 792
adamc@428 793 uw_unit uw_Basis_htmlifyBool_w(uw_context ctx, uw_Basis_bool b) {
adamc@311 794 if (b == uw_Basis_False) {
adamc@311 795 uw_check(ctx, 6);
adamc@286 796 strcpy(ctx->page_front, "False");
adamc@286 797 ctx->page_front += 5;
adamc@286 798 } else {
adamc@311 799 uw_check(ctx, 5);
adamc@286 800 strcpy(ctx->page_front, "True");
adamc@286 801 ctx->page_front += 4;
adamc@286 802 }
adamc@428 803
adamc@428 804 return uw_unit_v;
adamc@286 805 }
adamc@286 806
adamc@436 807 #define TIME_FMT "%x %X"
adamc@438 808 #define TIME_FMT_PG "%Y-%m-%d %T"
adamc@436 809
adamc@436 810 uw_Basis_string uw_Basis_htmlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@436 811 size_t len;
adamc@436 812 char *r;
adamc@436 813 struct tm stm;
adamc@436 814
adamc@436 815 if (localtime_r(&t, &stm)) {
adamc@436 816 uw_check_heap(ctx, TIMES_MAX);
adamc@436 817 r = ctx->heap_front;
adamc@436 818 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 819 ctx->heap_front += len+1;
adamc@436 820 return r;
adamc@436 821 } else
adamc@436 822 return "<i>Invalid time</i>";
adamc@436 823 }
adamc@436 824
adamc@436 825 uw_unit uw_Basis_htmlifyTime_w(uw_context ctx, uw_Basis_time t) {
adamc@436 826 size_t len;
adamc@436 827 char *r;
adamc@436 828 struct tm stm;
adamc@436 829
adamc@436 830 if (localtime_r(&t, &stm)) {
adamc@436 831 uw_check(ctx, TIMES_MAX);
adamc@436 832 r = ctx->page_front;
adamc@436 833 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 834 ctx->page_front += len;
adamc@436 835 } else {
adamc@436 836 uw_check(ctx, 20);
adamc@436 837 strcpy(ctx->page_front, "<i>Invalid time</i>");
adamc@436 838 ctx->page_front += 19;
adamc@436 839 }
adamc@436 840
adamc@436 841 return uw_unit_v;
adamc@436 842 }
adamc@436 843
adamc@311 844 uw_Basis_string uw_Basis_strcat(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
adamc@180 845 int len = strlen(s1) + strlen(s2) + 1;
adamc@180 846 char *s;
adamc@180 847
adamc@311 848 uw_check_heap(ctx, len);
adamc@180 849
adamc@180 850 s = ctx->heap_front;
adamc@180 851
adamc@180 852 strcpy(s, s1);
adamc@180 853 strcat(s, s2);
adamc@180 854 ctx->heap_front += len;
adamc@180 855
adamc@180 856 return s;
adamc@180 857 }
adamc@278 858
adamc@311 859 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) {
adamc@278 860 int len = strlen(s1) + 1;
adamc@278 861 char *s;
adamc@278 862
adamc@311 863 uw_check_heap(ctx, len);
adamc@278 864
adamc@278 865 s = ctx->heap_front;
adamc@278 866
adamc@278 867 strcpy(s, s1);
adamc@278 868 ctx->heap_front += len;
adamc@278 869
adamc@278 870 return s;
adamc@278 871 }
adamc@280 872
adamc@280 873
adamc@311 874 char *uw_Basis_sqlifyInt(uw_context ctx, uw_Basis_int n) {
adamc@281 875 int len;
adamc@281 876 char *r;
adamc@281 877
adamc@311 878 uw_check_heap(ctx, INTS_MAX + 6);
adamc@281 879 r = ctx->heap_front;
adamc@281 880 sprintf(r, "%lld::int8%n", n, &len);
adamc@281 881 ctx->heap_front += len+1;
adamc@281 882 return r;
adamc@281 883 }
adamc@281 884
adamc@311 885 char *uw_Basis_sqlifyFloat(uw_context ctx, uw_Basis_float n) {
adamc@281 886 int len;
adamc@281 887 char *r;
adamc@281 888
adamc@311 889 uw_check_heap(ctx, FLOATS_MAX + 8);
adamc@281 890 r = ctx->heap_front;
adamc@281 891 sprintf(r, "%g::float8%n", n, &len);
adamc@281 892 ctx->heap_front += len+1;
adamc@281 893 return r;
adamc@281 894 }
adamc@281 895
adamc@281 896
adamc@311 897 uw_Basis_string uw_Basis_sqlifyString(uw_context ctx, uw_Basis_string s) {
adamc@280 898 char *r, *s2;
adamc@280 899
adamc@311 900 uw_check_heap(ctx, strlen(s) * 2 + 10);
adamc@280 901
adamc@280 902 r = s2 = ctx->heap_front;
adamc@280 903 *s2++ = 'E';
adamc@280 904 *s2++ = '\'';
adamc@280 905
adamc@280 906 for (; *s; s++) {
adamc@280 907 char c = *s;
adamc@280 908
adamc@280 909 switch (c) {
adamc@280 910 case '\'':
adamc@280 911 strcpy(s2, "\\'");
adamc@280 912 s2 += 2;
adamc@280 913 break;
adamc@280 914 case '\\':
adamc@280 915 strcpy(s2, "\\\\");
adamc@280 916 s2 += 2;
adamc@280 917 break;
adamc@280 918 default:
adamc@280 919 if (isprint(c))
adamc@280 920 *s2++ = c;
adamc@280 921 else {
adamc@280 922 sprintf(s2, "\\%3o", c);
adamc@280 923 s2 += 4;
adamc@280 924 }
adamc@280 925 }
adamc@280 926 }
adamc@280 927
adamc@281 928 strcpy(s2, "'::text");
adamc@281 929 ctx->heap_front = s2 + 8;
adamc@280 930 return r;
adamc@280 931 }
adamc@281 932
adamc@311 933 char *uw_Basis_sqlifyBool(uw_context ctx, uw_Basis_bool b) {
adamc@311 934 if (b == uw_Basis_False)
adamc@281 935 return "FALSE";
adamc@281 936 else
adamc@281 937 return "TRUE";
adamc@281 938 }
adamc@282 939
adamc@439 940 char *uw_Basis_sqlifyTime(uw_context ctx, uw_Basis_time t) {
adamc@439 941 size_t len;
adamc@439 942 char *r;
adamc@439 943 struct tm stm;
adamc@439 944
adamc@439 945 if (localtime_r(&t, &stm)) {
adamc@439 946 uw_check_heap(ctx, TIMES_MAX);
adamc@439 947 r = ctx->heap_front;
adamc@439 948 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@439 949 ctx->heap_front += len+1;
adamc@439 950 return r;
adamc@439 951 } else
adamc@439 952 return "<Invalid time>";
adamc@439 953 }
adamc@439 954
adamc@311 955 char *uw_Basis_ensqlBool(uw_Basis_bool b) {
adamc@311 956 static uw_Basis_int true = 1;
adamc@311 957 static uw_Basis_int false = 0;
adamc@282 958
adamc@311 959 if (b == uw_Basis_False)
adamc@282 960 return (char *)&false;
adamc@282 961 else
adamc@282 962 return (char *)&true;
adamc@282 963 }
adamc@284 964
adamc@311 965 uw_Basis_string uw_Basis_intToString(uw_context ctx, uw_Basis_int n) {
adamc@284 966 int len;
adamc@284 967 char *r;
adamc@284 968
adamc@311 969 uw_check_heap(ctx, INTS_MAX);
adamc@284 970 r = ctx->heap_front;
adamc@284 971 sprintf(r, "%lld%n", n, &len);
adamc@284 972 ctx->heap_front += len+1;
adamc@284 973 return r;
adamc@284 974 }
adamc@285 975
adamc@311 976 uw_Basis_string uw_Basis_floatToString(uw_context ctx, uw_Basis_float n) {
adamc@285 977 int len;
adamc@285 978 char *r;
adamc@285 979
adamc@311 980 uw_check_heap(ctx, FLOATS_MAX);
adamc@285 981 r = ctx->heap_front;
adamc@285 982 sprintf(r, "%g%n", n, &len);
adamc@285 983 ctx->heap_front += len+1;
adamc@285 984 return r;
adamc@285 985 }
adamc@285 986
adamc@311 987 uw_Basis_string uw_Basis_boolToString(uw_context ctx, uw_Basis_bool b) {
adamc@311 988 if (b == uw_Basis_False)
adamc@285 989 return "False";
adamc@285 990 else
adamc@285 991 return "True";
adamc@285 992 }
adamc@288 993
adamc@436 994 uw_Basis_string uw_Basis_timeToString(uw_context ctx, uw_Basis_time t) {
adamc@436 995 size_t len;
adamc@436 996 char *r;
adamc@436 997 struct tm stm;
adamc@436 998
adamc@436 999 if (localtime_r(&t, &stm)) {
adamc@436 1000 uw_check_heap(ctx, TIMES_MAX);
adamc@436 1001 r = ctx->heap_front;
adamc@436 1002 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
adamc@436 1003 ctx->heap_front += len+1;
adamc@436 1004 return r;
adamc@436 1005 } else
adamc@436 1006 return "<Invalid time>";
adamc@436 1007 }
adamc@288 1008
adamc@311 1009 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
adamc@288 1010 char *endptr;
adamc@311 1011 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@288 1012
adamc@288 1013 if (*s != '\0' && *endptr == '\0') {
adamc@311 1014 uw_Basis_int *r = uw_malloc(ctx, sizeof(uw_Basis_int));
adamc@288 1015 *r = n;
adamc@288 1016 return r;
adamc@288 1017 } else
adamc@288 1018 return NULL;
adamc@288 1019 }
adamc@289 1020
adamc@311 1021 uw_Basis_float *uw_Basis_stringToFloat(uw_context ctx, uw_Basis_string s) {
adamc@289 1022 char *endptr;
adamc@311 1023 uw_Basis_float n = strtod(s, &endptr);
adamc@289 1024
adamc@289 1025 if (*s != '\0' && *endptr == '\0') {
adamc@311 1026 uw_Basis_float *r = uw_malloc(ctx, sizeof(uw_Basis_float));
adamc@289 1027 *r = n;
adamc@289 1028 return r;
adamc@289 1029 } else
adamc@289 1030 return NULL;
adamc@289 1031 }
adamc@289 1032
adamc@311 1033 uw_Basis_bool *uw_Basis_stringToBool(uw_context ctx, uw_Basis_string s) {
adamc@311 1034 static uw_Basis_bool true = uw_Basis_True;
adamc@311 1035 static uw_Basis_bool false = uw_Basis_False;
adamc@289 1036
adamc@289 1037 if (!strcasecmp (s, "True"))
adamc@289 1038 return &true;
adamc@289 1039 else if (!strcasecmp (s, "False"))
adamc@289 1040 return &false;
adamc@289 1041 else
adamc@289 1042 return NULL;
adamc@289 1043 }
adamc@292 1044
adamc@436 1045 uw_Basis_time *uw_Basis_stringToTime(uw_context ctx, uw_Basis_string s) {
adamc@438 1046 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1047 struct tm stm;
adamc@436 1048
adamc@439 1049 if (dot) {
adamc@439 1050 *dot = 0;
adamc@439 1051 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1052 *dot = '.';
adamc@439 1053 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1054 *r = mktime(&stm);
adamc@439 1055 return r;
adamc@439 1056 }
adamc@439 1057 else {
adamc@439 1058 *dot = '.';
adamc@439 1059 return NULL;
adamc@439 1060 }
adamc@436 1061 }
adamc@439 1062 else {
adamc@439 1063 if (strptime(s, TIME_FMT_PG, &stm) == end) {
adamc@439 1064 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1065 *r = mktime(&stm);
adamc@439 1066 return r;
adamc@439 1067 }
adamc@439 1068 else if (strptime(s, TIME_FMT, &stm) == end) {
adamc@439 1069 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
adamc@439 1070 *r = mktime(&stm);
adamc@439 1071 return r;
adamc@439 1072 }
adamc@439 1073 else
adamc@439 1074 return NULL;
adamc@439 1075 }
adamc@436 1076 }
adamc@436 1077
adamc@311 1078 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
adamc@292 1079 char *endptr;
adamc@311 1080 uw_Basis_int n = strtoll(s, &endptr, 10);
adamc@292 1081
adamc@292 1082 if (*s != '\0' && *endptr == '\0')
adamc@292 1083 return n;
adamc@292 1084 else
adamc@311 1085 uw_error(ctx, FATAL, "Can't parse int: %s", s);
adamc@292 1086 }
adamc@293 1087
adamc@311 1088 uw_Basis_float uw_Basis_stringToFloat_error(uw_context ctx, uw_Basis_string s) {
adamc@293 1089 char *endptr;
adamc@311 1090 uw_Basis_float n = strtod(s, &endptr);
adamc@293 1091
adamc@293 1092 if (*s != '\0' && *endptr == '\0')
adamc@293 1093 return n;
adamc@293 1094 else
adamc@311 1095 uw_error(ctx, FATAL, "Can't parse float: %s", s);
adamc@293 1096 }
adamc@293 1097
adamc@311 1098 uw_Basis_bool uw_Basis_stringToBool_error(uw_context ctx, uw_Basis_string s) {
adamc@296 1099 if (!strcasecmp(s, "T") || !strcasecmp (s, "True"))
adamc@311 1100 return uw_Basis_True;
adamc@296 1101 else if (!strcasecmp(s, "F") || !strcasecmp (s, "False"))
adamc@311 1102 return uw_Basis_False;
adamc@293 1103 else
adamc@311 1104 uw_error(ctx, FATAL, "Can't parse bool: %s", s);
adamc@293 1105 }
adamc@436 1106
adamc@436 1107 uw_Basis_time uw_Basis_stringToTime_error(uw_context ctx, uw_Basis_string s) {
adamc@438 1108 char *dot = strchr(s, '.'), *end = strchr(s, 0);
adamc@436 1109 struct tm stm = {};
adamc@436 1110
adamc@438 1111 if (dot) {
adamc@438 1112 *dot = 0;
adamc@438 1113 if (strptime(s, TIME_FMT_PG, &stm)) {
adamc@438 1114 *dot = '.';
adamc@438 1115 return mktime(&stm);
adamc@438 1116 }
adamc@438 1117 else {
adamc@438 1118 *dot = '.';
adamc@438 1119 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1120 }
adamc@438 1121 }
adamc@438 1122 else {
adamc@439 1123 if (strptime(s, TIME_FMT_PG, &stm) == end)
adamc@439 1124 return mktime(&stm);
adamc@439 1125 else if (strptime(s, TIME_FMT, &stm) == end)
adamc@438 1126 return mktime(&stm);
adamc@438 1127 else
adamc@438 1128 uw_error(ctx, FATAL, "Can't parse time: %s", s);
adamc@438 1129 }
adamc@436 1130 }
adamc@457 1131
adamc@457 1132 uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
adamc@457 1133 int len = strlen(h);
adamc@457 1134 char *s = ctx->headers, *p;
adamc@457 1135
adamc@457 1136 while (p = strchr(s, ':')) {
adamc@457 1137 if (p - s == len && !strncasecmp(s, h, len)) {
adamc@458 1138 return p + 2;
adamc@457 1139 } else {
adamc@458 1140 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@458 1141 s += 2;
adamc@457 1142 else
adamc@457 1143 return NULL;
adamc@457 1144 }
adamc@457 1145 }
adamc@463 1146 }
adamc@458 1147
adamc@463 1148 uw_Basis_string uw_Basis_get_cookie(uw_context ctx, uw_Basis_string c) {
adamc@463 1149 int len = strlen(c);
adamc@463 1150 char *s = ctx->headers, *p;
adamc@463 1151
adamc@463 1152 while (p = strchr(s, ':')) {
adamc@463 1153 if (!strncasecmp(s, "Cookie: ", 8) && !strncmp(p + 2, c, len)
adamc@463 1154 && p + 2 + len < ctx->headers_end && p[2 + len] == '=') {
adamc@463 1155 return p + 3 + len;
adamc@463 1156 } else {
adamc@463 1157 if ((s = strchr(p, 0)) && s < ctx->headers_end)
adamc@463 1158 s += 2;
adamc@463 1159 else
adamc@463 1160 return NULL;
adamc@463 1161 }
adamc@463 1162 }
adamc@457 1163 }
adamc@462 1164
adamc@462 1165 uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string c, uw_Basis_string v) {
adamc@462 1166 uw_write_header(ctx, "Set-Cookie: ");
adamc@462 1167 uw_write_header(ctx, c);
adamc@462 1168 uw_write_header(ctx, "=");
adamc@462 1169 uw_write_header(ctx, v);
adamc@462 1170 uw_write_header(ctx, "\r\n");
adamc@462 1171
adamc@462 1172 return uw_unit_v;
adamc@462 1173 }