Fossil SCM

Revamp the /register page for added security. Require entry of a display name and email address. Validate the email address format and check for duplicate email addresses.

drh 2018-07-24 13:30 forum-v2
Commit d8b20a555fba69212893102e08f71e15d405c3684d39d40adf10da46f1abbb93
+7 -7
--- src/email.c
+++ src/email.c
@@ -568,27 +568,27 @@
568568
return 0;
569569
}
570570
571571
/*
572572
** Make a copy of the input string up to but not including the
573
-** first ">" character.
573
+** first cTerm character.
574574
**
575575
** Verify that the string really that is to be copied really is a
576576
** valid email address. If it is not, then return NULL.
577577
**
578578
** This routine is more restrictive than necessary. It does not
579579
** allow comments, IP address, quoted strings, or certain uncommon
580580
** characters. The only non-alphanumerics allowed in the local
581581
** part are "_", "+", "-" and "+".
582582
*/
583
-char *email_copy_addr(const char *z){
583
+char *email_copy_addr(const char *z, char cTerm ){
584584
int i;
585585
int nAt = 0;
586586
int nDot = 0;
587587
char c;
588588
if( z[0]=='.' ) return 0; /* Local part cannot begin with "." */
589
- for(i=0; (c = z[i])!=0 && c!='>'; i++){
589
+ for(i=0; (c = z[i])!=0 && c!=cTerm; i++){
590590
if( fossil_isalnum(c) ){
591591
/* Alphanumerics are always ok */
592592
}else if( c=='@' ){
593593
if( nAt ) return 0; /* Only a single "@" allowed */
594594
if( i>64 ) return 0; /* Local part too big */
@@ -598,22 +598,22 @@
598598
if( z[i-1]=='.' ) return 0; /* Last char of local cannot be "." */
599599
if( z[i+1]=='.' || z[i+1]=='-' ){
600600
return 0; /* Domain cannot begin with "." or "-" */
601601
}
602602
}else if( c=='-' ){
603
- if( z[i+1]=='>' ) return 0; /* Last character cannot be "-" */
603
+ if( z[i+1]==cTerm ) return 0; /* Last character cannot be "-" */
604604
}else if( c=='.' ){
605605
if( z[i+1]=='.' ) return 0; /* Do not allow ".." */
606
- if( z[i+1]=='>' ) return 0; /* Domain may not end with . */
606
+ if( z[i+1]==cTerm ) return 0; /* Domain may not end with . */
607607
nDot++;
608608
}else if( (c=='_' || c=='+') && nAt==0 ){
609609
/* _ and + are ok in the local part */
610610
}else{
611611
return 0; /* Anything else is an error */
612612
}
613613
}
614
- if( c!='>' ) return 0; /* Missing final ">" */
614
+ if( c!=cTerm ) return 0; /* Missing terminator */
615615
if( nAt==0 ) return 0; /* No "@" found anywhere */
616616
if( nDot==0 ) return 0; /* No "." in the domain */
617617
618618
/* If we reach this point, the email address is valid */
619619
return mprintf("%.*s", i, z);
@@ -631,11 +631,11 @@
631631
int i;
632632
633633
email_header_value(pMsg, "to", &v);
634634
z = blob_str(&v);
635635
for(i=0; z[i]; i++){
636
- if( z[i]=='<' && (zAddr = email_copy_addr(&z[i+1]))!=0 ){
636
+ if( z[i]=='<' && (zAddr = email_copy_addr(&z[i+1],'>'))!=0 ){
637637
azTo = fossil_realloc(azTo, sizeof(azTo[0])*(nTo+1) );
638638
azTo[nTo++] = zAddr;
639639
}
640640
}
641641
*pnTo = nTo;
642642
--- src/email.c
+++ src/email.c
@@ -568,27 +568,27 @@
568 return 0;
569 }
570
571 /*
572 ** Make a copy of the input string up to but not including the
573 ** first ">" character.
574 **
575 ** Verify that the string really that is to be copied really is a
576 ** valid email address. If it is not, then return NULL.
577 **
578 ** This routine is more restrictive than necessary. It does not
579 ** allow comments, IP address, quoted strings, or certain uncommon
580 ** characters. The only non-alphanumerics allowed in the local
581 ** part are "_", "+", "-" and "+".
582 */
583 char *email_copy_addr(const char *z){
584 int i;
585 int nAt = 0;
586 int nDot = 0;
587 char c;
588 if( z[0]=='.' ) return 0; /* Local part cannot begin with "." */
589 for(i=0; (c = z[i])!=0 && c!='>'; i++){
590 if( fossil_isalnum(c) ){
591 /* Alphanumerics are always ok */
592 }else if( c=='@' ){
593 if( nAt ) return 0; /* Only a single "@" allowed */
594 if( i>64 ) return 0; /* Local part too big */
@@ -598,22 +598,22 @@
598 if( z[i-1]=='.' ) return 0; /* Last char of local cannot be "." */
599 if( z[i+1]=='.' || z[i+1]=='-' ){
600 return 0; /* Domain cannot begin with "." or "-" */
601 }
602 }else if( c=='-' ){
603 if( z[i+1]=='>' ) return 0; /* Last character cannot be "-" */
604 }else if( c=='.' ){
605 if( z[i+1]=='.' ) return 0; /* Do not allow ".." */
606 if( z[i+1]=='>' ) return 0; /* Domain may not end with . */
607 nDot++;
608 }else if( (c=='_' || c=='+') && nAt==0 ){
609 /* _ and + are ok in the local part */
610 }else{
611 return 0; /* Anything else is an error */
612 }
613 }
614 if( c!='>' ) return 0; /* Missing final ">" */
615 if( nAt==0 ) return 0; /* No "@" found anywhere */
616 if( nDot==0 ) return 0; /* No "." in the domain */
617
618 /* If we reach this point, the email address is valid */
619 return mprintf("%.*s", i, z);
@@ -631,11 +631,11 @@
631 int i;
632
633 email_header_value(pMsg, "to", &v);
634 z = blob_str(&v);
635 for(i=0; z[i]; i++){
636 if( z[i]=='<' && (zAddr = email_copy_addr(&z[i+1]))!=0 ){
637 azTo = fossil_realloc(azTo, sizeof(azTo[0])*(nTo+1) );
638 azTo[nTo++] = zAddr;
639 }
640 }
641 *pnTo = nTo;
642
--- src/email.c
+++ src/email.c
@@ -568,27 +568,27 @@
568 return 0;
569 }
570
571 /*
572 ** Make a copy of the input string up to but not including the
573 ** first cTerm character.
574 **
575 ** Verify that the string really that is to be copied really is a
576 ** valid email address. If it is not, then return NULL.
577 **
578 ** This routine is more restrictive than necessary. It does not
579 ** allow comments, IP address, quoted strings, or certain uncommon
580 ** characters. The only non-alphanumerics allowed in the local
581 ** part are "_", "+", "-" and "+".
582 */
583 char *email_copy_addr(const char *z, char cTerm ){
584 int i;
585 int nAt = 0;
586 int nDot = 0;
587 char c;
588 if( z[0]=='.' ) return 0; /* Local part cannot begin with "." */
589 for(i=0; (c = z[i])!=0 && c!=cTerm; i++){
590 if( fossil_isalnum(c) ){
591 /* Alphanumerics are always ok */
592 }else if( c=='@' ){
593 if( nAt ) return 0; /* Only a single "@" allowed */
594 if( i>64 ) return 0; /* Local part too big */
@@ -598,22 +598,22 @@
598 if( z[i-1]=='.' ) return 0; /* Last char of local cannot be "." */
599 if( z[i+1]=='.' || z[i+1]=='-' ){
600 return 0; /* Domain cannot begin with "." or "-" */
601 }
602 }else if( c=='-' ){
603 if( z[i+1]==cTerm ) return 0; /* Last character cannot be "-" */
604 }else if( c=='.' ){
605 if( z[i+1]=='.' ) return 0; /* Do not allow ".." */
606 if( z[i+1]==cTerm ) return 0; /* Domain may not end with . */
607 nDot++;
608 }else if( (c=='_' || c=='+') && nAt==0 ){
609 /* _ and + are ok in the local part */
610 }else{
611 return 0; /* Anything else is an error */
612 }
613 }
614 if( c!=cTerm ) return 0; /* Missing terminator */
615 if( nAt==0 ) return 0; /* No "@" found anywhere */
616 if( nDot==0 ) return 0; /* No "." in the domain */
617
618 /* If we reach this point, the email address is valid */
619 return mprintf("%.*s", i, z);
@@ -631,11 +631,11 @@
631 int i;
632
633 email_header_value(pMsg, "to", &v);
634 z = blob_str(&v);
635 for(i=0; z[i]; i++){
636 if( z[i]=='<' && (zAddr = email_copy_addr(&z[i+1],'>'))!=0 ){
637 azTo = fossil_realloc(azTo, sizeof(azTo[0])*(nTo+1) );
638 azTo[nTo++] = zAddr;
639 }
640 }
641 *pnTo = nTo;
642
+88 -67
--- src/login.c
+++ src/login.c
@@ -1457,82 +1457,81 @@
14571457
**
14581458
** Page to allow users to self-register. The "self-register" setting
14591459
** must be enabled for this page to operate.
14601460
*/
14611461
void register_page(void){
1462
- const char *zUsername, *zPasswd, *zConfirm, *zContact, *zCS, *zPw, *zCap;
1462
+ const char *zUserID, *zPasswd, *zConfirm, *zEAddr;
1463
+ const char *zDName;
14631464
unsigned int uSeed;
14641465
const char *zDecoded;
14651466
char *zCaptcha;
1467
+ int iErrLine = -1;
1468
+ const char *zErr;
14661469
if( !db_get_boolean("self-register", 0) ){
14671470
style_header("Registration not possible");
14681471
@ <p>This project does not allow user self-registration. Please contact the
14691472
@ project administrator to obtain an account.</p>
14701473
style_footer();
14711474
return;
14721475
}
14731476
14741477
style_header("Register");
1475
- zUsername = P("u");
1476
- zPasswd = P("p");
1477
- zConfirm = P("cp");
1478
- zContact = P("c");
1479
- zCap = P("cap");
1480
- zCS = P("cs"); /* Captcha Secret */
1478
+ zUserID = PDT("u","");
1479
+ zPasswd = PDT("p","");
1480
+ zConfirm = PDT("cp","");
1481
+ zEAddr = PDT("ea","");
1482
+ zDName = PDT("dn","");
14811483
14821484
/* Try to make any sense from user input. */
1483
- if( P("new") ){
1484
- if( zCS==0 ) fossil_redirect_home(); /* Forged request */
1485
- zPw = captcha_decode((unsigned int)atoi(zCS));
1486
- if( !(zUsername && zPasswd && zConfirm && zContact) ){
1487
- @ <p><span class="loginError">
1488
- @ All fields are obligatory.
1489
- @ </span></p>
1490
- }else if( strlen(zPasswd) < 6){
1491
- @ <p><span class="loginError">
1492
- @ Password too weak.
1493
- @ </span></p>
1494
- }else if( fossil_strcmp(zPasswd,zConfirm)!=0 ){
1495
- @ <p><span class="loginError">
1496
- @ The two copies of your new passwords do not match.
1497
- @ </span></p>
1498
- }else if( fossil_stricmp(zPw, zCap)!=0 ){
1499
- @ <p><span class="loginError">
1500
- @ Captcha text invalid.
1501
- @ </span></p>
1502
- }else{
1503
- /* This almost is stupid copy-paste of code from user.c:user_cmd(). */
1504
- Blob passwd, login, caps, contact;
1505
-
1506
- blob_init(&login, zUsername, -1);
1507
- blob_init(&contact, zContact, -1);
1508
- blob_init(&caps, db_get("default-perms", "u"), -1);
1509
- blob_init(&passwd, zPasswd, -1);
1510
-
1511
- if( db_exists("SELECT 1 FROM user WHERE login=%B", &login) ){
1512
- /* Here lies the reason I don't use zErrMsg - it would not substitute
1513
- * this %s(zUsername), or at least I don't know how to force it to.*/
1514
- @ <p><span class="loginError">
1515
- @ %h(zUsername) already exists.
1516
- @ </span></p>
1517
- }else{
1518
- char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
1519
- int uid;
1520
- db_multi_exec(
1521
- "INSERT INTO user(login,pw,cap,info,mtime)"
1522
- "VALUES(%B,%Q,%B,%B,strftime('%%s','now'))",
1523
- &login, zPw, &caps, &contact
1524
- );
1525
- free(zPw);
1526
-
1527
- /* The user is registered, now just log him in. */
1528
- uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername);
1529
- login_set_user_cookie( zUsername, uid, NULL );
1530
- redirect_to_g();
1531
-
1532
- }
1533
- }
1485
+ if( P("new")==0 || !cgi_csrf_safe(1) ){
1486
+ /* This is not a valid form submission. Fall through into
1487
+ ** the form display */
1488
+ }else if( !captcha_is_correct(1) ){
1489
+ iErrLine = 6;
1490
+ zErr = "Incorrect CAPTCHA";
1491
+ }else if( strlen(zUserID)<3 ){
1492
+ iErrLine = 1;
1493
+ zErr = "User ID too short. Must be at least 3 characters.";
1494
+ }else if( sqlite3_strglob("*[^-a-zA-Z0-9_.]*",zUserID)==0 ){
1495
+ iErrLine = 1;
1496
+ zErr = "User ID may not contain spaces or special characters.";
1497
+ }else if( zDName[0]==0 ){
1498
+ iErrLine = 2;
1499
+ zErr = "Required";
1500
+ }else if( zEAddr[0]==0 ){
1501
+ iErrLine = 3;
1502
+ zErr = "Required";
1503
+ }else if( email_copy_addr(zEAddr,0)==0 ){
1504
+ iErrLine = 3;
1505
+ zErr = "Not a valid email address";
1506
+ }else if( strlen(zPasswd)<6 ){
1507
+ iErrLine = 4;
1508
+ zErr = "Password must be at least 6 characters long";
1509
+ }else if( fossil_strcmp(zPasswd,zConfirm)!=0 ){
1510
+ iErrLine = 5;
1511
+ zErr = "Passwords do not match";
1512
+ }else if( db_exists("SELECT 1 FROM user WHERE login=%Q", zUserID) ){
1513
+ iErrLine = 1;
1514
+ zErr = "This User ID is already taken. Choose something different.";
1515
+ }else if( db_exists("SELECT 1 FROM user WHERE info LIKE '%%%q%%'", zEAddr) ){
1516
+ iErrLine = 3;
1517
+ zErr = "This address is already used.";
1518
+ }else{
1519
+ Blob sql;
1520
+ int uid;
1521
+ char *zPass = sha1_shared_secret(zPasswd, zUserID, 0);
1522
+ blob_init(&sql, 0, 0);
1523
+ blob_append_sql(&sql,
1524
+ "INSERT INTO user(login,pw,cap,info,mtime)\n"
1525
+ "VALUES(%Q,%Q,%Q,"
1526
+ "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())",
1527
+ zUserID, zPass, db_get("default-perms","u"), zDName, zEAddr, g.zIpAddr);
1528
+ fossil_free(zPass);
1529
+ db_multi_exec("%s", blob_sql_text(&sql));
1530
+ uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID);
1531
+ login_set_user_cookie(zUserID, uid, NULL);
1532
+ redirect_to_g();
15341533
}
15351534
15361535
/* Prepare the captcha. */
15371536
uSeed = captcha_seed();
15381537
zDecoded = captcha_decode(uSeed);
@@ -1541,31 +1540,53 @@
15411540
/* Print out the registration form. */
15421541
form_begin(0, "%R/register");
15431542
if( P("g") ){
15441543
@ <input type="hidden" name="g" value="%h(P("g"))" />
15451544
}
1546
- @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
1545
+ @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
15471546
@ <table class="login_out">
15481547
@ <tr>
15491548
@ <td class="form_label" align="right">User ID:</td>
1550
- @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
1549
+ @ <td><input type="text" name="u" value="%h(zUserID)" size="30"></td>
1550
+ if( iErrLine==1 ){
1551
+ @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1552
+ }
1553
+ @ </tr>
1554
+ @ <tr>
1555
+ @ <td class="form_label" align="right">Display Name:</td>
1556
+ @ <td><input type="text" name="dn" value="%h(zDName)" size="30"></td>
1557
+ if( iErrLine==2 ){
1558
+ @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1559
+ }
1560
+ @ </tr>
1561
+ @ <tr>
1562
+ @ <td class="form_label" align="right">Email Address:</td>
1563
+ @ <td><input type="text" name="ea" value="%h(zEAddr)" size="30"></td>
1564
+ if( iErrLine==3 ){
1565
+ @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1566
+ }
15511567
@ </tr>
15521568
@ <tr>
15531569
@ <td class="form_label" align="right">Password:</td>
1554
- @ <td><input type="password" id="p" name="p" value="" size="30" /></td>
1570
+ @ <td><input type="password" name="p" value="%h(zPasswd)" size="30"></td>
1571
+ if( iErrLine==4 ){
1572
+ @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1573
+ }
15551574
@ </tr>
15561575
@ <tr>
15571576
@ <td class="form_label" align="right">Confirm password:</td>
1558
- @ <td><input type="password" id="cp" name="cp" value="" size="30" /></td>
1559
- @ </tr>
1560
- @ <tr>
1561
- @ <td class="form_label" align="right">Contact info:</td>
1562
- @ <td><input type="text" id="c" name="c" value="" size="30" /></td>
1577
+ @ <td><input type="password" name="cp" value="%h(zConfirm)" size="30"></td>
1578
+ if( iErrLine==5 ){
1579
+ @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1580
+ }
15631581
@ </tr>
15641582
@ <tr>
15651583
@ <td class="form_label" align="right">Captcha text (below):</td>
1566
- @ <td><input type="text" id="cap" name="cap" value="" size="30" /></td>
1584
+ @ <td><input type="text" name="captcha" value="" size="30"></td>
1585
+ if( iErrLine==6 ){
1586
+ @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1587
+ }
15671588
@ </tr>
15681589
@ <tr><td></td>
15691590
@ <td><input type="submit" name="new" value="Register" /></td></tr>
15701591
@ </table>
15711592
@ <div class="captcha"><table class="captcha"><tr><td><pre>
15721593
--- src/login.c
+++ src/login.c
@@ -1457,82 +1457,81 @@
1457 **
1458 ** Page to allow users to self-register. The "self-register" setting
1459 ** must be enabled for this page to operate.
1460 */
1461 void register_page(void){
1462 const char *zUsername, *zPasswd, *zConfirm, *zContact, *zCS, *zPw, *zCap;
 
1463 unsigned int uSeed;
1464 const char *zDecoded;
1465 char *zCaptcha;
 
 
1466 if( !db_get_boolean("self-register", 0) ){
1467 style_header("Registration not possible");
1468 @ <p>This project does not allow user self-registration. Please contact the
1469 @ project administrator to obtain an account.</p>
1470 style_footer();
1471 return;
1472 }
1473
1474 style_header("Register");
1475 zUsername = P("u");
1476 zPasswd = P("p");
1477 zConfirm = P("cp");
1478 zContact = P("c");
1479 zCap = P("cap");
1480 zCS = P("cs"); /* Captcha Secret */
1481
1482 /* Try to make any sense from user input. */
1483 if( P("new") ){
1484 if( zCS==0 ) fossil_redirect_home(); /* Forged request */
1485 zPw = captcha_decode((unsigned int)atoi(zCS));
1486 if( !(zUsername && zPasswd && zConfirm && zContact) ){
1487 @ <p><span class="loginError">
1488 @ All fields are obligatory.
1489 @ </span></p>
1490 }else if( strlen(zPasswd) < 6){
1491 @ <p><span class="loginError">
1492 @ Password too weak.
1493 @ </span></p>
1494 }else if( fossil_strcmp(zPasswd,zConfirm)!=0 ){
1495 @ <p><span class="loginError">
1496 @ The two copies of your new passwords do not match.
1497 @ </span></p>
1498 }else if( fossil_stricmp(zPw, zCap)!=0 ){
1499 @ <p><span class="loginError">
1500 @ Captcha text invalid.
1501 @ </span></p>
1502 }else{
1503 /* This almost is stupid copy-paste of code from user.c:user_cmd(). */
1504 Blob passwd, login, caps, contact;
1505
1506 blob_init(&login, zUsername, -1);
1507 blob_init(&contact, zContact, -1);
1508 blob_init(&caps, db_get("default-perms", "u"), -1);
1509 blob_init(&passwd, zPasswd, -1);
1510
1511 if( db_exists("SELECT 1 FROM user WHERE login=%B", &login) ){
1512 /* Here lies the reason I don't use zErrMsg - it would not substitute
1513 * this %s(zUsername), or at least I don't know how to force it to.*/
1514 @ <p><span class="loginError">
1515 @ %h(zUsername) already exists.
1516 @ </span></p>
1517 }else{
1518 char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
1519 int uid;
1520 db_multi_exec(
1521 "INSERT INTO user(login,pw,cap,info,mtime)"
1522 "VALUES(%B,%Q,%B,%B,strftime('%%s','now'))",
1523 &login, zPw, &caps, &contact
1524 );
1525 free(zPw);
1526
1527 /* The user is registered, now just log him in. */
1528 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername);
1529 login_set_user_cookie( zUsername, uid, NULL );
1530 redirect_to_g();
1531
1532 }
1533 }
1534 }
1535
1536 /* Prepare the captcha. */
1537 uSeed = captcha_seed();
1538 zDecoded = captcha_decode(uSeed);
@@ -1541,31 +1540,53 @@
1541 /* Print out the registration form. */
1542 form_begin(0, "%R/register");
1543 if( P("g") ){
1544 @ <input type="hidden" name="g" value="%h(P("g"))" />
1545 }
1546 @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
1547 @ <table class="login_out">
1548 @ <tr>
1549 @ <td class="form_label" align="right">User ID:</td>
1550 @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1551 @ </tr>
1552 @ <tr>
1553 @ <td class="form_label" align="right">Password:</td>
1554 @ <td><input type="password" id="p" name="p" value="" size="30" /></td>
 
 
 
1555 @ </tr>
1556 @ <tr>
1557 @ <td class="form_label" align="right">Confirm password:</td>
1558 @ <td><input type="password" id="cp" name="cp" value="" size="30" /></td>
1559 @ </tr>
1560 @ <tr>
1561 @ <td class="form_label" align="right">Contact info:</td>
1562 @ <td><input type="text" id="c" name="c" value="" size="30" /></td>
1563 @ </tr>
1564 @ <tr>
1565 @ <td class="form_label" align="right">Captcha text (below):</td>
1566 @ <td><input type="text" id="cap" name="cap" value="" size="30" /></td>
 
 
 
1567 @ </tr>
1568 @ <tr><td></td>
1569 @ <td><input type="submit" name="new" value="Register" /></td></tr>
1570 @ </table>
1571 @ <div class="captcha"><table class="captcha"><tr><td><pre>
1572
--- src/login.c
+++ src/login.c
@@ -1457,82 +1457,81 @@
1457 **
1458 ** Page to allow users to self-register. The "self-register" setting
1459 ** must be enabled for this page to operate.
1460 */
1461 void register_page(void){
1462 const char *zUserID, *zPasswd, *zConfirm, *zEAddr;
1463 const char *zDName;
1464 unsigned int uSeed;
1465 const char *zDecoded;
1466 char *zCaptcha;
1467 int iErrLine = -1;
1468 const char *zErr;
1469 if( !db_get_boolean("self-register", 0) ){
1470 style_header("Registration not possible");
1471 @ <p>This project does not allow user self-registration. Please contact the
1472 @ project administrator to obtain an account.</p>
1473 style_footer();
1474 return;
1475 }
1476
1477 style_header("Register");
1478 zUserID = PDT("u","");
1479 zPasswd = PDT("p","");
1480 zConfirm = PDT("cp","");
1481 zEAddr = PDT("ea","");
1482 zDName = PDT("dn","");
 
1483
1484 /* Try to make any sense from user input. */
1485 if( P("new")==0 || !cgi_csrf_safe(1) ){
1486 /* This is not a valid form submission. Fall through into
1487 ** the form display */
1488 }else if( !captcha_is_correct(1) ){
1489 iErrLine = 6;
1490 zErr = "Incorrect CAPTCHA";
1491 }else if( strlen(zUserID)<3 ){
1492 iErrLine = 1;
1493 zErr = "User ID too short. Must be at least 3 characters.";
1494 }else if( sqlite3_strglob("*[^-a-zA-Z0-9_.]*",zUserID)==0 ){
1495 iErrLine = 1;
1496 zErr = "User ID may not contain spaces or special characters.";
1497 }else if( zDName[0]==0 ){
1498 iErrLine = 2;
1499 zErr = "Required";
1500 }else if( zEAddr[0]==0 ){
1501 iErrLine = 3;
1502 zErr = "Required";
1503 }else if( email_copy_addr(zEAddr,0)==0 ){
1504 iErrLine = 3;
1505 zErr = "Not a valid email address";
1506 }else if( strlen(zPasswd)<6 ){
1507 iErrLine = 4;
1508 zErr = "Password must be at least 6 characters long";
1509 }else if( fossil_strcmp(zPasswd,zConfirm)!=0 ){
1510 iErrLine = 5;
1511 zErr = "Passwords do not match";
1512 }else if( db_exists("SELECT 1 FROM user WHERE login=%Q", zUserID) ){
1513 iErrLine = 1;
1514 zErr = "This User ID is already taken. Choose something different.";
1515 }else if( db_exists("SELECT 1 FROM user WHERE info LIKE '%%%q%%'", zEAddr) ){
1516 iErrLine = 3;
1517 zErr = "This address is already used.";
1518 }else{
1519 Blob sql;
1520 int uid;
1521 char *zPass = sha1_shared_secret(zPasswd, zUserID, 0);
1522 blob_init(&sql, 0, 0);
1523 blob_append_sql(&sql,
1524 "INSERT INTO user(login,pw,cap,info,mtime)\n"
1525 "VALUES(%Q,%Q,%Q,"
1526 "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())",
1527 zUserID, zPass, db_get("default-perms","u"), zDName, zEAddr, g.zIpAddr);
1528 fossil_free(zPass);
1529 db_multi_exec("%s", blob_sql_text(&sql));
1530 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID);
1531 login_set_user_cookie(zUserID, uid, NULL);
1532 redirect_to_g();
 
 
 
1533 }
1534
1535 /* Prepare the captcha. */
1536 uSeed = captcha_seed();
1537 zDecoded = captcha_decode(uSeed);
@@ -1541,31 +1540,53 @@
1540 /* Print out the registration form. */
1541 form_begin(0, "%R/register");
1542 if( P("g") ){
1543 @ <input type="hidden" name="g" value="%h(P("g"))" />
1544 }
1545 @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
1546 @ <table class="login_out">
1547 @ <tr>
1548 @ <td class="form_label" align="right">User ID:</td>
1549 @ <td><input type="text" name="u" value="%h(zUserID)" size="30"></td>
1550 if( iErrLine==1 ){
1551 @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1552 }
1553 @ </tr>
1554 @ <tr>
1555 @ <td class="form_label" align="right">Display Name:</td>
1556 @ <td><input type="text" name="dn" value="%h(zDName)" size="30"></td>
1557 if( iErrLine==2 ){
1558 @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1559 }
1560 @ </tr>
1561 @ <tr>
1562 @ <td class="form_label" align="right">Email Address:</td>
1563 @ <td><input type="text" name="ea" value="%h(zEAddr)" size="30"></td>
1564 if( iErrLine==3 ){
1565 @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1566 }
1567 @ </tr>
1568 @ <tr>
1569 @ <td class="form_label" align="right">Password:</td>
1570 @ <td><input type="password" name="p" value="%h(zPasswd)" size="30"></td>
1571 if( iErrLine==4 ){
1572 @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1573 }
1574 @ </tr>
1575 @ <tr>
1576 @ <td class="form_label" align="right">Confirm password:</td>
1577 @ <td><input type="password" name="cp" value="%h(zConfirm)" size="30"></td>
1578 if( iErrLine==5 ){
1579 @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1580 }
 
1581 @ </tr>
1582 @ <tr>
1583 @ <td class="form_label" align="right">Captcha text (below):</td>
1584 @ <td><input type="text" name="captcha" value="" size="30"></td>
1585 if( iErrLine==6 ){
1586 @ <td><span class='loginError'>&larr; %h(zErr)</span></td>
1587 }
1588 @ </tr>
1589 @ <tr><td></td>
1590 @ <td><input type="submit" name="new" value="Register" /></td></tr>
1591 @ </table>
1592 @ <div class="captcha"><table class="captcha"><tr><td><pre>
1593
--- src/setup.c
+++ src/setup.c
@@ -1308,10 +1308,12 @@
13081308
"defaultperms", "u", 0);
13091309
@ <p>Permissions given to users that... <ul><li>register themselves using
13101310
@ the self-registration procedure (if enabled), or <li>access "public"
13111311
@ pages identified by the public-pages glob pattern above, or <li>
13121312
@ are users newly created by the administrator.</ul>
1313
+ @ <p>Recommended value: "u" for Reader.
1314
+ @ <a href="%R/setup_ucap_list">Capability Key</a>.
13131315
@ (Property: "default-perms")
13141316
@ </p>
13151317
13161318
@ <hr />
13171319
onoff_attribute("Show javascript button to fill in CAPTCHA",
13181320
--- src/setup.c
+++ src/setup.c
@@ -1308,10 +1308,12 @@
1308 "defaultperms", "u", 0);
1309 @ <p>Permissions given to users that... <ul><li>register themselves using
1310 @ the self-registration procedure (if enabled), or <li>access "public"
1311 @ pages identified by the public-pages glob pattern above, or <li>
1312 @ are users newly created by the administrator.</ul>
 
 
1313 @ (Property: "default-perms")
1314 @ </p>
1315
1316 @ <hr />
1317 onoff_attribute("Show javascript button to fill in CAPTCHA",
1318
--- src/setup.c
+++ src/setup.c
@@ -1308,10 +1308,12 @@
1308 "defaultperms", "u", 0);
1309 @ <p>Permissions given to users that... <ul><li>register themselves using
1310 @ the self-registration procedure (if enabled), or <li>access "public"
1311 @ pages identified by the public-pages glob pattern above, or <li>
1312 @ are users newly created by the administrator.</ul>
1313 @ <p>Recommended value: "u" for Reader.
1314 @ <a href="%R/setup_ucap_list">Capability Key</a>.
1315 @ (Property: "default-perms")
1316 @ </p>
1317
1318 @ <hr />
1319 onoff_attribute("Show javascript button to fill in CAPTCHA",
1320
+2 -2
--- src/smtp.c
+++ src/smtp.c
@@ -1271,11 +1271,11 @@
12711271
smtp_server_send(&x, "250 ok\r\n");
12721272
}else
12731273
if( strncmp(z, "MAIL FROM:<", 11)==0 ){
12741274
smtp_server_route_incoming(&x, 0);
12751275
smtp_server_clear(&x, SMTPSRV_CLEAR_MSG);
1276
- x.zFrom = email_copy_addr(z+11);
1276
+ x.zFrom = email_copy_addr(z+11,'>');
12771277
if( x.zFrom==0 ){
12781278
smtp_server_send(&x, "500 unacceptable email address\r\n");
12791279
}else{
12801280
smtp_server_send(&x, "250 ok\r\n");
12811281
}
@@ -1284,11 +1284,11 @@
12841284
char *zAddr;
12851285
if( x.zFrom==0 ){
12861286
smtp_server_send(&x, "500 missing MAIL FROM\r\n");
12871287
continue;
12881288
}
1289
- zAddr = email_copy_addr(z+9);
1289
+ zAddr = email_copy_addr(z+9, '>');
12901290
if( zAddr==0 ){
12911291
smtp_server_send(&x, "505 no such user\r\n");
12921292
continue;
12931293
}
12941294
smtp_append_to(&x, zAddr, 0);
12951295
--- src/smtp.c
+++ src/smtp.c
@@ -1271,11 +1271,11 @@
1271 smtp_server_send(&x, "250 ok\r\n");
1272 }else
1273 if( strncmp(z, "MAIL FROM:<", 11)==0 ){
1274 smtp_server_route_incoming(&x, 0);
1275 smtp_server_clear(&x, SMTPSRV_CLEAR_MSG);
1276 x.zFrom = email_copy_addr(z+11);
1277 if( x.zFrom==0 ){
1278 smtp_server_send(&x, "500 unacceptable email address\r\n");
1279 }else{
1280 smtp_server_send(&x, "250 ok\r\n");
1281 }
@@ -1284,11 +1284,11 @@
1284 char *zAddr;
1285 if( x.zFrom==0 ){
1286 smtp_server_send(&x, "500 missing MAIL FROM\r\n");
1287 continue;
1288 }
1289 zAddr = email_copy_addr(z+9);
1290 if( zAddr==0 ){
1291 smtp_server_send(&x, "505 no such user\r\n");
1292 continue;
1293 }
1294 smtp_append_to(&x, zAddr, 0);
1295
--- src/smtp.c
+++ src/smtp.c
@@ -1271,11 +1271,11 @@
1271 smtp_server_send(&x, "250 ok\r\n");
1272 }else
1273 if( strncmp(z, "MAIL FROM:<", 11)==0 ){
1274 smtp_server_route_incoming(&x, 0);
1275 smtp_server_clear(&x, SMTPSRV_CLEAR_MSG);
1276 x.zFrom = email_copy_addr(z+11,'>');
1277 if( x.zFrom==0 ){
1278 smtp_server_send(&x, "500 unacceptable email address\r\n");
1279 }else{
1280 smtp_server_send(&x, "250 ok\r\n");
1281 }
@@ -1284,11 +1284,11 @@
1284 char *zAddr;
1285 if( x.zFrom==0 ){
1286 smtp_server_send(&x, "500 missing MAIL FROM\r\n");
1287 continue;
1288 }
1289 zAddr = email_copy_addr(z+9, '>');
1290 if( zAddr==0 ){
1291 smtp_server_send(&x, "505 no such user\r\n");
1292 continue;
1293 }
1294 smtp_append_to(&x, zAddr, 0);
1295

Keyboard Shortcuts

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