Convert CtdlMessages to respect cm_lengths[]
authorWilfried Goesgens <dothebart@citadel.org>
Tue, 24 Sep 2013 22:37:08 +0000 (00:37 +0200)
committerWilfried Goesgens <dothebart@citadel.org>
Tue, 24 Sep 2013 22:37:08 +0000 (00:37 +0200)
  - move application specific code during message saving behind abstract handlers
    - IGNET spoorling
    - SMTP Spooling
    - ExtNotify Spooling
  - add new Message Hook: EVT_AFTERUSRMBOXSAVE
  - Put the volatile message ID to the message struct earlier

33 files changed:
citadel/event_client.h
citadel/include/ctdl_module.h
citadel/internet_addressing.c
citadel/internet_addressing.h
citadel/journaling.c
citadel/journaling.h
citadel/modules/blog/serv_blog.c
citadel/modules/calendar/serv_calendar.c
citadel/modules/clamav/serv_virus.c
citadel/modules/ctdlproto/serv_messages.c
citadel/modules/extnotify/extnotify_main.c
citadel/modules/imap/imap_acl.c
citadel/modules/inetcfg/serv_inetcfg.c
citadel/modules/network/serv_netmail.c
citadel/modules/network/serv_netspool.c
citadel/modules/network/serv_network.c
citadel/modules/notes/serv_notes.c
citadel/modules/rssclient/rss_atom_parser.h
citadel/modules/sieve/serv_sieve.c
citadel/modules/smtp/serv_smtp.c
citadel/modules/smtp/serv_smtpeventclient.c
citadel/modules/smtp/serv_smtpqueue.c
citadel/modules/smtp/smtp_clienthandlers.h
citadel/modules/smtp/smtp_util.c
citadel/modules/spam/serv_spam.c
citadel/modules/vcard/serv_vcard.c
citadel/modules/wiki/serv_wiki.c
citadel/msgbase.c
citadel/msgbase.h
citadel/serv_extensions.c
citadel/serv_extensions.h
citadel/server.h
citadel/user_ops.c

index 99d4259f65b3c377bf9f1803102f82c28b13c72e..e123979278d1987ffb4ed36a3e9b11cb1aad4b24 100644 (file)
@@ -204,7 +204,7 @@ struct AsyncIO {
        /* Saving / loading a message async from / to disk */
        ReadAsyncMsg *ReadMsg;
        struct CtdlMessage *AsyncMsg;
-       struct recptypes *AsyncRcp;
+       recptypes *AsyncRcp;
 
        /* Context specific data; Hint: put AsyncIO in there */
        void *Data;        /* application specific data */
index 8950a47ed9800b48f29743199d028c5fe00e6408..ca447f595e0398adb053d08cf2ef4d90a7b98a61 100644 (file)
@@ -134,10 +134,10 @@ void CtdlUnregisterUserHook(void (*fcn_ptr)(struct ctdluser *), int EventType);
 void CtdlRegisterXmsgHook(int (*fcn_ptr)(char *, char *, char *, char *), int order);
 void CtdlUnregisterXmsgHook(int (*fcn_ptr)(char *, char *, char *, char *), int order);
 
-void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *),
-                                                       int EventType);
-void CtdlUnregisterMessageHook(int (*handler)(struct CtdlMessage *),
+void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *, recptypes*),
                                                        int EventType);
+void CtdlUnregisterMessageHook(int (*handler)(struct CtdlMessage *, recptypes *),
+                              int EventType);
 
 void CtdlRegisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) );
 void CtdlUnregisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) );
@@ -537,4 +537,5 @@ void CtdlUserLogout(void);
 long CtdlLocateMessageByEuid(char *euid, struct ctdlroom *qrbuf);
 
 
+
 #endif /* CTDL_MODULE_H */
