Fossil SCM

Validate the email address in the subscription editing form.

drh 2020-03-26 13:53 trunk
Commit 32a8d1102527724a43977c05f18d105f68d699cd1e02f5f32952826c58db2097
2 files changed +66 -41 +1 -1
+66 -41
--- src/alerts.c
+++ src/alerts.c
@@ -575,22 +575,18 @@
575575
}
576576
return 0;
577577
}
578578
579579
/*
580
-** Make a copy of the input string up to but not including the
581
-** first cTerm character.
582
-**
583
-** Verify that the string really that is to be copied really is a
584
-** valid email address. If it is not, then return NULL.
585
-**
586
-** This routine is more restrictive than necessary. It does not
587
-** allow comments, IP address, quoted strings, or certain uncommon
588
-** characters. The only non-alphanumerics allowed in the local
589
-** part are "_", "+", "-" and "+".
590
-*/
591
-char *email_copy_addr(const char *z, char cTerm ){
580
+** Determine whether or not the input string is a valid email address.
581
+** Only look at character up to but not including the first \000 or
582
+** the first cTerm character, whichever comes first.
583
+**
584
+** Return the length of the email addresss string in bytes if the email
585
+** address is valid. If the email address is misformed, return 0.
586
+*/
587
+int email_address_is_valid(const char *z, char cTerm){
592588
int i;
593589
int nAt = 0;
594590
int nDot = 0;
595591
char c;
596592
if( z[0]=='.' ) return 0; /* Local part cannot begin with "." */
@@ -620,13 +616,28 @@
620616
}
621617
}
622618
if( c!=cTerm ) return 0; /* Missing terminator */
623619
if( nAt==0 ) return 0; /* No "@" found anywhere */
624620
if( nDot==0 ) return 0; /* No "." in the domain */
621
+ return i;
622
+}
625623
626
- /* If we reach this point, the email address is valid */
627
- return mprintf("%.*s", i, z);
624
+/*
625
+** Make a copy of the input string up to but not including the
626
+** first cTerm character.
627
+**
628
+** Verify that the string really that is to be copied really is a
629
+** valid email address. If it is not, then return NULL.
630
+**
631
+** This routine is more restrictive than necessary. It does not
632
+** allow comments, IP address, quoted strings, or certain uncommon
633
+** characters. The only non-alphanumerics allowed in the local
634
+** part are "_", "+", "-" and "+".
635
+*/
636
+char *email_copy_addr(const char *z, char cTerm ){
637
+ int i = email_address_is_valid(z, cTerm);
638
+ return i==0 ? 0 : mprintf("%.*s", i, z);
628639
}
629640
630641
/*
631642
** Scan the input string for a valid email address enclosed in <...>
632643
** If the string contains one or more email addresses, extract the first
@@ -1516,14 +1527,14 @@
15161527
const char *zName = P("name");
15171528
Stmt q;
15181529
int sa, sc, sf, st, sw;
15191530
int sdigest, sdonotcall, sverified;
15201531
int isLogin; /* Logged in as an individual */
1521
- const char *ssub;
1532
+ const char *ssub = 0;
15221533
const char *semail;
15231534
const char *smip;
1524
- const char *suname;
1535
+ const char *suname = 0;
15251536
const char *mtime;
15261537
const char *sctime;
15271538
int eErr = 0;
15281539
char *zErr = 0;
15291540
@@ -1542,22 +1553,24 @@
15421553
cgi_redirect("subscribe");
15431554
return;
15441555
}
15451556
alert_submenu_common();
15461557
if( P("submit")!=0 && cgi_csrf_safe(1) ){
1547
- int sdonotcall = PB("sdonotcall");
1548
- int sdigest = PB("sdigest");
1549
- const char *zEmail = P("semail");
1550
- char ssub[10];
1558
+ char newSsub[10];
15511559
int nsub = 0;
15521560
Blob update;
1553
- if( PB("sa") ) ssub[nsub++] = 'a';
1554
- if( g.perm.Read && PB("sc") ) ssub[nsub++] = 'c';
1555
- if( g.perm.RdForum && PB("sf") ) ssub[nsub++] = 'f';
1556
- if( g.perm.RdTkt && PB("st") ) ssub[nsub++] = 't';
1557
- if( g.perm.RdWiki && PB("sw") ) ssub[nsub++] = 'w';
1558
- ssub[nsub] = 0;
1561
+
1562
+ sdonotcall = PB("sdonotcall");
1563
+ sdigest = PB("sdigest");
1564
+ semail = P("semail");
1565
+ if( PB("sa") ) newSsub[nsub++] = 'a';
1566
+ if( g.perm.Read && PB("sc") ) newSsub[nsub++] = 'c';
1567
+ if( g.perm.RdForum && PB("sf") ) newSsub[nsub++] = 'f';
1568
+ if( g.perm.RdTkt && PB("st") ) newSsub[nsub++] = 't';
1569
+ if( g.perm.RdWiki && PB("sw") ) newSsub[nsub++] = 'w';
1570
+ newSsub[nsub] = 0;
1571
+ ssub = newSsub;
15591572
blob_init(&update, "UPDATE subscriber SET", -1);
15601573
blob_append_sql(&update,
15611574
" sdonotcall=%d,"
15621575
" sdigest=%d,"
15631576
" ssub=%Q,"
@@ -1567,25 +1580,31 @@
15671580
sdigest,
15681581
ssub,
15691582
g.zIpAddr
15701583
);
15711584
if( g.perm.Admin ){
1572
- const char *suname = PT("suname");
1573
- int sverified = PB("sverified");
1585
+ suname = PT("suname");
1586
+ sverified = PB("sverified");
15741587
if( suname && suname[0]==0 ) suname = 0;
15751588
blob_append_sql(&update,
15761589
", suname=%Q,"
15771590
" sverified=%d",
15781591
suname,
15791592
sverified
15801593
);
15811594
}
1582
- if( isLogin && zEmail && zEmail[0] ){
1583
- blob_append_sql(&update, ", semail=%Q", zEmail);
1595
+ if( isLogin ){
1596
+ if( semail==0 || email_address_is_valid(semail,0)==0 ){
1597
+ eErr = 8;
1598
+ }
1599
+ blob_append_sql(&update, ", semail=%Q", semail);
15841600
}
15851601
blob_append_sql(&update," WHERE subscriberCode=hextoblob(%Q)", zName);
1586
- db_exec_sql(blob_str(&update));
1602
+ if( eErr==0 ){
1603
+ db_exec_sql(blob_str(&update));
1604
+ ssub = 0;
1605
+ }
15871606
blob_reset(&update);
15881607
}
15891608
if( P("delete")!=0 && cgi_csrf_safe(1) ){
15901609
if( !PB("dodelete") ){
15911610
eErr = 9;
@@ -1594,10 +1613,11 @@
15941613
}else{
15951614
alert_unsubscribe(zName);
15961615
return;
15971616
}
15981617
}
1618
+ style_header("Update Subscription");
15991619
db_prepare(&q,
16001620
"SELECT"
16011621
" semail," /* 0 */
16021622
" sverified," /* 1 */
16031623
" sdonotcall," /* 2 */
@@ -1611,23 +1631,26 @@
16111631
if( db_step(&q)!=SQLITE_ROW ){
16121632
db_finalize(&q);
16131633
cgi_redirect("subscribe");
16141634
return;
16151635
}
1616
- style_header("Update Subscription");
1617
- semail = db_column_text(&q, 0);
1618
- sverified = db_column_int(&q, 1);
1619
- sdonotcall = db_column_int(&q, 2);
1620
- sdigest = db_column_int(&q, 3);
1621
- ssub = db_column_text(&q, 4);
1636
+ if( ssub==0 ){
1637
+ semail = db_column_text(&q, 0);
1638
+ sdonotcall = db_column_int(&q, 2);
1639
+ sdigest = db_column_int(&q, 3);
1640
+ ssub = db_column_text(&q, 4);
1641
+ }
1642
+ if( suname==0 ){
1643
+ suname = db_column_text(&q, 6);
1644
+ sverified = db_column_int(&q, 1);
1645
+ }
16221646
sa = strchr(ssub,'a')!=0;
16231647
sc = strchr(ssub,'c')!=0;
16241648
sf = strchr(ssub,'f')!=0;
16251649
st = strchr(ssub,'t')!=0;
16261650
sw = strchr(ssub,'w')!=0;
16271651
smip = db_column_text(&q, 5);
1628
- suname = db_column_text(&q, 6);
16291652
mtime = db_column_text(&q, 7);
16301653
sctime = db_column_text(&q, 8);
16311654
if( !g.perm.Admin && !sverified ){
16321655
db_multi_exec(
16331656
"UPDATE subscriber SET sverified=1 WHERE subscriberCode=hextoblob(%Q)",
@@ -1645,13 +1668,15 @@
16451668
@ <table class="subscribe">
16461669
@ <tr>
16471670
@ <td class="form_label">Email&nbsp;Address:</td>
16481671
if( isLogin ){
16491672
@ <td><input type="text" name="semail" value="%h(semail)" size="30">\
1650
- if( g.perm.Admin ){
1651
- @ &nbsp;&nbsp;<a href="%R/announce?to=%t(semail)">\
1652
- @ (Send a message to %h(semail))</a>\
1673
+ if( eErr==8 ){
1674
+ @ <span class='loginError'>&larr; not a valid email address!</span>
1675
+ }else if( g.perm.Admin ){
1676
+ @ &nbsp;&nbsp;<a href="%R/announce?to=%t(semail)">\
1677
+ @ (Send a message to %h(semail))</a>\
16531678
}
16541679
@ </td>
16551680
}else{
16561681
@ <td>%h(semail)</td>
16571682
}
16581683
--- src/alerts.c
+++ src/alerts.c
@@ -575,22 +575,18 @@
575 }
576 return 0;
577 }
578
579 /*
580 ** Make a copy of the input string up to but not including the
581 ** first cTerm character.
582 **
583 ** Verify that the string really that is to be copied really is a
584 ** valid email address. If it is not, then return NULL.
585 **
586 ** This routine is more restrictive than necessary. It does not
587 ** allow comments, IP address, quoted strings, or certain uncommon
588 ** characters. The only non-alphanumerics allowed in the local
589 ** part are "_", "+", "-" and "+".
590 */
591 char *email_copy_addr(const char *z, char cTerm ){
592 int i;
593 int nAt = 0;
594 int nDot = 0;
595 char c;
596 if( z[0]=='.' ) return 0; /* Local part cannot begin with "." */
@@ -620,13 +616,28 @@
620 }
621 }
622 if( c!=cTerm ) return 0; /* Missing terminator */
623 if( nAt==0 ) return 0; /* No "@" found anywhere */
624 if( nDot==0 ) return 0; /* No "." in the domain */
 
 
625
626 /* If we reach this point, the email address is valid */
627 return mprintf("%.*s", i, z);
 
 
 
 
 
 
 
 
 
 
 
 
 
628 }
629
630 /*
631 ** Scan the input string for a valid email address enclosed in <...>
632 ** If the string contains one or more email addresses, extract the first
@@ -1516,14 +1527,14 @@
1516 const char *zName = P("name");
1517 Stmt q;
1518 int sa, sc, sf, st, sw;
1519 int sdigest, sdonotcall, sverified;
1520 int isLogin; /* Logged in as an individual */
1521 const char *ssub;
1522 const char *semail;
1523 const char *smip;
1524 const char *suname;
1525 const char *mtime;
1526 const char *sctime;
1527 int eErr = 0;
1528 char *zErr = 0;
1529
@@ -1542,22 +1553,24 @@
1542 cgi_redirect("subscribe");
1543 return;
1544 }
1545 alert_submenu_common();
1546 if( P("submit")!=0 && cgi_csrf_safe(1) ){
1547 int sdonotcall = PB("sdonotcall");
1548 int sdigest = PB("sdigest");
1549 const char *zEmail = P("semail");
1550 char ssub[10];
1551 int nsub = 0;
1552 Blob update;
1553 if( PB("sa") ) ssub[nsub++] = 'a';
1554 if( g.perm.Read && PB("sc") ) ssub[nsub++] = 'c';
1555 if( g.perm.RdForum && PB("sf") ) ssub[nsub++] = 'f';
1556 if( g.perm.RdTkt && PB("st") ) ssub[nsub++] = 't';
1557 if( g.perm.RdWiki && PB("sw") ) ssub[nsub++] = 'w';
1558 ssub[nsub] = 0;
 
 
 
 
 
1559 blob_init(&update, "UPDATE subscriber SET", -1);
1560 blob_append_sql(&update,
1561 " sdonotcall=%d,"
1562 " sdigest=%d,"
1563 " ssub=%Q,"
@@ -1567,25 +1580,31 @@
1567 sdigest,
1568 ssub,
1569 g.zIpAddr
1570 );
1571 if( g.perm.Admin ){
1572 const char *suname = PT("suname");
1573 int sverified = PB("sverified");
1574 if( suname && suname[0]==0 ) suname = 0;
1575 blob_append_sql(&update,
1576 ", suname=%Q,"
1577 " sverified=%d",
1578 suname,
1579 sverified
1580 );
1581 }
1582 if( isLogin && zEmail && zEmail[0] ){
1583 blob_append_sql(&update, ", semail=%Q", zEmail);
 
 
 
1584 }
1585 blob_append_sql(&update," WHERE subscriberCode=hextoblob(%Q)", zName);
1586 db_exec_sql(blob_str(&update));
 
 
 
1587 blob_reset(&update);
1588 }
1589 if( P("delete")!=0 && cgi_csrf_safe(1) ){
1590 if( !PB("dodelete") ){
1591 eErr = 9;
@@ -1594,10 +1613,11 @@
1594 }else{
1595 alert_unsubscribe(zName);
1596 return;
1597 }
1598 }
 
