Fossil SCM

Implemented /json/wiki/create.

stephan 2011-09-22 19:14 UTC json
Commit 1df648abfeb97d303ea94069a92fbcf236ae74fa
--- ajax/wiki-editor.html
+++ ajax/wiki-editor.html
@@ -174,10 +174,16 @@
174174
TheApp.jqe.taResponse.val( val );
175175
};
176176
opt.onError = function(req,opt) {
177177
TheApp.jqe.taResponse.val( "ERROR SENDING REQUEST:\n"+WhAjaj.stringify(opt) );
178178
};
179
+
180
+ TheApp.jqe.taPageContent.blur(function(){
181
+ var p = TheApp.currentPage;
182
+ if(! p ) return;
183
+ p.content = TheApp.jqe.taPageContent.val();
184
+ });
179185
180186
TheApp.cgi.onLogin = function(){
181187
TheApp.jqe.taResponse.val( "Logged in. Auth token =\n"+this.authToken );
182188
TheApp.jqe.currentAuthToken.text("Auth token: "+(this.authToken || "not logged in"));
183189
};
@@ -191,11 +197,11 @@
191197
TheApp.currentPage = page;
192198
TheApp.jqe.spanPageName.text('('+page.name+')');
193199
TheApp.jqe.taPageContent.val(page.content);
194200
}
195201
var p = ('object' === typeof name) ? name : TheApp.pages[name];
196
- if('object' === typeof p) {
202
+ if(('object' === typeof p) && p.content) {
197203
doShow(p);
198204
return;
199205
}
200206
TheApp.cgi.sendCommand('/json/wiki/get',{
201207
page:name
@@ -206,42 +212,58 @@
206212
var p = resp.payload;
207213
doShow( TheApp.pages[p.name] = p );
208214
}
209215
});
210216
};
211
- TheApp.updatePageList = function(list){
212
- var tgt = TheApp.jqe.pageListArea;
213
- tgt.empty();
214
- var i, p, a;
217
+ TheApp.refreshPageListView = function(){
218
+ var list = (function(){
219
+ var k, v, li = [];
220
+ for( k in TheApp.pages ){
221
+ if(!TheApp.pages.hasOwnProperty(k)) continue;
222
+ li.push(k);
223
+ }
224
+ return li;
225
+ })();
226
+ var i, p, a, tgt = TheApp.jqe.pageListArea;
227
+ tgt.text('');
215228
function makeLink(name){
216
- var a = jQuery('<span class="wikiPageLink"></span>');
217
- a.text(name).
218
- click(function(e){
229
+ var link = jQuery('<span></span>');
230
+ link.text(name);
231
+ link.addClass('wikiPageLink');
232
+ link.click(function(e){
219233
TheApp.showPage(name);
220234
e.preventDefault();
221235
return false;
222236
});
223
- return a;
237
+ return link;
224238
}
239
+ list.sort();
225240
for( i = 0; i < list.length; ++i ){
226
- tgt.append(makeLink(list[i])).append('<br/>');
241
+ tgt.append(makeLink(list[i]));
242
+ tgt.append('<br/>');
227243
}
228244
};
229245
230246
TheApp.loadPageList = function(){
231247
TheApp.cgi.sendCommand('/json/wiki/list',null,{
232248
onResponse:function(resp,req){
233249
TheApp.onResponse(resp,req);
234250
if(resp.resultCode) return;
235
- else TheApp.updatePageList(resp.payload);
251
+ var i, v, p, ar = resp.payload;
252
+ for( i = 0; i < ar.length; ++i ){
253
+ v = ar[i];
254
+ p = TheApp.pages[v];
255
+ if( !p ) TheApp.pages[v] = {name:v};
256
+ }
257
+ TheApp.refreshPageListView();
236258
}
237259
});
238260
return false /*for click handlers*/;
239261
}
240262
241263
TheApp.savePage = function(p){
242
- p = p || TheApp.currentPage || TheApp.pages[TheApp.currentPage];
264
+ p = p || TheApp.currentPage;
243265
if( 'object' !== typeof p ){
244266
p = TheApp.pages[p];
245267
}
246268
if('object' !== typeof p){
247269
alert("savePage() argument is not a page object or known page name.");
@@ -251,11 +273,43 @@
251273
var req = {
252274
name:p.name,
253275
content:p.content
254276
};
255277
if(! confirm("Really save wiki page ["+p.name+"]?") ) return;
256
- TheApp.cgi.sendCommand('/json/wiki/save',req);
278
+ TheApp.cgi.sendCommand('/json/wiki/'+(p.isNew?'create':'save'),req,{
279
+ onResponse:function(resp,req){
280
+ TheApp.onResponse(resp,req);
281
+ if(resp.resultCode) return;
282
+ delete p.isNew;
283
+ p.timestamp = resp.payload.timestamp;
284
+ }
285
+ });
286
+
287
+ };
288
+
289
+ TheApp.createNewPage = function(){
290
+ var name = prompt("New page name?");
291
+ if(!name) return;
292
+ var p = {
293
+ name:name,
294
+ content:"New, empty page.",
295
+ isNew:true
296
+ };
297
+ TheApp.pages[name] = p;
298
+ TheApp.refreshPageListView();
299
+ TheApp.showPage(p);
300
+/*
301
+ if(! confirm("Really create new wiki page ["+name+"]?") ) return;
302
+ TheApp.cgi.sendCommand('/json/wiki/create',req,{
303
+ onResponse:function(resp,req){
304
+ TheApp.onResponse(resp,req);
305
+ if(resp.resultCode) return;
306
+ TheApp.pages[p.name] = p;
307
+ TheApp.refreshPageListView();
308
+ }
309
+ });
310
+*/
257311
};
258312
259313
});
260314
261315
</script>
@@ -303,10 +357,11 @@
303357
<th>Page List</th>
304358
<th>Content <span id='spanPageName'></span></th>
305359
</tr>
306360
<tr>
307361
<td width='25%' valign='top'>
362
+ <input type='button' value='Create new...' onclick='TheApp.createNewPage()' /><br/>
308363
<div id='pageListArea'></div>
309364
</td>
310365
<td width='75%' valign='top'>
311366
<input type='button' value='Save' onclick='TheApp.savePage()' /><br/>
312367
<textarea id='taPageContent' rows='20' cols='60'></textarea>
313368
--- ajax/wiki-editor.html
+++ ajax/wiki-editor.html
@@ -174,10 +174,16 @@
174 TheApp.jqe.taResponse.val( val );
175 };
176 opt.onError = function(req,opt) {
177 TheApp.jqe.taResponse.val( "ERROR SENDING REQUEST:\n"+WhAjaj.stringify(opt) );
178 };
 
 
 
 
 
 
179
180 TheApp.cgi.onLogin = function(){
181 TheApp.jqe.taResponse.val( "Logged in. Auth token =\n"+this.authToken );
182 TheApp.jqe.currentAuthToken.text("Auth token: "+(this.authToken || "not logged in"));
183 };
@@ -191,11 +197,11 @@
191 TheApp.currentPage = page;
192 TheApp.jqe.spanPageName.text('('+page.name+')');
193 TheApp.jqe.taPageContent.val(page.content);
194 }
195 var p = ('object' === typeof name) ? name : TheApp.pages[name];
196 if('object' === typeof p) {
197 doShow(p);
198 return;
199 }
200 TheApp.cgi.sendCommand('/json/wiki/get',{
201 page:name
@@ -206,42 +212,58 @@
206 var p = resp.payload;
207 doShow( TheApp.pages[p.name] = p );
208 }
209 });
210 };
211 TheApp.updatePageList = function(list){
212 var tgt = TheApp.jqe.pageListArea;
213 tgt.empty();
214 var i, p, a;
 
 
 
 
 
 
 
215 function makeLink(name){
216 var a = jQuery('<span class="wikiPageLink"></span>');
217 a.text(name).
218 click(function(e){
 
219 TheApp.showPage(name);
220 e.preventDefault();
221 return false;
222 });
223 return a;
224 }
 
225 for( i = 0; i < list.length; ++i ){
226 tgt.append(makeLink(list[i])).append('<br/>');
 
227 }
228 };
229
230 TheApp.loadPageList = function(){
231 TheApp.cgi.sendCommand('/json/wiki/list',null,{
232 onResponse:function(resp,req){
233 TheApp.onResponse(resp,req);
234 if(resp.resultCode) return;
235 else TheApp.updatePageList(resp.payload);
 
 
 
 
 
 
236 }
237 });
238 return false /*for click handlers*/;
239 }
240
241 TheApp.savePage = function(p){
242 p = p || TheApp.currentPage || TheApp.pages[TheApp.currentPage];
243 if( 'object' !== typeof p ){
244 p = TheApp.pages[p];
245 }
246 if('object' !== typeof p){
247 alert("savePage() argument is not a page object or known page name.");
@@ -251,11 +273,43 @@
251 var req = {
252 name:p.name,
253 content:p.content
254 };
255 if(! confirm("Really save wiki page ["+p.name+"]?") ) return;
256 TheApp.cgi.sendCommand('/json/wiki/save',req);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257 };
258
259 });
260
261 </script>
@@ -303,10 +357,11 @@
303 <th>Page List</th>
304 <th>Content <span id='spanPageName'></span></th>
305 </tr>
306 <tr>
307 <td width='25%' valign='top'>
 
