File Annotation
Not logged in
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: 
b2e55c0d4d 2007-09-01       drh: 
b2e55c0d4d 2007-09-01       drh: /*
b2e55c0d4d 2007-09-01       drh: ** Create a fake replicate of the "vfile" table as a TEMP table
b2e55c0d4d 2007-09-01       drh: ** using the manifest identified by manid.
b2e55c0d4d 2007-09-01       drh: */
b2e55c0d4d 2007-09-01       drh: static void create_fake_vfile(int manid){
b2e55c0d4d 2007-09-01       drh:   static const char zVfileDef[] =
b2e55c0d4d 2007-09-01       drh:     @ CREATE TEMP TABLE vfile(
b2e55c0d4d 2007-09-01       drh:     @   id INTEGER PRIMARY KEY,     -- ID of the checked out file
b2e55c0d4d 2007-09-01       drh:     @   vid INTEGER REFERENCES blob, -- The version this file is part of.
b2e55c0d4d 2007-09-01       drh:     @   chnged INT DEFAULT 0,       -- 0:unchnged 1:edited 2:m-chng 3:m-add
b2e55c0d4d 2007-09-01       drh:     @   deleted BOOLEAN DEFAULT 0,  -- True if deleted
b2e55c0d4d 2007-09-01       drh:     @   rid INTEGER,                -- Originally from this repository record
b2e55c0d4d 2007-09-01       drh:     @   mrid INTEGER,               -- Based on this record due to a merge
b2e55c0d4d 2007-09-01       drh:     @   pathname TEXT,              -- Full pathname
b2e55c0d4d 2007-09-01       drh:     @   UNIQUE(pathname,vid)
b2e55c0d4d 2007-09-01       drh:     @ );
b2e55c0d4d 2007-09-01       drh:     ;
b2e55c0d4d 2007-09-01       drh:   db_multi_exec(zVfileDef);
b2e55c0d4d 2007-09-01       drh:   load_vfile_from_rid(manid);
b2e55c0d4d 2007-09-01       drh: }
b2e55c0d4d 2007-09-01       drh: 
b2e55c0d4d 2007-09-01       drh: /*
b2e55c0d4d 2007-09-01       drh: ** Locate the wiki page with the name zPageName and render it.
b2e55c0d4d 2007-09-01       drh: */
b2e55c0d4d 2007-09-01       drh: static void locate_and_render_wikipage(const char *zPageName){
b2e55c0d4d 2007-09-01       drh:   Stmt q;
b2e55c0d4d 2007-09-01       drh:   int id = 0;
b2e55c0d4d 2007-09-01       drh:   int rid = 0;
b2e55c0d4d 2007-09-01       drh:   int chnged = 0;
b2e55c0d4d 2007-09-01       drh:   char *zPathname = 0;
b2e55c0d4d 2007-09-01       drh:   db_prepare(&q,
b2e55c0d4d 2007-09-01       drh:      "SELECT id, rid, chnged, pathname FROM vfile"
b2e55c0d4d 2007-09-01       drh:      " WHERE (pathname='%q.wiki' OR pathname LIKE '%%/%q.wiki')"
b2e55c0d4d 2007-09-01       drh:      "   AND NOT deleted", zPageName, zPageName
b2e55c0d4d 2007-09-01       drh:   );
b2e55c0d4d 2007-09-01       drh:   if( db_step(&q)==SQLITE_ROW ){
b2e55c0d4d 2007-09-01       drh:     id = db_column_int(&q, 0);
b2e55c0d4d 2007-09-01       drh:     rid = db_column_int(&q, 1);
b2e55c0d4d 2007-09-01       drh:     chnged = db_column_int(&q, 2);
b2e55c0d4d 2007-09-01       drh:     if( chnged || rid==0 ){
b2e55c0d4d 2007-09-01       drh:       zPathname = db_column_malloc(&q, 3);
b2e55c0d4d 2007-09-01       drh:     }
b2e55c0d4d 2007-09-01       drh:   }
b2e55c0d4d 2007-09-01       drh:   db_finalize(&q);
b2e55c0d4d 2007-09-01       drh:   if( id ){
b2e55c0d4d 2007-09-01       drh:     Blob page, src;
b2e55c0d4d 2007-09-01       drh:     char *zTitle = "wiki";
b2e55c0d4d 2007-09-01       drh:     char *z;
b2e55c0d4d 2007-09-01       drh:     blob_zero(&src);
b2e55c0d4d 2007-09-01       drh:     if( zPathname ){
b2e55c0d4d 2007-09-01       drh:       zPathname = mprintf("%s/%z", g.zLocalRoot, zPathname);
b2e55c0d4d 2007-09-01       drh:       blob_read_from_file(&src, zPathname);
b2e55c0d4d 2007-09-01       drh:       free(zPathname);
b2e55c0d4d 2007-09-01       drh:     }else{
b2e55c0d4d 2007-09-01       drh:       content_get(rid, &src);
b2e55c0d4d 2007-09-01       drh:     }
b2e55c0d4d 2007-09-01       drh: 
b2e55c0d4d 2007-09-01       drh:     /* The wiki page content is now in src.  Check to see if
b2e55c0d4d 2007-09-01       drh:     ** there is a <readonly/> or <appendonly/> element at the
b2e55c0d4d 2007-09-01       drh:     ** beginning of the content.
b2e55c0d4d 2007-09-01       drh:     */
b2e55c0d4d 2007-09-01       drh:     z = blob_str(&src);
b2e55c0d4d 2007-09-01       drh:     while( isspace(*z) ) z++;
b2e55c0d4d 2007-09-01       drh:     if( strncmp(z, "<readonly/>", 11)==0 ){
b2e55c0d4d 2007-09-01       drh:       z += 11;
b2e55c0d4d 2007-09-01       drh:     }else if( strncmp(z, "<appendonly/>", 13)==0 ){
b2e55c0d4d 2007-09-01       drh:       z += 13;
b2e55c0d4d 2007-09-01       drh:     }
b2e55c0d4d 2007-09-01       drh: 
b2e55c0d4d 2007-09-01       drh:     /* Check for <title>...</title> markup and remove it if present. */
b2e55c0d4d 2007-09-01       drh:     while( isspace(*z) ) z++;
b2e55c0d4d 2007-09-01       drh:     if( strncmp(z, "<title>", 7)==0 ){
b2e55c0d4d 2007-09-01       drh:       int i;
b2e55c0d4d 2007-09-01       drh:       for(i=7; z[i] && z[i]!='<'; i++){}
b2e55c0d4d 2007-09-01       drh:       if( z[i]=='<' && strncmp(&z[i], "</title>", 8)==0 ){
b2e55c0d4d 2007-09-01       drh:         zTitle = htmlize(&z[7], i-7);
b2e55c0d4d 2007-09-01       drh:         z = &z[i+8];
b2e55c0d4d 2007-09-01       drh:       }
b2e55c0d4d 2007-09-01       drh:     }
b2e55c0d4d 2007-09-01       drh: 
b2e55c0d4d 2007-09-01       drh:     /* Render the page */
b2e55c0d4d 2007-09-01       drh:     style_header(zTitle);
b2e55c0d4d 2007-09-01       drh:     blob_init(&page, z, -1);
b2e55c0d4d 2007-09-01       drh:     wiki_convert(&page, cgi_output_blob(), WIKI_HTML);
b2e55c0d4d 2007-09-01       drh:     blob_reset(&src);
b2e55c0d4d 2007-09-01       drh:   }else{
b2e55c0d4d 2007-09-01       drh:     style_header("Unknown Wiki Page");
b2e55c0d4d 2007-09-01       drh:     @ The wiki page "%h(zPageName)" does not exist.
b2e55c0d4d 2007-09-01       drh:   }
b2e55c0d4d 2007-09-01       drh:   style_footer();
b2e55c0d4d 2007-09-01       drh: }
b2e55c0d4d 2007-09-01       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** WEBPAGE: wiki
b2e55c0d4d 2007-09-01       drh: ** URL: /wiki/PAGENAME
dbda8d6ce9 2007-07-21       drh: **
b2e55c0d4d 2007-09-01       drh: ** If the local database is available (which only happens if run
b2e55c0d4d 2007-09-01       drh: ** as "server" instead of "cgi" or "http") then the file is taken
b2e55c0d4d 2007-09-01       drh: ** from the local checkout.  If there is no local checkout, then
b2e55c0d4d 2007-09-01       drh: ** the content is taken from the "head" baseline.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void wiki_page(void){
b2e55c0d4d 2007-09-01       drh:   login_check_credentials();
b2e55c0d4d 2007-09-01       drh:   if( !g.okRdWiki ){ login_needed(); return; }
b2e55c0d4d 2007-09-01       drh:   if( !g.localOpen ){
b2e55c0d4d 2007-09-01       drh:     int headid = db_int(0,
b2e55c0d4d 2007-09-01       drh:        "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1"
b2e55c0d4d 2007-09-01       drh:     );
b2e55c0d4d 2007-09-01       drh:     create_fake_vfile(headid);
b2e55c0d4d 2007-09-01       drh:   }
b2e55c0d4d 2007-09-01       drh:   locate_and_render_wikipage(g.zExtra);
b2e55c0d4d 2007-09-01       drh: }
b2e55c0d4d 2007-09-01       drh: 
b2e55c0d4d 2007-09-01       drh: /*
b2e55c0d4d 2007-09-01       drh: ** The g.zExtra value is of the form UUID/otherstuff.
b2e55c0d4d 2007-09-01       drh: ** Extract the UUID and convert it to a record id.  Leave
b2e55c0d4d 2007-09-01       drh: ** g.zExtra holding just otherstuff.  If UUID does not exist
b2e55c0d4d 2007-09-01       drh: ** or is malformed, return 0 and leave g.zExtra unchanged.
b2e55c0d4d 2007-09-01       drh: */
b2e55c0d4d 2007-09-01       drh: int extract_uuid_from_url(void){
b2e55c0d4d 2007-09-01       drh:   int i, rid;
b2e55c0d4d 2007-09-01       drh:   Blob uuid;
b2e55c0d4d 2007-09-01       drh:   for(i=0; g.zExtra[i] && g.zExtra[i]!='/'; i++){}
b2e55c0d4d 2007-09-01       drh:   blob_zero(&uuid);
b2e55c0d4d 2007-09-01       drh:   blob_append(&uuid, g.zExtra, i);
b2e55c0d4d 2007-09-01       drh:   rid = name_to_uuid(&uuid, 0);
b2e55c0d4d 2007-09-01       drh:   blob_reset(&uuid);
b2e55c0d4d 2007-09-01       drh:   if( rid ){
b2e55c0d4d 2007-09-01       drh:     while( g.zExtra[i]=='/' ){ i++; }
b2e55c0d4d 2007-09-01       drh:     g.zExtra = &g.zExtra[i];
b2e55c0d4d 2007-09-01       drh:   }
b2e55c0d4d 2007-09-01       drh:   return rid;
b2e55c0d4d 2007-09-01       drh: }
b2e55c0d4d 2007-09-01       drh: 
b2e55c0d4d 2007-09-01       drh: /*
b2e55c0d4d 2007-09-01       drh: ** WEBPAGE: bwiki
b2e55c0d4d 2007-09-01       drh: ** URL: /bwiki/UUID/PAGENAME
b2e55c0d4d 2007-09-01       drh: **
b2e55c0d4d 2007-09-01       drh: ** UUID specifies a baseline.  Render the wiki page PAGENAME as
b2e55c0d4d 2007-09-01       drh: ** it appears in that baseline.
b2e55c0d4d 2007-09-01       drh: */
b2e55c0d4d 2007-09-01       drh: void bwiki_page(void){
b2e55c0d4d 2007-09-01       drh:   int headid;
b2e55c0d4d 2007-09-01       drh:   login_check_credentials();
b2e55c0d4d 2007-09-01       drh:   if( !g.okRdWiki || !g.okHistory ){ login_needed(); return; }
b2e55c0d4d 2007-09-01       drh:   headid = extract_uuid_from_url();
b2e55c0d4d 2007-09-01       drh:   if( headid ){
b2e55c0d4d 2007-09-01       drh:     create_fake_vfile(headid);
b2e55c0d4d 2007-09-01       drh:   }
b2e55c0d4d 2007-09-01       drh:   locate_and_render_wikipage(g.zExtra);
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: }