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