Fossil SCM
New setting "anon-cookie-lifespan" sets the life span of an anonymous login cookie. The default is 8 hours. Set to zero to disable anonymous login.
Commit
7d2b47a7c3f068ebf948e2545c996897d98d167c4dd021931f643f5a490bea78
Parent
4c4bce351d974e5…
2 files changed
+29
-8
+14
+29
-8
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -160,10 +160,11 @@ | ||
| 160 | 160 | |
| 161 | 161 | if( zUsername==0 ) return 0; |
| 162 | 162 | else if( zPassword==0 ) return 0; |
| 163 | 163 | else if( zCS==0 ) return 0; |
| 164 | 164 | else if( fossil_strcmp(zUsername,"anonymous")!=0 ) return 0; |
| 165 | + else if( anon_cookie_lifespan()==0 ) return 0; | |
| 165 | 166 | while( 1/*exit-by-break*/ ){ |
| 166 | 167 | zPw = captcha_decode((unsigned int)atoi(zCS), n); |
| 167 | 168 | if( zPw==0 ) return 0; |
| 168 | 169 | if( fossil_stricmp(zPw, zPassword)==0 ) break; |
| 169 | 170 | n++; |
| @@ -340,13 +341,32 @@ | ||
| 340 | 341 | free(zCookie); |
| 341 | 342 | } |
| 342 | 343 | } |
| 343 | 344 | |
| 344 | 345 | /* |
| 345 | -** Lifetime of an anoymous cookie, in seconds. | |
| 346 | +** SETTING: anon-cookie-lifespan width=10 default=480 | |
| 347 | +** The number of minutes for which an anonymous login cookie is | |
| 348 | +** valid. Anonymous logins are prohibited if this value is zero. | |
| 349 | +*/ | |
| 350 | + | |
| 351 | + | |
| 352 | +/* | |
| 353 | +** The default lifetime of an anoymous cookie, in minutes. | |
| 354 | +*/ | |
| 355 | +#define ANONYMOUS_COOKIE_LIFESPAN (8*60) | |
| 356 | + | |
| 357 | +/* | |
| 358 | +** Return the lifetime of an anonymous cookie, in minutes. | |
| 346 | 359 | */ |
| 347 | -#define ANONYMOUS_COOKIE_LIFESPAN 28800 /* 28800 seconds == 8 hours */ | |
| 360 | +int anon_cookie_lifespan(void){ | |
| 361 | + static int lifespan = -1; | |
| 362 | + if( lifespan<0 ){ | |
| 363 | + lifespan = db_get_int("anon-cookie-lifespan", ANONYMOUS_COOKIE_LIFESPAN); | |
| 364 | + if( lifespan<0 ) lifespan = 0; | |
| 365 | + } | |
| 366 | + return lifespan; | |
| 367 | +} | |
| 348 | 368 | |
| 349 | 369 | /* Sets a cookie for an anonymous user login, which looks like this: |
| 350 | 370 | ** |
| 351 | 371 | ** HASH/TIME/anonymous |
| 352 | 372 | ** |
| @@ -364,11 +384,11 @@ | ||
| 364 | 384 | char *zNow; /* Current time (julian day number) */ |
| 365 | 385 | char *zCookie; /* The login cookie */ |
| 366 | 386 | const char *zUserAgent; /* The user agent */ |
| 367 | 387 | const char *zCookieName; /* Name of the login cookie */ |
| 368 | 388 | Blob b; /* Blob used during cookie construction */ |
| 369 | - int expires = bSessionCookie ? 0 : ANONYMOUS_COOKIE_LIFESPAN; | |
| 389 | + int expires = bSessionCookie ? 0 : anon_cookie_lifespan(); | |
| 370 | 390 | zCookieName = login_cookie_name(); |
| 371 | 391 | zNow = db_text("0", "SELECT julianday('now')"); |
| 372 | 392 | assert( zCookieName && zNow ); |
| 373 | 393 | blob_init(&b, zNow, -1); |
| 374 | 394 | zUserAgent = PD("HTTP_USER_AGENT","nil"); |
| @@ -602,11 +622,11 @@ | ||
| 602 | 622 | ** visitors. |
| 603 | 623 | ** |
| 604 | 624 | ** anon=1 is advisory and only has effect if there is not some other login |
| 605 | 625 | ** cookie. anon=2 means always show the captcha. |
| 606 | 626 | */ |
| 607 | - anonFlag = atoi(PD("anon","0")); | |
| 627 | + anonFlag = anon_cookie_lifespan()>0 ? atoi(PD("anon","0")) : 0; | |
| 608 | 628 | if( anonFlag==2 ){ |
| 609 | 629 | g.zLogin = 0; |
| 610 | 630 | }else{ |
| 611 | 631 | login_check_credentials(); |
| 612 | 632 | if( g.zLogin!=0 ) anonFlag = 0; |
| @@ -785,11 +805,11 @@ | ||
| 785 | 805 | @ <p>Currently logged in as <b>%h(g.zLogin)</b>. |
| 786 | 806 | @ <input type="submit" name="out" value="Logout" autofocus></p> |
| 787 | 807 | @ </form> |
| 788 | 808 | }else{ |
| 789 | 809 | unsigned int uSeed = captcha_seed(); |
| 790 | - if( g.zLogin==0 && (anonFlag || zGoto==0) ){ | |
| 810 | + if( g.zLogin==0 && (anonFlag || zGoto==0) && anon_cookie_lifespan()>0 ){ | |
| 791 | 811 | zAnonPw = db_text(0, "SELECT pw FROM user" |
| 792 | 812 | " WHERE login='anonymous'" |
| 793 | 813 | " AND cap!=''"); |
| 794 | 814 | }else{ |
| 795 | 815 | zAnonPw = 0; |
| @@ -1418,11 +1438,12 @@ | ||
| 1418 | 1438 | } |
| 1419 | 1439 | } |
| 1420 | 1440 | } |
| 1421 | 1441 | if( zUser==0 ){ |
| 1422 | 1442 | /* Invalid cookie */ |
| 1423 | - }else if( fossil_strcmp(zUser, "anonymous")==0 ){ | |
| 1443 | + }else if( fossil_strcmp(zUser, "anonymous")==0 | |
| 1444 | + && anon_cookie_lifespan()>0 ){ | |
| 1424 | 1445 | /* Cookies of the form "HASH/TIME/anonymous". The TIME must |
| 1425 | 1446 | ** not be more than ANONYMOUS_COOKIE_LIFESPAN seconds ago and |
| 1426 | 1447 | ** the sha1 hash of TIME/USERAGENT/SECRET must match HASH. USERAGENT |
| 1427 | 1448 | ** is the HTTP_USER_AGENT of the client and SECRET is the |
| 1428 | 1449 | ** "captcha-secret" value in the repository. See tag-20250817a |
| @@ -1444,11 +1465,11 @@ | ||
| 1444 | 1465 | uid = db_int(0, |
| 1445 | 1466 | "SELECT uid FROM user WHERE login='anonymous'" |
| 1446 | 1467 | " AND octet_length(cap)>0" |
| 1447 | 1468 | " AND octet_length(pw)>0" |
| 1448 | 1469 | " AND %.17g>julianday('now')", |
| 1449 | - rTime+ANONYMOUS_COOKIE_LIFESPAN/86400.0 | |
| 1470 | + rTime+anon_cookie_lifespan()/1440.0 | |
| 1450 | 1471 | ); |
| 1451 | 1472 | } |
| 1452 | 1473 | }while( uid==0 ); |
| 1453 | 1474 | blob_reset(&b); |
| 1454 | 1475 | }else{ |
| @@ -1909,11 +1930,11 @@ | ||
| 1909 | 1930 | ** the anonymous user has Hyperlink permission, then paint a mesage |
| 1910 | 1931 | ** to inform the user that much more information is available by |
| 1911 | 1932 | ** logging in as anonymous. |
| 1912 | 1933 | */ |
| 1913 | 1934 | void login_anonymous_available(void){ |
| 1914 | - if( !g.perm.Hyperlink && g.anon.Hyperlink ){ | |
| 1935 | + if( !g.perm.Hyperlink && g.anon.Hyperlink && anon_cookie_lifespan()>0 ){ | |
| 1915 | 1936 | const char *zUrl = PD("PATH_INFO", ""); |
| 1916 | 1937 | @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br> |
| 1917 | 1938 | @ Use <a href="%R/login?anon=1&g=%T(zUrl)">anonymous login</a> |
| 1918 | 1939 | @ to enable hyperlinks.</p> |
| 1919 | 1940 | } |
| 1920 | 1941 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -160,10 +160,11 @@ | |
| 160 | |
| 161 | if( zUsername==0 ) return 0; |
| 162 | else if( zPassword==0 ) return 0; |
| 163 | else if( zCS==0 ) return 0; |
| 164 | else if( fossil_strcmp(zUsername,"anonymous")!=0 ) return 0; |
| 165 | while( 1/*exit-by-break*/ ){ |
| 166 | zPw = captcha_decode((unsigned int)atoi(zCS), n); |
| 167 | if( zPw==0 ) return 0; |
| 168 | if( fossil_stricmp(zPw, zPassword)==0 ) break; |
| 169 | n++; |
| @@ -340,13 +341,32 @@ | |
| 340 | free(zCookie); |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | /* |
| 345 | ** Lifetime of an anoymous cookie, in seconds. |
| 346 | */ |
| 347 | #define ANONYMOUS_COOKIE_LIFESPAN 28800 /* 28800 seconds == 8 hours */ |
| 348 | |
| 349 | /* Sets a cookie for an anonymous user login, which looks like this: |
| 350 | ** |
| 351 | ** HASH/TIME/anonymous |
| 352 | ** |
| @@ -364,11 +384,11 @@ | |
| 364 | char *zNow; /* Current time (julian day number) */ |
| 365 | char *zCookie; /* The login cookie */ |
| 366 | const char *zUserAgent; /* The user agent */ |
| 367 | const char *zCookieName; /* Name of the login cookie */ |
| 368 | Blob b; /* Blob used during cookie construction */ |
| 369 | int expires = bSessionCookie ? 0 : ANONYMOUS_COOKIE_LIFESPAN; |
| 370 | zCookieName = login_cookie_name(); |
| 371 | zNow = db_text("0", "SELECT julianday('now')"); |
| 372 | assert( zCookieName && zNow ); |
| 373 | blob_init(&b, zNow, -1); |
| 374 | zUserAgent = PD("HTTP_USER_AGENT","nil"); |
| @@ -602,11 +622,11 @@ | |
| 602 | ** visitors. |
| 603 | ** |
| 604 | ** anon=1 is advisory and only has effect if there is not some other login |
| 605 | ** cookie. anon=2 means always show the captcha. |
| 606 | */ |
| 607 | anonFlag = atoi(PD("anon","0")); |
| 608 | if( anonFlag==2 ){ |
| 609 | g.zLogin = 0; |
| 610 | }else{ |
| 611 | login_check_credentials(); |
| 612 | if( g.zLogin!=0 ) anonFlag = 0; |
| @@ -785,11 +805,11 @@ | |
| 785 | @ <p>Currently logged in as <b>%h(g.zLogin)</b>. |
| 786 | @ <input type="submit" name="out" value="Logout" autofocus></p> |
| 787 | @ </form> |
| 788 | }else{ |
| 789 | unsigned int uSeed = captcha_seed(); |
| 790 | if( g.zLogin==0 && (anonFlag || zGoto==0) ){ |
| 791 | zAnonPw = db_text(0, "SELECT pw FROM user" |
| 792 | " WHERE login='anonymous'" |
| 793 | " AND cap!=''"); |
| 794 | }else{ |
| 795 | zAnonPw = 0; |
| @@ -1418,11 +1438,12 @@ | |
| 1418 | } |
| 1419 | } |
| 1420 | } |
| 1421 | if( zUser==0 ){ |
| 1422 | /* Invalid cookie */ |
| 1423 | }else if( fossil_strcmp(zUser, "anonymous")==0 ){ |
| 1424 | /* Cookies of the form "HASH/TIME/anonymous". The TIME must |
| 1425 | ** not be more than ANONYMOUS_COOKIE_LIFESPAN seconds ago and |
| 1426 | ** the sha1 hash of TIME/USERAGENT/SECRET must match HASH. USERAGENT |
| 1427 | ** is the HTTP_USER_AGENT of the client and SECRET is the |
| 1428 | ** "captcha-secret" value in the repository. See tag-20250817a |
| @@ -1444,11 +1465,11 @@ | |
| 1444 | uid = db_int(0, |
| 1445 | "SELECT uid FROM user WHERE login='anonymous'" |
| 1446 | " AND octet_length(cap)>0" |
| 1447 | " AND octet_length(pw)>0" |
| 1448 | " AND %.17g>julianday('now')", |
| 1449 | rTime+ANONYMOUS_COOKIE_LIFESPAN/86400.0 |
| 1450 | ); |
| 1451 | } |
| 1452 | }while( uid==0 ); |
| 1453 | blob_reset(&b); |
| 1454 | }else{ |
| @@ -1909,11 +1930,11 @@ | |
| 1909 | ** the anonymous user has Hyperlink permission, then paint a mesage |
| 1910 | ** to inform the user that much more information is available by |
| 1911 | ** logging in as anonymous. |
| 1912 | */ |
| 1913 | void login_anonymous_available(void){ |
| 1914 | if( !g.perm.Hyperlink && g.anon.Hyperlink ){ |
| 1915 | const char *zUrl = PD("PATH_INFO", ""); |
| 1916 | @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br> |
| 1917 | @ Use <a href="%R/login?anon=1&g=%T(zUrl)">anonymous login</a> |
| 1918 | @ to enable hyperlinks.</p> |
| 1919 | } |
| 1920 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -160,10 +160,11 @@ | |
| 160 | |
| 161 | if( zUsername==0 ) return 0; |
| 162 | else if( zPassword==0 ) return 0; |
| 163 | else if( zCS==0 ) return 0; |
| 164 | else if( fossil_strcmp(zUsername,"anonymous")!=0 ) return 0; |
| 165 | else if( anon_cookie_lifespan()==0 ) return 0; |
| 166 | while( 1/*exit-by-break*/ ){ |
| 167 | zPw = captcha_decode((unsigned int)atoi(zCS), n); |
| 168 | if( zPw==0 ) return 0; |
| 169 | if( fossil_stricmp(zPw, zPassword)==0 ) break; |
| 170 | n++; |
| @@ -340,13 +341,32 @@ | |
| 341 | free(zCookie); |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | /* |
| 346 | ** SETTING: anon-cookie-lifespan width=10 default=480 |
| 347 | ** The number of minutes for which an anonymous login cookie is |
| 348 | ** valid. Anonymous logins are prohibited if this value is zero. |
| 349 | */ |
| 350 | |
| 351 | |
| 352 | /* |
| 353 | ** The default lifetime of an anoymous cookie, in minutes. |
| 354 | */ |
| 355 | #define ANONYMOUS_COOKIE_LIFESPAN (8*60) |
| 356 | |
| 357 | /* |
| 358 | ** Return the lifetime of an anonymous cookie, in minutes. |
| 359 | */ |
| 360 | int anon_cookie_lifespan(void){ |
| 361 | static int lifespan = -1; |
| 362 | if( lifespan<0 ){ |
| 363 | lifespan = db_get_int("anon-cookie-lifespan", ANONYMOUS_COOKIE_LIFESPAN); |
| 364 | if( lifespan<0 ) lifespan = 0; |
| 365 | } |
| 366 | return lifespan; |
| 367 | } |
| 368 | |
| 369 | /* Sets a cookie for an anonymous user login, which looks like this: |
| 370 | ** |
| 371 | ** HASH/TIME/anonymous |
| 372 | ** |
| @@ -364,11 +384,11 @@ | |
| 384 | char *zNow; /* Current time (julian day number) */ |
| 385 | char *zCookie; /* The login cookie */ |
| 386 | const char *zUserAgent; /* The user agent */ |
| 387 | const char *zCookieName; /* Name of the login cookie */ |
| 388 | Blob b; /* Blob used during cookie construction */ |
| 389 | int expires = bSessionCookie ? 0 : anon_cookie_lifespan(); |
| 390 | zCookieName = login_cookie_name(); |
| 391 | zNow = db_text("0", "SELECT julianday('now')"); |
| 392 | assert( zCookieName && zNow ); |
| 393 | blob_init(&b, zNow, -1); |
| 394 | zUserAgent = PD("HTTP_USER_AGENT","nil"); |
| @@ -602,11 +622,11 @@ | |
| 622 | ** visitors. |
| 623 | ** |
| 624 | ** anon=1 is advisory and only has effect if there is not some other login |
| 625 | ** cookie. anon=2 means always show the captcha. |
| 626 | */ |
| 627 | anonFlag = anon_cookie_lifespan()>0 ? atoi(PD("anon","0")) : 0; |
| 628 | if( anonFlag==2 ){ |
| 629 | g.zLogin = 0; |
| 630 | }else{ |
| 631 | login_check_credentials(); |
| 632 | if( g.zLogin!=0 ) anonFlag = 0; |
| @@ -785,11 +805,11 @@ | |
| 805 | @ <p>Currently logged in as <b>%h(g.zLogin)</b>. |
| 806 | @ <input type="submit" name="out" value="Logout" autofocus></p> |
| 807 | @ </form> |
| 808 | }else{ |
| 809 | unsigned int uSeed = captcha_seed(); |
| 810 | if( g.zLogin==0 && (anonFlag || zGoto==0) && anon_cookie_lifespan()>0 ){ |
| 811 | zAnonPw = db_text(0, "SELECT pw FROM user" |
| 812 | " WHERE login='anonymous'" |
| 813 | " AND cap!=''"); |
| 814 | }else{ |
| 815 | zAnonPw = 0; |
| @@ -1418,11 +1438,12 @@ | |
| 1438 | } |
| 1439 | } |
| 1440 | } |
| 1441 | if( zUser==0 ){ |
| 1442 | /* Invalid cookie */ |
| 1443 | }else if( fossil_strcmp(zUser, "anonymous")==0 |
| 1444 | && anon_cookie_lifespan()>0 ){ |
| 1445 | /* Cookies of the form "HASH/TIME/anonymous". The TIME must |
| 1446 | ** not be more than ANONYMOUS_COOKIE_LIFESPAN seconds ago and |
| 1447 | ** the sha1 hash of TIME/USERAGENT/SECRET must match HASH. USERAGENT |
| 1448 | ** is the HTTP_USER_AGENT of the client and SECRET is the |
| 1449 | ** "captcha-secret" value in the repository. See tag-20250817a |
| @@ -1444,11 +1465,11 @@ | |
| 1465 | uid = db_int(0, |
| 1466 | "SELECT uid FROM user WHERE login='anonymous'" |
| 1467 | " AND octet_length(cap)>0" |
| 1468 | " AND octet_length(pw)>0" |
| 1469 | " AND %.17g>julianday('now')", |
| 1470 | rTime+anon_cookie_lifespan()/1440.0 |
| 1471 | ); |
| 1472 | } |
| 1473 | }while( uid==0 ); |
| 1474 | blob_reset(&b); |
| 1475 | }else{ |
| @@ -1909,11 +1930,11 @@ | |
| 1930 | ** the anonymous user has Hyperlink permission, then paint a mesage |
| 1931 | ** to inform the user that much more information is available by |
| 1932 | ** logging in as anonymous. |
| 1933 | */ |
| 1934 | void login_anonymous_available(void){ |
| 1935 | if( !g.perm.Hyperlink && g.anon.Hyperlink && anon_cookie_lifespan()>0 ){ |
| 1936 | const char *zUrl = PD("PATH_INFO", ""); |
| 1937 | @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br> |
| 1938 | @ Use <a href="%R/login?anon=1&g=%T(zUrl)">anonymous login</a> |
| 1939 | @ to enable hyperlinks.</p> |
| 1940 | } |
| 1941 |
+14
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -518,10 +518,17 @@ | ||
| 518 | 518 | "robot-restrict", "rbrestrict", robot_restrict_default(), 0); |
| 519 | 519 | |
| 520 | 520 | @ <hr> |
| 521 | 521 | addAutoHyperlinkSettings(); |
| 522 | 522 | |
| 523 | + @ <hr> | |
| 524 | + entry_attribute("Anonymous Login Validity", 11, "anon-cookie-lifespan", | |
| 525 | + "anoncookls", "840", 0); | |
| 526 | + @ <p>The number of minutes for which an anonymous login cookie is valid. | |
| 527 | + @ Set to zero to disable anonymous login. | |
| 528 | + @ (property: anon-cookie-lifespan) | |
| 529 | + | |
| 523 | 530 | @ <hr> |
| 524 | 531 | entry_attribute("Server Load Average Limit", 11, "max-loadavg", "mxldavg", |
| 525 | 532 | "0.0", 0); |
| 526 | 533 | @ <p>Some expensive operations (such as computing tarballs, zip archives, |
| 527 | 534 | @ or annotation/blame pages) are prohibited if the load average on the host |
| @@ -769,10 +776,17 @@ | ||
| 769 | 776 | @ "anonymous" that will automatically fill in the CAPTCHA password. |
| 770 | 777 | @ This is less secure than forcing the user to do it manually, but is |
| 771 | 778 | @ probably secure enough and it is certainly more convenient for |
| 772 | 779 | @ anonymous users. (Property: "auto-captcha")</p> |
| 773 | 780 | |
| 781 | + @ <hr> | |
| 782 | + entry_attribute("Anonymous Login Validity", 11, "anon-cookie-lifespan", | |
| 783 | + "anoncookls", "840", 0); | |
| 784 | + @ <p>The number of minutes for which an anonymous login cookie is valid. | |
| 785 | + @ Set to zero to disable anonymous logins. | |
| 786 | + @ (property: anon-cookie-lifespan) | |
| 787 | + | |
| 774 | 788 | @ <hr> |
| 775 | 789 | @ <p><input type="submit" name="submit" value="Apply Changes"></p> |
| 776 | 790 | @ </div></form> |
| 777 | 791 | db_end_transaction(0); |
| 778 | 792 | style_finish_page(); |
| 779 | 793 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -518,10 +518,17 @@ | |
| 518 | "robot-restrict", "rbrestrict", robot_restrict_default(), 0); |
| 519 | |
| 520 | @ <hr> |
| 521 | addAutoHyperlinkSettings(); |
| 522 | |
| 523 | @ <hr> |
| 524 | entry_attribute("Server Load Average Limit", 11, "max-loadavg", "mxldavg", |
| 525 | "0.0", 0); |
| 526 | @ <p>Some expensive operations (such as computing tarballs, zip archives, |
| 527 | @ or annotation/blame pages) are prohibited if the load average on the host |
| @@ -769,10 +776,17 @@ | |
| 769 | @ "anonymous" that will automatically fill in the CAPTCHA password. |
| 770 | @ This is less secure than forcing the user to do it manually, but is |
| 771 | @ probably secure enough and it is certainly more convenient for |
| 772 | @ anonymous users. (Property: "auto-captcha")</p> |
| 773 | |
| 774 | @ <hr> |
| 775 | @ <p><input type="submit" name="submit" value="Apply Changes"></p> |
| 776 | @ </div></form> |
| 777 | db_end_transaction(0); |
| 778 | style_finish_page(); |
| 779 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -518,10 +518,17 @@ | |
| 518 | "robot-restrict", "rbrestrict", robot_restrict_default(), 0); |
| 519 | |
| 520 | @ <hr> |
| 521 | addAutoHyperlinkSettings(); |
| 522 | |
| 523 | @ <hr> |
| 524 | entry_attribute("Anonymous Login Validity", 11, "anon-cookie-lifespan", |
| 525 | "anoncookls", "840", 0); |
| 526 | @ <p>The number of minutes for which an anonymous login cookie is valid. |
| 527 | @ Set to zero to disable anonymous login. |
| 528 | @ (property: anon-cookie-lifespan) |
| 529 | |
| 530 | @ <hr> |
| 531 | entry_attribute("Server Load Average Limit", 11, "max-loadavg", "mxldavg", |
| 532 | "0.0", 0); |
| 533 | @ <p>Some expensive operations (such as computing tarballs, zip archives, |
| 534 | @ or annotation/blame pages) are prohibited if the load average on the host |
| @@ -769,10 +776,17 @@ | |
| 776 | @ "anonymous" that will automatically fill in the CAPTCHA password. |
| 777 | @ This is less secure than forcing the user to do it manually, but is |
| 778 | @ probably secure enough and it is certainly more convenient for |
| 779 | @ anonymous users. (Property: "auto-captcha")</p> |
| 780 | |
| 781 | @ <hr> |
| 782 | entry_attribute("Anonymous Login Validity", 11, "anon-cookie-lifespan", |
| 783 | "anoncookls", "840", 0); |
| 784 | @ <p>The number of minutes for which an anonymous login cookie is valid. |
| 785 | @ Set to zero to disable anonymous logins. |
| 786 | @ (property: anon-cookie-lifespan) |
| 787 | |
| 788 | @ <hr> |
| 789 | @ <p><input type="submit" name="submit" value="Apply Changes"></p> |
| 790 | @ </div></form> |
| 791 | db_end_transaction(0); |
| 792 | style_finish_page(); |
| 793 |