* Initial support for having a room participate in a remote mailing list
authorArt Cancro <ajc@citadel.org>
Thu, 13 Jan 2005 05:43:17 +0000 (05:43 +0000)
committerArt Cancro <ajc@citadel.org>
Thu, 13 Jan 2005 05:43:17 +0000 (05:43 +0000)
citadel/ChangeLog
citadel/serv_network.c
citadel/serv_network.h
citadel/techdoc/netconfigs.txt

index 782446669246f392931193dcb5b45c668a1155c0..f7ae4282124a59c2ee6ea81e916a262df5c5ba9b 100644 (file)
@@ -1,4 +1,7 @@
  $Log$
+ Revision 629.4  2005/01/13 05:43:16  ajc
+ * Initial support for having a room participate in a remote mailing list
+
  Revision 629.3  2005/01/09 03:20:41  ajc
  * Applied a patch sent in by David Given for handling of the "&" character
    plus Unicode characters in IMAP folder names.
@@ -6265,3 +6268,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import
+
index e014411000681f843579faea15e555cd82452350..9b64504ac70dd58acbf32d490534967cacee9403 100644 (file)
@@ -429,12 +429,15 @@ void network_spool_msg(long msgnum, void *userdata) {
        int bang = 0;
        int send = 1;
        int delete_after_send = 0;      /* Set to 1 to delete after spooling */
+       long list_msgnum = 0L;
+       int ok_to_participate = 0;
 
        sc = (struct SpoolControl *)userdata;
 
        /*
         * Process mailing list recipients
         */
+       instr_len = SIZ;
        if (sc->listrecps != NULL) {
        
                /* First, copy it to the spoolout room */
@@ -454,7 +457,8 @@ void network_spool_msg(long msgnum, void *userdata) {
                lprintf(CTDL_DEBUG, "Generating delivery instructions\n");
                instr = malloc(instr_len);
                if (instr == NULL) {
-                       lprintf(CTDL_EMERG, "Cannot allocate %ld bytes for instr...\n",
+                       lprintf(CTDL_EMERG,
+                               "Cannot allocate %ld bytes for instr...\n",
                                (long)instr_len);
                        abort();
                }
@@ -498,6 +502,97 @@ void network_spool_msg(long msgnum, void *userdata) {
                CtdlRedirectOutput(NULL, -1);
                sc->num_msgs_spooled += 1;
        }
+
+       /*
+        * Process client-side list participations for this room
+        */
+       instr_len = SIZ;
+       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 (is_valid_node(NULL, NULL, msg->cm_fields['N']) == 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; i<strlen(msg->cm_fields['F']); ++i) {
+                                       if (isspace(msg->cm_fields['F'][i])) {
+                                               msg->cm_fields['F'][i] = '_';
+                                       }
+                               }
+
+                               /* Now save it and generate delivery instructions */
+                               list_msgnum = CtdlSubmitMsg(msg, NULL, SMTP_SPOOLOUT_ROOM);
+
+                               /* 
+                                * Figure out how big a buffer we need to allocate
+                                */
+                               for (nptr = sc->participates; nptr != NULL; nptr = nptr->next) {
+                                       instr_len = instr_len + strlen(nptr->name);
+                               }
+                       
+                               /*
+                                * allocate...
+                                */
+                               instr = malloc(instr_len);
+                               if (instr == NULL) {
+                                       lprintf(CTDL_EMERG,
+                                               "Cannot allocate %ld bytes for instr...\n",
+                                               (long)instr_len);
+                                       abort();
+                               }
+                               snprintf(instr, instr_len,
+                                       "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
+                                       "bounceto|postmaster@%s\n" ,
+                                       SPOOLMIME, list_msgnum, (long)time(NULL), config.c_fqdn );
+                       
+                               /* Generate delivery instructions for each recipient */
+                               for (nptr = sc->participates; nptr != NULL; nptr = nptr->next) {
+                                       size_t tmp = strlen(instr);
+                                       snprintf(&instr[tmp], instr_len - tmp,
+                                                "remote|%s|0||\n", nptr->name);
+                               }
+                       
+                               /*
+                                * Generate a message from the instructions
+                                */
+                               imsg = malloc(sizeof(struct CtdlMessage));
+                               memset(imsg, 0, sizeof(struct CtdlMessage));
+                               imsg->cm_magic = CTDLMESSAGE_MAGIC;
+                               imsg->cm_anon_type = MES_NORMAL;
+                               imsg->cm_format_type = FMT_RFC822;
+                               imsg->cm_fields['A'] = strdup("Citadel");
+                               imsg->cm_fields['M'] = instr;
+                       
+                               /* Save delivery instructions in spoolout room */
+                               CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM);
+                               CtdlFreeMessage(imsg);
+                       }
+                       CtdlFreeMessage(msg);
+               }
+       }
        
        /*
         * Process IGnet push shares
@@ -757,6 +852,13 @@ void network_spoolout_room(char *room_to_spool) {
                        extract(nptr->name, buf, 1);
                        sc.listrecps = nptr;
                }
+               else if (!strcasecmp(instr, "participate")) {
+                       nptr = (struct namelist *)
+                               malloc(sizeof(struct namelist));
+                       nptr->next = sc.participates;
+                       extract(nptr->name, buf, 1);
+                       sc.participates = nptr;
+               }
                else if (!strcasecmp(instr, "digestrecp")) {
                        nptr = (struct namelist *)
                                malloc(sizeof(struct namelist));
@@ -867,6 +969,13 @@ void network_spoolout_room(char *room_to_spool) {
                        free(sc.digestrecps);
                        sc.digestrecps = nptr;
                }
+               /* Do the same for participates */
+               while (sc.participates != NULL) {
+                       fprintf(fp, "participate|%s\n", sc.participates->name);
+                       nptr = sc.participates->next;
+                       free(sc.participates);
+                       sc.participates = nptr;
+               }
                while (sc.ignet_push_shares != NULL) {
                        /* by checking each node's validity, we automatically
                         * purge nodes which do not exist from room network
index 47c0158e28ffd0f3f0df44cbe5f1b2234142acd8..5c48b8d28d753e66c384b3ac0d1a3f2f0f3ceff6 100644 (file)
@@ -13,6 +13,7 @@ struct SpoolControl {
        long lastsent;
        struct namelist *listrecps;
        struct namelist *digestrecps;
+       struct namelist *participates;
        struct maplist *ignet_push_shares;
        char *misc;
        FILE *digestfp;
index e76cbc1c78f1920cdfa9f8e7ff5172fed1543c6c..ce4ec17f66296f92d389d613c9075123a48930d9 100644 (file)
@@ -40,12 +40,18 @@ e-mail address instead of the sender's e-mail address.
  
  INSTRUCTION:  ignet_push_share
  SYNTAX:       ignet_push_share|uncnsrd
+          (or) ignet_push_share|uncnsrd|Foo Bar Baz
  DESCRIPTION:
     Specifies that the second argument is the name of a neighboring node on an
 IGnet (Citadel networking) network, to which this room should be pushed
 (spooled).  Conceptually, this node will have a corresponding record pushing
 data in the other direction.
  
+    If the third argument is present, it is the name of the corresponding
+room on the remote node.  This allows a room to be shared even when the room
+name is different on each node.  Such a configuration *must* be configured
+mutually: each node must know the name of the room on the other.
   
  INSTRUCTION:  subpending
  SYNTAX:       subpending|friko@mumjiboolean.com|listrecp|A234Z|1234567890|http://foo.com/lists