Fossil SCM

Optionally require a CAPTCHA (controlled by Admin/Access) when a user who is not logged in tries to edit wiki, or a ticket, or an attachment.

drh 2012-11-21 00:51 trunk
Commit 82b8587a502f32e9e4a76a3312c55057bcfd1538
+8 -2
--- src/attach.c
+++ src/attach.c
@@ -236,10 +236,11 @@
236236
const char *aContent = P("f");
237237
const char *zName = PD("f:filename","unknown");
238238
const char *zTarget;
239239
const char *zTargetType;
240240
int szContent = atoi(PD("f:bytes","0"));
241
+ int goodCaptcha = 1;
241242
242243
if( P("cancel") ) cgi_redirect(zFrom);
243244
if( zPage && zTkt ) fossil_redirect_home();
244245
if( zPage==0 && zTkt==0 ) fossil_redirect_home();
245246
login_check_credentials();
@@ -264,11 +265,11 @@
264265
}
265266
if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop);
266267
if( P("cancel") ){
267268
cgi_redirect(zFrom);
268269
}
269
- if( P("ok") && szContent>0 ){
270
+ if( P("ok") && szContent>0 && (goodCaptcha = captcha_is_correct()) ){
270271
Blob content;
271272
Blob manifest;
272273
Blob cksum;
273274
char *zUUID;
274275
const char *zComment;
@@ -317,10 +318,13 @@
317318
assert( blob_is_reset(&manifest) );
318319
db_end_transaction(0);
319320
cgi_redirect(zFrom);
320321
}
321322
style_header("Add Attachment");
323
+ if( !goodCaptcha ){
324
+ @ <p class="generalError">Error: Incorrect security code.</p>
325
+ }
322326
@ <h2>Add Attachment To %s(zTargetType)</h2>
323327
form_begin("enctype='multipart/form-data'", "%R/attachadd");
324328
@ <div>
325329
@ File to Attach:
326330
@ <input type="file" name="f" size="60" /><br />
@@ -332,11 +336,13 @@
332336
@ <input type="hidden" name="page" value="%h(zPage)" />
333337
}
334338
@ <input type="hidden" name="from" value="%h(zFrom)" />
335339
@ <input type="submit" name="ok" value="Add Attachment" />
336340
@ <input type="submit" name="cancel" value="Cancel" />
337
- @ </div></form>
341
+ @ </div>
342
+ captcha_generate();
343
+ @ </form>
338344
style_footer();
339345
}
340346
341347
/*
342348
** WEBPAGE: ainfo
343349
--- src/attach.c
+++ src/attach.c
@@ -236,10 +236,11 @@
236 const char *aContent = P("f");
237 const char *zName = PD("f:filename","unknown");
238 const char *zTarget;
239 const char *zTargetType;
240 int szContent = atoi(PD("f:bytes","0"));
 
241
242 if( P("cancel") ) cgi_redirect(zFrom);
243 if( zPage && zTkt ) fossil_redirect_home();
244 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
245 login_check_credentials();
@@ -264,11 +265,11 @@
264 }
265 if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop);
266 if( P("cancel") ){
267 cgi_redirect(zFrom);
268 }
269 if( P("ok") && szContent>0 ){
270 Blob content;
271 Blob manifest;
272 Blob cksum;
273 char *zUUID;
274 const char *zComment;
@@ -317,10 +318,13 @@
317 assert( blob_is_reset(&manifest) );
318 db_end_transaction(0);
319 cgi_redirect(zFrom);
320 }
321 style_header("Add Attachment");
 
 
 
322 @ <h2>Add Attachment To %s(zTargetType)</h2>
323 form_begin("enctype='multipart/form-data'", "%R/attachadd");
324 @ <div>
325 @ File to Attach:
326 @ <input type="file" name="f" size="60" /><br />
@@ -332,11 +336,13 @@
332 @ <input type="hidden" name="page" value="%h(zPage)" />
333 }
334 @ <input type="hidden" name="from" value="%h(zFrom)" />
335 @ <input type="submit" name="ok" value="Add Attachment" />
336 @ <input type="submit" name="cancel" value="Cancel" />
337 @ </div></form>
 
 
338 style_footer();
339 }
340
341 /*
342 ** WEBPAGE: ainfo
343
--- src/attach.c
+++ src/attach.c
@@ -236,10 +236,11 @@
236 const char *aContent = P("f");
237 const char *zName = PD("f:filename","unknown");
238 const char *zTarget;
239 const char *zTargetType;
240 int szContent = atoi(PD("f:bytes","0"));
241 int goodCaptcha = 1;
242
243 if( P("cancel") ) cgi_redirect(zFrom);
244 if( zPage && zTkt ) fossil_redirect_home();
245 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
246 login_check_credentials();
@@ -264,11 +265,11 @@
265 }
266 if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop);
267 if( P("cancel") ){
268 cgi_redirect(zFrom);
269 }
270 if( P("ok") && szContent>0 && (goodCaptcha = captcha_is_correct()) ){
271 Blob content;
272 Blob manifest;
273 Blob cksum;
274 char *zUUID;
275 const char *zComment;
@@ -317,10 +318,13 @@
318 assert( blob_is_reset(&manifest) );
319 db_end_transaction(0);
320 cgi_redirect(zFrom);
321 }
322 style_header("Add Attachment");
323 if( !goodCaptcha ){
324 @ <p class="generalError">Error: Incorrect security code.</p>
325 }
326 @ <h2>Add Attachment To %s(zTargetType)</h2>
327 form_begin("enctype='multipart/form-data'", "%R/attachadd");
328 @ <div>
329 @ File to Attach:
330 @ <input type="file" name="f" size="60" /><br />
@@ -332,11 +336,13 @@
336 @ <input type="hidden" name="page" value="%h(zPage)" />
337 }
338 @ <input type="hidden" name="from" value="%h(zFrom)" />
339 @ <input type="submit" name="ok" value="Add Attachment" />
340 @ <input type="submit" name="cancel" value="Cancel" />
341 @ </div>
342 captcha_generate();
343 @ </form>
344 style_footer();
345 }
346
347 /*
348 ** WEBPAGE: ainfo
349
--- src/captcha.c
+++ src/captcha.c
@@ -438,5 +438,58 @@
438438
z = blob_buffer(&b);
439439
memcpy(zRes, z, 8);
440440
zRes[8] = 0;
441441
return zRes;
442442
}
443
+
444
+/*
445
+** Return true if a CAPTCHA is required.
446
+*/
447
+int captcha_needed(void){
448
+ if( g.zLogin!=0 ) return 0;
449
+ return db_get_boolean("require-captcha", 1);
450
+}
451
+
452
+/*
453
+** If a captcha is required but the correct captcha code is not supplied
454
+** in the query parameters, then return false (0).
455
+**
456
+** If no captcha is required or if the correct captcha is supplied, return
457
+** true (non-zero).
458
+*/
459
+int captcha_is_correct(void){
460
+ const char *zSeed;
461
+ const char *zEntered;
462
+ const char *zDecode;
463
+ if( !captcha_needed() ){
464
+ return 1; /* No captcha needed */
465
+ }
466
+ zSeed = P("captchaseed");
467
+ if( zSeed==0 ) return 0;
468
+ zEntered = P("captcha");
469
+ if( zEntered==0 || strlen(zEntered)!=8 ) return 0;
470
+ zDecode = captcha_decode((unsigned int)atoi(zSeed));
471
+ if( strcmp(zDecode,zEntered)!=0 ) return 0;
472
+ return 1;
473
+}
474
+
475
+/*
476
+** Generate a new CAPTCHA seed. Write it as a hidden variable named
477
+** "captchaseed". Then return the rendered captcha text.
478
+*/
479
+void captcha_generate(void){
480
+ unsigned int uSeed;
481
+ const char *zDecoded;
482
+ char *zCaptcha;
483
+
484
+ if( !captcha_needed() ) return;
485
+ uSeed = captcha_seed();
486
+ zDecoded = captcha_decode(uSeed);
487
+ zCaptcha = captcha_render(zDecoded);
488
+ @ <div class="captcha"><table class="captcha"><tr><td><pre>
489
+ @ %h(zCaptcha)
490
+ @ </pre>
491
+ @ Enter security code shown above:
492
+ @ <input type="hidden" name="captchaseed" value="%u(uSeed)" />
493
+ @ <input type="text" name="captcha" size=8 />
494
+ @ </td></tr></table></div>
495
+}
443496
--- src/captcha.c
+++ src/captcha.c
@@ -438,5 +438,58 @@
438 z = blob_buffer(&b);
439 memcpy(zRes, z, 8);
440 zRes[8] = 0;
441 return zRes;
442 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
--- src/captcha.c
+++ src/captcha.c
@@ -438,5 +438,58 @@
438 z = blob_buffer(&b);
439 memcpy(zRes, z, 8);
440 zRes[8] = 0;
441 return zRes;
442 }
443
444 /*
445 ** Return true if a CAPTCHA is required.
446 */
447 int captcha_needed(void){
448 if( g.zLogin!=0 ) return 0;
449 return db_get_boolean("require-captcha", 1);
450 }
451
452 /*
453 ** If a captcha is required but the correct captcha code is not supplied
454 ** in the query parameters, then return false (0).
455 **
456 ** If no captcha is required or if the correct captcha is supplied, return
457 ** true (non-zero).
458 */
459 int captcha_is_correct(void){
460 const char *zSeed;
461 const char *zEntered;
462 const char *zDecode;
463 if( !captcha_needed() ){
464 return 1; /* No captcha needed */
465 }
466 zSeed = P("captchaseed");
467 if( zSeed==0 ) return 0;
468 zEntered = P("captcha");
469 if( zEntered==0 || strlen(zEntered)!=8 ) return 0;
470 zDecode = captcha_decode((unsigned int)atoi(zSeed));
471 if( strcmp(zDecode,zEntered)!=0 ) return 0;
472 return 1;
473 }
474
475 /*
476 ** Generate a new CAPTCHA seed. Write it as a hidden variable named
477 ** "captchaseed". Then return the rendered captcha text.
478 */
479 void captcha_generate(void){
480 unsigned int uSeed;
481 const char *zDecoded;
482 char *zCaptcha;
483
484 if( !captcha_needed() ) return;
485 uSeed = captcha_seed();
486 zDecoded = captcha_decode(uSeed);
487 zCaptcha = captcha_render(zDecoded);
488 @ <div class="captcha"><table class="captcha"><tr><td><pre>
489 @ %h(zCaptcha)
490 @ </pre>
491 @ Enter security code shown above:
492 @ <input type="hidden" name="captchaseed" value="%u(uSeed)" />
493 @ <input type="text" name="captcha" size=8 />
494 @ </td></tr></table></div>
495 }
496
+7 -1
--- src/setup.c
+++ src/setup.c
@@ -934,10 +934,17 @@
934934
@ if it does, your server will end up computing diffs and annotations for
935935
@ every historical version of every file and creating ZIPs and tarballs of
936936
@ every historical check-in, which can use a lot of CPU and bandwidth
937937
@ even for relatively small projects.</p>
938938
939
+ @ <hr />
940
+ onoff_attribute("Require a CAPTCHA if not logged in",
941
+ "require-captcha", "reqcapt", 1);
942
+ @ <p>Require a CAPTCHA for edit operations (appending, creating, or
943
+ @ editing wiki or tickets or adding attachments to wiki or tickets)
944
+ @ for users who are not logged in.</p>
945
+
939946
@ <hr />
940947
entry_attribute("Public pages", 30, "public-pages",
941948
"pubpage", "");
942949
@ <p>A comma-separated list of glob patterns for pages that are accessible
943950
@ without needing a login and using the privileges given by the
@@ -944,11 +951,10 @@
944951
@ "Default privileges" setting below. Example use case: Set this field
945952
@ to "/doc/trunk/www/*" to give anonymous users read-only permission to the
946953
@ latest version of the embedded documentation in the www/ folder without
947954
@ allowing them to see the rest of the source code.
948955
@ </p>
949
-
950956
951957
@ <hr />
952958
onoff_attribute("Allow users to register themselves",
953959
"self-register", "selfregister", 0);
954960
@ <p>Allow users to register themselves through the HTTP UI.
955961
--- src/setup.c
+++ src/setup.c
@@ -934,10 +934,17 @@
934 @ if it does, your server will end up computing diffs and annotations for
935 @ every historical version of every file and creating ZIPs and tarballs of
936 @ every historical check-in, which can use a lot of CPU and bandwidth
937 @ even for relatively small projects.</p>
938
 
 
 
 
 
 
 
