Renamed SUBS command to LSUB and changed its parameters. Subscription Type no longer...
authorArt Cancro <ajc@citadel.org>
Sat, 20 Feb 2021 16:26:00 +0000 (11:26 -0500)
committerArt Cancro <ajc@citadel.org>
Sat, 20 Feb 2021 16:26:00 +0000 (11:26 -0500)
citadel/citadel.h
citadel/modules/listsub/serv_listsub.c
libcitadel/lib/libcitadel.h
webcit/listsub.c
webcit/webcit.h

index fe4654d60d2997fdb2a90ec5889f8e4c34f4de0f..437b6ceedae897cf8b09534d4f89c6ff161d6d6a 100644 (file)
@@ -35,10 +35,10 @@ extern "C" {
  */
 #define CITADEL        PACKAGE_STRING
 
-#define REV_LEVEL      930             // This version
+#define REV_LEVEL      931             // This version
 #define REV_MIN                591             // Oldest compatible database
 #define EXPORT_REV_MIN 760             // Oldest compatible export files
-#define LIBCITADEL_MIN 926             // Minimum required version of libcitadel
+#define LIBCITADEL_MIN 931             // Minimum required version of libcitadel
 #define SERVER_TYPE    0               // zero for stock Citadel; other developers please obtain SERVER_TYPE codes for your implementations
 
 #ifdef LIBCITADEL_VERSION_NUMBER
index 9cf3fb86c83f9ebf1bb94c8e66eec66771602b2c..d4db241bf0d61dac3ed8fcc91fe293f24b702796 100644 (file)
@@ -94,7 +94,10 @@ void send_subscribe_confirmation_email(char *roomname, char *emailaddr, char *ur
                "\n"
                "--__ctdlmultipart__--\n"
                ,
-               emailaddr, roomname, url, urlroom, confirmation_token, roomname,
+               emailaddr, roomname,
+               url, urlroom, confirmation_token,
+               roomname
+               ,
                emailaddr, roomname,
                url, urlroom, confirmation_token,
                url, urlroom, confirmation_token,
@@ -151,14 +154,17 @@ void send_unsubscribe_confirmation_email(char *roomname, char *emailaddr, char *
                "\n"
                "--__ctdlmultipart__--\n"
                ,
-               emailaddr, roomname, url, urlroom, confirmation_token, roomname,
+               emailaddr, roomname,
+               url, urlroom, confirmation_token,
+               roomname
+               ,
                emailaddr, roomname,
                url, urlroom, confirmation_token,
                url, urlroom, confirmation_token,
                roomname
        );
 
-       quickie_message("Citadel", from_address, emailaddr, NULL, emailtext, FMT_RFC822, "Please confirm your list subscription");
+       quickie_message("Citadel", from_address, emailaddr, NULL, emailtext, FMT_RFC822, "Please confirm your list unsubscription");
 }
 
 
@@ -195,21 +201,21 @@ void do_subscribe_or_unsubscribe(int action, char *emailaddr, char *url) {
                        keep_this_line = 0;
                }
 
-               char buf_token[1024];
+               char buf_directive[1024];
                char buf_email[1024];
-               extract_token(buf_token, buf, 0, '|', sizeof buf_token);
+               extract_token(buf_directive, buf, 0, '|', sizeof buf_directive);
                extract_token(buf_email, buf, 1, '|', sizeof buf_email);
 
-               if (    ( (!strcasecmp(buf_token, "listrecp")) || (!strcasecmp(buf_token, "digestrecp")) )
+               if (    ( (!strcasecmp(buf_directive, "listrecp")) || (!strcasecmp(buf_directive, "digestrecp")) )
                        && (!strcasecmp(buf_email, emailaddr)) 
                ) {
                        is_already_subscribed = 1;
                }
 
-               if ( (!strcasecmp(buf_token, "subpending")) || (!strcasecmp(buf_token, "unsubpending")) ) {
+               if ( (!strcasecmp(buf_directive, "subpending")) || (!strcasecmp(buf_directive, "unsubpending")) ) {
                        time_t pendingtime = extract_long(buf, 3);
                        if ((time(NULL) - pendingtime) > 259200) {
-                               syslog(LOG_DEBUG, "%s %s is %ld seconds old - deleting it", buf_email, buf_token, time(NULL) - pendingtime);
+                               syslog(LOG_DEBUG, "%s %s is %ld seconds old - deleting it", buf_email, buf_directive, time(NULL) - pendingtime);
                                keep_this_line = 0;
                        }
                }
@@ -232,8 +238,6 @@ void do_subscribe_or_unsubscribe(int action, char *emailaddr, char *url) {
        }
 
        // Write the new netconfig back to disk
-       syslog(LOG_DEBUG, "old: <\033[31m%s\033[0m>", oldnetconfig);
-       syslog(LOG_DEBUG, "new: <\033[32m%s\033[0m>", newnetconfig);
        SaveRoomNetConfigFile(CC->room.QRnumber, newnetconfig);
        end_critical_section(S_NETCONFIGS);
        free(newnetconfig);                     // this was the new netconfig, free it because we're done with it
@@ -241,27 +245,109 @@ void do_subscribe_or_unsubscribe(int action, char *emailaddr, char *url) {
 
        // Tell the client what happened.
        if ((action == SUBSCRIBE) && (is_already_subscribed)) {
-               cprintf("%d This email is already subscribed.\n", ERROR + ALREADY_EXISTS);
+               cprintf("%d This email address is already subscribed.\n", ERROR + ALREADY_EXISTS);
        }
        else if ((action == SUBSCRIBE) && (!is_already_subscribed)) {
-               cprintf("%d Confirmation email sent.\n", CIT_OK);
+               cprintf("%d Subscription was requested, and a confirmation email was sent.\n", CIT_OK);
        }
        else if ((action == UNSUBSCRIBE) && (!is_already_subscribed)) {
-               cprintf("%d This email is not subscribed.\n", ERROR + NO_SUCH_USER);
+               cprintf("%d This email address is not subscribed.\n", ERROR + NO_SUCH_USER);
        }
        else if ((action == UNSUBSCRIBE) && (is_already_subscribed)) {
-               cprintf("%d Confirmation email sent.\n", CIT_OK);
+               cprintf("%d Unsubscription was requested, and a confirmation email was sent.\n", CIT_OK);
        }
        else {
-               cprintf("%d FIXME tell the client what we did\n", ERROR);
+               cprintf("%d Nothing happens.\n", ERROR);
+       }
+}
+
+
+/*
+ * Confirm a list subscription or unsubscription
+ */
+void do_confirm(char *token) {
+       int yes_subscribe = 0;                          // Set to 1 if the confirmation to subscribe is validated.
+       int yes_unsubscribe = 0;                        // Set to 1 if the confirmation to unsubscribe is validated.
+       int i;
+       char buf[1024];
+       int config_lines = 0;
+       char pending_directive[128];
+       char pending_email[256];
+       char pending_token[128];
+
+       // We will have to do this in two passes.  The first pass checks to see if we have a confirmation request matching the token.
+        char *oldnetconfig = LoadRoomNetConfigFile(CC->room.QRnumber);
+        if (!oldnetconfig) {
+               cprintf("%d There are no pending requests.\n", ERROR + NO_SUCH_USER);
+               return;
        }
+
+       config_lines = num_tokens(oldnetconfig, '\n');
+       for (i=0; i<config_lines; ++i) {
+               extract_token(buf, oldnetconfig, i, '\n', sizeof buf);
+               extract_token(pending_directive, buf, 0, '|', sizeof pending_directive);
+               extract_token(pending_email, buf, 1, '|', sizeof pending_email);
+               extract_token(pending_token, buf, 2, '|', sizeof pending_token);
+
+               if (!strcasecmp(pending_token, token)) {
+                       if (!strcasecmp(pending_directive, "subpending")) {
+                               yes_subscribe = 1;
+                       }
+                       else if (!strcasecmp(pending_directive, "unsubpending")) {
+                               yes_unsubscribe = 1;
+                       }
+               }
+       }
+       free(oldnetconfig);
+
+       // We didn't find a pending subscribe or unsubscribe request with the supplied token.
+       if ((!yes_subscribe) && (!yes_unsubscribe)) {
+               cprintf("%d The request you are trying to confirm was not found.\n", ERROR + NO_SUCH_USER);
+               return;
+       }
+
+       // The second pass performs the now confirmed operation.
+       // We will have to do this in two passes.  The first pass checks to see if we have a confirmation request matching the token.
+        oldnetconfig = LoadRoomNetConfigFile(CC->room.QRnumber);
+        if (!oldnetconfig) {
+               oldnetconfig = strdup("");
+       }
+
+       // The new netconfig begins with an empty buffer...
+       begin_critical_section(S_NETCONFIGS);
+       char *newnetconfig = malloc(strlen(oldnetconfig) + 1024);
+       newnetconfig[0] = 0;
+
+       config_lines = num_tokens(oldnetconfig, '\n');
+       for (i=0; i<config_lines; ++i) {
+               char buf_email[256];
+               extract_token(buf, oldnetconfig, i, '\n', sizeof buf);
+               extract_token(buf_email, buf, 1, '|', sizeof pending_email);
+               if (strcasecmp(buf_email, pending_email)) {
+                       sprintf(&newnetconfig[strlen(newnetconfig)], "%s\n", buf);      // only keep lines that do not reference this subscriber
+               }
+       }
+
+       // We have now removed all lines containing the subscriber's email address.  This deletes any pending requests.
+       // If this was an unsubscribe operation, they're now gone from the list.
+       // But if this was a subscribe operation, we now need to add them.
+       if (yes_subscribe) {
+               sprintf(&newnetconfig[strlen(newnetconfig)], "listrecp|%s\n", pending_email);
+       }
+
+       // FIXME write it back to disk
+       SaveRoomNetConfigFile(CC->room.QRnumber, newnetconfig);
+       end_critical_section(S_NETCONFIGS);
+       free(oldnetconfig);
+       free(newnetconfig);
+       cprintf("%d The pending request was confirmed.\n", CIT_OK);
 }
 
 
 /* 
  * process subscribe/unsubscribe requests and confirmations
  */
-void cmd_subs(char *cmdbuf) {
+void cmd_lsub(char *cmdbuf) {
        char cmd[20];
        char roomname[ROOMNAMELEN];
        char emailaddr[1024];
@@ -287,21 +373,19 @@ void cmd_subs(char *cmdbuf) {
 
        if (!strcasecmp(cmd, "subscribe")) {
                extract_token(emailaddr, cmdbuf, 2, '|', sizeof emailaddr);     // token 2 is the subscriber's email address
-               extract_token(options, cmdbuf, 3, '|', sizeof options);         // there are no options ... ignore this token
-               extract_token(url, cmdbuf, 4, '|', sizeof url);                 // token 3 is the URL at which we subscribed
+               extract_token(url, cmdbuf, 3, '|', sizeof url);                 // token 3 is the URL at which we subscribed
                do_subscribe_or_unsubscribe(SUBSCRIBE, emailaddr, url);
        }
 
        else if (!strcasecmp(cmd, "unsubscribe")) {
                extract_token(emailaddr, cmdbuf, 2, '|', sizeof emailaddr);     // token 2 is the subscriber's email address
-               extract_token(options, cmdbuf, 3, '|', sizeof options);         // there are no options ... ignore this token
-               extract_token(url, cmdbuf, 4, '|', sizeof url);                 // token 3 is the URL at which we subscribed
+               extract_token(url, cmdbuf, 3, '|', sizeof url);                 // token 3 is the URL at which we subscribed
                do_subscribe_or_unsubscribe(UNSUBSCRIBE, emailaddr, url);
        }
 
        else if (!strcasecmp(cmd, "confirm")) {
                extract_token(token, cmdbuf, 2, '|', sizeof token);             // token 2 is the confirmation token
-               cprintf("%d not implemented\n", ERROR);
+               do_confirm(token);
        }
 
        else {                                                                  // sorry man, I can't deal with that
@@ -317,7 +401,7 @@ CTDL_MODULE_INIT(listsub)
 {
        if (!threading)
        {
-               CtdlRegisterProtoHook(cmd_subs, "SUBS", "List subscribe/unsubscribe");
+               CtdlRegisterProtoHook(cmd_lsub, "LSUB", "List subscribe/unsubscribe");
        }
        
        /* return our module name for the log */
index fe9cbd7003ab200575a5e1a9ae54c587a3cde81b..7740dc190215815d72a4d271b892801c95548f9a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Header file for libcitadel
  *
- * Copyright (c) 1987-2019 by the citadel.org team
+ * Copyright (c) 1987-2021 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 3.
@@ -26,7 +26,7 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 
-#define LIBCITADEL_VERSION_NUMBER      926
+#define LIBCITADEL_VERSION_NUMBER      931
 
 /*
  * Here's a bunch of stupid magic to make the MIME parser portable.
index 64f809e522f93feba0a380c1c6dba81ebcabf5b0..d445d05bd16cacdda9da0a7fe2850b02968100e7 100644 (file)
 /*
  * List subscription handling
  */
-
-int Conditional_LISTSUB_EXECUTE_SUBSCRIBE(StrBuf *Target, WCTemplputParams *TP)
-{
+int Conditional_LISTSUB_EXECUTE_SUBSCRIBE(StrBuf *Target, WCTemplputParams *TP) {
        int rc;
        StrBuf *Line;
        const char *ImpMsg;
-       const StrBuf *Room, *Email, *SubType;
+       const StrBuf *Room, *Email;
 
        if (strcmp(bstr("cmd"), "subscribe")) {
                return 0;
@@ -43,25 +41,20 @@ int Conditional_LISTSUB_EXECUTE_SUBSCRIBE(StrBuf *Target, WCTemplputParams *TP)
                AppendImportantMessage(ImpMsg, -1);
                return 0;
        }
-       SubType = sbstr("subtype");
 
        Line = NewStrBuf();
-       serv_printf("SUBS subscribe|%s|%s|%s|%s/listsub",
-                   ChrPtr(Room),
-                   ChrPtr(Email),
-                   ChrPtr(SubType),
-                   ChrPtr(site_prefix)
-               );
+       serv_printf("LSUB subscribe|%s|%s|%s/listsub", ChrPtr(Room), ChrPtr(Email), ChrPtr(site_prefix));
        StrBuf_ServGetln(Line);
        rc = GetServerStatusMsg(Line, NULL, 1, 2);
        FreeStrBuf(&Line);
-       if (rc == 2)
+       if (rc == 2) {
                putbstr("__FAIL", NewStrBufPlain(HKEY("1")));
+       }
        return rc == 2;
 }
 
-int Conditional_LISTSUB_EXECUTE_UNSUBSCRIBE(StrBuf *Target, WCTemplputParams *TP)
-{
+
+int Conditional_LISTSUB_EXECUTE_UNSUBSCRIBE(StrBuf *Target, WCTemplputParams *TP) {
        int rc;
        StrBuf *Line;
        const char *ImpMsg;
@@ -86,11 +79,7 @@ int Conditional_LISTSUB_EXECUTE_UNSUBSCRIBE(StrBuf *Target, WCTemplputParams *TP
                return 0;
        }
 
-       serv_printf("SUBS unsubscribe|%s|%s|%s/listsub",
-                   ChrPtr(Room),
-                   ChrPtr(Email),
-                   ChrPtr(site_prefix)
-               );
+       serv_printf("LSUB unsubscribe|%s|%s|%s/listsub", ChrPtr(Room), ChrPtr(Email), ChrPtr(site_prefix));
        Line = NewStrBuf();
        StrBuf_ServGetln(Line);
        rc = GetServerStatusMsg(Line, NULL, 1, 2);
@@ -127,10 +116,7 @@ int Conditional_LISTSUB_EXECUTE_CONFIRM_SUBSCRIBE(StrBuf *Target, WCTemplputPara
        }
 
        Line = NewStrBuf();
-       serv_printf("SUBS confirm|%s|%s",
-                   ChrPtr(Room),
-                   ChrPtr(Token)
-               );
+       serv_printf("LSUB confirm|%s|%s", ChrPtr(Room), ChrPtr(Token));
        StrBuf_ServGetln(Line);
        rc = GetServerStatusMsg(Line, NULL, 1, 2);
        FreeStrBuf(&Line);
index d263ef24672882da4b3801dfaeeb8b6b6d04b01a..cd48d5166becb8e945981d3c066d1c2ca89c5caa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1987-2020 by the citadel.org team
+ * Copyright (c) 1987-2021 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 3.
@@ -128,8 +128,8 @@ extern char *ssl_cipher_list;
 #define DEVELOPER_ID           0
 #define CLIENT_ID              4
 #define CLIENT_VERSION         927             /* This version of WebCit */
-#define MINIMUM_CIT_VERSION    930             /* Minimum required version of Citadel server */
-#define        LIBCITADEL_MIN          924             /* Minimum required version of libcitadel */
+#define MINIMUM_CIT_VERSION    931             /* Minimum required version of Citadel server */
+#define        LIBCITADEL_MIN          931             /* Minimum required version of libcitadel */
 #define DEFAULT_HOST           "localhost"     /* Default Citadel server */
 #define DEFAULT_PORT           "504"
 #define TARGET                 "webcit01"      /* Window target for inline URL's */