* This module handles shared rooms, inter-Citadel mail, and outbound
* mailing list processing.
*
- * Copyright (c) 2000-2011 by the citadel.org team
+ * Copyright (c) 2000-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 as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
+ * 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.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* ** NOTE ** A word on the S_NETCONFIGS semaphore:
* This is a fairly high-level type of critical section. It ensures that no
* two threads work on the netconfigs files at the same time. Since we do
#include "file_ops.h"
#include "citadel_dirs.h"
#include "threads.h"
-
-#ifndef HAVE_SNPRINTF
-#include "snprintf.h"
-#endif
-
#include "context.h"
-#include "netconfig.h"
+#include "ctdl_module.h"
#include "netspool.h"
#include "netmail.h"
-#include "ctdl_module.h"
/*
* Deliver digest messages
*/
void network_deliver_digest(SpoolControl *sc) {
+ struct CitContext *CCC = CC;
char buf[SIZ];
int i;
struct CtdlMessage *msg = NULL;
long msglen;
- char *recps = NULL;
+ StrBuf *recps = NULL;
+ char *precps;
size_t recps_len = SIZ;
struct recptypes *valid;
- namelist *nptr;
+ RoomNetCfgLine *nptr;
char bounce_to[256];
if (sc->num_msgs_spooled < 1) {
/*
* 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;
+ for (nptr = sc->RNCfg->NetConfigs[digestrecp]; nptr != NULL; nptr = nptr->next) {
+ recps_len = recps_len + StrLength(nptr->Value[0]) + 2;
}
- recps = malloc(recps_len);
+ recps = NewStrBufPlain(NULL, recps_len);
if (recps == NULL) {
- syslog(LOG_EMERG,
- "Cannot allocate %ld bytes for recps...\n",
- (long)recps_len);
+ 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, ",");
+ for (nptr = sc->RNCfg->NetConfigs[digestrecp]; nptr != NULL; nptr = nptr->next) {
+ if (nptr != sc->RNCfg->NetConfigs[digestrecp]) {
+ StrBufAppendBufPlain(recps, HKEY(","), 0);
}
- strcat(recps, nptr->name);
+ StrBufAppendBuf(recps, nptr->Value[0], 0);
}
/* Where do we want bounces and other noise to be heard?
snprintf(bounce_to, sizeof bounce_to, "room_aide@%s", config.c_fqdn);
/* Now submit the message */
- valid = validate_recipients(recps, NULL, 0);
- free(recps);
+ precps = SmashStrBuf(&recps);
+ valid = validate_recipients(precps, NULL, 0);
+ free(precps);
if (valid != NULL) {
valid->bounce_to = strdup(bounce_to);
valid->envelope_from = strdup(bounce_to);
/*
* Deliver list messages to everyone on the list ... efficiently
*/
-void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc) {
- char *recps = NULL;
+void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char *RoomName)
+{
+ struct CitContext *CCC = CC;
+ StrBuf *recps = NULL;
+ char *precps = NULL;
size_t recps_len = SIZ;
struct recptypes *valid;
- namelist *nptr;
+ RoomNetCfgLine *nptr;
char bounce_to[256];
/* Don't do this if there were no recipients! */
- if (sc->listrecps == NULL) return;
+ if (sc->RNCfg->NetConfigs[listrecp] == NULL) return;
/* Now generate the delivery instructions */
/*
* 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;
+ for (nptr = sc->RNCfg->NetConfigs[listrecp]; nptr != NULL; nptr = nptr->next) {
+ recps_len = recps_len + StrLength(nptr->Value[0]) + 2;
}
- recps = malloc(recps_len);
+ recps = NewStrBufPlain(NULL, recps_len);
if (recps == NULL) {
- syslog(LOG_EMERG,
- "Cannot allocate %ld bytes for recps...\n",
- (long)recps_len);
+ QN_syslog(LOG_EMERG,
+ "Cannot allocate %ld bytes for recps...\n",
+ (long)recps_len);
abort();
}
- strcpy(recps, "");
-
/* Each recipient */
- for (nptr = sc->listrecps; nptr != NULL; nptr = nptr->next) {
- if (nptr != sc->listrecps) {
- strcat(recps, ",");
+ for (nptr = sc->RNCfg->NetConfigs[listrecp]; nptr != NULL; nptr = nptr->next) {
+ if (nptr != sc->RNCfg->NetConfigs[listrecp]) {
+ StrBufAppendBufPlain(recps, HKEY(","), 0);
}
- strcat(recps, nptr->name);
+ StrBufAppendBuf(recps, nptr->Value[0], 0);
}
/* Where do we want bounces and other noise to be heard?
snprintf(bounce_to, sizeof bounce_to, "room_aide@%s", config.c_fqdn);
/* Now submit the message */
- valid = validate_recipients(recps, NULL, 0);
- free(recps);
+ precps = SmashStrBuf(&recps);
+ valid = validate_recipients(precps, NULL, 0);
+ free(precps);
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);
}
void network_spool_msg(long msgnum,
void *userdata)
{
+ RoomNetCfgLine* mptr;
+ struct CitContext *CCC = CC;
+ StrBuf *Buf = NULL;
SpoolControl *sc;
int i;
char *newpath = NULL;
struct CtdlMessage *msg = NULL;
- namelist *nptr;
- maplist *mptr;
+ RoomNetCfgLine *nptr;
struct ser_ret sermsg;
FILE *fp;
char filename[PATH_MAX];
/*
* Process mailing list recipients
*/
- if (sc->listrecps != NULL) {
+ if (sc->RNCfg->NetConfigs[listrecp] != NULL) {
/* Fetch the message. We're going to need to modify it
* in order to insert the [list name] in it, etc.
*/
}
/* Handle delivery */
- network_deliver_list(msg, sc);
+ network_deliver_list(msg, sc, CC->room.QRname);
CtdlFreeMessage(msg);
}
}
/*
* Process digest recipients
*/
- if ((sc->digestrecps != NULL) && (sc->digestfp != NULL)) {
+ if ((sc->RNCfg->NetConfigs[digestrecp] != NULL) && (sc->digestfp != NULL)) {
msg = CtdlFetchMessage(msgnum, 1);
if (msg != NULL) {
fprintf(sc->digestfp,
/*
* Process client-side list participations for this room
*/
- if (sc->participates != NULL) {
+ if (sc->RNCfg->NetConfigs[participate] != NULL) {
msg = CtdlFetchMessage(msgnum, 1);
if (msg != NULL) {
config.c_nodename)) {
ok_to_participate = 1;
}
- if (is_valid_node(NULL,
- NULL,
- msg->cm_fields['N'],
- sc->working_ignetcfg,
- sc->the_netmap) == 0)
+
+ Buf = NewStrBufPlain(msg->cm_fields['N'], -1);
+ if (CtdlIsValidNode(NULL,
+ NULL,
+ Buf,
+ sc->working_ignetcfg,
+ sc->the_netmap) == 0)
{
ok_to_participate = 1;
}
/*
* Figure out how big a buffer we need to alloc
*/
- for (nptr = sc->participates;
+ for (nptr = sc->RNCfg->NetConfigs[participate];
nptr != NULL;
nptr = nptr->next)
{
free(msg->cm_fields['R']);
}
msg->cm_fields['R'] =
- strdup(nptr->name);
+ strdup(ChrPtr(nptr->Value[0]));
- valid = validate_recipients(nptr->name,
+ valid = validate_recipients(msg->cm_fields['R'],
NULL, 0);
CtdlSubmitMsg(msg, valid, "", 0);
}
}
- /*
- * Process IGnet push shares
- */
- msg = CtdlFetchMessage(msgnum, 1);
- if (msg != NULL) {
- size_t newpath_len;
-
- /* 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");
- }
- 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;
-
+ if (sc->RNCfg->NetConfigs[ignet_push_share] != NULL)
+ {
/*
- * Determine if this message is set to be deleted
- * after sending out on the network
+ * Process IGnet push shares
*/
- if (msg->cm_fields['S'] != NULL) {
- if (!strcasecmp(msg->cm_fields['S'], "CANCEL")) {
- delete_after_send = 1;
- }
- }
-
- /* 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;
-
- /* Check for valid node name */
- if (is_valid_node(NULL,
- NULL,
- mptr->remote_nodename,
- sc->working_ignetcfg,
- sc->the_netmap) != 0)
- {
- syslog(LOG_ERR,
- "Invalid node <%s>\n",
- mptr->remote_nodename);
+ msg = CtdlFetchMessage(msgnum, 1);
+ if (msg != NULL) {
+ size_t newpath_len;
- send = 0;
+ /* 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");
}
-
- /* Check for split horizon */
- 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);
-
- syslog(LOG_DEBUG, "Compare <%s> to <%s>\n",
- buf, mptr->remote_nodename) ;
- if (!strcasecmp(buf, mptr->remote_nodename)) {
- send = 0;
- syslog(LOG_DEBUG, "Not sending to %s\n",
- mptr->remote_nodename);
- }
- else {
- syslog(LOG_DEBUG,
- "Sending to %s\n",
- mptr->remote_nodename);
+ 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;
}
}
- /* 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()
- );
-
- syslog(LOG_DEBUG,
- "Appending to %s\n",
- filename);
-
- fp = fopen(filename, "ab");
- if (fp != NULL) {
- fwrite(sermsg.ser,
- sermsg.len, 1, fp);
- fclose(fp);
+ /* Now send it to every node */
+ if (sc->RNCfg->NetConfigs[ignet_push_share] != NULL)
+ for (mptr = sc->RNCfg->NetConfigs[ignet_push_share]; mptr != NULL;
+ mptr = mptr->next) {
+
+ send = 1;
+ NewStrBufDupAppendFlush(&Buf, mptr->Value[0], 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(mptr->Value[0]));
+
+ send = 0;
}
- else {
- syslog(LOG_ERR,
- "%s: %s\n",
- filename,
- strerror(errno));
+
+ /* 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);
+
+ QN_syslog(LOG_DEBUG, "Compare <%s> to <%s>\n",
+ buf, ChrPtr(mptr->Value[0])) ;
+ if (!strcasecmp(buf, ChrPtr(mptr->Value[0]))) {
+ send = 0;
+ break;
+ }
+ }
+
+ QN_syslog(LOG_INFO,
+ "%sSending to %s\n",
+ (send)?"":"Not ",
+ ChrPtr(mptr->Value[0]));
}
- /* free the serialized version */
- free(sermsg.ser);
- }
+ /* 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 (StrLength(mptr->Value[0]) > 0) {
+ msg->cm_fields['C'] =
+ strdup(ChrPtr(mptr->Value[0]));
+ }
+ 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,
+ ChrPtr(mptr->Value[0]),
+ time(NULL),
+ rand()
+ );
+
+ 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);
+ }
- }
+ }
+ }
+ CtdlFreeMessage(msg);
}
- CtdlFreeMessage(msg);
}
-
/* update lastsent */
- sc->lastsent = msgnum;
+ ///sc->lastsent = msgnum; ////// TODO
/* Delete this message if delete-after-send is set */
if (delete_after_send) {
CtdlDeleteMessages(CC->room.QRname, &msgnum, 1, "");
}
-
+ FreeStrBuf(&Buf);
}