dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Copyright (c) 2007 D. Richard Hipp dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is free software; you can redistribute it and/or dbda8d6ce9 2007-07-21 drh: ** modify it under the terms of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License version 2 as published by the Free Software Foundation. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is distributed in the hope that it will be useful, dbda8d6ce9 2007-07-21 drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of dbda8d6ce9 2007-07-21 drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dbda8d6ce9 2007-07-21 drh: ** General Public License for more details. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** You should have received a copy of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License along with this library; if not, write to the dbda8d6ce9 2007-07-21 drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, dbda8d6ce9 2007-07-21 drh: ** Boston, MA 02111-1307, USA. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Author contact information: dbda8d6ce9 2007-07-21 drh: ** drh@hwaci.com dbda8d6ce9 2007-07-21 drh: ** http://www.hwaci.com/drh/ dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ******************************************************************************* dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This file contains code to do formatting of wiki text. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include <assert.h> dbda8d6ce9 2007-07-21 drh: #include "config.h" dbda8d6ce9 2007-07-21 drh: #include "wiki.h" dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* 488afb9746 2007-10-06 drh: ** Return true if the input string is a well-formed wiki page name. dbda8d6ce9 2007-07-21 drh: ** 488afb9746 2007-10-06 drh: ** Well-formed wiki page names do not begin or end with whitespace, 488afb9746 2007-10-06 drh: ** and do not contain tabs or other control characters and do not 488afb9746 2007-10-06 drh: ** contain more than a single space character in a row. Well-formed 488afb9746 2007-10-06 drh: ** names must be between 3 and 100 chracters in length, inclusive. 488afb9746 2007-10-06 drh: */ 488afb9746 2007-10-06 drh: int wiki_name_is_wellformed(const char *z){ 488afb9746 2007-10-06 drh: int i; 488afb9746 2007-10-06 drh: if( z[0]<=0x20 ){ 488afb9746 2007-10-06 drh: return 0; 488afb9746 2007-10-06 drh: } 488afb9746 2007-10-06 drh: for(i=1; z[i]; i++){ 488afb9746 2007-10-06 drh: if( z[i]<0x20 ) return 0; 488afb9746 2007-10-06 drh: if( z[i]==0x20 && z[i-1]==0x20 ) return 0; 488afb9746 2007-10-06 drh: } 488afb9746 2007-10-06 drh: if( z[i-1]==' ' ) return 0; 488afb9746 2007-10-06 drh: if( i<3 || i>100 ) return 0; 488afb9746 2007-10-06 drh: return 1; 488afb9746 2007-10-06 drh: } b2e55c0d4d 2007-09-01 drh: b2e55c0d4d 2007-09-01 drh: /* 488afb9746 2007-10-06 drh: ** Check a wiki name. If it is not well-formed, then issue an error 488afb9746 2007-10-06 drh: ** and return true. If it is well-formed, return false. b2e55c0d4d 2007-09-01 drh: */ 488afb9746 2007-10-06 drh: static int check_name(const char *z){ 488afb9746 2007-10-06 drh: if( !wiki_name_is_wellformed(z) ){ 488afb9746 2007-10-06 drh: style_header("Wiki Page Name Error"); 488afb9746 2007-10-06 drh: @ The wiki name "<b>%h(z)</b>" is not well-formed. Rules for 488afb9746 2007-10-06 drh: @ wiki page names: 488afb9746 2007-10-06 drh: @ <ul> 488afb9746 2007-10-06 drh: @ <li> Must not begin or end with a space. 488afb9746 2007-10-06 drh: @ <li> Must not contain any control characters, including tab or 488afb9746 2007-10-06 drh: @ newline. 488afb9746 2007-10-06 drh: @ <li> Must not have two or more spaces in a row internally. 488afb9746 2007-10-06 drh: @ <li> Must be between 3 and 100 characters in length. 488afb9746 2007-10-06 drh: @ </ul> 488afb9746 2007-10-06 drh: style_footer(); 488afb9746 2007-10-06 drh: return 1; 488afb9746 2007-10-06 drh: } 488afb9746 2007-10-06 drh: return 0; b2e55c0d4d 2007-09-01 drh: } b2e55c0d4d 2007-09-01 drh: b2e55c0d4d 2007-09-01 drh: /* 50a58adb76 2007-10-10 drh: ** WEBPAGE: home 50a58adb76 2007-10-10 drh: ** WEBPAGE: index 50a58adb76 2007-10-10 drh: ** WEBPAGE: not_found b2e55c0d4d 2007-09-01 drh: */ 50a58adb76 2007-10-10 drh: void home_page(void){ 50a58adb76 2007-10-10 drh: char *zPageName = db_get("project-name",0); 50a58adb76 2007-10-10 drh: if( zPageName ){ 50a58adb76 2007-10-10 drh: login_check_credentials(); 50a58adb76 2007-10-10 drh: g.zExtra = zPageName; 50a58adb76 2007-10-10 drh: g.okRdWiki = 1; 50a58adb76 2007-10-10 drh: g.okApndWiki = 0; 50a58adb76 2007-10-10 drh: g.okWrWiki = 0; 50a58adb76 2007-10-10 drh: g.okHistory = 0; 50a58adb76 2007-10-10 drh: wiki_page(); 50a58adb76 2007-10-10 drh: return; 50a58adb76 2007-10-10 drh: } 50a58adb76 2007-10-10 drh: style_header("Home"); 50a58adb76 2007-10-10 drh: @ <p>This is a stub home-page for the project. 50a58adb76 2007-10-10 drh: @ To fill in this page, first go to 50a58adb76 2007-10-10 drh: @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a> 50a58adb76 2007-10-10 drh: @ and establish a "Project Name". Then create a 50a58adb76 2007-10-10 drh: @ wiki page with that name. The content of that wiki page 50a58adb76 2007-10-10 drh: @ will be displayed in place of this message. b2e55c0d4d 2007-09-01 drh: style_footer(); b2e55c0d4d 2007-09-01 drh: } b2e55c0d4d 2007-09-01 drh: b2e55c0d4d 2007-09-01 drh: /* b2e55c0d4d 2007-09-01 drh: ** WEBPAGE: wiki b2e55c0d4d 2007-09-01 drh: ** URL: /wiki/PAGENAME dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void wiki_page(void){ bf428e6854 2007-10-06 drh: char *zTag; bf428e6854 2007-10-06 drh: int rid; bf428e6854 2007-10-06 drh: Blob wiki; bf428e6854 2007-10-06 drh: Manifest m; bf428e6854 2007-10-06 drh: char *zPageName; bf428e6854 2007-10-06 drh: char *zHtmlPageName; bf428e6854 2007-10-06 drh: char *zBody = mprintf("%s","<i>Empty Page</i>"); bf428e6854 2007-10-06 drh: b2e55c0d4d 2007-09-01 drh: login_check_credentials(); b2e55c0d4d 2007-09-01 drh: if( !g.okRdWiki ){ login_needed(); return; } bf428e6854 2007-10-06 drh: zPageName = mprintf("%s", g.zExtra); bf428e6854 2007-10-06 drh: dehttpize(zPageName); 488afb9746 2007-10-06 drh: if( check_name(zPageName) ) return; bf428e6854 2007-10-06 drh: zTag = mprintf("wiki-%s", zPageName); bf428e6854 2007-10-06 drh: rid = db_int(0, bf428e6854 2007-10-06 drh: "SELECT rid FROM tagxref" bf428e6854 2007-10-06 drh: " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" bf428e6854 2007-10-06 drh: " ORDER BY mtime DESC", zTag bf428e6854 2007-10-06 drh: ); bf428e6854 2007-10-06 drh: free(zTag); bf428e6854 2007-10-06 drh: memset(&m, 0, sizeof(m)); bf428e6854 2007-10-06 drh: blob_zero(&m.content); b2e55c0d4d 2007-09-01 drh: if( rid ){ bf428e6854 2007-10-06 drh: Blob content; bf428e6854 2007-10-06 drh: content_get(rid, &content); bf428e6854 2007-10-06 drh: manifest_parse(&m, &content); bf428e6854 2007-10-06 drh: if( m.type==CFTYPE_WIKI ){ bf428e6854 2007-10-06 drh: zBody = m.zWiki; bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: } 50a58adb76 2007-10-10 drh: if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){ 50a58adb76 2007-10-10 drh: style_submenu_element("Edit", "Edit Wiki Page", 61ce5e3685 2007-10-10 drh: mprintf("%s/wikiedit/%s", g.zTop, g.zExtra)); 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: if( rid && g.okApndWiki ){ 61ce5e3685 2007-10-10 drh: style_submenu_element("Append", "Add A Comment", 61ce5e3685 2007-10-10 drh: mprintf("%s/wikiappend/%s", g.zTop, g.zExtra)); 50a58adb76 2007-10-10 drh: } 50a58adb76 2007-10-10 drh: if( g.okHistory ){ 50a58adb76 2007-10-10 drh: style_submenu_element("History", "History", 50a58adb76 2007-10-10 drh: mprintf("%s/whistory/%s", g.zTop, g.zExtra)); 50a58adb76 2007-10-10 drh: } bf428e6854 2007-10-06 drh: zHtmlPageName = mprintf("%h", zPageName); bf428e6854 2007-10-06 drh: style_header(zHtmlPageName); bf428e6854 2007-10-06 drh: blob_init(&wiki, zBody, -1); bf428e6854 2007-10-06 drh: wiki_convert(&wiki, 0); bf428e6854 2007-10-06 drh: blob_reset(&wiki); bf428e6854 2007-10-06 drh: manifest_clear(&m); bf428e6854 2007-10-06 drh: style_footer(); bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: bf428e6854 2007-10-06 drh: /* bf428e6854 2007-10-06 drh: ** WEBPAGE: wikiedit bf428e6854 2007-10-06 drh: ** URL: /wikiedit/PAGENAME bf428e6854 2007-10-06 drh: */ bf428e6854 2007-10-06 drh: void wikiedit_page(void){ bf428e6854 2007-10-06 drh: char *zTag; bf428e6854 2007-10-06 drh: int rid; bf428e6854 2007-10-06 drh: Blob wiki; bf428e6854 2007-10-06 drh: Manifest m; bf428e6854 2007-10-06 drh: char *zPageName; bf428e6854 2007-10-06 drh: char *zHtmlPageName; bf428e6854 2007-10-06 drh: int n; bf428e6854 2007-10-06 drh: const char *z; bf428e6854 2007-10-06 drh: char *zBody = (char*)P("w"); bf428e6854 2007-10-06 drh: bf428e6854 2007-10-06 drh: if( zBody ){ bf428e6854 2007-10-06 drh: zBody = mprintf("%s", zBody); bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: login_check_credentials(); bf428e6854 2007-10-06 drh: zPageName = mprintf("%s", g.zExtra); bf428e6854 2007-10-06 drh: dehttpize(zPageName); 488afb9746 2007-10-06 drh: if( check_name(zPageName) ) return; bf428e6854 2007-10-06 drh: zTag = mprintf("wiki-%s", zPageName); bf428e6854 2007-10-06 drh: rid = db_int(0, bf428e6854 2007-10-06 drh: "SELECT rid FROM tagxref" bf428e6854 2007-10-06 drh: " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" bf428e6854 2007-10-06 drh: " ORDER BY mtime DESC", zTag bf428e6854 2007-10-06 drh: ); bf428e6854 2007-10-06 drh: free(zTag); bf428e6854 2007-10-06 drh: if( (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){ bf428e6854 2007-10-06 drh: login_needed(); bf428e6854 2007-10-06 drh: return; bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: memset(&m, 0, sizeof(m)); bf428e6854 2007-10-06 drh: blob_zero(&m.content); bf428e6854 2007-10-06 drh: if( rid && zBody==0 ){ bf428e6854 2007-10-06 drh: Blob content; bf428e6854 2007-10-06 drh: content_get(rid, &content); bf428e6854 2007-10-06 drh: manifest_parse(&m, &content); bf428e6854 2007-10-06 drh: if( m.type==CFTYPE_WIKI ){ bf428e6854 2007-10-06 drh: zBody = m.zWiki; bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: if( P("submit")!=0 && zBody!=0 ){ bf428e6854 2007-10-06 drh: char *zDate; bf428e6854 2007-10-06 drh: Blob cksum; bf428e6854 2007-10-06 drh: int nrid; bf428e6854 2007-10-06 drh: blob_zero(&wiki); bf428e6854 2007-10-06 drh: db_begin_transaction(); bf428e6854 2007-10-06 drh: zDate = db_text(0, "SELECT datetime('now')"); bf428e6854 2007-10-06 drh: zDate[10] = 'T'; bf428e6854 2007-10-06 drh: blob_appendf(&wiki, "D %s\n", zDate); bf428e6854 2007-10-06 drh: free(zDate); bf428e6854 2007-10-06 drh: blob_appendf(&wiki, "L %F\n", zPageName); bf428e6854 2007-10-06 drh: if( rid ){ bf428e6854 2007-10-06 drh: char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); bf428e6854 2007-10-06 drh: blob_appendf(&wiki, "P %s\n", zUuid); bf428e6854 2007-10-06 drh: free(zUuid); bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: if( g.zLogin ){ bf428e6854 2007-10-06 drh: blob_appendf(&wiki, "U %F\n", g.zLogin); bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: blob_appendf(&wiki, "W %d\n%s\n", strlen(zBody), zBody); bf428e6854 2007-10-06 drh: md5sum_blob(&wiki, &cksum); bf428e6854 2007-10-06 drh: blob_appendf(&wiki, "Z %b\n", &cksum); bf428e6854 2007-10-06 drh: blob_reset(&cksum); bf428e6854 2007-10-06 drh: nrid = content_put(&wiki, 0, 0); bf428e6854 2007-10-06 drh: db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); bf428e6854 2007-10-06 drh: manifest_crosslink(nrid, &wiki); bf428e6854 2007-10-06 drh: blob_reset(&wiki); bf428e6854 2007-10-06 drh: content_deltify(rid, nrid, 0); bf428e6854 2007-10-06 drh: db_end_transaction(0); bf428e6854 2007-10-06 drh: cgi_redirect(mprintf("wiki/%s", g.zExtra)); bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: if( P("cancel")!=0 ){ bf428e6854 2007-10-06 drh: cgi_redirect(mprintf("wiki/%s", g.zExtra)); bf428e6854 2007-10-06 drh: return; bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: if( zBody==0 ){ bf428e6854 2007-10-06 drh: zBody = mprintf("<i>Empty Page</i>"); bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: zHtmlPageName = mprintf("Edit: %h", zPageName); bf428e6854 2007-10-06 drh: style_header(zHtmlPageName); bf428e6854 2007-10-06 drh: if( P("preview")!=0 ){ bf428e6854 2007-10-06 drh: blob_zero(&wiki); bf428e6854 2007-10-06 drh: blob_append(&wiki, zBody, -1); bf428e6854 2007-10-06 drh: @ Preview:<hr> bf428e6854 2007-10-06 drh: wiki_convert(&wiki, 0); bf428e6854 2007-10-06 drh: @ <hr> bf428e6854 2007-10-06 drh: blob_reset(&wiki); bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: for(n=2, z=zBody; z[0]; z++){ bf428e6854 2007-10-06 drh: if( z[0]=='\n' ) n++; bf428e6854 2007-10-06 drh: } bf428e6854 2007-10-06 drh: if( n<20 ) n = 20; bf428e6854 2007-10-06 drh: if( n>200 ) n = 200; 9f89a8e68e 2007-10-10 drh: @ <form method="POST" action="%s(g.zBaseURL)/wikiedit/%t(g.zExtra)"> bf428e6854 2007-10-06 drh: @ <textarea name="w" class="wikiedit" cols="80" bf428e6854 2007-10-06 drh: @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> bf428e6854 2007-10-06 drh: @ <br> bf428e6854 2007-10-06 drh: @ <input type="submit" name="preview" value="Preview Your Changes"> bf428e6854 2007-10-06 drh: @ <input type="submit" name="submit" value="Apply These Changes"> bf428e6854 2007-10-06 drh: @ <input type="submit" name="cancel" value="Cancel"> bf428e6854 2007-10-06 drh: @ </form> bf428e6854 2007-10-06 drh: manifest_clear(&m); bf428e6854 2007-10-06 drh: style_footer(); 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: 61ce5e3685 2007-10-10 drh: /* 61ce5e3685 2007-10-10 drh: ** Append the wiki text for an remark to the end of the given BLOB. 61ce5e3685 2007-10-10 drh: */ 61ce5e3685 2007-10-10 drh: static void appendRemark(Blob *p){ 61ce5e3685 2007-10-10 drh: char *zDate; 61ce5e3685 2007-10-10 drh: const char *zUser; 61ce5e3685 2007-10-10 drh: const char *zRemark; 61ce5e3685 2007-10-10 drh: 61ce5e3685 2007-10-10 drh: zDate = db_text(0, "SELECT datetime('now')"); 61ce5e3685 2007-10-10 drh: blob_appendf(p, "On %s UTC %h", zDate, g.zLogin); 61ce5e3685 2007-10-10 drh: free(zDate); 61ce5e3685 2007-10-10 drh: zUser = PD("u",g.zLogin); 61ce5e3685 2007-10-10 drh: if( zUser[0] && strcmp(zUser,g.zLogin) ){ 61ce5e3685 2007-10-10 drh: blob_appendf(p, " (claiming to be %h)", zUser); 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: zRemark = PD("r",""); 61ce5e3685 2007-10-10 drh: blob_appendf(p, " added:\n\n%s", zRemark); 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: 61ce5e3685 2007-10-10 drh: /* 61ce5e3685 2007-10-10 drh: ** WEBPAGE: wikiappend 61ce5e3685 2007-10-10 drh: ** URL: /wikiappend/PAGENAME 61ce5e3685 2007-10-10 drh: */ 61ce5e3685 2007-10-10 drh: void wikiappend_page(void){ 61ce5e3685 2007-10-10 drh: char *zTag; 61ce5e3685 2007-10-10 drh: int rid; 61ce5e3685 2007-10-10 drh: char *zPageName; 61ce5e3685 2007-10-10 drh: char *zHtmlPageName; 61ce5e3685 2007-10-10 drh: const char *zUser; 61ce5e3685 2007-10-10 drh: 61ce5e3685 2007-10-10 drh: login_check_credentials(); 61ce5e3685 2007-10-10 drh: zPageName = mprintf("%s", g.zExtra); 61ce5e3685 2007-10-10 drh: dehttpize(zPageName); 61ce5e3685 2007-10-10 drh: if( check_name(zPageName) ) return; 61ce5e3685 2007-10-10 drh: zTag = mprintf("wiki-%s", zPageName); 61ce5e3685 2007-10-10 drh: rid = db_int(0, 61ce5e3685 2007-10-10 drh: "SELECT rid FROM tagxref" 61ce5e3685 2007-10-10 drh: " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" 61ce5e3685 2007-10-10 drh: " ORDER BY mtime DESC", zTag 61ce5e3685 2007-10-10 drh: ); 61ce5e3685 2007-10-10 drh: free(zTag); 61ce5e3685 2007-10-10 drh: if( !rid ){ 61ce5e3685 2007-10-10 drh: cgi_redirect("index"); 61ce5e3685 2007-10-10 drh: return; 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: if( !g.okApndWiki ){ 61ce5e3685 2007-10-10 drh: login_needed(); 61ce5e3685 2007-10-10 drh: return; 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: if( P("submit")!=0 && P("r")!=0 && P("u")!=0 ){ 61ce5e3685 2007-10-10 drh: char *zDate; 61ce5e3685 2007-10-10 drh: Blob cksum; 61ce5e3685 2007-10-10 drh: int nrid; 61ce5e3685 2007-10-10 drh: Blob body; 61ce5e3685 2007-10-10 drh: Blob content; 61ce5e3685 2007-10-10 drh: Blob wiki; 61ce5e3685 2007-10-10 drh: Manifest m; 50a58adb76 2007-10-10 drh: 61ce5e3685 2007-10-10 drh: content_get(rid, &content); 61ce5e3685 2007-10-10 drh: manifest_parse(&m, &content); 61ce5e3685 2007-10-10 drh: blob_zero(&body); 61ce5e3685 2007-10-10 drh: if( m.type==CFTYPE_WIKI ){ 61ce5e3685 2007-10-10 drh: blob_appendf(&body, m.zWiki, -1); 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: manifest_clear(&m); 61ce5e3685 2007-10-10 drh: blob_zero(&wiki); 61ce5e3685 2007-10-10 drh: db_begin_transaction(); 61ce5e3685 2007-10-10 drh: zDate = db_text(0, "SELECT datetime('now')"); 61ce5e3685 2007-10-10 drh: zDate[10] = 'T'; 61ce5e3685 2007-10-10 drh: blob_appendf(&wiki, "D %s\n", zDate); 61ce5e3685 2007-10-10 drh: blob_appendf(&wiki, "L %F\n", zPageName); 61ce5e3685 2007-10-10 drh: if( rid ){ 61ce5e3685 2007-10-10 drh: char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); 61ce5e3685 2007-10-10 drh: blob_appendf(&wiki, "P %s\n", zUuid); 61ce5e3685 2007-10-10 drh: free(zUuid); 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: if( g.zLogin ){ 61ce5e3685 2007-10-10 drh: blob_appendf(&wiki, "U %F\n", g.zLogin); 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: blob_appendf(&body, "\n<hr>\n"); 61ce5e3685 2007-10-10 drh: appendRemark(&body); 61ce5e3685 2007-10-10 drh: blob_appendf(&wiki, "W %d\n%s\n", blob_size(&body), blob_str(&body)); 61ce5e3685 2007-10-10 drh: md5sum_blob(&wiki, &cksum); 61ce5e3685 2007-10-10 drh: blob_appendf(&wiki, "Z %b\n", &cksum); 61ce5e3685 2007-10-10 drh: blob_reset(&cksum); 61ce5e3685 2007-10-10 drh: nrid = content_put(&wiki, 0, 0); 61ce5e3685 2007-10-10 drh: db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); 61ce5e3685 2007-10-10 drh: manifest_crosslink(nrid, &wiki); 61ce5e3685 2007-10-10 drh: blob_reset(&wiki); 61ce5e3685 2007-10-10 drh: content_deltify(rid, nrid, 0); 61ce5e3685 2007-10-10 drh: db_end_transaction(0); 61ce5e3685 2007-10-10 drh: cgi_redirect(mprintf("wiki/%s", g.zExtra)); 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: if( P("cancel")!=0 ){ 61ce5e3685 2007-10-10 drh: cgi_redirect(mprintf("wiki/%s", g.zExtra)); 61ce5e3685 2007-10-10 drh: return; 61ce5e3685 2007-10-10 drh: } 61ce5e3685 2007-10-10 drh: zHtmlPageName = mprintf("Append Comment To: %h", zPageName); 61ce5e3685 2007-10-10 drh: style_header(zHtmlPageName); 61ce5e3685 2007-10-10 drh: if( P("preview")!=0 ){ 61ce5e3685 2007-10-10 drh: Blob preview; 61ce5e3685 2007-10-10 drh: blob_zero(&preview); 61ce5e3685 2007-10-10 drh: appendRemark(&preview); 61ce5e3685 2007-10-10 drh: @ Preview:<hr> 61ce5e3685 2007-10-10 drh: wiki_convert(&preview, 0); 61ce5e3685 2007-10-10 drh: @ <hr> 61ce5e3685 2007-10-10 drh: blob_reset(&preview); b2e55c0d4d 2007-09-01 drh: } 61ce5e3685 2007-10-10 drh: zUser = PD("u", g.zLogin); 61ce5e3685 2007-10-10 drh: @ <form method="POST" action="%s(g.zBaseURL)/wikiappend/%t(g.zExtra)"> 61ce5e3685 2007-10-10 drh: @ Your Name: 61ce5e3685 2007-10-10 drh: @ <input type="text" name="u" size="20" value="%h(zUser)"><br> 61ce5e3685 2007-10-10 drh: @ Comment to append:<br> 61ce5e3685 2007-10-10 drh: @ <textarea name="r" class="wikiedit" cols="80" 61ce5e3685 2007-10-10 drh: @ rows="10" wrap="virtual">%h(PD("r",""))</textarea> 61ce5e3685 2007-10-10 drh: @ <br> 61ce5e3685 2007-10-10 drh: @ <input type="submit" name="preview" value="Preview Your Comment"> 61ce5e3685 2007-10-10 drh: @ <input type="submit" name="submit" value="Append Your Changes"> 61ce5e3685 2007-10-10 drh: @ <input type="submit" name="cancel" value="Cancel"> 61ce5e3685 2007-10-10 drh: @ </form> 61ce5e3685 2007-10-10 drh: style_footer(); 50a58adb76 2007-10-10 drh: } 50a58adb76 2007-10-10 drh: 50a58adb76 2007-10-10 drh: /* 50a58adb76 2007-10-10 drh: ** WEBPAGE: whistory 50a58adb76 2007-10-10 drh: ** 50a58adb76 2007-10-10 drh: ** Show the complete change history for a single wiki page. The name 50a58adb76 2007-10-10 drh: ** of the wiki is in g.zExtra 50a58adb76 2007-10-10 drh: */ 50a58adb76 2007-10-10 drh: void whistory_page(void){ 50a58adb76 2007-10-10 drh: Stmt q; 50a58adb76 2007-10-10 drh: char *zTitle; 50a58adb76 2007-10-10 drh: char *zSQL; 50a58adb76 2007-10-10 drh: login_check_credentials(); 50a58adb76 2007-10-10 drh: if( !g.okHistory ){ login_needed(); return; } 50a58adb76 2007-10-10 drh: zTitle = mprintf("History Of %h", g.zExtra); 50a58adb76 2007-10-10 drh: style_header(zTitle); 50a58adb76 2007-10-10 drh: free(zTitle); 50a58adb76 2007-10-10 drh: 50a58adb76 2007-10-10 drh: zSQL = mprintf("%s AND event.objid IN " 50a58adb76 2007-10-10 drh: " (SELECT rid FROM tagxref WHERE tagid=" 50a58adb76 2007-10-10 drh: "(SELECT tagid FROM tag WHERE tagname='wiki-%q'))" 50a58adb76 2007-10-10 drh: "ORDER BY mtime DESC", 50a58adb76 2007-10-10 drh: timeline_query_for_www(), g.zExtra); 50a58adb76 2007-10-10 drh: db_prepare(&q, zSQL); 50a58adb76 2007-10-10 drh: free(zSQL); 50a58adb76 2007-10-10 drh: www_print_timeline(&q, 0, 0, 0, 0); 50a58adb76 2007-10-10 drh: db_finalize(&q); 50a58adb76 2007-10-10 drh: style_footer(); b2e55c0d4d 2007-09-01 drh: } b2e55c0d4d 2007-09-01 drh: b2e55c0d4d 2007-09-01 drh: /* 50a58adb76 2007-10-10 drh: ** WEBPAGE: wcontent b2e55c0d4d 2007-09-01 drh: ** 50a58adb76 2007-10-10 drh: ** List all available wiki pages with date created and last modified. b2e55c0d4d 2007-09-01 drh: */ 50a58adb76 2007-10-10 drh: void wcontent_page(void){ 50a58adb76 2007-10-10 drh: Stmt q; b2e55c0d4d 2007-09-01 drh: login_check_credentials(); 50a58adb76 2007-10-10 drh: if( !g.okRdWiki ){ login_needed(); return; } 50a58adb76 2007-10-10 drh: style_header("Available Wiki Pages"); 50a58adb76 2007-10-10 drh: @ <ul> 50a58adb76 2007-10-10 drh: db_prepare(&q, 50a58adb76 2007-10-10 drh: "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname GLOB 'wiki-*'" 50a58adb76 2007-10-10 drh: " ORDER BY lower(tagname)" 50a58adb76 2007-10-10 drh: ); 50a58adb76 2007-10-10 drh: while( db_step(&q)==SQLITE_ROW ){ 50a58adb76 2007-10-10 drh: const char *zName = db_column_text(&q, 0); 50a58adb76 2007-10-10 drh: @ <li><a href="%s(g.zBaseURL)/wiki/%t(zName)">%h(zName)</a></li> b2e55c0d4d 2007-09-01 drh: } 50a58adb76 2007-10-10 drh: db_finalize(&q); 22c1ac41d4 2007-08-23 drh: style_footer(); 22c1ac41d4 2007-08-23 drh: } 22c1ac41d4 2007-08-23 drh: 22c1ac41d4 2007-08-23 drh: /* 22c1ac41d4 2007-08-23 drh: ** WEBPAGE: ambiguous 22c1ac41d4 2007-08-23 drh: ** 22c1ac41d4 2007-08-23 drh: ** This is the destination for UUID hyperlinks that are ambiguous. 22c1ac41d4 2007-08-23 drh: ** Show all possible choices for the destination with links to each. 22c1ac41d4 2007-08-23 drh: ** 22c1ac41d4 2007-08-23 drh: ** The ambiguous UUID prefix is in g.zExtra 22c1ac41d4 2007-08-23 drh: */ 22c1ac41d4 2007-08-23 drh: void ambiguous_page(void){ 22c1ac41d4 2007-08-23 drh: Stmt q; 22c1ac41d4 2007-08-23 drh: style_header("Ambiguous UUID"); 22c1ac41d4 2007-08-23 drh: @ <p>The link <a href="%s(g.zBaseURL)/ambiguous/%T(g.zExtra)"> 22c1ac41d4 2007-08-23 drh: @ [%h(g.zExtra)]</a> is ambiguous. It might mean any of the following:</p> 22c1ac41d4 2007-08-23 drh: @ <ul> 22c1ac41d4 2007-08-23 drh: db_prepare(&q, "SELECT uuid, rid FROM blob WHERE uuid>=%Q AND uuid<'%qz'" 22c1ac41d4 2007-08-23 drh: " ORDER BY uuid", g.zExtra, g.zExtra); 22c1ac41d4 2007-08-23 drh: while( db_step(&q)==SQLITE_ROW ){ 22c1ac41d4 2007-08-23 drh: const char *zUuid = db_column_text(&q, 0); 22c1ac41d4 2007-08-23 drh: int rid = db_column_int(&q, 1); 22c1ac41d4 2007-08-23 drh: @ <li> %s(zUuid) - %d(rid) 22c1ac41d4 2007-08-23 drh: } 22c1ac41d4 2007-08-23 drh: db_finalize(&q); 22c1ac41d4 2007-08-23 drh: @ </ul> dbda8d6ce9 2007-07-21 drh: style_footer(); dbda8d6ce9 2007-07-21 drh: }