diff 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
line wrap: on
line diff
--- a/src/c/urweb.c	Thu Dec 10 12:06:03 2009 -0500
+++ b/src/c/urweb.c	Thu Dec 10 13:32:09 2009 -0500
@@ -199,6 +199,7 @@
 }
 
 static char *on_success = "HTTP/1.1 200 OK\r\n";
+static char *on_redirect = "HTTP/1.1 303 See Other\r\n";
 
 void uw_set_on_success(char *s) {
   on_success = s;
@@ -352,7 +353,7 @@
   void *get_header_data;
 
   buf outHeaders, page, heap, script;
-  int returning_blob;
+  int returning_indirectly;
   input *inputs, *subinputs, *cur_container;
   size_t n_subinputs, used_subinputs;
 
@@ -396,7 +397,7 @@
 
   buf_init(&ctx->outHeaders, 0);
   buf_init(&ctx->page, 0);
-  ctx->returning_blob = 0;
+  ctx->returning_indirectly = 0;
   buf_init(&ctx->heap, 0);
   buf_init(&ctx->script, 1);
   ctx->script.start[0] = 0;
@@ -475,7 +476,7 @@
   buf_reset(&ctx->script);
   ctx->script.start[0] = 0;
   buf_reset(&ctx->page);
-  ctx->returning_blob = 0;
+  ctx->returning_indirectly = 0;
   buf_reset(&ctx->heap);
   ctx->regions = NULL;
   ctx->cleanup_front = ctx->cleanup;
@@ -2793,7 +2794,7 @@
     ctx->transactionals[i].free(ctx->transactionals[i].data);
 
   // Splice script data into appropriate part of page
-  if (ctx->returning_blob || ctx->script_header[0] == 0) {
+  if (ctx->returning_indirectly || ctx->script_header[0] == 0) {
     char *start = strstr(ctx->page.start, "<sc>");
     if (start) {
       memmove(start, start + 4, buf_used(&ctx->page) - (start - ctx->page.start) - 4);
@@ -2942,7 +2943,17 @@
 extern int uw_check_url(const char *);
 extern int uw_check_mime(const char *);
 
+static int url_bad(uw_Basis_string s) {
+  for (; *s; ++s)
+    if (!isgraph(*s))
+      return 1;
+
+  return 0;
+}
+
 uw_Basis_string uw_Basis_bless(uw_context ctx, uw_Basis_string s) {
+  if (url_bad(s))
+    uw_error(ctx, FATAL, "Invalid URL %s", uw_Basis_htmlifyString(ctx, s));
   if (uw_check_url(s))
     return s;
   else
@@ -2950,6 +2961,8 @@
 }
 
 uw_Basis_string uw_Basis_checkUrl(uw_context ctx, uw_Basis_string s) {
+  if (url_bad(s))
+    return NULL;
   if (uw_check_url(s))
     return s;
   else
@@ -3024,7 +3037,7 @@
   cleanup *cl;
   int len;
 
-  ctx->returning_blob = 1;
+  ctx->returning_indirectly = 1;
   buf_reset(&ctx->outHeaders);
   buf_reset(&ctx->page);
 
@@ -3044,7 +3057,28 @@
 
   ctx->cleanup_front = ctx->cleanup;
 
-  longjmp(ctx->jmp_buf, RETURN_BLOB);
+  longjmp(ctx->jmp_buf, RETURN_INDIRECTLY);
+}
+
+__attribute__((noreturn)) void uw_redirect(uw_context ctx, uw_Basis_string url) {
+  cleanup *cl;
+  int len;
+
+  ctx->returning_indirectly = 1;
+  buf_reset(&ctx->outHeaders);
+  buf_reset(&ctx->page);
+
+  uw_write_header(ctx, on_redirect);
+  uw_write_header(ctx, "Location: ");
+  uw_write_header(ctx, url);
+  uw_write_header(ctx, "\r\n\r\n");
+
+  for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
+    cl->func(cl->arg);
+
+  ctx->cleanup_front = ctx->cleanup;
+
+  longjmp(ctx->jmp_buf, RETURN_INDIRECTLY);
 }
 
 uw_Basis_string uw_Basis_unAs(uw_context ctx, uw_Basis_string s) {