| | @@ -26,13 +26,14 @@ |
| 26 | 26 | #include <sys/types.h> |
| 27 | 27 | #include <sys/stat.h> |
| 28 | 28 | #include <stdlib.h> /* atexit() */ |
| 29 | 29 | |
| 30 | 30 | #if INTERFACE |
| 31 | | -#include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ |
| 32 | | -#include "json_detail.h" |
| 33 | | - |
| 31 | +#ifdef FOSSIL_ENABLE_JSON |
| 32 | +# include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ |
| 33 | +# include "json_detail.h" |
| 34 | +#endif |
| 34 | 35 | /* |
| 35 | 36 | ** Number of elements in an array |
| 36 | 37 | */ |
| 37 | 38 | #define count(X) (sizeof(X)/sizeof(X[0])) |
| 38 | 39 | |
| | @@ -170,10 +171,11 @@ |
| 170 | 171 | const char **azAuxOpt[MX_AUX]; /* Options of each option() value */ |
| 171 | 172 | int anAuxCols[MX_AUX]; /* Number of columns for option() values */ |
| 172 | 173 | |
| 173 | 174 | int allowSymlinks; /* Cached "allow-symlinks" option */ |
| 174 | 175 | |
| 176 | +#ifdef FOSSIL_ENABLE_JSON |
| 175 | 177 | struct FossilJsonBits { |
| 176 | 178 | int isJsonMode; /* True if running in JSON mode, else |
| 177 | 179 | false. This changes how errors are |
| 178 | 180 | reported. In JSON mode we try to |
| 179 | 181 | always output JSON-form error |
| | @@ -223,10 +225,11 @@ |
| 223 | 225 | struct { /* response warnings */ |
| 224 | 226 | cson_value * v; |
| 225 | 227 | cson_array * a; |
| 226 | 228 | } warnings; |
| 227 | 229 | } json; |
| 230 | +#endif /* FOSSIL_ENABLE_JSON */ |
| 228 | 231 | }; |
| 229 | 232 | |
| 230 | 233 | /* |
| 231 | 234 | ** Macro for debugging: |
| 232 | 235 | */ |
| | @@ -293,14 +296,15 @@ |
| 293 | 296 | /* |
| 294 | 297 | ** atexit() handler which frees up "some" of the resources |
| 295 | 298 | ** used by fossil. |
| 296 | 299 | */ |
| 297 | 300 | void fossil_atexit() { |
| 298 | | - |
| 301 | +#ifdef FOSSIL_ENABLE_JSON |
| 299 | 302 | cson_value_free(g.json.gc.v); |
| 300 | | - free(g.zErrMsg); |
| 301 | 303 | memset(&g.json, 0, sizeof(g.json)); |
| 304 | +#endif |
| 305 | + free(g.zErrMsg); |
| 302 | 306 | if(g.db){ |
| 303 | 307 | db_close(0); |
| 304 | 308 | } |
| 305 | 309 | } |
| 306 | 310 | |
| | @@ -390,10 +394,11 @@ |
| 390 | 394 | sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0); |
| 391 | 395 | memset(&g, 0, sizeof(g)); |
| 392 | 396 | g.now = time(0); |
| 393 | 397 | g.argc = argc; |
| 394 | 398 | g.argv = argv; |
| 399 | +#ifdef FOSSIL_ENABLE_JSON |
| 395 | 400 | #if defined(NDEBUG) |
| 396 | 401 | g.json.errorDetailParanoia = 2 /* FIXME: make configurable |
| 397 | 402 | One problem we have here is that this |
| 398 | 403 | code is needed before the db is opened, |
| 399 | 404 | so we can't sql for it.*/; |
| | @@ -401,10 +406,11 @@ |
| 401 | 406 | g.json.errorDetailParanoia = 0; |
| 402 | 407 | #endif |
| 403 | 408 | g.json.outOpt = cson_output_opt_empty; |
| 404 | 409 | g.json.outOpt.addNewline = 1; |
| 405 | 410 | g.json.outOpt.indentation = 1 /* in CGI/server mode this can be configured */; |
| 411 | +#endif /* FOSSIL_ENABLE_JSON */ |
| 406 | 412 | expand_args_option(); |
| 407 | 413 | argc = g.argc; |
| 408 | 414 | argv = g.argv; |
| 409 | 415 | for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]); |
| 410 | 416 | if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){ |
| | @@ -462,15 +468,10 @@ |
| 462 | 468 | "%s: could be any of:%s\n" |
| 463 | 469 | "%s: use \"help\" for more information\n", |
| 464 | 470 | argv[0], zCmdName, argv[0], blob_str(&couldbe), argv[0]); |
| 465 | 471 | fossil_exit(1); |
| 466 | 472 | } |
| 467 | | - if(rc){ |
| 468 | | - fossil_fatal("%s: unrecoverable error while initializing JSON CGI bits: " |
| 469 | | - "cson error code #%d (%s)\n", |
| 470 | | - argv[0], rc, cson_rc_string(rc)); |
| 471 | | - } |
| 472 | 473 | atexit( fossil_atexit ); |
| 473 | 474 | aCommand[idx].xFunc(); |
| 474 | 475 | fossil_exit(0); |
| 475 | 476 | /*NOT_REACHED*/ |
| 476 | 477 | return 0; |
| | @@ -513,22 +514,28 @@ |
| 513 | 514 | static int once = 1; |
| 514 | 515 | mainInFatalError = 1; |
| 515 | 516 | va_start(ap, zFormat); |
| 516 | 517 | z = vmprintf(zFormat, ap); |
| 517 | 518 | va_end(ap); |
| 519 | +#ifdef FOSSIL_ENABLE_JSON |
| 518 | 520 | if( g.json.isJsonMode ){ |
| 519 | 521 | json_err( 0, z, 1 ); |
| 520 | 522 | if( g.isHTTP ){ |
| 521 | 523 | rc = 0 /* avoid HTTP 500 */; |
| 522 | 524 | } |
| 523 | | - }else if( g.cgiOutput && once ){ |
| 524 | | - once = 0; |
| 525 | | - cgi_printf("<p class=\"generalError\">%h</p>", z); |
| 526 | | - cgi_reply(); |
| 527 | | - }else{ |
| 528 | | - char *zOut = mprintf("%s: %s\n", fossil_nameofexe(), z); |
| 529 | | - fossil_puts(zOut, 1); |
| 525 | + } |
| 526 | + else |
| 527 | +#endif |
| 528 | + { |
| 529 | + if( g.cgiOutput && once ){ |
| 530 | + once = 0; |
| 531 | + cgi_printf("<p class=\"generalError\">%h</p>", z); |
| 532 | + cgi_reply(); |
| 533 | + }else{ |
| 534 | + char *zOut = mprintf("%s: %s\n", fossil_nameofexe(), z); |
| 535 | + fossil_puts(zOut, 1); |
| 536 | + } |
| 530 | 537 | } |
| 531 | 538 | free(z); |
| 532 | 539 | db_force_rollback(); |
| 533 | 540 | fossil_exit(rc); |
| 534 | 541 | } |
| | @@ -539,23 +546,28 @@ |
| 539 | 546 | va_list ap; |
| 540 | 547 | mainInFatalError = 1; |
| 541 | 548 | va_start(ap, zFormat); |
| 542 | 549 | z = vmprintf(zFormat, ap); |
| 543 | 550 | va_end(ap); |
| 551 | +#ifdef FOSSIL_ENABLE_JSON |
| 544 | 552 | if( g.json.isJsonMode ){ |
| 545 | 553 | json_err( g.json.resultCode, z, 1 ); |
| 546 | 554 | if( g.isHTTP ){ |
| 547 | 555 | rc = 0 /* avoid HTTP 500 */; |
| 548 | 556 | } |
| 549 | 557 | } |
| 550 | | - else if( g.cgiOutput ){ |
| 551 | | - g.cgiOutput = 0; |
| 552 | | - cgi_printf("<p class=\"generalError\">%h</p>", z); |
| 553 | | - cgi_reply(); |
| 554 | | - }else{ |
| 555 | | - char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z); |
| 556 | | - fossil_puts(zOut, 1); |
| 558 | + else |
| 559 | +#endif |
| 560 | + { |
| 561 | + if( g.cgiOutput ){ |
| 562 | + g.cgiOutput = 0; |
| 563 | + cgi_printf("<p class=\"generalError\">%h</p>", z); |
| 564 | + cgi_reply(); |
| 565 | + }else{ |
| 566 | + char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z); |
| 567 | + fossil_puts(zOut, 1); |
| 568 | + } |
| 557 | 569 | } |
| 558 | 570 | free(z); |
| 559 | 571 | db_force_rollback(); |
| 560 | 572 | fossil_exit(rc); |
| 561 | 573 | } |
| | @@ -576,23 +588,28 @@ |
| 576 | 588 | if( mainInFatalError ) return; |
| 577 | 589 | mainInFatalError = 1; |
| 578 | 590 | va_start(ap, zFormat); |
| 579 | 591 | z = vmprintf(zFormat, ap); |
| 580 | 592 | va_end(ap); |
| 593 | +#ifdef FOSSIL_ENABLE_JSON |
| 581 | 594 | if( g.json.isJsonMode ){ |
| 582 | 595 | json_err( g.json.resultCode, z, 1 ); |
| 583 | 596 | if( g.isHTTP ){ |
| 584 | 597 | rc = 0 /* avoid HTTP 500 */; |
| 585 | 598 | } |
| 586 | | - }else if( g.cgiOutput ){ |
| 587 | | - g.cgiOutput = 0; |
| 588 | | - cgi_printf("<p class=\"generalError\">%h</p>", z); |
| 589 | | - cgi_reply(); |
| 590 | | - }else{ |
| 591 | | - char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z); |
| 592 | | - fossil_puts(zOut, 1); |
| 593 | | - free(zOut); |
| 599 | + } else |
| 600 | +#endif |
| 601 | + { |
| 602 | + if( g.cgiOutput ){ |
| 603 | + g.cgiOutput = 0; |
| 604 | + cgi_printf("<p class=\"generalError\">%h</p>", z); |
| 605 | + cgi_reply(); |
| 606 | + }else{ |
| 607 | + char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z); |
| 608 | + fossil_puts(zOut, 1); |
| 609 | + free(zOut); |
| 610 | + } |
| 594 | 611 | } |
| 595 | 612 | db_force_rollback(); |
| 596 | 613 | fossil_exit(rc); |
| 597 | 614 | } |
| 598 | 615 | |
| | @@ -602,18 +619,23 @@ |
| 602 | 619 | char *z; |
| 603 | 620 | va_list ap; |
| 604 | 621 | va_start(ap, zFormat); |
| 605 | 622 | z = vmprintf(zFormat, ap); |
| 606 | 623 | va_end(ap); |
| 624 | +#ifdef FOSSIL_ENABLE_JSON |
| 607 | 625 | if(g.json.isJsonMode){ |
| 608 | 626 | json_warn( FSL_JSON_W_UNKNOWN, z ); |
| 609 | | - }else if( g.cgiOutput ){ |
| 610 | | - cgi_printf("<p class=\"generalError\">%h</p>", z); |
| 611 | | - }else{ |
| 612 | | - char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z); |
| 613 | | - fossil_puts(zOut, 1); |
| 614 | | - free(zOut); |
| 627 | + }else |
| 628 | +#endif |
| 629 | + { |
| 630 | + if( g.cgiOutput ){ |
| 631 | + cgi_printf("<p class=\"generalError\">%h</p>", z); |
| 632 | + }else{ |
| 633 | + char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z); |
| 634 | + fossil_puts(zOut, 1); |
| 635 | + free(zOut); |
| 636 | + } |
| 615 | 637 | } |
| 616 | 638 | free(z); |
| 617 | 639 | } |
| 618 | 640 | |
| 619 | 641 | /* |
| | @@ -1154,17 +1176,19 @@ |
| 1154 | 1176 | |
| 1155 | 1177 | if( szFile<1024 ){ |
| 1156 | 1178 | if( zNotFound ){ |
| 1157 | 1179 | cgi_redirect(zNotFound); |
| 1158 | 1180 | }else{ |
| 1181 | +#ifdef FOSSIL_ENABLE_JSON |
| 1159 | 1182 | if(g.json.isJsonMode){ |
| 1160 | 1183 | json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1); |
| 1161 | | - }else{ |
| 1162 | | - @ <h1>Not Found</h1> |
| 1163 | | - cgi_set_status(404, "not found"); |
| 1164 | | - cgi_reply(); |
| 1184 | + return; |
| 1165 | 1185 | } |
| 1186 | +#endif |
| 1187 | + @ <h1>Not Found</h1> |
| 1188 | + cgi_set_status(404, "not found"); |
| 1189 | + cgi_reply(); |
| 1166 | 1190 | } |
| 1167 | 1191 | return; |
| 1168 | 1192 | } |
| 1169 | 1193 | break; |
| 1170 | 1194 | } |
| | @@ -1189,16 +1213,17 @@ |
| 1189 | 1213 | zPathInfo = "/xfer"; |
| 1190 | 1214 | } |
| 1191 | 1215 | set_base_url(); |
| 1192 | 1216 | if( zPathInfo==0 || zPathInfo[0]==0 |
| 1193 | 1217 | || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){ |
| 1218 | +#ifdef FOSSIL_ENABLE_JSON |
| 1194 | 1219 | if(g.json.isJsonMode){ |
| 1195 | 1220 | json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1); |
| 1196 | 1221 | fossil_exit(0); |
| 1197 | | - }else{ |
| 1198 | | - fossil_redirect_home() /*does not return*/; |
| 1199 | 1222 | } |
| 1223 | +#endif |
| 1224 | + fossil_redirect_home() /*does not return*/; |
| 1200 | 1225 | }else{ |
| 1201 | 1226 | zPath = mprintf("%s", zPathInfo); |
| 1202 | 1227 | } |
| 1203 | 1228 | |
| 1204 | 1229 | /* Make g.zPath point to the first element of the path. Make |
| | @@ -1267,21 +1292,27 @@ |
| 1267 | 1292 | /* Locate the method specified by the path and execute the function |
| 1268 | 1293 | ** that implements that method. |
| 1269 | 1294 | */ |
| 1270 | 1295 | if( name_search(g.zPath, aWebpage, count(aWebpage), &idx) && |
| 1271 | 1296 | name_search("not_found", aWebpage, count(aWebpage), &idx) ){ |
| 1297 | +#ifdef FOSSIL_ENABLE_JSON |
| 1272 | 1298 | if(g.json.isJsonMode){ |
| 1273 | 1299 | json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,0); |
| 1274 | | - }else{ |
| 1300 | + }else |
| 1301 | +#endif |
| 1302 | + { |
| 1275 | 1303 | cgi_set_status(404,"Not Found"); |
| 1276 | 1304 | @ <h1>Not Found</h1> |
| 1277 | 1305 | @ <p>Page not found: %h(g.zPath)</p> |
| 1278 | 1306 | } |
| 1279 | 1307 | }else if( aWebpage[idx].xFunc!=page_xfer && db_schema_is_outofdate() ){ |
| 1308 | +#ifdef FOSSIL_ENABLE_JSON |
| 1280 | 1309 | if(g.json.isJsonMode){ |
| 1281 | 1310 | json_err(FSL_JSON_E_DB_NEEDS_REBUILD,NULL,0); |
| 1282 | | - }else{ |
| 1311 | + }else |
| 1312 | +#endif |
| 1313 | + { |
| 1283 | 1314 | @ <h1>Server Configuration Error</h1> |
| 1284 | 1315 | @ <p>The database schema on the server is out-of-date. Please ask |
| 1285 | 1316 | @ the administrator to run <b>fossil rebuild</b>.</p> |
| 1286 | 1317 | } |
| 1287 | 1318 | }else{ |
| 1288 | 1319 | |