Fossil SCM

Improve the captcha that pops up when a robot is suspected. The captcha page no loads in place of the request that is suspecious, without needing to redirect.

drh 2024-07-28 23:34 trunk
Commit 1958448c6ef271e4a91622b2919796ddc37fbd5f65313e90aaaf6bc5786503fd
+1 -1
--- src/browse.c
+++ src/browse.c
@@ -1162,11 +1162,11 @@
11621162
int showId = PB("showid");
11631163
Stmt q1, q2;
11641164
double baseTime;
11651165
login_check_credentials();
11661166
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1167
- if( exclude_spiders() ) return;
1167
+ if( exclude_spiders(0) ) return;
11681168
zName = P("name");
11691169
if( zName==0 ) zName = "tip";
11701170
rid = symbolic_name_to_rid(zName, "ci");
11711171
if( rid==0 ){
11721172
fossil_fatal("not a valid check-in: %s", zName);
11731173
--- src/browse.c
+++ src/browse.c
@@ -1162,11 +1162,11 @@
1162 int showId = PB("showid");
1163 Stmt q1, q2;
1164 double baseTime;
1165 login_check_credentials();
1166 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1167 if( exclude_spiders() ) return;
1168 zName = P("name");
1169 if( zName==0 ) zName = "tip";
1170 rid = symbolic_name_to_rid(zName, "ci");
1171 if( rid==0 ){
1172 fossil_fatal("not a valid check-in: %s", zName);
1173
--- src/browse.c
+++ src/browse.c
@@ -1162,11 +1162,11 @@
1162 int showId = PB("showid");
1163 Stmt q1, q2;
1164 double baseTime;
1165 login_check_credentials();
1166 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1167 if( exclude_spiders(0) ) return;
1168 zName = P("name");
1169 if( zName==0 ) zName = "tip";
1170 rid = symbolic_name_to_rid(zName, "ci");
1171 if( rid==0 ){
1172 fossil_fatal("not a valid check-in: %s", zName);
1173
+154 -59
--- src/captcha.c
+++ src/captcha.c
@@ -22,11 +22,11 @@
2222
#include "config.h"
2323
#include <assert.h>
2424
#include "captcha.h"
2525
2626
#if INTERFACE
27
-#define CAPTCHA 3 /* Which captcha rendering to use */
27
+#define CAPTCHA 2 /* Which captcha rendering to use */
2828
#endif
2929
3030
/*
3131
** Convert a hex digit into a value between 0 and 15
3232
*/
@@ -69,22 +69,26 @@
6969
** Render an 8-character hexadecimal string as ascii art.
7070
** Space to hold the result is obtained from malloc() and should be freed
7171
** by the caller.
7272
*/
7373
char *captcha_render(const char *zPw){
74
- char *z = fossil_malloc( 9*6*strlen(zPw) + 7 );
74
+ char *z = fossil_malloc( 9*12*3*strlen(zPw) + 8 );
7575
int i, j, k, m;
7676
7777
k = 0;
7878
for(i=0; i<6; i++){
7979
for(j=0; zPw[j]; j++){
8080
unsigned char v = hex_digit_value(zPw[j]);
8181
v = (aFont1[v] >> ((5-i)*4)) & 0xf;
8282
for(m=8; m>=1; m = m>>1){
8383
if( v & m ){
84
- z[k++] = 'X';
85
- z[k++] = 'X';
84
+ z[k++] = 0xe2;
85
+ z[k++] = 0x96;
86
+ z[k++] = 0x88;
87
+ z[k++] = 0xe2;
88
+ z[k++] = 0x96;
89
+ z[k++] = 0x88;
8690
}else{
8791
z[k++] = ' ';
8892
z[k++] = ' ';
8993
}
9094
}
@@ -96,13 +100,73 @@
96100
z[k] = 0;
97101
return z;
98102
}
99103
#endif /* CAPTCHA==1 */
100104
101
-
102105
#if CAPTCHA==2
103
-static const char *const azFont2[] = {
106
+/*
107
+** A 5x7 pixel bitmap font for hexadecimal digits
108
+*/
109
+static const unsigned char aFont2[] = {
110
+ /* 0 */ 0x0e, 0x13, 0x15, 0x19, 0x11, 0x11, 0x0e,
111
+ /* 1 */ 0x02, 0x06, 0x0A, 0x02, 0x02, 0x02, 0x02,
112
+ /* 2 */ 0x0e, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1f,
113
+ /* 3 */ 0x0e, 0x11, 0x01, 0x06, 0x01, 0x11, 0x0e,
114
+ /* 4 */ 0x02, 0x06, 0x0A, 0x12, 0x1f, 0x02, 0x02,
115
+ /* 5 */ 0x1f, 0x10, 0x1e, 0x01, 0x01, 0x11, 0x0e,
116
+ /* 6 */ 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x0e,
117
+ /* 7 */ 0x1f, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08,
118
+ /* 8 */ 0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e,
119
+ /* 9 */ 0x0e, 0x11, 0x11, 0x0f, 0x01, 0x11, 0x0e,
120
+ /* A */ 0x0e, 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11,
121
+ /* B */ 0x1e, 0x11, 0x11, 0x1e, 0x11, 0x11, 0x1e,
122
+ /* C */ 0x0e, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0e,
123
+ /* D */ 0x1c, 0x12, 0x11, 0x11, 0x11, 0x12, 0x1c,
124
+ /* E */ 0x1f, 0x10, 0x10, 0x1c, 0x10, 0x10, 0x1f,
125
+ /* F */ 0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x10,
126
+};
127
+
128
+/*
129
+** Render an 8-character hexadecimal string as ascii art.
130
+** Space to hold the result is obtained from malloc() and should be freed
131
+** by the caller.
132
+*/
133
+char *captcha_render(const char *zPw){
134
+ char *z = fossil_malloc( 160*strlen(zPw) + 9 );
135
+ int i, j, k, m;
136
+
137
+ k = 0;
138
+ for(i=0; i<7; i++){
139
+ for(j=0; zPw[j]; j++){
140
+ unsigned char v = hex_digit_value(zPw[j]);
141
+ v = aFont2[v*7+i];
142
+ for(m=16; m>=1; m = m>>1){
143
+ if( v & m ){
144
+ z[k++] = 0xe2;
145
+ z[k++] = 0x96;
146
+ z[k++] = 0x88;
147
+ z[k++] = 0xe2;
148
+ z[k++] = 0x96;
149
+ z[k++] = 0x88;
150
+ }else{
151
+ z[k++] = ' ';
152
+ z[k++] = ' ';
153
+ }
154
+ }
155
+ z[k++] = ' ';
156
+ z[k++] = ' ';
157
+ }
158
+ z[k++] = '\n';
159
+ }
160
+ z[k] = 0;
161
+ return z;
162
+}
163
+#endif /* CAPTCHA==2 */
164
+
165
+
166
+#if CAPTCHA==3
167
+static const char *const azFont3[] = {
104168
/* 0 */
105169
" __ ",
106170
" / \\ ",
107171
"| () |",
108172
" \\__/ ",
@@ -210,24 +274,24 @@
210274
211275
k = 0;
212276
for(i=0; i<4; i++){
213277
for(j=0; zPw[j]; j++){
214278
unsigned char v = hex_digit_value(zPw[j]);
215
- zChar = azFont2[4*v + i];
279
+ zChar = azFont3[4*v + i];
216280
for(m=0; zChar[m]; m++){
217281
z[k++] = zChar[m];
218282
}
219283
}
220284
z[k++] = '\n';
221285
}
222286
z[k] = 0;
223287
return z;
224288
}
225
-#endif /* CAPTCHA==2 */
289
+#endif /* CAPTCHA==3 */
226290
227
-#if CAPTCHA==3
228
-static const char *const azFont3[] = {
291
+#if CAPTCHA==4
292
+static const char *const azFont4[] = {
229293
/* 0 */
230294
" ___ ",
231295
" / _ \\ ",
232296
"| | | |",
233297
"| | | |",
@@ -398,11 +462,11 @@
398462
break;
399463
default:
400464
y = 0;
401465
break;
402466
}
403
- zChar = azFont3[6*v + i];
467
+ zChar = azFont4[6*v + i];
404468
while( y && zChar[0]==' ' ){ y--; zChar++; }
405469
while( y && z[k-1]==' ' ){ y--; k--; }
406470
for(m=0; zChar[m]; m++){
407471
z[k++] = zChar[m];
408472
}
@@ -410,11 +474,11 @@
410474
z[k++] = '\n';
411475
}
412476
z[k] = 0;
413477
return z;
414478
}
415
-#endif /* CAPTCHA==3 */
479
+#endif /* CAPTCHA==4 */
416480
417481
/*
418482
** COMMAND: test-captcha
419483
**
420484
** Render an ASCII-art captcha for numbers given on the command line.
@@ -530,27 +594,32 @@
530594
** Generate a captcha display together with the necessary hidden parameter
531595
** for the seed and the entry box into which the user will type the text of
532596
** the captcha. This is typically done at the very bottom of a form.
533597
**
534598
** This routine is a no-op if no captcha is required.
599
+**
600
+** Flag values:
601
+**
602
+** 0x01 Show the "Submit" button in the form.
603
+** 0x02 Always generate the captcha, even if not required
535604
*/
536
-void captcha_generate(int showButton){
605
+void captcha_generate(int mFlags){
537606
unsigned int uSeed;
538607
const char *zDecoded;
539608
char *zCaptcha;
540609
541
- if( !captcha_needed() ) return;
610
+ if( !captcha_needed() && (mFlags & 0x02)==0 ) return;
542611
uSeed = captcha_seed();
543612
zDecoded = captcha_decode(uSeed);
544613
zCaptcha = captcha_render(zDecoded);
545614
@ <div class="captcha"><table class="captcha"><tr><td><pre class="captcha">
546615
@ %h(zCaptcha)
547616
@ </pre>
548617
@ Enter security code shown above:
549618
@ <input type="hidden" name="captchaseed" value="%u(uSeed)">
550
- @ <input type="text" name="captcha" size=8>
551
- if( showButton ){
619
+ @ <input type="text" name="captcha" size="8" autofocus>
620
+ if( mFlags & 0x01 ){
552621
@ <input type="submit" value="Submit">
553622
}
554623
@ <br/>\
555624
captcha_speakit_button(uSeed, 0);
556625
@ </td></tr></table></div>
@@ -574,67 +643,93 @@
574643
@ </script>
575644
}
576645
577646
/*
578647
** WEBPAGE: test-captcha
579
-** Test the captcha-generator by rendering the value of the name= query
580
-** parameter using ascii-art. If name= is omitted, show a random 16-digit
581
-** hexadecimal number.
648
+**
649
+** If the name query parameter is provided, then render the hex value of
650
+** the name using the captcha font.
651
+**
652
+** Otherwise render the captcha screen. The "show-button" parameter causes
653
+** the submit button to be rendered.
582654
*/
583655
void captcha_test(void){
584656
const char *zPw = P("name");
585657
if( zPw==0 || zPw[0]==0 ){
586
- u64 x;
587
- sqlite3_randomness(sizeof(x), &x);
588
- zPw = mprintf("%016llx", x);
589
- }
590
- style_set_current_feature("test");
591
- style_header("Captcha Test");
592
- @ <pre>
593
- @ %s(captcha_render(zPw))
594
- @ </pre>
595
- style_finish_page();
658
+ (void)exclude_spiders(1);
659
+ @ <hr><p>The captcha is shown above. Add a name=HEX query parameter
660
+ @ to see how HEX would be rendered in the current captcha font.
661
+ @ <p>captcha_is_correct(1) returns %d(captcha_is_correct(1)).
662
+ style_finish_page();
663
+ }else{
664
+ style_set_current_feature("test");
665
+ style_header("Captcha Test");
666
+ @ <pre class="captcha">
667
+ @ %s(captcha_render(zPw))
668
+ @ </pre>
669
+ style_finish_page();
670
+ }
596671
}
597672
598673
/*
599
-** Check to see if the current request is coming from an agent that might
600
-** be a spider. If the agent is not a spider, then return 0 without doing
601
-** anything. But if the user agent appears to be a spider, offer
602
-** a captcha challenge to allow the user agent to prove that it is human
603
-** and return non-zero.
674
+** Check to see if the current request is coming from an agent that
675
+** self-identifies as a spider.
676
+**
677
+** If the agent does not claim to be a spider or if the user has logged
678
+** in (even as anonymous), then return 0 without doing anything.
679
+**
680
+** But if the user agent does self-identify as a spider and there is
681
+** no login, offer a captcha challenge to allow the user agent to prove
682
+** that he is human and return non-zero.
683
+**
684
+** If the bTest argument is non-zero, then show the captcha regardless of
685
+** how the agent identifies. This is used for testing only.
604686
*/
605
-int exclude_spiders(void){
606
- const char *zCookieValue;
607
- char *zCookieName;
608
- if( g.isHuman ) return 0;
609
-#if 0
610
- {
611
- const char *zReferer = P("HTTP_REFERER");
612
- if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
613
- return 0;
614
- }
615
- }
616
-#endif
617
- zCookieName = mprintf("fossil-cc-%.10s", db_get("project-code","x"));
618
- zCookieValue = P(zCookieName);
619
- if( zCookieValue && atoi(zCookieValue)==1 ) return 0;
620
- if( captcha_is_correct(0) ){
621
- cgi_set_cookie(zCookieName, "1", login_cookie_path(), 8*3600);
622
- return 0;
623
- }
687
+int exclude_spiders(int bTest){
688
+ if( !bTest && (g.isHuman || g.zLogin!=0) ) return 0;
624689
625690
/* This appears to be a spider. Offer the captcha */
626691
style_set_current_feature("captcha");
627
- style_header("Verification");
628
- @ <form method='POST' action='%s(g.zPath)'>
629
- cgi_query_parameters_to_hidden();
630
- @ <p>Please demonstrate that you are human, not a spider or robot</p>
631
- captcha_generate(1);
692
+ style_header("I think you are a robot");
693
+ style_submenu_enable(0);
694
+ @ <form method='POST' action='%R/captchacb'>
695
+ @ <p>You seem like a robot.
696
+ @
697
+ @ <p>If you are human, you can prove that by solving the captcha below,
698
+ @ after which you will be allowed to proceed.
699
+ captcha_generate(3);
632700
@ </form>
633
- style_finish_page();
701
+ if( !bTest ){
702
+ if( P("fossil-goto")==0 ){
703
+ cgi_set_cookie("fossil-goto", cgi_reconstruct_original_url(), 0, 600);
704
+ }
705
+ cgi_append_header("X-Robot: 1\r\n");
706
+ style_finish_page();
707
+ }
634708
return 1;
635709
}
710
+
711
+/*
712
+** WEBPAGE: captchacb
713
+**
714
+** This is action for the form that is the captcha. Not intended
715
+** for external use.
716
+**
717
+** If the captcha is correctly solved, then an anonymous login cookie
718
+** is set. Regardless of whether or not the captcha was solved, this
719
+** page always redirects to the fossil-goto cookie.
720
+*/
721
+void captcha_callback(void){
722
+ if( captcha_is_correct(1) ){
723
+ login_set_anon_cookie(0, 0);
724
+ cgi_append_header("X-Robot: 0\r\n");
725
+ login_redirect_to_g();
726
+ }else{
727
+ exclude_spiders(0);
728
+ }
729
+}
730
+
636731
637732
/*
638733
** Generate a WAV file that reads aloud the hex digits given by
639734
** zHex.
640735
*/
641736
--- src/captcha.c
+++ src/captcha.c
@@ -22,11 +22,11 @@
22 #include "config.h"
23 #include <assert.h>
24 #include "captcha.h"
25
26 #if INTERFACE
27 #define CAPTCHA 3 /* Which captcha rendering to use */
28 #endif
29
30 /*
31 ** Convert a hex digit into a value between 0 and 15
32 */
@@ -69,22 +69,26 @@
69 ** Render an 8-character hexadecimal string as ascii art.
70 ** Space to hold the result is obtained from malloc() and should be freed
71 ** by the caller.
72 */
73 char *captcha_render(const char *zPw){
74 char *z = fossil_malloc( 9*6*strlen(zPw) + 7 );
75 int i, j, k, m;
76
77 k = 0;
78 for(i=0; i<6; i++){
79 for(j=0; zPw[j]; j++){
80 unsigned char v = hex_digit_value(zPw[j]);
81 v = (aFont1[v] >> ((5-i)*4)) & 0xf;
82 for(m=8; m>=1; m = m>>1){
83 if( v & m ){
84 z[k++] = 'X';
85 z[k++] = 'X';
 
 
 
 
86 }else{
87 z[k++] = ' ';
88 z[k++] = ' ';
89 }
90 }
@@ -96,13 +100,73 @@
96 z[k] = 0;
97 return z;
98 }
99 #endif /* CAPTCHA==1 */
100
101
102 #if CAPTCHA==2
103 static const char *const azFont2[] = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104 /* 0 */
105 " __ ",
106 " / \\ ",
107 "| () |",
108 " \\__/ ",
@@ -210,24 +274,24 @@
210
211 k = 0;
212 for(i=0; i<4; i++){
213 for(j=0; zPw[j]; j++){
214 unsigned char v = hex_digit_value(zPw[j]);
215 zChar = azFont2[4*v + i];
216 for(m=0; zChar[m]; m++){
217 z[k++] = zChar[m];
218 }
219 }
220 z[k++] = '\n';
221 }
222 z[k] = 0;
223 return z;
224 }
225 #endif /* CAPTCHA==2 */
226
227 #if CAPTCHA==3
228 static const char *const azFont3[] = {
229 /* 0 */
230 " ___ ",
231 " / _ \\ ",
232 "| | | |",
233 "| | | |",
@@ -398,11 +462,11 @@
398 break;
399 default:
400 y = 0;
401 break;
402 }
403 zChar = azFont3[6*v + i];
404 while( y && zChar[0]==' ' ){ y--; zChar++; }
405 while( y && z[k-1]==' ' ){ y--; k--; }
406 for(m=0; zChar[m]; m++){
407 z[k++] = zChar[m];
408 }
@@ -410,11 +474,11 @@
410 z[k++] = '\n';
411 }
412 z[k] = 0;
413 return z;
414 }
415 #endif /* CAPTCHA==3 */
416
417 /*
418 ** COMMAND: test-captcha
419 **
420 ** Render an ASCII-art captcha for numbers given on the command line.
@@ -530,27 +594,32 @@
530 ** Generate a captcha display together with the necessary hidden parameter
531 ** for the seed and the entry box into which the user will type the text of
532 ** the captcha. This is typically done at the very bottom of a form.
533 **
534 ** This routine is a no-op if no captcha is required.
 
 
 
 
 
535 */
536 void captcha_generate(int showButton){
537 unsigned int uSeed;
538 const char *zDecoded;
539 char *zCaptcha;
540
541 if( !captcha_needed() ) return;
542 uSeed = captcha_seed();
543 zDecoded = captcha_decode(uSeed);
544 zCaptcha = captcha_render(zDecoded);
545 @ <div class="captcha"><table class="captcha"><tr><td><pre class="captcha">
546 @ %h(zCaptcha)
547 @ </pre>
548 @ Enter security code shown above:
549 @ <input type="hidden" name="captchaseed" value="%u(uSeed)">
550 @ <input type="text" name="captcha" size=8>
551 if( showButton ){
552 @ <input type="submit" value="Submit">
553 }
554 @ <br/>\
555 captcha_speakit_button(uSeed, 0);
556 @ </td></tr></table></div>
@@ -574,67 +643,93 @@
574 @ </script>
575 }
576
577 /*
578 ** WEBPAGE: test-captcha
579 ** Test the captcha-generator by rendering the value of the name= query
580 ** parameter using ascii-art. If name= is omitted, show a random 16-digit
581 ** hexadecimal number.
 
 
 
582 */
583 void captcha_test(void){
584 const char *zPw = P("name");
585 if( zPw==0 || zPw[0]==0 ){
586 u64 x;
587 sqlite3_randomness(sizeof(x), &x);
588 zPw = mprintf("%016llx", x);
589 }
590 style_set_current_feature("test");
591 style_header("Captcha Test");
592 @ <pre>
593 @ %s(captcha_render(zPw))
594 @ </pre>
595 style_finish_page();
 
 
 
596 }
597
598 /*
599 ** Check to see if the current request is coming from an agent that might
600 ** be a spider. If the agent is not a spider, then return 0 without doing
601 ** anything. But if the user agent appears to be a spider, offer
602 ** a captcha challenge to allow the user agent to prove that it is human
603 ** and return non-zero.
 
 
 
 
 
 
 
604 */
605 int exclude_spiders(void){
606 const char *zCookieValue;
607 char *zCookieName;
608 if( g.isHuman ) return 0;
609 #if 0
610 {
611 const char *zReferer = P("HTTP_REFERER");
612 if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
613 return 0;
614 }
615 }
616 #endif
617 zCookieName = mprintf("fossil-cc-%.10s", db_get("project-code","x"));
618 zCookieValue = P(zCookieName);
619 if( zCookieValue && atoi(zCookieValue)==1 ) return 0;
620 if( captcha_is_correct(0) ){
621 cgi_set_cookie(zCookieName, "1", login_cookie_path(), 8*3600);
622 return 0;
623 }
624
625 /* This appears to be a spider. Offer the captcha */
626 style_set_current_feature("captcha");
627 style_header("Verification");
628 @ <form method='POST' action='%s(g.zPath)'>
629 cgi_query_parameters_to_hidden();
630 @ <p>Please demonstrate that you are human, not a spider or robot</p>
631 captcha_generate(1);
 
 
 
632 @ </form>
633 style_finish_page();
 
 
 
 
 
 
634 return 1;
635 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
636
637 /*
638 ** Generate a WAV file that reads aloud the hex digits given by
639 ** zHex.
640 */
641
--- src/captcha.c
+++ src/captcha.c
@@ -22,11 +22,11 @@
22 #include "config.h"
23 #include <assert.h>
24 #include "captcha.h"
25
26 #if INTERFACE
27 #define CAPTCHA 2 /* Which captcha rendering to use */
28 #endif
29
30 /*
31 ** Convert a hex digit into a value between 0 and 15
32 */
@@ -69,22 +69,26 @@
69 ** Render an 8-character hexadecimal string as ascii art.
70 ** Space to hold the result is obtained from malloc() and should be freed
71 ** by the caller.
72 */
73 char *captcha_render(const char *zPw){
74 char *z = fossil_malloc( 9*12*3*strlen(zPw) + 8 );
75 int i, j, k, m;
76
77 k = 0;
78 for(i=0; i<6; i++){
79 for(j=0; zPw[j]; j++){
80 unsigned char v = hex_digit_value(zPw[j]);
81 v = (aFont1[v] >> ((5-i)*4)) & 0xf;
82 for(m=8; m>=1; m = m>>1){
83 if( v & m ){
84 z[k++] = 0xe2;
85 z[k++] = 0x96;
86 z[k++] = 0x88;
87 z[k++] = 0xe2;
88 z[k++] = 0x96;
89 z[k++] = 0x88;
90 }else{
91 z[k++] = ' ';
92 z[k++] = ' ';
93 }
94 }
@@ -96,13 +100,73 @@
100 z[k] = 0;
101 return z;
102 }
103 #endif /* CAPTCHA==1 */
104
 
105 #if CAPTCHA==2
106 /*
107 ** A 5x7 pixel bitmap font for hexadecimal digits
108 */
109 static const unsigned char aFont2[] = {
110 /* 0 */ 0x0e, 0x13, 0x15, 0x19, 0x11, 0x11, 0x0e,
111 /* 1 */ 0x02, 0x06, 0x0A, 0x02, 0x02, 0x02, 0x02,
112 /* 2 */ 0x0e, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1f,
113 /* 3 */ 0x0e, 0x11, 0x01, 0x06, 0x01, 0x11, 0x0e,
114 /* 4 */ 0x02, 0x06, 0x0A, 0x12, 0x1f, 0x02, 0x02,
115 /* 5 */ 0x1f, 0x10, 0x1e, 0x01, 0x01, 0x11, 0x0e,
116 /* 6 */ 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x0e,
117 /* 7 */ 0x1f, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08,
118 /* 8 */ 0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e,
119 /* 9 */ 0x0e, 0x11, 0x11, 0x0f, 0x01, 0x11, 0x0e,
120 /* A */ 0x0e, 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11,
121 /* B */ 0x1e, 0x11, 0x11, 0x1e, 0x11, 0x11, 0x1e,
122 /* C */ 0x0e, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0e,
123 /* D */ 0x1c, 0x12, 0x11, 0x11, 0x11, 0x12, 0x1c,
124 /* E */ 0x1f, 0x10, 0x10, 0x1c, 0x10, 0x10, 0x1f,
125 /* F */ 0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x10,
126 };
127
128 /*
129 ** Render an 8-character hexadecimal string as ascii art.
130 ** Space to hold the result is obtained from malloc() and should be freed
131 ** by the caller.
132 */
133 char *captcha_render(const char *zPw){
134 char *z = fossil_malloc( 160*strlen(zPw) + 9 );
135 int i, j, k, m;
136
137 k = 0;
138 for(i=0; i<7; i++){
139 for(j=0; zPw[j]; j++){
140 unsigned char v = hex_digit_value(zPw[j]);
141 v = aFont2[v*7+i];
142 for(m=16; m>=1; m = m>>1){
143 if( v & m ){
144 z[k++] = 0xe2;
145 z[k++] = 0x96;
146 z[k++] = 0x88;
147 z[k++] = 0xe2;
148 z[k++] = 0x96;
149 z[k++] = 0x88;
150 }else{
151 z[k++] = ' ';
152 z[k++] = ' ';
153 }
154 }
155 z[k++] = ' ';
156 z[k++] = ' ';
157 }
158 z[k++] = '\n';
159 }
160 z[k] = 0;
161 return z;
162 }
163 #endif /* CAPTCHA==2 */
164
165
166 #if CAPTCHA==3
167 static const char *const azFont3[] = {
168 /* 0 */
169 " __ ",
170 " / \\ ",
171 "| () |",
172 " \\__/ ",
@@ -210,24 +274,24 @@
274
275 k = 0;
276 for(i=0; i<4; i++){
277 for(j=0; zPw[j]; j++){
278 unsigned char v = hex_digit_value(zPw[j]);
279 zChar = azFont3[4*v + i];
280 for(m=0; zChar[m]; m++){
281 z[k++] = zChar[m];
282 }
283 }
284 z[k++] = '\n';
285 }
286 z[k] = 0;
287 return z;
288 }
289 #endif /* CAPTCHA==3 */
290
291 #if CAPTCHA==4
292 static const char *const azFont4[] = {
293 /* 0 */
294 " ___ ",
295 " / _ \\ ",
296 "| | | |",
297 "| | | |",
@@ -398,11 +462,11 @@
462 break;
463 default:
464 y = 0;
465 break;
466 }
467 zChar = azFont4[6*v + i];
468 while( y && zChar[0]==' ' ){ y--; zChar++; }
469 while( y && z[k-1]==' ' ){ y--; k--; }
470 for(m=0; zChar[m]; m++){
471 z[k++] = zChar[m];
472 }
@@ -410,11 +474,11 @@
474 z[k++] = '\n';
475 }
476 z[k] = 0;
477 return z;
478 }
479 #endif /* CAPTCHA==4 */
480
481 /*
482 ** COMMAND: test-captcha
483 **
484 ** Render an ASCII-art captcha for numbers given on the command line.
@@ -530,27 +594,32 @@
594 ** Generate a captcha display together with the necessary hidden parameter
595 ** for the seed and the entry box into which the user will type the text of
596 ** the captcha. This is typically done at the very bottom of a form.
597 **
598 ** This routine is a no-op if no captcha is required.
599 **
600 ** Flag values:
601 **
602 ** 0x01 Show the "Submit" button in the form.
603 ** 0x02 Always generate the captcha, even if not required
604 */
605 void captcha_generate(int mFlags){
606 unsigned int uSeed;
607 const char *zDecoded;
608 char *zCaptcha;
609
610 if( !captcha_needed() && (mFlags & 0x02)==0 ) return;
611 uSeed = captcha_seed();
612 zDecoded = captcha_decode(uSeed);
613 zCaptcha = captcha_render(zDecoded);
614 @ <div class="captcha"><table class="captcha"><tr><td><pre class="captcha">
615 @ %h(zCaptcha)
616 @ </pre>
617 @ Enter security code shown above:
618 @ <input type="hidden" name="captchaseed" value="%u(uSeed)">
619 @ <input type="text" name="captcha" size="8" autofocus>
620 if( mFlags & 0x01 ){
621 @ <input type="submit" value="Submit">
622 }
623 @ <br/>\
624 captcha_speakit_button(uSeed, 0);
625 @ </td></tr></table></div>
@@ -574,67 +643,93 @@
643 @ </script>
644 }
645
646 /*
647 ** WEBPAGE: test-captcha
648 **
649 ** If the name query parameter is provided, then render the hex value of
650 ** the name using the captcha font.
651 **
652 ** Otherwise render the captcha screen. The "show-button" parameter causes
653 ** the submit button to be rendered.
654 */
655 void captcha_test(void){
656 const char *zPw = P("name");
657 if( zPw==0 || zPw[0]==0 ){
658 (void)exclude_spiders(1);
659 @ <hr><p>The captcha is shown above. Add a name=HEX query parameter
660 @ to see how HEX would be rendered in the current captcha font.
661 @ <p>captcha_is_correct(1) returns %d(captcha_is_correct(1)).
662 style_finish_page();
663 }else{
664 style_set_current_feature("test");
665 style_header("Captcha Test");
666 @ <pre class="captcha">
667 @ %s(captcha_render(zPw))
668 @ </pre>
669 style_finish_page();
670 }
671 }
672
673 /*
674 ** Check to see if the current request is coming from an agent that
675 ** self-identifies as a spider.
676 **
677 ** If the agent does not claim to be a spider or if the user has logged
678 ** in (even as anonymous), then return 0 without doing anything.
679 **
680 ** But if the user agent does self-identify as a spider and there is
681 ** no login, offer a captcha challenge to allow the user agent to prove
682 ** that he is human and return non-zero.
683 **
684 ** If the bTest argument is non-zero, then show the captcha regardless of
685 ** how the agent identifies. This is used for testing only.
686 */
687 int exclude_spiders(int bTest){
688 if( !bTest && (g.isHuman || g.zLogin!=0) ) return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
689
690 /* This appears to be a spider. Offer the captcha */
691 style_set_current_feature("captcha");
692 style_header("I think you are a robot");
693 style_submenu_enable(0);
694 @ <form method='POST' action='%R/captchacb'>
695 @ <p>You seem like a robot.
696 @
697 @ <p>If you are human, you can prove that by solving the captcha below,
698 @ after which you will be allowed to proceed.
699 captcha_generate(3);
700 @ </form>
701 if( !bTest ){
702 if( P("fossil-goto")==0 ){
703 cgi_set_cookie("fossil-goto", cgi_reconstruct_original_url(), 0, 600);
704 }
705 cgi_append_header("X-Robot: 1\r\n");
706 style_finish_page();
707 }
708 return 1;
709 }
710
711 /*
712 ** WEBPAGE: captchacb
713 **
714 ** This is action for the form that is the captcha. Not intended
715 ** for external use.
716 **
717 ** If the captcha is correctly solved, then an anonymous login cookie
718 ** is set. Regardless of whether or not the captcha was solved, this
719 ** page always redirects to the fossil-goto cookie.
720 */
721 void captcha_callback(void){
722 if( captcha_is_correct(1) ){
723 login_set_anon_cookie(0, 0);
724 cgi_append_header("X-Robot: 0\r\n");
725 login_redirect_to_g();
726 }else{
727 exclude_spiders(0);
728 }
729 }
730
731
732 /*
733 ** Generate a WAV file that reads aloud the hex digits given by
734 ** zHex.
735 */
736
+1 -1
--- src/diff.c
+++ src/diff.c
@@ -3588,11 +3588,11 @@
35883588
int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
35893589
35903590
/* Gather query parameters */
35913591
login_check_credentials();
35923592
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
3593
- if( exclude_spiders() ) return;
3593
+ if( exclude_spiders(0) ) return;
35943594
fossil_nice_default();
35953595
zFilename = P("filename");
35963596
zRevision = PD("checkin",0);
35973597
zOrigin = P("origin");
35983598
zLimit = P("limit");
35993599
--- src/diff.c
+++ src/diff.c
@@ -3588,11 +3588,11 @@
3588 int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
3589
3590 /* Gather query parameters */
3591 login_check_credentials();
3592 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
3593 if( exclude_spiders() ) return;
3594 fossil_nice_default();
3595 zFilename = P("filename");
3596 zRevision = PD("checkin",0);
3597 zOrigin = P("origin");
3598 zLimit = P("limit");
3599
--- src/diff.c
+++ src/diff.c
@@ -3588,11 +3588,11 @@
3588 int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
3589
3590 /* Gather query parameters */
3591 login_check_credentials();
3592 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
3593 if( exclude_spiders(0) ) return;
3594 fossil_nice_default();
3595 zFilename = P("filename");
3596 zRevision = PD("checkin",0);
3597 zOrigin = P("origin");
3598 zLimit = P("limit");
3599
--- src/json_login.c
+++ src/json_login.c
@@ -145,11 +145,11 @@
145145
}else{
146146
char * cookie = NULL;
147147
cson_object * po;
148148
char * cap = NULL;
149149
if(anonSeed){
150
- login_set_anon_cookie(NULL, &cookie, 0);
150
+ login_set_anon_cookie(&cookie, 0);
151151
}else{
152152
login_set_user_cookie(name, uid, &cookie, 0);
153153
}
154154
payload = cson_value_new_object();
155155
po = cson_value_get_object(payload);
156156
--- src/json_login.c
+++ src/json_login.c
@@ -145,11 +145,11 @@
145 }else{
146 char * cookie = NULL;
147 cson_object * po;
148 char * cap = NULL;
149 if(anonSeed){
150 login_set_anon_cookie(NULL, &cookie, 0);
151 }else{
152 login_set_user_cookie(name, uid, &cookie, 0);
153 }
154 payload = cson_value_new_object();
155 po = cson_value_get_object(payload);
156
--- src/json_login.c
+++ src/json_login.c
@@ -145,11 +145,11 @@
145 }else{
146 char * cookie = NULL;
147 cson_object * po;
148 char * cap = NULL;
149 if(anonSeed){
150 login_set_anon_cookie(&cookie, 0);
151 }else{
152 login_set_user_cookie(name, uid, &cookie, 0);
153 }
154 payload = cson_value_new_object();
155 po = cson_value_get_object(payload);
156
+16 -15
--- src/login.c
+++ src/login.c
@@ -117,11 +117,11 @@
117117
118118
/*
119119
** Redirect to the page specified by the "g" query parameter.
120120
** Or if there is no "g" query parameter, redirect to the homepage.
121121
*/
122
-static void redirect_to_g(void){
122
+NORETURN void login_redirect_to_g(void){
123123
const char *zGoto = P("g");
124124
if( zGoto ){
125125
cgi_redirectf("%R/%s",zGoto);
126126
}else if( (zGoto = P("fossil-goto"))!=0 && zGoto[0]!=0 ){
127127
cgi_set_cookie("fossil-goto","",0,1);
@@ -345,12 +345,11 @@
345345
** If zCookieDest is not NULL then the generated cookie is assigned to
346346
** *zCookieDest and the caller must eventually free() it.
347347
**
348348
** If bSessionCookie is true, the cookie will be a session cookie.
349349
*/
350
-void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest,
351
- int bSessionCookie ){
350
+void login_set_anon_cookie(char **zCookieDest, int bSessionCookie){
352351
const char *zNow; /* Current time (julian day number) */
353352
char *zCookie; /* The login cookie */
354353
const char *zCookieName; /* Name of the login cookie */
355354
Blob b; /* Blob used during cookie construction */
356355
int expires = bSessionCookie ? 0 : 6*3600;
@@ -586,11 +585,11 @@
586585
zPasswd = P("p");
587586
anonFlag = g.zLogin==0 && PB("anon");
588587
/* Handle log-out requests */
589588
if( P("out") && cgi_csrf_safe(2) ){
590589
login_clear_login_data();
591
- redirect_to_g();
590
+ login_redirect_to_g();
592591
return;
593592
}
594593
595594
/* Redirect for create-new-account requests */
596595
if( P("self") ){
@@ -659,11 +658,11 @@
659658
660659
if( rc ){
661660
zErrMsg = mprintf("<span class=\"loginError\">%s</span>", zErr);
662661
fossil_free(zErr);
663662
}else{
664
- redirect_to_g();
663
+ login_redirect_to_g();
665664
return;
666665
}
667666
}
668667
}else{
669668
zErrMsg =
@@ -681,13 +680,13 @@
681680
rememberMe = 0;
682681
}else{
683682
rememberMe = P("remember")!=0;
684683
}
685684
if( uid>0 ){
686
- login_set_anon_cookie(zIpAddr, NULL, rememberMe?0:1);
685
+ login_set_anon_cookie(NULL, rememberMe?0:1);
687686
record_login_attempt("anonymous", zIpAddr, 1);
688
- redirect_to_g();
687
+ login_redirect_to_g();
689688
}
690689
if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
691690
/* Attempting to log in as a user other than anonymous.
692691
*/
693692
uid = login_search_uid(&zUsername, zPasswd);
@@ -707,11 +706,11 @@
707706
**
708707
** where HASH is a random hex number, PROJECT is either project
709708
** code prefix, and LOGIN is the user name.
710709
*/
711710
login_set_user_cookie(zUsername, uid, NULL, rememberMe?0:1);
712
- redirect_to_g();
711
+ login_redirect_to_g();
713712
}
714713
}
715714
style_set_current_feature("login");
716715
style_header("Login/Logout");
717716
style_adunit_config(ADUNIT_OFF);
@@ -1291,27 +1290,29 @@
12911290
*/
12921291
void login_restrict_robot_access(void){
12931292
const char *zReferer;
12941293
const char *zGlob;
12951294
Glob *pGlob;
1296
- int go = 1;
1295
+ int isMatch = 1;
12971296
if( g.zLogin!=0 ) return;
12981297
zReferer = P("HTTP_REFERER");
12991298
if( zReferer && zReferer[0]!=0 ) return;
13001299
zGlob = db_get("robot-restrict",0);
13011300
if( zGlob==0 || zGlob[0]==0 ) return;
13021301
if( cgi_qp_count()<1 ) return;
13031302
pGlob = glob_create(zGlob);
1304
- go = glob_match(pGlob, g.zPath);
1303
+ isMatch = glob_match(pGlob, g.zPath);
13051304
glob_free(pGlob);
1306
- if( !go ) return;
1305
+ if( !isMatch ) return;
13071306
13081307
/* If we reach this point, it means we have a situation where we
13091308
** want to restrict the activity of a robot.
13101309
*/
1311
- cgi_set_cookie("fossil-goto", cgi_reconstruct_original_url(), 0, 600);
1312
- cgi_redirectf("%R/honeypot");
1310
+ g.isHuman = 0;
1311
+ (void)exclude_spiders(0);
1312
+ cgi_reply();
1313
+ fossil_exit(0);
13131314
}
13141315
13151316
/*
13161317
** This routine examines the login cookie to see if it exists and
13171318
** is valid. If the login cookie checks out, it then sets global
@@ -2139,11 +2140,11 @@
21392140
if( db_exists("SELECT 1 FROM subscriber WHERE semail=%Q"
21402141
" AND sverified", zEAddr) ){
21412142
/* This the case where the user was formerly a verified subscriber
21422143
** and here they have also registered as a user as well. It is
21432144
** not necessary to repeat the verfication step */
2144
- redirect_to_g();
2145
+ login_redirect_to_g();
21452146
}
21462147
/* A verification email */
21472148
pSender = alert_sender_new(0,0);
21482149
blob_init(&hdr,0,0);
21492150
blob_init(&body,0,0);
@@ -2168,11 +2169,11 @@
21682169
@ <p><a href='%h(zGoto)'>Continue</a>
21692170
}
21702171
style_finish_page();
21712172
return;
21722173
}
2173
- redirect_to_g();
2174
+ login_redirect_to_g();
21742175
}
21752176
21762177
/* Prepare the captcha. */
21772178
if( captchaIsCorrect ){
21782179
uSeed = strtoul(P("captchaseed"),0,10);
21792180
--- src/login.c
+++ src/login.c
@@ -117,11 +117,11 @@
117
118 /*
119 ** Redirect to the page specified by the "g" query parameter.
120 ** Or if there is no "g" query parameter, redirect to the homepage.
121 */
122 static void redirect_to_g(void){
123 const char *zGoto = P("g");
124 if( zGoto ){
125 cgi_redirectf("%R/%s",zGoto);
126 }else if( (zGoto = P("fossil-goto"))!=0 && zGoto[0]!=0 ){
127 cgi_set_cookie("fossil-goto","",0,1);
@@ -345,12 +345,11 @@
345 ** If zCookieDest is not NULL then the generated cookie is assigned to
346 ** *zCookieDest and the caller must eventually free() it.
347 **
348 ** If bSessionCookie is true, the cookie will be a session cookie.
349 */
350 void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest,
351 int bSessionCookie ){
352 const char *zNow; /* Current time (julian day number) */
353 char *zCookie; /* The login cookie */
354 const char *zCookieName; /* Name of the login cookie */
355 Blob b; /* Blob used during cookie construction */
356 int expires = bSessionCookie ? 0 : 6*3600;
@@ -586,11 +585,11 @@
586 zPasswd = P("p");
587 anonFlag = g.zLogin==0 && PB("anon");
588 /* Handle log-out requests */
589 if( P("out") && cgi_csrf_safe(2) ){
590 login_clear_login_data();
591 redirect_to_g();
592 return;
593 }
594
595 /* Redirect for create-new-account requests */
596 if( P("self") ){
@@ -659,11 +658,11 @@
659
660 if( rc ){
661 zErrMsg = mprintf("<span class=\"loginError\">%s</span>", zErr);
662 fossil_free(zErr);
663 }else{
664 redirect_to_g();
665 return;
666 }
667 }
668 }else{
669 zErrMsg =
@@ -681,13 +680,13 @@
681 rememberMe = 0;
682 }else{
683 rememberMe = P("remember")!=0;
684 }
685 if( uid>0 ){
686 login_set_anon_cookie(zIpAddr, NULL, rememberMe?0:1);
687 record_login_attempt("anonymous", zIpAddr, 1);
688 redirect_to_g();
689 }
690 if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
691 /* Attempting to log in as a user other than anonymous.
692 */
693 uid = login_search_uid(&zUsername, zPasswd);
@@ -707,11 +706,11 @@
707 **
708 ** where HASH is a random hex number, PROJECT is either project
709 ** code prefix, and LOGIN is the user name.
710 */
711 login_set_user_cookie(zUsername, uid, NULL, rememberMe?0:1);
712 redirect_to_g();
713 }
714 }
715 style_set_current_feature("login");
716 style_header("Login/Logout");
717 style_adunit_config(ADUNIT_OFF);
@@ -1291,27 +1290,29 @@
1291 */
1292 void login_restrict_robot_access(void){
1293 const char *zReferer;
1294 const char *zGlob;
1295 Glob *pGlob;
1296 int go = 1;
1297 if( g.zLogin!=0 ) return;
1298 zReferer = P("HTTP_REFERER");
1299 if( zReferer && zReferer[0]!=0 ) return;
1300 zGlob = db_get("robot-restrict",0);
1301 if( zGlob==0 || zGlob[0]==0 ) return;
1302 if( cgi_qp_count()<1 ) return;
1303 pGlob = glob_create(zGlob);
1304 go = glob_match(pGlob, g.zPath);
1305 glob_free(pGlob);
1306 if( !go ) return;
1307
1308 /* If we reach this point, it means we have a situation where we
1309 ** want to restrict the activity of a robot.
1310 */
1311 cgi_set_cookie("fossil-goto", cgi_reconstruct_original_url(), 0, 600);
1312 cgi_redirectf("%R/honeypot");
 
 
1313 }
1314
1315 /*
1316 ** This routine examines the login cookie to see if it exists and
1317 ** is valid. If the login cookie checks out, it then sets global
@@ -2139,11 +2140,11 @@
2139 if( db_exists("SELECT 1 FROM subscriber WHERE semail=%Q"
2140 " AND sverified", zEAddr) ){
2141 /* This the case where the user was formerly a verified subscriber
2142 ** and here they have also registered as a user as well. It is
2143 ** not necessary to repeat the verfication step */
2144 redirect_to_g();
2145 }
2146 /* A verification email */
2147 pSender = alert_sender_new(0,0);
2148 blob_init(&hdr,0,0);
2149 blob_init(&body,0,0);
@@ -2168,11 +2169,11 @@
2168 @ <p><a href='%h(zGoto)'>Continue</a>
2169 }
2170 style_finish_page();
2171 return;
2172 }
2173 redirect_to_g();
2174 }
2175
2176 /* Prepare the captcha. */
2177 if( captchaIsCorrect ){
2178 uSeed = strtoul(P("captchaseed"),0,10);
2179
--- src/login.c
+++ src/login.c
@@ -117,11 +117,11 @@
117
118 /*
119 ** Redirect to the page specified by the "g" query parameter.
120 ** Or if there is no "g" query parameter, redirect to the homepage.
121 */
122 NORETURN void login_redirect_to_g(void){
123 const char *zGoto = P("g");
124 if( zGoto ){
125 cgi_redirectf("%R/%s",zGoto);
126 }else if( (zGoto = P("fossil-goto"))!=0 && zGoto[0]!=0 ){
127 cgi_set_cookie("fossil-goto","",0,1);
@@ -345,12 +345,11 @@
345 ** If zCookieDest is not NULL then the generated cookie is assigned to
346 ** *zCookieDest and the caller must eventually free() it.
347 **
348 ** If bSessionCookie is true, the cookie will be a session cookie.
349 */
350 void login_set_anon_cookie(char **zCookieDest, int bSessionCookie){
 
351 const char *zNow; /* Current time (julian day number) */
352 char *zCookie; /* The login cookie */
353 const char *zCookieName; /* Name of the login cookie */
354 Blob b; /* Blob used during cookie construction */
355 int expires = bSessionCookie ? 0 : 6*3600;
@@ -586,11 +585,11 @@
585 zPasswd = P("p");
586 anonFlag = g.zLogin==0 && PB("anon");
587 /* Handle log-out requests */
588 if( P("out") && cgi_csrf_safe(2) ){
589 login_clear_login_data();
590 login_redirect_to_g();
591 return;
592 }
593
594 /* Redirect for create-new-account requests */
595 if( P("self") ){
@@ -659,11 +658,11 @@
658
659 if( rc ){
660 zErrMsg = mprintf("<span class=\"loginError\">%s</span>", zErr);
661 fossil_free(zErr);
662 }else{
663 login_redirect_to_g();
664 return;
665 }
666 }
667 }else{
668 zErrMsg =
@@ -681,13 +680,13 @@
680 rememberMe = 0;
681 }else{
682 rememberMe = P("remember")!=0;
683 }
684 if( uid>0 ){
685 login_set_anon_cookie(NULL, rememberMe?0:1);
686 record_login_attempt("anonymous", zIpAddr, 1);
687 login_redirect_to_g();
688 }
689 if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
690 /* Attempting to log in as a user other than anonymous.
691 */
692 uid = login_search_uid(&zUsername, zPasswd);
@@ -707,11 +706,11 @@
706 **
707 ** where HASH is a random hex number, PROJECT is either project
708 ** code prefix, and LOGIN is the user name.
709 */
710 login_set_user_cookie(zUsername, uid, NULL, rememberMe?0:1);
711 login_redirect_to_g();
712 }
713 }
714 style_set_current_feature("login");
715 style_header("Login/Logout");
716 style_adunit_config(ADUNIT_OFF);
@@ -1291,27 +1290,29 @@
1290 */
1291 void login_restrict_robot_access(void){
1292 const char *zReferer;
1293 const char *zGlob;
1294 Glob *pGlob;
1295 int isMatch = 1;
1296 if( g.zLogin!=0 ) return;
1297 zReferer = P("HTTP_REFERER");
1298 if( zReferer && zReferer[0]!=0 ) return;
1299 zGlob = db_get("robot-restrict",0);
1300 if( zGlob==0 || zGlob[0]==0 ) return;
1301 if( cgi_qp_count()<1 ) return;
1302 pGlob = glob_create(zGlob);
1303 isMatch = glob_match(pGlob, g.zPath);
1304 glob_free(pGlob);
1305 if( !isMatch ) return;
1306
1307 /* If we reach this point, it means we have a situation where we
1308 ** want to restrict the activity of a robot.
1309 */
1310 g.isHuman = 0;
1311 (void)exclude_spiders(0);
1312 cgi_reply();
1313 fossil_exit(0);
1314 }
1315
1316 /*
1317 ** This routine examines the login cookie to see if it exists and
1318 ** is valid. If the login cookie checks out, it then sets global
@@ -2139,11 +2140,11 @@
2140 if( db_exists("SELECT 1 FROM subscriber WHERE semail=%Q"
2141 " AND sverified", zEAddr) ){
2142 /* This the case where the user was formerly a verified subscriber
2143 ** and here they have also registered as a user as well. It is
2144 ** not necessary to repeat the verfication step */
2145 login_redirect_to_g();
2146 }
2147 /* A verification email */
2148 pSender = alert_sender_new(0,0);
2149 blob_init(&hdr,0,0);
2150 blob_init(&body,0,0);
@@ -2168,11 +2169,11 @@
2169 @ <p><a href='%h(zGoto)'>Continue</a>
2170 }
2171 style_finish_page();
2172 return;
2173 }
2174 login_redirect_to_g();
2175 }
2176
2177 /* Prepare the captcha. */
2178 if( captchaIsCorrect ){
2179 uSeed = strtoul(P("captchaseed"),0,10);
2180

Keyboard Shortcuts

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