]> code.citadel.org Git - citadel.git/blobdiff - citadel/modules/network/serv_netmail.c
NETCFG: more work on details
[citadel.git] / citadel / modules / network / serv_netmail.c
index 709877a64a6454cc74530d6f5dcde76942a36f9f..ea324a5904be9ba9e61b40b33cfd7ad72be6c98f 100644 (file)
@@ -2,22 +2,16 @@
  * 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) {
@@ -160,27 +150,25 @@ void network_deliver_digest(SpoolControl *sc) {
        /*
         * 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?
@@ -188,8 +176,9 @@ void network_deliver_digest(SpoolControl *sc) {
        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);
@@ -203,42 +192,43 @@ void network_deliver_digest(SpoolControl *sc) {
 /*
  * 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?
@@ -246,11 +236,13 @@ void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc) {
        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);
        }
@@ -264,12 +256,14 @@ void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc) {
 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];
@@ -285,7 +279,7 @@ void network_spool_msg(long msgnum,
        /*
         * 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.
                 */
@@ -390,7 +384,7 @@ void network_spool_msg(long msgnum,
                        }
 
                        /* Handle delivery */
-                       network_deliver_list(msg, sc);
+                       network_deliver_list(msg, sc, CC->room.QRname);
                        CtdlFreeMessage(msg);
                }
        }
@@ -398,7 +392,7 @@ void network_spool_msg(long msgnum,
        /*
         * 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,
@@ -454,7 +448,7 @@ void network_spool_msg(long msgnum,
        /*
         * 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) {
 
@@ -469,11 +463,13 @@ void network_spool_msg(long msgnum,
                                                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;
                                }
@@ -501,7 +497,7 @@ void network_spool_msg(long msgnum,
                                /*
                                 * 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)
                                {
@@ -509,9 +505,9 @@ void network_spool_msg(long msgnum,
                                                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);
@@ -522,147 +518,151 @@ void network_spool_msg(long msgnum,
                }
        }
 
-       /*
-        * 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);
 }