Fossil SCM

Improved anti-robot captcha.

drh 2025-08-16 13:57 robot-restrict-simplified
Commit 206089acd1be4b95e8315d5e8063ac26c6f15b77c3035c535a594b387cf12591
1 file changed +70 -19
+70 -19
--- src/robot.c
+++ src/robot.c
@@ -22,10 +22,12 @@
2222
#include "config.h"
2323
#include "robot.h"
2424
#include <assert.h>
2525
#include <time.h>
2626
27
+#define POW_COOKIE "fossil-proofofwork"
28
+
2729
/*
2830
** Rewrite the current page with a robot squelch captcha and return 1.
2931
**
3032
** Or, if valid proof-of-work is present as either a query parameter or
3133
** as a cookie, then return 0.
@@ -61,14 +63,14 @@
6163
h2 = (h2 % 900000000) + 100000000;
6264
6365
/* If there is already a proof-of-work cookie with this value
6466
** that means that the user agent has already authenticated.
6567
*/
66
- z = P("fossil-proofofwork");
68
+ z = P(POW_COOKIE);
6769
if( z
6870
&& (atoi(z)==h1 || atoi(z)==h2)
69
- && !cgi_is_qp("fossil-proofofwork") ){
71
+ && !cgi_is_qp(POW_COOKIE) ){
7072
return 0;
7173
}
7274
7375
/* Check for a proof query parameter. If found, that means that
7476
** the captcha has just now passed, so set the proof-of-work cookie
@@ -76,39 +78,45 @@
7678
*/
7779
z = P("proof");
7880
if( z
7981
&& (atoi(z)==h1 || atoi(z)==h2)
8082
){
81
- cgi_set_cookie("fossil-proofofwork",z,"/",900);
83
+ cgi_set_cookie(POW_COOKIE,z,"/",900);
8284
return 0;
8385
}
8486
cgi_tag_query_parameter("proof");
8587
8688
/* Ask the client to present proof-of-work */
8789
cgi_reset_content();
8890
cgi_set_content_type("text/html");
89
- style_header("Captcha");
90
- @ <h1>Prove That You Are Human</h1>
91
+ style_header("Browser Verification");
92
+ @ <h1 id="x1">Checking to see if you are a robot<span id="x2"></span></h1>
9193
@ <form method="GET">
92
- @ <p>Press the button below</p><p>
94
+ @ <p id="x3" style="visibility:hidden;">\
95
+ @ Press <input type="submit" id="x5" value="Ok" focus> to continue</p>
9396
cgi_query_parameters_to_hidden();
94
- @ <input id="vx" type="hidden" name="proof" value="0">
95
- @ <input id="cx" type="submit" value="Wait..." disabled>
97
+ @ <input id="x4" type="hidden" name="proof" value="0">
9698
@ </form>
9799
@ <script nonce='%s(style_nonce())'>
98
- @ function Nhtot1520(x){return document.getElementById(x);}
99
- @ function Aoxlxzajv(h){\
100
- @ Nhtot1520("vx").value=h;\
101
- @ Nhtot1520("cx").value="Ok";\
102
- @ Nhtot1520("cx").disabled=false;\
103
- @ }
104
- @ function Vhcnyarsm(h,a){\
105
- @ if(a>0){setTimeout(Vhcnyarsm,1,h+a,a-1);}else{Aoxlxzajv(h);}\
106
- @ }
107
- k = 200 + h2%99;
100
+ @ function aaa(x){return document.getElementById(x);}
101
+ @ function bbb(h,a){
102
+ @ aaa("x4").value=h
103
+ @ if((a%%75)==0){
104
+ @ aaa("x2").textContent=aaa("x2").textContent+".";
105
+ @ }
106
+ @ if(a>0){
107
+ @ setTimeout(bbb,1,h+a,a-1);
108
+ @ }else{
109
+ @ aaa("x3").style.visibility="visible";
110
+ @ aaa("x2").textContent="";
111
+ @ aaa("x1").textContent="All clear";
112
+ @ aaa("x5").focus();
113
+ @ }
114
+ @ }
115
+ k = 800 + h2%99;
108116
h2 = (k*k + k)/2;
109
- @ setTimeout(function(){Vhcnyarsm(%u(h1-h2),%u(k));},10);
117
+ @ setTimeout(function(){bbb(%u(h1-h2),%u(k));},10);
110118
@ </script>
111119
style_finish_page();
112120
return 1;
113121
}
114122
@@ -162,5 +170,48 @@
162170
if( robot_proofofwork() ){
163171
return 1;
164172
}
165173
return 0;
166174
}
175
+
176
+
177
+/*
178
+** WEBPAGE: test-robotck
179
+**
180
+** Run the robot_restrict() function using the value of the "name="
181
+** query parameter as an argument. Used for testing the robot_restrict()
182
+** logic.
183
+**
184
+** Whenever this page is successfully rendered (when it doesn't go to
185
+** the captcha) it deletes the proof-of-work cookie. So reloading the
186
+** page will reset the cookie and restart the verification.
187
+*/
188
+void robot_restrict_test_page(void){
189
+ const char *zName = P("name");
190
+ const char *zP1 = P("proof");
191
+ const char *zP2 = P(POW_COOKIE);
192
+ const char *z;
193
+ if( zName==0 || zName[0]==0 ) zName = g.zPath;
194
+ login_check_credentials();
195
+ if( !g.perm.Admin ){ login_needed(0); return; }
196
+ g.zLogin = 0;
197
+ if( robot_restrict(zName) ) return;
198
+ style_set_current_feature("test");
199
+ style_header("robot_restrict() test");
200
+ @ <h1>Captcha passed</h1>
201
+ @
202
+ @ <p>
203
+ if( zP1 && zP1[0] ){
204
+ @ proof=%h(zP1)<br>
205
+ }
206
+ if( zP2 && zP2[0] ){
207
+ @ fossil_proofofwork=%h(zP2)<br>
208
+ cgi_set_cookie(POW_COOKIE,"",0,-1);
209
+ }
210
+ z = db_get("robot-restrict",robot_restrict_default());
211
+ if( z && z[0] ){
212
+ @ robot-restrict=%h(z)</br>
213
+ }
214
+ @ </p>
215
+ @ <p><a href="%R/test-robotck/%h(zName)">Retry</a>
216
+ style_finish_page();
217
+}
167218
--- src/robot.c
+++ src/robot.c
@@ -22,10 +22,12 @@
22 #include "config.h"
23 #include "robot.h"
24 #include <assert.h>
25 #include <time.h>
26
 
 
27 /*
28 ** Rewrite the current page with a robot squelch captcha and return 1.
29 **
30 ** Or, if valid proof-of-work is present as either a query parameter or
31 ** as a cookie, then return 0.
@@ -61,14 +63,14 @@
61 h2 = (h2 % 900000000) + 100000000;
62
63 /* If there is already a proof-of-work cookie with this value
64 ** that means that the user agent has already authenticated.
65 */
66 z = P("fossil-proofofwork");
67 if( z
68 && (atoi(z)==h1 || atoi(z)==h2)
69 && !cgi_is_qp("fossil-proofofwork") ){
70 return 0;
71 }
72
73 /* Check for a proof query parameter. If found, that means that
74 ** the captcha has just now passed, so set the proof-of-work cookie
@@ -76,39 +78,45 @@
76 */
77 z = P("proof");
78 if( z
79 && (atoi(z)==h1 || atoi(z)==h2)
80 ){
81 cgi_set_cookie("fossil-proofofwork",z,"/",900);
82 return 0;
83 }
84 cgi_tag_query_parameter("proof");
85
86 /* Ask the client to present proof-of-work */
87 cgi_reset_content();
88 cgi_set_content_type("text/html");
89 style_header("Captcha");
90 @ <h1>Prove That You Are Human</h1>
91 @ <form method="GET">
92 @ <p>Press the button below</p><p>
 
