Fossil

Check-in [b2e55c0d4d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the /wiki and /bwiki web pages. Currently renders content from the check-out as readonly.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b2e55c0d4db063caefc3d40f7e6b26f9acc313a6
User & Date: drh 2007-09-01 21:11:33.000
References
2009-02-01
10:42 New ticket [5b871546ce] Possible typo in file src/main.c, introduced by check-in [b2e55c0d4d]. artifact: 4478700846 user: anonymous
Context
2007-09-02
01:23
The /index webpage pulls up the wiki page specified in Setup/Configuration.s check-in: 4f641e7e4e user: drh tags: trunk
2007-09-01
21:11
Add the /wiki and /bwiki web pages. Currently renders content from the check-out as readonly. check-in: b2e55c0d4d user: drh tags: trunk
01:55
Updates to the timeline routines. Added the pqueue module. check-in: abce5105e2 user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/db.c.
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
}
double db_column_double(Stmt *pStmt, int N){
  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){
  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));
}








|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
}
double db_column_double(Stmt *pStmt, int N){
  return sqlite3_column_double(pStmt->pStmt, N);
}
const char *db_column_text(Stmt *pStmt, int N){
  return (char*)sqlite3_column_text(pStmt->pStmt, 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));
}

Changes to src/info.c.
533
534
535
536
537
538
539

540
541

542
543
544
545
546
547
548
  @ </pre></blockquote>
  blob_reset(&diff);
  style_footer();
}

/*
** WEBPAGE: fview

**
** Show the complete content of a file identified by g.zExtra

*/
void fview_page(void){
  int rid;
  Blob content;

  rid = name_to_rid(g.zExtra);
  login_check_credentials();







>
|
|
>







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
  @ </pre></blockquote>
  blob_reset(&diff);
  style_footer();
}

/*
** WEBPAGE: fview
** URL: /fview/UUID
** 
** Show the complete content of a file identified by UUID
** as preformatted text.
*/
void fview_page(void){
  int rid;
  Blob content;

  rid = name_to_rid(g.zExtra);
  login_check_credentials();
Changes to src/main.c.
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
      zSpacer = "  ";
    }
    printf("\n");
  }
}

/*
** COMMAND: commands
**
** Usage: %fossil commands
** List all supported commands.
*/
void cmd_cmd_list(void){
  int i, nCmd;
  const char *aCmd[count(aCommand)];







|







337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
      zSpacer = "  ";
    }
    printf("\n");
  }
}

/*
** COM MAND: commands
**
** Usage: %fossil commands
** List all supported commands.
*/
void cmd_cmd_list(void){
  int i, nCmd;
  const char *aCmd[count(aCommand)];
383
384
385
386
387
388
389

390
391
392
393
394
395
396
*/
void help_cmd(void){
  int rc, idx;
  const char *z;
  if( g.argc!=3 ){
    printf("Usage: %s help COMMAND.\nAvailable COMMANDs:\n", g.argv[0]);
    cmd_cmd_list();

    return;
  }
  rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
  if( rc==1 ){
    fossil_fatal("unknown command: %s", g.argv[2]);
  }else if( rc==2 ){
    fossil_fatal("ambiguous command prefix: %s", g.argv[2]);







>







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
*/
void help_cmd(void){
  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]);
  }else if( rc==2 ){
    fossil_fatal("ambiguous command prefix: %s", g.argv[2]);
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
      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
** cgi_redirect() stripped down and always returning an absolute URL.
*/
static char *get_base_url(void){
  int i;







<
<
<
<
<
<
<
<
<
<







409
410
411
412
413
414
415










416
417
418
419
420
421
422
      putchar(*z);
      z++;
    }
  }
  putchar('\n');
}











/*
** RSS feeds need to reference absolute URLs so we need to calculate
** the base URL onto which we add components. This is basically
** cgi_redirect() stripped down and always returning an absolute URL.
*/
static char *get_base_url(void){
  int i;
Changes to src/wiki.c.
23
24
25
26
27
28
29

30




























































































31

32
33



34
35
36










37
















38



39
















40
41
42
43
44
45
46
**
** This file contains code to do formatting of wiki text.
*/
#include <assert.h>
#include "config.h"
#include "wiki.h"


/*




























































































** WEBPAGE: wiki

**
** Render the wiki page that is named after the /wiki/ part of



** the url.
*/
void wiki_page(void){










  style_header("Wiki");
















  @ extra=%h(g.zExtra)



  style_footer();
















}

/*
** WEBPAGE: ambiguous
**
** This is the destination for UUID hyperlinks that are ambiguous.
** Show all possible choices for the destination with links to each.







>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

<
>
>
>
|


>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
**
** This file contains code to do formatting of wiki text.
*/
#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
**

** 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){
  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
**
** This is the destination for UUID hyperlinks that are ambiguous.
** Show all possible choices for the destination with links to each.
Changes to src/wikiformat.c.
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
*/
static void addMissingMarkup(Renderer *p){
  /* TBD */
}

/*
** Resolve a hyperlink.  The argument is the content of the [...]
** in the wiki.  Append the URL to the given blob.
*/
static void resolveHyperlink(const char *zTarget, Blob *pOut){
  blob_appendf(pOut, "http://www.fossil-scm.org/test-%T", zTarget);
}

/*
** Check to see if the given parsed markup is the correct
** </verbatim> tag.
*/
static int endVerbatim(Renderer *p, ParsedMarkup *pMarkup){







|

|
|







710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
*/
static void addMissingMarkup(Renderer *p){
  /* TBD */
}

/*
** Resolve a hyperlink.  The argument is the content of the [...]
** in the wiki.  Append the URL to the output of the Renderer.
*/
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.
*/
static int endVerbatim(Renderer *p, ParsedMarkup *pMarkup){
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
        z[i] = 0;
        if( zDisplay==0 ){
          zDisplay = zTarget;
        }else{
          while( isspace(*zDisplay) ) zDisplay++;
        }
        blob_append(p->pOut, "<a href=\"", -1);
        resolveHyperlink(zTarget, p->pOut);
        blob_append(p->pOut, "\">", -1);
        savedState = p->state;
        p->state &= ~ALLOW_WIKI;
        p->state |= FONT_MARKUP_ONLY;
        wiki_render(p, zDisplay);
        p->state = savedState;
        blob_append(p->pOut, "</a>", 4);







|







802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
        z[i] = 0;
        if( zDisplay==0 ){
          zDisplay = zTarget;
        }else{
          while( isspace(*zDisplay) ) zDisplay++;
        }
        blob_append(p->pOut, "<a href=\"", -1);
        resolveHyperlink(zTarget, p);
        blob_append(p->pOut, "\">", -1);
        savedState = p->state;
        p->state &= ~ALLOW_WIKI;
        p->state |= FONT_MARKUP_ONLY;
        wiki_render(p, zDisplay);
        p->state = savedState;
        blob_append(p->pOut, "</a>", 4);