changeset 1552:c3b5cf5c2f98

Gentle handling of back-button returns to pages with stale message-passing credentials
author Adam Chlipala <adam@chlipala.net>
date Sun, 28 Aug 2011 17:16:54 -0400
parents 5175bed443f9
children 4105f779de7b
files lib/js/urweb.js src/c/urweb.c tests/goback.ur tests/goback.urp tests/goback.urs
diffstat 5 files changed, 49 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/lib/js/urweb.js	Sun Aug 28 14:43:30 2011 -0400
+++ b/lib/js/urweb.js	Sun Aug 28 17:16:54 2011 -0400
@@ -736,6 +736,7 @@
 var client_pass = 0;
 var url_prefix = "/";
 var timeout = 60;
+var isPost = false;
 
 function getXHR(uri)
 {
@@ -909,6 +910,15 @@
                     return;
                 var lines = text.split("\n");
 
+                if (lines.length == 1 && lines[0] == "R") {
+                    if (isPost)
+                        history.back();
+                    else
+                        location.reload();
+
+                    return;
+                }
+
                 if (lines.length < 2) {
                     discon();
                     return;
--- a/src/c/urweb.c	Sun Aug 28 14:43:30 2011 -0400
+++ b/src/c/urweb.c	Sun Aug 28 17:16:54 2011 -0400
@@ -247,6 +247,13 @@
   on_success = s;
 }
 
+static void chastise(int (*send)(int sockfd, const void *buf, ssize_t len), int sock) {
+  send(sock, on_success, strlen(on_success));
+  send(sock, begin_msgs, sizeof(begin_msgs) - 1);
+  send(sock, "R", 1);
+  close(sock);
+}
+
 void uw_client_connect(unsigned id, int pass, int sock,
                        int (*send)(int sockfd, const void *buf, ssize_t len),
                        int (*close)(int fd),
@@ -254,7 +261,7 @@
   client *c = find_client(id);
 
   if (c == NULL) {
-    close(sock);
+    chastise(send, sock);
     log_error(logger_data, "Out-of-bounds client request (%u)\n", id);
     return;
   }
@@ -263,14 +270,14 @@
 
   if (c->mode != USED) {
     pthread_mutex_unlock(&c->lock);
-    close(sock);
+    chastise(send, sock);
     log_error(logger_data, "Client request for unused slot (%u)\n", id);
     return;
   }
 
   if (pass != c->pass) {
     pthread_mutex_unlock(&c->lock);
-    close(sock);
+    chastise(send, sock);
     log_error(logger_data, "Wrong client password (%u, %d)\n", id, pass);
     return;
   }
@@ -1342,7 +1349,8 @@
     char *sig = ctx->needs_sig ? ctx->app->cookie_sig(ctx) : "";
     char *r = uw_malloc(ctx, 59 + 3 * INTS_MAX + strlen(ctx->app->url_prefix)
                         + (ctx->needs_sig ? strlen(sig) + 7 : 0));
-    sprintf(r, "client_id=%u;client_pass=%d;url_prefix=\"%s\";timeout=%d;%s%s%slistener();",
+    sprintf(r, "isPost=%s;client_id=%u;client_pass=%d;url_prefix=\"%s\";timeout=%d;%s%s%slistener();",
+            (ctx->isPost ? "true" : "false"),
             ctx->client->id,
             ctx->client->pass,
             ctx->app->url_prefix,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/goback.ur	Sun Aug 28 17:16:54 2011 -0400
@@ -0,0 +1,20 @@
+table channels : { Channel : channel {} }
+
+fun get () =
+    ch <- channel;
+    dml (INSERT INTO channels (Channel) VALUES ({[ch]}));
+    return <xml><body onload={recv ch}>
+      Hi.
+    </body></xml>
+
+fun post () =
+    ch <- channel;
+    dml (INSERT INTO channels (Channel) VALUES ({[ch]}));
+    return <xml><body onload={recv ch}>
+      Hi!
+    </body></xml>
+
+fun main () = return <xml><body>
+  <li><a link={get ()}>Get</a></li>
+  <li><form><submit action={post}/></form></li>
+</body></xml>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/goback.urp	Sun Aug 28 17:16:54 2011 -0400
@@ -0,0 +1,6 @@
+database dbname=goback
+sql goback.sql
+rewrite all Goback/*
+safeGet get
+
+goback
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/goback.urs	Sun Aug 28 17:16:54 2011 -0400
@@ -0,0 +1,1 @@
+val main : {} -> transaction page