93 cgi_query_parameters_to_hidden();
94 @ <input id="vx" type="hidden" name="proof" value="0">
95 @ <input id="cx" type="submit" value="Wait..." disabled>
96 @ </form>
97 @ <script nonce='%s(style_nonce())'>
98 @ function Nhtot1520(x){return document.getElementById(x);}
99 @ function Aoxlxzajv(h){\
100 @ Nhtot1520("vx").value=h;\
101 @ Nhtot1520("cx").value="Ok";\
102 @ Nhtot1520("cx").disabled=false;\
103 @ }
104 @ function Vhcnyarsm(h,a){\
105 @ if(a>0){setTimeout(Vhcnyarsm,1,h+a,a-1);}else{Aoxlxzajv(h);}\
106 @ }
107 k = 200 + h2%99;
 
 
 
 
 
 
108 h2 = (k*k + k)/2;
109 @ setTimeout(function(){Vhcnyarsm(%u(h1-h2),%u(k));},10);
110 @ </script>
111 style_finish_page();
112 return 1;
113 }
114
@@ -162,5 +170,48 @@
162 if( robot_proofofwork() ){
163 return 1;
164 }
165 return 0;
166 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
--- src/robot.c
+++ src/robot.c
@@ -22,10 +22,12 @@
22 #include "config.h"
23 #include "robot.h"
24 #include <assert.h>
25 #include <time.h>
26
27 #define POW_COOKIE "fossil-proofofwork"
28
29 /*
30 ** Rewrite the current page with a robot squelch captcha and return 1.
31 **
32 ** Or, if valid proof-of-work is present as either a query parameter or
33 ** as a cookie, then return 0.
@@ -61,14 +63,14 @@
63 h2 = (h2 % 900000000) + 100000000;
64
65 /* If there is already a proof-of-work cookie with this value
66 ** that means that the user agent has already authenticated.
67 */
68 z = P(POW_COOKIE);
69 if( z
70 && (atoi(z)==h1 || atoi(z)==h2)
71 && !cgi_is_qp(POW_COOKIE) ){
72 return 0;
73 }
74
75 /* Check for a proof query parameter. If found, that means that
76 ** the captcha has just now passed, so set the proof-of-work cookie
@@ -76,39 +78,45 @@
78 */
79 z = P("proof");
80 if( z
81 && (atoi(z)==h1 || atoi(z)==h2)
82 ){
83 cgi_set_cookie(POW_COOKIE,z,"/",900);
84 return 0;
85 }
86 cgi_tag_query_parameter("proof");
87
88 /* Ask the client to present proof-of-work */
89 cgi_reset_content();
90 cgi_set_content_type("text/html");
91 style_header("Browser Verification");
92 @ <h1 id="x1">Checking to see if you are a robot<span id="x2"></span></h1>
93 @ <form method="GET">
94 @ <p id="x3" style="visibility:hidden;">\
95 @ Press <input type="submit" id="x5" value="Ok" focus> to continue</p>
96 cgi_query_parameters_to_hidden();
97 @ <input id="x4" type="hidden" name="proof" value="0">
 
