Fossil SCM

Changed fossil_json_f() callback interface. Refactored json command dispatching a bit. Fixed an ordering problem in the json timelines. Pulled in latest cson_amalgamation.

stephan 2011-09-23 10:52 UTC json
Commit c24b44501290ad103bd73ed3ee8b0f36fff6d802
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -2435,13 +2435,13 @@
24352435
#if CSON_VOID_PTR_IS_BIG
24362436
cson_value_clean( val );
24372437
val->value = (void *)v;
24382438
#else
24392439
cson_int_t * iv = NULL;
2440
- cson_value_clean( val );
24412440
iv = (cson_int_t*)cson_malloc(sizeof(cson_int_t), "cson_int_t");
24422441
if( ! iv ) return cson_rc.AllocError;
2442
+ cson_value_clean( val );
24432443
*iv = v;
24442444
val->value = iv;
24452445
#endif
24462446
val->api = &cson_value_api_integer;
24472447
return 0;
24482448
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -2435,13 +2435,13 @@
2435 #if CSON_VOID_PTR_IS_BIG
2436 cson_value_clean( val );
2437 val->value = (void *)v;
2438 #else
2439 cson_int_t * iv = NULL;
2440 cson_value_clean( val );
2441 iv = (cson_int_t*)cson_malloc(sizeof(cson_int_t), "cson_int_t");
2442 if( ! iv ) return cson_rc.AllocError;
 
2443 *iv = v;
2444 val->value = iv;
2445 #endif
2446 val->api = &cson_value_api_integer;
2447 return 0;
2448
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -2435,13 +2435,13 @@
2435 #if CSON_VOID_PTR_IS_BIG
2436 cson_value_clean( val );
2437 val->value = (void *)v;
2438 #else
2439 cson_int_t * iv = NULL;
 
