Fossil

Check-in [e649820b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improvements to on-line subscription management.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | email-alerts
Files: files | file ages | folders
SHA3-256:e649820ba1fdb2d1f69643f7a9df142f8eeb7a9ddce32c7d1578483837273ef8
User & Date: drh 2018-06-22 19:48:35
Context
2018-06-23
00:49
Fix some minor problems with email notification support Closed-Leaf check-in: c2566260 user: drh tags: email-alerts
2018-06-22
19:48
Improvements to on-line subscription management. check-in: e649820b user: drh tags: email-alerts
19:03
Add the "fossil email subscribers" and "fossil email unsubscribe" commands. check-in: ba60f874 user: drh tags: email-alerts
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/email.c.

129
130
131
132
133
134
135


136
137
138
139
140
141
142

143




144
145
146
147
148
149
150
...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
750
751
752
753
754
755
756


757








758
759
760
761


762
763
764
765
766
767
768
769
770
771
772



773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
...
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974

975
976
977
978
979
980
981
982

983
984
985
986
987
988

989
990
















991
992
993
994
995
996
997
....
1047
1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
....
1246
1247
1248
1249
1250
1251
1252

1253
1254
1255
1256
1257
1258
1259
** Return true if email alerts are active.
*/
int email_enabled(void){
  if( !db_table_exists("repository", "subscriber") ) return 0;
  if( fossil_strcmp(db_get("email-send-method","off"),"off")==0 ) return 0;
  return 1;
}



/*
** Insert a "Subscriber List" submenu link if the current user
** is an administrator.
*/
void email_subscriber_list_link(void){
  if( g.perm.Admin ){

    style_submenu_element("Subscriber List","%R/subscribers");




  }
}


/*
** WEBPAGE: setup_email
**
................................................................................
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed(0);
    return;
  }
  db_begin_transaction();

  email_subscriber_list_link();
  style_header("Email Notification Setup");
  @ <form action="%R/setup_email" method="post"><div>
  @ <input type="submit"  name="submit" value="Apply Changes" /><hr>
  login_insert_csrf_secret();

  entry_attribute("Canonical Server URL", 40, "email-url",
                   "eurl", "", 0);
................................................................................
    return;
  }
  if( login_is_individual()
   && db_exists("SELECT 1 FROM subscriber WHERE suname=%Q",g.zLogin)
  ){
    /* This person is already signed up for email alerts.  Jump
    ** to the screen that lets them edit their alert preferences.


    */








    cgi_redirectf("%R/alerts");
    return;
  }
  email_subscriber_list_link();


  needCaptcha = !login_is_individual();
  if( P("submit")
   && cgi_csrf_safe(1)
   && subscribe_error_check(&eErr,&zErr,needCaptcha)
  ){
    /* A validated request for a new subscription has been received. */
    char ssub[20];
    const char *zEAddr = P("e");
    sqlite3_int64 id;   /* New subscriber Id */
    const char *zCode;  /* New subscriber code (in hex) */
    int nsub = 0;



    if( PB("sa") ) ssub[nsub++] = 'a';
    if( PB("sc") ) ssub[nsub++] = 'c';
    if( PB("st") ) ssub[nsub++] = 't';
    if( PB("sw") ) ssub[nsub++] = 'w';
    ssub[nsub] = 0;
    db_multi_exec(
      "INSERT INTO subscriber(subscriberCode,semail,suname,"
      "  sverified,sdonotcall,sdigest,ssub,sctime,smtime,smip)"
      "VALUES(randomblob(32),%Q,%Q,%d,0,%d,%Q,"
      " julianday('now'),julianday('now'),%Q)",
      /* semail */    zEAddr,
      /* suname */    needCaptcha==0 ? g.zLogin : 0,
      /* sverified */ needCaptcha==0,
      /* sdigest */   PB("di"),
      /* ssub */      ssub,
      /* smip */      g.zIpAddr
    );
    id = db_last_insert_rowid();
    zCode = db_text(0,
................................................................................
    zName = db_text(0, "SELECT hex(subscriberCode) FROM subscriber"
                       " WHERE suname=%Q", g.zLogin);
  }
  if( zName==0 || !validate16(zName, -1) ){
    cgi_redirect("subscribe");
    return;
  }
  email_subscriber_list_link();
  if( P("submit")!=0 && cgi_csrf_safe(1) ){
    int sdonotcall = PB("sdonotcall");
    int sdigest = PB("sdigest");
    char ssub[10];
    int nsub = 0;
    const char *suname = 0;
    if( PB("sa") ) ssub[nsub++] = 'a';
    if( PB("sc") ) ssub[nsub++] = 'c';
    if( PB("st") ) ssub[nsub++] = 't';
    if( PB("sw") ) ssub[nsub++] = 'w';
    ssub[nsub] = 0;
    if( g.perm.Admin ){
      suname = PT("suname");
      if( suname && suname[0]==0 ) suname = 0;
    }

    db_multi_exec(
      "UPDATE subscriber SET"
      " sdonotcall=%d,"
      " sdigest=%d,"
      " ssub=%Q,"
      " smtime=julianday('now'),"
      " smip=%Q,"
      " suname=COALESCE(%Q,suname)"

      " WHERE subscriberCode=hextoblob(%Q)",
      sdonotcall,
      sdigest,
      ssub,
      g.zIpAddr,
      suname,

      zName
    );
















  }
  if( P("delete")!=0 && cgi_csrf_safe(1) ){
    if( !PB("dodelete") ){
      eErr = 9;
      zErr = mprintf("Select this checkbox and press \"Unsubscribe\" to"
                     " unsubscribe");
    }else{
................................................................................
  @ </tr>
  if( g.perm.Admin ){
    @ <tr>
    @  <td class='form_label'>IP Address:</td>
    @  <td>%h(smip)</td>
    @ </tr>
    @ <tr>
    @  <td class='form_label'>User:</td>
    @  <td>%h(suname?suname:"")</td>

    @ </tr>
  }
  @ <tr>
  @  <td class="form_label">Options:</td>
  @  <td><label><input type="checkbox" name="sa" %s(sa?"checked":"")>\
  @  Announcements</label><br>
  @  <label><input type="checkbox" name="sc" %s(sc?"checked":"")>\
................................................................................
  Blob sql;
  Stmt q;
  login_check_credentials();
  if( !g.perm.Admin ){
    fossil_redirect_home();
    return;
  }

  style_header("Subscriber List");
  blob_init(&sql, 0, 0);
  blob_append_sql(&sql,
    "SELECT hex(subscriberCode),"
    "       semail,"
    "       ssub,"
    "       suname,"







>
>





|

>
|
>
>
>
>







 







|







 







>
>

>
>
>
>
>
>
>
>
|
|
|
<
>
>











>
>
>











|







 







|





<






|

<
>
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|
>







 







>







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
...
973
974
975
976
977
978
979
980
981
982
983
984
985

986
987
988
989
990
991
992
993

994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
....
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
....
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
** Return true if email alerts are active.
*/
int email_enabled(void){
  if( !db_table_exists("repository", "subscriber") ) return 0;
  if( fossil_strcmp(db_get("email-send-method","off"),"off")==0 ) return 0;
  return 1;
}



/*
** Insert a "Subscriber List" submenu link if the current user
** is an administrator.
*/
void email_submenu_common(void){
  if( g.perm.Admin ){
    if( fossil_strcmp(g.zPath,"subscribers") ){
      style_submenu_element("List Subscribers","%R/subscribers");
    }
    if( fossil_strcmp(g.zPath,"subscribe") ){
      style_submenu_element("Add New Subscriber","%R/subscribe");
    }
  }
}


/*
** WEBPAGE: setup_email
**
................................................................................
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed(0);
    return;
  }
  db_begin_transaction();

  email_submenu_common();
  style_header("Email Notification Setup");
  @ <form action="%R/setup_email" method="post"><div>
  @ <input type="submit"  name="submit" value="Apply Changes" /><hr>
  login_insert_csrf_secret();

  entry_attribute("Canonical Server URL", 40, "email-url",
                   "eurl", "", 0);
................................................................................
    return;
  }
  if( login_is_individual()
   && db_exists("SELECT 1 FROM subscriber WHERE suname=%Q",g.zLogin)
  ){
    /* This person is already signed up for email alerts.  Jump
    ** to the screen that lets them edit their alert preferences.
    ** Except, administrators can create subscriptions for others so
    ** do not jump for them.
    */
    if( g.perm.Admin ){
      /* Admins get a link to admin their own account, but they
      ** stay on this page so that they can create subscriptions
      ** for other people. */
      style_submenu_element("My Subscription","%R/alerts");
    }else{
      /* Everybody else jumps to the page to administer their own
      ** account only. */
      cgi_redirectf("%R/alerts");
      return;
    }

  }
  email_submenu_common();
  needCaptcha = !login_is_individual();
  if( P("submit")
   && cgi_csrf_safe(1)
   && subscribe_error_check(&eErr,&zErr,needCaptcha)
  ){
    /* A validated request for a new subscription has been received. */
    char ssub[20];
    const char *zEAddr = P("e");
    sqlite3_int64 id;   /* New subscriber Id */
    const char *zCode;  /* New subscriber code (in hex) */
    int nsub = 0;
    const char *suname = PT("suname");
    if( suname==0 && needCaptcha==0 && !g.perm.Admin ) suname = g.zLogin;
    if( suname && suname[0]==0 ) suname = 0;
    if( PB("sa") ) ssub[nsub++] = 'a';
    if( PB("sc") ) ssub[nsub++] = 'c';
    if( PB("st") ) ssub[nsub++] = 't';
    if( PB("sw") ) ssub[nsub++] = 'w';
    ssub[nsub] = 0;
    db_multi_exec(
      "INSERT INTO subscriber(subscriberCode,semail,suname,"
      "  sverified,sdonotcall,sdigest,ssub,sctime,smtime,smip)"
      "VALUES(randomblob(32),%Q,%Q,%d,0,%d,%Q,"
      " julianday('now'),julianday('now'),%Q)",
      /* semail */    zEAddr,
      /* suname */    suname,
      /* sverified */ needCaptcha==0,
      /* sdigest */   PB("di"),
      /* ssub */      ssub,
      /* smip */      g.zIpAddr
    );
    id = db_last_insert_rowid();
    zCode = db_text(0,
................................................................................
    zName = db_text(0, "SELECT hex(subscriberCode) FROM subscriber"
                       " WHERE suname=%Q", g.zLogin);
  }
  if( zName==0 || !validate16(zName, -1) ){
    cgi_redirect("subscribe");
    return;
  }
  email_submenu_common();
  if( P("submit")!=0 && cgi_csrf_safe(1) ){
    int sdonotcall = PB("sdonotcall");
    int sdigest = PB("sdigest");
    char ssub[10];
    int nsub = 0;

    if( PB("sa") ) ssub[nsub++] = 'a';
    if( PB("sc") ) ssub[nsub++] = 'c';
    if( PB("st") ) ssub[nsub++] = 't';
    if( PB("sw") ) ssub[nsub++] = 'w';
    ssub[nsub] = 0;
    if( g.perm.Admin ){
      const char *suname = PT("suname");
      if( suname && suname[0]==0 ) suname = 0;

      int sverified = PB("sverified");
      db_multi_exec(
        "UPDATE subscriber SET"
        " sdonotcall=%d,"
        " sdigest=%d,"
        " ssub=%Q,"
        " smtime=julianday('now'),"
        " smip=%Q,"
        " suname=%Q,"
        " sverified=%d"
        " WHERE subscriberCode=hextoblob(%Q)",
        sdonotcall,
        sdigest,
        ssub,
        g.zIpAddr,
        suname,
        sverified,
        zName
      );
    }else{
      db_multi_exec(
        "UPDATE subscriber SET"
        " sdonotcall=%d,"
        " sdigest=%d,"
        " ssub=%Q,"
        " smtime=julianday('now'),"
        " smip=%Q,"
        " WHERE subscriberCode=hextoblob(%Q)",
        sdonotcall,
        sdigest,
        ssub,
        g.zIpAddr,
        zName
      );
    }
  }
  if( P("delete")!=0 && cgi_csrf_safe(1) ){
    if( !PB("dodelete") ){
      eErr = 9;
      zErr = mprintf("Select this checkbox and press \"Unsubscribe\" to"
                     " unsubscribe");
    }else{
................................................................................
  @ </tr>
  if( g.perm.Admin ){
    @ <tr>
    @  <td class='form_label'>IP Address:</td>
    @  <td>%h(smip)</td>
    @ </tr>
    @ <tr>
    @  <td class="form_label">User:</td>
    @  <td><input type="text" name="suname" value="%h(suname?suname:"")" \
    @  size="30"></td>
    @ </tr>
  }
  @ <tr>
  @  <td class="form_label">Options:</td>
  @  <td><label><input type="checkbox" name="sa" %s(sa?"checked":"")>\
  @  Announcements</label><br>
  @  <label><input type="checkbox" name="sc" %s(sc?"checked":"")>\
................................................................................
  Blob sql;
  Stmt q;
  login_check_credentials();
  if( !g.perm.Admin ){
    fossil_redirect_home();
    return;
  }
  email_submenu_common();
  style_header("Subscriber List");
  blob_init(&sql, 0, 0);
  blob_append_sql(&sql,
    "SELECT hex(subscriberCode),"
    "       semail,"
    "       ssub,"
    "       suname,"