* This module handles shared rooms, inter-Citadel mail, and outbound
* mailing list processing.
*
- * Copyright (c) 2000-2012 by the citadel.org team
+ * Copyright (c) 2000-2015 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 "internet_addressing.h"
#include "serv_network.h"
#include "clientsocket.h"
-#include "file_ops.h"
#include "citadel_dirs.h"
#include "threads.h"
#include "context.h"
-#include "netconfig.h"
+#include "ctdl_module.h"
#include "netspool.h"
#include "netmail.h"
-#include "ctdl_module.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;
+ struct CitContext *CCC = CC;
+
+ *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) {
+ QN_syslog(LOG_EMERG,
+ "Cannot allocate %ld bytes for recps...\n",
+ (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) {
+void network_deliver_digest(SpoolControl *sc)
+{
struct CitContext *CCC = CC;
+ long len;
char buf[SIZ];
- int i;
+ char *pbuf;
struct CtdlMessage *msg = NULL;
long msglen;
- char *recps = NULL;
- size_t recps_len = SIZ;
- struct recptypes *valid;
- namelist *nptr;
+ recptypes *valid;
char bounce_to[256];
- if (sc->num_msgs_spooled < 1) {
- fclose(sc->digestfp);
- sc->digestfp = NULL;
+ if (sc->Users[digestrecp] == NULL)
return;
- }
msg = malloc(sizeof(struct CtdlMessage));
memset(msg, 0, sizeof(struct CtdlMessage));
msg->cm_format_type = FMT_RFC822;
msg->cm_anon_type = MES_NORMAL;
- sprintf(buf, "%ld", time(NULL));
- msg->cm_fields['T'] = strdup(buf);
- msg->cm_fields['A'] = strdup(CC->room.QRname);
- snprintf(buf, sizeof buf, "[%s]", CC->room.QRname);
- msg->cm_fields['U'] = strdup(buf);
- sprintf(buf, "room_%s@%s", CC->room.QRname, config.c_fqdn);
- for (i=0; buf[i]; ++i) {
- if (isspace(buf[i])) buf[i]='_';
- buf[i] = tolower(buf[i]);
- }
- msg->cm_fields['F'] = strdup(buf);
- msg->cm_fields['R'] = strdup(buf);
+ 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 */
- msg->cm_fields['L'] = malloc(1024);
- snprintf(msg->cm_fields['L'], 1024,
- "%s <%ld.list-id.%s>",
- CC->room.QRname,
- CC->room.QRnumber,
- config.c_fqdn
- );
+ CM_SetField(msg, eListID, SKEY(sc->ListID));
/*
* Go fetch the contents of the digest
fseek(sc->digestfp, 0L, SEEK_END);
msglen = ftell(sc->digestfp);
- msg->cm_fields['M'] = malloc(msglen + 1);
+ pbuf = malloc(msglen + 1);
fseek(sc->digestfp, 0L, SEEK_SET);
- fread(msg->cm_fields['M'], (size_t)msglen, 1, sc->digestfp);
- msg->cm_fields['M'][msglen] = '\0';
-
- fclose(sc->digestfp);
- sc->digestfp = NULL;
+ fread(pbuf, (size_t)msglen, 1, sc->digestfp);
+ pbuf[msglen] = '\0';
+ CM_SetAsField(msg, eMesageText, &pbuf, msglen);
/* Now generate the delivery instructions */
- /*
- * Figure out how big a buffer we need to allocate
- */
- for (nptr = sc->digestrecps; nptr != NULL; nptr = nptr->next) {
- recps_len = recps_len + strlen(nptr->name) + 2;
- }
-
- recps = malloc(recps_len);
-
- if (recps == NULL) {
- QN_syslog(LOG_EMERG,
- "Cannot allocate %ld bytes for recps...\n",
- (long)recps_len);
- abort();
- }
-
- strcpy(recps, "");
-
- /* Each recipient */
- for (nptr = sc->digestrecps; nptr != NULL; nptr = nptr->next) {
- if (nptr != sc->digestrecps) {
- strcat(recps, ",");
- }
- strcat(recps, nptr->name);
- }
-
/* 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", config.c_fqdn);
+ * Surely not the list members! */
+ snprintf(bounce_to, sizeof bounce_to, "room_aide@%s", CtdlGetConfigStr("c_fqdn"));
/* Now submit the message */
- valid = validate_recipients(recps, NULL, 0);
- free(recps);
+ 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, 0);
}
- CtdlFreeMessage(msg);
+ CM_Free(msg);
free_recipients(valid);
}
-/*
- * Deliver list messages to everyone on the list ... efficiently
- */
-void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char *RoomName)
+void network_process_digest(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send)
{
- struct CitContext *CCC = CC;
- char *recps = NULL;
- size_t recps_len = SIZ;
- struct recptypes *valid;
- namelist *nptr;
- char bounce_to[256];
- /* Don't do this if there were no recipients! */
- if (sc->listrecps == NULL) return;
+ struct CtdlMessage *msg = NULL;
- /* Now generate the delivery instructions */
+ if (sc->Users[digestrecp] == NULL)
+ return;
- /*
- * Figure out how big a buffer we need to allocate
- */
- for (nptr = sc->listrecps; nptr != NULL; nptr = nptr->next) {
- recps_len = recps_len + strlen(nptr->name) + 2;
- }
+ /* If there are digest recipients, we have to build a digest */
+ if (sc->digestfp == NULL) {
+
+ sc->digestfp = create_digest_file(&sc->room, 1);
- recps = malloc(recps_len);
+ if (sc->digestfp == NULL)
+ return;
- if (recps == NULL) {
- QN_syslog(LOG_EMERG,
- "Cannot allocate %ld bytes for recps...\n",
- (long)recps_len);
- abort();
+ sc->haveDigest = ftell(sc->digestfp) > 0;
+ if (!sc->haveDigest) {
+ fprintf(sc->digestfp, "Content-type: text/plain\n\n");
+ }
+ sc->haveDigest = 1;
}
- strcpy(recps, "");
-
- /* Each recipient */
- for (nptr = sc->listrecps; nptr != NULL; nptr = nptr->next) {
- if (nptr != sc->listrecps) {
- strcat(recps, ",");
+ 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]);
+ }
+ else if (!CM_IsEmpty(msg, eNodeName)) {
+ fprintf(sc->digestfp,
+ "@%s ",
+ msg->cm_fields[eNodeName]);
+ }
+ fprintf(sc->digestfp, "\n");
+ if (!CM_IsEmpty(msg, eMsgSubject)) {
+ fprintf(sc->digestfp,
+ "Subject: %s\n",
+ msg->cm_fields[eMsgSubject]);
}
- strcat(recps, nptr->name);
- }
- /* 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", config.c_fqdn);
+ CC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
- /* Now submit the message */
- valid = validate_recipients(recps, NULL, 0);
- free(recps);
- if (valid != NULL) {
- valid->bounce_to = strdup(bounce_to);
- valid->envelope_from = strdup(bounce_to);
- valid->sending_room = strdup(RoomName);
- CtdlSubmitMsg(msg, valid, NULL, 0);
- free_recipients(valid);
+ 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);
}
- /* Do not call CtdlFreeMessage(msg) here; the caller will free it. */
}
-/*
- * Spools out one message from the list.
- */
-void network_spool_msg(long msgnum,
- void *userdata)
+void network_process_list(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send)
{
- struct CitContext *CCC = CC;
- StrBuf *Buf = NULL;
- SpoolControl *sc;
- int i;
- char *newpath = NULL;
struct CtdlMessage *msg = NULL;
- namelist *nptr;
- maplist *mptr;
- struct ser_ret sermsg;
- FILE *fp;
- char filename[PATH_MAX];
- char buf[SIZ];
- int bang = 0;
- int send = 1;
- int delete_after_send = 0; /* Set to 1 to delete after spooling */
- int ok_to_participate = 0;
- struct recptypes *valid;
-
- sc = (SpoolControl *)userdata;
/*
* Process mailing list recipients
*/
- if (sc->listrecps != NULL) {
- /* Fetch the message. We're going to need to modify it
- * in order to insert the [list name] in it, etc.
- */
- msg = CtdlFetchMessage(msgnum, 1);
- if (msg != NULL) {
- int rlen;
- char *pCh;
- StrBuf *Subject, *FlatSubject;
-
- if (msg->cm_fields['K'] != NULL)
- free(msg->cm_fields['K']);
- if (msg->cm_fields['V'] == NULL){
- /* local message, no enVelope */
- StrBuf *Buf;
- Buf = NewStrBuf();
- StrBufAppendBufPlain(Buf,
- msg->cm_fields['O']
- , -1, 0);
- StrBufAppendBufPlain(Buf, HKEY("@"), 0);
- StrBufAppendBufPlain(Buf, config.c_fqdn, -1, 0);
-
- msg->cm_fields['K'] = SmashStrBuf(&Buf);
- }
- else {
- msg->cm_fields['K'] =
- strdup (msg->cm_fields['V']);
- }
- /* Set the 'List-ID' header */
- if (msg->cm_fields['L'] != NULL) {
- free(msg->cm_fields['L']);
- }
- msg->cm_fields['L'] = malloc(1024);
- snprintf(msg->cm_fields['L'], 1024,
- "%s <%ld.list-id.%s>",
- CC->room.QRname,
- CC->room.QRnumber,
- config.c_fqdn
- );
-
- /* Prepend "[List name]" to the subject */
- if (msg->cm_fields['U'] == NULL) {
- Subject = NewStrBufPlain(HKEY("(no subject)"));
- }
- else {
- Subject = NewStrBufPlain(
- msg->cm_fields['U'], -1);
- }
- FlatSubject = NewStrBufPlain(NULL, StrLength(Subject));
- StrBuf_RFC822_to_Utf8(FlatSubject, Subject, NULL, NULL);
-
- rlen = strlen(CC->room.QRname);
- pCh = strstr(ChrPtr(FlatSubject), CC->room.QRname);
- if ((pCh == NULL) ||
- (*(pCh + rlen) != ']') ||
- (pCh == ChrPtr(FlatSubject)) ||
- (*(pCh - 1) != '[')
- )
- {
- StrBuf *tmp;
- StrBufPlain(Subject, HKEY("["));
- StrBufAppendBufPlain(Subject,
- CC->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);
- }
+ if (sc->Users[listrecp] == NULL)
+ return;
- if (msg->cm_fields['U'] != NULL)
- free (msg->cm_fields['U']);
- msg->cm_fields['U'] = SmashStrBuf(&Subject);
+ /* 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.
+ */
- FreeStrBuf(&FlatSubject);
+ msg = CM_Duplicate(omsg);
- /* else we won't modify the buffer, since the
- * roomname is already here.
- */
- /* if there is no other recipient, Set the recipient
- * of the list message to the email address of the
- * room itself.
- */
- if ((msg->cm_fields['R'] == NULL) ||
- IsEmptyStr(msg->cm_fields['R']))
- {
- if (msg->cm_fields['R'] != NULL)
- free(msg->cm_fields['R']);
-
- msg->cm_fields['R'] = malloc(256);
- snprintf(msg->cm_fields['R'], 256,
- "room_%s@%s", CC->room.QRname,
- config.c_fqdn);
- for (i=0; msg->cm_fields['R'][i]; ++i) {
- if (isspace(msg->cm_fields['R'][i])) {
- msg->cm_fields['R'][i] = '_';
- }
- }
- }
+ CM_SetField(msg, eReplyTo, SKEY(sc->Users[roommailalias]));
- /* Handle delivery */
- network_deliver_list(msg, sc, CC->room.QRname);
- CtdlFreeMessage(msg);
- }
+ /* 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]));
}
- /*
- * Process digest recipients
- */
- if ((sc->digestrecps != NULL) && (sc->digestfp != NULL)) {
- msg = CtdlFetchMessage(msgnum, 1);
- if (msg != NULL) {
- fprintf(sc->digestfp,
- " -----------------------------------"
- "------------------------------------"
- "-------\n");
- fprintf(sc->digestfp, "From: ");
- if (msg->cm_fields['A'] != NULL) {
- fprintf(sc->digestfp,
- "%s ",
- msg->cm_fields['A']);
- }
- if (msg->cm_fields['F'] != NULL) {
- fprintf(sc->digestfp,
- "<%s> ",
- msg->cm_fields['F']);
- }
- else if (msg->cm_fields['N'] != NULL) {
- fprintf(sc->digestfp,
- "@%s ",
- msg->cm_fields['N']);
- }
- fprintf(sc->digestfp, "\n");
- if (msg->cm_fields['U'] != NULL) {
- fprintf(sc->digestfp,
- "Subject: %s\n",
- msg->cm_fields['U']);
- }
+ /* Set the 'List-ID' header */
+ CM_SetField(msg, eListID, SKEY(sc->ListID));
- CC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
- safestrncpy(CC->preferred_formats,
- "text/plain",
- sizeof CC->preferred_formats);
+ /* Prepend "[List name]" to the subject */
+ ListCalculateSubject(msg);
- CtdlOutputPreLoadedMsg(msg,
- MT_CITADEL,
- HEADERS_NONE,
- 0, 0, 0);
+ /* 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];
- StrBufTrim(CC->redirect_buffer);
- fwrite(HKEY("\n"), 1, sc->digestfp);
- fwrite(SKEY(CC->redirect_buffer), 1, sc->digestfp);
- fwrite(HKEY("\n"), 1, sc->digestfp);
+ /* Don't do this if there were no recipients! */
+ if (sc->Users[listrecp] == NULL)
+ return;
- FreeStrBuf(&CC->redirect_buffer);
+ /* Now generate the delivery instructions */
- sc->num_msgs_spooled += 1;
- CtdlFreeMessage(msg);
- }
+ /* 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, 0);
+ 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;
+ StrBuf *Buf = NULL;
+ recptypes *valid;
/*
* Process client-side list participations for this room
*/
- if (sc->participates != NULL) {
- msg = CtdlFetchMessage(msgnum, 1);
- if (msg != NULL) {
-
- /* 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;
- if (msg->cm_fields['N'] != NULL) {
- if (!strcasecmp(msg->cm_fields['N'],
- config.c_nodename)) {
- ok_to_participate = 1;
- }
+ if (sc->Users[participate] == NULL)
+ return;
- Buf = NewStrBufPlain(msg->cm_fields['N'], -1);
- if (is_valid_node(NULL,
- NULL,
- Buf,
- sc->working_ignetcfg,
- sc->the_netmap) == 0)
- {
- ok_to_participate = 1;
- }
- }
- if (ok_to_participate) {
- if (msg->cm_fields['F'] != NULL) {
- free(msg->cm_fields['F']);
- }
- msg->cm_fields['F'] = malloc(SIZ);
- /* 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.
- * FIXME I want to be able to pick any address
- */
- snprintf(msg->cm_fields['F'], SIZ,
- "room_%s@%s", CC->room.QRname,
- config.c_fqdn);
- for (i=0; msg->cm_fields['F'][i]; ++i) {
- if (isspace(msg->cm_fields['F'][i])) {
- msg->cm_fields['F'][i] = '_';
- }
- }
+ msg = CM_Duplicate(omsg);
- /*
- * Figure out how big a buffer we need to alloc
- */
- for (nptr = sc->participates;
- nptr != NULL;
- nptr = nptr->next)
- {
- if (msg->cm_fields['R'] != NULL) {
- free(msg->cm_fields['R']);
- }
- msg->cm_fields['R'] =
- strdup(nptr->name);
-
- valid = validate_recipients(nptr->name,
- NULL, 0);
-
- CtdlSubmitMsg(msg, valid, "", 0);
- free_recipients(valid);
- }
- }
- CtdlFreeMessage(msg);
+ /* 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;
+ if (!CM_IsEmpty(msg, eNodeName)) {
+ if (!strcasecmp(msg->cm_fields[eNodeName], CtdlGetConfigStr("c_nodename")))
+ {
+ ok_to_participate = 1;
+ }
+
+ Buf = NewStrBufPlain(CM_KEY(msg, eNodeName));
+ if (CtdlIsValidNode(NULL,
+ NULL,
+ Buf,
+ sc->working_ignetcfg,
+ sc->the_netmap) == 0)
+ {
+ ok_to_participate = 1;
}
}
+ 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, "", 0);
+ free_recipients(valid);
+ }
+ FreeStrBuf(&Buf);
+ CM_Free(msg);
+}
+
+void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send)
+{
+ StrBuf *Recipient;
+ StrBuf *RemoteRoom;
+ const char *Pos = NULL;
+ struct CtdlMessage *msg = NULL;
+ struct CitContext *CCC = CC;
+ struct ser_ret sermsg;
+ char buf[SIZ];
+ char filename[PATH_MAX];
+ FILE *fp;
+ StrBuf *Buf = NULL;
+ int i;
+ int bang = 0;
+ int send = 1;
+
+ if (sc->Users[ignet_push_share] == NULL)
+ return;
/*
* Process IGnet push shares
*/
- msg = CtdlFetchMessage(msgnum, 1);
- if (msg != NULL) {
- size_t newpath_len;
+ msg = CM_Duplicate(omsg);
- /* Prepend our node name to the Path field whenever
- * sending a message to another IGnet node
- */
- if (msg->cm_fields['P'] == NULL) {
- msg->cm_fields['P'] = strdup("username");
+ /* Prepend our node name to the Path field whenever
+ * sending a message to another IGnet node
+ */
+ Netmap_AddMe(msg, HKEY("username"));
+
+ /*
+ * Determine if this message is set to be deleted
+ * after sending out on the network
+ */
+ if (!CM_IsEmpty(msg, eSpecialField)) {
+ if (!strcasecmp(msg->cm_fields[eSpecialField], "CANCEL")) {
+ *delete_after_send = 1;
}
- newpath_len = strlen(msg->cm_fields['P']) +
- strlen(config.c_nodename) + 2;
- newpath = malloc(newpath_len);
- snprintf(newpath, newpath_len, "%s!%s",
- config.c_nodename, msg->cm_fields['P']);
- free(msg->cm_fields['P']);
- msg->cm_fields['P'] = newpath;
-
- /*
- * Determine if this message is set to be deleted
- * after sending out on the network
- */
- if (msg->cm_fields['S'] != NULL) {
- if (!strcasecmp(msg->cm_fields['S'], "CANCEL")) {
- delete_after_send = 1;
+ }
+
+ /* Now send it to every node */
+ Recipient = NewStrBufPlain(NULL, StrLength(sc->Users[ignet_push_share]));
+ RemoteRoom = NewStrBufPlain(NULL, StrLength(sc->Users[ignet_push_share]));
+ while ((Pos != StrBufNOTNULL) &&
+ StrBufExtract_NextToken(Recipient, sc->Users[ignet_push_share], &Pos, ','))
+ {
+ StrBufExtract_NextToken(RemoteRoom, sc->Users[ignet_push_share], &Pos, ',');
+ send = 1;
+ NewStrBufDupAppendFlush(&Buf, Recipient, NULL, 1);
+
+ /* Check for valid node name */
+ if (CtdlIsValidNode(NULL,
+ NULL,
+ Buf,
+ sc->working_ignetcfg,
+ sc->the_netmap) != 0)
+ {
+ QN_syslog(LOG_ERR,
+ "Invalid node <%s>\n",
+ ChrPtr(Recipient));
+
+ send = 0;
+ }
+
+ /* Check for split horizon */
+ QN_syslog(LOG_DEBUG, "Path is %s\n", msg->cm_fields[eMessagePath]);
+ bang = num_tokens(msg->cm_fields[eMessagePath], '!');
+ if (bang > 1) {
+ for (i=0; i<(bang-1); ++i) {
+ extract_token(buf,
+ msg->cm_fields[eMessagePath],
+ i, '!',
+ sizeof buf);
+
+ QN_syslog(LOG_DEBUG, "Compare <%s> to <%s>\n",
+ buf, ChrPtr(Recipient)) ;
+ if (!strcasecmp(buf, ChrPtr(Recipient))) {
+ send = 0;
+ break;
+ }
}
+
+ QN_syslog(LOG_INFO,
+ " %sSending to %s\n",
+ (send)?"":"Not ",
+ ChrPtr(Recipient));
}
-
- /* Now send it to every node */
- if (sc->ignet_push_shares != NULL)
- for (mptr = sc->ignet_push_shares; mptr != NULL;
- mptr = mptr->next) {
-
- send = 1;
- if (Buf == NULL)
- Buf = NewStrBufPlain(mptr->remote_nodename, -1);
- else
- StrBufPlain(Buf, mptr->remote_nodename, -1);
- /* Check for valid node name */
- if (is_valid_node(NULL,
- NULL,
- Buf,
- sc->working_ignetcfg,
- sc->the_netmap) != 0)
- {
- QN_syslog(LOG_ERR,
- "Invalid node <%s>\n",
- mptr->remote_nodename);
-
- send = 0;
+
+ /* Send the message */
+ if (send == 1)
+ {
+ /*
+ * Force the message to appear in the correct
+ * room on the far end by setting the C field
+ * correctly
+ */
+ if (StrLength(RemoteRoom) > 0) {
+ CM_SetField(msg, eRemoteRoom, SKEY(RemoteRoom));
}
-
- /* Check for split horizon */
- QN_syslog(LOG_DEBUG, "Path is %s\n", msg->cm_fields['P']);
- bang = num_tokens(msg->cm_fields['P'], '!');
- if (bang > 1) {
- for (i=0; i<(bang-1); ++i) {
- extract_token(buf,
- msg->cm_fields['P'],
- i, '!',
- sizeof buf);
+ else {
+ CM_SetField(msg, eRemoteRoom, CCC->room.QRname, strlen(CCC->room.QRname));
+ }
+
+ /* serialize it for transmission */
+ CtdlSerializeMessage(&sermsg, msg);
+ if (sermsg.len > 0) {
+
+ /* write it to a spool file */
+ snprintf(filename,
+ sizeof(filename),
+ "%s/%s@%lx%x",
+ ctdl_netout_dir,
+ ChrPtr(Recipient),
+ time(NULL),
+ rand()
+ );
- QN_syslog(LOG_DEBUG, "Compare <%s> to <%s>\n",
- buf, mptr->remote_nodename) ;
- if (!strcasecmp(buf, mptr->remote_nodename)) {
- send = 0;
- break;
- }
+ QN_syslog(LOG_DEBUG,
+ "Appending to %s\n",
+ filename);
+
+ fp = fopen(filename, "ab");
+ if (fp != NULL) {
+ fwrite(sermsg.ser,
+ sermsg.len, 1, fp);
+ fclose(fp);
+ }
+ else {
+ QN_syslog(LOG_ERR,
+ "%s: %s\n",
+ filename,
+ strerror(errno));
}
- QN_syslog(LOG_INFO,
- "%sSending to %s\n",
- (send)?"":"Not ",
- mptr->remote_nodename);
+ /* free the serialized version */
+ free(sermsg.ser);
}
+ }
+ }
+ FreeStrBuf(&Buf);
+ FreeStrBuf(&Recipient);
+ FreeStrBuf(&RemoteRoom);
+ CM_Free(msg);
+}
- /* Send the message */
- if (send == 1)
- {
- /*
- * Force the message to appear in the correct
- * room on the far end by setting the C field
- * correctly
- */
- if (msg->cm_fields['C'] != NULL) {
- free(msg->cm_fields['C']);
- }
- if (!IsEmptyStr(mptr->remote_roomname)) {
- msg->cm_fields['C'] =
- strdup(mptr->remote_roomname);
- }
- else {
- msg->cm_fields['C'] =
- strdup(CC->room.QRname);
- }
- /* serialize it for transmission */
- serialize_message(&sermsg, msg);
- if (sermsg.len > 0) {
-
- /* write it to a spool file */
- snprintf(filename,
- sizeof(filename),
- "%s/%s@%lx%x",
- ctdl_netout_dir,
- mptr->remote_nodename,
- time(NULL),
- rand()
- );
+/*
+ * Spools out one message from the list.
+ */
+void network_spool_msg(long msgnum,
+ void *userdata)
+{
+ struct CitContext *CCC = CC;
+ struct CtdlMessage *msg = NULL;
+ long delete_after_send = 0; /* Set to 1 to delete after spooling */
+ SpoolControl *sc;
- QN_syslog(LOG_DEBUG,
- "Appending to %s\n",
- filename);
-
- fp = fopen(filename, "ab");
- if (fp != NULL) {
- fwrite(sermsg.ser,
- sermsg.len, 1, fp);
- fclose(fp);
- }
- else {
- QN_syslog(LOG_ERR,
- "%s: %s\n",
- filename,
- strerror(errno));
- }
-
- /* free the serialized version */
- free(sermsg.ser);
- }
+ sc = (SpoolControl *)userdata;
- }
- }
- CtdlFreeMessage(msg);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
+
+ if (msg == NULL)
+ {
+ QN_syslog(LOG_ERR,
+ "failed to load Message <%ld> from disk\n",
+ 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);
+ network_process_ignetpush(sc, msg, &delete_after_send);
+
+ CM_Free(msg);
/* update lastsent */
sc->lastsent = msgnum;
if (delete_after_send) {
CtdlDeleteMessages(CC->room.QRname, &msgnum, 1, "");
}
- FreeStrBuf(&Buf);
}