939 @ <hr />
940 entry_attribute("Public pages", 30, "public-pages",
941 "pubpage", "");
942 @ <p>A comma-separated list of glob patterns for pages that are accessible
943 @ without needing a login and using the privileges given by the
@@ -944,11 +951,10 @@
944 @ "Default privileges" setting below. Example use case: Set this field
945 @ to "/doc/trunk/www/*" to give anonymous users read-only permission to the
946 @ latest version of the embedded documentation in the www/ folder without
947 @ allowing them to see the rest of the source code.
948 @ </p>
949
950
951 @ <hr />
952 onoff_attribute("Allow users to register themselves",
953 "self-register", "selfregister", 0);
954 @ <p>Allow users to register themselves through the HTTP UI.
955
--- src/setup.c
+++ src/setup.c
@@ -934,10 +934,17 @@
934 @ if it does, your server will end up computing diffs and annotations for
935 @ every historical version of every file and creating ZIPs and tarballs of
936 @ every historical check-in, which can use a lot of CPU and bandwidth
937 @ even for relatively small projects.</p>
938
939 @ <hr />
940 onoff_attribute("Require a CAPTCHA if not logged in",
941 "require-captcha", "reqcapt", 1);
942 @ <p>Require a CAPTCHA for edit operations (appending, creating, or
943 @ editing wiki or tickets or adding attachments to wiki or tickets)
944 @ for users who are not logged in.</p>
945
946 @ <hr />
947 entry_attribute("Public pages", 30, "public-pages",
948 "pubpage", "");
949 @ <p>A comma-separated list of glob patterns for pages that are accessible
950 @ without needing a login and using the privileges given by the
@@ -944,11 +951,10 @@
951 @ "Default privileges" setting below. Example use case: Set this field
952 @ to "/doc/trunk/www/*" to give anonymous users read-only permission to the
953 @ latest version of the embedded documentation in the www/ folder without
954 @ allowing them to see the rest of the source code.
955 @ </p>
 
