Check-in [b2e55c0d4d]
Not logged in
Overview

SHA1 Hash:b2e55c0d4db063caefc3d40f7e6b26f9acc313a6
Date: 2007-09-01 21:11:33
User: drh
Comment:Add the /wiki and /bwiki web pages. Currently renders content from the check-out as readonly.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/db.c from [ca474c1e96] to [7ab2af8add].

@@ -257,11 +257,11 @@
   return sqlite3_column_double(pStmt->pStmt, N);
 }
 const char *db_column_text(Stmt *pStmt, int N){
   return (char*)sqlite3_column_text(pStmt->pStmt, N);
 }
-const char *db_column_malloc(Stmt *pStmt, int N){
+char *db_column_malloc(Stmt *pStmt, int N){
   return mprintf("%s", db_column_text(pStmt, N));
 }
 void db_column_blob(Stmt *pStmt, int N, Blob *pBlob){
   blob_append(pBlob, sqlite3_column_blob(pStmt->pStmt, N),
               sqlite3_column_bytes(pStmt->pStmt, N));

Modified src/info.c from [a7363a7c53] to [1d02bccab4].

@@ -535,12 +535,14 @@
   style_footer();
 }
 
 /*
 ** WEBPAGE: fview
+** URL: /fview/UUID
 **
-** Show the complete content of a file identified by g.zExtra
+** Show the complete content of a file identified by UUID
+** as preformatted text.
 */
 void fview_page(void){
   int rid;
   Blob content;
 

Modified src/main.c from [500655758a] to [17322e8c2b].

@@ -339,11 +339,11 @@
     printf("\n");
   }
 }
 
 /*
-** COMMAND: commands
+** COM MAND: commands
 **
 ** Usage: %fossil commands
 ** List all supported commands.
 */
 void cmd_cmd_list(void){
@@ -385,10 +385,11 @@
   int rc, idx;
   const char *z;
   if( g.argc!=3 ){
     printf("Usage: %s help COMMAND.\nAvailable COMMANDs:\n", g.argv[0]);
     cmd_cmd_list();
+    printf("You are running fossil baseline " MANIFEST_UUID "\n");
     return;
   }
   rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
   if( rc==1 ){
     fossil_fatal("unknown command: %s", g.argv[2]);
@@ -408,20 +409,10 @@
       putchar(*z);
       z++;
     }
   }
   putchar('\n');
-}
-
-/*
-** COMMAND: baseline
-**
-** Show the baseline number of the source code from which this
-** fossil executable was generated.
-*/
-void baseline_cmd(void){
-  printf("%s\n", MANIFEST_UUID);
 }
 
 /*
 ** RSS feeds need to reference absolute URLs so we need to calculate
 ** the base URL onto which we add components. This is basically

Modified src/wiki.c from [daf8014fa8] to [804763a66e].

@@ -25,20 +25,161 @@
 */
 #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
 **

Modified src/wikiformat.c from [8a54463d32] to [0d1f6957fe].

@@ -712,14 +712,14 @@
   /* TBD */
 }
 
 /*
 ** Resolve a hyperlink.  The argument is the content of the [...]
-** in the wiki.  Append the URL to the given blob.
+** in the wiki.  Append the URL to the output of the Renderer.
 */
-static void resolveHyperlink(const char *zTarget, Blob *pOut){
-  blob_appendf(pOut, "http://www.fossil-scm.org/test-%T", zTarget);
+static void resolveHyperlink(const char *zTarget, Renderer *p){
+  blob_appendf(p->pOut, "http://www.fossil-scm.org/test-%T", zTarget);
 }
 
 /*
 ** Check to see if the given parsed markup is the correct
 ** </verbatim> tag.
@@ -804,11 +804,11 @@
           zDisplay = zTarget;
         }else{
           while( isspace(*zDisplay) ) zDisplay++;
         }
         blob_append(p->pOut, "<a href=\"", -1);
-        resolveHyperlink(zTarget, p->pOut);
+        resolveHyperlink(zTarget, p);
         blob_append(p->pOut, "\">", -1);
         savedState = p->state;
         p->state &= ~ALLOW_WIKI;
         p->state |= FONT_MARKUP_ONLY;
         wiki_render(p, zDisplay);