Fossil SCM
Merge the self-registration changes into the trunk.
Commit
9039a6abed2e8d73cd36ac0ff06ce736bfc18d45
Parent
9e6f20bdf993b22…
6 files changed
+11
+11
+137
+137
+16
+4
-3
M
src/db.c
+11
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1584,10 +1584,11 @@ | ||
| 1584 | 1584 | { "auto-captcha", "autocaptcha", 0, "on" }, |
| 1585 | 1585 | { "auto-shun", 0, 0, "on" }, |
| 1586 | 1586 | { "autosync", 0, 0, "on" }, |
| 1587 | 1587 | { "binary-glob", 0, 32, "" }, |
| 1588 | 1588 | { "clearsign", 0, 0, "off" }, |
| 1589 | + { "default-perms", 0, 16, "u" }, | |
| 1589 | 1590 | { "diff-command", 0, 16, "" }, |
| 1590 | 1591 | { "dont-push", 0, 0, "off" }, |
| 1591 | 1592 | { "editor", 0, 16, "" }, |
| 1592 | 1593 | { "gdiff-command", 0, 16, "gdiff" }, |
| 1593 | 1594 | { "ignore-glob", 0, 40, "" }, |
| @@ -1596,10 +1597,11 @@ | ||
| 1596 | 1597 | { "manifest", 0, 0, "off" }, |
| 1597 | 1598 | { "mtime-changes", 0, 0, "on" }, |
| 1598 | 1599 | { "pgp-command", 0, 32, "gpg --clearsign -o " }, |
| 1599 | 1600 | { "proxy", 0, 32, "off" }, |
| 1600 | 1601 | { "repo-cksum", 0, 0, "on" }, |
| 1602 | + { "self-register", 0, 0, "off" }, | |
| 1601 | 1603 | { "ssh-command", 0, 32, "" }, |
| 1602 | 1604 | { "web-browser", 0, 32, "" }, |
| 1603 | 1605 | { 0,0,0,0 } |
| 1604 | 1606 | }; |
| 1605 | 1607 | |
| @@ -1635,10 +1637,14 @@ | ||
| 1635 | 1637 | ** purposes. Example: *.xml |
| 1636 | 1638 | ** |
| 1637 | 1639 | ** clearsign When enabled, fossil will attempt to sign all commits |
| 1638 | 1640 | ** with gpg. When disabled (the default), commits will |
| 1639 | 1641 | ** be unsigned. Default: off |
| 1642 | +** | |
| 1643 | +** default-perms Permissions given automatically to new users. For more | |
| 1644 | +** information on permissions see Users page in Server | |
| 1645 | +** Administration of the HTTP UI. Default: u. | |
| 1640 | 1646 | ** |
| 1641 | 1647 | ** diff-command External command to run when performing a diff. |
| 1642 | 1648 | ** If undefined, the internal text diff will be used. |
| 1643 | 1649 | ** |
| 1644 | 1650 | ** dont-push Prevent this repository from pushing from client to |
| @@ -1678,10 +1684,15 @@ | ||
| 1678 | 1684 | ** |
| 1679 | 1685 | ** repo-cksum Compute checksums over all files in each checkout |
| 1680 | 1686 | ** as a double-check of correctness. Defaults to "on". |
| 1681 | 1687 | ** Disable on large repositories for a performance |
| 1682 | 1688 | ** improvement. |
| 1689 | +** | |
| 1690 | +** self-register Allow users to register themselves through the HTTP UI. | |
| 1691 | +** This is useful if you want to see other names than | |
| 1692 | +** "Anonymous" in e.g. ticketing system. On the other hand | |
| 1693 | +** users can not be deleted. Default: off. | |
| 1683 | 1694 | ** |
| 1684 | 1695 | ** ssh-command Command used to talk to a remote machine with |
| 1685 | 1696 | ** the "ssh://" protocol. |
| 1686 | 1697 | ** |
| 1687 | 1698 | ** web-browser A shell command used to launch your preferred |
| 1688 | 1699 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1584,10 +1584,11 @@ | |
| 1584 | { "auto-captcha", "autocaptcha", 0, "on" }, |
| 1585 | { "auto-shun", 0, 0, "on" }, |
| 1586 | { "autosync", 0, 0, "on" }, |
| 1587 | { "binary-glob", 0, 32, "" }, |
| 1588 | { "clearsign", 0, 0, "off" }, |
| 1589 | { "diff-command", 0, 16, "" }, |
| 1590 | { "dont-push", 0, 0, "off" }, |
| 1591 | { "editor", 0, 16, "" }, |
| 1592 | { "gdiff-command", 0, 16, "gdiff" }, |
| 1593 | { "ignore-glob", 0, 40, "" }, |
| @@ -1596,10 +1597,11 @@ | |
| 1596 | { "manifest", 0, 0, "off" }, |
| 1597 | { "mtime-changes", 0, 0, "on" }, |
| 1598 | { "pgp-command", 0, 32, "gpg --clearsign -o " }, |
| 1599 | { "proxy", 0, 32, "off" }, |
| 1600 | { "repo-cksum", 0, 0, "on" }, |
| 1601 | { "ssh-command", 0, 32, "" }, |
| 1602 | { "web-browser", 0, 32, "" }, |
| 1603 | { 0,0,0,0 } |
| 1604 | }; |
| 1605 | |
| @@ -1635,10 +1637,14 @@ | |
| 1635 | ** purposes. Example: *.xml |
| 1636 | ** |
| 1637 | ** clearsign When enabled, fossil will attempt to sign all commits |
| 1638 | ** with gpg. When disabled (the default), commits will |
| 1639 | ** be unsigned. Default: off |
| 1640 | ** |
| 1641 | ** diff-command External command to run when performing a diff. |
| 1642 | ** If undefined, the internal text diff will be used. |
| 1643 | ** |
| 1644 | ** dont-push Prevent this repository from pushing from client to |
| @@ -1678,10 +1684,15 @@ | |
| 1678 | ** |
| 1679 | ** repo-cksum Compute checksums over all files in each checkout |
| 1680 | ** as a double-check of correctness. Defaults to "on". |
| 1681 | ** Disable on large repositories for a performance |
| 1682 | ** improvement. |
| 1683 | ** |
| 1684 | ** ssh-command Command used to talk to a remote machine with |
| 1685 | ** the "ssh://" protocol. |
| 1686 | ** |
| 1687 | ** web-browser A shell command used to launch your preferred |
| 1688 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1584,10 +1584,11 @@ | |
| 1584 | { "auto-captcha", "autocaptcha", 0, "on" }, |
| 1585 | { "auto-shun", 0, 0, "on" }, |
| 1586 | { "autosync", 0, 0, "on" }, |
| 1587 | { "binary-glob", 0, 32, "" }, |
| 1588 | { "clearsign", 0, 0, "off" }, |
| 1589 | { "default-perms", 0, 16, "u" }, |
| 1590 | { "diff-command", 0, 16, "" }, |
| 1591 | { "dont-push", 0, 0, "off" }, |
| 1592 | { "editor", 0, 16, "" }, |
| 1593 | { "gdiff-command", 0, 16, "gdiff" }, |
| 1594 | { "ignore-glob", 0, 40, "" }, |
| @@ -1596,10 +1597,11 @@ | |
| 1597 | { "manifest", 0, 0, "off" }, |
| 1598 | { "mtime-changes", 0, 0, "on" }, |
| 1599 | { "pgp-command", 0, 32, "gpg --clearsign -o " }, |
| 1600 | { "proxy", 0, 32, "off" }, |
| 1601 | { "repo-cksum", 0, 0, "on" }, |
| 1602 | { "self-register", 0, 0, "off" }, |
| 1603 | { "ssh-command", 0, 32, "" }, |
| 1604 | { "web-browser", 0, 32, "" }, |
| 1605 | { 0,0,0,0 } |
| 1606 | }; |
| 1607 | |
| @@ -1635,10 +1637,14 @@ | |
| 1637 | ** purposes. Example: *.xml |
| 1638 | ** |
| 1639 | ** clearsign When enabled, fossil will attempt to sign all commits |
| 1640 | ** with gpg. When disabled (the default), commits will |
| 1641 | ** be unsigned. Default: off |
| 1642 | ** |
| 1643 | ** default-perms Permissions given automatically to new users. For more |
| 1644 | ** information on permissions see Users page in Server |
| 1645 | ** Administration of the HTTP UI. Default: u. |
| 1646 | ** |
| 1647 | ** diff-command External command to run when performing a diff. |
| 1648 | ** If undefined, the internal text diff will be used. |
| 1649 | ** |
| 1650 | ** dont-push Prevent this repository from pushing from client to |
| @@ -1678,10 +1684,15 @@ | |
| 1684 | ** |
| 1685 | ** repo-cksum Compute checksums over all files in each checkout |
| 1686 | ** as a double-check of correctness. Defaults to "on". |
| 1687 | ** Disable on large repositories for a performance |
| 1688 | ** improvement. |
| 1689 | ** |
| 1690 | ** self-register Allow users to register themselves through the HTTP UI. |
| 1691 | ** This is useful if you want to see other names than |
| 1692 | ** "Anonymous" in e.g. ticketing system. On the other hand |
| 1693 | ** users can not be deleted. Default: off. |
| 1694 | ** |
| 1695 | ** ssh-command Command used to talk to a remote machine with |
| 1696 | ** the "ssh://" protocol. |
| 1697 | ** |
| 1698 | ** web-browser A shell command used to launch your preferred |
| 1699 |
M
src/db.c
+11
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1584,10 +1584,11 @@ | ||
| 1584 | 1584 | { "auto-captcha", "autocaptcha", 0, "on" }, |
| 1585 | 1585 | { "auto-shun", 0, 0, "on" }, |
| 1586 | 1586 | { "autosync", 0, 0, "on" }, |
| 1587 | 1587 | { "binary-glob", 0, 32, "" }, |
| 1588 | 1588 | { "clearsign", 0, 0, "off" }, |
| 1589 | + { "default-perms", 0, 16, "u" }, | |
| 1589 | 1590 | { "diff-command", 0, 16, "" }, |
| 1590 | 1591 | { "dont-push", 0, 0, "off" }, |
| 1591 | 1592 | { "editor", 0, 16, "" }, |
| 1592 | 1593 | { "gdiff-command", 0, 16, "gdiff" }, |
| 1593 | 1594 | { "ignore-glob", 0, 40, "" }, |
| @@ -1596,10 +1597,11 @@ | ||
| 1596 | 1597 | { "manifest", 0, 0, "off" }, |
| 1597 | 1598 | { "mtime-changes", 0, 0, "on" }, |
| 1598 | 1599 | { "pgp-command", 0, 32, "gpg --clearsign -o " }, |
| 1599 | 1600 | { "proxy", 0, 32, "off" }, |
| 1600 | 1601 | { "repo-cksum", 0, 0, "on" }, |
| 1602 | + { "self-register", 0, 0, "off" }, | |
| 1601 | 1603 | { "ssh-command", 0, 32, "" }, |
| 1602 | 1604 | { "web-browser", 0, 32, "" }, |
| 1603 | 1605 | { 0,0,0,0 } |
| 1604 | 1606 | }; |
| 1605 | 1607 | |
| @@ -1635,10 +1637,14 @@ | ||
| 1635 | 1637 | ** purposes. Example: *.xml |
| 1636 | 1638 | ** |
| 1637 | 1639 | ** clearsign When enabled, fossil will attempt to sign all commits |
| 1638 | 1640 | ** with gpg. When disabled (the default), commits will |
| 1639 | 1641 | ** be unsigned. Default: off |
| 1642 | +** | |
| 1643 | +** default-perms Permissions given automatically to new users. For more | |
| 1644 | +** information on permissions see Users page in Server | |
| 1645 | +** Administration of the HTTP UI. Default: u. | |
| 1640 | 1646 | ** |
| 1641 | 1647 | ** diff-command External command to run when performing a diff. |
| 1642 | 1648 | ** If undefined, the internal text diff will be used. |
| 1643 | 1649 | ** |
| 1644 | 1650 | ** dont-push Prevent this repository from pushing from client to |
| @@ -1678,10 +1684,15 @@ | ||
| 1678 | 1684 | ** |
| 1679 | 1685 | ** repo-cksum Compute checksums over all files in each checkout |
| 1680 | 1686 | ** as a double-check of correctness. Defaults to "on". |
| 1681 | 1687 | ** Disable on large repositories for a performance |
| 1682 | 1688 | ** improvement. |
| 1689 | +** | |
| 1690 | +** self-register Allow users to register themselves through the HTTP UI. | |
| 1691 | +** This is useful if you want to see other names than | |
| 1692 | +** "Anonymous" in e.g. ticketing system. On the other hand | |
| 1693 | +** users can not be deleted. Default: off. | |
| 1683 | 1694 | ** |
| 1684 | 1695 | ** ssh-command Command used to talk to a remote machine with |
| 1685 | 1696 | ** the "ssh://" protocol. |
| 1686 | 1697 | ** |
| 1687 | 1698 | ** web-browser A shell command used to launch your preferred |
| 1688 | 1699 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1584,10 +1584,11 @@ | |
| 1584 | { "auto-captcha", "autocaptcha", 0, "on" }, |
| 1585 | { "auto-shun", 0, 0, "on" }, |
| 1586 | { "autosync", 0, 0, "on" }, |
| 1587 | { "binary-glob", 0, 32, "" }, |
| 1588 | { "clearsign", 0, 0, "off" }, |
| 1589 | { "diff-command", 0, 16, "" }, |
| 1590 | { "dont-push", 0, 0, "off" }, |
| 1591 | { "editor", 0, 16, "" }, |
| 1592 | { "gdiff-command", 0, 16, "gdiff" }, |
| 1593 | { "ignore-glob", 0, 40, "" }, |
| @@ -1596,10 +1597,11 @@ | |
| 1596 | { "manifest", 0, 0, "off" }, |
| 1597 | { "mtime-changes", 0, 0, "on" }, |
| 1598 | { "pgp-command", 0, 32, "gpg --clearsign -o " }, |
| 1599 | { "proxy", 0, 32, "off" }, |
| 1600 | { "repo-cksum", 0, 0, "on" }, |
| 1601 | { "ssh-command", 0, 32, "" }, |
| 1602 | { "web-browser", 0, 32, "" }, |
| 1603 | { 0,0,0,0 } |
| 1604 | }; |
| 1605 | |
| @@ -1635,10 +1637,14 @@ | |
| 1635 | ** purposes. Example: *.xml |
| 1636 | ** |
| 1637 | ** clearsign When enabled, fossil will attempt to sign all commits |
| 1638 | ** with gpg. When disabled (the default), commits will |
| 1639 | ** be unsigned. Default: off |
| 1640 | ** |
| 1641 | ** diff-command External command to run when performing a diff. |
| 1642 | ** If undefined, the internal text diff will be used. |
| 1643 | ** |
| 1644 | ** dont-push Prevent this repository from pushing from client to |
| @@ -1678,10 +1684,15 @@ | |
| 1678 | ** |
| 1679 | ** repo-cksum Compute checksums over all files in each checkout |
| 1680 | ** as a double-check of correctness. Defaults to "on". |
| 1681 | ** Disable on large repositories for a performance |
| 1682 | ** improvement. |
| 1683 | ** |
| 1684 | ** ssh-command Command used to talk to a remote machine with |
| 1685 | ** the "ssh://" protocol. |
| 1686 | ** |
| 1687 | ** web-browser A shell command used to launch your preferred |
| 1688 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1584,10 +1584,11 @@ | |
| 1584 | { "auto-captcha", "autocaptcha", 0, "on" }, |
| 1585 | { "auto-shun", 0, 0, "on" }, |
| 1586 | { "autosync", 0, 0, "on" }, |
| 1587 | { "binary-glob", 0, 32, "" }, |
| 1588 | { "clearsign", 0, 0, "off" }, |
| 1589 | { "default-perms", 0, 16, "u" }, |
| 1590 | { "diff-command", 0, 16, "" }, |
| 1591 | { "dont-push", 0, 0, "off" }, |
| 1592 | { "editor", 0, 16, "" }, |
| 1593 | { "gdiff-command", 0, 16, "gdiff" }, |
| 1594 | { "ignore-glob", 0, 40, "" }, |
| @@ -1596,10 +1597,11 @@ | |
| 1597 | { "manifest", 0, 0, "off" }, |
| 1598 | { "mtime-changes", 0, 0, "on" }, |
| 1599 | { "pgp-command", 0, 32, "gpg --clearsign -o " }, |
| 1600 | { "proxy", 0, 32, "off" }, |
| 1601 | { "repo-cksum", 0, 0, "on" }, |
| 1602 | { "self-register", 0, 0, "off" }, |
| 1603 | { "ssh-command", 0, 32, "" }, |
| 1604 | { "web-browser", 0, 32, "" }, |
| 1605 | { 0,0,0,0 } |
| 1606 | }; |
| 1607 | |
| @@ -1635,10 +1637,14 @@ | |
| 1637 | ** purposes. Example: *.xml |
| 1638 | ** |
| 1639 | ** clearsign When enabled, fossil will attempt to sign all commits |
| 1640 | ** with gpg. When disabled (the default), commits will |
| 1641 | ** be unsigned. Default: off |
| 1642 | ** |
| 1643 | ** default-perms Permissions given automatically to new users. For more |
| 1644 | ** information on permissions see Users page in Server |
| 1645 | ** Administration of the HTTP UI. Default: u. |
| 1646 | ** |
| 1647 | ** diff-command External command to run when performing a diff. |
| 1648 | ** If undefined, the internal text diff will be used. |
| 1649 | ** |
| 1650 | ** dont-push Prevent this repository from pushing from client to |
| @@ -1678,10 +1684,15 @@ | |
| 1684 | ** |
| 1685 | ** repo-cksum Compute checksums over all files in each checkout |
| 1686 | ** as a double-check of correctness. Defaults to "on". |
| 1687 | ** Disable on large repositories for a performance |
| 1688 | ** improvement. |
| 1689 | ** |
| 1690 | ** self-register Allow users to register themselves through the HTTP UI. |
| 1691 | ** This is useful if you want to see other names than |
| 1692 | ** "Anonymous" in e.g. ticketing system. On the other hand |
| 1693 | ** users can not be deleted. Default: off. |
| 1694 | ** |
| 1695 | ** ssh-command Command used to talk to a remote machine with |
| 1696 | ** the "ssh://" protocol. |
| 1697 | ** |
| 1698 | ** web-browser A shell command used to launch your preferred |
| 1699 |
+137
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -266,10 +266,14 @@ | ||
| 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 | + if( db_get_boolean("self-register", 0) ){ | |
| 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 | + } | |
| 271 | 275 | if( zAnonPw ){ |
| 272 | 276 | unsigned int uSeed = captcha_seed(); |
| 273 | 277 | char const *zDecoded = captcha_decode(uSeed); |
| 274 | 278 | int bAutoCaptcha = db_get_boolean("auto-captcha", 1); |
| 275 | 279 | char *zCaptcha = captcha_render(zDecoded); |
| @@ -623,5 +627,138 @@ | ||
| 623 | 627 | g.okCsrf = 1; |
| 624 | 628 | return; |
| 625 | 629 | } |
| 626 | 630 | fossil_fatal("Cross-site request forgery attempt"); |
| 627 | 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 | + if( !db_get_boolean("self-register", 0) ){ | |
| 642 | + style_header("Registration not possible"); | |
| 643 | + @ <p>This project does not allow user self-registration. Please contact the | |
| 644 | + @ project administrator to obtain an account.</p> | |
| 645 | + style_footer(); | |
| 646 | + return; | |
| 647 | + } | |
| 648 | + | |
| 649 | + style_header("Register"); | |
| 650 | + zUsername = P("u"); | |
| 651 | + zPasswd = P("p"); | |
| 652 | + zConfirm = P("cp"); | |
| 653 | + zContact = P("c"); | |
| 654 | + zCap = P("cap"); | |
| 655 | + zCS = P("cs"); /* Captcha Secret */ | |
| 656 | + | |
| 657 | + /* Try to make any sense from user input. */ | |
| 658 | + if( P("new") ){ | |
| 659 | + if( zCS==0 ) fossil_redirect_home(); /* Forged request */ | |
| 660 | + zPw = captcha_decode((unsigned int)atoi(zCS)); | |
| 661 | + if( !(zUsername && zPasswd && zConfirm && zContact) ){ | |
| 662 | + @ <p><span class="loginError"> | |
| 663 | + @ All fields are obligatory. | |
| 664 | + @ </span></p> | |
| 665 | + }else if( strlen(zPasswd) < 6){ | |
| 666 | + @ <p><span class="loginError"> | |
| 667 | + @ Password too weak. | |
| 668 | + @ </span></p> | |
| 669 | + }else if( strcmp(zPasswd,zConfirm)!=0 ){ | |
| 670 | + @ <p><span class="loginError"> | |
| 671 | + @ The two copies of your new passwords do not match. | |
| 672 | + @ </span></p> | |
| 673 | + }else if( strcasecmp(zPw, zCap)!=0 ){ | |
| 674 | + @ <p><span class="loginError"> | |
| 675 | + @ Captcha text invalid. | |
| 676 | + @ </span></p> | |
| 677 | + }else{ | |
| 678 | + /* This almost is stupid copy-paste of code from user.c:user_cmd(). */ | |
| 679 | + Blob passwd, login, caps, contact; | |
| 680 | + | |
| 681 | + blob_init(&login, zUsername, -1); | |
| 682 | + blob_init(&contact, zContact, -1); | |
| 683 | + blob_init(&caps, db_get("default-perms", "u"), -1); | |
| 684 | + blob_init(&passwd, zPasswd, -1); | |
| 685 | + | |
| 686 | + if( db_exists("SELECT 1 FROM user WHERE login=%B", &login) ){ | |
| 687 | + /* Here lies the reason I don't use zErrMsg - it would not substitute | |
| 688 | + * this %s(zUsername), or at least I don't know how to force it to.*/ | |
| 689 | + @ <p><span class="loginError"> | |
| 690 | + @ %s(zUsername) already exists. | |
| 691 | + @ </span></p> | |
| 692 | + }else{ | |
| 693 | + char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login)); | |
| 694 | + db_multi_exec( | |
| 695 | + "INSERT INTO user(login,pw,cap,info)" | |
| 696 | + "VALUES(%B,%Q,%B,%B)", | |
| 697 | + &login, zPw, &caps, &contact | |
| 698 | + ); | |
| 699 | + free(zPw); | |
| 700 | + | |
| 701 | + /* The user is registered, now just log him in. */ | |
| 702 | + int uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername); | |
| 703 | + char *zCookie; | |
| 704 | + const char *zCookieName = login_cookie_name(); | |
| 705 | + const char *zExpire = db_get("cookie-expire","8766"); | |
| 706 | + int expires = atoi(zExpire)*3600; | |
| 707 | + const char *zIpAddr = PD("REMOTE_ADDR","nil"); | |
| 708 | + | |
| 709 | + zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid); | |
| 710 | + cgi_set_cookie(zCookieName, zCookie, 0, expires); | |
| 711 | + db_multi_exec( | |
| 712 | + "UPDATE user SET cookie=%Q, ipaddr=%Q, " | |
| 713 | + " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", | |
| 714 | + zCookie, zIpAddr, expires, uid | |
| 715 | + ); | |
| 716 | + redirect_to_g(); | |
| 717 | + | |
| 718 | + } | |
| 719 | + } | |
| 720 | + } | |
| 721 | + | |
| 722 | + /* Prepare the captcha. */ | |
| 723 | + unsigned int uSeed = captcha_seed(); | |
| 724 | + char const *zDecoded = captcha_decode(uSeed); | |
| 725 | + char *zCaptcha = captcha_render(zDecoded); | |
| 726 | + | |
| 727 | + /* Print out the registration form. */ | |
| 728 | + @ <form action="register" method="post"> | |
| 729 | + if( P("g") ){ | |
| 730 | + @ <input type="hidden" name="g" value="%h(P("g"))" /> | |
| 731 | + } | |
| 732 | + @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> | |
| 733 | + @ <table class="login_out"> | |
| 734 | + @ <tr> | |
| 735 | + @ <td class="login_out_label" align="right">User ID:</td> | |
| 736 | + @ <td><input type="text" id="u" name="u" value="" size="30" /></td> | |
| 737 | + @ </tr> | |
| 738 | + @ <tr> | |
| 739 | + @ <td class="login_out_label" align="right">Password:</td> | |
| 740 | + @ <td><input type="password" id="p" name="p" value="" size="30" /></td> | |
| 741 | + @ </tr> | |
| 742 | + @ <tr> | |
| 743 | + @ <td class="login_out_label" align="right">Confirm password:</td> | |
| 744 | + @ <td><input type="password" id="cp" name="cp" value="" size="30" /></td> | |
| 745 | + @ </tr> | |
| 746 | + @ <tr> | |
| 747 | + @ <td class="login_out_label" align="right">Contact info:</td> | |
| 748 | + @ <td><input type="text" id="c" name="c" value="" size="30" /></td> | |
| 749 | + @ </tr> | |
| 750 | + @ <tr> | |
| 751 | + @ <td class="login_out_label" align="right">Captcha text (below):</td> | |
| 752 | + @ <td><input type="text" id="cap" name="cap" value="" size="30" /></td> | |
| 753 | + @ </tr> | |
| 754 | + @ <tr><td></td> | |
| 755 | + @ <td><input type="submit" name="new" value="Register" /></td></tr> | |
| 756 | + @ </table> | |
| 757 | + @ <div class="captcha"><table class="captcha"><tr><td><pre> | |
| 758 | + @ %s(zCaptcha) | |
| 759 | + @ </pre></td></tr></table> | |
| 760 | + @ </form> | |
| 761 | + style_footer(); | |
| 762 | + | |
| 763 | + free(zCaptcha); | |
| 764 | +} | |
| 628 | 765 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -266,10 +266,14 @@ | |
| 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); |
| @@ -623,5 +627,138 @@ | |
| 623 | g.okCsrf = 1; |
| 624 | return; |
| 625 | } |
| 626 | fossil_fatal("Cross-site request forgery attempt"); |
| 627 | } |
| 628 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -266,10 +266,14 @@ | |
| 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( db_get_boolean("self-register", 0) ){ |
| 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 | } |
| 275 | if( zAnonPw ){ |
| 276 | unsigned int uSeed = captcha_seed(); |
| 277 | char const *zDecoded = captcha_decode(uSeed); |
| 278 | int bAutoCaptcha = db_get_boolean("auto-captcha", 1); |
| 279 | char *zCaptcha = captcha_render(zDecoded); |
| @@ -623,5 +627,138 @@ | |
| 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 | if( !db_get_boolean("self-register", 0) ){ |
| 642 | style_header("Registration not possible"); |
| 643 | @ <p>This project does not allow user self-registration. Please contact the |
| 644 | @ project administrator to obtain an account.</p> |
| 645 | style_footer(); |
| 646 | return; |
| 647 | } |
| 648 | |
| 649 | style_header("Register"); |
| 650 | zUsername = P("u"); |
| 651 | zPasswd = P("p"); |
| 652 | zConfirm = P("cp"); |
| 653 | zContact = P("c"); |
| 654 | zCap = P("cap"); |
| 655 | zCS = P("cs"); /* Captcha Secret */ |
| 656 | |
| 657 | /* Try to make any sense from user input. */ |
| 658 | if( P("new") ){ |
| 659 | if( zCS==0 ) fossil_redirect_home(); /* Forged request */ |
| 660 | zPw = captcha_decode((unsigned int)atoi(zCS)); |
| 661 | if( !(zUsername && zPasswd && zConfirm && zContact) ){ |
| 662 | @ <p><span class="loginError"> |
| 663 | @ All fields are obligatory. |
| 664 | @ </span></p> |
| 665 | }else if( strlen(zPasswd) < 6){ |
| 666 | @ <p><span class="loginError"> |
| 667 | @ Password too weak. |
| 668 | @ </span></p> |
| 669 | }else if( strcmp(zPasswd,zConfirm)!=0 ){ |
| 670 | @ <p><span class="loginError"> |
| 671 | @ The two copies of your new passwords do not match. |
| 672 | @ </span></p> |
| 673 | }else if( strcasecmp(zPw, zCap)!=0 ){ |
| 674 | @ <p><span class="loginError"> |
| 675 | @ Captcha text invalid. |
| 676 | @ </span></p> |
| 677 | }else{ |
| 678 | /* This almost is stupid copy-paste of code from user.c:user_cmd(). */ |
| 679 | Blob passwd, login, caps, contact; |
| 680 | |
| 681 | blob_init(&login, zUsername, -1); |
| 682 | blob_init(&contact, zContact, -1); |
| 683 | blob_init(&caps, db_get("default-perms", "u"), -1); |
| 684 | blob_init(&passwd, zPasswd, -1); |
| 685 | |
| 686 | if( db_exists("SELECT 1 FROM user WHERE login=%B", &login) ){ |
| 687 | /* Here lies the reason I don't use zErrMsg - it would not substitute |
| 688 | * this %s(zUsername), or at least I don't know how to force it to.*/ |
| 689 | @ <p><span class="loginError"> |
| 690 | @ %s(zUsername) already exists. |
| 691 | @ </span></p> |
| 692 | }else{ |
| 693 | char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login)); |
| 694 | db_multi_exec( |
| 695 | "INSERT INTO user(login,pw,cap,info)" |
| 696 | "VALUES(%B,%Q,%B,%B)", |
| 697 | &login, zPw, &caps, &contact |
| 698 | ); |
| 699 | free(zPw); |
| 700 | |
| 701 | /* The user is registered, now just log him in. */ |
| 702 | int uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername); |
| 703 | char *zCookie; |
| 704 | const char *zCookieName = login_cookie_name(); |
| 705 | const char *zExpire = db_get("cookie-expire","8766"); |
| 706 | int expires = atoi(zExpire)*3600; |
| 707 | const char *zIpAddr = PD("REMOTE_ADDR","nil"); |
| 708 | |
| 709 | zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid); |
| 710 | cgi_set_cookie(zCookieName, zCookie, 0, expires); |
| 711 | db_multi_exec( |
| 712 | "UPDATE user SET cookie=%Q, ipaddr=%Q, " |
| 713 | " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", |
| 714 | zCookie, zIpAddr, expires, uid |
| 715 | ); |
| 716 | redirect_to_g(); |
| 717 | |
| 718 | } |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | /* Prepare the captcha. */ |
| 723 | unsigned int uSeed = captcha_seed(); |
| 724 | char const *zDecoded = captcha_decode(uSeed); |
| 725 | char *zCaptcha = captcha_render(zDecoded); |
| 726 | |
| 727 | /* Print out the registration form. */ |
| 728 | @ <form action="register" method="post"> |
| 729 | if( P("g") ){ |
| 730 | @ <input type="hidden" name="g" value="%h(P("g"))" /> |
| 731 | } |
| 732 | @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> |
| 733 | @ <table class="login_out"> |
| 734 | @ <tr> |
| 735 | @ <td class="login_out_label" align="right">User ID:</td> |
| 736 | @ <td><input type="text" id="u" name="u" value="" size="30" /></td> |
| 737 | @ </tr> |
| 738 | @ <tr> |
| 739 | @ <td class="login_out_label" align="right">Password:</td> |
| 740 | @ <td><input type="password" id="p" name="p" value="" size="30" /></td> |
| 741 | @ </tr> |
| 742 | @ <tr> |
| 743 | @ <td class="login_out_label" align="right">Confirm password:</td> |
| 744 | @ <td><input type="password" id="cp" name="cp" value="" size="30" /></td> |
| 745 | @ </tr> |
| 746 | @ <tr> |
| 747 | @ <td class="login_out_label" align="right">Contact info:</td> |
| 748 | @ <td><input type="text" id="c" name="c" value="" size="30" /></td> |
| 749 | @ </tr> |
| 750 | @ <tr> |
| 751 | @ <td class="login_out_label" align="right">Captcha text (below):</td> |
| 752 | @ <td><input type="text" id="cap" name="cap" value="" size="30" /></td> |
| 753 | @ </tr> |
| 754 | @ <tr><td></td> |
| 755 | @ <td><input type="submit" name="new" value="Register" /></td></tr> |
| 756 | @ </table> |
| 757 | @ <div class="captcha"><table class="captcha"><tr><td><pre> |
| 758 | @ %s(zCaptcha) |
| 759 | @ </pre></td></tr></table> |
| 760 | @ </form> |
| 761 | style_footer(); |
| 762 | |
| 763 | free(zCaptcha); |
| 764 | } |
| 765 |
+137
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -266,10 +266,14 @@ | ||
| 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 | + if( db_get_boolean("self-register", 0) ){ | |
| 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 | + } | |
| 271 | 275 | if( zAnonPw ){ |
| 272 | 276 | unsigned int uSeed = captcha_seed(); |
| 273 | 277 | char const *zDecoded = captcha_decode(uSeed); |
| 274 | 278 | int bAutoCaptcha = db_get_boolean("auto-captcha", 1); |
| 275 | 279 | char *zCaptcha = captcha_render(zDecoded); |
| @@ -623,5 +627,138 @@ | ||
| 623 | 627 | g.okCsrf = 1; |
| 624 | 628 | return; |
| 625 | 629 | } |
| 626 | 630 | fossil_fatal("Cross-site request forgery attempt"); |
| 627 | 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 | + if( !db_get_boolean("self-register", 0) ){ | |
| 642 | + style_header("Registration not possible"); | |
| 643 | + @ <p>This project does not allow user self-registration. Please contact the | |
| 644 | + @ project administrator to obtain an account.</p> | |
| 645 | + style_footer(); | |
| 646 | + return; | |
| 647 | + } | |
| 648 | + | |
| 649 | + style_header("Register"); | |
| 650 | + zUsername = P("u"); | |
| 651 | + zPasswd = P("p"); | |
| 652 | + zConfirm = P("cp"); | |
| 653 | + zContact = P("c"); | |
| 654 | + zCap = P("cap"); | |
| 655 | + zCS = P("cs"); /* Captcha Secret */ | |
| 656 | + | |
| 657 | + /* Try to make any sense from user input. */ | |
| 658 | + if( P("new") ){ | |
| 659 | + if( zCS==0 ) fossil_redirect_home(); /* Forged request */ | |
| 660 | + zPw = captcha_decode((unsigned int)atoi(zCS)); | |
| 661 | + if( !(zUsername && zPasswd && zConfirm && zContact) ){ | |
| 662 | + @ <p><span class="loginError"> | |
| 663 | + @ All fields are obligatory. | |
| 664 | + @ </span></p> | |
| 665 | + }else if( strlen(zPasswd) < 6){ | |
| 666 | + @ <p><span class="loginError"> | |
| 667 | + @ Password too weak. | |
| 668 | + @ </span></p> | |
| 669 | + }else if( strcmp(zPasswd,zConfirm)!=0 ){ | |
| 670 | + @ <p><span class="loginError"> | |
| 671 | + @ The two copies of your new passwords do not match. | |
| 672 | + @ </span></p> | |
| 673 | + }else if( strcasecmp(zPw, zCap)!=0 ){ | |
| 674 | + @ <p><span class="loginError"> | |
| 675 | + @ Captcha text invalid. | |
| 676 | + @ </span></p> | |
| 677 | + }else{ | |
| 678 | + /* This almost is stupid copy-paste of code from user.c:user_cmd(). */ | |
| 679 | + Blob passwd, login, caps, contact; | |
| 680 | + | |
| 681 | + blob_init(&login, zUsername, -1); | |
| 682 | + blob_init(&contact, zContact, -1); | |
| 683 | + blob_init(&caps, db_get("default-perms", "u"), -1); | |
| 684 | + blob_init(&passwd, zPasswd, -1); | |
| 685 | + | |
| 686 | + if( db_exists("SELECT 1 FROM user WHERE login=%B", &login) ){ | |
| 687 | + /* Here lies the reason I don't use zErrMsg - it would not substitute | |
| 688 | + * this %s(zUsername), or at least I don't know how to force it to.*/ | |
| 689 | + @ <p><span class="loginError"> | |
| 690 | + @ %s(zUsername) already exists. | |
| 691 | + @ </span></p> | |
| 692 | + }else{ | |
| 693 | + char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login)); | |
| 694 | + db_multi_exec( | |
| 695 | + "INSERT INTO user(login,pw,cap,info)" | |
| 696 | + "VALUES(%B,%Q,%B,%B)", | |
| 697 | + &login, zPw, &caps, &contact | |
| 698 | + ); | |
| 699 | + free(zPw); | |
| 700 | + | |
| 701 | + /* The user is registered, now just log him in. */ | |
| 702 | + int uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername); | |
| 703 | + char *zCookie; | |
| 704 | + const char *zCookieName = login_cookie_name(); | |
| 705 | + const char *zExpire = db_get("cookie-expire","8766"); | |
| 706 | + int expires = atoi(zExpire)*3600; | |
| 707 | + const char *zIpAddr = PD("REMOTE_ADDR","nil"); | |
| 708 | + | |
| 709 | + zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid); | |
| 710 | + cgi_set_cookie(zCookieName, zCookie, 0, expires); | |
| 711 | + db_multi_exec( | |
| 712 | + "UPDATE user SET cookie=%Q, ipaddr=%Q, " | |
| 713 | + " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", | |
| 714 | + zCookie, zIpAddr, expires, uid | |
| 715 | + ); | |
| 716 | + redirect_to_g(); | |
| 717 | + | |
| 718 | + } | |
| 719 | + } | |
| 720 | + } | |
| 721 | + | |
| 722 | + /* Prepare the captcha. */ | |
| 723 | + unsigned int uSeed = captcha_seed(); | |
| 724 | + char const *zDecoded = captcha_decode(uSeed); | |
| 725 | + char *zCaptcha = captcha_render(zDecoded); | |
| 726 | + | |
| 727 | + /* Print out the registration form. */ | |
| 728 | + @ <form action="register" method="post"> | |
| 729 | + if( P("g") ){ | |
| 730 | + @ <input type="hidden" name="g" value="%h(P("g"))" /> | |
| 731 | + } | |
| 732 | + @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> | |
| 733 | + @ <table class="login_out"> | |
| 734 | + @ <tr> | |
| 735 | + @ <td class="login_out_label" align="right">User ID:</td> | |
| 736 | + @ <td><input type="text" id="u" name="u" value="" size="30" /></td> | |
| 737 | + @ </tr> | |
| 738 | + @ <tr> | |
| 739 | + @ <td class="login_out_label" align="right">Password:</td> | |
| 740 | + @ <td><input type="password" id="p" name="p" value="" size="30" /></td> | |
| 741 | + @ </tr> | |
| 742 | + @ <tr> | |
| 743 | + @ <td class="login_out_label" align="right">Confirm password:</td> | |
| 744 | + @ <td><input type="password" id="cp" name="cp" value="" size="30" /></td> | |
| 745 | + @ </tr> | |
| 746 | + @ <tr> | |
| 747 | + @ <td class="login_out_label" align="right">Contact info:</td> | |
| 748 | + @ <td><input type="text" id="c" name="c" value="" size="30" /></td> | |
| 749 | + @ </tr> | |
| 750 | + @ <tr> | |
| 751 | + @ <td class="login_out_label" align="right">Captcha text (below):</td> | |
| 752 | + @ <td><input type="text" id="cap" name="cap" value="" size="30" /></td> | |
| 753 | + @ </tr> | |
| 754 | + @ <tr><td></td> | |
| 755 | + @ <td><input type="submit" name="new" value="Register" /></td></tr> | |
| 756 | + @ </table> | |
| 757 | + @ <div class="captcha"><table class="captcha"><tr><td><pre> | |
| 758 | + @ %s(zCaptcha) | |
| 759 | + @ </pre></td></tr></table> | |
| 760 | + @ </form> | |
| 761 | + style_footer(); | |
| 762 | + | |
| 763 | + free(zCaptcha); | |
| 764 | +} | |
| 628 | 765 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -266,10 +266,14 @@ | |
| 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); |
| @@ -623,5 +627,138 @@ | |
| 623 | g.okCsrf = 1; |
| 624 | return; |
| 625 | } |
| 626 | fossil_fatal("Cross-site request forgery attempt"); |
| 627 | } |
| 628 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -266,10 +266,14 @@ | |
| 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( db_get_boolean("self-register", 0) ){ |
| 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 | } |
| 275 | if( zAnonPw ){ |
| 276 | unsigned int uSeed = captcha_seed(); |
| 277 | char const *zDecoded = captcha_decode(uSeed); |
| 278 | int bAutoCaptcha = db_get_boolean("auto-captcha", 1); |
| 279 | char *zCaptcha = captcha_render(zDecoded); |
| @@ -623,5 +627,138 @@ | |
| 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 | if( !db_get_boolean("self-register", 0) ){ |
| 642 | style_header("Registration not possible"); |
| 643 | @ <p>This project does not allow user self-registration. Please contact the |
| 644 | @ project administrator to obtain an account.</p> |
| 645 | style_footer(); |
| 646 | return; |
| 647 | } |
| 648 | |
| 649 | style_header("Register"); |
| 650 | zUsername = P("u"); |
| 651 | zPasswd = P("p"); |
| 652 | zConfirm = P("cp"); |
| 653 | zContact = P("c"); |
| 654 | zCap = P("cap"); |
| 655 | zCS = P("cs"); /* Captcha Secret */ |
| 656 | |
| 657 | /* Try to make any sense from user input. */ |
| 658 | if( P("new") ){ |
| 659 | if( zCS==0 ) fossil_redirect_home(); /* Forged request */ |
| 660 | zPw = captcha_decode((unsigned int)atoi(zCS)); |
| 661 | if( !(zUsername && zPasswd && zConfirm && zContact) ){ |
| 662 | @ <p><span class="loginError"> |
| 663 | @ All fields are obligatory. |
| 664 | @ </span></p> |
| 665 | }else if( strlen(zPasswd) < 6){ |
| 666 | @ <p><span class="loginError"> |
| 667 | @ Password too weak. |
| 668 | @ </span></p> |
| 669 | }else if( strcmp(zPasswd,zConfirm)!=0 ){ |
| 670 | @ <p><span class="loginError"> |
| 671 | @ The two copies of your new passwords do not match. |
| 672 | @ </span></p> |
| 673 | }else if( strcasecmp(zPw, zCap)!=0 ){ |
| 674 | @ <p><span class="loginError"> |
| 675 | @ Captcha text invalid. |
| 676 | @ </span></p> |
| 677 | }else{ |
| 678 | /* This almost is stupid copy-paste of code from user.c:user_cmd(). */ |
| 679 | Blob passwd, login, caps, contact; |
| 680 | |
| 681 | blob_init(&login, zUsername, -1); |
| 682 | blob_init(&contact, zContact, -1); |
| 683 | blob_init(&caps, db_get("default-perms", "u"), -1); |
| 684 | blob_init(&passwd, zPasswd, -1); |
| 685 | |
| 686 | if( db_exists("SELECT 1 FROM user WHERE login=%B", &login) ){ |
| 687 | /* Here lies the reason I don't use zErrMsg - it would not substitute |
| 688 | * this %s(zUsername), or at least I don't know how to force it to.*/ |
| 689 | @ <p><span class="loginError"> |
| 690 | @ %s(zUsername) already exists. |
| 691 | @ </span></p> |
| 692 | }else{ |
| 693 | char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login)); |
| 694 | db_multi_exec( |
| 695 | "INSERT INTO user(login,pw,cap,info)" |
| 696 | "VALUES(%B,%Q,%B,%B)", |
| 697 | &login, zPw, &caps, &contact |
| 698 | ); |
| 699 | free(zPw); |
| 700 | |
| 701 | /* The user is registered, now just log him in. */ |
| 702 | int uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername); |
| 703 | char *zCookie; |
| 704 | const char *zCookieName = login_cookie_name(); |
| 705 | const char *zExpire = db_get("cookie-expire","8766"); |
| 706 | int expires = atoi(zExpire)*3600; |
| 707 | const char *zIpAddr = PD("REMOTE_ADDR","nil"); |
| 708 | |
| 709 | zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid); |
| 710 | cgi_set_cookie(zCookieName, zCookie, 0, expires); |
| 711 | db_multi_exec( |
| 712 | "UPDATE user SET cookie=%Q, ipaddr=%Q, " |
| 713 | " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d", |
| 714 | zCookie, zIpAddr, expires, uid |
| 715 | ); |
| 716 | redirect_to_g(); |
| 717 | |
| 718 | } |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | /* Prepare the captcha. */ |
| 723 | unsigned int uSeed = captcha_seed(); |
| 724 | char const *zDecoded = captcha_decode(uSeed); |
| 725 | char *zCaptcha = captcha_render(zDecoded); |
| 726 | |
| 727 | /* Print out the registration form. */ |
| 728 | @ <form action="register" method="post"> |
| 729 | if( P("g") ){ |
| 730 | @ <input type="hidden" name="g" value="%h(P("g"))" /> |
| 731 | } |
| 732 | @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> |
| 733 | @ <table class="login_out"> |
| 734 | @ <tr> |
| 735 | @ <td class="login_out_label" align="right">User ID:</td> |
| 736 | @ <td><input type="text" id="u" name="u" value="" size="30" /></td> |
| 737 | @ </tr> |
| 738 | @ <tr> |
| 739 | @ <td class="login_out_label" align="right">Password:</td> |
| 740 | @ <td><input type="password" id="p" name="p" value="" size="30" /></td> |
| 741 | @ </tr> |
| 742 | @ <tr> |
| 743 | @ <td class="login_out_label" align="right">Confirm password:</td> |
| 744 | @ <td><input type="password" id="cp" name="cp" value="" size="30" /></td> |
| 745 | @ </tr> |
| 746 | @ <tr> |
| 747 | @ <td class="login_out_label" align="right">Contact info:</td> |
| 748 | @ <td><input type="text" id="c" name="c" value="" size="30" /></td> |
| 749 | @ </tr> |
| 750 | @ <tr> |
| 751 | @ <td class="login_out_label" align="right">Captcha text (below):</td> |
| 752 | @ <td><input type="text" id="cap" name="cap" value="" size="30" /></td> |
| 753 | @ </tr> |
| 754 | @ <tr><td></td> |
| 755 | @ <td><input type="submit" name="new" value="Register" /></td></tr> |
| 756 | @ </table> |
| 757 | @ <div class="captcha"><table class="captcha"><tr><td><pre> |
| 758 | @ %s(zCaptcha) |
| 759 | @ </pre></td></tr></table> |
| 760 | @ </form> |
| 761 | style_footer(); |
| 762 | |
| 763 | free(zCaptcha); |
| 764 | } |
| 765 |
+16
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -790,10 +790,26 @@ | ||
| 790 | 790 | @ <p>Fossil tries to limit out-bound sync, clone, and pull packets |
| 791 | 791 | @ to this many bytes, uncompressed. If the client requires more data |
| 792 | 792 | @ than this, then the client will issue multiple HTTP requests. |
| 793 | 793 | @ Values below 1 million are not recommended. 5 million is a |
| 794 | 794 | @ reasonable number.</p> |
| 795 | + | |
| 796 | + @ <hr /> | |
| 797 | + onoff_attribute("Allow users to register themselves", | |
| 798 | + "self-register", "selfregister", 0); | |
| 799 | + @ <p>Allow users to register themselves through the HTTP UI. | |
| 800 | + @ The registration form always requires filling in a CAPTCHA | |
| 801 | + @ (<em>auto-captcha</em> setting is ignored). Still, bear in mind that anyone | |
| 802 | + @ can register under any user name. This option is useful for public projects | |
| 803 | + @ where you do not want everyone in any ticket discussion to be named | |
| 804 | + @ "Anonymous".</p> | |
| 805 | + | |
| 806 | + @ <hr /> | |
| 807 | + entry_attribute("Default privileges", 10, "default-perms", "defaultperms", "u"); | |
| 808 | + @ <p>Permissions given to users that register themselves using the HTTP UI | |
| 809 | + @ or are registered by the administrator using the command line interface. | |
| 810 | + @ </p> | |
| 795 | 811 | |
| 796 | 812 | @ <hr /> |
| 797 | 813 | onoff_attribute("Show javascript button to fill in CAPTCHA", |
| 798 | 814 | "auto-captcha", "autocaptcha", 0); |
| 799 | 815 | @ <p>When enabled, a button appears on the login screen for user |
| 800 | 816 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -790,10 +790,26 @@ | |
| 790 | @ <p>Fossil tries to limit out-bound sync, clone, and pull packets |
| 791 | @ to this many bytes, uncompressed. If the client requires more data |
| 792 | @ than this, then the client will issue multiple HTTP requests. |
| 793 | @ Values below 1 million are not recommended. 5 million is a |
| 794 | @ reasonable number.</p> |
| 795 | |
| 796 | @ <hr /> |
| 797 | onoff_attribute("Show javascript button to fill in CAPTCHA", |
| 798 | "auto-captcha", "autocaptcha", 0); |
| 799 | @ <p>When enabled, a button appears on the login screen for user |
| 800 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -790,10 +790,26 @@ | |
| 790 | @ <p>Fossil tries to limit out-bound sync, clone, and pull packets |
| 791 | @ to this many bytes, uncompressed. If the client requires more data |
| 792 | @ than this, then the client will issue multiple HTTP requests. |
| 793 | @ Values below 1 million are not recommended. 5 million is a |
| 794 | @ reasonable number.</p> |
| 795 | |
| 796 | @ <hr /> |
| 797 | onoff_attribute("Allow users to register themselves", |
| 798 | "self-register", "selfregister", 0); |
| 799 | @ <p>Allow users to register themselves through the HTTP UI. |
| 800 | @ The registration form always requires filling in a CAPTCHA |
| 801 | @ (<em>auto-captcha</em> setting is ignored). Still, bear in mind that anyone |
| 802 | @ can register under any user name. This option is useful for public projects |
| 803 | @ where you do not want everyone in any ticket discussion to be named |
| 804 | @ "Anonymous".</p> |
| 805 | |
| 806 | @ <hr /> |
| 807 | entry_attribute("Default privileges", 10, "default-perms", "defaultperms", "u"); |
| 808 | @ <p>Permissions given to users that register themselves using the HTTP UI |
| 809 | @ or are registered by the administrator using the command line interface. |
| 810 | @ </p> |
| 811 | |
| 812 | @ <hr /> |
| 813 | onoff_attribute("Show javascript button to fill in CAPTCHA", |
| 814 | "auto-captcha", "autocaptcha", 0); |
| 815 | @ <p>When enabled, a button appears on the login screen for user |
| 816 |
+4
-3
| --- src/user.c | ||
| +++ src/user.c | ||
| @@ -180,12 +180,13 @@ | ||
| 180 | 180 | if( g.argc<3 ){ |
| 181 | 181 | usage("capabilities|default|list|new|password ..."); |
| 182 | 182 | } |
| 183 | 183 | n = strlen(g.argv[2]); |
| 184 | 184 | if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){ |
| 185 | - Blob passwd, login, contact; | |
| 185 | + Blob passwd, login, caps, contact; | |
| 186 | 186 | char *zPw; |
| 187 | + blob_init(&caps, db_get("default-perms", "u"), -1); | |
| 187 | 188 | |
| 188 | 189 | if( g.argc>=4 ){ |
| 189 | 190 | blob_init(&login, g.argv[3], -1); |
| 190 | 191 | }else{ |
| 191 | 192 | prompt_user("login: ", &login); |
| @@ -204,12 +205,12 @@ | ||
| 204 | 205 | prompt_for_password("password: ", &passwd, 1); |
| 205 | 206 | } |
| 206 | 207 | zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login)); |
| 207 | 208 | db_multi_exec( |
| 208 | 209 | "INSERT INTO user(login,pw,cap,info)" |
| 209 | - "VALUES(%B,%Q,'v',%B)", | |
| 210 | - &login, zPw, &contact | |
| 210 | + "VALUES(%B,%Q,%B,%B)", | |
| 211 | + &login, zPw, &caps, &contact | |
| 211 | 212 | ); |
| 212 | 213 | free(zPw); |
| 213 | 214 | }else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){ |
| 214 | 215 | user_select(); |
| 215 | 216 | if( g.argc==3 ){ |
| 216 | 217 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -180,12 +180,13 @@ | |
| 180 | if( g.argc<3 ){ |
| 181 | usage("capabilities|default|list|new|password ..."); |
| 182 | } |
| 183 | n = strlen(g.argv[2]); |
| 184 | if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){ |
| 185 | Blob passwd, login, contact; |
| 186 | char *zPw; |
| 187 | |
| 188 | if( g.argc>=4 ){ |
| 189 | blob_init(&login, g.argv[3], -1); |
| 190 | }else{ |
| 191 | prompt_user("login: ", &login); |
| @@ -204,12 +205,12 @@ | |
| 204 | prompt_for_password("password: ", &passwd, 1); |
| 205 | } |
| 206 | zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login)); |
| 207 | db_multi_exec( |
| 208 | "INSERT INTO user(login,pw,cap,info)" |
| 209 | "VALUES(%B,%Q,'v',%B)", |
| 210 | &login, zPw, &contact |
| 211 | ); |
| 212 | free(zPw); |
| 213 | }else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){ |
| 214 | user_select(); |
| 215 | if( g.argc==3 ){ |
| 216 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -180,12 +180,13 @@ | |
| 180 | if( g.argc<3 ){ |
| 181 | usage("capabilities|default|list|new|password ..."); |
| 182 | } |
| 183 | n = strlen(g.argv[2]); |
| 184 | if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){ |
| 185 | Blob passwd, login, caps, contact; |
| 186 | char *zPw; |
| 187 | blob_init(&caps, db_get("default-perms", "u"), -1); |
| 188 | |
| 189 | if( g.argc>=4 ){ |
| 190 | blob_init(&login, g.argv[3], -1); |
| 191 | }else{ |
| 192 | prompt_user("login: ", &login); |
| @@ -204,12 +205,12 @@ | |
| 205 | prompt_for_password("password: ", &passwd, 1); |
| 206 | } |
| 207 | zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login)); |
| 208 | db_multi_exec( |
| 209 | "INSERT INTO user(login,pw,cap,info)" |
| 210 | "VALUES(%B,%Q,%B,%B)", |
| 211 | &login, zPw, &caps, &contact |
| 212 | ); |
| 213 | free(zPw); |
| 214 | }else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){ |
| 215 | user_select(); |
| 216 | if( g.argc==3 ){ |
| 217 |