Fossil SCM

Spiders and robots are presented with a captcha if they request the annotation page.

drh 2013-08-25 02:11 trunk
Commit f8a2aa0ce7e372a25d8b9b48488005336039ce29
+1 -1
--- src/attach.c
+++ src/attach.c
@@ -337,11 +337,11 @@
337337
}
338338
@ <input type="hidden" name="from" value="%h(zFrom)" />
339339
@ <input type="submit" name="ok" value="Add Attachment" />
340340
@ <input type="submit" name="cancel" value="Cancel" />
341341
@ </div>
342
- captcha_generate();
342
+ captcha_generate(0);
343343
@ </form>
344344
style_footer();
345345
}
346346
347347
/*
348348
--- src/attach.c
+++ src/attach.c
@@ -337,11 +337,11 @@
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
--- src/attach.c
+++ src/attach.c
@@ -337,11 +337,11 @@
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(0);
343 @ </form>
344 style_footer();
345 }
346
347 /*
348
+42 -1
--- src/captcha.c
+++ src/captcha.c
@@ -529,11 +529,11 @@
529529
** for the seed and the entry box into which the user will type the text of
530530
** the captcha. This is typically done at the very bottom of a form.
531531
**
532532
** This routine is a no-op if no captcha is required.
533533
*/
534
-void captcha_generate(void){
534
+void captcha_generate(int showButton){
535535
unsigned int uSeed;
536536
const char *zDecoded;
537537
char *zCaptcha;
538538
539539
if( !captcha_needed() ) return;
@@ -544,10 +544,13 @@
544544
@ %h(zCaptcha)
545545
@ </pre>
546546
@ Enter security code shown above:
547547
@ <input type="hidden" name="captchaseed" value="%u(uSeed)" />
548548
@ <input type="text" name="captcha" size=8 />
549
+ if( showButton ){
550
+ @ <input type="submit" value="Submit">
551
+ }
549552
@ </td></tr></table></div>
550553
}
551554
552555
/*
553556
** WEBPAGE: test-captcha
@@ -563,5 +566,43 @@
563566
@ <pre>
564567
@ %s(captcha_render(zPw))
565568
@ </pre>
566569
style_footer();
567570
}
571
+
572
+/*
573
+** Check to see if the current request is coming from an agent that might
574
+** be a spider. If the agent is not a spider, then return 0 without doing
575
+** anything. But if the user agent appears to be a spider, offer
576
+** a captcha challenge to allow the user agent to prove that it is human
577
+** and return non-zero.
578
+*/
579
+int exclude_spiders(const char *zPage){
580
+ const char *zCookieValue;
581
+ char *zCookieName;
582
+ if( g.isHuman ) return 0;
583
+#if 0
584
+ {
585
+ const char *zReferer = P("HTTP_REFERER");
586
+ if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
587
+ return 0;
588
+ }
589
+ }
590
+#endif
591
+ zCookieName = mprintf("fossil-cc-%.10s", db_get("project-code","x"));
592
+ zCookieValue = P(zCookieName);
593
+ if( zCookieValue && atoi(zCookieValue)==1 ) return 0;
594
+ if( captcha_is_correct() ){
595
+ cgi_set_cookie(zCookieName, "1", login_cookie_path(), 8*3600);
596
+ return 0;
597
+ }
598
+
599
+ /* This appears to be a spider. Offer the captcha */
600
+ style_header("Verification");
601
+ form_begin(0, "%s", zPage);
602
+ cgi_query_parameters_to_hidden();
603
+ @ <p>Please demonstrate that you are human, not a spider or robot</p>
604
+ captcha_generate(1);
605
+ @ </form>
606
+ style_footer();
607
+ return 1;
608
+}
568609
--- src/captcha.c
+++ src/captcha.c
@@ -529,11 +529,11 @@
529 ** for the seed and the entry box into which the user will type the text of
530 ** the captcha. This is typically done at the very bottom of a form.
531 **
532 ** This routine is a no-op if no captcha is required.
533 */
534 void captcha_generate(void){
535 unsigned int uSeed;
536 const char *zDecoded;
537 char *zCaptcha;
538
539 if( !captcha_needed() ) return;
@@ -544,10 +544,13 @@
544 @ %h(zCaptcha)
545 @ </pre>
546 @ Enter security code shown above:
547 @ <input type="hidden" name="captchaseed" value="%u(uSeed)" />
548 @ <input type="text" name="captcha" size=8 />
 
 
 
549 @ </td></tr></table></div>
550 }
551
552 /*
553 ** WEBPAGE: test-captcha
@@ -563,5 +566,43 @@
563 @ <pre>
564 @ %s(captcha_render(zPw))
565 @ </pre>
566 style_footer();
567 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
--- src/captcha.c
+++ src/captcha.c
@@ -529,11 +529,11 @@
529 ** for the seed and the entry box into which the user will type the text of
530 ** the captcha. This is typically done at the very bottom of a form.
531 **
532 ** This routine is a no-op if no captcha is required.
533 */
534 void captcha_generate(int showButton){
535 unsigned int uSeed;
536 const char *zDecoded;
537 char *zCaptcha;
538
539 if( !captcha_needed() ) return;
@@ -544,10 +544,13 @@
544 @ %h(zCaptcha)
545 @ </pre>
546 @ Enter security code shown above:
547 @ <input type="hidden" name="captchaseed" value="%u(uSeed)" />
548 @ <input type="text" name="captcha" size=8 />
549 if( showButton ){
550 @ <input type="submit" value="Submit">
551 }
552 @ </td></tr></table></div>
553 }
554
555 /*
556 ** WEBPAGE: test-captcha
@@ -563,5 +566,43 @@
566 @ <pre>
567 @ %s(captcha_render(zPw))
568 @ </pre>
569 style_footer();
570 }
571
572 /*
573 ** Check to see if the current request is coming from an agent that might
574 ** be a spider. If the agent is not a spider, then return 0 without doing
575 ** anything. But if the user agent appears to be a spider, offer
576 ** a captcha challenge to allow the user agent to prove that it is human
577 ** and return non-zero.
578 */
579 int exclude_spiders(const char *zPage){
580 const char *zCookieValue;
581 char *zCookieName;
582 if( g.isHuman ) return 0;
583 #if 0
584 {
585 const char *zReferer = P("HTTP_REFERER");
586 if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
587 return 0;
588 }
589 }
590 #endif
591 zCookieName = mprintf("fossil-cc-%.10s", db_get("project-code","x"));
592 zCookieValue = P(zCookieName);
593 if( zCookieValue && atoi(zCookieValue)==1 ) return 0;
594 if( captcha_is_correct() ){
595 cgi_set_cookie(zCookieName, "1", login_cookie_path(), 8*3600);
596 return 0;
597 }
598
599 /* This appears to be a spider. Offer the captcha */
600 style_header("Verification");
601 form_begin(0, "%s", zPage);
602 cgi_query_parameters_to_hidden();
603 @ <p>Please demonstrate that you are human, not a spider or robot</p>
604 captcha_generate(1);
605 @ </form>
606 style_footer();
607 return 1;
608 }
609
+28 -10
--- src/cgi.c
+++ src/cgi.c
@@ -404,10 +404,11 @@
404404
static int seqQP = 0; /* Sequence numbers */
405405
static struct QParam { /* One entry for each query parameter or cookie */
406406
const char *zName; /* Parameter or cookie name */
407407
const char *zValue; /* Value of the query parameter or cookie */
408408
int seq; /* Order of insertion */
409
+ int isQP; /* True for query parameters */
409410
} *aParamQP; /* An array of all parameters and cookies */
410411
411412
/*
412413
** Add another query parameter or cookie to the parameter set.
413414
** zName is the name of the query parameter or cookie and zValue
@@ -414,11 +415,11 @@
414415
** is its fully decoded value.
415416
**
416417
** zName and zValue are not copied and must not change or be
417418
** deallocated after this routine returns.
418419
*/
419
-void cgi_set_parameter_nocopy(const char *zName, const char *zValue){
420
+void cgi_set_parameter_nocopy(const char *zName, const char *zValue, int isQP){
420421
if( nAllocQP<=nUsedQP ){
421422
nAllocQP = nAllocQP*2 + 10;
422423
if( nAllocQP>1000 ){
423424
/* Prevent a DOS service attack against the framework */
424425
fossil_fatal("Too many query parameters");
@@ -429,10 +430,11 @@
429430
aParamQP[nUsedQP].zValue = zValue;
430431
if( g.fHttpTrace ){
431432
fprintf(stderr, "# cgi: %s = [%s]\n", zName, zValue);
432433
}
433434
aParamQP[nUsedQP].seq = seqQP++;
435
+ aParamQP[nUsedQP].isQP = isQP;
434436
nUsedQP++;
435437
sortQP = 1;
436438
}
437439
438440
/*
@@ -441,11 +443,11 @@
441443
** is its fully decoded value.
442444
**
443445
** Copies are made of both the zName and zValue parameters.
444446
*/
445447
void cgi_set_parameter(const char *zName, const char *zValue){
446
- cgi_set_parameter_nocopy(mprintf("%s",zName), mprintf("%s",zValue));
448
+ cgi_set_parameter_nocopy(mprintf("%s",zName), mprintf("%s",zValue), 0);
447449
}
448450
449451
/*
450452
** Replace a parameter with a new value.
451453
*/
@@ -455,19 +457,19 @@
455457
if( fossil_strcmp(aParamQP[i].zName,zName)==0 ){
456458
aParamQP[i].zValue = zValue;
457459
return;
458460
}
459461
}
460
- cgi_set_parameter_nocopy(zName, zValue);
462
+ cgi_set_parameter_nocopy(zName, zValue, 0);
461463
}
462464
463465
/*
464466
** Add a query parameter. The zName portion is fixed but a copy
465467
** must be made of zValue.
466468
*/
467469
void cgi_setenv(const char *zName, const char *zValue){
468
- cgi_set_parameter_nocopy(zName, mprintf("%s",zValue));
470
+ cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
469471
}
470472
471473
472474
/*
473475
** Add a list of query parameters or cookies to the parameter set.
@@ -493,10 +495,11 @@
493495
** The input string "z" is modified but no copies is made. "z"
494496
** should not be deallocated or changed again after this routine
495497
** returns or it will corrupt the parameter table.
496498
*/
497499
static void add_param_list(char *z, int terminator){
500
+ int isQP = terminator=='&';
498501
while( *z ){
499502
char *zName;
500503
char *zValue;
501504
while( fossil_isspace(*z) ){ z++; }
502505
zName = z;
@@ -514,11 +517,11 @@
514517
}else{
515518
if( *z ){ *z++ = 0; }
516519
zValue = "";
517520
}
518521
if( fossil_islower(zName[0]) ){
519
- cgi_set_parameter_nocopy(zName, zValue);
522
+ cgi_set_parameter_nocopy(zName, zValue, isQP);
520523
}
521524
#ifdef FOSSIL_ENABLE_JSON
522525
json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) );
523526
#endif /* FOSSIL_ENABLE_JSON */
524527
}
@@ -658,14 +661,14 @@
658661
while( (zLine = get_line_from_string(&z, &len))!=0 ){
659662
if( zLine[0]==0 ){
660663
int nContent = 0;
661664
zValue = get_bounded_content(&z, &len, zBoundry, &nContent);
662665
if( zName && zValue && fossil_islower(zName[0]) ){
663
- cgi_set_parameter_nocopy(zName, zValue);
666
+ cgi_set_parameter_nocopy(zName, zValue, 1);
664667
if( showBytes ){
665668
cgi_set_parameter_nocopy(mprintf("%s:bytes", zName),
666
- mprintf("%d",nContent));
669
+ mprintf("%d",nContent), 1);
667670
}
668671
}
669672
zName = 0;
670673
showBytes = 0;
671674
}else{
@@ -678,17 +681,17 @@
678681
}else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){
679682
zName = azArg[++i];
680683
}else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){
681684
char *z = azArg[++i];
682685
if( zName && z && fossil_islower(zName[0]) ){
683
- cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z);
686
+ cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z, 1);
684687
}
685688
showBytes = 1;
686689
}else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){
687690
char *z = azArg[++i];
688691
if( zName && z && fossil_islower(zName[0]) ){
689
- cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z);
692
+ cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
690693
}
691694
}
692695
}
693696
}
694697
}
@@ -980,11 +983,11 @@
980983
** with the given name.
981984
*/
982985
if( fossil_isupper(zName[0]) ){
983986
const char *zValue = fossil_getenv(zName);
984987
if( zValue ){
985
- cgi_set_parameter_nocopy(zName, zValue);
988
+ cgi_set_parameter_nocopy(zName, zValue, 0);
986989
CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue));
987990
return zValue;
988991
}
989992
}
990993
CGIDEBUG(("no-match [%s]\n", zName));
@@ -1081,10 +1084,25 @@
10811084
if( fossil_strnicmp("fossil-",zName,7)==0 ) continue;
10821085
}
10831086
cgi_printf("%h = %h <br />\n", zName, aParamQP[i].zValue);
10841087
}
10851088
}
1089
+
1090
+/*
1091
+** Export all query parameters (but not cookies or environment variables)
1092
+** as hidden values of a form.
1093
+*/
1094
+void cgi_query_parameters_to_hidden(void){
1095
+ int i;
1096
+ const char *zN, *zV;
1097
+ for(i=0; i<nUsedQP; i++){
1098
+ if( aParamQP[i].isQP==0 ) continue;
1099
+ zN = aParamQP[i].zName;
1100
+ zV = aParamQP[i].zValue;
1101
+ @ <input type="hidden" name="%h(zN)" value="%h(zV)">
1102
+ }
1103
+}
10861104
10871105
/*
10881106
** This routine works like "printf" except that it has the
10891107
** extra formatting capabilities such as %h and %t.
10901108
*/
10911109
--- src/cgi.c
+++ src/cgi.c
@@ -404,10 +404,11 @@
404 static int seqQP = 0; /* Sequence numbers */
405 static struct QParam { /* One entry for each query parameter or cookie */
406 const char *zName; /* Parameter or cookie name */
407 const char *zValue; /* Value of the query parameter or cookie */
408 int seq; /* Order of insertion */
 
409 } *aParamQP; /* An array of all parameters and cookies */
410
411 /*
412 ** Add another query parameter or cookie to the parameter set.
413 ** zName is the name of the query parameter or cookie and zValue
@@ -414,11 +415,11 @@
414 ** is its fully decoded value.
415 **
416 ** zName and zValue are not copied and must not change or be
417 ** deallocated after this routine returns.
418 */
419 void cgi_set_parameter_nocopy(const char *zName, const char *zValue){
420 if( nAllocQP<=nUsedQP ){
421 nAllocQP = nAllocQP*2 + 10;
422 if( nAllocQP>1000 ){
423 /* Prevent a DOS service attack against the framework */
424 fossil_fatal("Too many query parameters");
@@ -429,10 +430,11 @@
429 aParamQP[nUsedQP].zValue = zValue;
430 if( g.fHttpTrace ){
431 fprintf(stderr, "# cgi: %s = [%s]\n", zName, zValue);
432 }
433 aParamQP[nUsedQP].seq = seqQP++;
 
434 nUsedQP++;
435 sortQP = 1;
436 }
437
438 /*
@@ -441,11 +443,11 @@
441 ** is its fully decoded value.
442 **
443 ** Copies are made of both the zName and zValue parameters.
444 */
445 void cgi_set_parameter(const char *zName, const char *zValue){
446 cgi_set_parameter_nocopy(mprintf("%s",zName), mprintf("%s",zValue));
447 }
448
449 /*
450 ** Replace a parameter with a new value.
451 */
@@ -455,19 +457,19 @@
455 if( fossil_strcmp(aParamQP[i].zName,zName)==0 ){
456 aParamQP[i].zValue = zValue;
457 return;
458 }
459 }
460 cgi_set_parameter_nocopy(zName, zValue);
461 }
462
463 /*
464 ** Add a query parameter. The zName portion is fixed but a copy
465 ** must be made of zValue.
466 */
467 void cgi_setenv(const char *zName, const char *zValue){
468 cgi_set_parameter_nocopy(zName, mprintf("%s",zValue));
469 }
470
471
472 /*
473 ** Add a list of query parameters or cookies to the parameter set.
@@ -493,10 +495,11 @@
493 ** The input string "z" is modified but no copies is made. "z"
494 ** should not be deallocated or changed again after this routine
495 ** returns or it will corrupt the parameter table.
496 */
497 static void add_param_list(char *z, int terminator){
 
498 while( *z ){
499 char *zName;
500 char *zValue;
501 while( fossil_isspace(*z) ){ z++; }
502 zName = z;
@@ -514,11 +517,11 @@
514 }else{
515 if( *z ){ *z++ = 0; }
516 zValue = "";
517 }
518 if( fossil_islower(zName[0]) ){
519 cgi_set_parameter_nocopy(zName, zValue);
520 }
521 #ifdef FOSSIL_ENABLE_JSON
522 json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) );
523 #endif /* FOSSIL_ENABLE_JSON */
524 }
@@ -658,14 +661,14 @@
658 while( (zLine = get_line_from_string(&z, &len))!=0 ){
659 if( zLine[0]==0 ){
660 int nContent = 0;
661 zValue = get_bounded_content(&z, &len, zBoundry, &nContent);
662 if( zName && zValue && fossil_islower(zName[0]) ){
663 cgi_set_parameter_nocopy(zName, zValue);
664 if( showBytes ){
665 cgi_set_parameter_nocopy(mprintf("%s:bytes", zName),
666 mprintf("%d",nContent));
667 }
668 }
669 zName = 0;
670 showBytes = 0;
671 }else{
@@ -678,17 +681,17 @@
678 }else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){
679 zName = azArg[++i];
680 }else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){
681 char *z = azArg[++i];
682 if( zName && z && fossil_islower(zName[0]) ){
683 cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z);
684 }
685 showBytes = 1;
686 }else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){
687 char *z = azArg[++i];
688 if( zName && z && fossil_islower(zName[0]) ){
689 cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z);
690 }
691 }
692 }
693 }
694 }
@@ -980,11 +983,11 @@
980 ** with the given name.
981 */
982 if( fossil_isupper(zName[0]) ){
983 const char *zValue = fossil_getenv(zName);
984 if( zValue ){
985 cgi_set_parameter_nocopy(zName, zValue);
986 CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue));
987 return zValue;
988 }
989 }
990 CGIDEBUG(("no-match [%s]\n", zName));
@@ -1081,10 +1084,25 @@
1081 if( fossil_strnicmp("fossil-",zName,7)==0 ) continue;
1082 }
1083 cgi_printf("%h = %h <br />\n", zName, aParamQP[i].zValue);
1084 }
1085 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1086
1087 /*
1088 ** This routine works like "printf" except that it has the
1089 ** extra formatting capabilities such as %h and %t.
1090 */
1091
--- src/cgi.c
+++ src/cgi.c
@@ -404,10 +404,11 @@
404 static int seqQP = 0; /* Sequence numbers */
405 static struct QParam { /* One entry for each query parameter or cookie */
406 const char *zName; /* Parameter or cookie name */
407 const char *zValue; /* Value of the query parameter or cookie */
408 int seq; /* Order of insertion */
409 int isQP; /* True for query parameters */
410 } *aParamQP; /* An array of all parameters and cookies */
411
412 /*
413 ** Add another query parameter or cookie to the parameter set.
414 ** zName is the name of the query parameter or cookie and zValue
@@ -414,11 +415,11 @@
415 ** is its fully decoded value.
416 **
417 ** zName and zValue are not copied and must not change or be
418 ** deallocated after this routine returns.
419 */
420 void cgi_set_parameter_nocopy(const char *zName, const char *zValue, int isQP){
421 if( nAllocQP<=nUsedQP ){
422 nAllocQP = nAllocQP*2 + 10;
423 if( nAllocQP>1000 ){
424 /* Prevent a DOS service attack against the framework */
425 fossil_fatal("Too many query parameters");
@@ -429,10 +430,11 @@
430 aParamQP[nUsedQP].zValue = zValue;
431 if( g.fHttpTrace ){
432 fprintf(stderr, "# cgi: %s = [%s]\n", zName, zValue);
433 }
434 aParamQP[nUsedQP].seq = seqQP++;
435 aParamQP[nUsedQP].isQP = isQP;
436 nUsedQP++;
437 sortQP = 1;
438 }
439
440 /*
@@ -441,11 +443,11 @@
443 ** is its fully decoded value.
444 **
445 ** Copies are made of both the zName and zValue parameters.
446 */
447 void cgi_set_parameter(const char *zName, const char *zValue){
448 cgi_set_parameter_nocopy(mprintf("%s",zName), mprintf("%s",zValue), 0);
449 }
450
451 /*
452 ** Replace a parameter with a new value.
453 */
@@ -455,19 +457,19 @@
457 if( fossil_strcmp(aParamQP[i].zName,zName)==0 ){
458 aParamQP[i].zValue = zValue;
459 return;
460 }
461 }
462 cgi_set_parameter_nocopy(zName, zValue, 0);
463 }
464
465 /*
466 ** Add a query parameter. The zName portion is fixed but a copy
467 ** must be made of zValue.
468 */
469 void cgi_setenv(const char *zName, const char *zValue){
470 cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
471 }
472
473
474 /*
475 ** Add a list of query parameters or cookies to the parameter set.
@@ -493,10 +495,11 @@
495 ** The input string "z" is modified but no copies is made. "z"
496 ** should not be deallocated or changed again after this routine
497 ** returns or it will corrupt the parameter table.
498 */
499 static void add_param_list(char *z, int terminator){
500 int isQP = terminator=='&';
501 while( *z ){
502 char *zName;
503 char *zValue;
504 while( fossil_isspace(*z) ){ z++; }
505 zName = z;
@@ -514,11 +517,11 @@
517 }else{
518 if( *z ){ *z++ = 0; }
519 zValue = "";
520 }
521 if( fossil_islower(zName[0]) ){
522 cgi_set_parameter_nocopy(zName, zValue, isQP);
523 }
524 #ifdef FOSSIL_ENABLE_JSON
525 json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) );
526 #endif /* FOSSIL_ENABLE_JSON */
527 }
@@ -658,14 +661,14 @@
661 while( (zLine = get_line_from_string(&z, &len))!=0 ){
662 if( zLine[0]==0 ){
663 int nContent = 0;
664 zValue = get_bounded_content(&z, &len, zBoundry, &nContent);
665 if( zName && zValue && fossil_islower(zName[0]) ){
666 cgi_set_parameter_nocopy(zName, zValue, 1);
667 if( showBytes ){
668 cgi_set_parameter_nocopy(mprintf("%s:bytes", zName),
669 mprintf("%d",nContent), 1);
670 }
671 }
672 zName = 0;
673 showBytes = 0;
674 }else{
@@ -678,17 +681,17 @@
681 }else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){
682 zName = azArg[++i];
683 }else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){
684 char *z = azArg[++i];
685 if( zName && z && fossil_islower(zName[0]) ){
686 cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z, 1);
687 }
688 showBytes = 1;
689 }else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){
690 char *z = azArg[++i];
691 if( zName && z && fossil_islower(zName[0]) ){
692 cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
693 }
694 }
695 }
696 }
697 }
@@ -980,11 +983,11 @@
983 ** with the given name.
984 */
985 if( fossil_isupper(zName[0]) ){
986 const char *zValue = fossil_getenv(zName);
987 if( zValue ){
988 cgi_set_parameter_nocopy(zName, zValue, 0);
989 CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue));
990 return zValue;
991 }
992 }
993 CGIDEBUG(("no-match [%s]\n", zName));
@@ -1081,10 +1084,25 @@
1084 if( fossil_strnicmp("fossil-",zName,7)==0 ) continue;
1085 }
1086 cgi_printf("%h = %h <br />\n", zName, aParamQP[i].zValue);
1087 }
1088 }
1089
1090 /*
1091 ** Export all query parameters (but not cookies or environment variables)
1092 ** as hidden values of a form.
1093 */
1094 void cgi_query_parameters_to_hidden(void){
1095 int i;
1096 const char *zN, *zV;
1097 for(i=0; i<nUsedQP; i++){
1098 if( aParamQP[i].isQP==0 ) continue;
1099 zN = aParamQP[i].zName;
1100 zV = aParamQP[i].zValue;
1101 @ <input type="hidden" name="%h(zN)" value="%h(zV)">
1102 }
1103 }
1104
1105 /*
1106 ** This routine works like "printf" except that it has the
1107 ** extra formatting capabilities such as %h and %t.
1108 */
1109
+1
--- src/diff.c
+++ src/diff.c
@@ -2150,10 +2150,11 @@
21502150
21512151
/* Gather query parameters */
21522152
showLog = atoi(PD("log","1"));
21532153
login_check_credentials();
21542154
if( !g.perm.Read ){ login_needed(); return; }
2155
+ if( exclude_spiders("annotate") ) return;
21552156
mid = name_to_typed_rid(PD("checkin","0"),"ci");
21562157
zFilename = P("filename");
21572158
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
21582159
if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
21592160
iLimit = atoi(PD("limit","20"));
21602161
--- src/diff.c
+++ src/diff.c
@@ -2150,10 +2150,11 @@
2150
2151 /* Gather query parameters */
2152 showLog = atoi(PD("log","1"));
2153 login_check_credentials();
2154 if( !g.perm.Read ){ login_needed(); return; }
 
