* Renamed "struct user" to "struct ctdluser"
[citadel.git] / citadel / serv_network.c
index 114eed6f1f12f361b4dd56bcb02f8566f643dfb9..a60e73cf5196fbbe00d5d9438c91b2853ba83237 100644 (file)
  */
 
 /*
- * FIXME
- * Don't allow polls during network processing
+ * Duration of time (in seconds) after which pending list subscribe/unsubscribe
+ * requests that have not been confirmed will be deleted.
  */
+#define EXP    259200  /* three days */
 
 #include "sysdep.h"
 #include <stdlib.h>
@@ -52,7 +53,7 @@
 #include "citserver.h"
 #include "support.h"
 #include "config.h"
-#include "dynloader.h"
+#include "serv_extensions.h"
 #include "room_ops.h"
 #include "user_ops.h"
 #include "policy.h"
@@ -68,6 +69,8 @@
 #include "snprintf.h"
 #endif
 
+/* Nonzero while we are doing outbound network processing */
+static int doing_queue = 0;
 
 /*
  * When we do network processing, it's accomplished in two passes; one to
@@ -331,10 +334,10 @@ void cmd_gnet(char *argbuf) {
        FILE *fp;
 
        if (CtdlAccessCheck(ac_room_aide)) return;
-       assoc_file_name(filename, sizeof filename, &CC->quickroom, "netconfigs");
+       assoc_file_name(filename, sizeof filename, &CC->room, "netconfigs");
        cprintf("%d Network settings for room #%ld <%s>\n",
                LISTING_FOLLOWS,
-               CC->quickroom.QRnumber, CC->quickroom.QRname);
+               CC->room.QRnumber, CC->room.QRname);
 
        fp = fopen(filename, "r");
        if (fp != NULL) {
@@ -357,7 +360,7 @@ void cmd_snet(char *argbuf) {
 
        if (CtdlAccessCheck(ac_room_aide)) return;
        safestrncpy(tempfilename, tmpnam(NULL), sizeof tempfilename);
-       assoc_file_name(filename, sizeof filename, &CC->quickroom, "netconfigs");
+       assoc_file_name(filename, sizeof filename, &CC->room, "netconfigs");
 
        fp = fopen(tempfilename, "w");
        if (fp == NULL) {
@@ -505,7 +508,7 @@ void network_spool_msg(long msgnum, void *userdata) {
                        if (msg->cm_fields['C'] != NULL) {
                                phree(msg->cm_fields['C']);
                        }
-                       msg->cm_fields['C'] = strdoop(CC->quickroom.QRname);
+                       msg->cm_fields['C'] = strdoop(CC->room.QRname);
 
                        /*
                         * Determine if this message is set to be deleted
@@ -570,7 +573,7 @@ void network_spool_msg(long msgnum, void *userdata) {
 
        /* Delete this message if delete-after-send is set */
        if (delete_after_send) {
-               CtdlDeleteMessages(CC->quickroom.QRname, msgnum, "");
+               CtdlDeleteMessages(CC->room.QRname, msgnum, "");
        }
 
 }
