Diff
Not logged in

Differences From:

File src/wiki.c part of check-in [ab637af752] - Add enumeration lists and indented paragraphs in the wiki. by drh on 2007-09-28 15:44:08. [view]

To:

File src/wiki.c part of check-in [bf428e6854] - Now able to enter and edit and display wiki pages. Still many problems to be resolved. by drh on 2007-10-06 13:13:33. [view]

@@ -28,157 +28,160 @@
 #include "wiki.h"
 
 
 /*
-** Create a fake replicate of the "vfile" table as a TEMP table
-** using the manifest identified by manid.
+** WEBPAGE: wiki
+** URL: /wiki/PAGENAME
 */
-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);
-}
+void wiki_page(void){
+  char *zTag;
+  int rid;
+  Blob wiki;
+  Manifest m;
+  char *zPageName;
+  char *zHtmlPageName;
+  char *zBody = mprintf("%s","<i>Empty Page</i>");
 
-/*
-** 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
+  login_check_credentials();
+  if( !g.okRdWiki ){ login_needed(); return; }
+  zPageName = mprintf("%s", g.zExtra);
+  dehttpize(zPageName);
+  zTag = mprintf("wiki-%s", zPageName);
+  rid = db_int(0,
+    "SELECT rid FROM tagxref"
+    " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
+    " ORDER BY mtime DESC", zTag
   );
-  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);
+  free(zTag);
+  memset(&m, 0, sizeof(m));
+  blob_zero(&m.content);
+  if( rid ){
+    Blob content;
+    content_get(rid, &content);
+    manifest_parse(&m, &content);
+    if( m.type==CFTYPE_WIKI ){
+      zBody = m.zWiki;
     }
   }
-  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, 0);
-    blob_reset(&src);
-  }else{
-    style_header("Unknown Wiki Page");
-    @ The wiki page "%h(zPageName)" does not exist.
+  zHtmlPageName = mprintf("%h", zPageName);
+  style_header(zHtmlPageName);
+  blob_init(&wiki, zBody, -1);
+  wiki_convert(&wiki, 0);
+  blob_reset(&wiki);
+  manifest_clear(&m);
+  @ <hr>
+  if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){
+    @ [<a href="%s(g.zBaseURL)/wikiedit/%s(g.zExtra)">Edit</a>]
   }
   style_footer();
 }
 
 /*
-** WEBPAGE: wiki
-** URL: /wiki/PAGENAME
-**
-** 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.
+** WEBPAGE: wikiedit
+** URL: /wikiedit/PAGENAME
 */
-void wiki_page(void){
-  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);
-}
+void wikiedit_page(void){
+  char *zTag;
+  int rid;
+  Blob wiki;
+  Manifest m;
+  char *zPageName;
+  char *zHtmlPageName;
+  int n;
+  const char *z;
+  char *zBody = (char*)P("w");
 
-/*
-** 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;
+  if( zBody ){
+    zBody = mprintf("%s", zBody);
+  }
   login_check_credentials();
-  if( !g.okRdWiki || !g.okHistory ){ login_needed(); return; }
-  headid = extract_uuid_from_url();
-  if( headid ){
-    create_fake_vfile(headid);
+  zPageName = mprintf("%s", g.zExtra);
+  dehttpize(zPageName);
+  zTag = mprintf("wiki-%s", zPageName);
+  rid = db_int(0,
+    "SELECT rid FROM tagxref"
+    " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
+    " ORDER BY mtime DESC", zTag
+  );
+  free(zTag);
+  if( (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){
+    login_needed();
+    return;
+  }
+  memset(&m, 0, sizeof(m));
+  blob_zero(&m.content);
+  if( rid && zBody==0 ){
+    Blob content;
+    content_get(rid, &content);
+    manifest_parse(&m, &content);
+    if( m.type==CFTYPE_WIKI ){
+      zBody = m.zWiki;
+    }
+  }
+  if( P("submit")!=0 && zBody!=0 ){
+    char *zDate;
+    Blob cksum;
+    int nrid;
+    blob_zero(&wiki);
+    db_begin_transaction();
+    zDate = db_text(0, "SELECT datetime('now')");
+    zDate[10] = 'T';
+    blob_appendf(&wiki, "D %s\n", zDate);
+    free(zDate);
+    blob_appendf(&wiki, "L %F\n", zPageName);
+    if( rid ){
+      char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
+      blob_appendf(&wiki, "P %s\n", zUuid);
+      free(zUuid);
+    }
+    if( g.zLogin ){
+      blob_appendf(&wiki, "U %F\n", g.zLogin);
+    }
+    blob_appendf(&wiki, "W %d\n%s\n", strlen(zBody), zBody);
+    md5sum_blob(&wiki, &cksum);
+    blob_appendf(&wiki, "Z %b\n", &cksum);
+    blob_reset(&cksum);
+    nrid = content_put(&wiki, 0, 0);
+    db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
+    manifest_crosslink(nrid, &wiki);
+    blob_reset(&wiki);
+    content_deltify(rid, nrid, 0);
+    db_end_transaction(0);
+    cgi_redirect(mprintf("wiki/%s", g.zExtra));
+  }
+  if( P("cancel")!=0 ){
+    cgi_redirect(mprintf("wiki/%s", g.zExtra));
+    return;
+  }
+  if( zBody==0 ){
+    zBody = mprintf("<i>Empty Page</i>");
+  }
+  zHtmlPageName = mprintf("Edit: %h", zPageName);
+  style_header(zHtmlPageName);
+  if( P("preview")!=0 ){
+    blob_zero(&wiki);
+    blob_append(&wiki, zBody, -1);
+    @ Preview:<hr>
+    wiki_convert(&wiki, 0);
+    @ <hr>
+    blob_reset(&wiki);
+  }
+  for(n=2, z=zBody; z[0]; z++){
+    if( z[0]=='\n' ) n++;
   }
-  locate_and_render_wikipage(g.zExtra);
+  if( n<20 ) n = 20;
+  if( n>200 ) n = 200;
+  @ <form method="POST" action="%s(g.zBaseURL)/wikiedit/%s(g.zExtra)">
+  @ <textarea name="w" class="wikiedit" cols="80"
+  @  rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
+  @ <br>
+  @ <input type="submit" name="preview" value="Preview Your Changes">
+  @ <input type="submit" name="submit" value="Apply These Changes">
+  @ <input type="submit" name="cancel" value="Cancel">
+  @ </form>
+  manifest_clear(&m);
+  style_footer();
+
 }
 
 /*
 ** WEBPAGE: ambiguous