Fossil SCM
Merge in Markdown changes from trunk.
Commit
bf5a21e0364383bca4443ba69f16e4e156109385f259f19a023b8ddb52d7c29b
Parent
07829f371b1c0c9…
9 files changed
+2
-1
-1
+2
-1
+15
-16
+1
-1
+208
-3
+5
-9
+38
-6
+25
-34
+2
-1
| --- src/config.h | ||
| +++ src/config.h | ||
| @@ -254,11 +254,12 @@ | ||
| 254 | 254 | #endif |
| 255 | 255 | |
| 256 | 256 | /* |
| 257 | 257 | ** Number of elements in an array |
| 258 | 258 | */ |
| 259 | -#define count(X) (sizeof(X)/sizeof(X[0])) | |
| 259 | +#define count(X) (int)(sizeof(X)/sizeof(X[0])) | |
| 260 | +#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) | |
| 260 | 261 | |
| 261 | 262 | /* |
| 262 | 263 | ** The pledge() interface is currently only available on OpenBSD 5.9 |
| 263 | 264 | ** and later. Make calls to fossil_pledge() no-ops on all platforms |
| 264 | 265 | ** that omit the HAVE_PLEDGE configuration parameter. |
| 265 | 266 |
| --- src/config.h | |
| +++ src/config.h | |
| @@ -254,11 +254,12 @@ | |
| 254 | #endif |
| 255 | |
| 256 | /* |
| 257 | ** Number of elements in an array |
| 258 | */ |
| 259 | #define count(X) (sizeof(X)/sizeof(X[0])) |
| 260 | |
| 261 | /* |
| 262 | ** The pledge() interface is currently only available on OpenBSD 5.9 |
| 263 | ** and later. Make calls to fossil_pledge() no-ops on all platforms |
| 264 | ** that omit the HAVE_PLEDGE configuration parameter. |
| 265 |
| --- src/config.h | |
| +++ src/config.h | |
| @@ -254,11 +254,12 @@ | |
| 254 | #endif |
| 255 | |
| 256 | /* |
| 257 | ** Number of elements in an array |
| 258 | */ |
| 259 | #define count(X) (int)(sizeof(X)/sizeof(X[0])) |
| 260 | #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) |
| 261 | |
| 262 | /* |
| 263 | ** The pledge() interface is currently only available on OpenBSD 5.9 |
| 264 | ** and later. Make calls to fossil_pledge() no-ops on all platforms |
| 265 | ** that omit the HAVE_PLEDGE configuration parameter. |
| 266 |
-1
| --- src/forum.c | ||
| +++ src/forum.c | ||
| @@ -667,11 +667,10 @@ | ||
| 667 | 667 | @ <div id='forum%d(fpid)' class='forumHierRoot%s(zSel)'> |
| 668 | 668 | }else{ |
| 669 | 669 | @ <div id='forum%d(fpid)' class='forumHier%s(zSel)' \ |
| 670 | 670 | @ style='margin-left: %d((p->nIndent-1)*iIndentScale)ex;'> |
| 671 | 671 | } |
| 672 | - pPost = manifest_get(fpid, CFTYPE_FORUM, 0); | |
| 673 | 672 | if( pPost==0 ) continue; |
| 674 | 673 | if( pPost->zThreadTitle ){ |
| 675 | 674 | @ <h1>%h(pPost->zThreadTitle)</h1> |
| 676 | 675 | } |
| 677 | 676 | zDate = db_text(0, "SELECT datetime(%.17g)", pOPost->rDate); |
| 678 | 677 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -667,11 +667,10 @@ | |
| 667 | @ <div id='forum%d(fpid)' class='forumHierRoot%s(zSel)'> |
| 668 | }else{ |
| 669 | @ <div id='forum%d(fpid)' class='forumHier%s(zSel)' \ |
| 670 | @ style='margin-left: %d((p->nIndent-1)*iIndentScale)ex;'> |
| 671 | } |
| 672 | pPost = manifest_get(fpid, CFTYPE_FORUM, 0); |
| 673 | if( pPost==0 ) continue; |
| 674 | if( pPost->zThreadTitle ){ |
| 675 | @ <h1>%h(pPost->zThreadTitle)</h1> |
| 676 | } |
| 677 | zDate = db_text(0, "SELECT datetime(%.17g)", pOPost->rDate); |
| 678 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -667,11 +667,10 @@ | |
| 667 | @ <div id='forum%d(fpid)' class='forumHierRoot%s(zSel)'> |
| 668 | }else{ |
| 669 | @ <div id='forum%d(fpid)' class='forumHier%s(zSel)' \ |
| 670 | @ style='margin-left: %d((p->nIndent-1)*iIndentScale)ex;'> |
| 671 | } |
| 672 | if( pPost==0 ) continue; |
| 673 | if( pPost->zThreadTitle ){ |
| 674 | @ <h1>%h(pPost->zThreadTitle)</h1> |
| 675 | } |
| 676 | zDate = db_text(0, "SELECT datetime(%.17g)", pOPost->rDate); |
| 677 |
+2
-1
| --- src/markdown.c | ||
| +++ src/markdown.c | ||
| @@ -2008,11 +2008,12 @@ | ||
| 2008 | 2008 | ){ |
| 2009 | 2009 | size_t beg, end, i; |
| 2010 | 2010 | char *txt_data; |
| 2011 | 2011 | int has_table = (rndr->make.table |
| 2012 | 2012 | && rndr->make.table_row |
| 2013 | - && rndr->make.table_cell); | |
| 2013 | + && rndr->make.table_cell | |
| 2014 | + && memchr(data, '|', size)!=0); | |
| 2014 | 2015 | |
| 2015 | 2016 | beg = 0; |
| 2016 | 2017 | while( beg<size ){ |
| 2017 | 2018 | txt_data = data+beg; |
| 2018 | 2019 | end = size-beg; |
| 2019 | 2020 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -2008,11 +2008,12 @@ | |
| 2008 | ){ |
| 2009 | size_t beg, end, i; |
| 2010 | char *txt_data; |
| 2011 | int has_table = (rndr->make.table |
| 2012 | && rndr->make.table_row |
| 2013 | && rndr->make.table_cell); |
| 2014 | |
| 2015 | beg = 0; |
| 2016 | while( beg<size ){ |
| 2017 | txt_data = data+beg; |
| 2018 | end = size-beg; |
| 2019 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -2008,11 +2008,12 @@ | |
| 2008 | ){ |
| 2009 | size_t beg, end, i; |
| 2010 | char *txt_data; |
| 2011 | int has_table = (rndr->make.table |
| 2012 | && rndr->make.table_row |
| 2013 | && rndr->make.table_cell |
| 2014 | && memchr(data, '|', size)!=0); |
| 2015 | |
| 2016 | beg = 0; |
| 2017 | while( beg<size ){ |
| 2018 | txt_data = data+beg; |
| 2019 | end = size-beg; |
| 2020 |
+15
-16
| --- src/markdown_html.c | ||
| +++ src/markdown_html.c | ||
| @@ -45,11 +45,11 @@ | ||
| 45 | 45 | * the error is not overly explicit. |
| 46 | 46 | */ |
| 47 | 47 | |
| 48 | 48 | /* BLOB_APPEND_BLOB -- append blob contents to another */ |
| 49 | 49 | #define BLOB_APPEND_BLOB(dest, src) \ |
| 50 | - blob_append((dest), blob_buffer(src), blob_size(src)) | |
| 50 | + safe_html_append((dest), blob_buffer(src), blob_size(src)) | |
| 51 | 51 | |
| 52 | 52 | |
| 53 | 53 | /* HTML escapes |
| 54 | 54 | ** |
| 55 | 55 | ** html_escape() converts < to <, > to >, and & to &. |
| @@ -129,11 +129,11 @@ | ||
| 129 | 129 | static void html_epilog(struct Blob *ob, void *opaque){ |
| 130 | 130 | INTER_BLOCK(ob); |
| 131 | 131 | BLOB_APPEND_LITERAL(ob, "</div>\n"); |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | -static void html_raw_block(struct Blob *ob, struct Blob *text, void *opaque){ | |
| 134 | +static void html_blockhtml(struct Blob *ob, struct Blob *text, void *opaque){ | |
| 135 | 135 | char *data = blob_buffer(text); |
| 136 | 136 | size_t size = blob_size(text); |
| 137 | 137 | Blob *title = (Blob*)opaque; |
| 138 | 138 | while( size>0 && fossil_isspace(data[0]) ){ data++; size--; } |
| 139 | 139 | while( size>0 && fossil_isspace(data[size-1]) ){ size--; } |
| @@ -142,16 +142,16 @@ | ||
| 142 | 142 | && size>9 |
| 143 | 143 | && title!=0 |
| 144 | 144 | && sqlite3_strnicmp("<h1",data,3)==0 |
| 145 | 145 | && sqlite3_strnicmp("</h1>", &data[size-5],5)==0 |
| 146 | 146 | ){ |
| 147 | - int nTag = htmlTagLength(data); | |
| 147 | + int nTag = html_tag_length(data); | |
| 148 | 148 | blob_append(title, data+nTag, size - nTag - 5); |
| 149 | 149 | return; |
| 150 | 150 | } |
| 151 | 151 | INTER_BLOCK(ob); |
| 152 | - blob_append(ob, data, size); | |
| 152 | + safe_html_append(ob, data, size); | |
| 153 | 153 | BLOB_APPEND_LITERAL(ob, "\n"); |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | 156 | static void html_blockcode(struct Blob *ob, struct Blob *text, void *opaque){ |
| 157 | 157 | INTER_BLOCK(ob); |
| @@ -298,13 +298,12 @@ | ||
| 298 | 298 | |
| 299 | 299 | |
| 300 | 300 | |
| 301 | 301 | /* HTML span tags */ |
| 302 | 302 | |
| 303 | -static int html_raw_span(struct Blob *ob, struct Blob *text, void *opaque){ | |
| 304 | - /* If the document begins with a <h1> markup, take that as the header. */ | |
| 305 | - BLOB_APPEND_BLOB(ob, text); | |
| 303 | +static int html_raw_html_tag(struct Blob *ob, struct Blob *text, void *opaque){ | |
| 304 | + blob_append(ob, blob_buffer(text), blob_size(text)); | |
| 306 | 305 | return 1; |
| 307 | 306 | } |
| 308 | 307 | |
| 309 | 308 | static int html_autolink( |
| 310 | 309 | struct Blob *ob, |
| @@ -334,11 +333,11 @@ | ||
| 334 | 333 | ** * https://spec.commonmark.org/0.29/#code-spans |
| 335 | 334 | ** |
| 336 | 335 | ** If nSep is 1 or 2, then this is a code-span which is inline. |
| 337 | 336 | ** If nSep is 3 or more, then this is a fenced code block |
| 338 | 337 | */ |
| 339 | -static int html_code_span( | |
| 338 | +static int html_codespan( | |
| 340 | 339 | struct Blob *ob, /* Write the output here */ |
| 341 | 340 | struct Blob *text, /* The stuff in between the code span marks */ |
| 342 | 341 | int nSep, /* Number of grave accents marks as delimiters */ |
| 343 | 342 | void *opaque |
| 344 | 343 | ){ |
| @@ -414,11 +413,11 @@ | ||
| 414 | 413 | } |
| 415 | 414 | BLOB_APPEND_LITERAL(ob, "\" />"); |
| 416 | 415 | return 1; |
| 417 | 416 | } |
| 418 | 417 | |
| 419 | -static int html_line_break(struct Blob *ob, void *opaque){ | |
| 418 | +static int html_linebreak(struct Blob *ob, void *opaque){ | |
| 420 | 419 | BLOB_APPEND_LITERAL(ob, "<br />\n"); |
| 421 | 420 | return 1; |
| 422 | 421 | } |
| 423 | 422 | |
| 424 | 423 | static int html_link( |
| @@ -484,11 +483,11 @@ | ||
| 484 | 483 | html_epilog, |
| 485 | 484 | |
| 486 | 485 | /* block level elements */ |
| 487 | 486 | html_blockcode, |
| 488 | 487 | html_blockquote, |
| 489 | - html_raw_block, | |
| 488 | + html_blockhtml, | |
| 490 | 489 | html_header, |
| 491 | 490 | html_hrule, |
| 492 | 491 | html_list, |
| 493 | 492 | html_list_item, |
| 494 | 493 | html_paragraph, |
| @@ -496,27 +495,27 @@ | ||
| 496 | 495 | html_table_cell, |
| 497 | 496 | html_table_row, |
| 498 | 497 | |
| 499 | 498 | /* span level elements */ |
| 500 | 499 | html_autolink, |
| 501 | - html_code_span, | |
| 500 | + html_codespan, | |
| 502 | 501 | html_double_emphasis, |
| 503 | 502 | html_emphasis, |
| 504 | 503 | html_image, |
| 505 | - html_line_break, | |
| 504 | + html_linebreak, | |
| 506 | 505 | html_link, |
| 507 | - html_raw_span, | |
| 506 | + html_raw_html_tag, | |
| 508 | 507 | html_triple_emphasis, |
| 509 | 508 | |
| 510 | 509 | /* low level elements */ |
| 511 | - 0, /* entities are copied verbatim */ | |
| 510 | + 0, /* entity */ | |
| 512 | 511 | html_normal_text, |
| 513 | 512 | |
| 514 | 513 | /* misc. parameters */ |
| 515 | - "*_", /* emphasis characters */ | |
| 516 | - 0 /* opaque data */ | |
| 514 | + "*_", /* emph_chars */ | |
| 515 | + 0 /* opaque */ | |
| 517 | 516 | }; |
| 518 | 517 | html_renderer.opaque = output_title; |
| 519 | 518 | if( output_title ) blob_reset(output_title); |
| 520 | 519 | blob_reset(output_body); |
| 521 | 520 | markdown(output_body, input_markdown, &html_renderer); |
| 522 | 521 | } |
| 523 | 522 |
| --- src/markdown_html.c | |
| +++ src/markdown_html.c | |
| @@ -45,11 +45,11 @@ | |
| 45 | * the error is not overly explicit. |
| 46 | */ |
| 47 | |
| 48 | /* BLOB_APPEND_BLOB -- append blob contents to another */ |
| 49 | #define BLOB_APPEND_BLOB(dest, src) \ |
| 50 | blob_append((dest), blob_buffer(src), blob_size(src)) |
| 51 | |
| 52 | |
| 53 | /* HTML escapes |
| 54 | ** |
| 55 | ** html_escape() converts < to <, > to >, and & to &. |
| @@ -129,11 +129,11 @@ | |
| 129 | static void html_epilog(struct Blob *ob, void *opaque){ |
| 130 | INTER_BLOCK(ob); |
| 131 | BLOB_APPEND_LITERAL(ob, "</div>\n"); |
| 132 | } |
| 133 | |
| 134 | static void html_raw_block(struct Blob *ob, struct Blob *text, void *opaque){ |
| 135 | char *data = blob_buffer(text); |
| 136 | size_t size = blob_size(text); |
| 137 | Blob *title = (Blob*)opaque; |
| 138 | while( size>0 && fossil_isspace(data[0]) ){ data++; size--; } |
| 139 | while( size>0 && fossil_isspace(data[size-1]) ){ size--; } |
| @@ -142,16 +142,16 @@ | |
| 142 | && size>9 |
| 143 | && title!=0 |
| 144 | && sqlite3_strnicmp("<h1",data,3)==0 |
| 145 | && sqlite3_strnicmp("</h1>", &data[size-5],5)==0 |
| 146 | ){ |
| 147 | int nTag = htmlTagLength(data); |
| 148 | blob_append(title, data+nTag, size - nTag - 5); |
| 149 | return; |
| 150 | } |
| 151 | INTER_BLOCK(ob); |
| 152 | blob_append(ob, data, size); |
| 153 | BLOB_APPEND_LITERAL(ob, "\n"); |
| 154 | } |
| 155 | |
| 156 | static void html_blockcode(struct Blob *ob, struct Blob *text, void *opaque){ |
| 157 | INTER_BLOCK(ob); |
| @@ -298,13 +298,12 @@ | |
| 298 | |
| 299 | |
| 300 | |
| 301 | /* HTML span tags */ |
| 302 | |
| 303 | static int html_raw_span(struct Blob *ob, struct Blob *text, void *opaque){ |
| 304 | /* If the document begins with a <h1> markup, take that as the header. */ |
| 305 | BLOB_APPEND_BLOB(ob, text); |
| 306 | return 1; |
| 307 | } |
| 308 | |
| 309 | static int html_autolink( |
| 310 | struct Blob *ob, |
| @@ -334,11 +333,11 @@ | |
| 334 | ** * https://spec.commonmark.org/0.29/#code-spans |
| 335 | ** |
| 336 | ** If nSep is 1 or 2, then this is a code-span which is inline. |
| 337 | ** If nSep is 3 or more, then this is a fenced code block |
| 338 | */ |
| 339 | static int html_code_span( |
| 340 | struct Blob *ob, /* Write the output here */ |
| 341 | struct Blob *text, /* The stuff in between the code span marks */ |
| 342 | int nSep, /* Number of grave accents marks as delimiters */ |
| 343 | void *opaque |
| 344 | ){ |
| @@ -414,11 +413,11 @@ | |
| 414 | } |
| 415 | BLOB_APPEND_LITERAL(ob, "\" />"); |
| 416 | return 1; |
| 417 | } |
| 418 | |
| 419 | static int html_line_break(struct Blob *ob, void *opaque){ |
| 420 | BLOB_APPEND_LITERAL(ob, "<br />\n"); |
| 421 | return 1; |
| 422 | } |
| 423 | |
| 424 | static int html_link( |
| @@ -484,11 +483,11 @@ | |
| 484 | html_epilog, |
| 485 | |
| 486 | /* block level elements */ |
| 487 | html_blockcode, |
| 488 | html_blockquote, |
| 489 | html_raw_block, |
| 490 | html_header, |
| 491 | html_hrule, |
| 492 | html_list, |
| 493 | html_list_item, |
| 494 | html_paragraph, |
| @@ -496,27 +495,27 @@ | |
| 496 | html_table_cell, |
| 497 | html_table_row, |
| 498 | |
| 499 | /* span level elements */ |
| 500 | html_autolink, |
| 501 | html_code_span, |
| 502 | html_double_emphasis, |
| 503 | html_emphasis, |
| 504 | html_image, |
| 505 | html_line_break, |
| 506 | html_link, |
| 507 | html_raw_span, |
| 508 | html_triple_emphasis, |
| 509 | |
| 510 | /* low level elements */ |
| 511 | 0, /* entities are copied verbatim */ |
| 512 | html_normal_text, |
| 513 | |
| 514 | /* misc. parameters */ |
| 515 | "*_", /* emphasis characters */ |
| 516 | 0 /* opaque data */ |
| 517 | }; |
| 518 | html_renderer.opaque = output_title; |
| 519 | if( output_title ) blob_reset(output_title); |
| 520 | blob_reset(output_body); |
| 521 | markdown(output_body, input_markdown, &html_renderer); |
| 522 | } |
| 523 |
| --- src/markdown_html.c | |
| +++ src/markdown_html.c | |
| @@ -45,11 +45,11 @@ | |
| 45 | * the error is not overly explicit. |
| 46 | */ |
| 47 | |
| 48 | /* BLOB_APPEND_BLOB -- append blob contents to another */ |
| 49 | #define BLOB_APPEND_BLOB(dest, src) \ |
| 50 | safe_html_append((dest), blob_buffer(src), blob_size(src)) |
| 51 | |
| 52 | |
| 53 | /* HTML escapes |
| 54 | ** |
| 55 | ** html_escape() converts < to <, > to >, and & to &. |
| @@ -129,11 +129,11 @@ | |
| 129 | static void html_epilog(struct Blob *ob, void *opaque){ |
| 130 | INTER_BLOCK(ob); |
| 131 | BLOB_APPEND_LITERAL(ob, "</div>\n"); |
| 132 | } |
| 133 | |
| 134 | static void html_blockhtml(struct Blob *ob, struct Blob *text, void *opaque){ |
| 135 | char *data = blob_buffer(text); |
| 136 | size_t size = blob_size(text); |
| 137 | Blob *title = (Blob*)opaque; |
| 138 | while( size>0 && fossil_isspace(data[0]) ){ data++; size--; } |
| 139 | while( size>0 && fossil_isspace(data[size-1]) ){ size--; } |
| @@ -142,16 +142,16 @@ | |
| 142 | && size>9 |
| 143 | && title!=0 |
| 144 | && sqlite3_strnicmp("<h1",data,3)==0 |
| 145 | && sqlite3_strnicmp("</h1>", &data[size-5],5)==0 |
| 146 | ){ |
| 147 | int nTag = html_tag_length(data); |
| 148 | blob_append(title, data+nTag, size - nTag - 5); |
| 149 | return; |
| 150 | } |
| 151 | INTER_BLOCK(ob); |
| 152 | safe_html_append(ob, data, size); |
| 153 | BLOB_APPEND_LITERAL(ob, "\n"); |
| 154 | } |
| 155 | |
| 156 | static void html_blockcode(struct Blob *ob, struct Blob *text, void *opaque){ |
| 157 | INTER_BLOCK(ob); |
| @@ -298,13 +298,12 @@ | |
| 298 | |
| 299 | |
| 300 | |
| 301 | /* HTML span tags */ |
| 302 | |
| 303 | static int html_raw_html_tag(struct Blob *ob, struct Blob *text, void *opaque){ |
| 304 | blob_append(ob, blob_buffer(text), blob_size(text)); |
| 305 | return 1; |
| 306 | } |
| 307 | |
| 308 | static int html_autolink( |
| 309 | struct Blob *ob, |
| @@ -334,11 +333,11 @@ | |
| 333 | ** * https://spec.commonmark.org/0.29/#code-spans |
| 334 | ** |
| 335 | ** If nSep is 1 or 2, then this is a code-span which is inline. |
| 336 | ** If nSep is 3 or more, then this is a fenced code block |
| 337 | */ |
| 338 | static int html_codespan( |
| 339 | struct Blob *ob, /* Write the output here */ |
| 340 | struct Blob *text, /* The stuff in between the code span marks */ |
| 341 | int nSep, /* Number of grave accents marks as delimiters */ |
| 342 | void *opaque |
| 343 | ){ |
| @@ -414,11 +413,11 @@ | |
| 413 | } |
| 414 | BLOB_APPEND_LITERAL(ob, "\" />"); |
| 415 | return 1; |
| 416 | } |
| 417 | |
| 418 | static int html_linebreak(struct Blob *ob, void *opaque){ |
| 419 | BLOB_APPEND_LITERAL(ob, "<br />\n"); |
| 420 | return 1; |
| 421 | } |
| 422 | |
| 423 | static int html_link( |
| @@ -484,11 +483,11 @@ | |
| 483 | html_epilog, |
| 484 | |
| 485 | /* block level elements */ |
| 486 | html_blockcode, |
| 487 | html_blockquote, |
| 488 | html_blockhtml, |
| 489 | html_header, |
| 490 | html_hrule, |
| 491 | html_list, |
| 492 | html_list_item, |
| 493 | html_paragraph, |
| @@ -496,27 +495,27 @@ | |
| 495 | html_table_cell, |
| 496 | html_table_row, |
| 497 | |
| 498 | /* span level elements */ |
| 499 | html_autolink, |
| 500 | html_codespan, |
| 501 | html_double_emphasis, |
| 502 | html_emphasis, |
| 503 | html_image, |
| 504 | html_linebreak, |
| 505 | html_link, |
| 506 | html_raw_html_tag, |
| 507 | html_triple_emphasis, |
| 508 | |
| 509 | /* low level elements */ |
| 510 | 0, /* entity */ |
| 511 | html_normal_text, |
| 512 | |
| 513 | /* misc. parameters */ |
| 514 | "*_", /* emph_chars */ |
| 515 | 0 /* opaque */ |
| 516 | }; |
| 517 | html_renderer.opaque = output_title; |
| 518 | if( output_title ) blob_reset(output_title); |
| 519 | blob_reset(output_body); |
| 520 | markdown(output_body, input_markdown, &html_renderer); |
| 521 | } |
| 522 |
+1
-1
| --- src/name.c | ||
| +++ src/name.c | ||
| @@ -380,11 +380,11 @@ | ||
| 380 | 380 | if( zType[0]=='*' ){ |
| 381 | 381 | db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid); |
| 382 | 382 | }else{ |
| 383 | 383 | db_prepare(&q, |
| 384 | 384 | "SELECT blob.rid" |
| 385 | - " FROM blob, event" | |
| 385 | + " FROM blob CROSS JOIN event" | |
| 386 | 386 | " WHERE blob.uuid GLOB '%q*'" |
| 387 | 387 | " AND event.objid=blob.rid" |
| 388 | 388 | " AND event.type GLOB '%q'", |
| 389 | 389 | zUuid, zType |
| 390 | 390 | ); |
| 391 | 391 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -380,11 +380,11 @@ | |
| 380 | if( zType[0]=='*' ){ |
| 381 | db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid); |
| 382 | }else{ |
| 383 | db_prepare(&q, |
| 384 | "SELECT blob.rid" |
| 385 | " FROM blob, event" |
| 386 | " WHERE blob.uuid GLOB '%q*'" |
| 387 | " AND event.objid=blob.rid" |
| 388 | " AND event.type GLOB '%q'", |
| 389 | zUuid, zType |
| 390 | ); |
| 391 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -380,11 +380,11 @@ | |
| 380 | if( zType[0]=='*' ){ |
| 381 | db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid); |
| 382 | }else{ |
| 383 | db_prepare(&q, |
| 384 | "SELECT blob.rid" |
| 385 | " FROM blob CROSS JOIN event" |
| 386 | " WHERE blob.uuid GLOB '%q*'" |
| 387 | " AND event.objid=blob.rid" |
| 388 | " AND event.type GLOB '%q'", |
| 389 | zUuid, zType |
| 390 | ); |
| 391 |
+208
-3
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -249,10 +249,13 @@ | ||
| 249 | 249 | #define MUTYPE_TR 0x0080 /* <tr> */ |
| 250 | 250 | #define MUTYPE_TD 0x0100 /* <td> or <th> */ |
| 251 | 251 | #define MUTYPE_SPECIAL 0x0200 /* <nowiki> or <verbatim> */ |
| 252 | 252 | #define MUTYPE_HYPERLINK 0x0400 /* <a> */ |
| 253 | 253 | |
| 254 | +/* MUTYPE values for elements that require strictly nested end-tags */ | |
| 255 | +#define MUTYPE_Nested 0x0656 | |
| 256 | + | |
| 254 | 257 | /* |
| 255 | 258 | ** These markup types must have an end tag. |
| 256 | 259 | */ |
| 257 | 260 | #define MUTYPE_STACK (MUTYPE_BLOCK | MUTYPE_FONT | MUTYPE_LIST | MUTYPE_TABLE) |
| 258 | 261 | |
| @@ -469,11 +472,11 @@ | ||
| 469 | 472 | ** z points to a "<" character. Check to see if this is the start of |
| 470 | 473 | ** a valid markup. If it is, return the total number of characters in |
| 471 | 474 | ** the markup including the initial "<" and the terminating ">". If |
| 472 | 475 | ** it is not well-formed markup, return 0. |
| 473 | 476 | */ |
| 474 | -int htmlTagLength(const char *z){ | |
| 477 | +int html_tag_length(const char *z){ | |
| 475 | 478 | int n = 1; |
| 476 | 479 | int inparen = 0; |
| 477 | 480 | int c; |
| 478 | 481 | if( z[n]=='/' ){ n++; } |
| 479 | 482 | if( !fossil_isalpha(z[n]) ) return 0; |
| @@ -656,11 +659,11 @@ | ||
| 656 | 659 | ** characters in that token. Write the token type into *pTokenType. |
| 657 | 660 | */ |
| 658 | 661 | static int nextWikiToken(const char *z, Renderer *p, int *pTokenType){ |
| 659 | 662 | int n; |
| 660 | 663 | if( z[0]=='<' ){ |
| 661 | - n = htmlTagLength(z); | |
| 664 | + n = html_tag_length(z); | |
| 662 | 665 | if( n>0 ){ |
| 663 | 666 | *pTokenType = TOKEN_MARKUP; |
| 664 | 667 | return n; |
| 665 | 668 | }else{ |
| 666 | 669 | *pTokenType = TOKEN_CHARACTER; |
| @@ -2026,11 +2029,11 @@ | ||
| 2026 | 2029 | */ |
| 2027 | 2030 | int html_token_length(const char *z){ |
| 2028 | 2031 | int n; |
| 2029 | 2032 | char c; |
| 2030 | 2033 | if( (c=z[0])=='<' ){ |
| 2031 | - n = htmlTagLength(z); | |
| 2034 | + n = html_tag_length(z); | |
| 2032 | 2035 | if( n<=0 ) n = 1; |
| 2033 | 2036 | }else if( fossil_isspace(c) ){ |
| 2034 | 2037 | for(n=1; z[n] && fossil_isspace(z[n]); n++){} |
| 2035 | 2038 | }else if( c=='&' ){ |
| 2036 | 2039 | n = z[1]=='#' ? 2 : 1; |
| @@ -2396,5 +2399,207 @@ | ||
| 2396 | 2399 | blob_reset(&in); |
| 2397 | 2400 | fossil_puts(blob_str(&out), 0); |
| 2398 | 2401 | blob_reset(&out); |
| 2399 | 2402 | } |
| 2400 | 2403 | } |
| 2404 | + | |
| 2405 | +/**************************************************************************** | |
| 2406 | +** safe-html: | |
| 2407 | +** | |
| 2408 | +** An interface for preventing HTML constructs (ex: <style>, <form>, etc) | |
| 2409 | +** from being inserted into Wiki and Forum posts using Markdown. See the | |
| 2410 | +** comment on safe_html_append() for additional information on what is meant | |
| 2411 | +** by "safe". | |
| 2412 | +** | |
| 2413 | +** The safe-html restrictions only apply to Markdown, as Fossil-Wiki only | |
| 2414 | +** allows safe-html by design - unsafe-HTML is never and has never been | |
| 2415 | +** allowed in Fossil-Wiki. | |
| 2416 | +** | |
| 2417 | +** This code is in the wikiformat.c file so that it can have access to the | |
| 2418 | +** white-list of acceptable HTML in the aMarkup[] array. | |
| 2419 | +*/ | |
| 2420 | + | |
| 2421 | +/* | |
| 2422 | +** An instance of this object keeps track of the nesting of HTML | |
| 2423 | +** elements for safe_html_append(). | |
| 2424 | +*/ | |
| 2425 | +typedef struct HtmlTagStack HtmlTagStack; | |
| 2426 | +struct HtmlTagStack { | |
| 2427 | + int n; /* Current tag stack depth */ | |
| 2428 | + int nAlloc; /* Space allocated for aStack[] */ | |
| 2429 | + int *aStack; /* The stack of tags */ | |
| 2430 | + int aSpace[10]; /* Initial static space, to avoid malloc() */ | |
| 2431 | +}; | |
| 2432 | + | |
| 2433 | +/* | |
| 2434 | +** Initialize bulk memory to a valid empty tagstack. | |
| 2435 | +*/ | |
| 2436 | +static void html_tagstack_init(HtmlTagStack *p){ | |
| 2437 | + p->n = 0; | |
| 2438 | + p->nAlloc = 0; | |
| 2439 | + p->aStack = p->aSpace; | |
| 2440 | +} | |
| 2441 | + | |
| 2442 | +/* | |
| 2443 | +** Push a new element onto the tag statk | |
| 2444 | +*/ | |
| 2445 | +static void html_tagstack_push(HtmlTagStack *p, int e){ | |
| 2446 | + if( p->n>=ArraySize(p->aSpace) && p->n>=p->nAlloc ){ | |
| 2447 | + if( p->nAlloc==0 ){ | |
| 2448 | + int *aNew; | |
| 2449 | + p->nAlloc = 50; | |
| 2450 | + aNew = fossil_malloc( sizeof(p->aStack[0])*p->nAlloc ); | |
| 2451 | + memcpy(aNew, p->aStack, sizeof(p->aStack[0])*p->n ); | |
| 2452 | + p->aStack = aNew; | |
| 2453 | + }else{ | |
| 2454 | + p->nAlloc *= 2; | |
| 2455 | + p->aStack = fossil_realloc(p->aStack, sizeof(p->aStack[0])*p->nAlloc ); | |
| 2456 | + } | |
| 2457 | + } | |
| 2458 | + p->aStack[p->n++] = e; | |
| 2459 | +} | |
| 2460 | + | |
| 2461 | +/* | |
| 2462 | +** Clear a tag stack, reclaiming any memory allocations. | |
| 2463 | +*/ | |
| 2464 | +static void html_tagstack_clear(HtmlTagStack *p){ | |
| 2465 | + if( p->nAlloc ){ | |
| 2466 | + fossil_free(p->aStack); | |
| 2467 | + p->nAlloc = 0; | |
| 2468 | + p->aStack = p->aSpace; | |
| 2469 | + } | |
| 2470 | + p->n = 0; | |
| 2471 | +} | |
| 2472 | + | |
| 2473 | +/* | |
| 2474 | +** The HTML end-tag eEnd wants to be added to pBlob. | |
| 2475 | +** | |
| 2476 | +** If an open-tag for eEnd exists anywhere on the stack, then | |
| 2477 | +** pop it and all prior elements from the task, issuing appropriate | |
| 2478 | +** end-tags as you go. | |
| 2479 | +** | |
| 2480 | +** If there is no open-tag for eEnd on the stack, then this | |
| 2481 | +** routine is a no-op. | |
| 2482 | +*/ | |
| 2483 | +static void html_tagstack_pop(HtmlTagStack *p, Blob *pBlob, int eEnd){ | |
| 2484 | + int i, e; | |
| 2485 | + if( eEnd!=0 ){ | |
| 2486 | + for(i=p->n-1; i>=0 && p->aStack[i]!=eEnd; i--){} | |
| 2487 | + if( i<0 ){ | |
| 2488 | + blob_appendf(pBlob, "<span class='error'></%s></span>", | |
| 2489 | + aMarkup[eEnd].zName); | |
| 2490 | + return; | |
| 2491 | + } | |
| 2492 | + }else if( p->n==0 ){ | |
| 2493 | + return; | |
| 2494 | + } | |
| 2495 | + do{ | |
| 2496 | + e = p->aStack[--p->n]; | |
| 2497 | + if( e==eEnd || (aMarkup[e].iType & MUTYPE_Nested)!=0 ){ | |
| 2498 | + blob_appendf(pBlob, "</%s>", aMarkup[e].zName); | |
| 2499 | + } | |
| 2500 | + }while( e!=eEnd && p->n>0 ); | |
| 2501 | +} | |
| 2502 | + | |
| 2503 | +/* | |
| 2504 | +** Append HTML text to a Blob object. The appended text is modified | |
| 2505 | +** changed in the following ways: | |
| 2506 | +** | |
| 2507 | +** 1. Omit any elements that are not on the AllowedMarkup list. | |
| 2508 | +** | |
| 2509 | +** 2. Omit any attributes that are not on the AllowedMarkup list. | |
| 2510 | +** | |
| 2511 | +** 3. Omit any surplus close-tags. (This prevents a surplus </div> | |
| 2512 | +** or </body> or similar element from interferring with formatting | |
| 2513 | +** of the outer context in which the HTML is being inserted.) | |
| 2514 | +** | |
| 2515 | +** 4. Insert additional close-tags as necessary so that any | |
| 2516 | +** tag in the input that needs a close-tag has one. (This prevents | |
| 2517 | +** the inserted HTML from messing up the formatting of subsequent | |
| 2518 | +** sections of the document into which it is being inserted.) | |
| 2519 | +** | |
| 2520 | +** The input must be writable. Temporary changes may be made to the | |
| 2521 | +** input, but the input is restored to its original state prior to | |
| 2522 | +** returning. If zHtml[nHtml] is not a zero character, then a zero | |
| 2523 | +** might be written in that position temporarily, but that slot will | |
| 2524 | +** also be restored before this routine returns. | |
| 2525 | +*/ | |
| 2526 | +void safe_html_append(Blob *pBlob, char *zHtml, int nHtml){ | |
| 2527 | + char cLast; | |
| 2528 | + int i, j, n; | |
| 2529 | + HtmlTagStack s; | |
| 2530 | + ParsedMarkup markup; | |
| 2531 | + | |
| 2532 | + if( nHtml<=0 ) return; | |
| 2533 | + cLast = zHtml[nHtml]; | |
| 2534 | + zHtml[nHtml] = 0; | |
| 2535 | + html_tagstack_init(&s); | |
| 2536 | + | |
| 2537 | + i = 0; | |
| 2538 | + while( i<nHtml ){ | |
| 2539 | + if( zHtml[i]=='<' ){ | |
| 2540 | + j = i; | |
| 2541 | + }else{ | |
| 2542 | + char *z = strchr(zHtml+i, '<'); | |
| 2543 | + if( z==0 ){ | |
| 2544 | + blob_append(pBlob, zHtml+i, nHtml-i); | |
| 2545 | + break; | |
| 2546 | + } | |
| 2547 | + j = (int)(z - zHtml); | |
| 2548 | + blob_append(pBlob, zHtml+i, j-i); | |
| 2549 | + } | |
| 2550 | + n = html_tag_length(zHtml+j); | |
| 2551 | + if( n==0 ){ | |
| 2552 | + blob_append(pBlob, "<", 4); | |
| 2553 | + i = j+1; | |
| 2554 | + continue; | |
| 2555 | + }else{ | |
| 2556 | + i = j + n; | |
| 2557 | + } | |
| 2558 | + parseMarkup(&markup, zHtml+j); | |
| 2559 | + if( markup.iCode==MARKUP_INVALID ){ | |
| 2560 | + blob_appendf(pBlob, "<span class='error'><%.*s></span>", | |
| 2561 | + n-2, zHtml+j+1); | |
| 2562 | + }else{ | |
| 2563 | + if( markup.endTag ){ | |
| 2564 | + html_tagstack_pop(&s, pBlob, markup.iCode); | |
| 2565 | + }else{ | |
| 2566 | + renderMarkup(pBlob, &markup); | |
| 2567 | + html_tagstack_push(&s, markup.iCode); | |
| 2568 | + } | |
| 2569 | + } | |
| 2570 | + unparseMarkup(&markup); | |
| 2571 | + } | |
| 2572 | + html_tagstack_pop(&s, pBlob, 0); | |
| 2573 | + html_tagstack_clear(&s); | |
| 2574 | + zHtml[nHtml] = cLast; | |
| 2575 | +} | |
| 2576 | + | |
| 2577 | + | |
| 2578 | +/* | |
| 2579 | +** COMMAND: test-safe-html | |
| 2580 | +** | |
| 2581 | +** Usage: %fossil test-safe-html FILE ... | |
| 2582 | +** | |
| 2583 | +** Read files named on the command-line. Send the text of each file | |
| 2584 | +** through safe_html_append() and then write the result on | |
| 2585 | +** standard output. | |
| 2586 | +*/ | |
| 2587 | +void test_safe_html_cmd(void){ | |
| 2588 | + int i; | |
| 2589 | + Blob x; | |
| 2590 | + Blob y; | |
| 2591 | + for(i=2; i<g.argc; i++){ | |
| 2592 | + char *z; | |
| 2593 | + int n; | |
| 2594 | + blob_read_from_file(&x, g.argv[i], ExtFILE); | |
| 2595 | + blob_init(&y, 0, 0); | |
| 2596 | + blob_terminate(&x); | |
| 2597 | + safe_html_append(&y, blob_buffer(&x), blob_size(&x)); | |
| 2598 | + blob_reset(&x); | |
| 2599 | + z = blob_str(&y); | |
| 2600 | + n = blob_size(&y); | |
| 2601 | + while( n>0 && (z[n-1]=='\n' || z[n-1]=='\r') ) n--; | |
| 2602 | + fossil_print("%.*s\n", n, z); | |
| 2603 | + blob_reset(&y); | |
| 2604 | + } | |
| 2605 | +} | |
| 2401 | 2606 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -249,10 +249,13 @@ | |
| 249 | #define MUTYPE_TR 0x0080 /* <tr> */ |
| 250 | #define MUTYPE_TD 0x0100 /* <td> or <th> */ |
| 251 | #define MUTYPE_SPECIAL 0x0200 /* <nowiki> or <verbatim> */ |
| 252 | #define MUTYPE_HYPERLINK 0x0400 /* <a> */ |
| 253 | |
| 254 | /* |
| 255 | ** These markup types must have an end tag. |
| 256 | */ |
| 257 | #define MUTYPE_STACK (MUTYPE_BLOCK | MUTYPE_FONT | MUTYPE_LIST | MUTYPE_TABLE) |
| 258 | |
| @@ -469,11 +472,11 @@ | |
| 469 | ** z points to a "<" character. Check to see if this is the start of |
| 470 | ** a valid markup. If it is, return the total number of characters in |
| 471 | ** the markup including the initial "<" and the terminating ">". If |
| 472 | ** it is not well-formed markup, return 0. |
| 473 | */ |
| 474 | int htmlTagLength(const char *z){ |
| 475 | int n = 1; |
| 476 | int inparen = 0; |
| 477 | int c; |
| 478 | if( z[n]=='/' ){ n++; } |
| 479 | if( !fossil_isalpha(z[n]) ) return 0; |
| @@ -656,11 +659,11 @@ | |
| 656 | ** characters in that token. Write the token type into *pTokenType. |
| 657 | */ |
| 658 | static int nextWikiToken(const char *z, Renderer *p, int *pTokenType){ |
| 659 | int n; |
| 660 | if( z[0]=='<' ){ |
| 661 | n = htmlTagLength(z); |
| 662 | if( n>0 ){ |
| 663 | *pTokenType = TOKEN_MARKUP; |
| 664 | return n; |
| 665 | }else{ |
| 666 | *pTokenType = TOKEN_CHARACTER; |
| @@ -2026,11 +2029,11 @@ | |
| 2026 | */ |
| 2027 | int html_token_length(const char *z){ |
| 2028 | int n; |
| 2029 | char c; |
| 2030 | if( (c=z[0])=='<' ){ |
| 2031 | n = htmlTagLength(z); |
| 2032 | if( n<=0 ) n = 1; |
| 2033 | }else if( fossil_isspace(c) ){ |
| 2034 | for(n=1; z[n] && fossil_isspace(z[n]); n++){} |
| 2035 | }else if( c=='&' ){ |
| 2036 | n = z[1]=='#' ? 2 : 1; |
| @@ -2396,5 +2399,207 @@ | |
| 2396 | blob_reset(&in); |
| 2397 | fossil_puts(blob_str(&out), 0); |
| 2398 | blob_reset(&out); |
| 2399 | } |
| 2400 | } |
| 2401 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -249,10 +249,13 @@ | |
| 249 | #define MUTYPE_TR 0x0080 /* <tr> */ |
| 250 | #define MUTYPE_TD 0x0100 /* <td> or <th> */ |
| 251 | #define MUTYPE_SPECIAL 0x0200 /* <nowiki> or <verbatim> */ |
| 252 | #define MUTYPE_HYPERLINK 0x0400 /* <a> */ |
| 253 | |
| 254 | /* MUTYPE values for elements that require strictly nested end-tags */ |
| 255 | #define MUTYPE_Nested 0x0656 |
| 256 | |
| 257 | /* |
| 258 | ** These markup types must have an end tag. |
| 259 | */ |
| 260 | #define MUTYPE_STACK (MUTYPE_BLOCK | MUTYPE_FONT | MUTYPE_LIST | MUTYPE_TABLE) |
| 261 | |
| @@ -469,11 +472,11 @@ | |
| 472 | ** z points to a "<" character. Check to see if this is the start of |
| 473 | ** a valid markup. If it is, return the total number of characters in |
| 474 | ** the markup including the initial "<" and the terminating ">". If |
| 475 | ** it is not well-formed markup, return 0. |
| 476 | */ |
| 477 | int html_tag_length(const char *z){ |
| 478 | int n = 1; |
| 479 | int inparen = 0; |
| 480 | int c; |
| 481 | if( z[n]=='/' ){ n++; } |
| 482 | if( !fossil_isalpha(z[n]) ) return 0; |
| @@ -656,11 +659,11 @@ | |
| 659 | ** characters in that token. Write the token type into *pTokenType. |
| 660 | */ |
| 661 | static int nextWikiToken(const char *z, Renderer *p, int *pTokenType){ |
| 662 | int n; |
| 663 | if( z[0]=='<' ){ |
| 664 | n = html_tag_length(z); |
| 665 | if( n>0 ){ |
| 666 | *pTokenType = TOKEN_MARKUP; |
| 667 | return n; |
| 668 | }else{ |
| 669 | *pTokenType = TOKEN_CHARACTER; |
| @@ -2026,11 +2029,11 @@ | |
| 2029 | */ |
| 2030 | int html_token_length(const char *z){ |
| 2031 | int n; |
| 2032 | char c; |
| 2033 | if( (c=z[0])=='<' ){ |
| 2034 | n = html_tag_length(z); |
| 2035 | if( n<=0 ) n = 1; |
| 2036 | }else if( fossil_isspace(c) ){ |
| 2037 | for(n=1; z[n] && fossil_isspace(z[n]); n++){} |
| 2038 | }else if( c=='&' ){ |
| 2039 | n = z[1]=='#' ? 2 : 1; |
| @@ -2396,5 +2399,207 @@ | |
| 2399 | blob_reset(&in); |
| 2400 | fossil_puts(blob_str(&out), 0); |
| 2401 | blob_reset(&out); |
| 2402 | } |
| 2403 | } |
| 2404 | |
| 2405 | /**************************************************************************** |
| 2406 | ** safe-html: |
| 2407 | ** |
| 2408 | ** An interface for preventing HTML constructs (ex: <style>, <form>, etc) |
| 2409 | ** from being inserted into Wiki and Forum posts using Markdown. See the |
| 2410 | ** comment on safe_html_append() for additional information on what is meant |
| 2411 | ** by "safe". |
| 2412 | ** |
| 2413 | ** The safe-html restrictions only apply to Markdown, as Fossil-Wiki only |
| 2414 | ** allows safe-html by design - unsafe-HTML is never and has never been |
| 2415 | ** allowed in Fossil-Wiki. |
| 2416 | ** |
| 2417 | ** This code is in the wikiformat.c file so that it can have access to the |
| 2418 | ** white-list of acceptable HTML in the aMarkup[] array. |
| 2419 | */ |
| 2420 | |
| 2421 | /* |
| 2422 | ** An instance of this object keeps track of the nesting of HTML |
| 2423 | ** elements for safe_html_append(). |
| 2424 | */ |
| 2425 | typedef struct HtmlTagStack HtmlTagStack; |
| 2426 | struct HtmlTagStack { |
| 2427 | int n; /* Current tag stack depth */ |
| 2428 | int nAlloc; /* Space allocated for aStack[] */ |
| 2429 | int *aStack; /* The stack of tags */ |
| 2430 | int aSpace[10]; /* Initial static space, to avoid malloc() */ |
| 2431 | }; |
| 2432 | |
| 2433 | /* |
| 2434 | ** Initialize bulk memory to a valid empty tagstack. |
| 2435 | */ |
| 2436 | static void html_tagstack_init(HtmlTagStack *p){ |
| 2437 | p->n = 0; |
| 2438 | p->nAlloc = 0; |
| 2439 | p->aStack = p->aSpace; |
| 2440 | } |
| 2441 | |
| 2442 | /* |
| 2443 | ** Push a new element onto the tag statk |
| 2444 | */ |
| 2445 | static void html_tagstack_push(HtmlTagStack *p, int e){ |
| 2446 | if( p->n>=ArraySize(p->aSpace) && p->n>=p->nAlloc ){ |
| 2447 | if( p->nAlloc==0 ){ |
| 2448 | int *aNew; |
| 2449 | p->nAlloc = 50; |
| 2450 | aNew = fossil_malloc( sizeof(p->aStack[0])*p->nAlloc ); |
| 2451 | memcpy(aNew, p->aStack, sizeof(p->aStack[0])*p->n ); |
| 2452 | p->aStack = aNew; |
| 2453 | }else{ |
| 2454 | p->nAlloc *= 2; |
| 2455 | p->aStack = fossil_realloc(p->aStack, sizeof(p->aStack[0])*p->nAlloc ); |
| 2456 | } |
| 2457 | } |
| 2458 | p->aStack[p->n++] = e; |
| 2459 | } |
| 2460 | |
| 2461 | /* |
| 2462 | ** Clear a tag stack, reclaiming any memory allocations. |
| 2463 | */ |
| 2464 | static void html_tagstack_clear(HtmlTagStack *p){ |
| 2465 | if( p->nAlloc ){ |
| 2466 | fossil_free(p->aStack); |
| 2467 | p->nAlloc = 0; |
| 2468 | p->aStack = p->aSpace; |
| 2469 | } |
| 2470 | p->n = 0; |
| 2471 | } |
| 2472 | |
| 2473 | /* |
| 2474 | ** The HTML end-tag eEnd wants to be added to pBlob. |
| 2475 | ** |
| 2476 | ** If an open-tag for eEnd exists anywhere on the stack, then |
| 2477 | ** pop it and all prior elements from the task, issuing appropriate |
| 2478 | ** end-tags as you go. |
| 2479 | ** |
| 2480 | ** If there is no open-tag for eEnd on the stack, then this |
| 2481 | ** routine is a no-op. |
| 2482 | */ |
| 2483 | static void html_tagstack_pop(HtmlTagStack *p, Blob *pBlob, int eEnd){ |
| 2484 | int i, e; |
| 2485 | if( eEnd!=0 ){ |
| 2486 | for(i=p->n-1; i>=0 && p->aStack[i]!=eEnd; i--){} |
| 2487 | if( i<0 ){ |
| 2488 | blob_appendf(pBlob, "<span class='error'></%s></span>", |
| 2489 | aMarkup[eEnd].zName); |
| 2490 | return; |
| 2491 | } |
| 2492 | }else if( p->n==0 ){ |
| 2493 | return; |
| 2494 | } |
| 2495 | do{ |
| 2496 | e = p->aStack[--p->n]; |
| 2497 | if( e==eEnd || (aMarkup[e].iType & MUTYPE_Nested)!=0 ){ |
| 2498 | blob_appendf(pBlob, "</%s>", aMarkup[e].zName); |
| 2499 | } |
| 2500 | }while( e!=eEnd && p->n>0 ); |
| 2501 | } |
| 2502 | |
| 2503 | /* |
| 2504 | ** Append HTML text to a Blob object. The appended text is modified |
| 2505 | ** changed in the following ways: |
| 2506 | ** |
| 2507 | ** 1. Omit any elements that are not on the AllowedMarkup list. |
| 2508 | ** |
| 2509 | ** 2. Omit any attributes that are not on the AllowedMarkup list. |
| 2510 | ** |
| 2511 | ** 3. Omit any surplus close-tags. (This prevents a surplus </div> |
| 2512 | ** or </body> or similar element from interferring with formatting |
| 2513 | ** of the outer context in which the HTML is being inserted.) |
| 2514 | ** |
| 2515 | ** 4. Insert additional close-tags as necessary so that any |
| 2516 | ** tag in the input that needs a close-tag has one. (This prevents |
| 2517 | ** the inserted HTML from messing up the formatting of subsequent |
| 2518 | ** sections of the document into which it is being inserted.) |
| 2519 | ** |
| 2520 | ** The input must be writable. Temporary changes may be made to the |
| 2521 | ** input, but the input is restored to its original state prior to |
| 2522 | ** returning. If zHtml[nHtml] is not a zero character, then a zero |
| 2523 | ** might be written in that position temporarily, but that slot will |
| 2524 | ** also be restored before this routine returns. |
| 2525 | */ |
| 2526 | void safe_html_append(Blob *pBlob, char *zHtml, int nHtml){ |
| 2527 | char cLast; |
| 2528 | int i, j, n; |
| 2529 | HtmlTagStack s; |
| 2530 | ParsedMarkup markup; |
| 2531 | |
| 2532 | if( nHtml<=0 ) return; |
| 2533 | cLast = zHtml[nHtml]; |
| 2534 | zHtml[nHtml] = 0; |
| 2535 | html_tagstack_init(&s); |
| 2536 | |
| 2537 | i = 0; |
| 2538 | while( i<nHtml ){ |
| 2539 | if( zHtml[i]=='<' ){ |
| 2540 | j = i; |
| 2541 | }else{ |
| 2542 | char *z = strchr(zHtml+i, '<'); |
| 2543 | if( z==0 ){ |
| 2544 | blob_append(pBlob, zHtml+i, nHtml-i); |
| 2545 | break; |
| 2546 | } |
| 2547 | j = (int)(z - zHtml); |
| 2548 | blob_append(pBlob, zHtml+i, j-i); |
| 2549 | } |
| 2550 | n = html_tag_length(zHtml+j); |
| 2551 | if( n==0 ){ |
| 2552 | blob_append(pBlob, "<", 4); |
| 2553 | i = j+1; |
| 2554 | continue; |
| 2555 | }else{ |
| 2556 | i = j + n; |
| 2557 | } |
| 2558 | parseMarkup(&markup, zHtml+j); |
| 2559 | if( markup.iCode==MARKUP_INVALID ){ |
| 2560 | blob_appendf(pBlob, "<span class='error'><%.*s></span>", |
| 2561 | n-2, zHtml+j+1); |
| 2562 | }else{ |
| 2563 | if( markup.endTag ){ |
| 2564 | html_tagstack_pop(&s, pBlob, markup.iCode); |
| 2565 | }else{ |
| 2566 | renderMarkup(pBlob, &markup); |
| 2567 | html_tagstack_push(&s, markup.iCode); |
| 2568 | } |
| 2569 | } |
| 2570 | unparseMarkup(&markup); |
| 2571 | } |
| 2572 | html_tagstack_pop(&s, pBlob, 0); |
| 2573 | html_tagstack_clear(&s); |
| 2574 | zHtml[nHtml] = cLast; |
| 2575 | } |
| 2576 | |
| 2577 | |
| 2578 | /* |
| 2579 | ** COMMAND: test-safe-html |
| 2580 | ** |
| 2581 | ** Usage: %fossil test-safe-html FILE ... |
| 2582 | ** |
| 2583 | ** Read files named on the command-line. Send the text of each file |
| 2584 | ** through safe_html_append() and then write the result on |
| 2585 | ** standard output. |
| 2586 | */ |
| 2587 | void test_safe_html_cmd(void){ |
| 2588 | int i; |
| 2589 | Blob x; |
| 2590 | Blob y; |
| 2591 | for(i=2; i<g.argc; i++){ |
| 2592 | char *z; |
| 2593 | int n; |
| 2594 | blob_read_from_file(&x, g.argv[i], ExtFILE); |
| 2595 | blob_init(&y, 0, 0); |
| 2596 | blob_terminate(&x); |
| 2597 | safe_html_append(&y, blob_buffer(&x), blob_size(&x)); |
| 2598 | blob_reset(&x); |
| 2599 | z = blob_str(&y); |
| 2600 | n = blob_size(&y); |
| 2601 | while( n>0 && (z[n-1]=='\n' || z[n-1]=='\r') ) n--; |
| 2602 | fossil_print("%.*s\n", n, z); |
| 2603 | blob_reset(&y); |
| 2604 | } |
| 2605 | } |
| 2606 |
+5
-9
| --- www/server/debian/nginx.md | ||
| +++ www/server/debian/nginx.md | ||
| @@ -109,19 +109,15 @@ | ||
| 109 | 109 | |
| 110 | 110 | ## <a name="scgi"></a>Running Fossil in SCGI Mode |
| 111 | 111 | |
| 112 | 112 | For the following nginx configuration to work, it needs to contact a |
| 113 | 113 | Fossil instance speaking the SCGI protocol. There are [many ways](../) |
| 114 | -to set that up. For Debian type systems, we primarily recommend | |
| 115 | -following [our systemd user service guide](service.md). | |
| 116 | - | |
| 117 | -Another option would be to customize [the `fslsrv` shell | |
| 118 | -script](/file/tools/fslsrv) that ships with Fossil as an example of | |
| 119 | -launching multiple Fossil instances in the background to serve multiple | |
| 120 | -URLs. | |
| 121 | - | |
| 122 | -However you do it, you need to match up the TCP port numbers between it | |
| 114 | +to set that up. For Debian type systems, we recommend | |
| 115 | +following [our systemd system service guide](service.md). | |
| 116 | + | |
| 117 | +There are other ways to arrange for Fossil to run as a service backing | |
| 118 | +nginx, but however you do it, you need to match up the TCP port numbers between it | |
| 123 | 119 | and those in the nginx configuration below. |
| 124 | 120 | |
| 125 | 121 | |
| 126 | 122 | ## <a name="config"></a>Configuration |
| 127 | 123 | |
| 128 | 124 |
| --- www/server/debian/nginx.md | |
| +++ www/server/debian/nginx.md | |
| @@ -109,19 +109,15 @@ | |
| 109 | |
| 110 | ## <a name="scgi"></a>Running Fossil in SCGI Mode |
| 111 | |
| 112 | For the following nginx configuration to work, it needs to contact a |
| 113 | Fossil instance speaking the SCGI protocol. There are [many ways](../) |
| 114 | to set that up. For Debian type systems, we primarily recommend |
| 115 | following [our systemd user service guide](service.md). |
| 116 | |
| 117 | Another option would be to customize [the `fslsrv` shell |
| 118 | script](/file/tools/fslsrv) that ships with Fossil as an example of |
| 119 | launching multiple Fossil instances in the background to serve multiple |
| 120 | URLs. |
| 121 | |
| 122 | However you do it, you need to match up the TCP port numbers between it |
| 123 | and those in the nginx configuration below. |
| 124 | |
| 125 | |
| 126 | ## <a name="config"></a>Configuration |
| 127 | |
| 128 |
| --- www/server/debian/nginx.md | |
| +++ www/server/debian/nginx.md | |
| @@ -109,19 +109,15 @@ | |
| 109 | |
| 110 | ## <a name="scgi"></a>Running Fossil in SCGI Mode |
| 111 | |
| 112 | For the following nginx configuration to work, it needs to contact a |
| 113 | Fossil instance speaking the SCGI protocol. There are [many ways](../) |
| 114 | to set that up. For Debian type systems, we recommend |
| 115 | following [our systemd system service guide](service.md). |
| 116 | |
| 117 | There are other ways to arrange for Fossil to run as a service backing |
| 118 | nginx, but however you do it, you need to match up the TCP port numbers between it |
| 119 | and those in the nginx configuration below. |
| 120 | |
| 121 | |
| 122 | ## <a name="config"></a>Configuration |
| 123 | |
| 124 |
+38
-6
| --- www/server/debian/service.md | ||
| +++ www/server/debian/service.md | ||
| @@ -43,17 +43,23 @@ | ||
| 43 | 43 | WantedBy=sockets.target |
| 44 | 44 | WantedBy=multi-user.target |
| 45 | 45 | ``` |
| 46 | 46 | |
| 47 | 47 | Unlike with `inetd` and `xinetd`, we don’t need to tell `systemd` which |
| 48 | -user and group to run this service as, because we’ve installed it as a | |
| 49 | -user service under the account we’re logged into. | |
| 48 | +user and group to run this service as, because we’ve installed it | |
| 49 | +under the account we’re logged into, which `systemd` will use as the | |
| 50 | +service’s owner. | |
| 50 | 51 | |
| 51 | 52 | We’ve told `systemd` that we want automatic service restarts with |
| 52 | 53 | back-off logic, making this much more robust than the by-hand launches |
| 53 | 54 | of `fossil` in the platform-independent Fossil server instructions. The |
| 54 | 55 | service will stay up until we explicitly tell it to shut down. |
| 56 | + | |
| 57 | +A simple and useful modification to the above scheme is to add the | |
| 58 | +`--scgi` and `--localhost` flags to the `ExecStart` line to replace the | |
| 59 | +use of `fslsrv` in [the generic SCGI instructions](../any/scgi.md), | |
| 60 | +giving a much more robust configuration. | |
| 55 | 61 | |
| 56 | 62 | Because we’ve set this up as a user service, the commands you give to |
| 57 | 63 | manipulate the service vary somewhat from the sort you’re more likely to |
| 58 | 64 | find online: |
| 59 | 65 | |
| @@ -69,14 +75,40 @@ | ||
| 69 | 75 | |
| 70 | 76 | This scheme isolates the permissions needed by the Fossil server, which |
| 71 | 77 | reduces the amount of damage it can do if there is ever a |
| 72 | 78 | remotely-triggerable security flaw found in Fossil. |
| 73 | 79 | |
| 74 | -A simple and useful modification to the above scheme is to add the | |
| 75 | -`--scgi` and `--localhost` flags to the `ExecStart` line to replace the | |
| 76 | -use of `fslsrv` in [the generic SCGI instructions](../any/scgi.md), | |
| 77 | -giving a much more robust configuration. | |
| 80 | +On some `systemd` based OSes, user services only run while that user is | |
| 81 | +logged in interactively. This is common on systems aiming to provide | |
| 82 | +desktop environments, where this is the behavior you often want. To | |
| 83 | +allow background services to continue to run after logout, say: | |
| 84 | + | |
| 85 | + $ sudo loginctl enable-linger $USER | |
| 86 | + | |
| 87 | +You can paste the command just like that into your terminal, since | |
| 88 | +`$USER` will expand to your login name. | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | +### System Service Alternative | |
| 93 | + | |
| 94 | +Another workaround for the problem with user services above is to | |
| 95 | +install the service as a system service instead. This is a better path | |
| 96 | +when you are proxying Fossil with a system-level service, such as | |
| 97 | +[nginx](./nginx.md). | |
| 98 | + | |
| 99 | +There are just a small set of changes required: | |
| 100 | + | |
| 101 | +1. Install the unit file to one of the persistent system-level unit | |
| 102 | + file directories. Typically, these are: | |
| 103 | + | |
| 104 | + /etc/systemd/system | |
| 105 | + /lib/systemd/system | |
| 106 | + | |
| 107 | +2. Add `User` and `Group` directives to the `[Service]` section so | |
| 108 | + Fossil runs as a normal user, preferrably one with access only to | |
| 109 | + the Fossil repo files, rather than running as `root`. | |
| 78 | 110 | |
| 79 | 111 | |
| 80 | 112 | ## Socket Activation |
| 81 | 113 | |
| 82 | 114 | Another useful method to serve a Fossil repo via `systemd` is via a |
| 83 | 115 |
| --- www/server/debian/service.md | |
| +++ www/server/debian/service.md | |
| @@ -43,17 +43,23 @@ | |
| 43 | WantedBy=sockets.target |
| 44 | WantedBy=multi-user.target |
| 45 | ``` |
| 46 | |
| 47 | Unlike with `inetd` and `xinetd`, we don’t need to tell `systemd` which |
| 48 | user and group to run this service as, because we’ve installed it as a |
| 49 | user service under the account we’re logged into. |
| 50 | |
| 51 | We’ve told `systemd` that we want automatic service restarts with |
| 52 | back-off logic, making this much more robust than the by-hand launches |
| 53 | of `fossil` in the platform-independent Fossil server instructions. The |
| 54 | service will stay up until we explicitly tell it to shut down. |
| 55 | |
| 56 | Because we’ve set this up as a user service, the commands you give to |
| 57 | manipulate the service vary somewhat from the sort you’re more likely to |
| 58 | find online: |
| 59 | |
| @@ -69,14 +75,40 @@ | |
| 69 | |
| 70 | This scheme isolates the permissions needed by the Fossil server, which |
| 71 | reduces the amount of damage it can do if there is ever a |
| 72 | remotely-triggerable security flaw found in Fossil. |
| 73 | |
| 74 | A simple and useful modification to the above scheme is to add the |
| 75 | `--scgi` and `--localhost` flags to the `ExecStart` line to replace the |
| 76 | use of `fslsrv` in [the generic SCGI instructions](../any/scgi.md), |
| 77 | giving a much more robust configuration. |
| 78 | |
| 79 | |
| 80 | ## Socket Activation |
| 81 | |
| 82 | Another useful method to serve a Fossil repo via `systemd` is via a |
| 83 |
| --- www/server/debian/service.md | |
| +++ www/server/debian/service.md | |
| @@ -43,17 +43,23 @@ | |
| 43 | WantedBy=sockets.target |
| 44 | WantedBy=multi-user.target |
| 45 | ``` |
| 46 | |
| 47 | Unlike with `inetd` and `xinetd`, we don’t need to tell `systemd` which |
| 48 | user and group to run this service as, because we’ve installed it |
| 49 | under the account we’re logged into, which `systemd` will use as the |
| 50 | service’s owner. |
| 51 | |
| 52 | We’ve told `systemd` that we want automatic service restarts with |
| 53 | back-off logic, making this much more robust than the by-hand launches |
| 54 | of `fossil` in the platform-independent Fossil server instructions. The |
| 55 | service will stay up until we explicitly tell it to shut down. |
| 56 | |
| 57 | A simple and useful modification to the above scheme is to add the |
| 58 | `--scgi` and `--localhost` flags to the `ExecStart` line to replace the |
| 59 | use of `fslsrv` in [the generic SCGI instructions](../any/scgi.md), |
| 60 | giving a much more robust configuration. |
| 61 | |
| 62 | Because we’ve set this up as a user service, the commands you give to |
| 63 | manipulate the service vary somewhat from the sort you’re more likely to |
| 64 | find online: |
| 65 | |
| @@ -69,14 +75,40 @@ | |
| 75 | |
| 76 | This scheme isolates the permissions needed by the Fossil server, which |
| 77 | reduces the amount of damage it can do if there is ever a |
| 78 | remotely-triggerable security flaw found in Fossil. |
| 79 | |
| 80 | On some `systemd` based OSes, user services only run while that user is |
| 81 | logged in interactively. This is common on systems aiming to provide |
| 82 | desktop environments, where this is the behavior you often want. To |
| 83 | allow background services to continue to run after logout, say: |
| 84 | |
| 85 | $ sudo loginctl enable-linger $USER |
| 86 | |
| 87 | You can paste the command just like that into your terminal, since |
| 88 | `$USER` will expand to your login name. |
| 89 | |
| 90 | |
| 91 | |
| 92 | ### System Service Alternative |
| 93 | |
| 94 | Another workaround for the problem with user services above is to |
| 95 | install the service as a system service instead. This is a better path |
| 96 | when you are proxying Fossil with a system-level service, such as |
| 97 | [nginx](./nginx.md). |
| 98 | |
| 99 | There are just a small set of changes required: |
| 100 | |
| 101 | 1. Install the unit file to one of the persistent system-level unit |
| 102 | file directories. Typically, these are: |
| 103 | |
| 104 | /etc/systemd/system |
| 105 | /lib/systemd/system |
| 106 | |
| 107 | 2. Add `User` and `Group` directives to the `[Service]` section so |
| 108 | Fossil runs as a normal user, preferrably one with access only to |
| 109 | the Fossil repo files, rather than running as `root`. |
| 110 | |
| 111 | |
| 112 | ## Socket Activation |
| 113 | |
| 114 | Another useful method to serve a Fossil repo via `systemd` is via a |
| 115 |
+25
-34
| --- www/webpage-ex.md | ||
| +++ www/webpage-ex.md | ||
| @@ -2,112 +2,103 @@ | ||
| 2 | 2 | ================= |
| 3 | 3 | |
| 4 | 4 | Here are just a few examples of the many web pages supported |
| 5 | 5 | by Fossil. Follow hyperlinks on the examples below to see many |
| 6 | 6 | other examples. |
| 7 | -<style> | |
| 8 | -.exbtn { | |
| 9 | - border: 1px solid #000; | |
| 10 | - margin: 1ex; | |
| 11 | - border-radius: 1ex; | |
| 12 | - padding: 0 1ex; | |
| 13 | - background-color: #eee; | |
| 14 | -} | |
| 15 | -</style> | |
| 16 | 7 | |
| 17 | 8 | * <a target='_blank' class='exbtn' |
| 18 | - href='$ROOT/timeline?y=ci&n=100'>Example</a> | |
| 9 | + href='$ROOT/timeline?y=ci&n=100'>(Example)</a> → | |
| 19 | 10 | 100 most recent check-ins. |
| 20 | 11 | |
| 21 | 12 | * <a target='_blank' class='exbtn' |
| 22 | - href='$ROOT/finfo?name=src/file.c'>Example</a> | |
| 13 | + href='$ROOT/finfo?name=src/file.c'>(Example)</a> → | |
| 23 | 14 | All changes to the <b>src/file.c</b> source file. |
| 24 | 15 | |
| 25 | 16 | * <a target='_blank' class='exbtn' |
| 26 | - href='$ROOT/timeline?n=200&uf=0c3c2d086a'>Example</a> | |
| 17 | + href='$ROOT/timeline?n=200&uf=0c3c2d086a'>(Example)</a> → | |
| 27 | 18 | All check-ins using a particular version of the <b>src/file.c</b> |
| 28 | 19 | source file. |
| 29 | 20 | |
| 30 | 21 | * <a target='_blank' class='exbtn' |
| 31 | - href='$ROOT/timeline?n=11&y=ci&c=2014-01-01'>Example</a> | |
| 22 | + href='$ROOT/timeline?n=11&y=ci&c=2014-01-01'>(Example)</a> → | |
| 32 | 23 | Check-ins proximate to an historical point in time (2014-01-01). |
| 33 | 24 | |
| 34 | 25 | * <a target='_blank' class='exbtn' |
| 35 | - href='$ROOT/timeline?n=11&y=ci&c=2014-01-01&v=1'>Example</a> | |
| 26 | + href='$ROOT/timeline?n=11&y=ci&c=2014-01-01&v=1'>(Example)</a> → | |
| 36 | 27 | The previous example augmented with file changes. |
| 37 | 28 | |
| 38 | 29 | * <a target='_blank' class='exbtn' |
| 39 | - href='$ROOT/timeline?n=25&y=ci&a=1970-01-01'>Example</a> | |
| 30 | + href='$ROOT/timeline?n=25&y=ci&a=1970-01-01'>(Example)</a> → | |
| 40 | 31 | First 25 check-ins after 1970-01-01. (The first 25 check-ins of |
| 41 | 32 | the project.) |
| 42 | 33 | |
| 43 | 34 | * <a target='_blank' class='exbtn' |
| 44 | - href='$ROOT/timeline?n=200&r=svn-import'>Example</a> | |
| 35 | + href='$ROOT/timeline?n=200&r=svn-import'>(Example)</a> → | |
| 45 | 36 | All check-ins of the "svn-import" branch together with check-ins |
| 46 | 37 | that merge with that branch. |
| 47 | 38 | |
| 48 | 39 | * <a target='_blank' class='exbtn' |
| 49 | - href='$ROOT/timeline?n=200&t=svn-import'>Example</a> | |
| 40 | + href='$ROOT/timeline?n=200&t=svn-import'>(Example)</a> → | |
| 50 | 41 | All check-ins of the "svn-import" branch only. |
| 51 | 42 | |
| 52 | 43 | * <a target='_blank' class='exbtn' |
| 53 | - href='$ROOT/timeline?n=100&y=ci&ubg'>Example</a> | |
| 44 | + href='$ROOT/timeline?n=100&y=ci&ubg'>(Example)</a> → | |
| 54 | 45 | 100 most recent check-ins color coded by committer rather than by branch. |
| 55 | 46 | |
| 56 | 47 | * <a target='_blank' class='exbtn' |
| 57 | - href='$ROOT/timeline?from=version-1.27&to=version-1.28'>Example</a> | |
| 48 | + href='$ROOT/timeline?from=version-1.27&to=version-1.28'>(Example)</a> → | |
| 58 | 49 | All check-ins on the most direct path from |
| 59 | 50 | version-1.27 to version-1.28 |
| 60 | 51 | |
| 61 | 52 | * <a target='_blank' class='exbtn' |
| 62 | - href='$ROOT/timeline?namechng'>Example</a> | |
| 53 | + href='$ROOT/timeline?namechng'>(Example)</a> → | |
| 63 | 54 | Show check-ins that contain file name changes |
| 64 | 55 | |
| 65 | 56 | * <a target='_blank' class='exbtn' |
| 66 | - href='$ROOT/timeline?u=drh&c=2014-01-08&y=ci'>Example</a> | |
| 57 | + href='$ROOT/timeline?u=drh&c=2014-01-08&y=ci'>(Example)</a> → | |
| 67 | 58 | Show check-ins circa 2014-01-08 by user "drh". |
| 68 | 59 | |
| 69 | 60 | * <a target='_blank' class='exbtn' |
| 70 | - href='$ROOT/timeline?from=version-1.34&to=version-1.35&chng=src/timeline.c,src/doc.c'>Example</a> | |
| 61 | + href='$ROOT/timeline?from=version-1.34&to=version-1.35&chng=src/timeline.c,src/doc.c'>(Example)</a> → | |
| 71 | 62 | Show all check-ins between version-1.34 and version-1.35 that make |
| 72 | 63 | changes to either of the files src/timeline.c or src/doc.c. |
| 73 | 64 | |
| 74 | 65 | <big><b>→</b></big> (Hint: In the pages above, click the graph nodes |
| 75 | 66 | for any two check-ins or files to see a diff.) |
| 76 | 67 | <big><b>←</b></big> |
| 77 | 68 | |
| 78 | 69 | * <a target='_blank' class='exbtn' |
| 79 | - href='$ROOT/search?s=interesting+pages'>Example</a> | |
| 70 | + href='$ROOT/search?s=interesting+pages'>(Example)</a> → | |
| 80 | 71 | Full-text search for "interesting pages". |
| 81 | 72 | |
| 82 | 73 | * <a target='_blank' class='exbtn' |
| 83 | - href='$ROOT/tree?ci=daff9d20621&type=tree'>Example</a> | |
| 74 | + href='$ROOT/tree?ci=daff9d20621&type=tree'>(Example)</a> → | |
| 84 | 75 | All files for a particular check-in (daff9d20621480) |
| 85 | 76 | |
| 86 | 77 | * <a target='_blank' class='exbtn' |
| 87 | - href='$ROOT/tree?ci=trunk&type=tree&mtime=1'>Example</a> | |
| 78 | + href='$ROOT/tree?ci=trunk&type=tree&mtime=1'>(Example)</a> → | |
| 88 | 79 | All files for the latest check-in on a branch (trunk) sorted by |
| 89 | 80 | last modification time. |
| 90 | 81 | |
| 91 | 82 | * <a target='_blank' class='exbtn' |
| 92 | - href='$ROOT/fileage?name=svn-import'>Example</a> | |
| 83 | + href='$ROOT/fileage?name=svn-import'>(Example)</a> → | |
| 93 | 84 | Age of all files in the latest checking for branch "svn-import". |
| 94 | 85 | |
| 95 | 86 | * <a target='_blank' class='exbtn' |
| 96 | - href='$ROOT/brlist'>Example</a> | |
| 87 | + href='$ROOT/brlist'>(Example)</a> → | |
| 97 | 88 | Table of branches. (Click on column headers to sort.) |
| 98 | 89 | |
| 99 | 90 | * <a target='_blank' class='exbtn' |
| 100 | - href='$ROOT/stat'>Example</a> | |
| 91 | + href='$ROOT/stat'>(Example)</a> → | |
| 101 | 92 | Overall repository status. |
| 102 | 93 | |
| 103 | 94 | * <a target='_blank' class='exbtn' |
| 104 | - href='$ROOT/reports?type=ci&view=byuser'>Example</a> | |
| 95 | + href='$ROOT/reports?type=ci&view=byuser'>(Example)</a> → | |
| 105 | 96 | Number of check-ins per committer. |
| 106 | 97 | |
| 107 | 98 | * <a target='_blank' class='exbtn' |
| 108 | - href='$ROOT/reports?view=byfile'>Example</a> | |
| 99 | + href='$ROOT/reports?view=byfile'>(Example)</a> → | |
| 109 | 100 | Number of check-ins for each source file. |
| 110 | 101 | (Click on column headers to sort.) |
| 111 | 102 | |
| 112 | 103 | * <a target='_blank' class='exbtn' |
| 113 | 104 | href='$ROOT/blame?checkin=5260fbf63287&filename=src/rss.c&limit=-1'> |
| @@ -114,19 +105,19 @@ | ||
| 114 | 105 | Example</a> |
| 115 | 106 | Most recent change to each line of a particular source file in a |
| 116 | 107 | particular check-in. |
| 117 | 108 | |
| 118 | 109 | * <a target='_blank' class='exbtn' |
| 119 | - href='$ROOT/taglist'>Example</a> | |
| 110 | + href='$ROOT/taglist'>(Example)</a> → | |
| 120 | 111 | List of tags on check-ins. |
| 121 | 112 | |
| 122 | 113 | * <a target='_blank' class='exbtn' |
| 123 | - href='$ROOT/bigbloblist'>Example</a> | |
| 114 | + href='$ROOT/bigbloblist'>(Example)</a> → | |
| 124 | 115 | The largest objects in the repository. |
| 125 | 116 | |
| 126 | 117 | * <a target='_blank' class='exbtn' |
| 127 | - href='$ROOT/hash-collisions'>Example</a> | |
| 118 | + href='$ROOT/hash-collisions'>(Example)</a> → | |
| 128 | 119 | Hash prefix collisions |
| 129 | 120 | |
| 130 | 121 | * <a target='_blank' class='exbtn' |
| 131 | - href='$ROOT/sitemap'>Example</a> | |
| 122 | + href='$ROOT/sitemap'>(Example)</a> → | |
| 132 | 123 | The "sitemap" containing links to many other pages |
| 133 | 124 |
| --- www/webpage-ex.md | |
| +++ www/webpage-ex.md | |
| @@ -2,112 +2,103 @@ | |
| 2 | ================= |
| 3 | |
| 4 | Here are just a few examples of the many web pages supported |
| 5 | by Fossil. Follow hyperlinks on the examples below to see many |
| 6 | other examples. |
| 7 | <style> |
| 8 | .exbtn { |
| 9 | border: 1px solid #000; |
| 10 | margin: 1ex; |
| 11 | border-radius: 1ex; |
| 12 | padding: 0 1ex; |
| 13 | background-color: #eee; |
| 14 | } |
| 15 | </style> |
| 16 | |
| 17 | * <a target='_blank' class='exbtn' |
| 18 | href='$ROOT/timeline?y=ci&n=100'>Example</a> |
| 19 | 100 most recent check-ins. |
| 20 | |
| 21 | * <a target='_blank' class='exbtn' |
| 22 | href='$ROOT/finfo?name=src/file.c'>Example</a> |
| 23 | All changes to the <b>src/file.c</b> source file. |
| 24 | |
| 25 | * <a target='_blank' class='exbtn' |
| 26 | href='$ROOT/timeline?n=200&uf=0c3c2d086a'>Example</a> |
| 27 | All check-ins using a particular version of the <b>src/file.c</b> |
| 28 | source file. |
| 29 | |
| 30 | * <a target='_blank' class='exbtn' |
| 31 | href='$ROOT/timeline?n=11&y=ci&c=2014-01-01'>Example</a> |
| 32 | Check-ins proximate to an historical point in time (2014-01-01). |
| 33 | |
| 34 | * <a target='_blank' class='exbtn' |
| 35 | href='$ROOT/timeline?n=11&y=ci&c=2014-01-01&v=1'>Example</a> |
| 36 | The previous example augmented with file changes. |
| 37 | |
| 38 | * <a target='_blank' class='exbtn' |
| 39 | href='$ROOT/timeline?n=25&y=ci&a=1970-01-01'>Example</a> |
| 40 | First 25 check-ins after 1970-01-01. (The first 25 check-ins of |
| 41 | the project.) |
| 42 | |
| 43 | * <a target='_blank' class='exbtn' |
| 44 | href='$ROOT/timeline?n=200&r=svn-import'>Example</a> |
| 45 | All check-ins of the "svn-import" branch together with check-ins |
| 46 | that merge with that branch. |
| 47 | |
| 48 | * <a target='_blank' class='exbtn' |
| 49 | href='$ROOT/timeline?n=200&t=svn-import'>Example</a> |
| 50 | All check-ins of the "svn-import" branch only. |
| 51 | |
| 52 | * <a target='_blank' class='exbtn' |
| 53 | href='$ROOT/timeline?n=100&y=ci&ubg'>Example</a> |
| 54 | 100 most recent check-ins color coded by committer rather than by branch. |
| 55 | |
| 56 | * <a target='_blank' class='exbtn' |
| 57 | href='$ROOT/timeline?from=version-1.27&to=version-1.28'>Example</a> |
| 58 | All check-ins on the most direct path from |
| 59 | version-1.27 to version-1.28 |
| 60 | |
| 61 | * <a target='_blank' class='exbtn' |
| 62 | href='$ROOT/timeline?namechng'>Example</a> |
| 63 | Show check-ins that contain file name changes |
| 64 | |
| 65 | * <a target='_blank' class='exbtn' |
| 66 | href='$ROOT/timeline?u=drh&c=2014-01-08&y=ci'>Example</a> |
| 67 | Show check-ins circa 2014-01-08 by user "drh". |
| 68 | |
| 69 | * <a target='_blank' class='exbtn' |
| 70 | href='$ROOT/timeline?from=version-1.34&to=version-1.35&chng=src/timeline.c,src/doc.c'>Example</a> |
| 71 | Show all check-ins between version-1.34 and version-1.35 that make |
| 72 | changes to either of the files src/timeline.c or src/doc.c. |
| 73 | |
| 74 | <big><b>→</b></big> (Hint: In the pages above, click the graph nodes |
| 75 | for any two check-ins or files to see a diff.) |
| 76 | <big><b>←</b></big> |
| 77 | |
| 78 | * <a target='_blank' class='exbtn' |
| 79 | href='$ROOT/search?s=interesting+pages'>Example</a> |
| 80 | Full-text search for "interesting pages". |
| 81 | |
| 82 | * <a target='_blank' class='exbtn' |
| 83 | href='$ROOT/tree?ci=daff9d20621&type=tree'>Example</a> |
| 84 | All files for a particular check-in (daff9d20621480) |
| 85 | |
| 86 | * <a target='_blank' class='exbtn' |
| 87 | href='$ROOT/tree?ci=trunk&type=tree&mtime=1'>Example</a> |
| 88 | All files for the latest check-in on a branch (trunk) sorted by |
| 89 | last modification time. |
| 90 | |
| 91 | * <a target='_blank' class='exbtn' |
| 92 | href='$ROOT/fileage?name=svn-import'>Example</a> |
| 93 | Age of all files in the latest checking for branch "svn-import". |
| 94 | |
| 95 | * <a target='_blank' class='exbtn' |
| 96 | href='$ROOT/brlist'>Example</a> |
| 97 | Table of branches. (Click on column headers to sort.) |
| 98 | |
| 99 | * <a target='_blank' class='exbtn' |
| 100 | href='$ROOT/stat'>Example</a> |
| 101 | Overall repository status. |
| 102 | |
| 103 | * <a target='_blank' class='exbtn' |
| 104 | href='$ROOT/reports?type=ci&view=byuser'>Example</a> |
| 105 | Number of check-ins per committer. |
| 106 | |
| 107 | * <a target='_blank' class='exbtn' |
| 108 | href='$ROOT/reports?view=byfile'>Example</a> |
| 109 | Number of check-ins for each source file. |
| 110 | (Click on column headers to sort.) |
| 111 | |
| 112 | * <a target='_blank' class='exbtn' |
| 113 | href='$ROOT/blame?checkin=5260fbf63287&filename=src/rss.c&limit=-1'> |
| @@ -114,19 +105,19 @@ | |
| 114 | Example</a> |
| 115 | Most recent change to each line of a particular source file in a |
| 116 | particular check-in. |
| 117 | |
| 118 | * <a target='_blank' class='exbtn' |
| 119 | href='$ROOT/taglist'>Example</a> |
| 120 | List of tags on check-ins. |
| 121 | |
| 122 | * <a target='_blank' class='exbtn' |
| 123 | href='$ROOT/bigbloblist'>Example</a> |
| 124 | The largest objects in the repository. |
| 125 | |
| 126 | * <a target='_blank' class='exbtn' |
| 127 | href='$ROOT/hash-collisions'>Example</a> |
| 128 | Hash prefix collisions |
| 129 | |
| 130 | * <a target='_blank' class='exbtn' |
| 131 | href='$ROOT/sitemap'>Example</a> |
| 132 | The "sitemap" containing links to many other pages |
| 133 |
| --- www/webpage-ex.md | |
| +++ www/webpage-ex.md | |
| @@ -2,112 +2,103 @@ | |
| 2 | ================= |
| 3 | |
| 4 | Here are just a few examples of the many web pages supported |
| 5 | by Fossil. Follow hyperlinks on the examples below to see many |
| 6 | other examples. |
| 7 | |
| 8 | * <a target='_blank' class='exbtn' |
| 9 | href='$ROOT/timeline?y=ci&n=100'>(Example)</a> → |
| 10 | 100 most recent check-ins. |
| 11 | |
| 12 | * <a target='_blank' class='exbtn' |
| 13 | href='$ROOT/finfo?name=src/file.c'>(Example)</a> → |
| 14 | All changes to the <b>src/file.c</b> source file. |
| 15 | |
| 16 | * <a target='_blank' class='exbtn' |
| 17 | href='$ROOT/timeline?n=200&uf=0c3c2d086a'>(Example)</a> → |
| 18 | All check-ins using a particular version of the <b>src/file.c</b> |
| 19 | source file. |
| 20 | |
| 21 | * <a target='_blank' class='exbtn' |
| 22 | href='$ROOT/timeline?n=11&y=ci&c=2014-01-01'>(Example)</a> → |
| 23 | Check-ins proximate to an historical point in time (2014-01-01). |
| 24 | |
| 25 | * <a target='_blank' class='exbtn' |
| 26 | href='$ROOT/timeline?n=11&y=ci&c=2014-01-01&v=1'>(Example)</a> → |
| 27 | The previous example augmented with file changes. |
| 28 | |
| 29 | * <a target='_blank' class='exbtn' |
| 30 | href='$ROOT/timeline?n=25&y=ci&a=1970-01-01'>(Example)</a> → |
| 31 | First 25 check-ins after 1970-01-01. (The first 25 check-ins of |
| 32 | the project.) |
| 33 | |
| 34 | * <a target='_blank' class='exbtn' |
| 35 | href='$ROOT/timeline?n=200&r=svn-import'>(Example)</a> → |
| 36 | All check-ins of the "svn-import" branch together with check-ins |
| 37 | that merge with that branch. |
| 38 | |
| 39 | * <a target='_blank' class='exbtn' |
| 40 | href='$ROOT/timeline?n=200&t=svn-import'>(Example)</a> → |
| 41 | All check-ins of the "svn-import" branch only. |
| 42 | |
| 43 | * <a target='_blank' class='exbtn' |
| 44 | href='$ROOT/timeline?n=100&y=ci&ubg'>(Example)</a> → |
| 45 | 100 most recent check-ins color coded by committer rather than by branch. |
| 46 | |
| 47 | * <a target='_blank' class='exbtn' |
| 48 | href='$ROOT/timeline?from=version-1.27&to=version-1.28'>(Example)</a> → |
| 49 | All check-ins on the most direct path from |
| 50 | version-1.27 to version-1.28 |
| 51 | |
| 52 | * <a target='_blank' class='exbtn' |
| 53 | href='$ROOT/timeline?namechng'>(Example)</a> → |
| 54 | Show check-ins that contain file name changes |
| 55 | |
| 56 | * <a target='_blank' class='exbtn' |
| 57 | href='$ROOT/timeline?u=drh&c=2014-01-08&y=ci'>(Example)</a> → |
| 58 | Show check-ins circa 2014-01-08 by user "drh". |
| 59 | |
| 60 | * <a target='_blank' class='exbtn' |
| 61 | href='$ROOT/timeline?from=version-1.34&to=version-1.35&chng=src/timeline.c,src/doc.c'>(Example)</a> → |
| 62 | Show all check-ins between version-1.34 and version-1.35 that make |
| 63 | changes to either of the files src/timeline.c or src/doc.c. |
| 64 | |
| 65 | <big><b>→</b></big> (Hint: In the pages above, click the graph nodes |
| 66 | for any two check-ins or files to see a diff.) |
| 67 | <big><b>←</b></big> |
| 68 | |
| 69 | * <a target='_blank' class='exbtn' |
| 70 | href='$ROOT/search?s=interesting+pages'>(Example)</a> → |
| 71 | Full-text search for "interesting pages". |
| 72 | |
| 73 | * <a target='_blank' class='exbtn' |
| 74 | href='$ROOT/tree?ci=daff9d20621&type=tree'>(Example)</a> → |
| 75 | All files for a particular check-in (daff9d20621480) |
| 76 | |
| 77 | * <a target='_blank' class='exbtn' |
| 78 | href='$ROOT/tree?ci=trunk&type=tree&mtime=1'>(Example)</a> → |
| 79 | All files for the latest check-in on a branch (trunk) sorted by |
| 80 | last modification time. |
| 81 | |
| 82 | * <a target='_blank' class='exbtn' |
| 83 | href='$ROOT/fileage?name=svn-import'>(Example)</a> → |
| 84 | Age of all files in the latest checking for branch "svn-import". |
| 85 | |
| 86 | * <a target='_blank' class='exbtn' |
| 87 | href='$ROOT/brlist'>(Example)</a> → |
| 88 | Table of branches. (Click on column headers to sort.) |
| 89 | |
| 90 | * <a target='_blank' class='exbtn' |
| 91 | href='$ROOT/stat'>(Example)</a> → |
| 92 | Overall repository status. |
| 93 | |
| 94 | * <a target='_blank' class='exbtn' |
| 95 | href='$ROOT/reports?type=ci&view=byuser'>(Example)</a> → |
| 96 | Number of check-ins per committer. |
| 97 | |
| 98 | * <a target='_blank' class='exbtn' |
| 99 | href='$ROOT/reports?view=byfile'>(Example)</a> → |
| 100 | Number of check-ins for each source file. |
| 101 | (Click on column headers to sort.) |
| 102 | |
| 103 | * <a target='_blank' class='exbtn' |
| 104 | href='$ROOT/blame?checkin=5260fbf63287&filename=src/rss.c&limit=-1'> |
| @@ -114,19 +105,19 @@ | |
| 105 | Example</a> |
| 106 | Most recent change to each line of a particular source file in a |
| 107 | particular check-in. |
| 108 | |
| 109 | * <a target='_blank' class='exbtn' |
| 110 | href='$ROOT/taglist'>(Example)</a> → |
| 111 | List of tags on check-ins. |
| 112 | |
| 113 | * <a target='_blank' class='exbtn' |
| 114 | href='$ROOT/bigbloblist'>(Example)</a> → |
| 115 | The largest objects in the repository. |
| 116 | |
| 117 | * <a target='_blank' class='exbtn' |
| 118 | href='$ROOT/hash-collisions'>(Example)</a> → |
| 119 | Hash prefix collisions |
| 120 | |
| 121 | * <a target='_blank' class='exbtn' |
| 122 | href='$ROOT/sitemap'>(Example)</a> → |
| 123 | The "sitemap" containing links to many other pages |
| 124 |