diff options
-rw-r--r-- | lib/js/urweb.js | 2 | ||||
-rw-r--r-- | src/c/urweb.c | 48 | ||||
-rw-r--r-- | tests/channelThief.ur | 32 | ||||
-rw-r--r-- | tests/channelThief.urp | 5 | ||||
-rw-r--r-- | tests/channelThief.urs | 1 |
5 files changed, 62 insertions, 26 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js index e211d318..6830945a 100644 --- a/lib/js/urweb.js +++ b/lib/js/urweb.js @@ -1575,7 +1575,7 @@ function rv(chn, parse, k) { er("May not 'recv' in main thread of 'code' for <active>"); if (chn == null) - return; + er("Client-side code tried to recv() from a channel belonging to a different page view."); if (chn < 0) whine("Out-of-bounds channel receive"); diff --git a/src/c/urweb.c b/src/c/urweb.c index af5cc461..0265c67f 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -734,36 +734,34 @@ void uw_push_cleanup(uw_context ctx, void (*func)(void *), void *arg) { char *uw_Basis_htmlifyString(uw_context, const char *); void uw_login(uw_context ctx) { - if (ctx->needs_push) { - char *id_s, *pass_s; + char *id_s, *pass_s; - if ((id_s = uw_Basis_requestHeader(ctx, "UrWeb-Client")) - && (pass_s = uw_Basis_requestHeader(ctx, "UrWeb-Pass"))) { - unsigned id = atoi(id_s); - int pass = atoi(pass_s); - client *c = find_client(id); - - if (c == NULL) - uw_error(ctx, FATAL, "Unknown client ID in HTTP headers (%s, %s)", uw_Basis_htmlifyString(ctx, id_s), uw_Basis_htmlifyString(ctx, pass_s)); - else { - use_client(c); - ctx->client = c; - - if (c->mode != USED) - uw_error(ctx, FATAL, "Stale client ID (%u) in subscription request", id); - if (c->pass != pass) - uw_error(ctx, FATAL, "Wrong client password (%u, %d) in subscription request", id, pass); - } - } else { - client *c = new_client(); - - if (c == NULL) - uw_error(ctx, FATAL, "Limit exceeded on number of message-passing clients"); + if ((id_s = uw_Basis_requestHeader(ctx, "UrWeb-Client")) + && (pass_s = uw_Basis_requestHeader(ctx, "UrWeb-Pass"))) { + unsigned id = atoi(id_s); + int pass = atoi(pass_s); + client *c = find_client(id); + if (c == NULL) + uw_error(ctx, FATAL, "Unknown client ID in HTTP headers (%s, %s)", uw_Basis_htmlifyString(ctx, id_s), uw_Basis_htmlifyString(ctx, pass_s)); + else { use_client(c); - uw_copy_client_data(c->data, ctx->client_data); ctx->client = c; + + if (c->mode != USED) + uw_error(ctx, FATAL, "Stale client ID (%u) in subscription request", id); + if (c->pass != pass) + uw_error(ctx, FATAL, "Wrong client password (%u, %d) in subscription request", id, pass); } + } else if (ctx->needs_push) { + client *c = new_client(); + + if (c == NULL) + uw_error(ctx, FATAL, "Limit exceeded on number of message-passing clients"); + + use_client(c); + uw_copy_client_data(c->data, ctx->client_data); + ctx->client = c; } } diff --git a/tests/channelThief.ur b/tests/channelThief.ur new file mode 100644 index 00000000..1893979a --- /dev/null +++ b/tests/channelThief.ur @@ -0,0 +1,32 @@ +table t : { Ch : channel string } + +fun go () = + let + fun overwrite () = + dml (DELETE FROM t WHERE TRUE); + ch <- channel; + dml (INSERT INTO t (Ch) VALUES ({[ch]})); + return ch + + fun retrieve () = + oneRowE1 (SELECT (t.Ch) FROM t) + + fun transmit () = + ch <- retrieve (); + send ch "Test" + + fun listenOn ch = + s <- recv ch; + alert s + in + ch <- overwrite (); + return <xml><body onload={listenOn ch}> + <button value="overwrite" onclick={fn _ => ch <- rpc (overwrite ()); listenOn ch}/> + <button value="retrieve" onclick={fn _ => ch <- rpc (retrieve ()); listenOn ch}/> + <button value="transmit" onclick={fn _ => rpc (transmit ())}/> + </body></xml> + end + +fun main () = return <xml><body> + <form><submit action={go}/></form> +</body></xml> diff --git a/tests/channelThief.urp b/tests/channelThief.urp new file mode 100644 index 00000000..dee402d4 --- /dev/null +++ b/tests/channelThief.urp @@ -0,0 +1,5 @@ +database dbname=test +sql channelThief.sql +rewrite url ChannelThief/* + +channelThief diff --git a/tests/channelThief.urs b/tests/channelThief.urs new file mode 100644 index 00000000..6ac44e0b --- /dev/null +++ b/tests/channelThief.urs @@ -0,0 +1 @@ +val main : unit -> transaction page |