98 @ </form>
99 @ <script nonce='%s(style_nonce())'>
100 @ function aaa(x){return document.getElementById(x);}
101 @ function bbb(h,a){
102 @ aaa("x4").value=h
103 @ if((a%%75)==0){
104 @ aaa("x2").textContent=aaa("x2").textContent+".";
105 @ }
106 @ if(a>0){
107 @ setTimeout(bbb,1,h+a,a-1);
108 @ }else{
109 @ aaa("x3").style.visibility="visible";
110 @ aaa("x2").textContent="";
111 @ aaa("x1").textContent="All clear";
112 @ aaa("x5").focus();
113 @ }
114 @ }
115 k = 800 + h2%99;
116 h2 = (k*k + k)/2;
117 @ setTimeout(function(){bbb(%u(h1-h2),%u(k));},10);
118 @ </script>
119 style_finish_page();
120 return 1;
121 }
122
@@ -162,5 +170,48 @@
170 if( robot_proofofwork() ){
171 return 1;
172 }
173 return 0;
174 }
175
176
177 /*
178 ** WEBPAGE: test-robotck
179 **
180 ** Run the robot_restrict() function using the value of the "name="
181 ** query parameter as an argument. Used for testing the robot_restrict()
182 ** logic.
183 **
184 ** Whenever this page is successfully rendered (when it doesn't go to
185 ** the captcha) it deletes the proof-of-work cookie. So reloading the
186 ** page will reset the cookie and restart the verification.
187 */
188 void robot_restrict_test_page(void){
189 const char *zName = P("name");
190 const char *zP1 = P("proof");
191 const char *zP2 = P(POW_COOKIE);
192 const char *z;
193 if( zName==0 || zName[0]==0 ) zName = g.zPath;
194 login_check_credentials();
195 if( !g.perm.Admin ){ login_needed(0); return; }
196 g.zLogin = 0;
197 if( robot_restrict(zName) ) return;
198 style_set_current_feature("test");
199 style_header("robot_restrict() test");
200 @ <h1>Captcha passed</h1>
201 @
202 @ <p>
203 if( zP1 && zP1[0] ){
204 @ proof=%h(zP1)<br>
205 }
206 if( zP2 && zP2[0] ){
207 @ fossil_proofofwork=%h(zP2)<br>
208 cgi_set_cookie(POW_COOKIE,"",0,-1);
209 }
210 z = db_get("robot-restrict",robot_restrict_default());
211 if( z && z[0] ){
212 @ robot-restrict=%h(z)</br>
213 }
214 @ </p>
215 @ <p><a href="%R/test-robotck/%h(zName)">Retry</a>
216 style_finish_page();
217 }
218

Keyboard Shortcuts

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