@@ -604,9 +607,9 @@ void network_deliver_digest(struct SpoolControl *sc) {
 
        sprintf(buf, "%ld", time(NULL));
        msg->cm_fields['T'] = strdoop(buf);
-       msg->cm_fields['A'] = strdoop(CC->quickroom.QRname);
-       msg->cm_fields['U'] = strdoop(CC->quickroom.QRname);
-       sprintf(buf, "room_%s@%s", CC->quickroom.QRname, config.c_fqdn);
+       msg->cm_fields['A'] = strdoop(CC->room.QRname);
+       msg->cm_fields['U'] = strdoop(CC->room.QRname);
+       sprintf(buf, "room_%s@%s", CC->room.QRname, config.c_fqdn);
        for (i=0; i<strlen(buf); ++i) {
                if (isspace(buf[i])) buf[i]='_';
                buf[i] = tolower(buf[i]);
@@ -687,15 +690,17 @@ void network_spoolout_room(char *room_to_spool) {
        struct namelist *nptr;
        size_t miscsize = 0;
        size_t linesize = 0;
+       int skipthisline = 0;
+       int i;
 
        lprintf(7, "Spooling <%s>\n", room_to_spool);
-       if (getroom(&CC->quickroom, room_to_spool) != 0) {
+       if (getroom(&CC->room, room_to_spool) != 0) {
                lprintf(1, "ERROR: cannot load <%s>\n", room_to_spool);
                return;
        }
 
        memset(&sc, 0, sizeof(struct SpoolControl));
-       assoc_file_name(filename, sizeof filename, &CC->quickroom, "netconfigs");
+       assoc_file_name(filename, sizeof filename, &CC->room, "netconfigs");
 
        begin_critical_section(S_NETCONFIGS);
        end_critical_section(S_NETCONFIGS);
@@ -703,13 +708,13 @@ void network_spoolout_room(char *room_to_spool) {
        fp = fopen(filename, "r");
        if (fp == NULL) {
                lprintf(7, "Outbound batch processing skipped for <%s>\n",
-                       CC->quickroom.QRname);
+                       CC->room.QRname);
                end_critical_section(S_NETCONFIGS);
                return;
        }
 
        lprintf(5, "Outbound batch processing started for <%s>\n",
-               CC->quickroom.QRname);
+               CC->room.QRname);
 
        while (fgets(buf, sizeof buf, fp) != NULL) {
                buf[strlen(buf)-1] = 0;
@@ -740,11 +745,29 @@ void network_spoolout_room(char *room_to_spool) {
                        sc.ignet_push_shares = nptr;
                }
                else {
-                       linesize = strlen(buf);
-                       sc.misc = realloc(sc.misc,
-                               (miscsize + linesize + 2) );
-                       sprintf(&sc.misc[miscsize], "%s\n", buf);
-                       miscsize = miscsize + linesize + 1;
+                       /* Preserve 'other' lines ... *unless* they happen to
+                        * be subscribe/unsubscribe pendings with expired
+                        * timestamps.
+                        */
+                       skipthisline = 0;
+                       if (!strncasecmp(buf, "subpending|", 11)) {
+                               if (time(NULL) - extract_long(buf, 4) > EXP) {
+                                       skipthisline = 1;
+                               }
+                       }
+                       if (!strncasecmp(buf, "unsubpending|", 13)) {
+                               if (time(NULL) - extract_long(buf, 3) > EXP) {
+                                       skipthisline = 1;
+                               }
+                       }
+
+                       if (skipthisline == 0) {
+                               linesize = strlen(buf);
+                               sc.misc = realloc(sc.misc,
+                                       (miscsize + linesize + 2) );
+                               sprintf(&sc.misc[miscsize], "%s\n", buf);
+                               miscsize = miscsize + linesize + 1;
+                       }
                }
 
 
@@ -762,13 +785,20 @@ void network_spoolout_room(char *room_to_spool) {
                network_spool_msg, &sc);
 
        /* If we wrote a digest, deliver it and then close it */
+       snprintf(buf, sizeof buf, "room_%s@%s",
+               CC->room.QRname, config.c_fqdn);
+       for (i=0; i<strlen(buf); ++i) {
+               buf[i] = tolower(buf[i]);
+               if (isspace(buf[i])) buf[i] = '_';
+       }
        if (sc.digestfp != NULL) {
                fprintf(sc.digestfp,    " -----------------------------------"
                                        "------------------------------------"
                                        "-------\n"
                                        "You are subscribed to the '%s' "
-                                       "list.\n",
-                                       CC->quickroom.QRname
+                                       "list.\n"
+                                       "To post to the list: %s\n",
+                                       CC->room.QRname, buf
                );
                network_deliver_digest(&sc);    /* deliver and close */
        }
@@ -815,14 +845,14 @@ void network_spoolout_room(char *room_to_spool) {
        end_critical_section(S_NETCONFIGS);
 
        lprintf(5, "Outbound batch processing finished for <%s>\n",
-               CC->quickroom.QRname);
+               CC->room.QRname);
 }
 
 
 /*
  * Batch up and send all outbound traffic from the current room
  */
-void network_queue_room(struct quickroom *qrbuf, void *data) {
+void network_queue_room(struct ctdlroom *qrbuf, void *data) {
        struct RoomProcList *ptr;
 
        ptr = (struct RoomProcList *) mallok(sizeof (struct RoomProcList));
@@ -1438,7 +1468,6 @@ void network_poll_other_citadel_nodes(void) {
  * Run through the rooms doing various types of network stuff.
  */
 void network_do_queue(void) {
-       static int doing_queue = 0;
        static time_t last_run = 0L;
        struct RoomProcList *ptr;
 
@@ -1509,6 +1538,11 @@ void cmd_netp(char *cmdbuf)
        char secret[SIZ];
        char nexthop[SIZ];
 
+       if (doing_queue) {
+               cprintf("%d spooling - try again in a few minutes\n", ERROR);
+               return;
+       }
+
        extract(node, cmdbuf, 0);
        extract(pass, cmdbuf, 1);
 
@@ -1540,7 +1574,7 @@ void cmd_netp(char *cmdbuf)
 /*
  * Module entry point
  */
-char *Dynamic_Module_Init(void)
+char *serv_network_init(void)
 {
        CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
        CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config");