Mercurial > urweb
comparison src/c/urweb.c @ 1728:95d3b4f26f59
Ensure proper ordering of <script> execution, to bring identifiers into scope in time
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Fri, 27 Apr 2012 09:43:09 -0400 |
parents | 4df4521fbd3b |
children | 6817ddd6cf1f |
comparison
equal
deleted
inserted
replaced
1727:318ba997a149 | 1728:95d3b4f26f59 |
---|---|
1308 int len = strlen(s); | 1308 int len = strlen(s); |
1309 | 1309 |
1310 uw_check_script(ctx, len + 1); | 1310 uw_check_script(ctx, len + 1); |
1311 strcpy(ctx->script.front, s); | 1311 strcpy(ctx->script.front, s); |
1312 ctx->script.front += len; | 1312 ctx->script.front += len; |
1313 } | |
1314 | |
1315 const char *uw_Basis_get_script(uw_context ctx, uw_unit u) { | |
1316 return "<sc>"; | |
1317 } | 1313 } |
1318 | 1314 |
1319 const char *uw_get_real_script(uw_context ctx) { | 1315 const char *uw_get_real_script(uw_context ctx) { |
1320 if (strstr(ctx->outHeaders.start, "Set-Cookie: ")) { | 1316 if (strstr(ctx->outHeaders.start, "Set-Cookie: ")) { |
1321 uw_write_script(ctx, "sig=\""); | 1317 uw_write_script(ctx, "sig=\""); |
3155 ctx->transactionals[i].free(ctx->transactionals[i].data, will_retry); | 3151 ctx->transactionals[i].free(ctx->transactionals[i].data, will_retry); |
3156 | 3152 |
3157 return ctx->app ? ctx->app->db_rollback(ctx) : 0; | 3153 return ctx->app ? ctx->app->db_rollback(ctx) : 0; |
3158 } | 3154 } |
3159 | 3155 |
3156 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\">"; | |
3157 | |
3160 void uw_commit(uw_context ctx) { | 3158 void uw_commit(uw_context ctx) { |
3161 int i; | 3159 int i; |
3162 | 3160 |
3163 if (uw_has_error(ctx)) { | 3161 if (uw_has_error(ctx)) { |
3164 uw_rollback(ctx, 0); | 3162 uw_rollback(ctx, 0); |
3208 ctx->transactionals[i].free(ctx->transactionals[i].data, 0); | 3206 ctx->transactionals[i].free(ctx->transactionals[i].data, 0); |
3209 | 3207 |
3210 uw_check(ctx, 1); | 3208 uw_check(ctx, 1); |
3211 *ctx->page.front = 0; | 3209 *ctx->page.front = 0; |
3212 | 3210 |
3213 // Splice script data into appropriate part of page | 3211 if (!ctx->returning_indirectly && !strncmp(ctx->page.start, begin_xhtml, sizeof begin_xhtml - 1)) { |
3214 if (ctx->returning_indirectly || ctx->script_header[0] == 0) { | 3212 char *s; |
3215 char *start = strstr(ctx->page.start, "<sc>"); | 3213 |
3216 if (start) { | 3214 // Splice script data into appropriate part of page, also adding <head> if needed. |
3217 memmove(start, start + 4, uw_buffer_used(&ctx->page) - (start - ctx->page.start) - 4); | 3215 s = ctx->page.start + sizeof begin_xhtml - 1; |
3218 ctx->page.front -= 4; | 3216 s = strchr(s, '<'); |
3219 } | 3217 if (s == NULL) { |
3220 } else if (uw_buffer_used(&ctx->script) == 0) { | 3218 // Weird. Document has no tags! |
3221 size_t len = strlen(ctx->script_header); | 3219 |
3222 char *start = strstr(ctx->page.start, "<sc>"); | 3220 uw_write(ctx, "<head></head><body></body>"); |
3223 if (start) { | 3221 uw_check(ctx, 1); |
3224 ctx_uw_buffer_check(ctx, "page", &ctx->page, uw_buffer_used(&ctx->page) - 4 + len); | 3222 *ctx->page.front = 0; |
3225 start = strstr(ctx->page.start, "<sc>"); | 3223 } else if (!strncmp(s, "<head>", 6)) { |
3226 memmove(start + len, start + 4, uw_buffer_used(&ctx->page) - (start - ctx->page.start) - 3); | 3224 // <head> is present. Let's add the <script> tags immediately after it. |
3227 ctx->page.front += len - 4; | 3225 |
3228 memcpy(start, ctx->script_header, len); | 3226 size_t lenH = strlen(ctx->script_header), len = uw_buffer_used(&ctx->script); |
3229 } | 3227 size_t lenP = lenH + 40 + len; |
3230 } else { | 3228 char *start = s + 6, *oldPage = ctx->page.start; |
3231 size_t lenH = strlen(ctx->script_header), len = uw_buffer_used(&ctx->script); | 3229 |
3232 size_t lenP = lenH + 40 + len; | 3230 ctx_uw_buffer_check(ctx, "page", &ctx->page, uw_buffer_used(&ctx->page) + lenP); |
3233 char *start = strstr(ctx->page.start, "<sc>"); | 3231 start += ctx->page.start - oldPage; |
3234 if (start) { | 3232 memmove(start + lenP, start, uw_buffer_used(&ctx->page) - (start - ctx->page.start) + 1); |
3235 ctx_uw_buffer_check(ctx, "page", &ctx->page, uw_buffer_used(&ctx->page) - 4 + lenP); | 3233 ctx->page.front += lenP; |
3236 start = strstr(ctx->page.start, "<sc>"); | |
3237 memmove(start + lenP, start + 4, uw_buffer_used(&ctx->page) - (start - ctx->page.start) - 3); | |
3238 ctx->page.front += lenP - 4; | |
3239 memcpy(start, ctx->script_header, lenH); | 3234 memcpy(start, ctx->script_header, lenH); |
3240 memcpy(start + lenH, "<script type=\"text/javascript\">", 31); | 3235 memcpy(start + lenH, "<script type=\"text/javascript\">", 31); |
3241 memcpy(start + lenH + 31, ctx->script.start, len); | 3236 memcpy(start + lenH + 31, ctx->script.start, len); |
3242 memcpy(start + lenH + 31 + len, "</script>", 9); | 3237 memcpy(start + lenH + 31 + len, "</script>", 9); |
3238 } else { | |
3239 // No <head>. At this point, add it, with <script> tags inside. | |
3240 | |
3241 size_t lenH = strlen(ctx->script_header), len = uw_buffer_used(&ctx->script); | |
3242 size_t lenP = lenH + 53 + len; | |
3243 char *start = s, *oldPage = ctx->page.start; | |
3244 | |
3245 printf("start = %ld\n", start - ctx->page.start); | |
3246 | |
3247 ctx_uw_buffer_check(ctx, "page", &ctx->page, uw_buffer_used(&ctx->page) + lenP); | |
3248 start += ctx->page.start - oldPage; | |
3249 printf("page1 = %s\n", ctx->page.start); | |
3250 memmove(start + lenP, start, uw_buffer_used(&ctx->page) - (start - ctx->page.start) + 1); | |
3251 printf("page2 = %s\n", ctx->page.start); | |
3252 ctx->page.front += lenP; | |
3253 memcpy(start, "<head>", 6); | |
3254 memcpy(start + 6, ctx->script_header, lenH); | |
3255 memcpy(start + 6 + lenH, "<script type=\"text/javascript\">", 31); | |
3256 memcpy(start + 6 + lenH + 31, ctx->script.start, len); | |
3257 memcpy(start + 6 + lenH + 31 + len, "</script></head>", 16); | |
3243 } | 3258 } |
3244 } | 3259 } |
3245 } | 3260 } |
3246 | 3261 |
3247 | 3262 |
3917 } | 3932 } |
3918 else | 3933 else |
3919 return NULL; | 3934 return NULL; |
3920 } | 3935 } |
3921 | 3936 |
3922 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\">"; | |
3923 | |
3924 failure_kind uw_begin_onError(uw_context ctx, char *msg) { | 3937 failure_kind uw_begin_onError(uw_context ctx, char *msg) { |
3925 int r = setjmp(ctx->jmp_buf); | 3938 int r = setjmp(ctx->jmp_buf); |
3926 | 3939 |
3927 if (ctx->app->on_error) { | 3940 if (ctx->app->on_error) { |
3928 if (r == 0) { | 3941 if (r == 0) { |