annotate src/c/lacweb.c @ 142:6f9e224692ec

Form submission type-checking
author Adam Chlipala <adamc@hcoop.net>
date Sun, 20 Jul 2008 12:21:30 -0400
parents d6d78055f001
children f0d3402184d1
rev   line source
adamc@117 1 #include <stdlib.h>
adamc@102 2 #include <stdio.h>
adamc@117 3 #include <string.h>
adamc@106 4 #include <ctype.h>
adamc@136 5 #include <assert.h>
adamc@102 6
adamc@102 7 #include "types.h"
adamc@102 8
adamc@102 9 lw_unit lw_unit_v = {};
adamc@102 10
adamc@117 11 struct lw_context {
adamc@117 12 char *page, *page_front, *page_back;
adamc@136 13 char *heap, *heap_front, *heap_back;
adamc@117 14 };
adamc@117 15
adamc@136 16 lw_context lw_init(size_t page_len, size_t heap_len) {
adamc@117 17 lw_context ctx = malloc(sizeof(struct lw_context));
adamc@136 18
adamc@117 19 ctx->page_front = ctx->page = malloc(page_len);
adamc@117 20 ctx->page_back = ctx->page_front + page_len;
adamc@136 21
adamc@136 22 ctx->heap_front = ctx->heap = malloc(heap_len);
adamc@136 23 ctx->heap_back = ctx->heap_front + heap_len;
adamc@136 24
adamc@117 25 return ctx;
adamc@106 26 }
adamc@106 27
adamc@117 28 void lw_free(lw_context ctx) {
adamc@117 29 free(ctx->page);
adamc@136 30 free(ctx->heap);
adamc@136 31 free(ctx);
adamc@136 32 }
adamc@136 33
adamc@138 34 void lw_reset(lw_context ctx) {
adamc@138 35 ctx->page_front = ctx->page;
adamc@138 36 ctx->heap_front = ctx->heap;
adamc@138 37 }
adamc@138 38
adamc@136 39 static void lw_check_heap(lw_context ctx, size_t extra) {
adamc@136 40 if (ctx->heap_back - ctx->heap_front < extra) {
adamc@136 41 size_t desired = ctx->heap_back - ctx->heap_front + extra, next;
adamc@136 42 char *new_heap;
adamc@136 43
adamc@136 44 for (next = ctx->heap_back - ctx->heap_front; next < desired; next *= 2);
adamc@136 45
adamc@136 46 new_heap = realloc(ctx->heap, next);
adamc@136 47
adamc@136 48 if (new_heap != ctx->heap) {
adamc@136 49 ctx->heap = new_heap;
adamc@136 50 puts("Couldn't get contiguous chunk");
adamc@136 51 exit(1);
adamc@136 52 }
adamc@136 53
adamc@136 54 ctx->heap_back = new_heap + next;
adamc@136 55 }
adamc@136 56 }
adamc@136 57
adamc@136 58 void *lw_malloc(lw_context ctx, size_t len) {
adamc@136 59 void *result;
adamc@136 60
adamc@136 61 lw_check_heap(ctx, len);
adamc@136 62
adamc@136 63 result = ctx->heap_front;
adamc@136 64 ctx->heap_front += len;
adamc@136 65 return result;
adamc@117 66 }
adamc@117 67
adamc@117 68 int lw_really_send(int sock, const void *buf, ssize_t len) {
adamc@117 69 while (len > 0) {
adamc@117 70 ssize_t n = send(sock, buf, len, 0);
adamc@117 71
adamc@117 72 if (n < 0)
adamc@117 73 return n;
adamc@117 74
adamc@117 75 buf += n;
adamc@117 76 len -= n;
adamc@117 77 }
adamc@117 78
adamc@117 79 return 0;
adamc@117 80 }
adamc@117 81
adamc@117 82 int lw_send(lw_context ctx, int sock) {
adamc@117 83 return lw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
adamc@117 84 }
adamc@117 85
adamc@117 86 static void lw_check(lw_context ctx, size_t extra) {
adamc@117 87 size_t desired = ctx->page_back - ctx->page_front + extra, next;
adamc@117 88 char *new_page;
adamc@117 89
adamc@117 90 for (next = ctx->page_back - ctx->page_front; next < desired; next *= 2);
adamc@117 91
adamc@117 92 new_page = realloc(ctx->page, next);
adamc@117 93 ctx->page_front = new_page + (ctx->page_front - ctx->page);
adamc@117 94 ctx->page_back = new_page + (ctx->page_back - ctx->page);
adamc@117 95 ctx->page = new_page;
adamc@117 96 }
adamc@117 97
adamc@117 98 static void lw_writec_unsafe(lw_context ctx, char c) {
adamc@117 99 *(ctx->page_front)++ = c;
adamc@117 100 }
adamc@117 101
adamc@117 102 void lw_writec(lw_context ctx, char c) {
adamc@117 103 lw_check(ctx, 1);
adamc@117 104 lw_writec_unsafe(ctx, c);
adamc@117 105 }
adamc@117 106
adamc@117 107 static void lw_write_unsafe(lw_context ctx, const char* s) {
adamc@117 108 int len = strlen(s);
adamc@117 109 memcpy(ctx->page_front, s, len);
adamc@117 110 ctx->page_front += len;
adamc@117 111 }
adamc@117 112
adamc@117 113 void lw_write(lw_context ctx, const char* s) {
adamc@117 114 lw_check(ctx, strlen(s));
adamc@117 115 lw_write_unsafe(ctx, s);
adamc@102 116 }
adamc@106 117
adamc@135 118
adamc@136 119 #define INTS_MAX 50
adamc@136 120 #define FLOATS_MAX 100
adamc@136 121
adamc@136 122 char *lw_Basis_attrifyInt(lw_context ctx, lw_Basis_int n) {
adamc@136 123 char *result;
adamc@136 124 int len;
adamc@136 125 lw_check_heap(ctx, INTS_MAX);
adamc@136 126 result = ctx->heap_front;
adamc@136 127 sprintf(result, "%d%n", n, &len);
adamc@137 128 ctx->heap_front += len+1;
adamc@136 129 return result;
adamc@106 130 }
adamc@106 131
adamc@136 132 char *lw_Basis_attrifyFloat(lw_context ctx, lw_Basis_float n) {
adamc@136 133 char *result;
adamc@136 134 int len;
adamc@137 135 lw_check_heap(ctx, FLOATS_MAX);
adamc@136 136 result = ctx->heap_front;
adamc@136 137 sprintf(result, "%g%n", n, &len);
adamc@137 138 ctx->heap_front += len+1;
adamc@136 139 return result;
adamc@106 140 }
adamc@106 141
adamc@136 142 char *lw_Basis_attrifyString(lw_context ctx, lw_Basis_string s) {
adamc@136 143 int len = strlen(s);
adamc@136 144 char *result, *p;
adamc@137 145 lw_check_heap(ctx, len * 6 + 1);
adamc@136 146
adamc@136 147 result = p = ctx->heap_front;
adamc@136 148
adamc@136 149 for (; *s; s++) {
adamc@136 150 char c = *s;
adamc@136 151
adamc@136 152 if (c == '"') {
adamc@136 153 strcpy(p, "&quot;");
adamc@136 154 p += 6;
adamc@136 155 } else if (c == '&') {
adamc@136 156 strcpy(p, "&amp;");
adamc@136 157 p += 5;
adamc@136 158 }
adamc@136 159 else if (isprint(c))
adamc@136 160 *p++ = c;
adamc@136 161 else {
adamc@136 162 int len2;
adamc@136 163 sprintf(p, "&#%d;%n", c, &len2);
adamc@136 164 p += len2;
adamc@136 165 }
adamc@136 166 }
adamc@136 167
adamc@137 168 *p++ = 0;
adamc@136 169 ctx->heap_front = p;
adamc@136 170 return result;
adamc@106 171 }
adamc@106 172
adamc@117 173 static void lw_Basis_attrifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
adamc@117 174 int len;
adamc@117 175
adamc@117 176 sprintf(ctx->page_front, "%d%n", n, &len);
adamc@117 177 ctx->page_front += len;
adamc@106 178 }
adamc@106 179
adamc@117 180 void lw_Basis_attrifyInt_w(lw_context ctx, lw_Basis_int n) {
adamc@117 181 lw_check(ctx, INTS_MAX);
adamc@117 182 lw_Basis_attrifyInt_w_unsafe(ctx, n);
adamc@106 183 }
adamc@106 184
adamc@117 185 void lw_Basis_attrifyFloat_w(lw_context ctx, lw_Basis_float n) {
adamc@117 186 int len;
adamc@117 187
adamc@117 188 lw_check(ctx, FLOATS_MAX);
adamc@117 189 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@117 190 ctx->page_front += len;
adamc@117 191 }
adamc@117 192
adamc@117 193 void lw_Basis_attrifyString_w(lw_context ctx, lw_Basis_string s) {
adamc@117 194 lw_check(ctx, strlen(s) * 6);
adamc@117 195
adamc@106 196 for (; *s; s++) {
adamc@106 197 char c = *s;
adamc@106 198
adamc@106 199 if (c == '"')
adamc@117 200 lw_write_unsafe(ctx, "&quot;");
adamc@136 201 else if (c == '&')
adamc@136 202 lw_write_unsafe(ctx, "&amp;");
adamc@106 203 else if (isprint(c))
adamc@117 204 lw_writec_unsafe(ctx, c);
adamc@106 205 else {
adamc@117 206 lw_write_unsafe(ctx, "&#");
adamc@117 207 lw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@117 208 lw_writec_unsafe(ctx, ';');
adamc@106 209 }
adamc@106 210 }
adamc@106 211 }
adamc@120 212
adamc@120 213
adamc@137 214 char *lw_Basis_urlifyInt(lw_context ctx, lw_Basis_int n) {
adamc@137 215 int len;
adamc@137 216 char *r;
adamc@137 217
adamc@137 218 lw_check_heap(ctx, INTS_MAX);
adamc@137 219 r = ctx->heap_front;
adamc@137 220 sprintf(r, "%d%n", n, &len);
adamc@137 221 ctx->heap_front += len+1;
adamc@137 222 return r;
adamc@120 223 }
adamc@120 224
adamc@137 225 char *lw_Basis_urlifyFloat(lw_context ctx, lw_Basis_float n) {
adamc@137 226 int len;
adamc@137 227 char *r;
adamc@137 228
adamc@137 229 lw_check_heap(ctx, FLOATS_MAX);
adamc@137 230 r = ctx->heap_front;
adamc@137 231 sprintf(r, "%g%n", n, &len);
adamc@137 232 ctx->heap_front += len+1;
adamc@137 233 return r;
adamc@120 234 }
adamc@120 235
adamc@137 236 char *lw_Basis_urlifyString(lw_context ctx, lw_Basis_string s) {
adamc@137 237 char *r, *p;
adamc@137 238
adamc@137 239 lw_check_heap(ctx, strlen(s) * 3 + 1);
adamc@137 240
adamc@137 241 for (r = p = ctx->heap_front; *s; s++) {
adamc@137 242 char c = *s;
adamc@137 243
adamc@137 244 if (c == ' ')
adamc@137 245 *p++ = '+';
adamc@137 246 else if (isalnum(c))
adamc@137 247 *p++ = c;
adamc@137 248 else {
adamc@137 249 sprintf(p, "%%%02X", c);
adamc@137 250 p += 3;
adamc@137 251 }
adamc@137 252 }
adamc@137 253
adamc@137 254 *p++ = 0;
adamc@137 255 ctx->heap_front = p;
adamc@137 256 return r;
adamc@120 257 }
adamc@120 258
adamc@120 259 static void lw_Basis_urlifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
adamc@120 260 int len;
adamc@120 261
adamc@120 262 sprintf(ctx->page_front, "%d%n", n, &len);
adamc@120 263 ctx->page_front += len;
adamc@120 264 }
adamc@120 265
adamc@120 266 void lw_Basis_urlifyInt_w(lw_context ctx, lw_Basis_int n) {
adamc@120 267 lw_check(ctx, INTS_MAX);
adamc@120 268 lw_Basis_urlifyInt_w_unsafe(ctx, n);
adamc@120 269 }
adamc@120 270
adamc@120 271 void lw_Basis_urlifyFloat_w(lw_context ctx, lw_Basis_float n) {
adamc@120 272 int len;
adamc@120 273
adamc@120 274 lw_check(ctx, FLOATS_MAX);
adamc@120 275 sprintf(ctx->page_front, "%g%n", n, &len);
adamc@120 276 ctx->page_front += len;
adamc@120 277 }
adamc@120 278
adamc@120 279 void lw_Basis_urlifyString_w(lw_context ctx, lw_Basis_string s) {
adamc@120 280 lw_check(ctx, strlen(s) * 3);
adamc@120 281
adamc@120 282 for (; *s; s++) {
adamc@120 283 char c = *s;
adamc@120 284
adamc@120 285 if (c == ' ')
adamc@120 286 lw_writec_unsafe(ctx, '+');
adamc@120 287 else if (isalnum(c))
adamc@120 288 lw_writec_unsafe(ctx, c);
adamc@120 289 else {
adamc@120 290 sprintf(ctx->page_front, "%%%02X", c);
adamc@120 291 ctx->page_front += 3;
adamc@120 292 }
adamc@120 293 }
adamc@120 294 }
adamc@120 295
adamc@120 296
adamc@120 297 lw_Basis_int lw_unurlifyInt(char **s) {
adamc@120 298 char *new_s = strchr(*s, '/');
adamc@120 299 int r;
adamc@120 300
adamc@120 301 if (new_s)
adamc@120 302 *new_s++ = 0;
adamc@120 303 else
adamc@120 304 new_s = strchr(*s, 0);
adamc@120 305
adamc@120 306 r = atoi(*s);
adamc@120 307 *s = new_s;
adamc@120 308 return r;
adamc@120 309 }
adamc@120 310
adamc@120 311 lw_Basis_float lw_unurlifyFloat(char **s) {
adamc@120 312 char *new_s = strchr(*s, '/');
adamc@120 313 int r;
adamc@120 314
adamc@120 315 if (new_s)
adamc@120 316 *new_s++ = 0;
adamc@120 317 else
adamc@120 318 new_s = strchr(*s, 0);
adamc@120 319
adamc@120 320 r = atof(*s);
adamc@120 321 *s = new_s;
adamc@120 322 return r;
adamc@120 323 }
adamc@120 324
adamc@136 325 lw_Basis_string lw_unurlifyString(lw_context ctx, char **s) {
adamc@136 326 char *new_s = strchr(*s, '/');
adamc@136 327 char *r, *s1, *s2;
adamc@136 328 int len, n;
adamc@136 329
adamc@136 330 if (new_s)
adamc@136 331 *new_s++ = 0;
adamc@136 332 else
adamc@136 333 new_s = strchr(*s, 0);
adamc@136 334
adamc@136 335 len = strlen(*s);
adamc@136 336 lw_check_heap(ctx, len + 1);
adamc@136 337
adamc@136 338 r = ctx->heap_front;
adamc@136 339 for (s1 = r, s2 = *s; *s2; ++s1, ++s2) {
adamc@136 340 char c = *s2;
adamc@136 341
adamc@136 342 switch (c) {
adamc@136 343 case '+':
adamc@136 344 *s1 = ' ';
adamc@136 345 break;
adamc@136 346 case '%':
adamc@136 347 assert(s2 + 2 < new_s);
adamc@136 348 sscanf(s2+1, "%02X", &n);
adamc@136 349 *s1 = n;
adamc@136 350 s2 += 2;
adamc@136 351 break;
adamc@136 352 default:
adamc@136 353 *s1 = c;
adamc@136 354 }
adamc@136 355 }
adamc@136 356 *s1++ = 0;
adamc@136 357 ctx->heap_front = s1;
adamc@136 358 *s = new_s;
adamc@136 359 return r;
adamc@120 360 }
adamc@135 361
adamc@135 362
adamc@136 363 char *lw_Basis_htmlifyString(lw_context ctx, lw_Basis_string s) {
adamc@137 364 char *r, *s2;
adamc@137 365
adamc@137 366 lw_check_heap(ctx, strlen(s) * 5 + 1);
adamc@137 367
adamc@137 368 for (r = s2 = ctx->heap_front; *s; s++) {
adamc@137 369 char c = *s;
adamc@137 370
adamc@137 371 switch (c) {
adamc@137 372 case '<':
adamc@137 373 strcpy(s2, "&lt;");
adamc@137 374 s2 += 4;
adamc@137 375 break;
adamc@137 376 case '&':
adamc@137 377 strcpy(s2, "&amp;");
adamc@137 378 s2 += 5;
adamc@137 379 break;
adamc@137 380 default:
adamc@137 381 if (isprint(c))
adamc@137 382 *s2++ = c;
adamc@137 383 else {
adamc@137 384 int len2;
adamc@137 385 sprintf(s2, "&#%d;%n", c, &len2);
adamc@137 386 s2 += len2;
adamc@137 387 }
adamc@137 388 }
adamc@137 389 }
adamc@137 390
adamc@137 391 *s2++ = 0;
adamc@137 392 ctx->heap_front = s2;
adamc@137 393 return r;
adamc@135 394 }
adamc@135 395
adamc@135 396 void lw_Basis_htmlifyString_w(lw_context ctx, lw_Basis_string s) {
adamc@135 397 lw_check(ctx, strlen(s) * 5);
adamc@135 398
adamc@135 399 for (; *s; s++) {
adamc@135 400 char c = *s;
adamc@135 401
adamc@135 402 switch (c) {
adamc@135 403 case '<':
adamc@135 404 lw_write_unsafe(ctx, "&lt;");
adamc@135 405 break;
adamc@135 406 case '&':
adamc@135 407 lw_write_unsafe(ctx, "&amp;");
adamc@135 408 break;
adamc@135 409 default:
adamc@135 410 if (isprint(c))
adamc@135 411 lw_writec_unsafe(ctx, c);
adamc@135 412 else {
adamc@135 413 lw_write_unsafe(ctx, "&#");
adamc@135 414 lw_Basis_attrifyInt_w_unsafe(ctx, c);
adamc@135 415 lw_writec_unsafe(ctx, ';');
adamc@135 416 }
adamc@135 417 }
adamc@135 418 }
adamc@135 419 }