1599 db_prepare(&q,
1600 "SELECT"
1601 " semail," /* 0 */
1602 " sverified," /* 1 */
1603 " sdonotcall," /* 2 */
@@ -1611,23 +1631,26 @@
1611 if( db_step(&q)!=SQLITE_ROW ){
1612 db_finalize(&q);
1613 cgi_redirect("subscribe");
1614 return;
1615 }
1616 style_header("Update Subscription");
1617 semail = db_column_text(&q, 0);
1618 sverified = db_column_int(&q, 1);
1619 sdonotcall = db_column_int(&q, 2);
1620 sdigest = db_column_int(&q, 3);
1621 ssub = db_column_text(&q, 4);
 
 
 
 
1622 sa = strchr(ssub,'a')!=0;
1623 sc = strchr(ssub,'c')!=0;
1624 sf = strchr(ssub,'f')!=0;
1625 st = strchr(ssub,'t')!=0;
1626 sw = strchr(ssub,'w')!=0;
1627 smip = db_column_text(&q, 5);
1628 suname = db_column_text(&q, 6);
1629 mtime = db_column_text(&q, 7);
1630 sctime = db_column_text(&q, 8);
1631 if( !g.perm.Admin && !sverified ){
1632 db_multi_exec(
1633 "UPDATE subscriber SET sverified=1 WHERE subscriberCode=hextoblob(%Q)",
@@ -1645,13 +1668,15 @@
1645 @ <table class="subscribe">
1646 @ <tr>
1647 @ <td class="form_label">Email&nbsp;Address:</td>
1648 if( isLogin ){
1649 @ <td><input type="text" name="semail" value="%h(semail)" size="30">\
1650 if( g.perm.Admin ){
1651 @ &nbsp;&nbsp;<a href="%R/announce?to=%t(semail)">\
1652 @ (Send a message to %h(semail))</a>\
 
 
1653 }
1654 @ </td>
1655 }else{
1656 @ <td>%h(semail)</td>
1657 }
1658
--- src/alerts.c
+++ src/alerts.c
@@ -575,22 +575,18 @@
575 }
576 return 0;
577 }
578
579 /*
580 ** Determine whether or not the input string is a valid email address.
581 ** Only look at character up to but not including the first \000 or
582 ** the first cTerm character, whichever comes first.
583 **
584 ** Return the length of the email addresss string in bytes if the email
585 ** address is valid. If the email address is misformed, return 0.
586 */
587 int email_address_is_valid(const char *z, char cTerm){
 
 
 
 
588 int i;
589 int nAt = 0;
590 int nDot = 0;
591 char c;
592 if( z[0]=='.' ) return 0; /* Local part cannot begin with "." */
@@ -620,13 +616,28 @@
616 }
617 }
618 if( c!=cTerm ) return 0; /* Missing terminator */
619 if( nAt==0 ) return 0; /* No "@" found anywhere */
620 if( nDot==0 ) return 0; /* No "." in the domain */
621 return i;
622 }
623
624 /*
625 ** Make a copy of the input string up to but not including the
626 ** first cTerm character.
627 **
628 ** Verify that the string really that is to be copied really is a
629 ** valid email address. If it is not, then return NULL.
630 **
631 ** This routine is more restrictive than necessary. It does not
632 ** allow comments, IP address, quoted strings, or certain uncommon
633 ** characters. The only non-alphanumerics allowed in the local
634 ** part are "_", "+", "-" and "+".
635 */
636 char *email_copy_addr(const char *z, char cTerm ){
637 int i = email_address_is_valid(z, cTerm);
638 return i==0 ? 0 : mprintf("%.*s", i, z);
639 }
640
641 /*
642 ** Scan the input string for a valid email address enclosed in <...>
643 ** If the string contains one or more email addresses, extract the first
@@ -1516,14 +1527,14 @@
1527 const char *zName = P("name");
1528 Stmt q;
1529 int sa, sc, sf, st, sw;
1530 int sdigest, sdonotcall, sverified;
1531 int isLogin; /* Logged in as an individual */
1532 const char *ssub = 0;
1533 const char *semail;
1534 const char *smip;
1535 const char *suname = 0;
1536 const char *mtime;
1537 const char *sctime;
1538 int eErr = 0;
1539 char *zErr = 0;
1540
@@ -1542,22 +1553,24 @@
1553 cgi_redirect("subscribe");
1554 return;
1555 }
1556 alert_submenu_common();
1557 if( P("submit")!=0 && cgi_csrf_safe(1) ){
1558 char newSsub[10];
 
 
 
1559 int nsub = 0;
1560 Blob update;
1561
1562 sdonotcall = PB("sdonotcall");
1563 sdigest = PB("sdigest");
1564 semail = P("semail");
1565 if( PB("sa") ) newSsub[nsub++] = 'a';
1566 if( g.perm.Read && PB("sc") ) newSsub[nsub++] = 'c';
1567 if( g.perm.RdForum && PB("sf") ) newSsub[nsub++] = 'f';
1568 if( g.perm.RdTkt && PB("st") ) newSsub[nsub++] = 't';
1569 if( g.perm.RdWiki && PB("sw") ) newSsub[nsub++] = 'w';
1570 newSsub[nsub] = 0;
1571 ssub = newSsub;
1572 blob_init(&update, "UPDATE subscriber SET", -1);
1573 blob_append_sql(&update,
1574 " sdonotcall=%d,"
1575 " sdigest=%d,"
1576 " ssub=%Q,"
@@ -1567,25 +1580,31 @@
1580 sdigest,
1581 ssub,
1582 g.zIpAddr
1583 );
1584 if( g.perm.Admin ){
1585 suname = PT("suname");
1586 sverified = PB("sverified");
1587 if( suname && suname[0]==0 ) suname = 0;
1588 blob_append_sql(&update,
1589 ", suname=%Q,"
1590 " sverified=%d",
1591 suname,
1592 sverified
1593 );
1594 }
1595 if( isLogin ){
1596 if( semail==0 || email_address_is_valid(semail,0)==0 ){
1597 eErr = 8;
1598 }
1599 blob_append_sql(&update, ", semail=%Q", semail);
1600 }
1601 blob_append_sql(&update," WHERE subscriberCode=hextoblob(%Q)", zName);
1602 if( eErr==0 ){
1603 db_exec_sql(blob_str(&update));
1604 ssub = 0;
1605 }
1606 blob_reset(&update);
1607 }
1608 if( P("delete")!=0 && cgi_csrf_safe(1) ){
1609 if( !PB("dodelete") ){
1610 eErr = 9;
@@ -1594,10 +1613,11 @@
1613 }else{
1614 alert_unsubscribe(zName);
1615 return;
1616 }
1617 }
1618 style_header("Update Subscription");
1619 db_prepare(&q,
1620 "SELECT"
1621 " semail," /* 0 */
1622 " sverified," /* 1 */
1623 " sdonotcall," /* 2 */
@@ -1611,23 +1631,26 @@
1631 if( db_step(&q)!=SQLITE_ROW ){
1632 db_finalize(&q);
1633 cgi_redirect("subscribe");
1634 return;
1635 }
1636 if( ssub==0 ){
1637 semail = db_column_text(&q, 0);
1638 sdonotcall = db_column_int(&q, 2);
1639 sdigest = db_column_int(&q, 3);
1640 ssub = db_column_text(&q, 4);
1641 }
1642 if( suname==0 ){
1643 suname = db_column_text(&q, 6);
1644 sverified = db_column_int(&q, 1);
1645 }
1646 sa = strchr(ssub,'a')!=0;
1647 sc = strchr(ssub,'c')!=0;
1648 sf = strchr(ssub,'f')!=0;
1649 st = strchr(ssub,'t')!=0;
1650 sw = strchr(ssub,'w')!=0;
1651 smip = db_column_text(&q, 5);
 
1652 mtime = db_column_text(&q, 7);
1653 sctime = db_column_text(&q, 8);
1654 if( !g.perm.Admin && !sverified ){
1655 db_multi_exec(
1656 "UPDATE subscriber SET sverified=1 WHERE subscriberCode=hextoblob(%Q)",
@@ -1645,13 +1668,15 @@
1668 @ <table class="subscribe">
1669 @ <tr>
1670 @ <td class="form_label">Email&nbsp;Address:</td>
1671 if( isLogin ){
1672 @ <td><input type="text" name="semail" value="%h(semail)" size="30">\
1673 if( eErr==8 ){
1674 @ <span class='loginError'>&larr; not a valid email address!</span>
1675 }else if( g.perm.Admin ){
1676 @ &nbsp;&nbsp;<a href="%R/announce?to=%t(semail)">\
1677 @ (Send a message to %h(semail))</a>\
1678 }
1679 @ </td>
1680 }else{
1681 @ <td>%h(semail)</td>
1682 }
1683
+1 -1
--- src/login.c
+++ src/login.c
@@ -1544,11 +1544,11 @@
15441544
iErrLine = 2;
15451545
zErr = "Required";
15461546
}else if( zEAddr[0]==0 ){
15471547
iErrLine = 3;
15481548
zErr = "Required";
1549
- }else if( email_copy_addr(zEAddr,0)==0 ){
1549
+ }else if( email_address_is_valid(zEAddr,0)==0 ){
15501550
iErrLine = 3;
15511551
zErr = "Not a valid email address";
15521552
}else if( strlen(zPasswd)<6 ){
15531553
iErrLine = 4;
15541554
zErr = "Password must be at least 6 characters long";
15551555
--- src/login.c
+++ src/login.c
@@ -1544,11 +1544,11 @@
1544 iErrLine = 2;
1545 zErr = "Required";
1546 }else if( zEAddr[0]==0 ){
1547 iErrLine = 3;
1548 zErr = "Required";
1549 }else if( email_copy_addr(zEAddr,0)==0 ){
1550 iErrLine = 3;
1551 zErr = "Not a valid email address";
1552 }else if( strlen(zPasswd)<6 ){
1553 iErrLine = 4;
1554 zErr = "Password must be at least 6 characters long";
1555
--- src/login.c
+++ src/login.c
@@ -1544,11 +1544,11 @@
1544 iErrLine = 2;
1545 zErr = "Required";
1546 }else if( zEAddr[0]==0 ){
1547 iErrLine = 3;
1548 zErr = "Required";
1549 }else if( email_address_is_valid(zEAddr,0)==0 ){
1550 iErrLine = 3;
1551 zErr = "Not a valid email address";
1552 }else if( strlen(zPasswd)<6 ){
1553 iErrLine = 4;
1554 zErr = "Password must be at least 6 characters long";
1555

Keyboard Shortcuts

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