Fossil SCM
Added "Remember me?" checkbox to login (default=on). Corrected cgi_set_cookie() to immediately expire the cookie for a negative lifetime (it was previously re-setting the cookie as a session cookie for that case).
Commit
32975aabe7ea4c492410f302b48f8dcb5c6b27a84054d5d73ad86d352d134be7
Parent
ba3cf9c4de03f3e…
2 files changed
+8
-5
+30
-14
+8
-5
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -234,11 +234,12 @@ | ||
| 234 | 234 | |
| 235 | 235 | /* |
| 236 | 236 | ** Set a cookie by queuing up the appropriate HTTP header output. If |
| 237 | 237 | ** !g.isHTTP, this is a no-op. |
| 238 | 238 | ** |
| 239 | -** Zero lifetime implies a session cookie. | |
| 239 | +** Zero lifetime implies a session cookie. A negative one expires | |
| 240 | +** the cookie immediately. | |
| 240 | 241 | */ |
| 241 | 242 | void cgi_set_cookie( |
| 242 | 243 | const char *zName, /* Name of the cookie */ |
| 243 | 244 | const char *zValue, /* Value of the cookie. Automatically escaped */ |
| 244 | 245 | const char *zPath, /* Path cookie applies to. NULL means "/" */ |
| @@ -251,17 +252,19 @@ | ||
| 251 | 252 | if( zPath[0]==0 ) zPath = "/"; |
| 252 | 253 | } |
| 253 | 254 | if( g.zBaseURL!=0 && strncmp(g.zBaseURL, "https:", 6)==0 ){ |
| 254 | 255 | zSecure = " secure;"; |
| 255 | 256 | } |
| 256 | - if( lifetime>0 ){ | |
| 257 | + if( lifetime!=0 ){ | |
| 257 | 258 | blob_appendf(&extraHeader, |
| 258 | - "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly;%s Version=1\r\n", | |
| 259 | - zName, zValue, zPath, lifetime, zSecure); | |
| 259 | + "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; " | |
| 260 | + "SameSite=strict; %s Version=1\r\n", | |
| 261 | + zName, lifetime>0 ? zValue : "null", zPath, lifetime, zSecure); | |
| 260 | 262 | }else{ |
| 261 | 263 | blob_appendf(&extraHeader, |
| 262 | - "Set-Cookie: %s=%t; Path=%s; HttpOnly;%s Version=1\r\n", | |
| 264 | + "Set-Cookie: %s=%t; Path=%s; HttpOnly; SameSite=strict; " | |
| 265 | + "%s Version=1\r\n", | |
| 263 | 266 | zName, zValue, zPath, zSecure); |
| 264 | 267 | } |
| 265 | 268 | } |
| 266 | 269 | |
| 267 | 270 | |
| 268 | 271 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -234,11 +234,12 @@ | |
| 234 | |
| 235 | /* |
| 236 | ** Set a cookie by queuing up the appropriate HTTP header output. If |
| 237 | ** !g.isHTTP, this is a no-op. |
| 238 | ** |
| 239 | ** Zero lifetime implies a session cookie. |
| 240 | */ |
| 241 | void cgi_set_cookie( |
| 242 | const char *zName, /* Name of the cookie */ |
| 243 | const char *zValue, /* Value of the cookie. Automatically escaped */ |
| 244 | const char *zPath, /* Path cookie applies to. NULL means "/" */ |
| @@ -251,17 +252,19 @@ | |
| 251 | if( zPath[0]==0 ) zPath = "/"; |
| 252 | } |
| 253 | if( g.zBaseURL!=0 && strncmp(g.zBaseURL, "https:", 6)==0 ){ |
| 254 | zSecure = " secure;"; |
| 255 | } |
| 256 | if( lifetime>0 ){ |
| 257 | blob_appendf(&extraHeader, |
| 258 | "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly;%s Version=1\r\n", |
| 259 | zName, zValue, zPath, lifetime, zSecure); |
| 260 | }else{ |
| 261 | blob_appendf(&extraHeader, |
| 262 | "Set-Cookie: %s=%t; Path=%s; HttpOnly;%s Version=1\r\n", |
| 263 | zName, zValue, zPath, zSecure); |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | |
| 268 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -234,11 +234,12 @@ | |
| 234 | |
| 235 | /* |
| 236 | ** Set a cookie by queuing up the appropriate HTTP header output. If |
| 237 | ** !g.isHTTP, this is a no-op. |
| 238 | ** |
| 239 | ** Zero lifetime implies a session cookie. A negative one expires |
| 240 | ** the cookie immediately. |
| 241 | */ |
| 242 | void cgi_set_cookie( |
| 243 | const char *zName, /* Name of the cookie */ |
| 244 | const char *zValue, /* Value of the cookie. Automatically escaped */ |
| 245 | const char *zPath, /* Path cookie applies to. NULL means "/" */ |
| @@ -251,17 +252,19 @@ | |
| 252 | if( zPath[0]==0 ) zPath = "/"; |
| 253 | } |
| 254 | if( g.zBaseURL!=0 && strncmp(g.zBaseURL, "https:", 6)==0 ){ |
| 255 | zSecure = " secure;"; |
| 256 | } |
| 257 | if( lifetime!=0 ){ |
| 258 | blob_appendf(&extraHeader, |
| 259 | "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; " |
| 260 | "SameSite=strict; %s Version=1\r\n", |
| 261 | zName, lifetime>0 ? zValue : "null", zPath, lifetime, zSecure); |
| 262 | }else{ |
| 263 | blob_appendf(&extraHeader, |
| 264 | "Set-Cookie: %s=%t; Path=%s; HttpOnly; SameSite=strict; " |
| 265 | "%s Version=1\r\n", |
| 266 | zName, zValue, zPath, zSecure); |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | |
| 271 |
+30
-14
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -262,11 +262,13 @@ | ||
| 262 | 262 | ** |
| 263 | 263 | ** If zDest is not NULL then the generated cookie is copied to |
| 264 | 264 | ** *zDdest and ownership is transfered to the caller (who should |
| 265 | 265 | ** eventually pass it to free()). |
| 266 | 266 | ** |
| 267 | -** If bSessionCookie is true, the cookie will be a session cookie. | |
| 267 | +** If bSessionCookie is true, the cookie will be a session cookie | |
| 268 | +** and the [user].[cexpire] and [user].[cookie] entries will not be | |
| 269 | +** modified. | |
| 268 | 270 | */ |
| 269 | 271 | void login_set_user_cookie( |
| 270 | 272 | const char *zUsername, /* User's name */ |
| 271 | 273 | int uid, /* User's ID */ |
| 272 | 274 | char **zDest, /* Optional: store generated cookie value. */ |
| @@ -273,31 +275,33 @@ | ||
| 273 | 275 | int bSessionCookie /* True for session-only cookie */ |
| 274 | 276 | ){ |
| 275 | 277 | const char *zCookieName = login_cookie_name(); |
| 276 | 278 | const char *zExpire = bSessionCookie ? 0 : db_get("cookie-expire","8766"); |
| 277 | 279 | int expires = bSessionCookie ? 0 : atoi(zExpire)*3600; |
| 278 | - char *zHash; | |
| 280 | + char *zHash = 0; | |
| 279 | 281 | char *zCookie; |
| 280 | 282 | const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */ |
| 281 | 283 | |
| 282 | 284 | assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data."); |
| 283 | - zHash = db_text(0, | |
| 285 | + if(bSessionCookie==0){ | |
| 286 | + zHash = db_text(0, | |
| 284 | 287 | "SELECT cookie FROM user" |
| 285 | 288 | " WHERE uid=%d" |
| 286 | 289 | " AND cexpire>julianday('now')" |
| 287 | 290 | " AND length(cookie)>30", |
| 288 | 291 | uid); |
| 292 | + } | |
| 289 | 293 | if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))"); |
| 290 | 294 | zCookie = login_gen_user_cookie_value(zUsername, zHash); |
| 291 | 295 | cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires); |
| 292 | 296 | record_login_attempt(zUsername, zIpAddr, 1); |
| 293 | - db_multi_exec( | |
| 294 | - "UPDATE user SET cookie=%Q," | |
| 295 | - " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", | |
| 296 | - zHash, expires, uid | |
| 297 | - ); | |
| 298 | - free(zHash); | |
| 297 | + if(bSessionCookie==0){ | |
| 298 | + db_multi_exec("UPDATE user SET cookie=%Q," | |
| 299 | + " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", | |
| 300 | + zHash, expires, uid); | |
| 301 | + } | |
| 302 | + fossil_free(zHash); | |
| 299 | 303 | if( zDest ){ |
| 300 | 304 | *zDest = zCookie; |
| 301 | 305 | }else{ |
| 302 | 306 | free(zCookie); |
| 303 | 307 | } |
| @@ -521,20 +525,21 @@ | ||
| 521 | 525 | char *zErrMsg = ""; |
| 522 | 526 | int uid; /* User id logged in user */ |
| 523 | 527 | char *zSha1Pw; |
| 524 | 528 | const char *zIpAddr; /* IP address of requestor */ |
| 525 | 529 | const char *zReferer; |
| 526 | - int noAnon = P("noanon")!=0; | |
| 530 | + const int noAnon = P("noanon")!=0; | |
| 531 | + int rememberMe; /* If true, use persistent cookie, | |
| 532 | + else session cookie */ | |
| 527 | 533 | |
| 528 | 534 | login_check_credentials(); |
| 529 | 535 | fossil_redirect_to_https_if_needed(1); |
| 530 | 536 | sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0, |
| 531 | 537 | constant_time_cmp_function, 0, 0); |
| 532 | 538 | zUsername = P("u"); |
| 533 | 539 | zPasswd = P("p"); |
| 534 | 540 | anonFlag = g.zLogin==0 && PB("anon"); |
| 535 | - | |
| 536 | 541 | /* Handle log-out requests */ |
| 537 | 542 | if( P("out") ){ |
| 538 | 543 | login_clear_login_data(); |
| 539 | 544 | redirect_to_g(); |
| 540 | 545 | return; |
| @@ -606,12 +611,18 @@ | ||
| 606 | 611 | } |
| 607 | 612 | } |
| 608 | 613 | zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */ |
| 609 | 614 | zReferer = P("HTTP_REFERER"); |
| 610 | 615 | uid = login_is_valid_anonymous(zUsername, zPasswd, P("cs")); |
| 616 | + if(zUsername==0){ | |
| 617 | + /* Initial login page hit. */ | |
| 618 | + rememberMe = 1 /* seems like a sensible default */; | |
| 619 | + }else{ | |
| 620 | + rememberMe = P("remember")!=0; | |
| 621 | + } | |
| 611 | 622 | if( uid>0 ){ |
| 612 | - login_set_anon_cookie(zIpAddr, NULL, 0); | |
| 623 | + login_set_anon_cookie(zIpAddr, NULL, rememberMe?0:1); | |
| 613 | 624 | record_login_attempt("anonymous", zIpAddr, 1); |
| 614 | 625 | redirect_to_g(); |
| 615 | 626 | } |
| 616 | 627 | if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ |
| 617 | 628 | /* Attempting to log in as a user other than anonymous. |
| @@ -631,11 +642,11 @@ | ||
| 631 | 642 | ** HASH/PROJECT/LOGIN |
| 632 | 643 | ** |
| 633 | 644 | ** where HASH is a random hex number, PROJECT is either project |
| 634 | 645 | ** code prefix, and LOGIN is the user name. |
| 635 | 646 | */ |
| 636 | - login_set_user_cookie(zUsername, uid, NULL, 0); | |
| 647 | + login_set_user_cookie(zUsername, uid, NULL, rememberMe?0:1); | |
| 637 | 648 | redirect_to_g(); |
| 638 | 649 | } |
| 639 | 650 | } |
| 640 | 651 | style_header("Login/Logout"); |
| 641 | 652 | style_adunit_config(ADUNIT_OFF); |
| @@ -652,10 +663,11 @@ | ||
| 652 | 663 | @ <p>Login as <b>anonymous</b> or any named user |
| 653 | 664 | @ to access page <b>%h(zAbbrev)</b>. |
| 654 | 665 | }else{ |
| 655 | 666 | @ <p>Login as a named user to access page <b>%h(zAbbrev)</b>. |
| 656 | 667 | } |
| 668 | + fossil_free(zAbbrev); | |
| 657 | 669 | } |
| 658 | 670 | if( g.sslNotAvailable==0 |
| 659 | 671 | && strncmp(g.zBaseURL,"https:",6)!=0 |
| 660 | 672 | && db_get_boolean("https-login",0) |
| 661 | 673 | ){ |
| @@ -712,11 +724,15 @@ | ||
| 712 | 724 | } |
| 713 | 725 | @ </span></td></tr> |
| 714 | 726 | } |
| 715 | 727 | @ <tr> |
| 716 | 728 | @ <td></td> |
| 717 | - @ <td><input type="submit" name="in" value="Login"></td> | |
| 729 | + @ <td><input type="submit" name="in" value="Login"> | |
| 730 | + @ <input type="checkbox" name="remember" value="1" \ | |
| 731 | + @ %s(rememberMe ? "checked=\"checked\"" : "")>Remember me? | |
| 732 | + @ (If checked, login will use a persistent cookie, else it | |
| 733 | + @ will use a session cookie.)</td> | |
| 718 | 734 | @ </tr> |
| 719 | 735 | if( !noAnon && login_self_register_available(0) ){ |
| 720 | 736 | @ <tr> |
| 721 | 737 | @ <td></td> |
| 722 | 738 | @ <td><input type="submit" name="self" value="Create A New Account"> |
| 723 | 739 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -262,11 +262,13 @@ | |
| 262 | ** |
| 263 | ** If zDest is not NULL then the generated cookie is copied to |
| 264 | ** *zDdest and ownership is transfered to the caller (who should |
| 265 | ** eventually pass it to free()). |
| 266 | ** |
| 267 | ** If bSessionCookie is true, the cookie will be a session cookie. |
| 268 | */ |
| 269 | void login_set_user_cookie( |
| 270 | const char *zUsername, /* User's name */ |
| 271 | int uid, /* User's ID */ |
| 272 | char **zDest, /* Optional: store generated cookie value. */ |
| @@ -273,31 +275,33 @@ | |
| 273 | int bSessionCookie /* True for session-only cookie */ |
| 274 | ){ |
| 275 | const char *zCookieName = login_cookie_name(); |
| 276 | const char *zExpire = bSessionCookie ? 0 : db_get("cookie-expire","8766"); |
| 277 | int expires = bSessionCookie ? 0 : atoi(zExpire)*3600; |
| 278 | char *zHash; |
| 279 | char *zCookie; |
| 280 | const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */ |
| 281 | |
| 282 | assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data."); |
| 283 | zHash = db_text(0, |
| 284 | "SELECT cookie FROM user" |
| 285 | " WHERE uid=%d" |
| 286 | " AND cexpire>julianday('now')" |
| 287 | " AND length(cookie)>30", |
| 288 | uid); |
| 289 | if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))"); |
| 290 | zCookie = login_gen_user_cookie_value(zUsername, zHash); |
| 291 | cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires); |
| 292 | record_login_attempt(zUsername, zIpAddr, 1); |
| 293 | db_multi_exec( |
| 294 | "UPDATE user SET cookie=%Q," |
| 295 | " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", |
| 296 | zHash, expires, uid |
| 297 | ); |
| 298 | free(zHash); |
| 299 | if( zDest ){ |
| 300 | *zDest = zCookie; |
| 301 | }else{ |
| 302 | free(zCookie); |
| 303 | } |
| @@ -521,20 +525,21 @@ | |
| 521 | char *zErrMsg = ""; |
| 522 | int uid; /* User id logged in user */ |
| 523 | char *zSha1Pw; |
| 524 | const char *zIpAddr; /* IP address of requestor */ |
| 525 | const char *zReferer; |
| 526 | int noAnon = P("noanon")!=0; |
| 527 | |
| 528 | login_check_credentials(); |
| 529 | fossil_redirect_to_https_if_needed(1); |
| 530 | sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0, |
| 531 | constant_time_cmp_function, 0, 0); |
| 532 | zUsername = P("u"); |
| 533 | zPasswd = P("p"); |
| 534 | anonFlag = g.zLogin==0 && PB("anon"); |
| 535 | |
| 536 | /* Handle log-out requests */ |
| 537 | if( P("out") ){ |
| 538 | login_clear_login_data(); |
| 539 | redirect_to_g(); |
| 540 | return; |
| @@ -606,12 +611,18 @@ | |
| 606 | } |
| 607 | } |
| 608 | zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */ |
| 609 | zReferer = P("HTTP_REFERER"); |
| 610 | uid = login_is_valid_anonymous(zUsername, zPasswd, P("cs")); |
| 611 | if( uid>0 ){ |
| 612 | login_set_anon_cookie(zIpAddr, NULL, 0); |
| 613 | record_login_attempt("anonymous", zIpAddr, 1); |
| 614 | redirect_to_g(); |
| 615 | } |
| 616 | if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ |
| 617 | /* Attempting to log in as a user other than anonymous. |
| @@ -631,11 +642,11 @@ | |
| 631 | ** HASH/PROJECT/LOGIN |
| 632 | ** |
| 633 | ** where HASH is a random hex number, PROJECT is either project |
| 634 | ** code prefix, and LOGIN is the user name. |
| 635 | */ |
| 636 | login_set_user_cookie(zUsername, uid, NULL, 0); |
| 637 | redirect_to_g(); |
| 638 | } |
| 639 | } |
| 640 | style_header("Login/Logout"); |
| 641 | style_adunit_config(ADUNIT_OFF); |
| @@ -652,10 +663,11 @@ | |
| 652 | @ <p>Login as <b>anonymous</b> or any named user |
| 653 | @ to access page <b>%h(zAbbrev)</b>. |
| 654 | }else{ |
| 655 | @ <p>Login as a named user to access page <b>%h(zAbbrev)</b>. |
| 656 | } |
| 657 | } |
| 658 | if( g.sslNotAvailable==0 |
| 659 | && strncmp(g.zBaseURL,"https:",6)!=0 |
| 660 | && db_get_boolean("https-login",0) |
| 661 | ){ |
| @@ -712,11 +724,15 @@ | |
| 712 | } |
| 713 | @ </span></td></tr> |
| 714 | } |
| 715 | @ <tr> |
| 716 | @ <td></td> |
| 717 | @ <td><input type="submit" name="in" value="Login"></td> |
| 718 | @ </tr> |
| 719 | if( !noAnon && login_self_register_available(0) ){ |
| 720 | @ <tr> |
| 721 | @ <td></td> |
| 722 | @ <td><input type="submit" name="self" value="Create A New Account"> |
| 723 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -262,11 +262,13 @@ | |
| 262 | ** |
| 263 | ** If zDest is not NULL then the generated cookie is copied to |
| 264 | ** *zDdest and ownership is transfered to the caller (who should |
| 265 | ** eventually pass it to free()). |
| 266 | ** |
| 267 | ** If bSessionCookie is true, the cookie will be a session cookie |
| 268 | ** and the [user].[cexpire] and [user].[cookie] entries will not be |
| 269 | ** modified. |
| 270 | */ |
| 271 | void login_set_user_cookie( |
| 272 | const char *zUsername, /* User's name */ |
| 273 | int uid, /* User's ID */ |
| 274 | char **zDest, /* Optional: store generated cookie value. */ |
| @@ -273,31 +275,33 @@ | |
| 275 | int bSessionCookie /* True for session-only cookie */ |
| 276 | ){ |
| 277 | const char *zCookieName = login_cookie_name(); |
| 278 | const char *zExpire = bSessionCookie ? 0 : db_get("cookie-expire","8766"); |
| 279 | int expires = bSessionCookie ? 0 : atoi(zExpire)*3600; |
| 280 | char *zHash = 0; |
| 281 | char *zCookie; |
| 282 | const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */ |
| 283 | |
| 284 | assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data."); |
| 285 | if(bSessionCookie==0){ |
| 286 | zHash = db_text(0, |
| 287 | "SELECT cookie FROM user" |
| 288 | " WHERE uid=%d" |
| 289 | " AND cexpire>julianday('now')" |
| 290 | " AND length(cookie)>30", |
| 291 | uid); |
| 292 | } |
| 293 | if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))"); |
| 294 | zCookie = login_gen_user_cookie_value(zUsername, zHash); |
| 295 | cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires); |
| 296 | record_login_attempt(zUsername, zIpAddr, 1); |
| 297 | if(bSessionCookie==0){ |
| 298 | db_multi_exec("UPDATE user SET cookie=%Q," |
| 299 | " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", |
| 300 | zHash, expires, uid); |
| 301 | } |
| 302 | fossil_free(zHash); |
| 303 | if( zDest ){ |
| 304 | *zDest = zCookie; |
| 305 | }else{ |
| 306 | free(zCookie); |
| 307 | } |
| @@ -521,20 +525,21 @@ | |
| 525 | char *zErrMsg = ""; |
| 526 | int uid; /* User id logged in user */ |
| 527 | char *zSha1Pw; |
| 528 | const char *zIpAddr; /* IP address of requestor */ |
| 529 | const char *zReferer; |
| 530 | const int noAnon = P("noanon")!=0; |
| 531 | int rememberMe; /* If true, use persistent cookie, |
| 532 | else session cookie */ |
| 533 | |
| 534 | login_check_credentials(); |
| 535 | fossil_redirect_to_https_if_needed(1); |
| 536 | sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0, |
| 537 | constant_time_cmp_function, 0, 0); |
| 538 | zUsername = P("u"); |
| 539 | zPasswd = P("p"); |
| 540 | anonFlag = g.zLogin==0 && PB("anon"); |
| 541 | /* Handle log-out requests */ |
| 542 | if( P("out") ){ |
| 543 | login_clear_login_data(); |
| 544 | redirect_to_g(); |
| 545 | return; |
| @@ -606,12 +611,18 @@ | |
| 611 | } |
| 612 | } |
| 613 | zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */ |
| 614 | zReferer = P("HTTP_REFERER"); |
| 615 | uid = login_is_valid_anonymous(zUsername, zPasswd, P("cs")); |
| 616 | if(zUsername==0){ |
| 617 | /* Initial login page hit. */ |
| 618 | rememberMe = 1 /* seems like a sensible default */; |
| 619 | }else{ |
| 620 | rememberMe = P("remember")!=0; |
| 621 | } |
| 622 | if( uid>0 ){ |
| 623 | login_set_anon_cookie(zIpAddr, NULL, rememberMe?0:1); |
| 624 | record_login_attempt("anonymous", zIpAddr, 1); |
| 625 | redirect_to_g(); |
| 626 | } |
| 627 | if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ |
| 628 | /* Attempting to log in as a user other than anonymous. |
| @@ -631,11 +642,11 @@ | |
| 642 | ** HASH/PROJECT/LOGIN |
| 643 | ** |
| 644 | ** where HASH is a random hex number, PROJECT is either project |
| 645 | ** code prefix, and LOGIN is the user name. |
| 646 | */ |
| 647 | login_set_user_cookie(zUsername, uid, NULL, rememberMe?0:1); |
| 648 | redirect_to_g(); |
| 649 | } |
| 650 | } |
| 651 | style_header("Login/Logout"); |
| 652 | style_adunit_config(ADUNIT_OFF); |
| @@ -652,10 +663,11 @@ | |
| 663 | @ <p>Login as <b>anonymous</b> or any named user |
| 664 | @ to access page <b>%h(zAbbrev)</b>. |
| 665 | }else{ |
| 666 | @ <p>Login as a named user to access page <b>%h(zAbbrev)</b>. |
| 667 | } |
| 668 | fossil_free(zAbbrev); |
| 669 | } |
| 670 | if( g.sslNotAvailable==0 |
| 671 | && strncmp(g.zBaseURL,"https:",6)!=0 |
| 672 | && db_get_boolean("https-login",0) |
| 673 | ){ |
| @@ -712,11 +724,15 @@ | |
| 724 | } |
| 725 | @ </span></td></tr> |
| 726 | } |
| 727 | @ <tr> |
| 728 | @ <td></td> |
| 729 | @ <td><input type="submit" name="in" value="Login"> |
| 730 | @ <input type="checkbox" name="remember" value="1" \ |
| 731 | @ %s(rememberMe ? "checked=\"checked\"" : "")>Remember me? |
| 732 | @ (If checked, login will use a persistent cookie, else it |
| 733 | @ will use a session cookie.)</td> |
| 734 | @ </tr> |
| 735 | if( !noAnon && login_self_register_available(0) ){ |
| 736 | @ <tr> |
| 737 | @ <td></td> |
| 738 | @ <td><input type="submit" name="self" value="Create A New Account"> |
| 739 |