Mercurial > urweb
diff src/c/urweb.c @ 1877:22b44fe822bf
Take proper account of signatures changing during page generation
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Thu, 10 Oct 2013 14:48:43 -0400 |
parents | 216a3a67ebe3 |
children | 0354df1b6849 |
line wrap: on
line diff
--- a/src/c/urweb.c Mon Oct 07 14:08:53 2013 +0400 +++ b/src/c/urweb.c Thu Oct 10 14:48:43 2013 -0400 @@ -471,6 +471,8 @@ int amInitializing; char error_message[ERROR_BUF_LEN]; + + int usedSig, needsResig; }; size_t uw_headers_max = SIZE_MAX; @@ -546,6 +548,9 @@ ctx->amInitializing = 0; + ctx->usedSig = 0; + ctx->needsResig = 0; + return ctx; } @@ -624,6 +629,8 @@ ctx->queryString = NULL; ctx->nextId = 0; ctx->amInitializing = 0; + ctx->usedSig = 0; + ctx->needsResig = 0; } void uw_reset_keep_request(uw_context ctx) { @@ -3083,6 +3090,11 @@ return NULL; } +static void set_cookie(uw_context ctx) { + if (ctx->usedSig) + ctx->needsResig = 1; +} + uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v, uw_Basis_time *expires, uw_Basis_bool secure) { uw_write_header(ctx, "Set-Cookie: "); uw_write_header(ctx, c); @@ -3105,6 +3117,7 @@ if (secure) uw_write_header(ctx, "; secure"); uw_write_header(ctx, "\r\n"); + set_cookie(ctx); return uw_unit_v; } @@ -3115,6 +3128,7 @@ uw_write_header(ctx, "=; path="); uw_write_header(ctx, prefix); uw_write_header(ctx, "; " THE_PAST "\r\n"); + set_cookie(ctx); return uw_unit_v; } @@ -3192,8 +3206,32 @@ static const char begin_xhtml[] = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">"; +extern int uw_hash_blocksize; + +static const char sig_intro[] = "<input type=\"hidden\" name=\"Sig\" value=\""; + +static char *find_sig(char *haystack) { + int i; + char *s = strstr(haystack, sig_intro); + + if (!s || strlen(haystack) - (s - haystack) - (sizeof sig_intro - 1) < uw_hash_blocksize*2+1) + return NULL; + + s += sizeof sig_intro - 1; + + for (i = 0; i < uw_hash_blocksize*2; ++i) + if (!isxdigit((int)s[i])) + return NULL; + + if (s[i] != '"') + return NULL; + + return s; +} + void uw_commit(uw_context ctx) { int i; + char *sig; if (uw_has_error(ctx)) { uw_rollback(ctx, 0); @@ -3316,6 +3354,18 @@ } } } + + if (ctx->needsResig) { + sig = find_sig(ctx->page.start); + if (sig) { + char *realsig = ctx->app->cookie_sig(ctx); + + do { + memcpy(sig, realsig, 2*uw_hash_blocksize); + sig = find_sig(sig); + } while (sig); + } + } } @@ -3561,8 +3611,6 @@ return s ? s : ""; } -extern int uw_hash_blocksize; - uw_Basis_string uw_Basis_makeSigString(uw_context ctx, uw_Basis_string sig) { uw_Basis_string r = uw_malloc(ctx, 2 * uw_hash_blocksize + 1); int i; @@ -3591,6 +3639,7 @@ } uw_Basis_string uw_Basis_sigString(uw_context ctx, uw_unit u) { + ctx->usedSig = 1; return ctx->app->cookie_sig(ctx); }