2440 iv = (cson_int_t*)cson_malloc(sizeof(cson_int_t), "cson_int_t");
2441 if( ! iv ) return cson_rc.AllocError;
2442 cson_value_clean( val );
2443 *iv = v;
2444 val->value = iv;
2445 #endif
2446 val->api = &cson_value_api_integer;
2447 return 0;
2448
+45 -53
--- src/json.c
+++ src/json.c
@@ -58,21 +58,10 @@
5858
** payload. If g.json.resultCode is non-zero when this function
5959
** returns then the top-level dispatcher will destroy any payload
6060
** returned by this function and will output a JSON error response
6161
** instead.
6262
**
63
-** The depth parameter comes from the dispatcher and tells the
64
-** callback what index in json_command_arg() its command/path starts.
65
-** e.g. when dispatching /json/foo/bar, the foo callback will get a
66
-** depth of 1 and the bar callback will get a depth of 2. This is only
67
-** useful for callbacks which use json_command_arg(), and the only
68
-** callbacks which do that are ones which dispatch to sub-pages
69
-** (e.g. /json/wiki/...). This is a parameter, as opposed to simply
70
-** hard-coding the offset in each callback impl, so that refactoring
71
-** will (or should) be easier if we later reimplement the path/command
72
-** handling and arguments/path parts get moved around.
73
-**
7463
** All of the setup/response code is handled by the top dispatcher
7564
** functions and the callbacks concern themselves only with generating
7665
** the payload.
7766
**
7867
** It is imperitive that NO callback functions EVER output ANYTHING to
@@ -80,11 +69,11 @@
8069
** almost certainly will corrupt any HTTP response headers. Output
8170
** sent to stderr ends up in my apache log, so that might be useful
8271
** for debuggering in some cases, but so such code should be left
8372
** enabled for non-debuggering builds.
8473
*/
85
-typedef cson_value * (*fossil_json_f)(unsigned int depth);
74
+typedef cson_value * (*fossil_json_f)();
8675
8776
/*
8877
** Internal helpers to manipulate a byte array as a bitset. The B
8978
** argument must be-a array at least (BIT/8+1) bytes long.
9079
** The BIT argument is the bit number to query/set/clear/toggle.
@@ -98,11 +87,11 @@
9887
9988
/*
10089
** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
10190
** (but planned) pages/commands.
10291
*/
103
-static cson_value * json_page_nyi(unsigned int depth){
92
+static cson_value * json_page_nyi(){
10493
g.json.resultCode = FSL_JSON_E_NYI;
10594
return NULL;
10695
}
10796
10897
/*
@@ -1189,11 +1178,11 @@
11891178
/*
11901179
** /json/version implementation.
11911180
**
11921181
** Returns the payload object (owned by the caller).
11931182
*/
1194
-cson_value * json_page_version(unsigned int depth){
1183
+cson_value * json_page_version(){
11951184
cson_value * jval = NULL;
11961185
cson_object * jobj = NULL;
11971186
jval = cson_value_new_object();
11981187
jobj = cson_value_get_object(jval);
11991188
#define FSET(X,K) cson_object_set( jobj, K, cson_value_new_string(X,strlen(X)))
@@ -1218,11 +1207,11 @@
12181207
** current user (what he may/may not do).
12191208
**
12201209
** This is primarily intended for debuggering, but may have
12211210
** a use in client code. (?)
12221211
*/
1223
-cson_value * json_page_cap(unsigned int depth){
1212
+cson_value * json_page_cap(){
12241213
cson_value * payload = cson_value_new_object();
12251214
cson_value * sub = cson_value_new_object();
12261215
Stmt q;
12271216
cson_object * obj = cson_value_get_object(payload);
12281217
db_prepare(&q, "SELECT login, cap FROM user WHERE uid=%d", g.userUid);
@@ -1274,11 +1263,11 @@
12741263
12751264
/*
12761265
** Implementation of the /json/login page.
12771266
**
12781267
*/
1279
-cson_value * json_page_login(unsigned int depth){
1268
+cson_value * json_page_login(){
12801269
static char preciseErrors = /* if true, "complete" JSON error codes are used,
12811270
else they are "dumbed down" to a generic login
12821271
error code.
12831272
*/
12841273
#if 0
@@ -1404,11 +1393,11 @@
14041393
14051394
/*
14061395
** Impl of /json/logout.
14071396
**
14081397
*/
1409
-cson_value * json_page_logout(unsigned int depth){
1398
+cson_value * json_page_logout(){
14101399
cson_value const *token = g.json.authToken;
14111400
/* Remember that json_mode_bootstrap() replaces the login cookie
14121401
with the JSON auth token if the request contains it. If the
14131402
reqest is missing the auth token then this will fetch fossil's
14141403
original cookie. Either way, it's what we want :).
@@ -1429,11 +1418,11 @@
14291418
}
14301419
14311420
/*
14321421
** Implementation of the /json/anonymousPassword page.
14331422
*/
1434
-cson_value * json_page_anon_password(unsigned int depth){
1423
+cson_value * json_page_anon_password(){
14351424
cson_value * v = cson_value_new_object();
14361425
cson_object * o = cson_value_get_object(v);
14371426
unsigned const int seed = captcha_seed();
14381427
char const * zCaptcha = captcha_decode(seed);
14391428
cson_object_set(o, "seed",
@@ -1448,11 +1437,11 @@
14481437
14491438
/*
14501439
** Implementation of the /json/stat page/command.
14511440
**
14521441
*/
1453
-cson_value * json_page_stat(unsigned int depth){
1442
+cson_value * json_page_stat(){
14541443
i64 t, fsize;
14551444
int n, m;
14561445
const char *zDb;
14571446
enum { BufLen = 1000 };
14581447
char zBuf[BufLen];
@@ -1543,14 +1532,14 @@
15431532
return jv;
15441533
#undef SETBUF
15451534
}
15461535
15471536
1548
-static cson_value * json_wiki_list(unsigned int depth);
1549
-static cson_value * json_wiki_get(unsigned int depth);
1550
-static cson_value * json_wiki_save(unsigned int depth);
1551
-static cson_value * json_wiki_create(unsigned int depth);
1537
+static cson_value * json_wiki_list();
1538
+static cson_value * json_wiki_get();
1539
+static cson_value * json_wiki_save();
1540
+static cson_value * json_wiki_create();
15521541
15531542
/*
15541543
** Mapping of /json/wiki/XXX commands/paths to callbacks.
15551544
*/
15561545
static const JsonPageDef JsonPageDefs_Wiki[] = {
@@ -1567,21 +1556,21 @@
15671556
** depth should be the depth parameter passed to the fossil_json_f().
15681557
** pages must be an array of JsonPageDef commands which we can
15691558
** dispatch. The final item in the array MUST have a NULL name
15701559
** element.
15711560
**
1572
-** This function takes json_comand_arg(1+depth) and searches pages
1573
-** for a matching name. If found then that page's func() is called
1574
-** to fetch the payload, which is returned to the caller.
1561
+** This function takes json_comand_arg(1+g.json.dispatchDepth) and
1562
+** searches pages for a matching name. If found then that page's
1563
+** func() is called to fetch the payload, which is returned to the
1564
+** caller.
15751565
**
15761566
** On error, g.json.resultCode is set to one of the FossilJsonCodes
15771567
** values.
15781568
*/
1579
-static cson_value * json_page_dispatch_helper(unsigned int depth,
1580
- JsonPageDef const * pages){
1569
+static cson_value * json_page_dispatch_helper(JsonPageDef const * pages){
15811570
JsonPageDef const * def;
1582
- char const * cmd = json_command_arg(1+depth);
1571
+ char const * cmd = json_command_arg(1+g.json.dispatchDepth);
15831572
assert( NULL != pages );
15841573
if( ! cmd ){
15851574
g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
15861575
return NULL;
15871576
}
@@ -1589,31 +1578,32 @@
15891578
if(!def){
15901579
g.json.resultCode = FSL_JSON_E_UNKNOWN_COMMAND;
15911580
return NULL;
15921581
}
15931582
else{
1594
- return (*def->func)(1+depth);
1583
+ ++g.json.dispatchDepth;
1584
+ return (*def->func)();
15951585
}
15961586
}
15971587
15981588
/*
15991589
** Implements the /json/wiki family of pages/commands. Far from
16001590
** complete.
16011591
**
16021592
*/
1603
-static cson_value * json_page_wiki(unsigned int depth){
1604
- return json_page_dispatch_helper(depth,&JsonPageDefs_Wiki[0]);
1593
+static cson_value * json_page_wiki(){
1594
+ return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
16051595
}
16061596
16071597
16081598
/*
16091599
** Implementation of /json/wiki/get.
16101600
**
16111601
** TODO: add option to parse wiki output. It is currently
16121602
** unparsed.
16131603
*/
1614
-static cson_value * json_wiki_get(unsigned int depth){
1604
+static cson_value * json_wiki_get(){
16151605
int rid;
16161606
Manifest *pWiki = 0;
16171607
char const * zBody = NULL;
16181608
char const * zPageName;
16191609
char doParse = 0/*not yet implemented*/;
@@ -1764,26 +1754,26 @@
17641754
}
17651755
17661756
/*
17671757
** Implementation of /json/wiki/create.
17681758
*/
1769
-static cson_value * json_wiki_create(unsigned int depth){
1759
+static cson_value * json_wiki_create(){
17701760
return json_wiki_create_or_save(1);
17711761
}
17721762
17731763
/*
17741764
** Implementation of /json/wiki/save.
17751765
*/
1776
-static cson_value * json_wiki_save(unsigned int depth){
1766
+static cson_value * json_wiki_save(){
17771767
/* FIXME: add GET/POST.payload bool option createIfNotExists. */
17781768
return json_wiki_create_or_save(0);
17791769
}
17801770
17811771
/*
17821772
** Implementation of /json/wiki/list.
17831773
*/
1784
-static cson_value * json_wiki_list(unsigned int depth){
1774
+static cson_value * json_wiki_list(){
17851775
cson_value * listV = NULL;
17861776
cson_array * list = NULL;
17871777
Stmt q;
17881778
if( !g.perm.RdWiki ){
17891779
g.json.resultCode = FSL_JSON_E_DENIED;
@@ -1813,11 +1803,11 @@
18131803
db_finalize(&q);
18141804
return listV;
18151805
}
18161806
18171807
1818
-static cson_value * json_branch_list(unsigned int depth);
1808
+static cson_value * json_branch_list();
18191809
/*
18201810
** Mapping of /json/branch/XXX commands/paths to callbacks.
18211811
*/
18221812
static const JsonPageDef JsonPageDefs_Branch[] = {
18231813
{"list", json_branch_list, 0},
@@ -1829,12 +1819,12 @@
18291819
/*
18301820
** Implements the /json/branch family of pages/commands. Far from
18311821
** complete.
18321822
**
18331823
*/
1834
-static cson_value * json_page_branch(unsigned int depth){
1835
- return json_page_dispatch_helper(depth,&JsonPageDefs_Branch[0]);
1824
+static cson_value * json_page_branch(){
1825
+ return json_page_dispatch_helper(&JsonPageDefs_Branch[0]);
18361826
}
18371827
18381828
/*
18391829
** Impl for /json/branch/list
18401830
**
@@ -1849,11 +1839,11 @@
18491839
** HTTP mode options:
18501840
**
18511841
** "range" GET/POST.payload parameter. FIXME: currently we also use
18521842
** POST, but really want to restrict this to POST.payload.
18531843
*/
1854
-static cson_value * json_branch_list(unsigned int depth){
1844
+static cson_value * json_branch_list(){
18551845
cson_value * payV;
18561846
cson_object * pay;
18571847
cson_value * listV;
18581848
cson_array * list;
18591849
char const * range = NULL;
@@ -1930,12 +1920,12 @@
19301920
}
19311921
}
19321922
return payV;
19331923
}
19341924
1935
-static cson_value * json_timeline_ci(unsigned int depth);
1936
-static cson_value * json_timeline_wiki(unsigned int depth);
1925
+static cson_value * json_timeline_ci();
1926
+static cson_value * json_timeline_wiki();
19371927
/*
19381928
** Mapping of /json/timeline/XXX commands/paths to callbacks.
19391929
*/
19401930
static const JsonPageDef JsonPageDefs_Timeline[] = {
19411931
{"ci", json_timeline_ci, 0},
@@ -1947,12 +1937,12 @@
19471937
/*
19481938
** Implements the /json/timeline family of pages/commands. Far from
19491939
** complete.
19501940
**
19511941
*/
1952
-static cson_value * json_page_timeline(unsigned int depth){
1953
- return json_page_dispatch_helper(depth,&JsonPageDefs_Timeline[0]);
1942
+static cson_value * json_page_timeline(){
1943
+ return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]);
19541944
}
19551945
19561946
/*
19571947
** Create a temporary table suitable for storing timeline data.
19581948
*/
@@ -2013,11 +2003,11 @@
20132003
** of the "after" ("a") or "before" ("b") environment parameters.
20142004
** This function gives "after" precedence over "before", and only
20152005
** applies one of them.
20162006
**
20172007
** Returns -1 if it adds a "before" clause, 1 if it adds
2018
-** an "after" clause, and 0 if it does not change pSql.
2008
+** an "after" clause, and 0 if adds only an order-by clause.
20192009
*/
20202010
static char json_timeline_add_time_clause(Blob *pSql){
20212011
char const * zAfter = NULL;
20222012
char const * zBefore = NULL;
20232013
if( g.isHTTP ){
@@ -2052,10 +2042,11 @@
20522042
" AND event.mtime<=(SELECT julianday(%Q,'utc')) "
20532043
" ORDER BY event.mtime DESC ",
20542044
zBefore);
20552045
return -1;
20562046
}else{
2047
+ blob_append(pSql," ORDER BY event.mtime DESC ", -1);
20572048
return 0;
20582049
}
20592050
}
20602051
20612052
/*
@@ -2085,11 +2076,11 @@
20852076
** Implementation of /json/timeline/ci.
20862077
**
20872078
** Still a few TODOs (like figuring out how to structure
20882079
** inheritance info).
20892080
*/
2090
-static cson_value * json_timeline_ci(unsigned int depth){
2081
+static cson_value * json_timeline_ci(){
20912082
cson_value * payV = NULL;
20922083
cson_object * pay = NULL;
20932084
cson_value * tmp = NULL;
20942085
cson_value * listV = NULL;
20952086
cson_array * list = NULL;
@@ -2201,11 +2192,11 @@
22012192
22022193
/*
22032194
** Implementation of /json/timeline/wiki.
22042195
**
22052196
*/
2206
-static cson_value * json_timeline_wiki(unsigned int depth){
2197
+static cson_value * json_timeline_wiki(){
22072198
/* This code is 95% the same as json_timeline_ci(), by the way. */
22082199
cson_value * payV = NULL;
22092200
cson_object * pay = NULL;
22102201
cson_value * tmp = NULL;
22112202
cson_value * listV = NULL;
@@ -2309,11 +2300,11 @@
23092300
23102301
23112302
/*
23122303
** Implements the /json/whoami page/command.
23132304
*/
2314
-static cson_value * json_page_whoami(unsigned int depth){
2305
+static cson_value * json_page_whoami(){
23152306
cson_value * payload = NULL;
23162307
cson_object * obj = NULL;
23172308
Stmt q;
23182309
db_prepare(&q, "SELECT login, cap FROM user WHERE uid=%d", g.userUid);
23192310
if( db_step(&q)==SQLITE_ROW ){
@@ -2412,11 +2403,10 @@
24122403
*/
24132404
void json_page_top(void){
24142405
int rc = FSL_JSON_E_UNKNOWN_COMMAND;
24152406
char const * cmd;
24162407
cson_value * payload = NULL;
2417
- cson_value * root = NULL;
24182408
JsonPageDef const * pageDef = NULL;
24192409
json_mode_bootstrap();
24202410
cmd = json_command_arg(1);
24212411
/*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/
24222412
pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]);
@@ -2425,17 +2415,18 @@
24252415
return;
24262416
}else if( pageDef->runMode < 0 /*CLI only*/){
24272417
rc = FSL_JSON_E_WRONG_MODE;
24282418
}else{
24292419
rc = 0;
2430
- payload = (*pageDef->func)(1);
2420
+ g.json.dispatchDepth = 1;
2421
+ payload = (*pageDef->func)();
24312422
}
24322423
if( g.json.resultCode ){
24332424
json_err(g.json.resultCode, NULL, 0);
24342425
}else{
2435
- root = json_create_response(rc, NULL, payload);
2436
- json_send_response(payload);
2426
+ cson_value * root = json_create_response(rc, NULL, payload);
2427
+ json_send_response(root);
24372428
cson_value_free(root);
24382429
}
24392430
}
24402431
24412432
/*
@@ -2497,11 +2488,12 @@
24972488
return;
24982489
}else if( pageDef->runMode > 0 /*HTTP only*/){
24992490
rc = FSL_JSON_E_WRONG_MODE;
25002491
}else{
25012492
rc = 0;
2502
- payload = (*pageDef->func)(1);
2493
+ g.json.dispatchDepth = 1;
2494
+ payload = (*pageDef->func)();
25032495
}
25042496
if( g.json.resultCode ){
25052497
json_err(g.json.resultCode, NULL, 1);
25062498
}else{
25072499
payload = json_create_response(rc, NULL, payload);
25082500
--- src/json.c
+++ src/json.c
@@ -58,21 +58,10 @@
58 ** payload. If g.json.resultCode is non-zero when this function
59 ** returns then the top-level dispatcher will destroy any payload
60 ** returned by this function and will output a JSON error response
61 ** instead.
62 **
63 ** The depth parameter comes from the dispatcher and tells the
64 ** callback what index in json_command_arg() its command/path starts.
65 ** e.g. when dispatching /json/foo/bar, the foo callback will get a
66 ** depth of 1 and the bar callback will get a depth of 2. This is only
67 ** useful for callbacks which use json_command_arg(), and the only
68 ** callbacks which do that are ones which dispatch to sub-pages
69 ** (e.g. /json/wiki/...). This is a parameter, as opposed to simply
70 ** hard-coding the offset in each callback impl, so that refactoring
71 ** will (or should) be easier if we later reimplement the path/command
72 ** handling and arguments/path parts get moved around.
73 **
74 ** All of the setup/response code is handled by the top dispatcher
75 ** functions and the callbacks concern themselves only with generating
76 ** the payload.
77 **
78 ** It is imperitive that NO callback functions EVER output ANYTHING to
@@ -80,11 +69,11 @@
80 ** almost certainly will corrupt any HTTP response headers. Output
81 ** sent to stderr ends up in my apache log, so that might be useful
82 ** for debuggering in some cases, but so such code should be left
83 ** enabled for non-debuggering builds.
84 */
85 typedef cson_value * (*fossil_json_f)(unsigned int depth);
86
87 /*
88 ** Internal helpers to manipulate a byte array as a bitset. The B
89 ** argument must be-a array at least (BIT/8+1) bytes long.
90 ** The BIT argument is the bit number to query/set/clear/toggle.
@@ -98,11 +87,11 @@
98
99 /*
100 ** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
101 ** (but planned) pages/commands.
102 */
103 static cson_value * json_page_nyi(unsigned int depth){
104 g.json.resultCode = FSL_JSON_E_NYI;
105 return NULL;
106 }
107
108 /*
@@ -1189,11 +1178,11 @@
1189 /*
1190 ** /json/version implementation.
1191 **
1192 ** Returns the payload object (owned by the caller).
1193 */
1194 cson_value * json_page_version(unsigned int depth){
1195 cson_value * jval = NULL;
1196 cson_object * jobj = NULL;
1197 jval = cson_value_new_object();
1198 jobj = cson_value_get_object(jval);
1199 #define FSET(X,K) cson_object_set( jobj, K, cson_value_new_string(X,strlen(X)))
@@ -1218,11 +1207,11 @@
1218 ** current user (what he may/may not do).
1219 **
1220 ** This is primarily intended for debuggering, but may have
1221 ** a use in client code. (?)
1222 */
1223 cson_value * json_page_cap(unsigned int depth){
1224 cson_value * payload = cson_value_new_object();
1225 cson_value * sub = cson_value_new_object();
1226 Stmt q;
1227 cson_object * obj = cson_value_get_object(payload);
1228 db_prepare(&q, "SELECT login, cap FROM user WHERE uid=%d", g.userUid);
@@ -1274,11 +1263,11 @@
1274
1275 /*
1276 ** Implementation of the /json/login page.
1277 **
1278 */
1279 cson_value * json_page_login(unsigned int depth){
1280 static char preciseErrors = /* if true, "complete" JSON error codes are used,
1281 else they are "dumbed down" to a generic login
1282 error code.
1283 */
1284 #if 0
@@ -1404,11 +1393,11 @@
1404
1405 /*
1406 ** Impl of /json/logout.
1407 **
1408 */
1409 cson_value * json_page_logout(unsigned int depth){
1410 cson_value const *token = g.json.authToken;
1411 /* Remember that json_mode_bootstrap() replaces the login cookie
1412 with the JSON auth token if the request contains it. If the
1413 reqest is missing the auth token then this will fetch fossil's
1414 original cookie. Either way, it's what we want :).
@@ -1429,11 +1418,11 @@
1429 }
1430
1431 /*
1432 ** Implementation of the /json/anonymousPassword page.
1433 */
1434 cson_value * json_page_anon_password(unsigned int depth){
1435 cson_value * v = cson_value_new_object();
1436 cson_object * o = cson_value_get_object(v);
1437 unsigned const int seed = captcha_seed();
1438 char const * zCaptcha = captcha_decode(seed);
1439 cson_object_set(o, "seed",
@@ -1448,11 +1437,11 @@
1448
1449 /*
1450 ** Implementation of the /json/stat page/command.
1451 **
1452 */
1453 cson_value * json_page_stat(unsigned int depth){
1454 i64 t, fsize;
1455 int n, m;
1456 const char *zDb;
1457 enum { BufLen = 1000 };
1458 char zBuf[BufLen];
@@ -1543,14 +1532,14 @@
1543 return jv;
1544 #undef SETBUF
1545 }
1546
1547
1548 static cson_value * json_wiki_list(unsigned int depth);
1549 static cson_value * json_wiki_get(unsigned int depth);
1550 static cson_value * json_wiki_save(unsigned int depth);
1551 static cson_value * json_wiki_create(unsigned int depth);
1552
1553 /*
1554 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
1555 */
1556 static const JsonPageDef JsonPageDefs_Wiki[] = {
@@ -1567,21 +1556,21 @@
1567 ** depth should be the depth parameter passed to the fossil_json_f().
1568 ** pages must be an array of JsonPageDef commands which we can
1569 ** dispatch. The final item in the array MUST have a NULL name
1570 ** element.
1571 **
1572 ** This function takes json_comand_arg(1+depth) and searches pages
1573 ** for a matching name. If found then that page's func() is called
1574 ** to fetch the payload, which is returned to the caller.
 
1575 **
1576 ** On error, g.json.resultCode is set to one of the FossilJsonCodes
1577 ** values.
1578 */
1579 static cson_value * json_page_dispatch_helper(unsigned int depth,
1580 JsonPageDef const * pages){
1581 JsonPageDef const * def;
1582 char const * cmd = json_command_arg(1+depth);
1583 assert( NULL != pages );
1584 if( ! cmd ){
1585 g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
1586 return NULL;
1587 }
@@ -1589,31 +1578,32 @@
1589 if(!def){
1590 g.json.resultCode = FSL_JSON_E_UNKNOWN_COMMAND;
1591 return NULL;
1592 }
1593 else{
1594 return (*def->func)(1+depth);
 
1595 }
1596 }
1597
1598 /*
1599 ** Implements the /json/wiki family of pages/commands. Far from
1600 ** complete.
1601 **
1602 */
1603 static cson_value * json_page_wiki(unsigned int depth){
1604 return json_page_dispatch_helper(depth,&JsonPageDefs_Wiki[0]);
1605 }
1606
1607
1608 /*
1609 ** Implementation of /json/wiki/get.
1610 **
1611 ** TODO: add option to parse wiki output. It is currently
1612 ** unparsed.
1613 */
1614 static cson_value * json_wiki_get(unsigned int depth){
1615 int rid;
1616 Manifest *pWiki = 0;
1617 char const * zBody = NULL;
1618 char const * zPageName;
1619 char doParse = 0/*not yet implemented*/;
@@ -1764,26 +1754,26 @@
1764 }
1765
1766 /*
1767 ** Implementation of /json/wiki/create.
1768 */
1769 static cson_value * json_wiki_create(unsigned int depth){
1770 return json_wiki_create_or_save(1);
1771 }
1772
1773 /*
1774 ** Implementation of /json/wiki/save.
1775 */
1776 static cson_value * json_wiki_save(unsigned int depth){
1777 /* FIXME: add GET/POST.payload bool option createIfNotExists. */
1778 return json_wiki_create_or_save(0);
1779 }
1780
1781 /*
1782 ** Implementation of /json/wiki/list.
1783 */
1784 static cson_value * json_wiki_list(unsigned int depth){
1785 cson_value * listV = NULL;
1786 cson_array * list = NULL;
1787 Stmt q;
1788 if( !g.perm.RdWiki ){
1789 g.json.resultCode = FSL_JSON_E_DENIED;
@@ -1813,11 +1803,11 @@
1813 db_finalize(&q);
1814 return listV;
1815 }
1816
1817
1818 static cson_value * json_branch_list(unsigned int depth);
1819 /*
1820 ** Mapping of /json/branch/XXX commands/paths to callbacks.
1821 */
1822 static const JsonPageDef JsonPageDefs_Branch[] = {
1823 {"list", json_branch_list, 0},
@@ -1829,12 +1819,12 @@
1829 /*
1830 ** Implements the /json/branch family of pages/commands. Far from
1831 ** complete.
1832 **
1833 */
1834 static cson_value * json_page_branch(unsigned int depth){
1835 return json_page_dispatch_helper(depth,&JsonPageDefs_Branch[0]);
1836 }
1837
1838 /*
1839 ** Impl for /json/branch/list
1840 **
@@ -1849,11 +1839,11 @@
1849 ** HTTP mode options:
1850 **
1851 ** "range" GET/POST.payload parameter. FIXME: currently we also use
1852 ** POST, but really want to restrict this to POST.payload.
1853 */
1854 static cson_value * json_branch_list(unsigned int depth){
1855 cson_value * payV;
1856 cson_object * pay;
1857 cson_value * listV;
1858 cson_array * list;
1859 char const * range = NULL;
@@ -1930,12 +1920,12 @@
1930 }
1931 }
1932 return payV;
1933 }
1934
1935 static cson_value * json_timeline_ci(unsigned int depth);
1936 static cson_value * json_timeline_wiki(unsigned int depth);
1937 /*
1938 ** Mapping of /json/timeline/XXX commands/paths to callbacks.
1939 */
1940 static const JsonPageDef JsonPageDefs_Timeline[] = {
1941 {"ci", json_timeline_ci, 0},
@@ -1947,12 +1937,12 @@
1947 /*
1948 ** Implements the /json/timeline family of pages/commands. Far from
1949 ** complete.
1950 **
1951 */
1952 static cson_value * json_page_timeline(unsigned int depth){
1953 return json_page_dispatch_helper(depth,&JsonPageDefs_Timeline[0]);
1954 }
1955
1956 /*
1957 ** Create a temporary table suitable for storing timeline data.
1958 */
@@ -2013,11 +2003,11 @@
2013 ** of the "after" ("a") or "before" ("b") environment parameters.
2014 ** This function gives "after" precedence over "before", and only
2015 ** applies one of them.
2016 **
2017 ** Returns -1 if it adds a "before" clause, 1 if it adds
2018 ** an "after" clause, and 0 if it does not change pSql.
2019 */
2020 static char json_timeline_add_time_clause(Blob *pSql){
2021 char const * zAfter = NULL;
2022 char const * zBefore = NULL;
2023 if( g.isHTTP ){
@@ -2052,10 +2042,11 @@
2052 " AND event.mtime<=(SELECT julianday(%Q,'utc')) "
2053 " ORDER BY event.mtime DESC ",
2054 zBefore);
2055 return -1;
2056 }else{
 
2057 return 0;
2058 }
2059 }
2060
2061 /*
@@ -2085,11 +2076,11 @@
2085 ** Implementation of /json/timeline/ci.
2086 **
2087 ** Still a few TODOs (like figuring out how to structure
2088 ** inheritance info).
2089 */
2090 static cson_value * json_timeline_ci(unsigned int depth){
2091 cson_value * payV = NULL;
2092 cson_object * pay = NULL;
2093 cson_value * tmp = NULL;
2094 cson_value * listV = NULL;
2095 cson_array * list = NULL;
@@ -2201,11 +2192,11 @@
2201
2202 /*
2203 ** Implementation of /json/timeline/wiki.
2204 **
2205 */
2206 static cson_value * json_timeline_wiki(unsigned int depth){
2207 /* This code is 95% the same as json_timeline_ci(), by the way. */
2208 cson_value * payV = NULL;
2209 cson_object * pay = NULL;
2210 cson_value * tmp = NULL;
2211 cson_value * listV = NULL;
@@ -2309,11 +2300,11 @@
2309
2310
2311 /*
2312 ** Implements the /json/whoami page/command.
2313 */
2314 static cson_value * json_page_whoami(unsigned int depth){
2315 cson_value * payload = NULL;
2316 cson_object * obj = NULL;
2317 Stmt q;
2318 db_prepare(&q, "SELECT login, cap FROM user WHERE uid=%d", g.userUid);
2319 if( db_step(&q)==SQLITE_ROW ){
@@ -2412,11 +2403,10 @@
2412 */
2413 void json_page_top(void){
2414 int rc = FSL_JSON_E_UNKNOWN_COMMAND;
2415 char const * cmd;
2416 cson_value * payload = NULL;
2417 cson_value * root = NULL;
2418 JsonPageDef const * pageDef = NULL;
2419 json_mode_bootstrap();
2420 cmd = json_command_arg(1);
2421 /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/
2422 pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]);
@@ -2425,17 +2415,18 @@
2425 return;
2426 }else if( pageDef->runMode < 0 /*CLI only*/){
2427 rc = FSL_JSON_E_WRONG_MODE;
2428 }else{
2429 rc = 0;
2430 payload = (*pageDef->func)(1);
 
2431 }
2432 if( g.json.resultCode ){
2433 json_err(g.json.resultCode, NULL, 0);
2434 }else{
2435 root = json_create_response(rc, NULL, payload);
2436 json_send_response(payload);
2437 cson_value_free(root);
2438 }
2439 }
2440
2441 /*
@@ -2497,11 +2488,12 @@
2497 return;
2498 }else if( pageDef->runMode > 0 /*HTTP only*/){
2499 rc = FSL_JSON_E_WRONG_MODE;
2500 }else{
2501 rc = 0;
2502 payload = (*pageDef->func)(1);
 
2503 }
2504 if( g.json.resultCode ){
2505 json_err(g.json.resultCode, NULL, 1);
2506 }else{
2507 payload = json_create_response(rc, NULL, payload);
2508
--- src/json.c
+++ src/json.c
@@ -58,21 +58,10 @@
58 ** payload. If g.json.resultCode is non-zero when this function
59 ** returns then the top-level dispatcher will destroy any payload
60 ** returned by this function and will output a JSON error response
61 ** instead.
62 **
 
 
 
 
 
 
 
 
 
 
 
63 ** All of the setup/response code is handled by the top dispatcher
64 ** functions and the callbacks concern themselves only with generating
65 ** the payload.
66 **
67 ** It is imperitive that NO callback functions EVER output ANYTHING to
@@ -80,11 +69,11 @@
69 ** almost certainly will corrupt any HTTP response headers. Output
70 ** sent to stderr ends up in my apache log, so that might be useful
71 ** for debuggering in some cases, but so such code should be left
72 ** enabled for non-debuggering builds.
73 */
74 typedef cson_value * (*fossil_json_f)();
75
76 /*
77 ** Internal helpers to manipulate a byte array as a bitset. The B
78 ** argument must be-a array at least (BIT/8+1) bytes long.
79 ** The BIT argument is the bit number to query/set/clear/toggle.
@@ -98,11 +87,11 @@
87
88 /*
89 ** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
90 ** (but planned) pages/commands.
91 */
92 static cson_value * json_page_nyi(){
93 g.json.resultCode = FSL_JSON_E_NYI;
94 return NULL;
95 }
96
97 /*
@@ -1189,11 +1178,11 @@
1178 /*
1179 ** /json/version implementation.
1180 **
1181 ** Returns the payload object (owned by the caller).
1182 */
1183 cson_value * json_page_version(){
1184 cson_value * jval = NULL;
1185 cson_object * jobj = NULL;
1186 jval = cson_value_new_object();
1187 jobj = cson_value_get_object(jval);
1188 #define FSET(X,K) cson_object_set( jobj, K, cson_value_new_string(X,strlen(X)))
@@ -1218,11 +1207,11 @@
1207 ** current user (what he may/may not do).
1208 **
1209 ** This is primarily intended for debuggering, but may have
1210 ** a use in client code. (?)
1211 */
1212 cson_value * json_page_cap(){
1213 cson_value * payload = cson_value_new_object();
1214 cson_value * sub = cson_value_new_object();
1215 Stmt q;
1216 cson_object * obj = cson_value_get_object(payload);
1217 db_prepare(&q, "SELECT login, cap FROM user WHERE uid=%d", g.userUid);
@@ -1274,11 +1263,11 @@
1263
1264 /*
1265 ** Implementation of the /json/login page.
1266 **
1267 */
1268 cson_value * json_page_login(){
1269 static char preciseErrors = /* if true, "complete" JSON error codes are used,
1270 else they are "dumbed down" to a generic login
1271 error code.
1272 */
1273 #if 0
@@ -1404,11 +1393,11 @@
1393
1394 /*
1395 ** Impl of /json/logout.
1396 **
1397 */
1398 cson_value * json_page_logout(){
1399 cson_value const *token = g.json.authToken;
1400 /* Remember that json_mode_bootstrap() replaces the login cookie
1401 with the JSON auth token if the request contains it. If the
1402 reqest is missing the auth token then this will fetch fossil's
1403 original cookie. Either way, it's what we want :).
@@ -1429,11 +1418,11 @@
1418 }
1419
1420 /*
1421 ** Implementation of the /json/anonymousPassword page.
1422 */
1423 cson_value * json_page_anon_password(){
1424 cson_value * v = cson_value_new_object();
1425 cson_object * o = cson_value_get_object(v);
1426 unsigned const int seed = captcha_seed();
1427 char const * zCaptcha = captcha_decode(seed);
1428 cson_object_set(o, "seed",
@@ -1448,11 +1437,11 @@
1437
1438 /*
1439 ** Implementation of the /json/stat page/command.
1440 **
1441 */
1442 cson_value * json_page_stat(){
1443 i64 t, fsize;
1444 int n, m;
1445 const char *zDb;
1446 enum { BufLen = 1000 };
1447 char zBuf[BufLen];
@@ -1543,14 +1532,14 @@
1532 return jv;
1533 #undef SETBUF
1534 }
1535
1536
1537 static cson_value * json_wiki_list();
1538 static cson_value * json_wiki_get();
1539 static cson_value * json_wiki_save();
1540 static cson_value * json_wiki_create();
1541
1542 /*
1543 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
1544 */
1545 static const JsonPageDef JsonPageDefs_Wiki[] = {
@@ -1567,21 +1556,21 @@
1556 ** depth should be the depth parameter passed to the fossil_json_f().
1557 ** pages must be an array of JsonPageDef commands which we can
1558 ** dispatch. The final item in the array MUST have a NULL name
1559 ** element.
1560 **
1561 ** This function takes json_comand_arg(1+g.json.dispatchDepth) and
1562 ** searches pages for a matching name. If found then that page's
1563 ** func() is called to fetch the payload, which is returned to the
1564 ** caller.
1565 **
1566 ** On error, g.json.resultCode is set to one of the FossilJsonCodes
1567 ** values.
1568 */
1569 static cson_value * json_page_dispatch_helper(JsonPageDef const * pages){
 
1570 JsonPageDef const * def;
1571 char const * cmd = json_command_arg(1+g.json.dispatchDepth);
1572 assert( NULL != pages );
1573 if( ! cmd ){
1574 g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
1575 return NULL;
1576 }
@@ -1589,31 +1578,32 @@
1578 if(!def){
1579 g.json.resultCode = FSL_JSON_E_UNKNOWN_COMMAND;
1580 return NULL;
1581 }
1582 else{
1583 ++g.json.dispatchDepth;
1584 return (*def->func)();
1585 }
1586 }
1587
1588 /*
1589 ** Implements the /json/wiki family of pages/commands. Far from
1590 ** complete.
1591 **
1592 */
1593 static cson_value * json_page_wiki(){
1594 return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
1595 }
1596
1597
1598 /*
1599 ** Implementation of /json/wiki/get.
1600 **
1601 ** TODO: add option to parse wiki output. It is currently
1602 ** unparsed.
1603 */
1604 static cson_value * json_wiki_get(){
1605 int rid;
1606 Manifest *pWiki = 0;
1607 char const * zBody = NULL;
1608 char const * zPageName;
1609 char doParse = 0/*not yet implemented*/;
@@ -1764,26 +1754,26 @@
1754 }
1755
1756 /*
1757 ** Implementation of /json/wiki/create.
1758 */
1759 static cson_value * json_wiki_create(){
1760 return json_wiki_create_or_save(1);
1761 }
1762
1763 /*
1764 ** Implementation of /json/wiki/save.
1765 */
1766 static cson_value * json_wiki_save(){
1767 /* FIXME: add GET/POST.payload bool option createIfNotExists. */
1768 return json_wiki_create_or_save(0);
1769 }
1770
1771 /*
1772 ** Implementation of /json/wiki/list.
1773 */
1774 static cson_value * json_wiki_list(){
1775 cson_value * listV = NULL;
1776 cson_array * list = NULL;
1777 Stmt q;
1778 if( !g.perm.RdWiki ){
1779 g.json.resultCode = FSL_JSON_E_DENIED;
@@ -1813,11 +1803,11 @@
1803 db_finalize(&q);
1804 return listV;
1805 }
1806
1807
1808 static cson_value * json_branch_list();
1809 /*
1810 ** Mapping of /json/branch/XXX commands/paths to callbacks.
1811 */
1812 static const JsonPageDef JsonPageDefs_Branch[] = {
1813 {"list", json_branch_list, 0},
@@ -1829,12 +1819,12 @@
1819 /*
1820 ** Implements the /json/branch family of pages/commands. Far from
1821 ** complete.
1822 **
1823 */
1824 static cson_value * json_page_branch(){
1825 return json_page_dispatch_helper(&JsonPageDefs_Branch[0]);
1826 }
1827
1828 /*
1829 ** Impl for /json/branch/list
1830 **
@@ -1849,11 +1839,11 @@
1839 ** HTTP mode options:
1840 **
1841 ** "range" GET/POST.payload parameter. FIXME: currently we also use
1842 ** POST, but really want to restrict this to POST.payload.
1843 */
1844 static cson_value * json_branch_list(){
1845 cson_value * payV;
1846 cson_object * pay;
1847 cson_value * listV;
1848 cson_array * list;
1849 char const * range = NULL;
@@ -1930,12 +1920,12 @@
1920 }
1921 }
1922 return payV;
1923 }
1924
1925 static cson_value * json_timeline_ci();
1926 static cson_value * json_timeline_wiki();
1927 /*
1928 ** Mapping of /json/timeline/XXX commands/paths to callbacks.
1929 */
1930 static const JsonPageDef JsonPageDefs_Timeline[] = {
1931 {"ci", json_timeline_ci, 0},
@@ -1947,12 +1937,12 @@
1937 /*
1938 ** Implements the /json/timeline family of pages/commands. Far from
1939 ** complete.
1940 **
1941 */
1942 static cson_value * json_page_timeline(){
1943 return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]);
1944 }
1945
1946 /*
1947 ** Create a temporary table suitable for storing timeline data.
1948 */
@@ -2013,11 +2003,11 @@
2003 ** of the "after" ("a") or "before" ("b") environment parameters.
2004 ** This function gives "after" precedence over "before", and only
2005 ** applies one of them.
2006 **
2007 ** Returns -1 if it adds a "before" clause, 1 if it adds
2008 ** an "after" clause, and 0 if adds only an order-by clause.
2009 */
2010 static char json_timeline_add_time_clause(Blob *pSql){
2011 char const * zAfter = NULL;
2012 char const * zBefore = NULL;
2013 if( g.isHTTP ){
@@ -2052,10 +2042,11 @@
2042 " AND event.mtime<=(SELECT julianday(%Q,'utc')) "
2043 " ORDER BY event.mtime DESC ",
2044 zBefore);
2045 return -1;
2046 }else{
2047 blob_append(pSql," ORDER BY event.mtime DESC ", -1);
2048 return 0;
2049 }
2050 }
2051
2052 /*
@@ -2085,11 +2076,11 @@
2076 ** Implementation of /json/timeline/ci.
2077 **
2078 ** Still a few TODOs (like figuring out how to structure
2079 ** inheritance info).
2080 */
2081 static cson_value * json_timeline_ci(){
2082 cson_value * payV = NULL;
2083 cson_object * pay = NULL;
2084 cson_value * tmp = NULL;
2085 cson_value * listV = NULL;
2086 cson_array * list = NULL;
@@ -2201,11 +2192,11 @@
2192
2193 /*
2194 ** Implementation of /json/timeline/wiki.
2195 **
2196 */
2197 static cson_value * json_timeline_wiki(){
2198 /* This code is 95% the same as json_timeline_ci(), by the way. */
2199 cson_value * payV = NULL;
2200 cson_object * pay = NULL;
2201 cson_value * tmp = NULL;
2202 cson_value * listV = NULL;
@@ -2309,11 +2300,11 @@
2300
2301
2302 /*
2303 ** Implements the /json/whoami page/command.
2304 */
2305 static cson_value * json_page_whoami(){
2306 cson_value * payload = NULL;
2307 cson_object * obj = NULL;
2308 Stmt q;
2309 db_prepare(&q, "SELECT login, cap FROM user WHERE uid=%d", g.userUid);
2310 if( db_step(&q)==SQLITE_ROW ){
@@ -2412,11 +2403,10 @@
2403 */
2404 void json_page_top(void){
2405 int rc = FSL_JSON_E_UNKNOWN_COMMAND;
2406 char const * cmd;
2407 cson_value * payload = NULL;
 
2408 JsonPageDef const * pageDef = NULL;
2409 json_mode_bootstrap();
2410 cmd = json_command_arg(1);
2411 /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/
2412 pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]);
@@ -2425,17 +2415,18 @@
2415 return;
2416 }else if( pageDef->runMode < 0 /*CLI only*/){
2417 rc = FSL_JSON_E_WRONG_MODE;
2418 }else{
2419 rc = 0;
2420 g.json.dispatchDepth = 1;
2421 payload = (*pageDef->func)();
2422 }
2423 if( g.json.resultCode ){
2424 json_err(g.json.resultCode, NULL, 0);
2425 }else{
2426 cson_value * root = json_create_response(rc, NULL, payload);
2427 json_send_response(root);
2428 cson_value_free(root);
2429 }
2430 }
2431
2432 /*
@@ -2497,11 +2488,12 @@
2488 return;
2489 }else if( pageDef->runMode > 0 /*HTTP only*/){
2490 rc = FSL_JSON_E_WRONG_MODE;
2491 }else{
2492 rc = 0;
2493 g.json.dispatchDepth = 1;
2494 payload = (*pageDef->func)();
2495 }
2496 if( g.json.resultCode ){
2497 json_err(g.json.resultCode, NULL, 1);
2498 }else{
2499 payload = json_create_response(rc, NULL, payload);
2500
+5
--- src/main.c
+++ src/main.c
@@ -182,10 +182,15 @@
182182
int resultCode; /* used for passing back specific codes from /json callbacks. */
183183
int errorDetailParanoia; /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
184184
cson_output_opt outOpt; /* formatting options for JSON mode. */
185185
cson_value * authToken; /* authentication token */
186186
char const * jsonp; /* Name of JSONP function wrapper. */
187
+ unsigned char dispatchDepth /* Tells JSON command dispatching
188
+ which argument we are currently
189
+ working on. For this purpose, arg#0
190
+ is the "json" path/CLI arg.
191
+ */;
187192
struct { /* "garbage collector" */
188193
cson_value * v;
189194
cson_object * o;
190195
} gc;
191196
struct { /* JSON POST data. */
192197
--- src/main.c
+++ src/main.c
@@ -182,10 +182,15 @@
182 int resultCode; /* used for passing back specific codes from /json callbacks. */
183 int errorDetailParanoia; /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
184 cson_output_opt outOpt; /* formatting options for JSON mode. */
185 cson_value * authToken; /* authentication token */
186 char const * jsonp; /* Name of JSONP function wrapper. */
 
 
 
 
 
187 struct { /* "garbage collector" */
188 cson_value * v;
189 cson_object * o;
190 } gc;
191 struct { /* JSON POST data. */
192
--- src/main.c
+++ src/main.c
@@ -182,10 +182,15 @@
182 int resultCode; /* used for passing back specific codes from /json callbacks. */
183 int errorDetailParanoia; /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
184 cson_output_opt outOpt; /* formatting options for JSON mode. */
185 cson_value * authToken; /* authentication token */
186 char const * jsonp; /* Name of JSONP function wrapper. */
187 unsigned char dispatchDepth /* Tells JSON command dispatching
188 which argument we are currently
189 working on. For this purpose, arg#0
190 is the "json" path/CLI arg.
191 */;
192 struct { /* "garbage collector" */
193 cson_value * v;
194 cson_object * o;
195 } gc;
196 struct { /* JSON POST data. */
197

Keyboard Shortcuts

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