Overview
SHA1 Hash: | 488afb97461a34ae63ac2a1f5e8b018e68466686 |
---|---|
Date: | 2007-10-06 17:10:47 |
User: | drh |
Comment: | Enforce well-formedness constraints on wiki pagenames. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/manifest.c from [fb34bded33] to [d51cf77a0b].
@@ -370,10 +370,13 @@ if( p->zWikiTitle!=0 ) goto manifest_syntax_error; if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; p->zWikiTitle = blob_terminate(&a1); defossilize(p->zWikiTitle); + if( !wiki_name_is_wellformed(p->zWikiTitle) ){ + goto manifest_syntax_error; + } break; } /* ** M <uuid>
Modified src/wiki.c from [1ab1276742] to [22c7d6d4bb].
@@ -25,10 +25,53 @@ */ #include <assert.h> #include "config.h" #include "wiki.h" +/* +** Return true if the input string is a well-formed wiki page name. +** +** Well-formed wiki page names do not begin or end with whitespace, +** and do not contain tabs or other control characters and do not +** contain more than a single space character in a row. Well-formed +** names must be between 3 and 100 chracters in length, inclusive. +*/ +int wiki_name_is_wellformed(const char *z){ + int i; + if( z[0]<=0x20 ){ + return 0; + } + for(i=1; z[i]; i++){ + if( z[i]<0x20 ) return 0; + if( z[i]==0x20 && z[i-1]==0x20 ) return 0; + } + if( z[i-1]==' ' ) return 0; + if( i<3 || i>100 ) return 0; + return 1; +} + +/* +** Check a wiki name. If it is not well-formed, then issue an error +** and return true. If it is well-formed, return false. +*/ +static int check_name(const char *z){ + if( !wiki_name_is_wellformed(z) ){ + style_header("Wiki Page Name Error"); + @ The wiki name "<b>%h(z)</b>" is not well-formed. Rules for + @ wiki page names: + @ <ul> + @ <li> Must not begin or end with a space. + @ <li> Must not contain any control characters, including tab or + @ newline. + @ <li> Must not have two or more spaces in a row internally. + @ <li> Must be between 3 and 100 characters in length. + @ </ul> + style_footer(); + return 1; + } + return 0; +} /* ** WEBPAGE: wiki ** URL: /wiki/PAGENAME */ @@ -43,10 +86,11 @@ login_check_credentials(); if( !g.okRdWiki ){ login_needed(); return; } zPageName = mprintf("%s", g.zExtra); dehttpize(zPageName); + if( check_name(zPageName) ) return; zTag = mprintf("wiki-%s", zPageName); rid = db_int(0, "SELECT rid FROM tagxref" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " ORDER BY mtime DESC", zTag @@ -66,11 +110,11 @@ style_header(zHtmlPageName); blob_init(&wiki, zBody, -1); wiki_convert(&wiki, 0); blob_reset(&wiki); manifest_clear(&m); - if( zPageName[0] && ((rid && g.okWrWiki) || (!rid && g.okNewWiki)) ){ + if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){ @ <hr> @ [<a href="%s(g.zBaseURL)/wikiedit/%s(g.zExtra)">Edit</a>] } style_footer(); } @@ -94,10 +138,11 @@ zBody = mprintf("%s", zBody); } login_check_credentials(); zPageName = mprintf("%s", g.zExtra); dehttpize(zPageName); + if( check_name(zPageName) ) return; zTag = mprintf("wiki-%s", zPageName); rid = db_int(0, "SELECT rid FROM tagxref" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " ORDER BY mtime DESC", zTag @@ -146,11 +191,11 @@ blob_reset(&wiki); content_deltify(rid, nrid, 0); db_end_transaction(0); cgi_redirect(mprintf("wiki/%s", g.zExtra)); } - if( P("cancel")!=0 || zPageName[0]==0 ){ + if( P("cancel")!=0 ){ cgi_redirect(mprintf("wiki/%s", g.zExtra)); return; } if( zBody==0 ){ zBody = mprintf("<i>Empty Page</i>");
Modified src/wikiformat.c from [6d7f89510a] to [83901f90e7].
@@ -760,12 +760,14 @@ || strncmp(zTarget, "https:", 6)==0 || strncmp(zTarget, "ftp:", 4)==0 || strncmp(zTarget, "mailto:", 7)==0 ){ blob_appendf(p->pOut, zTarget); - }else{ + }else if( wiki_name_is_wellformed(zTarget) ){ blob_appendf(p->pOut, "%s/wiki/%T", g.zBaseURL, zTarget); + }else{ + blob_appendf(p->pOut, "error"); } } /* ** Check to see if the given parsed markup is the correct @@ -862,18 +864,19 @@ break; } case TOKEN_LINK: { char *zTarget; char *zDisplay = 0; - int i; + int i, j; int savedState; addMissingMarkup(p); zTarget = &z[1]; for(i=1; z[i] && z[i]!=']'; i++){ if( z[i]=='|' && zDisplay==0 ){ zDisplay = &z[i+1]; z[i] = 0; + for(j=i-1; j>0 && isspace(z[j]); j--){ z[j] = 0; } } } z[i] = 0; if( zDisplay==0 ){ zDisplay = zTarget;