Fossil

Check-in [afb3c89f]
Login

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

Overview
Comment:A few internal cosmetic cleanups, added json_get_wiki_page_by_rid().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | json-multitag-test | json
Files: files | file ages | folders
SHA1: afb3c89fe6beee621a18d212eee9be83f7cbf73d
User & Date: stephan 2011-10-05 06:42:17
Context
2011-10-05
07:01
fixed a url-updating problem caused by recent refactoring. check-in: 4b708534 user: stephan tags: json-multitag-test, json
06:42
A few internal cosmetic cleanups, added json_get_wiki_page_by_rid(). check-in: afb3c89f user: stephan tags: json-multitag-test, json
05:41
Tweaks to the JS API, mainly to simplify a common 2-callbacks-per-event use case. Added missing json2.js. check-in: cf10d9d9 user: stephan tags: json-multitag-test, json
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ajax/index.html.

181
182
183
184
185
186
187





188
189
190
191
192
193
194
195

196
197
198
199
200
201
202

203
204
205
206
207
208
209
...
219
220
221
222
223
224
225

226

227
228
229
230
231
232
233
      TheApp.jqe.currentAuthToken.html("Logged in: "+WhAjaj.stringify(this.auth));
    };
    TheApp.cgi.onLogout = function(){
      TheApp.jqe.taResponse.val( "Logged out!" );
      TheApp.jqe.currentAuthToken.text("Not logged in");
    };
    TheApp.cgi.whoami();





});

</script>

</head>

<body>
<span id='ajaxNotification'></span>

<h1>You know, for sending raw JSON requests to Fossil...</h1>

If you're actually using this page, then you know what you're doing and don't
need help text, hoverhelp, and a snazzy interface.

<br><br>
See also: <a href='wiki-editor.html'>prototype wiki editor</a>.


<h2>Request...</h2>

Path: <input type='text' size='40' id='textPath' value='/json/HAI'/>
<input type='button' value='Send...' id='btnSend' onclick='TheApp.sendRequest()' /><br/>
If the POST textarea is not empty then it will be posted with the request.
<hr/>
................................................................................
<input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci?files=true")' />
<input type='button' value='timeline/wiki' onclick='TheApp.cgi.sendCommand("/json/timeline/wiki")' />
<input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
<input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
<input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{page:"Fossil"})' />
<input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
<input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />

<input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' />


<!--
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
<input type='button' value='get more' onclick='TheApp.cgi.getPages("HelloWorld/WhikiNews")' />
<input type='button' value='get client data' onclick='TheApp.cgi.getPageClientData("HelloWorld/whiki/WhikiCommands")' />
<input type='button' value='save client data' onclick='TheApp.cgi.savePageClientData({"HelloWorld":[1,3,5]})' />
-->







>
>
>
>
>








>







>







 







>

>







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
      TheApp.jqe.currentAuthToken.html("Logged in: "+WhAjaj.stringify(this.auth));
    };
    TheApp.cgi.onLogout = function(){
      TheApp.jqe.taResponse.val( "Logged out!" );
      TheApp.jqe.currentAuthToken.text("Not logged in");
    };
    TheApp.cgi.whoami();
    jQuery('#headerArea').click(function(){
        jQuery(this).slideUp('fast',function(){
            jQuery(this).remove();
        });
    });
});

</script>

</head>

<body>
<span id='ajaxNotification'></span>
<div id='headerArea'>
<h1>You know, for sending raw JSON requests to Fossil...</h1>

If you're actually using this page, then you know what you're doing and don't
need help text, hoverhelp, and a snazzy interface.

<br><br>
See also: <a href='wiki-editor.html'>prototype wiki editor</a>.
</div><!-- #headerArea -->

<h2>Request...</h2>

Path: <input type='text' size='40' id='textPath' value='/json/HAI'/>
<input type='button' value='Send...' id='btnSend' onclick='TheApp.sendRequest()' /><br/>
If the POST textarea is not empty then it will be posted with the request.
<hr/>
................................................................................
<input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci?files=true")' />
<input type='button' value='timeline/wiki' onclick='TheApp.cgi.sendCommand("/json/timeline/wiki")' />
<input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
<input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
<input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{page:"Fossil"})' />
<input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
<input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
<!-- not yet ready...
<input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' />
-->

