Fossil SCM

Initial implementation of the /announce webpage.

drh 2018-06-26 01:24 trunk
Commit 65f57546110b186d016ff1567d460a719e9e3490cd1a61979ee9e97b414913cf
+2 -2
--- src/blob.c
+++ src/blob.c
@@ -484,12 +484,12 @@
484484
}
485485
486486
/*
487487
** Truncate a blob back to zero length
488488
*/
489
-void blob_truncate(Blob *p){
490
- p->nUsed = 0;
489
+void blob_truncate(Blob *p, int sz){
490
+ if( sz>=0 && sz<p->nUsed ) p->nUsed = sz;
491491
}
492492
493493
/*
494494
** Seek the cursor in a blob to the indicated offset.
495495
*/
496496
--- src/blob.c
+++ src/blob.c
@@ -484,12 +484,12 @@
484 }
485
486 /*
487 ** Truncate a blob back to zero length
488 */
489 void blob_truncate(Blob *p){
490 p->nUsed = 0;
491 }
492
493 /*
494 ** Seek the cursor in a blob to the indicated offset.
495 */
496
--- src/blob.c
+++ src/blob.c
@@ -484,12 +484,12 @@
484 }
485
486 /*
487 ** Truncate a blob back to zero length
488 */
489 void blob_truncate(Blob *p, int sz){
490 if( sz>=0 && sz<p->nUsed ) p->nUsed = sz;
491 }
492
493 /*
494 ** Seek the cursor in a blob to the indicated offset.
495 */
496
+156 -12
--- src/email.c
+++ src/email.c
@@ -337,10 +337,11 @@
337337
const char *zDest; /* How to send email. */
338338
const char *zDb; /* Name of database file */
339339
const char *zDir; /* Directory in which to store as email files */
340340
const char *zCmd; /* Command to run for each email */
341341
const char *zFrom; /* Emails come from here */
342
+ Blob out; /* For zDest=="blob" */
342343
char *zErr; /* Error message */
343344
int bImmediateFail; /* On any error, call fossil_fatal() */
344345
};
345346
#endif /* INTERFACE */
346347
@@ -354,10 +355,11 @@
354355
p->db = 0;
355356
p->zDb = 0;
356357
p->zDir = 0;
357358
p->zCmd = 0;
358359
p->zDest = "off";
360
+ blob_zero(&p->out);
359361
}
360362
361363
/*
362364
** Put the EmailSender into an error state.
363365
*/
@@ -454,10 +456,12 @@
454456
}
455457
}else if( fossil_strcmp(p->zDest, "pipe")==0 ){
456458
emailerGetSetting(p, &p->zCmd, "email-send-command");
457459
}else if( fossil_strcmp(p->zDest, "dir")==0 ){
458460
emailerGetSetting(p, &p->zDir, "email-send-dir");
461
+ }else if( fossil_strcmp(p->zDest, "blob")==0 ){
462
+ blob_init(&p->out, 0, 0);
459463
}
460464
return p;
461465
}
462466
463467
/*
@@ -477,21 +481,29 @@
477481
** The caller maintains ownership of the input Blobs. This routine will
478482
** read the Blobs and send them onward to the email system, but it will
479483
** not free them.
480484
*/
481485
void email_send(EmailSender *p, Blob *pHdr, Blob *pBody){
482
- Blob all;
486
+ Blob all, *pOut;
483487
if( fossil_strcmp(p->zDest, "off")==0 ){
484488
return;
485489
}
486
- blob_init(&all, 0, 0);
487
- blob_append(&all, blob_buffer(pHdr), blob_size(pHdr));
488
- blob_appendf(&all, "From: %s\r\n", p->zFrom);
490
+ if( fossil_strcmp(p->zDest, "blob")==0 ){
491
+ pOut = &p->out;
492
+ if( blob_size(pOut) ){
493
+ blob_appendf(pOut, "%.72c\n", '=');
494
+ }
495
+ }else{
496
+ blob_init(&all, 0, 0);
497
+ pOut = &all;
498
+ }
499
+ blob_append(pOut, blob_buffer(pHdr), blob_size(pHdr));
500
+ blob_appendf(pOut, "From: %s\r\n", p->zFrom);
489501
blob_add_final_newline(pBody);
490
- blob_appendf(&all,"Content-Type: text/plain\r\n");
491
- blob_appendf(&all, "Content-Transfer-Encoding: base64\r\n\r\n");
492
- append_base64(&all, pBody);
502
+ blob_appendf(pOut,"Content-Type: text/plain\r\n");
503
+ blob_appendf(pOut, "Content-Transfer-Encoding: base64\r\n\r\n");
504
+ append_base64(pOut, pBody);
493505
if( p->pStmt ){
494506
int i, rc;
495507
sqlite3_bind_text(p->pStmt, 1, blob_str(&all), -1, SQLITE_TRANSIENT);
496508
for(i=0; i<100 && sqlite3_step(p->pStmt)==SQLITE_BUSY; i++){
497509
sqlite3_sleep(10);
@@ -1762,12 +1774,12 @@
17621774
}
17631775
if( nHit==0 ) continue;
17641776
blob_appendf(&body,"\n%.72c\nSubscription info: %s/alerts/%s\n",
17651777
'-', zUrl, zCode);
17661778
email_send(pSender,&hdr,&body);
1767
- blob_truncate(&hdr);
1768
- blob_truncate(&body);
1779
+ blob_truncate(&hdr, 0);
1780
+ blob_truncate(&body, 0);
17691781
}
17701782
blob_zero(&hdr);
17711783
blob_zero(&body);
17721784
db_finalize(&q);
17731785
email_free_eventlist(pEvents);
@@ -1816,15 +1828,15 @@
18161828
autoexec_done:
18171829
db_end_transaction(0);
18181830
}
18191831
18201832
/*
1821
-** WEBPAGE: msgadmin
1833
+** WEBPAGE: msgtoadmin
18221834
**
18231835
** A web-form to send a message to the repository administrator.
18241836
*/
1825
-void msgadmin_page(void){
1837
+void msgtoadmin_page(void){
18261838
const char *zAdminEmail = db_get("email-admin",0);
18271839
unsigned int uSeed;
18281840
const char *zDecoded;
18291841
char *zCaptcha = 0;
18301842
@@ -1871,11 +1883,11 @@
18711883
uSeed = captcha_seed();
18721884
zDecoded = captcha_decode(uSeed);
18731885
zCaptcha = captcha_render(zDecoded);
18741886
}
18751887
style_header("Message To Administrator");
1876
- form_begin(0, "%R/msgadmin");
1888
+ form_begin(0, "%R/msgtoadmin");
18771889
@ <p>Enter a message to the repository administrator below:</p>
18781890
@ <table class="subscribe">
18791891
if( zCaptcha ){
18801892
@ <tr>
18811893
@ <td class="form_label">Security&nbsp;Code:</td>
@@ -1907,8 +1919,140 @@
19071919
@ %h(zCaptcha)
19081920
@ </pre>
19091921
@ Enter the 8 characters above in the "Security Code" box
19101922
@ </td></tr></table></div>
19111923
}
1924
+ @ </form>
1925
+ style_footer();
1926
+}
1927
+
1928
+/*
1929
+** Send an annoucement message described by query parameter.
1930
+** Permission to do this has already been verified.
1931
+*/
1932
+static char *email_send_announcement(void){
1933
+ EmailSender *pSender;
1934
+ char *zErr;
1935
+ const char *zTo = PT("to");
1936
+ char *zSubject = PT("subject");
1937
+ int bAll = PB("all");
1938
+ int bAA = PB("aa");
1939
+ const char *zSub = db_get("email-subname", "[Fossil Repo]");
1940
+ int bTest2 = fossil_strcmp(P("name"),"test2")==0;
1941
+ Blob hdr, body;
1942
+ blob_init(&body, 0, 0);
1943
+ blob_init(&hdr, 0, 0);
1944
+ blob_appendf(&body, "%s", PT("msg")/*safe-for-%s*/);
1945
+ pSender = email_sender_new(bTest2 ? "blob" : 0, 0);
1946
+ if( zTo[0] ){
1947
+ blob_appendf(&hdr, "To: %s\nSubject: %s %s\n", zTo, zSub, zSubject);
1948
+ email_send(pSender, &hdr, &body);
1949
+ }
1950
+ if( bAll || bAA ){
1951
+ Stmt q;
1952
+ int nUsed = blob_size(&body);
1953
+ const char *zURL = db_get("email-url",0);
1954
+ db_prepare(&q, "SELECT semail, subscriberCode FROM subscriber "
1955
+ " WHERE sverified AND NOT sdonotcall %s",
1956
+ bAll ? "" : " AND ssub LIKE '%a%'");
1957
+ while( db_step(&q)==SQLITE_ROW ){
1958
+ const char *zCode = db_column_text(&q, 1);
1959
+ zTo = db_column_text(&q, 0);
1960
+ blob_truncate(&hdr, 0);
1961
+ blob_appendf(&hdr, "To: %s\nSubject: %s %s\n", zTo, zSub, zSubject);
1962
+ if( zURL ){
1963
+ blob_truncate(&body, nUsed);
1964
+ blob_appendf(&body,"\n%.72c\nSubscription info: %s/alerts/%s\n",
1965
+ '-', zURL, zCode);
1966
+ }
1967
+ email_send(pSender, &hdr, &body);
1968
+ }
1969
+ db_finalize(&q);
1970
+ }
1971
+ if( bTest2 ){
1972
+ /* If the URL is /announce/test2 instead of just /announce, then no
1973
+ ** email is actually sent. Instead, the text of the email that would
1974
+ ** have been sent is displayed in the result window. */
1975
+ @ <pre style='border: 2px solid blue; padding: 1ex'>
1976
+ @ %h(blob_str(&pSender->out))
1977
+ @ </pre>
1978
+ }
1979
+ zErr = pSender->zErr;
1980
+ pSender->zErr = 0;
1981
+ email_sender_free(pSender);
1982
+ return zErr;
1983
+}
1984
+
1985
+
1986
+/*
1987
+** WEBPAGE: announce
1988
+**
1989
+** A web-form, available to users with the "Send-Announcement" or "A"
1990
+** capability, that allows one to to send an announcements to whomever
1991
+** has subscribed to them. The administrator can also send an announcement
1992
+** to the entire mailing list (including people who have elected to
1993
+** receive no announcements or notifications of any kind, or to
1994
+** individual email to anyone.
1995
+*/
1996
+void announce_page(void){
1997
+ const char *zTo = PT("to");
1998
+ login_check_credentials();
1999
+ if( !g.perm.Announce ){
2000
+ login_needed(0);
2001
+ return;
2002
+ }
2003
+ if( fossil_strcmp(P("name"),"test1")==0 ){
2004
+ /* Visit the /announce/test1 page to see the CGI variables */
2005
+ @ <p style='border: 1px solid black; padding: 1ex;'>
2006
+ cgi_print_all(0, 0);
2007
+ @ </p>
2008
+ }else
2009
+ if( P("submit")!=0 && cgi_csrf_safe(1) ){
2010
+ char *zErr = email_send_announcement();
2011
+ style_header("Announcement Sent");
2012
+ if( zErr ){
2013
+ @ <h1>Internal Error</h1>
2014
+ @ <p>The following error was reported by the system:
2015
+ @ <blockquote><pre>
2016
+ @ %h(zErr)
2017
+ @ </pre></blockquote>
2018
+ }else{
2019
+ @ <p>The announcement has been sent.</p>
2020
+ }
2021
+ style_footer();
2022
+ return;
2023
+ }
2024
+ style_header("Send Announcement");
2025
+ @ <form method="POST">
2026
+ @ <table class="subscribe">
2027
+ if( g.perm.Admin ){
2028
+ int aa = PB("aa");
2029
+ int all = PB("all");
2030
+ const char *aack = aa ? "checked" : "";
2031
+ const char *allck = all ? "checked" : "";
2032
+ @ <tr>
2033
+ @ <td class="form_label">To:</td>
2034
+ @ <td><input type="text" name="to" value="%h(PT("to"))" size="30"><br>
2035
+ @ <label><input type="checkbox" name="aa" %s(aack)> \
2036
+ @ All "announcement" subscribers</label><br>
2037
+ @ <label><input type="checkbox" name="all" %s(allck)> \
2038
+ @ All subscribers</label></td>
2039
+ @ </tr>
2040
+ }
2041
+ @ <tr>
2042
+ @ <td class="form_label">Subject:</td>
2043
+ @ <td><input type="text" name="subject" value="%h(PT("subject"))"\
2044
+ @ size="80"></td>
2045
+ @ </tr>
2046
+ @ <tr>
2047
+ @ <td class="form_label">Message:</td>
2048
+ @ <td><textarea name="msg" cols="80" rows="10" wrap="virtual">\
2049
+ @ %h(PT("msg"))</textarea>
2050
+ @ </tr>
2051
+ @ <tr>
2052
+ @ <td></td>
2053
+ @ <td><input type="submit" name="submit" value="Send Message">
2054
+ @ </tr>
2055
+ @ </table>
19122056
@ </form>
19132057
style_footer();
19142058
}
19152059
--- src/email.c
+++ src/email.c
@@ -337,10 +337,11 @@
337 const char *zDest; /* How to send email. */
338 const char *zDb; /* Name of database file */
339 const char *zDir; /* Directory in which to store as email files */
340 const char *zCmd; /* Command to run for each email */
341 const char *zFrom; /* Emails come from here */
 
