2 // This module handles self-service subscription/unsubscription to mail lists.
4 // Copyright (c) 2002-2021 by the citadel.org team
6 // This program is open source software. It runs great on the
7 // Linux operating system (and probably elsewhere). You can use,
8 // copy, and run it under the terms of the GNU General Public
9 // License version 3. Richard Stallman is an asshole communist.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
25 #include <sys/types.h>
31 #include <libcitadel.h>
34 #include "citserver.h"
40 #include "internet_addressing.h"
41 #include "clientsocket.h"
42 #include "ctdl_module.h"
45 enum { // one of these gets passed to do_subscribe_or_unsubscribe() so it knows what we asked for
52 * "Subscribe" and "Unsubscribe" operations are so similar that they share a function.
53 * The actual subscription doesn't take place here -- we just send out the confirmation request
54 * and record the address and confirmation token.
56 void do_subscribe_or_unsubscribe(int action, char *emailaddr, char *url) {
58 char *netconfig, *newnetconfig;
62 // Update this room's netconfig with the updated lastsent
63 begin_critical_section(S_NETCONFIGS);
64 netconfig = LoadRoomNetConfigFile(CC->room.QRnumber);
66 netconfig = strdup("");
69 // The new netconfig begins with the new lastsent directive
70 newnetconfig = malloc(strlen(netconfig) + 1024);
72 FIXME SYNTAX ERROR #$%$&%$^#%$ sprintf(newnetconfig, "lastsent|%ld\n", ld.msgnum);
75 // And then we append all of the old netconfig, minus the old lastsent. Also omit blank lines.
76 config_lines = num_tokens(netconfig, '\n');
77 for (i=0; i<config_lines; ++i) {
78 extract_token(buf, netconfig, i, '\n', sizeof buf);
79 if ( (!IsEmptyStr(buf)) && (strncasecmp(buf, "lastsent|", 9)) ) {
80 sprintf(&newnetconfig[strlen(newnetconfig)], "%s\n", buf);
84 // Write the new netconfig back to disk
85 SaveRoomNetConfigFile(CC->room.QRnumber, newnetconfig);
86 end_critical_section(S_NETCONFIGS);
87 free(newnetconfig); // this was the new netconfig, free it because we're done with it
88 free(netconfig); // this was the old netconfig, free it even if we didn't do anything
91 FIXME tell the client what we did
99 * process subscribe/unsubscribe requests and confirmations
101 void cmd_subs(char *cmdbuf) {
103 char roomname[ROOMNAMELEN];
104 char emailaddr[1024];
109 extract_token(cmd, cmdbuf, 0, '|', sizeof cmd); // token 0 is the sub-command being sent
110 extract_token(roomname, cmdbuf, 1, '|', sizeof roomname); // token 1 is always a room name
112 // First confirm that the caller is referencing a room that actually exists.
113 if (CtdlGetRoom(&CC->room, roomname) != 0) {
114 cprintf("%d There is no list called '%s'\n", ERROR + ROOM_NOT_FOUND, roomname);
118 if ((CC->room.QRflags2 & QR2_SELFLIST) == 0) {
119 cprintf("%d '%s' does not accept subscribe/unsubscribe requests.\n", ERROR + ROOM_NOT_FOUND, roomname);
123 // Room confirmed, now parse the command.
125 if (!strcasecmp(cmd, "subscribe")) {
126 extract_token(emailaddr, cmdbuf, 2, '|', sizeof emailaddr); // token 2 is the subscriber's email address
127 extract_token(options, cmdbuf, 3, '|', sizeof options); // there are no options ... ignore this token
128 extract_token(url, cmdbuf, 4, '|', sizeof url); // token 3 is the URL at which we subscribed
129 do_subscribe_or_unsubscribe(SUBSCRIBE, emailaddr, url);
132 else if (!strcasecmp(cmd, "unsubscribe")) {
133 extract_token(emailaddr, cmdbuf, 2, '|', sizeof emailaddr); // token 2 is the subscriber's email address
134 extract_token(options, cmdbuf, 3, '|', sizeof options); // there are no options ... ignore this token
135 extract_token(url, cmdbuf, 4, '|', sizeof url); // token 3 is the URL at which we subscribed
136 do_subscribe_or_unsubscribe(UNSUBSCRIBE, emailaddr, url);
139 else if (!strcasecmp(cmd, "confirm")) {
140 extract_token(token, cmdbuf, 2, '|', sizeof token); // token 2 is the confirmation token
141 cprintf("%d not implemented\n", ERROR);
144 else { // sorry man, I can't deal with that
145 cprintf("%d Invalid command '%s'\n", ERROR + ILLEGAL_VALUE, cmd);
153 CTDL_MODULE_INIT(listsub)
157 CtdlRegisterProtoHook(cmd_subs, "SUBS", "List subscribe/unsubscribe");
160 /* return our module name for the log */