<!--
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
<input type='button' value='get more' onclick='TheApp.cgi.getPages("HelloWorld/WhikiNews")' />
<input type='button' value='get client data' onclick='TheApp.cgi.getPageClientData("HelloWorld/whiki/WhikiCommands")' />
<input type='button' value='save client data' onclick='TheApp.cgi.savePageClientData({"HelloWorld":[1,3,5]})' />
-->

Changes to ajax/js/whajaj.js.

205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
...
404
405
406
407
408
409
410





























411
412
413
414
415
416
417
...
419
420
421
422
423
424
425

426
427
428
429
430
431
432
...
530
531
532
533
534
535
536



537
538
539
540
541
542
543
...
619
620
621
622
623
624
625



626
627
628
629
630
631
632
    apps unduly).
*/
WhAjaj.Connector = function(opt)
{
    if(WhAjaj.isObject(opt)) this.options = opt;
    //TODO?: this.$cache = {};
};
WhAjaj.Connector.prototype.callbacks = {};
WhAjaj.Connector.prototype.options = {};

/**
    The core options used by WhAjaj.Connector instances for performing
    network operations. These options can (and some _should_)
    be changed by a client application. They can also be changed
    on specific instances of WhAjaj.Connector, but for most applications
    it is simpler to set them here and not have to bother with configuring
................................................................................
        TODO: rename this to 'ajaj' (the name is historical). The 
        problem with renaming it is is that the word 'ajax' is 
        pretty prevelant in the source tree, so i can't globally 
        swap it out.
    */
    ajax: {
        /**
            URL of the whiki back-end CGI binary.
        */
        url: '/some/path',

        /**
            Connection method. Some connection-related functions might
            override any client-defined setting.
            
................................................................................
            construct and eval()s it after afterSend() but before onResponse().
            In this case, onResponse() will get a string value for the response
            instead of a response object parsed from JSON. 
        */
        jsonp:undefined
    }
};






























/**
    Tries to find the given key in any of the following, returning
    the first match found: opt, this.options, WhAjaj.Connector.options.ajax.

    Returns undefined if key is not found.
*/
................................................................................
    var v = opt ? opt[key] : undefined;
    if( undefined !== v ) return v;
    else v = this.options[key];
    if( undefined !== v ) return v;
    else v = WhAjaj.Connector.options.ajax[key];
    return v;
};

/**
    Returns a unique string on each call containing a generic 
    reandom request identifier string. This is not used by the core 
    API but can be used by client code to generate unique IDs for 
    each request (if needed).

    The exact format is unspecified and may change in the future.
................................................................................
        the sendImpl() function. It may legally be null for GET requests.
        
        The opt object should be the normalized AJAX options used 
        for the connection.
        
        The resp argument may be either a plain Object or a string 
        (in which case it is assumed to be JSON).



        
        This function takes care of the following:
        
        - Calling opt.afterSend()
        
        - If resp is a string, de-JSON-izing it to an object.
        
................................................................................
        reached). This function takes care of most of ensuring that
        framework-level conventions involving WhAjaj.Connector.options.ajax
        properties are followed.
        
        The request argument must be the original request passed to 
        the sendImpl() function. It may legally be null for GET 
        requests.



        
        The opt object should be the normalized AJAX options used 
        for the connection. By convention, the caller of this 
        function "should" set opt.errorMessage to contain a 
        human-readable description of the error.
        
        The sendImpl() should return immediately after calling this. The







<
<







 







|







 







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







 







>







 







>
>
>







 







>
>
>







205
206
207
208
209
210
211


212
213
214
215
216
217
218
...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
...
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
    apps unduly).
*/
WhAjaj.Connector = function(opt)
{
    if(WhAjaj.isObject(opt)) this.options = opt;
    //TODO?: this.$cache = {};
};



