Fossil SCM
Enhancement to codecheck1.c to verify that routines like db_set() use a string literal as the setting argument, and are thus impervious to injection attacks.
Commit
0a5d0e191cd6ff1dae343b85accf0da1aaf1d2e4be426ebed3863a361bf08623
Parent
ccce70fb59a636a…
12 files changed
+1
-1
+1
-1
+1
-3
+2
-6
+91
-58
+9
-4
+1
-3
+1
-1
+15
-15
+3
-5
+2
-2
+2
-2
+1
-1
| --- src/alerts.c | ||
| +++ src/alerts.c | ||
| @@ -1153,11 +1153,11 @@ | ||
| 1153 | 1153 | const char *zLabel = g.argv[3]; |
| 1154 | 1154 | if( strncmp(zLabel, "email-", 6)!=0 |
| 1155 | 1155 | || (pSetting = db_find_setting(zLabel, 1))==0 ){ |
| 1156 | 1156 | fossil_fatal("not a valid email setting: \"%s\"", zLabel); |
| 1157 | 1157 | } |
| 1158 | - db_set(pSetting->name, g.argv[4], isGlobal); | |
| 1158 | + db_set(pSetting->name/*works-like:""*/, g.argv[4], isGlobal); | |
| 1159 | 1159 | g.argc = 3; |
| 1160 | 1160 | } |
| 1161 | 1161 | pSetting = setting_info(&nSetting); |
| 1162 | 1162 | for(; nSetting>0; nSetting--, pSetting++ ){ |
| 1163 | 1163 | if( strncmp(pSetting->name,"email-",6)!=0 ) continue; |
| 1164 | 1164 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -1153,11 +1153,11 @@ | |
| 1153 | const char *zLabel = g.argv[3]; |
| 1154 | if( strncmp(zLabel, "email-", 6)!=0 |
| 1155 | || (pSetting = db_find_setting(zLabel, 1))==0 ){ |
| 1156 | fossil_fatal("not a valid email setting: \"%s\"", zLabel); |
| 1157 | } |
| 1158 | db_set(pSetting->name, g.argv[4], isGlobal); |
| 1159 | g.argc = 3; |
| 1160 | } |
| 1161 | pSetting = setting_info(&nSetting); |
| 1162 | for(; nSetting>0; nSetting--, pSetting++ ){ |
| 1163 | if( strncmp(pSetting->name,"email-",6)!=0 ) continue; |
| 1164 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -1153,11 +1153,11 @@ | |
| 1153 | const char *zLabel = g.argv[3]; |
| 1154 | if( strncmp(zLabel, "email-", 6)!=0 |
| 1155 | || (pSetting = db_find_setting(zLabel, 1))==0 ){ |
| 1156 | fossil_fatal("not a valid email setting: \"%s\"", zLabel); |
| 1157 | } |
| 1158 | db_set(pSetting->name/*works-like:""*/, g.argv[4], isGlobal); |
| 1159 | g.argc = 3; |
| 1160 | } |
| 1161 | pSetting = setting_info(&nSetting); |
| 1162 | for(; nSetting>0; nSetting--, pSetting++ ){ |
| 1163 | if( strncmp(pSetting->name,"email-",6)!=0 ) continue; |
| 1164 |
+1
-1
| --- src/bisect.c | ||
| +++ src/bisect.c | ||
| @@ -673,11 +673,11 @@ | ||
| 673 | 673 | n = strlen(g.argv[3]); |
| 674 | 674 | for(i=0; i<count(aBisectOption); i++){ |
| 675 | 675 | if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){ |
| 676 | 676 | char *z = mprintf("bisect-%s", aBisectOption[i].zName); |
| 677 | 677 | if( g.argc==5 ){ |
| 678 | - db_lset(z, g.argv[4]); | |
| 678 | + db_lset(z/*works-like:"bisect-%s"*/, g.argv[4]); | |
| 679 | 679 | } |
| 680 | 680 | fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault)); |
| 681 | 681 | fossil_free(z); |
| 682 | 682 | break; |
| 683 | 683 | } |
| 684 | 684 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -673,11 +673,11 @@ | |
| 673 | n = strlen(g.argv[3]); |
| 674 | for(i=0; i<count(aBisectOption); i++){ |
| 675 | if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){ |
| 676 | char *z = mprintf("bisect-%s", aBisectOption[i].zName); |
| 677 | if( g.argc==5 ){ |
| 678 | db_lset(z, g.argv[4]); |
| 679 | } |
| 680 | fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault)); |
| 681 | fossil_free(z); |
| 682 | break; |
| 683 | } |
| 684 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -673,11 +673,11 @@ | |
| 673 | n = strlen(g.argv[3]); |
| 674 | for(i=0; i<count(aBisectOption); i++){ |
| 675 | if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){ |
| 676 | char *z = mprintf("bisect-%s", aBisectOption[i].zName); |
| 677 | if( g.argc==5 ){ |
| 678 | db_lset(z/*works-like:"bisect-%s"*/, g.argv[4]); |
| 679 | } |
| 680 | fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault)); |
| 681 | fossil_free(z); |
| 682 | break; |
| 683 | } |
| 684 |
+1
-3
| --- src/checkout.c | ||
| +++ src/checkout.c | ||
| @@ -418,13 +418,11 @@ | ||
| 418 | 418 | && db_exists("SELECT 1 FROM localdb.stash") |
| 419 | 419 | ){ |
| 420 | 420 | fossil_fatal("closing the checkout will delete your stash"); |
| 421 | 421 | } |
| 422 | 422 | if( db_is_writeable("repository") ){ |
| 423 | - char *zUnset = mprintf("ckout:%q", g.zLocalRoot); | |
| 424 | - db_unset(zUnset, 1); | |
| 425 | - fossil_free(zUnset); | |
| 423 | + db_unset_mprintf(1, "ckout:%q", g.zLocalRoot); | |
| 426 | 424 | } |
| 427 | 425 | unlink_local_database(1); |
| 428 | 426 | db_close(1); |
| 429 | 427 | unlink_local_database(0); |
| 430 | 428 | } |
| 431 | 429 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -418,13 +418,11 @@ | |
| 418 | && db_exists("SELECT 1 FROM localdb.stash") |
| 419 | ){ |
| 420 | fossil_fatal("closing the checkout will delete your stash"); |
| 421 | } |
| 422 | if( db_is_writeable("repository") ){ |
| 423 | char *zUnset = mprintf("ckout:%q", g.zLocalRoot); |
| 424 | db_unset(zUnset, 1); |
| 425 | fossil_free(zUnset); |
| 426 | } |
| 427 | unlink_local_database(1); |
| 428 | db_close(1); |
| 429 | unlink_local_database(0); |
| 430 | } |
| 431 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -418,13 +418,11 @@ | |
| 418 | && db_exists("SELECT 1 FROM localdb.stash") |
| 419 | ){ |
| 420 | fossil_fatal("closing the checkout will delete your stash"); |
| 421 | } |
| 422 | if( db_is_writeable("repository") ){ |
| 423 | db_unset_mprintf(1, "ckout:%q", g.zLocalRoot); |
| 424 | } |
| 425 | unlink_local_database(1); |
| 426 | db_close(1); |
| 427 | unlink_local_database(0); |
| 428 | } |
| 429 |
+2
-6
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -314,26 +314,24 @@ | ||
| 314 | 314 | void remember_or_get_http_auth( |
| 315 | 315 | const char *zHttpAuth, /* Credentials in the form "user:password" */ |
| 316 | 316 | int fRemember, /* True to remember credentials for later reuse */ |
| 317 | 317 | const char *zUrl /* URL for which these credentials apply */ |
| 318 | 318 | ){ |
| 319 | - char *zKey = mprintf("http-auth:%s", g.url.canonical); | |
| 320 | 319 | if( zHttpAuth && zHttpAuth[0] ){ |
| 321 | 320 | g.zHttpAuth = mprintf("%s", zHttpAuth); |
| 322 | 321 | } |
| 323 | 322 | if( fRemember ){ |
| 324 | 323 | if( g.zHttpAuth && g.zHttpAuth[0] ){ |
| 325 | 324 | set_httpauth(g.zHttpAuth); |
| 326 | 325 | }else if( zUrl && zUrl[0] ){ |
| 327 | - db_unset(zKey, 0); | |
| 326 | + db_unset_mprintf(0, "http-auth:%s", g.url.canonical); | |
| 328 | 327 | }else{ |
| 329 | 328 | g.zHttpAuth = get_httpauth(); |
| 330 | 329 | } |
| 331 | 330 | }else if( g.zHttpAuth==0 && zUrl==0 ){ |
| 332 | 331 | g.zHttpAuth = get_httpauth(); |
| 333 | 332 | } |
| 334 | - free(zKey); | |
| 335 | 333 | } |
| 336 | 334 | |
| 337 | 335 | /* |
| 338 | 336 | ** Get the HTTP Authorization preference from db. |
| 339 | 337 | */ |
| @@ -346,13 +344,11 @@ | ||
| 346 | 344 | |
| 347 | 345 | /* |
| 348 | 346 | ** Set the HTTP Authorization preference in db. |
| 349 | 347 | */ |
| 350 | 348 | void set_httpauth(const char *zHttpAuth){ |
| 351 | - char *zKey = mprintf("http-auth:%s", g.url.canonical); | |
| 352 | - db_set(zKey, obscure(zHttpAuth), 0); | |
| 353 | - free(zKey); | |
| 349 | + db_set_mprintf(obscure(zHttpAuth), 0, "http-auth:%s", g.url.canonical); | |
| 354 | 350 | } |
| 355 | 351 | |
| 356 | 352 | /* |
| 357 | 353 | ** Look for SSH clone command line options and setup in globals. |
| 358 | 354 | */ |
| 359 | 355 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -314,26 +314,24 @@ | |
| 314 | void remember_or_get_http_auth( |
| 315 | const char *zHttpAuth, /* Credentials in the form "user:password" */ |
| 316 | int fRemember, /* True to remember credentials for later reuse */ |
| 317 | const char *zUrl /* URL for which these credentials apply */ |
| 318 | ){ |
| 319 | char *zKey = mprintf("http-auth:%s", g.url.canonical); |
| 320 | if( zHttpAuth && zHttpAuth[0] ){ |
| 321 | g.zHttpAuth = mprintf("%s", zHttpAuth); |
| 322 | } |
| 323 | if( fRemember ){ |
| 324 | if( g.zHttpAuth && g.zHttpAuth[0] ){ |
| 325 | set_httpauth(g.zHttpAuth); |
| 326 | }else if( zUrl && zUrl[0] ){ |
| 327 | db_unset(zKey, 0); |
| 328 | }else{ |
| 329 | g.zHttpAuth = get_httpauth(); |
| 330 | } |
| 331 | }else if( g.zHttpAuth==0 && zUrl==0 ){ |
| 332 | g.zHttpAuth = get_httpauth(); |
| 333 | } |
| 334 | free(zKey); |
| 335 | } |
| 336 | |
| 337 | /* |
| 338 | ** Get the HTTP Authorization preference from db. |
| 339 | */ |
| @@ -346,13 +344,11 @@ | |
| 346 | |
| 347 | /* |
| 348 | ** Set the HTTP Authorization preference in db. |
| 349 | */ |
| 350 | void set_httpauth(const char *zHttpAuth){ |
| 351 | char *zKey = mprintf("http-auth:%s", g.url.canonical); |
| 352 | db_set(zKey, obscure(zHttpAuth), 0); |
| 353 | free(zKey); |
| 354 | } |
| 355 | |
| 356 | /* |
| 357 | ** Look for SSH clone command line options and setup in globals. |
| 358 | */ |
| 359 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -314,26 +314,24 @@ | |
| 314 | void remember_or_get_http_auth( |
| 315 | const char *zHttpAuth, /* Credentials in the form "user:password" */ |
| 316 | int fRemember, /* True to remember credentials for later reuse */ |
| 317 | const char *zUrl /* URL for which these credentials apply */ |
| 318 | ){ |
| 319 | if( zHttpAuth && zHttpAuth[0] ){ |
| 320 | g.zHttpAuth = mprintf("%s", zHttpAuth); |
| 321 | } |
| 322 | if( fRemember ){ |
| 323 | if( g.zHttpAuth && g.zHttpAuth[0] ){ |
| 324 | set_httpauth(g.zHttpAuth); |
| 325 | }else if( zUrl && zUrl[0] ){ |
| 326 | db_unset_mprintf(0, "http-auth:%s", g.url.canonical); |
| 327 | }else{ |
| 328 | g.zHttpAuth = get_httpauth(); |
| 329 | } |
| 330 | }else if( g.zHttpAuth==0 && zUrl==0 ){ |
| 331 | g.zHttpAuth = get_httpauth(); |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | /* |
| 336 | ** Get the HTTP Authorization preference from db. |
| 337 | */ |
| @@ -346,13 +344,11 @@ | |
| 344 | |
| 345 | /* |
| 346 | ** Set the HTTP Authorization preference in db. |
| 347 | */ |
| 348 | void set_httpauth(const char *zHttpAuth){ |
| 349 | db_set_mprintf(obscure(zHttpAuth), 0, "http-auth:%s", g.url.canonical); |
| 350 | } |
| 351 | |
| 352 | /* |
| 353 | ** Look for SSH clone command line options and setup in globals. |
| 354 | */ |
| 355 |
+91
-58
| --- src/codecheck1.c | ||
| +++ src/codecheck1.c | ||
| @@ -347,10 +347,12 @@ | ||
| 347 | 347 | */ |
| 348 | 348 | #define FMT_SQL 0x00001 /* Generator for SQL text */ |
| 349 | 349 | #define FMT_HTML 0x00002 /* Generator for HTML text */ |
| 350 | 350 | #define FMT_URL 0x00004 /* Generator for URLs */ |
| 351 | 351 | #define FMT_SAFE 0x00008 /* Generator for human-readable text */ |
| 352 | +#define FMT_LIT 0x00010 /* Just verify that a string literal */ | |
| 353 | +#define FMT_PX 0x00020 /* Must have a literal prefix in format string */ | |
| 352 | 354 | |
| 353 | 355 | /* |
| 354 | 356 | ** A list of internal Fossil interfaces that take a printf-style format |
| 355 | 357 | ** string. |
| 356 | 358 | */ |
| @@ -357,65 +359,76 @@ | ||
| 357 | 359 | struct FmtFunc { |
| 358 | 360 | const char *zFName; /* Name of the function */ |
| 359 | 361 | int iFmtArg; /* Index of format argument. Leftmost is 1. */ |
| 360 | 362 | unsigned fmtFlags; /* Processing flags */ |
| 361 | 363 | } aFmtFunc[] = { |
| 362 | - { "admin_log", 1, FMT_SAFE }, | |
| 363 | - { "audit_append", 3, FMT_SAFE }, | |
| 364 | - { "backofficeTrace", 1, FMT_SAFE }, | |
| 365 | - { "blob_append_sql", 2, FMT_SQL }, | |
| 366 | - { "blob_appendf", 2, FMT_SAFE }, | |
| 367 | - { "cgi_debug", 1, FMT_SAFE }, | |
| 368 | - { "cgi_panic", 1, FMT_SAFE }, | |
| 369 | - { "cgi_printf", 1, FMT_HTML }, | |
| 370 | - { "cgi_printf_header", 1, FMT_HTML }, | |
| 371 | - { "cgi_redirectf", 1, FMT_URL }, | |
| 372 | - { "chref", 2, FMT_URL }, | |
| 373 | - { "CX", 1, FMT_HTML }, | |
| 374 | - { "db_blob", 2, FMT_SQL }, | |
| 375 | - { "db_debug", 1, FMT_SQL }, | |
| 376 | - { "db_double", 2, FMT_SQL }, | |
| 377 | - { "db_err", 1, FMT_SAFE }, | |
| 378 | - { "db_exists", 1, FMT_SQL }, | |
| 379 | - { "db_get_mprintf", 2, FMT_SAFE }, | |
| 380 | - { "db_int", 2, FMT_SQL }, | |
| 381 | - { "db_int64", 2, FMT_SQL }, | |
| 382 | - { "db_multi_exec", 1, FMT_SQL }, | |
| 383 | - { "db_optional_sql", 2, FMT_SQL }, | |
| 384 | - { "db_prepare", 2, FMT_SQL }, | |
| 385 | - { "db_prepare_ignore_error", 2, FMT_SQL }, | |
| 386 | - { "db_set_mprintf", 3, FMT_SAFE }, | |
| 387 | - { "db_static_prepare", 2, FMT_SQL }, | |
| 388 | - { "db_text", 2, FMT_SQL }, | |
| 389 | - { "db_unset_mprintf", 2, FMT_SAFE }, | |
| 390 | - { "emailerError", 2, FMT_SAFE }, | |
| 391 | - { "fileedit_ajax_error", 2, FMT_SAFE }, | |
| 392 | - { "form_begin", 2, FMT_URL }, | |
| 393 | - { "fossil_error", 2, FMT_SAFE }, | |
| 394 | - { "fossil_errorlog", 1, FMT_SAFE }, | |
| 395 | - { "fossil_fatal", 1, FMT_SAFE }, | |
| 396 | - { "fossil_fatal_recursive", 1, FMT_SAFE }, | |
| 397 | - { "fossil_panic", 1, FMT_SAFE }, | |
| 398 | - { "fossil_print", 1, FMT_SAFE }, | |
| 399 | - { "fossil_trace", 1, FMT_SAFE }, | |
| 400 | - { "fossil_warning", 1, FMT_SAFE }, | |
| 401 | - { "href", 1, FMT_URL }, | |
| 402 | - { "json_new_string_f", 1, FMT_SAFE }, | |
| 403 | - { "json_set_err", 2, FMT_SAFE }, | |
| 404 | - { "json_warn", 2, FMT_SAFE }, | |
| 405 | - { "mprintf", 1, FMT_SAFE }, | |
| 406 | - { "pop3_print", 2, FMT_SAFE }, | |
| 407 | - { "smtp_send_line", 2, FMT_SAFE }, | |
| 408 | - { "smtp_server_send", 2, FMT_SAFE }, | |
| 409 | - { "socket_set_errmsg", 1, FMT_SAFE }, | |
| 410 | - { "ssl_set_errmsg", 1, FMT_SAFE }, | |
| 411 | - { "style_header", 1, FMT_HTML }, | |
| 412 | - { "style_set_current_page", 1, FMT_URL }, | |
| 413 | - { "style_submenu_element", 2, FMT_URL }, | |
| 414 | - { "style_submenu_sql", 3, FMT_SQL }, | |
| 415 | - { "webpage_error", 1, FMT_SAFE }, | |
| 416 | - { "xhref", 2, FMT_URL }, | |
| 364 | + { "admin_log", 1, FMT_SAFE }, | |
| 365 | + { "audit_append", 3, FMT_SAFE }, | |
| 366 | + { "backofficeTrace", 1, FMT_SAFE }, | |
| 367 | + { "blob_append_sql", 2, FMT_SQL }, | |
| 368 | + { "blob_appendf", 2, FMT_SAFE }, | |
| 369 | + { "cgi_debug", 1, FMT_SAFE }, | |
| 370 | + { "cgi_panic", 1, FMT_SAFE }, | |
| 371 | + { "cgi_printf", 1, FMT_HTML }, | |
| 372 | + { "cgi_printf_header", 1, FMT_HTML }, | |
| 373 | + { "cgi_redirectf", 1, FMT_URL }, | |
| 374 | + { "chref", 2, FMT_URL }, | |
| 375 | + { "CX", 1, FMT_HTML }, | |
| 376 | + { "db_blob", 2, FMT_SQL }, | |
| 377 | + { "db_debug", 1, FMT_SQL }, | |
| 378 | + { "db_double", 2, FMT_SQL }, | |
| 379 | + { "db_err", 1, FMT_SAFE }, | |
| 380 | + { "db_exists", 1, FMT_SQL }, | |
| 381 | + { "db_get_mprintf", 2, FMT_SAFE }, | |
| 382 | + { "db_int", 2, FMT_SQL }, | |
| 383 | + { "db_int64", 2, FMT_SQL }, | |
| 384 | + { "db_lset", 1, FMT_LIT }, | |
| 385 | + { "db_lset_int", 1, FMT_LIT }, | |
| 386 | + { "db_multi_exec", 1, FMT_SQL }, | |
| 387 | + { "db_optional_sql", 2, FMT_SQL }, | |
| 388 | + { "db_prepare", 2, FMT_SQL }, | |
| 389 | + { "db_prepare_ignore_error", 2, FMT_SQL }, | |
| 390 | + { "db_set", 1, FMT_LIT }, | |
| 391 | + { "db_set_int", 1, FMT_LIT }, | |
| 392 | + { "db_set_mprintf", 3, FMT_PX }, | |
| 393 | + { "db_static_prepare", 2, FMT_SQL }, | |
| 394 | + { "db_text", 2, FMT_SQL }, | |
| 395 | + { "db_unset", 1, FMT_LIT }, | |
| 396 | + { "db_unset_mprintf", 2, FMT_PX }, | |
| 397 | + { "emailerError", 2, FMT_SAFE }, | |
| 398 | + { "entry_attribute", 4, FMT_LIT }, | |
| 399 | + { "fileedit_ajax_error", 2, FMT_SAFE }, | |
| 400 | + { "form_begin", 2, FMT_URL }, | |
| 401 | + { "fossil_error", 2, FMT_SAFE }, | |
| 402 | + { "fossil_errorlog", 1, FMT_SAFE }, | |
| 403 | + { "fossil_fatal", 1, FMT_SAFE }, | |
| 404 | + { "fossil_fatal_recursive", 1, FMT_SAFE }, | |
| 405 | + { "fossil_panic", 1, FMT_SAFE }, | |
| 406 | + { "fossil_print", 1, FMT_SAFE }, | |
| 407 | + { "fossil_trace", 1, FMT_SAFE }, | |
| 408 | + { "fossil_warning", 1, FMT_SAFE }, | |
| 409 | + { "href", 1, FMT_URL }, | |
| 410 | + { "json_new_string_f", 1, FMT_SAFE }, | |
| 411 | + { "json_set_err", 2, FMT_SAFE }, | |
| 412 | + { "json_warn", 2, FMT_SAFE }, | |
| 413 | + { "mprintf", 1, FMT_SAFE }, | |
| 414 | + { "multiple_choice_attribute", 3, FMT_LIT }, | |
| 415 | + { "onoff_attribute", 3, FMT_LIT }, | |
| 416 | + { "pop3_print", 2, FMT_SAFE }, | |
| 417 | + { "smtp_send_line", 2, FMT_SAFE }, | |
| 418 | + { "smtp_server_send", 2, FMT_SAFE }, | |
| 419 | + { "socket_set_errmsg", 1, FMT_SAFE }, | |
| 420 | + { "ssl_set_errmsg", 1, FMT_SAFE }, | |
| 421 | + { "style_header", 1, FMT_HTML }, | |
| 422 | + { "style_set_current_page", 1, FMT_URL }, | |
| 423 | + { "style_submenu_element", 2, FMT_URL }, | |
| 424 | + { "style_submenu_sql", 3, FMT_SQL }, | |
| 425 | + { "textarea_attribute", 5, FMT_LIT }, | |
| 426 | + { "tktsetup_generic", 1, FMT_LIT }, | |
| 427 | + { "webpage_error", 1, FMT_SAFE }, | |
| 428 | + { "xfersetup_generic", 1, FMT_LIT }, | |
| 429 | + { "xhref", 2, FMT_URL }, | |
| 417 | 430 | }; |
| 418 | 431 | |
| 419 | 432 | /* |
| 420 | 433 | ** Comparison function for two FmtFunc entries |
| 421 | 434 | */ |
| @@ -459,20 +472,26 @@ | ||
| 459 | 472 | ** Return the expected number of arguments for the format string. |
| 460 | 473 | ** Return -1 if the value cannot be computed. |
| 461 | 474 | ** |
| 462 | 475 | ** For each argument less than nType, store the conversion character |
| 463 | 476 | ** for that argument in cType[i]. |
| 477 | +** | |
| 478 | +** Store the number of initial literal characters of the format string | |
| 479 | +** in *pInit. | |
| 464 | 480 | */ |
| 465 | -static int formatArgCount(const char *z, int nType, char *cType){ | |
| 481 | +static int formatArgCount(const char *z, int nType, char *cType, int *pInit){ | |
| 466 | 482 | int nArg = 0; |
| 467 | 483 | int i, k; |
| 468 | 484 | int len; |
| 469 | 485 | int eType; |
| 470 | 486 | int ln = 0; |
| 487 | + *pInit = 0; | |
| 471 | 488 | while( z[0] ){ |
| 472 | 489 | len = token_length(z, &eType, &ln); |
| 473 | 490 | if( eType==TK_STR ){ |
| 491 | + for(i=1; i<len-1 && isalpha(z[i]); i++){} | |
| 492 | + *pInit = i-1; | |
| 474 | 493 | for(i=1; i<len-1; i++){ |
| 475 | 494 | if( z[i]!='%' ) continue; |
| 476 | 495 | if( z[i+1]=='%' ){ i++; continue; } |
| 477 | 496 | for(k=i+1; k<len && !isalpha(z[k]); k++){ |
| 478 | 497 | if( z[k]=='*' || z[k]=='#' ){ |
| @@ -515,10 +534,11 @@ | ||
| 515 | 534 | int nArg = 0; |
| 516 | 535 | const char **azArg = 0; |
| 517 | 536 | int i, k; |
| 518 | 537 | int nErr = 0; |
| 519 | 538 | char *acType; |
| 539 | + int nInit = 0; | |
| 520 | 540 | |
| 521 | 541 | szFName = token_length(zFCall, &eToken, &ln); |
| 522 | 542 | zStart = next_non_whitespace(zFCall+szFName, &len, &eToken); |
| 523 | 543 | assert( zStart[0]=='(' && len==1 ); |
| 524 | 544 | len = distance_to(zStart+1, ')'); |
| @@ -545,21 +565,34 @@ | ||
| 545 | 565 | nErr++; |
| 546 | 566 | }else{ |
| 547 | 567 | const char *zFmt = azArg[fmtArg-1]; |
| 548 | 568 | const char *zOverride = strstr(zFmt, "/*works-like:"); |
| 549 | 569 | if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1; |
| 550 | - if( !is_string_lit(zFmt) ){ | |
| 570 | + if( fmtFlags & FMT_LIT ){ | |
| 571 | + if( !is_string_lit(zFmt) ){ | |
| 572 | + printf("%s:%d: argument %d to %.*s() should be a string literal\n", | |
| 573 | + zFilename, lnFCall, fmtArg, szFName, zFCall); | |
| 574 | + nErr++; | |
| 575 | + } | |
| 576 | + }else if( !is_string_lit(zFmt) ){ | |
| 551 | 577 | printf("%s:%d: %.*s() has non-constant format on arg[%d]\n", |
| 552 | 578 | zFilename, lnFCall, szFName, zFCall, fmtArg-1); |
| 553 | 579 | nErr++; |
| 554 | - }else if( (k = formatArgCount(zFmt, nArg, acType))>=0 | |
| 580 | + }else if( (k = formatArgCount(zFmt, nArg, acType, &nInit))>=0 | |
| 555 | 581 | && nArg!=fmtArg+k ){ |
| 556 | 582 | printf("%s:%d: too %s arguments to %.*s() " |
| 557 | 583 | "- got %d and expected %d\n", |
| 558 | 584 | zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"), |
| 559 | 585 | szFName, zFCall, nArg, fmtArg+k); |
| 560 | 586 | nErr++; |
| 587 | + }else if( (fmtFlags & FMT_PX)!=0 ){ | |
| 588 | + if( nInit==0 ){ | |
| 589 | + printf("%s:%d: format string on %.*s() should have" | |
| 590 | + " an ASCII character prefix\n", | |
| 591 | + zFilename, lnFCall, szFName, zFCall); | |
| 592 | + nErr++; | |
| 593 | + } | |
| 561 | 594 | }else if( (fmtFlags & FMT_SAFE)==0 ){ |
| 562 | 595 | for(i=0; i<nArg && i<k; i++){ |
| 563 | 596 | if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){ |
| 564 | 597 | const char *zExpr = azArg[fmtArg+i]; |
| 565 | 598 | if( never_safe(zExpr) ){ |
| 566 | 599 |
| --- src/codecheck1.c | |
| +++ src/codecheck1.c | |
| @@ -347,10 +347,12 @@ | |
| 347 | */ |
| 348 | #define FMT_SQL 0x00001 /* Generator for SQL text */ |
| 349 | #define FMT_HTML 0x00002 /* Generator for HTML text */ |
| 350 | #define FMT_URL 0x00004 /* Generator for URLs */ |
| 351 | #define FMT_SAFE 0x00008 /* Generator for human-readable text */ |
| 352 | |
| 353 | /* |
| 354 | ** A list of internal Fossil interfaces that take a printf-style format |
| 355 | ** string. |
| 356 | */ |
| @@ -357,65 +359,76 @@ | |
| 357 | struct FmtFunc { |
| 358 | const char *zFName; /* Name of the function */ |
| 359 | int iFmtArg; /* Index of format argument. Leftmost is 1. */ |
| 360 | unsigned fmtFlags; /* Processing flags */ |
| 361 | } aFmtFunc[] = { |
| 362 | { "admin_log", 1, FMT_SAFE }, |
| 363 | { "audit_append", 3, FMT_SAFE }, |
| 364 | { "backofficeTrace", 1, FMT_SAFE }, |
| 365 | { "blob_append_sql", 2, FMT_SQL }, |
| 366 | { "blob_appendf", 2, FMT_SAFE }, |
| 367 | { "cgi_debug", 1, FMT_SAFE }, |
| 368 | { "cgi_panic", 1, FMT_SAFE }, |
| 369 | { "cgi_printf", 1, FMT_HTML }, |
| 370 | { "cgi_printf_header", 1, FMT_HTML }, |
| 371 | { "cgi_redirectf", 1, FMT_URL }, |
| 372 | { "chref", 2, FMT_URL }, |
| 373 | { "CX", 1, FMT_HTML }, |
| 374 | { "db_blob", 2, FMT_SQL }, |
| 375 | { "db_debug", 1, FMT_SQL }, |
| 376 | { "db_double", 2, FMT_SQL }, |
| 377 | { "db_err", 1, FMT_SAFE }, |
| 378 | { "db_exists", 1, FMT_SQL }, |
| 379 | { "db_get_mprintf", 2, FMT_SAFE }, |
| 380 | { "db_int", 2, FMT_SQL }, |
| 381 | { "db_int64", 2, FMT_SQL }, |
| 382 | { "db_multi_exec", 1, FMT_SQL }, |
| 383 | { "db_optional_sql", 2, FMT_SQL }, |
| 384 | { "db_prepare", 2, FMT_SQL }, |
| 385 | { "db_prepare_ignore_error", 2, FMT_SQL }, |
| 386 | { "db_set_mprintf", 3, FMT_SAFE }, |
| 387 | { "db_static_prepare", 2, FMT_SQL }, |
| 388 | { "db_text", 2, FMT_SQL }, |
| 389 | { "db_unset_mprintf", 2, FMT_SAFE }, |
| 390 | { "emailerError", 2, FMT_SAFE }, |
| 391 | { "fileedit_ajax_error", 2, FMT_SAFE }, |
| 392 | { "form_begin", 2, FMT_URL }, |
| 393 | { "fossil_error", 2, FMT_SAFE }, |
| 394 | { "fossil_errorlog", 1, FMT_SAFE }, |
| 395 | { "fossil_fatal", 1, FMT_SAFE }, |
| 396 | { "fossil_fatal_recursive", 1, FMT_SAFE }, |
| 397 | { "fossil_panic", 1, FMT_SAFE }, |
| 398 | { "fossil_print", 1, FMT_SAFE }, |
| 399 | { "fossil_trace", 1, FMT_SAFE }, |
| 400 | { "fossil_warning", 1, FMT_SAFE }, |
| 401 | { "href", 1, FMT_URL }, |
| 402 | { "json_new_string_f", 1, FMT_SAFE }, |
| 403 | { "json_set_err", 2, FMT_SAFE }, |
| 404 | { "json_warn", 2, FMT_SAFE }, |
| 405 | { "mprintf", 1, FMT_SAFE }, |
| 406 | { "pop3_print", 2, FMT_SAFE }, |
| 407 | { "smtp_send_line", 2, FMT_SAFE }, |
| 408 | { "smtp_server_send", 2, FMT_SAFE }, |
| 409 | { "socket_set_errmsg", 1, FMT_SAFE }, |
| 410 | { "ssl_set_errmsg", 1, FMT_SAFE }, |
| 411 | { "style_header", 1, FMT_HTML }, |
| 412 | { "style_set_current_page", 1, FMT_URL }, |
| 413 | { "style_submenu_element", 2, FMT_URL }, |
| 414 | { "style_submenu_sql", 3, FMT_SQL }, |
| 415 | { "webpage_error", 1, FMT_SAFE }, |
| 416 | { "xhref", 2, FMT_URL }, |
| 417 | }; |
| 418 | |
| 419 | /* |
| 420 | ** Comparison function for two FmtFunc entries |
| 421 | */ |
| @@ -459,20 +472,26 @@ | |
| 459 | ** Return the expected number of arguments for the format string. |
| 460 | ** Return -1 if the value cannot be computed. |
| 461 | ** |
| 462 | ** For each argument less than nType, store the conversion character |
| 463 | ** for that argument in cType[i]. |
| 464 | */ |
| 465 | static int formatArgCount(const char *z, int nType, char *cType){ |
| 466 | int nArg = 0; |
| 467 | int i, k; |
| 468 | int len; |
| 469 | int eType; |
| 470 | int ln = 0; |
| 471 | while( z[0] ){ |
| 472 | len = token_length(z, &eType, &ln); |
| 473 | if( eType==TK_STR ){ |
| 474 | for(i=1; i<len-1; i++){ |
| 475 | if( z[i]!='%' ) continue; |
| 476 | if( z[i+1]=='%' ){ i++; continue; } |
| 477 | for(k=i+1; k<len && !isalpha(z[k]); k++){ |
| 478 | if( z[k]=='*' || z[k]=='#' ){ |
| @@ -515,10 +534,11 @@ | |
| 515 | int nArg = 0; |
| 516 | const char **azArg = 0; |
| 517 | int i, k; |
| 518 | int nErr = 0; |
| 519 | char *acType; |
| 520 | |
| 521 | szFName = token_length(zFCall, &eToken, &ln); |
| 522 | zStart = next_non_whitespace(zFCall+szFName, &len, &eToken); |
| 523 | assert( zStart[0]=='(' && len==1 ); |
| 524 | len = distance_to(zStart+1, ')'); |
| @@ -545,21 +565,34 @@ | |
| 545 | nErr++; |
| 546 | }else{ |
| 547 | const char *zFmt = azArg[fmtArg-1]; |
| 548 | const char *zOverride = strstr(zFmt, "/*works-like:"); |
| 549 | if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1; |
| 550 | if( !is_string_lit(zFmt) ){ |
| 551 | printf("%s:%d: %.*s() has non-constant format on arg[%d]\n", |
| 552 | zFilename, lnFCall, szFName, zFCall, fmtArg-1); |
| 553 | nErr++; |
| 554 | }else if( (k = formatArgCount(zFmt, nArg, acType))>=0 |
| 555 | && nArg!=fmtArg+k ){ |
| 556 | printf("%s:%d: too %s arguments to %.*s() " |
| 557 | "- got %d and expected %d\n", |
| 558 | zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"), |
| 559 | szFName, zFCall, nArg, fmtArg+k); |
| 560 | nErr++; |
| 561 | }else if( (fmtFlags & FMT_SAFE)==0 ){ |
| 562 | for(i=0; i<nArg && i<k; i++){ |
| 563 | if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){ |
| 564 | const char *zExpr = azArg[fmtArg+i]; |
| 565 | if( never_safe(zExpr) ){ |
| 566 |
| --- src/codecheck1.c | |
| +++ src/codecheck1.c | |
| @@ -347,10 +347,12 @@ | |
| 347 | */ |
| 348 | #define FMT_SQL 0x00001 /* Generator for SQL text */ |
| 349 | #define FMT_HTML 0x00002 /* Generator for HTML text */ |
| 350 | #define FMT_URL 0x00004 /* Generator for URLs */ |
| 351 | #define FMT_SAFE 0x00008 /* Generator for human-readable text */ |
| 352 | #define FMT_LIT 0x00010 /* Just verify that a string literal */ |
| 353 | #define FMT_PX 0x00020 /* Must have a literal prefix in format string */ |
| 354 | |
| 355 | /* |
| 356 | ** A list of internal Fossil interfaces that take a printf-style format |
| 357 | ** string. |
| 358 | */ |
| @@ -357,65 +359,76 @@ | |
| 359 | struct FmtFunc { |
| 360 | const char *zFName; /* Name of the function */ |
| 361 | int iFmtArg; /* Index of format argument. Leftmost is 1. */ |
| 362 | unsigned fmtFlags; /* Processing flags */ |
| 363 | } aFmtFunc[] = { |
| 364 | { "admin_log", 1, FMT_SAFE }, |
| 365 | { "audit_append", 3, FMT_SAFE }, |
| 366 | { "backofficeTrace", 1, FMT_SAFE }, |
| 367 | { "blob_append_sql", 2, FMT_SQL }, |
| 368 | { "blob_appendf", 2, FMT_SAFE }, |
| 369 | { "cgi_debug", 1, FMT_SAFE }, |
| 370 | { "cgi_panic", 1, FMT_SAFE }, |
| 371 | { "cgi_printf", 1, FMT_HTML }, |
| 372 | { "cgi_printf_header", 1, FMT_HTML }, |
| 373 | { "cgi_redirectf", 1, FMT_URL }, |
| 374 | { "chref", 2, FMT_URL }, |
| 375 | { "CX", 1, FMT_HTML }, |
| 376 | { "db_blob", 2, FMT_SQL }, |
| 377 | { "db_debug", 1, FMT_SQL }, |
| 378 | { "db_double", 2, FMT_SQL }, |
| 379 | { "db_err", 1, FMT_SAFE }, |
| 380 | { "db_exists", 1, FMT_SQL }, |
| 381 | { "db_get_mprintf", 2, FMT_SAFE }, |
| 382 | { "db_int", 2, FMT_SQL }, |
| 383 | { "db_int64", 2, FMT_SQL }, |
| 384 | { "db_lset", 1, FMT_LIT }, |
| 385 | { "db_lset_int", 1, FMT_LIT }, |
| 386 | { "db_multi_exec", 1, FMT_SQL }, |
| 387 | { "db_optional_sql", 2, FMT_SQL }, |
| 388 | { "db_prepare", 2, FMT_SQL }, |
| 389 | { "db_prepare_ignore_error", 2, FMT_SQL }, |
| 390 | { "db_set", 1, FMT_LIT }, |
| 391 | { "db_set_int", 1, FMT_LIT }, |
| 392 | { "db_set_mprintf", 3, FMT_PX }, |
| 393 | { "db_static_prepare", 2, FMT_SQL }, |
| 394 | { "db_text", 2, FMT_SQL }, |
| 395 | { "db_unset", 1, FMT_LIT }, |
| 396 | { "db_unset_mprintf", 2, FMT_PX }, |
| 397 | { "emailerError", 2, FMT_SAFE }, |
| 398 | { "entry_attribute", 4, FMT_LIT }, |
| 399 | { "fileedit_ajax_error", 2, FMT_SAFE }, |
| 400 | { "form_begin", 2, FMT_URL }, |
| 401 | { "fossil_error", 2, FMT_SAFE }, |
| 402 | { "fossil_errorlog", 1, FMT_SAFE }, |
| 403 | { "fossil_fatal", 1, FMT_SAFE }, |
| 404 | { "fossil_fatal_recursive", 1, FMT_SAFE }, |
| 405 | { "fossil_panic", 1, FMT_SAFE }, |
| 406 | { "fossil_print", 1, FMT_SAFE }, |
| 407 | { "fossil_trace", 1, FMT_SAFE }, |
| 408 | { "fossil_warning", 1, FMT_SAFE }, |
| 409 | { "href", 1, FMT_URL }, |
| 410 | { "json_new_string_f", 1, FMT_SAFE }, |
| 411 | { "json_set_err", 2, FMT_SAFE }, |
| 412 | { "json_warn", 2, FMT_SAFE }, |
| 413 | { "mprintf", 1, FMT_SAFE }, |
| 414 | { "multiple_choice_attribute", 3, FMT_LIT }, |
| 415 | { "onoff_attribute", 3, FMT_LIT }, |
| 416 | { "pop3_print", 2, FMT_SAFE }, |
| 417 | { "smtp_send_line", 2, FMT_SAFE }, |
| 418 | { "smtp_server_send", 2, FMT_SAFE }, |
| 419 | { "socket_set_errmsg", 1, FMT_SAFE }, |
| 420 | { "ssl_set_errmsg", 1, FMT_SAFE }, |
| 421 | { "style_header", 1, FMT_HTML }, |
| 422 | { "style_set_current_page", 1, FMT_URL }, |
| 423 | { "style_submenu_element", 2, FMT_URL }, |
| 424 | { "style_submenu_sql", 3, FMT_SQL }, |
| 425 | { "textarea_attribute", 5, FMT_LIT }, |
| 426 | { "tktsetup_generic", 1, FMT_LIT }, |
| 427 | { "webpage_error", 1, FMT_SAFE }, |
| 428 | { "xfersetup_generic", 1, FMT_LIT }, |
| 429 | { "xhref", 2, FMT_URL }, |
| 430 | }; |
| 431 | |
| 432 | /* |
| 433 | ** Comparison function for two FmtFunc entries |
| 434 | */ |
| @@ -459,20 +472,26 @@ | |
| 472 | ** Return the expected number of arguments for the format string. |
| 473 | ** Return -1 if the value cannot be computed. |
| 474 | ** |
| 475 | ** For each argument less than nType, store the conversion character |
| 476 | ** for that argument in cType[i]. |
| 477 | ** |
| 478 | ** Store the number of initial literal characters of the format string |
| 479 | ** in *pInit. |
| 480 | */ |
| 481 | static int formatArgCount(const char *z, int nType, char *cType, int *pInit){ |
| 482 | int nArg = 0; |
| 483 | int i, k; |
| 484 | int len; |
| 485 | int eType; |
| 486 | int ln = 0; |
| 487 | *pInit = 0; |
| 488 | while( z[0] ){ |
| 489 | len = token_length(z, &eType, &ln); |
| 490 | if( eType==TK_STR ){ |
| 491 | for(i=1; i<len-1 && isalpha(z[i]); i++){} |
| 492 | *pInit = i-1; |
| 493 | for(i=1; i<len-1; i++){ |
| 494 | if( z[i]!='%' ) continue; |
| 495 | if( z[i+1]=='%' ){ i++; continue; } |
| 496 | for(k=i+1; k<len && !isalpha(z[k]); k++){ |
| 497 | if( z[k]=='*' || z[k]=='#' ){ |
| @@ -515,10 +534,11 @@ | |
| 534 | int nArg = 0; |
| 535 | const char **azArg = 0; |
| 536 | int i, k; |
| 537 | int nErr = 0; |
| 538 | char *acType; |
| 539 | int nInit = 0; |
| 540 | |
| 541 | szFName = token_length(zFCall, &eToken, &ln); |
| 542 | zStart = next_non_whitespace(zFCall+szFName, &len, &eToken); |
| 543 | assert( zStart[0]=='(' && len==1 ); |
| 544 | len = distance_to(zStart+1, ')'); |
| @@ -545,21 +565,34 @@ | |
| 565 | nErr++; |
| 566 | }else{ |
| 567 | const char *zFmt = azArg[fmtArg-1]; |
| 568 | const char *zOverride = strstr(zFmt, "/*works-like:"); |
| 569 | if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1; |
| 570 | if( fmtFlags & FMT_LIT ){ |
| 571 | if( !is_string_lit(zFmt) ){ |
| 572 | printf("%s:%d: argument %d to %.*s() should be a string literal\n", |
| 573 | zFilename, lnFCall, fmtArg, szFName, zFCall); |
| 574 | nErr++; |
| 575 | } |
| 576 | }else if( !is_string_lit(zFmt) ){ |
| 577 | printf("%s:%d: %.*s() has non-constant format on arg[%d]\n", |
| 578 | zFilename, lnFCall, szFName, zFCall, fmtArg-1); |
| 579 | nErr++; |
| 580 | }else if( (k = formatArgCount(zFmt, nArg, acType, &nInit))>=0 |
| 581 | && nArg!=fmtArg+k ){ |
| 582 | printf("%s:%d: too %s arguments to %.*s() " |
| 583 | "- got %d and expected %d\n", |
| 584 | zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"), |
| 585 | szFName, zFCall, nArg, fmtArg+k); |
| 586 | nErr++; |
| 587 | }else if( (fmtFlags & FMT_PX)!=0 ){ |
| 588 | if( nInit==0 ){ |
| 589 | printf("%s:%d: format string on %.*s() should have" |
| 590 | " an ASCII character prefix\n", |
| 591 | zFilename, lnFCall, szFName, zFCall); |
| 592 | nErr++; |
| 593 | } |
| 594 | }else if( (fmtFlags & FMT_SAFE)==0 ){ |
| 595 | for(i=0; i<nArg && i<k; i++){ |
| 596 | if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){ |
| 597 | const char *zExpr = azArg[fmtArg+i]; |
| 598 | if( never_safe(zExpr) ){ |
| 599 |
M
src/db.c
+9
-4
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -3321,10 +3321,15 @@ | ||
| 3321 | 3321 | void db_lset_int(const char *zName, int value){ |
| 3322 | 3322 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 3323 | 3323 | } |
| 3324 | 3324 | |
| 3325 | 3325 | /* Va-args versions of db_get(), db_set(), and db_unset() |
| 3326 | +** | |
| 3327 | +** codecheck1.c verifies that the format string for db_set_mprintf() | |
| 3328 | +** and db_unset_mprintf() begins with an ASCII character prefix. We | |
| 3329 | +** don't want that format string to begin with %s or %d as that might | |
| 3330 | +** allow an injection attack to set or overwrite arbitrary settings. | |
| 3326 | 3331 | */ |
| 3327 | 3332 | char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){ |
| 3328 | 3333 | va_list ap; |
| 3329 | 3334 | char *zName; |
| 3330 | 3335 | char *zResult; |
| @@ -3339,20 +3344,20 @@ | ||
| 3339 | 3344 | va_list ap; |
| 3340 | 3345 | char *zName; |
| 3341 | 3346 | va_start(ap, zFormat); |
| 3342 | 3347 | zName = vmprintf(zFormat, ap); |
| 3343 | 3348 | va_end(ap); |
| 3344 | - db_set(zName, zNew, iGlobal); | |
| 3349 | + db_set(zName/*works-like:"x"*/, zNew, iGlobal); | |
| 3345 | 3350 | fossil_free(zName); |
| 3346 | 3351 | } |
| 3347 | 3352 | void db_unset_mprintf(int iGlobal, const char *zFormat, ...){ |
| 3348 | 3353 | va_list ap; |
| 3349 | 3354 | char *zName; |
| 3350 | 3355 | va_start(ap, zFormat); |
| 3351 | 3356 | zName = vmprintf(zFormat, ap); |
| 3352 | 3357 | va_end(ap); |
| 3353 | - db_unset(zName, iGlobal); | |
| 3358 | + db_unset(zName/*works-like:"x"*/, iGlobal); | |
| 3354 | 3359 | fossil_free(zName); |
| 3355 | 3360 | } |
| 3356 | 3361 | |
| 3357 | 3362 | |
| 3358 | 3363 | |
| @@ -4413,14 +4418,14 @@ | ||
| 4413 | 4418 | } |
| 4414 | 4419 | if( globalFlag && isManifest ){ |
| 4415 | 4420 | fossil_fatal("cannot set 'manifest' globally"); |
| 4416 | 4421 | } |
| 4417 | 4422 | if( unsetFlag ){ |
| 4418 | - db_unset(pSetting->name, globalFlag); | |
| 4423 | + db_unset(pSetting->name/*works-like:"x"*/, globalFlag); | |
| 4419 | 4424 | }else{ |
| 4420 | 4425 | db_protect_only(PROTECT_NONE); |
| 4421 | - db_set(pSetting->name, g.argv[3], globalFlag); | |
| 4426 | + db_set(pSetting->name/*works-like:"x"*/, g.argv[3], globalFlag); | |
| 4422 | 4427 | db_protect_pop(); |
| 4423 | 4428 | } |
| 4424 | 4429 | if( isManifest && g.localOpen ){ |
| 4425 | 4430 | manifest_to_disk(db_lget_int("checkout", 0)); |
| 4426 | 4431 | } |
| 4427 | 4432 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -3321,10 +3321,15 @@ | |
| 3321 | void db_lset_int(const char *zName, int value){ |
| 3322 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 3323 | } |
| 3324 | |
| 3325 | /* Va-args versions of db_get(), db_set(), and db_unset() |
| 3326 | */ |
| 3327 | char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){ |
| 3328 | va_list ap; |
| 3329 | char *zName; |
| 3330 | char *zResult; |
| @@ -3339,20 +3344,20 @@ | |
| 3339 | va_list ap; |
| 3340 | char *zName; |
| 3341 | va_start(ap, zFormat); |
| 3342 | zName = vmprintf(zFormat, ap); |
| 3343 | va_end(ap); |
| 3344 | db_set(zName, zNew, iGlobal); |
| 3345 | fossil_free(zName); |
| 3346 | } |
| 3347 | void db_unset_mprintf(int iGlobal, const char *zFormat, ...){ |
| 3348 | va_list ap; |
| 3349 | char *zName; |
| 3350 | va_start(ap, zFormat); |
| 3351 | zName = vmprintf(zFormat, ap); |
| 3352 | va_end(ap); |
| 3353 | db_unset(zName, iGlobal); |
| 3354 | fossil_free(zName); |
| 3355 | } |
| 3356 | |
| 3357 | |
| 3358 | |
| @@ -4413,14 +4418,14 @@ | |
| 4413 | } |
| 4414 | if( globalFlag && isManifest ){ |
| 4415 | fossil_fatal("cannot set 'manifest' globally"); |
| 4416 | } |
| 4417 | if( unsetFlag ){ |
| 4418 | db_unset(pSetting->name, globalFlag); |
| 4419 | }else{ |
| 4420 | db_protect_only(PROTECT_NONE); |
| 4421 | db_set(pSetting->name, g.argv[3], globalFlag); |
| 4422 | db_protect_pop(); |
| 4423 | } |
| 4424 | if( isManifest && g.localOpen ){ |
| 4425 | manifest_to_disk(db_lget_int("checkout", 0)); |
| 4426 | } |
| 4427 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -3321,10 +3321,15 @@ | |
| 3321 | void db_lset_int(const char *zName, int value){ |
| 3322 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 3323 | } |
| 3324 | |
| 3325 | /* Va-args versions of db_get(), db_set(), and db_unset() |
| 3326 | ** |
| 3327 | ** codecheck1.c verifies that the format string for db_set_mprintf() |
| 3328 | ** and db_unset_mprintf() begins with an ASCII character prefix. We |
| 3329 | ** don't want that format string to begin with %s or %d as that might |
| 3330 | ** allow an injection attack to set or overwrite arbitrary settings. |
| 3331 | */ |
| 3332 | char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){ |
| 3333 | va_list ap; |
| 3334 | char *zName; |
| 3335 | char *zResult; |
| @@ -3339,20 +3344,20 @@ | |
| 3344 | va_list ap; |
| 3345 | char *zName; |
| 3346 | va_start(ap, zFormat); |
| 3347 | zName = vmprintf(zFormat, ap); |
| 3348 | va_end(ap); |
| 3349 | db_set(zName/*works-like:"x"*/, zNew, iGlobal); |
| 3350 | fossil_free(zName); |
| 3351 | } |
| 3352 | void db_unset_mprintf(int iGlobal, const char *zFormat, ...){ |
| 3353 | va_list ap; |
| 3354 | char *zName; |
| 3355 | va_start(ap, zFormat); |
| 3356 | zName = vmprintf(zFormat, ap); |
| 3357 | va_end(ap); |
| 3358 | db_unset(zName/*works-like:"x"*/, iGlobal); |
| 3359 | fossil_free(zName); |
| 3360 | } |
| 3361 | |
| 3362 | |
| 3363 | |
| @@ -4413,14 +4418,14 @@ | |
| 4418 | } |
| 4419 | if( globalFlag && isManifest ){ |
| 4420 | fossil_fatal("cannot set 'manifest' globally"); |
| 4421 | } |
| 4422 | if( unsetFlag ){ |
| 4423 | db_unset(pSetting->name/*works-like:"x"*/, globalFlag); |
| 4424 | }else{ |
| 4425 | db_protect_only(PROTECT_NONE); |
| 4426 | db_set(pSetting->name/*works-like:"x"*/, g.argv[3], globalFlag); |
| 4427 | db_protect_pop(); |
| 4428 | } |
| 4429 | if( isManifest && g.localOpen ){ |
| 4430 | manifest_to_disk(db_lget_int("checkout", 0)); |
| 4431 | } |
| 4432 |
+1
-3
| --- src/http_ssl.c | ||
| +++ src/http_ssl.c | ||
| @@ -437,13 +437,11 @@ | ||
| 437 | 437 | */ |
| 438 | 438 | LOCAL void ssl_remember_certificate_exception( |
| 439 | 439 | UrlData *pUrlData, |
| 440 | 440 | const char *zHash |
| 441 | 441 | ){ |
| 442 | - char *zName = mprintf("cert:%s", pUrlData->name); | |
| 443 | - db_set(zName, zHash, 1); | |
| 444 | - fossil_free(zName); | |
| 442 | + db_set_mprintf(zHash, 1, "cert:%s", pUrlData->name); | |
| 445 | 443 | } |
| 446 | 444 | |
| 447 | 445 | /* |
| 448 | 446 | ** Return true if the there exists a certificate exception for |
| 449 | 447 | ** pUrlData->name that matches the hash. |
| 450 | 448 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -437,13 +437,11 @@ | |
| 437 | */ |
| 438 | LOCAL void ssl_remember_certificate_exception( |
| 439 | UrlData *pUrlData, |
| 440 | const char *zHash |
| 441 | ){ |
| 442 | char *zName = mprintf("cert:%s", pUrlData->name); |
| 443 | db_set(zName, zHash, 1); |
| 444 | fossil_free(zName); |
| 445 | } |
| 446 | |
| 447 | /* |
| 448 | ** Return true if the there exists a certificate exception for |
| 449 | ** pUrlData->name that matches the hash. |
| 450 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -437,13 +437,11 @@ | |
| 437 | */ |
| 438 | LOCAL void ssl_remember_certificate_exception( |
| 439 | UrlData *pUrlData, |
| 440 | const char *zHash |
| 441 | ){ |
| 442 | db_set_mprintf(zHash, 1, "cert:%s", pUrlData->name); |
| 443 | } |
| 444 | |
| 445 | /* |
| 446 | ** Return true if the there exists a certificate exception for |
| 447 | ** pUrlData->name that matches the hash. |
| 448 |
+1
-1
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -1930,11 +1930,11 @@ | ||
| 1930 | 1930 | const char *zCtrl; |
| 1931 | 1931 | if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd)); |
| 1932 | 1932 | zCtrl = g.argv[3]; |
| 1933 | 1933 | for(j=0; j<count(aSetng); j++){ |
| 1934 | 1934 | if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){ |
| 1935 | - db_set_int(aSetng[j].zSetting, iCmd-3, 0); | |
| 1935 | + db_set_int(aSetng[j].zSetting/*works-like:"x"*/, iCmd-3, 0); | |
| 1936 | 1936 | } |
| 1937 | 1937 | } |
| 1938 | 1938 | } |
| 1939 | 1939 | if( iCmd==5 ){ |
| 1940 | 1940 | if( g.argc<4 ) usage("porter ON/OFF"); |
| 1941 | 1941 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -1930,11 +1930,11 @@ | |
| 1930 | const char *zCtrl; |
| 1931 | if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd)); |
| 1932 | zCtrl = g.argv[3]; |
| 1933 | for(j=0; j<count(aSetng); j++){ |
| 1934 | if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){ |
| 1935 | db_set_int(aSetng[j].zSetting, iCmd-3, 0); |
| 1936 | } |
| 1937 | } |
| 1938 | } |
| 1939 | if( iCmd==5 ){ |
| 1940 | if( g.argc<4 ) usage("porter ON/OFF"); |
| 1941 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -1930,11 +1930,11 @@ | |
| 1930 | const char *zCtrl; |
| 1931 | if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd)); |
| 1932 | zCtrl = g.argv[3]; |
| 1933 | for(j=0; j<count(aSetng); j++){ |
| 1934 | if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){ |
| 1935 | db_set_int(aSetng[j].zSetting/*works-like:"x"*/, iCmd-3, 0); |
| 1936 | } |
| 1937 | } |
| 1938 | } |
| 1939 | if( iCmd==5 ){ |
| 1940 | if( g.argc<4 ) usage("porter ON/OFF"); |
| 1941 |
+15
-15
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -186,13 +186,13 @@ | ||
| 186 | 186 | /* |
| 187 | 187 | ** Generate a checkbox for an attribute. |
| 188 | 188 | */ |
| 189 | 189 | void onoff_attribute( |
| 190 | 190 | const char *zLabel, /* The text label on the checkbox */ |
| 191 | - const char *zVar, /* The corresponding row in the VAR table */ | |
| 191 | + const char *zVar, /* The corresponding row in the CONFIG table */ | |
| 192 | 192 | const char *zQParm, /* The query parameter */ |
| 193 | - int dfltVal, /* Default value if VAR table entry does not exist */ | |
| 193 | + int dfltVal, /* Default value if CONFIG table entry does not exist */ | |
| 194 | 194 | int disabled /* 1 if disabled */ |
| 195 | 195 | ){ |
| 196 | 196 | const char *zQ = P(zQParm); |
| 197 | 197 | int iVal = db_get_boolean(zVar, dfltVal); |
| 198 | 198 | if( zQ==0 && !disabled && P("submit") ){ |
| @@ -201,11 +201,11 @@ | ||
| 201 | 201 | if( zQ ){ |
| 202 | 202 | int iQ = fossil_strcmp(zQ,"on")==0 || atoi(zQ); |
| 203 | 203 | if( iQ!=iVal ){ |
| 204 | 204 | login_verify_csrf_secret(); |
| 205 | 205 | db_protect_only(PROTECT_NONE); |
| 206 | - db_set(zVar, iQ ? "1" : "0", 0); | |
| 206 | + db_set(zVar/*works-like:"x"*/, iQ ? "1" : "0", 0); | |
| 207 | 207 | db_protect_pop(); |
| 208 | 208 | setup_incr_cfgcnt(); |
| 209 | 209 | admin_log("Set option [%q] to [%q].", |
| 210 | 210 | zVar, iQ ? "on" : "off"); |
| 211 | 211 | iVal = iQ; |
| @@ -226,23 +226,23 @@ | ||
| 226 | 226 | ** Generate an entry box for an attribute. |
| 227 | 227 | */ |
| 228 | 228 | void entry_attribute( |
| 229 | 229 | const char *zLabel, /* The text label on the entry box */ |
| 230 | 230 | int width, /* Width of the entry box */ |
| 231 | - const char *zVar, /* The corresponding row in the VAR table */ | |
| 231 | + const char *zVar, /* The corresponding row in the CONFIG table */ | |
| 232 | 232 | const char *zQParm, /* The query parameter */ |
| 233 | - const char *zDflt, /* Default value if VAR table entry does not exist */ | |
| 233 | + const char *zDflt, /* Default value if CONFIG table entry does not exist */ | |
| 234 | 234 | int disabled /* 1 if disabled */ |
| 235 | 235 | ){ |
| 236 | 236 | const char *zVal = db_get(zVar, zDflt); |
| 237 | 237 | const char *zQ = P(zQParm); |
| 238 | 238 | if( zQ && fossil_strcmp(zQ,zVal)!=0 ){ |
| 239 | 239 | const int nZQ = (int)strlen(zQ); |
| 240 | 240 | login_verify_csrf_secret(); |
| 241 | 241 | setup_incr_cfgcnt(); |
| 242 | 242 | db_protect_only(PROTECT_NONE); |
| 243 | - db_set(zVar, zQ, 0); | |
| 243 | + db_set(zVar/*works-like:"x"*/, zQ, 0); | |
| 244 | 244 | db_protect_pop(); |
| 245 | 245 | admin_log("Set entry_attribute %Q to: %.*s%s", |
| 246 | 246 | zVar, 20, zQ, (nZQ>20 ? "..." : "")); |
| 247 | 247 | zVal = zQ; |
| 248 | 248 | } |
| @@ -259,22 +259,22 @@ | ||
| 259 | 259 | */ |
| 260 | 260 | const char *textarea_attribute( |
| 261 | 261 | const char *zLabel, /* The text label on the textarea */ |
| 262 | 262 | int rows, /* Rows in the textarea */ |
| 263 | 263 | int cols, /* Columns in the textarea */ |
| 264 | - const char *zVar, /* The corresponding row in the VAR table */ | |
| 264 | + const char *zVar, /* The corresponding row in the CONFIG table */ | |
| 265 | 265 | const char *zQP, /* The query parameter */ |
| 266 | - const char *zDflt, /* Default value if VAR table entry does not exist */ | |
| 266 | + const char *zDflt, /* Default value if CONFIG table entry does not exist */ | |
| 267 | 267 | int disabled /* 1 if the textarea should not be editable */ |
| 268 | 268 | ){ |
| 269 | 269 | const char *z = db_get(zVar, zDflt); |
| 270 | 270 | const char *zQ = P(zQP); |
| 271 | 271 | if( zQ && !disabled && fossil_strcmp(zQ,z)!=0){ |
| 272 | 272 | const int nZQ = (int)strlen(zQ); |
| 273 | 273 | login_verify_csrf_secret(); |
| 274 | 274 | db_protect_only(PROTECT_NONE); |
| 275 | - db_set(zVar, zQ, 0); | |
| 275 | + db_set(zVar/*works-like:"x"*/, zQ, 0); | |
| 276 | 276 | db_protect_pop(); |
| 277 | 277 | setup_incr_cfgcnt(); |
| 278 | 278 | admin_log("Set textarea_attribute %Q to: %.*s%s", |
| 279 | 279 | zVar, 20, zQ, (nZQ>20 ? "..." : "")); |
| 280 | 280 | z = zQ; |
| @@ -296,13 +296,13 @@ | ||
| 296 | 296 | /* |
| 297 | 297 | ** Generate a text box for an attribute. |
| 298 | 298 | */ |
| 299 | 299 | void multiple_choice_attribute( |
| 300 | 300 | const char *zLabel, /* The text label on the menu */ |
| 301 | - const char *zVar, /* The corresponding row in the VAR table */ | |
| 301 | + const char *zVar, /* The corresponding row in the CONFIG table */ | |
| 302 | 302 | const char *zQP, /* The query parameter */ |
| 303 | - const char *zDflt, /* Default value if VAR table entry does not exist */ | |
| 303 | + const char *zDflt, /* Default value if CONFIG table entry does not exist */ | |
| 304 | 304 | int nChoice, /* Number of choices */ |
| 305 | 305 | const char *const *azChoice /* Choices in pairs (VAR value, Display) */ |
| 306 | 306 | ){ |
| 307 | 307 | const char *z = db_get(zVar, zDflt); |
| 308 | 308 | const char *zQ = P(zQP); |
| @@ -309,11 +309,11 @@ | ||
| 309 | 309 | int i; |
| 310 | 310 | if( zQ && fossil_strcmp(zQ,z)!=0){ |
| 311 | 311 | const int nZQ = (int)strlen(zQ); |
| 312 | 312 | login_verify_csrf_secret(); |
| 313 | 313 | db_unprotect(PROTECT_ALL); |
| 314 | - db_set(zVar, zQ, 0); | |
| 314 | + db_set(zVar/*works-like:"x"*/, zQ, 0); | |
| 315 | 315 | setup_incr_cfgcnt(); |
| 316 | 316 | db_protect_pop(); |
| 317 | 317 | admin_log("Set multiple_choice_attribute %Q to: %.*s%s", |
| 318 | 318 | zVar, 20, zQ, (nZQ>20 ? "..." : "")); |
| 319 | 319 | z = zQ; |
| @@ -899,11 +899,11 @@ | ||
| 899 | 899 | for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){ |
| 900 | 900 | if( pSet->width==0 ){ |
| 901 | 901 | int hasVersionableValue = pSet->versionable && |
| 902 | 902 | (db_get_versioned(pSet->name, NULL)!=0); |
| 903 | 903 | onoff_attribute("", pSet->name, |
| 904 | - pSet->var!=0 ? pSet->var : pSet->name, | |
| 904 | + pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, | |
| 905 | 905 | is_truth(pSet->def), hasVersionableValue); |
| 906 | 906 | @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a> |
| 907 | 907 | if( pSet->versionable ){ |
| 908 | 908 | @ (v)<br /> |
| 909 | 909 | } else { |
| @@ -925,11 +925,11 @@ | ||
| 925 | 925 | } else { |
| 926 | 926 | @ |
| 927 | 927 | } |
| 928 | 928 | @</td><td> |
| 929 | 929 | entry_attribute("", /*pSet->width*/ 25, pSet->name, |
| 930 | - pSet->var!=0 ? pSet->var : pSet->name, | |
| 930 | + pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, | |
| 931 | 931 | (char*)pSet->def, hasVersionableValue); |
| 932 | 932 | @</td></tr> |
| 933 | 933 | } |
| 934 | 934 | } |
| 935 | 935 | @</table> |
| @@ -942,11 +942,11 @@ | ||
| 942 | 942 | @ (v)<br /> |
| 943 | 943 | } else { |
| 944 | 944 | @ <br /> |
| 945 | 945 | } |
| 946 | 946 | textarea_attribute("", /*rows*/ 2, /*cols*/ 35, pSet->name, |
| 947 | - pSet->var!=0 ? pSet->var : pSet->name, | |
| 947 | + pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, | |
| 948 | 948 | (char*)pSet->def, hasVersionableValue); |
| 949 | 949 | @<br /> |
| 950 | 950 | } |
| 951 | 951 | } |
| 952 | 952 | @ </td></tr></table> |
| 953 | 953 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -186,13 +186,13 @@ | |
| 186 | /* |
| 187 | ** Generate a checkbox for an attribute. |
| 188 | */ |
| 189 | void onoff_attribute( |
| 190 | const char *zLabel, /* The text label on the checkbox */ |
| 191 | const char *zVar, /* The corresponding row in the VAR table */ |
| 192 | const char *zQParm, /* The query parameter */ |
| 193 | int dfltVal, /* Default value if VAR table entry does not exist */ |
| 194 | int disabled /* 1 if disabled */ |
| 195 | ){ |
| 196 | const char *zQ = P(zQParm); |
| 197 | int iVal = db_get_boolean(zVar, dfltVal); |
| 198 | if( zQ==0 && !disabled && P("submit") ){ |
| @@ -201,11 +201,11 @@ | |
| 201 | if( zQ ){ |
| 202 | int iQ = fossil_strcmp(zQ,"on")==0 || atoi(zQ); |
| 203 | if( iQ!=iVal ){ |
| 204 | login_verify_csrf_secret(); |
| 205 | db_protect_only(PROTECT_NONE); |
| 206 | db_set(zVar, iQ ? "1" : "0", 0); |
| 207 | db_protect_pop(); |
| 208 | setup_incr_cfgcnt(); |
| 209 | admin_log("Set option [%q] to [%q].", |
| 210 | zVar, iQ ? "on" : "off"); |
| 211 | iVal = iQ; |
| @@ -226,23 +226,23 @@ | |
| 226 | ** Generate an entry box for an attribute. |
| 227 | */ |
| 228 | void entry_attribute( |
| 229 | const char *zLabel, /* The text label on the entry box */ |
| 230 | int width, /* Width of the entry box */ |
| 231 | const char *zVar, /* The corresponding row in the VAR table */ |
| 232 | const char *zQParm, /* The query parameter */ |
| 233 | const char *zDflt, /* Default value if VAR table entry does not exist */ |
| 234 | int disabled /* 1 if disabled */ |
| 235 | ){ |
| 236 | const char *zVal = db_get(zVar, zDflt); |
| 237 | const char *zQ = P(zQParm); |
| 238 | if( zQ && fossil_strcmp(zQ,zVal)!=0 ){ |
| 239 | const int nZQ = (int)strlen(zQ); |
| 240 | login_verify_csrf_secret(); |
| 241 | setup_incr_cfgcnt(); |
| 242 | db_protect_only(PROTECT_NONE); |
| 243 | db_set(zVar, zQ, 0); |
| 244 | db_protect_pop(); |
| 245 | admin_log("Set entry_attribute %Q to: %.*s%s", |
| 246 | zVar, 20, zQ, (nZQ>20 ? "..." : "")); |
| 247 | zVal = zQ; |
| 248 | } |
| @@ -259,22 +259,22 @@ | |
| 259 | */ |
| 260 | const char *textarea_attribute( |
| 261 | const char *zLabel, /* The text label on the textarea */ |
| 262 | int rows, /* Rows in the textarea */ |
| 263 | int cols, /* Columns in the textarea */ |
| 264 | const char *zVar, /* The corresponding row in the VAR table */ |
| 265 | const char *zQP, /* The query parameter */ |
| 266 | const char *zDflt, /* Default value if VAR table entry does not exist */ |
| 267 | int disabled /* 1 if the textarea should not be editable */ |
| 268 | ){ |
| 269 | const char *z = db_get(zVar, zDflt); |
| 270 | const char *zQ = P(zQP); |
| 271 | if( zQ && !disabled && fossil_strcmp(zQ,z)!=0){ |
| 272 | const int nZQ = (int)strlen(zQ); |
| 273 | login_verify_csrf_secret(); |
| 274 | db_protect_only(PROTECT_NONE); |
| 275 | db_set(zVar, zQ, 0); |
| 276 | db_protect_pop(); |
| 277 | setup_incr_cfgcnt(); |
| 278 | admin_log("Set textarea_attribute %Q to: %.*s%s", |
| 279 | zVar, 20, zQ, (nZQ>20 ? "..." : "")); |
| 280 | z = zQ; |
| @@ -296,13 +296,13 @@ | |
| 296 | /* |
| 297 | ** Generate a text box for an attribute. |
| 298 | */ |
| 299 | void multiple_choice_attribute( |
| 300 | const char *zLabel, /* The text label on the menu */ |
| 301 | const char *zVar, /* The corresponding row in the VAR table */ |
| 302 | const char *zQP, /* The query parameter */ |
| 303 | const char *zDflt, /* Default value if VAR table entry does not exist */ |
| 304 | int nChoice, /* Number of choices */ |
| 305 | const char *const *azChoice /* Choices in pairs (VAR value, Display) */ |
| 306 | ){ |
| 307 | const char *z = db_get(zVar, zDflt); |
| 308 | const char *zQ = P(zQP); |
| @@ -309,11 +309,11 @@ | |
| 309 | int i; |
| 310 | if( zQ && fossil_strcmp(zQ,z)!=0){ |
| 311 | const int nZQ = (int)strlen(zQ); |
| 312 | login_verify_csrf_secret(); |
| 313 | db_unprotect(PROTECT_ALL); |
| 314 | db_set(zVar, zQ, 0); |
| 315 | setup_incr_cfgcnt(); |
| 316 | db_protect_pop(); |
| 317 | admin_log("Set multiple_choice_attribute %Q to: %.*s%s", |
| 318 | zVar, 20, zQ, (nZQ>20 ? "..." : "")); |
| 319 | z = zQ; |
| @@ -899,11 +899,11 @@ | |
| 899 | for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){ |
| 900 | if( pSet->width==0 ){ |
| 901 | int hasVersionableValue = pSet->versionable && |
| 902 | (db_get_versioned(pSet->name, NULL)!=0); |
| 903 | onoff_attribute("", pSet->name, |
| 904 | pSet->var!=0 ? pSet->var : pSet->name, |
| 905 | is_truth(pSet->def), hasVersionableValue); |
| 906 | @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a> |
| 907 | if( pSet->versionable ){ |
| 908 | @ (v)<br /> |
| 909 | } else { |
| @@ -925,11 +925,11 @@ | |
| 925 | } else { |
| 926 | @ |
| 927 | } |
| 928 | @</td><td> |
| 929 | entry_attribute("", /*pSet->width*/ 25, pSet->name, |
| 930 | pSet->var!=0 ? pSet->var : pSet->name, |
| 931 | (char*)pSet->def, hasVersionableValue); |
| 932 | @</td></tr> |
| 933 | } |
| 934 | } |
| 935 | @</table> |
| @@ -942,11 +942,11 @@ | |
| 942 | @ (v)<br /> |
| 943 | } else { |
| 944 | @ <br /> |
| 945 | } |
| 946 | textarea_attribute("", /*rows*/ 2, /*cols*/ 35, pSet->name, |
| 947 | pSet->var!=0 ? pSet->var : pSet->name, |
| 948 | (char*)pSet->def, hasVersionableValue); |
| 949 | @<br /> |
| 950 | } |
| 951 | } |
| 952 | @ </td></tr></table> |
| 953 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -186,13 +186,13 @@ | |
| 186 | /* |
| 187 | ** Generate a checkbox for an attribute. |
| 188 | */ |
| 189 | void onoff_attribute( |
| 190 | const char *zLabel, /* The text label on the checkbox */ |
| 191 | const char *zVar, /* The corresponding row in the CONFIG table */ |
| 192 | const char *zQParm, /* The query parameter */ |
| 193 | int dfltVal, /* Default value if CONFIG table entry does not exist */ |
| 194 | int disabled /* 1 if disabled */ |
| 195 | ){ |
| 196 | const char *zQ = P(zQParm); |
| 197 | int iVal = db_get_boolean(zVar, dfltVal); |
| 198 | if( zQ==0 && !disabled && P("submit") ){ |
| @@ -201,11 +201,11 @@ | |
| 201 | if( zQ ){ |
| 202 | int iQ = fossil_strcmp(zQ,"on")==0 || atoi(zQ); |
| 203 | if( iQ!=iVal ){ |
| 204 | login_verify_csrf_secret(); |
| 205 | db_protect_only(PROTECT_NONE); |
| 206 | db_set(zVar/*works-like:"x"*/, iQ ? "1" : "0", 0); |
| 207 | db_protect_pop(); |
| 208 | setup_incr_cfgcnt(); |
| 209 | admin_log("Set option [%q] to [%q].", |
| 210 | zVar, iQ ? "on" : "off"); |
| 211 | iVal = iQ; |
| @@ -226,23 +226,23 @@ | |
| 226 | ** Generate an entry box for an attribute. |
| 227 | */ |
| 228 | void entry_attribute( |
| 229 | const char *zLabel, /* The text label on the entry box */ |
| 230 | int width, /* Width of the entry box */ |
| 231 | const char *zVar, /* The corresponding row in the CONFIG table */ |
| 232 | const char *zQParm, /* The query parameter */ |
| 233 | const char *zDflt, /* Default value if CONFIG table entry does not exist */ |
| 234 | int disabled /* 1 if disabled */ |
| 235 | ){ |
| 236 | const char *zVal = db_get(zVar, zDflt); |
| 237 | const char *zQ = P(zQParm); |
| 238 | if( zQ && fossil_strcmp(zQ,zVal)!=0 ){ |
| 239 | const int nZQ = (int)strlen(zQ); |
| 240 | login_verify_csrf_secret(); |
| 241 | setup_incr_cfgcnt(); |
| 242 | db_protect_only(PROTECT_NONE); |
| 243 | db_set(zVar/*works-like:"x"*/, zQ, 0); |
| 244 | db_protect_pop(); |
| 245 | admin_log("Set entry_attribute %Q to: %.*s%s", |
| 246 | zVar, 20, zQ, (nZQ>20 ? "..." : "")); |
| 247 | zVal = zQ; |
| 248 | } |
| @@ -259,22 +259,22 @@ | |
| 259 | */ |
| 260 | const char *textarea_attribute( |
| 261 | const char *zLabel, /* The text label on the textarea */ |
| 262 | int rows, /* Rows in the textarea */ |
| 263 | int cols, /* Columns in the textarea */ |
| 264 | const char *zVar, /* The corresponding row in the CONFIG table */ |
| 265 | const char *zQP, /* The query parameter */ |
| 266 | const char *zDflt, /* Default value if CONFIG table entry does not exist */ |
| 267 | int disabled /* 1 if the textarea should not be editable */ |
| 268 | ){ |
| 269 | const char *z = db_get(zVar, zDflt); |
| 270 | const char *zQ = P(zQP); |
| 271 | if( zQ && !disabled && fossil_strcmp(zQ,z)!=0){ |
| 272 | const int nZQ = (int)strlen(zQ); |
| 273 | login_verify_csrf_secret(); |
| 274 | db_protect_only(PROTECT_NONE); |
| 275 | db_set(zVar/*works-like:"x"*/, zQ, 0); |
| 276 | db_protect_pop(); |
| 277 | setup_incr_cfgcnt(); |
| 278 | admin_log("Set textarea_attribute %Q to: %.*s%s", |
| 279 | zVar, 20, zQ, (nZQ>20 ? "..." : "")); |
| 280 | z = zQ; |
| @@ -296,13 +296,13 @@ | |
| 296 | /* |
| 297 | ** Generate a text box for an attribute. |
| 298 | */ |
| 299 | void multiple_choice_attribute( |
| 300 | const char *zLabel, /* The text label on the menu */ |
| 301 | const char *zVar, /* The corresponding row in the CONFIG table */ |
| 302 | const char *zQP, /* The query parameter */ |
| 303 | const char *zDflt, /* Default value if CONFIG table entry does not exist */ |
| 304 | int nChoice, /* Number of choices */ |
| 305 | const char *const *azChoice /* Choices in pairs (VAR value, Display) */ |
| 306 | ){ |
| 307 | const char *z = db_get(zVar, zDflt); |
| 308 | const char *zQ = P(zQP); |
| @@ -309,11 +309,11 @@ | |
| 309 | int i; |
| 310 | if( zQ && fossil_strcmp(zQ,z)!=0){ |
| 311 | const int nZQ = (int)strlen(zQ); |
| 312 | login_verify_csrf_secret(); |
| 313 | db_unprotect(PROTECT_ALL); |
| 314 | db_set(zVar/*works-like:"x"*/, zQ, 0); |
| 315 | setup_incr_cfgcnt(); |
| 316 | db_protect_pop(); |
| 317 | admin_log("Set multiple_choice_attribute %Q to: %.*s%s", |
| 318 | zVar, 20, zQ, (nZQ>20 ? "..." : "")); |
| 319 | z = zQ; |
| @@ -899,11 +899,11 @@ | |
| 899 | for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){ |
| 900 | if( pSet->width==0 ){ |
| 901 | int hasVersionableValue = pSet->versionable && |
| 902 | (db_get_versioned(pSet->name, NULL)!=0); |
| 903 | onoff_attribute("", pSet->name, |
| 904 | pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, |
| 905 | is_truth(pSet->def), hasVersionableValue); |
| 906 | @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a> |
| 907 | if( pSet->versionable ){ |
| 908 | @ (v)<br /> |
| 909 | } else { |
| @@ -925,11 +925,11 @@ | |
| 925 | } else { |
| 926 | @ |
| 927 | } |
| 928 | @</td><td> |
| 929 | entry_attribute("", /*pSet->width*/ 25, pSet->name, |
| 930 | pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, |
| 931 | (char*)pSet->def, hasVersionableValue); |
| 932 | @</td></tr> |
| 933 | } |
| 934 | } |
| 935 | @</table> |
| @@ -942,11 +942,11 @@ | |
| 942 | @ (v)<br /> |
| 943 | } else { |
| 944 | @ <br /> |
| 945 | } |
| 946 | textarea_attribute("", /*rows*/ 2, /*cols*/ 35, pSet->name, |
| 947 | pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, |
| 948 | (char*)pSet->def, hasVersionableValue); |
| 949 | @<br /> |
| 950 | } |
| 951 | } |
| 952 | @ </td></tr></table> |
| 953 |
+3
-5
| --- src/skins.c | ||
| +++ src/skins.c | ||
| @@ -789,11 +789,10 @@ | ||
| 789 | 789 | const char *zBasis; /* The baseline file */ |
| 790 | 790 | const char *zOrig; /* Original content prior to editing */ |
| 791 | 791 | const char *zContent; /* Content after editing */ |
| 792 | 792 | const char *zDflt; /* Default content */ |
| 793 | 793 | char *zDraft; /* Which draft: "draft%d" */ |
| 794 | - char *zKey; /* CONFIG table key name: "draft%d-%s" */ | |
| 795 | 794 | char *zTitle; /* Title of this page */ |
| 796 | 795 | const char *zFile; /* One of "css", "footer", "header", "details" */ |
| 797 | 796 | int iSkin; /* draft number. 1..9 */ |
| 798 | 797 | int ii; /* Index in aSkinAttr[] of this file */ |
| 799 | 798 | int j; /* Loop counter */ |
| @@ -827,15 +826,14 @@ | ||
| 827 | 826 | /* figure out which file is to be edited */ |
| 828 | 827 | ii = atoi(PD("w","0")); |
| 829 | 828 | if( ii<0 || ii>count(aSkinAttr) ) ii = 0; |
| 830 | 829 | zFile = aSkinAttr[ii].zFile; |
| 831 | 830 | zDraft = mprintf("draft%d", iSkin); |
| 832 | - zKey = mprintf("draft%d-%s", iSkin, zFile); | |
| 833 | 831 | zTitle = mprintf("%s for Draft%d", aSkinAttr[ii].zTitle, iSkin); |
| 834 | 832 | zBasis = PD("basis","current"); |
| 835 | 833 | zDflt = skin_file_content(zBasis, zFile); |
| 836 | - zOrig = db_get(zKey, zDflt); | |
| 834 | + zOrig = db_get_mprintf(zDflt, "draft%d-%s",iSkin,zFile); | |
| 837 | 835 | zContent = PD(zFile,zOrig); |
| 838 | 836 | if( P("revert")!=0 && cgi_csrf_safe(0) ){ |
| 839 | 837 | zContent = zDflt; |
| 840 | 838 | isRevert = 1; |
| 841 | 839 | } |
| @@ -851,11 +849,11 @@ | ||
| 851 | 849 | login_insert_csrf_secret(); |
| 852 | 850 | @ <input type='hidden' name='w' value='%d(ii)'> |
| 853 | 851 | @ <input type='hidden' name='sk' value='%d(iSkin)'> |
| 854 | 852 | @ <h2>Edit %s(zTitle):</h2> |
| 855 | 853 | if( P("submit") && cgi_csrf_safe(0) && strcmp(zOrig,zContent)!=0 ){ |
| 856 | - db_set(zKey, zContent, 0); | |
| 854 | + db_set_mprintf(zContent, 0, "draft%d-%s",iSkin,zFile); | |
| 857 | 855 | } |
| 858 | 856 | @ <textarea name="%s(zFile)" rows="10" cols="80">\ |
| 859 | 857 | @ %h(zContent)</textarea> |
| 860 | 858 | @ <br /> |
| 861 | 859 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| @@ -942,11 +940,11 @@ | ||
| 942 | 940 | } |
| 943 | 941 | |
| 944 | 942 | /* Publish draft iSkin */ |
| 945 | 943 | for(i=0; i<count(azSkinFile); i++){ |
| 946 | 944 | char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]); |
| 947 | - db_set(azSkinFile[i], zNew, 0); | |
| 945 | + db_set(azSkinFile[i]/*works-like:"x"*/, zNew, 0); | |
| 948 | 946 | } |
| 949 | 947 | } |
| 950 | 948 | |
| 951 | 949 | /* |
| 952 | 950 | ** WEBPAGE: setup_skin |
| 953 | 951 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -789,11 +789,10 @@ | |
| 789 | const char *zBasis; /* The baseline file */ |
| 790 | const char *zOrig; /* Original content prior to editing */ |
| 791 | const char *zContent; /* Content after editing */ |
| 792 | const char *zDflt; /* Default content */ |
| 793 | char *zDraft; /* Which draft: "draft%d" */ |
| 794 | char *zKey; /* CONFIG table key name: "draft%d-%s" */ |
| 795 | char *zTitle; /* Title of this page */ |
| 796 | const char *zFile; /* One of "css", "footer", "header", "details" */ |
| 797 | int iSkin; /* draft number. 1..9 */ |
| 798 | int ii; /* Index in aSkinAttr[] of this file */ |
| 799 | int j; /* Loop counter */ |
| @@ -827,15 +826,14 @@ | |
| 827 | /* figure out which file is to be edited */ |
| 828 | ii = atoi(PD("w","0")); |
| 829 | if( ii<0 || ii>count(aSkinAttr) ) ii = 0; |
| 830 | zFile = aSkinAttr[ii].zFile; |
| 831 | zDraft = mprintf("draft%d", iSkin); |
| 832 | zKey = mprintf("draft%d-%s", iSkin, zFile); |
| 833 | zTitle = mprintf("%s for Draft%d", aSkinAttr[ii].zTitle, iSkin); |
| 834 | zBasis = PD("basis","current"); |
| 835 | zDflt = skin_file_content(zBasis, zFile); |
| 836 | zOrig = db_get(zKey, zDflt); |
| 837 | zContent = PD(zFile,zOrig); |
| 838 | if( P("revert")!=0 && cgi_csrf_safe(0) ){ |
| 839 | zContent = zDflt; |
| 840 | isRevert = 1; |
| 841 | } |
| @@ -851,11 +849,11 @@ | |
| 851 | login_insert_csrf_secret(); |
| 852 | @ <input type='hidden' name='w' value='%d(ii)'> |
| 853 | @ <input type='hidden' name='sk' value='%d(iSkin)'> |
| 854 | @ <h2>Edit %s(zTitle):</h2> |
| 855 | if( P("submit") && cgi_csrf_safe(0) && strcmp(zOrig,zContent)!=0 ){ |
| 856 | db_set(zKey, zContent, 0); |
| 857 | } |
| 858 | @ <textarea name="%s(zFile)" rows="10" cols="80">\ |
| 859 | @ %h(zContent)</textarea> |
| 860 | @ <br /> |
| 861 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| @@ -942,11 +940,11 @@ | |
| 942 | } |
| 943 | |
| 944 | /* Publish draft iSkin */ |
| 945 | for(i=0; i<count(azSkinFile); i++){ |
| 946 | char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]); |
| 947 | db_set(azSkinFile[i], zNew, 0); |
| 948 | } |
| 949 | } |
| 950 | |
| 951 | /* |
| 952 | ** WEBPAGE: setup_skin |
| 953 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -789,11 +789,10 @@ | |
| 789 | const char *zBasis; /* The baseline file */ |
| 790 | const char *zOrig; /* Original content prior to editing */ |
| 791 | const char *zContent; /* Content after editing */ |
| 792 | const char *zDflt; /* Default content */ |
| 793 | char *zDraft; /* Which draft: "draft%d" */ |
| 794 | char *zTitle; /* Title of this page */ |
| 795 | const char *zFile; /* One of "css", "footer", "header", "details" */ |
| 796 | int iSkin; /* draft number. 1..9 */ |
| 797 | int ii; /* Index in aSkinAttr[] of this file */ |
| 798 | int j; /* Loop counter */ |
| @@ -827,15 +826,14 @@ | |
| 826 | /* figure out which file is to be edited */ |
| 827 | ii = atoi(PD("w","0")); |
| 828 | if( ii<0 || ii>count(aSkinAttr) ) ii = 0; |
| 829 | zFile = aSkinAttr[ii].zFile; |
| 830 | zDraft = mprintf("draft%d", iSkin); |
| 831 | zTitle = mprintf("%s for Draft%d", aSkinAttr[ii].zTitle, iSkin); |
| 832 | zBasis = PD("basis","current"); |
| 833 | zDflt = skin_file_content(zBasis, zFile); |
| 834 | zOrig = db_get_mprintf(zDflt, "draft%d-%s",iSkin,zFile); |
| 835 | zContent = PD(zFile,zOrig); |
| 836 | if( P("revert")!=0 && cgi_csrf_safe(0) ){ |
| 837 | zContent = zDflt; |
| 838 | isRevert = 1; |
| 839 | } |
| @@ -851,11 +849,11 @@ | |
| 849 | login_insert_csrf_secret(); |
| 850 | @ <input type='hidden' name='w' value='%d(ii)'> |
| 851 | @ <input type='hidden' name='sk' value='%d(iSkin)'> |
| 852 | @ <h2>Edit %s(zTitle):</h2> |
| 853 | if( P("submit") && cgi_csrf_safe(0) && strcmp(zOrig,zContent)!=0 ){ |
| 854 | db_set_mprintf(zContent, 0, "draft%d-%s",iSkin,zFile); |
| 855 | } |
| 856 | @ <textarea name="%s(zFile)" rows="10" cols="80">\ |
| 857 | @ %h(zContent)</textarea> |
| 858 | @ <br /> |
| 859 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| @@ -942,11 +940,11 @@ | |
| 940 | } |
| 941 | |
| 942 | /* Publish draft iSkin */ |
| 943 | for(i=0; i<count(azSkinFile); i++){ |
| 944 | char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]); |
| 945 | db_set(azSkinFile[i]/*works-like:"x"*/, zNew, 0); |
| 946 | } |
| 947 | } |
| 948 | |
| 949 | /* |
| 950 | ** WEBPAGE: setup_skin |
| 951 |
+2
-2
| --- src/tktsetup.c | ||
| +++ src/tktsetup.c | ||
| @@ -136,20 +136,20 @@ | ||
| 136 | 136 | } |
| 137 | 137 | style_set_current_feature("tktsetup"); |
| 138 | 138 | style_header("Edit %s", zTitle); |
| 139 | 139 | if( P("clear")!=0 ){ |
| 140 | 140 | login_verify_csrf_secret(); |
| 141 | - db_unset(zDbField, 0); | |
| 141 | + db_unset(zDbField/*works-like:"x"*/, 0); | |
| 142 | 142 | if( xRebuild ) xRebuild(); |
| 143 | 143 | cgi_redirect("tktsetup"); |
| 144 | 144 | }else if( isSubmit ){ |
| 145 | 145 | char *zErr = 0; |
| 146 | 146 | login_verify_csrf_secret(); |
| 147 | 147 | if( xText && (zErr = xText(z))!=0 ){ |
| 148 | 148 | @ <p class="tktsetupError">ERROR: %h(zErr)</p> |
| 149 | 149 | }else{ |
| 150 | - db_set(zDbField, z, 0); | |
| 150 | + db_set(zDbField/*works-like:"x"*/, z, 0); | |
| 151 | 151 | if( xRebuild ) xRebuild(); |
| 152 | 152 | cgi_redirect("tktsetup"); |
| 153 | 153 | } |
| 154 | 154 | } |
| 155 | 155 | @ <form action="%R/%s(g.zPath)" method="post"><div> |
| 156 | 156 |
| --- src/tktsetup.c | |
| +++ src/tktsetup.c | |
| @@ -136,20 +136,20 @@ | |
| 136 | } |
| 137 | style_set_current_feature("tktsetup"); |
| 138 | style_header("Edit %s", zTitle); |
| 139 | if( P("clear")!=0 ){ |
| 140 | login_verify_csrf_secret(); |
| 141 | db_unset(zDbField, 0); |
| 142 | if( xRebuild ) xRebuild(); |
| 143 | cgi_redirect("tktsetup"); |
| 144 | }else if( isSubmit ){ |
| 145 | char *zErr = 0; |
| 146 | login_verify_csrf_secret(); |
| 147 | if( xText && (zErr = xText(z))!=0 ){ |
| 148 | @ <p class="tktsetupError">ERROR: %h(zErr)</p> |
| 149 | }else{ |
| 150 | db_set(zDbField, z, 0); |
| 151 | if( xRebuild ) xRebuild(); |
| 152 | cgi_redirect("tktsetup"); |
| 153 | } |
| 154 | } |
| 155 | @ <form action="%R/%s(g.zPath)" method="post"><div> |
| 156 |
| --- src/tktsetup.c | |
| +++ src/tktsetup.c | |
| @@ -136,20 +136,20 @@ | |
| 136 | } |
| 137 | style_set_current_feature("tktsetup"); |
| 138 | style_header("Edit %s", zTitle); |
| 139 | if( P("clear")!=0 ){ |
| 140 | login_verify_csrf_secret(); |
| 141 | db_unset(zDbField/*works-like:"x"*/, 0); |
| 142 | if( xRebuild ) xRebuild(); |
| 143 | cgi_redirect("tktsetup"); |
| 144 | }else if( isSubmit ){ |
| 145 | char *zErr = 0; |
| 146 | login_verify_csrf_secret(); |
| 147 | if( xText && (zErr = xText(z))!=0 ){ |
| 148 | @ <p class="tktsetupError">ERROR: %h(zErr)</p> |
| 149 | }else{ |
| 150 | db_set(zDbField/*works-like:"x"*/, z, 0); |
| 151 | if( xRebuild ) xRebuild(); |
| 152 | cgi_redirect("tktsetup"); |
| 153 | } |
| 154 | } |
| 155 | @ <form action="%R/%s(g.zPath)" method="post"><div> |
| 156 |
+2
-2
| --- src/xfersetup.c | ||
| +++ src/xfersetup.c | ||
| @@ -120,20 +120,20 @@ | ||
| 120 | 120 | } |
| 121 | 121 | style_set_current_feature("xfersetup"); |
| 122 | 122 | style_header("Edit %s", zTitle); |
| 123 | 123 | if( P("clear")!=0 ){ |
| 124 | 124 | login_verify_csrf_secret(); |
| 125 | - db_unset(zDbField, 0); | |
| 125 | + db_unset(zDbField/*works-like:"x"*/, 0); | |
| 126 | 126 | if( xRebuild ) xRebuild(); |
| 127 | 127 | z = zDfltValue; |
| 128 | 128 | }else if( isSubmit ){ |
| 129 | 129 | char *zErr = 0; |
| 130 | 130 | login_verify_csrf_secret(); |
| 131 | 131 | if( xText && (zErr = xText(z))!=0 ){ |
| 132 | 132 | @ <p class="xfersetupError">ERROR: %h(zErr)</p> |
| 133 | 133 | }else{ |
| 134 | - db_set(zDbField, z, 0); | |
| 134 | + db_set(zDbField/*works-like:"x"*/, z, 0); | |
| 135 | 135 | if( xRebuild ) xRebuild(); |
| 136 | 136 | cgi_redirect("xfersetup"); |
| 137 | 137 | } |
| 138 | 138 | } |
| 139 | 139 | @ <form action="%R/%s(g.zPath)" method="post"><div> |
| 140 | 140 |
| --- src/xfersetup.c | |
| +++ src/xfersetup.c | |
| @@ -120,20 +120,20 @@ | |
| 120 | } |
| 121 | style_set_current_feature("xfersetup"); |
| 122 | style_header("Edit %s", zTitle); |
| 123 | if( P("clear")!=0 ){ |
| 124 | login_verify_csrf_secret(); |
| 125 | db_unset(zDbField, 0); |
| 126 | if( xRebuild ) xRebuild(); |
| 127 | z = zDfltValue; |
| 128 | }else if( isSubmit ){ |
| 129 | char *zErr = 0; |
| 130 | login_verify_csrf_secret(); |
| 131 | if( xText && (zErr = xText(z))!=0 ){ |
| 132 | @ <p class="xfersetupError">ERROR: %h(zErr)</p> |
| 133 | }else{ |
| 134 | db_set(zDbField, z, 0); |
| 135 | if( xRebuild ) xRebuild(); |
| 136 | cgi_redirect("xfersetup"); |
| 137 | } |
| 138 | } |
| 139 | @ <form action="%R/%s(g.zPath)" method="post"><div> |
| 140 |
| --- src/xfersetup.c | |
| +++ src/xfersetup.c | |
| @@ -120,20 +120,20 @@ | |
| 120 | } |
| 121 | style_set_current_feature("xfersetup"); |
| 122 | style_header("Edit %s", zTitle); |
| 123 | if( P("clear")!=0 ){ |
| 124 | login_verify_csrf_secret(); |
| 125 | db_unset(zDbField/*works-like:"x"*/, 0); |
| 126 | if( xRebuild ) xRebuild(); |
| 127 | z = zDfltValue; |
| 128 | }else if( isSubmit ){ |
| 129 | char *zErr = 0; |
| 130 | login_verify_csrf_secret(); |
| 131 | if( xText && (zErr = xText(z))!=0 ){ |
| 132 | @ <p class="xfersetupError">ERROR: %h(zErr)</p> |
| 133 | }else{ |
| 134 | db_set(zDbField/*works-like:"x"*/, z, 0); |
| 135 | if( xRebuild ) xRebuild(); |
| 136 | cgi_redirect("xfersetup"); |
| 137 | } |
| 138 | } |
| 139 | @ <form action="%R/%s(g.zPath)" method="post"><div> |
| 140 |