Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Added initial JSONP support, but lacks significant testing. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | json |
Files: | files | file ages | folders |
SHA1: |
e72ae99dc2aa29b57f2c29014225c2c7 |
User & Date: | stephan 2011-09-23 00:39:41.248 |
Context
2011-09-23
| ||
01:00 | Corrected /json/wiki/save|create to honor the proper g.perm.WrWiki/NewWiki perm, instead of just WrWiki. ... (check-in: d3759cd4 user: stephan tags: json) | |
00:39 | Added initial JSONP support, but lacks significant testing. ... (check-in: e72ae99d user: stephan tags: json) | |
2011-09-22
| ||
23:40 | Added --after/--before support to /json/timeline/ci and wiki. ... (check-in: e01d49b2 user: stephan tags: json) | |
Changes
Changes to src/json.c.
︙ | ︙ | |||
215 216 217 218 219 220 221 222 223 224 225 226 227 228 | */ cson_value * cson_parse_Blob( Blob * pSrc, cson_parse_info * pInfo ){ cson_value * root = NULL; blob_rewind( pSrc ); cson_parse( &root, cson_data_src_Blob, pSrc, NULL, pInfo ); return root; } /* ** Returns a string in the form FOSSIL-XXXX, where XXXX is a ** left-zero-padded value of code. The returned buffer is static, and ** must be copied if needed for later. The returned value will always ** be 11 bytes long (not including the trailing NUL byte). ** | > > > > > > > > | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | */ cson_value * cson_parse_Blob( Blob * pSrc, cson_parse_info * pInfo ){ cson_value * root = NULL; blob_rewind( pSrc ); cson_parse( &root, cson_data_src_Blob, pSrc, NULL, pInfo ); return root; } /* ** Implements the cson_data_dest_f() interface and outputs the data to ** cgi_append_content(). pState is ignored. **/ int cson_data_dest_cgi(void * pState, void const * src, unsigned int n){ cgi_append_content( (char const *)src, (int)n ); return 0; } /* ** Returns a string in the form FOSSIL-XXXX, where XXXX is a ** left-zero-padded value of code. The returned buffer is static, and ** must be copied if needed for later. The returned value will always ** be 11 bytes long (not including the trailing NUL byte). ** |
︙ | ︙ | |||
422 423 424 425 426 427 428 429 430 431 432 433 434 435 | : "application/json"; }else{ return "text/plain"; } } } } /* ** Returns the current request's JSON authentication token, or NULL if ** none is found. The token's memory is owned by (or shared with) ** g.json. ** ** If an auth token is found in the GET/POST request data then fossil | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | : "application/json"; }else{ return "text/plain"; } } } } /* ** Sends pResponse to the output stream as the response object. This ** function does no validation of pResponse except to assert() that it ** is not NULL. The caller is responsible for ensuring that it meets ** API response envelope conventions. ** ** In CLI mode pResponse is sent to stdout immediately. In HTTP ** mode pResponse replaces any current CGI content but cgi_reply() ** is not called to flush the output. ** ** If g.json.jsonp is not NULL then the content type is set to ** application/javascript and the output is wrapped in a jsonp ** wrapper. */ void json_send_response( cson_value const * pResponse ){ assert( NULL != pResponse ); if( g.isHTTP ){ cgi_reset_content(); if( g.json.jsonp ){ cgi_printf("%s(",g.json.jsonp); } cson_output( pResponse, cson_data_dest_cgi, NULL, &g.json.outOpt ); if( g.json.jsonp ){ cgi_append_content(")",1); } }else{/*CLI mode*/ if( g.json.jsonp ){ fprintf(stdout,"%s(",g.json.jsonp); } cson_output_FILE( pResponse, stdout, &g.json.outOpt ); if( g.json.jsonp ){ fwrite(")\n", 2, 1, stdout); } } } /* ** Returns the current request's JSON authentication token, or NULL if ** none is found. The token's memory is owned by (or shared with) ** g.json. ** ** If an auth token is found in the GET/POST request data then fossil |
︙ | ︙ | |||
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | cson_value * pathSplit = NULL; assert( (0==once) && "json_mode_bootstrap() called too many times!"); if( once ){ return; }else{ once = 1; } g.json.isJsonMode = 1; g.json.resultCode = 0; g.json.cmd.offset = -1; if( !g.isHTTP && g.fullHttpReply ){ /* workaround for server mode, so we see it as CGI mode. */ g.isHTTP = 1; } if( !g.isHTTP ){ g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/; | > > > > > > > | | | < > | | | < > > | 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 | cson_value * pathSplit = NULL; assert( (0==once) && "json_mode_bootstrap() called too many times!"); if( once ){ return; }else{ once = 1; } g.json.jsonp = PD("jsonp",NULL); g.json.isJsonMode = 1; g.json.resultCode = 0; g.json.cmd.offset = -1; if( !g.isHTTP && g.fullHttpReply ){ /* workaround for server mode, so we see it as CGI mode. */ g.isHTTP = 1; } if(!g.json.jsonp && g.json.post.o){ g.json.jsonp = cson_string_cstr(cson_value_get_string(cson_object_get(g.json.post.o,"jsonp"))); } if( !g.isHTTP ){ g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/; if(!g.json.jsonp){ g.json.jsonp = find_option("jsonp",NULL,1); } } /* FIXME: do some sanity checking on g.json.jsonp and ignore it if it is not halfway reasonable. */ cgi_set_content_type(json_guess_content_type()) /* reminder: must be done after g.json.jsonp is initialized */ ; #if defined(NDEBUG) /* avoids debug messages on stderr in JSON mode */ sqlite3_config(SQLITE_CONFIG_LOG, NULL, 0); #endif g.json.cmd.v = cson_value_new_array(); |
︙ | ︙ | |||
791 792 793 794 795 796 797 | : 0; }else if(cson_value_is_number(indentV)){ cson_int_t const n = cson_value_get_integer(indentV); indent = (n>0) ? (unsigned char)n : 0; } } g.json.outOpt.indentation = indent; | | > > | 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 | : 0; }else if(cson_value_is_number(indentV)){ cson_int_t const n = cson_value_get_integer(indentV); indent = (n>0) ? (unsigned char)n : 0; } } g.json.outOpt.indentation = indent; g.json.outOpt.addNewline = g.isHTTP ? 0 : (g.json.jsonp ? 0 : 1); } if( g.isHTTP ){ json_auth_token()/* will copy our auth token, if any, to fossil's core, which we need before we call login_check_credentials(). */; login_check_credentials()/* populates g.perm */; |
︙ | ︙ | |||
992 993 994 995 996 997 998 | ** response. If resultCode is non-0 and pMsg is NULL then ** json_err_str() is used to get the error string. The caller may ** provide his own or may use an empty string to suppress the ** resultText property. ** */ cson_value * json_create_response( int resultCode, | > | < | 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 | ** response. If resultCode is non-0 and pMsg is NULL then ** json_err_str() is used to get the error string. The caller may ** provide his own or may use an empty string to suppress the ** resultText property. ** */ cson_value * json_create_response( int resultCode, char const * pMsg, cson_value * payload){ cson_value * v = NULL; cson_value * tmp = NULL; cson_object * o = NULL; int rc; resultCode = json_dumbdown_rc(resultCode); v = cson_value_new_object(); o = cson_value_get_object(v); |
︙ | ︙ | |||
1098 1099 1100 1101 1102 1103 1104 | ? g.json.resultCode : FSL_JSON_E_UNKNOWN); cson_value * resp = NULL; rc = json_dumbdown_rc(rc); if( rc && !msg ){ msg = json_err_str(rc); } | | | > > > > | | | > > | | | > | | 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 | ? g.json.resultCode : FSL_JSON_E_UNKNOWN); cson_value * resp = NULL; rc = json_dumbdown_rc(rc); if( rc && !msg ){ msg = json_err_str(rc); } resp = json_create_response(rc, msg, NULL); if(!resp){ /* about the only error case here is out-of-memory. DO NOT call fossil_panic() here because that calls this function. */ fprintf(stderr, "%s: Fatal error: could not allocate " "response object.\n", fossil_nameofexe()); fossil_exit(1); } if( g.isHTTP ){ if(alsoOutput){ json_send_response(resp); }else{ /* almost a duplicate of json_send_response() :( */ cgi_set_content_type("application/javascript"); cgi_reset_content(); if( g.json.jsonp ){ cgi_printf("%s(",g.json.jsonp); } cson_output( resp, cson_data_dest_cgi, NULL, &g.json.outOpt ); if( g.json.jsonp ){ cgi_append_content(")",1); } } }else{ json_send_response(resp); } cson_value_free(resp); } /* ** /json/version implementation. ** |
︙ | ︙ | |||
2346 2347 2348 2349 2350 2351 2352 | ** ** Pages under /json/... must be entered into JsonPageDefs. ** This function dispatches them, and is the HTTP equivalent of ** json_cmd_top(). */ void json_page_top(void){ int rc = FSL_JSON_E_UNKNOWN_COMMAND; | < < | | < | 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 | ** ** Pages under /json/... must be entered into JsonPageDefs. ** This function dispatches them, and is the HTTP equivalent of ** json_cmd_top(). */ void json_page_top(void){ int rc = FSL_JSON_E_UNKNOWN_COMMAND; char const * cmd; cson_value * payload = NULL; cson_value * root = NULL; JsonPageDef const * pageDef = NULL; json_mode_bootstrap(); cmd = json_command_arg(1); /*cgi_printf("{\"cmd\":\"%s\"}\n",cmd); return;*/ pageDef = json_handler_for_name(cmd,&JsonPageDefs[0]); if( ! pageDef ){ json_err( FSL_JSON_E_UNKNOWN_COMMAND, NULL, 0 ); return; }else if( pageDef->runMode < 0 /*CLI only*/){ rc = FSL_JSON_E_WRONG_MODE; }else{ rc = 0; payload = (*pageDef->func)(1); } if( g.json.resultCode ){ json_err(g.json.resultCode, NULL, 0); }else{ root = json_create_response(rc, NULL, payload); json_send_response(payload); cson_value_free(root); } } /* ** This function dispatches json commands and is the CLI equivalent of ** json_page_top(). ** |
︙ | ︙ | |||
2441 2442 2443 2444 2445 2446 2447 | }else{ rc = 0; payload = (*pageDef->func)(1); } if( g.json.resultCode ){ json_err(g.json.resultCode, NULL, 1); }else{ | | | | 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 | }else{ rc = 0; payload = (*pageDef->func)(1); } if( g.json.resultCode ){ json_err(g.json.resultCode, NULL, 1); }else{ payload = json_create_response(rc, NULL, payload); json_send_response(payload); cson_value_free( payload ); if((0 != rc) && !g.isHTTP){ /* FIXME: we need a way of passing this error back up to the routine which called this callback. e.g. add g.errCode. */ fossil_exit(1); |
︙ | ︙ |