/**
    The core options used by WhAjaj.Connector instances for performing
    network operations. These options can (and some _should_)
    be changed by a client application. They can also be changed
    on specific instances of WhAjaj.Connector, but for most applications
    it is simpler to set them here and not have to bother with configuring
................................................................................
        TODO: rename this to 'ajaj' (the name is historical). The 
        problem with renaming it is is that the word 'ajax' is 
        pretty prevelant in the source tree, so i can't globally 
        swap it out.
    */
    ajax: {
        /**
            URL of the back-end server/CGI.
        */
        url: '/some/path',

        /**
            Connection method. Some connection-related functions might
            override any client-defined setting.
            
................................................................................
            construct and eval()s it after afterSend() but before onResponse().
            In this case, onResponse() will get a string value for the response
            instead of a response object parsed from JSON. 
        */
        jsonp:undefined
    }
};


/**
    WhAjaj.Connector.prototype.callbacks defines callbacks analog
    to the onXXX callbacks defined in WhAjaj.Connector.options.ajax,
    with two notable differences:

    1) these callbacks, if set, are called in addition to any
    request-specific callback. The intention is to allow a framework to set
    "framework-level" callbacks which should be called independently of the
    request-specific callbacks (without interfering with them, e.g.
    requiring special re-forwarding features).

    2) The 'this' object in these callbacks is the Connector instance
    associated with the callback, whereas the "other" onXXX form has its
    "ajax options" object as its this.

    When this API says that an onXXX callback will be called for a request,
    both the request's onXXX (if set) and this one (if set) will be called.
*/
WhAjaj.Connector.prototype.callbacks = {};
/**
    Instance-specific values for AJAJ-level properties (as opposed to
    application-level request properties). Options set here "override" those
    specified in WhAjaj.Connector.options.ajax and are "overridden" by
    options passed to sendRequest().
*/
WhAjaj.Connector.prototype.options = {};


/**
    Tries to find the given key in any of the following, returning
    the first match found: opt, this.options, WhAjaj.Connector.options.ajax.

    Returns undefined if key is not found.
*/
................................................................................
    var v = opt ? opt[key] : undefined;
    if( undefined !== v ) return v;
    else v = this.options[key];
    if( undefined !== v ) return v;
    else v = WhAjaj.Connector.options.ajax[key];
    return v;
};

/**
    Returns a unique string on each call containing a generic 
    reandom request identifier string. This is not used by the core 
    API but can be used by client code to generate unique IDs for 
    each request (if needed).

    The exact format is unspecified and may change in the future.
................................................................................
        the sendImpl() function. It may legally be null for GET requests.
        
        The opt object should be the normalized AJAX options used 
        for the connection.
        
        The resp argument may be either a plain Object or a string 
        (in which case it is assumed to be JSON).

        The 'this' object for this call MUST be a WhAjaj.Connector
        instance in order for callback processing to work properly.
        
        This function takes care of the following:
        
        - Calling opt.afterSend()
        
        - If resp is a string, de-JSON-izing it to an object.
        
................................................................................
        reached). This function takes care of most of ensuring that
        framework-level conventions involving WhAjaj.Connector.options.ajax
        properties are followed.
        
        The request argument must be the original request passed to 
        the sendImpl() function. It may legally be null for GET 
        requests.

        The 'this' object for this call MUST be a WhAjaj.Connector
        instance in order for callback processing to work properly.
        
        The opt object should be the normalized AJAX options used 
        for the connection. By convention, the caller of this 
        function "should" set opt.errorMessage to contain a 
        human-readable description of the error.
        
        The sendImpl() should return immediately after calling this. The

Changes to ajax/wiki-editor.html.

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
188
189
190
191
192
193
194
195
...
306
307
308
309
310
311
312


313
314
315
316
317
318
319
...
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
            this._tstart = (new Date()).getTime();
        },
        end:function(){
            this._tend = (new Date()).getTime();
            return this.duration = this._tend - this._tstart;
        }
    };
    var opt = TheApp.cgi.ajaj.options;
    opt.beforeSend = TheApp.beforeSend = function(req,opt) {
        TheApp.timer.start();
        var val =
            req ?
            (('string'===typeof req) ? req : WhAjaj.stringify(req))
            : '';
        TheApp.jqe.taResponse.val('');
        TheApp.startAjaxNotif();
    };
    opt.afterSend = TheApp.afterSend = function(req,opt) {
        TheApp.timer.end();
        TheApp.endAjaxNotif();
        TheApp.jqe.timer.text( "(Round-trip time: "+TheApp.timer.duration+'ms)' );
    };
    opt.onResponse = TheApp.onResponse = function(resp,req) {
        var val;
        try {
            val = WhAjaj.stringify(resp);
        }
        catch(e) {
            val = WhAjaj.stringify(e)
        }
        if(resp.resultCode){
            alert("Response contains error info:\n"+val);
        }
        //alert("onResponse this:"+WhAjaj.stringify(this));
        //alert("val="+val);
        // FIXME: this.url is hosed for login because of how i overload onResponse()
        if( this.url ) TheApp.jqe.textPath.val(this.url.replace(WhAjaj.Connector.options.ajax.url,''));
        TheApp.jqe.taResponse.val( val );
    };
    opt.onError = function(req,opt) {
        TheApp.jqe.taResponse.val( "ERROR SENDING REQUEST:\n"+WhAjaj.stringify(opt) );
    };

    TheApp.jqe.taPageContent.blur(function(){
        var p = TheApp.currentPage;
        if(! p ) return;
        p.content = TheApp.jqe.taPageContent.val();
    });

    TheApp.cgi.onLogin = function(){
      TheApp.jqe.taResponse.val( "Logged in. Auth token =\n"+this.authToken );
      TheApp.jqe.currentAuthToken.text("Auth token: "+(this.authToken || "not logged in"));
    };
    TheApp.cgi.onLogout = function(){
      TheApp.jqe.taResponse.val( "Logged out!" );
      TheApp.jqe.currentAuthToken.text("");
    };

    TheApp.showPage = function(name){
................................................................................
                TheApp.pages[p.name] = p;
                TheApp.refreshPageListView();
            }
        });
*/
    };



});

