Fossil SCM

Enhancement to robot defense. The auto-hyperlink setting can now be 2 (UserAgent only) in which case the UserAgent string is consulted and hyperlinks are generated if and only if the UserAgent looks human. Javascript does not come into play. When auto-hyperlink is 1, the traditional Javascript changes to href= in anchor tags are still used.

drh 2022-02-12 20:30 trunk
Commit df337eb61c8e6327449f315bfd57ec14e57f346583826ec43ccb2ac910078454
+38 -5
--- src/db.c
+++ src/db.c
@@ -3869,15 +3869,48 @@
38693869
** If enabled, the /login page provides a button that will automatically
38703870
** fill in the captcha password. This makes things easier for human users,
38713871
** at the expense of also making logins easier for malicious robots.
38723872
*/
38733873
/*
3874
-** SETTING: auto-hyperlink boolean default=on
3875
-** Use javascript to enable hyperlinks on web pages
3876
-** for all users (regardless of the "h" privilege) if the
3877
-** User-Agent string in the HTTP header look like it came
3878
-** from real person, not a spider or bot.
3874
+** SETTING: auto-hyperlink width=16 default=1
3875
+**
3876
+** If non-zero, enable hyperlinks on web pages even for users that lack
3877
+** the "h" privilege as long as the UserAgent string in the HTTP request
3878
+** (The HTTP_USER_AGENT cgi variable) looks like it comes from a human and
3879
+** not a robot. Details depend on the value of the setting.
3880
+**
3881
+** (0) Off: No adjustments are made to the 'h' privilege based on
3882
+** the user agent.
3883
+**
3884
+** (1) UserAgent and Javascript: The the href= values of hyperlinks
3885
+** initially point to /honeypot and are changed to point to the
3886
+** correct target by javascript that runs after the page loads.
3887
+** The auto-hyperlink-delay and auto-hyperlink-mouseover settings
3888
+** influence that javascript.
3889
+**
3890
+** (2) UserAgent only: If the HTTP_USER_AGENT looks human
3891
+** then generate hyperlinks, otherwise do not.
3892
+**
3893
+** Better robot exclusion is obtained when this setting is 1 versus 2.
3894
+** However, a value of 1 causes the visited/unvisited colors of hyperlinks
3895
+** to stop working on Safari-derived web browsers. When this setting is 2,
3896
+** the hyperlinks work better on Safari, but more robots are able to sneak
3897
+** in.
3898
+*/
3899
+/* SETTING: auto-hyperlink-delay width=16 default=0
3900
+**
3901
+** When the auto-hyperlink setting is 1, the javascript that runs to set
3902
+** the href= attributes of hyperlinks delays by this many milliseconds
3903
+** after the page load. Suggested values: 50 to 200.
3904
+*/
3905
+/* Setting: auto-hyperlink-mouseover boolean default=off
3906
+**
3907
+** When the auto-hyperlink setting is 1 and this setting is on, the
3908
+** javascript that runs to set the href= attributes of hyperlinks waits
3909
+** until either a mousedown or mousemove event is seen. This helps
3910
+** to distinguish real users from robots. For maximum robot defense,
3911
+** the recommended setting is ON.
38793912
*/
38803913
/*
38813914
** SETTING: auto-shun boolean default=on
38823915
** If enabled, automatically pull the shunning list
38833916
** from a server to which the client autosyncs.
38843917
--- src/db.c
+++ src/db.c
@@ -3869,15 +3869,48 @@
3869 ** If enabled, the /login page provides a button that will automatically
3870 ** fill in the captcha password. This makes things easier for human users,
3871 ** at the expense of also making logins easier for malicious robots.
3872 */
3873 /*
3874 ** SETTING: auto-hyperlink boolean default=on
3875 ** Use javascript to enable hyperlinks on web pages
3876 ** for all users (regardless of the "h" privilege) if the
3877 ** User-Agent string in the HTTP header look like it came
3878 ** from real person, not a spider or bot.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3879 */
3880 /*
3881 ** SETTING: auto-shun boolean default=on
3882 ** If enabled, automatically pull the shunning list
3883 ** from a server to which the client autosyncs.
3884
--- src/db.c
+++ src/db.c
@@ -3869,15 +3869,48 @@
3869 ** If enabled, the /login page provides a button that will automatically
3870 ** fill in the captcha password. This makes things easier for human users,
3871 ** at the expense of also making logins easier for malicious robots.
3872 */
3873 /*
3874 ** SETTING: auto-hyperlink width=16 default=1
3875 **
3876 ** If non-zero, enable hyperlinks on web pages even for users that lack
3877 ** the "h" privilege as long as the UserAgent string in the HTTP request
3878 ** (The HTTP_USER_AGENT cgi variable) looks like it comes from a human and
3879 ** not a robot. Details depend on the value of the setting.
3880 **
3881 ** (0) Off: No adjustments are made to the 'h' privilege based on
3882 ** the user agent.
3883 **
3884 ** (1) UserAgent and Javascript: The the href= values of hyperlinks
3885 ** initially point to /honeypot and are changed to point to the
3886 ** correct target by javascript that runs after the page loads.
3887 ** The auto-hyperlink-delay and auto-hyperlink-mouseover settings
3888 ** influence that javascript.
3889 **
3890 ** (2) UserAgent only: If the HTTP_USER_AGENT looks human
3891 ** then generate hyperlinks, otherwise do not.
3892 **
3893 ** Better robot exclusion is obtained when this setting is 1 versus 2.
3894 ** However, a value of 1 causes the visited/unvisited colors of hyperlinks
3895 ** to stop working on Safari-derived web browsers. When this setting is 2,
3896 ** the hyperlinks work better on Safari, but more robots are able to sneak
3897 ** in.
3898 */
3899 /* SETTING: auto-hyperlink-delay width=16 default=0
3900 **
3901 ** When the auto-hyperlink setting is 1, the javascript that runs to set
3902 ** the href= attributes of hyperlinks delays by this many milliseconds
3903 ** after the page load. Suggested values: 50 to 200.
3904 */
3905 /* Setting: auto-hyperlink-mouseover boolean default=off
3906 **
3907 ** When the auto-hyperlink setting is 1 and this setting is on, the
3908 ** javascript that runs to set the href= attributes of hyperlinks waits
3909 ** until either a mousedown or mousemove event is seen. This helps
3910 ** to distinguish real users from robots. For maximum robot defense,
3911 ** the recommended setting is ON.
3912 */
3913 /*
3914 ** SETTING: auto-shun boolean default=on
3915 ** If enabled, automatically pull the shunning list
3916 ** from a server to which the client autosyncs.
3917
+8 -7
--- src/login.c
+++ src/login.c
@@ -1178,17 +1178,18 @@
11781178
** enabled for this repository and make appropriate adjustments to the
11791179
** permission flags if it is. This should be done before the permissions
11801180
** are (potentially) copied to the anonymous permission set; otherwise,
11811181
** those will be out-of-sync.
11821182
*/
1183
- if( zCap[0]
1184
- && !g.perm.Hyperlink
1185
- && g.isHuman
1186
- && db_get_boolean("auto-hyperlink",1)
1187
- ){
1188
- g.perm.Hyperlink = 1;
1189
- g.javascriptHyperlink = 1;
1183
+ if( zCap[0] && !g.perm.Hyperlink && g.isHuman ){
1184
+ int autoLink = db_get_int("auto-hyperlink",1);
1185
+ if( autoLink==1 ){
1186
+ g.jsHref = 1;
1187
+ g.perm.Hyperlink = 1;
1188
+ }else if( autoLink==2 ){
1189
+ g.perm.Hyperlink = 1;
1190
+ }
11901191
}
11911192
11921193
/*
11931194
** At this point, the capabilities for the logged in user are not going
11941195
** to be modified anymore; therefore, we can copy them over to the ones
11951196
--- src/login.c
+++ src/login.c
@@ -1178,17 +1178,18 @@
1178 ** enabled for this repository and make appropriate adjustments to the
1179 ** permission flags if it is. This should be done before the permissions
1180 ** are (potentially) copied to the anonymous permission set; otherwise,
1181 ** those will be out-of-sync.
1182 */
1183 if( zCap[0]
1184 && !g.perm.Hyperlink
1185 && g.isHuman
1186 && db_get_boolean("auto-hyperlink",1)
1187 ){
1188 g.perm.Hyperlink = 1;
1189 g.javascriptHyperlink = 1;
 
1190 }
1191
1192 /*
1193 ** At this point, the capabilities for the logged in user are not going
1194 ** to be modified anymore; therefore, we can copy them over to the ones
1195
--- src/login.c
+++ src/login.c
@@ -1178,17 +1178,18 @@
1178 ** enabled for this repository and make appropriate adjustments to the
1179 ** permission flags if it is. This should be done before the permissions
1180 ** are (potentially) copied to the anonymous permission set; otherwise,
1181 ** those will be out-of-sync.
1182 */
1183 if( zCap[0] && !g.perm.Hyperlink && g.isHuman ){
1184 int autoLink = db_get_int("auto-hyperlink",1);
1185 if( autoLink==1 ){
1186 g.jsHref = 1;
1187 g.perm.Hyperlink = 1;
1188 }else if( autoLink==2 ){
1189 g.perm.Hyperlink = 1;
1190 }
1191 }
1192
1193 /*
1194 ** At this point, the capabilities for the logged in user are not going
1195 ** to be modified anymore; therefore, we can copy them over to the ones
1196
+1 -1
--- src/main.c
+++ src/main.c
@@ -206,11 +206,11 @@
206206
int markPrivate; /* All new artifacts are private if true */
207207
char *ckinLockFail; /* Check-in lock failure received from server */
208208
int clockSkewSeen; /* True if clocks on client and server out of sync */
209209
int wikiFlags; /* Wiki conversion flags applied to %W */
210210
char isHTTP; /* True if server/CGI modes, else assume CLI. */
211
- char javascriptHyperlink; /* If true, set href= using script, not HTML */
211
+ char jsHref; /* If true, set href= using javascript, not HTML */
212212
Blob httpHeader; /* Complete text of the HTTP request header */
213213
UrlData url; /* Information about current URL */
214214
const char *zLogin; /* Login name. NULL or "" if not logged in. */
215215
const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
216216
const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
217217
--- src/main.c
+++ src/main.c
@@ -206,11 +206,11 @@
206 int markPrivate; /* All new artifacts are private if true */
207 char *ckinLockFail; /* Check-in lock failure received from server */
208 int clockSkewSeen; /* True if clocks on client and server out of sync */
209 int wikiFlags; /* Wiki conversion flags applied to %W */
210 char isHTTP; /* True if server/CGI modes, else assume CLI. */
211 char javascriptHyperlink; /* If true, set href= using script, not HTML */
212 Blob httpHeader; /* Complete text of the HTTP request header */
213 UrlData url; /* Information about current URL */
214 const char *zLogin; /* Login name. NULL or "" if not logged in. */
215 const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
216 const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
217
--- src/main.c
+++ src/main.c
@@ -206,11 +206,11 @@
206 int markPrivate; /* All new artifacts are private if true */
207 char *ckinLockFail; /* Check-in lock failure received from server */
208 int clockSkewSeen; /* True if clocks on client and server out of sync */
209 int wikiFlags; /* Wiki conversion flags applied to %W */
210 char isHTTP; /* True if server/CGI modes, else assume CLI. */
211 char jsHref; /* If true, set href= using javascript, not HTML */
212 Blob httpHeader; /* Complete text of the HTTP request header */
213 UrlData url; /* Information about current URL */
214 const char *zLogin; /* Login name. NULL or "" if not logged in. */
215 const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
216 const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
217
--- src/security_audit.c
+++ src/security_audit.c
@@ -487,13 +487,13 @@
487487
@ Suggested remediation:
488488
@ <ol type="a">
489489
@ <li>Remove the 'h' privilege from the
490490
@ <a href="%R/setup_uedit?id=%d(nobodyId)">'nobody' user</a> so that
491491
@ robots cannot see hyperlinks.
492
- @ <li>Activate <a href="%R/setup_access#autoh">autohyperlink</a> so that
492
+ @ <li>Activate <a href="%R/setup_robot">autohyperlink</a> so that
493493
@ human readers can still see hyperlinks even if they are not logged in.
494
- @ Set the delay to at least 50 milliseconds and require a mousedown
494
+ @ Set the delay to at least 50 milliseconds and require a mouse
495495
@ event for maximum robot defense.
496496
if( anonId>0 ){
497497
@ <li>Perhaps set the 'h' privilege on the
498498
@ <a href="%R/setup_uedit?id=%d(anonId)">'anonymous' user</a> so
499499
@ that humans that have javascript disabled in their browsers can
500500
--- src/security_audit.c
+++ src/security_audit.c
@@ -487,13 +487,13 @@
487 @ Suggested remediation:
488 @ <ol type="a">
489 @ <li>Remove the 'h' privilege from the
490 @ <a href="%R/setup_uedit?id=%d(nobodyId)">'nobody' user</a> so that
491 @ robots cannot see hyperlinks.
492 @ <li>Activate <a href="%R/setup_access#autoh">autohyperlink</a> so that
493 @ human readers can still see hyperlinks even if they are not logged in.
494 @ Set the delay to at least 50 milliseconds and require a mousedown
495 @ event for maximum robot defense.
496 if( anonId>0 ){
497 @ <li>Perhaps set the 'h' privilege on the
498 @ <a href="%R/setup_uedit?id=%d(anonId)">'anonymous' user</a> so
499 @ that humans that have javascript disabled in their browsers can
500
--- src/security_audit.c
+++ src/security_audit.c
@@ -487,13 +487,13 @@
487 @ Suggested remediation:
488 @ <ol type="a">
489 @ <li>Remove the 'h' privilege from the
490 @ <a href="%R/setup_uedit?id=%d(nobodyId)">'nobody' user</a> so that
491 @ robots cannot see hyperlinks.
492 @ <li>Activate <a href="%R/setup_robot">autohyperlink</a> so that
493 @ human readers can still see hyperlinks even if they are not logged in.
494 @ Set the delay to at least 50 milliseconds and require a mouse
495 @ event for maximum robot defense.
496 if( anonId>0 ){
497 @ <li>Perhaps set the 'h' privilege on the
498 @ <a href="%R/setup_uedit?id=%d(anonId)">'anonymous' user</a> so
499 @ that humans that have javascript disabled in their browsers can
500
+102 -49
--- src/setup.c
+++ src/setup.c
@@ -111,10 +111,12 @@
111111
"Configure the WWW components of the repository");
112112
}
113113
setup_menu_entry("Security-Audit", "secaudit0",
114114
"Analyze the current configuration for security problems");
115115
if( setup_user ){
116
+ setup_menu_entry("Robot-Defense", "setup_robot",
117
+ "Settings for configure defense against robots");
116118
setup_menu_entry("Settings", "setup_settings",
117119
"Web interface to the \"fossil settings\" command");
118120
}
119121
setup_menu_entry("Timeline", "setup_timeline",
120122
"Timeline display preferences");
@@ -322,10 +324,105 @@
322324
@ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
323325
}
324326
@ </select> <b>%h(zLabel)</b>
325327
}
326328
329
+/*
330
+** Insert code into the current page that allows the user to configure
331
+** auto-hyperlink related robot defense settings.
332
+*/
333
+static void addAutoHyperlinkSettings(void){
334
+ static const char *const azDefenseOpts[] = {
335
+ "0", "Off",
336
+ "2", "UserAgent only",
337
+ "1", "UserAgent and Javascript",
338
+ };
339
+ multiple_choice_attribute(
340
+ "Enable hyperlinks base on User-Agent and/or Javascript",
341
+ "auto-hyperlink", "autohyperlink", "1",
342
+ count(azDefenseOpts)/2, azDefenseOpts);
343
+ @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users,
344
+ @ including user "nobody", as long as the User-Agent string in the
345
+ @ HTTP header indicates that the request is coming from an actual human
346
+ @ being. If this setting is "UserAgent only" (2) then the
347
+ @ UserAgent string is the only factor considered. If the value of this
348
+ @ setting is "UserAgent And Javascript" (1) then Javascript is added that
349
+ @ runs after the page loads and fills in the href= values of &lt;a&gt;
350
+ @ elements. In either case, &lt;a&gt; tags are only generated if the
351
+ @ UserAgent string indicates that the request is coming from a human and
352
+ @ not a robot.
353
+ @
354
+ @ <p>This setting is designed to give easy access to humans while
355
+ @ keeping out robots.
356
+ @ You do not normally want a robot to walk your entire repository because
357
+ @ if it does, your server will end up computing diffs and annotations for
358
+ @ every historical version of every file and creating ZIPs and tarballs of
359
+ @ every historical check-in, which can use a lot of CPU and bandwidth
360
+ @ even for relatively small projects.</p>
361
+ @
362
+ @ <p>The "UserAgent and Javascript" value for this setting provides
363
+ @ superior protection from robots. However, that setting also prevents
364
+ @ the visited/unvisited colors on hyperlinks from displaying correctly
365
+ @ on Safara-derived browsers. (Chrome and Firefox work fine.) Since
366
+ @ Safari is the underlying rendering engine on all iPhones and iPads,
367
+ @ this means that hyperlink visited/unvisited colors will not operate
368
+ @ on those platforms when "UserAgent and Javascript" is selected.</p>
369
+ @
370
+ @ <p>Additional parameters that control the behavior of Javascript:</p>
371
+ @ <blockquote>
372
+ entry_attribute("Delay in milliseconds before enabling hyperlinks", 5,
373
+ "auto-hyperlink-delay", "ah-delay", "50", 0);
374
+ @ <br />
375
+ onoff_attribute("Also require a mouse event before enabling hyperlinks",
376
+ "auto-hyperlink-mouseover", "ahmo", 0, 0);
377
+ @ </blockquote>
378
+ @ <p>For maximum robot defense, "Delay" should be at least 50 milliseconds
379
+ @ and "require a mouse event" should be turned on. These values only come
380
+ @ into play when the main auto-hyperlink settings is 2 ("UserAgent and
381
+ @ Javascript").</p>
382
+ @
383
+ @ <p>To see if Javascript-base hyperlink enabling mechanism is working,
384
+ @ visit the <a href="%R/test_env">/test_env</a> page (from a separate
385
+ @ web browser that is not logged in, even as "anonymous") and verify
386
+ @ that the "g.jsHref" value is "1".</p>
387
+ @ <p>(Properties: "auto-hyperlink", "auto-hyperlink-delay", and
388
+ @ "auto-hyperlink-mouseover"")</p>
389
+}
390
+
391
+/*
392
+** WEBPAGE: setup_robot
393
+**
394
+** Settings associated with defense against robots. Requires setup privilege.
395
+*/
396
+void setup_robots(void){
397
+ login_check_credentials();
398
+ if( !g.perm.Setup ){
399
+ login_needed(0);
400
+ return;
401
+ }
402
+ style_set_current_feature("setup");
403
+ style_header("Robot Defense Settings");
404
+ db_begin_transaction();
405
+ @ <p>A Fossil website can have billions of pages in its tree, even for a
406
+ @ modest project. Many of those pages (examples: diffs and tarballs)
407
+ @ might be expensive to compute. A robot that tries to walk the entire
408
+ @ website can present a crippling CPU and bandwidth load.
409
+ @
410
+ @ <p>The settings on this page are intended to help site administrators
411
+ @ defend the site against robots.
412
+ @
413
+ @ <form action="%R/setup_robot" method="post"><div>
414
+ login_insert_csrf_secret();
415
+ @ <input type="submit" name="submit" value="Apply Changes" /></p>
416
+ @ <hr />
417
+ addAutoHyperlinkSettings();
418
+ @ <hr />
419
+ @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
420
+ @ </div></form>
421
+ db_end_transaction(0);
422
+ style_finish_page();
423
+}
327424
328425
/*
329426
** WEBPAGE: setup_access
330427
**
331428
** The access-control settings page. Requires Setup privileges.
@@ -460,59 +557,15 @@
460557
@ This limit is only enforced on Unix servers. On Linux systems,
461558
@ access to the /proc virtual filesystem is required, which means this limit
462559
@ might not work inside a chroot() jail.
463560
@ (Property: "max-loadavg")</p>
464561
465
- @ <hr />
466
- @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
467
-
468
- @ <a id="autoh"></a>
469
- @ <hr />
470
- onoff_attribute(
471
- "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript",
472
- "auto-hyperlink", "autohyperlink", 1, 0);
473
- @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users,
474
- @ including user "nobody", as long as
475
- @ <ol><li>the User-Agent string in the
476
- @ HTTP header indicates that the request is coming from an actual human
477
- @ being, and
478
- @ <li>the user agent is able to
479
- @ run Javascript in order to set the href= attribute of hyperlinks, and
480
- @ <li>a number of milliseconds have passed since the page loaded, and
481
- @ <li>a mousedown event is detected (optional - see the checkbox below)
482
- @ </ol>
483
- @
484
- @ <p>This setting is designed to give easy access to humans while
485
- @ keeping out robots and spiders.
486
- @ You do not normally want a robot to walk your entire repository because
487
- @ if it does, your server will end up computing diffs and annotations for
488
- @ every historical version of every file and creating ZIPs and tarballs of
489
- @ every historical check-in, which can use a lot of CPU and bandwidth
490
- @ even for relatively small projects.</p>
491
- @
492
- @ <p>Limitation: Hyperlink visited/unvisited colors will not work
493
- @ correctly with this option on Safari-based browsers. They work fine
494
- @ on Chrome-based browsers and on Firefox, but not Safari. Since
495
- @ Safari is the underlying rendering engine on all iPhones and iPads,
496
- @ this means that hyperlink visited/unvisited colors will not operate
497
- @ on those platforms when this option is enabled.</p>
498
- @
499
- @ <p>Additional parameters that control this behavior:</p>
500
- @ <blockquote>
501
- entry_attribute("Delay in milliseconds before enabling hyperlinks", 5,
502
- "auto-hyperlink-delay", "ah-delay", "50", 0);
503
- @ <br />
504
- onoff_attribute("Also require a mouse event before enabling hyperlinks",
505
- "auto-hyperlink-mouseover", "ahmo", 0, 0);
506
- @ </blockquote>
507
- @ <p>For maximum robot defense, "Delay" should be at least 50 milliseconds
508
- @ and "require a mouse event" should be turned on. To test to see that
509
- @ this mechanism is working, visit the <a href="%R/test_env">/test_env</a>
510
- @ page (from a separate web browser that is not logged in, even as
511
- @ "anonymous") and verify that the "g.javascriptHyperlink" value is "1".</p>
512
- @ <p>(Properties: "auto-hyperlink", "auto-hyperlink-delay", and
513
- @ "auto-hyperlink-mouseover"")</p>
562
+ /* Add the auto-hyperlink settings controls. These same controls
563
+ ** are also accessible from the /setup_robot page.
564
+ */
565
+ @ <hr />
566
+ addAutoHyperlinkSettings();
514567
515568
@ <hr />
516569
onoff_attribute("Require a CAPTCHA if not logged in",
517570
"require-captcha", "reqcapt", 1, 0);
518571
@ <p>Require a CAPTCHA for edit operations (appending, creating, or
519572
--- src/setup.c
+++ src/setup.c
@@ -111,10 +111,12 @@
111 "Configure the WWW components of the repository");
112 }
113 setup_menu_entry("Security-Audit", "secaudit0",
114 "Analyze the current configuration for security problems");
115 if( setup_user ){
 
 
116 setup_menu_entry("Settings", "setup_settings",
117 "Web interface to the \"fossil settings\" command");
118 }
119 setup_menu_entry("Timeline", "setup_timeline",
120 "Timeline display preferences");
@@ -322,10 +324,105 @@
322 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
323 }
324 @ </select> <b>%h(zLabel)</b>
325 }
326
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
328 /*
329 ** WEBPAGE: setup_access
330 **
331 ** The access-control settings page. Requires Setup privileges.
@@ -460,59 +557,15 @@
460 @ This limit is only enforced on Unix servers. On Linux systems,
461 @ access to the /proc virtual filesystem is required, which means this limit
462 @ might not work inside a chroot() jail.
463 @ (Property: "max-loadavg")</p>
464
465 @ <hr />
466 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
467
468 @ <a id="autoh"></a>
469 @ <hr />
470 onoff_attribute(
471 "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript",
472 "auto-hyperlink", "autohyperlink", 1, 0);
473 @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users,
474 @ including user "nobody", as long as
475 @ <ol><li>the User-Agent string in the
476 @ HTTP header indicates that the request is coming from an actual human
477 @ being, and
478 @ <li>the user agent is able to
479 @ run Javascript in order to set the href= attribute of hyperlinks, and
480 @ <li>a number of milliseconds have passed since the page loaded, and
481 @ <li>a mousedown event is detected (optional - see the checkbox below)
482 @ </ol>
483 @
484 @ <p>This setting is designed to give easy access to humans while
485 @ keeping out robots and spiders.
486 @ You do not normally want a robot to walk your entire repository because
487 @ if it does, your server will end up computing diffs and annotations for
488 @ every historical version of every file and creating ZIPs and tarballs of
489 @ every historical check-in, which can use a lot of CPU and bandwidth
490 @ even for relatively small projects.</p>
491 @
492 @ <p>Limitation: Hyperlink visited/unvisited colors will not work
493 @ correctly with this option on Safari-based browsers. They work fine
494 @ on Chrome-based browsers and on Firefox, but not Safari. Since
495 @ Safari is the underlying rendering engine on all iPhones and iPads,
496 @ this means that hyperlink visited/unvisited colors will not operate
497 @ on those platforms when this option is enabled.</p>
498 @
499 @ <p>Additional parameters that control this behavior:</p>
500 @ <blockquote>
501 entry_attribute("Delay in milliseconds before enabling hyperlinks", 5,
502 "auto-hyperlink-delay", "ah-delay", "50", 0);
503 @ <br />
504 onoff_attribute("Also require a mouse event before enabling hyperlinks",
505 "auto-hyperlink-mouseover", "ahmo", 0, 0);
506 @ </blockquote>
507 @ <p>For maximum robot defense, "Delay" should be at least 50 milliseconds
508 @ and "require a mouse event" should be turned on. To test to see that
509 @ this mechanism is working, visit the <a href="%R/test_env">/test_env</a>
510 @ page (from a separate web browser that is not logged in, even as
511 @ "anonymous") and verify that the "g.javascriptHyperlink" value is "1".</p>
512 @ <p>(Properties: "auto-hyperlink", "auto-hyperlink-delay", and
513 @ "auto-hyperlink-mouseover"")</p>
514
515 @ <hr />
516 onoff_attribute("Require a CAPTCHA if not logged in",
517 "require-captcha", "reqcapt", 1, 0);
518 @ <p>Require a CAPTCHA for edit operations (appending, creating, or
519
--- src/setup.c
+++ src/setup.c
@@ -111,10 +111,12 @@
111 "Configure the WWW components of the repository");
112 }
113 setup_menu_entry("Security-Audit", "secaudit0",
114 "Analyze the current configuration for security problems");
115 if( setup_user ){
116 setup_menu_entry("Robot-Defense", "setup_robot",
117 "Settings for configure defense against robots");
118 setup_menu_entry("Settings", "setup_settings",
119 "Web interface to the \"fossil settings\" command");
120 }
121 setup_menu_entry("Timeline", "setup_timeline",
122 "Timeline display preferences");
@@ -322,10 +324,105 @@
324 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
325 }
326 @ </select> <b>%h(zLabel)</b>
327 }
328
329 /*
330 ** Insert code into the current page that allows the user to configure
331 ** auto-hyperlink related robot defense settings.
332 */
333 static void addAutoHyperlinkSettings(void){
334 static const char *const azDefenseOpts[] = {
335 "0", "Off",
336 "2", "UserAgent only",
337 "1", "UserAgent and Javascript",
338 };
339 multiple_choice_attribute(
340 "Enable hyperlinks base on User-Agent and/or Javascript",
341 "auto-hyperlink", "autohyperlink", "1",
342 count(azDefenseOpts)/2, azDefenseOpts);
343 @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users,
344 @ including user "nobody", as long as the User-Agent string in the
345 @ HTTP header indicates that the request is coming from an actual human
346 @ being. If this setting is "UserAgent only" (2) then the
347 @ UserAgent string is the only factor considered. If the value of this
348 @ setting is "UserAgent And Javascript" (1) then Javascript is added that
349 @ runs after the page loads and fills in the href= values of &lt;a&gt;
350 @ elements. In either case, &lt;a&gt; tags are only generated if the
351 @ UserAgent string indicates that the request is coming from a human and
352 @ not a robot.
353 @
354 @ <p>This setting is designed to give easy access to humans while
355 @ keeping out robots.
356 @ You do not normally want a robot to walk your entire repository because
357 @ if it does, your server will end up computing diffs and annotations for
358 @ every historical version of every file and creating ZIPs and tarballs of
359 @ every historical check-in, which can use a lot of CPU and bandwidth
360 @ even for relatively small projects.</p>
361 @
362 @ <p>The "UserAgent and Javascript" value for this setting provides
363 @ superior protection from robots. However, that setting also prevents
364 @ the visited/unvisited colors on hyperlinks from displaying correctly
365 @ on Safara-derived browsers. (Chrome and Firefox work fine.) Since
366 @ Safari is the underlying rendering engine on all iPhones and iPads,
367 @ this means that hyperlink visited/unvisited colors will not operate
368 @ on those platforms when "UserAgent and Javascript" is selected.</p>
369 @
370 @ <p>Additional parameters that control the behavior of Javascript:</p>
371 @ <blockquote>
372 entry_attribute("Delay in milliseconds before enabling hyperlinks", 5,
373 "auto-hyperlink-delay", "ah-delay", "50", 0);
374 @ <br />
375 onoff_attribute("Also require a mouse event before enabling hyperlinks",
376 "auto-hyperlink-mouseover", "ahmo", 0, 0);
377 @ </blockquote>
378 @ <p>For maximum robot defense, "Delay" should be at least 50 milliseconds
379 @ and "require a mouse event" should be turned on. These values only come
380 @ into play when the main auto-hyperlink settings is 2 ("UserAgent and
381 @ Javascript").</p>
382 @
383 @ <p>To see if Javascript-base hyperlink enabling mechanism is working,
384 @ visit the <a href="%R/test_env">/test_env</a> page (from a separate
385 @ web browser that is not logged in, even as "anonymous") and verify
386 @ that the "g.jsHref" value is "1".</p>
387 @ <p>(Properties: "auto-hyperlink", "auto-hyperlink-delay", and
388 @ "auto-hyperlink-mouseover"")</p>
389 }
390
391 /*
392 ** WEBPAGE: setup_robot
393 **
394 ** Settings associated with defense against robots. Requires setup privilege.
395 */
396 void setup_robots(void){
397 login_check_credentials();
398 if( !g.perm.Setup ){
399 login_needed(0);
400 return;
401 }
402 style_set_current_feature("setup");
403 style_header("Robot Defense Settings");
404 db_begin_transaction();
405 @ <p>A Fossil website can have billions of pages in its tree, even for a
406 @ modest project. Many of those pages (examples: diffs and tarballs)
407 @ might be expensive to compute. A robot that tries to walk the entire
408 @ website can present a crippling CPU and bandwidth load.
409 @
410 @ <p>The settings on this page are intended to help site administrators
411 @ defend the site against robots.
412 @
413 @ <form action="%R/setup_robot" method="post"><div>
414 login_insert_csrf_secret();
415 @ <input type="submit" name="submit" value="Apply Changes" /></p>
416 @ <hr />
417 addAutoHyperlinkSettings();
418 @ <hr />
419 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
420 @ </div></form>
421 db_end_transaction(0);
422 style_finish_page();
423 }
424
425 /*
426 ** WEBPAGE: setup_access
427 **
428 ** The access-control settings page. Requires Setup privileges.
@@ -460,59 +557,15 @@
557 @ This limit is only enforced on Unix servers. On Linux systems,
558 @ access to the /proc virtual filesystem is required, which means this limit
559 @ might not work inside a chroot() jail.
560 @ (Property: "max-loadavg")</p>
561
562 /* Add the auto-hyperlink settings controls. These same controls
563 ** are also accessible from the /setup_robot page.
564 */
565 @ <hr />
566 addAutoHyperlinkSettings();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
567
568 @ <hr />
569 onoff_attribute("Require a CAPTCHA if not logged in",
570 "require-captcha", "reqcapt", 1, 0);
571 @ <p>Require a CAPTCHA for edit operations (appending, creating, or
572
+3 -3
--- src/sitemap.c
+++ src/sitemap.c
@@ -74,11 +74,11 @@
7474
if( P("popup")!=0 ){
7575
/* The "popup" query parameter
7676
** then disable anti-robot defenses */
7777
isPopup = 1;
7878
g.perm.Hyperlink = 1;
79
- g.javascriptHyperlink = 0;
79
+ g.jsHref = 0;
8080
}
8181
srchFlags = search_restrict(SRCH_ALL);
8282
if( !isPopup ){
8383
style_header("Site Map");
8484
style_adunit_config(ADUNIT_RIGHT_OK);
@@ -312,11 +312,11 @@
312312
if( P("popup")!=0 && cgi_csrf_safe(0) ){
313313
/* If this is a POST from the same origin with the popup=1 parameter,
314314
** then disable anti-robot defenses */
315315
isPopup = 1;
316316
g.perm.Hyperlink = 1;
317
- g.javascriptHyperlink = 0;
317
+ g.jsHref = 0;
318318
}
319319
if( !isPopup ){
320320
style_header("Test Page Map");
321321
style_adunit_config(ADUNIT_RIGHT_OK);
322322
}
@@ -364,11 +364,11 @@
364364
if( P("popup")!=0 && cgi_csrf_safe(0) ){
365365
/* If this is a POST from the same origin with the popup=1 parameter,
366366
** then disable anti-robot defenses */
367367
isPopup = 1;
368368
g.perm.Hyperlink = 1;
369
- g.javascriptHyperlink = 0;
369
+ g.jsHref = 0;
370370
}
371371
if( !isPopup ){
372372
style_header("Timeline Examples");
373373
style_adunit_config(ADUNIT_RIGHT_OK);
374374
}
375375
--- src/sitemap.c
+++ src/sitemap.c
@@ -74,11 +74,11 @@
74 if( P("popup")!=0 ){
75 /* The "popup" query parameter
76 ** then disable anti-robot defenses */
77 isPopup = 1;
78 g.perm.Hyperlink = 1;
79 g.javascriptHyperlink = 0;
80 }
81 srchFlags = search_restrict(SRCH_ALL);
82 if( !isPopup ){
83 style_header("Site Map");
84 style_adunit_config(ADUNIT_RIGHT_OK);
@@ -312,11 +312,11 @@
312 if( P("popup")!=0 && cgi_csrf_safe(0) ){
313 /* If this is a POST from the same origin with the popup=1 parameter,
314 ** then disable anti-robot defenses */
315 isPopup = 1;
316 g.perm.Hyperlink = 1;
317 g.javascriptHyperlink = 0;
318 }
319 if( !isPopup ){
320 style_header("Test Page Map");
321 style_adunit_config(ADUNIT_RIGHT_OK);
322 }
@@ -364,11 +364,11 @@
364 if( P("popup")!=0 && cgi_csrf_safe(0) ){
365 /* If this is a POST from the same origin with the popup=1 parameter,
366 ** then disable anti-robot defenses */
367 isPopup = 1;
368 g.perm.Hyperlink = 1;
369 g.javascriptHyperlink = 0;
370 }
371 if( !isPopup ){
372 style_header("Timeline Examples");
373 style_adunit_config(ADUNIT_RIGHT_OK);
374 }
375
--- src/sitemap.c
+++ src/sitemap.c
@@ -74,11 +74,11 @@
74 if( P("popup")!=0 ){
75 /* The "popup" query parameter
76 ** then disable anti-robot defenses */
77 isPopup = 1;
78 g.perm.Hyperlink = 1;
79 g.jsHref = 0;
80 }
81 srchFlags = search_restrict(SRCH_ALL);
82 if( !isPopup ){
83 style_header("Site Map");
84 style_adunit_config(ADUNIT_RIGHT_OK);
@@ -312,11 +312,11 @@
312 if( P("popup")!=0 && cgi_csrf_safe(0) ){
313 /* If this is a POST from the same origin with the popup=1 parameter,
314 ** then disable anti-robot defenses */
315 isPopup = 1;
316 g.perm.Hyperlink = 1;
317 g.jsHref = 0;
318 }
319 if( !isPopup ){
320 style_header("Test Page Map");
321 style_adunit_config(ADUNIT_RIGHT_OK);
322 }
@@ -364,11 +364,11 @@
364 if( P("popup")!=0 && cgi_csrf_safe(0) ){
365 /* If this is a POST from the same origin with the popup=1 parameter,
366 ** then disable anti-robot defenses */
367 isPopup = 1;
368 g.perm.Hyperlink = 1;
369 g.jsHref = 0;
370 }
371 if( !isPopup ){
372 style_header("Timeline Examples");
373 style_adunit_config(ADUNIT_RIGHT_OK);
374 }
375
+22 -22
--- src/style.c
+++ src/style.c
@@ -106,35 +106,35 @@
106106
** Generate and return a anchor tag like this:
107107
**
108108
** <a href="URL">
109109
** or <a id="ID">
110110
**
111
-** The form of the anchor tag is determined by the g.javascriptHyperlink
111
+** The form of the anchor tag is determined by the g.jsHref
112112
** and g.perm.Hyperlink variables.
113113
**
114
-** g.perm.Hyperlink g.javascriptHyperlink Returned anchor format
115
-** ---------------- --------------------- ------------------------
116
-** 0 0 (empty string)
117
-** 0 1 (empty string)
118
-** 1 0 <a href="URL">
119
-** 1 1 <a data-href="URL">
114
+** g.perm.Hyperlink g.jsHref Returned anchor format
115
+** ---------------- -------- ------------------------
116
+** 0 0 (empty string)
117
+** 0 1 (empty string)
118
+** 1 0 <a href="URL">
119
+** 1 1 <a data-href="URL">
120120
**
121121
** No anchor tag is generated if g.perm.Hyperlink is false.
122
-** The href="URL" form is used if g.javascriptHyperlink is false.
123
-** If g.javascriptHyperlink is true then the data-href="URL" and
122
+** The href="URL" form is used if g.jsHref is false.
123
+** If g.jsHref is true then the data-href="URL" and
124124
** href="/honeypot" is generated and javascript is added to the footer
125125
** to cause data-href values to be inserted into href
126126
** after the page has loaded. The use of the data-href="URL" form
127127
** instead of href="URL" is a defense against bots.
128128
**
129129
** If the user lacks the Hyperlink (h) property and the "auto-hyperlink"
130130
** setting is true, then g.perm.Hyperlink is changed from 0 to 1 and
131
-** g.javascriptHyperlink is set to 1 by login_check_credentials(). Thus
131
+** g.jsHref is set to 1 by login_check_credentials(). Thus
132132
** the g.perm.Hyperlink property will be true even if the user does not
133133
** have the "h" privilege if the "auto-hyperlink" setting is true.
134134
**
135
-** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink
135
+** User has "h" auto-hyperlink g.perm.Hyperlink g.jsHref
136136
** ------------ -------------- ---------------- ---------------------
137137
** 0 0 0 0
138138
** 1 0 1 0
139139
** 0 1 1 1
140140
** 1 1 1 0
@@ -173,11 +173,11 @@
173173
va_list ap;
174174
if( !g.perm.Hyperlink ) return fossil_strdup("");
175175
va_start(ap, zFormat);
176176
zUrl = vmprintf(zFormat, ap);
177177
va_end(ap);
178
- if( !g.javascriptHyperlink ){
178
+ if( !g.jsHref ){
179179
char *zHUrl;
180180
if( zExtra ){
181181
zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl);
182182
}else{
183183
zHUrl = mprintf("<a href=\"%h\">", zUrl);
@@ -198,11 +198,11 @@
198198
va_list ap;
199199
if( !g.perm.Hyperlink ) return fossil_strdup("");
200200
va_start(ap, zFormat);
201201
zUrl = vmprintf(zFormat, ap);
202202
va_end(ap);
203
- if( !g.javascriptHyperlink ){
203
+ if( !g.jsHref ){
204204
char *zHUrl = mprintf("<a class=\"%s\" href=\"%h\">", zExtra, zUrl);
205205
fossil_free(zUrl);
206206
return zHUrl;
207207
}
208208
needHrefJs = 1;
@@ -214,11 +214,11 @@
214214
va_list ap;
215215
if( !g.perm.Hyperlink ) return fossil_strdup("");
216216
va_start(ap, zFormat);
217217
zUrl = vmprintf(zFormat, ap);
218218
va_end(ap);
219
- if( !g.javascriptHyperlink ){
219
+ if( !g.jsHref ){
220220
char *zHUrl = mprintf("<a href=\"%h\">", zUrl);
221221
fossil_free(zUrl);
222222
return zHUrl;
223223
}
224224
needHrefJs = 1;
@@ -233,18 +233,18 @@
233233
** As a defense against robots, the action=ARG might instead by data-action=ARG
234234
** and javascript (href.js) added to the page so that the data-action= is
235235
** changed into action= after the page loads. Whether or not this happens
236236
** depends on if the user has the "h" privilege and whether or not the
237237
** auto-hyperlink setting is on. These setings determine the values of
238
-** variables g.perm.Hyperlink and g.javascriptHyperlink.
238
+** variables g.perm.Hyperlink and g.jsHref.
239239
**
240
-** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink
241
-** ------------ -------------- ---------------- ---------------------
242
-** 1: 0 0 0 0
243
-** 2: 1 0 1 0
244
-** 3: 0 1 1 1
245
-** 4: 1 1 1 0
240
+** User has "h" auto-hyperlink g.perm.Hyperlink g.jsHref
241
+** ------------ -------------- ---------------- --------
242
+** 1: 0 0 0 0
243
+** 2: 1 0 1 0
244
+** 3: 0 1 1 1
245
+** 4: 1 1 1 0
246246
**
247247
** The data-action=ARG form is used for cases 1 and 3. In case 1, the href.js
248248
** javascript is omitted and so the form is effectively disabled.
249249
*/
250250
void form_begin(const char *zOtherArgs, const char *zAction, ...){
@@ -1388,11 +1388,11 @@
13881388
@ g.zTop = %h(g.zTop)<br />
13891389
@ g.zPath = %h(g.zPath)<br />
13901390
@ g.userUid = %d(g.userUid)<br />
13911391
@ g.zLogin = %h(g.zLogin)<br />
13921392
@ g.isHuman = %d(g.isHuman)<br />
1393
- @ g.javascriptHyperlink = %d(g.javascriptHyperlink)<br />
1393
+ @ g.jsHref = %d(g.jsHref)<br />
13941394
if( g.nRequest ){
13951395
@ g.nRequest = %d(g.nRequest)<br />
13961396
}
13971397
if( g.nPendingRequest>1 ){
13981398
@ g.nPendingRequest = %d(g.nPendingRequest)<br />
13991399
--- src/style.c
+++ src/style.c
@@ -106,35 +106,35 @@
106 ** Generate and return a anchor tag like this:
107 **
108 ** <a href="URL">
109 ** or <a id="ID">
110 **
111 ** The form of the anchor tag is determined by the g.javascriptHyperlink
112 ** and g.perm.Hyperlink variables.
113 **
114 ** g.perm.Hyperlink g.javascriptHyperlink Returned anchor format
115 ** ---------------- --------------------- ------------------------
116 ** 0 0 (empty string)
117 ** 0 1 (empty string)
118 ** 1 0 <a href="URL">
119 ** 1 1 <a data-href="URL">
120 **
121 ** No anchor tag is generated if g.perm.Hyperlink is false.
122 ** The href="URL" form is used if g.javascriptHyperlink is false.
123 ** If g.javascriptHyperlink is true then the data-href="URL" and
124 ** href="/honeypot" is generated and javascript is added to the footer
125 ** to cause data-href values to be inserted into href
126 ** after the page has loaded. The use of the data-href="URL" form
127 ** instead of href="URL" is a defense against bots.
128 **
129 ** If the user lacks the Hyperlink (h) property and the "auto-hyperlink"
130 ** setting is true, then g.perm.Hyperlink is changed from 0 to 1 and
131 ** g.javascriptHyperlink is set to 1 by login_check_credentials(). Thus
132 ** the g.perm.Hyperlink property will be true even if the user does not
133 ** have the "h" privilege if the "auto-hyperlink" setting is true.
134 **
135 ** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink
136 ** ------------ -------------- ---------------- ---------------------
137 ** 0 0 0 0
138 ** 1 0 1 0
139 ** 0 1 1 1
140 ** 1 1 1 0
@@ -173,11 +173,11 @@
173 va_list ap;
174 if( !g.perm.Hyperlink ) return fossil_strdup("");
175 va_start(ap, zFormat);
176 zUrl = vmprintf(zFormat, ap);
177 va_end(ap);
178 if( !g.javascriptHyperlink ){
179 char *zHUrl;
180 if( zExtra ){
181 zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl);
182 }else{
183 zHUrl = mprintf("<a href=\"%h\">", zUrl);
@@ -198,11 +198,11 @@
198 va_list ap;
199 if( !g.perm.Hyperlink ) return fossil_strdup("");
200 va_start(ap, zFormat);
201 zUrl = vmprintf(zFormat, ap);
202 va_end(ap);
203 if( !g.javascriptHyperlink ){
204 char *zHUrl = mprintf("<a class=\"%s\" href=\"%h\">", zExtra, zUrl);
205 fossil_free(zUrl);
206 return zHUrl;
207 }
208 needHrefJs = 1;
@@ -214,11 +214,11 @@
214 va_list ap;
215 if( !g.perm.Hyperlink ) return fossil_strdup("");
216 va_start(ap, zFormat);
217 zUrl = vmprintf(zFormat, ap);
218 va_end(ap);
219 if( !g.javascriptHyperlink ){
220 char *zHUrl = mprintf("<a href=\"%h\">", zUrl);
221 fossil_free(zUrl);
222 return zHUrl;
223 }
224 needHrefJs = 1;
@@ -233,18 +233,18 @@
233 ** As a defense against robots, the action=ARG might instead by data-action=ARG
234 ** and javascript (href.js) added to the page so that the data-action= is
235 ** changed into action= after the page loads. Whether or not this happens
236 ** depends on if the user has the "h" privilege and whether or not the
237 ** auto-hyperlink setting is on. These setings determine the values of
238 ** variables g.perm.Hyperlink and g.javascriptHyperlink.
239 **
240 ** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink
241 ** ------------ -------------- ---------------- ---------------------
242 ** 1: 0 0 0 0
243 ** 2: 1 0 1 0
244 ** 3: 0 1 1 1
245 ** 4: 1 1 1 0
246 **
247 ** The data-action=ARG form is used for cases 1 and 3. In case 1, the href.js
248 ** javascript is omitted and so the form is effectively disabled.
249 */
250 void form_begin(const char *zOtherArgs, const char *zAction, ...){
@@ -1388,11 +1388,11 @@
1388 @ g.zTop = %h(g.zTop)<br />
1389 @ g.zPath = %h(g.zPath)<br />
1390 @ g.userUid = %d(g.userUid)<br />
1391 @ g.zLogin = %h(g.zLogin)<br />
1392 @ g.isHuman = %d(g.isHuman)<br />
1393 @ g.javascriptHyperlink = %d(g.javascriptHyperlink)<br />
1394 if( g.nRequest ){
1395 @ g.nRequest = %d(g.nRequest)<br />
1396 }
1397 if( g.nPendingRequest>1 ){
1398 @ g.nPendingRequest = %d(g.nPendingRequest)<br />
1399
--- src/style.c
+++ src/style.c
@@ -106,35 +106,35 @@
106 ** Generate and return a anchor tag like this:
107 **
108 ** <a href="URL">
109 ** or <a id="ID">
110 **
111 ** The form of the anchor tag is determined by the g.jsHref
112 ** and g.perm.Hyperlink variables.
113 **
114 ** g.perm.Hyperlink g.jsHref Returned anchor format
115 ** ---------------- -------- ------------------------
116 ** 0 0 (empty string)
117 ** 0 1 (empty string)
118 ** 1 0 <a href="URL">
119 ** 1 1 <a data-href="URL">
120 **
121 ** No anchor tag is generated if g.perm.Hyperlink is false.
122 ** The href="URL" form is used if g.jsHref is false.
123 ** If g.jsHref is true then the data-href="URL" and
124 ** href="/honeypot" is generated and javascript is added to the footer
125 ** to cause data-href values to be inserted into href
126 ** after the page has loaded. The use of the data-href="URL" form
127 ** instead of href="URL" is a defense against bots.
128 **
129 ** If the user lacks the Hyperlink (h) property and the "auto-hyperlink"
130 ** setting is true, then g.perm.Hyperlink is changed from 0 to 1 and
131 ** g.jsHref is set to 1 by login_check_credentials(). Thus
132 ** the g.perm.Hyperlink property will be true even if the user does not
133 ** have the "h" privilege if the "auto-hyperlink" setting is true.
134 **
135 ** User has "h" auto-hyperlink g.perm.Hyperlink g.jsHref
136 ** ------------ -------------- ---------------- ---------------------
137 ** 0 0 0 0
138 ** 1 0 1 0
139 ** 0 1 1 1
140 ** 1 1 1 0
@@ -173,11 +173,11 @@
173 va_list ap;
174 if( !g.perm.Hyperlink ) return fossil_strdup("");
175 va_start(ap, zFormat);
176 zUrl = vmprintf(zFormat, ap);
177 va_end(ap);
178 if( !g.jsHref ){
179 char *zHUrl;
180 if( zExtra ){
181 zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl);
182 }else{
183 zHUrl = mprintf("<a href=\"%h\">", zUrl);
@@ -198,11 +198,11 @@
198 va_list ap;
199 if( !g.perm.Hyperlink ) return fossil_strdup("");
200 va_start(ap, zFormat);
201 zUrl = vmprintf(zFormat, ap);
202 va_end(ap);
203 if( !g.jsHref ){
204 char *zHUrl = mprintf("<a class=\"%s\" href=\"%h\">", zExtra, zUrl);
205 fossil_free(zUrl);
206 return zHUrl;
207 }
208 needHrefJs = 1;
@@ -214,11 +214,11 @@
214 va_list ap;
215 if( !g.perm.Hyperlink ) return fossil_strdup("");
216 va_start(ap, zFormat);
217 zUrl = vmprintf(zFormat, ap);
218 va_end(ap);
219 if( !g.jsHref ){
220 char *zHUrl = mprintf("<a href=\"%h\">", zUrl);
221 fossil_free(zUrl);
222 return zHUrl;
223 }
224 needHrefJs = 1;
@@ -233,18 +233,18 @@
233 ** As a defense against robots, the action=ARG might instead by data-action=ARG
234 ** and javascript (href.js) added to the page so that the data-action= is
235 ** changed into action= after the page loads. Whether or not this happens
236 ** depends on if the user has the "h" privilege and whether or not the
237 ** auto-hyperlink setting is on. These setings determine the values of
238 ** variables g.perm.Hyperlink and g.jsHref.
239 **
240 ** User has "h" auto-hyperlink g.perm.Hyperlink g.jsHref
241 ** ------------ -------------- ---------------- --------
242 ** 1: 0 0 0 0
243 ** 2: 1 0 1 0
244 ** 3: 0 1 1 1
245 ** 4: 1 1 1 0
246 **
247 ** The data-action=ARG form is used for cases 1 and 3. In case 1, the href.js
248 ** javascript is omitted and so the form is effectively disabled.
249 */
250 void form_begin(const char *zOtherArgs, const char *zAction, ...){
@@ -1388,11 +1388,11 @@
1388 @ g.zTop = %h(g.zTop)<br />
1389 @ g.zPath = %h(g.zPath)<br />
1390 @ g.userUid = %d(g.userUid)<br />
1391 @ g.zLogin = %h(g.zLogin)<br />
1392 @ g.isHuman = %d(g.isHuman)<br />
1393 @ g.jsHref = %d(g.jsHref)<br />
1394 if( g.nRequest ){
1395 @ g.nRequest = %d(g.nRequest)<br />
1396 }
1397 if( g.nPendingRequest>1 ){
1398 @ g.nPendingRequest = %d(g.nPendingRequest)<br />
1399

Keyboard Shortcuts

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