308 <div id='pageListArea'></div>
309 </td>
310 <td width='75%' valign='top'>
311 <input type='button' value='Save' onclick='TheApp.savePage()' /><br/>
312 <textarea id='taPageContent' rows='20' cols='60'></textarea>
313
--- ajax/wiki-editor.html
+++ ajax/wiki-editor.html
@@ -174,10 +174,16 @@
174 TheApp.jqe.taResponse.val( val );
175 };
176 opt.onError = function(req,opt) {
177 TheApp.jqe.taResponse.val( "ERROR SENDING REQUEST:\n"+WhAjaj.stringify(opt) );
178 };
179
180 TheApp.jqe.taPageContent.blur(function(){
181 var p = TheApp.currentPage;
182 if(! p ) return;
183 p.content = TheApp.jqe.taPageContent.val();
184 });
185
186 TheApp.cgi.onLogin = function(){
187 TheApp.jqe.taResponse.val( "Logged in. Auth token =\n"+this.authToken );
188 TheApp.jqe.currentAuthToken.text("Auth token: "+(this.authToken || "not logged in"));
189 };
@@ -191,11 +197,11 @@
197 TheApp.currentPage = page;
198 TheApp.jqe.spanPageName.text('('+page.name+')');
199 TheApp.jqe.taPageContent.val(page.content);
200 }
201 var p = ('object' === typeof name) ? name : TheApp.pages[name];
202 if(('object' === typeof p) && p.content) {
203 doShow(p);
204 return;
205 }
206 TheApp.cgi.sendCommand('/json/wiki/get',{
207 page:name
@@ -206,42 +212,58 @@
212 var p = resp.payload;
213 doShow( TheApp.pages[p.name] = p );
214 }
215 });
216 };
217 TheApp.refreshPageListView = function(){
218 var list = (function(){
219 var k, v, li = [];
220 for( k in TheApp.pages ){
221 if(!TheApp.pages.hasOwnProperty(k)) continue;
222 li.push(k);
223 }
224 return li;
225 })();
226 var i, p, a, tgt = TheApp.jqe.pageListArea;
227 tgt.text('');
228 function makeLink(name){
229 var link = jQuery('<span></span>');
230 link.text(name);
231 link.addClass('wikiPageLink');
232 link.click(function(e){
233 TheApp.showPage(name);
234 e.preventDefault();
235 return false;
236 });
237 return link;
238 }
239 list.sort();
240 for( i = 0; i < list.length; ++i ){
241 tgt.append(makeLink(list[i]));
242 tgt.append('<br/>');
243 }
244 };
245
246 TheApp.loadPageList = function(){
247 TheApp.cgi.sendCommand('/json/wiki/list',null,{
248 onResponse:function(resp,req){
249 TheApp.onResponse(resp,req);
250 if(resp.resultCode) return;
251 var i, v, p, ar = resp.payload;
252 for( i = 0; i < ar.length; ++i ){
253 v = ar[i];
254 p = TheApp.pages[v];
255 if( !p ) TheApp.pages[v] = {name:v};
256 }
257 TheApp.refreshPageListView();
258 }
259 });
260 return false /*for click handlers*/;
261 }
262
263 TheApp.savePage = function(p){
264 p = p || TheApp.currentPage;
265 if( 'object' !== typeof p ){
266 p = TheApp.pages[p];
267 }
268 if('object' !== typeof p){
269 alert("savePage() argument is not a page object or known page name.");
@@ -251,11 +273,43 @@
273 var req = {
274 name:p.name,
275 content:p.content
276 };
277 if(! confirm("Really save wiki page ["+p.name+"]?") ) return;
278 TheApp.cgi.sendCommand('/json/wiki/'+(p.isNew?'create':'save'),req,{
279 onResponse:function(resp,req){
280 TheApp.onResponse(resp,req);
281 if(resp.resultCode) return;
282 delete p.isNew;
283 p.timestamp = resp.payload.timestamp;
284 }
285 });
286
287 };
288
289 TheApp.createNewPage = function(){
290 var name = prompt("New page name?");
291 if(!name) return;
292 var p = {
293 name:name,
294 content:"New, empty page.",
295 isNew:true
296 };
297 TheApp.pages[name] = p;
298 TheApp.refreshPageListView();
299 TheApp.showPage(p);
300 /*
301 if(! confirm("Really create new wiki page ["+name+"]?") ) return;
302 TheApp.cgi.sendCommand('/json/wiki/create',req,{
303 onResponse:function(resp,req){
304 TheApp.onResponse(resp,req);
305 if(resp.resultCode) return;
306 TheApp.pages[p.name] = p;
307 TheApp.refreshPageListView();
308 }
309 });
310 */
311 };
312
313 });
314
315 </script>
@@ -303,10 +357,11 @@
357 <th>Page List</th>
358 <th>Content <span id='spanPageName'></span></th>
359 </tr>
360 <tr>
361 <td width='25%' valign='top'>
362 <input type='button' value='Create new...' onclick='TheApp.createNewPage()' /><br/>
363 <div id='pageListArea'></div>
364 </td>
365 <td width='75%' valign='top'>
366 <input type='button' value='Save' onclick='TheApp.savePage()' /><br/>
367 <textarea id='taPageContent' rows='20' cols='60'></textarea>
368
+85 -9
--- src/json.c
+++ src/json.c
@@ -1481,14 +1481,17 @@
14811481
14821482
14831483
static cson_value * json_wiki_list(unsigned int depth);
14841484
static cson_value * json_wiki_get(unsigned int depth);
14851485
static cson_value * json_wiki_save(unsigned int depth);
1486
+static cson_value * json_wiki_create(unsigned int depth);
1487
+
14861488
/*
14871489
** Mapping of /json/wiki/XXX commands/paths to callbacks.
14881490
*/
14891491
static const JsonPageDef JsonPageDefs_Wiki[] = {
1492
+{"create", json_wiki_create, 1},
14901493
{"get", json_wiki_get, 0},
14911494
{"list", json_wiki_list, 0},
14921495
{"save", json_wiki_save, 1},
14931496
/* Last entry MUST have a NULL name. */
14941497
{NULL,NULL,0}
@@ -1593,49 +1596,122 @@
15931596
return payV;
15941597
}
15951598
}
15961599
15971600
/*
1598
-** Implementation of /json/wiki/save.
1601
+** Internal impl of /wiki/save and /wiki/create. If createMode is 0
1602
+** and the page already exists then a
1603
+** FSL_JSON_E_RESOURCE_ALREADY_EXISTS error is triggered. If
1604
+** createMode is false then the FSL_JSON_E_RESOURCE_NOT_FOUND is
1605
+** triggered if the page does not already exists.
1606
+**
1607
+** Note that the error triggered when createMode==0 and no such page
1608
+** exists is rather arbitrary - we could just as well create the entry
1609
+** here if it doesn't already exist. With that, save/create would
1610
+** become one operation. That said, i expect there are people who
1611
+** would categorize such behaviour as "being too clever" or "doing too
1612
+** much automatically" (and i would likely agree with them).
15991613
*/
1600
-static cson_value * json_wiki_save(unsigned int depth){
1614
+static cson_value * json_wiki_create_or_save(char createMode){
16011615
Blob content = empty_blob;
16021616
cson_value * nameV;
16031617
cson_value * contentV;
1618
+ cson_value * emptyContent = NULL;
16041619
cson_value * payV = NULL;
16051620
cson_object * pay = NULL;
16061621
cson_string const * jstr = NULL;
16071622
char const * zContent;
16081623
char const * zBody = NULL;
16091624
char const * zPageName;
1625
+ unsigned int contentLen = 0;
1626
+ int rid;
16101627
if( !g.perm.WrWiki ){
16111628
g.json.resultCode = FSL_JSON_E_DENIED;
16121629
return NULL;
16131630
}
16141631
nameV = json_req_payload_get("name");
1615
- contentV = nameV ? json_req_payload_get("content") : NULL;
1616
- if(!nameV || !contentV){
1632
+ if(!nameV){
16171633
g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
1618
- return NULL;
1634
+ goto error;
1635
+ }
1636
+ zPageName = cson_string_cstr(cson_value_get_string(nameV));
1637
+ rid = db_int(0,
1638
+ "SELECT x.rid FROM tag t, tagxref x"
1639
+ " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1640
+ " ORDER BY x.mtime DESC LIMIT 1",
1641
+ zPageName
1642
+ );
1643
+
1644
+ if(rid){
1645
+ if(createMode){
1646
+ g.json.resultCode = FSL_JSON_E_RESOURCE_ALREADY_EXISTS;
1647
+ goto error;
1648
+ }
1649
+ }else{
1650
+ if(!createMode){
1651
+ g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;
1652
+ goto error;
1653
+ }
1654
+ }
1655
+
1656
+ contentV = json_req_payload_get("content");
1657
+ if( !contentV ){
1658
+ if( createMode ){
1659
+ contentV = emptyContent = cson_value_new_string("",0);
1660
+ }else{
1661
+ g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
1662
+ goto error;
1663
+ }
16191664
}
16201665
if( !cson_value_is_string(nameV)
16211666
|| !cson_value_is_string(contentV)){
16221667
g.json.resultCode = FSL_JSON_E_INVALID_ARGS;
1623
- return NULL;
1668
+ goto error;
16241669
}
1625
- zPageName = cson_string_cstr(cson_value_get_string(nameV));
16261670
jstr = cson_value_get_string(contentV);
1627
- blob_append(&content, cson_string_cstr(jstr),(int)cson_string_length_bytes(jstr));
1628
- wiki_cmd_commit(zPageName, 0, &content);
1671
+ contentLen = (int)cson_string_length_bytes(jstr);
1672
+ if(contentLen){
1673
+ blob_append(&content, cson_string_cstr(jstr),contentLen);
1674
+ }
1675
+ wiki_cmd_commit(zPageName, 0==rid, &content);
16291676
blob_reset(&content);
16301677
16311678
payV = cson_value_new_object();
16321679
pay = cson_value_get_object(payV);
16331680
cson_object_set( pay, "name", nameV );
16341681
cson_object_set( pay, FossilJsonKeys.timestamp,
16351682
json_new_timestamp(-1) );
1683
+
1684
+ goto ok;
1685
+ error:
1686
+ assert( 0 != g.json.resultCode );
1687
+ cson_value_free(payV);
1688
+ payV = NULL;
1689
+ ok:
1690
+ if( emptyContent ){
1691
+ /* We have some potentially tricky memory ownership
1692
+ here, which is why we handle emptyContent separately.
1693
+ */
1694
+ cson_value_free(emptyContent);
1695
+ }
16361696
return payV;
1697
+
1698
+}
1699
+
1700
+/*
1701
+** Implementation of /json/wiki/create.
1702
+*/
1703
+static cson_value * json_wiki_create(unsigned int depth){
1704
+ return json_wiki_create_or_save(1);
1705
+}
1706
+
1707
+/*
1708
+** Implementation of /json/wiki/save.
1709
+*/
1710
+static cson_value * json_wiki_save(unsigned int depth){
1711
+ /* FIXME: add GET/POST.payload bool option createIfNotExists. */
1712
+ return json_wiki_create_or_save(0);
16371713
}
16381714
16391715
/*
16401716
** Implementation of /json/wiki/list.
16411717
*/
16421718
--- src/json.c
+++ src/json.c
@@ -1481,14 +1481,17 @@
1481
1482
1483 static cson_value * json_wiki_list(unsigned int depth);
1484 static cson_value * json_wiki_get(unsigned int depth);
1485 static cson_value * json_wiki_save(unsigned int depth);
 
 
1486 /*
1487 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
1488 */
1489 static const JsonPageDef JsonPageDefs_Wiki[] = {
 
1490 {"get", json_wiki_get, 0},
1491 {"list", json_wiki_list, 0},
1492 {"save", json_wiki_save, 1},
1493 /* Last entry MUST have a NULL name. */
1494 {NULL,NULL,0}
@@ -1593,49 +1596,122 @@
1593 return payV;
1594 }
1595 }
1596
1597 /*
1598 ** Implementation of /json/wiki/save.
 
 
 
 
 
 
 
 
 
 
 
1599 */
1600 static cson_value * json_wiki_save(unsigned int depth){
1601 Blob content = empty_blob;
1602 cson_value * nameV;
1603 cson_value * contentV;
 
1604 cson_value * payV = NULL;
1605 cson_object * pay = NULL;
1606 cson_string const * jstr = NULL;
1607 char const * zContent;
1608 char const * zBody = NULL;
1609 char const * zPageName;
 
 
1610 if( !g.perm.WrWiki ){
1611 g.json.resultCode = FSL_JSON_E_DENIED;
1612 return NULL;
1613 }
1614 nameV = json_req_payload_get("name");
1615 contentV = nameV ? json_req_payload_get("content") : NULL;
1616 if(!nameV || !contentV){
1617 g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
1618 return NULL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1619 }
1620 if( !cson_value_is_string(nameV)
1621 || !cson_value_is_string(contentV)){
1622 g.json.resultCode = FSL_JSON_E_INVALID_ARGS;
1623 return NULL;
1624 }
1625 zPageName = cson_string_cstr(cson_value_get_string(nameV));
1626 jstr = cson_value_get_string(contentV);
1627 blob_append(&content, cson_string_cstr(jstr),(int)cson_string_length_bytes(jstr));
1628 wiki_cmd_commit(zPageName, 0, &content);
 
 
 
1629 blob_reset(&content);
1630
1631 payV = cson_value_new_object();
1632 pay = cson_value_get_object(payV);
1633 cson_object_set( pay, "name", nameV );
1634 cson_object_set( pay, FossilJsonKeys.timestamp,
1635 json_new_timestamp(-1) );
 
 
 
 
 
 
 
 
 
 
 
 
 
1636 return payV;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1637 }
1638
1639 /*
1640 ** Implementation of /json/wiki/list.
1641 */
1642
--- src/json.c
+++ src/json.c
@@ -1481,14 +1481,17 @@
1481
1482
1483 static cson_value * json_wiki_list(unsigned int depth);
1484 static cson_value * json_wiki_get(unsigned int depth);
1485 static cson_value * json_wiki_save(unsigned int depth);
1486 static cson_value * json_wiki_create(unsigned int depth);
1487
1488 /*
1489 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
1490 */
1491 static const JsonPageDef JsonPageDefs_Wiki[] = {
1492 {"create", json_wiki_create, 1},
1493 {"get", json_wiki_get, 0},
1494 {"list", json_wiki_list, 0},
1495 {"save", json_wiki_save, 1},
1496 /* Last entry MUST have a NULL name. */
1497 {NULL,NULL,0}
@@ -1593,49 +1596,122 @@
1596 return payV;
1597 }
1598 }
1599
1600 /*
1601 ** Internal impl of /wiki/save and /wiki/create. If createMode is 0
1602 ** and the page already exists then a
1603 ** FSL_JSON_E_RESOURCE_ALREADY_EXISTS error is triggered. If
1604 ** createMode is false then the FSL_JSON_E_RESOURCE_NOT_FOUND is
1605 ** triggered if the page does not already exists.
1606 **
1607 ** Note that the error triggered when createMode==0 and no such page
1608 ** exists is rather arbitrary - we could just as well create the entry
1609 ** here if it doesn't already exist. With that, save/create would
1610 ** become one operation. That said, i expect there are people who
1611 ** would categorize such behaviour as "being too clever" or "doing too
1612 ** much automatically" (and i would likely agree with them).
1613 */
1614 static cson_value * json_wiki_create_or_save(char createMode){
1615 Blob content = empty_blob;
1616 cson_value * nameV;
1617 cson_value * contentV;
1618 cson_value * emptyContent = NULL;
1619 cson_value * payV = NULL;
1620 cson_object * pay = NULL;
1621 cson_string const * jstr = NULL;
1622 char const * zContent;
1623 char const * zBody = NULL;
1624 char const * zPageName;
1625 unsigned int contentLen = 0;
1626 int rid;
1627 if( !g.perm.WrWiki ){
1628 g.json.resultCode = FSL_JSON_E_DENIED;
1629 return NULL;
1630 }
1631 nameV = json_req_payload_get("name");
1632 if(!nameV){
 
1633 g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
1634 goto error;
1635 }
1636 zPageName = cson_string_cstr(cson_value_get_string(nameV));
1637 rid = db_int(0,
1638 "SELECT x.rid FROM tag t, tagxref x"
1639 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1640 " ORDER BY x.mtime DESC LIMIT 1",
1641 zPageName
1642 );
1643
1644 if(rid){
1645 if(createMode){
1646 g.json.resultCode = FSL_JSON_E_RESOURCE_ALREADY_EXISTS;
1647 goto error;
1648 }
1649 }else{
1650 if(!createMode){
1651 g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;
1652 goto error;
1653 }
1654 }
1655
1656 contentV = json_req_payload_get("content");
1657 if( !contentV ){
1658 if( createMode ){
1659 contentV = emptyContent = cson_value_new_string("",0);
1660 }else{
1661 g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
1662 goto error;
1663 }
1664 }
1665 if( !cson_value_is_string(nameV)
1666 || !cson_value_is_string(contentV)){
1667 g.json.resultCode = FSL_JSON_E_INVALID_ARGS;
1668 goto error;
1669 }
 
1670 jstr = cson_value_get_string(contentV);
1671 contentLen = (int)cson_string_length_bytes(jstr);
1672 if(contentLen){
1673 blob_append(&content, cson_string_cstr(jstr),contentLen);
1674 }
1675 wiki_cmd_commit(zPageName, 0==rid, &content);
1676 blob_reset(&content);
1677
1678 payV = cson_value_new_object();
1679 pay = cson_value_get_object(payV);
1680 cson_object_set( pay, "name", nameV );
1681 cson_object_set( pay, FossilJsonKeys.timestamp,
1682 json_new_timestamp(-1) );
1683
1684 goto ok;
1685 error:
1686 assert( 0 != g.json.resultCode );
1687 cson_value_free(payV);
1688 payV = NULL;
1689 ok:
1690 if( emptyContent ){
1691 /* We have some potentially tricky memory ownership
1692 here, which is why we handle emptyContent separately.
1693 */
1694 cson_value_free(emptyContent);
1695 }
1696 return payV;
1697
1698 }
1699
1700 /*
1701 ** Implementation of /json/wiki/create.
1702 */
1703 static cson_value * json_wiki_create(unsigned int depth){
1704 return json_wiki_create_or_save(1);
1705 }
1706
1707 /*
1708 ** Implementation of /json/wiki/save.
1709 */
1710 static cson_value * json_wiki_save(unsigned int depth){
1711 /* FIXME: add GET/POST.payload bool option createIfNotExists. */
1712 return json_wiki_create_or_save(0);
1713 }
1714
1715 /*
1716 ** Implementation of /json/wiki/list.
1717 */
1718
--- src/json_detail.h
+++ src/json_detail.h
@@ -37,10 +37,11 @@
3737
3838
FSL_JSON_E_AUTH = 2000,
3939
FSL_JSON_E_MISSING_AUTH = FSL_JSON_E_AUTH + 1,
4040
FSL_JSON_E_DENIED = FSL_JSON_E_AUTH + 2,
4141
FSL_JSON_E_WRONG_MODE = FSL_JSON_E_AUTH + 3,
42
+FSL_JSON_E_RESOURCE_ALREADY_EXISTS = FSL_JSON_E_AUTH + 4,
4243
4344
FSL_JSON_E_LOGIN_FAILED = FSL_JSON_E_AUTH + 100,
4445
FSL_JSON_E_LOGIN_FAILED_NOSEED = FSL_JSON_E_LOGIN_FAILED + 1,
4546
FSL_JSON_E_LOGIN_FAILED_NONAME = FSL_JSON_E_LOGIN_FAILED + 2,
4647
FSL_JSON_E_LOGIN_FAILED_NOPW = FSL_JSON_E_LOGIN_FAILED + 3,
4748
--- src/json_detail.h
+++ src/json_detail.h
@@ -37,10 +37,11 @@
37
38 FSL_JSON_E_AUTH = 2000,
39 FSL_JSON_E_MISSING_AUTH = FSL_JSON_E_AUTH + 1,
40 FSL_JSON_E_DENIED = FSL_JSON_E_AUTH + 2,
41 FSL_JSON_E_WRONG_MODE = FSL_JSON_E_AUTH + 3,
 