</script>

</head>

<body>
................................................................................

<br/>
<span id='currentAuthToken' style='font-family:monospaced'></span>

<hr/>
<strong>Quick-posts:</strong><br/>
<input type='button' value='HAI' onclick='TheApp.cgi.HAI()' />
<input type='button' value='version' onclick='TheApp.cgi.sendCommand("/json/version")' />
<input type='button' value='stat' onclick='TheApp.cgi.sendCommand("/json/stat")' />
<input type='button' value='whoami' onclick='TheApp.cgi.sendCommand("/json/whoami")' />
<input type='button' value='cap' onclick='TheApp.cgi.sendCommand("/json/cap")' />
<input type='button' value='wiki/list' onclick='TheApp.loadPageList()' />
<!--
<input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci")' />
-->

<!--
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />







|
|








|




|










<
<
<
<


|










|
|







 







>
>







 







<


<







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
188
189
190
191
...
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
332
333
334
335
336
337
338

339
340

341
342
343
344
345
346
347
            this._tstart = (new Date()).getTime();
        },
        end:function(){
            this._tend = (new Date()).getTime();
            return this.duration = this._tend - this._tstart;
        }
    };
    var ajcb = TheApp.cgi.ajaj.callbacks;
    ajcb.beforeSend = TheApp.beforeSend = function(req,opt) {
        TheApp.timer.start();
        var val =
            req ?
            (('string'===typeof req) ? req : WhAjaj.stringify(req))
            : '';
        TheApp.jqe.taResponse.val('');
        TheApp.startAjaxNotif();
    };
    ajcb.afterSend = TheApp.afterSend = function(req,opt) {
        TheApp.timer.end();
        TheApp.endAjaxNotif();
        TheApp.jqe.timer.text( "(Round-trip time: "+TheApp.timer.duration+'ms)' );
    };
    ajcb.onResponse = TheApp.onResponse = function(resp,req) {
        var val;
        try {
            val = WhAjaj.stringify(resp);
        }
        catch(e) {
            val = WhAjaj.stringify(e)
        }
        if(resp.resultCode){
            alert("Response contains error info:\n"+val);
        }




        TheApp.jqe.taResponse.val( val );
    };
    ajcb.onError = function(req,opt) {
        TheApp.jqe.taResponse.val( "ERROR SENDING REQUEST:\n"+WhAjaj.stringify(opt) );
    };

    TheApp.jqe.taPageContent.blur(function(){
        var p = TheApp.currentPage;
        if(! p ) return;
        p.content = TheApp.jqe.taPageContent.val();
    });

    TheApp.cgi.onLogin = function(){
      TheApp.jqe.taResponse.val( "Logged in: "+WhAjaj.stringify(this.auth));
      TheApp.jqe.currentAuthToken.text("Logged in: "+WhAjaj.stringify(this.auth));
    };
    TheApp.cgi.onLogout = function(){
      TheApp.jqe.taResponse.val( "Logged out!" );
      TheApp.jqe.currentAuthToken.text("");
    };

    TheApp.showPage = function(name){
................................................................................
                TheApp.pages[p.name] = p;
                TheApp.refreshPageListView();
            }
        });
