Fossil SCM
Add defenses against [http://en.wikipedia.org/wiki/Cross-site_request_forgery | cross-site request forgery] attacks.
Commit
0be54823ba2b5afe0b058e77376feaa1ff47751a
Parent
ac3f1f2ba755061…
10 files changed
+2
+2
+33
-6
+4
+4
+11
-1
+4
+3
+4
+4
+2
| --- src/admin.c | ||
| +++ src/admin.c | ||
| @@ -76,15 +76,17 @@ | ||
| 76 | 76 | style_header("Admin SQL"); |
| 77 | 77 | @ <h2>SQL:</h2> |
| 78 | 78 | @ You can enter only SELECT statements here, and some SQL-side functions |
| 79 | 79 | @ are also restricted.<br/> |
| 80 | 80 | @ <form action='' method='post'> |
| 81 | + login_insert_csrf_secret(); | |
| 81 | 82 | @ <textarea style='border:2px solid black' name='sql' |
| 82 | 83 | @ cols='80' rows='5'>%h(zSql)</textarea> |
| 83 | 84 | @ <br/><input type='submit' name='sql_submit'/> <input type='reset'/> |
| 84 | 85 | @ </form> |
| 85 | 86 | if( zSql[0] ){ |
| 87 | + login_verify_csrf_secret(); | |
| 86 | 88 | sqlite3_set_authorizer(g.db, selectOnly, 0); |
| 87 | 89 | db_generic_query_view(zSql, 0); |
| 88 | 90 | sqlite3_set_authorizer(g.db, 0, 0); |
| 89 | 91 | } |
| 90 | 92 | style_footer(); |
| 91 | 93 |
| --- src/admin.c | |
| +++ src/admin.c | |
| @@ -76,15 +76,17 @@ | |
| 76 | style_header("Admin SQL"); |
| 77 | @ <h2>SQL:</h2> |
| 78 | @ You can enter only SELECT statements here, and some SQL-side functions |
| 79 | @ are also restricted.<br/> |
| 80 | @ <form action='' method='post'> |
| 81 | @ <textarea style='border:2px solid black' name='sql' |
| 82 | @ cols='80' rows='5'>%h(zSql)</textarea> |
| 83 | @ <br/><input type='submit' name='sql_submit'/> <input type='reset'/> |
| 84 | @ </form> |
| 85 | if( zSql[0] ){ |
| 86 | sqlite3_set_authorizer(g.db, selectOnly, 0); |
| 87 | db_generic_query_view(zSql, 0); |
| 88 | sqlite3_set_authorizer(g.db, 0, 0); |
| 89 | } |
| 90 | style_footer(); |
| 91 |
| --- src/admin.c | |
| +++ src/admin.c | |
| @@ -76,15 +76,17 @@ | |
| 76 | style_header("Admin SQL"); |
| 77 | @ <h2>SQL:</h2> |
| 78 | @ You can enter only SELECT statements here, and some SQL-side functions |
| 79 | @ are also restricted.<br/> |
| 80 | @ <form action='' method='post'> |
| 81 | login_insert_csrf_secret(); |
| 82 | @ <textarea style='border:2px solid black' name='sql' |
| 83 | @ cols='80' rows='5'>%h(zSql)</textarea> |
| 84 | @ <br/><input type='submit' name='sql_submit'/> <input type='reset'/> |
| 85 | @ </form> |
| 86 | if( zSql[0] ){ |
| 87 | login_verify_csrf_secret(); |
| 88 | sqlite3_set_authorizer(g.db, selectOnly, 0); |
| 89 | db_generic_query_view(zSql, 0); |
| 90 | sqlite3_set_authorizer(g.db, 0, 0); |
| 91 | } |
| 92 | style_footer(); |
| 93 |
+2
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1022,10 +1022,11 @@ | ||
| 1022 | 1022 | if( P("apply") ){ |
| 1023 | 1023 | Blob ctrl; |
| 1024 | 1024 | char *zDate; |
| 1025 | 1025 | int nChng = 0; |
| 1026 | 1026 | |
| 1027 | + login_verify_csrf_secret(); | |
| 1027 | 1028 | blob_zero(&ctrl); |
| 1028 | 1029 | zDate = db_text(0, "SELECT datetime('now')"); |
| 1029 | 1030 | zDate[10] = 'T'; |
| 1030 | 1031 | blob_appendf(&ctrl, "D %s\n", zDate); |
| 1031 | 1032 | if( strcmp(zComment,zNewComment)!=0 ){ |
| @@ -1055,10 +1056,11 @@ | ||
| 1055 | 1056 | style_header("Edit Baseline [%s]", zUuid); |
| 1056 | 1057 | @ <p>Make changes to the User and Comment for baseline |
| 1057 | 1058 | @ [<a href="vinfo?name=%d(rid)">%s(zUuid)</a>] then press the |
| 1058 | 1059 | @ "Apply Changes" button.</p> |
| 1059 | 1060 | @ <form action="%s(g.zBaseURL)/vedit" method="POST"> |
| 1061 | + login_insert_csrf_secret(); | |
| 1060 | 1062 | @ <input type="hidden" name="r" value="%d(rid)"> |
| 1061 | 1063 | @ <p> |
| 1062 | 1064 | @ <b>User:</b> <input type="text" name="u" size="20" value="%h(zNewUser)"> |
| 1063 | 1065 | @ </p> |
| 1064 | 1066 | @ <p><b>Comment:</b></b><br /> |
| 1065 | 1067 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1022,10 +1022,11 @@ | |
| 1022 | if( P("apply") ){ |
| 1023 | Blob ctrl; |
| 1024 | char *zDate; |
| 1025 | int nChng = 0; |
| 1026 | |
| 1027 | blob_zero(&ctrl); |
| 1028 | zDate = db_text(0, "SELECT datetime('now')"); |
| 1029 | zDate[10] = 'T'; |
| 1030 | blob_appendf(&ctrl, "D %s\n", zDate); |
| 1031 | if( strcmp(zComment,zNewComment)!=0 ){ |
| @@ -1055,10 +1056,11 @@ | |
| 1055 | style_header("Edit Baseline [%s]", zUuid); |
| 1056 | @ <p>Make changes to the User and Comment for baseline |
| 1057 | @ [<a href="vinfo?name=%d(rid)">%s(zUuid)</a>] then press the |
| 1058 | @ "Apply Changes" button.</p> |
| 1059 | @ <form action="%s(g.zBaseURL)/vedit" method="POST"> |
| 1060 | @ <input type="hidden" name="r" value="%d(rid)"> |
| 1061 | @ <p> |
| 1062 | @ <b>User:</b> <input type="text" name="u" size="20" value="%h(zNewUser)"> |
| 1063 | @ </p> |
| 1064 | @ <p><b>Comment:</b></b><br /> |
| 1065 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1022,10 +1022,11 @@ | |
| 1022 | if( P("apply") ){ |
| 1023 | Blob ctrl; |
| 1024 | char *zDate; |
| 1025 | int nChng = 0; |
| 1026 | |
| 1027 | login_verify_csrf_secret(); |
| 1028 | blob_zero(&ctrl); |
| 1029 | zDate = db_text(0, "SELECT datetime('now')"); |
| 1030 | zDate[10] = 'T'; |
| 1031 | blob_appendf(&ctrl, "D %s\n", zDate); |
| 1032 | if( strcmp(zComment,zNewComment)!=0 ){ |
| @@ -1055,10 +1056,11 @@ | |
| 1056 | style_header("Edit Baseline [%s]", zUuid); |
| 1057 | @ <p>Make changes to the User and Comment for baseline |
| 1058 | @ [<a href="vinfo?name=%d(rid)">%s(zUuid)</a>] then press the |
| 1059 | @ "Apply Changes" button.</p> |
| 1060 | @ <form action="%s(g.zBaseURL)/vedit" method="POST"> |
| 1061 | login_insert_csrf_secret(); |
| 1062 | @ <input type="hidden" name="r" value="%d(rid)"> |
| 1063 | @ <p> |
| 1064 | @ <b>User:</b> <input type="text" name="u" size="20" value="%h(zNewUser)"> |
| 1065 | @ </p> |
| 1066 | @ <p><b>Comment:</b></b><br /> |
| 1067 |
+33
-6
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -234,16 +234,16 @@ | ||
| 234 | 234 | ** and is valid. If the login cookie checks out, it then sets |
| 235 | 235 | ** g.zUserUuid appropriately. |
| 236 | 236 | ** |
| 237 | 237 | */ |
| 238 | 238 | void login_check_credentials(void){ |
| 239 | - int uid = 0; | |
| 240 | - const char *zCookie; | |
| 241 | - const char *zRemoteAddr; | |
| 242 | - const char *zCap = 0; | |
| 243 | - const char *zNcap; | |
| 244 | - const char *zAcap; | |
| 239 | + int uid = 0; /* User id */ | |
| 240 | + const char *zCookie; /* Text of the login cookie */ | |
| 241 | + const char *zRemoteAddr; /* IP address of the requestor */ | |
| 242 | + const char *zCap = 0; /* Capability string */ | |
| 243 | + const char *zNcap; /* Capabilities of user "nobody" */ | |
| 244 | + const char *zAcap; /* Capabllities of user "anonymous" */ | |
| 245 | 245 | |
| 246 | 246 | /* Only run this check once. */ |
| 247 | 247 | if( g.userUid!=0 ) return; |
| 248 | 248 | |
| 249 | 249 | |
| @@ -255,10 +255,11 @@ | ||
| 255 | 255 | if( strcmp(zRemoteAddr, "127.0.0.1")==0 && db_get_int("localauth",0)==0 ){ |
| 256 | 256 | uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'"); |
| 257 | 257 | g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid); |
| 258 | 258 | zCap = "s"; |
| 259 | 259 | g.noPswd = 1; |
| 260 | + strcpy(g.zCsrfToken, "localhost"); | |
| 260 | 261 | } |
| 261 | 262 | |
| 262 | 263 | /* Check the login cookie to see if it matches a known valid user. |
| 263 | 264 | */ |
| 264 | 265 | if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){ |
| @@ -272,18 +273,20 @@ | ||
| 272 | 273 | atoi(zCookie), zCookie, zRemoteAddr |
| 273 | 274 | ); |
| 274 | 275 | }else if( zCookie[0]=='a' ){ |
| 275 | 276 | uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'"); |
| 276 | 277 | } |
| 278 | + snprintf(g.zCsrfToken, sizeof(g.zCsrfToken), "%.10s", zCookie); | |
| 277 | 279 | } |
| 278 | 280 | |
| 279 | 281 | if( uid==0 ){ |
| 280 | 282 | uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); |
| 281 | 283 | if( uid==0 ){ |
| 282 | 284 | uid = -1; |
| 283 | 285 | zCap = ""; |
| 284 | 286 | } |
| 287 | + strcpy(g.zCsrfToken, "none"); | |
| 285 | 288 | } |
| 286 | 289 | if( zCap==0 ){ |
| 287 | 290 | if( uid ){ |
| 288 | 291 | Stmt s; |
| 289 | 292 | db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid); |
| @@ -432,5 +435,29 @@ | ||
| 432 | 435 | @ <p>Many <font color="red">hyperlinks are disabled.</font><br /> |
| 433 | 436 | @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> |
| 434 | 437 | @ to enable hyperlinks.</p> |
| 435 | 438 | } |
| 436 | 439 | } |
| 440 | + | |
| 441 | +/* | |
| 442 | +** While rendering a form, call this routine to add the Anti-CSRF token | |
| 443 | +** as a hidden element of the form. | |
| 444 | +*/ | |
| 445 | +void login_insert_csrf_secret(void){ | |
| 446 | + @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)"> | |
| 447 | +} | |
| 448 | + | |
| 449 | +/* | |
| 450 | +** Before using the results of a form, first call this routine to verify | |
| 451 | +** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token | |
| 452 | +** is missing or is incorrect, then this emits and error message and never | |
| 453 | +** returns. | |
| 454 | +*/ | |
| 455 | +void login_verify_csrf_secret(void){ | |
| 456 | + const char *zCsrf; /* The CSRF secret */ | |
| 457 | + if( g.okCsrf ) return; | |
| 458 | + if( (zCsrf = P("csrf"))!=0 && strcmp(zCsrf, g.zCsrfToken)==0 ){ | |
| 459 | + g.okCsrf = 1; | |
| 460 | + return; | |
| 461 | + } | |
| 462 | + fossil_fatal("Cross-site request forgery attempt"); | |
| 463 | +} | |
| 437 | 464 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -234,16 +234,16 @@ | |
| 234 | ** and is valid. If the login cookie checks out, it then sets |
| 235 | ** g.zUserUuid appropriately. |
| 236 | ** |
| 237 | */ |
| 238 | void login_check_credentials(void){ |
| 239 | int uid = 0; |
| 240 | const char *zCookie; |
| 241 | const char *zRemoteAddr; |
| 242 | const char *zCap = 0; |
| 243 | const char *zNcap; |
| 244 | const char *zAcap; |
| 245 | |
| 246 | /* Only run this check once. */ |
| 247 | if( g.userUid!=0 ) return; |
| 248 | |
| 249 | |
| @@ -255,10 +255,11 @@ | |
| 255 | if( strcmp(zRemoteAddr, "127.0.0.1")==0 && db_get_int("localauth",0)==0 ){ |
| 256 | uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'"); |
| 257 | g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid); |
| 258 | zCap = "s"; |
| 259 | g.noPswd = 1; |
| 260 | } |
| 261 | |
| 262 | /* Check the login cookie to see if it matches a known valid user. |
| 263 | */ |
| 264 | if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){ |
| @@ -272,18 +273,20 @@ | |
| 272 | atoi(zCookie), zCookie, zRemoteAddr |
| 273 | ); |
| 274 | }else if( zCookie[0]=='a' ){ |
| 275 | uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'"); |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | if( uid==0 ){ |
| 280 | uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); |
| 281 | if( uid==0 ){ |
| 282 | uid = -1; |
| 283 | zCap = ""; |
| 284 | } |
| 285 | } |
| 286 | if( zCap==0 ){ |
| 287 | if( uid ){ |
| 288 | Stmt s; |
| 289 | db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid); |
| @@ -432,5 +435,29 @@ | |
| 432 | @ <p>Many <font color="red">hyperlinks are disabled.</font><br /> |
| 433 | @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> |
| 434 | @ to enable hyperlinks.</p> |
| 435 | } |
| 436 | } |
| 437 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -234,16 +234,16 @@ | |
| 234 | ** and is valid. If the login cookie checks out, it then sets |
| 235 | ** g.zUserUuid appropriately. |
| 236 | ** |
| 237 | */ |
| 238 | void login_check_credentials(void){ |
| 239 | int uid = 0; /* User id */ |
| 240 | const char *zCookie; /* Text of the login cookie */ |
| 241 | const char *zRemoteAddr; /* IP address of the requestor */ |
| 242 | const char *zCap = 0; /* Capability string */ |
| 243 | const char *zNcap; /* Capabilities of user "nobody" */ |
| 244 | const char *zAcap; /* Capabllities of user "anonymous" */ |
| 245 | |
| 246 | /* Only run this check once. */ |
| 247 | if( g.userUid!=0 ) return; |
| 248 | |
| 249 | |
| @@ -255,10 +255,11 @@ | |
| 255 | if( strcmp(zRemoteAddr, "127.0.0.1")==0 && db_get_int("localauth",0)==0 ){ |
| 256 | uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'"); |
| 257 | g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid); |
| 258 | zCap = "s"; |
| 259 | g.noPswd = 1; |
| 260 | strcpy(g.zCsrfToken, "localhost"); |
| 261 | } |
| 262 | |
| 263 | /* Check the login cookie to see if it matches a known valid user. |
| 264 | */ |
| 265 | if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){ |
| @@ -272,18 +273,20 @@ | |
| 273 | atoi(zCookie), zCookie, zRemoteAddr |
| 274 | ); |
| 275 | }else if( zCookie[0]=='a' ){ |
| 276 | uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'"); |
| 277 | } |
| 278 | snprintf(g.zCsrfToken, sizeof(g.zCsrfToken), "%.10s", zCookie); |
| 279 | } |
| 280 | |
| 281 | if( uid==0 ){ |
| 282 | uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); |
| 283 | if( uid==0 ){ |
| 284 | uid = -1; |
| 285 | zCap = ""; |
| 286 | } |
| 287 | strcpy(g.zCsrfToken, "none"); |
| 288 | } |
| 289 | if( zCap==0 ){ |
| 290 | if( uid ){ |
| 291 | Stmt s; |
| 292 | db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid); |
| @@ -432,5 +435,29 @@ | |
| 435 | @ <p>Many <font color="red">hyperlinks are disabled.</font><br /> |
| 436 | @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> |
| 437 | @ to enable hyperlinks.</p> |
| 438 | } |
| 439 | } |
| 440 | |
| 441 | /* |
| 442 | ** While rendering a form, call this routine to add the Anti-CSRF token |
| 443 | ** as a hidden element of the form. |
| 444 | */ |
| 445 | void login_insert_csrf_secret(void){ |
| 446 | @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)"> |
| 447 | } |
| 448 | |
| 449 | /* |
| 450 | ** Before using the results of a form, first call this routine to verify |
| 451 | ** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token |
| 452 | ** is missing or is incorrect, then this emits and error message and never |
| 453 | ** returns. |
| 454 | */ |
| 455 | void login_verify_csrf_secret(void){ |
| 456 | const char *zCsrf; /* The CSRF secret */ |
| 457 | if( g.okCsrf ) return; |
| 458 | if( (zCsrf = P("csrf"))!=0 && strcmp(zCsrf, g.zCsrfToken)==0 ){ |
| 459 | g.okCsrf = 1; |
| 460 | return; |
| 461 | } |
| 462 | fossil_fatal("Cross-site request forgery attempt"); |
| 463 | } |
| 464 |
+4
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -119,10 +119,14 @@ | ||
| 119 | 119 | int okWrTkt; /* w: make changes to tickets via web */ |
| 120 | 120 | int okTktFmt; /* t: create new ticket report formats */ |
| 121 | 121 | int okRdAddr; /* e: read email addresses or other private data */ |
| 122 | 122 | int okZip; /* z: download zipped artifact via /zip URL */ |
| 123 | 123 | |
| 124 | + /* For defense against Cross-site Request Forgery attacks */ | |
| 125 | + char zCsrfToken[12]; /* Value of the anti-CSRF token */ | |
| 126 | + int okCsrf; /* Anti-CSRF token is present and valid */ | |
| 127 | + | |
| 124 | 128 | FILE *fDebug; /* Write debug information here, if the file exists */ |
| 125 | 129 | |
| 126 | 130 | /* Storage for the aux() and/or option() SQL function arguments */ |
| 127 | 131 | int nAux; /* Number of distinct aux() or option() values */ |
| 128 | 132 | const char *azAuxName[MX_AUX]; /* Name of each aux() or option() value */ |
| 129 | 133 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -119,10 +119,14 @@ | |
| 119 | int okWrTkt; /* w: make changes to tickets via web */ |
| 120 | int okTktFmt; /* t: create new ticket report formats */ |
| 121 | int okRdAddr; /* e: read email addresses or other private data */ |
| 122 | int okZip; /* z: download zipped artifact via /zip URL */ |
| 123 | |
| 124 | FILE *fDebug; /* Write debug information here, if the file exists */ |
| 125 | |
| 126 | /* Storage for the aux() and/or option() SQL function arguments */ |
| 127 | int nAux; /* Number of distinct aux() or option() values */ |
| 128 | const char *azAuxName[MX_AUX]; /* Name of each aux() or option() value */ |
| 129 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -119,10 +119,14 @@ | |
| 119 | int okWrTkt; /* w: make changes to tickets via web */ |
| 120 | int okTktFmt; /* t: create new ticket report formats */ |
| 121 | int okRdAddr; /* e: read email addresses or other private data */ |
| 122 | int okZip; /* z: download zipped artifact via /zip URL */ |
| 123 | |
| 124 | /* For defense against Cross-site Request Forgery attacks */ |
| 125 | char zCsrfToken[12]; /* Value of the anti-CSRF token */ |
| 126 | int okCsrf; /* Anti-CSRF token is present and valid */ |
| 127 | |
| 128 | FILE *fDebug; /* Write debug information here, if the file exists */ |
| 129 | |
| 130 | /* Storage for the aux() and/or option() SQL function arguments */ |
| 131 | int nAux; /* Number of distinct aux() or option() values */ |
| 132 | const char *azAuxName[MX_AUX]; /* Name of each aux() or option() value */ |
| 133 |
+4
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -319,10 +319,11 @@ | ||
| 319 | 319 | zOwner = PD("w",g.zLogin); |
| 320 | 320 | z = P("s"); |
| 321 | 321 | zSQL = z ? trim_string(z) : 0; |
| 322 | 322 | zClrKey = trim_string(PD("k","")); |
| 323 | 323 | if( rn>0 && P("del2") ){ |
| 324 | + login_verify_csrf_secret(); | |
| 324 | 325 | db_multi_exec("DELETE FROM reportfmt WHERE rn=%d", rn); |
| 325 | 326 | cgi_redirect("reportlist"); |
| 326 | 327 | return; |
| 327 | 328 | }else if( rn>0 && P("del1") ){ |
| 328 | 329 | zTitle = db_text(0, "SELECT title FROM reportfmt " |
| @@ -335,10 +336,11 @@ | ||
| 335 | 336 | @ <strong>%h(zTitle)</strong> from |
| 336 | 337 | @ the database. This is an irreversible operation. All records |
| 337 | 338 | @ related to this report will be removed and cannot be recovered.</p> |
| 338 | 339 | @ |
| 339 | 340 | @ <input type="hidden" name="rn" value="%d(rn)"> |
| 341 | + login_insert_csrf_secret(); | |
| 340 | 342 | @ <input type="submit" name="del2" value="Delete The Report"> |
| 341 | 343 | @ <input type="submit" name="can" value="Cancel"> |
| 342 | 344 | @ </form> |
| 343 | 345 | style_footer(); |
| 344 | 346 | return; |
| @@ -354,10 +356,11 @@ | ||
| 354 | 356 | zErr = "Please supply a title"; |
| 355 | 357 | }else{ |
| 356 | 358 | zErr = verify_sql_statement(zSQL); |
| 357 | 359 | } |
| 358 | 360 | if( zErr==0 ){ |
| 361 | + login_verify_csrf_secret(); | |
| 359 | 362 | if( rn>0 ){ |
| 360 | 363 | db_multi_exec("UPDATE reportfmt SET title=%Q, sqlcode=%Q," |
| 361 | 364 | " owner=%Q, cols=%Q WHERE rn=%d", |
| 362 | 365 | zTitle, zSQL, zOwner, zClrKey, rn); |
| 363 | 366 | }else{ |
| @@ -404,10 +407,11 @@ | ||
| 404 | 407 | @ <p>Report Title:<br> |
| 405 | 408 | @ <input type="text" name="t" value="%h(zTitle)" size="60"></p> |
| 406 | 409 | @ <p>Enter a complete SQL query statement against the "TICKET" table:<br> |
| 407 | 410 | @ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea> |
| 408 | 411 | @ </p> |
| 412 | + login_insert_csrf_secret(); | |
| 409 | 413 | if( g.okAdmin ){ |
| 410 | 414 | @ <p>Report owner: |
| 411 | 415 | @ <input type="text" name="w" size="20" value="%h(zOwner)"> |
| 412 | 416 | @ </p> |
| 413 | 417 | } else { |
| 414 | 418 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -319,10 +319,11 @@ | |
| 319 | zOwner = PD("w",g.zLogin); |
| 320 | z = P("s"); |
| 321 | zSQL = z ? trim_string(z) : 0; |
| 322 | zClrKey = trim_string(PD("k","")); |
| 323 | if( rn>0 && P("del2") ){ |
| 324 | db_multi_exec("DELETE FROM reportfmt WHERE rn=%d", rn); |
| 325 | cgi_redirect("reportlist"); |
| 326 | return; |
| 327 | }else if( rn>0 && P("del1") ){ |
| 328 | zTitle = db_text(0, "SELECT title FROM reportfmt " |
| @@ -335,10 +336,11 @@ | |
| 335 | @ <strong>%h(zTitle)</strong> from |
| 336 | @ the database. This is an irreversible operation. All records |
| 337 | @ related to this report will be removed and cannot be recovered.</p> |
| 338 | @ |
| 339 | @ <input type="hidden" name="rn" value="%d(rn)"> |
| 340 | @ <input type="submit" name="del2" value="Delete The Report"> |
| 341 | @ <input type="submit" name="can" value="Cancel"> |
| 342 | @ </form> |
| 343 | style_footer(); |
| 344 | return; |
| @@ -354,10 +356,11 @@ | |
| 354 | zErr = "Please supply a title"; |
| 355 | }else{ |
| 356 | zErr = verify_sql_statement(zSQL); |
| 357 | } |
| 358 | if( zErr==0 ){ |
| 359 | if( rn>0 ){ |
| 360 | db_multi_exec("UPDATE reportfmt SET title=%Q, sqlcode=%Q," |
| 361 | " owner=%Q, cols=%Q WHERE rn=%d", |
| 362 | zTitle, zSQL, zOwner, zClrKey, rn); |
| 363 | }else{ |
| @@ -404,10 +407,11 @@ | |
| 404 | @ <p>Report Title:<br> |
| 405 | @ <input type="text" name="t" value="%h(zTitle)" size="60"></p> |
| 406 | @ <p>Enter a complete SQL query statement against the "TICKET" table:<br> |
| 407 | @ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea> |
| 408 | @ </p> |
| 409 | if( g.okAdmin ){ |
| 410 | @ <p>Report owner: |
| 411 | @ <input type="text" name="w" size="20" value="%h(zOwner)"> |
| 412 | @ </p> |
| 413 | } else { |
| 414 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -319,10 +319,11 @@ | |
| 319 | zOwner = PD("w",g.zLogin); |
| 320 | z = P("s"); |
| 321 | zSQL = z ? trim_string(z) : 0; |
| 322 | zClrKey = trim_string(PD("k","")); |
| 323 | if( rn>0 && P("del2") ){ |
| 324 | login_verify_csrf_secret(); |
| 325 | db_multi_exec("DELETE FROM reportfmt WHERE rn=%d", rn); |
| 326 | cgi_redirect("reportlist"); |
| 327 | return; |
| 328 | }else if( rn>0 && P("del1") ){ |
| 329 | zTitle = db_text(0, "SELECT title FROM reportfmt " |
| @@ -335,10 +336,11 @@ | |
| 336 | @ <strong>%h(zTitle)</strong> from |
| 337 | @ the database. This is an irreversible operation. All records |
| 338 | @ related to this report will be removed and cannot be recovered.</p> |
| 339 | @ |
| 340 | @ <input type="hidden" name="rn" value="%d(rn)"> |
| 341 | login_insert_csrf_secret(); |
| 342 | @ <input type="submit" name="del2" value="Delete The Report"> |
| 343 | @ <input type="submit" name="can" value="Cancel"> |
| 344 | @ </form> |
| 345 | style_footer(); |
| 346 | return; |
| @@ -354,10 +356,11 @@ | |
| 356 | zErr = "Please supply a title"; |
| 357 | }else{ |
| 358 | zErr = verify_sql_statement(zSQL); |
| 359 | } |
| 360 | if( zErr==0 ){ |
| 361 | login_verify_csrf_secret(); |
| 362 | if( rn>0 ){ |
| 363 | db_multi_exec("UPDATE reportfmt SET title=%Q, sqlcode=%Q," |
| 364 | " owner=%Q, cols=%Q WHERE rn=%d", |
| 365 | zTitle, zSQL, zOwner, zClrKey, rn); |
| 366 | }else{ |
| @@ -404,10 +407,11 @@ | |
| 407 | @ <p>Report Title:<br> |
| 408 | @ <input type="text" name="t" value="%h(zTitle)" size="60"></p> |
| 409 | @ <p>Enter a complete SQL query statement against the "TICKET" table:<br> |
| 410 | @ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea> |
| 411 | @ </p> |
| 412 | login_insert_csrf_secret(); |
| 413 | if( g.okAdmin ){ |
| 414 | @ <p>Report owner: |
| 415 | @ <input type="text" name="w" size="20" value="%h(zOwner)"> |
| 416 | @ </p> |
| 417 | } else { |
| 418 |
+11
-1
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -286,10 +286,11 @@ | ||
| 286 | 286 | @ |
| 287 | 287 | @ <p><a href="setup_uedit?id=%d(uid))>[Bummer]</a></p> |
| 288 | 288 | style_footer(); |
| 289 | 289 | return; |
| 290 | 290 | } |
| 291 | + login_verify_csrf_secret(); | |
| 291 | 292 | db_multi_exec( |
| 292 | 293 | "REPLACE INTO user(uid,login,info,pw,cap) " |
| 293 | 294 | "VALUES(nullif(%d,0),%Q,%Q,%Q,'%s')", |
| 294 | 295 | uid, P("login"), P("info"), zPw, zCap |
| 295 | 296 | ); |
| @@ -340,10 +341,11 @@ | ||
| 340 | 341 | }else{ |
| 341 | 342 | style_header("Add A New User"); |
| 342 | 343 | } |
| 343 | 344 | @ <table align="left" hspace="20" vspace="10"><tr><td> |
| 344 | 345 | @ <form action="%s(g.zPath)" method="POST"> |
| 346 | + login_insert_csrf_secret(); | |
| 345 | 347 | @ <table> |
| 346 | 348 | @ <tr> |
| 347 | 349 | @ <td align="right"><nobr>User ID:</nobr></td> |
| 348 | 350 | if( uid ){ |
| 349 | 351 | @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)"></td> |
| @@ -543,10 +545,11 @@ | ||
| 543 | 545 | zQ = "off"; |
| 544 | 546 | } |
| 545 | 547 | if( zQ ){ |
| 546 | 548 | int iQ = strcmp(zQ,"on")==0 || atoi(zQ); |
| 547 | 549 | if( iQ!=iVal ){ |
| 550 | + login_verify_csrf_secret(); | |
| 548 | 551 | db_set(zVar, iQ ? "1" : "0", 0); |
| 549 | 552 | iVal = iQ; |
| 550 | 553 | } |
| 551 | 554 | } |
| 552 | 555 | if( iVal ){ |
| @@ -567,10 +570,11 @@ | ||
| 567 | 570 | char *zDflt /* Default value if VAR table entry does not exist */ |
| 568 | 571 | ){ |
| 569 | 572 | const char *zVal = db_get(zVar, zDflt); |
| 570 | 573 | const char *zQ = P(zQParm); |
| 571 | 574 | if( zQ && strcmp(zQ,zVal)!=0 ){ |
| 575 | + login_verify_csrf_secret(); | |
| 572 | 576 | db_set(zVar, zQ, 0); |
| 573 | 577 | zVal = zQ; |
| 574 | 578 | } |
| 575 | 579 | @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)"> |
| 576 | 580 | @ <b>%s(zLabel)</b> |
| @@ -588,10 +592,11 @@ | ||
| 588 | 592 | const char *zDflt /* Default value if VAR table entry does not exist */ |
| 589 | 593 | ){ |
| 590 | 594 | const char *z = db_get(zVar, (char*)zDflt); |
| 591 | 595 | const char *zQ = P(zQP); |
| 592 | 596 | if( zQ && strcmp(zQ,z)!=0 ){ |
| 597 | + login_verify_csrf_secret(); | |
| 593 | 598 | db_set(zVar, zQ, 0); |
| 594 | 599 | z = zQ; |
| 595 | 600 | } |
| 596 | 601 | if( rows>0 && cols>0 ){ |
| 597 | 602 | @ <textarea name="%s(zQP)" rows="%d(rows)" cols="%d(cols)">%h(z)</textarea> |
| @@ -610,11 +615,11 @@ | ||
| 610 | 615 | } |
| 611 | 616 | |
| 612 | 617 | style_header("Access Control Settings"); |
| 613 | 618 | db_begin_transaction(); |
| 614 | 619 | @ <form action="%s(g.zBaseURL)/setup_access" method="POST"> |
| 615 | - | |
| 620 | + login_insert_csrf_secret(); | |
| 616 | 621 | @ <hr> |
| 617 | 622 | onoff_attribute("Require password for local access", |
| 618 | 623 | "localauth", "localauth", 1); |
| 619 | 624 | @ <p>When enabled, the password sign-in is required for |
| 620 | 625 | @ web access coming from 127.0.0.1. When disabled, web access |
| @@ -661,10 +666,11 @@ | ||
| 661 | 666 | } |
| 662 | 667 | |
| 663 | 668 | style_header("Timeline Display Preferences"); |
| 664 | 669 | db_begin_transaction(); |
| 665 | 670 | @ <form action="%s(g.zBaseURL)/setup_timeline" method="POST"> |
| 671 | + login_insert_csrf_secret(); | |
| 666 | 672 | |
| 667 | 673 | @ <hr> |
| 668 | 674 | onoff_attribute("Block markup in timeline", |
| 669 | 675 | "timeline-block-markup", "tbm", 0); |
| 670 | 676 | @ <p>In timeline displays, check-in comments can be displayed with or |
| @@ -693,10 +699,11 @@ | ||
| 693 | 699 | } |
| 694 | 700 | |
| 695 | 701 | style_header("WWW Configuration"); |
| 696 | 702 | db_begin_transaction(); |
| 697 | 703 | @ <form action="%s(g.zBaseURL)/setup_config" method="POST"> |
| 704 | + login_insert_csrf_secret(); | |
| 698 | 705 | @ <hr /> |
| 699 | 706 | entry_attribute("Project Name", 60, "project-name", "pn", ""); |
| 700 | 707 | @ <p>Give your project a name so visitors know what this site is about. |
| 701 | 708 | @ The project name will also be used as the RSS feed title.</p> |
| 702 | 709 | @ <hr /> |
| @@ -735,10 +742,11 @@ | ||
| 735 | 742 | if( !g.okSetup ){ |
| 736 | 743 | login_needed(); |
| 737 | 744 | } |
| 738 | 745 | style_header("Edit CSS"); |
| 739 | 746 | @ <form action="%s(g.zBaseURL)/setup_editcss" method="POST"> |
| 747 | + login_insert_csrf_secret(); | |
| 740 | 748 | @ Edit the CSS:<br /> |
| 741 | 749 | textarea_attribute("", 40, 80, "css", "css", zDefaultCSS); |
| 742 | 750 | @ <br /> |
| 743 | 751 | @ <input type="submit" name="submit" value="Apply Changes"> |
| 744 | 752 | @ </form> |
| @@ -765,10 +773,11 @@ | ||
| 765 | 773 | }else{ |
| 766 | 774 | textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader); |
| 767 | 775 | } |
| 768 | 776 | style_header("Edit Page Header"); |
| 769 | 777 | @ <form action="%s(g.zBaseURL)/setup_header" method="POST"> |
| 778 | + login_insert_csrf_secret(); | |
| 770 | 779 | @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to |
| 771 | 780 | @ generate the beginning of every page through start of the main |
| 772 | 781 | @ menu.</p> |
| 773 | 782 | textarea_attribute("", 40, 80, "header", "header", zDefaultHeader); |
| 774 | 783 | @ <br /> |
| @@ -799,10 +808,11 @@ | ||
| 799 | 808 | }else{ |
| 800 | 809 | textarea_attribute(0, 0, 0, "footer", "footer", zDefaultFooter); |
| 801 | 810 | } |
| 802 | 811 | style_header("Edit Page Footer"); |
| 803 | 812 | @ <form action="%s(g.zBaseURL)/setup_footer" method="POST"> |
| 813 | + login_insert_csrf_secret(); | |
| 804 | 814 | @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to |
| 805 | 815 | @ generate the end of every page.</p> |
| 806 | 816 | textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter); |
| 807 | 817 | @ <br /> |
| 808 | 818 | @ <input type="submit" name="submit" value="Apply Changes"> |
| 809 | 819 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -286,10 +286,11 @@ | |
| 286 | @ |
| 287 | @ <p><a href="setup_uedit?id=%d(uid))>[Bummer]</a></p> |
| 288 | style_footer(); |
| 289 | return; |
| 290 | } |
| 291 | db_multi_exec( |
| 292 | "REPLACE INTO user(uid,login,info,pw,cap) " |
| 293 | "VALUES(nullif(%d,0),%Q,%Q,%Q,'%s')", |
| 294 | uid, P("login"), P("info"), zPw, zCap |
| 295 | ); |
| @@ -340,10 +341,11 @@ | |
| 340 | }else{ |
| 341 | style_header("Add A New User"); |
| 342 | } |
| 343 | @ <table align="left" hspace="20" vspace="10"><tr><td> |
| 344 | @ <form action="%s(g.zPath)" method="POST"> |
| 345 | @ <table> |
| 346 | @ <tr> |
| 347 | @ <td align="right"><nobr>User ID:</nobr></td> |
| 348 | if( uid ){ |
| 349 | @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)"></td> |
| @@ -543,10 +545,11 @@ | |
| 543 | zQ = "off"; |
| 544 | } |
| 545 | if( zQ ){ |
| 546 | int iQ = strcmp(zQ,"on")==0 || atoi(zQ); |
| 547 | if( iQ!=iVal ){ |
| 548 | db_set(zVar, iQ ? "1" : "0", 0); |
| 549 | iVal = iQ; |
| 550 | } |
| 551 | } |
| 552 | if( iVal ){ |
| @@ -567,10 +570,11 @@ | |
| 567 | char *zDflt /* Default value if VAR table entry does not exist */ |
| 568 | ){ |
| 569 | const char *zVal = db_get(zVar, zDflt); |
| 570 | const char *zQ = P(zQParm); |
| 571 | if( zQ && strcmp(zQ,zVal)!=0 ){ |
| 572 | db_set(zVar, zQ, 0); |
| 573 | zVal = zQ; |
| 574 | } |
| 575 | @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)"> |
| 576 | @ <b>%s(zLabel)</b> |
| @@ -588,10 +592,11 @@ | |
| 588 | const char *zDflt /* Default value if VAR table entry does not exist */ |
| 589 | ){ |
| 590 | const char *z = db_get(zVar, (char*)zDflt); |
| 591 | const char *zQ = P(zQP); |
| 592 | if( zQ && strcmp(zQ,z)!=0 ){ |
| 593 | db_set(zVar, zQ, 0); |
| 594 | z = zQ; |
| 595 | } |
| 596 | if( rows>0 && cols>0 ){ |
| 597 | @ <textarea name="%s(zQP)" rows="%d(rows)" cols="%d(cols)">%h(z)</textarea> |
| @@ -610,11 +615,11 @@ | |
| 610 | } |
| 611 | |
| 612 | style_header("Access Control Settings"); |
| 613 | db_begin_transaction(); |
| 614 | @ <form action="%s(g.zBaseURL)/setup_access" method="POST"> |
| 615 | |
| 616 | @ <hr> |
| 617 | onoff_attribute("Require password for local access", |
| 618 | "localauth", "localauth", 1); |
| 619 | @ <p>When enabled, the password sign-in is required for |
| 620 | @ web access coming from 127.0.0.1. When disabled, web access |
| @@ -661,10 +666,11 @@ | |
| 661 | } |
| 662 | |
| 663 | style_header("Timeline Display Preferences"); |
| 664 | db_begin_transaction(); |
| 665 | @ <form action="%s(g.zBaseURL)/setup_timeline" method="POST"> |
| 666 | |
| 667 | @ <hr> |
| 668 | onoff_attribute("Block markup in timeline", |
| 669 | "timeline-block-markup", "tbm", 0); |
| 670 | @ <p>In timeline displays, check-in comments can be displayed with or |
| @@ -693,10 +699,11 @@ | |
| 693 | } |
| 694 | |
| 695 | style_header("WWW Configuration"); |
| 696 | db_begin_transaction(); |
| 697 | @ <form action="%s(g.zBaseURL)/setup_config" method="POST"> |
| 698 | @ <hr /> |
| 699 | entry_attribute("Project Name", 60, "project-name", "pn", ""); |
| 700 | @ <p>Give your project a name so visitors know what this site is about. |
| 701 | @ The project name will also be used as the RSS feed title.</p> |
| 702 | @ <hr /> |
| @@ -735,10 +742,11 @@ | |
| 735 | if( !g.okSetup ){ |
| 736 | login_needed(); |
| 737 | } |
| 738 | style_header("Edit CSS"); |
| 739 | @ <form action="%s(g.zBaseURL)/setup_editcss" method="POST"> |
| 740 | @ Edit the CSS:<br /> |
| 741 | textarea_attribute("", 40, 80, "css", "css", zDefaultCSS); |
| 742 | @ <br /> |
| 743 | @ <input type="submit" name="submit" value="Apply Changes"> |
| 744 | @ </form> |
| @@ -765,10 +773,11 @@ | |
| 765 | }else{ |
| 766 | textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader); |
| 767 | } |
| 768 | style_header("Edit Page Header"); |
| 769 | @ <form action="%s(g.zBaseURL)/setup_header" method="POST"> |
| 770 | @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to |
| 771 | @ generate the beginning of every page through start of the main |
| 772 | @ menu.</p> |
| 773 | textarea_attribute("", 40, 80, "header", "header", zDefaultHeader); |
| 774 | @ <br /> |
| @@ -799,10 +808,11 @@ | |
| 799 | }else{ |
| 800 | textarea_attribute(0, 0, 0, "footer", "footer", zDefaultFooter); |
| 801 | } |
| 802 | style_header("Edit Page Footer"); |
| 803 | @ <form action="%s(g.zBaseURL)/setup_footer" method="POST"> |
| 804 | @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to |
| 805 | @ generate the end of every page.</p> |
| 806 | textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter); |
| 807 | @ <br /> |
| 808 | @ <input type="submit" name="submit" value="Apply Changes"> |
| 809 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -286,10 +286,11 @@ | |
| 286 | @ |
| 287 | @ <p><a href="setup_uedit?id=%d(uid))>[Bummer]</a></p> |
| 288 | style_footer(); |
| 289 | return; |
| 290 | } |
| 291 | login_verify_csrf_secret(); |
| 292 | db_multi_exec( |
| 293 | "REPLACE INTO user(uid,login,info,pw,cap) " |
| 294 | "VALUES(nullif(%d,0),%Q,%Q,%Q,'%s')", |
| 295 | uid, P("login"), P("info"), zPw, zCap |
| 296 | ); |
| @@ -340,10 +341,11 @@ | |
| 341 | }else{ |
| 342 | style_header("Add A New User"); |
| 343 | } |
| 344 | @ <table align="left" hspace="20" vspace="10"><tr><td> |
| 345 | @ <form action="%s(g.zPath)" method="POST"> |
| 346 | login_insert_csrf_secret(); |
| 347 | @ <table> |
| 348 | @ <tr> |
| 349 | @ <td align="right"><nobr>User ID:</nobr></td> |
| 350 | if( uid ){ |
| 351 | @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)"></td> |
| @@ -543,10 +545,11 @@ | |
| 545 | zQ = "off"; |
| 546 | } |
| 547 | if( zQ ){ |
| 548 | int iQ = strcmp(zQ,"on")==0 || atoi(zQ); |
| 549 | if( iQ!=iVal ){ |
| 550 | login_verify_csrf_secret(); |
| 551 | db_set(zVar, iQ ? "1" : "0", 0); |
| 552 | iVal = iQ; |
| 553 | } |
| 554 | } |
| 555 | if( iVal ){ |
| @@ -567,10 +570,11 @@ | |
| 570 | char *zDflt /* Default value if VAR table entry does not exist */ |
| 571 | ){ |
| 572 | const char *zVal = db_get(zVar, zDflt); |
| 573 | const char *zQ = P(zQParm); |
| 574 | if( zQ && strcmp(zQ,zVal)!=0 ){ |
| 575 | login_verify_csrf_secret(); |
| 576 | db_set(zVar, zQ, 0); |
| 577 | zVal = zQ; |
| 578 | } |
| 579 | @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)"> |
| 580 | @ <b>%s(zLabel)</b> |
| @@ -588,10 +592,11 @@ | |
| 592 | const char *zDflt /* Default value if VAR table entry does not exist */ |
| 593 | ){ |
| 594 | const char *z = db_get(zVar, (char*)zDflt); |
| 595 | const char *zQ = P(zQP); |
| 596 | if( zQ && strcmp(zQ,z)!=0 ){ |
| 597 | login_verify_csrf_secret(); |
| 598 | db_set(zVar, zQ, 0); |
| 599 | z = zQ; |
| 600 | } |
| 601 | if( rows>0 && cols>0 ){ |
| 602 | @ <textarea name="%s(zQP)" rows="%d(rows)" cols="%d(cols)">%h(z)</textarea> |
| @@ -610,11 +615,11 @@ | |
| 615 | } |
| 616 | |
| 617 | style_header("Access Control Settings"); |
| 618 | db_begin_transaction(); |
| 619 | @ <form action="%s(g.zBaseURL)/setup_access" method="POST"> |
| 620 | login_insert_csrf_secret(); |
| 621 | @ <hr> |
| 622 | onoff_attribute("Require password for local access", |
| 623 | "localauth", "localauth", 1); |
| 624 | @ <p>When enabled, the password sign-in is required for |
| 625 | @ web access coming from 127.0.0.1. When disabled, web access |
| @@ -661,10 +666,11 @@ | |
| 666 | } |
| 667 | |
| 668 | style_header("Timeline Display Preferences"); |
| 669 | db_begin_transaction(); |
| 670 | @ <form action="%s(g.zBaseURL)/setup_timeline" method="POST"> |
| 671 | login_insert_csrf_secret(); |
| 672 | |
| 673 | @ <hr> |
| 674 | onoff_attribute("Block markup in timeline", |
| 675 | "timeline-block-markup", "tbm", 0); |
| 676 | @ <p>In timeline displays, check-in comments can be displayed with or |
| @@ -693,10 +699,11 @@ | |
| 699 | } |
| 700 | |
| 701 | style_header("WWW Configuration"); |
| 702 | db_begin_transaction(); |
| 703 | @ <form action="%s(g.zBaseURL)/setup_config" method="POST"> |
| 704 | login_insert_csrf_secret(); |
| 705 | @ <hr /> |
| 706 | entry_attribute("Project Name", 60, "project-name", "pn", ""); |
| 707 | @ <p>Give your project a name so visitors know what this site is about. |
| 708 | @ The project name will also be used as the RSS feed title.</p> |
| 709 | @ <hr /> |
| @@ -735,10 +742,11 @@ | |
| 742 | if( !g.okSetup ){ |
| 743 | login_needed(); |
| 744 | } |
| 745 | style_header("Edit CSS"); |
| 746 | @ <form action="%s(g.zBaseURL)/setup_editcss" method="POST"> |
| 747 | login_insert_csrf_secret(); |
| 748 | @ Edit the CSS:<br /> |
| 749 | textarea_attribute("", 40, 80, "css", "css", zDefaultCSS); |
| 750 | @ <br /> |
| 751 | @ <input type="submit" name="submit" value="Apply Changes"> |
| 752 | @ </form> |
| @@ -765,10 +773,11 @@ | |
| 773 | }else{ |
| 774 | textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader); |
| 775 | } |
| 776 | style_header("Edit Page Header"); |
| 777 | @ <form action="%s(g.zBaseURL)/setup_header" method="POST"> |
| 778 | login_insert_csrf_secret(); |
| 779 | @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to |
| 780 | @ generate the beginning of every page through start of the main |
| 781 | @ menu.</p> |
| 782 | textarea_attribute("", 40, 80, "header", "header", zDefaultHeader); |
| 783 | @ <br /> |
| @@ -799,10 +808,11 @@ | |
| 808 | }else{ |
| 809 | textarea_attribute(0, 0, 0, "footer", "footer", zDefaultFooter); |
| 810 | } |
| 811 | style_header("Edit Page Footer"); |
| 812 | @ <form action="%s(g.zBaseURL)/setup_footer" method="POST"> |
| 813 | login_insert_csrf_secret(); |
| 814 | @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to |
| 815 | @ generate the end of every page.</p> |
| 816 | textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter); |
| 817 | @ <br /> |
| 818 | @ <input type="submit" name="submit" value="Apply Changes"> |
| 819 |
+4
| --- src/shun.c | ||
| +++ src/shun.c | ||
| @@ -65,10 +65,11 @@ | ||
| 65 | 65 | zUuid = zCanonical; |
| 66 | 66 | } |
| 67 | 67 | } |
| 68 | 68 | style_header("Shunned Artifacts"); |
| 69 | 69 | if( zUuid && P("sub") ){ |
| 70 | + login_verify_csrf_secret(); | |
| 70 | 71 | db_multi_exec("DELETE FROM shun WHERE uuid='%s'", zUuid); |
| 71 | 72 | if( db_exists("SELECT 1 FROM blob WHERE uuid='%s'", zUuid) ){ |
| 72 | 73 | @ <p><font color="blue">Artifact |
| 73 | 74 | @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> is no |
| 74 | 75 | @ longer being shunned.</font></p> |
| @@ -79,10 +80,11 @@ | ||
| 79 | 80 | @ <b>fossil rebuild</b> command-line before the artifact content |
| 80 | 81 | @ can pulled in from other respositories.</font></p> |
| 81 | 82 | } |
| 82 | 83 | } |
| 83 | 84 | if( zUuid && P("add") ){ |
| 85 | + login_verify_csrf_secret(); | |
| 84 | 86 | db_multi_exec("INSERT OR IGNORE INTO shun VALUES('%s')", zUuid); |
| 85 | 87 | @ <p><font color="blue">Artifact |
| 86 | 88 | @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> has been |
| 87 | 89 | @ shunned. It will no longer be pushed. |
| 88 | 90 | @ It will be removed from the repository the next time the respository |
| @@ -124,10 +126,11 @@ | ||
| 124 | 126 | @ of the repository. Do not shun artifacts merely to remove them from |
| 125 | 127 | @ sight - set the "hidden" tag on such artifacts instead.</p> |
| 126 | 128 | @ |
| 127 | 129 | @ <blockquote> |
| 128 | 130 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 131 | + login_insert_csrf_secret(); | |
| 129 | 132 | @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50"> |
| 130 | 133 | @ <input type="submit" name="add" value="Shun"> |
| 131 | 134 | @ </form> |
| 132 | 135 | @ </blockquote> |
| 133 | 136 | @ |
| @@ -137,10 +140,11 @@ | ||
| 137 | 140 | @ the formerly shunned artifact will be accepted on subsequent sync |
| 138 | 141 | @ operations.</p> |
| 139 | 142 | @ |
| 140 | 143 | @ <blockquote> |
| 141 | 144 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 145 | + login_insert_csrf_secret(); | |
| 142 | 146 | @ <input type="text" name="uuid" size="50"> |
| 143 | 147 | @ <input type="submit" name="sub" value="Accept"> |
| 144 | 148 | @ </form> |
| 145 | 149 | @ </blockquote> |
| 146 | 150 | style_footer(); |
| 147 | 151 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -65,10 +65,11 @@ | |
| 65 | zUuid = zCanonical; |
| 66 | } |
| 67 | } |
| 68 | style_header("Shunned Artifacts"); |
| 69 | if( zUuid && P("sub") ){ |
| 70 | db_multi_exec("DELETE FROM shun WHERE uuid='%s'", zUuid); |
| 71 | if( db_exists("SELECT 1 FROM blob WHERE uuid='%s'", zUuid) ){ |
| 72 | @ <p><font color="blue">Artifact |
| 73 | @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> is no |
| 74 | @ longer being shunned.</font></p> |
| @@ -79,10 +80,11 @@ | |
| 79 | @ <b>fossil rebuild</b> command-line before the artifact content |
| 80 | @ can pulled in from other respositories.</font></p> |
| 81 | } |
| 82 | } |
| 83 | if( zUuid && P("add") ){ |
| 84 | db_multi_exec("INSERT OR IGNORE INTO shun VALUES('%s')", zUuid); |
| 85 | @ <p><font color="blue">Artifact |
| 86 | @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> has been |
| 87 | @ shunned. It will no longer be pushed. |
| 88 | @ It will be removed from the repository the next time the respository |
| @@ -124,10 +126,11 @@ | |
| 124 | @ of the repository. Do not shun artifacts merely to remove them from |
| 125 | @ sight - set the "hidden" tag on such artifacts instead.</p> |
| 126 | @ |
| 127 | @ <blockquote> |
| 128 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 129 | @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50"> |
| 130 | @ <input type="submit" name="add" value="Shun"> |
| 131 | @ </form> |
| 132 | @ </blockquote> |
| 133 | @ |
| @@ -137,10 +140,11 @@ | |
| 137 | @ the formerly shunned artifact will be accepted on subsequent sync |
| 138 | @ operations.</p> |
| 139 | @ |
| 140 | @ <blockquote> |
| 141 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 142 | @ <input type="text" name="uuid" size="50"> |
| 143 | @ <input type="submit" name="sub" value="Accept"> |
| 144 | @ </form> |
| 145 | @ </blockquote> |
| 146 | style_footer(); |
| 147 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -65,10 +65,11 @@ | |
| 65 | zUuid = zCanonical; |
| 66 | } |
| 67 | } |
| 68 | style_header("Shunned Artifacts"); |
| 69 | if( zUuid && P("sub") ){ |
| 70 | login_verify_csrf_secret(); |
| 71 | db_multi_exec("DELETE FROM shun WHERE uuid='%s'", zUuid); |
| 72 | if( db_exists("SELECT 1 FROM blob WHERE uuid='%s'", zUuid) ){ |
| 73 | @ <p><font color="blue">Artifact |
| 74 | @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> is no |
| 75 | @ longer being shunned.</font></p> |
| @@ -79,10 +80,11 @@ | |
| 80 | @ <b>fossil rebuild</b> command-line before the artifact content |
| 81 | @ can pulled in from other respositories.</font></p> |
| 82 | } |
| 83 | } |
| 84 | if( zUuid && P("add") ){ |
| 85 | login_verify_csrf_secret(); |
| 86 | db_multi_exec("INSERT OR IGNORE INTO shun VALUES('%s')", zUuid); |
| 87 | @ <p><font color="blue">Artifact |
| 88 | @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> has been |
| 89 | @ shunned. It will no longer be pushed. |
| 90 | @ It will be removed from the repository the next time the respository |
| @@ -124,10 +126,11 @@ | |
| 126 | @ of the repository. Do not shun artifacts merely to remove them from |
| 127 | @ sight - set the "hidden" tag on such artifacts instead.</p> |
| 128 | @ |
| 129 | @ <blockquote> |
| 130 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 131 | login_insert_csrf_secret(); |
| 132 | @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50"> |
| 133 | @ <input type="submit" name="add" value="Shun"> |
| 134 | @ </form> |
| 135 | @ </blockquote> |
| 136 | @ |
| @@ -137,10 +140,11 @@ | |
| 140 | @ the formerly shunned artifact will be accepted on subsequent sync |
| 141 | @ operations.</p> |
| 142 | @ |
| 143 | @ <blockquote> |
| 144 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 145 | login_insert_csrf_secret(); |
| 146 | @ <input type="text" name="uuid" size="50"> |
| 147 | @ <input type="submit" name="sub" value="Accept"> |
| 148 | @ </form> |
| 149 | @ </blockquote> |
| 150 | style_footer(); |
| 151 |
+3
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -384,10 +384,11 @@ | ||
| 384 | 384 | const char *zUuid; |
| 385 | 385 | int i; |
| 386 | 386 | int rid; |
| 387 | 387 | Blob tktchng, cksum; |
| 388 | 388 | |
| 389 | + login_verify_csrf_secret(); | |
| 389 | 390 | zUuid = (const char *)pUuid; |
| 390 | 391 | blob_zero(&tktchng); |
| 391 | 392 | zDate = db_text(0, "SELECT datetime('now')"); |
| 392 | 393 | zDate[10] = 'T'; |
| 393 | 394 | blob_appendf(&tktchng, "D %s\n", zDate); |
| @@ -467,10 +468,11 @@ | ||
| 467 | 468 | ticket_init(); |
| 468 | 469 | getAllTicketFields(); |
| 469 | 470 | initializeVariablesFromDb(); |
| 470 | 471 | initializeVariablesFromCGI(); |
| 471 | 472 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 473 | + login_insert_csrf_secret(); | |
| 472 | 474 | zScript = ticket_newpage_code(); |
| 473 | 475 | Th_Store("login", g.zLogin); |
| 474 | 476 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 475 | 477 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, |
| 476 | 478 | (void*)&zNewUuid, 0); |
| @@ -528,10 +530,11 @@ | ||
| 528 | 530 | getAllTicketFields(); |
| 529 | 531 | initializeVariablesFromCGI(); |
| 530 | 532 | initializeVariablesFromDb(); |
| 531 | 533 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 532 | 534 | @ <input type="hidden" name="name" value="%s(zName)"> |
| 535 | + login_insert_csrf_secret(); | |
| 533 | 536 | zScript = ticket_editpage_code(); |
| 534 | 537 | Th_Store("login", g.zLogin); |
| 535 | 538 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 536 | 539 | Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); |
| 537 | 540 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); |
| 538 | 541 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -384,10 +384,11 @@ | |
| 384 | const char *zUuid; |
| 385 | int i; |
| 386 | int rid; |
| 387 | Blob tktchng, cksum; |
| 388 | |
| 389 | zUuid = (const char *)pUuid; |
| 390 | blob_zero(&tktchng); |
| 391 | zDate = db_text(0, "SELECT datetime('now')"); |
| 392 | zDate[10] = 'T'; |
| 393 | blob_appendf(&tktchng, "D %s\n", zDate); |
| @@ -467,10 +468,11 @@ | |
| 467 | ticket_init(); |
| 468 | getAllTicketFields(); |
| 469 | initializeVariablesFromDb(); |
| 470 | initializeVariablesFromCGI(); |
| 471 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 472 | zScript = ticket_newpage_code(); |
| 473 | Th_Store("login", g.zLogin); |
| 474 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 475 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, |
| 476 | (void*)&zNewUuid, 0); |
| @@ -528,10 +530,11 @@ | |
| 528 | getAllTicketFields(); |
| 529 | initializeVariablesFromCGI(); |
| 530 | initializeVariablesFromDb(); |
| 531 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 532 | @ <input type="hidden" name="name" value="%s(zName)"> |
| 533 | zScript = ticket_editpage_code(); |
| 534 | Th_Store("login", g.zLogin); |
| 535 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 536 | Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); |
| 537 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); |
| 538 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -384,10 +384,11 @@ | |
| 384 | const char *zUuid; |
| 385 | int i; |
| 386 | int rid; |
| 387 | Blob tktchng, cksum; |
| 388 | |
| 389 | login_verify_csrf_secret(); |
| 390 | zUuid = (const char *)pUuid; |
| 391 | blob_zero(&tktchng); |
| 392 | zDate = db_text(0, "SELECT datetime('now')"); |
| 393 | zDate[10] = 'T'; |
| 394 | blob_appendf(&tktchng, "D %s\n", zDate); |
| @@ -467,10 +468,11 @@ | |
| 468 | ticket_init(); |
| 469 | getAllTicketFields(); |
| 470 | initializeVariablesFromDb(); |
| 471 | initializeVariablesFromCGI(); |
| 472 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 473 | login_insert_csrf_secret(); |
| 474 | zScript = ticket_newpage_code(); |
| 475 | Th_Store("login", g.zLogin); |
| 476 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 477 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, |
| 478 | (void*)&zNewUuid, 0); |
| @@ -528,10 +530,11 @@ | |
| 530 | getAllTicketFields(); |
| 531 | initializeVariablesFromCGI(); |
| 532 | initializeVariablesFromDb(); |
| 533 | @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> |
| 534 | @ <input type="hidden" name="name" value="%s(zName)"> |
| 535 | login_insert_csrf_secret(); |
| 536 | zScript = ticket_editpage_code(); |
| 537 | Th_Store("login", g.zLogin); |
| 538 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 539 | Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); |
| 540 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); |
| 541 |
+4
| --- src/tktsetup.c | ||
| +++ src/tktsetup.c | ||
| @@ -119,24 +119,27 @@ | ||
| 119 | 119 | if( z==0 ){ |
| 120 | 120 | z = db_get(zDbField, (char*)zDfltValue); |
| 121 | 121 | } |
| 122 | 122 | style_header("Edit %s", zTitle); |
| 123 | 123 | if( P("clear")!=0 ){ |
| 124 | + login_verify_csrf_secret(); | |
| 124 | 125 | db_unset(zDbField, 0); |
| 125 | 126 | if( xRebuild ) xRebuild(); |
| 126 | 127 | z = zDfltValue; |
| 127 | 128 | }else if( isSubmit ){ |
| 128 | 129 | char *zErr = 0; |
| 130 | + login_verify_csrf_secret(); | |
| 129 | 131 | if( xText && (zErr = xText(z))!=0 ){ |
| 130 | 132 | @ <p><font color="red"><b>ERROR: %h(zErr)</b></font></p> |
| 131 | 133 | }else{ |
| 132 | 134 | db_set(zDbField, z, 0); |
| 133 | 135 | if( xRebuild ) xRebuild(); |
| 134 | 136 | cgi_redirect("tktsetup"); |
| 135 | 137 | } |
| 136 | 138 | } |
| 137 | 139 | @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="POST"> |
| 140 | + login_insert_csrf_secret(); | |
| 138 | 141 | @ <p>%s(zDesc)</p> |
| 139 | 142 | @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea> |
| 140 | 143 | @ <blockquote> |
| 141 | 144 | @ <input type="submit" name="submit" value="Apply Changes"> |
| 142 | 145 | @ <input type="submit" name="clear" value="Revert To Default"> |
| @@ -634,10 +637,11 @@ | ||
| 634 | 637 | cgi_redirect("tktsetup"); |
| 635 | 638 | } |
| 636 | 639 | style_header("Ticket Display On Timelines"); |
| 637 | 640 | db_begin_transaction(); |
| 638 | 641 | @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="POST"> |
| 642 | + login_insert_csrf_secret(); | |
| 639 | 643 | |
| 640 | 644 | @ <hr> |
| 641 | 645 | entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title"); |
| 642 | 646 | @ <p>An SQL expression in a query against the TICKET table that will |
| 643 | 647 | @ return the title of the ticket for display purposes after hyperlinks to |
| 644 | 648 |
| --- src/tktsetup.c | |
| +++ src/tktsetup.c | |
| @@ -119,24 +119,27 @@ | |
| 119 | if( z==0 ){ |
| 120 | z = db_get(zDbField, (char*)zDfltValue); |
| 121 | } |
| 122 | style_header("Edit %s", zTitle); |
| 123 | if( P("clear")!=0 ){ |
| 124 | db_unset(zDbField, 0); |
| 125 | if( xRebuild ) xRebuild(); |
| 126 | z = zDfltValue; |
| 127 | }else if( isSubmit ){ |
| 128 | char *zErr = 0; |
| 129 | if( xText && (zErr = xText(z))!=0 ){ |
| 130 | @ <p><font color="red"><b>ERROR: %h(zErr)</b></font></p> |
| 131 | }else{ |
| 132 | db_set(zDbField, z, 0); |
| 133 | if( xRebuild ) xRebuild(); |
| 134 | cgi_redirect("tktsetup"); |
| 135 | } |
| 136 | } |
| 137 | @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="POST"> |
| 138 | @ <p>%s(zDesc)</p> |
| 139 | @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea> |
| 140 | @ <blockquote> |
| 141 | @ <input type="submit" name="submit" value="Apply Changes"> |
| 142 | @ <input type="submit" name="clear" value="Revert To Default"> |
| @@ -634,10 +637,11 @@ | |
| 634 | cgi_redirect("tktsetup"); |
| 635 | } |
| 636 | style_header("Ticket Display On Timelines"); |
| 637 | db_begin_transaction(); |
| 638 | @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="POST"> |
| 639 | |
| 640 | @ <hr> |
| 641 | entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title"); |
| 642 | @ <p>An SQL expression in a query against the TICKET table that will |
| 643 | @ return the title of the ticket for display purposes after hyperlinks to |
| 644 |
| --- src/tktsetup.c | |
| +++ src/tktsetup.c | |
| @@ -119,24 +119,27 @@ | |
| 119 | if( z==0 ){ |
| 120 | z = db_get(zDbField, (char*)zDfltValue); |
| 121 | } |
| 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><font color="red"><b>ERROR: %h(zErr)</b></font></p> |
| 133 | }else{ |
| 134 | db_set(zDbField, z, 0); |
| 135 | if( xRebuild ) xRebuild(); |
| 136 | cgi_redirect("tktsetup"); |
| 137 | } |
| 138 | } |
| 139 | @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="POST"> |
| 140 | login_insert_csrf_secret(); |
| 141 | @ <p>%s(zDesc)</p> |
| 142 | @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea> |
| 143 | @ <blockquote> |
| 144 | @ <input type="submit" name="submit" value="Apply Changes"> |
| 145 | @ <input type="submit" name="clear" value="Revert To Default"> |
| @@ -634,10 +637,11 @@ | |
| 637 | cgi_redirect("tktsetup"); |
| 638 | } |
| 639 | style_header("Ticket Display On Timelines"); |
| 640 | db_begin_transaction(); |
| 641 | @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="POST"> |
| 642 | login_insert_csrf_secret(); |
| 643 | |
| 644 | @ <hr> |
| 645 | entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title"); |
| 646 | @ <p>An SQL expression in a query against the TICKET table that will |
| 647 | @ return the title of the ticket for display purposes after hyperlinks to |
| 648 |
+4
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -251,10 +251,11 @@ | ||
| 251 | 251 | blob_zero(&wiki); |
| 252 | 252 | db_begin_transaction(); |
| 253 | 253 | if( isSandbox ){ |
| 254 | 254 | db_set("sandbox",zBody,0); |
| 255 | 255 | }else{ |
| 256 | + login_verify_csrf_secret(); | |
| 256 | 257 | zDate = db_text(0, "SELECT datetime('now')"); |
| 257 | 258 | zDate[10] = 'T'; |
| 258 | 259 | blob_appendf(&wiki, "D %s\n", zDate); |
| 259 | 260 | free(zDate); |
| 260 | 261 | blob_appendf(&wiki, "L %F\n", zPageName); |
| @@ -300,10 +301,11 @@ | ||
| 300 | 301 | if( z[0]=='\n' ) n++; |
| 301 | 302 | } |
| 302 | 303 | if( n<20 ) n = 20; |
| 303 | 304 | if( n>40 ) n = 40; |
| 304 | 305 | @ <form method="POST" action="%s(g.zBaseURL)/wikiedit"> |
| 306 | + login_insert_csrf_secret(); | |
| 305 | 307 | @ <input type="hidden" name="name" value="%h(zPageName)"> |
| 306 | 308 | @ <textarea name="w" class="wikiedit" cols="80" |
| 307 | 309 | @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> |
| 308 | 310 | @ <br> |
| 309 | 311 | @ <input type="submit" name="preview" value="Preview Your Changes"> |
| @@ -384,10 +386,11 @@ | ||
| 384 | 386 | if( isSandbox ){ |
| 385 | 387 | blob_appendf(&body, db_get("sandbox","")); |
| 386 | 388 | appendRemark(&body); |
| 387 | 389 | db_set("sandbox", blob_str(&body), 0); |
| 388 | 390 | }else{ |
| 391 | + login_verify_csrf_secret(); | |
| 389 | 392 | content_get(rid, &content); |
| 390 | 393 | manifest_parse(&m, &content); |
| 391 | 394 | if( m.type==CFTYPE_WIKI ){ |
| 392 | 395 | blob_append(&body, m.zWiki, -1); |
| 393 | 396 | } |
| @@ -435,10 +438,11 @@ | ||
| 435 | 438 | @ <hr> |
| 436 | 439 | blob_reset(&preview); |
| 437 | 440 | } |
| 438 | 441 | zUser = PD("u", g.zLogin); |
| 439 | 442 | @ <form method="POST" action="%s(g.zBaseURL)/wikiappend"> |
| 443 | + login_insert_csrf_secret(); | |
| 440 | 444 | @ <input type="hidden" name="name" value="%h(zPageName)"> |
| 441 | 445 | @ Your Name: |
| 442 | 446 | @ <input type="text" name="u" size="20" value="%h(zUser)"><br> |
| 443 | 447 | @ Comment to append:<br> |
| 444 | 448 | @ <textarea name="r" class="wikiedit" cols="80" |
| 445 | 449 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -251,10 +251,11 @@ | |
| 251 | blob_zero(&wiki); |
| 252 | db_begin_transaction(); |
| 253 | if( isSandbox ){ |
| 254 | db_set("sandbox",zBody,0); |
| 255 | }else{ |
| 256 | zDate = db_text(0, "SELECT datetime('now')"); |
| 257 | zDate[10] = 'T'; |
| 258 | blob_appendf(&wiki, "D %s\n", zDate); |
| 259 | free(zDate); |
| 260 | blob_appendf(&wiki, "L %F\n", zPageName); |
| @@ -300,10 +301,11 @@ | |
| 300 | if( z[0]=='\n' ) n++; |
| 301 | } |
| 302 | if( n<20 ) n = 20; |
| 303 | if( n>40 ) n = 40; |
| 304 | @ <form method="POST" action="%s(g.zBaseURL)/wikiedit"> |
| 305 | @ <input type="hidden" name="name" value="%h(zPageName)"> |
| 306 | @ <textarea name="w" class="wikiedit" cols="80" |
| 307 | @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> |
| 308 | @ <br> |
| 309 | @ <input type="submit" name="preview" value="Preview Your Changes"> |
| @@ -384,10 +386,11 @@ | |
| 384 | if( isSandbox ){ |
| 385 | blob_appendf(&body, db_get("sandbox","")); |
| 386 | appendRemark(&body); |
| 387 | db_set("sandbox", blob_str(&body), 0); |
| 388 | }else{ |
| 389 | content_get(rid, &content); |
| 390 | manifest_parse(&m, &content); |
| 391 | if( m.type==CFTYPE_WIKI ){ |
| 392 | blob_append(&body, m.zWiki, -1); |
| 393 | } |
| @@ -435,10 +438,11 @@ | |
| 435 | @ <hr> |
| 436 | blob_reset(&preview); |
| 437 | } |
| 438 | zUser = PD("u", g.zLogin); |
| 439 | @ <form method="POST" action="%s(g.zBaseURL)/wikiappend"> |
| 440 | @ <input type="hidden" name="name" value="%h(zPageName)"> |
| 441 | @ Your Name: |
| 442 | @ <input type="text" name="u" size="20" value="%h(zUser)"><br> |
| 443 | @ Comment to append:<br> |
| 444 | @ <textarea name="r" class="wikiedit" cols="80" |
| 445 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -251,10 +251,11 @@ | |
| 251 | blob_zero(&wiki); |
| 252 | db_begin_transaction(); |
| 253 | if( isSandbox ){ |
| 254 | db_set("sandbox",zBody,0); |
| 255 | }else{ |
| 256 | login_verify_csrf_secret(); |
| 257 | zDate = db_text(0, "SELECT datetime('now')"); |
| 258 | zDate[10] = 'T'; |
| 259 | blob_appendf(&wiki, "D %s\n", zDate); |
| 260 | free(zDate); |
| 261 | blob_appendf(&wiki, "L %F\n", zPageName); |
| @@ -300,10 +301,11 @@ | |
| 301 | if( z[0]=='\n' ) n++; |
| 302 | } |
| 303 | if( n<20 ) n = 20; |
| 304 | if( n>40 ) n = 40; |
| 305 | @ <form method="POST" action="%s(g.zBaseURL)/wikiedit"> |
| 306 | login_insert_csrf_secret(); |
| 307 | @ <input type="hidden" name="name" value="%h(zPageName)"> |
| 308 | @ <textarea name="w" class="wikiedit" cols="80" |
| 309 | @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> |
| 310 | @ <br> |
| 311 | @ <input type="submit" name="preview" value="Preview Your Changes"> |
| @@ -384,10 +386,11 @@ | |
| 386 | if( isSandbox ){ |
| 387 | blob_appendf(&body, db_get("sandbox","")); |
| 388 | appendRemark(&body); |
| 389 | db_set("sandbox", blob_str(&body), 0); |
| 390 | }else{ |
| 391 | login_verify_csrf_secret(); |
| 392 | content_get(rid, &content); |
| 393 | manifest_parse(&m, &content); |
| 394 | if( m.type==CFTYPE_WIKI ){ |
| 395 | blob_append(&body, m.zWiki, -1); |
| 396 | } |
| @@ -435,10 +438,11 @@ | |
| 438 | @ <hr> |
| 439 | blob_reset(&preview); |
| 440 | } |
| 441 | zUser = PD("u", g.zLogin); |
| 442 | @ <form method="POST" action="%s(g.zBaseURL)/wikiappend"> |
| 443 | login_insert_csrf_secret(); |
| 444 | @ <input type="hidden" name="name" value="%h(zPageName)"> |
| 445 | @ Your Name: |
| 446 | @ <input type="text" name="u" size="20" value="%h(zUser)"><br> |
| 447 | @ Comment to append:<br> |
| 448 | @ <textarea name="r" class="wikiedit" cols="80" |
| 449 |