Mercurial > urweb
comparison src/c/urweb.c @ 1065:217eb87dde31
Basis.url and redirects
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Thu, 10 Dec 2009 13:32:09 -0500 |
parents | e3f6620afd51 |
children | 740b85ef4352 |
comparison
equal
deleted
inserted
replaced
1064:b89e3d8731ed | 1065:217eb87dde31 |
---|---|
197 pthread_mutex_unlock(&clients_mutex); | 197 pthread_mutex_unlock(&clients_mutex); |
198 return c; | 198 return c; |
199 } | 199 } |
200 | 200 |
201 static char *on_success = "HTTP/1.1 200 OK\r\n"; | 201 static char *on_success = "HTTP/1.1 200 OK\r\n"; |
202 static char *on_redirect = "HTTP/1.1 303 See Other\r\n"; | |
202 | 203 |
203 void uw_set_on_success(char *s) { | 204 void uw_set_on_success(char *s) { |
204 on_success = s; | 205 on_success = s; |
205 } | 206 } |
206 | 207 |
350 struct uw_context { | 351 struct uw_context { |
351 char *(*get_header)(void *, const char *); | 352 char *(*get_header)(void *, const char *); |
352 void *get_header_data; | 353 void *get_header_data; |
353 | 354 |
354 buf outHeaders, page, heap, script; | 355 buf outHeaders, page, heap, script; |
355 int returning_blob; | 356 int returning_indirectly; |
356 input *inputs, *subinputs, *cur_container; | 357 input *inputs, *subinputs, *cur_container; |
357 size_t n_subinputs, used_subinputs; | 358 size_t n_subinputs, used_subinputs; |
358 | 359 |
359 int source_count; | 360 int source_count; |
360 | 361 |
394 ctx->get_header = NULL; | 395 ctx->get_header = NULL; |
395 ctx->get_header_data = NULL; | 396 ctx->get_header_data = NULL; |
396 | 397 |
397 buf_init(&ctx->outHeaders, 0); | 398 buf_init(&ctx->outHeaders, 0); |
398 buf_init(&ctx->page, 0); | 399 buf_init(&ctx->page, 0); |
399 ctx->returning_blob = 0; | 400 ctx->returning_indirectly = 0; |
400 buf_init(&ctx->heap, 0); | 401 buf_init(&ctx->heap, 0); |
401 buf_init(&ctx->script, 1); | 402 buf_init(&ctx->script, 1); |
402 ctx->script.start[0] = 0; | 403 ctx->script.start[0] = 0; |
403 | 404 |
404 ctx->inputs = calloc(uw_inputs_len, sizeof(input)); | 405 ctx->inputs = calloc(uw_inputs_len, sizeof(input)); |
473 | 474 |
474 buf_reset(&ctx->outHeaders); | 475 buf_reset(&ctx->outHeaders); |
475 buf_reset(&ctx->script); | 476 buf_reset(&ctx->script); |
476 ctx->script.start[0] = 0; | 477 ctx->script.start[0] = 0; |
477 buf_reset(&ctx->page); | 478 buf_reset(&ctx->page); |
478 ctx->returning_blob = 0; | 479 ctx->returning_indirectly = 0; |
479 buf_reset(&ctx->heap); | 480 buf_reset(&ctx->heap); |
480 ctx->regions = NULL; | 481 ctx->regions = NULL; |
481 ctx->cleanup_front = ctx->cleanup; | 482 ctx->cleanup_front = ctx->cleanup; |
482 ctx->source_count = 0; | 483 ctx->source_count = 0; |
483 ctx->used_deltas = 0; | 484 ctx->used_deltas = 0; |
2791 | 2792 |
2792 for (i = 0; i < ctx->used_transactionals; ++i) | 2793 for (i = 0; i < ctx->used_transactionals; ++i) |
2793 ctx->transactionals[i].free(ctx->transactionals[i].data); | 2794 ctx->transactionals[i].free(ctx->transactionals[i].data); |
2794 | 2795 |
2795 // Splice script data into appropriate part of page | 2796 // Splice script data into appropriate part of page |
2796 if (ctx->returning_blob || ctx->script_header[0] == 0) { | 2797 if (ctx->returning_indirectly || ctx->script_header[0] == 0) { |
2797 char *start = strstr(ctx->page.start, "<sc>"); | 2798 char *start = strstr(ctx->page.start, "<sc>"); |
2798 if (start) { | 2799 if (start) { |
2799 memmove(start, start + 4, buf_used(&ctx->page) - (start - ctx->page.start) - 4); | 2800 memmove(start, start + 4, buf_used(&ctx->page) - (start - ctx->page.start) - 4); |
2800 ctx->page.front -= 4; | 2801 ctx->page.front -= 4; |
2801 } | 2802 } |
2940 } | 2941 } |
2941 | 2942 |
2942 extern int uw_check_url(const char *); | 2943 extern int uw_check_url(const char *); |
2943 extern int uw_check_mime(const char *); | 2944 extern int uw_check_mime(const char *); |
2944 | 2945 |
2946 static int url_bad(uw_Basis_string s) { | |
2947 for (; *s; ++s) | |
2948 if (!isgraph(*s)) | |
2949 return 1; | |
2950 | |
2951 return 0; | |
2952 } | |
2953 | |
2945 uw_Basis_string uw_Basis_bless(uw_context ctx, uw_Basis_string s) { | 2954 uw_Basis_string uw_Basis_bless(uw_context ctx, uw_Basis_string s) { |
2955 if (url_bad(s)) | |
2956 uw_error(ctx, FATAL, "Invalid URL %s", uw_Basis_htmlifyString(ctx, s)); | |
2946 if (uw_check_url(s)) | 2957 if (uw_check_url(s)) |
2947 return s; | 2958 return s; |
2948 else | 2959 else |
2949 uw_error(ctx, FATAL, "Disallowed URL %s", uw_Basis_htmlifyString(ctx, s)); | 2960 uw_error(ctx, FATAL, "Disallowed URL %s", uw_Basis_htmlifyString(ctx, s)); |
2950 } | 2961 } |
2951 | 2962 |
2952 uw_Basis_string uw_Basis_checkUrl(uw_context ctx, uw_Basis_string s) { | 2963 uw_Basis_string uw_Basis_checkUrl(uw_context ctx, uw_Basis_string s) { |
2964 if (url_bad(s)) | |
2965 return NULL; | |
2953 if (uw_check_url(s)) | 2966 if (uw_check_url(s)) |
2954 return s; | 2967 return s; |
2955 else | 2968 else |
2956 return NULL; | 2969 return NULL; |
2957 } | 2970 } |
3022 | 3035 |
3023 __attribute__((noreturn)) void uw_return_blob(uw_context ctx, uw_Basis_blob b, uw_Basis_string mimeType) { | 3036 __attribute__((noreturn)) void uw_return_blob(uw_context ctx, uw_Basis_blob b, uw_Basis_string mimeType) { |
3024 cleanup *cl; | 3037 cleanup *cl; |
3025 int len; | 3038 int len; |
3026 | 3039 |
3027 ctx->returning_blob = 1; | 3040 ctx->returning_indirectly = 1; |
3028 buf_reset(&ctx->outHeaders); | 3041 buf_reset(&ctx->outHeaders); |
3029 buf_reset(&ctx->page); | 3042 buf_reset(&ctx->page); |
3030 | 3043 |
3031 uw_write_header(ctx, on_success); | 3044 uw_write_header(ctx, on_success); |
3032 uw_write_header(ctx, "Content-Type: "); | 3045 uw_write_header(ctx, "Content-Type: "); |
3042 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl) | 3055 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl) |
3043 cl->func(cl->arg); | 3056 cl->func(cl->arg); |
3044 | 3057 |
3045 ctx->cleanup_front = ctx->cleanup; | 3058 ctx->cleanup_front = ctx->cleanup; |
3046 | 3059 |
3047 longjmp(ctx->jmp_buf, RETURN_BLOB); | 3060 longjmp(ctx->jmp_buf, RETURN_INDIRECTLY); |
3061 } | |
3062 | |
3063 __attribute__((noreturn)) void uw_redirect(uw_context ctx, uw_Basis_string url) { | |
3064 cleanup *cl; | |
3065 int len; | |
3066 | |
3067 ctx->returning_indirectly = 1; | |
3068 buf_reset(&ctx->outHeaders); | |
3069 buf_reset(&ctx->page); | |
3070 | |
3071 uw_write_header(ctx, on_redirect); | |
3072 uw_write_header(ctx, "Location: "); | |
3073 uw_write_header(ctx, url); | |
3074 uw_write_header(ctx, "\r\n\r\n"); | |
3075 | |
3076 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl) | |
3077 cl->func(cl->arg); | |
3078 | |
3079 ctx->cleanup_front = ctx->cleanup; | |
3080 | |
3081 longjmp(ctx->jmp_buf, RETURN_INDIRECTLY); | |
3048 } | 3082 } |
3049 | 3083 |
3050 uw_Basis_string uw_Basis_unAs(uw_context ctx, uw_Basis_string s) { | 3084 uw_Basis_string uw_Basis_unAs(uw_context ctx, uw_Basis_string s) { |
3051 uw_Basis_string r = uw_malloc(ctx, strlen(s) + 1); | 3085 uw_Basis_string r = uw_malloc(ctx, strlen(s) + 1); |
3052 | 3086 |