Fossil SCM
First cut at code to allow anonymous users to self-register.
Commit
fedf27e483764c5f7389981ac3a4b1a8266d3c18
Parent
5f23fbad37cdc2c…
1 file changed
+124
+124
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -266,10 +266,13 @@ | ||
| 266 | 266 | } |
| 267 | 267 | @ your user-id and password at the left and press the |
| 268 | 268 | @ "Login" button. Your user name will be stored in a browser cookie. |
| 269 | 269 | @ You must configure your web browser to accept cookies in order for |
| 270 | 270 | @ the login to take.</p> |
| 271 | + @ | |
| 272 | + @ <p>If you do not have an account, you can | |
| 273 | + @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>. | |
| 271 | 274 | if( zAnonPw ){ |
| 272 | 275 | unsigned int uSeed = captcha_seed(); |
| 273 | 276 | char const *zDecoded = captcha_decode(uSeed); |
| 274 | 277 | int bAutoCaptcha = db_get_boolean("auto-captcha", 1); |
| 275 | 278 | char *zCaptcha = captcha_render(zDecoded); |
| @@ -624,5 +627,126 @@ | ||
| 624 | 627 | g.okCsrf = 1; |
| 625 | 628 | return; |
| 626 | 629 | } |
| 627 | 630 | fossil_fatal("Cross-site request forgery attempt"); |
| 628 | 631 | } |
| 632 | + | |
| 633 | +/* | |
| 634 | +** WEBPAGE: register | |
| 635 | +** | |
| 636 | +** Generate the register page. | |
| 637 | +** | |
| 638 | +*/ | |
| 639 | +void register_page(void){ | |
| 640 | + const char *zUsername, *zPasswd, *zConfirm, *zContact, *zCS, *zPw, *zCap; | |
| 641 | + | |
| 642 | + style_header("Register"); | |
| 643 | + zUsername = P("u"); | |
| 644 | + zPasswd = P("p"); | |
| 645 | + zConfirm = P("cp"); | |
| 646 | + zContact = P("c"); | |
| 647 | + zCap = P("cap"); | |
| 648 | + zCS = P("cs"); /* Captcha Secret */ | |
| 649 | + | |
| 650 | + /* Try to make any sense from user input. */ | |
| 651 | + if( P("new") ){ | |
| 652 | + if( zCS==0 ) fossil_redirect_home(); /* Forged request */ | |
| 653 | + zPw = captcha_decode((unsigned int)atoi(zCS)); | |
| 654 | + if( !(zUsername && zPasswd && zConfirm && zContact) ){ | |
| 655 | + @ <p><span class="loginError"> | |
| 656 | + @ All fields are obligatory. | |
| 657 | + @ </span></p> | |
| 658 | + }else if( strcmp(zPasswd,zConfirm)!=0 ){ | |
| 659 | + @ <p><span class="loginError"> | |
| 660 | + @ The two copies of your new passwords do not match. | |
| 661 | + @ </span></p> | |
| 662 | + }else if( strcasecmp(zPw, zCap)!=0 ){ | |
| 663 | + @ <p><span class="loginError"> | |
| 664 | + @ Captcha text invalid. | |
| 665 | + @ </span></p> | |
| 666 | + }else{ | |
| 667 | + /* This almost is stupid copy-paste of code from user.c:user_cmd(). */ | |
| 668 | + Blob passwd, login, contact; | |
| 669 | + | |
| 670 | + blob_init(&login, zUsername, -1); | |
| 671 | + blob_init(&contact, zContact, -1); | |
| 672 | + blob_init(&passwd, zPasswd, -1); | |
| 673 | + | |
| 674 | + if( db_exists("SELECT 1 FROM user WHERE login=%B", &login) ){ | |
| 675 | + /* Here lies the reason I don't use zErrMsg - it would not substitute | |
| 676 | + * this %s(zUsername), or at least I don't know how to force it to.*/ | |
| 677 | + @ <p><span class="loginError"> | |
| 678 | + @ %s(zUsername) already exists. | |
| 679 | + @ </span></p> | |
| 680 | + }else{ | |
| 681 | + char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login)); | |
| 682 | + db_multi_exec( | |
| 683 | + "INSERT INTO user(login,pw,cap,info)" | |
| 684 | + "VALUES(%B,%Q,'u',%B)", /* u - register as reader, not developer! */ | |
| 685 | + &login, zPw, &contact | |
| 686 | + ); | |
| 687 | + free(zPw); | |
| 688 | + | |
| 689 | + /* The user is registered, now just log him in. */ | |
| 690 | + int uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername); | |
| 691 | + char *zCookie; | |
| 692 | + const char *zCookieName = login_cookie_name(); | |
| 693 | + const char *zExpire = db_get("cookie-expire","8766"); | |
| 694 | + int expires = atoi(zExpire)*3600; | |
| 695 | + const char *zIpAddr = PD("REMOTE_ADDR","nil"); | |
| 696 | + | |
| 697 | + zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid); | |
| 698 | + cgi_set_cookie(zCookieName, zCookie, 0, expires); | |
| 699 | + db_multi_exec( | |
| 700 | + "UPDATE user SET cookie=%Q, ipaddr=%Q, " | |
| 701 | + " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", | |
| 702 | + zCookie, zIpAddr, expires, uid | |
| 703 | + ); | |
| 704 | + redirect_to_g(); | |
| 705 | + | |
| 706 | + } | |
| 707 | + } | |
| 708 | + } | |
| 709 | + | |
| 710 | + /* Prepare the captcha. */ | |
| 711 | + unsigned int uSeed = captcha_seed(); | |
| 712 | + char const *zDecoded = captcha_decode(uSeed); | |
| 713 | + char *zCaptcha = captcha_render(zDecoded); | |
| 714 | + | |
| 715 | + /* Print out the registration form. */ | |
| 716 | + @ <form action="register" method="post"> | |
| 717 | + if( P("g") ){ | |
| 718 | + @ <input type="hidden" name="g" value="%h(P("g"))" /> | |
| 719 | + } | |
| 720 | + @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> | |
| 721 | + @ <table class="login_out"> | |
| 722 | + @ <tr> | |
| 723 | + @ <td class="login_out_label" align="right">User ID:</td> | |
| 724 | + @ <td><input type="text" id="u" name="u" value="" size="30" /></td> | |
| 725 | + @ </tr> | |
| 726 | + @ <tr> | |
| 727 | + @ <td class="login_out_label" align="right">Password:</td> | |
| 728 | + @ <td><input type="password" id="p" name="p" value="" size="30" /></td> | |
| 729 | + @ </tr> | |
| 730 | + @ <tr> | |
| 731 | + @ <td class="login_out_label" align="right">Confirm password:</td> | |
| 732 | + @ <td><input type="password" id="cp" name="cp" value="" size="30" /></td> | |
| 733 | + @ </tr> | |
| 734 | + @ <tr> | |
| 735 | + @ <td class="login_out_label" align="right">Contact info:</td> | |
| 736 | + @ <td><input type="text" id="c" name="c" value="" size="30" /></td> | |
| 737 | + @ </tr> | |
| 738 | + @ <tr> | |
| 739 | + @ <td class="login_out_label" align="right">Captcha text (below):</td> | |
| 740 | + @ <td><input type="text" id="cap" name="cap" value="" size="30" /></td> | |
| 741 | + @ </tr> | |
| 742 | + @ <tr><td></td> | |
| 743 | + @ <td><input type="submit" name="new" value="Register" /></td></tr> | |
| 744 | + @ </table> | |
| 745 | + @ <div class="captcha"><table class="captcha"><tr><td><pre> | |
| 746 | + @ %s(zCaptcha) | |
| 747 | + @ </pre></td></tr></table> | |
| 748 | + @ </form> | |
| 749 | + style_footer(); | |
| 750 | + | |
| 751 | + free(zCaptcha); | |
| 752 | +} | |
| 629 | 753 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -266,10 +266,13 @@ | |
| 266 | } |
| 267 | @ your user-id and password at the left and press the |
| 268 | @ "Login" button. Your user name will be stored in a browser cookie. |
| 269 | @ You must configure your web browser to accept cookies in order for |
| 270 | @ the login to take.</p> |
| 271 | if( zAnonPw ){ |
| 272 | unsigned int uSeed = captcha_seed(); |
| 273 | char const *zDecoded = captcha_decode(uSeed); |
| 274 | int bAutoCaptcha = db_get_boolean("auto-captcha", 1); |
| 275 | char *zCaptcha = captcha_render(zDecoded); |
| @@ -624,5 +627,126 @@ | |
| 624 | g.okCsrf = 1; |
| 625 | return; |
| 626 | } |
| 627 | fossil_fatal("Cross-site request forgery attempt"); |
| 628 | } |
| 629 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -266,10 +266,13 @@ | |
| 266 | } |
| 267 | @ your user-id and password at the left and press the |
| 268 | @ "Login" button. Your user name will be stored in a browser cookie. |
| 269 | @ You must configure your web browser to accept cookies in order for |
| 270 | @ the login to take.</p> |
| 271 | @ |
| 272 | @ <p>If you do not have an account, you can |
| 273 | @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>. |
| 274 | if( zAnonPw ){ |
| 275 | unsigned int uSeed = captcha_seed(); |
| 276 | char const *zDecoded = captcha_decode(uSeed); |
| 277 | int bAutoCaptcha = db_get_boolean("auto-captcha", 1); |
| 278 | char *zCaptcha = captcha_render(zDecoded); |
| @@ -624,5 +627,126 @@ | |
| 627 | g.okCsrf = 1; |
| 628 | return; |
| 629 | } |
| 630 | fossil_fatal("Cross-site request forgery attempt"); |
| 631 | } |
| 632 | |
| 633 | /* |
| 634 | ** WEBPAGE: register |
| 635 | ** |
| 636 | ** Generate the register page. |
| 637 | ** |
| 638 | */ |
| 639 | void register_page(void){ |
| 640 | const char *zUsername, *zPasswd, *zConfirm, *zContact, *zCS, *zPw, *zCap; |
| 641 | |
| 642 | style_header("Register"); |
| 643 | zUsername = P("u"); |
| 644 | zPasswd = P("p"); |
| 645 | zConfirm = P("cp"); |
| 646 | zContact = P("c"); |
| 647 | zCap = P("cap"); |
| 648 | zCS = P("cs"); /* Captcha Secret */ |
| 649 | |
| 650 | /* Try to make any sense from user input. */ |
| 651 | if( P("new") ){ |
| 652 | if( zCS==0 ) fossil_redirect_home(); /* Forged request */ |
| 653 | zPw = captcha_decode((unsigned int)atoi(zCS)); |
| 654 | if( !(zUsername && zPasswd && zConfirm && zContact) ){ |
| 655 | @ <p><span class="loginError"> |
| 656 | @ All fields are obligatory. |
| 657 | @ </span></p> |
| 658 | }else if( strcmp(zPasswd,zConfirm)!=0 ){ |
| 659 | @ <p><span class="loginError"> |
| 660 | @ The two copies of your new passwords do not match. |
| 661 | @ </span></p> |
| 662 | }else if( strcasecmp(zPw, zCap)!=0 ){ |
| 663 | @ <p><span class="loginError"> |
| 664 | @ Captcha text invalid. |
| 665 | @ </span></p> |
| 666 | }else{ |
| 667 | /* This almost is stupid copy-paste of code from user.c:user_cmd(). */ |
| 668 | Blob passwd, login, contact; |
| 669 | |
| 670 | blob_init(&login, zUsername, -1); |
| 671 | blob_init(&contact, zContact, -1); |
| 672 | blob_init(&passwd, zPasswd, -1); |
| 673 | |
| 674 | if( db_exists("SELECT 1 FROM user WHERE login=%B", &login) ){ |
| 675 | /* Here lies the reason I don't use zErrMsg - it would not substitute |
| 676 | * this %s(zUsername), or at least I don't know how to force it to.*/ |
| 677 | @ <p><span class="loginError"> |
| 678 | @ %s(zUsername) already exists. |
| 679 | @ </span></p> |
| 680 | }else{ |
| 681 | char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login)); |
| 682 | db_multi_exec( |
| 683 | "INSERT INTO user(login,pw,cap,info)" |
| 684 | "VALUES(%B,%Q,'u',%B)", /* u - register as reader, not developer! */ |
| 685 | &login, zPw, &contact |
| 686 | ); |
| 687 | free(zPw); |
| 688 | |
| 689 | /* The user is registered, now just log him in. */ |
| 690 | int uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername); |
| 691 | char *zCookie; |
| 692 | const char *zCookieName = login_cookie_name(); |
| 693 | const char *zExpire = db_get("cookie-expire","8766"); |
| 694 | int expires = atoi(zExpire)*3600; |
| 695 | const char *zIpAddr = PD("REMOTE_ADDR","nil"); |
| 696 | |
| 697 | zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid); |
| 698 | cgi_set_cookie(zCookieName, zCookie, 0, expires); |
| 699 | db_multi_exec( |
| 700 | "UPDATE user SET cookie=%Q, ipaddr=%Q, " |
| 701 | " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", |
| 702 | zCookie, zIpAddr, expires, uid |
| 703 | ); |
| 704 | redirect_to_g(); |
| 705 | |
| 706 | } |
| 707 | } |
| 708 | } |
| 709 | |
| 710 | /* Prepare the captcha. */ |
| 711 | unsigned int uSeed = captcha_seed(); |
| 712 | char const *zDecoded = captcha_decode(uSeed); |
| 713 | char *zCaptcha = captcha_render(zDecoded); |
| 714 | |
| 715 | /* Print out the registration form. */ |
| 716 | @ <form action="register" method="post"> |
| 717 | if( P("g") ){ |
| 718 | @ <input type="hidden" name="g" value="%h(P("g"))" /> |
| 719 | } |
| 720 | @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> |
| 721 | @ <table class="login_out"> |
| 722 | @ <tr> |
| 723 | @ <td class="login_out_label" align="right">User ID:</td> |
| 724 | @ <td><input type="text" id="u" name="u" value="" size="30" /></td> |
| 725 | @ </tr> |
| 726 | @ <tr> |
| 727 | @ <td class="login_out_label" align="right">Password:</td> |
| 728 | @ <td><input type="password" id="p" name="p" value="" size="30" /></td> |
| 729 | @ </tr> |
| 730 | @ <tr> |
| 731 | @ <td class="login_out_label" align="right">Confirm password:</td> |
| 732 | @ <td><input type="password" id="cp" name="cp" value="" size="30" /></td> |
| 733 | @ </tr> |
| 734 | @ <tr> |
| 735 | @ <td class="login_out_label" align="right">Contact info:</td> |
| 736 | @ <td><input type="text" id="c" name="c" value="" size="30" /></td> |
| 737 | @ </tr> |
| 738 | @ <tr> |
| 739 | @ <td class="login_out_label" align="right">Captcha text (below):</td> |
| 740 | @ <td><input type="text" id="cap" name="cap" value="" size="30" /></td> |
| 741 | @ </tr> |
| 742 | @ <tr><td></td> |
| 743 | @ <td><input type="submit" name="new" value="Register" /></td></tr> |
| 744 | @ </table> |
| 745 | @ <div class="captcha"><table class="captcha"><tr><td><pre> |
| 746 | @ %s(zCaptcha) |
| 747 | @ </pre></td></tr></table> |
| 748 | @ </form> |
| 749 | style_footer(); |
| 750 | |
| 751 | free(zCaptcha); |
| 752 | } |
| 753 |