2155 mid = name_to_typed_rid(PD("checkin","0"),"ci");
2156 zFilename = P("filename");
2157 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
2158 if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
2159 iLimit = atoi(PD("limit","20"));
2160
--- src/diff.c
+++ src/diff.c
@@ -2150,10 +2150,11 @@
2150
2151 /* Gather query parameters */
2152 showLog = atoi(PD("log","1"));
2153 login_check_credentials();
2154 if( !g.perm.Read ){ login_needed(); return; }
2155 if( exclude_spiders("annotate") ) return;
2156 mid = name_to_typed_rid(PD("checkin","0"),"ci");
2157 zFilename = P("filename");
2158 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
2159 if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
2160 iLimit = atoi(PD("limit","20"));
2161
+1 -1
--- src/login.c
+++ src/login.c
@@ -69,11 +69,11 @@
6969
** Return a path appropriate for setting a cookie.
7070
**
7171
** The path is g.zTop for single-repo cookies. It is "/" for
7272
** cookies of a login-group.
7373
*/
74
-static const char *login_cookie_path(void){
74
+const char *login_cookie_path(void){
7575
if( login_group_name()==0 ){
7676
return g.zTop;
7777
}else{
7878
return "/";
7979
}
8080
--- src/login.c
+++ src/login.c
@@ -69,11 +69,11 @@
69 ** Return a path appropriate for setting a cookie.
70 **
71 ** The path is g.zTop for single-repo cookies. It is "/" for
72 ** cookies of a login-group.
73 */
74 static const char *login_cookie_path(void){
75 if( login_group_name()==0 ){
76 return g.zTop;
77 }else{
78 return "/";
79 }
80
--- src/login.c
+++ src/login.c
@@ -69,11 +69,11 @@
69 ** Return a path appropriate for setting a cookie.
70 **
71 ** The path is g.zTop for single-repo cookies. It is "/" for
72 ** cookies of a login-group.
73 */
74 const char *login_cookie_path(void){
75 if( login_group_name()==0 ){
76 return g.zTop;
77 }else{
78 return "/";
79 }
80
+1 -1
--- src/main.c
+++ src/main.c
@@ -1367,11 +1367,11 @@
13671367
*/
13681368
#ifdef FOSSIL_ENABLE_JSON
13691369
if(!g.json.isJsonMode){
13701370
#endif
13711371
dehttpize(g.zExtra);
1372
- cgi_set_parameter_nocopy("name", g.zExtra);
1372
+ cgi_set_parameter_nocopy("name", g.zExtra, 1);
13731373
#ifdef FOSSIL_ENABLE_JSON
13741374
}
13751375
#endif
13761376
}
13771377
13781378
--- src/main.c
+++ src/main.c
@@ -1367,11 +1367,11 @@
1367 */
1368 #ifdef FOSSIL_ENABLE_JSON
1369 if(!g.json.isJsonMode){
1370 #endif
1371 dehttpize(g.zExtra);
1372 cgi_set_parameter_nocopy("name", g.zExtra);
1373 #ifdef FOSSIL_ENABLE_JSON
1374 }
1375 #endif
1376 }
1377
1378
--- src/main.c
+++ src/main.c
@@ -1367,11 +1367,11 @@
1367 */
1368 #ifdef FOSSIL_ENABLE_JSON
1369 if(!g.json.isJsonMode){
1370 #endif
1371 dehttpize(g.zExtra);
1372 cgi_set_parameter_nocopy("name", g.zExtra, 1);
1373 #ifdef FOSSIL_ENABLE_JSON
1374 }
1375 #endif
1376 }
1377
1378
+2 -2
--- src/tkt.c
+++ src/tkt.c
@@ -676,11 +676,11 @@
676676
if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1);
677677
if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){
678678
cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid));
679679
return;
680680
}
681
- captcha_generate();
681
+ captcha_generate(0);
682682
@ </form>
683683
if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
684684
style_footer();
685685
}
686686
@@ -744,11 +744,11 @@
744744
if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1);
745745
if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){
746746
cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName));
747747
return;
748748
}
749
- captcha_generate();
749
+ captcha_generate(0);
750750
@ </form>
751751
if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
752752
style_footer();
753753
}
754754
755755
--- src/tkt.c
+++ src/tkt.c
@@ -676,11 +676,11 @@
676 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1);
677 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){
678 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid));
679 return;
680 }
681 captcha_generate();
682 @ </form>
683 if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
684 style_footer();
685 }
686
@@ -744,11 +744,11 @@
744 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1);
745 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){
746 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName));
747 return;
748 }
749 captcha_generate();
750 @ </form>
751 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
752 style_footer();
753 }
754
755
--- src/tkt.c
+++ src/tkt.c
@@ -676,11 +676,11 @@
676 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1);
677 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){
678 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid));
679 return;
680 }
681 captcha_generate(0);
682 @ </form>
683 if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
684 style_footer();
685 }
686
@@ -744,11 +744,11 @@
744 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1);
745 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){
746 cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName));
747 return;
748 }
749 captcha_generate(0);
750 @ </form>
751 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
752 style_footer();
753 }
754
755
+3 -3
--- src/wiki.c
+++ src/wiki.c
@@ -96,11 +96,11 @@
9696
cgi_redirectf("%s/login?g=%s/home", g.zTop, g.zTop);
9797
}
9898
if( zPageName ){
9999
login_check_credentials();
100100
g.zExtra = zPageName;
101
- cgi_set_parameter_nocopy("name", g.zExtra);
101
+ cgi_set_parameter_nocopy("name", g.zExtra, 1);
102102
g.isHome = 1;
103103
wiki_page();
104104
return;
105105
}
106106
style_header("Home");
@@ -493,11 +493,11 @@
493493
@ <input type="submit" name="submit" value="Apply These Changes" />
494494
@ <input type="hidden" name="name" value="%h(zPageName)" />
495495
@ <input type="submit" name="cancel" value="Cancel"
496496
@ onclick='confirm("Abandon your changes?")' />
497497
@ </div>
498
- captcha_generate();
498
+ captcha_generate(0);
499499
@ </form>
500500
manifest_destroy(pWiki);
501501
blob_reset(&wiki);
502502
style_footer();
503503
}
@@ -696,11 +696,11 @@
696696
@ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
697697
@ <br />
698698
@ <input type="submit" name="preview" value="Preview Your Comment" />
699699
@ <input type="submit" name="submit" value="Append Your Changes" />
700700
@ <input type="submit" name="cancel" value="Cancel" />
701
- captcha_generate();
701
+ captcha_generate(0);
702702
@ </form>
703703
style_footer();
704704
}
705705
706706
/*
707707
--- src/wiki.c
+++ src/wiki.c
@@ -96,11 +96,11 @@
96 cgi_redirectf("%s/login?g=%s/home", g.zTop, g.zTop);
97 }
98 if( zPageName ){
99 login_check_credentials();
100 g.zExtra = zPageName;
101 cgi_set_parameter_nocopy("name", g.zExtra);
102 g.isHome = 1;
103 wiki_page();
104 return;
105 }
106 style_header("Home");
@@ -493,11 +493,11 @@
493 @ <input type="submit" name="submit" value="Apply These Changes" />
494 @ <input type="hidden" name="name" value="%h(zPageName)" />
495 @ <input type="submit" name="cancel" value="Cancel"
496 @ onclick='confirm("Abandon your changes?")' />
497 @ </div>
498 captcha_generate();
499 @ </form>
500 manifest_destroy(pWiki);
501 blob_reset(&wiki);
502 style_footer();
503 }
@@ -696,11 +696,11 @@
696 @ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
697 @ <br />
698 @ <input type="submit" name="preview" value="Preview Your Comment" />
699 @ <input type="submit" name="submit" value="Append Your Changes" />
700 @ <input type="submit" name="cancel" value="Cancel" />
701 captcha_generate();
702 @ </form>
703 style_footer();
704 }
705
706 /*
707
--- src/wiki.c
+++ src/wiki.c
@@ -96,11 +96,11 @@
96 cgi_redirectf("%s/login?g=%s/home", g.zTop, g.zTop);
97 }
98 if( zPageName ){
99 login_check_credentials();
100 g.zExtra = zPageName;
101 cgi_set_parameter_nocopy("name", g.zExtra, 1);
102 g.isHome = 1;
103 wiki_page();
104 return;
105 }
106 style_header("Home");
@@ -493,11 +493,11 @@
493 @ <input type="submit" name="submit" value="Apply These Changes" />
494 @ <input type="hidden" name="name" value="%h(zPageName)" />
495 @ <input type="submit" name="cancel" value="Cancel"
496 @ onclick='confirm("Abandon your changes?")' />
497 @ </div>
498 captcha_generate(0);
499 @ </form>
500 manifest_destroy(pWiki);
501 blob_reset(&wiki);
502 style_footer();
503 }
@@ -696,11 +696,11 @@
696 @ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
697 @ <br />
698 @ <input type="submit" name="preview" value="Preview Your Comment" />
699 @ <input type="submit" name="submit" value="Append Your Changes" />
700 @ <input type="submit" name="cancel" value="Cancel" />
701 captcha_generate(0);
702 @ </form>
703 style_footer();
704 }
705
706 /*
707

Keyboard Shortcuts

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