index bc60368e6de1806f49f56f0327316f5c4a48fa65..507347307553f679dbdcb9994ddfd077d293593f 100644 (file)
@@ -331,7 +331,7 @@ int CtdlHostAlias(char *fqdn) {
  */
 int CtdlIsMe(char *addr, int addr_buf_len)
 {
-       struct recptypes *recp;
+       recptypes *recp;
        int i;
 
        recp = validate_recipients(addr, NULL, 0);
@@ -531,11 +531,11 @@ int alias(char *name)
  *
  * Caller needs to free the result using free_recipients()
  */
-struct recptypes *validate_recipients(const char *supplied_recipients, 
-                                     const char *RemoteIdentifier, 
-                                     int Flags) {
+recptypes *validate_recipients(const char *supplied_recipients, 
+                              const char *RemoteIdentifier, 
+                              int Flags) {
        struct CitContext *CCC = CC;
-       struct recptypes *ret;
+       recptypes *ret;
        char *recipients = NULL;
        char *org_recp;
        char this_recp[256];
@@ -554,11 +554,11 @@ struct recptypes *validate_recipients(const char *supplied_recipients,
        int in_quotes = 0;
 
        /* Initialize */
-       ret = (struct recptypes *) malloc(sizeof(struct recptypes));
+       ret = (recptypes *) malloc(sizeof(recptypes));
        if (ret == NULL) return(NULL);
 
        /* Set all strings to null and numeric values to zero */
-       memset(ret, 0, sizeof(struct recptypes));
+       memset(ret, 0, sizeof(recptypes));
 
        if (supplied_recipients == NULL) {
                recipients = strdup("");
@@ -785,9 +785,9 @@ struct recptypes *validate_recipients(const char *supplied_recipients,
 
 
 /*
- * Destructor for struct recptypes
+ * Destructor for recptypes
  */
-void free_recipients(struct recptypes *valid) {
+void free_recipients(recptypes *valid) {
 
        if (valid == NULL) {
                return;
index 74e581883803cdb0e2b37ee3f71baed0cc1bcb07..87d35b923ae60541d40ec0aca90beeecc29d2614 100644 (file)
@@ -1,5 +1,6 @@
 
 #include "server.h"
+#include "ctdl_module.h"
 
 struct internet_address_list {
        struct internet_address_list *next;
@@ -8,33 +9,12 @@ struct internet_address_list {
        char ial_name[SIZ];
 };
 
-/* Data structure returned by validate_recipients() */
-struct recptypes {
-       int recptypes_magic;
-        int num_local;
-        int num_internet;
-        int num_ignet;
-       int num_room;
-        int num_error;
-       char *errormsg;
-       char *recp_local;
-       char *recp_internet;
-       char *recp_ignet;
-       char *recp_room;
-       char *recp_orgroom;
-       char *display_recp;
-       char *bounce_to;
-       char *envelope_from;
-       char *sending_room;
-};
-
-#define RECPTYPES_MAGIC 0xfeeb
 
-struct recptypes *validate_recipients(const char *recipients,
+recptypes *validate_recipients(const char *recipients,
                                      const char *RemoteIdentifier, 
                                      int Flags);
 
-void free_recipients(struct recptypes *);
+void free_recipients(recptypes *);
 
 
 int fuzzy_match(struct ctdluser *us, char *matchstring);
@@ -53,6 +33,7 @@ int CtdlDirectoryLookup(char *target, char *internet_addr, size_t targbuflen);
 struct CtdlMessage *convert_internet_message(char *rfc822);
 struct CtdlMessage *convert_internet_message_buf(StrBuf **rfc822);
 
+int CtdlIsMe(char *addr, int addr_buf_len);
 int CtdlHostAlias(char *fqdn);
 char *harvest_collected_addresses(struct CtdlMessage *msg);
 
index 3dae1074997940f3437c47a6bd1772b916bea618..eb9e378e7f76872b95d7291d946598bcf2bb8ad2 100644 (file)
@@ -20,7 +20,7 @@ struct jnlq *jnlq = NULL;     /* journal queue */
  */
 void JournalBackgroundSubmit(struct CtdlMessage *msg,
                        StrBuf *saved_rfc822_version,
-                       struct recptypes *recps) {
+                       recptypes *recps) {
 
        struct jnlq *jptr = NULL;
 
@@ -36,7 +36,7 @@ void JournalBackgroundSubmit(struct CtdlMessage *msg,
                return;
        }
        memset(jptr, 0, sizeof(struct jnlq));
-       if (recps != NULL) memcpy(&jptr->recps, recps, sizeof(struct recptypes));
+       if (recps != NULL) memcpy(&jptr->recps, recps, sizeof(recptypes));
        if (!CM_IsEmpty(msg, eAuthor)) jptr->from = strdup(msg->cm_fields[eAuthor]);
        if (!CM_IsEmpty(msg, eNodeName)) jptr->node = strdup(msg->cm_fields[eNodeName]);
        if (!CM_IsEmpty(msg, erFc822Addr)) jptr->rfca = strdup(msg->cm_fields[erFc822Addr]);
@@ -88,7 +88,7 @@ void local_to_inetemail(char *inetemail, char *localuser, size_t inetemail_len)
 void JournalRunQueueMsg(struct jnlq *jmsg) {
 
        struct CtdlMessage *journal_msg = NULL;
-       struct recptypes *journal_recps = NULL;
+       recptypes *journal_recps = NULL;
        StrBuf *message_text = NULL;
        char mime_boundary[256];
        long mblen;
@@ -128,7 +128,7 @@ void JournalRunQueueMsg(struct jnlq *jmsg) {
                                         "--Citadel-Journal-%08lx-%04x--", time(NULL), ++seq);
                        rfc822len = strlen(jmsg->rfc822);
                       
-                       message_text = NewStrBufPlain(NULL, rfc822len + sizeof(struct recptypes) + 1024);
+                       message_text = NewStrBufPlain(NULL, rfc822len + sizeof(recptypes) + 1024);
 
                        /*
                         * Here is where we begin to compose the journalized message.
index 4a66781aed8e5956f1bcb8aa96080efa8e4d807e..74c79816afaf05e33123e730ff75e2b8ffce86e7 100644 (file)
@@ -1,6 +1,6 @@
 struct jnlq {
        struct jnlq *next;
-       struct recptypes recps;
+       recptypes recps;
        char *from;
        char *node;
        char *rfca;
@@ -11,6 +11,6 @@ struct jnlq {
 
 void JournalBackgroundSubmit(struct CtdlMessage *msg,
                         StrBuf *saved_rfc822_version,
-                        struct recptypes *recps);
+                        recptypes *recps);
 void JournalRunQueueMsg(struct jnlq *jmsg);
 void JournalRunQueue(void);
index 891c2cccffe57429b8b54729edab3c49e5559bcb..0402e0190e650c6b4e01a79f3e6d38978a188a9b 100644 (file)
@@ -62,7 +62,7 @@
  * Pre-save hook for saving a message in a blog room.
  * (Do we want to only do this for top-level messages?)
  */
-int blog_upload_beforesave(struct CtdlMessage *msg) {
+int blog_upload_beforesave(struct CtdlMessage *msg, recptypes *recp) {
 
        /* Only run this hook for blog rooms */
        if (CC->room.QRdefaultview != VIEW_BLOG) {
index 1acd28251aa688ad4b5fcb6e44fc1580e3ff000b..8d3fe42cbb8ee13106532ac429de4f7c581c1d0b 100644 (file)
@@ -185,13 +185,13 @@ void ical_send_a_reply(icalcomponent *request, char *action) {
        icalproperty *summary = NULL;
        char summary_string[SIZ];
        icalproperty *me_attend = NULL;
-       struct recptypes *recp = NULL;
+       recptypes *recp = NULL;
        icalparameter *partstat = NULL;
        char *serialized_reply = NULL;
        char *reply_message_text = NULL;
        const char *ch;
        struct CtdlMessage *msg = NULL;
-       struct recptypes *valid = NULL;
+       recptypes *valid = NULL;
 
        *organizer_string = '\0';
        strcpy(summary_string, "Calendar item");
@@ -1439,7 +1439,7 @@ void ical_freebusy(char *who) {
        icalcomponent *encaps = NULL;
        icalcomponent *fb = NULL;
        int found_user = (-1);
-       struct recptypes *recp = NULL;
+       recptypes *recp = NULL;
        char buf[256];
        char host[256];
        char type[256];
@@ -1999,7 +1999,7 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
        icalcomponent *encaps = NULL;
        char *request_message_text = NULL;
        struct CtdlMessage *msg = NULL;
-       struct recptypes *valid = NULL;
+       recptypes *valid = NULL;
        char attendees_string[SIZ];
        int num_attendees = 0;
        char this_attendee[256];
@@ -2393,7 +2393,7 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum,
  * If the message is being saved, we also set various message header fields
  * using data found in the iCalendar object.
  */
-int ical_obj_beforesave(struct CtdlMessage *msg)
+int ical_obj_beforesave(struct CtdlMessage *msg, recptypes *recp)
 {
        /* First determine if this is a calendar or tasks room */
        if (  (CC->room.QRdefaultview != VIEW_CALENDAR)
@@ -2461,7 +2461,7 @@ void ical_obj_aftersave_backend(char *name, char *filename, char *partnum,
  * (This will start back end tasks such as automatic generation of invitations,
  * if such actions are appropriate.)
  */
-int ical_obj_aftersave(struct CtdlMessage *msg)
+int ical_obj_aftersave(struct CtdlMessage *msg, recptypes *recp)
 {
        char roomname[ROOMNAMELEN];
 
index ae24461aa028b491f8174dd6faea08d2fadcdbd5..81f53e13a41f68b8ee506ee1de8df8ab72c4dbdd 100644 (file)
@@ -70,7 +70,7 @@
 /*
  * Connect to the clamd server and scan a message.
  */
-int clamd(struct CtdlMessage *msg) {
+int clamd(struct CtdlMessage *msg, recptypes *recp) {
        int sock = (-1);
        int streamsock = (-1);
        char clamhosts[SIZ];
index 08aaf566f5e5f937290012219e4ff99598d2ea63..f7ac4575e3d0e1a7162e93c7408400cdbd8b0590 100644 (file)
@@ -332,10 +332,10 @@ void cmd_ent0(char *entargs)
        int anonymous = 0;
        char errmsg[SIZ];
        int err = 0;
-       struct recptypes *valid = NULL;
-       struct recptypes *valid_to = NULL;
-       struct recptypes *valid_cc = NULL;
-       struct recptypes *valid_bcc = NULL;
+       recptypes *valid = NULL;
+       recptypes *valid_to = NULL;
+       recptypes *valid_cc = NULL;
+       recptypes *valid_bcc = NULL;
        char subject[SIZ];
        int subject_required = 0;
        int do_confirm = 0;
index ef253c8760455a6f52ec312a817b8807b7b1b955..46c9ab8ea415cd206cdf643360c17ee99ab124c6 100644 (file)
@@ -465,12 +465,56 @@ void create_extnotify_queue(void) {
        }
 }
 
+int extnotify_after_mbox_save(struct CtdlMessage *msg,
+                             recptypes *recps)
+
+{
+       /* If this is private, local mail, make a copy in the
+        * recipient's mailbox and bump the reference count.
+        */
+       if (!IsEmptyStr(config.c_funambol_host) || !IsEmptyStr(config.c_pager_program))
+       {
+               /* Generate a instruction message for the Funambol notification
+                * server, in the same style as the SMTP queue
+                */
+               StrBuf *instr;
+               struct CtdlMessage *imsg;
+
+               instr = NewStrBufPlain(NULL, 1024);
+               StrBufPrintf(instr,
+                            "Content-type: "SPOOLMIME"\n"
+                            "\n"
+                            "msgid|%s\n"
+                            "submitted|%ld\n"
+                            "bounceto|%s\n",
+                            msg->cm_fields[eVltMsgNum],
+                            (long)time(NULL), //todo: time() is expensive!
+                            recps->bounce_to
+                       );
+                               
+               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;
+               CM_SetField(imsg, eMsgSubject, HKEY("QMSG"));
+               CM_SetField(imsg, eAuthor, HKEY("Citadel"));
+               CM_SetField(imsg, eJournal, HKEY("do not journal"));
+               CM_SetAsFieldSB(imsg, eMesageText, &instr);
+               CM_SetField(imsg, eExtnotify, recps->recp_local, strlen(recps->recp_local));
+               CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM, 0);
+               CM_Free(imsg);
+       }
+       return 0;
+}
 
 CTDL_MODULE_INIT(extnotify)
 {
        if (!threading)
        {
                create_extnotify_queue();
+               CtdlRegisterMessageHook(extnotify_after_mbox_save, EVT_AFTERUSRMBOXSAVE);
+
                CtdlRegisterSessionHook(do_extnotify_queue, EVT_TIMER, PRIO_SEND + 10);
        }
        /* return our module name for the log */
index 0ca96dfc85b7de6d1c0007eded07ffefa0a9dc51..b1c1f0fe869666928d181823272296bde9d051b3 100644 (file)
@@ -221,7 +221,7 @@ void imap_listrights(int num_parms, ConstStr *Params) {
        char savedroom[ROOMNAMELEN];
        int msgs, new;
        int ret;
-       struct recptypes *valid;
+       recptypes *valid;
        struct ctdluser temp;
 
        if (num_parms != 4) {
index 7c0bedaa10aaf1cd89604a9c463b09f6c71b8e7f..c37dd24fbdfcb103ea033bbb10fb5bdd2664b07c 100644 (file)
@@ -85,7 +85,7 @@ void inetcfg_setTo(struct CtdlMessage *msg) {
  * This handler detects changes being made to the system's Internet
  * configuration.
  */
-int inetcfg_aftersave(struct CtdlMessage *msg) {
+int inetcfg_aftersave(struct CtdlMessage *msg, recptypes *recp) {
        char *ptr;
        int linelen;
 
index d71cbdbfb331c24184a534c29258a45a5e96ec68..b06da93f1a0e17461d31a0b88ee49a01db525089 100644 (file)
@@ -180,7 +180,7 @@ void network_deliver_digest(SpoolControl *sc)
        char *pbuf;
        struct CtdlMessage *msg = NULL;
        long msglen;
-       struct recptypes *valid;
+       recptypes *valid;
        char bounce_to[256];
 
        if (sc->Users[listrecp] == NULL)
@@ -354,7 +354,7 @@ void network_process_list(SpoolControl *sc, struct CtdlMessage *omsg, long *dele
  */
 void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char *RoomName)
 {
-       struct recptypes *valid;
+       recptypes *valid;
        char bounce_to[256];
 
        /* Don't do this if there were no recipients! */
@@ -385,7 +385,7 @@ void network_process_participate(SpoolControl *sc, struct CtdlMessage *omsg, lon
        struct CtdlMessage *msg = NULL;
        int ok_to_participate = 0;
        StrBuf *Buf = NULL;
-       struct recptypes *valid;
+       recptypes *valid;
 
        /*
         * Process client-side list participations for this room
index c75e682fb74a1b51d30e0821e8635c39bc3851b7..5b90ef23d89f40510e98920e04bc9a1922dace9d 100644 (file)
@@ -420,7 +420,7 @@ void network_process_buffer(char *buffer, long size, HashList *working_ignetcfg,
        struct CtdlMessage *msg = NULL;
        long pos;
        int field;
-       struct recptypes *recp = NULL;
+       recptypes *recp = NULL;
        char target_room[ROOMNAMELEN];
        struct ser_ret sermsg;
        char filename[PATH_MAX];
index 998a83df1c8415cfa166f18aecae11e58a492278..32bf49564a1f4f7b6f370df7eacf5abe4e3cdf15 100644 (file)
@@ -350,7 +350,7 @@ void network_bounce(struct CtdlMessage *msg, char *reason)
        char buf[SIZ];
        char bouncesource[SIZ];
        char recipient[SIZ];
-       struct recptypes *valid = NULL;
+       recptypes *valid = NULL;
        char force_room[ROOMNAMELEN];
        static int serialnum = 0;
        long len;
@@ -589,6 +589,80 @@ void network_cleanup_function(void)
 }
 
 
+int ignet_aftersave(struct CtdlMessage *msg,
+                   recptypes *recps)   /* recipients (if mail) */
+{
+       /* For IGnet mail, we have to save a new copy into the spooler for
+        * each recipient, with the R and D fields set to the recipient and
+        * destination-node.  This has two ugly side effects: all other
+        * recipients end up being unlisted in this recipient's copy of the
+        * message, and it has to deliver multiple messages to the same
+        * node.  We'll revisit this again in a year or so when everyone has
+        * a network spool receiver that can handle the new style messages.
+        */
+       if ((recps != NULL) && (recps->num_ignet > 0))
+       {
+               char *recipient;
+               int rv = 0;
+               struct ser_ret smr;
+               FILE *network_fp = NULL;
+               char submit_filename[128];
+               static int seqnum = 1;
+               int i;
+               char *hold_R, *hold_D, *RBuf, *DBuf;
+               long hrlen, hdlen, rblen, dblen, count, rlen;
+               CitContext *CCC = MyContext();
+
+               CM_GetAsField(msg, eRecipient, &hold_R, &hrlen);;
+               CM_GetAsField(msg, eDestination, &hold_D, &hdlen);;
+
+               count = num_tokens(recps->recp_ignet, '|');
+               rlen = strlen(recps->recp_ignet);
+               recipient = malloc(rlen + 1);
+               RBuf = malloc(rlen + 1);
+               DBuf = malloc(rlen + 1);
+               for (i=0; i<count; ++i) {
+                       extract_token(recipient, recps->recp_ignet, i,
+                                     '|', rlen + 1);
+
+                       rblen = extract_token(RBuf, recipient, 0, '@', rlen + 1);
+                       dblen = extract_token(DBuf, recipient, 1, '@', rlen + 1);
+               
+                       CM_SetAsField(msg, eRecipient, &RBuf, rblen);;
+                       CM_SetAsField(msg, eDestination, &DBuf, dblen);;
+                       CtdlSerializeMessage(&smr, msg);
+                       if (smr.len > 0) {
+                               snprintf(submit_filename, sizeof submit_filename,
+                                        "%s/netmail.%04lx.%04x.%04x",
+                                        ctdl_netin_dir,
+                                        (long) getpid(),
+                                        CCC->cs_pid,
+                                        ++seqnum);
+
+                               network_fp = fopen(submit_filename, "wb+");
+                               if (network_fp != NULL) {
+                                       rv = fwrite(smr.ser, smr.len, 1, network_fp);
+                                       if (rv == -1) {
+                                               MSG_syslog(LOG_EMERG, "CtdlSubmitMsg(): Couldn't write network spool file: %s\n",
+                                                          strerror(errno));
+                                       }
+                                       fclose(network_fp);
+                               }
+                               free(smr.ser);
+                       }
+                       CM_GetAsField(msg, eRecipient, &RBuf, &rblen);;
+                       CM_GetAsField(msg, eDestination, &DBuf, &dblen);;
+               }
+               free(RBuf);
+               free(DBuf);
+               free(recipient);
+               CM_SetAsField(msg, eRecipient, &hold_R, hrlen);
+               CM_SetAsField(msg, eDestination, &hold_D, hdlen);
+               return 1;
+       }
+       return 0;
+}
+
 /*
  * Module entry point
  */
@@ -602,6 +676,8 @@ CTDL_MODULE_INIT(network)
 {
        if (!threading)
        {
+               CtdlRegisterMessageHook(ignet_aftersave, EVT_AFTERSAVE);
+
                CtdlFillSystemContext(&networker_spool_CC, "CitNetSpool");
                CtdlRegisterDebugFlagHook(HKEY("networkqueue"), SetNetQDebugEnabled, &NetQDebugEnabled);
                CtdlRegisterSessionHook(network_cleanup_function, EVT_STOP, PRIO_STOP + 30);
index 9c1c944d9f881f542f79179b046a02333c18a032..839d5d537eb6ffa04e926aae200589004483a940 100644 (file)
@@ -80,7 +80,7 @@ void notes_extract_vnote(char *name, char *filename, char *partnum, char *disp,
  * and modern vNote format notes) and does its best to learn the subject (summary)
  * and EUID (uid) of the note for Citadel's own nefarious purposes.
  */
-int serv_notes_beforesave(struct CtdlMessage *msg)
+int serv_notes_beforesave(struct CtdlMessage *msg, recptypes *recp)
 {
        char *p;
        int a, i;
index ad0f8b2c41b68f74a6d073f75ebaea01fd847d5c..da4c6161f3f1fa3d79afe73daae2bfedd501a834 100644 (file)
@@ -110,7 +110,7 @@ struct rss_aggregator {
        StrBuf          *Key;
 
        rss_item        *Item;
-       struct recptypes recp;
+       recptypes        recp;
        HashPos         *Pos;
        HashList        *Messages;
        networker_save_message *ThisMsg;
index ecdaafd78b819b8e19ee9f80c7ae21f1b3409291..daf067331bf6a7db8eb0b273a21bd0dbb3d4afe3 100644 (file)
@@ -106,7 +106,7 @@ int ctdl_redirect(sieve2_context_t *s, void *my)
 {
        struct ctdl_sieve *cs = (struct ctdl_sieve *)my;
        struct CtdlMessage *msg = NULL;
-       struct recptypes *valid = NULL;
+       recptypes *valid = NULL;
        char recp[256];
 
        safestrncpy(recp, sieve2_getvalue_string(s, "address"), sizeof recp);
index 681e0c740bf1076a89e25c61563d87393b51110b..9ac94212a52f5f43ab2563c0de3ed0ff571da649 100644 (file)
@@ -668,7 +668,7 @@ void smtp_rcpt(long offset, long flags)
 {
        struct CitContext *CCC = CC;
        char message_to_spammer[SIZ];
-       struct recptypes *valid = NULL;
+       recptypes *valid = NULL;
        citsmtp *sSMTP = SMTP;
 
        if (StrLength(sSMTP->from) == 0) {
@@ -767,7 +767,7 @@ void smtp_data(long offset, long flags)
        struct CtdlMessage *msg = NULL;
        long msgnum = (-1L);
        char nowstamp[SIZ];
-       struct recptypes *valid;
+       recptypes *valid;
        int scan_errors;
        int i;
        citsmtp *sSMTP = SMTP;
@@ -896,7 +896,7 @@ void smtp_data(long offset, long flags)
                scan_errors = 0;
        }
        else {
-               scan_errors = PerformMessageHooks(msg, EVT_SMTPSCAN);
+               scan_errors = PerformMessageHooks(msg, valid, EVT_SMTPSCAN);
        }
 
        if (scan_errors > 0) {  /* We don't want this message! */
index 47c1d605e525c213424501448f51e3d3d2e3335a..3be726e8503e40848a96e85f117947f75685232f 100644 (file)
@@ -356,7 +356,7 @@ eNextState mx_connect_ip(AsyncIO *IO)
        SmtpOutMsg *Msg = IO->Data;
        SetSMTPState(IO, eSTMPconnecting);
 
-       EVS_syslog(LOG_DEBUG, "%s\n", __FUNCTION__);
+       EVS_syslog(LOG_DEBUG, "%s(%s)\n", __FUNCTION__, (Msg->IsRelay)? "Relay":"Remote");
 
        IO->ConnectMe = Msg->pCurrRelay;
        Msg->State = eConnectMX;
@@ -656,6 +656,7 @@ void smtp_try_one_queue_entry(OneQueItem *MyQItem,
                                          resolve_mx_records);
                }
                else { /* oh... via relay host */
+                       Msg->IsRelay = 1;
                        if (Msg->pCurrRelay->IsIP) {
                                SetSMTPState(&Msg->IO, eSTMPconnecting);
                                QueueEventContext(&Msg->IO,
index 99b9d0795ae105075911d9e6f60c5cfe0702c711..b2196a88755a1dc76fec4ed185606f0704b6a563 100644 (file)
@@ -523,7 +523,7 @@ void smtpq_do_bounce(OneQueItem *MyQItem, StrBuf *OMsgTxt, ParsedURL *Relay)
        StrBuf *boundary;
        StrBuf *Msg = NULL;
        StrBuf *BounceMB;
-       struct recptypes *valid;
+       recptypes *valid;
        time_t now;
 
        HashPos *It;
@@ -1205,6 +1205,70 @@ void cmd_smtp(char *argbuf) {
 
 }
 
+int smtp_aftersave(struct CtdlMessage *msg,
+                  recptypes *recps)
+{
+       /* For internet mail, generate delivery instructions.
+        * Yes, this is recursive.  Deal with it.  Infinite recursion does
+        * not happen because the delivery instructions message does not
+        * contain a recipient.
+        */
+       if ((recps != NULL) && (recps->num_internet > 0)) {
+               struct CtdlMessage *imsg = NULL;
+               char recipient[SIZ];
+               CitContext *CCC = MyContext();
+               StrBuf *SpoolMsg = NewStrBuf();
+               long nTokens;
+               int i;
+
+               MSGM_syslog(LOG_DEBUG, "Generating delivery instructions\n");
+
+               StrBufPrintf(SpoolMsg,
+                            "Content-type: "SPOOLMIME"\n"
+                            "\n"
+                            "msgid|%s\n"
+                            "submitted|%ld\n"
+                            "bounceto|%s\n",
+                            msg->cm_fields[eVltMsgNum],
+                            (long)time(NULL),
+                            recps->bounce_to);
+
+               if (recps->envelope_from != NULL) {
+                       StrBufAppendBufPlain(SpoolMsg, HKEY("envelope_from|"), 0);
+                       StrBufAppendBufPlain(SpoolMsg, recps->envelope_from, -1, 0);
+                       StrBufAppendBufPlain(SpoolMsg, HKEY("\n"), 0);
+               }
+               if (recps->sending_room != NULL) {
+                       StrBufAppendBufPlain(SpoolMsg, HKEY("source_room|"), 0);
+                       StrBufAppendBufPlain(SpoolMsg, recps->sending_room, -1, 0);
+                       StrBufAppendBufPlain(SpoolMsg, HKEY("\n"), 0);
+               }
+
+               nTokens = num_tokens(recps->recp_internet, '|');
+               for (i = 0; i < nTokens; i++) {
+                       long len;
+                       len = extract_token(recipient, recps->recp_internet, i, '|', sizeof recipient);
+                       if (len > 0) {
+                               StrBufAppendBufPlain(SpoolMsg, HKEY("remote|"), 0);
+                               StrBufAppendBufPlain(SpoolMsg, recipient, len, 0);
+                               StrBufAppendBufPlain(SpoolMsg, HKEY("|0||\n"), 0);
+                       }
+               }
+
+               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;
+               CM_SetField(imsg, eMsgSubject, HKEY("QMSG"));
+               CM_SetField(imsg, eAuthor, HKEY("Citadel"));
+               CM_SetField(imsg, eJournal, HKEY("do not journal"));
+               CM_SetAsFieldSB(imsg, eMesageText, &SpoolMsg);
+               CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM, QP_EADDR);
+               CM_Free(imsg);
+       }
+       return 0;
+}
 
 CTDL_MODULE_INIT(smtp_queu)
 {
@@ -1224,8 +1288,7 @@ CTDL_MODULE_INIT(smtp_queu)
                if ((pstr != NULL) && (*pstr != '\0'))
                        delay_msec = atol(pstr) * 1000; /* this many seconds. */
 
-
-
+               CtdlRegisterMessageHook(smtp_aftersave, EVT_AFTERSAVE);
 
                CtdlFillSystemContext(&smtp_queue_CC, "SMTP_Send");
                ActiveQItems = NewHash(1, lFlathash);
index dedab4ba49b5c8af79e9ed30bdf40b7e21f8e664..3e18261a22fe1fa671d904ae6c22ccb7a691fa9c 100644 (file)
@@ -70,6 +70,7 @@ typedef struct _stmp_out_msg {
        char mailfrom[1024];
        long SendLogin;
        long Flags;
+       long IsRelay;
 } SmtpOutMsg;
 
 
index dae60b6daf14a8d46f2c457d9fbcfd69ddca4302..675001ea0d3570cdfef6303a294c2cf0d5cad9d3 100644 (file)
@@ -119,7 +119,7 @@ void smtp_do_bounce(char *instr, StrBuf *OMsgTxt)
        time_t submitted = 0L;
        struct CtdlMessage *bmsg = NULL;
        int give_up = 0;
-       struct recptypes *valid;
+       recptypes *valid;
        int successful_bounce = 0;
        static int seq = 0;
        StrBuf *BounceMB;
index 77365b16c3844735e16340dcb3d6f463d9a8a962..f9a823d9ed5466994f25500ba924fd253effa8e6 100644 (file)
@@ -70,7 +70,7 @@
 /*
  * Connect to the SpamAssassin server and scan a message.
  */
-int spam_assassin(struct CtdlMessage *msg) {
+int spam_assassin(struct CtdlMessage *msg, recptypes *recp) {
        int sock = (-1);
        char sahosts[SIZ];
        int num_sahosts;
index 393cf72101fbfd3fc1d1ebc58810234b6b7df84c..3d62c83d0b710e97442ab2e25f1af64b4070a0f0 100644 (file)
@@ -329,7 +329,7 @@ void vcard_extract_vcard(char *name, char *filename, char *partnum, char *disp,
  * function accordingly (delete the user's existing vCard in the config room
  * and in the global address book).
  */
-int vcard_upload_beforesave(struct CtdlMessage *msg) {
+int vcard_upload_beforesave(struct CtdlMessage *msg, recptypes *recp) {
        struct CitContext *CCC = CC;
        char *s;
        char buf[SIZ];
@@ -504,7 +504,7 @@ int vcard_upload_beforesave(struct CtdlMessage *msg) {
  * function accordingly (copy the vCard from the config room to the global
  * address book).
  */
-int vcard_upload_aftersave(struct CtdlMessage *msg) {
+int vcard_upload_aftersave(struct CtdlMessage *msg, recptypes *recp) {
        struct CitContext *CCC = CC;
        char *ptr;
        int linelen;
@@ -1172,7 +1172,7 @@ void check_get(void) {
        
        if (strncasecmp(cmdbuf, "GET ", 4)==0)
        {
-               struct recptypes *rcpt;
+               recptypes *rcpt;
                char *argbuf = &cmdbuf[4];
                
                extract_token(internet_addr, argbuf, 0, '|', sizeof internet_addr);
index 79a961f451ed1ae289435db0586cbb8dcef6f107..e68055d05b8eda39c6077066f2e3884c2bd11bf7 100644 (file)
@@ -70,7 +70,7 @@ char *wwm = "9999999999.WikiWaybackMachine";
  * Before allowing a wiki page save to execute, we have to perform version control.
  * This involves fetching the old version of the page if it exists.
  */
-int wiki_upload_beforesave(struct CtdlMessage *msg) {
+int wiki_upload_beforesave(struct CtdlMessage *msg, recptypes *recp) {
        struct CitContext *CCC = CC;
        long old_msgnum = (-1L);
        struct CtdlMessage *old_msg = NULL;
index d4a933e76e13c478463fe9be3ae078763a5800bc..d9629700fcd3736ed516a2a72614f9ecf5c78acd 100644 (file)
@@ -136,6 +136,7 @@ void CM_SetField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long
        Msg->cm_fields[which] = malloc(length + 1);
        memcpy(Msg->cm_fields[which], buf, length);
        Msg->cm_fields[which][length] = '\0';
+       Msg->cm_lengths[which] = length;
 }
 
 void CM_SetFieldLONG(struct CtdlMessage *Msg, eMsgField which, long lvalue)
@@ -150,8 +151,11 @@ void CM_CutFieldAt(struct CtdlMessage *Msg, eMsgField WhichToCut, long maxlen)
        if (Msg->cm_fields[WhichToCut] == NULL)
                return;
 
-       if (strlen(Msg->cm_fields[WhichToCut]) > maxlen)
+       if (Msg->cm_lengths[WhichToCut] > maxlen)
+       {
                Msg->cm_fields[WhichToCut][maxlen] = '\0';
+               Msg->cm_lengths[WhichToCut] = maxlen;
+       }
 }
 
 void CM_FlushField(struct CtdlMessage *Msg, eMsgField which)
@@ -159,6 +163,7 @@ void CM_FlushField(struct CtdlMessage *Msg, eMsgField which)
        if (Msg->cm_fields[which] != NULL)
                free (Msg->cm_fields[which]);
        Msg->cm_fields[which] = NULL;
+       Msg->cm_lengths[which] = 0;
 }
 void CM_Flush(struct CtdlMessage *Msg)
 {
@@ -181,13 +186,17 @@ void CM_CopyField(struct CtdlMessage *Msg, eMsgField WhichToPutTo, eMsgField Whi
 
        if (Msg->cm_fields[WhichtToCopy] != NULL)
        {
-               len = strlen(Msg->cm_fields[WhichtToCopy]);
+               len = Msg->cm_lengths[WhichtToCopy];
                Msg->cm_fields[WhichToPutTo] = malloc(len + 1);
                memcpy(Msg->cm_fields[WhichToPutTo], Msg->cm_fields[WhichtToCopy], len);
                Msg->cm_fields[WhichToPutTo][len] = '\0';
+               Msg->cm_lengths[WhichToPutTo] = len;
        }
        else
+       {
                Msg->cm_fields[WhichToPutTo] = NULL;
+               Msg->cm_lengths[WhichToPutTo] = 0;
+       }
 }
 
 
@@ -198,7 +207,7 @@ void CM_PrependToField(struct CtdlMessage *Msg, eMsgField which, const char *buf
                long newmsgsize;
                char *new;
 
-               oldmsgsize = strlen(Msg->cm_fields[which]) + 1;
+               oldmsgsize = Msg->cm_lengths[which] + 1;
                newmsgsize = length + oldmsgsize;
 
                new = malloc(newmsgsize);
@@ -206,11 +215,13 @@ void CM_PrependToField(struct CtdlMessage *Msg, eMsgField which, const char *buf
                memcpy(new + length, Msg->cm_fields[which], oldmsgsize);
                free(Msg->cm_fields[which]);
                Msg->cm_fields[which] = new;
+               Msg->cm_lengths[which] = newmsgsize - 1;
        }
        else {
                Msg->cm_fields[which] = malloc(length + 1);
                memcpy(Msg->cm_fields[which], buf, length);
                Msg->cm_fields[which][length] = '\0';
+               Msg->cm_lengths[which] = length;
        }
 }
 
@@ -221,6 +232,7 @@ void CM_SetAsField(struct CtdlMessage *Msg, eMsgField which, char **buf, long le
 
        Msg->cm_fields[which] = *buf;
        *buf = NULL;
+       Msg->cm_lengths[which] = length;
 }
 
 void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf)
@@ -228,6 +240,7 @@ void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf)
        if (Msg->cm_fields[which] != NULL)
                free (Msg->cm_fields[which]);
 
+       Msg->cm_lengths[which] = StrLength(*buf);
        Msg->cm_fields[which] = SmashStrBuf(buf);
 }
 
@@ -235,9 +248,10 @@ void CM_GetAsField(struct CtdlMessage *Msg, eMsgField which, char **ret, long *r
 {
        if (Msg->cm_fields[which] != NULL)
        {
-               *retlen = strlen(Msg->cm_fields[which]);
+               *retlen = Msg->cm_lengths[which];
                *ret = Msg->cm_fields[which];
                Msg->cm_fields[which] = NULL;
+               Msg->cm_lengths[which] = 0;
        }
        else
        {
@@ -268,6 +282,7 @@ void CM_FreeContents(struct CtdlMessage *msg)
        for (i = 0; i < 256; ++i)
                if (msg->cm_fields[i] != NULL) {
                        free(msg->cm_fields[i]);
+                       msg->cm_lengths[i] = 0;
                }
 
        msg->cm_magic = 0;      /* just in case */
@@ -289,12 +304,13 @@ void CM_Free(struct CtdlMessage *msg)
 int CM_DupField(eMsgField i, struct CtdlMessage *OrgMsg, struct CtdlMessage *NewMsg)
 {
        long len;
-       len = strlen(OrgMsg->cm_fields[i]);
+       len = OrgMsg->cm_lengths[i];
        NewMsg->cm_fields[i] = malloc(len + 1);
        if (NewMsg->cm_fields[i] == NULL)
                return 0;
        memcpy(NewMsg->cm_fields[i], OrgMsg->cm_fields[i], len);
        NewMsg->cm_fields[i][len] = '\0';
+       NewMsg->cm_lengths[i] = len;
        return 1;
 }
 
@@ -353,8 +369,9 @@ int CtdlMsgCmp(struct CtdlMessage *msg, struct CtdlMessage *template) {
                                if (IsEmptyStr(template->cm_fields[i])) continue;
                                return 1;
                        }
-                       if (strcasecmp(msg->cm_fields[i],
-                               template->cm_fields[i])) return 1;
+                       if ((template->cm_lengths[i] != msg->cm_lengths[i]) ||
+                           (strcasecmp(msg->cm_fields[i], template->cm_fields[i])))
+                               return 1;
                }
        }
 
@@ -1084,6 +1101,7 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body)
        char *upper_bound;
        cit_uint8_t ch;
        cit_uint8_t field_header;
+       eMsgField which;
 
        MSG_syslog(LOG_DEBUG, "CtdlFetchMessage(%ld, %d)\n", msgnum, with_body);
        dmsgtext = cdb_fetch(CDB_MSGMAIN, &msgnum, sizeof(long));
@@ -1123,8 +1141,9 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body)
                        break;
                }
                field_header = *mptr++;
+               which = field_header;
                len = strlen(mptr);
-               CM_SetField(ret, field_header, mptr, len);
+               CM_SetField(ret, which, mptr, len);
 
                mptr += len + 1;        /* advance to next field */
 
@@ -1149,7 +1168,7 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body)
        }
 
        /* Perform "before read" hooks (aborting if any return nonzero) */
-       if (PerformMessageHooks(ret, EVT_BEFOREREAD) > 0) {
+       if (PerformMessageHooks(ret, NULL, EVT_BEFOREREAD) > 0) {
                CM_Free(ret);
                return NULL;
        }
@@ -2438,6 +2457,7 @@ long send_message(struct CtdlMessage *msg) {
        struct ser_ret smr;
        int is_bigmsg = 0;
        char *holdM = NULL;
+       long oldMLen = 0;
 
        /* Get a new message number */
        newmsgid = get_new_message_number();
@@ -2454,10 +2474,12 @@ long send_message(struct CtdlMessage *msg) {
 
        /* If the message is big, set its body aside for storage elsewhere */
        if (!CM_IsEmpty(msg, eMesageText)) {
-               if (strlen(msg->cm_fields[eMesageText]) > BIGMSG) {
+               if (msg->cm_lengths[eMesageText] > BIGMSG) {
                        is_bigmsg = 1;
                        holdM = msg->cm_fields[eMesageText];
                        msg->cm_fields[eMesageText] = NULL;
+                       oldMLen = msg->cm_lengths[eMesageText];
+                       msg->cm_lengths[eMesageText] = 0;
                }
        }
 
@@ -2485,7 +2507,7 @@ long send_message(struct CtdlMessage *msg) {
                                  &newmsgid,
                                  (int)sizeof(long),
                                  holdM,
-                                 (strlen(holdM) + 1)
+                                 (oldMLen + 1)
                                );
                }
                retval = newmsgid;
@@ -2513,11 +2535,8 @@ void CtdlSerializeMessage(struct ser_ret *ret,           /* return values */
                       struct CtdlMessage *msg) /* unserialized msg */
 {
        struct CitContext *CCC = CC;
-       size_t wlen, fieldlen;
+       size_t wlen;
        int i;
-       long lengths[NDiskFields];
-       
-       memset(lengths, 0, sizeof(lengths));
 
        /*
         * Check for valid message format
@@ -2532,10 +2551,7 @@ void CtdlSerializeMessage(struct ser_ret *ret,           /* return values */
        ret->len = 3;
        for (i=0; i < NDiskFields; ++i)
                if (msg->cm_fields[FieldOrder[i]] != NULL)
-               {
-                       lengths[i] = strlen(msg->cm_fields[FieldOrder[i]]);
-                       ret->len += lengths[i] + 2;
-               }
+                       ret->len += msg->cm_lengths[FieldOrder[i]] + 2;
 
        ret->ser = malloc(ret->len);
        if (ret->ser == NULL) {
@@ -2554,14 +2570,13 @@ void CtdlSerializeMessage(struct ser_ret *ret,          /* return values */
        for (i=0; i < NDiskFields; ++i)
                if (msg->cm_fields[FieldOrder[i]] != NULL)
                {
-                       fieldlen = lengths[i];
                        ret->ser[wlen++] = (char)FieldOrder[i];
 
                        memcpy(&ret->ser[wlen],
                               msg->cm_fields[FieldOrder[i]],
-                              fieldlen+1);
+                              msg->cm_lengths[FieldOrder[i]] + 1);
 
-                       wlen = wlen + fieldlen + 1;
+                       wlen = wlen + msg->cm_lengths[FieldOrder[i]] + 1;
                }
 
        if (ret->len != wlen) {
@@ -2606,37 +2621,28 @@ void ReplicationChecks(struct CtdlMessage *msg) {
  * Save a message to disk and submit it into the delivery system.
  */
 long CtdlSubmitMsg(struct CtdlMessage *msg,    /* message to save */
-                  struct recptypes *recps,     /* recipients (if mail) */
+                  recptypes *recps,            /* recipients (if mail) */
                   const char *force,           /* force a particular room? */
                   int flags                    /* should the message be exported clean? */
        )
 {
-       char submit_filename[128];
        char hold_rm[ROOMNAMELEN];
        char actual_rm[ROOMNAMELEN];
        char force_room[ROOMNAMELEN];
        char content_type[SIZ];                 /* We have to learn this */
        char recipient[SIZ];
+       char bounce_to[1024];
        const char *room;
        long newmsgid;
        const char *mptr = NULL;
        struct ctdluser userbuf;
        int a, i;
        struct MetaData smi;
-       FILE *network_fp = NULL;
-       static int seqnum = 1;
-       struct CtdlMessage *imsg = NULL;
-       char *instr = NULL;
-       size_t instr_alloc = 0;
-       struct ser_ret smr;
-       char *hold_R, *hold_D;
        char *collected_addresses = NULL;
        struct addresses_to_be_filed *aptr = NULL;
        StrBuf *saved_rfc822_version = NULL;
        int qualified_for_journaling = 0;
        CitContext *CCC = MyContext();
-       char bounce_to[1024] = "";
-       int rv = 0;
 
        MSGM_syslog(LOG_DEBUG, "CtdlSubmitMsg() called\n");
        if (CM_IsValidMsg(msg) == 0) return(-1);        /* self check */
@@ -2742,7 +2748,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
 
        /* Perform "before save" hooks (aborting if any return nonzero) */
        MSGM_syslog(LOG_DEBUG, "Performing before-save hooks\n");
-       if (PerformMessageHooks(msg, EVT_BEFORESAVE) > 0) return(-3);
+       if (PerformMessageHooks(msg, recps, EVT_BEFORESAVE) > 0) return(-3);
 
        /*
         * If this message has an Exclusive ID, and the room is replication
@@ -2825,180 +2831,60 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,    /* message to save */
        CtdlPutUserLock(&CCC->user);
 
        /* Decide where bounces need to be delivered */
-       if ((recps != NULL) && (recps->bounce_to != NULL)) {
-               safestrncpy(bounce_to, recps->bounce_to, sizeof bounce_to);
-       }
-       else if (CCC->logged_in) {
-               snprintf(bounce_to, sizeof bounce_to, "%s@%s", CCC->user.fullname, config.c_nodename);
-       }
-       else {
-               snprintf(bounce_to, sizeof bounce_to, "%s@%s", msg->cm_fields[eAuthor], msg->cm_fields[eNodeName]);
+       if ((recps != NULL) && (recps->bounce_to == NULL))
+       {
+               if (CCC->logged_in) 
+                       snprintf(bounce_to, sizeof bounce_to, "%s@%s",
+                                CCC->user.fullname, config.c_nodename);
+               else 
+                       snprintf(bounce_to, sizeof bounce_to, "%s@%s",
+                                msg->cm_fields[eAuthor], msg->cm_fields[eNodeName]);
+               recps->bounce_to = bounce_to;
        }
+               
+       CM_SetFieldLONG(msg, eVltMsgNum, newmsgid);
+
 
        /* If this is private, local mail, make a copy in the
         * recipient's mailbox and bump the reference count.
         */
        if ((recps != NULL) && (recps->num_local > 0))
-               for (i=0; i<num_tokens(recps->recp_local, '|'); ++i) {
-                       long recipientlen;
-                       recipientlen = extract_token(recipient,
-                                                    recps->recp_local, i,
-                                                    '|', sizeof recipient);
-                       MSG_syslog(LOG_DEBUG, "Delivering private local mail to <%s>\n",
-                              recipient);
+       {
+               char *pch;
+               int ntokens;
+
+               pch = recps->recp_local;
+               recps->recp_local = recipient;
+               ntokens = num_tokens(pch, '|');
+               for (i=0; i<ntokens; ++i)
+               {
+                       extract_token(recipient, pch, i, '|', sizeof recipient);
+                       MSG_syslog(LOG_DEBUG, "Delivering private local mail to <%s>\n", recipient);
                        if (CtdlGetUser(&userbuf, recipient) == 0) {
                                CtdlMailboxName(actual_rm, sizeof actual_rm, &userbuf, MAILROOM);
                                CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0, msg);
                                CtdlBumpNewMailCounter(userbuf.usernum);
-                               if (!IsEmptyStr(config.c_funambol_host) || !IsEmptyStr(config.c_pager_program)) {
-                                       /* Generate a instruction message for the Funambol notification
-                                        * server, in the same style as the SMTP queue
-                                        */
-                                       long instrlen;
-                                       instr_alloc = 1024;
-                                       instr = malloc(instr_alloc);
-                                       instrlen = snprintf(
-                                               instr, instr_alloc,
-                                               "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
-                                               "bounceto|%s\n",
-                                               SPOOLMIME,
-                                               newmsgid,
-                                               (long)time(NULL), //todo: time() is expensive!
-                                               bounce_to
-                                               );
-                               
-                                       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;
-                                       CM_SetField(imsg, eMsgSubject, HKEY("QMSG"));
-                                       CM_SetField(imsg, eAuthor, HKEY("Citadel"));
-                                       CM_SetField(imsg, eJournal, HKEY("do not journal"));
-                                       CM_SetAsField(imsg, eMesageText, &instr, instrlen);
-                                       CM_SetField(imsg, eExtnotify, recipient, recipientlen);
-                                       CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM, 0);
-                                       CM_Free(imsg);
-                               }
+                               PerformMessageHooks(msg, recps, EVT_AFTERUSRMBOXSAVE);
                        }
                        else {
                                MSG_syslog(LOG_DEBUG, "No user <%s>\n", recipient);
                                CtdlSaveMsgPointerInRoom(config.c_aideroom, newmsgid, 0, msg);
                        }
                }
+               recps->recp_local = pch;
+       }
 
        /* Perform "after save" hooks */
        MSGM_syslog(LOG_DEBUG, "Performing after-save hooks\n");
 
-       CM_SetFieldLONG(msg, eVltMsgNum, newmsgid);
-       PerformMessageHooks(msg, EVT_AFTERSAVE);
+       PerformMessageHooks(msg, recps, EVT_AFTERSAVE);
        CM_FlushField(msg, eVltMsgNum);
 
-       /* For IGnet mail, we have to save a new copy into the spooler for
-        * each recipient, with the R and D fields set to the recipient and
-        * destination-node.  This has two ugly side effects: all other
-        * recipients end up being unlisted in this recipient's copy of the
-        * message, and it has to deliver multiple messages to the same
-        * node.  We'll revisit this again in a year or so when everyone has
-        * a network spool receiver that can handle the new style messages.
-        */
-       if ((recps != NULL) && (recps->num_ignet > 0))
-               for (i=0; i<num_tokens(recps->recp_ignet, '|'); ++i) {
-                       extract_token(recipient, recps->recp_ignet, i,
-                                     '|', sizeof recipient);
-
-                       hold_R = msg->cm_fields[eRecipient];
-                       hold_D = msg->cm_fields[eDestination];
-                       msg->cm_fields[eRecipient] = malloc(SIZ);
-                       msg->cm_fields[eDestination] = malloc(128);
-                       extract_token(msg->cm_fields[eRecipient], recipient, 0, '@', SIZ);
-                       extract_token(msg->cm_fields[eDestination], recipient, 1, '@', 128);
-               
-                       CtdlSerializeMessage(&smr, msg);
-                       if (smr.len > 0) {
-                               snprintf(submit_filename, sizeof submit_filename,
-                                        "%s/netmail.%04lx.%04x.%04x",
-                                        ctdl_netin_dir,
-                                        (long) getpid(), CCC->cs_pid, ++seqnum);
-                               network_fp = fopen(submit_filename, "wb+");
-                               if (network_fp != NULL) {
-                                       rv = fwrite(smr.ser, smr.len, 1, network_fp);
-                                       if (rv == -1) {
-                                               MSG_syslog(LOG_EMERG, "CtdlSubmitMsg(): Couldn't write network spool file: %s\n",
-                                                          strerror(errno));
-                                       }
-                                       fclose(network_fp);
-                               }
-                               free(smr.ser);
-                       }
-
-                       free(msg->cm_fields[eRecipient]);
-                       free(msg->cm_fields[eDestination]);
-                       msg->cm_fields[eRecipient] = hold_R;
-                       msg->cm_fields[eDestination] = hold_D;
-               }
-
        /* Go back to the room we started from */
        MSG_syslog(LOG_DEBUG, "Returning to original room %s\n", hold_rm);
        if (strcasecmp(hold_rm, CCC->room.QRname))
                CtdlUserGoto(hold_rm, 0, 1, NULL, NULL);
 
-       /* For internet mail, generate delivery instructions.
-        * Yes, this is recursive.  Deal with it.  Infinite recursion does
-        * not happen because the delivery instructions message does not
-        * contain a recipient.
-        */
-       if ((recps != NULL) && (recps->num_internet > 0)) {
-               StrBuf *SpoolMsg = NewStrBuf();
-               long nTokens;
-
-               MSGM_syslog(LOG_DEBUG, "Generating delivery instructions\n");
-
-               StrBufPrintf(SpoolMsg,
-                            "Content-type: "SPOOLMIME"\n"
-                            "\n"
-                            "msgid|%ld\n"
-                            "submitted|%ld\n"
-                            "bounceto|%s\n",
-                            newmsgid,
-                            (long)time(NULL),
-                            bounce_to);
-
-               if (recps->envelope_from != NULL) {
-                       StrBufAppendBufPlain(SpoolMsg, HKEY("envelope_from|"), 0);
-                       StrBufAppendBufPlain(SpoolMsg, recps->envelope_from, -1, 0);
-                       StrBufAppendBufPlain(SpoolMsg, HKEY("\n"), 0);
-               }
-               if (recps->sending_room != NULL) {
-                       StrBufAppendBufPlain(SpoolMsg, HKEY("source_room|"), 0);
-                       StrBufAppendBufPlain(SpoolMsg, recps->sending_room, -1, 0);
-                       StrBufAppendBufPlain(SpoolMsg, HKEY("\n"), 0);
-               }
-
-               nTokens = num_tokens(recps->recp_internet, '|');
-               for (i = 0; i < nTokens; i++) {
-                       long len;
-                       len = extract_token(recipient, recps->recp_internet, i, '|', sizeof recipient);
-                       if (len > 0) {
-                               StrBufAppendBufPlain(SpoolMsg, HKEY("remote|"), 0);
-                               StrBufAppendBufPlain(SpoolMsg, recipient, len, 0);
-                               StrBufAppendBufPlain(SpoolMsg, HKEY("|0||\n"), 0);
-                       }
-               }
-
-               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[eMsgSubject] = strdup("QMSG");
-               imsg->cm_fields[eAuthor] = strdup("Citadel");
-               imsg->cm_fields[eJournal] = strdup("do not journal");
-               imsg->cm_fields[eMesageText] = SmashStrBuf(&SpoolMsg);  /* imsg owns this memory now */
-               CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM, QP_EADDR);
-               CM_Free(imsg);
-       }
-
        /*
         * Any addresses to harvest for someone's address book?
         */
@@ -3051,6 +2937,9 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
                }
        }
 
+       if ((recps != NULL) && (recps->bounce_to == bounce_to))
+               recps->bounce_to = NULL;
+
        /* Done. */
        return(newmsgid);
 }
@@ -3068,7 +2957,7 @@ void quickie_message(const char *from,
                     const char *subject)
 {
        struct CtdlMessage *msg;
-       struct recptypes *recp = NULL;
+       recptypes *recp = NULL;
 
        msg = malloc(sizeof(struct CtdlMessage));
        memset(msg, 0, sizeof(struct CtdlMessage));
@@ -3433,6 +3322,45 @@ char *CtdlReadMessageBody(char *terminator,      /* token signalling EOT */
                return SmashStrBuf(&Message);
 }
 
+struct CtdlMessage *CtdlMakeMessage(
+        struct ctdluser *author,        /* author's user structure */
+        char *recipient,                /* NULL if it's not mail */
+        char *recp_cc,                 /* NULL if it's not mail */
+        char *room,                     /* room where it's going */
+        int type,                       /* see MES_ types in header file */
+        int format_type,                /* variformat, plain text, MIME... */
+        char *fake_name,                /* who we're masquerading as */
+       char *my_email,                 /* which of my email addresses to use (empty is ok) */
+        char *subject,                  /* Subject (optional) */
+       char *supplied_euid,            /* ...or NULL if this is irrelevant */
+        char *preformatted_text,        /* ...or NULL to read text from client */
+       char *references                /* Thread references */
+)
+{
+       return CtdlMakeMessageLen(
+               author, /* author's user structure */
+               recipient,              /* NULL if it's not mail */
+               (recipient)?strlen(recipient) : 0,
+               recp_cc,                        /* NULL if it's not mail */
+               (recp_cc)?strlen(recp_cc): 0,
+               room,                   /* room where it's going */
+               (room)?strlen(room): 0,
+               type,                   /* see MES_ types in header file */
+               format_type,            /* variformat, plain text, MIME... */
+               fake_name,              /* who we're masquerading as */
+               (fake_name)?strlen(fake_name): 0,
+               my_email,                       /* which of my email addresses to use (empty is ok) */
+               (my_email)?strlen(my_email): 0,
+               subject,                        /* Subject (optional) */
+               (subject)?strlen(subject): 0,
+               supplied_euid,          /* ...or NULL if this is irrelevant */
+               (supplied_euid)?strlen(supplied_euid):0,
+               preformatted_text,      /* ...or NULL to read text from client */
+               (preformatted_text)?strlen(preformatted_text) : 0,
+               references,             /* Thread references */
+               (references)?strlen(references):0);
+
+}
 
 /*
  * Build a binary message to be saved on disk.
@@ -3442,21 +3370,34 @@ char *CtdlReadMessageBody(char *terminator,     /* token signalling EOT */
  * the rest of the fields when CM_Free() is called.)
  */
 
-struct CtdlMessage *CtdlMakeMessage(
+struct CtdlMessage *CtdlMakeMessageLen(
        struct ctdluser *author,        /* author's user structure */
        char *recipient,                /* NULL if it's not mail */
+       long rcplen,
        char *recp_cc,                  /* NULL if it's not mail */
+       long cclen,
        char *room,                     /* room where it's going */
+       long roomlen,
        int type,                       /* see MES_ types in header file */
        int format_type,                /* variformat, plain text, MIME... */
        char *fake_name,                /* who we're masquerading as */
+       long fnlen,
        char *my_email,                 /* which of my email addresses to use (empty is ok) */
+       long myelen,
        char *subject,                  /* Subject (optional) */
+       long subjlen,
        char *supplied_euid,            /* ...or NULL if this is irrelevant */
+       long euidlen,
        char *preformatted_text,        /* ...or NULL to read text from client */
-       char *references                /* Thread references */
-       ) {
-       char dest_node[256];
+       long textlen,
+       char *references,               /* Thread references */
+       long reflen
+       )
+{
+       struct CitContext *CCC = CC;
+       /* Don't confuse the poor folks if it's not routed mail. * /
+          char dest_node[256] = "";*/
+       long blen;
        char buf[1024];
        struct CtdlMessage *msg;
        StrBuf *FakeAuthor;
@@ -3468,68 +3409,57 @@ struct CtdlMessage *CtdlMakeMessage(
        msg->cm_anon_type = type;
        msg->cm_format_type = format_type;
 
-       /* Don't confuse the poor folks if it's not routed mail. */
-       strcpy(dest_node, "");
-
-       if (recipient != NULL) striplt(recipient);
-       if (recp_cc != NULL) striplt(recp_cc);
+       if (recipient != NULL) rcplen = striplt(recipient);
+       if (recp_cc != NULL) cclen = striplt(recp_cc);
 
        /* Path or Return-Path */
-       if (my_email == NULL) my_email = "";
-
-       if (!IsEmptyStr(my_email)) {
-               msg->cm_fields[eMessagePath] = strdup(my_email);
+       if (myelen > 0) {
+               CM_SetField(msg, eMessagePath, my_email, myelen);
        }
        else {
-               snprintf(buf, sizeof buf, "%s", author->fullname);
-               msg->cm_fields[eMessagePath] = strdup(buf);
+               CM_SetField(msg, eMessagePath, author->fullname, strlen(author->fullname));
        }
        convert_spaces_to_underscores(msg->cm_fields[eMessagePath]);
 
-       snprintf(buf, sizeof buf, "%ld", (long)time(NULL));     /* timestamp */
-       msg->cm_fields[eTimestamp] = strdup(buf);
+       blen = snprintf(buf, sizeof buf, "%ld", (long)time(NULL));
+       CM_SetField(msg, eTimestamp, buf, blen);
 
-       if ((fake_name != NULL) && (fake_name[0])) {            /* author */
-               FakeAuthor = NewStrBufPlain (fake_name, -1);
+       if (fnlen > 0) {
+               FakeAuthor = NewStrBufPlain (fake_name, fnlen);
        }
        else {
                FakeAuthor = NewStrBufPlain (author->fullname, -1);
        }
        StrBufRFC2047encode(&FakeEncAuthor, FakeAuthor);
-       msg->cm_fields[eAuthor] = SmashStrBuf(&FakeEncAuthor);
-       FreeStrBuf(&FakeAuthor);
+       CM_SetAsFieldSB(msg, eAuthor, &FakeEncAuthor);
 
-       if (CC->room.QRflags & QR_MAILBOX) {            /* room */
-               msg->cm_fields[eOriginalRoom] = strdup(&CC->room.QRname[11]);
+       if (CCC->room.QRflags & QR_MAILBOX) {           /* room */
+               CM_SetField(msg, eOriginalRoom, &CCC->room.QRname[11], strlen(&CCC->room.QRname[11]));
        }
        else {
-               msg->cm_fields[eOriginalRoom] = strdup(CC->room.QRname);
+               CM_SetField(msg, eOriginalRoom, CCC->room.QRname, strlen(CCC->room.QRname));
        }
 
-       msg->cm_fields[eNodeName] = strdup(NODENAME);           /* nodename */
-       msg->cm_fields[eHumanNode] = strdup(HUMANNODE);         /* hnodename */
+       CM_SetField(msg, eNodeName, NODENAME, strlen(NODENAME));
+       CM_SetField(msg, eHumanNode, HUMANNODE, strlen(HUMANNODE));
 
-       if ((recipient != NULL) && (recipient[0] != 0)) {
-               msg->cm_fields[eRecipient] = strdup(recipient);
-       }
-       if ((recp_cc != NULL) && (recp_cc[0] != 0)) {
-               msg->cm_fields[eCarbonCopY] = strdup(recp_cc);
+       if (rcplen > 0) {
+               CM_SetField(msg, eRecipient, recipient, rcplen);
        }
-       if (dest_node[0] != 0) {
-               msg->cm_fields[eDestination] = strdup(dest_node);
+       if (cclen > 0) {
+               CM_SetField(msg, eCarbonCopY, recp_cc, cclen);
        }
 
-       if (!IsEmptyStr(my_email)) {
-               msg->cm_fields[erFc822Addr] = strdup(my_email);
+       if (myelen > 0) {
+               CM_SetField(msg, erFc822Addr, my_email, myelen);
        }
-       else if ( (author == &CC->user) && (!IsEmptyStr(CC->cs_inet_email)) ) {
-               msg->cm_fields[erFc822Addr] = strdup(CC->cs_inet_email);
+       else if ( (author == &CCC->user) && (!IsEmptyStr(CCC->cs_inet_email)) ) {
+               CM_SetField(msg, erFc822Addr, CCC->cs_inet_email, strlen(CCC->cs_inet_email));
        }
 
        if (subject != NULL) {
                long length;
-               striplt(subject);
-               length = strlen(subject);
+               length = striplt(subject);
                if (length > 0) {
                        long i;
                        long IsAscii;
@@ -3539,30 +3469,31 @@ struct CtdlMessage *CtdlMakeMessage(
                               (IsAscii = isascii(subject[i]) != 0 ))
                                i++;
                        if (IsAscii != 0)
-                               msg->cm_fields[eMsgSubject] = strdup(subject);
+                               CM_SetField(msg, eMsgSubject, subject, subjlen);
                        else /* ok, we've got utf8 in the string. */
                        {
-                               msg->cm_fields[eMsgSubject] = rfc2047encode(subject, length);
+                               char *rfc2047Subj;
+                               rfc2047Subj = rfc2047encode(subject, length);
+                               CM_SetAsField(msg, eMsgSubject, &rfc2047Subj, strlen(rfc2047Subj));
                        }
 
                }
        }
 
-       if (supplied_euid != NULL) {
-               msg->cm_fields[eExclusiveID] = strdup(supplied_euid);
+       if (euidlen > 0) {
+               CM_SetField(msg, eExclusiveID, supplied_euid, euidlen);
        }
 
-       if ((references != NULL) && (!IsEmptyStr(references))) {
-               if (msg->cm_fields[eWeferences] != NULL)
-                       free(msg->cm_fields[eWeferences]);
-               msg->cm_fields[eWeferences] = strdup(references);
+       if (reflen > 0) {
+               CM_SetField(msg, eWeferences, references, reflen);
        }
 
        if (preformatted_text != NULL) {
-               msg->cm_fields[eMesageText] = preformatted_text;
+               CM_SetField(msg, eMesageText, preformatted_text, textlen);
        }
        else {
-               msg->cm_fields[eMesageText] = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
+               preformatted_text = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
+               CM_SetField(msg, eMesageText, preformatted_text, strlen(preformatted_text));
        }
 
        return(msg);
@@ -3996,7 +3927,7 @@ void CtdlWriteObject(char *req_room,                      /* Room to stuff it in */
        struct ctdlroom qrbuf;
        char roomname[ROOMNAMELEN];
        struct CtdlMessage *msg;
-       char *encoded_message = NULL;
+       StrBuf *encoded_message = NULL;
 
        if (is_mailbox != NULL) {
                CtdlMailboxName(roomname, sizeof roomname, is_mailbox, req_room);
@@ -4008,39 +3939,28 @@ void CtdlWriteObject(char *req_room,                    /* Room to stuff it in */
        MSG_syslog(LOG_DEBUG, "Raw length is %ld\n", (long)raw_length);
 
        if (is_binary) {
-               encoded_message = malloc((size_t) (((raw_length * 134) / 100) + 4096 ) );
+               encoded_message = NewStrBufPlain(NULL, (size_t) (((raw_length * 134) / 100) + 4096 ) );
        }
        else {
-               encoded_message = malloc((size_t)(raw_length + 4096));
+               encoded_message = NewStrBufPlain(NULL, (size_t)(raw_length + 4096));
        }
 
-       sprintf(encoded_message, "Content-type: %s\n", content_type);
+       StrBufAppendBufPlain(encoded_message, HKEY("Content-type: "), 0);
+       StrBufAppendBufPlain(encoded_message, content_type, -1, 0);
+       StrBufAppendBufPlain(encoded_message, HKEY("\n"), 0);
 
        if (is_binary) {
-               sprintf(&encoded_message[strlen(encoded_message)],
-                       "Content-transfer-encoding: base64\n\n"
-                       );
+               StrBufAppendBufPlain(encoded_message, HKEY("Content-transfer-encoding: base64\n\n"), 0);
        }
        else {
-               sprintf(&encoded_message[strlen(encoded_message)],
-                       "Content-transfer-encoding: 7bit\n\n"
-                       );
+               StrBufAppendBufPlain(encoded_message, HKEY("Content-transfer-encoding: 7bit\n\n"), 0);
        }
 
        if (is_binary) {
-               CtdlEncodeBase64(
-                       &encoded_message[strlen(encoded_message)],
-                       raw_message,
-                       (int)raw_length,
-                       0
-                       );
+               StrBufBase64Append(encoded_message, NULL, raw_message, raw_length, 0);
        }
        else {
-               memcpy(
-                       &encoded_message[strlen(encoded_message)],
-                       raw_message,
-                       (int)(raw_length+1)
-                       );
+               StrBufAppendBufPlain(encoded_message, raw_message, raw_length, 0);
        }
 
        MSGM_syslog(LOG_DEBUG, "Allocating\n");
@@ -4049,13 +3969,13 @@ void CtdlWriteObject(char *req_room,                    /* Room to stuff it in */
        msg->cm_magic = CTDLMESSAGE_MAGIC;
        msg->cm_anon_type = MES_NORMAL;
        msg->cm_format_type = 4;
-       msg->cm_fields[eAuthor] = strdup(CCC->user.fullname);
-       msg->cm_fields[eOriginalRoom] = strdup(req_room);
-       msg->cm_fields[eNodeName] = strdup(config.c_nodename);
-       msg->cm_fields[eHumanNode] = strdup(config.c_humannode);
+       CM_SetField(msg, eAuthor, CCC->user.fullname, strlen(CCC->user.fullname));
+       CM_SetField(msg, eOriginalRoom, req_room, strlen(req_room));
+       CM_SetField(msg, eNodeName, config.c_nodename, strlen(config.c_nodename));
+       CM_SetField(msg, eHumanNode, config.c_humannode, strlen(config.c_humannode));
        msg->cm_flags = flags;
        
-       msg->cm_fields[eMesageText] = encoded_message;
+       CM_SetAsFieldSB(msg, eMesageText, &encoded_message);
 
        /* Create the requested room if we have to. */
        if (CtdlGetRoom(&qrbuf, roomname) != 0) {
index 7780d69fc54b3784e209d5d602c6ea31d618ebee..058c902e583d231f399fb6b094bd7b61b940f99d 100644 (file)
@@ -77,7 +77,7 @@ void memfmout (char *mptr, const char *nl);
 void output_mime_parts(char *);
 long send_message (struct CtdlMessage *);
 void loadtroom (void);
-long CtdlSubmitMsg(struct CtdlMessage *, struct recptypes *, const char *, int);
+long CtdlSubmitMsg(struct CtdlMessage *, recptypes *, const char *, int);
 
 void quickie_message(const char *from,
                     const char *fromaddr,
@@ -211,7 +211,29 @@ struct CtdlMessage *CtdlMakeMessage(
         char *preformatted_text,        /* ...or NULL to read text from client */
        char *references                /* Thread references */
 );
-int CtdlIsMe(char *addr, int addr_buf_len);
+
+struct CtdlMessage *CtdlMakeMessageLen(
+       struct ctdluser *author,        /* author's user structure */
+       char *recipient,                /* NULL if it's not mail */
+       long rcplen,
+       char *recp_cc,                  /* NULL if it's not mail */
+       long cclen,
+       char *room,                     /* room where it's going */
+       long roomlen,
+       int type,                       /* see MES_ types in header file */
+       int format_type,                /* variformat, plain text, MIME... */
+       char *fake_name,                /* who we're masquerading as */
+       long fnlen,
+       char *my_email,                 /* which of my email addresses to use (empty is ok) */
+       long myelen,
+       char *subject,                  /* Subject (optional) */
+       long subjlen,
+       char *supplied_euid,            /* ...or NULL if this is irrelevant */
+       long euidlen,
+       char *preformatted_text,        /* ...or NULL to read text from client */
+       long textlen,
+       char *references,               /* Thread references */
+       long reflen);
 
 /* 
  * loading messages async via an FD: 
index 387b8754dd775027811a116405999f8731cd7622..4b4e44c08ab958bdb32478fa6e1629dbaaf3cd8b 100644 (file)
@@ -101,7 +101,7 @@ UserFunctionHook *UserHookTable = NULL;
 typedef struct MessageFunctionHook MessageFunctionHook;
 struct MessageFunctionHook {
        MessageFunctionHook *next;
-       int (*h_function_pointer) (struct CtdlMessage *msg);
+       int (*h_function_pointer) (struct CtdlMessage *msg, recptypes *recps);
        int eventtype;
 };
 MessageFunctionHook *MessageHookTable = NULL;
@@ -730,7 +730,7 @@ void CtdlDestroyUserHooks(void)
 }
 
 
-void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *),
+void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *, recptypes *),
                                int EventType)
 {
 
@@ -748,7 +748,7 @@ void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *),
 }
 
 
-void CtdlUnregisterMessageHook(int (*handler)(struct CtdlMessage *),
+void CtdlUnregisterMessageHook(int (*handler)(struct CtdlMessage *, recptypes *),
                int EventType)
 {
        MessageFunctionHook *cur, *p, *last;
@@ -1379,7 +1379,7 @@ void PerformUserHooks(ctdluser *usbuf, int EventType)
        }
 }
 
-int PerformMessageHooks(struct CtdlMessage *msg, int EventType)
+int PerformMessageHooks(struct CtdlMessage *msg, recptypes *recps, int EventType)
 {
        MessageFunctionHook *fcn = NULL;
        int total_retval = 0;
@@ -1397,7 +1397,7 @@ int PerformMessageHooks(struct CtdlMessage *msg, int EventType)
         */
        for (fcn = MessageHookTable; fcn != NULL; fcn = fcn->next) {
                if (fcn->eventtype == EventType) {
-                       total_retval = total_retval + (*fcn->h_function_pointer) (msg);
+                       total_retval = total_retval + (*fcn->h_function_pointer) (msg, recps);
                }
        }
 
index 53973fe90ed88e19df9190c46499c2816de7296b..8591737ae9ede824231639d3c38a50a6545914a4 100644 (file)
@@ -82,7 +82,7 @@ void CtdlDestroyXmsgHooks(void);
 
 
 void CtdlDestroyMessageHook(void);
-int PerformMessageHooks(struct CtdlMessage *, int EventType);
+int PerformMessageHooks(struct CtdlMessage *, recptypes *recps, int EventType);
 
 
 void CtdlDestroyNetprocHooks(void);
index 10e8bee731ff5e246c196e24c901ee50bc535472..6aedb546393124cce3a72d7e6259eea3740404c5 100644 (file)
@@ -21,6 +21,7 @@ struct CtdlMessage {
        char cm_anon_type;              /* Anonymous or author-visible */
        char cm_format_type;            /* Format type */
        char *cm_fields[256];           /* Data fields */
+       long cm_lengths[256];           /* size of datafields */
        unsigned int cm_flags;          /* How to handle (NOT SAVED TO DISK) */
 };
 
@@ -28,6 +29,28 @@ struct CtdlMessage {
 #define        CM_SKIP_HOOKS   0x01            /* Don't run server-side handlers */
 
 
+/* Data structure returned by validate_recipients() */
+typedef struct __recptypes {
+       int recptypes_magic;
+        int num_local;
+        int num_internet;
+        int num_ignet;
+       int num_room;
+        int num_error;
+       char *errormsg;
+       char *recp_local;
+       char *recp_internet;
+       char *recp_ignet;
+       char *recp_room;
+       char *recp_orgroom;
+       char *display_recp;
+       char *bounce_to;
+       char *envelope_from;
+       char *sending_room;
+} recptypes;
+
+#define RECPTYPES_MAGIC 0xfeeb
+
 
 #define CTDLEXIT_SHUTDOWN      0       /* Normal shutdown; do NOT auto-restart */
 
@@ -224,6 +247,7 @@ struct cdbdata {
 #define EVT_BEFORESAVE 201
 #define EVT_AFTERSAVE  202
 #define EVT_SMTPSCAN   203     /* called before submitting a msg from SMTP */
+#define EVT_AFTERUSRMBOXSAVE 204 /* called afte a message was saved into a users inbox */
 /* Priority levels for paging functions (lower is better) */
 enum {
        XMSG_PRI_LOCAL,         /* Other users on -this- server */
index 0b50d129b651133086a1e96f1dc89528419dc14a..e55807dd33196103c1537c27ed5670d9dbcaf4cf 100644 (file)
@@ -653,7 +653,7 @@ int CtdlLoginExistingUser(char *authname, const char *trythisname)
        else {
                /* native auth mode */
 
-               struct recptypes *valid = NULL;
+               recptypes *valid = NULL;
        
                /* First, try to log in as if the supplied name is a display name */
                found_user = CtdlGetUser(&CC->user, username);