Fossil SCM

Add an ascii-art captcha for anonymous login.

drh 2009-08-10 02:29 trunk
Commit b4a29fac93a027384bf30d0a9acb851dae03a367
--- a/src/captcha.c
+++ b/src/captcha.c
@@ -0,0 +1,11 @@
1
+/*
2
+** Copyriprintfprintf(hGNU General Public
3
+** License version 2 as published by the Free Software Foundation.
4
+**WITHOUT ANY WARRANTYMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5
+** General Public License for more details.
6
+**
7
+** You should have received a copy of the GNU General Public
8
+** License along with this library; if not, write to the
9
+** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
10
+** Boston, MA 02111-1307, USACopyriprintfprintf(h/*
11
+** Copyriprintfprintf(h2 32-bit unsigned integer as an 85 32-bit unsigned integer as an 83
--- a/src/captcha.c
+++ b/src/captcha.c
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
--- a/src/captcha.c
+++ b/src/captcha.c
@@ -0,0 +1,11 @@
1 /*
2 ** Copyriprintfprintf(hGNU General Public
3 ** License version 2 as published by the Free Software Foundation.
4 **WITHOUT ANY WARRANTYMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5 ** General Public License for more details.
6 **
7 ** You should have received a copy of the GNU General Public
8 ** License along with this library; if not, write to the
9 ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
10 ** Boston, MA 02111-1307, USACopyriprintfprintf(h/*
11 ** Copyriprintfprintf(h2 32-bit unsigned integer as an 85 32-bit unsigned integer as an 83
+92 -28
--- src/login.c
+++ src/login.c
@@ -77,10 +77,34 @@
7777
cgi_redirect(zGoto);
7878
}else{
7979
fossil_redirect_home();
8080
}
8181
}
82
+
83
+/*
84
+** Check to see if the anonymous login is valid. If it is valid, return
85
+** the userid of the anonymous user.
86
+*/
87
+static int isValidAnonymousLogin(
88
+ const char *zUsername, /* The username. Must be "anonymous" */
89
+ const char *zPassword /* The supplied password */
90
+){
91
+ const char *zCS; /* The captcha seed value */
92
+ const char *zPw; /* The correct password shown in the captcha */
93
+ int uid; /* The user ID of anonymous */
94
+
95
+ if( zUsername==0 ) return 0;
96
+ if( zPassword==0 ) return 0;
97
+ if( strcmp(zUsername,"anonymous")!=0 ) return 0;
98
+ zCS = P("cs"); /* The "cs" parameter is the "captcha seed" */
99
+ if( zCS==0 ) return 0;
100
+ zPw = captcha_decode((unsigned int)atoi(zCS));
101
+ if( strcasecmp(zPw, zPassword)!=0 ) return 0;
102
+ uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'"
103
+ " AND length(pw)>0 AND length(cap)>0");
104
+ return uid;
105
+}
82106
83107
/*
84108
** WEBPAGE: /login
85109
** WEBPAGE: /logout
86110
**
@@ -90,10 +114,11 @@
90114
const char *zUsername, *zPasswd;
91115
const char *zNew1, *zNew2;
92116
const char *zAnonPw = 0;
93117
int anonFlag;
94118
char *zErrMsg = "";
119
+ int uid; /* User id loged in user */
95120
96121
login_check_credentials();
97122
zUsername = P("u");
98123
zPasswd = P("p");
99124
anonFlag = P("anon")!=0;
@@ -124,13 +149,33 @@
124149
"UPDATE user SET pw=%Q WHERE uid=%d", zNew1, g.userUid
125150
);
126151
redirect_to_g();
127152
return;
128153
}
154
+ }
155
+ uid = isValidAnonymousLogin(zUsername, zPasswd);
156
+ if( uid>0 ){
157
+ char *zNow; /* Current time (julian day number) */
158
+ const char *zIpAddr; /* IP address of requestor */
159
+ char *zCookie; /* The login cookie */
160
+ const char *zCookieName; /* Name of the login cookie */
161
+ Blob b; /* Blob used during cookie construction */
162
+
163
+ zIpAddr = PD("REMOTE_ADDR","nil");
164
+ zCookieName = login_cookie_name();
165
+ zNow = db_text("0", "SELECT julianday('now')");
166
+ blob_init(&b, zNow, -1);
167
+ blob_appendf(&b, "/%s/%s", zIpAddr, db_get("captcha-secret",""));
168
+ sha1sum_blob(&b, &b);
169
+ zCookie = sqlite3_mprintf("anon/%s/%s", zNow, blob_buffer(&b));
170
+ blob_reset(&b);
171
+ free(zNow);
172
+ cgi_set_cookie(zCookieName, zCookie, 0, 6*3600);
173
+ redirect_to_g();
129174
}
130175
if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
131
- int uid = db_int(0,
176
+ uid = db_int(0,
132177
"SELECT uid FROM user"
133178
" WHERE login=%Q AND pw=%Q", zUsername, zPasswd);
134179
if( uid<=0 || strcmp(zUsername,"nobody")==0 ){
135180
sleep(1);
136181
zErrMsg =
@@ -143,21 +188,17 @@
143188
const char *zCookieName = login_cookie_name();
144189
const char *zExpire = db_get("cookie-expire","8766");
145190
int expires = atoi(zExpire)*3600;
146191
const char *zIpAddr = PD("REMOTE_ADDR","nil");
147192
148
- if( strcmp(zUsername, "anonymous")==0 ){
149
- cgi_set_cookie(zCookieName, "anonymous", 0, expires);
150
- }else{
151
- zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid);
152
- cgi_set_cookie(zCookieName, zCookie, 0, expires);
153
- db_multi_exec(
154
- "UPDATE user SET cookie=%Q, ipaddr=%Q, "
155
- " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
156
- zCookie, zIpAddr, expires, uid
157
- );
158
- }
193
+ zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid);
194
+ cgi_set_cookie(zCookieName, zCookie, 0, expires);
195
+ db_multi_exec(
196
+ "UPDATE user SET cookie=%Q, ipaddr=%Q, "
197
+ " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
198
+ zCookie, zIpAddr, expires, uid
199
+ );
159200
redirect_to_g();
160201
}
161202
}
162203
style_header("Login/Logout");
163204
@ %s(zErrMsg)
@@ -180,15 +221,10 @@
180221
@ </tr>
181222
if( g.zLogin==0 ){
182223
zAnonPw = db_text(0, "SELECT pw FROM user"
183224
" WHERE login='anonymous'"
184225
" AND cap!=''");
185
- if( zAnonPw && anonFlag ){
186
- @ <tr><td></td>
187
- @ <td>The anonymous password is "<b>%h(zAnonPw)</b>".</td>
188
- @ </tr>
189
- }
190226
}
191227
@ <tr>
192228
@ <td></td>
193229
@ <td><input type="submit" name="in" value="Login"></td>
194230
@ </tr>
@@ -201,17 +237,21 @@
201237
}
202238
@ enter the user-id and password at the left and press the
203239
@ "Login" button. Your user name will be stored in a browser cookie.
204240
@ You must configure your web browser to accept cookies in order for
205241
@ the login to take.</p>
206
- if( g.zLogin==0 ){
207
- if( zAnonPw && !anonFlag ){
208
- @ <p>The password for user "anonymous" is "<b>%h(zAnonPw)</b>".</p>
209
- @ <p>&nbsp;</p>
210
- }else{
211
- @ <p>&nbsp;</p><p>&nbsp;</p>
212
- }
242
+ if( zAnonPw ){
243
+ unsigned int uSeed = captcha_seed();
244
+ char *zCaptcha = captcha_render(captcha_decode(uSeed));
245
+
246
+ @ <input type="hidden" name="cs" value="%u(uSeed)">
247
+ @ <p>To login as user <b>anonymous</b> use the following
248
+ @ 8-character hexadecimal password:</p>
249
+ @ <center><table border="1" cellpadding="10"><tr><td><pre>
250
+ @ %s(zCaptcha)
251
+ @ </pre></td></tr></table></center>
252
+ free(zCaptcha);
213253
}
214254
if( g.zLogin ){
215255
@ <br clear="both"><hr>
216256
@ <p>To log off the system (and delete your login cookie)
217257
@ press the following button:<br>
@@ -278,20 +318,44 @@
278318
279319
/* Check the login cookie to see if it matches a known valid user.
280320
*/
281321
if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
282322
if( isdigit(zCookie[0]) ){
323
+ /* Cookies of the form "uid/randomness". There must be a
324
+ ** corresponding entry in the user table. */
283325
uid = db_int(0,
284326
"SELECT uid FROM user"
285327
" WHERE uid=%d"
286328
" AND cookie=%Q"
287329
" AND ipaddr=%Q"
288330
" AND cexpire>julianday('now')",
289331
atoi(zCookie), zCookie, zRemoteAddr
290332
);
291
- }else if( zCookie[0]=='a' ){
292
- uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'");
333
+ }else if( memcmp(zCookie,"anon/",5)==0 ){
334
+ /* Cookies of the form "anon/TIME/HASH". The TIME must not be
335
+ ** too old and the sha1 hash of TIME+IPADDR+SECRET must match HASH.
336
+ ** SECRET is the "captcha-secret" value in the repository.
337
+ */
338
+ double rTime;
339
+ int i;
340
+ Blob b;
341
+ rTime = atof(&zCookie[5]);
342
+ for(i=5; zCookie[i] && zCookie[i]!='/'; i++){}
343
+ blob_init(&b, &zCookie[5], i-5);
344
+ if( zCookie[i]=='/' ){ i++; }
345
+ blob_append(&b, "/", 1);
346
+ blob_appendf(&b, "%s/%s", zRemoteAddr, db_get("captcha-secret",""));
347
+ sha1sum_blob(&b, &b);
348
+ uid = db_int(0,
349
+ "SELECT uid FROM user WHERE login='anonymous'"
350
+ " AND length(cap)>0"
351
+ " AND length(pw)>0"
352
+ " AND %f+0.25>julianday('now')"
353
+ " AND %Q=%Q",
354
+ rTime, &zCookie[i], blob_buffer(&b)
355
+ );
356
+ blob_reset(&b);
293357
}
294358
sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zCookie);
295359
}
296360
297361
if( uid==0 ){
@@ -474,12 +538,12 @@
474538
}
475539
476540
/*
477541
** Before using the results of a form, first call this routine to verify
478542
** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token
479
-** is missing or is incorrect, then this emits and error message and never
480
-** returns.
543
+** is missing or is incorrect, that indicates a cross-site scripting attach
544
+** so emits an error message and abort.
481545
*/
482546
void login_verify_csrf_secret(void){
483547
const char *zCsrf; /* The CSRF secret */
484548
if( g.okCsrf ) return;
485549
if( (zCsrf = P("csrf"))!=0 && strcmp(zCsrf, g.zCsrfToken)==0 ){
486550
--- src/login.c
+++ src/login.c
@@ -77,10 +77,34 @@
77 cgi_redirect(zGoto);
78 }else{
79 fossil_redirect_home();
80 }
81 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
83 /*
84 ** WEBPAGE: /login
85 ** WEBPAGE: /logout
86 **
@@ -90,10 +114,11 @@
90 const char *zUsername, *zPasswd;
91 const char *zNew1, *zNew2;
92 const char *zAnonPw = 0;
93 int anonFlag;
94 char *zErrMsg = "";
 
95
96 login_check_credentials();
97 zUsername = P("u");
98 zPasswd = P("p");
99 anonFlag = P("anon")!=0;
@@ -124,13 +149,33 @@
124 "UPDATE user SET pw=%Q WHERE uid=%d", zNew1, g.userUid
125 );
126 redirect_to_g();
127 return;
128 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129 }
130 if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
131 int uid = db_int(0,
132 "SELECT uid FROM user"
133 " WHERE login=%Q AND pw=%Q", zUsername, zPasswd);
134 if( uid<=0 || strcmp(zUsername,"nobody")==0 ){
135 sleep(1);
136 zErrMsg =
@@ -143,21 +188,17 @@
143 const char *zCookieName = login_cookie_name();
144 const char *zExpire = db_get("cookie-expire","8766");
145 int expires = atoi(zExpire)*3600;
146 const char *zIpAddr = PD("REMOTE_ADDR","nil");
147
148 if( strcmp(zUsername, "anonymous")==0 ){
149 cgi_set_cookie(zCookieName, "anonymous", 0, expires);
150 }else{
151 zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid);
152 cgi_set_cookie(zCookieName, zCookie, 0, expires);
153 db_multi_exec(
154 "UPDATE user SET cookie=%Q, ipaddr=%Q, "
155 " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
156 zCookie, zIpAddr, expires, uid
157 );
158 }
159 redirect_to_g();
160 }
161 }
162 style_header("Login/Logout");
163 @ %s(zErrMsg)
@@ -180,15 +221,10 @@
180 @ </tr>
181 if( g.zLogin==0 ){
182 zAnonPw = db_text(0, "SELECT pw FROM user"
183 " WHERE login='anonymous'"
184 " AND cap!=''");
185 if( zAnonPw && anonFlag ){
186 @ <tr><td></td>
187 @ <td>The anonymous password is "<b>%h(zAnonPw)</b>".</td>
188 @ </tr>
189 }
190 }
191 @ <tr>
192 @ <td></td>
193 @ <td><input type="submit" name="in" value="Login"></td>
194 @ </tr>
@@ -201,17 +237,21 @@
201 }
202 @ enter the user-id and password at the left and press the
203 @ "Login" button. Your user name will be stored in a browser cookie.
204 @ You must configure your web browser to accept cookies in order for
205 @ the login to take.</p>
206 if( g.zLogin==0 ){
207 if( zAnonPw && !anonFlag ){
208 @ <p>The password for user "anonymous" is "<b>%h(zAnonPw)</b>".</p>
209 @ <p>&nbsp;</p>
210 }else{
211 @ <p>&nbsp;</p><p>&nbsp;</p>
212 }
 
 
 
 
213 }
214 if( g.zLogin ){
215 @ <br clear="both"><hr>
216 @ <p>To log off the system (and delete your login cookie)
217 @ press the following button:<br>
@@ -278,20 +318,44 @@
278
279 /* Check the login cookie to see if it matches a known valid user.
280 */
281 if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
282 if( isdigit(zCookie[0]) ){
 
 
283 uid = db_int(0,
284 "SELECT uid FROM user"
285 " WHERE uid=%d"
286 " AND cookie=%Q"
287 " AND ipaddr=%Q"
288 " AND cexpire>julianday('now')",
289 atoi(zCookie), zCookie, zRemoteAddr
290 );
291 }else if( zCookie[0]=='a' ){
292 uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293 }
294 sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zCookie);
295 }
296
297 if( uid==0 ){
@@ -474,12 +538,12 @@
474 }
475
476 /*
477 ** Before using the results of a form, first call this routine to verify
478 ** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token
479 ** is missing or is incorrect, then this emits and error message and never
480 ** returns.
481 */
482 void login_verify_csrf_secret(void){
483 const char *zCsrf; /* The CSRF secret */
484 if( g.okCsrf ) return;
485 if( (zCsrf = P("csrf"))!=0 && strcmp(zCsrf, g.zCsrfToken)==0 ){
486
--- src/login.c
+++ src/login.c
@@ -77,10 +77,34 @@
77 cgi_redirect(zGoto);
78 }else{
79 fossil_redirect_home();
80 }
81 }
82
83 /*
84 ** Check to see if the anonymous login is valid. If it is valid, return
85 ** the userid of the anonymous user.
86 */
87 static int isValidAnonymousLogin(
88 const char *zUsername, /* The username. Must be "anonymous" */
89 const char *zPassword /* The supplied password */
90 ){
91 const char *zCS; /* The captcha seed value */
92 const char *zPw; /* The correct password shown in the captcha */
93 int uid; /* The user ID of anonymous */
94
95 if( zUsername==0 ) return 0;
96 if( zPassword==0 ) return 0;
97 if( strcmp(zUsername,"anonymous")!=0 ) return 0;
98 zCS = P("cs"); /* The "cs" parameter is the "captcha seed" */
99 if( zCS==0 ) return 0;
100 zPw = captcha_decode((unsigned int)atoi(zCS));
101 if( strcasecmp(zPw, zPassword)!=0 ) return 0;
102 uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'"
103 " AND length(pw)>0 AND length(cap)>0");
104 return uid;
105 }
106
107 /*
108 ** WEBPAGE: /login
109 ** WEBPAGE: /logout
110 **
@@ -90,10 +114,11 @@
114 const char *zUsername, *zPasswd;
115 const char *zNew1, *zNew2;
116 const char *zAnonPw = 0;
117 int anonFlag;
118 char *zErrMsg = "";
119 int uid; /* User id loged in user */
120
121 login_check_credentials();
122 zUsername = P("u");
123 zPasswd = P("p");
124 anonFlag = P("anon")!=0;
@@ -124,13 +149,33 @@
149 "UPDATE user SET pw=%Q WHERE uid=%d", zNew1, g.userUid
150 );
151 redirect_to_g();
152 return;
153 }
154 }
155 uid = isValidAnonymousLogin(zUsername, zPasswd);
156 if( uid>0 ){
157 char *zNow; /* Current time (julian day number) */
158 const char *zIpAddr; /* IP address of requestor */
159 char *zCookie; /* The login cookie */
160 const char *zCookieName; /* Name of the login cookie */
161 Blob b; /* Blob used during cookie construction */
162
163 zIpAddr = PD("REMOTE_ADDR","nil");
164 zCookieName = login_cookie_name();
165 zNow = db_text("0", "SELECT julianday('now')");
166 blob_init(&b, zNow, -1);
167 blob_appendf(&b, "/%s/%s", zIpAddr, db_get("captcha-secret",""));
168 sha1sum_blob(&b, &b);
169 zCookie = sqlite3_mprintf("anon/%s/%s", zNow, blob_buffer(&b));
170 blob_reset(&b);
171 free(zNow);
172 cgi_set_cookie(zCookieName, zCookie, 0, 6*3600);
173 redirect_to_g();
174 }
175 if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
176 uid = db_int(0,
177 "SELECT uid FROM user"
178 " WHERE login=%Q AND pw=%Q", zUsername, zPasswd);
179 if( uid<=0 || strcmp(zUsername,"nobody")==0 ){
180 sleep(1);
181 zErrMsg =
@@ -143,21 +188,17 @@
188 const char *zCookieName = login_cookie_name();
189 const char *zExpire = db_get("cookie-expire","8766");
190 int expires = atoi(zExpire)*3600;
191 const char *zIpAddr = PD("REMOTE_ADDR","nil");
192
193 zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid);
194 cgi_set_cookie(zCookieName, zCookie, 0, expires);
195 db_multi_exec(
196 "UPDATE user SET cookie=%Q, ipaddr=%Q, "
197 " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
198 zCookie, zIpAddr, expires, uid
199 );
 
 
 
 
200 redirect_to_g();
201 }
202 }
203 style_header("Login/Logout");
204 @ %s(zErrMsg)
@@ -180,15 +221,10 @@
221 @ </tr>
222 if( g.zLogin==0 ){
223 zAnonPw = db_text(0, "SELECT pw FROM user"
224 " WHERE login='anonymous'"
225 " AND cap!=''");
 
 
 
 
 
226 }
227 @ <tr>
228 @ <td></td>
229 @ <td><input type="submit" name="in" value="Login"></td>
230 @ </tr>
@@ -201,17 +237,21 @@
237 }
238 @ enter the user-id and password at the left and press the
239 @ "Login" button. Your user name will be stored in a browser cookie.
240 @ You must configure your web browser to accept cookies in order for
241 @ the login to take.</p>
242 if( zAnonPw ){
243 unsigned int uSeed = captcha_seed();
244 char *zCaptcha = captcha_render(captcha_decode(uSeed));
245
246 @ <input type="hidden" name="cs" value="%u(uSeed)">
247 @ <p>To login as user <b>anonymous</b> use the following
248 @ 8-character hexadecimal password:</p>
249 @ <center><table border="1" cellpadding="10"><tr><td><pre>
250 @ %s(zCaptcha)
251 @ </pre></td></tr></table></center>
252 free(zCaptcha);
253 }
254 if( g.zLogin ){
255 @ <br clear="both"><hr>
256 @ <p>To log off the system (and delete your login cookie)
257 @ press the following button:<br>
@@ -278,20 +318,44 @@
318
319 /* Check the login cookie to see if it matches a known valid user.
320 */
321 if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
322 if( isdigit(zCookie[0]) ){
323 /* Cookies of the form "uid/randomness". There must be a
324 ** corresponding entry in the user table. */
325 uid = db_int(0,
326 "SELECT uid FROM user"
327 " WHERE uid=%d"
328 " AND cookie=%Q"
329 " AND ipaddr=%Q"
330 " AND cexpire>julianday('now')",
331 atoi(zCookie), zCookie, zRemoteAddr
332 );
333 }else if( memcmp(zCookie,"anon/",5)==0 ){
334 /* Cookies of the form "anon/TIME/HASH". The TIME must not be
335 ** too old and the sha1 hash of TIME+IPADDR+SECRET must match HASH.
336 ** SECRET is the "captcha-secret" value in the repository.
337 */
338 double rTime;
339 int i;
340 Blob b;
341 rTime = atof(&zCookie[5]);
342 for(i=5; zCookie[i] && zCookie[i]!='/'; i++){}
343 blob_init(&b, &zCookie[5], i-5);
344 if( zCookie[i]=='/' ){ i++; }
345 blob_append(&b, "/", 1);
346 blob_appendf(&b, "%s/%s", zRemoteAddr, db_get("captcha-secret",""));
347 sha1sum_blob(&b, &b);
348 uid = db_int(0,
349 "SELECT uid FROM user WHERE login='anonymous'"
350 " AND length(cap)>0"
351 " AND length(pw)>0"
352 " AND %f+0.25>julianday('now')"
353 " AND %Q=%Q",
354 rTime, &zCookie[i], blob_buffer(&b)
355 );
356 blob_reset(&b);
357 }
358 sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zCookie);
359 }
360
361 if( uid==0 ){
@@ -474,12 +538,12 @@
538 }
539
540 /*
541 ** Before using the results of a form, first call this routine to verify
542 ** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token
543 ** is missing or is incorrect, that indicates a cross-site scripting attach
544 ** so emits an error message and abort.
545 */
546 void login_verify_csrf_secret(void){
547 const char *zCsrf; /* The CSRF secret */
548 if( g.okCsrf ) return;
549 if( (zCsrf = P("csrf"))!=0 && strcmp(zCsrf, g.zCsrfToken)==0 ){
550
+12 -2
--- src/main.mk
+++ src/main.mk
@@ -18,10 +18,11 @@
1818
$(SRCDIR)/allrepo.c \
1919
$(SRCDIR)/bag.c \
2020
$(SRCDIR)/blob.c \
2121
$(SRCDIR)/branch.c \
2222
$(SRCDIR)/browse.c \
23
+ $(SRCDIR)/captcha.c \
2324
$(SRCDIR)/cgi.c \
2425
$(SRCDIR)/checkin.c \
2526
$(SRCDIR)/checkout.c \
2627
$(SRCDIR)/clearsign.c \
2728
$(SRCDIR)/clone.c \
@@ -88,10 +89,11 @@
8889
allrepo_.c \
8990
bag_.c \
9091
blob_.c \
9192
branch_.c \
9293
browse_.c \
94
+ captcha_.c \
9395
cgi_.c \
9496
checkin_.c \
9597
checkout_.c \
9698
clearsign_.c \
9799
clone_.c \
@@ -158,10 +160,11 @@
158160
allrepo.o \
159161
bag.o \
160162
blob.o \
161163
branch.o \
162164
browse.o \
165
+ captcha.o \
163166
cgi.o \
164167
checkin.o \
165168
checkout.o \
166169
clearsign.o \
167170
clone.o \
@@ -261,16 +264,16 @@
261264
# noop
262265
263266
clean:
264267
rm -f *.o *_.c $(APPNAME) VERSION.h
265268
rm -f translate makeheaders mkindex page_index.h headers
266
- rm -f add.h admin.h allrepo.h bag.h blob.h branch.h browse.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h my_page.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h setup.h sha1.h shun.h stat.h style.h sync.h tag.h tagview.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h
269
+ rm -f add.h admin.h allrepo.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h my_page.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h setup.h sha1.h shun.h stat.h style.h sync.h tag.h tagview.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h
267270
268271
page_index.h: $(TRANS_SRC) mkindex
269272
./mkindex $(TRANS_SRC) >$@
270273
headers: page_index.h makeheaders VERSION.h
271
- ./makeheaders add_.c:add.h admin_.c:admin.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h my_page_.c:my_page.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tagview_.c:tagview.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
274
+ ./makeheaders add_.c:add.h admin_.c:admin.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h my_page_.c:my_page.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tagview_.c:tagview.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
272275
touch headers
273276
headers: Makefile
274277
Makefile:
275278
add_.c: $(SRCDIR)/add.c $(SRCDIR)/VERSION translate
276279
./translate $(SRCDIR)/add.c | sed -f $(SRCDIR)/VERSION >add_.c
@@ -319,10 +322,17 @@
319322
320323
browse.o: browse_.c browse.h $(SRCDIR)/config.h
321324
$(XTCC) -o browse.o -c browse_.c
322325
323326
browse.h: headers
327
+captcha_.c: $(SRCDIR)/captcha.c $(SRCDIR)/VERSION translate
328
+ ./translate $(SRCDIR)/captcha.c | sed -f $(SRCDIR)/VERSION >captcha_.c
329
+
330
+captcha.o: captcha_.c captcha.h $(SRCDIR)/config.h
331
+ $(XTCC) -o captcha.o -c captcha_.c
332
+
333
+captcha.h: headers
324334
cgi_.c: $(SRCDIR)/cgi.c $(SRCDIR)/VERSION translate
325335
./translate $(SRCDIR)/cgi.c | sed -f $(SRCDIR)/VERSION >cgi_.c
326336
327337
cgi.o: cgi_.c cgi.h $(SRCDIR)/config.h
328338
$(XTCC) -o cgi.o -c cgi_.c
329339
--- src/main.mk
+++ src/main.mk
@@ -18,10 +18,11 @@
18 $(SRCDIR)/allrepo.c \
19 $(SRCDIR)/bag.c \
20 $(SRCDIR)/blob.c \
21 $(SRCDIR)/branch.c \
22 $(SRCDIR)/browse.c \
 
23 $(SRCDIR)/cgi.c \
24 $(SRCDIR)/checkin.c \
25 $(SRCDIR)/checkout.c \
26 $(SRCDIR)/clearsign.c \
27 $(SRCDIR)/clone.c \
@@ -88,10 +89,11 @@
88 allrepo_.c \
89 bag_.c \
90 blob_.c \
91 branch_.c \
92 browse_.c \
 
93 cgi_.c \
94 checkin_.c \
95 checkout_.c \
96 clearsign_.c \
97 clone_.c \
@@ -158,10 +160,11 @@
158 allrepo.o \
159 bag.o \
160 blob.o \
161 branch.o \
162 browse.o \
 
163 cgi.o \
164 checkin.o \
165 checkout.o \
166 clearsign.o \
167 clone.o \
@@ -261,16 +264,16 @@
261 # noop
262
263 clean:
264 rm -f *.o *_.c $(APPNAME) VERSION.h
265 rm -f translate makeheaders mkindex page_index.h headers
266 rm -f add.h admin.h allrepo.h bag.h blob.h branch.h browse.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h my_page.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h setup.h sha1.h shun.h stat.h style.h sync.h tag.h tagview.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h
267
268 page_index.h: $(TRANS_SRC) mkindex
269 ./mkindex $(TRANS_SRC) >$@
270 headers: page_index.h makeheaders VERSION.h
271 ./makeheaders add_.c:add.h admin_.c:admin.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h my_page_.c:my_page.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tagview_.c:tagview.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
272 touch headers
273 headers: Makefile
274 Makefile:
275 add_.c: $(SRCDIR)/add.c $(SRCDIR)/VERSION translate
276 ./translate $(SRCDIR)/add.c | sed -f $(SRCDIR)/VERSION >add_.c
@@ -319,10 +322,17 @@
319
320 browse.o: browse_.c browse.h $(SRCDIR)/config.h
321 $(XTCC) -o browse.o -c browse_.c
322
323 browse.h: headers
 
 
 
 
 
 
 
324 cgi_.c: $(SRCDIR)/cgi.c $(SRCDIR)/VERSION translate
325 ./translate $(SRCDIR)/cgi.c | sed -f $(SRCDIR)/VERSION >cgi_.c
326
327 cgi.o: cgi_.c cgi.h $(SRCDIR)/config.h
328 $(XTCC) -o cgi.o -c cgi_.c
329
--- src/main.mk
+++ src/main.mk
@@ -18,10 +18,11 @@
18 $(SRCDIR)/allrepo.c \
19 $(SRCDIR)/bag.c \
20 $(SRCDIR)/blob.c \
21 $(SRCDIR)/branch.c \
22 $(SRCDIR)/browse.c \
23 $(SRCDIR)/captcha.c \
24 $(SRCDIR)/cgi.c \
25 $(SRCDIR)/checkin.c \
26 $(SRCDIR)/checkout.c \
27 $(SRCDIR)/clearsign.c \
28 $(SRCDIR)/clone.c \
@@ -88,10 +89,11 @@
89 allrepo_.c \
90 bag_.c \
91 blob_.c \
92 branch_.c \
93 browse_.c \
94 captcha_.c \
95 cgi_.c \
96 checkin_.c \
97 checkout_.c \
98 clearsign_.c \
99 clone_.c \
@@ -158,10 +160,11 @@
160 allrepo.o \
161 bag.o \
162 blob.o \
163 branch.o \
164 browse.o \
165 captcha.o \
166 cgi.o \
167 checkin.o \
168 checkout.o \
169 clearsign.o \
170 clone.o \
@@ -261,16 +264,16 @@
264 # noop
265
266 clean:
267 rm -f *.o *_.c $(APPNAME) VERSION.h
268 rm -f translate makeheaders mkindex page_index.h headers
269 rm -f add.h admin.h allrepo.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h my_page.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h setup.h sha1.h shun.h stat.h style.h sync.h tag.h tagview.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h
270
271 page_index.h: $(TRANS_SRC) mkindex
272 ./mkindex $(TRANS_SRC) >$@
273 headers: page_index.h makeheaders VERSION.h
274 ./makeheaders add_.c:add.h admin_.c:admin.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h my_page_.c:my_page.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tagview_.c:tagview.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
275 touch headers
276 headers: Makefile
277 Makefile:
278 add_.c: $(SRCDIR)/add.c $(SRCDIR)/VERSION translate
279 ./translate $(SRCDIR)/add.c | sed -f $(SRCDIR)/VERSION >add_.c
@@ -319,10 +322,17 @@
322
323 browse.o: browse_.c browse.h $(SRCDIR)/config.h
324 $(XTCC) -o browse.o -c browse_.c
325
326 browse.h: headers
327 captcha_.c: $(SRCDIR)/captcha.c $(SRCDIR)/VERSION translate
328 ./translate $(SRCDIR)/captcha.c | sed -f $(SRCDIR)/VERSION >captcha_.c
329
330 captcha.o: captcha_.c captcha.h $(SRCDIR)/config.h
331 $(XTCC) -o captcha.o -c captcha_.c
332
333 captcha.h: headers
334 cgi_.c: $(SRCDIR)/cgi.c $(SRCDIR)/VERSION translate
335 ./translate $(SRCDIR)/cgi.c | sed -f $(SRCDIR)/VERSION >cgi_.c
336
337 cgi.o: cgi_.c cgi.h $(SRCDIR)/config.h
338 $(XTCC) -o cgi.o -c cgi_.c
339
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -12,10 +12,11 @@
1212
allrepo
1313
bag
1414
blob
1515
branch
1616
browse
17
+ captcha
1718
cgi
1819
checkin
1920
checkout
2021
clearsign
2122
clone
2223
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -12,10 +12,11 @@
12 allrepo
13 bag
14 blob
15 branch
16 browse
 
17 cgi
18 checkin
19 checkout
20 clearsign
21 clone
22
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -12,10 +12,11 @@
12 allrepo
13 bag
14 blob
15 branch
16 browse
17 captcha
18 cgi
19 checkin
20 checkout
21 clearsign
22 clone
23

Keyboard Shortcuts

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