Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Clarify the origin of JS in the generated HTML. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
6854244949f334722f97d3d8a60ee8ad |
User & Date: | drh 2020-09-18 03:28:39 |
Context
2020-09-18
| ||
04:10 | pikchr js: hide/show the SVG's parent element instead of the SVG, so that output from pikchr print commands is hidden when the source is shown. ... (check-in: 43116c73 user: stephan tags: trunk) | |
03:28 | Clarify the origin of JS in the generated HTML. ... (check-in: 68542449 user: drh tags: trunk) | |
02:54 | Always include a \n after the opening safe_html() nonce when generating Pikchr output, for improved human readability of the generated HTML. ... (check-in: 39b2081e user: drh tags: trunk) | |
Changes
Changes to src/ajax.c.
︙ | ︙ | |||
44 45 46 47 48 49 50 | ** with the current nonce, else no SCRIPT tag is emitted. ** ** Requires that builtin_emit_script_fossil_bootstrap() has already been ** called in order to initialize the window.fossil.page object. */ void ajax_emit_js_preview_modes(int addScriptTag){ if(addScriptTag){ | | < | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | ** with the current nonce, else no SCRIPT tag is emitted. ** ** Requires that builtin_emit_script_fossil_bootstrap() has already been ** called in order to initialize the window.fossil.page object. */ void ajax_emit_js_preview_modes(int addScriptTag){ if(addScriptTag){ style_script_begin(__FILE__,__LINE__); } CX("fossil.page.previewModes={" "guess: %d, %d: 'guess', wiki: %d, %d: 'wiki'," "htmlIframe: %d, %d: 'htmlIframe', " "htmlInline: %d, %d: 'htmlInline', " "text: %d, %d: 'text'" "};\n", AJAX_RENDER_GUESS, AJAX_RENDER_GUESS, AJAX_RENDER_WIKI, AJAX_RENDER_WIKI, AJAX_RENDER_HTML_IFRAME, AJAX_RENDER_HTML_IFRAME, AJAX_RENDER_HTML_INLINE, AJAX_RENDER_HTML_INLINE, AJAX_RENDER_PLAIN_TEXT, AJAX_RENDER_PLAIN_TEXT); if(addScriptTag){ style_script_end(); } } /* ** Returns a value from the ajax_render_modes enum, based on the ** given mime type string (which may be NULL), defaulting to ** AJAX_RENDER_PLAIN_TEXT. |
︙ | ︙ |
Changes to src/builtin.c.
︙ | ︙ | |||
314 315 316 317 318 319 320 | void builtin_fulfill_js_requests(void){ if( builtin.nSent>=builtin.nReq ) return; /* nothing to do */ switch( builtin.eDelivery ){ case JS_INLINE: { CX("<script nonce='%h'>\n",style_nonce()); do{ int i = builtin.aReq[builtin.nSent++]; | | | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | void builtin_fulfill_js_requests(void){ if( builtin.nSent>=builtin.nReq ) return; /* nothing to do */ switch( builtin.eDelivery ){ case JS_INLINE: { CX("<script nonce='%h'>\n",style_nonce()); do{ int i = builtin.aReq[builtin.nSent++]; CX("/* %s %.60c*/\n", aBuiltinFiles[i].zName, '*'); cgi_append_content((const char*)aBuiltinFiles[i].pData, aBuiltinFiles[i].nByte); }while( builtin.nSent<builtin.nReq ); CX("</script>\n"); break; } case JS_BUNDLED: { |
︙ | ︙ | |||
590 591 592 593 594 595 596 | void builtin_emit_script_fossil_bootstrap(int addScriptTag){ static int once = 0; if(0==once++){ char * zName; /* Set up the generic/app-agnostic parts of window.fossil ** which require C-level state... */ if(addScriptTag!=0){ | | | 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 | void builtin_emit_script_fossil_bootstrap(int addScriptTag){ static int once = 0; if(0==once++){ char * zName; /* Set up the generic/app-agnostic parts of window.fossil ** which require C-level state... */ if(addScriptTag!=0){ style_script_begin(__FILE__,__LINE__); } CX("(function(){\n"); CX(/*MSIE NodeList.forEach polyfill, courtesy of Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Polyfill */ "if(window.NodeList && !NodeList.prototype.forEach){" "NodeList.prototype.forEach = Array.prototype.forEach;" |
︙ | ︙ | |||
653 654 655 656 657 658 659 | ** page-specific state, and it is reserved for that purpose. */ CX("window.fossil.page = {" "name:\"%T\"" "};\n", g.zPath); CX("})();\n"); if(addScriptTag!=0){ | | | 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 | ** page-specific state, and it is reserved for that purpose. */ CX("window.fossil.page = {" "name:\"%T\"" "};\n", g.zPath); CX("})();\n"); if(addScriptTag!=0){ style_script_end(); } /* The remaining window.fossil bootstrap code is not dependent on ** C-runtime state... */ builtin_request_js("fossil.bootstrap.js"); } } |
︙ | ︙ |
Changes to src/captcha.c.
︙ | ︙ | |||
560 561 562 563 564 565 566 | /* ** Add a "Speak the captcha" button. */ void captcha_speakit_button(unsigned int uSeed, const char *zMsg){ if( zMsg==0 ) zMsg = "Speak the text"; @ <input aria-label="%h(zMsg)" type="button" value="%h(zMsg)" \ @ id="speakthetext"> | | | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 | /* ** Add a "Speak the captcha" button. */ void captcha_speakit_button(unsigned int uSeed, const char *zMsg){ if( zMsg==0 ) zMsg = "Speak the text"; @ <input aria-label="%h(zMsg)" type="button" value="%h(zMsg)" \ @ id="speakthetext"> @ <script nonce="%h(style_nonce())">/* captcha_speakit_button() */ @ document.getElementById("speakthetext").onclick = function(){ @ var audio = window.fossilAudioCaptcha \ @ || new Audio("%R/captcha-audio/%u(uSeed)"); @ window.fossilAudioCaptcha = audio; @ audio.currentTime = 0; @ audio.play(); @ } |
︙ | ︙ |
Changes to src/doc.c.
︙ | ︙ | |||
406 407 408 409 410 411 412 | ** functionality, just nice-to-haves. Only call this once per page. */ void document_emit_js(void){ if(!builtin_bundle_all_fossil_js_apis()){ builtin_emit_fossil_js_apis("dom", "copybutton", "pikchr", 0); } | | | | 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | ** functionality, just nice-to-haves. Only call this once per page. */ void document_emit_js(void){ if(!builtin_bundle_all_fossil_js_apis()){ builtin_emit_fossil_js_apis("dom", "copybutton", "pikchr", 0); } style_script_begin(__FILE__,__LINE__); CX("window.addEventListener('load', " "()=>window.fossil.pikchr.addSrcView(), " "false);\n"); style_script_end(); } /* ** Guess the mime-type of a document based on its name. */ const char *mimetype_from_name(const char *zName){ const char *z; |
︙ | ︙ |
Changes to src/fileedit.c.
︙ | ︙ | |||
1664 1665 1666 1667 1668 1669 1670 | /* The CSS for this page lives in a common file but much of it we ** don't want inadvertently being used by other pages. We don't ** have a common, page-specific container we can filter our CSS ** selectors, but we do have the BODY, which we can decorate with ** whatever CSS we wish... */ | | | | 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 | /* The CSS for this page lives in a common file but much of it we ** don't want inadvertently being used by other pages. We don't ** have a common, page-specific container we can filter our CSS ** selectors, but we do have the BODY, which we can decorate with ** whatever CSS we wish... */ style_script_begin(__FILE__,__LINE__); CX("document.body.classList.add('fileedit');\n"); style_script_end(); /* Status bar */ CX("<div id='fossil-status-bar' " "title='Status message area. Double-click to clear them.'>" "Status messages will go here.</div>\n" /* will be moved into the tab container via JS */); |
︙ | ︙ | |||
2007 2008 2009 2010 2011 2012 2013 | builtin_request_js("fossil.page.fileedit.js"); builtin_fulfill_js_requests(); { /* Dynamically populate the editor, display any error in the err ** blob, and/or switch to tab #0, where the file selector ** lives. The extra C scopes here correspond to JS-level scopes, ** to improve grokability. */ | | | 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 | builtin_request_js("fossil.page.fileedit.js"); builtin_fulfill_js_requests(); { /* Dynamically populate the editor, display any error in the err ** blob, and/or switch to tab #0, where the file selector ** lives. The extra C scopes here correspond to JS-level scopes, ** to improve grokability. */ style_script_begin(__FILE__,__LINE__); CX("\n(function(){\n"); CX("try{\n"); { char * zFirstLeafUuid = 0; CX("fossil.config['fileedit-glob'] = "); glob_render_json_to_cgi(fileedit_glob()); CX(";\n"); |
︙ | ︙ | |||
2056 2057 2058 2059 2060 2061 2062 | } CX("});\n")/*fossil.onPageLoad()*/; } CX("}catch(e){" "fossil.error(e); console.error('Exception:',e);" "}\n"); CX("})();")/*anonymous function*/; | | | 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 | } CX("});\n")/*fossil.onPageLoad()*/; } CX("}catch(e){" "fossil.error(e); console.error('Exception:',e);" "}\n"); CX("})();")/*anonymous function*/; style_script_end(); } blob_reset(&err); CheckinMiniInfo_cleanup(&cimi); db_end_transaction(0); style_footer(); } |
Changes to src/info.c.
︙ | ︙ | |||
2442 2443 2444 2445 2446 2447 2448 | safe_html_context(DOCSRC_FILE); wiki_render_by_mimetype(&content, zMime); }else if( renderAsHtml ){ @ <iframe src="%R/raw/%s(zUuid)" @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" @ sandbox="allow-same-origin" id="ifm1"> @ </iframe> | | | 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 | safe_html_context(DOCSRC_FILE); wiki_render_by_mimetype(&content, zMime); }else if( renderAsHtml ){ @ <iframe src="%R/raw/%s(zUuid)" @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" @ sandbox="allow-same-origin" id="ifm1"> @ </iframe> @ <script nonce="%h(style_nonce())">/* info.c:%d(__LINE__) */ @ document.getElementById("ifm1").addEventListener("load", @ function(){ @ this.height=this.contentDocument.documentElement.scrollHeight + 75; @ } @ ); @ </script> }else{ |
︙ | ︙ |
Changes to src/style.c.
︙ | ︙ | |||
712 713 714 715 716 717 718 | static void style_load_all_js_files(void){ if( needHrefJs ){ int nDelay = db_get_int("auto-hyperlink-delay",0); int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0); @ <script id='href-data' type='application/json'>\ @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script> } | | | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 | static void style_load_all_js_files(void){ if( needHrefJs ){ int nDelay = db_get_int("auto-hyperlink-delay",0); int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0); @ <script id='href-data' type='application/json'>\ @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script> } @ <script nonce="%h(style_nonce())">/* style.c:%d(__LINE__) */ @ function debugMsg(msg){ @ var n = document.getElementById("debugMsg"); @ if(n){n.textContent=msg;} @ } if( needHrefJs ){ @ /* href.js */ cgi_append_content(builtin_text("href.js"),-1); |
︙ | ︙ | |||
1426 1427 1428 1429 1430 1431 1432 | CX("</select>\n"); CX("</div>\n"); va_end(vargs); fossil_free(zLabelID); } /* | < < < < < < < < | < < < < < > | > | > | | < < > > | | | > > > | < | 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 | CX("</select>\n"); CX("</div>\n"); va_end(vargs); fossil_free(zLabelID); } /* ** Generate a <script> with an appropriate nonce. ** ** zOrigin and iLine are the source code filename and line number ** that generated this request. */ void style_script_begin(const char *zOrigin, int iLine){ const char *z; for(z=zOrigin; z[0]!=0; z++){ if( z[0]=='/' || z[0]=='\\' ){ zOrigin = z+1; } } CX("<script nonce='%s'>/* %s:%d */\n", style_nonce(), zOrigin, iLine); } /* Generate the closing </script> tag */ void style_script_end(void){ CX("</script>\n"); } /* ** Emits a NOSCRIPT tag with an error message stating that JS is ** required for the current page. This "should" be called near the top ** of pages which *require* JS. The inner DIV has the CSS class ** 'error' and can be styled via a (noscript > .error) CSS selector. */ void style_emit_noscript_for_js_page(void){ CX("<noscript><div class='error'>" "This page requires JavaScript (ES2015, a.k.a. ES6, or newer)." "</div></noscript>"); } |
Changes to src/wiki.c.
︙ | ︙ | |||
1289 1290 1291 1292 1293 1294 1295 | "storage", "popupwidget", "copybutton", "pikchr", 0); } builtin_request_js("sbsdiff.js"); builtin_request_js("fossil.page.wikiedit.js"); builtin_fulfill_js_requests(); /* Dynamically populate the editor... */ | | | 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 | "storage", "popupwidget", "copybutton", "pikchr", 0); } builtin_request_js("sbsdiff.js"); builtin_request_js("fossil.page.wikiedit.js"); builtin_fulfill_js_requests(); /* Dynamically populate the editor... */ style_script_begin(__FILE__,__LINE__); { /* Render the current page list to save us an XHR request during page initialization. This must be OUTSIDE of an onPageLoad() handler or else it does not get applied until after the wiki list widget is initialized. Similarly, it must come *after* window.fossil is initialized. */ CX("\nfossil.page.initialPageList = "); |
︙ | ︙ | |||
1328 1329 1330 1331 1332 1333 1334 | if(zPageName && *zPageName){ CX("P.loadPage(%!j);\n", zPageName); } CX("}catch(e){" "fossil.error(e); console.error('Exception:',e);" "}\n"); CX("});\n"/*fossil.onPageLoad()*/); | | | 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 | if(zPageName && *zPageName){ CX("P.loadPage(%!j);\n", zPageName); } CX("}catch(e){" "fossil.error(e); console.error('Exception:',e);" "}\n"); CX("});\n"/*fossil.onPageLoad()*/); style_script_end(); style_footer(); } /* ** WEBPAGE: wikinew ** URL /wikinew ** |
︙ | ︙ |