Fossil SCM
Cleaned up the recently consolidated top-most json command dispatching a bit.
Commit
5daadddfdb911819080c73f957e3735f76b0944b
Parent
f81e3e7f45d8a6d…
1 file changed
+26
-33
+26
-33
| --- src/json.c | ||
| +++ src/json.c | ||
| @@ -200,11 +200,11 @@ | ||
| 200 | 200 | case 0: return "Success"; |
| 201 | 201 | #define C(X,V) case FSL_JSON_E_ ## X: return V |
| 202 | 202 | |
| 203 | 203 | C(GENERIC,"Generic error"); |
| 204 | 204 | C(INVALID_REQUEST,"Invalid request"); |
| 205 | - C(UNKNOWN_COMMAND,"Unknown Command"); | |
| 205 | + C(UNKNOWN_COMMAND,"Unknown command or subcommand"); | |
| 206 | 206 | C(UNKNOWN,"Unknown error"); |
| 207 | 207 | C(TIMEOUT,"Timeout reached"); |
| 208 | 208 | C(ASSERT,"Assertion failed"); |
| 209 | 209 | C(ALLOC,"Resource allocation failed"); |
| 210 | 210 | C(NYI,"Not yet implemented"); |
| @@ -1464,11 +1464,12 @@ | ||
| 1464 | 1464 | ** by the caller, who must eventually free it using cson_value_free(), |
| 1465 | 1465 | ** or add it to a cson container to transfer ownership. Returns NULL |
| 1466 | 1466 | ** on error. |
| 1467 | 1467 | ** |
| 1468 | 1468 | ** If payload is not NULL and resultCode is 0 then it is set as the |
| 1469 | -** "payload" property of the returned object. If resultCode is | |
| 1469 | +** "payload" property of the returned object. If resultCode is 0 then | |
| 1470 | +** it defaults to g.json.resultCode. If resultCode is (or defaults to) | |
| 1470 | 1471 | ** non-zero and payload is not NULL then this function calls |
| 1471 | 1472 | ** cson_value_free(payload) and does not insert the payload into the |
| 1472 | 1473 | ** response. In either case, onwership of payload is transfered to (or |
| 1473 | 1474 | ** shared with, if the caller holds a reference) this function. |
| 1474 | 1475 | ** |
| @@ -1484,11 +1485,11 @@ | ||
| 1484 | 1485 | cson_value * payload){ |
| 1485 | 1486 | cson_value * v = NULL; |
| 1486 | 1487 | cson_value * tmp = NULL; |
| 1487 | 1488 | cson_object * o = NULL; |
| 1488 | 1489 | int rc; |
| 1489 | - resultCode = json_dumbdown_rc(resultCode); | |
| 1490 | + resultCode = json_dumbdown_rc(resultCode ? resultCode : g.json.resultCode); | |
| 1490 | 1491 | o = cson_new_object(); |
| 1491 | 1492 | v = cson_object_value(o); |
| 1492 | 1493 | if( ! o ) return NULL; |
| 1493 | 1494 | #define SET(K) if(!tmp) goto cleanup; \ |
| 1494 | 1495 | rc = cson_object_set( o, K, tmp ); \ |
| @@ -2129,11 +2130,12 @@ | ||
| 2129 | 2130 | blob_reset(&cmdNames); |
| 2130 | 2131 | return NULL; |
| 2131 | 2132 | } |
| 2132 | 2133 | def = json_handler_for_name( cmd, pages ); |
| 2133 | 2134 | if(!def){ |
| 2134 | - g.json.resultCode = FSL_JSON_E_UNKNOWN_COMMAND; | |
| 2135 | + json_set_err(FSL_JSON_E_UNKNOWN_COMMAND, | |
| 2136 | + "Unknown subcommand: %s", cmd); | |
| 2135 | 2137 | return NULL; |
| 2136 | 2138 | } |
| 2137 | 2139 | else{ |
| 2138 | 2140 | ++g.json.dispatchDepth; |
| 2139 | 2141 | return (*def->func)(); |
| @@ -2267,22 +2269,22 @@ | ||
| 2267 | 2269 | |
| 2268 | 2270 | /* |
| 2269 | 2271 | ** Internal helper for json_cmd_top() and json_page_top(). |
| 2270 | 2272 | ** |
| 2271 | 2273 | ** Searches JsonPageDefs for a command with the given name. If found, |
| 2272 | -** it is used to generate and output JSON response. If not found, it | |
| 2273 | -** generates a JSON-style error response. | |
| 2274 | +** it is used to generate and output a JSON response. If not found, it | |
| 2275 | +** generates a JSON-style error response. Returns 0 on success, non-0 | |
| 2276 | +** on error. On error it will set g.json's error state. | |
| 2274 | 2277 | */ |
| 2275 | -static void json_dispatch_root_command( char const * zCommand ){ | |
| 2276 | - int rc = FSL_JSON_E_UNKNOWN_COMMAND; | |
| 2278 | +static int json_dispatch_root_command( char const * zCommand ){ | |
| 2279 | + int rc = 0; | |
| 2277 | 2280 | cson_value * payload = NULL; |
| 2278 | 2281 | JsonPageDef const * pageDef = NULL; |
| 2279 | - /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/ | |
| 2280 | 2282 | pageDef = json_handler_for_name(zCommand,&JsonPageDefs[0]); |
| 2281 | 2283 | if( ! pageDef ){ |
| 2282 | - json_err( FSL_JSON_E_UNKNOWN_COMMAND, NULL, 0 ); | |
| 2283 | - return; | |
| 2284 | + rc = FSL_JSON_E_UNKNOWN_COMMAND; | |
| 2285 | + json_set_err( rc, "Unknown command: %s", zCommand ); | |
| 2284 | 2286 | }else if( pageDef->runMode < 0 /*CLI only*/){ |
| 2285 | 2287 | rc = FSL_JSON_E_WRONG_MODE; |
| 2286 | 2288 | }else if( (g.isHTTP && (pageDef->runMode < 0 /*CLI only*/)) |
| 2287 | 2289 | || |
| 2288 | 2290 | (!g.isHTTP && (pageDef->runMode > 0 /*HTTP only*/)) |
| @@ -2292,25 +2294,14 @@ | ||
| 2292 | 2294 | else{ |
| 2293 | 2295 | rc = 0; |
| 2294 | 2296 | g.json.dispatchDepth = 1; |
| 2295 | 2297 | payload = (*pageDef->func)(); |
| 2296 | 2298 | } |
| 2297 | - if( g.json.resultCode /*can be set via pageDef->func()*/ ){ | |
| 2298 | - cson_value_free(payload); | |
| 2299 | - json_err(g.json.resultCode, NULL, 0); | |
| 2300 | - }else{ | |
| 2301 | - payload = json_create_response(rc, NULL, payload); | |
| 2302 | - json_send_response(payload); | |
| 2303 | - cson_value_free(payload); | |
| 2304 | - if((0 != rc) && !g.isHTTP){ | |
| 2305 | - /* FIXME: we need a way of passing this error back | |
| 2306 | - up to the routine which called this callback. | |
| 2307 | - e.g. add g.errCode. | |
| 2308 | - */ | |
| 2309 | - fossil_exit(1); | |
| 2310 | - } | |
| 2311 | - } | |
| 2299 | + payload = json_create_response(rc, rc ? g.zErrMsg : NULL, payload); | |
| 2300 | + json_send_response(payload); | |
| 2301 | + cson_value_free(payload); | |
| 2302 | + return rc; | |
| 2312 | 2303 | } |
| 2313 | 2304 | |
| 2314 | 2305 | #ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */ |
| 2315 | 2306 | /* |
| 2316 | 2307 | ** WEBPAGE: json |
| @@ -2318,14 +2309,11 @@ | ||
| 2318 | 2309 | ** Pages under /json/... must be entered into JsonPageDefs. |
| 2319 | 2310 | ** This function dispatches them, and is the HTTP equivalent of |
| 2320 | 2311 | ** json_cmd_top(). |
| 2321 | 2312 | */ |
| 2322 | 2313 | void json_page_top(void){ |
| 2323 | - int rc = FSL_JSON_E_UNKNOWN_COMMAND; | |
| 2324 | 2314 | char const * zCommand; |
| 2325 | - cson_value * payload = NULL; | |
| 2326 | - JsonPageDef const * pageDef = NULL; | |
| 2327 | 2315 | BEGIN_TIMER; |
| 2328 | 2316 | json_mode_bootstrap(); |
| 2329 | 2317 | zCommand = json_command_arg(1); |
| 2330 | 2318 | if(!zCommand || !*zCommand){ |
| 2331 | 2319 | goto usage; |
| @@ -2373,13 +2361,11 @@ | ||
| 2373 | 2361 | ** ... |
| 2374 | 2362 | ** |
| 2375 | 2363 | */ |
| 2376 | 2364 | void json_cmd_top(void){ |
| 2377 | 2365 | char const * cmd = NULL; |
| 2378 | - int rc = FSL_JSON_E_UNKNOWN_COMMAND; | |
| 2379 | - cson_value * payload = NULL; | |
| 2380 | - JsonPageDef const * pageDef; | |
| 2366 | + int rc = 0; | |
| 2381 | 2367 | BEGIN_TIMER; |
| 2382 | 2368 | memset( &g.perm, 0xff, sizeof(g.perm) ) |
| 2383 | 2369 | /* In CLI mode fossil does not use permissions |
| 2384 | 2370 | and they all default to false. We enable them |
| 2385 | 2371 | here because (A) fossil doesn't use them in local |
| @@ -2399,11 +2385,18 @@ | ||
| 2399 | 2385 | #endif |
| 2400 | 2386 | cmd = json_command_arg(1); |
| 2401 | 2387 | if( !cmd || !*cmd ){ |
| 2402 | 2388 | goto usage; |
| 2403 | 2389 | } |
| 2404 | - json_dispatch_root_command( cmd ); | |
| 2390 | + rc = json_dispatch_root_command( cmd ); | |
| 2391 | + if(0 != rc){ | |
| 2392 | + /* FIXME: we need a way of passing this error back | |
| 2393 | + up to the routine which called this callback. | |
| 2394 | + e.g. add g.errCode. | |
| 2395 | + */ | |
| 2396 | + fossil_exit(1); | |
| 2397 | + } | |
| 2405 | 2398 | return; |
| 2406 | 2399 | usage: |
| 2407 | 2400 | { |
| 2408 | 2401 | Blob cmdNames = empty_blob; |
| 2409 | 2402 | blob_init(&cmdNames, |
| 2410 | 2403 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -200,11 +200,11 @@ | |
| 200 | case 0: return "Success"; |
| 201 | #define C(X,V) case FSL_JSON_E_ ## X: return V |
| 202 | |
| 203 | C(GENERIC,"Generic error"); |
| 204 | C(INVALID_REQUEST,"Invalid request"); |
| 205 | C(UNKNOWN_COMMAND,"Unknown Command"); |
| 206 | C(UNKNOWN,"Unknown error"); |
| 207 | C(TIMEOUT,"Timeout reached"); |
| 208 | C(ASSERT,"Assertion failed"); |
| 209 | C(ALLOC,"Resource allocation failed"); |
| 210 | C(NYI,"Not yet implemented"); |
| @@ -1464,11 +1464,12 @@ | |
| 1464 | ** by the caller, who must eventually free it using cson_value_free(), |
| 1465 | ** or add it to a cson container to transfer ownership. Returns NULL |
| 1466 | ** on error. |
| 1467 | ** |
| 1468 | ** If payload is not NULL and resultCode is 0 then it is set as the |
| 1469 | ** "payload" property of the returned object. If resultCode is |
| 1470 | ** non-zero and payload is not NULL then this function calls |
| 1471 | ** cson_value_free(payload) and does not insert the payload into the |
| 1472 | ** response. In either case, onwership of payload is transfered to (or |
| 1473 | ** shared with, if the caller holds a reference) this function. |
| 1474 | ** |
| @@ -1484,11 +1485,11 @@ | |
| 1484 | cson_value * payload){ |
| 1485 | cson_value * v = NULL; |
| 1486 | cson_value * tmp = NULL; |
| 1487 | cson_object * o = NULL; |
| 1488 | int rc; |
| 1489 | resultCode = json_dumbdown_rc(resultCode); |
| 1490 | o = cson_new_object(); |
| 1491 | v = cson_object_value(o); |
| 1492 | if( ! o ) return NULL; |
| 1493 | #define SET(K) if(!tmp) goto cleanup; \ |
| 1494 | rc = cson_object_set( o, K, tmp ); \ |
| @@ -2129,11 +2130,12 @@ | |
| 2129 | blob_reset(&cmdNames); |
| 2130 | return NULL; |
| 2131 | } |
| 2132 | def = json_handler_for_name( cmd, pages ); |
| 2133 | if(!def){ |
| 2134 | g.json.resultCode = FSL_JSON_E_UNKNOWN_COMMAND; |
| 2135 | return NULL; |
| 2136 | } |
| 2137 | else{ |
| 2138 | ++g.json.dispatchDepth; |
| 2139 | return (*def->func)(); |
| @@ -2267,22 +2269,22 @@ | |
| 2267 | |
| 2268 | /* |
| 2269 | ** Internal helper for json_cmd_top() and json_page_top(). |
| 2270 | ** |
| 2271 | ** Searches JsonPageDefs for a command with the given name. If found, |
| 2272 | ** it is used to generate and output JSON response. If not found, it |
| 2273 | ** generates a JSON-style error response. |
| 2274 | */ |
| 2275 | static void json_dispatch_root_command( char const * zCommand ){ |
| 2276 | int rc = FSL_JSON_E_UNKNOWN_COMMAND; |
| 2277 | cson_value * payload = NULL; |
| 2278 | JsonPageDef const * pageDef = NULL; |
| 2279 | /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/ |
| 2280 | pageDef = json_handler_for_name(zCommand,&JsonPageDefs[0]); |
| 2281 | if( ! pageDef ){ |
| 2282 | json_err( FSL_JSON_E_UNKNOWN_COMMAND, NULL, 0 ); |
| 2283 | return; |
| 2284 | }else if( pageDef->runMode < 0 /*CLI only*/){ |
| 2285 | rc = FSL_JSON_E_WRONG_MODE; |
| 2286 | }else if( (g.isHTTP && (pageDef->runMode < 0 /*CLI only*/)) |
| 2287 | || |
| 2288 | (!g.isHTTP && (pageDef->runMode > 0 /*HTTP only*/)) |
| @@ -2292,25 +2294,14 @@ | |
| 2292 | else{ |
| 2293 | rc = 0; |
| 2294 | g.json.dispatchDepth = 1; |
| 2295 | payload = (*pageDef->func)(); |
| 2296 | } |
| 2297 | if( g.json.resultCode /*can be set via pageDef->func()*/ ){ |
| 2298 | cson_value_free(payload); |
| 2299 | json_err(g.json.resultCode, NULL, 0); |
| 2300 | }else{ |
| 2301 | payload = json_create_response(rc, NULL, payload); |
| 2302 | json_send_response(payload); |
| 2303 | cson_value_free(payload); |
| 2304 | if((0 != rc) && !g.isHTTP){ |
| 2305 | /* FIXME: we need a way of passing this error back |
| 2306 | up to the routine which called this callback. |
| 2307 | e.g. add g.errCode. |
| 2308 | */ |
| 2309 | fossil_exit(1); |
| 2310 | } |
| 2311 | } |
| 2312 | } |
| 2313 | |
| 2314 | #ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */ |
| 2315 | /* |
| 2316 | ** WEBPAGE: json |
| @@ -2318,14 +2309,11 @@ | |
| 2318 | ** Pages under /json/... must be entered into JsonPageDefs. |
| 2319 | ** This function dispatches them, and is the HTTP equivalent of |
| 2320 | ** json_cmd_top(). |
| 2321 | */ |
| 2322 | void json_page_top(void){ |
| 2323 | int rc = FSL_JSON_E_UNKNOWN_COMMAND; |
| 2324 | char const * zCommand; |
| 2325 | cson_value * payload = NULL; |
| 2326 | JsonPageDef const * pageDef = NULL; |
| 2327 | BEGIN_TIMER; |
| 2328 | json_mode_bootstrap(); |
| 2329 | zCommand = json_command_arg(1); |
| 2330 | if(!zCommand || !*zCommand){ |
| 2331 | goto usage; |
| @@ -2373,13 +2361,11 @@ | |
| 2373 | ** ... |
| 2374 | ** |
| 2375 | */ |
| 2376 | void json_cmd_top(void){ |
| 2377 | char const * cmd = NULL; |
| 2378 | int rc = FSL_JSON_E_UNKNOWN_COMMAND; |
| 2379 | cson_value * payload = NULL; |
| 2380 | JsonPageDef const * pageDef; |
| 2381 | BEGIN_TIMER; |
| 2382 | memset( &g.perm, 0xff, sizeof(g.perm) ) |
| 2383 | /* In CLI mode fossil does not use permissions |
| 2384 | and they all default to false. We enable them |
| 2385 | here because (A) fossil doesn't use them in local |
| @@ -2399,11 +2385,18 @@ | |
| 2399 | #endif |
| 2400 | cmd = json_command_arg(1); |
| 2401 | if( !cmd || !*cmd ){ |
| 2402 | goto usage; |
| 2403 | } |
| 2404 | json_dispatch_root_command( cmd ); |
| 2405 | return; |
| 2406 | usage: |
| 2407 | { |
| 2408 | Blob cmdNames = empty_blob; |
| 2409 | blob_init(&cmdNames, |
| 2410 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -200,11 +200,11 @@ | |
| 200 | case 0: return "Success"; |
| 201 | #define C(X,V) case FSL_JSON_E_ ## X: return V |
| 202 | |
| 203 | C(GENERIC,"Generic error"); |
| 204 | C(INVALID_REQUEST,"Invalid request"); |
| 205 | C(UNKNOWN_COMMAND,"Unknown command or subcommand"); |
| 206 | C(UNKNOWN,"Unknown error"); |
| 207 | C(TIMEOUT,"Timeout reached"); |
| 208 | C(ASSERT,"Assertion failed"); |
| 209 | C(ALLOC,"Resource allocation failed"); |
| 210 | C(NYI,"Not yet implemented"); |
| @@ -1464,11 +1464,12 @@ | |
| 1464 | ** by the caller, who must eventually free it using cson_value_free(), |
| 1465 | ** or add it to a cson container to transfer ownership. Returns NULL |
| 1466 | ** on error. |
| 1467 | ** |
| 1468 | ** If payload is not NULL and resultCode is 0 then it is set as the |
| 1469 | ** "payload" property of the returned object. If resultCode is 0 then |
| 1470 | ** it defaults to g.json.resultCode. If resultCode is (or defaults to) |
| 1471 | ** non-zero and payload is not NULL then this function calls |
| 1472 | ** cson_value_free(payload) and does not insert the payload into the |
| 1473 | ** response. In either case, onwership of payload is transfered to (or |
| 1474 | ** shared with, if the caller holds a reference) this function. |
| 1475 | ** |
| @@ -1484,11 +1485,11 @@ | |
| 1485 | cson_value * payload){ |
| 1486 | cson_value * v = NULL; |
| 1487 | cson_value * tmp = NULL; |
| 1488 | cson_object * o = NULL; |
| 1489 | int rc; |
| 1490 | resultCode = json_dumbdown_rc(resultCode ? resultCode : g.json.resultCode); |
| 1491 | o = cson_new_object(); |
| 1492 | v = cson_object_value(o); |
| 1493 | if( ! o ) return NULL; |
| 1494 | #define SET(K) if(!tmp) goto cleanup; \ |
| 1495 | rc = cson_object_set( o, K, tmp ); \ |
| @@ -2129,11 +2130,12 @@ | |
| 2130 | blob_reset(&cmdNames); |
| 2131 | return NULL; |
| 2132 | } |
| 2133 | def = json_handler_for_name( cmd, pages ); |
| 2134 | if(!def){ |
| 2135 | json_set_err(FSL_JSON_E_UNKNOWN_COMMAND, |
| 2136 | "Unknown subcommand: %s", cmd); |
| 2137 | return NULL; |
| 2138 | } |
| 2139 | else{ |
| 2140 | ++g.json.dispatchDepth; |
| 2141 | return (*def->func)(); |
| @@ -2267,22 +2269,22 @@ | |
| 2269 | |
| 2270 | /* |
| 2271 | ** Internal helper for json_cmd_top() and json_page_top(). |
| 2272 | ** |
| 2273 | ** Searches JsonPageDefs for a command with the given name. If found, |
| 2274 | ** it is used to generate and output a JSON response. If not found, it |
| 2275 | ** generates a JSON-style error response. Returns 0 on success, non-0 |
| 2276 | ** on error. On error it will set g.json's error state. |
| 2277 | */ |
| 2278 | static int json_dispatch_root_command( char const * zCommand ){ |
| 2279 | int rc = 0; |
| 2280 | cson_value * payload = NULL; |
| 2281 | JsonPageDef const * pageDef = NULL; |
| 2282 | pageDef = json_handler_for_name(zCommand,&JsonPageDefs[0]); |
| 2283 | if( ! pageDef ){ |
| 2284 | rc = FSL_JSON_E_UNKNOWN_COMMAND; |
| 2285 | json_set_err( rc, "Unknown command: %s", zCommand ); |
| 2286 | }else if( pageDef->runMode < 0 /*CLI only*/){ |
| 2287 | rc = FSL_JSON_E_WRONG_MODE; |
| 2288 | }else if( (g.isHTTP && (pageDef->runMode < 0 /*CLI only*/)) |
| 2289 | || |
| 2290 | (!g.isHTTP && (pageDef->runMode > 0 /*HTTP only*/)) |
| @@ -2292,25 +2294,14 @@ | |
| 2294 | else{ |
| 2295 | rc = 0; |
| 2296 | g.json.dispatchDepth = 1; |
| 2297 | payload = (*pageDef->func)(); |
| 2298 | } |
| 2299 | payload = json_create_response(rc, rc ? g.zErrMsg : NULL, payload); |
| 2300 | json_send_response(payload); |
| 2301 | cson_value_free(payload); |
| 2302 | return rc; |
| 2303 | } |
| 2304 | |
| 2305 | #ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */ |
| 2306 | /* |
| 2307 | ** WEBPAGE: json |
| @@ -2318,14 +2309,11 @@ | |
| 2309 | ** Pages under /json/... must be entered into JsonPageDefs. |
| 2310 | ** This function dispatches them, and is the HTTP equivalent of |
| 2311 | ** json_cmd_top(). |
| 2312 | */ |
| 2313 | void json_page_top(void){ |
| 2314 | char const * zCommand; |
| 2315 | BEGIN_TIMER; |
| 2316 | json_mode_bootstrap(); |
| 2317 | zCommand = json_command_arg(1); |
| 2318 | if(!zCommand || !*zCommand){ |
| 2319 | goto usage; |
| @@ -2373,13 +2361,11 @@ | |
| 2361 | ** ... |
| 2362 | ** |
| 2363 | */ |
| 2364 | void json_cmd_top(void){ |
| 2365 | char const * cmd = NULL; |
| 2366 | int rc = 0; |
| 2367 | BEGIN_TIMER; |
| 2368 | memset( &g.perm, 0xff, sizeof(g.perm) ) |
| 2369 | /* In CLI mode fossil does not use permissions |
| 2370 | and they all default to false. We enable them |
| 2371 | here because (A) fossil doesn't use them in local |
| @@ -2399,11 +2385,18 @@ | |
| 2385 | #endif |
| 2386 | cmd = json_command_arg(1); |
| 2387 | if( !cmd || !*cmd ){ |
| 2388 | goto usage; |
| 2389 | } |
| 2390 | rc = json_dispatch_root_command( cmd ); |
| 2391 | if(0 != rc){ |
| 2392 | /* FIXME: we need a way of passing this error back |
| 2393 | up to the routine which called this callback. |
| 2394 | e.g. add g.errCode. |
| 2395 | */ |
| 2396 | fossil_exit(1); |
| 2397 | } |
| 2398 | return; |
| 2399 | usage: |
| 2400 | { |
| 2401 | Blob cmdNames = empty_blob; |
| 2402 | blob_init(&cmdNames, |
| 2403 |