Fossil SCM
Refactored the special-case CLI-mode arg/path handling in the CGI/server-mode mechanism. Fixed: server-mode response timestamp was always the time the server process started.
Commit
0bb823032fd4c1934f37d9f433b155c75a78ee34
Parent
35b9edba835d0ad…
1 file changed
+22
-27
+22
-27
| --- src/json.c | ||
| +++ src/json.c | ||
| @@ -281,13 +281,17 @@ | ||
| 281 | 281 | /* avoids debug messages on stderr in JSON mode */ |
| 282 | 282 | sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0); |
| 283 | 283 | #endif |
| 284 | 284 | |
| 285 | 285 | /* |
| 286 | - The following if/else block translates the PATH_INFO path into an | |
| 287 | - internal list so that we can simplify command dispatching later | |
| 288 | - on. | |
| 286 | + The following if/else block translates the PATH_INFO path (in | |
| 287 | + CLI/server modes) or g.argv (CLI mode) into an internal list so | |
| 288 | + that we can simplify command dispatching later on. | |
| 289 | + | |
| 290 | + Note that translating g.argv this way is overkill but allows us to | |
| 291 | + avoid CLI-only special-case handling in other code, e.g. | |
| 292 | + json_command_arg(). | |
| 289 | 293 | */ |
| 290 | 294 | if( pathSplit ){ |
| 291 | 295 | /* cson_cgi already did this, so let's just re-use it. This does |
| 292 | 296 | not happen in "plain server" mode, but does in CGI mode. |
| 293 | 297 | */ |
| @@ -331,11 +335,11 @@ | ||
| 331 | 335 | /* assume CLI mode */ |
| 332 | 336 | int i; |
| 333 | 337 | char const * arg; |
| 334 | 338 | cson_value * part; |
| 335 | 339 | assert( (!g.isCGI) && "g.isCGI set and we do not expect that to be the case here." ); |
| 336 | - for(i = 1; i < g.argc; ++i ){ | |
| 340 | + for(i = 1/*skip argv[0]*/; i < g.argc; ++i ){ | |
| 337 | 341 | arg = g.argv[i]; |
| 338 | 342 | if( !arg || !*arg ) continue; |
| 339 | 343 | part = cson_value_new_string(arg,strlen(arg)); |
| 340 | 344 | cson_array_append(ar, part); |
| 341 | 345 | } |
| @@ -366,29 +370,23 @@ | ||
| 366 | 370 | ** of bounds or there is no "json" path element. |
| 367 | 371 | ** |
| 368 | 372 | ** In CLI mode the "path" is the list of arguments (skipping argv[0]). |
| 369 | 373 | ** In server/CGI modes the path is taken from PATH_INFO. |
| 370 | 374 | */ |
| 371 | -static char const * json_path_part(unsigned char ndx){ | |
| 372 | - cson_array * ar = g.isCGI | |
| 373 | - ? cson_value_get_array(cson_cgi_getenv(&g.json.cgiCx, | |
| 374 | - "a", | |
| 375 | - FossilJsonKeys.commandPath)) | |
| 376 | - : NULL; | |
| 377 | - if( g.isCGI ){ | |
| 378 | - assert((NULL!=ar) && "Internal error."); | |
| 379 | - } | |
| 375 | +static char const * json_command_arg(unsigned char ndx){ | |
| 376 | + cson_array * ar = cson_value_get_array( | |
| 377 | + cson_cgi_getenv(&g.json.cgiCx, | |
| 378 | + "a", | |
| 379 | + FossilJsonKeys.commandPath)); | |
| 380 | + assert((NULL!=ar) && "Internal error. Was json_mode_bootstrap() called?"); | |
| 380 | 381 | if( g.json.cmdOffset < 0 ){ |
| 381 | 382 | /* first-time setup. */ |
| 382 | - short i = g.isCGI ? 0 : 1/*skip argv[0] in CLI mode*/; | |
| 383 | -#define PARTAT cson_string_cstr( \ | |
| 383 | + short i = 0; | |
| 384 | +#define NEXT cson_string_cstr( \ | |
| 384 | 385 | cson_value_get_string( \ |
| 385 | 386 | cson_array_get(ar,i) \ |
| 386 | 387 | )) |
| 387 | -#define NEXT (g.isCGI \ | |
| 388 | - ? PARTAT \ | |
| 389 | - : ((g.argc > i) ? g.argv[i] : NULL)) | |
| 390 | 388 | char const * tok = NEXT; |
| 391 | 389 | while( tok ){ |
| 392 | 390 | if( 0==strncmp("json",tok,4) ){ |
| 393 | 391 | g.json.cmdOffset = i; |
| 394 | 392 | break; |
| @@ -396,19 +394,15 @@ | ||
| 396 | 394 | ++i; |
| 397 | 395 | tok = NEXT; |
| 398 | 396 | } |
| 399 | 397 | } |
| 400 | 398 | #undef NEXT |
| 401 | -#undef PARTAT | |
| 402 | 399 | if( g.json.cmdOffset < 0 ){ |
| 403 | 400 | return NULL; |
| 404 | 401 | }else{ |
| 405 | 402 | ndx = g.json.cmdOffset + ndx; |
| 406 | - return g.isCGI | |
| 407 | - ? cson_string_cstr(cson_value_get_string(cson_array_get( ar, g.json.cmdOffset + ndx ))) | |
| 408 | - : ((ndx < g.argc) ? g.argv[ndx] : NULL) | |
| 409 | - ; | |
| 403 | + return cson_string_cstr(cson_value_get_string(cson_array_get( ar, g.json.cmdOffset + ndx ))); | |
| 410 | 404 | } |
| 411 | 405 | } |
| 412 | 406 | |
| 413 | 407 | /* |
| 414 | 408 | ** If g.json.reqPayload.o is NULL then NULL is returned, else the |
| @@ -543,11 +537,11 @@ | ||
| 543 | 537 | |
| 544 | 538 | tmp = cson_value_new_string(MANIFEST_UUID,strlen(MANIFEST_UUID)); |
| 545 | 539 | SET("fossil"); |
| 546 | 540 | |
| 547 | 541 | {/* "timestamp" */ |
| 548 | - time_t const t = (time_t)g.now; | |
| 542 | + time_t const t = (time_t)time(0); | |
| 549 | 543 | struct tm gt = *gmtime(&t); |
| 550 | 544 | cson_int_t jsTime = (cson_int_t)mktime(>); |
| 551 | 545 | tmp = cson_value_new_integer(jsTime); |
| 552 | 546 | SET("timestamp"); |
| 553 | 547 | } |
| @@ -570,11 +564,12 @@ | ||
| 570 | 564 | tmp = payload; |
| 571 | 565 | SET("payload"); |
| 572 | 566 | } |
| 573 | 567 | } |
| 574 | 568 | #undef SET |
| 575 | - if(0){/*only for my own debuggering*/ | |
| 569 | + | |
| 570 | + if(0){/*Only for debuggering, add some info to the response.*/ | |
| 576 | 571 | tmp = cson_cgi_env_get_val(&g.json.cgiCx,'a', 0); |
| 577 | 572 | if(tmp){ |
| 578 | 573 | cson_object_set( o, "$APP", tmp ); |
| 579 | 574 | } |
| 580 | 575 | tmp = cson_value_new_integer( g.json.cmdOffset ); |
| @@ -901,11 +896,11 @@ | ||
| 901 | 896 | cson_value * payload = NULL; |
| 902 | 897 | cson_value * root = NULL; |
| 903 | 898 | JsonPageDef const * pageDef = NULL; |
| 904 | 899 | cgi_set_content_type( cson_cgi_guess_content_type(&g.json.cgiCx) ); |
| 905 | 900 | json_mode_bootstrap(); |
| 906 | - cmd = json_path_part(1); | |
| 901 | + cmd = json_command_arg(1); | |
| 907 | 902 | /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/ |
| 908 | 903 | pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]); |
| 909 | 904 | if( ! pageDef ){ |
| 910 | 905 | json_err( FSL_JSON_E_UNKNOWN_COMMAND, cmd, 0 ); |
| 911 | 906 | return; |
| @@ -954,11 +949,11 @@ | ||
| 954 | 949 | json_mode_bootstrap(); |
| 955 | 950 | if( g.argc<3 ){ |
| 956 | 951 | goto usage; |
| 957 | 952 | } |
| 958 | 953 | db_find_and_open_repository(0, 0); |
| 959 | - cmd = json_path_part(1); | |
| 954 | + cmd = json_command_arg(1); | |
| 960 | 955 | n = cmd ? strlen(cmd) : 0; |
| 961 | 956 | if( n==0 ){ |
| 962 | 957 | goto usage; |
| 963 | 958 | } |
| 964 | 959 | cgi_set_content_type( cson_cgi_guess_content_type(&g.json.cgiCx) ); |
| 965 | 960 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -281,13 +281,17 @@ | |
| 281 | /* avoids debug messages on stderr in JSON mode */ |
| 282 | sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0); |
| 283 | #endif |
| 284 | |
| 285 | /* |
| 286 | The following if/else block translates the PATH_INFO path into an |
| 287 | internal list so that we can simplify command dispatching later |
| 288 | on. |
| 289 | */ |
| 290 | if( pathSplit ){ |
| 291 | /* cson_cgi already did this, so let's just re-use it. This does |
| 292 | not happen in "plain server" mode, but does in CGI mode. |
| 293 | */ |
| @@ -331,11 +335,11 @@ | |
| 331 | /* assume CLI mode */ |
| 332 | int i; |
| 333 | char const * arg; |
| 334 | cson_value * part; |
| 335 | assert( (!g.isCGI) && "g.isCGI set and we do not expect that to be the case here." ); |
| 336 | for(i = 1; i < g.argc; ++i ){ |
| 337 | arg = g.argv[i]; |
| 338 | if( !arg || !*arg ) continue; |
| 339 | part = cson_value_new_string(arg,strlen(arg)); |
| 340 | cson_array_append(ar, part); |
| 341 | } |
| @@ -366,29 +370,23 @@ | |
| 366 | ** of bounds or there is no "json" path element. |
| 367 | ** |
| 368 | ** In CLI mode the "path" is the list of arguments (skipping argv[0]). |
| 369 | ** In server/CGI modes the path is taken from PATH_INFO. |
| 370 | */ |
| 371 | static char const * json_path_part(unsigned char ndx){ |
| 372 | cson_array * ar = g.isCGI |
| 373 | ? cson_value_get_array(cson_cgi_getenv(&g.json.cgiCx, |
| 374 | "a", |
| 375 | FossilJsonKeys.commandPath)) |
| 376 | : NULL; |
| 377 | if( g.isCGI ){ |
| 378 | assert((NULL!=ar) && "Internal error."); |
| 379 | } |
| 380 | if( g.json.cmdOffset < 0 ){ |
| 381 | /* first-time setup. */ |
| 382 | short i = g.isCGI ? 0 : 1/*skip argv[0] in CLI mode*/; |
| 383 | #define PARTAT cson_string_cstr( \ |
| 384 | cson_value_get_string( \ |
| 385 | cson_array_get(ar,i) \ |
| 386 | )) |
| 387 | #define NEXT (g.isCGI \ |
| 388 | ? PARTAT \ |
| 389 | : ((g.argc > i) ? g.argv[i] : NULL)) |
| 390 | char const * tok = NEXT; |
| 391 | while( tok ){ |
| 392 | if( 0==strncmp("json",tok,4) ){ |
| 393 | g.json.cmdOffset = i; |
| 394 | break; |
| @@ -396,19 +394,15 @@ | |
| 396 | ++i; |
| 397 | tok = NEXT; |
| 398 | } |
| 399 | } |
| 400 | #undef NEXT |
| 401 | #undef PARTAT |
| 402 | if( g.json.cmdOffset < 0 ){ |
| 403 | return NULL; |
| 404 | }else{ |
| 405 | ndx = g.json.cmdOffset + ndx; |
| 406 | return g.isCGI |
| 407 | ? cson_string_cstr(cson_value_get_string(cson_array_get( ar, g.json.cmdOffset + ndx ))) |
| 408 | : ((ndx < g.argc) ? g.argv[ndx] : NULL) |
| 409 | ; |
| 410 | } |
| 411 | } |
| 412 | |
| 413 | /* |
| 414 | ** If g.json.reqPayload.o is NULL then NULL is returned, else the |
| @@ -543,11 +537,11 @@ | |
| 543 | |
| 544 | tmp = cson_value_new_string(MANIFEST_UUID,strlen(MANIFEST_UUID)); |
| 545 | SET("fossil"); |
| 546 | |
| 547 | {/* "timestamp" */ |
| 548 | time_t const t = (time_t)g.now; |
| 549 | struct tm gt = *gmtime(&t); |
| 550 | cson_int_t jsTime = (cson_int_t)mktime(>); |
| 551 | tmp = cson_value_new_integer(jsTime); |
| 552 | SET("timestamp"); |
| 553 | } |
| @@ -570,11 +564,12 @@ | |
| 570 | tmp = payload; |
| 571 | SET("payload"); |
| 572 | } |
| 573 | } |
| 574 | #undef SET |
| 575 | if(0){/*only for my own debuggering*/ |
| 576 | tmp = cson_cgi_env_get_val(&g.json.cgiCx,'a', 0); |
| 577 | if(tmp){ |
| 578 | cson_object_set( o, "$APP", tmp ); |
| 579 | } |
| 580 | tmp = cson_value_new_integer( g.json.cmdOffset ); |
| @@ -901,11 +896,11 @@ | |
| 901 | cson_value * payload = NULL; |
| 902 | cson_value * root = NULL; |
| 903 | JsonPageDef const * pageDef = NULL; |
| 904 | cgi_set_content_type( cson_cgi_guess_content_type(&g.json.cgiCx) ); |
| 905 | json_mode_bootstrap(); |
| 906 | cmd = json_path_part(1); |
| 907 | /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/ |
| 908 | pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]); |
| 909 | if( ! pageDef ){ |
| 910 | json_err( FSL_JSON_E_UNKNOWN_COMMAND, cmd, 0 ); |
| 911 | return; |
| @@ -954,11 +949,11 @@ | |
| 954 | json_mode_bootstrap(); |
| 955 | if( g.argc<3 ){ |
| 956 | goto usage; |
| 957 | } |
| 958 | db_find_and_open_repository(0, 0); |
| 959 | cmd = json_path_part(1); |
| 960 | n = cmd ? strlen(cmd) : 0; |
| 961 | if( n==0 ){ |
| 962 | goto usage; |
| 963 | } |
| 964 | cgi_set_content_type( cson_cgi_guess_content_type(&g.json.cgiCx) ); |
| 965 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -281,13 +281,17 @@ | |
| 281 | /* avoids debug messages on stderr in JSON mode */ |
| 282 | sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0); |
| 283 | #endif |
| 284 | |
| 285 | /* |
| 286 | The following if/else block translates the PATH_INFO path (in |
| 287 | CLI/server modes) or g.argv (CLI mode) into an internal list so |
| 288 | that we can simplify command dispatching later on. |
| 289 | |
| 290 | Note that translating g.argv this way is overkill but allows us to |
| 291 | avoid CLI-only special-case handling in other code, e.g. |
| 292 | json_command_arg(). |
| 293 | */ |
| 294 | if( pathSplit ){ |
| 295 | /* cson_cgi already did this, so let's just re-use it. This does |
| 296 | not happen in "plain server" mode, but does in CGI mode. |
| 297 | */ |
| @@ -331,11 +335,11 @@ | |
| 335 | /* assume CLI mode */ |
| 336 | int i; |
| 337 | char const * arg; |
| 338 | cson_value * part; |
| 339 | assert( (!g.isCGI) && "g.isCGI set and we do not expect that to be the case here." ); |
| 340 | for(i = 1/*skip argv[0]*/; i < g.argc; ++i ){ |
| 341 | arg = g.argv[i]; |
| 342 | if( !arg || !*arg ) continue; |
| 343 | part = cson_value_new_string(arg,strlen(arg)); |
| 344 | cson_array_append(ar, part); |
| 345 | } |
| @@ -366,29 +370,23 @@ | |
| 370 | ** of bounds or there is no "json" path element. |
| 371 | ** |
| 372 | ** In CLI mode the "path" is the list of arguments (skipping argv[0]). |
| 373 | ** In server/CGI modes the path is taken from PATH_INFO. |
| 374 | */ |
| 375 | static char const * json_command_arg(unsigned char ndx){ |
| 376 | cson_array * ar = cson_value_get_array( |
| 377 | cson_cgi_getenv(&g.json.cgiCx, |
| 378 | "a", |
| 379 | FossilJsonKeys.commandPath)); |
| 380 | assert((NULL!=ar) && "Internal error. Was json_mode_bootstrap() called?"); |
| 381 | if( g.json.cmdOffset < 0 ){ |
| 382 | /* first-time setup. */ |
| 383 | short i = 0; |
| 384 | #define NEXT cson_string_cstr( \ |
| 385 | cson_value_get_string( \ |
| 386 | cson_array_get(ar,i) \ |
| 387 | )) |
| 388 | char const * tok = NEXT; |
| 389 | while( tok ){ |
| 390 | if( 0==strncmp("json",tok,4) ){ |
| 391 | g.json.cmdOffset = i; |
| 392 | break; |
| @@ -396,19 +394,15 @@ | |
| 394 | ++i; |
| 395 | tok = NEXT; |
| 396 | } |
| 397 | } |
| 398 | #undef NEXT |
| 399 | if( g.json.cmdOffset < 0 ){ |
| 400 | return NULL; |
| 401 | }else{ |
| 402 | ndx = g.json.cmdOffset + ndx; |
| 403 | return cson_string_cstr(cson_value_get_string(cson_array_get( ar, g.json.cmdOffset + ndx ))); |
| 404 | } |
| 405 | } |
| 406 | |
| 407 | /* |
| 408 | ** If g.json.reqPayload.o is NULL then NULL is returned, else the |
| @@ -543,11 +537,11 @@ | |
| 537 | |
| 538 | tmp = cson_value_new_string(MANIFEST_UUID,strlen(MANIFEST_UUID)); |
| 539 | SET("fossil"); |
| 540 | |
| 541 | {/* "timestamp" */ |
| 542 | time_t const t = (time_t)time(0); |
| 543 | struct tm gt = *gmtime(&t); |
| 544 | cson_int_t jsTime = (cson_int_t)mktime(>); |
| 545 | tmp = cson_value_new_integer(jsTime); |
| 546 | SET("timestamp"); |
| 547 | } |
| @@ -570,11 +564,12 @@ | |
| 564 | tmp = payload; |
| 565 | SET("payload"); |
| 566 | } |
| 567 | } |
| 568 | #undef SET |
| 569 | |
| 570 | if(0){/*Only for debuggering, add some info to the response.*/ |
| 571 | tmp = cson_cgi_env_get_val(&g.json.cgiCx,'a', 0); |
| 572 | if(tmp){ |
| 573 | cson_object_set( o, "$APP", tmp ); |
| 574 | } |
| 575 | tmp = cson_value_new_integer( g.json.cmdOffset ); |
| @@ -901,11 +896,11 @@ | |
| 896 | cson_value * payload = NULL; |
| 897 | cson_value * root = NULL; |
| 898 | JsonPageDef const * pageDef = NULL; |
| 899 | cgi_set_content_type( cson_cgi_guess_content_type(&g.json.cgiCx) ); |
| 900 | json_mode_bootstrap(); |
| 901 | cmd = json_command_arg(1); |
| 902 | /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/ |
| 903 | pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]); |
| 904 | if( ! pageDef ){ |
| 905 | json_err( FSL_JSON_E_UNKNOWN_COMMAND, cmd, 0 ); |
| 906 | return; |
| @@ -954,11 +949,11 @@ | |
| 949 | json_mode_bootstrap(); |
| 950 | if( g.argc<3 ){ |
| 951 | goto usage; |
| 952 | } |
| 953 | db_find_and_open_repository(0, 0); |
| 954 | cmd = json_command_arg(1); |
| 955 | n = cmd ? strlen(cmd) : 0; |
| 956 | if( n==0 ){ |
| 957 | goto usage; |
| 958 | } |
| 959 | cgi_set_content_type( cson_cgi_guess_content_type(&g.json.cgiCx) ); |
| 960 |