956
957 @ <hr />
958 onoff_attribute("Allow users to register themselves",
959 "self-register", "selfregister", 0);
960 @ <p>Allow users to register themselves through the HTTP UI.
961
--- src/style.c
+++ src/style.c
@@ -712,10 +712,11 @@
712712
@ margin-top: 10px;
713713
},
714714
{ "div.captcha",
715715
"captcha display options",
716716
@ text-align: center;
717
+ @ padding: 1ex;
717718
},
718719
{ "table.captcha",
719720
"format for the layout table, used for the captcha display",
720721
@ margin: auto;
721722
@ padding: 10px;
722723
--- src/style.c
+++ src/style.c
@@ -712,10 +712,11 @@
712 @ margin-top: 10px;
713 },
714 { "div.captcha",
715 "captcha display options",
716 @ text-align: center;
 
717 },
718 { "table.captcha",
719 "format for the layout table, used for the captcha display",
720 @ margin: auto;
721 @ padding: 10px;
722
--- src/style.c
+++ src/style.c
@@ -712,10 +712,11 @@
712 @ margin-top: 10px;
713 },
714 { "div.captcha",
715 "captcha display options",
716 @ text-align: center;
717 @ padding: 1ex;
718 },
719 { "table.captcha",
720 "format for the layout table, used for the captcha display",
721 @ margin: auto;
722 @ padding: 10px;
723
+8 -2
--- src/tkt.c
+++ src/tkt.c
@@ -430,10 +430,14 @@
430430
int i;
431431
int nJ = 0;
432432
Blob tktchng, cksum;
433433
434434
login_verify_csrf_secret();
435
+ if( !captcha_is_correct() ){
436
+ @ <p class="generalError">Error: Incorrect security code.</p>
437
+ return TH_OK;
438
+ }
435439
zUuid = (const char *)pUuid;
436440
blob_zero(&tktchng);
437441
zDate = date_in_standard_format("now");
438442
blob_appendf(&tktchng, "D %s\n", zDate);
439443
free(zDate);
@@ -529,19 +533,20 @@
529533
if( P("date_override") && g.perm.Setup ){
530534
@ <input type="hidden" name="date_override" value="%h(P("date_override"))">
531535
}
532536
@ </p>
533537
zScript = ticket_newpage_code();
534
- Th_Store("login", g.zLogin);
538
+ Th_Store("login", g.zLogin ? g.zLogin : "nobody");
535539
Th_Store("date", db_text(0, "SELECT datetime('now')"));
536540
Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd,
537541
(void*)&zNewUuid, 0);
538542
if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1);
539543
if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){
540544
cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid));
541545
return;
542546
}
547
+ captcha_generate();
543548
@ </form>
544549
if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
545550
style_footer();
546551
}
547552
@@ -596,19 +601,20 @@
596601
form_begin(0, "%R/%s", g.zPath);
597602
@ <input type="hidden" name="name" value="%s(zName)" />
598603
login_insert_csrf_secret();
599604
@ </p>
600605
zScript = ticket_editpage_code();
601
- Th_Store("login", g.zLogin);
606
+ Th_Store("login", g.zLogin ? g.zLogin : "nobody");
602607
Th_Store("date", db_text(0, "SELECT datetime('now')"));
603608
Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0);
604609
Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0);
605610
if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1);
606611
if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){
607612
cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName));
608613
return;
609614
}
615
+ captcha_generate();
610616
@ </form>
611617
if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
612618
style_footer();
613619
}
614620
615621
--- src/tkt.c
+++ src/tkt.c
@@ -430,10 +430,14 @@
430 int i;
431 int nJ = 0;
432 Blob tktchng, cksum;
433
434 login_verify_csrf_secret();
 
 
 
 
435 zUuid = (const char *)pUuid;
436 blob_zero(&tktchng);
437 zDate = date_in_standard_format("now");
438 blob_appendf(&tktchng, "D %s\n", zDate);
439 free(zDate);
@@ -529,19 +533,20 @@
529 if( P("date_override") && g.perm.Setup ){
530 @ <input type="hidden" name="date_override" value="%h(P("date_override"))">
531 }
532 @ </p>
533 zScript = ticket_newpage_code();
534 Th_Store("login", g.zLogin);
535 Th_Store("date", db_text(0, "SELECT datetime('now')"));
536 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd,
537 (void*)&zNewUuid, 0);
538 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1);
539 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){
540 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid));
541 return;
542 }
 