342 char *zErr; /* Error message */
343 int bImmediateFail; /* On any error, call fossil_fatal() */
344 };
345 #endif /* INTERFACE */
346
@@ -354,10 +355,11 @@
354 p->db = 0;
355 p->zDb = 0;
356 p->zDir = 0;
357 p->zCmd = 0;
358 p->zDest = "off";
 
359 }
360
361 /*
362 ** Put the EmailSender into an error state.
363 */
@@ -454,10 +456,12 @@
454 }
455 }else if( fossil_strcmp(p->zDest, "pipe")==0 ){
456 emailerGetSetting(p, &p->zCmd, "email-send-command");
457 }else if( fossil_strcmp(p->zDest, "dir")==0 ){
458 emailerGetSetting(p, &p->zDir, "email-send-dir");
 
 
459 }
460 return p;
461 }
462
463 /*
@@ -477,21 +481,29 @@
477 ** The caller maintains ownership of the input Blobs. This routine will
478 ** read the Blobs and send them onward to the email system, but it will
479 ** not free them.
480 */
481 void email_send(EmailSender *p, Blob *pHdr, Blob *pBody){
482 Blob all;
483 if( fossil_strcmp(p->zDest, "off")==0 ){
484 return;
485 }
486 blob_init(&all, 0, 0);
487 blob_append(&all, blob_buffer(pHdr), blob_size(pHdr));
488 blob_appendf(&all, "From: %s\r\n", p->zFrom);
 
 
 
 
 
 
 
 
489 blob_add_final_newline(pBody);
490 blob_appendf(&all,"Content-Type: text/plain\r\n");
491 blob_appendf(&all, "Content-Transfer-Encoding: base64\r\n\r\n");
492 append_base64(&all, pBody);
493 if( p->pStmt ){
494 int i, rc;
495 sqlite3_bind_text(p->pStmt, 1, blob_str(&all), -1, SQLITE_TRANSIENT);
496 for(i=0; i<100 && sqlite3_step(p->pStmt)==SQLITE_BUSY; i++){
497 sqlite3_sleep(10);
@@ -1762,12 +1774,12 @@
1762 }
1763 if( nHit==0 ) continue;
1764 blob_appendf(&body,"\n%.72c\nSubscription info: %s/alerts/%s\n",
1765 '-', zUrl, zCode);
1766 email_send(pSender,&hdr,&body);
1767 blob_truncate(&hdr);
1768 blob_truncate(&body);
1769 }
1770 blob_zero(&hdr);
1771 blob_zero(&body);
1772 db_finalize(&q);
1773 email_free_eventlist(pEvents);
@@ -1816,15 +1828,15 @@
1816 autoexec_done:
1817 db_end_transaction(0);
1818 }
1819
1820 /*
1821 ** WEBPAGE: msgadmin
1822 **
1823 ** A web-form to send a message to the repository administrator.
1824 */
1825 void msgadmin_page(void){
1826 const char *zAdminEmail = db_get("email-admin",0);
1827 unsigned int uSeed;
1828 const char *zDecoded;
1829 char *zCaptcha = 0;
1830
@@ -1871,11 +1883,11 @@
1871 uSeed = captcha_seed();
1872 zDecoded = captcha_decode(uSeed);
1873 zCaptcha = captcha_render(zDecoded);
1874 }
1875 style_header("Message To Administrator");
1876 form_begin(0, "%R/msgadmin");
1877 @ <p>Enter a message to the repository administrator below:</p>
1878 @ <table class="subscribe">
1879 if( zCaptcha ){
1880 @ <tr>
1881 @ <td class="form_label">Security&nbsp;Code:</td>
@@ -1907,8 +1919,140 @@
1907 @ %h(zCaptcha)
1908 @ </pre>
1909 @ Enter the 8 characters above in the "Security Code" box
1910 @ </td></tr></table></div>
1911 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1912 @ </form>
1913 style_footer();
1914 }
1915
--- src/email.c
+++ src/email.c
@@ -337,10 +337,11 @@
337 const char *zDest; /* How to send email. */
338 const char *zDb; /* Name of database file */
339 const char *zDir; /* Directory in which to store as email files */
340 const char *zCmd; /* Command to run for each email */
341 const char *zFrom; /* Emails come from here */
342 Blob out; /* For zDest=="blob" */
343 char *zErr; /* Error message */
344 int bImmediateFail; /* On any error, call fossil_fatal() */
345 };
346 #endif /* INTERFACE */
347
@@ -354,10 +355,11 @@
355 p->db = 0;
356 p->zDb = 0;
357 p->zDir = 0;
358 p->zCmd = 0;
359 p->zDest = "off";
360 blob_zero(&p->out);
361 }
362
363 /*
364 ** Put the EmailSender into an error state.
365 */
@@ -454,10 +456,12 @@
456 }
457 }else if( fossil_strcmp(p->zDest, "pipe")==0 ){
458 emailerGetSetting(p, &p->zCmd, "email-send-command");
459 }else if( fossil_strcmp(p->zDest, "dir")==0 ){
460 emailerGetSetting(p, &p->zDir, "email-send-dir");
461 }else if( fossil_strcmp(p->zDest, "blob")==0 ){
462 blob_init(&p->out, 0, 0);
463 }
464 return p;
465 }
466
467 /*
@@ -477,21 +481,29 @@
481 ** The caller maintains ownership of the input Blobs. This routine will
482 ** read the Blobs and send them onward to the email system, but it will
483 ** not free them.
484 */
485 void email_send(EmailSender *p, Blob *pHdr, Blob *pBody){
486 Blob all, *pOut;
487 if( fossil_strcmp(p->zDest, "off")==0 ){
488 return;
489 }
490 if( fossil_strcmp(p->zDest, "blob")==0 ){
491 pOut = &p->out;
492 if( blob_size(pOut) ){
493 blob_appendf(pOut, "%.72c\n", '=');
494 }
495 }else{
496 blob_init(&all, 0, 0);
497 pOut = &all;
498 }
499 blob_append(pOut, blob_buffer(pHdr), blob_size(pHdr));
500 blob_appendf(pOut, "From: %s\r\n", p->zFrom);
501 blob_add_final_newline(pBody);
502 blob_appendf(pOut,"Content-Type: text/plain\r\n");
503 blob_appendf(pOut, "Content-Transfer-Encoding: base64\r\n\r\n");
504 append_base64(pOut, pBody);
505 if( p->pStmt ){
506 int i, rc;
507 sqlite3_bind_text(p->pStmt, 1, blob_str(&all), -1, SQLITE_TRANSIENT);
508 for(i=0; i<100 && sqlite3_step(p->pStmt)==SQLITE_BUSY; i++){
509 sqlite3_sleep(10);
@@ -1762,12 +1774,12 @@
1774 }
1775 if( nHit==0 ) continue;
1776 blob_appendf(&body,"\n%.72c\nSubscription info: %s/alerts/%s\n",
1777 '-', zUrl, zCode);
1778 email_send(pSender,&hdr,&body);
1779 blob_truncate(&hdr, 0);
1780 blob_truncate(&body, 0);
1781 }
1782 blob_zero(&hdr);
1783 blob_zero(&body);
1784 db_finalize(&q);
1785 email_free_eventlist(pEvents);
@@ -1816,15 +1828,15 @@
1828 autoexec_done:
1829 db_end_transaction(0);
1830 }
1831
1832 /*
1833 ** WEBPAGE: msgtoadmin
1834 **
1835 ** A web-form to send a message to the repository administrator.
1836 */
1837 void msgtoadmin_page(void){
1838 const char *zAdminEmail = db_get("email-admin",0);
1839 unsigned int uSeed;
1840 const char *zDecoded;
1841 char *zCaptcha = 0;
1842
@@ -1871,11 +1883,11 @@
1883 uSeed = captcha_seed();
1884 zDecoded = captcha_decode(uSeed);
1885 zCaptcha = captcha_render(zDecoded);
1886 }
1887 style_header("Message To Administrator");
1888 form_begin(0, "%R/msgtoadmin");
1889 @ <p>Enter a message to the repository administrator below:</p>
1890 @ <table class="subscribe">
1891 if( zCaptcha ){
1892 @ <tr>
1893 @ <td class="form_label">Security&nbsp;Code:</td>
@@ -1907,8 +1919,140 @@
1919 @ %h(zCaptcha)
1920 @ </pre>
1921 @ Enter the 8 characters above in the "Security Code" box
1922 @ </td></tr></table></div>
1923 }
1924 @ </form>
1925 style_footer();
1926 }
1927
1928 /*
1929 ** Send an annoucement message described by query parameter.
1930 ** Permission to do this has already been verified.
1931 */
1932 static char *email_send_announcement(void){
1933 EmailSender *pSender;
1934 char *zErr;
1935 const char *zTo = PT("to");
1936 char *zSubject = PT("subject");
1937 int bAll = PB("all");
1938 int bAA = PB("aa");
1939 const char *zSub = db_get("email-subname", "[Fossil Repo]");
1940 int bTest2 = fossil_strcmp(P("name"),"test2")==0;
1941 Blob hdr, body;
1942 blob_init(&body, 0, 0);
1943 blob_init(&hdr, 0, 0);
1944 blob_appendf(&body, "%s", PT("msg")/*safe-for-%s*/);
1945 pSender = email_sender_new(bTest2 ? "blob" : 0, 0);
1946 if( zTo[0] ){
1947 blob_appendf(&hdr, "To: %s\nSubject: %s %s\n", zTo, zSub, zSubject);
1948 email_send(pSender, &hdr, &body);
1949 }
1950 if( bAll || bAA ){
1951 Stmt q;
1952 int nUsed = blob_size(&body);
1953 const char *zURL = db_get("email-url",0);
1954 db_prepare(&q, "SELECT semail, subscriberCode FROM subscriber "
1955 " WHERE sverified AND NOT sdonotcall %s",
1956 bAll ? "" : " AND ssub LIKE '%a%'");
1957 while( db_step(&q)==SQLITE_ROW ){
1958 const char *zCode = db_column_text(&q, 1);
1959 zTo = db_column_text(&q, 0);
1960 blob_truncate(&hdr, 0);
1961 blob_appendf(&hdr, "To: %s\nSubject: %s %s\n", zTo, zSub, zSubject);
1962 if( zURL ){
1963 blob_truncate(&body, nUsed);
1964 blob_appendf(&body,"\n%.72c\nSubscription info: %s/alerts/%s\n",
1965 '-', zURL, zCode);
1966 }
1967 email_send(pSender, &hdr, &body);
1968 }
1969 db_finalize(&q);
1970 }
1971 if( bTest2 ){
1972 /* If the URL is /announce/test2 instead of just /announce, then no
1973 ** email is actually sent. Instead, the text of the email that would
1974 ** have been sent is displayed in the result window. */
1975 @ <pre style='border: 2px solid blue; padding: 1ex'>
1976 @ %h(blob_str(&pSender->out))
1977 @ </pre>
1978 }
1979 zErr = pSender->zErr;
1980 pSender->zErr = 0;
1981 email_sender_free(pSender);
1982 return zErr;
1983 }
1984
1985
1986 /*
1987 ** WEBPAGE: announce
1988 **
1989 ** A web-form, available to users with the "Send-Announcement" or "A"
1990 ** capability, that allows one to to send an announcements to whomever
1991 ** has subscribed to them. The administrator can also send an announcement
1992 ** to the entire mailing list (including people who have elected to
1993 ** receive no announcements or notifications of any kind, or to
1994 ** individual email to anyone.
1995 */
1996 void announce_page(void){
1997 const char *zTo = PT("to");
1998 login_check_credentials();
1999 if( !g.perm.Announce ){
2000 login_needed(0);
2001 return;
2002 }
2003 if( fossil_strcmp(P("name"),"test1")==0 ){
2004 /* Visit the /announce/test1 page to see the CGI variables */
2005 @ <p style='border: 1px solid black; padding: 1ex;'>
2006 cgi_print_all(0, 0);
2007 @ </p>
2008 }else
2009 if( P("submit")!=0 && cgi_csrf_safe(1) ){
2010 char *zErr = email_send_announcement();
2011 style_header("Announcement Sent");
2012 if( zErr ){
2013 @ <h1>Internal Error</h1>
2014 @ <p>The following error was reported by the system:
2015 @ <blockquote><pre>
2016 @ %h(zErr)
2017 @ </pre></blockquote>
2018 }else{
2019 @ <p>The announcement has been sent.</p>
2020 }
2021 style_footer();
2022 return;
2023 }
2024 style_header("Send Announcement");
2025 @ <form method="POST">
2026 @ <table class="subscribe">
2027 if( g.perm.Admin ){
2028 int aa = PB("aa");
2029 int all = PB("all");
2030 const char *aack = aa ? "checked" : "";
2031 const char *allck = all ? "checked" : "";
2032 @ <tr>
2033 @ <td class="form_label">To:</td>
2034 @ <td><input type="text" name="to" value="%h(PT("to"))" size="30"><br>
2035 @ <label><input type="checkbox" name="aa" %s(aack)> \
2036 @ All "announcement" subscribers</label><br>
2037 @ <label><input type="checkbox" name="all" %s(allck)> \
2038 @ All subscribers</label></td>
2039 @ </tr>
2040 }
2041 @ <tr>
2042 @ <td class="form_label">Subject:</td>
2043 @ <td><input type="text" name="subject" value="%h(PT("subject"))"\
2044 @ size="80"></td>
2045 @ </tr>
2046 @ <tr>
2047 @ <td class="form_label">Message:</td>
2048 @ <td><textarea name="msg" cols="80" rows="10" wrap="virtual">\
2049 @ %h(PT("msg"))</textarea>
2050 @ </tr>
2051 @ <tr>
2052 @ <td></td>
2053 @ <td><input type="submit" name="submit" value="Send Message">
2054 @ </tr>
2055 @ </table>
2056 @ </form>
2057 style_footer();
2058 }
2059
+9 -1
--- src/login.c
+++ src/login.c
@@ -1202,11 +1202,11 @@
12021202
p->NewTkt = p->Password = p->RdAddr =
12031203
p->TktFmt = p->Attach = p->ApndTkt =
12041204
p->ModWiki = p->ModTkt = p->Delete =
12051205
p->RdForum = p->WrForum = p->ModForum =
12061206
p->WrTForum = p->AdminForum =
1207
- p->EmailAlert =
1207
+ p->EmailAlert = p->Announce =
12081208
p->WrUnver = p->Private = 1;
12091209
/* Fall thru into Read/Write */
12101210
case 'i': p->Read = p->Write = 1; break;
12111211
case 'o': p->Read = 1; break;
12121212
case 'z': p->Zip = 1; break;
@@ -1239,10 +1239,11 @@
12391239
case '4': p->WrTForum = 1;
12401240
case '3': p->WrForum = 1;
12411241
case '2': p->RdForum = 1; break;
12421242
12431243
case '7': p->EmailAlert = 1; break;
1244
+ case 'A': p->Announce = 1; break;
12441245
12451246
/* The "u" privileges is a little different. It recursively
12461247
** inherits all privileges of the user named "reader" */
12471248
case 'u': {
12481249
if( (flags & LOGIN_IGNORE_UV)==0 ){
@@ -1312,10 +1313,17 @@
13121313
/* case 'v': DEVELOPER */
13131314
case 'w': rc = p->WrTkt; break;
13141315
case 'x': rc = p->Private; break;
13151316
case 'y': rc = p->WrUnver; break;
13161317
case 'z': rc = p->Zip; break;
1318
+ case '2': rc = p->RdForum; break;
1319
+ case '3': rc = p->WrForum; break;
1320
+ case '4': rc = p->WrTForum; break;
1321
+ case '5': rc = p->ModForum; break;
1322
+ case '6': rc = p->AdminForum;break;
1323
+ case '7': rc = p->EmailAlert;break;
1324
+ case 'A': rc = p->Announce; break;
13171325
default: rc = 0; break;
13181326
}
13191327
}
13201328
return rc;
13211329
}
13221330
--- src/login.c
+++ src/login.c
@@ -1202,11 +1202,11 @@
1202 p->NewTkt = p->Password = p->RdAddr =
1203 p->TktFmt = p->Attach = p->ApndTkt =
1204 p->ModWiki = p->ModTkt = p->Delete =
1205 p->RdForum = p->WrForum = p->ModForum =
1206 p->WrTForum = p->AdminForum =
1207 p->EmailAlert =
1208 p->WrUnver = p->Private = 1;
1209 /* Fall thru into Read/Write */
1210 case 'i': p->Read = p->Write = 1; break;
1211 case 'o': p->Read = 1; break;
1212 case 'z': p->Zip = 1; break;
@@ -1239,10 +1239,11 @@
1239 case '4': p->WrTForum = 1;
1240 case '3': p->WrForum = 1;
1241 case '2': p->RdForum = 1; break;
1242
1243 case '7': p->EmailAlert = 1; break;
 