*/
    };

    TheApp.cgi.whoami();

});

</script>

</head>

<body>
................................................................................

<br/>
<span id='currentAuthToken' style='font-family:monospaced'></span>

<hr/>
<strong>Quick-posts:</strong><br/>
<input type='button' value='HAI' onclick='TheApp.cgi.HAI()' />

<input type='button' value='stat' onclick='TheApp.cgi.sendCommand("/json/stat")' />
<input type='button' value='whoami' onclick='TheApp.cgi.sendCommand("/json/whoami")' />

<input type='button' value='wiki/list' onclick='TheApp.loadPageList()' />
<!--
<input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci")' />
-->

<!--
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />

Changes to src/json.c.

1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
      }
    }
    tmp = json_new_string(json_rc_cstr(resultCode));
    SET(FossilJsonKeys.resultCode);
  }

  if( pMsg && *pMsg ){
    tmp = cson_value_new_string(pMsg, strlen(pMsg));
    SET(FossilJsonKeys.resultText);
  }

  if(g.json.cmd.commandStr){
    tmp = json_new_string(g.json.cmd.commandStr);
    SET("command");
  }







|







1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
      }
    }
    tmp = json_new_string(json_rc_cstr(resultCode));
    SET(FossilJsonKeys.resultCode);
  }

  if( pMsg && *pMsg ){
    tmp = json_new_string(pMsg);
    SET(FossilJsonKeys.resultText);
  }

  if(g.json.cmd.commandStr){
    tmp = json_new_string(g.json.cmd.commandStr);
    SET("command");
  }

Changes to src/json_artifact.c.

151
152
153
154
155
156
157



158
159
160
161
162
163
164
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

#undef SET
  }
  db_finalize(&q);
  return v;
}




cson_value * json_artifact_ticket( int rid ){
  cson_value * payV = NULL;
  cson_object * pay = NULL;
  Manifest *pTktChng = NULL;
  static cson_value * eventTypeLabel = NULL;
  if(! g.perm.RdTkt ){
    g.json.resultCode = FSL_JSON_E_DENIED;
................................................................................
    return NULL;
  }else{
    return json_artifact_for_ci(rid, 1);
  }
}

/*
** Permissions callback func for ArtifactDispatchEntry.
*/
static char perms_can_read(){
  return g.perm.Read ? 1 : 0;
}

static ArtifactDispatchEntry ArtifactDispatchList[] = {
{"checkin", json_artifact_ci},
{"tag", NULL},
{"ticket", json_artifact_ticket},
{"wiki", NULL},
/* Final entry MUST have a NULL name. */
{NULL,NULL}







>
>
>







 







|

<
<
<
<







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
...
196
197
198
199
200
201
202
203
204




205
206
207
208
209
210
211

#undef SET
  }
  db_finalize(&q);
  return v;
}

/*
** Very incomplete/incorrect impl of /json/artifact/TICKET_ID.
*/
cson_value * json_artifact_ticket( int rid ){
  cson_value * payV = NULL;
  cson_object * pay = NULL;
  Manifest *pTktChng = NULL;
  static cson_value * eventTypeLabel = NULL;
  if(! g.perm.RdTkt ){
    g.json.resultCode = FSL_JSON_E_DENIED;
................................................................................
    return NULL;
  }else{
    return json_artifact_for_ci(rid, 1);
  }
}

/*
** Internal mapping of /json/artifact/FOO commands/callbacks.
*/