42
43 FSL_JSON_E_LOGIN_FAILED = FSL_JSON_E_AUTH + 100,
44 FSL_JSON_E_LOGIN_FAILED_NOSEED = FSL_JSON_E_LOGIN_FAILED + 1,
45 FSL_JSON_E_LOGIN_FAILED_NONAME = FSL_JSON_E_LOGIN_FAILED + 2,
46 FSL_JSON_E_LOGIN_FAILED_NOPW = FSL_JSON_E_LOGIN_FAILED + 3,
47
--- src/json_detail.h
+++ src/json_detail.h
@@ -37,10 +37,11 @@
37
38 FSL_JSON_E_AUTH = 2000,
39 FSL_JSON_E_MISSING_AUTH = FSL_JSON_E_AUTH + 1,
40 FSL_JSON_E_DENIED = FSL_JSON_E_AUTH + 2,
41 FSL_JSON_E_WRONG_MODE = FSL_JSON_E_AUTH + 3,
42 FSL_JSON_E_RESOURCE_ALREADY_EXISTS = FSL_JSON_E_AUTH + 4,
43
44 FSL_JSON_E_LOGIN_FAILED = FSL_JSON_E_AUTH + 100,
45 FSL_JSON_E_LOGIN_FAILED_NOSEED = FSL_JSON_E_LOGIN_FAILED + 1,
46 FSL_JSON_E_LOGIN_FAILED_NONAME = FSL_JSON_E_LOGIN_FAILED + 2,
47 FSL_JSON_E_LOGIN_FAILED_NOPW = FSL_JSON_E_LOGIN_FAILED + 3,
48
+1 -1
--- src/wiki.c
+++ src/wiki.c
@@ -805,11 +805,11 @@
805805
if( rid==0 && !isNew ){
806806
g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;
807807
fossil_fatal("no such wiki page: %s", zPageName);
808808
}
809809
if( rid!=0 && isNew ){
810
- g.json.resultCode = FSL_JSON_E_DENIED/*need a better code for this*/;
810
+ g.json.resultCode = FSL_JSON_E_RESOURCE_ALREADY_EXISTS;
811811
fossil_fatal("wiki page %s already exists", zPageName);
812812
}
813813
814814
blob_zero(&wiki);
815815
zDate = date_in_standard_format("now");
816816
--- src/wiki.c
+++ src/wiki.c
@@ -805,11 +805,11 @@
805 if( rid==0 && !isNew ){
806 g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;
807 fossil_fatal("no such wiki page: %s", zPageName);
808 }
809 if( rid!=0 && isNew ){
810 g.json.resultCode = FSL_JSON_E_DENIED/*need a better code for this*/;
811 fossil_fatal("wiki page %s already exists", zPageName);
812 }
813
814 blob_zero(&wiki);
815 zDate = date_in_standard_format("now");
816
--- src/wiki.c
+++ src/wiki.c
@@ -805,11 +805,11 @@
805 if( rid==0 && !isNew ){
806 g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;
807 fossil_fatal("no such wiki page: %s", zPageName);
808 }
809 if( rid!=0 && isNew ){
810 g.json.resultCode = FSL_JSON_E_RESOURCE_ALREADY_EXISTS;
811 fossil_fatal("wiki page %s already exists", zPageName);
812 }
813
814 blob_zero(&wiki);
815 zDate = date_in_standard_format("now");
816

Keyboard Shortcuts

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