Fossil

Diff
Login

Differences From Artifact [d50aed7ed0]:

To Artifact [0cf6abf3c7]:


29
30
31
32
33
34
35

36
37
38
39
40
41
42
#define WIKI_INLINE         0x002  /* Do not surround with <p>..</p> */
#define WIKI_NOBLOCK        0x004  /* No block markup of any kind */
#define WIKI_BUTTONS        0x008  /* Allow sub-menu buttons */
#define WIKI_NOBADLINKS     0x010  /* Ignore broken hyperlinks */
#define WIKI_LINKSONLY      0x020  /* No markup.  Only decorate links */
#define WIKI_NEWLINE        0x040  /* Honor \n - break lines at each \n */
#define WIKI_MARKDOWNLINKS  0x080  /* Resolve hyperlinks as in markdown */

#endif


/*
** These are the only markup attributes allowed.
*/
enum allowed_attr_t {







>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#define WIKI_INLINE         0x002  /* Do not surround with <p>..</p> */
#define WIKI_NOBLOCK        0x004  /* No block markup of any kind */
#define WIKI_BUTTONS        0x008  /* Allow sub-menu buttons */
#define WIKI_NOBADLINKS     0x010  /* Ignore broken hyperlinks */
#define WIKI_LINKSONLY      0x020  /* No markup.  Only decorate links */
#define WIKI_NEWLINE        0x040  /* Honor \n - break lines at each \n */
#define WIKI_MARKDOWNLINKS  0x080  /* Resolve hyperlinks as in markdown */
#define WIKI_SAFE           0x100  /* Make the result safe for embedding */
#endif


/*
** These are the only markup attributes allowed.
*/
enum allowed_attr_t {
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
*/
void wiki_convert(Blob *pIn, Blob *pOut, int flags){
  Renderer renderer;

  memset(&renderer, 0, sizeof(renderer));
  renderer.renderFlags = flags;
  renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH|flags;
  if( flags & WIKI_NOBLOCK ){
    renderer.state |= INLINE_MARKUP_ONLY;
  }
  if( flags & WIKI_INLINE ){
    renderer.wantAutoParagraph = 0;
  }else{
    renderer.wantAutoParagraph = 1;
  }
  if( wikiUsesHtml() ){
    renderer.state |= WIKI_HTMLONLY;







<
<
<







1743
1744
1745
1746
1747
1748
1749



1750
1751
1752
1753
1754
1755
1756
*/
void wiki_convert(Blob *pIn, Blob *pOut, int flags){
  Renderer renderer;

  memset(&renderer, 0, sizeof(renderer));
  renderer.renderFlags = flags;
  renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH|flags;



  if( flags & WIKI_INLINE ){
    renderer.wantAutoParagraph = 0;
  }else{
    renderer.wantAutoParagraph = 1;
  }
  if( wikiUsesHtml() ){
    renderer.state |= WIKI_HTMLONLY;
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834

1835
1836
1837
1838
1839
1840
1841
** Options:
**
**    --safe           Do "safe-html" rendering.
*/
void test_markdown_render(void){
  Blob in, out;
  int i;

  db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
  if( find_option("safe",0,0)!=0 ){
    safe_html_enable(1);
  }
  verify_all_options();
  for(i=2; i<g.argc; i++){
    blob_zero(&out);
    blob_read_from_file(&in, g.argv[i], ExtFILE);
    if( g.argc>3 ){
      fossil_print("<!------ %h ------->\n", g.argv[i]);
    }
    markdown_to_html(&in, 0, &out);

    blob_write_to_file(&out, "-");
    blob_reset(&in);
    blob_reset(&out);
  }
}

/*







>

|
<
<








>







1814
1815
1816
1817
1818
1819
1820
1821
1822
1823


1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
** Options:
**
**    --safe           Do "safe-html" rendering.
*/
void test_markdown_render(void){
  Blob in, out;
  int i;
  int bSafe = 0;
  db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
  bSafe = find_option("safe",0,0)!=0;


  verify_all_options();
  for(i=2; i<g.argc; i++){
    blob_zero(&out);
    blob_read_from_file(&in, g.argv[i], ExtFILE);
    if( g.argc>3 ){
      fossil_print("<!------ %h ------->\n", g.argv[i]);
    }
    markdown_to_html(&in, 0, &out);
    if( bSafe ) safe_html(&out);
    blob_write_to_file(&out, "-");
    blob_reset(&in);
    blob_reset(&out);
  }
}

/*
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
    e = p->aStack[--p->n];
    if( e==eEnd || (aMarkup[e].iType & MUTYPE_Nested)!=0 ){
      blob_appendf(pBlob, "</%s>", aMarkup[e].zName);
    }
  }while( e!=eEnd && p->n>0 );
}

/*
** Enable or disable the "safe-html" feature.  When enabled, the
** HTML generated by Markdown is adjusted so that it cannot cause
** problems when embedded in a larger document.
*/
static int safeHtml = 0;
void safe_html_enable(int v){
  safeHtml = v;
}

/*
** Append HTML text to a Blob object.
**
** If safe-html is enabled then the appended text is modified
** changed in the following ways:
**
**    1.  Omit any elements that are not on the AllowedMarkup list.







<
<
<
<
<
<
<
<
<
<







2505
2506
2507
2508
2509
2510
2511










2512
2513
2514
2515
2516
2517
2518
    e = p->aStack[--p->n];
    if( e==eEnd || (aMarkup[e].iType & MUTYPE_Nested)!=0 ){
      blob_appendf(pBlob, "</%s>", aMarkup[e].zName);
    }
  }while( e!=eEnd && p->n>0 );
}











/*
** Append HTML text to a Blob object.
**
** If safe-html is enabled then the appended text is modified
** changed in the following ways:
**
**    1.  Omit any elements that are not on the AllowedMarkup list.
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
void safe_html_append(Blob *pBlob, char *zHtml, int nHtml){
  char cLast;
  int i, j, n;
  HtmlTagStack s;
  ParsedMarkup markup;

  if( nHtml<=0 ) return;
  if( !safeHtml ){
    blob_append(pBlob, zHtml, nHtml);
    return;
  }
  cLast = zHtml[nHtml];
  zHtml[nHtml] = 0;
  html_tagstack_init(&s);

  i = 0;
  while( i<nHtml ){
    if( zHtml[i]=='<' ){







<
<
<
<







2539
2540
2541
2542
2543
2544
2545




2546
2547
2548
2549
2550
2551
2552
void safe_html_append(Blob *pBlob, char *zHtml, int nHtml){
  char cLast;
  int i, j, n;
  HtmlTagStack s;
  ParsedMarkup markup;

  if( nHtml<=0 ) return;




  cLast = zHtml[nHtml];
  zHtml[nHtml] = 0;
  html_tagstack_init(&s);

  i = 0;
  while( i<nHtml ){
    if( zHtml[i]=='<' ){
2584
2585
2586
2587
2588
2589
2590


2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
































2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
    }else{
      i = j + n;
    }
    parseMarkup(&markup, zHtml+j);
    if( markup.iCode==MARKUP_INVALID ){
      blob_appendf(pBlob, "<span class='error'>&lt;%.*s&gt;</span>",
                   n-2, zHtml+j+1);


    }else{
      if( markup.endTag ){
        html_tagstack_pop(&s, pBlob, markup.iCode);
      }else{
        renderMarkup(pBlob, &markup);
        html_tagstack_push(&s, markup.iCode);
      }
    }
    unparseMarkup(&markup);
  }
  html_tagstack_pop(&s, pBlob, 0);
  html_tagstack_clear(&s);
  zHtml[nHtml] = cLast;
}


































/*
** COMMAND: test-safe-html
**
** Usage: %fossil test-safe-html FILE ...
**
** Read files named on the command-line.  Send the text of each file
** through safe_html_append() and then write the result on
** standard output.
*/
void test_safe_html_cmd(void){
  int i;
  Blob x;
  Blob y;
  for(i=2; i<g.argc; i++){
    char *z;
    int n;
    blob_read_from_file(&x, g.argv[i], ExtFILE);
    blob_init(&y, 0, 0);
    blob_terminate(&x);
    safe_html_append(&y, blob_buffer(&x), blob_size(&x));
    blob_reset(&x);
    z = blob_str(&y);
    n = blob_size(&y);
    while( n>0 && (z[n-1]=='\n' || z[n-1]=='\r') ) n--;
    fossil_print("%.*s\n", n, z);
    blob_reset(&y);
  }
}







>
>















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













<




<

|
<
|
|


|


2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636

2637
2638
2639
2640

2641
2642

2643
2644
2645
2646
2647
2648
2649
    }else{
      i = j + n;
    }
    parseMarkup(&markup, zHtml+j);
    if( markup.iCode==MARKUP_INVALID ){
      blob_appendf(pBlob, "<span class='error'>&lt;%.*s&gt;</span>",
                   n-2, zHtml+j+1);
    }else if( (markup.iType & MUTYPE_Nested)==0 || markup.iCode==MARKUP_P ){
      renderMarkup(pBlob, &markup);
    }else{
      if( markup.endTag ){
        html_tagstack_pop(&s, pBlob, markup.iCode);
      }else{
        renderMarkup(pBlob, &markup);
        html_tagstack_push(&s, markup.iCode);
      }
    }
    unparseMarkup(&markup);
  }
  html_tagstack_pop(&s, pBlob, 0);
  html_tagstack_clear(&s);
  zHtml[nHtml] = cLast;
}

/*
** The input blob consists of HTML.  Convert it into "safe HTML".  Safe
** HTML has no potentially disruptive elements (ex: <script>, <style>)
** and it is embeddable, meaning that it won't close any outer elements
** from the script in which it is embedded, nor will it leave any open
** elements to affect the tail of the outer script.
*/
void safe_html(Blob *in){
  Blob out;
  char *z = blob_str(in);
  int n = blob_size(in);
  int k;
  blob_init(&out, 0, 0);
  while( fossil_isspace(z[0]) ){ z++; n--; }
  for(k=n-1; k>5 && fossil_isspace(z[k]); k--){}

  if( fossil_strnicmp(z, "<div",4)==0 && !fossil_isalpha(z[4])
   && fossil_strnicmp(z+k-5, "</div>",6)==0
  ){
    /* The input contains an outer <div>...</div>.  Preserve the
    ** full scope of that <div>. */
    int m = html_tag_length(z);
    k -= 5;
    blob_append(&out, z, m);
    safe_html_append(&out, z+m, k-m);
    blob_append(&out, z+k, n-k);
  }else{
    safe_html_append(&out, z, n);
  }
  blob_reset(in);
  *in = out;
}

/*
** COMMAND: test-safe-html
**
** Usage: %fossil test-safe-html FILE ...
**
** Read files named on the command-line.  Send the text of each file
** through safe_html_append() and then write the result on
** standard output.
*/
void test_safe_html_cmd(void){
  int i;
  Blob x;

  for(i=2; i<g.argc; i++){
    char *z;
    int n;
    blob_read_from_file(&x, g.argv[i], ExtFILE);

    blob_terminate(&x);
    safe_html(&x);

    z = blob_str(&x);
    n = blob_size(&x);
    while( n>0 && (z[n-1]=='\n' || z[n-1]=='\r') ) n--;
    fossil_print("%.*s\n", n, z);
    blob_reset(&x);
  }
}