Fossil SCM
Correctly render the title of embedded Markdown documents that contain characters that are special to HTML: > " ' & <
Commit
0b24a45f49f9abbad03c794f25cc52b85ee1c2daba5e749b509963a6479d28ee
Parent
29831c2b1602512…
2 files changed
+1
+57
+1
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -807,10 +807,11 @@ | ||
| 807 | 807 | }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 808 | 808 | Blob tail = BLOB_INITIALIZER; |
| 809 | 809 | markdown_to_html(pBody, &title, &tail); |
| 810 | 810 | if( !isPopup ){ |
| 811 | 811 | if( blob_size(&title)>0 ){ |
| 812 | + markdown_dehtmlize_blob(&title); | |
| 812 | 813 | style_header("%s", blob_str(&title)); |
| 813 | 814 | }else{ |
| 814 | 815 | style_header("%s", zDefaultTitle); |
| 815 | 816 | } |
| 816 | 817 | } |
| 817 | 818 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -807,10 +807,11 @@ | |
| 807 | }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 808 | Blob tail = BLOB_INITIALIZER; |
| 809 | markdown_to_html(pBody, &title, &tail); |
| 810 | if( !isPopup ){ |
| 811 | if( blob_size(&title)>0 ){ |
| 812 | style_header("%s", blob_str(&title)); |
| 813 | }else{ |
| 814 | style_header("%s", zDefaultTitle); |
| 815 | } |
| 816 | } |
| 817 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -807,10 +807,11 @@ | |
| 807 | }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 808 | Blob tail = BLOB_INITIALIZER; |
| 809 | markdown_to_html(pBody, &title, &tail); |
| 810 | if( !isPopup ){ |
| 811 | if( blob_size(&title)>0 ){ |
| 812 | markdown_dehtmlize_blob(&title); |
| 813 | style_header("%s", blob_str(&title)); |
| 814 | }else{ |
| 815 | style_header("%s", zDefaultTitle); |
| 816 | } |
| 817 | } |
| 818 |
+57
| --- src/markdown_html.c | ||
| +++ src/markdown_html.c | ||
| @@ -911,5 +911,62 @@ | ||
| 911 | 911 | html_renderer.opaque = &context; |
| 912 | 912 | if( output_title ) blob_reset(output_title); |
| 913 | 913 | blob_reset(output_body); |
| 914 | 914 | markdown(output_body, input_markdown, &html_renderer); |
| 915 | 915 | } |
| 916 | + | |
| 917 | +/* | |
| 918 | +** Undo HTML escapes in Blob p. In other words convert: | |
| 919 | +** | |
| 920 | +** & -> & | |
| 921 | +** < -> < | |
| 922 | +** > -> > | |
| 923 | +** " -> " | |
| 924 | +** &#NNN; -> ascii character NNN | |
| 925 | +*/ | |
| 926 | +void markdown_dehtmlize_blob(Blob *p){ | |
| 927 | + char *z; | |
| 928 | + unsigned int j, k; | |
| 929 | + | |
| 930 | + z = p->aData; | |
| 931 | + for(j=k=0; j<p->nUsed; j++){ | |
| 932 | + char c = z[j]; | |
| 933 | + if( c=='&' ){ | |
| 934 | + if( z[j+1]=='#' && fossil_isdigit(z[j+2]) ){ | |
| 935 | + int n = 3; | |
| 936 | + int x = z[j+2] - '0'; | |
| 937 | + if( fossil_isdigit(z[j+3]) ){ | |
| 938 | + x = x*10 + z[j+3] - '0'; | |
| 939 | + n++; | |
| 940 | + if( fossil_isdigit(z[j+4]) ){ | |
| 941 | + x = x*10 + z[j+4] - '0'; | |
| 942 | + n++; | |
| 943 | + } | |
| 944 | + } | |
| 945 | + if( z[j+n]==';' ){ | |
| 946 | + z[k++] = (char)x; | |
| 947 | + j += n; | |
| 948 | + }else{ | |
| 949 | + z[k++] = c; | |
| 950 | + } | |
| 951 | + }else if( memcmp(&z[j],"<",4)==0 ){ | |
| 952 | + z[k++] = '<'; | |
| 953 | + j += 3; | |
| 954 | + }else if( memcmp(&z[j],">",4)==0 ){ | |
| 955 | + z[k++] = '>'; | |
| 956 | + j += 3; | |
| 957 | + }else if( memcmp(&z[j],""",6)==0 ){ | |
| 958 | + z[k++] = '"'; | |
| 959 | + j += 5; | |
| 960 | + }else if( memcmp(&z[j],"&",5)==0 ){ | |
| 961 | + z[k++] = '&'; | |
| 962 | + j += 4; | |
| 963 | + }else{ | |
| 964 | + z[k++] = c; | |
| 965 | + } | |
| 966 | + }else{ | |
| 967 | + z[k++] = c; | |
| 968 | + } | |
| 969 | + } | |
| 970 | + z[k] = 0; | |
| 971 | + p->nUsed = k; | |
| 972 | +} | |
| 916 | 973 |
| --- src/markdown_html.c | |
| +++ src/markdown_html.c | |
| @@ -911,5 +911,62 @@ | |
| 911 | html_renderer.opaque = &context; |
| 912 | if( output_title ) blob_reset(output_title); |
| 913 | blob_reset(output_body); |
| 914 | markdown(output_body, input_markdown, &html_renderer); |
| 915 | } |
| 916 |
| --- src/markdown_html.c | |
| +++ src/markdown_html.c | |
| @@ -911,5 +911,62 @@ | |
| 911 | html_renderer.opaque = &context; |
| 912 | if( output_title ) blob_reset(output_title); |
| 913 | blob_reset(output_body); |
| 914 | markdown(output_body, input_markdown, &html_renderer); |
| 915 | } |
| 916 | |
| 917 | /* |
| 918 | ** Undo HTML escapes in Blob p. In other words convert: |
| 919 | ** |
| 920 | ** & -> & |
| 921 | ** < -> < |
| 922 | ** > -> > |
| 923 | ** " -> " |
| 924 | ** &#NNN; -> ascii character NNN |
| 925 | */ |
| 926 | void markdown_dehtmlize_blob(Blob *p){ |
| 927 | char *z; |
| 928 | unsigned int j, k; |
| 929 | |
| 930 | z = p->aData; |
| 931 | for(j=k=0; j<p->nUsed; j++){ |
| 932 | char c = z[j]; |
| 933 | if( c=='&' ){ |
| 934 | if( z[j+1]=='#' && fossil_isdigit(z[j+2]) ){ |
| 935 | int n = 3; |
| 936 | int x = z[j+2] - '0'; |
| 937 | if( fossil_isdigit(z[j+3]) ){ |
| 938 | x = x*10 + z[j+3] - '0'; |
| 939 | n++; |
| 940 | if( fossil_isdigit(z[j+4]) ){ |
| 941 | x = x*10 + z[j+4] - '0'; |
| 942 | n++; |
| 943 | } |
| 944 | } |
| 945 | if( z[j+n]==';' ){ |
| 946 | z[k++] = (char)x; |
| 947 | j += n; |
| 948 | }else{ |
| 949 | z[k++] = c; |
| 950 | } |
| 951 | }else if( memcmp(&z[j],"<",4)==0 ){ |
| 952 | z[k++] = '<'; |
| 953 | j += 3; |
| 954 | }else if( memcmp(&z[j],">",4)==0 ){ |
| 955 | z[k++] = '>'; |
| 956 | j += 3; |
| 957 | }else if( memcmp(&z[j],""",6)==0 ){ |
| 958 | z[k++] = '"'; |
| 959 | j += 5; |
| 960 | }else if( memcmp(&z[j],"&",5)==0 ){ |
| 961 | z[k++] = '&'; |
| 962 | j += 4; |
| 963 | }else{ |
| 964 | z[k++] = c; |
| 965 | } |
| 966 | }else{ |
| 967 | z[k++] = c; |
| 968 | } |
| 969 | } |
| 970 | z[k] = 0; |
| 971 | p->nUsed = k; |
| 972 | } |
| 973 |