static ArtifactDispatchEntry ArtifactDispatchList[] = {
{"checkin", json_artifact_ci},
{"tag", NULL},
{"ticket", json_artifact_ticket},
{"wiki", NULL},
/* Final entry MUST have a NULL name. */
{NULL,NULL}

Changes to src/json_wiki.c.

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
...
115
116
117
118
119
120
121

























122
123
124
125
126
127
128
...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
** of it. If the page is not found then NULL is returned. If doParse
** is true then the page content is HTML-ized using fossil's
** conventional wiki format, else it is not parsed.
**
** The returned value, if not NULL, is-a JSON Object owned by the
** caller.
*/
cson_value * json_get_wiki_page(char const * zPageName, char doParse){
  int rid;
  Manifest *pWiki = 0;
  char const * zBody = NULL;
  char const * zFormat = NULL;
  char * zUuid = NULL;
  Stmt q;
  db_prepare(&q,
................................................................................
    /*TODO: add 'T' (tag) fields*/
    /*TODO: add the 'A' card (file attachment) entries?*/
    manifest_destroy(pWiki);
    return payV;
  }
}


























/*
** Implementation of /json/wiki/get.
**
*/
static cson_value * json_wiki_get(){
  int rid;
  Manifest *pWiki = 0;
................................................................................
  zFormat = json_find_option_cstr("format",NULL,"f");
  if(!zFormat || !*zFormat){
    zFormat = "raw";
  }
  if( 'r' != *zFormat ){
    zFormat = "html";
  }
  return json_get_wiki_page(zPageName, 'h'==*zFormat);
}

/*
** Internal impl of /wiki/save and /wiki/create. If createMode is 0
** and the page already exists then a
** FSL_JSON_E_RESOURCE_ALREADY_EXISTS error is triggered.  If
** createMode is false then the FSL_JSON_E_RESOURCE_NOT_FOUND is







|







 







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







 







|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
...
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
...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
** of it. If the page is not found then NULL is returned. If doParse
** is true then the page content is HTML-ized using fossil's
** conventional wiki format, else it is not parsed.
**
** The returned value, if not NULL, is-a JSON Object owned by the
** caller.
*/
cson_value * json_get_wiki_page_by_name(char const * zPageName, char doParse){
  int rid;
  Manifest *pWiki = 0;
  char const * zBody = NULL;
  char const * zFormat = NULL;
  char * zUuid = NULL;
  Stmt q;
  db_prepare(&q,
................................................................................
    /*TODO: add 'T' (tag) fields*/
    /*TODO: add the 'A' card (file attachment) entries?*/
    manifest_destroy(pWiki);
    return payV;
  }
}


/*
** UNTESTED!
**
** Searches for a wiki page with the given rid. If found it behaves
** like json_get_wiki_page_by_name(pageName, doParse), else it returns
** NULL.
*/
cson_value * json_get_wiki_page_by_rid(int rid, char doParse){
  char * zPageName = NULL;
  cson_value * rc = NULL;
  zPageName = db_text(NULL,
                      "SELECT substr(t.tagname,6) AS name "
                      " FROM tag t, tagxref x, blob b "
                      " WHERE b.rid=%d "
                      " AND t.tagname GLOB 'wiki-*'"
                      " AND x.tagid=t.tagid AND b.rid=x.rid ",
                      rid);
  if( zPageName ){
    rc = json_get_wiki_page_by_name(zPageName, doParse);
    free(zPageName);
  }
  return rc;
}

/*
** Implementation of /json/wiki/get.
**
*/
static cson_value * json_wiki_get(){
  int rid;
  Manifest *pWiki = 0;
................................................................................
  zFormat = json_find_option_cstr("format",NULL,"f");
  if(!zFormat || !*zFormat){
    zFormat = "raw";
  }
  if( 'r' != *zFormat ){
    zFormat = "html";
  }
  return json_get_wiki_page_by_name(zPageName, 'h'==*zFormat);
}

/*
** Internal impl of /wiki/save and /wiki/create. If createMode is 0
** and the page already exists then a
** FSL_JSON_E_RESOURCE_ALREADY_EXISTS error is triggered.  If
** createMode is false then the FSL_JSON_E_RESOURCE_NOT_FOUND is