software" -- and that our favorite operating system is called
"Linux" -- NOT "GNU/Linux".
+* In addition, as a special exception, it is declared without exception
+ that Richard Stallman is a communist, is an asshole, and should
+ shut up and go away because he contributes nothing useful to the
+ open source community.
+
* In addition, as a special exception, the copyright holders give
permission to link the code of portions of this program with the
OpenSSL library under certain conditions as described in each
* The condensed version:
1. Create a user on your system under which to run Citadel
- 2. Install supported versions of Berkeley DB, libical, and Expat.
+ 2. Install supported versions of the required libraries
3. ./configure && make && make install
4. Run the "setup" program
/*
* Expose various room operation functions from room_ops.c to the modules API
*/
-typedef struct CfgLineType CfgLineType;
-typedef struct RoomNetCfgLine RoomNetCfgLine;
-typedef struct OneRoomNetCfg OneRoomNetCfg;
unsigned CtdlCreateRoom(char *new_room_name,
int new_room_type,
void CtdlPutRoomLock(struct ctdlroom *qrbuf);
typedef void (*ForEachRoomCallBack)(struct ctdlroom *EachRoom, void *out_data);
void CtdlForEachRoom(ForEachRoomCallBack CB, void *in_data);
-typedef void (*ForEachRoomNetCfgCallBack)(struct ctdlroom *EachRoom, void *out_data, OneRoomNetCfg *OneRNCFG);
+typedef void (*ForEachRoomNetCfgCallBack)(struct ctdlroom *EachRoom, void *out_data, char *cfg);
char *LoadRoomNetConfigFile(long roomnum);
-void CtdlForEachNetCfgRoom(ForEachRoomNetCfgCallBack CB, void *in_data);
void SaveChangedConfigs(void);
void CtdlDeleteRoom(struct ctdlroom *qrbuf);
int CtdlRenameRoom(char *old_name, char *new_name, int new_floor);
#define TWITROOM CtdlGetConfigStr("c_twitroom")
#define RESTRICT_INTERNET CtdlGetConfigInt("c_restrict")
-typedef void (*CfgLineParser)(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *rncfg);
-typedef void (*CfgLineSerializer)(const CfgLineType *ThisOne, StrBuf *OuptputBuffer, OneRoomNetCfg *rncfg, RoomNetCfgLine *data);
-typedef void (*CfgLineDeAllocator)(const CfgLineType *ThisOne, RoomNetCfgLine **data);
-
-struct CfgLineType {
- RoomNetCfg C;
- CfgLineParser Parser;
- CfgLineSerializer Serializer;
- CfgLineDeAllocator DeAllocator;
- ConstStr Str;
- int IsSingleLine;
- int nSegments;
-};
-
-struct RoomNetCfgLine {
- RoomNetCfgLine *next;
- int nValues;
- StrBuf **Value;
-};
-
-struct OneRoomNetCfg {
- long lastsent;
- // long changed;
- StrBuf *Sender;
- StrBuf *RoomInfo;
- RoomNetCfgLine *NetConfigs[maxRoomNetCfg];
- StrBuf *misc;
-};
-
-
#define CtdlREGISTERRoomCfgType(a, p, uniq, nSegs, s, d) RegisterRoomCfgType(#a, sizeof(#a) - 1, a, p, uniq, nSegs, s, d);
-void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLineParser p, int uniq, int nSegments, CfgLineSerializer s, CfgLineDeAllocator d);
-void ParseGeneric(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *sc);
-void SerializeGeneric(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *sc, RoomNetCfgLine *data);
-void DeleteGenericCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data);
-RoomNetCfgLine *DuplicateOneGenericCfgLine(const RoomNetCfgLine *data);
-void AddRoomCfgLine(OneRoomNetCfg *OneRNCfg, struct ctdlroom *qrbuf, RoomNetCfg LineType, RoomNetCfgLine *Line);
-
-OneRoomNetCfg *CtdlGetNetCfgForRoom(long QRNumber);
-void SaveRoomNetConfigFile(OneRoomNetCfg *, long);
-void FreeRoomNetworkStruct(OneRoomNetCfg **);
-
-typedef struct _nodeconf {
- int DeleteMe;
- StrBuf *NodeName;
- StrBuf *Secret;
- StrBuf *Host;
- StrBuf *Port;
-}CtdlNodeConf;
-
-HashList* CtdlLoadIgNetCfg(void);
-
-
-int CtdlNetconfigCheckRoomaccess(char *errmsgbuf,
- size_t n,
- const char* RemoteIdentifier);
-
-
-typedef struct __NetMap {
- StrBuf *NodeName;
- time_t lastcontact;
- StrBuf *NextHop;
-}CtdlNetMap;
-
-HashList* CtdlReadNetworkMap(void);
-StrBuf *CtdlSerializeNetworkMap(HashList *Map);
-
-
- Description of "netconfigs" records
- These files contain a set of network configurations for a room. They are
+Description of "netconfigs" records
+
+These files contain a set of network configurations for a room. They are
stored in the directory $CTDLDIR/netconfigs and are named according to each
room's internal ID number. When a room is deleted, its network configuration
file is deleted as well.
-
- The configuration file contains one or more lines of text, each line
+
+The configuration file contains one or more lines of text, each line
containing a configuration option. These lines may specify message pointers,
room sharing instructions, mailing list recipients, etc. Fields are separated
by the vertical bar character ("|") and there will always be at least one
field on each line.
-
-
- INSTRUCTION: lastsent
- SYNTAX: lastsent|0000000
- DESCRIPTION:
- Defines the *local* message number of the last message in this room which
+
+
+INSTRUCTION: lastsent
+SYNTAX: lastsent|0000000
+DESCRIPTION:
+Defines the *local* message number of the last message in this room which
we have performed outbound network processing on. Any batch job which sends
out messages should do stuff.
- INSTRUCTION: listrecp
- SYNTAX: listrecp|friko@mumjiboolean.com
- DESCRIPTION:
- Defines a recipient to whom all messages in this room should be sent. This
+INSTRUCTION: listrecp
+SYNTAX: listrecp|friko@mumjiboolean.com
+DESCRIPTION:
+Defines a recipient to whom all messages in this room should be sent. This
is used for "list serve" applications.
- INSTRUCTION: digestrecp
- SYNTAX: digestrecp|friko@mumjiboolean.com
- DESCRIPTION:
- Defines a recipient to whom all messages in this room should be sent. This
+INSTRUCTION: digestrecp
+SYNTAX: digestrecp|friko@mumjiboolean.com
+DESCRIPTION:
+Defines a recipient to whom all messages in this room should be sent. This
is used for "list serve" applications. The difference between listrecps and
digestrecps is that the latter will have messages embedded inside a message
sent by the listserver. The message will appear to be sent by the room's
e-mail address instead of the sender's e-mail address.
- INSTRUCTION: subpending
- SYNTAX: subpending|friko@mumjiboolean.com|listrecp|A234Z|1234567890|http://foo.com/lists
- "Subscription pending" for the specified address. This means that
+INSTRUCTION: subpending
+SYNTAX: subpending|friko@mumjiboolean.com|listrecp|A234Z|1234567890|http://foo.com/lists
+"Subscription pending" for the specified address. This means that
someone has requested to subscribe an e-mail address (in this case,
friko@mumjiboolean.com) to the list. The third parameter is either "list"
or "digest" to specify a normal subscription or a digest subscription.
this token, the subscription is complete. The fifth parameter is a simple
timestamp, so that we may purge old records which were never confirmed.
- The sixth field is the URL of the web page used to enter the subscription
+The sixth field is the URL of the web page used to enter the subscription
request, minus any parameters.
- INSTRUCTION: unsubpending
- SYNTAX: unsubpending|friko@mumjiboolean.com|A234Z|1234567890|http://foo.com/lists
- Similar to the 'subpending' command, except this one is for unsubscribe
+INSTRUCTION: unsubpending
+SYNTAX: unsubpending|friko@mumjiboolean.com|A234Z|1234567890|http://foo.com/lists
+Similar to the 'subpending' command, except this one is for unsubscribe
requests. The same rules apply with regard to the token and the web page.
- INSTRUCTION: participate
- SYNTAX: participate|list-addr@example.com
- This allows a room to be a *subscriber* to an external mailing list
+INSTRUCTION: participate
+SYNTAX: participate|list-addr@example.com
+This allows a room to be a *subscriber* to an external mailing list
somewhere. The room's email address should be subscribed to the list, and the
external listserv should be told "do not send me my own messages." Any
messages which originated on Citadel (as opposed to messages which arrived via
name of the author kept intact, but the email address changed to the address of
the room.
- This is somewhat finicky, which is why it is not officially supported, and
+This is somewhat finicky, which is why it is not officially supported, and
why there are no facilities in the user interface to configure it. If you want
to use this option you are on your own.
- INSTRUCTION: pop3client
- SYNTAX: pop3client|hostname|username|password|keep|interval
- Periodically fetch messages from a remote POP3 account and store them in this
+INSTRUCTION: pop3client
+SYNTAX: pop3client|hostname|username|password|keep|interval
+Periodically fetch messages from a remote POP3 account and store them in this
room. Messages will be deleted from the remote account once successfully stored.
if Keep is set, messages won't be erased on the remote host.
Interval can specify a bigger value than the system configs value.
+
+
+INSTRUCTION: rssclient
+SYNTAX: rssclient|url
+Periodically scrape an external RSS or Atom feed and store new items in this
+room. We try to positively identify unique messages and avoid storing them
+multiple times.
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <openssl/rand.h>
#endif
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
+#include <time.h>
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#include <sys/stat.h>
#include <string.h>
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <limits.h>
#include <libcitadel.h>
#include "citadel.h"
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include "clientsocket.h"
#include "ctdl_module.h"
-/*
- * Generate a randomizationalisticized token to use for authentication of
- * a subscribe or unsubscribe request.
- */
-void listsub_generate_token(char *buf) {
- char sourcebuf[SIZ];
- static int seq = 0;
- size_t len;
-
- /* Theo, please sit down and shut up. This key doesn't have to be
- * tinfoil-hat secure, it just needs to be reasonably unguessable
- * and unique.
- */
- len = sprintf(sourcebuf, "%lx", (long) (++seq + getpid() + time(NULL)));
-
- /* Convert it to base64 so it looks cool */
- len = CtdlEncodeBase64(buf, sourcebuf, len, 0);
- if (buf[len - 1] == '\n') {
- buf[len - 1] = '\0';
- }
-}
-
-
-const RoomNetCfg ActiveSubscribers[] = {listrecp, digestrecp};
-
-int CountThisSubscriber(OneRoomNetCfg *OneRNCfg, StrBuf *email)
-{
- RoomNetCfgLine *Line;
- int found_sub = 0;
- int i;
-
- for (i = 0; i < 2; i++)
- {
- Line = OneRNCfg->NetConfigs[ActiveSubscribers[i]];
- while (Line != NULL)
- {
- if (!strcmp(ChrPtr(email),
- ChrPtr(Line->Value[0])))
- {
- ++found_sub;
- break;
- }
- Line = Line->next;
- }
- }
- return found_sub;
-}
-
-/*
- * Enter a subscription request
- */
-void do_subscribe(StrBuf **room, StrBuf **email, StrBuf **subtype, StrBuf **webpage) {
- struct ctdlroom qrbuf;
- char token[256];
- char *pcf_req;
- StrBuf *cf_req;
- StrBuf *UrlRoom;
- int found_sub = 0;
- const char *RoomMailAddress;
- OneRoomNetCfg *OneRNCfg;
- RoomNetCfgLine *Line;
- const char *EmailSender = NULL;
- long RoomMailAddressLen;
-
- if (CtdlGetRoom(&qrbuf, ChrPtr(*room)) != 0) {
- cprintf("%d There is no list called '%s'\n", ERROR + ROOM_NOT_FOUND, ChrPtr(*room));
- return;
- }
-
- if ((qrbuf.QRflags2 & QR2_SELFLIST) == 0) {
- cprintf("%d '%s' "
- "does not accept subscribe/unsubscribe requests.\n",
- ERROR + HIGHER_ACCESS_REQUIRED, qrbuf.QRname);
- return;
- }
-
- /*
- * Make sure the requested address isn't already subscribed
- */
- begin_critical_section(S_NETCONFIGS);
-
- RoomMailAddress = qrbuf.QRname;
- OneRNCfg = CtdlGetNetCfgForRoom(qrbuf.QRnumber);
- if (OneRNCfg != NULL) {
- found_sub = CountThisSubscriber(OneRNCfg, *email);
- if (StrLength(OneRNCfg->Sender) > 0) {
- EmailSender = RoomMailAddress = ChrPtr(OneRNCfg->Sender);
- }
- }
-
- if (found_sub != 0) {
- cprintf("%d '%s' is already subscribed to '%s'.\n",
- ERROR + ALREADY_EXISTS,
- ChrPtr(*email),
- RoomMailAddress);
-
- FreeRoomNetworkStruct(&OneRNCfg);
- end_critical_section(S_NETCONFIGS);
- return;
- }
-
- /*
- * Now add it to the config
- */
-
- RoomMailAddressLen = strlen(RoomMailAddress);
- listsub_generate_token(token);
- Line = (RoomNetCfgLine*)malloc(sizeof(RoomNetCfgLine));
- memset(Line, 0, sizeof(RoomNetCfgLine));
-
- Line->Value = (StrBuf**) malloc(sizeof(StrBuf*) * 5);
-
- Line->Value[0] = NewStrBufDup(*email);
- Line->Value[1] = *subtype; *subtype = NULL;
- Line->Value[2] = NewStrBufPlain(token, -1);
- Line->Value[3] = NewStrBufPlain(NULL, 10);
- StrBufPrintf(Line->Value[3], "%ld", time(NULL));
- Line->Value[4] = *webpage; *webpage = NULL;
- Line->nValues = 5;
-
- AddRoomCfgLine(OneRNCfg, &qrbuf, subpending, Line);
-
- /* Generate and send the confirmation request */
- UrlRoom = NewStrBuf();
- StrBufUrlescAppend(UrlRoom, NULL, qrbuf.QRname);
-
- cf_req = NewStrBufPlain(NULL, 2048);
- StrBufAppendBufPlain(
- cf_req,
- HKEY("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"
- "<"), 0);
- StrBufAppendBuf(cf_req, Line->Value[0], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("> to the '"), 0);
- StrBufAppendBufPlain(cf_req, RoomMailAddress, RoomMailAddressLen, 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("' mailing list.\n"
- "\n"
- "Please go here to confirm this request:\n"
- " "), 0);
- StrBufAppendBuf(cf_req, Line->Value[4], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("?room="), 0);
- StrBufAppendBuf(cf_req, UrlRoom, 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("&token="), 0);
- StrBufAppendBuf(cf_req, Line->Value[2], 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("&cmd=confirm \n"
- "\n"
- "If this request has been submitted in error and you do not\n"
- "wish to receive the '"), 0);
- StrBufAppendBufPlain(cf_req, RoomMailAddress, RoomMailAddressLen, 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("' 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>\n"
- "Someone (probably you) has submitted a request to subscribe\n"
- "<"), 0);
- StrBufAppendBuf(cf_req, Line->Value[0], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY( "> to the <B>"), 0);
-
- StrBufAppendBufPlain(cf_req, RoomMailAddress, RoomMailAddressLen, 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("'</B> mailing list.<BR><BR>\n"
- "Please click here to confirm this request:<BR>\n"
- "<A HREF=\""), 0);
- StrBufAppendBuf(cf_req, Line->Value[4], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("?room="), 0);
- StrBufAppendBuf(cf_req, UrlRoom, 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("&token="), 0);
- StrBufAppendBuf(cf_req, Line->Value[2], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("&cmd=confirm\">"), 0);
- StrBufAppendBuf(cf_req, Line->Value[4], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("?room="), 0);
- StrBufAppendBuf(cf_req, UrlRoom, 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("&token="), 0);
- StrBufAppendBuf(cf_req, Line->Value[2], 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("&cmd=confirm</A><BR><BR>\n"
- "If this request has been submitted in error and you do not\n"
- "wish to receive the '"), 0);
- StrBufAppendBufPlain(cf_req, RoomMailAddress, RoomMailAddressLen, 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("' mailing list, simply do nothing,\n"
- "and you will not receive any further mailings.\n"
- "</BODY></HTML>\n"
- "\n"
- "--__ctdlmultipart__--\n"), 0);
-
- SaveRoomNetConfigFile(OneRNCfg, qrbuf.QRnumber);
- FreeRoomNetworkStruct(&OneRNCfg);
- end_critical_section(S_NETCONFIGS);
-
- pcf_req = SmashStrBuf(&cf_req);
- quickie_message( /* This delivers the message */
- "Citadel",
- EmailSender,
- ChrPtr(*email),
- NULL,
- pcf_req,
- FMT_RFC822,
- "Please confirm your list subscription"
- );
- free(pcf_req);
- cprintf("%d Subscription entered; confirmation request sent\n", CIT_OK);
-
- FreeStrBuf(&UrlRoom);
-}
-
-
-/*
- * Enter an unsubscription request
- */
-void do_unsubscribe(StrBuf **room, StrBuf **email, StrBuf **webpage) {
- struct ctdlroom qrbuf;
- const char *EmailSender = NULL;
- char token[256];
- char *pcf_req;
- StrBuf *cf_req;
- StrBuf *UrlRoom;
- int found_sub = 0;
- const char *RoomMailAddress;
- OneRoomNetCfg *OneRNCfg;
- RoomNetCfgLine *Line;
- long RoomMailAddressLen;
-
- if (CtdlGetRoom(&qrbuf, ChrPtr(*room)) != 0) {
- cprintf("%d There is no list called '%s'\n",
- ERROR + ROOM_NOT_FOUND, ChrPtr(*room));
- return;
- }
-
- if ((qrbuf.QRflags2 & QR2_SELFLIST) == 0) {
- cprintf("%d '%s' "
- "does not accept subscribe/unsubscribe requests.\n",
- ERROR + HIGHER_ACCESS_REQUIRED, qrbuf.QRname);
- return;
- }
-
- listsub_generate_token(token);
-
- /*
- * Make sure there's actually a subscription there to remove
- */
- begin_critical_section(S_NETCONFIGS);
- RoomMailAddress = qrbuf.QRname;
- OneRNCfg = CtdlGetNetCfgForRoom(qrbuf.QRnumber);
- if (OneRNCfg!=NULL) {
- found_sub = CountThisSubscriber(OneRNCfg, *email);
- if (StrLength(OneRNCfg->Sender) > 0)
- EmailSender = RoomMailAddress = ChrPtr(OneRNCfg->Sender);
- }
-
- if (found_sub == 0) {
- cprintf("%d '%s' is not subscribed to '%s'.\n", ERROR + NO_SUCH_USER, ChrPtr(*email), qrbuf.QRname);
- FreeRoomNetworkStruct(&OneRNCfg);
- end_critical_section(S_NETCONFIGS);
- return;
- }
-
- /*
- * Ok, now enter the unsubscribe-pending entry.
- */
- RoomMailAddressLen = strlen(RoomMailAddress);
- listsub_generate_token(token);
- Line = (RoomNetCfgLine*)malloc(sizeof(RoomNetCfgLine));
- memset(Line, 0, sizeof(RoomNetCfgLine));
-
- Line->Value = (StrBuf**) malloc(sizeof(StrBuf*) * 4);
-
- Line->Value[0] = NewStrBufDup(*email);
- Line->Value[1] = NewStrBufPlain(token, -1);
- Line->Value[2] = NewStrBufPlain(NULL, 10);
- StrBufPrintf(Line->Value[2], "%ld", time(NULL));
- Line->Value[3] = *webpage; *webpage = NULL;
- Line->nValues = 4;
-
- AddRoomCfgLine(OneRNCfg, &qrbuf, unsubpending, Line);
-
- /* Generate and send the confirmation request */
- UrlRoom = NewStrBuf();
- StrBufUrlescAppend(UrlRoom, NULL, qrbuf.QRname);
-
- cf_req = NewStrBufPlain(NULL, 2048);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("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"
- "<"), 0);
- StrBufAppendBuf(cf_req, Line->Value[0], 0);
-
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("> from the '"), 0);
- StrBufAppendBufPlain(cf_req, RoomMailAddress, RoomMailAddressLen, 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("' mailing list.\n"
- "\n"
- "Please go here to confirm this request:\n "), 0);
- StrBufAppendBuf(cf_req, Line->Value[3], 0);
- StrBufAppendBufPlain(cf_req, HKEY("?room="), 0);
- StrBufAppendBuf(cf_req, UrlRoom, 0);
- StrBufAppendBufPlain(cf_req, HKEY("&token="), 0);
- StrBufAppendBuf(cf_req, Line->Value[1], 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("&cmd=confirm \n"
- "\n"
- "If this request has been submitted in error and you do not\n"
- "wish to unsubscribe from the '"), 0);
-
- StrBufAppendBufPlain(cf_req, RoomMailAddress, RoomMailAddressLen, 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("' mailing list, simply do nothing,\n"
- "and the request will not be processed.\n"
- "\n"
- "--__ctdlmultipart__\n"
- "Content-type: text/html\n"
- "\n"
- "<HTML><BODY>\n"
- "Someone (probably you) has submitted a request to unsubscribe\n"
- "<"), 0);
- StrBufAppendBuf(cf_req, Line->Value[0], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("> from the <B>"), 0);
- StrBufAppendBufPlain(cf_req, RoomMailAddress, RoomMailAddressLen, 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("</B> mailing list.<BR><BR>\n"
- "Please click here to confirm this request:<BR>\n"
- "<A HREF=\""), 0);
- StrBufAppendBuf(cf_req, Line->Value[3], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("?room="), 0);
- StrBufAppendBuf(cf_req, UrlRoom, 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("&token="), 0);
- StrBufAppendBuf(cf_req, Line->Value[1], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("&cmd=confirm\">"), 0);
- StrBufAppendBuf(cf_req, Line->Value[3], 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("?room="), 0);
- StrBufAppendBuf(cf_req, UrlRoom, 0);
-
- StrBufAppendBufPlain(cf_req, HKEY("&token="), 0);
- StrBufAppendBuf(cf_req, Line->Value[1], 0);
-
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("&cmd=confirm</A><BR><BR>\n"
- "If this request has been submitted in error and you do not\n"
- "wish to unsubscribe from the '"), 0);
- StrBufAppendBufPlain(cf_req, RoomMailAddress, RoomMailAddressLen, 0);
-
- StrBufAppendBufPlain(
- cf_req,
- HKEY("' mailing list, simply do nothing,\n"
- "and the request will not be processed.\n"
- "</BODY></HTML>\n"
- "\n"
- "--__ctdlmultipart__--\n"), 0);
-
- SaveRoomNetConfigFile(OneRNCfg, qrbuf.QRnumber);
- FreeRoomNetworkStruct(&OneRNCfg);
- end_critical_section(S_NETCONFIGS);
-
- pcf_req = SmashStrBuf(&cf_req);
- quickie_message( /* This delivers the message */
- "Citadel",
- EmailSender,
- ChrPtr(*email),
- NULL,
- pcf_req,
- FMT_RFC822,
- "Please confirm your unsubscribe request"
- );
-
- free(pcf_req);
- FreeStrBuf(&UrlRoom);
- cprintf("%d Unubscription noted; confirmation request sent\n", CIT_OK);
-}
-
-
-const RoomNetCfg ConfirmSubscribers[] = {subpending, unsubpending};
-
-/*
- * Confirm a subscribe/unsubscribe request.
- */
-void do_confirm(StrBuf **room, StrBuf **token) {
- struct ctdlroom qrbuf;
- OneRoomNetCfg *OneRNCfg;
- RoomNetCfgLine *Line;
- RoomNetCfgLine *ConfirmLine = NULL;
- RoomNetCfgLine *RemoveLine = NULL;
- RoomNetCfgLine **PrevLine;
- int success = 0;
- RoomNetCfg ConfirmType;
- const char *errmsg = "";
- int i;
-
- if (CtdlGetRoom(&qrbuf, ChrPtr(*room)) != 0) {
- cprintf("%d There is no list called '%s'\n",
- ERROR + ROOM_NOT_FOUND, ChrPtr(*room));
- return;
- }
-
- if ((qrbuf.QRflags2 & QR2_SELFLIST) == 0) {
- cprintf("%d '%s' "
- "does not accept subscribe/unsubscribe requests.\n",
- ERROR + HIGHER_ACCESS_REQUIRED, qrbuf.QRname);
- return;
- }
-
- if (StrLength(*token) == 0) {
- cprintf("%d empty token.\n", ERROR + ILLEGAL_VALUE);
- return;
- }
- /*
- * Now start scanning this room's netconfig file for the
- * specified token.
- */
- begin_critical_section(S_NETCONFIGS);
- OneRNCfg = CtdlGetNetCfgForRoom(qrbuf.QRnumber);
-
- ConfirmType = maxRoomNetCfg;
- if (OneRNCfg==NULL)
- {
- errmsg = "no networking config found";
- }
- else for (i = 0; i < 2; i++)
- {
- int offset;
-
- if (ConfirmSubscribers[i] == subpending)
- offset = 2;
- else
- offset = 1;
- PrevLine = &OneRNCfg->NetConfigs[ConfirmSubscribers[i]];
- Line = *PrevLine;
- while (Line != NULL)
- {
- if (!strcasecmp(ChrPtr(*token),
- ChrPtr(Line->Value[offset])))
- {
- ConfirmLine = Line;
- *PrevLine = Line->next; /* Remove it from the list */
- ConfirmType = ConfirmSubscribers[i];
- ConfirmLine->next = NULL;
-
- i += 100;
- break;
-
- }
- PrevLine = &(*PrevLine)->next;
- Line = Line->next;
- }
- if (ConfirmType == maxRoomNetCfg)
- {
- errmsg = "No active un/subscribe request found";
- }
- }
-
- if (ConfirmType == subpending)
- {
- if (CountThisSubscriber(OneRNCfg, ConfirmLine->Value[0]) == 0)
- {
- if (!strcasecmp(ChrPtr(ConfirmLine->Value[2]),
- ("digest")))
- {
- ConfirmType = digestrecp;
- }
- else /* "list" */
- {
- ConfirmType = listrecp;
- }
-
- syslog(LOG_NOTICE,
- "Mailing list: %s subscribed to %s with token %s\n",
- ChrPtr(ConfirmLine->Value[0]),
- qrbuf.QRname,
- ChrPtr(*token));
-
- FreeStrBuf(&ConfirmLine->Value[1]);
- FreeStrBuf(&ConfirmLine->Value[2]);
- FreeStrBuf(&ConfirmLine->Value[3]);
- FreeStrBuf(&ConfirmLine->Value[4]);
- ConfirmLine->nValues = 1;
-
- AddRoomCfgLine(OneRNCfg, &qrbuf, ConfirmType, ConfirmLine);
- success = 1;
- }
- else
- {
- /* whipe duplicate subscribe entry... */
- errmsg = "already subscribed";
- }
- }
- else if (ConfirmType == unsubpending)
- {
-
- for (i = 0; i < 2; i++)
- {
- PrevLine = &OneRNCfg->NetConfigs[ActiveSubscribers[i]];
- Line = *PrevLine;
- while (Line != NULL)
- {
- if (!strcasecmp(ChrPtr(ConfirmLine->Value[0]),
- ChrPtr(Line->Value[0])))
- {
- success = 1;
- RemoveLine = Line;
- *PrevLine = Line->next; /* Remove it from the list */
- RemoveLine->next = NULL;
- if (RemoveLine != NULL)
- DeleteGenericCfgLine(NULL/*TODO*/, &RemoveLine);
- Line = *PrevLine;
- continue;
- }
- PrevLine = &(*PrevLine)->next;
- Line = Line->next;
- }
- }
-
- if (success)
- {
- syslog(LOG_NOTICE,
- "Mailing list: %s unsubscribed to %s with token %s\n",
- ChrPtr(ConfirmLine->Value[0]),
- qrbuf.QRname,
- ChrPtr(*token));
- }
- else
- {
- errmsg = "no subscriber found for this unsubscription request";
- }
- DeleteGenericCfgLine(NULL/*TODO*/, &ConfirmLine);
- }
-
- SaveRoomNetConfigFile(OneRNCfg, qrbuf.QRnumber);
- FreeRoomNetworkStruct(&OneRNCfg);
- end_critical_section(S_NETCONFIGS);
-
- /*
- * Did we do anything useful today?
- */
- if (success) {
- cprintf("%d %d operation(s) confirmed.\n", CIT_OK, success);
- }
- else {
- syslog(LOG_NOTICE, "failed processing (un)subscribe request: %s",
- errmsg);
- cprintf("%d Invalid token.\n", ERROR + ILLEGAL_VALUE);
- }
-
-}
+// FIXME rewrite the subscribe-o-matic AJC 2021
/*
*/
void cmd_subs(char *cmdbuf)
{
- const char *Pos = NULL;
- StrBuf *Segments[20];
- int i=1;
-
- memset(Segments, 0, sizeof(StrBuf*) * 20);
- Segments[0] = NewStrBufPlain(cmdbuf, -1);
- while ((Pos != StrBufNOTNULL) && (i < 20))
- {
- Segments[i] = NewStrBufPlain(NULL, StrLength(Segments[0]));
- StrBufExtract_NextToken(Segments[i], Segments[0], &Pos, '|');
- i++;
- }
-
- if (!strcasecmp(ChrPtr(Segments[1]), "subscribe")) {
- if ( (strcasecmp(ChrPtr(Segments[4]), "list"))
- && (strcasecmp(ChrPtr(Segments[4]), "digest")) ) {
- cprintf("%d Invalid subscription type '%s'\n",
- ERROR + ILLEGAL_VALUE, ChrPtr(Segments[4]));
- }
- else {
- do_subscribe(&Segments[2], &Segments[3], &Segments[4], &Segments[5]);
- }
- }
- else if (!strcasecmp(ChrPtr(Segments[1]), "unsubscribe")) {
- do_unsubscribe(&Segments[2], &Segments[3], &Segments[4]);
- }
- else if (!strcasecmp(ChrPtr(Segments[1]), "confirm")) {
- do_confirm(&Segments[2], &Segments[3]);
- }
- else {
- cprintf("%d Invalid command\n", ERROR + ILLEGAL_VALUE);
- }
-
- for (; i>=0; i--)
- {
- FreeStrBuf(&Segments[i]);
- }
+ cprintf("%d Invalid command\n", ERROR + ILLEGAL_VALUE);
}
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <ctype.h>
-void network_deliver_digest(SpoolControl *sc);
-void network_spool_msg(long msgnum, void *userdata);
*
*/
-typedef struct SpoolControl SpoolControl;
-
-struct SpoolControl {
- OneRoomNetCfg *RNCfg;
- struct ctdlroom room;
- StrBuf *Users[maxRoomNetCfg];
- StrBuf *RoomInfo;
- StrBuf *ListID;
- FILE *digestfp;
- int haveDigest;
- int num_msgs_spooled;
- long lastsent;
- HashList *working_ignetcfg;
- HashList *the_netmap;
- SpoolControl *next;
-};
-
-
-void network_spoolout_room(SpoolControl *sc);
-
-void InspectQueuedRoom(SpoolControl **pSC,
- RoomProcList *room_to_spool,
- HashList *working_ignetcfg,
- HashList *the_netmap);
-
-int HaveSpoolConfig(OneRoomNetCfg* RNCfg);
-
-void network_do_spoolin(HashList *working_ignetcfg, HashList *the_netmap, int *netmap_changed);
-void free_spoolcontrol_struct(SpoolControl **scc);
-void free_spoolcontrol_struct_members(SpoolControl *scc);
-int writenfree_spoolcontrol_file(SpoolControl **scc, char *filename);
-int read_spoolcontrol_file(SpoolControl **scc, char *filename);
-
-void aggregate_recipients(StrBuf **recps, RoomNetCfg Which, OneRoomNetCfg *OneRNCfg, long nSegments);
-
-void CalcListID(SpoolControl *sc);
/*
* This module handles network mail and mailing list processing.
*
- * Copyright (c) 2000-2020 by the citadel.org team
+ * Copyright (c) 2000-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.
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
+#include <time.h>
#ifdef HAVE_SYSCALL_H
# include <syscall.h>
#else
#include "ctdl_module.h"
#include "netspool.h"
#include "netmail.h"
-
-void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char *RoomName);
-
-void aggregate_recipients(StrBuf **recps, RoomNetCfg Which, OneRoomNetCfg *OneRNCfg, long nSegments)
-{
- int i;
- size_t recps_len = 0;
- RoomNetCfgLine *nptr;
-
- *recps = NULL;
- /*
- * Figure out how big a buffer we need to allocate
- */
- for (nptr = OneRNCfg->NetConfigs[Which]; nptr != NULL; nptr = nptr->next) {
- recps_len = recps_len + StrLength(nptr->Value[0]) + 2;
- }
-
- /* Nothing todo... */
- if (recps_len == 0)
- return;
-
- *recps = NewStrBufPlain(NULL, recps_len);
-
- if (*recps == NULL) {
- syslog(LOG_ERR, "netmail: cannot allocate %ld bytes for recps", (long)recps_len);
- abort();
- }
-
- /* Each recipient */
- for (nptr = OneRNCfg->NetConfigs[Which]; nptr != NULL; nptr = nptr->next) {
- if (nptr != OneRNCfg->NetConfigs[Which]) {
- for (i = 0; i < nSegments; i++)
- StrBufAppendBufPlain(*recps, HKEY(","), i);
- }
- StrBufAppendBuf(*recps, nptr->Value[0], 0);
- if (Which == ignet_push_share)
- {
- StrBufAppendBufPlain(*recps, HKEY(","), 0);
- StrBufAppendBuf(*recps, nptr->Value[1], 0);
-
- }
- }
-}
-
-static void ListCalculateSubject(struct CtdlMessage *msg)
-{
- struct CitContext *CCC = CC;
- StrBuf *Subject, *FlatSubject;
- int rlen;
- char *pCh;
-
- if (CM_IsEmpty(msg, eMsgSubject)) {
- Subject = NewStrBufPlain(HKEY("(no subject)"));
- }
- else {
- Subject = NewStrBufPlain(CM_KEY(msg, eMsgSubject));
- }
- FlatSubject = NewStrBufPlain(NULL, StrLength(Subject));
- StrBuf_RFC822_to_Utf8(FlatSubject, Subject, NULL, NULL);
-
- rlen = strlen(CCC->room.QRname);
- pCh = strstr(ChrPtr(FlatSubject), CCC->room.QRname);
- if ((pCh == NULL) ||
- (*(pCh + rlen) != ']') ||
- (pCh == ChrPtr(FlatSubject)) ||
- (*(pCh - 1) != '[')
- )
- {
- StrBuf *tmp;
- StrBufPlain(Subject, HKEY("["));
- StrBufAppendBufPlain(Subject,
- CCC->room.QRname,
- rlen, 0);
- StrBufAppendBufPlain(Subject, HKEY("] "), 0);
- StrBufAppendBuf(Subject, FlatSubject, 0);
- /* so we can free the right one swap them */
- tmp = Subject;
- Subject = FlatSubject;
- FlatSubject = tmp;
- StrBufRFC2047encode(&Subject, FlatSubject);
- }
-
- CM_SetAsFieldSB(msg, eMsgSubject, &Subject);
-
- FreeStrBuf(&FlatSubject);
-}
-
-/*
- * Deliver digest messages
- */
-void network_deliver_digest(SpoolControl *sc)
-{
- struct CitContext *CCC = CC;
- long len;
- char buf[SIZ];
- char *pbuf;
- struct CtdlMessage *msg = NULL;
- long msglen;
- recptypes *valid;
- char bounce_to[256];
-
- if (sc->Users[digestrecp] == NULL)
- return;
-
- msg = malloc(sizeof(struct CtdlMessage));
- memset(msg, 0, sizeof(struct CtdlMessage));
- msg->cm_magic = CTDLMESSAGE_MAGIC;
- msg->cm_format_type = FMT_RFC822;
- msg->cm_anon_type = MES_NORMAL;
-
- CM_SetFieldLONG(msg, eTimestamp, time(NULL));
- CM_SetField(msg, eAuthor, CCC->room.QRname, strlen(CCC->room.QRname));
- len = snprintf(buf, sizeof buf, "[%s]", CCC->room.QRname);
- CM_SetField(msg, eMsgSubject, buf, len);
-
- CM_SetField(msg, erFc822Addr, SKEY(sc->Users[roommailalias]));
- CM_SetField(msg, eRecipient, SKEY(sc->Users[roommailalias]));
-
- /* Set the 'List-ID' header */
- CM_SetField(msg, eListID, SKEY(sc->ListID));
-
- /*
- * Go fetch the contents of the digest
- */
- fseek(sc->digestfp, 0L, SEEK_END);
- msglen = ftell(sc->digestfp);
-
- pbuf = malloc(msglen + 1);
- fseek(sc->digestfp, 0L, SEEK_SET);
- fread(pbuf, (size_t)msglen, 1, sc->digestfp);
- pbuf[msglen] = '\0';
- CM_SetAsField(msg, eMesageText, &pbuf, msglen);
-
- /* Now generate the delivery instructions */
-
- /* Where do we want bounces and other noise to be heard?
- * Surely not the list members! */
- snprintf(bounce_to, sizeof bounce_to, "room_aide@%s", CtdlGetConfigStr("c_fqdn"));
-
- /* Now submit the message */
- valid = validate_recipients(ChrPtr(sc->Users[digestrecp]), NULL, 0);
- if (valid != NULL) {
- valid->bounce_to = strdup(bounce_to);
- valid->envelope_from = strdup(bounce_to);
- CtdlSubmitMsg(msg, valid, NULL);
- }
- CM_Free(msg);
- free_recipients(valid);
-}
-
-
-void network_process_digest(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send)
-{
-
- struct CtdlMessage *msg = NULL;
-
- if (sc->Users[digestrecp] == NULL)
- return;
-
- /* If there are digest recipients, we have to build a digest */
- if (sc->digestfp == NULL) {
-
- sc->digestfp = tmpfile();
-
- if (sc->digestfp == NULL)
- return;
-
- sc->haveDigest = ftell(sc->digestfp) > 0;
- if (!sc->haveDigest) {
- fprintf(sc->digestfp, "Content-type: text/plain\n\n");
- }
- sc->haveDigest = 1;
- }
-
- msg = CM_Duplicate(omsg);
- if (msg != NULL) {
- sc->haveDigest = 1;
- fprintf(sc->digestfp,
- " -----------------------------------"
- "------------------------------------"
- "-------\n");
- fprintf(sc->digestfp, "From: ");
- if (!CM_IsEmpty(msg, eAuthor)) {
- fprintf(sc->digestfp,
- "%s ",
- msg->cm_fields[eAuthor]);
- }
- if (!CM_IsEmpty(msg, erFc822Addr)) {
- fprintf(sc->digestfp,
- "<%s> ",
- msg->cm_fields[erFc822Addr]);
- }
- fprintf(sc->digestfp, "\n");
- if (!CM_IsEmpty(msg, eMsgSubject)) {
- fprintf(sc->digestfp,
- "Subject: %s\n",
- msg->cm_fields[eMsgSubject]);
- }
-
- CC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
-
- safestrncpy(CC->preferred_formats,
- "text/plain",
- sizeof CC->preferred_formats);
-
- CtdlOutputPreLoadedMsg(msg,
- MT_CITADEL,
- HEADERS_NONE,
- 0, 0, 0);
-
- StrBufTrim(CC->redirect_buffer);
- fwrite(HKEY("\n"), 1, sc->digestfp);
- fwrite(SKEY(CC->redirect_buffer), 1, sc->digestfp);
- fwrite(HKEY("\n"), 1, sc->digestfp);
-
- FreeStrBuf(&CC->redirect_buffer);
-
- sc->num_msgs_spooled += 1;
- CM_Free(msg);
- }
-}
-
-
-void network_process_list(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send)
-{
- struct CtdlMessage *msg = NULL;
-
- /*
- * Process mailing list recipients
- */
- if (sc->Users[listrecp] == NULL)
- return;
-
- /* create our own copy of the message.
- * We're going to need to modify it
- * in order to insert the [list name] in it, etc.
- */
-
- msg = CM_Duplicate(omsg);
-
-
- CM_SetField(msg, eReplyTo, SKEY(sc->Users[roommailalias]));
-
- /* if there is no other recipient, Set the recipient
- * of the list message to the email address of the
- * room itself.
- */
- if (CM_IsEmpty(msg, eRecipient))
- {
- CM_SetField(msg, eRecipient, SKEY(sc->Users[roommailalias]));
- }
-
- /* Set the 'List-ID' header */
- CM_SetField(msg, eListID, SKEY(sc->ListID));
-
-
- /* Prepend "[List name]" to the subject */
- ListCalculateSubject(msg);
-
- /* Handle delivery */
- network_deliver_list(msg, sc, CC->room.QRname);
- CM_Free(msg);
-}
-
-/*
- * Deliver list messages to everyone on the list ... efficiently
- */
-void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char *RoomName)
-{
- recptypes *valid;
- char bounce_to[256];
-
- /* Don't do this if there were no recipients! */
- if (sc->Users[listrecp] == NULL)
- return;
-
- /* Now generate the delivery instructions */
-
- /* Where do we want bounces and other noise to be heard?
- * Surely not the list members! */
- snprintf(bounce_to, sizeof bounce_to, "room_aide@%s", CtdlGetConfigStr("c_fqdn"));
-
- /* Now submit the message */
- valid = validate_recipients(ChrPtr(sc->Users[listrecp]), NULL, 0);
- if (valid != NULL) {
- valid->bounce_to = strdup(bounce_to);
- valid->envelope_from = strdup(bounce_to);
- valid->sending_room = strdup(RoomName);
- CtdlSubmitMsg(msg, valid, NULL);
- free_recipients(valid);
- }
- /* Do not call CM_Free(msg) here; the caller will free it. */
-}
-
-
-void network_process_participate(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send)
-{
- struct CtdlMessage *msg = NULL;
- int ok_to_participate = 0;
- recptypes *valid;
-
- /*
- * Process client-side list participations for this room
- */
- if (sc->Users[participate] == NULL)
- return;
-
- msg = CM_Duplicate(omsg);
-
- /* Only send messages which originated on our own
- * Citadel network, otherwise we'll end up sending the
- * remote mailing list's messages back to it, which
- * is rude...
- */
- ok_to_participate = 0;
-
- // FIXME -- After we removed CitaNet/IGnet support , we now need a new heuristic to determine
- // whether a message originated locally. This means the "participate" mode no longer works.
- // We'll definitely need to refactor this when we do other federated stuff later.
-
- if (ok_to_participate)
- {
- /* Replace the Internet email address of the
- * actual author with the email address of the
- * room itself, so the remote listserv doesn't
- * reject us.
- */
- CM_SetField(msg, erFc822Addr, SKEY(sc->Users[roommailalias]));
-
- valid = validate_recipients(ChrPtr(sc->Users[participate]) , NULL, 0);
-
- CM_SetField(msg, eRecipient, SKEY(sc->Users[roommailalias]));
- CtdlSubmitMsg(msg, valid, "");
- free_recipients(valid);
- }
- CM_Free(msg);
-}
-
-
-/*
- * Spools out one message from the list.
- */
-void network_spool_msg(long msgnum, void *userdata)
-{
- struct CtdlMessage *msg = NULL;
- long delete_after_send = 0; /* Set to 1 to delete after spooling */
- SpoolControl *sc;
-
- sc = (SpoolControl *)userdata;
- msg = CtdlFetchMessage(msgnum, 1);
-
- if (msg == NULL)
- {
- syslog(LOG_ERR, "netmail: failed to load Message <%ld> from disk", msgnum);
- return;
- }
- network_process_list(sc, msg, &delete_after_send);
- network_process_digest(sc, msg, &delete_after_send);
- network_process_participate(sc, msg, &delete_after_send);
-
- CM_Free(msg);
-
- /* update lastsent */
- sc->lastsent = msgnum;
-
- /* Delete this message if delete-after-send is set */
- if (delete_after_send) {
- CtdlDeleteMessages(CC->room.QRname, &msgnum, 1, "");
- }
-}
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
+#include <time.h>
+
#ifdef HAVE_SYSCALL_H
# include <syscall.h>
#else
#include "netmail.h"
-void ParseLastSent(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG)
-{
- RoomNetCfgLine *nptr;
- nptr = (RoomNetCfgLine *) malloc(sizeof(RoomNetCfgLine));
- memset(nptr, 0, sizeof(RoomNetCfgLine));
- OneRNCFG->lastsent = extract_long(LinePos, 0);
- OneRNCFG->NetConfigs[ThisOne->C] = nptr;
-}
-
-void ParseRoomAlias(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *rncfg)
-{
- if (rncfg->Sender != NULL) {
- return;
- }
-
- ParseGeneric(ThisOne, Line, LinePos, rncfg);
- rncfg->Sender = NewStrBufDup(rncfg->NetConfigs[roommailalias]->Value[0]);
-}
-
-void ParseSubPendingLine(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG)
-{
- if (time(NULL) - extract_long(LinePos, 3) > EXP)
- return; /* expired subscription... */
-
- ParseGeneric(ThisOne, Line, LinePos, OneRNCFG);
-}
-void ParseUnSubPendingLine(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG)
-{
- if (time(NULL) - extract_long(LinePos, 2) > EXP)
- return; /* expired subscription... */
-
- ParseGeneric(ThisOne, Line, LinePos, OneRNCFG);
-}
-
-
-void SerializeLastSent(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *RNCfg, RoomNetCfgLine *data)
-{
- StrBufAppendBufPlain(OutputBuffer, CKEY(ThisOne->Str), 0);
- StrBufAppendPrintf(OutputBuffer, "|%ld\n", RNCfg->lastsent);
-}
-
-void DeleteLastSent(const CfgLineType *ThisOne, RoomNetCfgLine **data)
-{
- free(*data);
- *data = NULL;
-}
-
-static const RoomNetCfg SpoolCfgs [4] = {
- listrecp,
- digestrecp,
- participate,
-};
-
-static const long SpoolCfgsCopyN [4] = {
- 1, 1, 1, 2
-};
-
-int HaveSpoolConfig(OneRoomNetCfg* RNCfg)
-{
- int i;
- int interested = 0;
- for (i=0; i < 4; i++) if (RNCfg->NetConfigs[SpoolCfgs[i]] == NULL) interested = 1;
- return interested;
-}
-
-
-void InspectQueuedRoom(SpoolControl **pSC,
- RoomProcList *room_to_spool,
- HashList *working_ignetcfg,
- HashList *the_netmap
-) {
- SpoolControl *sc;
- int i = 0;
-
- syslog(LOG_INFO, "netspool: InspectQueuedRoom(%s)", room_to_spool->name);
-
- sc = (SpoolControl*)malloc(sizeof(SpoolControl));
- memset(sc, 0, sizeof(SpoolControl));
- sc->working_ignetcfg = working_ignetcfg;
- sc->the_netmap = the_netmap;
-
- /*
- * If the room doesn't exist, don't try to perform its networking tasks.
- * Normally this should never happen, but once in a while maybe a room gets
- * queued for networking and then deleted before it can happen.
- */
- if (CtdlGetRoom(&sc->room, room_to_spool->name) != 0) {
- syslog(LOG_INFO, "netspool: ERROR; cannot load <%s>", room_to_spool->name);
- free(sc);
- return;
- }
-
- assert(sc->RNCfg == NULL); // checking to make sure we cleared it from last time
-
- sc->RNCfg = CtdlGetNetCfgForRoom(sc->room.QRnumber);
-
- syslog(LOG_DEBUG, "netspool: room <%s> highest=%ld lastsent=%ld", room_to_spool->name, sc->room.QRhighest, sc->RNCfg->lastsent);
- if ( (!HaveSpoolConfig(sc->RNCfg)) || (sc->room.QRhighest <= sc->RNCfg->lastsent) )
- {
- // There is nothing to send from this room.
- syslog(LOG_DEBUG, "netspool: nothing to do for <%s>", room_to_spool->name);
- FreeRoomNetworkStruct(&sc->RNCfg);
- sc->RNCfg = NULL;
- free(sc);
- return;
- }
-
- sc->lastsent = sc->RNCfg->lastsent;
- room_to_spool->lastsent = sc->lastsent;
-
- /* Now lets remember whats needed for the actual work... */
-
- for (i=0; i < 4; i++)
- {
- aggregate_recipients(&sc->Users[SpoolCfgs[i]], SpoolCfgs[i], sc->RNCfg, SpoolCfgsCopyN[i]);
- }
-
- if (StrLength(sc->RNCfg->Sender) > 0) {
- sc->Users[roommailalias] = NewStrBufDup(sc->RNCfg->Sender);
- }
-
- sc->next = *pSC;
- *pSC = sc;
-
- FreeRoomNetworkStruct(&sc->RNCfg); // done with this for now, we'll grab it again next time
- sc->RNCfg = NULL;
-}
-
-
-void CalcListID(SpoolControl *sc)
-{
- StrBuf *RoomName;
- struct CitContext *CCC = CC;
-#define MAX_LISTIDLENGTH 150
-
- // Load the room banner as the list description
- struct CtdlMessage *msg = CtdlFetchMessage(sc->room.msgnum_info, 1);
- if (msg != NULL) {
- CC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
- CtdlOutputPreLoadedMsg(msg, MT_CITADEL, HEADERS_NONE, 0, 0, 0);
- CM_Free(msg);
- sc->RoomInfo = CC->redirect_buffer;
- CC->redirect_buffer = NULL;
- }
- else {
- sc->RoomInfo = NewStrBufPlain(NULL, SIZ);
- }
-
- // Calculate the List ID
- sc->ListID = NewStrBufPlain(NULL, 1024);
- if (StrLength(sc->RoomInfo) > 0)
- {
- const char *Pos = NULL;
- StrBufSipLine(sc->ListID, sc->RoomInfo, &Pos);
-
- if (StrLength(sc->ListID) > MAX_LISTIDLENGTH)
- {
- StrBufCutAt(sc->ListID, MAX_LISTIDLENGTH, NULL);
- StrBufAppendBufPlain(sc->ListID, HKEY("..."), 0);
- }
- StrBufAsciify(sc->ListID, ' ');
- }
- else
- {
- StrBufAppendBufPlain(sc->ListID, CCC->room.QRname, -1, 0);
- }
-
- StrBufAppendBufPlain(sc->ListID, HKEY("<"), 0);
- RoomName = NewStrBufPlain (sc->room.QRname, -1);
- StrBufAsciify(RoomName, '_');
- StrBufReplaceChars(RoomName, ' ', '_');
-
- if (StrLength(sc->Users[roommailalias]) > 0)
- {
- long Pos;
- const char *AtPos;
-
- Pos = StrLength(sc->ListID);
- StrBufAppendBuf(sc->ListID, sc->Users[roommailalias], 0);
- AtPos = strchr(ChrPtr(sc->ListID) + Pos, '@');
-
- if (AtPos != NULL)
- {
- StrBufPeek(sc->ListID, AtPos, 0, '.');
- }
- }
- else
- {
- StrBufAppendBufPlain(sc->ListID, HKEY("room_"), 0);
- StrBufAppendBuf(sc->ListID, RoomName, 0);
- StrBufAppendBufPlain(sc->ListID, HKEY("."), 0);
- StrBufAppendBufPlain(sc->ListID, CtdlGetConfigStr("c_fqdn"), -1, 0);
- /*
- * this used to be:
- * roomname <Room-Number.list-id.fqdn>
- * according to rfc2919.txt it only has to be a unique identifier
- * under the domain of the system;
- * in general MUAs use it to calculate the reply address nowadays.
- */
- }
- StrBufAppendBufPlain(sc->ListID, HKEY(">"), 0);
-
- if (StrLength(sc->Users[roommailalias]) == 0)
- {
- sc->Users[roommailalias] = NewStrBuf();
-
- StrBufAppendBufPlain(sc->Users[roommailalias], HKEY("room_"), 0);
- StrBufAppendBuf(sc->Users[roommailalias], RoomName, 0);
- StrBufAppendBufPlain(sc->Users[roommailalias], HKEY("@"), 0);
- StrBufAppendBufPlain(sc->Users[roommailalias], CtdlGetConfigStr("c_fqdn"), -1, 0);
-
- StrBufLowerCase(sc->Users[roommailalias]);
- }
-
- FreeStrBuf(&RoomName);
-}
-
-
-/*
- * Batch up and send all outbound traffic from the current room (this is definitely used for mailing lists)
- */
-void network_spoolout_room(SpoolControl *sc)
-{
- struct CitContext *CCC = CC;
- char buf[SIZ];
- int i;
- long lastsent;
-
- /*
- * If the room doesn't exist, don't try to perform its networking tasks.
- * Normally this should never happen, but once in a while maybe a room gets
- * queued for networking and then deleted before it can happen.
- */
- memcpy (&CCC->room, &sc->room, sizeof(ctdlroom));
-
- syslog(LOG_INFO, "netspool: network_spoolout_room(room=%s, lastsent=%ld)", CCC->room.QRname, sc->lastsent);
-
- CalcListID(sc);
-
- /* remember where we started... */
- lastsent = sc->lastsent;
-
- /* Fetch the messages we ought to send & prepare them. */
- CtdlForEachMessage(MSGS_GT, sc->lastsent, NULL, NULL, NULL, network_spool_msg, sc);
-
- if (StrLength(sc->Users[roommailalias]) > 0)
- {
- long len;
- len = StrLength(sc->Users[roommailalias]);
- if (len + 1 > sizeof(buf))
- len = sizeof(buf) - 1;
- memcpy(buf, ChrPtr(sc->Users[roommailalias]), len);
- buf[len] = '\0';
- }
- else
- {
- snprintf(buf, sizeof buf, "room_%s@%s", CCC->room.QRname, CtdlGetConfigStr("c_fqdn"));
- }
-
- for (i=0; buf[i]; ++i) {
- buf[i] = tolower(buf[i]);
- if (isspace(buf[i])) buf[i] = '_';
- }
-
- /* If we wrote a digest, deliver it and then close it */
- if ( (sc->Users[digestrecp] != NULL) && (sc->digestfp != NULL) )
- {
- fprintf(sc->digestfp,
- " ------------------------------------------------------------------------------\n"
- "You are subscribed to the '%s' list.\n"
- "To post to the list: %s\n",
- CCC->room.QRname, buf
- );
- network_deliver_digest(sc); /* deliver */
- fclose(sc->digestfp);
- sc->digestfp = NULL;
- }
-
- /* Now rewrite the netconfig */
- syslog(LOG_DEBUG, "netspool: lastsent was %ld , now it is %ld", lastsent, sc->lastsent);
- if (sc->lastsent != lastsent)
- {
- OneRoomNetCfg *r;
-
- begin_critical_section(S_NETCONFIGS);
- r = CtdlGetNetCfgForRoom(sc->room.QRnumber);
- r->lastsent = sc->lastsent;
- SaveRoomNetConfigFile(r, sc->room.QRnumber);
- FreeRoomNetworkStruct(&r);
- end_critical_section(S_NETCONFIGS);
- }
-}
-
-
-void free_spoolcontrol_struct(SpoolControl **sc)
-{
- free_spoolcontrol_struct_members(*sc);
- free(*sc);
- *sc = NULL;
-}
-
-
-void free_spoolcontrol_struct_members(SpoolControl *sc)
-{
- int i;
- FreeStrBuf(&sc->RoomInfo);
- FreeStrBuf(&sc->ListID);
- for (i = 0; i < maxRoomNetCfg; i++)
- FreeStrBuf(&sc->Users[i]);
-}
-
-
/*
* Module entry point
*/
{
if (!threading)
{
- CtdlREGISTERRoomCfgType(subpending, ParseSubPendingLine, 0, 5, SerializeGeneric, DeleteGenericCfgLine);
- CtdlREGISTERRoomCfgType(unsubpending, ParseUnSubPendingLine, 0, 4, SerializeGeneric, DeleteGenericCfgLine);
- CtdlREGISTERRoomCfgType(lastsent, ParseLastSent, 1, 1, SerializeLastSent, DeleteLastSent);
- CtdlREGISTERRoomCfgType(listrecp, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine);
- CtdlREGISTERRoomCfgType(digestrecp, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine);
- CtdlREGISTERRoomCfgType(participate, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine);
- CtdlREGISTERRoomCfgType(roommailalias, ParseRoomAlias, 0, 1, SerializeGeneric, DeleteGenericCfgLine);
+ //CtdlREGISTERRoomCfgType(subpending, ParseSubPendingLine, 0, 5, SerializeGeneric, DeleteGenericCfgLine);
+ //CtdlREGISTERRoomCfgType(unsubpending, ParseUnSubPendingLine, 0, 4, SerializeGeneric, DeleteGenericCfgLine);
+ //CtdlREGISTERRoomCfgType(lastsent, ParseLastSent, 1, 1, SerializeLastSent, DeleteLastSent);
+ //CtdlREGISTERRoomCfgType(listrecp, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine);
+ //CtdlREGISTERRoomCfgType(digestrecp, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine);
+ //CtdlREGISTERRoomCfgType(participate, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine);
+ //CtdlREGISTERRoomCfgType(roommailalias, ParseRoomAlias, 0, 1, SerializeGeneric, DeleteGenericCfgLine);
}
return "network_spool";
}
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
+#include <time.h>
+
#ifdef HAVE_SYSCALL_H
# include <syscall.h>
#else
/* comes from lookup3.c from libcitadel... */
extern uint32_t hashlittle( const void *key, size_t length, uint32_t initval);
-typedef struct __roomlists {
- RoomProcList *rplist;
-} roomlists;
-
-
-/*
- * When we do network processing, it's accomplished in two passes; one to
- * gather a list of rooms and one to actually do them. It's ok that rplist
- * is global; we have a mutex that keeps it safe.
- */
-struct RoomProcList *rplist = NULL;
-
-RoomProcList *CreateRoomProcListEntry(struct ctdlroom *qrbuf, OneRoomNetCfg *OneRNCFG)
-{
- int i;
- struct RoomProcList *ptr;
-
- ptr = (struct RoomProcList *) malloc(sizeof (struct RoomProcList));
- if (ptr == NULL) {
- return NULL;
- }
-
- ptr->namelen = strlen(qrbuf->QRname);
- if (ptr->namelen > ROOMNAMELEN) {
- ptr->namelen = ROOMNAMELEN - 1;
- }
-
- memcpy (ptr->name, qrbuf->QRname, ptr->namelen);
- ptr->name[ptr->namelen] = '\0';
- ptr->QRNum = qrbuf->QRnumber;
-
- for (i = 0; i < ptr->namelen; i++)
- {
- ptr->lcname[i] = tolower(ptr->name[i]);
- }
-
- ptr->lcname[ptr->namelen] = '\0';
- ptr->key = hashlittle(ptr->lcname, ptr->namelen, 9872345);
- return ptr;
-}
-
-/*
- * Batch up and send all outbound traffic from the current room
- */
-void network_queue_interesting_rooms(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *OneRNCfg)
-{
- struct RoomProcList *ptr;
- roomlists *RP = (roomlists*) data;
-
- if (!HaveSpoolConfig(OneRNCfg)) {
- return;
- }
-
- ptr = CreateRoomProcListEntry(qrbuf, OneRNCfg);
-
- if (ptr != NULL)
- {
- ptr->next = RP->rplist;
- RP->rplist = ptr;
- }
-}
-
-/*
- * Batch up and send all outbound traffic from the current room
- */
-int network_room_handler(struct ctdlroom *qrbuf)
-{
- struct RoomProcList *ptr;
- OneRoomNetCfg *RNCfg;
-
- if (qrbuf->QRdefaultview == VIEW_QUEUE) {
- return 1;
- }
-
- RNCfg = CtdlGetNetCfgForRoom(qrbuf->QRnumber);
- if (RNCfg == NULL) {
- return 1;
- }
-
- if (!HaveSpoolConfig(RNCfg)) {
- FreeRoomNetworkStruct(&RNCfg);
- return 1;
- }
-
- ptr = CreateRoomProcListEntry(qrbuf, RNCfg);
- if (ptr == NULL) {
- FreeRoomNetworkStruct(&RNCfg);
- return 1;
- }
-
- begin_critical_section(S_RPLIST);
- ptr->next = rplist;
- rplist = ptr;
- end_critical_section(S_RPLIST);
- FreeRoomNetworkStruct(&RNCfg);
- return 1;
-}
-
-void destroy_network_queue_room(RoomProcList *rplist)
-{
- struct RoomProcList *cur, *p;
-
- cur = rplist;
- while (cur != NULL)
- {
- p = cur->next;
- free (cur);
- cur = p;
- }
-}
-
-
/*
* network_do_queue()
*
* Run through the rooms doing various types of network stuff.
*/
-void network_do_queue(void)
-{
+void network_do_queue(void) {
static time_t last_run = 0L;
int full_processing = 1;
- HashList *working_ignetcfg;
- HashList *the_netmap = NULL;
- int netmap_changed = 0;
- roomlists RL;
- SpoolControl *sc = NULL;
- SpoolControl *pSC;
/*
* Run the full set of processing tasks no more frequently
* than once every n seconds
*/
- if ( (time(NULL) - last_run) < CtdlGetConfigLong("c_net_freq") )
- {
+ if ( (time(NULL) - last_run) < CtdlGetConfigLong("c_net_freq") ) {
full_processing = 0;
syslog(LOG_DEBUG, "network: full processing in %ld seconds.", CtdlGetConfigLong("c_net_freq") - (time(NULL)- last_run));
}
begin_critical_section(S_RPLIST);
- RL.rplist = rplist;
- rplist = NULL;
end_critical_section(S_RPLIST);
- // TODO hm, check whether we have a config at all here?
- /* Load the IGnet Configuration into memory */
- working_ignetcfg = CtdlLoadIgNetCfg();
-
- /*
- * Load the network map and filter list into memory.
- */
- if (!server_shutting_down) {
- the_netmap = CtdlReadNetworkMap();
- }
-
/*
* Go ahead and run the queue
*/
if (full_processing && !server_shutting_down) {
syslog(LOG_DEBUG, "network: loading outbound queue");
- CtdlForEachNetCfgRoom(network_queue_interesting_rooms, &RL);
- }
-
- if ((RL.rplist != NULL) && (!server_shutting_down)) {
- RoomProcList *ptr, *cmp;
- ptr = RL.rplist;
- syslog(LOG_DEBUG, "network: running outbound queue");
- while (ptr != NULL && !server_shutting_down) {
-
- cmp = ptr->next;
- /* filter duplicates from the list... */
- while (cmp != NULL) {
- if ((cmp->namelen > 0) &&
- (cmp->key == ptr->key) &&
- (cmp->namelen == ptr->namelen) &&
- (strcmp(cmp->lcname, ptr->lcname) == 0))
- {
- cmp->namelen = 0;
- }
- cmp = cmp->next;
- }
-
- if (ptr->namelen > 0) {
- InspectQueuedRoom(&sc, ptr, working_ignetcfg, the_netmap);
- }
- ptr = ptr->next;
- }
- }
-
-
- pSC = sc;
- while (pSC != NULL)
- {
- network_spoolout_room(pSC);
- pSC = pSC->next;
+ //CtdlForEachNetCfgRoom(network_queue_interesting_rooms, &RL);
+ // FIXME do the outbound crapola AJC 2021
}
-
- pSC = sc;
- while (pSC != NULL)
- {
- sc = pSC->next;
- free_spoolcontrol_struct(&pSC);
- pSC = sc;
- }
-
- /* Save the network map back to disk */
- if (netmap_changed) {
- StrBuf *MapStr = CtdlSerializeNetworkMap(the_netmap);
- char *pMapStr = SmashStrBuf(&MapStr);
- CtdlPutSysConfig(IGNETMAP, pMapStr);
- free(pMapStr);
- }
-
- /* shut down. */
-
- DeleteHash(&the_netmap);
-
- DeleteHash(&working_ignetcfg);
-
syslog(LOG_DEBUG, "network: queue run completed");
if (full_processing) {
last_run = time(NULL);
}
- destroy_network_queue_room(RL.rplist);
}
{
if (!threading)
{
- CtdlRegisterRoomHook(network_room_handler);
CtdlRegisterSessionHook(network_do_queue, EVT_TIMER, PRIO_QUEUE + 10);
}
return "network";
*
* 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.
- *
- *
*
* 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.
- *
- *
- *
- *
*/
/*
*/
#define NEWUSERGREETINGS "New User Greetings"
-
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
-
#include "ctdl_module.h"
-
#include "citadel.h"
#include "server.h"
#include "citserver.h"
#include "database.h"
#include "msgbase.h"
-
-
-
-
-
/*
* Copy the contents of the New User Greetings> room to the user's Mail> room.
*/
#include <errno.h>
#include <sys/types.h>
#include <syslog.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
extern long timezone;
-// ***************** BEGIN UTILITY FUNCTIONS THAT COULD BE MOVED ELSEWHERE LATER **************
-
-
//
// Tests whether the supplied string is a valid newsgroup name
// Returns true (nonzero) or false (0)
}
-// ***************** END UTILITY FUNCTIONS THAT COULD BE MOVED ELSEWHERE LATER **************
-
-
-
//
// Here's where our NNTP session begins its happy day.
//
*
* Copyright (c) 2007-2012 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.
- *
- *
+ * 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.
*
- * 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.
- *
- *
- *
- *
+ * 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 <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include "user_ops.h"
#include "database.h"
#include "msgbase.h"
-
#include "ctdl_module.h"
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
/*
* Consolidate mail from remote POP3 accounts.
*
- * Copyright (c) 2007-2020 by the citadel.org team
+ * Copyright (c) 2007-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 as published
#include <unistd.h>
#include <stdio.h>
#include <sysconfig.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
/*
* Process one mailbox.
*/
-void pop3client_one_mailbox(char *room, const char *host, const char *user, const char *pass, int keep, long interval)
-{
+void pop3client_one_mailbox(char *room, const char *host, const char *user, const char *pass, int keep, long interval) {
syslog(LOG_DEBUG, "pop3client: room=<%s> host=<%s> user=<%s> keep=<%d> interval=<%ld>", room, host, user, keep, interval);
char url[SIZ];
curl_easy_setopt(curl, CURLOPT_URL, url);
res = curl_easy_perform(curl);
if (res == CURLE_OK) {
- } else {
+ }
+ else {
syslog(LOG_DEBUG, "pop3client: POP3S connection failed: %s , trying POP3 next", curl_easy_strerror(res));
snprintf(url, sizeof url, "pop3://%s", host); // try unencrypted next
curl_easy_setopt(curl, CURLOPT_URL, url);
}
-/*
- * Scan a room's netconfig to determine whether it requires POP3 aggregation
- */
-void pop3client_scan_room(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *OneRNCFG)
+// Scan a room's netconfig looking for RSS feed parsing requests
+//
+void pop3client_scan_room(struct ctdlroom *qrbuf, void *data)
{
- const RoomNetCfgLine *pLine;
- struct p3cq *pptr = NULL;
-
- if (server_shutting_down) return;
+ char *serialized_config = NULL;
+ int num_configs = 0;
+ char cfgline[SIZ];
+ int i = 0;
- pLine = OneRNCFG->NetConfigs[pop3client];
+ serialized_config = LoadRoomNetConfigFile(qrbuf->QRnumber);
+ if (!serialized_config) {
+ return;
+ }
- while (pLine != NULL)
- {
- pptr = malloc(sizeof(struct p3cq));
- pptr->next = p3cq;
- p3cq = pptr;
- pptr->room = strdup(qrbuf->QRname);
- pptr->host = strdup(ChrPtr(pLine->Value[0]));
- pptr->user = strdup(ChrPtr(pLine->Value[1]));
- pptr->pass = strdup(ChrPtr(pLine->Value[2]));
- pptr->keep = atoi(ChrPtr(pLine->Value[3]));
- pptr->interval = atol(ChrPtr(pLine->Value[4]));
-
- pLine = pLine->next;
+ num_configs = num_tokens(serialized_config, '\n');
+ for (i=0; i<num_configs; ++i) {
+ extract_token(cfgline, serialized_config, i, '\n', sizeof cfgline);
+ if (!strncasecmp(cfgline, HKEY("pop3client|"))) {
+ struct p3cq *pptr = malloc(sizeof(struct p3cq));
+ pptr->next = p3cq;
+ p3cq = pptr;
+ p3cq->room = "FIXME";
+ p3cq->host = "FIXME";
+ p3cq->user = "FIXME";
+ p3cq->pass = "FIXME";
+ p3cq->keep = "FIXME";
+ p3cq->interval = 0;
+ }
}
+
+ free(serialized_config);
}
doing_pop3client = 1;
syslog(LOG_DEBUG, "pop3client: scan started");
- CtdlForEachNetCfgRoom(pop3client_scan_room, NULL);
+ CtdlForEachRoom(pop3client_scan_room, NULL);
/*
* We have to queue and process in separate phases, otherwise we leave a cursor open
{
if (!threading)
{
- CtdlREGISTERRoomCfgType(pop3client, ParseGeneric, 0, 5, SerializeGeneric, DeleteGenericCfgLine);
CtdlRegisterSessionHook(pop3client_scan, EVT_TIMER, PRIO_AGGR + 50);
}
#include <errno.h>
#include <sys/types.h>
#include <assert.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-#include <sys/time.h>
-# else
#include <time.h>
-# endif
-#endif
-
#include <ctype.h>
#include <string.h>
#include <errno.h>
}
return "rssclient";
}
-
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include "user_ops.h"
#include "database.h"
#include "msgbase.h"
-
-
#include "ctdl_module.h"
/* Don't show the names of private rooms unless the viewing
#include <errno.h>
#include <sys/types.h>
#include <syslog.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sysconfig.h>
-
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
#include <time.h>
-#endif
-#endif
-
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <errno.h>
#include <sys/types.h>
#include <syslog.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <sys/types.h>
#include <assert.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
* Indicate the presence of another user to the client
* (used in several places)
*/
-void xmpp_indicate_presence(char *presence_jid)
-{
+void xmpp_indicate_presence(char *presence_jid) {
char xmlbuf[256];
syslog(LOG_DEBUG, "xmpp: indicating presence of <%s> to <%s>", presence_jid, XMPP->client_jid);
/*
* Initial dump of the entire wholist
*/
-void xmpp_wholist_presence_dump(void)
-{
+void xmpp_wholist_presence_dump(void) {
struct CitContext *cptr = NULL;
int nContexts, i;
);
HashPos = GetNewHashPos(mortuary, 0);
- while (GetNextHashPos(mortuary, HashPos, &len, &Key, &Value) != 0)
- {
+ while (GetNextHashPos(mortuary, HashPos, &len, &Key, &Value) != 0) {
StrBufAppendPrintf(themsg, "%s\n", (char *)Value);
}
DeleteHashPos(&HashPos);
* Since the client is probably not still alive, also remember the current
* roster for next time so we can delete dead buddies then.
*/
-void xmpp_massacre_roster(void)
-{
+void xmpp_massacre_roster(void) {
struct CitContext *cptr;
int nContexts, i;
HashList *mortuary = xmpp_fetch_mortuary();
* when they're connecting from the same client and when they're connecting from a different client,
* so we have no guarantee of what is in the client side roster at connect time.
*/
-void xmpp_delete_old_buddies_who_no_longer_exist_from_the_client_roster(void)
-{
+void xmpp_delete_old_buddies_who_no_longer_exist_from_the_client_roster(void) {
long len;
void *Value;
const char *Key;
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include "serv_extensions.h"
#include "config.h"
-void vFreeRoomNetworkStruct(void *vOneRoomNetCfg);
-void FreeRoomNetworkStructContent(OneRoomNetCfg *OneRNCfg);
-
-HashList *CfgTypeHash = NULL;
-
-/*-----------------------------------------------------------------------------*
- * Per room network configs *
- *-----------------------------------------------------------------------------*/
-
-
-void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLineParser p, int uniq, int nSegments, CfgLineSerializer s, CfgLineDeAllocator d)
-{
- CfgLineType *pCfg;
-
- pCfg = (CfgLineType*) malloc(sizeof(CfgLineType));
- pCfg->Parser = p;
- pCfg->Serializer = s;
- pCfg->DeAllocator = d;
- pCfg->C = eCfg;
- pCfg->Str.Key = Name;
- pCfg->Str.len = len;
- pCfg->IsSingleLine = uniq;
- pCfg->nSegments = nSegments;
- if (CfgTypeHash == NULL) {
- CfgTypeHash = NewHash(1, NULL);
- }
- Put(CfgTypeHash, Name, len, pCfg, NULL);
-}
-
-
-const CfgLineType *GetCfgTypeByStr(const char *Key, long len)
-{
- void *pv;
-
- if (GetHash(CfgTypeHash, Key, len, &pv) && (pv != NULL))
- {
- return (const CfgLineType *) pv;
- }
- else
- {
- return NULL;
- }
-}
-
-
-const CfgLineType *GetCfgTypeByEnum(RoomNetCfg eCfg, HashPos *It)
-{
- const char *Key;
- long len;
- void *pv;
- CfgLineType *pCfg;
-
- RewindHashPos(CfgTypeHash, It, 1);
- while (GetNextHashPos(CfgTypeHash, It, &len, &Key, &pv) && (pv != NULL))
- {
- pCfg = (CfgLineType*) pv;
- if (pCfg->C == eCfg)
- return pCfg;
- }
- return NULL;
-}
-
-
-void ParseGeneric(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCfg)
-{
- RoomNetCfgLine *nptr;
- int i;
-
- nptr = (RoomNetCfgLine *)
- malloc(sizeof(RoomNetCfgLine));
- nptr->next = OneRNCfg->NetConfigs[ThisOne->C];
- nptr->Value = malloc(sizeof(StrBuf*) * ThisOne->nSegments);
- nptr->nValues = 0;
- memset(nptr->Value, 0, sizeof(StrBuf*) * ThisOne->nSegments);
- if (ThisOne->nSegments == 1)
- {
- nptr->Value[0] = NewStrBufPlain(LinePos, StrLength(Line) - ( LinePos - ChrPtr(Line)) );
- nptr->nValues = 1;
- }
- else for (i = 0; i < ThisOne->nSegments; i++)
- {
- nptr->nValues++;
- nptr->Value[i] = NewStrBufPlain(NULL, StrLength(Line) - ( LinePos - ChrPtr(Line)) );
- StrBufExtract_NextToken(nptr->Value[i], Line, &LinePos, '|');
- }
-
- OneRNCfg->NetConfigs[ThisOne->C] = nptr;
-}
-
-
-void SerializeGeneric(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *OneRNCfg, RoomNetCfgLine *data)
-{
- int i;
-
- StrBufAppendBufPlain(OutputBuffer, CKEY(ThisOne->Str), 0);
- StrBufAppendBufPlain(OutputBuffer, HKEY("|"), 0);
- for (i = 0; i < ThisOne->nSegments; i++)
- {
- StrBufAppendBuf(OutputBuffer, data->Value[i], 0);
- if (i + 1 < ThisOne->nSegments)
- StrBufAppendBufPlain(OutputBuffer, HKEY("|"), 0);
- }
- StrBufAppendBufPlain(OutputBuffer, HKEY("\n"), 0);
-}
-
-
-void DeleteGenericCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data)
-{
- int i;
-
- if (*data == NULL)
- return;
-
- for (i = 0; i < (*data)->nValues; i++)
- {
- FreeStrBuf(&(*data)->Value[i]);
- }
- free ((*data)->Value);
- free(*data);
- *data = NULL;
-}
-
-
-RoomNetCfgLine *DuplicateOneGenericCfgLine(const RoomNetCfgLine *data)
-{
- int i;
- RoomNetCfgLine *NewData;
-
- NewData = (RoomNetCfgLine*)malloc(sizeof(RoomNetCfgLine));
- memset(NewData, 0, sizeof(RoomNetCfgLine));
- NewData->Value = (StrBuf **)malloc(sizeof(StrBuf*) * data->nValues);
- memset(NewData->Value, 0, sizeof(StrBuf*) * data->nValues);
-
- for (i = 0; i < data->nValues; i++)
- {
- NewData->Value[i] = NewStrBufDup(data->Value[i]);
- }
- NewData->nValues = data->nValues;
- return NewData;
-}
-
/*
* Create a config key for a room's netconfig entry
*/
-void netcfg_keyname(char *keybuf, long roomnum)
-{
+void netcfg_keyname(char *keybuf, long roomnum) {
if (!keybuf) return;
sprintf(keybuf, "c_netconfig_%010ld", roomnum);
}
/*
* Given a room number and a textual netconfig, convert to base64 and write to the configdb
*/
-void write_netconfig_to_configdb(long roomnum, const char *raw_netconfig)
-{
+void write_netconfig_to_configdb(long roomnum, const char *raw_netconfig) {
char keyname[25];
char *enc;
int enc_len;
* If it returns NULL, there is no netconfig.
* Otherwise the caller owns the returned memory and is responsible for freeing it.
*/
-char *LoadRoomNetConfigFile(long roomnum)
-{
+char *LoadRoomNetConfigFile(long roomnum) {
char keyname[25];
char *encoded_netconfig = NULL;
char *decoded_netconfig = NULL;
}
-/*
- * Deserialize a netconfig , allocate and return structured data
- */
-OneRoomNetCfg *ParseRoomNetConfigFile(char *serialized_data)
-{
- const char *Pos = NULL;
- const CfgLineType *pCfg = NULL;
- StrBuf *Line = NULL;
- StrBuf *InStr = NULL;
- StrBuf *Cfg = NULL;
- OneRoomNetCfg *OneRNCfg = NULL;
- int num_lines = 0;
- int i = 0;
-
- OneRNCfg = malloc(sizeof(OneRoomNetCfg));
- memset(OneRNCfg, 0, sizeof(OneRoomNetCfg));
-
- Line = NewStrBuf();
- InStr = NewStrBuf();
- Cfg = NewStrBufPlain(serialized_data, -1);
- num_lines = num_tokens(ChrPtr(Cfg), '\n');
-
- for (i=0; i<num_lines; ++i) {
- StrBufExtract_token(Line, Cfg, i, '\n');
- if (StrLength(Line) > 0) {
- Pos = NULL;
- StrBufExtract_NextToken(InStr, Line, &Pos, '|');
-
- pCfg = GetCfgTypeByStr(SKEY(InStr));
- if (pCfg != NULL)
- {
- pCfg->Parser(pCfg, Line, Pos, OneRNCfg);
- }
- else
- {
- if (OneRNCfg->misc == NULL)
- {
- OneRNCfg->misc = NewStrBufDup(Line);
- }
- else
- {
- if (StrLength(OneRNCfg->misc) > 0) {
- StrBufAppendBufPlain(OneRNCfg->misc, HKEY("\n"), 0);
- }
- StrBufAppendBuf(OneRNCfg->misc, Line, 0);
- }
- }
- }
- }
- FreeStrBuf(&InStr);
- FreeStrBuf(&Line);
- FreeStrBuf(&Cfg);
- return OneRNCfg;
-}
-
-
-void SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCfg, long roomnum)
-{
- RoomNetCfg eCfg;
- StrBuf *Cfg = NULL;
- StrBuf *OutBuffer = NULL;
- HashPos *CfgIt;
-
- Cfg = NewStrBuf();
- OutBuffer = NewStrBuf();
- CfgIt = GetNewHashPos(CfgTypeHash, 1);
- for (eCfg = subpending; eCfg < maxRoomNetCfg; eCfg ++)
- {
- const CfgLineType *pCfg;
- pCfg = GetCfgTypeByEnum(eCfg, CfgIt);
- if (pCfg)
- {
- if (pCfg->IsSingleLine)
- {
- pCfg->Serializer(pCfg, OutBuffer, OneRNCfg, NULL);
- }
- else
- {
- RoomNetCfgLine *pName = OneRNCfg->NetConfigs[pCfg->C];
- while (pName != NULL)
- {
- pCfg->Serializer(pCfg, OutBuffer, OneRNCfg, pName);
- pName = pName->next;
- }
- }
- }
-
- }
- DeleteHashPos(&CfgIt);
-
- if (OneRNCfg->misc != NULL) {
- StrBufAppendBuf(OutBuffer, OneRNCfg->misc, 0);
- }
-
- write_netconfig_to_configdb(roomnum, ChrPtr(OutBuffer));
-
- FreeStrBuf(&OutBuffer);
- FreeStrBuf(&Cfg);
-}
-
-
-void AddRoomCfgLine(OneRoomNetCfg *OneRNCfg, struct ctdlroom *qrbuf, RoomNetCfg LineType, RoomNetCfgLine *Line)
-{
- RoomNetCfgLine **pLine;
-
- if (OneRNCfg == NULL)
- {
- OneRNCfg = (OneRoomNetCfg*) malloc(sizeof(OneRoomNetCfg));
- memset(OneRNCfg, 0, sizeof(OneRoomNetCfg));
- }
- pLine = &OneRNCfg->NetConfigs[LineType];
-
- while(*pLine != NULL) pLine = &((*pLine)->next);
- *pLine = Line;
-}
-
-
-void FreeRoomNetworkStructContent(OneRoomNetCfg *OneRNCfg)
-{
- RoomNetCfg eCfg;
- HashPos *CfgIt;
-
- CfgIt = GetNewHashPos(CfgTypeHash, 1);
- for (eCfg = subpending; eCfg < maxRoomNetCfg; eCfg ++)
- {
- const CfgLineType *pCfg;
- RoomNetCfgLine *pNext, *pName;
-
- pCfg = GetCfgTypeByEnum(eCfg, CfgIt);
- pName= OneRNCfg->NetConfigs[eCfg];
- while (pName != NULL)
- {
- pNext = pName->next;
- if (pCfg != NULL)
- {
- pCfg->DeAllocator(pCfg, &pName);
- }
- else
- {
- DeleteGenericCfgLine(NULL, &pName);
- }
- pName = pNext;
- }
- }
- DeleteHashPos(&CfgIt);
-
- FreeStrBuf(&OneRNCfg->Sender);
- FreeStrBuf(&OneRNCfg->RoomInfo);
- FreeStrBuf(&OneRNCfg->misc);
- memset(OneRNCfg, 0, sizeof(OneRoomNetCfg));
-}
-
-
-void vFreeRoomNetworkStruct(void *vOneRoomNetCfg)
-{
- OneRoomNetCfg *OneRNCfg;
- OneRNCfg = (OneRoomNetCfg*)vOneRoomNetCfg;
- FreeRoomNetworkStructContent(OneRNCfg);
- free(OneRNCfg);
-}
-
-
-void FreeRoomNetworkStruct(OneRoomNetCfg **pOneRNCfg)
-{
- vFreeRoomNetworkStruct(*pOneRNCfg);
- *pOneRNCfg=NULL;
-}
-
-
-/*
- * Fetch the netconfig entry for a room, parse it, and return the data.
- * Caller owns the returned memory and MUST free it using FreeRoomNetworkStruct()
- */
-OneRoomNetCfg *CtdlGetNetCfgForRoom(long roomnum)
-{
- OneRoomNetCfg *OneRNCfg = NULL;
- char *serialized_config = NULL;
-
- serialized_config = LoadRoomNetConfigFile(roomnum);
- if (!serialized_config) return NULL;
-
- OneRNCfg = ParseRoomNetConfigFile(serialized_config);
- free(serialized_config);
- return OneRNCfg;
-}
-
-
/*-----------------------------------------------------------------------------*
* Per room network configs : exchange with client *
*-----------------------------------------------------------------------------*/
-void cmd_gnet(char *argbuf)
-{
+void cmd_gnet(char *argbuf) {
if ( (CC->room.QRflags & QR_MAILBOX) && (CC->user.usernum == atol(CC->room.QRname)) ) {
/* users can edit the netconfigs for their own mailbox rooms */
}
}
-void cmd_snet(char *argbuf)
-{
- struct CitContext *CCC = CC;
+void cmd_snet(char *argbuf) {
StrBuf *Line = NULL;
StrBuf *TheConfig = NULL;
int rc;
TheConfig = NewStrBuf();
cprintf("%d send new netconfig now\n", SEND_LISTING);
- while (rc = CtdlClientGetLine(Line), (rc >= 0))
- {
+ while (rc = CtdlClientGetLine(Line), (rc >= 0)) {
if ((rc == 3) && (strcmp(ChrPtr(Line), "000") == 0))
break;
}
FreeStrBuf(&Line);
- write_netconfig_to_configdb(CCC->room.QRnumber, ChrPtr(TheConfig));
+ write_netconfig_to_configdb(CC->room.QRnumber, ChrPtr(TheConfig));
FreeStrBuf(&TheConfig);
}
-/*-----------------------------------------------------------------------------*
- * Per node network configs *
- *-----------------------------------------------------------------------------*/
-void DeleteCtdlNodeConf(void *vNode)
-{
- CtdlNodeConf *Node = (CtdlNodeConf*) vNode;
- FreeStrBuf(&Node->NodeName);
- FreeStrBuf(&Node->Secret);
- FreeStrBuf(&Node->Host);
- FreeStrBuf(&Node->Port);
- free(Node);
-}
-
-
-CtdlNodeConf *NewNode(StrBuf *SerializedNode)
-{
- const char *Pos = NULL;
- CtdlNodeConf *Node;
-
- /* we need at least 4 pipes and some other text so its invalid. */
- if (StrLength(SerializedNode) < 8)
- return NULL;
- Node = (CtdlNodeConf *) malloc(sizeof(CtdlNodeConf));
-
- Node->DeleteMe = 0;
-
- Node->NodeName=NewStrBuf();
- StrBufExtract_NextToken(Node->NodeName, SerializedNode, &Pos, '|');
-
- Node->Secret=NewStrBuf();
- StrBufExtract_NextToken(Node->Secret, SerializedNode, &Pos, '|');
-
- Node->Host=NewStrBuf();
- StrBufExtract_NextToken(Node->Host, SerializedNode, &Pos, '|');
-
- Node->Port=NewStrBuf();
- StrBufExtract_NextToken(Node->Port, SerializedNode, &Pos, '|');
- return Node;
-}
-
-
-/*
- * Load or refresh the Citadel network (IGnet) configuration for this node.
- */
-HashList* CtdlLoadIgNetCfg(void)
-{
- const char *LinePos;
- char *Cfg;
- StrBuf *Buf;
- StrBuf *LineBuf;
- HashList *Hash;
- CtdlNodeConf *Node;
-
- Cfg = CtdlGetSysConfig(IGNETCFG);
- if ((Cfg == NULL) || IsEmptyStr(Cfg)) {
- if (Cfg != NULL)
- free(Cfg);
- return NULL;
- }
-
- Hash = NewHash(1, NULL);
- Buf = NewStrBufPlain(Cfg, -1);
- free(Cfg);
- LineBuf = NewStrBufPlain(NULL, StrLength(Buf));
- LinePos = NULL;
- do
- {
- StrBufSipLine(LineBuf, Buf, &LinePos);
- if (StrLength(LineBuf) != 0) {
- Node = NewNode(LineBuf);
- if (Node != NULL) {
- Put(Hash, SKEY(Node->NodeName), Node, DeleteCtdlNodeConf);
- }
- }
- } while (LinePos != StrBufNOTNULL);
- FreeStrBuf(&Buf);
- FreeStrBuf(&LineBuf);
- return Hash;
-}
-
-
-int is_recipient(OneRoomNetCfg *RNCfg, const char *Name)
-{
- const RoomNetCfg RecipientCfgs[] = {
- listrecp,
- digestrecp,
- participate,
- maxRoomNetCfg
- };
- int i;
- RoomNetCfgLine *nptr;
- size_t len;
-
- len = strlen(Name);
- i = 0;
- while (RecipientCfgs[i] != maxRoomNetCfg)
- {
- nptr = RNCfg->NetConfigs[RecipientCfgs[i]];
-
- while (nptr != NULL)
- {
- if ((StrLength(nptr->Value[0]) == len) &&
- (!strcmp(Name, ChrPtr(nptr->Value[0]))))
- {
- return 1;
- }
- nptr = nptr->next;
- }
- i++;
- }
- return 0;
-}
-
-
-int CtdlNetconfigCheckRoomaccess(char *errmsgbuf, size_t n, const char* RemoteIdentifier)
-{
- OneRoomNetCfg *RNCfg;
- int found;
-
- if (RemoteIdentifier == NULL)
- {
- snprintf(errmsgbuf, n, "Need sender to permit access.");
- return (ERROR + USERNAME_REQUIRED);
- }
-
- begin_critical_section(S_NETCONFIGS);
- RNCfg = CtdlGetNetCfgForRoom (CC->room.QRnumber);
- if (RNCfg == NULL)
- {
- end_critical_section(S_NETCONFIGS);
- snprintf(errmsgbuf, n,
- "This mailing list only accepts posts from subscribers.");
- return (ERROR + NO_SUCH_USER);
- }
- found = is_recipient (RNCfg, RemoteIdentifier);
- FreeRoomNetworkStruct(&RNCfg);
- end_critical_section(S_NETCONFIGS);
-
- if (found) {
- return (0);
- }
- else {
- snprintf(errmsgbuf, n,
- "This mailing list only accepts posts from subscribers.");
- return (ERROR + NO_SUCH_USER);
- }
-}
-
-
-/*-----------------------------------------------------------------------------*
- * Network maps: evaluate other nodes *
- *-----------------------------------------------------------------------------*/
-
-void DeleteNetMap(void *vNetMap)
-{
- CtdlNetMap *TheNetMap = (CtdlNetMap*) vNetMap;
- FreeStrBuf(&TheNetMap->NodeName);
- FreeStrBuf(&TheNetMap->NextHop);
- free(TheNetMap);
-}
-
-
-CtdlNetMap *NewNetMap(StrBuf *SerializedNetMap)
-{
- const char *Pos = NULL;
- CtdlNetMap *NM;
-
- /* we need at least 3 pipes and some other text so its invalid. */
- if (StrLength(SerializedNetMap) < 6)
- return NULL;
- NM = (CtdlNetMap *) malloc(sizeof(CtdlNetMap));
-
- NM->NodeName=NewStrBuf();
- StrBufExtract_NextToken(NM->NodeName, SerializedNetMap, &Pos, '|');
-
- NM->lastcontact = StrBufExtractNext_long(SerializedNetMap, &Pos, '|');
-
- NM->NextHop=NewStrBuf();
- StrBufExtract_NextToken(NM->NextHop, SerializedNetMap, &Pos, '|');
-
- return NM;
-}
-
-
-HashList* CtdlReadNetworkMap(void)
-{
- const char *LinePos;
- char *Cfg;
- StrBuf *Buf;
- StrBuf *LineBuf;
- HashList *Hash;
- CtdlNetMap *TheNetMap;
-
- Hash = NewHash(1, NULL);
- Cfg = CtdlGetSysConfig(IGNETMAP);
- if ((Cfg == NULL) || IsEmptyStr(Cfg)) {
- if (Cfg != NULL)
- free(Cfg);
- return Hash;
- }
-
- Buf = NewStrBufPlain(Cfg, -1);
- free(Cfg);
- LineBuf = NewStrBufPlain(NULL, StrLength(Buf));
- LinePos = NULL;
- while (StrBufSipLine(Buf, LineBuf, &LinePos))
- {
- TheNetMap = NewNetMap(LineBuf);
- if (TheNetMap != NULL) { /* TODO: is the NodeName Uniq? */
- Put(Hash, SKEY(TheNetMap->NodeName), TheNetMap, DeleteNetMap);
- }
- }
- FreeStrBuf(&Buf);
- FreeStrBuf(&LineBuf);
- return Hash;
-}
-
-
-StrBuf *CtdlSerializeNetworkMap(HashList *Map)
-{
- void *vMap;
- const char *key;
- long len;
- StrBuf *Ret = NewStrBuf();
- HashPos *Pos = GetNewHashPos(Map, 0);
-
- while (GetNextHashPos(Map, Pos, &len, &key, &vMap))
- {
- CtdlNetMap *pMap = (CtdlNetMap*) vMap;
- StrBufAppendBuf(Ret, pMap->NodeName, 0);
- StrBufAppendBufPlain(Ret, HKEY("|"), 0);
-
- StrBufAppendPrintf(Ret, "%ld", pMap->lastcontact, 0);
- StrBufAppendBufPlain(Ret, HKEY("|"), 0);
-
- StrBufAppendBuf(Ret, pMap->NextHop, 0);
- StrBufAppendBufPlain(Ret, HKEY("\n"), 0);
- }
- DeleteHashPos(&Pos);
- return Ret;
-}
-
-
/*
* Convert any legacy configuration files in the "netconfigs" directory
*/
syslog(LOG_INFO, "netconfig: legacy netconfig files exist - converting them!");
- while (dit = readdir(dh), dit != NULL) // yes, we use the non-reentrant version; we're not in threaded mode yet
- {
+ while (dit = readdir(dh), dit != NULL) { // yes, we use the non-reentrant version; we're not in threaded mode yet
roomnum = atol(dit->d_name);
if (roomnum > 0) {
snprintf(filename, sizeof filename, "%s/%ld", ctdl_netcfg_dir, roomnum);
fp = fopen(filename, "r");
- if (fp)
- {
+ if (fp) {
fseek(fp, 0L, SEEK_END);
len = ftell(fp);
- if (len > 0)
- {
+ if (len > 0) {
v = malloc(len);
- if (v)
- {
+ if (v) {
rewind(fp);
- if (fread(v, len, 1, fp))
- {
+ if (fread(v, len, 1, fp)) {
write_netconfig_to_configdb(roomnum, v);
unlink(filename);
}
free(v);
}
}
- else
- {
+ else {
unlink(filename); // zero length netconfig, just delete it
}
fclose(fp);
/*
* Server functions which perform operations on room objects.
*
- * Copyright (c) 1987-2017 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.
const char* RemoteIdentifier,
PostType PostPublic,
int is_reply
- ) {
+) {
int ra;
- if (!(CC->logged_in) &&
- (PostPublic == POST_LOGGED_IN)) {
+ if (!(CC->logged_in) && (PostPublic == POST_LOGGED_IN)) {
snprintf(errmsgbuf, n, "Not logged in.");
return (ERROR + NOT_LOGGED_IN);
}
else if (PostPublic == CHECK_EXISTANCE) {
- return (0); // We're Evaling whether a recipient exists
+ return (0); // evaluate whether a recipient exists
}
else if (!(CC->logged_in)) {
-
if ((CC->room.QRflags & QR_READONLY)) {
snprintf(errmsgbuf, n, "Not logged in.");
return (ERROR + NOT_LOGGED_IN);
snprintf(errmsgbuf, n, "Not logged in Moderation feature not yet implemented!");
return (ERROR + NOT_LOGGED_IN);
}
- if ((PostPublic!=POST_LMTP) &&(CC->room.QRflags2 & QR2_SMTP_PUBLIC) == 0) {
-
- return CtdlNetconfigCheckRoomaccess(errmsgbuf, n, RemoteIdentifier);
- }
+ // FIXME what was this? AJC 2021
+ //if ((PostPublic != POST_LMTP) && (CC->room.QRflags2 & QR2_SMTP_PUBLIC) == 0) {
+ //return CtdlNetconfigCheckRoomaccess(errmsgbuf, n, RemoteIdentifier);
+ //}
return (0);
-
}
- if ((CC->user.axlevel < AxProbU) && ((CC->room.QRflags & QR_MAILBOX) == 0))
- {
+ if ((CC->user.axlevel < AxProbU) && ((CC->room.QRflags & QR_MAILBOX) == 0)) {
snprintf(errmsgbuf, n, "Need to be validated to enter (except in %s> to sysop)", MAILROOM);
return (ERROR + HIGHER_ACCESS_REQUIRED);
}
* Retrieve access control information for any user/room pair.
* Yes, it has a couple of gotos. If you don't like that, go die in a car fire.
*/
-void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf,
- int *result, int *view)
-{
+void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf, int *result, int *view) {
int retval = 0;
visit vbuf;
int is_me = 0;
/*
* Self-checking stuff for a room record read into memory
*/
-void room_sanity_check(struct ctdlroom *qrbuf)
-{
+void room_sanity_check(struct ctdlroom *qrbuf) {
/* Mailbox rooms are always on the lowest floor */
if (qrbuf->QRflags & QR_MAILBOX) {
qrbuf->QRfloor = 0;
/*
* CtdlGetRoom() - retrieve room data from disk
*/
-int CtdlGetRoom(struct ctdlroom *qrbuf, const char *room_name)
-{
+int CtdlGetRoom(struct ctdlroom *qrbuf, const char *room_name) {
struct cdbdata *cdbqr;
char lowercase_name[ROOMNAMELEN];
char personal_lowercase_name[ROOMNAMELEN];
dptr = lowercase_name;
sptr = room_name;
eptr = (dptr + (sizeof lowercase_name - 1));
- while (!IsEmptyStr(sptr) && (dptr < eptr)){
+ while (!IsEmptyStr(sptr) && (dptr < eptr)) {
*dptr = tolower(*sptr);
sptr++; dptr++;
}
memset(qrbuf, 0, sizeof(struct ctdlroom));
/* First, try the public namespace */
- cdbqr = cdb_fetch(CDB_ROOMS,
- lowercase_name, strlen(lowercase_name));
+ cdbqr = cdb_fetch(CDB_ROOMS, lowercase_name, strlen(lowercase_name));
/* If that didn't work, try the user's personal namespace */
if (cdbqr == NULL) {
- snprintf(personal_lowercase_name,
- sizeof personal_lowercase_name, "%010ld.%s",
- CC->user.usernum, lowercase_name);
- cdbqr = cdb_fetch(CDB_ROOMS,
- personal_lowercase_name,
- strlen(personal_lowercase_name));
+ snprintf(personal_lowercase_name, sizeof personal_lowercase_name, "%010ld.%s", CC->user.usernum, lowercase_name);
+ cdbqr = cdb_fetch(CDB_ROOMS, personal_lowercase_name, strlen(personal_lowercase_name));
}
if (cdbqr != NULL) {
- memcpy(qrbuf, cdbqr->ptr,
- ((cdbqr->len > sizeof(struct ctdlroom)) ?
- sizeof(struct ctdlroom) : cdbqr->len));
+ memcpy(qrbuf, cdbqr->ptr, ((cdbqr->len > sizeof(struct ctdlroom)) ? sizeof(struct ctdlroom) : cdbqr->len));
cdb_free(cdbqr);
-
room_sanity_check(qrbuf);
-
return (0);
- } else {
+ }
+ else {
return (1);
}
}
/*
* CtdlGetRoomLock() - same as getroom() but locks the record (if supported)
*/
-int CtdlGetRoomLock(struct ctdlroom *qrbuf, const char *room_name)
-{
+int CtdlGetRoomLock(struct ctdlroom *qrbuf, const char *room_name) {
register int retval;
retval = CtdlGetRoom(qrbuf, room_name);
if (retval == 0) begin_critical_section(S_ROOMS);
aptr = room_name;
bptr = lowercase_name;
- while (!IsEmptyStr(aptr))
- {
+ while (!IsEmptyStr(aptr)) {
*bptr = tolower(*aptr);
aptr++;
bptr++;
len = bptr - lowercase_name;
if (qrbuf == NULL) {
cdb_delete(CDB_ROOMS, lowercase_name, len);
- } else {
+ }
+ else {
time(&qrbuf->QRmtime);
cdb_store(CDB_ROOMS, lowercase_name, len, qrbuf, sizeof(struct ctdlroom));
}
/*
* CtdlPutRoomLock() - same as CtdlPutRoom() but unlocks the record (if supported)
*/
-void CtdlPutRoomLock(struct ctdlroom *qrbuf)
-{
+void CtdlPutRoomLock(struct ctdlroom *qrbuf) {
CtdlPutRoom(qrbuf);
end_critical_section(S_ROOMS);
}
* CtdlGetFloorByName() - retrieve the number of the named floor
* return < 0 if not found else return floor number
*/
-int CtdlGetFloorByName(const char *floor_name)
-{
+int CtdlGetFloorByName(const char *floor_name) {
int a;
struct floor *flbuf = NULL;
flbuf = CtdlGetCachedFloor(a);
/* check to see if it already exists */
- if ((!strcasecmp(flbuf->f_name, floor_name))
- && (flbuf->f_flags & F_INUSE)) {
+ if ((!strcasecmp(flbuf->f_name, floor_name)) && (flbuf->f_flags & F_INUSE)) {
return a;
}
}
}
-
/*
* CtdlGetAvailableFloor() - Return number of first unused floor
* return < 0 if none available
*/
-int CtdlGetAvailableFloor(void)
-{
+int CtdlGetAvailableFloor(void) {
int a;
struct floor *flbuf = NULL;
/*
* CtdlGetFloor() - retrieve floor data from disk
*/
-void CtdlGetFloor(struct floor *flbuf, int floor_num)
-{
+void CtdlGetFloor(struct floor *flbuf, int floor_num) {
struct cdbdata *cdbfl;
memset(flbuf, 0, sizeof(struct floor));
cdbfl = cdb_fetch(CDB_FLOORTAB, &floor_num, sizeof(int));
if (cdbfl != NULL) {
- memcpy(flbuf, cdbfl->ptr,
- ((cdbfl->len > sizeof(struct floor)) ?
- sizeof(struct floor) : cdbfl->len));
+ memcpy(flbuf, cdbfl->ptr, ((cdbfl->len > sizeof(struct floor)) ? sizeof(struct floor) : cdbfl->len));
cdb_free(cdbfl);
} else {
if (floor_num == 0) {
- safestrncpy(flbuf->f_name, "Main Floor",
- sizeof flbuf->f_name);
+ safestrncpy(flbuf->f_name, "Main Floor", sizeof flbuf->f_name);
flbuf->f_flags = F_INUSE;
flbuf->f_ref_count = 3;
}
}
-
}
/*
* lgetfloor() - same as CtdlGetFloor() but locks the record (if supported)
*/
-void lgetfloor(struct floor *flbuf, int floor_num)
-{
+void lgetfloor(struct floor *flbuf, int floor_num) {
begin_critical_section(S_FLOORTAB);
CtdlGetFloor(flbuf, floor_num);
}
/*
* CtdlPutFloor() - store floor data on disk
*/
-void CtdlPutFloor(struct floor *flbuf, int floor_num)
-{
+void CtdlPutFloor(struct floor *flbuf, int floor_num) {
/* If we've cached this, clear it out, 'cuz it's WRONG now! */
begin_critical_section(S_FLOORCACHE);
if (floorcache[floor_num] != NULL) {
/*
* CtdlPutFloorLock() - same as CtdlPutFloor() but unlocks the record (if supported)
*/
-void CtdlPutFloorLock(struct floor *flbuf, int floor_num)
-{
+void CtdlPutFloorLock(struct floor *flbuf, int floor_num) {
CtdlPutFloor(flbuf, floor_num);
end_critical_section(S_FLOORTAB);
/*
* lputfloor() - same as CtdlPutFloor() but unlocks the record (if supported)
*/
-void lputfloor(struct floor *flbuf, int floor_num)
-{
+void lputfloor(struct floor *flbuf, int floor_num) {
CtdlPutFloorLock(flbuf, floor_num);
}
-
/*
* Iterate through the room table, performing a callback for each room.
*/
-void CtdlForEachRoom(ForEachRoomCallBack CB, void *in_data)
-{
+void CtdlForEachRoom(ForEachRoomCallBack callback_func, void *in_data) {
struct ctdlroom qrbuf;
struct cdbdata *cdbqr;
cdb_rewind(CDB_ROOMS);
while (cdbqr = cdb_next_item(CDB_ROOMS), cdbqr != NULL) {
- memset(&qrbuf, 0, sizeof(struct ctdlroom));
- memcpy(&qrbuf, cdbqr->ptr,
- ((cdbqr->len > sizeof(struct ctdlroom)) ?
- sizeof(struct ctdlroom) : cdbqr->len)
- );
+ memset(&qrbuf, 0, sizeof(struct ctdlroom));
+ memcpy(&qrbuf, cdbqr->ptr, ((cdbqr->len > sizeof(struct ctdlroom)) ? sizeof(struct ctdlroom) : cdbqr->len) );
cdb_free(cdbqr);
room_sanity_check(&qrbuf);
if (qrbuf.QRflags & QR_INUSE) {
- CB(&qrbuf, in_data);
- }
- }
-}
-
-/*
- * Iterate through the room table, performing a callback for each room that has a netconfig entry.
- */
-void CtdlForEachNetCfgRoom(ForEachRoomNetCfgCallBack CB, void *in_data)
-{
- struct ctdlroom qrbuf;
- struct cdbdata *cdbqr;
-
- cdb_rewind(CDB_ROOMS);
-
- while (cdbqr = cdb_next_item(CDB_ROOMS), cdbqr != NULL) {
- memset(&qrbuf, 0, sizeof(struct ctdlroom));
- memcpy(&qrbuf, cdbqr->ptr, ((cdbqr->len > sizeof(struct ctdlroom)) ? sizeof(struct ctdlroom) : cdbqr->len));
- cdb_free(cdbqr);
- room_sanity_check(&qrbuf);
- if (qrbuf.QRflags & QR_INUSE)
- {
- OneRoomNetCfg *RNCfg;
- RNCfg = CtdlGetNetCfgForRoom(qrbuf.QRnumber);
- if (RNCfg != NULL)
- {
- CB(&qrbuf, in_data, RNCfg);
- FreeRoomNetworkStruct(&RNCfg);
- }
+ callback_func(&qrbuf, in_data);
}
}
}
/*
* delete_msglist() - delete room message pointers
*/
-void delete_msglist(struct ctdlroom *whichroom)
-{
+void delete_msglist(struct ctdlroom *whichroom) {
struct cdbdata *cdbml;
/* Make sure the msglist we're deleting actually exists, otherwise
* sort message pointers
* (returns new msg count)
*/
-int sort_msglist(long listptrs[], int oldcount)
-{
+int sort_msglist(long listptrs[], int oldcount) {
int numitems;
int i = 0;
/* and yank any nulls */
while ((i < numitems) && (listptrs[i] == 0L)) i++;
- if (i > 0)
- {
+ if (i > 0) {
memmove(&listptrs[0], &listptrs[i], (sizeof(long) * (numitems - i)));
numitems-=i;
}
/*
* Determine whether a given room is non-editable.
*/
-int CtdlIsNonEditable(struct ctdlroom *qrbuf)
-{
+int CtdlIsNonEditable(struct ctdlroom *qrbuf) {
/* Mail> rooms are non-editable */
- if ( (qrbuf->QRflags & QR_MAILBOX)
- && (!strcasecmp(&qrbuf->QRname[11], MAILROOM)) )
+ if ( (qrbuf->QRflags & QR_MAILBOX) && (!strcasecmp(&qrbuf->QRname[11], MAILROOM)) ) {
return (1);
+ }
/* Everything else is editable */
return (0);
void CtdlUserGoto(char *where, int display_result, int transiently,
int *retmsgs, int *retnew, long *retoldest, long *retnewest)
{
- struct CitContext *CCC = CC;
int a;
int new_messages = 0;
int old_messages = 0;
* we can skip the extra database fetch.
*/
if (where != NULL) {
- safestrncpy(CCC->room.QRname, where, sizeof CCC->room.QRname);
- CtdlGetRoom(&CCC->room, where);
+ safestrncpy(CC->room.QRname, where, sizeof CC->room.QRname);
+ CtdlGetRoom(&CC->room, where);
}
/* Take care of all the formalities. */
begin_critical_section(S_USERS);
- CtdlGetRelationship(&vbuf, &CCC->user, &CCC->room);
+ CtdlGetRelationship(&vbuf, &CC->user, &CC->room);
original_v_flags = vbuf.v_flags;
/* Know the room ... but not if it's the page log room, or if the
add_room_to_known_list = 0;
}
char *c_logpages = CtdlGetConfigStr("c_logpages");
- if ( (c_logpages != NULL) && (!strcasecmp(CCC->room.QRname, c_logpages)) ) {
+ if ( (c_logpages != NULL) && (!strcasecmp(CC->room.QRname, c_logpages)) ) {
add_room_to_known_list = 0;
}
if (add_room_to_known_list) {
/* Only rewrite the database record if we changed something */
if (vbuf.v_flags != original_v_flags) {
- CtdlSetRelationship(&vbuf, &CCC->user, &CCC->room);
+ CtdlSetRelationship(&vbuf, &CC->user, &CC->room);
}
end_critical_section(S_USERS);
/* Set info to 1 if the room banner is new since our last visit.
* Some clients only want to display it when it changes.
*/
- if (CCC->room.msgnum_info > vbuf.v_lastseen) {
+ if (CC->room.msgnum_info > vbuf.v_lastseen) {
info = 1;
}
- cdbfr = cdb_fetch(CDB_MSGLISTS, &CCC->room.QRnumber, sizeof(long));
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
if (cdbfr != NULL) {
msglist = (long *) cdbfr->ptr;
cdbfr->ptr = NULL; /* CtdlUserGoto() now owns this memory */
if (msglist != NULL) free(msglist);
- if (CCC->room.QRflags & QR_MAILBOX)
+ if (CC->room.QRflags & QR_MAILBOX)
rmailflag = 1;
else
rmailflag = 0;
- if ((CCC->room.QRroomaide == CCC->user.usernum)
- || (CCC->user.axlevel >= AxAideU))
+ if ((CC->room.QRroomaide == CC->user.usernum) || (CC->user.axlevel >= AxAideU))
raideflag = 1;
else
raideflag = 0;
- safestrncpy(truncated_roomname, CCC->room.QRname, sizeof truncated_roomname);
- if ( (CCC->room.QRflags & QR_MAILBOX)
- && (atol(CCC->room.QRname) == CCC->user.usernum) ) {
+ safestrncpy(truncated_roomname, CC->room.QRname, sizeof truncated_roomname);
+ if ( (CC->room.QRflags & QR_MAILBOX) && (atol(CC->room.QRname) == CC->user.usernum) ) {
safestrncpy(truncated_roomname, &truncated_roomname[11], sizeof truncated_roomname);
}
if (retoldest != NULL) *retoldest = oldest_message;
if (retnewest != NULL) *retnewest = newest_message;
syslog(LOG_DEBUG, "room_ops: %s : %d new of %d total messages, oldest=%ld, newest=%ld",
- CCC->room.QRname, new_messages, total_messages, oldest_message, newest_message
+ CC->room.QRname, new_messages, total_messages, oldest_message, newest_message
);
- CCC->curr_view = (int)vbuf.v_view;
+ CC->curr_view = (int)vbuf.v_view;
if (display_result) {
cprintf("%d%c%s|%d|%d|%d|%d|%ld|%ld|%d|%d|%d|%d|%d|%d|%d|%d|%ld|\n",
(int)new_messages,
(int)total_messages,
(int)info,
- (int)CCC->room.QRflags,
- (long)CCC->room.QRhighest,
+ (int)CC->room.QRflags,
+ (long)CC->room.QRhighest,
(long)vbuf.v_lastseen,
(int)rmailflag,
(int)raideflag,
(int)newmailcount,
- (int)CCC->room.QRfloor,
+ (int)CC->room.QRfloor,
(int)vbuf.v_view,
- (int)CCC->room.QRdefaultview,
+ (int)CC->room.QRdefaultview,
(int)is_trash,
- (int)CCC->room.QRflags2,
- (long)CCC->room.QRmtime
+ (int)CC->room.QRflags2,
+ (long)CC->room.QRmtime
);
}
}
* in *at least* the old name!
*/
int CtdlRenameRoom(char *old_name, char *new_name, int new_floor) {
- struct CitContext *CCC = CC;
int old_floor = 0;
struct ctdlroom qrbuf;
struct ctdlroom qrtmp;
begin_critical_section(S_ROOMS);
- if ( (CtdlGetRoom(&qrtmp, new_name) == 0)
- && (strcasecmp(new_name, old_name)) ) {
+ if ( (CtdlGetRoom(&qrtmp, new_name) == 0) && (strcasecmp(new_name, old_name)) ) {
ret = crr_already_exists;
}
ret = crr_room_not_found;
}
- else if ( (CCC->user.axlevel < AxAideU) && (!CCC->internal_pgm)
- && (CCC->user.usernum != qrbuf.QRroomaide)
- && ( (((qrbuf.QRflags & QR_MAILBOX) == 0) || (atol(qrbuf.QRname) != CCC->user.usernum))) ) {
+ else if ( (CC->user.axlevel < AxAideU) && (!CC->internal_pgm)
+ && (CC->user.usernum != qrbuf.QRroomaide)
+ && ( (((qrbuf.QRflags & QR_MAILBOX) == 0) || (atol(qrbuf.QRname) != CC->user.usernum))) ) {
ret = crr_access_denied;
}
* database operations to complete. Instead, the room gets purged when THE DREADED AUTO-PURGER makes
* its next run. Aren't we so clever?!!
*/
-void CtdlScheduleRoomForDeletion(struct ctdlroom *qrbuf)
-{
+void CtdlScheduleRoomForDeletion(struct ctdlroom *qrbuf) {
char old_name[ROOMNAMELEN];
static int seq = 0;
}
-
/*
* Back end processing to delete a room and everything associated with it
* (This one is synchronous and should only get called by THE DREADED
* AUTO-PURGER in serv_expire.c. All user-facing code should call
* the asynchronous schedule_room_for_deletion() instead.)
*/
-void CtdlDeleteRoom(struct ctdlroom *qrbuf)
-{
+void CtdlDeleteRoom(struct ctdlroom *qrbuf) {
struct floor flbuf;
char configdbkeyname[25];
}
-
/*
* Internal code to create a new room (returns room flags)
*
int avoid_access,
int new_room_view)
{
-
struct ctdlroom qrbuf;
struct floor flbuf;
visit vbuf;