Fossil SCM

Now able to enter and edit and display wiki pages. Still many problems to be resolved.

drh 2007-10-06 13:13 trunk
Commit bf428e685457cc187ced6432d322e5c116de1760
+3 -2
--- src/login.c
+++ src/login.c
@@ -289,12 +289,13 @@
289289
int i;
290290
for(i=0; zCap[i]; i++){
291291
switch( zCap[i] ){
292292
case 's': g.okSetup = g.okDelete = 1;
293293
case 'a': g.okAdmin = g.okRdTkt = g.okWrTkt = g.okQuery =
294
- g.okRdWiki = g.okWrWiki = g.okHistory =
295
- g.okNewTkt = g.okPassword = g.okClone = 1;
294
+ g.okRdWiki = g.okWrWiki = g.okNewWiki =
295
+ g.okHistory = g.okClone =
296
+ g.okNewTkt = g.okPassword = 1;
296297
case 'i': g.okRead = g.okWrite = 1; break;
297298
case 'o': g.okRead = 1; break;
298299
299300
case 'd': g.okDelete = 1; break;
300301
case 'h': g.okHistory = 1; break;
301302
--- src/login.c
+++ src/login.c
@@ -289,12 +289,13 @@
289 int i;
290 for(i=0; zCap[i]; i++){
291 switch( zCap[i] ){
292 case 's': g.okSetup = g.okDelete = 1;
293 case 'a': g.okAdmin = g.okRdTkt = g.okWrTkt = g.okQuery =
294 g.okRdWiki = g.okWrWiki = g.okHistory =
295 g.okNewTkt = g.okPassword = g.okClone = 1;
 
296 case 'i': g.okRead = g.okWrite = 1; break;
297 case 'o': g.okRead = 1; break;
298
299 case 'd': g.okDelete = 1; break;
300 case 'h': g.okHistory = 1; break;
301
--- src/login.c
+++ src/login.c
@@ -289,12 +289,13 @@
289 int i;
290 for(i=0; zCap[i]; i++){
291 switch( zCap[i] ){
292 case 's': g.okSetup = g.okDelete = 1;
293 case 'a': g.okAdmin = g.okRdTkt = g.okWrTkt = g.okQuery =
294 g.okRdWiki = g.okWrWiki = g.okNewWiki =
295 g.okHistory = g.okClone =
296 g.okNewTkt = g.okPassword = 1;
297 case 'i': g.okRead = g.okWrite = 1; break;
298 case 'o': g.okRead = 1; break;
299
300 case 'd': g.okDelete = 1; break;
301 case 'h': g.okHistory = 1; break;
302
+1 -1
--- src/manifest.c
+++ src/manifest.c
@@ -541,10 +541,11 @@
541541
blob_zero(&wiki);
542542
if( blob_extract(pContent, size+1, &wiki)!=size+1 ){
543543
goto manifest_syntax_error;
544544
}
545545
p->zWiki = blob_buffer(&wiki);
546
+ md5sum_step_text(p->zWiki, size+1);
546547
if( p->zWiki[size]!='\n' ) goto manifest_syntax_error;
547548
p->zWiki[size] = 0;
548549
break;
549550
}
550551
@@ -620,11 +621,10 @@
620621
if( p->rDate==0.0 ) goto manifest_syntax_error;
621622
if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
622623
if( p->nCChild>0 ) goto manifest_syntax_error;
623624
if( p->nTag>0 ) goto manifest_syntax_error;
624625
if( p->zTicketUuid!=0 ) goto manifest_syntax_error;
625
- if( p->zUser==0 ) goto manifest_syntax_error;
626626
if( p->zWikiTitle==0 ) goto manifest_syntax_error;
627627
if( !seenZ ) goto manifest_syntax_error;
628628
p->type = CFTYPE_WIKI;
629629
}else if( p->nTag>0 ){
630630
if( p->rDate<=0.0 ) goto manifest_syntax_error;
631631
--- src/manifest.c
+++ src/manifest.c
@@ -541,10 +541,11 @@
541 blob_zero(&wiki);
542 if( blob_extract(pContent, size+1, &wiki)!=size+1 ){
543 goto manifest_syntax_error;
544 }
545 p->zWiki = blob_buffer(&wiki);
 
546 if( p->zWiki[size]!='\n' ) goto manifest_syntax_error;
547 p->zWiki[size] = 0;
548 break;
549 }
550
@@ -620,11 +621,10 @@
620 if( p->rDate==0.0 ) goto manifest_syntax_error;
621 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
622 if( p->nCChild>0 ) goto manifest_syntax_error;
623 if( p->nTag>0 ) goto manifest_syntax_error;
624 if( p->zTicketUuid!=0 ) goto manifest_syntax_error;
625 if( p->zUser==0 ) goto manifest_syntax_error;
626 if( p->zWikiTitle==0 ) goto manifest_syntax_error;
627 if( !seenZ ) goto manifest_syntax_error;
628 p->type = CFTYPE_WIKI;
629 }else if( p->nTag>0 ){
630 if( p->rDate<=0.0 ) goto manifest_syntax_error;
631
--- src/manifest.c
+++ src/manifest.c
@@ -541,10 +541,11 @@
541 blob_zero(&wiki);
542 if( blob_extract(pContent, size+1, &wiki)!=size+1 ){
543 goto manifest_syntax_error;
544 }
545 p->zWiki = blob_buffer(&wiki);
546 md5sum_step_text(p->zWiki, size+1);
547 if( p->zWiki[size]!='\n' ) goto manifest_syntax_error;
548 p->zWiki[size] = 0;
549 break;
550 }
551
@@ -620,11 +621,10 @@
621 if( p->rDate==0.0 ) goto manifest_syntax_error;
622 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
623 if( p->nCChild>0 ) goto manifest_syntax_error;
624 if( p->nTag>0 ) goto manifest_syntax_error;
625 if( p->zTicketUuid!=0 ) goto manifest_syntax_error;
 
626 if( p->zWikiTitle==0 ) goto manifest_syntax_error;
627 if( !seenZ ) goto manifest_syntax_error;
628 p->type = CFTYPE_WIKI;
629 }else if( p->nTag>0 ){
630 if( p->rDate<=0.0 ) goto manifest_syntax_error;
631
+147 -144
--- src/wiki.c
+++ src/wiki.c
@@ -27,159 +27,162 @@
2727
#include "config.h"
2828
#include "wiki.h"
2929
3030
3131
/*
32
-** Create a fake replicate of the "vfile" table as a TEMP table
33
-** using the manifest identified by manid.
34
-*/
35
-static void create_fake_vfile(int manid){
36
- static const char zVfileDef[] =
37
- @ CREATE TEMP TABLE vfile(
38
- @ id INTEGER PRIMARY KEY, -- ID of the checked out file
39
- @ vid INTEGER REFERENCES blob, -- The version this file is part of.
40
- @ chnged INT DEFAULT 0, -- 0:unchnged 1:edited 2:m-chng 3:m-add
41
- @ deleted BOOLEAN DEFAULT 0, -- True if deleted
42
- @ rid INTEGER, -- Originally from this repository record
43
- @ mrid INTEGER, -- Based on this record due to a merge
44
- @ pathname TEXT, -- Full pathname
45
- @ UNIQUE(pathname,vid)
46
- @ );
47
- ;
48
- db_multi_exec(zVfileDef);
49
- load_vfile_from_rid(manid);
50
-}
51
-
52
-/*
53
-** Locate the wiki page with the name zPageName and render it.
54
-*/
55
-static void locate_and_render_wikipage(const char *zPageName){
56
- Stmt q;
57
- int id = 0;
58
- int rid = 0;
59
- int chnged = 0;
60
- char *zPathname = 0;
61
- db_prepare(&q,
62
- "SELECT id, rid, chnged, pathname FROM vfile"
63
- " WHERE (pathname='%q.wiki' OR pathname LIKE '%%/%q.wiki')"
64
- " AND NOT deleted", zPageName, zPageName
65
- );
66
- if( db_step(&q)==SQLITE_ROW ){
67
- id = db_column_int(&q, 0);
68
- rid = db_column_int(&q, 1);
69
- chnged = db_column_int(&q, 2);
70
- if( chnged || rid==0 ){
71
- zPathname = db_column_malloc(&q, 3);
72
- }
73
- }
74
- db_finalize(&q);
75
- if( id ){
76
- Blob page, src;
77
- char *zTitle = "wiki";
78
- char *z;
79
- blob_zero(&src);
80
- if( zPathname ){
81
- zPathname = mprintf("%s/%z", g.zLocalRoot, zPathname);
82
- blob_read_from_file(&src, zPathname);
83
- free(zPathname);
84
- }else{
85
- content_get(rid, &src);
86
- }
87
-
88
- /* The wiki page content is now in src. Check to see if
89
- ** there is a <readonly/> or <appendonly/> element at the
90
- ** beginning of the content.
91
- */
92
- z = blob_str(&src);
93
- while( isspace(*z) ) z++;
94
- if( strncmp(z, "<readonly/>", 11)==0 ){
95
- z += 11;
96
- }else if( strncmp(z, "<appendonly/>", 13)==0 ){
97
- z += 13;
98
- }
99
-
100
- /* Check for <title>...</title> markup and remove it if present. */
101
- while( isspace(*z) ) z++;
102
- if( strncmp(z, "<title>", 7)==0 ){
103
- int i;
104
- for(i=7; z[i] && z[i]!='<'; i++){}
105
- if( z[i]=='<' && strncmp(&z[i], "</title>", 8)==0 ){
106
- zTitle = htmlize(&z[7], i-7);
107
- z = &z[i+8];
108
- }
109
- }
110
-
111
- /* Render the page */
112
- style_header(zTitle);
113
- blob_init(&page, z, -1);
114
- wiki_convert(&page, 0);
115
- blob_reset(&src);
116
- }else{
117
- style_header("Unknown Wiki Page");
118
- @ The wiki page "%h(zPageName)" does not exist.
32
+** WEBPAGE: wiki
33
+** URL: /wiki/PAGENAME
34
+*/
35
+void wiki_page(void){
36
+ char *zTag;
37
+ int rid;
38
+ Blob wiki;
39
+ Manifest m;
40
+ char *zPageName;
41
+ char *zHtmlPageName;
42
+ char *zBody = mprintf("%s","<i>Empty Page</i>");
43
+
44
+ login_check_credentials();
45
+ if( !g.okRdWiki ){ login_needed(); return; }
46
+ zPageName = mprintf("%s", g.zExtra);
47
+ dehttpize(zPageName);
48
+ zTag = mprintf("wiki-%s", zPageName);
49
+ rid = db_int(0,
50
+ "SELECT rid FROM tagxref"
51
+ " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
52
+ " ORDER BY mtime DESC", zTag
53
+ );
54
+ free(zTag);
55
+ memset(&m, 0, sizeof(m));
56
+ blob_zero(&m.content);
57
+ if( rid ){
58
+ Blob content;
59
+ content_get(rid, &content);
60
+ manifest_parse(&m, &content);
61
+ if( m.type==CFTYPE_WIKI ){
62
+ zBody = m.zWiki;
63
+ }
64
+ }
65
+ zHtmlPageName = mprintf("%h", zPageName);
66
+ style_header(zHtmlPageName);
67
+ blob_init(&wiki, zBody, -1);
68
+ wiki_convert(&wiki, 0);
69
+ blob_reset(&wiki);
70
+ manifest_clear(&m);
71
+ @ <hr>
72
+ if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){
73
+ @ [<a href="%s(g.zBaseURL)/wikiedit/%s(g.zExtra)">Edit</a>]
11974
}
12075
style_footer();
12176
}
12277
12378
/*
124
-** WEBPAGE: wiki
125
-** URL: /wiki/PAGENAME
126
-**
127
-** If the local database is available (which only happens if run
128
-** as "server" instead of "cgi" or "http") then the file is taken
129
-** from the local checkout. If there is no local checkout, then
130
-** the content is taken from the "head" baseline.
131
-*/
132
-void wiki_page(void){
133
- login_check_credentials();
134
- if( !g.okRdWiki ){ login_needed(); return; }
135
- if( !g.localOpen ){
136
- int headid = db_int(0,
137
- "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1"
138
- );
139
- create_fake_vfile(headid);
140
- }
141
- locate_and_render_wikipage(g.zExtra);
142
-}
143
-
144
-/*
145
-** The g.zExtra value is of the form UUID/otherstuff.
146
-** Extract the UUID and convert it to a record id. Leave
147
-** g.zExtra holding just otherstuff. If UUID does not exist
148
-** or is malformed, return 0 and leave g.zExtra unchanged.
149
-*/
150
-int extract_uuid_from_url(void){
151
- int i, rid;
152
- Blob uuid;
153
- for(i=0; g.zExtra[i] && g.zExtra[i]!='/'; i++){}
154
- blob_zero(&uuid);
155
- blob_append(&uuid, g.zExtra, i);
156
- rid = name_to_uuid(&uuid, 0);
157
- blob_reset(&uuid);
158
- if( rid ){
159
- while( g.zExtra[i]=='/' ){ i++; }
160
- g.zExtra = &g.zExtra[i];
161
- }
162
- return rid;
163
-}
164
-
165
-/*
166
-** WEBPAGE: bwiki
167
-** URL: /bwiki/UUID/PAGENAME
168
-**
169
-** UUID specifies a baseline. Render the wiki page PAGENAME as
170
-** it appears in that baseline.
171
-*/
172
-void bwiki_page(void){
173
- int headid;
174
- login_check_credentials();
175
- if( !g.okRdWiki || !g.okHistory ){ login_needed(); return; }
176
- headid = extract_uuid_from_url();
177
- if( headid ){
178
- create_fake_vfile(headid);
179
- }
180
- locate_and_render_wikipage(g.zExtra);
79
+** WEBPAGE: wikiedit
80
+** URL: /wikiedit/PAGENAME
81
+*/
82
+void wikiedit_page(void){
83
+ char *zTag;
84
+ int rid;
85
+ Blob wiki;
86
+ Manifest m;
87
+ char *zPageName;
88
+ char *zHtmlPageName;
89
+ int n;
90
+ const char *z;
91
+ char *zBody = (char*)P("w");
92
+
93
+ if( zBody ){
94
+ zBody = mprintf("%s", zBody);
95
+ }
96
+ login_check_credentials();
97
+ zPageName = mprintf("%s", g.zExtra);
98
+ dehttpize(zPageName);
99
+ zTag = mprintf("wiki-%s", zPageName);
100
+ rid = db_int(0,
101
+ "SELECT rid FROM tagxref"
102
+ " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
103
+ " ORDER BY mtime DESC", zTag
104
+ );
105
+ free(zTag);
106
+ if( (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){
107
+ login_needed();
108
+ return;
109
+ }
110
+ memset(&m, 0, sizeof(m));
111
+ blob_zero(&m.content);
112
+ if( rid && zBody==0 ){
113
+ Blob content;
114
+ content_get(rid, &content);
115
+ manifest_parse(&m, &content);
116
+ if( m.type==CFTYPE_WIKI ){
117
+ zBody = m.zWiki;
118
+ }
119
+ }
120
+ if( P("submit")!=0 && zBody!=0 ){
121
+ char *zDate;
122
+ Blob cksum;
123
+ int nrid;
124
+ blob_zero(&wiki);
125
+ db_begin_transaction();
126
+ zDate = db_text(0, "SELECT datetime('now')");
127
+ zDate[10] = 'T';
128
+ blob_appendf(&wiki, "D %s\n", zDate);
129
+ free(zDate);
130
+ blob_appendf(&wiki, "L %F\n", zPageName);
131
+ if( rid ){
132
+ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
133
+ blob_appendf(&wiki, "P %s\n", zUuid);
134
+ free(zUuid);
135
+ }
136
+ if( g.zLogin ){
137
+ blob_appendf(&wiki, "U %F\n", g.zLogin);
138
+ }
139
+ blob_appendf(&wiki, "W %d\n%s\n", strlen(zBody), zBody);
140
+ md5sum_blob(&wiki, &cksum);
141
+ blob_appendf(&wiki, "Z %b\n", &cksum);
142
+ blob_reset(&cksum);
143
+ nrid = content_put(&wiki, 0, 0);
144
+ db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
145
+ manifest_crosslink(nrid, &wiki);
146
+ blob_reset(&wiki);
147
+ content_deltify(rid, nrid, 0);
148
+ db_end_transaction(0);
149
+ cgi_redirect(mprintf("wiki/%s", g.zExtra));
150
+ }
151
+ if( P("cancel")!=0 ){
152
+ cgi_redirect(mprintf("wiki/%s", g.zExtra));
153
+ return;
154
+ }
155
+ if( zBody==0 ){
156
+ zBody = mprintf("<i>Empty Page</i>");
157
+ }
158
+ zHtmlPageName = mprintf("Edit: %h", zPageName);
159
+ style_header(zHtmlPageName);
160
+ if( P("preview")!=0 ){
161
+ blob_zero(&wiki);
162
+ blob_append(&wiki, zBody, -1);
163
+ @ Preview:<hr>
164
+ wiki_convert(&wiki, 0);
165
+ @ <hr>
166
+ blob_reset(&wiki);
167
+ }
168
+ for(n=2, z=zBody; z[0]; z++){
169
+ if( z[0]=='\n' ) n++;
170
+ }
171
+ if( n<20 ) n = 20;
172
+ if( n>200 ) n = 200;
173
+ @ <form method="POST" action="%s(g.zBaseURL)/wikiedit/%s(g.zExtra)">
174
+ @ <textarea name="w" class="wikiedit" cols="80"
175
+ @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
176
+ @ <br>
177
+ @ <input type="submit" name="preview" value="Preview Your Changes">
178
+ @ <input type="submit" name="submit" value="Apply These Changes">
179
+ @ <input type="submit" name="cancel" value="Cancel">
180
+ @ </form>
181
+ manifest_clear(&m);
182
+ style_footer();
183
+
181184
}
182185
183186
/*
184187
** WEBPAGE: ambiguous
185188
**
186189
--- src/wiki.c
+++ src/wiki.c
@@ -27,159 +27,162 @@
27 #include "config.h"
28 #include "wiki.h"
29
30
31 /*
32 ** Create a fake replicate of the "vfile" table as a TEMP table
33 ** using the manifest identified by manid.
34 */
35 static void create_fake_vfile(int manid){
36 static const char zVfileDef[] =
37 @ CREATE TEMP TABLE vfile(
38 @ id INTEGER PRIMARY KEY, -- ID of the checked out file
39 @ vid INTEGER REFERENCES blob, -- The version this file is part of.
40 @ chnged INT DEFAULT 0, -- 0:unchnged 1:edited 2:m-chng 3:m-add
41 @ deleted BOOLEAN DEFAULT 0, -- True if deleted
42 @ rid INTEGER, -- Originally from this repository record
43 @ mrid INTEGER, -- Based on this record due to a merge
44 @ pathname TEXT, -- Full pathname
45 @ UNIQUE(pathname,vid)
46 @ );
47 ;
48 db_multi_exec(zVfileDef);
49 load_vfile_from_rid(manid);
50 }
51
52 /*
53 ** Locate the wiki page with the name zPageName and render it.
54 */
55 static void locate_and_render_wikipage(const char *zPageName){
56 Stmt q;
57 int id = 0;
58 int rid = 0;
59 int chnged = 0;
60 char *zPathname = 0;
61 db_prepare(&q,
62 "SELECT id, rid, chnged, pathname FROM vfile"
63 " WHERE (pathname='%q.wiki' OR pathname LIKE '%%/%q.wiki')"
64 " AND NOT deleted", zPageName, zPageName
65 );
66 if( db_step(&q)==SQLITE_ROW ){
67 id = db_column_int(&q, 0);
68 rid = db_column_int(&q, 1);
69 chnged = db_column_int(&q, 2);
70 if( chnged || rid==0 ){
71 zPathname = db_column_malloc(&q, 3);
72 }
73 }
74 db_finalize(&q);
75 if( id ){
76 Blob page, src;
77 char *zTitle = "wiki";
78 char *z;
79 blob_zero(&src);
80 if( zPathname ){
81 zPathname = mprintf("%s/%z", g.zLocalRoot, zPathname);
82 blob_read_from_file(&src, zPathname);
83 free(zPathname);
84 }else{
85 content_get(rid, &src);
86 }
87
88 /* The wiki page content is now in src. Check to see if
89 ** there is a <readonly/> or <appendonly/> element at the
90 ** beginning of the content.
91 */
92 z = blob_str(&src);
93 while( isspace(*z) ) z++;
94 if( strncmp(z, "<readonly/>", 11)==0 ){
95 z += 11;
96 }else if( strncmp(z, "<appendonly/>", 13)==0 ){
97 z += 13;
98 }
99
100 /* Check for <title>...</title> markup and remove it if present. */
101 while( isspace(*z) ) z++;
102 if( strncmp(z, "<title>", 7)==0 ){
103 int i;
104 for(i=7; z[i] && z[i]!='<'; i++){}
105 if( z[i]=='<' && strncmp(&z[i], "</title>", 8)==0 ){
106 zTitle = htmlize(&z[7], i-7);
107 z = &z[i+8];
108 }
109 }
110
111 /* Render the page */
112 style_header(zTitle);
113 blob_init(&page, z, -1);
114 wiki_convert(&page, 0);
115 blob_reset(&src);
116 }else{
117 style_header("Unknown Wiki Page");
118 @ The wiki page "%h(zPageName)" does not exist.
119 }
120 style_footer();
121 }
122
123 /*
124 ** WEBPAGE: wiki
125 ** URL: /wiki/PAGENAME
126 **
127 ** If the local database is available (which only happens if run
128 ** as "server" instead of "cgi" or "http") then the file is taken
129 ** from the local checkout. If there is no local checkout, then
130 ** the content is taken from the "head" baseline.
131 */
132 void wiki_page(void){
133 login_check_credentials();
134 if( !g.okRdWiki ){ login_needed(); return; }
135 if( !g.localOpen ){
136 int headid = db_int(0,
137 "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1"
138 );
139 create_fake_vfile(headid);
140 }
141 locate_and_render_wikipage(g.zExtra);
142 }
143
144 /*
145 ** The g.zExtra value is of the form UUID/otherstuff.
146 ** Extract the UUID and convert it to a record id. Leave
147 ** g.zExtra holding just otherstuff. If UUID does not exist
148 ** or is malformed, return 0 and leave g.zExtra unchanged.
149 */
150 int extract_uuid_from_url(void){
151 int i, rid;
152 Blob uuid;
153 for(i=0; g.zExtra[i] && g.zExtra[i]!='/'; i++){}
154 blob_zero(&uuid);
155 blob_append(&uuid, g.zExtra, i);
156 rid = name_to_uuid(&uuid, 0);
157 blob_reset(&uuid);
158 if( rid ){
159 while( g.zExtra[i]=='/' ){ i++; }
160 g.zExtra = &g.zExtra[i];
161 }
162 return rid;
163 }
164
165 /*
166 ** WEBPAGE: bwiki
167 ** URL: /bwiki/UUID/PAGENAME
168 **
169 ** UUID specifies a baseline. Render the wiki page PAGENAME as
170 ** it appears in that baseline.
171 */
172 void bwiki_page(void){
173 int headid;
174 login_check_credentials();
175 if( !g.okRdWiki || !g.okHistory ){ login_needed(); return; }
176 headid = extract_uuid_from_url();
177 if( headid ){
178 create_fake_vfile(headid);
179 }
180 locate_and_render_wikipage(g.zExtra);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181 }
182
183 /*
184 ** WEBPAGE: ambiguous
185 **
186
--- src/wiki.c
+++ src/wiki.c
@@ -27,159 +27,162 @@
27 #include "config.h"
28 #include "wiki.h"
29
30
31 /*
32 ** WEBPAGE: wiki
33 ** URL: /wiki/PAGENAME
34 */
35 void wiki_page(void){
36 char *zTag;
37 int rid;
38 Blob wiki;
39 Manifest m;
40 char *zPageName;
41 char *zHtmlPageName;
42 char *zBody = mprintf("%s","<i>Empty Page</i>");
43
44 login_check_credentials();
45 if( !g.okRdWiki ){ login_needed(); return; }
46 zPageName = mprintf("%s", g.zExtra);
47 dehttpize(zPageName);
48 zTag = mprintf("wiki-%s", zPageName);
49 rid = db_int(0,
50 "SELECT rid FROM tagxref"
51 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
52 " ORDER BY mtime DESC", zTag
53 );
54 free(zTag);
55 memset(&m, 0, sizeof(m));
56 blob_zero(&m.content);
57 if( rid ){
58 Blob content;
59 content_get(rid, &content);
60 manifest_parse(&m, &content);
61 if( m.type==CFTYPE_WIKI ){
62 zBody = m.zWiki;
63 }
64 }
65 zHtmlPageName = mprintf("%h", zPageName);
66 style_header(zHtmlPageName);
67 blob_init(&wiki, zBody, -1);
68 wiki_convert(&wiki, 0);
69 blob_reset(&wiki);
70 manifest_clear(&m);
71 @ <hr>
72 if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){
73 @ [<a href="%s(g.zBaseURL)/wikiedit/%s(g.zExtra)">Edit</a>]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74 }
75 style_footer();
76 }
77
78 /*
79 ** WEBPAGE: wikiedit
80 ** URL: /wikiedit/PAGENAME
81 */
82 void wikiedit_page(void){
83 char *zTag;
84 int rid;
85 Blob wiki;
86 Manifest m;
87 char *zPageName;
88 char *zHtmlPageName;
89 int n;
90 const char *z;
91 char *zBody = (char*)P("w");
92
93 if( zBody ){
94 zBody = mprintf("%s", zBody);
95 }
96 login_check_credentials();
97 zPageName = mprintf("%s", g.zExtra);
98 dehttpize(zPageName);
99 zTag = mprintf("wiki-%s", zPageName);
100 rid = db_int(0,
101 "SELECT rid FROM tagxref"
102 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
103 " ORDER BY mtime DESC", zTag
104 );
105 free(zTag);
106 if( (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){
107 login_needed();
108 return;
109 }
110 memset(&m, 0, sizeof(m));
111 blob_zero(&m.content);
112 if( rid && zBody==0 ){
113 Blob content;
114 content_get(rid, &content);
115 manifest_parse(&m, &content);
116 if( m.type==CFTYPE_WIKI ){
117 zBody = m.zWiki;
118 }
119 }
120 if( P("submit")!=0 && zBody!=0 ){
121 char *zDate;
122 Blob cksum;
123 int nrid;
124 blob_zero(&wiki);
125 db_begin_transaction();
126 zDate = db_text(0, "SELECT datetime('now')");
127 zDate[10] = 'T';
128 blob_appendf(&wiki, "D %s\n", zDate);
129 free(zDate);
130 blob_appendf(&wiki, "L %F\n", zPageName);
131 if( rid ){
132 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
133 blob_appendf(&wiki, "P %s\n", zUuid);
134 free(zUuid);
135 }
136 if( g.zLogin ){
137 blob_appendf(&wiki, "U %F\n", g.zLogin);
138 }
139 blob_appendf(&wiki, "W %d\n%s\n", strlen(zBody), zBody);
140 md5sum_blob(&wiki, &cksum);
141 blob_appendf(&wiki, "Z %b\n", &cksum);
142 blob_reset(&cksum);
143 nrid = content_put(&wiki, 0, 0);
144 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
145 manifest_crosslink(nrid, &wiki);
146 blob_reset(&wiki);
147 content_deltify(rid, nrid, 0);
148 db_end_transaction(0);
149 cgi_redirect(mprintf("wiki/%s", g.zExtra));
150 }
151 if( P("cancel")!=0 ){
152 cgi_redirect(mprintf("wiki/%s", g.zExtra));
153 return;
154 }
155 if( zBody==0 ){
156 zBody = mprintf("<i>Empty Page</i>");
157 }
158 zHtmlPageName = mprintf("Edit: %h", zPageName);
159 style_header(zHtmlPageName);
160 if( P("preview")!=0 ){
161 blob_zero(&wiki);
162 blob_append(&wiki, zBody, -1);
163 @ Preview:<hr>
164 wiki_convert(&wiki, 0);
165 @ <hr>
166 blob_reset(&wiki);
167 }
168 for(n=2, z=zBody; z[0]; z++){
169 if( z[0]=='\n' ) n++;
170 }
171 if( n<20 ) n = 20;
172 if( n>200 ) n = 200;
173 @ <form method="POST" action="%s(g.zBaseURL)/wikiedit/%s(g.zExtra)">
174 @ <textarea name="w" class="wikiedit" cols="80"
175 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
176 @ <br>
177 @ <input type="submit" name="preview" value="Preview Your Changes">
178 @ <input type="submit" name="submit" value="Apply These Changes">
179 @ <input type="submit" name="cancel" value="Cancel">
180 @ </form>
181 manifest_clear(&m);
182 style_footer();
183
184 }
185
186 /*
187 ** WEBPAGE: ambiguous
188 **
189
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -989,11 +989,11 @@
989989
z = blob_str(pIn);
990990
wiki_render(&renderer, z);
991991
while( renderer.nStack ){
992992
popStack(&renderer);
993993
}
994
- blob_append(pOut, "\n", 1);
994
+ blob_append(renderer.pOut, "\n", 1);
995995
free(renderer.aStack);
996996
}
997997
998998
/*
999999
** COMMAND: test-wiki-render
10001000
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -989,11 +989,11 @@
989 z = blob_str(pIn);
990 wiki_render(&renderer, z);
991 while( renderer.nStack ){
992 popStack(&renderer);
993 }
994 blob_append(pOut, "\n", 1);
995 free(renderer.aStack);
996 }
997
998 /*
999 ** COMMAND: test-wiki-render
1000
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -989,11 +989,11 @@
989 z = blob_str(pIn);
990 wiki_render(&renderer, z);
991 while( renderer.nStack ){
992 popStack(&renderer);
993 }
994 blob_append(renderer.pOut, "\n", 1);
995 free(renderer.aStack);
996 }
997
998 /*
999 ** COMMAND: test-wiki-render
1000

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button