@@ -2396,5 +2396,179 @@
2396 2396 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_reset(&in);
2397 2397 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fossil_puts(blob_str(&out), 0);
2398 2398 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_reset(&out);
2399 2399 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
2400 2400 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
2401 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2402 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
2403 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** An instance of this object keeps track of the nesting of HTML
2404 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** elements for blob_append_safe_html().
2405 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
2406 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #if LOCAL_INTERFACE
2407 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ struct HtmlTagStack {
2408 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int n; /* Current tag stack depth */
2409 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int nAlloc; /* Space allocated for aStack[] */
2410 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int *aStack; /* The stack of tags */
2411 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int aSpace[10]; /* Initial static space, to avoid malloc() */
2412 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ };
2413 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #endif /* LOCAL_INTERFACE */
2414 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2415 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
2416 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Initialize bulk memory to a valid empty tagstack.
2417 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
2418 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void html_tagstack_init(HtmlTagStack *p){
2419 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->n = 0;
2420 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->nAlloc = 0;
2421 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->aStack = p->aSpace;
2422 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2423 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2424 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
2425 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Push a new element onto the tag statk
2426 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
2427 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void html_tagstack_push(HtmlTagStack *p, int e){
2428 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( p->n>=ArraySize(p->aSpace) && p->n>=p->nAlloc ){
2429 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( p->nAlloc==0 ){
2430 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int *aNew;
2431 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->nAlloc = 50;
2432 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ aNew = fossil_malloc( sizeof(p->aStack[0])*p->nAlloc );
2433 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ memcpy(aNew, p->aStack, sizeof(p->aStack[0])*p->n );
2434 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->aStack = aNew;
2435 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
2436 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->nAlloc *= 2;
2437 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->aStack = fossil_realloc(p->aStack, sizeof(p->aStack[0])*p->nAlloc );
2438 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2439 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2440 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->aStack[p->n++] = e;
2441 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2442 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2443 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
2444 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Clear a tag stack, reclaiming any memory allocations.
2445 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
2446 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void html_tagstack_clear(HtmlTagStack *p){
2447 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( p->nAlloc ){
2448 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(p->aStack);
2449 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->nAlloc = 0;
2450 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->aStack = p->aSpace;
2451 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2452 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->n = 0;
2453 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2454 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2455 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
2456 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** The HTML end-tag eEnd wants to be added to pBlob.
2457 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2458 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If an open-tag for eEnd exists anywhere on the stack, then
2459 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** pop it and all prior elements from the task, issuing appropriate
2460 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** end-tags as you go.
2461 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2462 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If there is no open-tag for eEnd on the stack, then this
2463 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** routine is a no-op.
2464 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
2465 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void html_tagstack_pop(HtmlTagStack *p, Blob *pBlob, int eEnd){
2466 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int i;
2467 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(i=p->n-1; i>=0 && p->aStack[i]!=eEnd; i--){}
2468 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( i<0 ) return;
2469 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ do{
2470 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ p->n--;
2471 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_appendf(pBlob, "</%s>", aMarkup[eEnd].zName);
2472 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }while( p->aStack[p->n]!=eEnd );
2473 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2474 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2475 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
2476 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Append HTML text to a Blob object. The appended text is modified
2477 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** changed in the following ways:
2478 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2479 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** 1. Omit any elements that are not on the AllowedMarkup list.
2480 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2481 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** 2. Omit any attributes that are not on the AllowedMarkup list.
2482 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2483 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** 3. Omit any surplus close-tags.
2484 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2485 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** 4. Insert additional close-tags as necessary so that all
2486 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** non-empty tags in the input have a corresponding close tag.
2487 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Non-empty tags are elements other than <br>, <hr>, <img>, etc.
2488 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2489 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** The input must be writable. Temporary changes may be made to the
2490 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** input, but the input is restored to its original state prior to
2491 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** returning. If zHtml[nHtml] is not a zero character, then a zero
2492 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** might be written in that position temporarily, but that slot will
2493 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** also be restored before this routine returns.
2494 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
2495 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void blob_append_safe_html(Blob *pBlob, char *zHtml, int nHtml){
2496 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char cLast;
2497 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int i, j, n;
2498 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ HtmlTagStack s;
2499 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ParsedMarkup markup;
2500 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cLast = zHtml[nHtml];
2501 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zHtml[nHtml] = 0;
2502 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ html_tagstack_init(&s);
2503 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2504 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ i = 0;
2505 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while( i<nHtml ){
2506 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zHtml[i]=='<' ){
2507 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ j = i;
2508 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
2509 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *z = strchr(zHtml+i, '<');
2510 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( z==0 ){
2511 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(pBlob, zHtml+i, nHtml-i);
2512 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
2513 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2514 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ j = (int)(z - zHtml);
2515 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(pBlob, zHtml+i, j-i);
2516 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2517 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ n = html_tag_length(zHtml+j);
2518 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( n==0 ){
2519 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(pBlob, "<", 4);
2520 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ i = j+1;
2521 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ continue;
2522 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
2523 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ i = j + n;
2524 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2525 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ parseMarkup(&markup, zHtml+j);
2526 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( markup.iCode!=MARKUP_INVALID ){
2527 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( markup.endTag ){
2528 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ html_tagstack_pop(&s, pBlob, markup.iCode);
2529 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
2530 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ renderMarkup(pBlob, &markup);
2531 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( markup.iType!=MUTYPE_SINGLE ){
2532 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ html_tagstack_push(&s, markup.iCode);
2533 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2534 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2535 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2536 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ unparseMarkup(&markup);
2537 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2538 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while( s.n>0 ){
2539 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ s.n--;
2540 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_appendf(pBlob, "</%s>", aMarkup[s.aStack[s.n]]);
2541 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2542 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ html_tagstack_clear(&s);
2543 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zHtml[nHtml] = cLast;
2544 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2545 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2546 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2547 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
2548 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** COMMAND: test-safe-html
2549 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2550 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Usage: %fossil test-safe-html FILE ...
2551 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2552 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Read files named on the command-line. Send the text of each file
2553 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** through blob_append_safe_html() and then write the result on
2554 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** standard output.
2555 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
2556 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void test_safe_html_cmd(void){
2557 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int i;
2558 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Blob x;
2559 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Blob y;
2560 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(i=2; i<g.argc; i++){
2561 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *z;
2562 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int n;
2563 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_read_from_file(&x, g.argv[i], ExtFILE);
2564 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_init(&y, 0, 0);
2565 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_terminate(&x);
2566 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_safe_html(&y, blob_buffer(&x), blob_size(&x));
2567 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_reset(&x);
2568 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ z = blob_str(&y);
2569 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ n = blob_size(&y);
2570 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while( n>0 && (z[n-1]=='\n' || z[n-1]=='\r') ) n--;
2571 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_print("%.*s\n", n, z);
2572 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_reset(&y);
2573 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2574 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2401 2575 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!