1244
1245 /* The "u" privileges is a little different. It recursively
1246 ** inherits all privileges of the user named "reader" */
1247 case 'u': {
1248 if( (flags & LOGIN_IGNORE_UV)==0 ){
@@ -1312,10 +1313,17 @@
1312 /* case 'v': DEVELOPER */
1313 case 'w': rc = p->WrTkt; break;
1314 case 'x': rc = p->Private; break;
1315 case 'y': rc = p->WrUnver; break;
1316 case 'z': rc = p->Zip; break;
 
 
 
 
 
 
 
1317 default: rc = 0; break;
1318 }
1319 }
1320 return rc;
1321 }
1322
--- src/login.c
+++ src/login.c
@@ -1202,11 +1202,11 @@
1202 p->NewTkt = p->Password = p->RdAddr =
1203 p->TktFmt = p->Attach = p->ApndTkt =
1204 p->ModWiki = p->ModTkt = p->Delete =
1205 p->RdForum = p->WrForum = p->ModForum =
1206 p->WrTForum = p->AdminForum =
1207 p->EmailAlert = p->Announce =
1208 p->WrUnver = p->Private = 1;
1209 /* Fall thru into Read/Write */
1210 case 'i': p->Read = p->Write = 1; break;
1211 case 'o': p->Read = 1; break;
1212 case 'z': p->Zip = 1; break;
@@ -1239,10 +1239,11 @@
1239 case '4': p->WrTForum = 1;
1240 case '3': p->WrForum = 1;
1241 case '2': p->RdForum = 1; break;
1242
1243 case '7': p->EmailAlert = 1; break;
1244 case 'A': p->Announce = 1; break;
1245
1246 /* The "u" privileges is a little different. It recursively
1247 ** inherits all privileges of the user named "reader" */
1248 case 'u': {
1249 if( (flags & LOGIN_IGNORE_UV)==0 ){
@@ -1312,10 +1313,17 @@
1313 /* case 'v': DEVELOPER */
1314 case 'w': rc = p->WrTkt; break;
1315 case 'x': rc = p->Private; break;
1316 case 'y': rc = p->WrUnver; break;
1317 case 'z': rc = p->Zip; break;
1318 case '2': rc = p->RdForum; break;
1319 case '3': rc = p->WrForum; break;
1320 case '4': rc = p->WrTForum; break;
1321 case '5': rc = p->ModForum; break;
1322 case '6': rc = p->AdminForum;break;
1323 case '7': rc = p->EmailAlert;break;
1324 case 'A': rc = p->Announce; break;
1325 default: rc = 0; break;
1326 }
1327 }
1328 return rc;
1329 }
1330
+1
--- src/main.c
+++ src/main.c
@@ -89,10 +89,11 @@
8989
char WrForum; /* 3: Create new forum posts */
9090
char WrTForum; /* 4: Post to forums not subject to moderation */
9191
char ModForum; /* 5: Moderate (approve or reject) forum posts */
9292
char AdminForum; /* 6: Edit forum posts by other users */
9393
char EmailAlert; /* 7: Sign up for email notifications */
94
+ char Announce; /* A: Send announcements */
9495
};
9596
9697
#ifdef FOSSIL_ENABLE_TCL
9798
/*
9899
** All Tcl related context information is in this structure. This structure
99100
--- src/main.c
+++ src/main.c
@@ -89,10 +89,11 @@
89 char WrForum; /* 3: Create new forum posts */
90 char WrTForum; /* 4: Post to forums not subject to moderation */
91 char ModForum; /* 5: Moderate (approve or reject) forum posts */
92 char AdminForum; /* 6: Edit forum posts by other users */
93 char EmailAlert; /* 7: Sign up for email notifications */
 
