Fossil SCM
Add the safe-html setting that determines which kinds of documents are allowed to generate unsafe HTML from Markdown.
Commit
89b6dda99c45533358f1af425acc226fec851c8f325565d24980bb2f1fe1aa02
Parent
03ce4e70b62b93f…
9 files changed
+2
-1
+2
-1
+2
-1
+2
-1
+4
-2
+21
+1
+17
-8
+52
-3
+2
-1
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -390,11 +390,12 @@ | ||
| 390 | 390 | @ </iframe> |
| 391 | 391 | }else{ |
| 392 | 392 | Blob content; |
| 393 | 393 | const char *zMime = mimetype_from_name(zName); |
| 394 | 394 | content_get(rid, &content); |
| 395 | - wiki_render_by_mimetype(&content, zMime, 0); | |
| 395 | + safe_html_context(DOCSRC_FILE); | |
| 396 | + wiki_render_by_mimetype(&content, zMime); | |
| 396 | 397 | } |
| 397 | 398 | } |
| 398 | 399 | } |
| 399 | 400 | db_finalize(&q); |
| 400 | 401 | style_footer(); |
| 401 | 402 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -390,11 +390,12 @@ | |
| 390 | @ </iframe> |
| 391 | }else{ |
| 392 | Blob content; |
| 393 | const char *zMime = mimetype_from_name(zName); |
| 394 | content_get(rid, &content); |
| 395 | wiki_render_by_mimetype(&content, zMime, 0); |
| 396 | } |
| 397 | } |
| 398 | } |
| 399 | db_finalize(&q); |
| 400 | style_footer(); |
| 401 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -390,11 +390,12 @@ | |
| 390 | @ </iframe> |
| 391 | }else{ |
| 392 | Blob content; |
| 393 | const char *zMime = mimetype_from_name(zName); |
| 394 | content_get(rid, &content); |
| 395 | safe_html_context(DOCSRC_FILE); |
| 396 | wiki_render_by_mimetype(&content, zMime); |
| 397 | } |
| 398 | } |
| 399 | } |
| 400 | db_finalize(&q); |
| 401 | style_footer(); |
| 402 |
+2
-1
| --- src/event.c | ||
| +++ src/event.c | ||
| @@ -508,11 +508,12 @@ | ||
| 508 | 508 | @ </blockquote> |
| 509 | 509 | @ <p><b>Page content preview:</b><p> |
| 510 | 510 | @ <blockquote> |
| 511 | 511 | blob_init(&event, 0, 0); |
| 512 | 512 | blob_append(&event, zBody, -1); |
| 513 | - wiki_render_by_mimetype(&event, zMimetype, 0); | |
| 513 | + safe_html_context(DOCSRC_WIKI); | |
| 514 | + wiki_render_by_mimetype(&event, zMimetype); | |
| 514 | 515 | @ </blockquote><hr /> |
| 515 | 516 | blob_reset(&event); |
| 516 | 517 | } |
| 517 | 518 | for(n=2, z=zBody; z[0]; z++){ |
| 518 | 519 | if( z[0]=='\n' ) n++; |
| 519 | 520 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -508,11 +508,12 @@ | |
| 508 | @ </blockquote> |
| 509 | @ <p><b>Page content preview:</b><p> |
| 510 | @ <blockquote> |
| 511 | blob_init(&event, 0, 0); |
| 512 | blob_append(&event, zBody, -1); |
| 513 | wiki_render_by_mimetype(&event, zMimetype, 0); |
| 514 | @ </blockquote><hr /> |
| 515 | blob_reset(&event); |
| 516 | } |
| 517 | for(n=2, z=zBody; z[0]; z++){ |
| 518 | if( z[0]=='\n' ) n++; |
| 519 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -508,11 +508,12 @@ | |
| 508 | @ </blockquote> |
| 509 | @ <p><b>Page content preview:</b><p> |
| 510 | @ <blockquote> |
| 511 | blob_init(&event, 0, 0); |
| 512 | blob_append(&event, zBody, -1); |
| 513 | safe_html_context(DOCSRC_WIKI); |
| 514 | wiki_render_by_mimetype(&event, zMimetype); |
| 515 | @ </blockquote><hr /> |
| 516 | blob_reset(&event); |
| 517 | } |
| 518 | for(n=2, z=zBody; z[0]; z++){ |
| 519 | if( z[0]=='\n' ) n++; |
| 520 |
+2
-1
| --- src/fileedit.c | ||
| +++ src/fileedit.c | ||
| @@ -976,11 +976,12 @@ | ||
| 976 | 976 | case FE_RENDER_HTML_INLINE:{ |
| 977 | 977 | CX("%b",pContent); |
| 978 | 978 | break; |
| 979 | 979 | } |
| 980 | 980 | case FE_RENDER_WIKI: |
| 981 | - wiki_render_by_mimetype(pContent, zMime, 0); | |
| 981 | + safe_html_context(DOCSRC_FILE); | |
| 982 | + wiki_render_by_mimetype(pContent, zMime); | |
| 982 | 983 | break; |
| 983 | 984 | default:{ |
| 984 | 985 | const char *zExt = strrchr(zFilename,'.'); |
| 985 | 986 | const char *zContent = blob_str(pContent); |
| 986 | 987 | if(FE_PREVIEW_LINE_NUMBERS & flags){ |
| 987 | 988 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -976,11 +976,12 @@ | |
| 976 | case FE_RENDER_HTML_INLINE:{ |
| 977 | CX("%b",pContent); |
| 978 | break; |
| 979 | } |
| 980 | case FE_RENDER_WIKI: |
| 981 | wiki_render_by_mimetype(pContent, zMime, 0); |
| 982 | break; |
| 983 | default:{ |
| 984 | const char *zExt = strrchr(zFilename,'.'); |
| 985 | const char *zContent = blob_str(pContent); |
| 986 | if(FE_PREVIEW_LINE_NUMBERS & flags){ |
| 987 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -976,11 +976,12 @@ | |
| 976 | case FE_RENDER_HTML_INLINE:{ |
| 977 | CX("%b",pContent); |
| 978 | break; |
| 979 | } |
| 980 | case FE_RENDER_WIKI: |
| 981 | safe_html_context(DOCSRC_FILE); |
| 982 | wiki_render_by_mimetype(pContent, zMime); |
| 983 | break; |
| 984 | default:{ |
| 985 | const char *zExt = strrchr(zFilename,'.'); |
| 986 | const char *zContent = blob_str(pContent); |
| 987 | if(FE_PREVIEW_LINE_NUMBERS & flags){ |
| 988 |
+2
-1
| --- src/forum.c | ||
| +++ src/forum.c | ||
| @@ -340,11 +340,12 @@ | ||
| 340 | 340 | }else{ |
| 341 | 341 | @ <div class='forumPostFullBody'> |
| 342 | 342 | } |
| 343 | 343 | blob_init(&x, 0, 0); |
| 344 | 344 | blob_append(&x, zContent, -1); |
| 345 | - wiki_render_by_mimetype(&x, zMimetype, WIKI_SAFE); | |
| 345 | + safe_html_context(DOCSRC_FORUM); | |
| 346 | + wiki_render_by_mimetype(&x, zMimetype); | |
| 346 | 347 | blob_reset(&x); |
| 347 | 348 | @ </div> |
| 348 | 349 | }else{ |
| 349 | 350 | @ <i>Deleted</i> |
| 350 | 351 | } |
| 351 | 352 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -340,11 +340,12 @@ | |
| 340 | }else{ |
| 341 | @ <div class='forumPostFullBody'> |
| 342 | } |
| 343 | blob_init(&x, 0, 0); |
| 344 | blob_append(&x, zContent, -1); |
| 345 | wiki_render_by_mimetype(&x, zMimetype, WIKI_SAFE); |
| 346 | blob_reset(&x); |
| 347 | @ </div> |
| 348 | }else{ |
| 349 | @ <i>Deleted</i> |
| 350 | } |
| 351 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -340,11 +340,12 @@ | |
| 340 | }else{ |
| 341 | @ <div class='forumPostFullBody'> |
| 342 | } |
| 343 | blob_init(&x, 0, 0); |
| 344 | blob_append(&x, zContent, -1); |
| 345 | safe_html_context(DOCSRC_FORUM); |
| 346 | wiki_render_by_mimetype(&x, zMimetype); |
| 347 | blob_reset(&x); |
| 348 | @ </div> |
| 349 | }else{ |
| 350 | @ <i>Deleted</i> |
| 351 | } |
| 352 |
+4
-2
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1043,11 +1043,12 @@ | ||
| 1043 | 1043 | } |
| 1044 | 1044 | |
| 1045 | 1045 | |
| 1046 | 1046 | @ <div class="section">Content</div> |
| 1047 | 1047 | blob_init(&wiki, pWiki->zWiki, -1); |
| 1048 | - wiki_render_by_mimetype(&wiki, pWiki->zMimetype, 0); | |
| 1048 | + safe_html_context(DOCSRC_WIKI); | |
| 1049 | + wiki_render_by_mimetype(&wiki, pWiki->zMimetype); | |
| 1049 | 1050 | blob_reset(&wiki); |
| 1050 | 1051 | manifest_destroy(pWiki); |
| 1051 | 1052 | style_footer(); |
| 1052 | 1053 | } |
| 1053 | 1054 | |
| @@ -2362,11 +2363,12 @@ | ||
| 2362 | 2363 | style_submenu_element("Content", "%R/artifact/%s", zUuid); |
| 2363 | 2364 | }else{ |
| 2364 | 2365 | @ <hr /> |
| 2365 | 2366 | content_get(rid, &content); |
| 2366 | 2367 | if( renderAsWiki ){ |
| 2367 | - wiki_render_by_mimetype(&content, zMime, 0); | |
| 2368 | + safe_html_context(DOCSRC_FILE); | |
| 2369 | + wiki_render_by_mimetype(&content, zMime); | |
| 2368 | 2370 | }else if( renderAsHtml ){ |
| 2369 | 2371 | @ <iframe src="%R/raw/%s(zUuid)" |
| 2370 | 2372 | @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" |
| 2371 | 2373 | @ sandbox="allow-same-origin" id="ifm1"> |
| 2372 | 2374 | @ </iframe> |
| 2373 | 2375 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1043,11 +1043,12 @@ | |
| 1043 | } |
| 1044 | |
| 1045 | |
| 1046 | @ <div class="section">Content</div> |
| 1047 | blob_init(&wiki, pWiki->zWiki, -1); |
| 1048 | wiki_render_by_mimetype(&wiki, pWiki->zMimetype, 0); |
| 1049 | blob_reset(&wiki); |
| 1050 | manifest_destroy(pWiki); |
| 1051 | style_footer(); |
| 1052 | } |
| 1053 | |
| @@ -2362,11 +2363,12 @@ | |
| 2362 | style_submenu_element("Content", "%R/artifact/%s", zUuid); |
| 2363 | }else{ |
| 2364 | @ <hr /> |
| 2365 | content_get(rid, &content); |
| 2366 | if( renderAsWiki ){ |
| 2367 | wiki_render_by_mimetype(&content, zMime, 0); |
| 2368 | }else if( renderAsHtml ){ |
| 2369 | @ <iframe src="%R/raw/%s(zUuid)" |
| 2370 | @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" |
| 2371 | @ sandbox="allow-same-origin" id="ifm1"> |
| 2372 | @ </iframe> |
| 2373 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1043,11 +1043,12 @@ | |
| 1043 | } |
| 1044 | |
| 1045 | |
| 1046 | @ <div class="section">Content</div> |
| 1047 | blob_init(&wiki, pWiki->zWiki, -1); |
| 1048 | safe_html_context(DOCSRC_WIKI); |
| 1049 | wiki_render_by_mimetype(&wiki, pWiki->zMimetype); |
| 1050 | blob_reset(&wiki); |
| 1051 | manifest_destroy(pWiki); |
| 1052 | style_footer(); |
| 1053 | } |
| 1054 | |
| @@ -2362,11 +2363,12 @@ | |
| 2363 | style_submenu_element("Content", "%R/artifact/%s", zUuid); |
| 2364 | }else{ |
| 2365 | @ <hr /> |
| 2366 | content_get(rid, &content); |
| 2367 | if( renderAsWiki ){ |
| 2368 | safe_html_context(DOCSRC_FILE); |
| 2369 | wiki_render_by_mimetype(&content, zMime); |
| 2370 | }else if( renderAsHtml ){ |
| 2371 | @ <iframe src="%R/raw/%s(zUuid)" |
| 2372 | @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" |
| 2373 | @ sandbox="allow-same-origin" id="ifm1"> |
| 2374 | @ </iframe> |
| 2375 |
+21
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -1052,10 +1052,31 @@ | ||
| 1052 | 1052 | @ <li> <b>branch/</b><i>branch-name</i> |
| 1053 | 1053 | @ <li> <b>checkin/</b><i>full-checkin-hash</i> |
| 1054 | 1054 | @ <li> <b>tag/</b><i>tag-name</i> |
| 1055 | 1055 | @ </ul> |
| 1056 | 1056 | @ (Property: "wiki-about")</p> |
| 1057 | + @ <hr /> | |
| 1058 | + entry_attribute("Allow Unsafe HTML In Markdown", 6, | |
| 1059 | + "safe-html", "safe-html", "", 0); | |
| 1060 | + @ <p>Allow "unsafe" HTML (ex: <script>, <form>, etc) to be | |
| 1061 | + @ generated by <a href="%R/md_rules">Markdown-formatted</a> documents. | |
| 1062 | + @ This setting is a string where each character indicates a "type" of | |
| 1063 | + @ document in which to allow unsafe HTML: | |
| 1064 | + @ <ul> | |
| 1065 | + @ <li> <b>b</b> → checked-in files, embedded documentation | |
| 1066 | + @ <li> <b>f</b> → forum posts | |
| 1067 | + @ <li> <b>t</b> → tickets | |
| 1068 | + @ <li> <b>w</b> → wiki pages | |
| 1069 | + @ </ul> | |
| 1070 | + @ Include letters for each type of document for which unsafe HTML should | |
| 1071 | + @ be allowed. For example, to allow unsafe HTML only for checked-in files, | |
| 1072 | + @ make this setting be just "<b>b</b>". To allow unsafe HTML anywhere except | |
| 1073 | + @ in forum posts, make this setting be "<b>btw</b>". The default is an | |
| 1074 | + @ empty string which means that Fossil never allows Markdown documents | |
| 1075 | + @ to generate unsafe HTML. | |
| 1076 | + @ (Property: "safe-html")</p> | |
| 1077 | + @ <hr /> | |
| 1057 | 1078 | @ <hr /> |
| 1058 | 1079 | onoff_attribute("Enable WYSIWYG Wiki Editing", |
| 1059 | 1080 | "wysiwyg-wiki", "wysiwyg-wiki", 0, 0); |
| 1060 | 1081 | @ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages. |
| 1061 | 1082 | @ The WYSIWYG editor generates HTML instead of markup, which makes |
| 1062 | 1083 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1052,10 +1052,31 @@ | |
| 1052 | @ <li> <b>branch/</b><i>branch-name</i> |
| 1053 | @ <li> <b>checkin/</b><i>full-checkin-hash</i> |
| 1054 | @ <li> <b>tag/</b><i>tag-name</i> |
| 1055 | @ </ul> |
| 1056 | @ (Property: "wiki-about")</p> |
| 1057 | @ <hr /> |
| 1058 | onoff_attribute("Enable WYSIWYG Wiki Editing", |
| 1059 | "wysiwyg-wiki", "wysiwyg-wiki", 0, 0); |
| 1060 | @ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages. |
| 1061 | @ The WYSIWYG editor generates HTML instead of markup, which makes |
| 1062 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1052,10 +1052,31 @@ | |
| 1052 | @ <li> <b>branch/</b><i>branch-name</i> |
| 1053 | @ <li> <b>checkin/</b><i>full-checkin-hash</i> |
| 1054 | @ <li> <b>tag/</b><i>tag-name</i> |
| 1055 | @ </ul> |
| 1056 | @ (Property: "wiki-about")</p> |
| 1057 | @ <hr /> |
| 1058 | entry_attribute("Allow Unsafe HTML In Markdown", 6, |
| 1059 | "safe-html", "safe-html", "", 0); |
| 1060 | @ <p>Allow "unsafe" HTML (ex: <script>, <form>, etc) to be |
| 1061 | @ generated by <a href="%R/md_rules">Markdown-formatted</a> documents. |
| 1062 | @ This setting is a string where each character indicates a "type" of |
| 1063 | @ document in which to allow unsafe HTML: |
| 1064 | @ <ul> |
| 1065 | @ <li> <b>b</b> → checked-in files, embedded documentation |
| 1066 | @ <li> <b>f</b> → forum posts |
| 1067 | @ <li> <b>t</b> → tickets |
| 1068 | @ <li> <b>w</b> → wiki pages |
| 1069 | @ </ul> |
| 1070 | @ Include letters for each type of document for which unsafe HTML should |
| 1071 | @ be allowed. For example, to allow unsafe HTML only for checked-in files, |
| 1072 | @ make this setting be just "<b>b</b>". To allow unsafe HTML anywhere except |
| 1073 | @ in forum posts, make this setting be "<b>btw</b>". The default is an |
| 1074 | @ empty string which means that Fossil never allows Markdown documents |
| 1075 | @ to generate unsafe HTML. |
| 1076 | @ (Property: "safe-html")</p> |
| 1077 | @ <hr /> |
| 1078 | @ <hr /> |
| 1079 | onoff_attribute("Enable WYSIWYG Wiki Editing", |
| 1080 | "wysiwyg-wiki", "wysiwyg-wiki", 0, 0); |
| 1081 | @ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages. |
| 1082 | @ The WYSIWYG editor generates HTML instead of markup, which makes |
| 1083 |
+1
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -512,10 +512,11 @@ | ||
| 512 | 512 | getAllTicketFields(); |
| 513 | 513 | initializeVariablesFromDb(); |
| 514 | 514 | zScript = ticket_viewpage_code(); |
| 515 | 515 | if( P("showfields")!=0 ) showAllFields(); |
| 516 | 516 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1); |
| 517 | + safe_html_context(DOCSRC_TICKET); | |
| 517 | 518 | Th_Render(zScript); |
| 518 | 519 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| 519 | 520 | |
| 520 | 521 | zFullName = db_text(0, |
| 521 | 522 | "SELECT tkt_uuid FROM ticket" |
| 522 | 523 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -512,10 +512,11 @@ | |
| 512 | getAllTicketFields(); |
| 513 | initializeVariablesFromDb(); |
| 514 | zScript = ticket_viewpage_code(); |
| 515 | if( P("showfields")!=0 ) showAllFields(); |
| 516 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1); |
| 517 | Th_Render(zScript); |
| 518 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| 519 | |
| 520 | zFullName = db_text(0, |
| 521 | "SELECT tkt_uuid FROM ticket" |
| 522 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -512,10 +512,11 @@ | |
| 512 | getAllTicketFields(); |
| 513 | initializeVariablesFromDb(); |
| 514 | zScript = ticket_viewpage_code(); |
| 515 | if( P("showfields")!=0 ) showAllFields(); |
| 516 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1); |
| 517 | safe_html_context(DOCSRC_TICKET); |
| 518 | Th_Render(zScript); |
| 519 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| 520 | |
| 521 | zFullName = db_text(0, |
| 522 | "SELECT tkt_uuid FROM ticket" |
| 523 |
+17
-8
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -191,17 +191,17 @@ | ||
| 191 | 191 | ** text/x-markdown Markdown |
| 192 | 192 | ** anything else... Plain text |
| 193 | 193 | ** |
| 194 | 194 | ** If zMimetype is a null pointer, then use "text/x-fossil-wiki". |
| 195 | 195 | */ |
| 196 | -void wiki_render_by_mimetype(Blob *pWiki, const char *zMimetype, int flags){ | |
| 196 | +void wiki_render_by_mimetype(Blob *pWiki, const char *zMimetype){ | |
| 197 | 197 | if( zMimetype==0 || fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){ |
| 198 | - wiki_convert(pWiki, 0, flags); | |
| 198 | + wiki_convert(pWiki, 0, 0); | |
| 199 | 199 | }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){ |
| 200 | 200 | Blob tail = BLOB_INITIALIZER; |
| 201 | 201 | markdown_to_html(pWiki, 0, &tail); |
| 202 | - if( flags & WIKI_SAFE ) safe_html(&tail); | |
| 202 | + safe_html(&tail); | |
| 203 | 203 | @ %s(blob_str(&tail)) |
| 204 | 204 | blob_reset(&tail); |
| 205 | 205 | }else{ |
| 206 | 206 | @ <pre class='textPlain'> |
| 207 | 207 | @ %h(blob_str(pWiki)) |
| @@ -223,11 +223,12 @@ | ||
| 223 | 223 | }else{ |
| 224 | 224 | style_submenu_element("Plain-Text", "%R/md_rules?txt=1"); |
| 225 | 225 | } |
| 226 | 226 | blob_init(&x, builtin_text("markdown.md"), -1); |
| 227 | 227 | blob_materialize(&x); |
| 228 | - wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown", 0); | |
| 228 | + safe_html_context(DOCSRC_TRUSTED); | |
| 229 | + wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); | |
| 229 | 230 | blob_reset(&x); |
| 230 | 231 | style_footer(); |
| 231 | 232 | } |
| 232 | 233 | |
| 233 | 234 | /* |
| @@ -244,11 +245,12 @@ | ||
| 244 | 245 | }else{ |
| 245 | 246 | style_submenu_element("Plain-Text", "%R/wiki_rules?txt=1"); |
| 246 | 247 | } |
| 247 | 248 | blob_init(&x, builtin_text("wiki.wiki"), -1); |
| 248 | 249 | blob_materialize(&x); |
| 249 | - wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki", 0); | |
| 250 | + safe_html_context(DOCSRC_TRUSTED); | |
| 251 | + wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki"); | |
| 250 | 252 | blob_reset(&x); |
| 251 | 253 | style_footer(); |
| 252 | 254 | } |
| 253 | 255 | |
| 254 | 256 | /* |
| @@ -561,11 +563,12 @@ | ||
| 561 | 563 | } |
| 562 | 564 | if( zBody[0]==0 ){ |
| 563 | 565 | @ <i>This page has been deleted</i> |
| 564 | 566 | }else{ |
| 565 | 567 | blob_init(&wiki, zBody, -1); |
| 566 | - wiki_render_by_mimetype(&wiki, zMimetype, 0); | |
| 568 | + safe_html_context(DOCSRC_WIKI); | |
| 569 | + wiki_render_by_mimetype(&wiki, zMimetype); | |
| 567 | 570 | blob_reset(&wiki); |
| 568 | 571 | } |
| 569 | 572 | attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>"); |
| 570 | 573 | manifest_destroy(pWiki); |
| 571 | 574 | style_footer(); |
| @@ -748,11 +751,12 @@ | ||
| 748 | 751 | blob_append(&wiki, zBody, -1); |
| 749 | 752 | if( P("preview")!=0 ){ |
| 750 | 753 | havePreview = 1; |
| 751 | 754 | if( zBody[0] ){ |
| 752 | 755 | @ Preview:<hr /> |
| 753 | - wiki_render_by_mimetype(&wiki, zMimetype, 0); | |
| 756 | + safe_html_context(DOCSRC_WIKI); | |
| 757 | + wiki_render_by_mimetype(&wiki, zMimetype); | |
| 754 | 758 | @ <hr /> |
| 755 | 759 | blob_reset(&wiki); |
| 756 | 760 | } |
| 757 | 761 | } |
| 758 | 762 | for(n=2, z=zBody; z[0]; z++){ |
| @@ -1010,11 +1014,12 @@ | ||
| 1010 | 1014 | if( P("preview")!=0 ){ |
| 1011 | 1015 | Blob preview; |
| 1012 | 1016 | blob_zero(&preview); |
| 1013 | 1017 | appendRemark(&preview, zMimetype); |
| 1014 | 1018 | @ Preview:<hr /> |
| 1015 | - wiki_render_by_mimetype(&preview, zMimetype, 0); | |
| 1019 | + safe_html_context(DOCSRC_WIKI); | |
| 1020 | + wiki_render_by_mimetype(&preview, zMimetype); | |
| 1016 | 1021 | @ <hr /> |
| 1017 | 1022 | blob_reset(&preview); |
| 1018 | 1023 | } |
| 1019 | 1024 | zUser = PD("u", g.zLogin); |
| 1020 | 1025 | form_begin(0, "%R/wikiappend"); |
| @@ -1561,10 +1566,12 @@ | ||
| 1561 | 1566 | ** input blob before appending the output, which is |
| 1562 | 1567 | ** different from wiki_convert() and htmlize_to_blob(), and |
| 1563 | 1568 | ** precludes us simply appending the opening <html><body> |
| 1564 | 1569 | ** part to the body |
| 1565 | 1570 | */; |
| 1571 | + safe_html_context(DOCSRC_WIKI); | |
| 1572 | + safe_html(&html); | |
| 1566 | 1573 | }else if( fossil_strcmp(zMimetype, "text/plain")==0 ){ |
| 1567 | 1574 | htmlize_to_blob(&html,zBody,i); |
| 1568 | 1575 | }else{ |
| 1569 | 1576 | fossil_fatal("Unsupported MIME type '%s' for wiki page '%s'.", |
| 1570 | 1577 | zMimetype, pWiki->zWikiTitle ); |
| @@ -1802,10 +1809,12 @@ | ||
| 1802 | 1809 | }else{ |
| 1803 | 1810 | wiki_section_label(zPrefix, zName, mFlags); |
| 1804 | 1811 | } |
| 1805 | 1812 | wiki_submenu_to_edit_wiki(zPrefix, zName, mFlags); |
| 1806 | 1813 | @ <div class="accordion_panel"> |
| 1814 | + safe_html_context(DOCSRC_WIKI); | |
| 1815 | + safe_html(&tail); | |
| 1807 | 1816 | convert_href_and_output(&tail); |
| 1808 | 1817 | @ </div> |
| 1809 | 1818 | blob_reset(&tail); |
| 1810 | 1819 | blob_reset(&title); |
| 1811 | 1820 | blob_reset(&markdown); |
| 1812 | 1821 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -191,17 +191,17 @@ | |
| 191 | ** text/x-markdown Markdown |
| 192 | ** anything else... Plain text |
| 193 | ** |
| 194 | ** If zMimetype is a null pointer, then use "text/x-fossil-wiki". |
| 195 | */ |
| 196 | void wiki_render_by_mimetype(Blob *pWiki, const char *zMimetype, int flags){ |
| 197 | if( zMimetype==0 || fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){ |
| 198 | wiki_convert(pWiki, 0, flags); |
| 199 | }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){ |
| 200 | Blob tail = BLOB_INITIALIZER; |
| 201 | markdown_to_html(pWiki, 0, &tail); |
| 202 | if( flags & WIKI_SAFE ) safe_html(&tail); |
| 203 | @ %s(blob_str(&tail)) |
| 204 | blob_reset(&tail); |
| 205 | }else{ |
| 206 | @ <pre class='textPlain'> |
| 207 | @ %h(blob_str(pWiki)) |
| @@ -223,11 +223,12 @@ | |
| 223 | }else{ |
| 224 | style_submenu_element("Plain-Text", "%R/md_rules?txt=1"); |
| 225 | } |
| 226 | blob_init(&x, builtin_text("markdown.md"), -1); |
| 227 | blob_materialize(&x); |
| 228 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown", 0); |
| 229 | blob_reset(&x); |
| 230 | style_footer(); |
| 231 | } |
| 232 | |
| 233 | /* |
| @@ -244,11 +245,12 @@ | |
| 244 | }else{ |
| 245 | style_submenu_element("Plain-Text", "%R/wiki_rules?txt=1"); |
| 246 | } |
| 247 | blob_init(&x, builtin_text("wiki.wiki"), -1); |
| 248 | blob_materialize(&x); |
| 249 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki", 0); |
| 250 | blob_reset(&x); |
| 251 | style_footer(); |
| 252 | } |
| 253 | |
| 254 | /* |
| @@ -561,11 +563,12 @@ | |
| 561 | } |
| 562 | if( zBody[0]==0 ){ |
| 563 | @ <i>This page has been deleted</i> |
| 564 | }else{ |
| 565 | blob_init(&wiki, zBody, -1); |
| 566 | wiki_render_by_mimetype(&wiki, zMimetype, 0); |
| 567 | blob_reset(&wiki); |
| 568 | } |
| 569 | attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>"); |
| 570 | manifest_destroy(pWiki); |
| 571 | style_footer(); |
| @@ -748,11 +751,12 @@ | |
| 748 | blob_append(&wiki, zBody, -1); |
| 749 | if( P("preview")!=0 ){ |
| 750 | havePreview = 1; |
| 751 | if( zBody[0] ){ |
| 752 | @ Preview:<hr /> |
| 753 | wiki_render_by_mimetype(&wiki, zMimetype, 0); |
| 754 | @ <hr /> |
| 755 | blob_reset(&wiki); |
| 756 | } |
| 757 | } |
| 758 | for(n=2, z=zBody; z[0]; z++){ |
| @@ -1010,11 +1014,12 @@ | |
| 1010 | if( P("preview")!=0 ){ |
| 1011 | Blob preview; |
| 1012 | blob_zero(&preview); |
| 1013 | appendRemark(&preview, zMimetype); |
| 1014 | @ Preview:<hr /> |
| 1015 | wiki_render_by_mimetype(&preview, zMimetype, 0); |
| 1016 | @ <hr /> |
| 1017 | blob_reset(&preview); |
| 1018 | } |
| 1019 | zUser = PD("u", g.zLogin); |
| 1020 | form_begin(0, "%R/wikiappend"); |
| @@ -1561,10 +1566,12 @@ | |
| 1561 | ** input blob before appending the output, which is |
| 1562 | ** different from wiki_convert() and htmlize_to_blob(), and |
| 1563 | ** precludes us simply appending the opening <html><body> |
| 1564 | ** part to the body |
| 1565 | */; |
| 1566 | }else if( fossil_strcmp(zMimetype, "text/plain")==0 ){ |
| 1567 | htmlize_to_blob(&html,zBody,i); |
| 1568 | }else{ |
| 1569 | fossil_fatal("Unsupported MIME type '%s' for wiki page '%s'.", |
| 1570 | zMimetype, pWiki->zWikiTitle ); |
| @@ -1802,10 +1809,12 @@ | |
| 1802 | }else{ |
| 1803 | wiki_section_label(zPrefix, zName, mFlags); |
| 1804 | } |
| 1805 | wiki_submenu_to_edit_wiki(zPrefix, zName, mFlags); |
| 1806 | @ <div class="accordion_panel"> |
| 1807 | convert_href_and_output(&tail); |
| 1808 | @ </div> |
| 1809 | blob_reset(&tail); |
| 1810 | blob_reset(&title); |
| 1811 | blob_reset(&markdown); |
| 1812 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -191,17 +191,17 @@ | |
| 191 | ** text/x-markdown Markdown |
| 192 | ** anything else... Plain text |
| 193 | ** |
| 194 | ** If zMimetype is a null pointer, then use "text/x-fossil-wiki". |
| 195 | */ |
| 196 | void wiki_render_by_mimetype(Blob *pWiki, const char *zMimetype){ |
| 197 | if( zMimetype==0 || fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){ |
| 198 | wiki_convert(pWiki, 0, 0); |
| 199 | }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){ |
| 200 | Blob tail = BLOB_INITIALIZER; |
| 201 | markdown_to_html(pWiki, 0, &tail); |
| 202 | safe_html(&tail); |
| 203 | @ %s(blob_str(&tail)) |
| 204 | blob_reset(&tail); |
| 205 | }else{ |
| 206 | @ <pre class='textPlain'> |
| 207 | @ %h(blob_str(pWiki)) |
| @@ -223,11 +223,12 @@ | |
| 223 | }else{ |
| 224 | style_submenu_element("Plain-Text", "%R/md_rules?txt=1"); |
| 225 | } |
| 226 | blob_init(&x, builtin_text("markdown.md"), -1); |
| 227 | blob_materialize(&x); |
| 228 | safe_html_context(DOCSRC_TRUSTED); |
| 229 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 230 | blob_reset(&x); |
| 231 | style_footer(); |
| 232 | } |
| 233 | |
| 234 | /* |
| @@ -244,11 +245,12 @@ | |
| 245 | }else{ |
| 246 | style_submenu_element("Plain-Text", "%R/wiki_rules?txt=1"); |
| 247 | } |
| 248 | blob_init(&x, builtin_text("wiki.wiki"), -1); |
| 249 | blob_materialize(&x); |
| 250 | safe_html_context(DOCSRC_TRUSTED); |
| 251 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki"); |
| 252 | blob_reset(&x); |
| 253 | style_footer(); |
| 254 | } |
| 255 | |
| 256 | /* |
| @@ -561,11 +563,12 @@ | |
| 563 | } |
| 564 | if( zBody[0]==0 ){ |
| 565 | @ <i>This page has been deleted</i> |
| 566 | }else{ |
| 567 | blob_init(&wiki, zBody, -1); |
| 568 | safe_html_context(DOCSRC_WIKI); |
| 569 | wiki_render_by_mimetype(&wiki, zMimetype); |
| 570 | blob_reset(&wiki); |
| 571 | } |
| 572 | attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>"); |
| 573 | manifest_destroy(pWiki); |
| 574 | style_footer(); |
| @@ -748,11 +751,12 @@ | |
| 751 | blob_append(&wiki, zBody, -1); |
| 752 | if( P("preview")!=0 ){ |
| 753 | havePreview = 1; |
| 754 | if( zBody[0] ){ |
| 755 | @ Preview:<hr /> |
| 756 | safe_html_context(DOCSRC_WIKI); |
| 757 | wiki_render_by_mimetype(&wiki, zMimetype); |
| 758 | @ <hr /> |
| 759 | blob_reset(&wiki); |
| 760 | } |
| 761 | } |
| 762 | for(n=2, z=zBody; z[0]; z++){ |
| @@ -1010,11 +1014,12 @@ | |
| 1014 | if( P("preview")!=0 ){ |
| 1015 | Blob preview; |
| 1016 | blob_zero(&preview); |
| 1017 | appendRemark(&preview, zMimetype); |
| 1018 | @ Preview:<hr /> |
| 1019 | safe_html_context(DOCSRC_WIKI); |
| 1020 | wiki_render_by_mimetype(&preview, zMimetype); |
| 1021 | @ <hr /> |
| 1022 | blob_reset(&preview); |
| 1023 | } |
| 1024 | zUser = PD("u", g.zLogin); |
| 1025 | form_begin(0, "%R/wikiappend"); |
| @@ -1561,10 +1566,12 @@ | |
| 1566 | ** input blob before appending the output, which is |
| 1567 | ** different from wiki_convert() and htmlize_to_blob(), and |
| 1568 | ** precludes us simply appending the opening <html><body> |
| 1569 | ** part to the body |
| 1570 | */; |
| 1571 | safe_html_context(DOCSRC_WIKI); |
| 1572 | safe_html(&html); |
| 1573 | }else if( fossil_strcmp(zMimetype, "text/plain")==0 ){ |
| 1574 | htmlize_to_blob(&html,zBody,i); |
| 1575 | }else{ |
| 1576 | fossil_fatal("Unsupported MIME type '%s' for wiki page '%s'.", |
| 1577 | zMimetype, pWiki->zWikiTitle ); |
| @@ -1802,10 +1809,12 @@ | |
| 1809 | }else{ |
| 1810 | wiki_section_label(zPrefix, zName, mFlags); |
| 1811 | } |
| 1812 | wiki_submenu_to_edit_wiki(zPrefix, zName, mFlags); |
| 1813 | @ <div class="accordion_panel"> |
| 1814 | safe_html_context(DOCSRC_WIKI); |
| 1815 | safe_html(&tail); |
| 1816 | convert_href_and_output(&tail); |
| 1817 | @ </div> |
| 1818 | blob_reset(&tail); |
| 1819 | blob_reset(&title); |
| 1820 | blob_reset(&markdown); |
| 1821 |
+52
-3
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -1811,11 +1811,11 @@ | ||
| 1811 | 1811 | ** Usage: %fossil test-markdown-render FILE ... |
| 1812 | 1812 | ** |
| 1813 | 1813 | ** Render markdown in FILE as HTML on stdout. |
| 1814 | 1814 | ** Options: |
| 1815 | 1815 | ** |
| 1816 | -** --safe Do "safe-html" rendering. | |
| 1816 | +** --safe Restrict the output to use only "safe" HTML | |
| 1817 | 1817 | */ |
| 1818 | 1818 | void test_markdown_render(void){ |
| 1819 | 1819 | Blob in, out; |
| 1820 | 1820 | int i; |
| 1821 | 1821 | int bSafe = 0; |
| @@ -1827,11 +1827,12 @@ | ||
| 1827 | 1827 | blob_read_from_file(&in, g.argv[i], ExtFILE); |
| 1828 | 1828 | if( g.argc>3 ){ |
| 1829 | 1829 | fossil_print("<!------ %h ------->\n", g.argv[i]); |
| 1830 | 1830 | } |
| 1831 | 1831 | markdown_to_html(&in, 0, &out); |
| 1832 | - if( bSafe ) safe_html(&out); | |
| 1832 | + safe_html_context( bSafe ? DOCSRC_UNTRUSTED : DOCSRC_TRUSTED ); | |
| 1833 | + safe_html(&out); | |
| 1833 | 1834 | blob_write_to_file(&out, "-"); |
| 1834 | 1835 | blob_reset(&in); |
| 1835 | 1836 | blob_reset(&out); |
| 1836 | 1837 | } |
| 1837 | 1838 | } |
| @@ -2569,10 +2570,58 @@ | ||
| 2569 | 2570 | } |
| 2570 | 2571 | html_tagstack_pop(&s, pBlob, 0); |
| 2571 | 2572 | html_tagstack_clear(&s); |
| 2572 | 2573 | zHtml[nHtml] = cLast; |
| 2573 | 2574 | } |
| 2575 | + | |
| 2576 | +/* | |
| 2577 | +** This local variable is true if the safe_html() function is enabled. | |
| 2578 | +** In other words, this is true if the output of Markdown should be | |
| 2579 | +** restricted to use only "safe" HTML. | |
| 2580 | +*/ | |
| 2581 | +static int safeHtmlEnable = 1; | |
| 2582 | + | |
| 2583 | + | |
| 2584 | +#if INTERFACE | |
| 2585 | +/* | |
| 2586 | +** Allowed values for the eTrust parameter to safe_html_context(). | |
| 2587 | +*/ | |
| 2588 | +#define DOCSRC_FILE 1 /* Document is a checked-in file */ | |
| 2589 | +#define DOCSRC_FORUM 2 /* Document is a forum post */ | |
| 2590 | +#define DOCSRC_TICKET 3 /* Document is a ticket comment */ | |
| 2591 | +#define DOCSRC_WIKI 4 /* Document is a wiki page */ | |
| 2592 | +#define DOCSRC_TRUSTED 5 /* safe_html() is always a no-op */ | |
| 2593 | +#define DOCSRC_UNTRUSTED 6 /* safe_html() is always enabled */ | |
| 2594 | +#endif /* INTERFACE */ | |
| 2595 | + | |
| 2596 | + | |
| 2597 | +/* | |
| 2598 | +** Specify the context in which a markdown document with potentially | |
| 2599 | +** unsafe HTML will be rendered. | |
| 2600 | +*/ | |
| 2601 | +void safe_html_context(int eTrust){ | |
| 2602 | + static const char *zSafeHtmlSetting = 0; | |
| 2603 | + char cPerm = 0; | |
| 2604 | + if( eTrust==DOCSRC_TRUSTED ){ | |
| 2605 | + safeHtmlEnable = 0; | |
| 2606 | + return; | |
| 2607 | + } | |
| 2608 | + if( eTrust==DOCSRC_UNTRUSTED ){ | |
| 2609 | + safeHtmlEnable = 1; | |
| 2610 | + return; | |
| 2611 | + } | |
| 2612 | + if( zSafeHtmlSetting==0 ){ | |
| 2613 | + zSafeHtmlSetting = db_get("safe-html", ""); | |
| 2614 | + } | |
| 2615 | + switch( eTrust ){ | |
| 2616 | + case DOCSRC_FILE: cPerm = 'b'; break; | |
| 2617 | + case DOCSRC_FORUM: cPerm = 'f'; break; | |
| 2618 | + case DOCSRC_TICKET: cPerm = 't'; break; | |
| 2619 | + case DOCSRC_WIKI: cPerm = 'w'; break; | |
| 2620 | + } | |
| 2621 | + safeHtmlEnable = (strchr(zSafeHtmlSetting,cPerm)==0); | |
| 2622 | +} | |
| 2574 | 2623 | |
| 2575 | 2624 | /* |
| 2576 | 2625 | ** The input blob contains HTML. If safe-html is enabled, then |
| 2577 | 2626 | ** convert the input into "safe HTML". The following modifications |
| 2578 | 2627 | ** are made: |
| @@ -2603,11 +2652,11 @@ | ||
| 2603 | 2652 | Blob out; /* Holding area for the revised text during construction */ |
| 2604 | 2653 | char *z; /* Original input text */ |
| 2605 | 2654 | int n; /* Number of bytes in the original input text */ |
| 2606 | 2655 | int k; |
| 2607 | 2656 | |
| 2608 | - /* if( safeHtml==0 ) return; TBD: Always used at this time */ | |
| 2657 | + if( safeHtmlEnable==0 ) return; | |
| 2609 | 2658 | z = blob_str(in); |
| 2610 | 2659 | n = blob_size(in); |
| 2611 | 2660 | blob_init(&out, 0, 0); |
| 2612 | 2661 | while( fossil_isspace(z[0]) ){ z++; n--; } |
| 2613 | 2662 | for(k=n-1; k>5 && fossil_isspace(z[k]); k--){} |
| 2614 | 2663 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1811,11 +1811,11 @@ | |
| 1811 | ** Usage: %fossil test-markdown-render FILE ... |
| 1812 | ** |
| 1813 | ** Render markdown in FILE as HTML on stdout. |
| 1814 | ** Options: |
| 1815 | ** |
| 1816 | ** --safe Do "safe-html" rendering. |
| 1817 | */ |
| 1818 | void test_markdown_render(void){ |
| 1819 | Blob in, out; |
| 1820 | int i; |
| 1821 | int bSafe = 0; |
| @@ -1827,11 +1827,12 @@ | |
| 1827 | blob_read_from_file(&in, g.argv[i], ExtFILE); |
| 1828 | if( g.argc>3 ){ |
| 1829 | fossil_print("<!------ %h ------->\n", g.argv[i]); |
| 1830 | } |
| 1831 | markdown_to_html(&in, 0, &out); |
| 1832 | if( bSafe ) safe_html(&out); |
| 1833 | blob_write_to_file(&out, "-"); |
| 1834 | blob_reset(&in); |
| 1835 | blob_reset(&out); |
| 1836 | } |
| 1837 | } |
| @@ -2569,10 +2570,58 @@ | |
| 2569 | } |
| 2570 | html_tagstack_pop(&s, pBlob, 0); |
| 2571 | html_tagstack_clear(&s); |
| 2572 | zHtml[nHtml] = cLast; |
| 2573 | } |
| 2574 | |
| 2575 | /* |
| 2576 | ** The input blob contains HTML. If safe-html is enabled, then |
| 2577 | ** convert the input into "safe HTML". The following modifications |
| 2578 | ** are made: |
| @@ -2603,11 +2652,11 @@ | |
| 2603 | Blob out; /* Holding area for the revised text during construction */ |
| 2604 | char *z; /* Original input text */ |
| 2605 | int n; /* Number of bytes in the original input text */ |
| 2606 | int k; |
| 2607 | |
| 2608 | /* if( safeHtml==0 ) return; TBD: Always used at this time */ |
| 2609 | z = blob_str(in); |
| 2610 | n = blob_size(in); |
| 2611 | blob_init(&out, 0, 0); |
| 2612 | while( fossil_isspace(z[0]) ){ z++; n--; } |
| 2613 | for(k=n-1; k>5 && fossil_isspace(z[k]); k--){} |
| 2614 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1811,11 +1811,11 @@ | |
| 1811 | ** Usage: %fossil test-markdown-render FILE ... |
| 1812 | ** |
| 1813 | ** Render markdown in FILE as HTML on stdout. |
| 1814 | ** Options: |
| 1815 | ** |
| 1816 | ** --safe Restrict the output to use only "safe" HTML |
| 1817 | */ |
| 1818 | void test_markdown_render(void){ |
| 1819 | Blob in, out; |
| 1820 | int i; |
| 1821 | int bSafe = 0; |
| @@ -1827,11 +1827,12 @@ | |
| 1827 | blob_read_from_file(&in, g.argv[i], ExtFILE); |
| 1828 | if( g.argc>3 ){ |
| 1829 | fossil_print("<!------ %h ------->\n", g.argv[i]); |
| 1830 | } |
| 1831 | markdown_to_html(&in, 0, &out); |
| 1832 | safe_html_context( bSafe ? DOCSRC_UNTRUSTED : DOCSRC_TRUSTED ); |
| 1833 | safe_html(&out); |
| 1834 | blob_write_to_file(&out, "-"); |
| 1835 | blob_reset(&in); |
| 1836 | blob_reset(&out); |
| 1837 | } |
| 1838 | } |
| @@ -2569,10 +2570,58 @@ | |
| 2570 | } |
| 2571 | html_tagstack_pop(&s, pBlob, 0); |
| 2572 | html_tagstack_clear(&s); |
| 2573 | zHtml[nHtml] = cLast; |
| 2574 | } |
| 2575 | |
| 2576 | /* |
| 2577 | ** This local variable is true if the safe_html() function is enabled. |
| 2578 | ** In other words, this is true if the output of Markdown should be |
| 2579 | ** restricted to use only "safe" HTML. |
| 2580 | */ |
| 2581 | static int safeHtmlEnable = 1; |
| 2582 | |
| 2583 | |
| 2584 | #if INTERFACE |
| 2585 | /* |
| 2586 | ** Allowed values for the eTrust parameter to safe_html_context(). |
| 2587 | */ |
| 2588 | #define DOCSRC_FILE 1 /* Document is a checked-in file */ |
| 2589 | #define DOCSRC_FORUM 2 /* Document is a forum post */ |
| 2590 | #define DOCSRC_TICKET 3 /* Document is a ticket comment */ |
| 2591 | #define DOCSRC_WIKI 4 /* Document is a wiki page */ |
| 2592 | #define DOCSRC_TRUSTED 5 /* safe_html() is always a no-op */ |
| 2593 | #define DOCSRC_UNTRUSTED 6 /* safe_html() is always enabled */ |
| 2594 | #endif /* INTERFACE */ |
| 2595 | |
| 2596 | |
| 2597 | /* |
| 2598 | ** Specify the context in which a markdown document with potentially |
| 2599 | ** unsafe HTML will be rendered. |
| 2600 | */ |
| 2601 | void safe_html_context(int eTrust){ |
| 2602 | static const char *zSafeHtmlSetting = 0; |
| 2603 | char cPerm = 0; |
| 2604 | if( eTrust==DOCSRC_TRUSTED ){ |
| 2605 | safeHtmlEnable = 0; |
| 2606 | return; |
| 2607 | } |
| 2608 | if( eTrust==DOCSRC_UNTRUSTED ){ |
| 2609 | safeHtmlEnable = 1; |
| 2610 | return; |
| 2611 | } |
| 2612 | if( zSafeHtmlSetting==0 ){ |
| 2613 | zSafeHtmlSetting = db_get("safe-html", ""); |
| 2614 | } |
| 2615 | switch( eTrust ){ |
| 2616 | case DOCSRC_FILE: cPerm = 'b'; break; |
| 2617 | case DOCSRC_FORUM: cPerm = 'f'; break; |
| 2618 | case DOCSRC_TICKET: cPerm = 't'; break; |
| 2619 | case DOCSRC_WIKI: cPerm = 'w'; break; |
| 2620 | } |
| 2621 | safeHtmlEnable = (strchr(zSafeHtmlSetting,cPerm)==0); |
| 2622 | } |
| 2623 | |
| 2624 | /* |
| 2625 | ** The input blob contains HTML. If safe-html is enabled, then |
| 2626 | ** convert the input into "safe HTML". The following modifications |
| 2627 | ** are made: |
| @@ -2603,11 +2652,11 @@ | |
| 2652 | Blob out; /* Holding area for the revised text during construction */ |
| 2653 | char *z; /* Original input text */ |
| 2654 | int n; /* Number of bytes in the original input text */ |
| 2655 | int k; |
| 2656 | |
| 2657 | if( safeHtmlEnable==0 ) return; |
| 2658 | z = blob_str(in); |
| 2659 | n = blob_size(in); |
| 2660 | blob_init(&out, 0, 0); |
| 2661 | while( fossil_isspace(z[0]) ){ z++; n--; } |
| 2662 | for(k=n-1; k>5 && fossil_isspace(z[k]); k--){} |
| 2663 |