Fossil SCM

Webpages function (with an sensible error) if the email notification tables are not in the schema.

drh 2018-06-23 17:07 trunk
Commit 98d2338a431b95efa2172a214fc802bb5b7ee633bf5ab31ecf197f022274135d
1 file changed +44 -11
+44 -11
--- src/email.c
+++ src/email.c
@@ -29,10 +29,11 @@
2929
/*
3030
** SQL code to implement the tables needed by the email notification
3131
** system.
3232
*/
3333
static const char zEmailInit[] =
34
+@ DROP TABLE IF EXISTS repository.subscriber;
3435
@ -- Subscribers are distinct from users. A person can have a log-in in
3536
@ -- the USER table without being a subscriber. Or a person can be a
3637
@ -- subscriber without having a USER table entry. Or they can have both.
3738
@ -- In the last case the suname column points from the subscriber entry
3839
@ -- to the USER entry.
@@ -61,10 +62,11 @@
6162
@ smip TEXT -- IP address of last change
6263
@ );
6364
@ CREATE INDEX repository.subscriberUname
6465
@ ON subscriber(suname) WHERE suname IS NOT NULL;
6566
@
67
+@ DROP TABLE IF EXISTS repository.pending_alert;
6668
@ -- Email notifications that need to be sent.
6769
@ --
6870
@ -- The first character of the eventid determines the event type.
6971
@ -- Remaining characters determine the specific event. For example,
7072
@ -- 'c4413' means check-in with rid=4413.
@@ -73,10 +75,11 @@
7375
@ eventid TEXT PRIMARY KEY, -- Object that changed
7476
@ sentSep BOOLEAN DEFAULT false, -- individual emails sent
7577
@ sentDigest BOOLEAN DEFAULT false -- digest emails sent
7678
@ ) WITHOUT ROWID;
7779
@
80
+@ DROP TABLE IF EXISTS repository.email_bounce;
7881
@ -- Record bounced emails. If too many bounces are received within
7982
@ -- some defined time range, then cancel the subscription. Older
8083
@ -- entries are periodically purged.
8184
@ --
8285
@ CREATE TABLE repository.email_bounce(
@@ -85,21 +88,36 @@
8588
@ rcvdTime INTEGER -- seconds since 1970 when bounce was received
8689
@ );
8790
;
8891
8992
/*
90
-** Make sure the unversioned table exists in the repository.
93
+** Return true if the email notification tables exist.
94
+*/
95
+int email_tables_exist(void){
96
+ return db_table_exists("repository", "subscriber");
97
+}
98
+
99
+/*
100
+** Make sure the table needed for email notification exist in the repository.
101
+**
102
+** If the bOnlyIfEnabled option is true, then tables are only created
103
+** if the email-send-method is something other than "off".
91104
*/
92
-void email_schema(void){
93
- if( !db_table_exists("repository", "subscriber") ){
105
+void email_schema(int bOnlyIfEnabled){
106
+ if( !email_tables_exist() ){
107
+ if( bOnlyIfEnabled
108
+ && fossil_strcmp(db_get("email-send-method","off"),"off")==0
109
+ ){
110
+ return; /* Don't create table for disabled email */
111
+ }
94112
db_multi_exec(zEmailInit/*works-like:""*/);
95113
email_triggers_enable();
96114
}
97115
}
98116
99117
/*
100
-** Enable triggers that automatically populate the event_pending
118
+** Enable triggers that automatically populate the pending_alert
101119
** table.
102120
*/
103121
void email_triggers_enable(void){
104122
if( !db_table_exists("repository","pending_alert") ) return;
105123
db_multi_exec(
@@ -126,16 +144,28 @@
126144
127145
/*
128146
** Return true if email alerts are active.
129147
*/
130148
int email_enabled(void){
131
- if( !db_table_exists("repository", "subscriber") ) return 0;
149
+ if( !email_tables_exist() ) return 0;
132150
if( fossil_strcmp(db_get("email-send-method","off"),"off")==0 ) return 0;
133151
return 1;
134152
}
135153
136
-
154
+/*
155
+** If the subscriber table does not exist, then paint an error message
156
+** web page and return true.
157
+**
158
+** If the subscriber table does exist, return 0 without doing anything.
159
+*/
160
+static int email_webpages_disabled(void){
161
+ if( email_tables_exist() ) return 0;
162
+ style_header("Email Alerts Are Disabled");
163
+ @ <p>Email alerts are disabled on this server</p>
164
+ style_footer();
165
+ return 1;
166
+}
137167
138168
/*
139169
** Insert a "Subscriber List" submenu link if the current user
140170
** is an administrator.
141171
*/
@@ -208,11 +238,11 @@
208238
"off", count(azSendMethods)/2, azSendMethods);
209239
@ <p>How to send email. The "Pipe to a command"
210240
@ method is the usual choice in production.
211241
@ (Property: "email-send-method")</p>
212242
@ <hr>
213
-
243
+ email_schema(1);
214244
215245
entry_attribute("Command To Pipe Email To", 80, "email-send-command",
216246
"ecmd", "sendmail -t", 0);
217247
@ <p>When the send method is "pipe to a command", this is the command
218248
@ that is run. Email messages are piped into the standard input of this
@@ -579,11 +609,11 @@
579609
*/
580610
void email_cmd(void){
581611
const char *zCmd;
582612
int nCmd;
583613
db_find_and_open_repository(0, 0);
584
- email_schema();
614
+ email_schema(0);
585615
zCmd = g.argc>=3 ? g.argv[2] : "x";
586616
nCmd = (int)strlen(zCmd);
587617
if( strncmp(zCmd, "exec", nCmd)==0 ){
588618
u32 eFlags = 0;
589619
if( find_option("digest",0,0)!=0 ) eFlags |= SENDALERT_DIGEST;
@@ -632,11 +662,11 @@
632662
"DROP TABLE IF EXISTS email_bounce;\n"
633663
/* Legacy */
634664
"DROP TABLE IF EXISTS email_pending;\n"
635665
"DROP TABLE IF EXISTS subscription;\n"
636666
);
637
- email_schema();
667
+ email_schema(0);
638668
}
639669
}else
640670
if( strncmp(zCmd, "send", nCmd)==0 ){
641671
Blob prompt, body, hdr;
642672
const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0;
@@ -835,10 +865,11 @@
835865
const char *zDecoded;
836866
char *zCaptcha = 0;
837867
char *zErr = 0;
838868
int eErr = 0;
839869
870
+ if( email_webpages_disabled() ) return;
840871
login_check_credentials();
841872
if( !g.perm.EmailAlert ){
842873
login_needed(g.anon.EmailAlert);
843874
return;
844875
}
@@ -1059,10 +1090,11 @@
10591090
const char *smip;
10601091
const char *suname;
10611092
int eErr = 0;
10621093
char *zErr = 0;
10631094
1095
+ if( email_webpages_disabled() ) return;
10641096
login_check_credentials();
10651097
if( !g.perm.EmailAlert ){
10661098
cgi_redirect("subscribe");
10671099
return;
10681100
}
@@ -1392,10 +1424,11 @@
13921424
** modified.
13931425
*/
13941426
void subscriber_list_page(void){
13951427
Blob sql;
13961428
Stmt q;
1429
+ if( email_webpages_disabled() ) return;
13971430
login_check_credentials();
13981431
if( !g.perm.Admin ){
13991432
fossil_redirect_home();
14001433
return;
14011434
}
@@ -1564,11 +1597,11 @@
15641597
EmailEvent *pEvent, *p;
15651598
15661599
db_find_and_open_repository(0, 0);
15671600
verify_all_options();
15681601
db_begin_transaction();
1569
- email_schema();
1602
+ email_schema(0);
15701603
db_multi_exec("CREATE TEMP TABLE wantalert(eventid TEXT)");
15711604
if( g.argc==2 ){
15721605
db_multi_exec("INSERT INTO wantalert SELECT eventid FROM pending_alert");
15731606
}else{
15741607
int i;
@@ -1607,11 +1640,11 @@
16071640
void test_add_alert_cmd(void){
16081641
int i;
16091642
db_find_and_open_repository(0, 0);
16101643
verify_all_options();
16111644
db_begin_transaction();
1612
- email_schema();
1645
+ email_schema(0);
16131646
for(i=2; i<g.argc; i++){
16141647
db_multi_exec("REPLACE INTO pending_alert(eventId) VALUES(%Q)", g.argv[i]);
16151648
}
16161649
db_end_transaction(0);
16171650
}
16181651
--- src/email.c
+++ src/email.c
@@ -29,10 +29,11 @@
29 /*
30 ** SQL code to implement the tables needed by the email notification
31 ** system.
32 */
33 static const char zEmailInit[] =
 
34 @ -- Subscribers are distinct from users. A person can have a log-in in
35 @ -- the USER table without being a subscriber. Or a person can be a
36 @ -- subscriber without having a USER table entry. Or they can have both.
37 @ -- In the last case the suname column points from the subscriber entry
38 @ -- to the USER entry.
@@ -61,10 +62,11 @@
61 @ smip TEXT -- IP address of last change
62 @ );
63 @ CREATE INDEX repository.subscriberUname
64 @ ON subscriber(suname) WHERE suname IS NOT NULL;
65 @
 
66 @ -- Email notifications that need to be sent.
67 @ --
68 @ -- The first character of the eventid determines the event type.
69 @ -- Remaining characters determine the specific event. For example,
70 @ -- 'c4413' means check-in with rid=4413.
@@ -73,10 +75,11 @@
73 @ eventid TEXT PRIMARY KEY, -- Object that changed
74 @ sentSep BOOLEAN DEFAULT false, -- individual emails sent
75 @ sentDigest BOOLEAN DEFAULT false -- digest emails sent
76 @ ) WITHOUT ROWID;
77 @
 
78 @ -- Record bounced emails. If too many bounces are received within
79 @ -- some defined time range, then cancel the subscription. Older
80 @ -- entries are periodically purged.
81 @ --
82 @ CREATE TABLE repository.email_bounce(
@@ -85,21 +88,36 @@
85 @ rcvdTime INTEGER -- seconds since 1970 when bounce was received
86 @ );
87 ;
88
89 /*
90 ** Make sure the unversioned table exists in the repository.
 
 
 
 
 
 
 
 
 
 
91 */
92 void email_schema(void){
93 if( !db_table_exists("repository", "subscriber") ){
 
 
 
 
 
94 db_multi_exec(zEmailInit/*works-like:""*/);
95 email_triggers_enable();
96 }
97 }
98
99 /*
100 ** Enable triggers that automatically populate the event_pending
101 ** table.
102 */
103 void email_triggers_enable(void){
104 if( !db_table_exists("repository","pending_alert") ) return;
105 db_multi_exec(
@@ -126,16 +144,28 @@
126
127 /*
128 ** Return true if email alerts are active.
129 */
130 int email_enabled(void){
131 if( !db_table_exists("repository", "subscriber") ) return 0;
132 if( fossil_strcmp(db_get("email-send-method","off"),"off")==0 ) return 0;
133 return 1;
134 }
135
136
 
 
 
 
 
 
 
 
 
 
 
 
137
138 /*
139 ** Insert a "Subscriber List" submenu link if the current user
140 ** is an administrator.
141 */
@@ -208,11 +238,11 @@
208 "off", count(azSendMethods)/2, azSendMethods);
209 @ <p>How to send email. The "Pipe to a command"
210 @ method is the usual choice in production.
211 @ (Property: "email-send-method")</p>
212 @ <hr>
213
214
215 entry_attribute("Command To Pipe Email To", 80, "email-send-command",
216 "ecmd", "sendmail -t", 0);
217 @ <p>When the send method is "pipe to a command", this is the command
218 @ that is run. Email messages are piped into the standard input of this
@@ -579,11 +609,11 @@
579 */
580 void email_cmd(void){
581 const char *zCmd;
582 int nCmd;
583 db_find_and_open_repository(0, 0);
584 email_schema();
585 zCmd = g.argc>=3 ? g.argv[2] : "x";
586 nCmd = (int)strlen(zCmd);
587 if( strncmp(zCmd, "exec", nCmd)==0 ){
588 u32 eFlags = 0;
589 if( find_option("digest",0,0)!=0 ) eFlags |= SENDALERT_DIGEST;
@@ -632,11 +662,11 @@
632 "DROP TABLE IF EXISTS email_bounce;\n"
633 /* Legacy */
634 "DROP TABLE IF EXISTS email_pending;\n"
635 "DROP TABLE IF EXISTS subscription;\n"
636 );
637 email_schema();
638 }
639 }else
640 if( strncmp(zCmd, "send", nCmd)==0 ){
641 Blob prompt, body, hdr;
642 const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0;
@@ -835,10 +865,11 @@
835 const char *zDecoded;
836 char *zCaptcha = 0;
837 char *zErr = 0;
838 int eErr = 0;
839
 
840 login_check_credentials();
841 if( !g.perm.EmailAlert ){
842 login_needed(g.anon.EmailAlert);
843 return;
844 }
@@ -1059,10 +1090,11 @@
1059 const char *smip;
1060 const char *suname;
1061 int eErr = 0;
1062 char *zErr = 0;
1063
 
1064 login_check_credentials();
1065 if( !g.perm.EmailAlert ){
1066 cgi_redirect("subscribe");
1067 return;
1068 }
@@ -1392,10 +1424,11 @@
1392 ** modified.
1393 */
1394 void subscriber_list_page(void){
1395 Blob sql;
1396 Stmt q;
 
1397 login_check_credentials();
1398 if( !g.perm.Admin ){
1399 fossil_redirect_home();
1400 return;
1401 }
@@ -1564,11 +1597,11 @@
1564 EmailEvent *pEvent, *p;
1565
1566 db_find_and_open_repository(0, 0);
1567 verify_all_options();
1568 db_begin_transaction();
1569 email_schema();
1570 db_multi_exec("CREATE TEMP TABLE wantalert(eventid TEXT)");
1571 if( g.argc==2 ){
1572 db_multi_exec("INSERT INTO wantalert SELECT eventid FROM pending_alert");
1573 }else{
1574 int i;
@@ -1607,11 +1640,11 @@
1607 void test_add_alert_cmd(void){
1608 int i;
1609 db_find_and_open_repository(0, 0);
1610 verify_all_options();
1611 db_begin_transaction();
1612 email_schema();
1613 for(i=2; i<g.argc; i++){
1614 db_multi_exec("REPLACE INTO pending_alert(eventId) VALUES(%Q)", g.argv[i]);
1615 }
1616 db_end_transaction(0);
1617 }
1618
--- src/email.c
+++ src/email.c
@@ -29,10 +29,11 @@
29 /*
30 ** SQL code to implement the tables needed by the email notification
31 ** system.
32 */
33 static const char zEmailInit[] =
34 @ DROP TABLE IF EXISTS repository.subscriber;
35 @ -- Subscribers are distinct from users. A person can have a log-in in
36 @ -- the USER table without being a subscriber. Or a person can be a
37 @ -- subscriber without having a USER table entry. Or they can have both.
38 @ -- In the last case the suname column points from the subscriber entry
39 @ -- to the USER entry.
@@ -61,10 +62,11 @@
62 @ smip TEXT -- IP address of last change
63 @ );
64 @ CREATE INDEX repository.subscriberUname
65 @ ON subscriber(suname) WHERE suname IS NOT NULL;
66 @
67 @ DROP TABLE IF EXISTS repository.pending_alert;
68 @ -- Email notifications that need to be sent.
69 @ --
70 @ -- The first character of the eventid determines the event type.
71 @ -- Remaining characters determine the specific event. For example,
72 @ -- 'c4413' means check-in with rid=4413.
@@ -73,10 +75,11 @@
75 @ eventid TEXT PRIMARY KEY, -- Object that changed
76 @ sentSep BOOLEAN DEFAULT false, -- individual emails sent
77 @ sentDigest BOOLEAN DEFAULT false -- digest emails sent
78 @ ) WITHOUT ROWID;
79 @
80 @ DROP TABLE IF EXISTS repository.email_bounce;
81 @ -- Record bounced emails. If too many bounces are received within
82 @ -- some defined time range, then cancel the subscription. Older
83 @ -- entries are periodically purged.
84 @ --
85 @ CREATE TABLE repository.email_bounce(
@@ -85,21 +88,36 @@
88 @ rcvdTime INTEGER -- seconds since 1970 when bounce was received
89 @ );
90 ;
91
92 /*
93 ** Return true if the email notification tables exist.
94 */
95 int email_tables_exist(void){
96 return db_table_exists("repository", "subscriber");
97 }
98
99 /*
100 ** Make sure the table needed for email notification exist in the repository.
101 **
102 ** If the bOnlyIfEnabled option is true, then tables are only created
103 ** if the email-send-method is something other than "off".
104 */
105 void email_schema(int bOnlyIfEnabled){
106 if( !email_tables_exist() ){
107 if( bOnlyIfEnabled
108 && fossil_strcmp(db_get("email-send-method","off"),"off")==0
109 ){
110 return; /* Don't create table for disabled email */
111 }
112 db_multi_exec(zEmailInit/*works-like:""*/);
113 email_triggers_enable();
114 }
115 }
116
117 /*
118 ** Enable triggers that automatically populate the pending_alert
119 ** table.
120 */
121 void email_triggers_enable(void){
122 if( !db_table_exists("repository","pending_alert") ) return;
123 db_multi_exec(
@@ -126,16 +144,28 @@
144
145 /*
146 ** Return true if email alerts are active.
147 */
148 int email_enabled(void){
149 if( !email_tables_exist() ) return 0;
150 if( fossil_strcmp(db_get("email-send-method","off"),"off")==0 ) return 0;
151 return 1;
152 }
153
154 /*
155 ** If the subscriber table does not exist, then paint an error message
156 ** web page and return true.
157 **
158 ** If the subscriber table does exist, return 0 without doing anything.
159 */
160 static int email_webpages_disabled(void){
161 if( email_tables_exist() ) return 0;
162 style_header("Email Alerts Are Disabled");
163 @ <p>Email alerts are disabled on this server</p>
164 style_footer();
165 return 1;
166 }
167
168 /*
169 ** Insert a "Subscriber List" submenu link if the current user
170 ** is an administrator.
171 */
@@ -208,11 +238,11 @@
238 "off", count(azSendMethods)/2, azSendMethods);
239 @ <p>How to send email. The "Pipe to a command"
240 @ method is the usual choice in production.
241 @ (Property: "email-send-method")</p>
242 @ <hr>
243 email_schema(1);
244
245 entry_attribute("Command To Pipe Email To", 80, "email-send-command",
246 "ecmd", "sendmail -t", 0);
247 @ <p>When the send method is "pipe to a command", this is the command
248 @ that is run. Email messages are piped into the standard input of this
@@ -579,11 +609,11 @@
609 */
610 void email_cmd(void){
611 const char *zCmd;
612 int nCmd;
613 db_find_and_open_repository(0, 0);
614 email_schema(0);
615 zCmd = g.argc>=3 ? g.argv[2] : "x";
616 nCmd = (int)strlen(zCmd);
617 if( strncmp(zCmd, "exec", nCmd)==0 ){
618 u32 eFlags = 0;
619 if( find_option("digest",0,0)!=0 ) eFlags |= SENDALERT_DIGEST;
@@ -632,11 +662,11 @@
662 "DROP TABLE IF EXISTS email_bounce;\n"
663 /* Legacy */
664 "DROP TABLE IF EXISTS email_pending;\n"
665 "DROP TABLE IF EXISTS subscription;\n"
666 );
667 email_schema(0);
668 }
669 }else
670 if( strncmp(zCmd, "send", nCmd)==0 ){
671 Blob prompt, body, hdr;
672 const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0;
@@ -835,10 +865,11 @@
865 const char *zDecoded;
866 char *zCaptcha = 0;
867 char *zErr = 0;
868 int eErr = 0;
869
870 if( email_webpages_disabled() ) return;
871 login_check_credentials();
872 if( !g.perm.EmailAlert ){
873 login_needed(g.anon.EmailAlert);
874 return;
875 }
@@ -1059,10 +1090,11 @@
1090 const char *smip;
1091 const char *suname;
1092 int eErr = 0;
1093 char *zErr = 0;
1094
1095 if( email_webpages_disabled() ) return;
1096 login_check_credentials();
1097 if( !g.perm.EmailAlert ){
1098 cgi_redirect("subscribe");
1099 return;
1100 }
@@ -1392,10 +1424,11 @@
1424 ** modified.
1425 */
1426 void subscriber_list_page(void){
1427 Blob sql;
1428 Stmt q;
1429 if( email_webpages_disabled() ) return;
1430 login_check_credentials();
1431 if( !g.perm.Admin ){
1432 fossil_redirect_home();
1433 return;
1434 }
@@ -1564,11 +1597,11 @@
1597 EmailEvent *pEvent, *p;
1598
1599 db_find_and_open_repository(0, 0);
1600 verify_all_options();
1601 db_begin_transaction();
1602 email_schema(0);
1603 db_multi_exec("CREATE TEMP TABLE wantalert(eventid TEXT)");
1604 if( g.argc==2 ){
1605 db_multi_exec("INSERT INTO wantalert SELECT eventid FROM pending_alert");
1606 }else{
1607 int i;
@@ -1607,11 +1640,11 @@
1640 void test_add_alert_cmd(void){
1641 int i;
1642 db_find_and_open_repository(0, 0);
1643 verify_all_options();
1644 db_begin_transaction();
1645 email_schema(0);
1646 for(i=2; i<g.argc; i++){
1647 db_multi_exec("REPLACE INTO pending_alert(eventId) VALUES(%Q)", g.argv[i]);
1648 }
1649 db_end_transaction(0);
1650 }
1651

Keyboard Shortcuts

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