94 };
95
96 #ifdef FOSSIL_ENABLE_TCL
97 /*
98 ** All Tcl related context information is in this structure. This structure
99
--- src/main.c
+++ src/main.c
@@ -89,10 +89,11 @@
89 char WrForum; /* 3: Create new forum posts */
90 char WrTForum; /* 4: Post to forums not subject to moderation */
91 char ModForum; /* 5: Moderate (approve or reject) forum posts */
92 char AdminForum; /* 6: Edit forum posts by other users */
93 char EmailAlert; /* 7: Sign up for email notifications */
94 char Announce; /* A: Send announcements */
95 };
96
97 #ifdef FOSSIL_ENABLE_TCL
98 /*
99 ** All Tcl related context information is in this structure. This structure
100
+6 -3
--- src/setup.c
+++ src/setup.c
@@ -364,12 +364,13 @@
364364
@ <td><i>Forum-Moderator:</i> Approve or disapprove forum posts</td></tr>
365365
@ <tr><th valign="top">6</th>
366366
@ <td><i>Forum-Supervisor:</i> \
367367
@ Forum administrator
368368
@ <tr><th valign="top">7</th>
369
- @ <td><i>Email-Alerts:</i> \
370
- @ Sign up for email notifications</td></tr>
369
+ @ <td><i>Email-Alerts:</i> Sign up for email nofications</td></tr>
370
+ @ <tr><th valign="top">A</th>
371
+ @ <td><i>Announce:</i> Send announcements</td></tr>
371372
@ </table>
372373
}
373374
374375
/*
375376
** WEBPAGE: setup_ulist_notes
@@ -764,11 +765,13 @@
764765
@ <label><input type="checkbox" name="a5"%s(oa['5']) />
765766
@ Moderate Forum%s(B('5'))</label><br>
766767
@ <label><input type="checkbox" name="a6"%s(oa['6']) />
767768
@ Supervise Forum%s(B('6'))</label><br>
768769
@ <label><input type="checkbox" name="a7"%s(oa['7']) />
769
- @ Email Alerts%s(B('7'))</label>
770
+ @ Email Alerts%s(B('7'))</label><br>
771
+ @ <label><input type="checkbox" name="aA"%s(oa['A']) />
772
+ @ Send Announcements%s(B('A'))</label>
770773
@ </td></tr>
771774
@ </table>
772775
@ </td>
773776
@ </tr>
774777
@ <tr>
775778
--- src/setup.c
+++ src/setup.c
@@ -364,12 +364,13 @@
364 @ <td><i>Forum-Moderator:</i> Approve or disapprove forum posts</td></tr>
365 @ <tr><th valign="top">6</th>
366 @ <td><i>Forum-Supervisor:</i> \
367 @ Forum administrator
368 @ <tr><th valign="top">7</th>
369 @ <td><i>Email-Alerts:</i> \
370 @ Sign up for email notifications</td></tr>
 
371 @ </table>
372 }
373
374 /*
375 ** WEBPAGE: setup_ulist_notes
@@ -764,11 +765,13 @@
764 @ <label><input type="checkbox" name="a5"%s(oa['5']) />
765 @ Moderate Forum%s(B('5'))</label><br>
766 @ <label><input type="checkbox" name="a6"%s(oa['6']) />
767 @ Supervise Forum%s(B('6'))</label><br>
768 @ <label><input type="checkbox" name="a7"%s(oa['7']) />
769 @ Email Alerts%s(B('7'))</label>
 
 
770 @ </td></tr>
771 @ </table>
772 @ </td>
773 @ </tr>
774 @ <tr>
775
--- src/setup.c
+++ src/setup.c
@@ -364,12 +364,13 @@
364 @ <td><i>Forum-Moderator:</i> Approve or disapprove forum posts</td></tr>
365 @ <tr><th valign="top">6</th>
366 @ <td><i>Forum-Supervisor:</i> \
367 @ Forum administrator
368 @ <tr><th valign="top">7</th>
369 @ <td><i>Email-Alerts:</i> Sign up for email nofications</td></tr>
370 @ <tr><th valign="top">A</th>
371 @ <td><i>Announce:</i> Send announcements</td></tr>
372 @ </table>
373 }
374
375 /*
376 ** WEBPAGE: setup_ulist_notes
@@ -764,11 +765,13 @@
765 @ <label><input type="checkbox" name="a5"%s(oa['5']) />
766 @ Moderate Forum%s(B('5'))</label><br>
767 @ <label><input type="checkbox" name="a6"%s(oa['6']) />
768 @ Supervise Forum%s(B('6'))</label><br>
769 @ <label><input type="checkbox" name="a7"%s(oa['7']) />
770 @ Email Alerts%s(B('7'))</label><br>
771 @ <label><input type="checkbox" name="aA"%s(oa['A']) />
772 @ Send Announcements%s(B('A'))</label>
773 @ </td></tr>
774 @ </table>
775 @ </td>
776 @ </tr>
777 @ <tr>
778
--- www/emaildesign.md
+++ www/emaildesign.md
@@ -122,11 +122,11 @@
122122
Web pages:
123123
124124
* The [/subscribe](/help?cmd=/subscribe) page
125125
* The [/alerts](/help?cmd=/alerts) page
126126
* The [/unsubscribe](/help?cmd=/unsubscribe) page
127
- * The [/msgadmin](/help?cmd=/msgadmin) page
127
+ * The [/msgtoadmin](/help?cmd=/msgtoadmin) page
128128
129129
Web pages for administrators only:
130130
131131
* The [/setup_email](/help?cmd=/setup_email) page
132132
* The [/subscribers](/help?cmd=/subscribers) page
133133
--- www/emaildesign.md
+++ www/emaildesign.md
@@ -122,11 +122,11 @@
122 Web pages:
123
124 * The [/subscribe](/help?cmd=/subscribe) page
125 * The [/alerts](/help?cmd=/alerts) page
126 * The [/unsubscribe](/help?cmd=/unsubscribe) page
127 * The [/msgadmin](/help?cmd=/msgadmin) page
128
129 Web pages for administrators only:
130
131 * The [/setup_email](/help?cmd=/setup_email) page
132 * The [/subscribers](/help?cmd=/subscribers) page
133
--- www/emaildesign.md
+++ www/emaildesign.md
@@ -122,11 +122,11 @@
122 Web pages:
123
124 * The [/subscribe](/help?cmd=/subscribe) page
125 * The [/alerts](/help?cmd=/alerts) page
126 * The [/unsubscribe](/help?cmd=/unsubscribe) page
127 * The [/msgtoadmin](/help?cmd=/msgtoadmin) page
128
129 Web pages for administrators only:
130
131 * The [/setup_email](/help?cmd=/setup_email) page
132 * The [/subscribers](/help?cmd=/subscribers) page
133

Keyboard Shortcuts

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