Differences From:
File
src/wiki.c
part of check-in
[22c1ac41d4]
- Add separate "clone" permissions. Previously, one needed "History"
premission in order to clone. But sometimes we want to grant clone
without granting history.
by
drh on
2007-08-23 19:52:19.
[view]
To:
File
src/wiki.c
part of check-in
[b2e55c0d4d]
- Add the /wiki and /bwiki web pages. Currently renders content from
the check-out as readonly.
by
drh on
2007-09-01 21:11:33.
Also file
src/wiki.c
part of check-in
[bbcb6326c9]
- Pulled in the navbar and timeline changes.
by
aku on
2007-09-17 00:58:51.
[view]
@@ -26,18 +26,159 @@
#include <assert.h>
#include "config.h"
#include "wiki.h"
+
+/*
+** Create a fake replicate of the "vfile" table as a TEMP table
+** using the manifest identified by manid.
+*/
+static void create_fake_vfile(int manid){
+ static const char zVfileDef[] =
+ @ CREATE TEMP TABLE vfile(
+ @ id INTEGER PRIMARY KEY, -- ID of the checked out file
+ @ vid INTEGER REFERENCES blob, -- The version this file is part of.
+ @ chnged INT DEFAULT 0, -- 0:unchnged 1:edited 2:m-chng 3:m-add
+ @ deleted BOOLEAN DEFAULT 0, -- True if deleted
+ @ rid INTEGER, -- Originally from this repository record
+ @ mrid INTEGER, -- Based on this record due to a merge
+ @ pathname TEXT, -- Full pathname
+ @ UNIQUE(pathname,vid)
+ @ );
+ ;
+ db_multi_exec(zVfileDef);
+ load_vfile_from_rid(manid);
+}
+
+/*
+** Locate the wiki page with the name zPageName and render it.
+*/
+static void locate_and_render_wikipage(const char *zPageName){
+ Stmt q;
+ int id = 0;
+ int rid = 0;
+ int chnged = 0;
+ char *zPathname = 0;
+ db_prepare(&q,
+ "SELECT id, rid, chnged, pathname FROM vfile"
+ " WHERE (pathname='%q.wiki' OR pathname LIKE '%%/%q.wiki')"
+ " AND NOT deleted", zPageName, zPageName
+ );
+ if( db_step(&q)==SQLITE_ROW ){
+ id = db_column_int(&q, 0);
+ rid = db_column_int(&q, 1);
+ chnged = db_column_int(&q, 2);
+ if( chnged || rid==0 ){
+ zPathname = db_column_malloc(&q, 3);
+ }
+ }
+ db_finalize(&q);
+ if( id ){
+ Blob page, src;
+ char *zTitle = "wiki";
+ char *z;
+ blob_zero(&src);
+ if( zPathname ){
+ zPathname = mprintf("%s/%z", g.zLocalRoot, zPathname);
+ blob_read_from_file(&src, zPathname);
+ free(zPathname);
+ }else{
+ content_get(rid, &src);
+ }
+
+ /* The wiki page content is now in src. Check to see if
+ ** there is a <readonly/> or <appendonly/> element at the
+ ** beginning of the content.
+ */
+ z = blob_str(&src);
+ while( isspace(*z) ) z++;
+ if( strncmp(z, "<readonly/>", 11)==0 ){
+ z += 11;
+ }else if( strncmp(z, "<appendonly/>", 13)==0 ){
+ z += 13;
+ }
+
+ /* Check for <title>...</title> markup and remove it if present. */
+ while( isspace(*z) ) z++;
+ if( strncmp(z, "<title>", 7)==0 ){
+ int i;
+ for(i=7; z[i] && z[i]!='<'; i++){}
+ if( z[i]=='<' && strncmp(&z[i], "</title>", 8)==0 ){
+ zTitle = htmlize(&z[7], i-7);
+ z = &z[i+8];
+ }
+ }
+
+ /* Render the page */
+ style_header(zTitle);
+ blob_init(&page, z, -1);
+ wiki_convert(&page, cgi_output_blob(), WIKI_HTML);
+ blob_reset(&src);
+ }else{
+ style_header("Unknown Wiki Page");
+ @ The wiki page "%h(zPageName)" does not exist.
+ }
+ style_footer();
+}
+
/*
** WEBPAGE: wiki
+** URL: /wiki/PAGENAME
**
-** Render the wiki page that is named after the /wiki/ part of
-** the url.
+** If the local database is available (which only happens if run
+** as "server" instead of "cgi" or "http") then the file is taken
+** from the local checkout. If there is no local checkout, then
+** the content is taken from the "head" baseline.
*/
void wiki_page(void){
- style_header("Wiki");
- @ extra=%h(g.zExtra)
- style_footer();
+ login_check_credentials();
+ if( !g.okRdWiki ){ login_needed(); return; }
+ if( !g.localOpen ){
+ int headid = db_int(0,
+ "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1"
+ );
+ create_fake_vfile(headid);
+ }
+ locate_and_render_wikipage(g.zExtra);
+}
+
+/*
+** The g.zExtra value is of the form UUID/otherstuff.
+** Extract the UUID and convert it to a record id. Leave
+** g.zExtra holding just otherstuff. If UUID does not exist
+** or is malformed, return 0 and leave g.zExtra unchanged.
+*/
+int extract_uuid_from_url(void){
+ int i, rid;
+ Blob uuid;
+ for(i=0; g.zExtra[i] && g.zExtra[i]!='/'; i++){}
+ blob_zero(&uuid);
+ blob_append(&uuid, g.zExtra, i);
+ rid = name_to_uuid(&uuid, 0);
+ blob_reset(&uuid);
+ if( rid ){
+ while( g.zExtra[i]=='/' ){ i++; }
+ g.zExtra = &g.zExtra[i];
+ }
+ return rid;
+}
+
+/*
+** WEBPAGE: bwiki
+** URL: /bwiki/UUID/PAGENAME
+**
+** UUID specifies a baseline. Render the wiki page PAGENAME as
+** it appears in that baseline.
+*/
+void bwiki_page(void){
+ int headid;
+ login_check_credentials();
+ if( !g.okRdWiki || !g.okHistory ){ login_needed(); return; }
+ headid = extract_uuid_from_url();
+ if( headid ){
+ create_fake_vfile(headid);
+ }
+ locate_and_render_wikipage(g.zExtra);
}
/*
** WEBPAGE: ambiguous