543 @ </form>
544 if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
545 style_footer();
546 }
547
@@ -596,19 +601,20 @@
596 form_begin(0, "%R/%s", g.zPath);
597 @ <input type="hidden" name="name" value="%s(zName)" />
598 login_insert_csrf_secret();
599 @ </p>
600 zScript = ticket_editpage_code();
601 Th_Store("login", g.zLogin);
602 Th_Store("date", db_text(0, "SELECT datetime('now')"));
603 Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0);
604 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0);
605 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1);
606 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){
607 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName));
608 return;
609 }
 
610 @ </form>
611 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
612 style_footer();
613 }
614
615
--- src/tkt.c
+++ src/tkt.c
@@ -430,10 +430,14 @@
430 int i;
431 int nJ = 0;
432 Blob tktchng, cksum;
433
434 login_verify_csrf_secret();
435 if( !captcha_is_correct() ){
436 @ <p class="generalError">Error: Incorrect security code.</p>
437 return TH_OK;
438 }
439 zUuid = (const char *)pUuid;
440 blob_zero(&tktchng);
441 zDate = date_in_standard_format("now");
442 blob_appendf(&tktchng, "D %s\n", zDate);
443 free(zDate);
@@ -529,19 +533,20 @@
533 if( P("date_override") && g.perm.Setup ){
534 @ <input type="hidden" name="date_override" value="%h(P("date_override"))">
535 }
536 @ </p>
537 zScript = ticket_newpage_code();
538 Th_Store("login", g.zLogin ? g.zLogin : "nobody");
539 Th_Store("date", db_text(0, "SELECT datetime('now')"));
540 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd,
541 (void*)&zNewUuid, 0);
542 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1);
543 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){
544 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid));
545 return;
546 }
547 captcha_generate();
548 @ </form>
549 if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
550 style_footer();
551 }
552
@@ -596,19 +601,20 @@
601 form_begin(0, "%R/%s", g.zPath);
602 @ <input type="hidden" name="name" value="%s(zName)" />
603 login_insert_csrf_secret();
604 @ </p>
605 zScript = ticket_editpage_code();
606 Th_Store("login", g.zLogin ? g.zLogin : "nobody");
607 Th_Store("date", db_text(0, "SELECT datetime('now')"));
608 Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0);
609 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0);
610 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1);
611 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){
612 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName));
613 return;
614 }
615 captcha_generate();
616 @ </form>
617 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
618 style_footer();
619 }
620
621
+19 -4
--- src/wiki.c
+++ src/wiki.c
@@ -263,10 +263,11 @@
263263
const char *zPageName;
264264
int n;
265265
const char *z;
266266
char *zBody = (char*)P("w");
267267
int isWysiwyg = P("wysiwyg")!=0;
268
+ int goodCaptcha = 1;
268269
269270
if( P("edit-wysiwyg")!=0 ){ isWysiwyg = 1; zBody = 0; }
270271
if( P("edit-markup")!=0 ){ isWysiwyg = 0; zBody = 0; }
271272
if( zBody ){
272273
if( isWysiwyg ){
@@ -304,11 +305,13 @@
304305
}
305306
if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
306307
zBody = pWiki->zWiki;
307308
}
308309
}
309
- if( P("submit")!=0 && zBody!=0 ){
310
+ if( P("submit")!=0 && zBody!=0
311
+ && (goodCaptcha = captcha_is_correct())
312
+ ){
310313
char *zDate;
311314
Blob cksum;
312315
blob_zero(&wiki);
313316
db_begin_transaction();
314317
if( isSandbox ){
@@ -343,10 +346,13 @@
343346
if( zBody==0 ){
344347
zBody = mprintf("<i>Empty Page</i>");
345348
}
346349
style_set_current_page("%s?name=%T", g.zPath, zPageName);
347350
style_header("Edit: %s", zPageName);
351
+ if( !goodCaptcha ){
352
+ @ <p class="generalError">Error: Incorrect security code.</p>
353
+ }
348354
blob_zero(&wiki);
349355
blob_append(&wiki, zBody, -1);
350356
if( P("preview")!=0 ){
351357
@ Preview:<hr />
352358
wiki_convert(&wiki, 0, 0);
@@ -385,16 +391,18 @@
385391
blob_reset(&html);
386392
@ <br />
387393
@ <input type="submit" name="edit-markup" value="Markup Editor"
388394
@ onclick='return confirm("Switching to markup-mode\nwill erase your WYSIWYG\nedits. Continue?")' />
389395
}
390
- @ <input type="submit" name="submit" value="Apply These Changes" />
391396
login_insert_csrf_secret();
397
+ @ <input type="submit" name="submit" value="Apply These Changes" />
392398
@ <input type="hidden" name="name" value="%h(zPageName)" />
393399
@ <input type="submit" name="cancel" value="Cancel"
394400
@ onclick='confirm("Abandon your changes?")' />
395
- @ </div></form>
401
+ @ </div>
402
+ captcha_generate();
403
+ @ </form>
396404
manifest_destroy(pWiki);
397405
blob_reset(&wiki);
398406
style_footer();
399407
}
400408
@@ -466,10 +474,11 @@
466474
char *zTag;
467475
int rid = 0;
468476
int isSandbox;
469477
const char *zPageName;
470478
const char *zUser;
479
+ int goodCaptcha = 1;
471480
472481
login_check_credentials();
473482
zPageName = PD("name","");
474483
if( check_name(zPageName) ) return;
475484
isSandbox = is_sandbox(zPageName);
@@ -488,11 +497,13 @@
488497
}
489498
if( !g.perm.ApndWiki ){
490499
login_needed();
491500
return;
492501
}
493
- if( P("submit")!=0 && P("r")!=0 && P("u")!=0 ){
502
+ if( P("submit")!=0 && P("r")!=0 && P("u")!=0
503
+ && (goodCaptcha = captcha_is_correct())
504
+ ){
494505
char *zDate;
495506
Blob cksum;
496507
Blob body;
497508
Blob wiki;
498509
Manifest *pWiki = 0;
@@ -536,10 +547,13 @@
536547
cgi_redirectf("wiki?name=%T", zPageName);
537548
return;
538549
}
539550
style_set_current_page("%s?name=%T", g.zPath, zPageName);
540551
style_header("Append Comment To: %s", zPageName);
552
+ if( !goodCaptcha ){
553
+ @ <p class="generalError">Error: Incorrect security code.</p>
554
+ }
541555
if( P("preview")!=0 ){
542556
Blob preview;
543557
blob_zero(&preview);
544558
appendRemark(&preview);
545559
@ Preview:<hr>
@@ -558,10 +572,11 @@
558572
@ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
559573
@ <br />
560574
@ <input type="submit" name="preview" value="Preview Your Comment" />
561575
@ <input type="submit" name="submit" value="Append Your Changes" />
562576
@ <input type="submit" name="cancel" value="Cancel" />
577
+ captcha_generate();
563578
@ </form>
564579
style_footer();
565580
}
566581
567582
/*
568583
--- src/wiki.c
+++ src/wiki.c
@@ -263,10 +263,11 @@
263 const char *zPageName;
264 int n;
265 const char *z;
266 char *zBody = (char*)P("w");
267 int isWysiwyg = P("wysiwyg")!=0;
 
268
269 if( P("edit-wysiwyg")!=0 ){ isWysiwyg = 1; zBody = 0; }
270 if( P("edit-markup")!=0 ){ isWysiwyg = 0; zBody = 0; }
271 if( zBody ){
272 if( isWysiwyg ){
@@ -304,11 +305,13 @@
304 }
305 if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
306 zBody = pWiki->zWiki;
307 }
308 }
309 if( P("submit")!=0 && zBody!=0 ){
 
 
310 char *zDate;
311 Blob cksum;
312 blob_zero(&wiki);
313 db_begin_transaction();
314 if( isSandbox ){
@@ -343,10 +346,13 @@
343 if( zBody==0 ){
344 zBody = mprintf("<i>Empty Page</i>");
345 }
346 style_set_current_page("%s?name=%T", g.zPath, zPageName);
347 style_header("Edit: %s", zPageName);
 
 
 
348 blob_zero(&wiki);
349 blob_append(&wiki, zBody, -1);
350 if( P("preview")!=0 ){
351 @ Preview:<hr />
352 wiki_convert(&wiki, 0, 0);
@@ -385,16 +391,18 @@
385 blob_reset(&html);
386 @ <br />
387 @ <input type="submit" name="edit-markup" value="Markup Editor"
388 @ onclick='return confirm("Switching to markup-mode\nwill erase your WYSIWYG\nedits. Continue?")' />
389 }
390 @ <input type="submit" name="submit" value="Apply These Changes" />
391 login_insert_csrf_secret();
 
392 @ <input type="hidden" name="name" value="%h(zPageName)" />
393 @ <input type="submit" name="cancel" value="Cancel"
394 @ onclick='confirm("Abandon your changes?")' />
395 @ </div></form>
 
 
396 manifest_destroy(pWiki);
397 blob_reset(&wiki);
398 style_footer();
399 }
400
@@ -466,10 +474,11 @@
466 char *zTag;
467 int rid = 0;
468 int isSandbox;
469 const char *zPageName;
470 const char *zUser;
 
471
472 login_check_credentials();
473 zPageName = PD("name","");
474 if( check_name(zPageName) ) return;
475 isSandbox = is_sandbox(zPageName);
@@ -488,11 +497,13 @@
488 }
489 if( !g.perm.ApndWiki ){
490 login_needed();
491 return;
492 }
493 if( P("submit")!=0 && P("r")!=0 && P("u")!=0 ){
 
 
494 char *zDate;
495 Blob cksum;
496 Blob body;
497 Blob wiki;
498 Manifest *pWiki = 0;
@@ -536,10 +547,13 @@
536 cgi_redirectf("wiki?name=%T", zPageName);
537 return;
538 }
539 style_set_current_page("%s?name=%T", g.zPath, zPageName);
540 style_header("Append Comment To: %s", zPageName);
 
 
 
541 if( P("preview")!=0 ){
542 Blob preview;
543 blob_zero(&preview);
544 appendRemark(&preview);
545 @ Preview:<hr>
@@ -558,10 +572,11 @@
558 @ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
559 @ <br />
560 @ <input type="submit" name="preview" value="Preview Your Comment" />
561 @ <input type="submit" name="submit" value="Append Your Changes" />
562 @ <input type="submit" name="cancel" value="Cancel" />
 
563 @ </form>
564 style_footer();
565 }
566
567 /*
568
--- src/wiki.c
+++ src/wiki.c
@@ -263,10 +263,11 @@
263 const char *zPageName;
264 int n;
265 const char *z;
266 char *zBody = (char*)P("w");
267 int isWysiwyg = P("wysiwyg")!=0;
268 int goodCaptcha = 1;
269
270 if( P("edit-wysiwyg")!=0 ){ isWysiwyg = 1; zBody = 0; }
271 if( P("edit-markup")!=0 ){ isWysiwyg = 0; zBody = 0; }
272 if( zBody ){
273 if( isWysiwyg ){
@@ -304,11 +305,13 @@
305 }
306 if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
307 zBody = pWiki->zWiki;
308 }
309 }
310 if( P("submit")!=0 && zBody!=0
311 && (goodCaptcha = captcha_is_correct())
312 ){
313 char *zDate;
314 Blob cksum;
315 blob_zero(&wiki);
316 db_begin_transaction();
317 if( isSandbox ){
@@ -343,10 +346,13 @@
346 if( zBody==0 ){
347 zBody = mprintf("<i>Empty Page</i>");
348 }
349 style_set_current_page("%s?name=%T", g.zPath, zPageName);
350 style_header("Edit: %s", zPageName);
351 if( !goodCaptcha ){
352 @ <p class="generalError">Error: Incorrect security code.</p>
353 }
354 blob_zero(&wiki);
355 blob_append(&wiki, zBody, -1);
356 if( P("preview")!=0 ){
357 @ Preview:<hr />
358 wiki_convert(&wiki, 0, 0);
@@ -385,16 +391,18 @@
391 blob_reset(&html);
392 @ <br />
393 @ <input type="submit" name="edit-markup" value="Markup Editor"
394 @ onclick='return confirm("Switching to markup-mode\nwill erase your WYSIWYG\nedits. Continue?")' />
395 }
 
396 login_insert_csrf_secret();
397 @ <input type="submit" name="submit" value="Apply These Changes" />
398 @ <input type="hidden" name="name" value="%h(zPageName)" />
399 @ <input type="submit" name="cancel" value="Cancel"
400 @ onclick='confirm("Abandon your changes?")' />
401 @ </div>
402 captcha_generate();
403 @ </form>
404 manifest_destroy(pWiki);
405 blob_reset(&wiki);
406 style_footer();
407 }
408
@@ -466,10 +474,11 @@
474 char *zTag;
475 int rid = 0;
476 int isSandbox;
477 const char *zPageName;
478 const char *zUser;
479 int goodCaptcha = 1;
480
481 login_check_credentials();
482 zPageName = PD("name","");
483 if( check_name(zPageName) ) return;
484 isSandbox = is_sandbox(zPageName);
@@ -488,11 +497,13 @@
497 }
498 if( !g.perm.ApndWiki ){
499 login_needed();
500 return;
501 }
502 if( P("submit")!=0 && P("r")!=0 && P("u")!=0
503 && (goodCaptcha = captcha_is_correct())
504 ){
505 char *zDate;
506 Blob cksum;
507 Blob body;
508 Blob wiki;
509 Manifest *pWiki = 0;
@@ -536,10 +547,13 @@
547 cgi_redirectf("wiki?name=%T", zPageName);
548 return;
549 }
550 style_set_current_page("%s?name=%T", g.zPath, zPageName);
551 style_header("Append Comment To: %s", zPageName);
552 if( !goodCaptcha ){
553 @ <p class="generalError">Error: Incorrect security code.</p>
554 }
555 if( P("preview")!=0 ){
556 Blob preview;
557 blob_zero(&preview);
558 appendRemark(&preview);
559 @ Preview:<hr>
@@ -558,10 +572,11 @@
572 @ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
573 @ <br />
574 @ <input type="submit" name="preview" value="Preview Your Comment" />
575 @ <input type="submit" name="submit" value="Append Your Changes" />
576 @ <input type="submit" name="cancel" value="Cancel" />
577 captcha_generate();
578 @ </form>
579 style_footer();
580 }
581
582 /*
583

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button