@@ -51,8 +51,21 @@
return 1;
}
/*
+** Output rules for well-formed wiki pages
+*/
+static void well_formed_wiki_name_rules(void){
+ @ <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>
+}
+
+/*
** 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){
@@ -59,15 +72,9 @@
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>
+ well_formed_wiki_name_rules();
style_footer();
return 1;
}
return 0;
@@ -120,9 +127,8 @@
int isSandbox;
Blob wiki;
Manifest m;
const char *zPageName;
- char *zHtmlPageName;
char *zBody = mprintf("%s","<i>Empty Page</i>");
login_check_credentials();
if( !g.okRdWiki ){ login_needed(); return; }
@@ -131,10 +137,10 @@
style_header("Wiki");
@ <ul>
{ char *zHomePageName = db_get("project-name",0);
if( zHomePageName ){
- @ <li> <a href="%s(g.zBaseURL)/wiki?name=%s(zHomePageName)">
- @ %s(zHomePageName)</a> wiki home page.</li>
+ @ <li> <a href="%s(g.zBaseURL)/wiki?name=%t(zHomePageName)">
+ @ %h(zHomePageName)</a> wiki home page.</li>
}
}
@ <li> <a href="%s(g.zBaseURL)/timeline?y=w">Recent changes</a> to wiki
@ pages. </li>
@@ -141,8 +147,11 @@
@ <li> <a href="%s(g.zBaseURL)/wiki_rules">Formatting rules</a> for
@ wiki.</li>
@ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a>
@ to experiment.</li>
+ if( g.okNewWiki ){
+ @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li>
+ }
@ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a>
@ available on this server.</li>
@ </ul>
style_footer();
@@ -184,10 +193,9 @@
style_submenu_element("History", "History", "%s/whistory?name=%T",
g.zTop, zPageName);
}
}
- zHtmlPageName = mprintf("%h", zPageName);
- style_header(zHtmlPageName);
+ style_header(zPageName);
blob_init(&wiki, zBody, -1);
wiki_convert(&wiki, 0, 0);
blob_reset(&wiki);
if( !isSandbox ){
@@ -292,9 +300,9 @@
}
if( zBody==0 ){
zBody = mprintf("<i>Empty Page</i>");
}
- zHtmlPageName = mprintf("Edit: %h", zPageName);
+ zHtmlPageName = mprintf("Edit: %s", zPageName);
style_header(zHtmlPageName);
if( P("preview")!=0 ){
blob_zero(&wiki);
blob_append(&wiki, zBody, -1);
@@ -322,8 +330,43 @@
manifest_clear(&m);
}
style_footer();
}
+
+/*
+** WEBPAGE: wikinew
+** URL /wikinew
+**
+** Prompt the user to enter the name of a new wiki page. Then redirect
+** to the wikiedit screen for that new page.
+*/
+void wikinew_page(void){
+ const char *zName;
+ login_check_credentials();
+ if( !g.okNewWiki ){
+ login_needed();
+ return;
+ }
+ zName = PD("name","");
+ if( zName[0] && wiki_name_is_wellformed(zName) ){
+ cgi_redirectf("wikiedit?name=%T", zName);
+ }
+ style_header("Create A New Wiki Page");
+ @ <p>Rules for wiki page names:
+ well_formed_wiki_name_rules();
+ @ </p>
+ @ <form method="POST" action="%s(g.zBaseURL)/wikinew">
+ @ <p>Name of new wiki page:
+ @ <input type="text" width="35" name="name" value="%h(zName)">
+ @ <input type="submit" value="Create">
+ @ </p></form>
+ if( zName[0] ){
+ @ <p><b><font color="red">
+ @ "%h(zName)" is not a valid wiki page name!</font></b></p>
+ }
+ style_footer();
+}
+
/*
** Append the wiki text for an remark to the end of the given BLOB.
*/
@@ -433,9 +476,9 @@
if( P("cancel")!=0 ){
cgi_redirectf("wiki?name=%T", zPageName);
return;
}
- zHtmlPageName = mprintf("Append Comment To: %h", zPageName);
+ zHtmlPageName = mprintf("Append Comment To: %s", zPageName);
style_header(zHtmlPageName);
if( P("preview")!=0 ){
Blob preview;
blob_zero(&preview);
@@ -462,8 +505,21 @@
style_footer();
}
/*
+** Name of the wiki history page being generated
+*/
+static const char *zWikiPageName;
+
+/*
+** Function called to output extra text at the end of each line in
+** a wiki history listing.
+*/
+static void wiki_history_extra(int rid){
+ @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a>
+}
+
+/*
** WEBPAGE: whistory
** URL: /whistory?name=PAGENAME
**
** Show the complete change history for a single wiki page.
@@ -475,9 +531,9 @@
const char *zPageName;
login_check_credentials();
if( !g.okHistory ){ login_needed(); return; }
zPageName = PD("name","");
- zTitle = mprintf("History Of %h", zPageName);
+ zTitle = mprintf("History Of %s", zPageName);
style_header(zTitle);
free(zTitle);
zSQL = mprintf("%s AND event.objid IN "
@@ -486,10 +542,64 @@
"ORDER BY mtime DESC",
timeline_query_for_www(), zPageName);
db_prepare(&q, zSQL);
free(zSQL);
- www_print_timeline(&q, TIMELINE_ARTID, 0);
+ zWikiPageName = zPageName;
+ www_print_timeline(&q, TIMELINE_ARTID, wiki_history_extra);
db_finalize(&q);
+ style_footer();
+}
+
+/*
+** WEBPAGE: wdiff
+** URL: /whistory?name=PAGENAME&a=RID1&b=RID2
+**
+** Show the difference between two wiki pages.
+*/
+void wdiff_page(void){
+ char *zTitle;
+ int rid1, rid2;
+ const char *zPageName;
+ Blob content1, content2;
+ Manifest m1, m2;
+ Blob w1, w2, d;
+
+ login_check_credentials();
+ rid1 = atoi(PD("a","0"));
+ if( !g.okHistory ){ login_needed(); return; }
+ if( rid1==0 ) fossil_redirect_home();
+ rid2 = atoi(PD("b","0"));
+ zPageName = PD("name","");
+ zTitle = mprintf("Changes To %s", zPageName);
+ style_header(zTitle);
+ free(zTitle);
+
+ if( rid2==0 ){
+ rid2 = db_int(0,
+ "SELECT objid FROM event JOIN tagxref ON objid=rid AND tagxref.tagid="
+ "(SELECT tagid FROM tag WHERE tagname='wiki-%q')"
+ " WHERE event.mtime<(SELECT mtime FROM event WHERE objid=%d)"
+ " ORDER BY event.mtime DESC LIMIT 1",
+ zPageName, rid1
+ );
+ }
+ content_get(rid1, &content1);
+ manifest_parse(&m1, &content1);
+ if( m1.type!=CFTYPE_WIKI ) fossil_redirect_home();
+ blob_init(&w1, m1.zWiki, -1);
+ blob_zero(&w2);
+ if( rid2 ){
+ content_get(rid2, &content2);
+ manifest_parse(&m2, &content2);
+ if( m2.type==CFTYPE_WIKI ){
+ blob_init(&w2, m2.zWiki, -1);
+ }
+ }
+ blob_zero(&d);
+ text_diff(&w2, &w1, &d, 5);
+ @ <pre>
+ @ %h(blob_str(&d))
+ @ </pre>
style_footer();
}
/*
@@ -692,9 +802,9 @@
** COMMAND: wiki
**
** Usage: %fossil wiki (export|create|commit|list) WikiName
**
-** Run various subcommands to fetch wiki entries.
+** Run various subcommands to work with wiki entries.
**
** %fossil wiki export PAGENAME ?FILE?
**
** Sends the latest version of the PAGENAME wiki
@@ -701,9 +811,10 @@
** entry to the given file or standard output.
**
** %fossil wiki commit PAGENAME ?FILE?
**
-** Commit changes to a wiki page from FILE or from standard.
+** Commit changes to a wiki page from FILE or from standard
+** input.
**
** %fossil wiki create PAGENAME ?FILE?
**
** Create a new wiki page with initial content taken from