This is an omnibus commit which moves the Citadel Server from crusty old GNU Autotool...
[citadel.git] / citadel / modules / listsub / serv_listsub.c
diff --git a/citadel/modules/listsub/serv_listsub.c b/citadel/modules/listsub/serv_listsub.c
deleted file mode 100644 (file)
index 7d7e936..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-// This module handles self-service subscription/unsubscription to mail lists.
-//
-// Copyright (c) 2002-2022 by the citadel.org team
-//
-// This program is open source software.  It runs great on the
-// Linux operating system (and probably elsewhere).  You can use,
-// copy, and run it under the terms of the GNU General Public
-// License version 3.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-#include "sysdep.h"
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <signal.h>
-#include <pwd.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <time.h>
-#include <sys/wait.h>
-#include <string.h>
-#include <limits.h>
-#include <crypt.h>
-#include <libcitadel.h>
-#include "citadel.h"
-#include "server.h"
-#include "citserver.h"
-#include "support.h"
-#include "config.h"
-#include "user_ops.h"
-#include "database.h"
-#include "msgbase.h"
-#include "internet_addressing.h"
-#include "clientsocket.h"
-#include "ctdl_module.h"
-
-
-enum {                         // one of these gets passed to do_subscribe_or_unsubscribe() so it knows what we asked for
-       UNSUBSCRIBE,
-       SUBSCRIBE
-};
-
-
-// The confirmation token will be generated by combining the room name and email address with the host key,
-// and then generating an encrypted hash of that string.  The encrypted hash is included as part of the
-// confirmation link.
-void generate_confirmation_token(char *token_buf, size_t token_buf_len, char *roomname, char *emailaddr) {
-       char string_to_hash[1024];
-       struct crypt_data cd;
-       char *ptr;
-
-       snprintf(string_to_hash, sizeof string_to_hash, "%s|%s|%s", roomname, emailaddr, CtdlGetConfigStr("host_key"));
-       memset(&cd, 0, sizeof cd);
-
-       strncpy(token_buf, crypt_r(string_to_hash, "$1$ctdl", &cd), token_buf_len);
-
-       for (ptr=token_buf; *ptr; ++ptr) {
-               if (!isalnum((char)*ptr)) *ptr='X';
-       }
-}
-
-
-// This generates an email with a link the user clicks to confirm a list subscription.
-void send_subscribe_confirmation_email(char *roomname, char *emailaddr, char *url, char *confirmation_token) {
-       // We need a URL-safe representation of the room name
-       char urlroom[ROOMNAMELEN+10];
-       urlesc(urlroom, sizeof(urlroom), roomname);
-
-       char from_address[1024];
-       snprintf(from_address, sizeof from_address, "noreply@%s", CtdlGetConfigStr("c_fqdn"));
-
-       char emailtext[SIZ];
-       snprintf(emailtext, sizeof emailtext,
-               "MIME-Version: 1.0\n"
-               "Content-Type: multipart/alternative; boundary=\"__ctdlmultipart__\"\n"
-               "\n"
-               "This is a multipart message in MIME format.\n"
-               "\n"
-               "--__ctdlmultipart__\n"
-               "Content-type: text/plain\n"
-               "\n"
-               "Someone (probably you) has submitted a request to subscribe\n"
-               "<%s> to the <%s> mailing list.\n"
-               "\n"
-               "Please go here to confirm this request:\n"
-               "%s?cmd=confirm_subscribe&email=%s&room=%s&token=%s\n"
-               "\n"
-               "If this request has been submitted in error and you do not\n"
-               "wish to receive the <%s> mailing list, simply do nothing,\n"
-               "and you will not receive any further mailings.\n"
-               "\n"
-               "--__ctdlmultipart__\n"
-               "Content-type: text/html\n"
-               "\n"
-               "<html><body><p>Someone (probably you) has submitted a request to subscribe "
-               "<strong>%s</strong> to the <strong>%s</strong> mailing list.</p>"
-               "<p>Please go here to confirm this request:</p>"
-               "<p><a href=\"%s?cmd=confirm_subscribe&email=%s&room=%s&token=%s\">"
-               "%s?cmd=confirm_subscribe&email=%s&room=%s&token=%s</a></p>"
-               "<p>If this request has been submitted in error and you do not "
-               "wish to receive the <strong>%s<strong> mailing list, simply do nothing, "
-               "and you will not receive any further mailings.</p>"
-               "</body></html>\n"
-               "\n"
-               "--__ctdlmultipart__--\n"
-               ,
-               emailaddr, roomname,
-               url, emailaddr, urlroom, confirmation_token,
-               roomname
-               ,
-               emailaddr, roomname,
-               url, emailaddr, urlroom, confirmation_token,
-               url, emailaddr, urlroom, confirmation_token,
-               roomname
-       );
-
-       quickie_message("Citadel", from_address, emailaddr, NULL, emailtext, FMT_RFC822, "Please confirm your list subscription");
-       cprintf("%d confirmation email sent\n", CIT_OK);
-}
-
-
-// This generates an email with a link the user clicks to confirm a list unsubscription.
-void send_unsubscribe_confirmation_email(char *roomname, char *emailaddr, char *url, char *confirmation_token) {
-       // We need a URL-safe representation of the room name
-       char urlroom[ROOMNAMELEN+10];
-       urlesc(urlroom, sizeof(urlroom), roomname);
-
-       char from_address[1024];
-       snprintf(from_address, sizeof from_address, "noreply@%s", CtdlGetConfigStr("c_fqdn"));
-
-       char emailtext[SIZ];
-       snprintf(emailtext, sizeof emailtext,
-               "MIME-Version: 1.0\n"
-               "Content-Type: multipart/alternative; boundary=\"__ctdlmultipart__\"\n"
-               "\n"
-               "This is a multipart message in MIME format.\n"
-               "\n"
-               "--__ctdlmultipart__\n"
-               "Content-type: text/plain\n"
-               "\n"
-               "Someone (probably you) has submitted a request to unsubscribe\n"
-               "<%s> from the <%s> mailing list.\n"
-               "\n"
-               "Please go here to confirm this request:\n"
-               "%s?cmd=confirm_unsubscribe&email=%s&room=%s&token=%s\n"
-               "\n"
-               "If this request has been submitted in error and you still\n"
-               "wish to receive the <%s> mailing list, simply do nothing,\n"
-               "and you will remain subscribed.\n"
-               "\n"
-               "--__ctdlmultipart__\n"
-               "Content-type: text/html\n"
-               "\n"
-               "<html><body><p>Someone (probably you) has submitted a request to unsubscribe "
-               "<strong>%s</strong> from the <strong>%s</strong> mailing list.</p>"
-               "<p>Please go here to confirm this request:</p>"
-               "<p><a href=\"%s?cmd=confirm_unsubscribe&email=%s&room=%s&token=%s\">"
-               "%s?cmd=confirm_unsubscribe&email=%s&room=%s&token=%s</a></p>"
-               "<p>If this request has been submitted in error and you still "
-               "wish to receive the <strong>%s<strong> mailing list, simply do nothing, "
-               "and you will remain subscribed.</p>"
-               "</body></html>\n"
-               "\n"
-               "--__ctdlmultipart__--\n"
-               ,
-               emailaddr, roomname,
-               url, emailaddr, urlroom, confirmation_token,
-               roomname
-               ,
-               emailaddr, roomname,
-               url, emailaddr, urlroom, confirmation_token,
-               url, emailaddr, urlroom, confirmation_token,
-               roomname
-       );
-
-       quickie_message("Citadel", from_address, emailaddr, NULL, emailtext, FMT_RFC822, "Please confirm your list unsubscription");
-       cprintf("%d confirmation email sent\n", CIT_OK);
-}
-
-
-// Confirm a list subscription or unsubscription
-void do_confirm(int cmd, char *roomname, char *emailaddr, char *url, char *generated_token, char *supplied_token) {
-       int i;
-       char buf[1024];
-       int config_lines = 0;
-       char *oldnetconfig, *newnetconfig;
-
-       // During opt #1, the server generated a persistent confirmation token for the user+room combination.
-       // Let's see if the user has supplied the same token during opt #2.
-       if (strcmp(generated_token, supplied_token)) {
-               cprintf("%d This request could not be authenticated.\n", ERROR + PASSWORD_REQUIRED);
-               return;
-       }
-
-       // If the generated token matches the supplied token, the request is authentic.  Do what it says.
-
-       // Load the room's network configuration...
-        oldnetconfig = LoadRoomNetConfigFile(CC->room.QRnumber);
-        if (!oldnetconfig) {
-               oldnetconfig = strdup("");
-       }
-
-       // The new netconfig begins with an empty buffer...
-       begin_critical_section(S_NETCONFIGS);
-       newnetconfig = malloc(strlen(oldnetconfig) + 1024);
-       newnetconfig[0] = 0;
-
-       // Load the config lines in one by one, skipping any that reference this subscriber.  Also remove blank lines.
-       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 buf_email);
-               if ( !IsEmptyStr(buf) && (strcasecmp(buf_email, emailaddr)) ) {
-                       sprintf(&newnetconfig[strlen(newnetconfig)], "%s\n", buf);
-               }
-       }
-
-       // 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 (cmd == SUBSCRIBE) {
-               sprintf(&newnetconfig[strlen(newnetconfig)], "listrecp|%s\n", emailaddr);
-       }
-
-       // 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_lsub(char *cmdbuf) {
-       char cmd[20];
-       char roomname[ROOMNAMELEN];
-       char emailaddr[1024];
-       char url[1024];
-       char generated_token[128];
-       char supplied_token[128];
-
-       extract_token(cmd, cmdbuf, 0, '|', sizeof cmd);                         // token 0 is the sub-command being sent
-       extract_token(roomname, cmdbuf, 1, '|', sizeof roomname);               // token 1 is always a room name
-       extract_token(emailaddr, cmdbuf, 2, '|', sizeof emailaddr);             // token 2 is the subscriber's email address
-       extract_token(url, cmdbuf, 3, '|', sizeof url);                         // token 3 is the URL at which we subscribed
-       extract_token(supplied_token, cmdbuf, 4, '|', sizeof supplied_token);   // token 4 is the token supplied by the caller
-
-       // First confirm that the caller is referencing a room that actually exists.
-       if (CtdlGetRoom(&CC->room, roomname) != 0) {
-               cprintf("%d There is no list called '%s'\n", ERROR + ROOM_NOT_FOUND, roomname);
-               return;
-       }
-
-       if ((CC->room.QRflags2 & QR2_SELFLIST) == 0) {
-               cprintf("%d '%s' does not accept subscribe/unsubscribe requests.\n", ERROR + ROOM_NOT_FOUND, roomname);
-               return;
-       }
-
-       // Generate a confirmation token -- either to supply to the user for opt #1 or to compare for opt #2
-       generate_confirmation_token(generated_token, sizeof generated_token, roomname, emailaddr);
-
-       // Now parse the command.
-       if (!strcasecmp(cmd, "subscribe")) {
-               send_subscribe_confirmation_email(roomname, emailaddr, url, generated_token);
-       }
-
-       else if (!strcasecmp(cmd, "unsubscribe")) {
-               send_unsubscribe_confirmation_email(roomname, emailaddr, url, generated_token);
-       }
-
-       else if (!strcasecmp(cmd, "confirm_subscribe")) {
-               do_confirm(SUBSCRIBE, roomname, emailaddr, url, generated_token, supplied_token);
-       }
-
-       else if (!strcasecmp(cmd, "confirm_unsubscribe")) {
-               do_confirm(UNSUBSCRIBE, roomname, emailaddr, url, generated_token, supplied_token);
-       }
-
-       else {                                                                  // sorry man, I can't deal with that
-               cprintf("%d Invalid command '%s'\n", ERROR + ILLEGAL_VALUE, cmd);
-       }
-}
-
-
-/*
- * Module entry point
- */
-CTDL_MODULE_INIT(listsub)
-{
-       if (!threading)
-       {
-               CtdlRegisterProtoHook(cmd_lsub, "LSUB", "List subscribe/unsubscribe");
-       }
-       
-       /* return our module name for the log */
-       return "listsub";
-}