struct recptypes now uses dynamically allocated
authorArt Cancro <ajc@citadel.org>
Wed, 4 Apr 2007 04:43:21 +0000 (04:43 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 4 Apr 2007 04:43:21 +0000 (04:43 +0000)
string buffers.  The struct returned by validate_recipients() must now
always be freed using free_recipients(), the new destructor for
this data type.  C is my favorite OO language.  :)

citadel/imap_acl.c
citadel/journaling.c
citadel/msgbase.c
citadel/msgbase.h
citadel/serv_calendar.c
citadel/serv_network.c
citadel/serv_sieve.c
citadel/serv_smtp.c
citadel/serv_vcard.c
citadel/user_ops.c

index fdda833bb9c5df9462eb8f5978061a2715f474be..204b5473977ffd381c8104d605359460bbe98a1b 100644 (file)
@@ -242,7 +242,7 @@ void imap_listrights(int num_parms, char *parms[]) {
                if (valid->num_local == 1) {
                        ret = getuser(&temp, valid->recp_local);
                }
-               free(valid);
+               free_recipients(valid);
        }
        if (ret != 0) {
                cprintf("%s NO Invalid user name or access denied\r\n",
index 7febabd0ae3b2cfbad2d886ad05ea85222636790..c30c5d63ae76f48a743be445b8cc10ba6eec85c3 100644 (file)
@@ -241,7 +241,7 @@ void JournalRunQueueMsg(struct jnlq *jmsg) {
                        CtdlFreeMessage(journal_msg);
                }
 
-               free(journal_recps);
+               free_recipients(journal_recps);
        }
 
        /* We are responsible for freeing this memory. */
index c76c7fa8bc8779b1e55d1ca64881bef007827c9f..5161bef7d45295a15703aa936c6b81721550d43a 100644 (file)
@@ -2791,7 +2791,7 @@ void quickie_message(char *from, char *fromaddr, char *to, char *room, char *tex
 
        CtdlSubmitMsg(msg, recp, room);
        CtdlFreeMessage(msg);
-       if (recp != NULL) free(recp);
+       if (recp != NULL) free_recipients(recp);
 }
 
 
@@ -3063,13 +3063,15 @@ int CtdlCheckInternetMailPermission(struct ctdluser *who) {
 /*
  * Validate recipients, count delivery types and errors, and handle aliasing
  * FIXME check for dupes!!!!!
+ *
  * Returns 0 if all addresses are ok, ret->num_error = -1 if no addresses 
  * were specified, or the number of addresses found invalid.
- * caller needs to free the result.
+ *
+ * Caller needs to free the result using free_recipients()
  */
 struct recptypes *validate_recipients(char *supplied_recipients) {
        struct recptypes *ret;
-       char recipients[SIZ];
+       char *recipients = NULL;
        char this_recp[256];
        char this_recp_cooked[256];
        char append[SIZ];
@@ -3084,21 +3086,38 @@ struct recptypes *validate_recipients(char *supplied_recipients) {
        /* Initialize */
        ret = (struct recptypes *) malloc(sizeof(struct recptypes));
        if (ret == NULL) return(NULL);
-       memset(ret, 0, sizeof(struct recptypes));
 
-       ret->num_local = 0;
-       ret->num_internet = 0;
-       ret->num_ignet = 0;
-       ret->num_error = 0;
-       ret->num_room = 0;
+       /* Set all strings to null and numeric values to zero */
+       memset(ret, 0, sizeof(struct recptypes));
 
        if (supplied_recipients == NULL) {
-               strcpy(recipients, "");
+               recipients = strdup("");
        }
        else {
-               safestrncpy(recipients, supplied_recipients, sizeof recipients);
+               recipients = strdup(supplied_recipients);
        }
 
+       /* Allocate some memory.  Yes, this allocates 500% more memory than we will
+        * actually need, but it's healthier for the heap than doing lots of tiny
+        * realloc() calls instead.
+        */
+
+       ret->errormsg = malloc(strlen(recipients) + 1024);
+       ret->recp_local = malloc(strlen(recipients) + 1024);
+       ret->recp_internet = malloc(strlen(recipients) + 1024);
+       ret->recp_ignet = malloc(strlen(recipients) + 1024);
+       ret->recp_room = malloc(strlen(recipients) + 1024);
+       ret->display_recp = malloc(strlen(recipients) + 1024);
+
+       ret->errormsg[0] = 0;
+       ret->recp_local[0] = 0;
+       ret->recp_internet[0] = 0;
+       ret->recp_ignet[0] = 0;
+       ret->recp_room[0] = 0;
+       ret->display_recp[0] = 0;
+
+       ret->recptypes_magic = RECPTYPES_MAGIC;
+
        /* Change all valid separator characters to commas */
        for (i=0; i<strlen(recipients); ++i) {
                if ((recipients[i] == ';') || (recipients[i] == '|')) {
@@ -3217,8 +3236,7 @@ struct recptypes *validate_recipients(char *supplied_recipients) {
                                         this_recp);
                        }
                        else {
-                               snprintf(append, sizeof append,
-                                        ", %s", this_recp);
+                               snprintf(append, sizeof append, ", %s", this_recp);
                        }
                        if ( (strlen(ret->errormsg) + strlen(append)) < SIZ) {
                                strcat(ret->errormsg, append);
@@ -3229,8 +3247,7 @@ struct recptypes *validate_recipients(char *supplied_recipients) {
                                strcpy(append, this_recp);
                        }
                        else {
-                               snprintf(append, sizeof append, ", %s",
-                                        this_recp);
+                               snprintf(append, sizeof append, ", %s", this_recp);
                        }
                        if ( (strlen(ret->display_recp)+strlen(append)) < SIZ) {
                                strcat(ret->display_recp, append);
@@ -3251,10 +3268,35 @@ struct recptypes *validate_recipients(char *supplied_recipients) {
        lprintf(CTDL_DEBUG, " ignet: %d <%s>\n", ret->num_ignet, ret->recp_ignet);
        lprintf(CTDL_DEBUG, " error: %d <%s>\n", ret->num_error, ret->errormsg);
 
+       free(recipients);
        return(ret);
 }
 
 
+/*
+ * Destructor for struct recptypes
+ */
+void free_recipients(struct recptypes *valid) {
+
+       if (valid == NULL) {
+               return;
+       }
+
+       if (valid->recptypes_magic != RECPTYPES_MAGIC) {
+               lprintf(CTDL_EMERG, "Attempt to call free_recipients() on some other data type!\n");
+               abort();
+       }
+
+       if (valid->errormsg != NULL)            free(valid->errormsg);
+       if (valid->recp_local != NULL)          free(valid->recp_local);
+       if (valid->recp_internet != NULL)       free(valid->recp_internet);
+       if (valid->recp_ignet != NULL)          free(valid->recp_ignet);
+       if (valid->recp_room != NULL)           free(valid->recp_room);
+       if (valid->display_recp != NULL)        free(valid->display_recp);
+       free(valid);
+}
+
+
 
 /*
  * message entry  -  mode 0 (normal)
@@ -3378,32 +3420,32 @@ void cmd_ent0(char *entargs)
                valid_to = validate_recipients(recp);
                if (valid_to->num_error > 0) {
                        cprintf("%d Invalid recipient (To)\n", ERROR + NO_SUCH_USER);
-                       free(valid_to);
+                       free_recipients(valid_to);
                        return;
                }
 
                valid_cc = validate_recipients(cc);
                if (valid_cc->num_error > 0) {
                        cprintf("%d Invalid recipient (CC)\n", ERROR + NO_SUCH_USER);
-                       free(valid_to);
-                       free(valid_cc);
+                       free_recipients(valid_to);
+                       free_recipients(valid_cc);
                        return;
                }
 
                valid_bcc = validate_recipients(bcc);
                if (valid_bcc->num_error > 0) {
                        cprintf("%d Invalid recipient (BCC)\n", ERROR + NO_SUCH_USER);
-                       free(valid_to);
-                       free(valid_cc);
-                       free(valid_bcc);
+                       free_recipients(valid_to);
+                       free_recipients(valid_cc);
+                       free_recipients(valid_bcc);
                        return;
                }
 
                /* Recipient required, but none were specified */
                if ( (valid_to->num_error < 0) && (valid_cc->num_error < 0) && (valid_bcc->num_error < 0) ) {
-                       free(valid_to);
-                       free(valid_cc);
-                       free(valid_bcc);
+                       free_recipients(valid_to);
+                       free_recipients(valid_cc);
+                       free_recipients(valid_bcc);
                        cprintf("%d At least one recipient is required.\n", ERROR + NO_SUCH_USER);
                        return;
                }
@@ -3413,9 +3455,9 @@ void cmd_ent0(char *entargs)
                                cprintf("%d You do not have permission "
                                        "to send Internet mail.\n",
                                        ERROR + HIGHER_ACCESS_REQUIRED);
-                               free(valid_to);
-                               free(valid_cc);
-                               free(valid_bcc);
+                               free_recipients(valid_to);
+                               free_recipients(valid_cc);
+                               free_recipients(valid_bcc);
                                return;
                        }
                }
@@ -3424,9 +3466,9 @@ void cmd_ent0(char *entargs)
                   && (CC->user.axlevel < 4) ) {
                        cprintf("%d Higher access required for network mail.\n",
                                ERROR + HIGHER_ACCESS_REQUIRED);
-                       free(valid_to);
-                       free(valid_cc);
-                       free(valid_bcc);
+                       free_recipients(valid_to);
+                       free_recipients(valid_cc);
+                       free_recipients(valid_bcc);
                        return;
                }
        
@@ -3436,9 +3478,9 @@ void cmd_ent0(char *entargs)
                    && (!CC->internal_pgm)) {
                        cprintf("%d You don't have access to Internet mail.\n",
                                ERROR + HIGHER_ACCESS_REQUIRED);
-                       free(valid_to);
-                       free(valid_cc);
-                       free(valid_bcc);
+                       free_recipients(valid_to);
+                       free_recipients(valid_cc);
+                       free_recipients(valid_bcc);
                        return;
                }
 
@@ -3465,16 +3507,16 @@ void cmd_ent0(char *entargs)
        if (post == 0) {
                cprintf("%d %s\n", CIT_OK,
                        ((valid_to != NULL) ? valid_to->display_recp : "") );
-               free(valid_to);
-               free(valid_cc);
-               free(valid_bcc);
+               free_recipients(valid_to);
+               free_recipients(valid_cc);
+               free_recipients(valid_bcc);
                return;
        }
 
        /* We don't need these anymore because we'll do it differently below */
-       free(valid_to);
-       free(valid_cc);
-       free(valid_bcc);
+       free_recipients(valid_to);
+       free_recipients(valid_cc);
+       free_recipients(valid_bcc);
 
        /* Read in the message from the client. */
        if (do_confirm) {
@@ -3536,7 +3578,7 @@ void cmd_ent0(char *entargs)
                CtdlFreeMessage(msg);
        }
        if (valid != NULL) {
-               free(valid);
+               free_recipients(valid);
        }
        return;
 }
@@ -4226,19 +4268,19 @@ int CtdlIsMe(char *addr, int addr_buf_len)
        if (recp == NULL) return(0);
 
        if (recp->num_local == 0) {
-               free(recp);
+               free_recipients(recp);
                return(0);
        }
 
        for (i=0; i<recp->num_local; ++i) {
                extract_token(addr, recp->recp_local, i, '|', addr_buf_len);
                if (!strcasecmp(addr, CC->user.fullname)) {
-                       free(recp);
+                       free_recipients(recp);
                        return(1);
                }
        }
 
-       free(recp);
+       free_recipients(recp);
        return(0);
 }
 
index 1e0616bbb1aeb4ec40d16093a6a1070bd8f6a70a..6a6f5e109b831c0228376d364355f47f9356d03a 100644 (file)
@@ -51,19 +51,22 @@ struct repl {                       /* Info for replication checking */
 
 /* 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[SIZ];
-       char recp_local[SIZ];
-       char recp_internet[SIZ];
-       char recp_ignet[SIZ];
-       char recp_room[SIZ];
-       char display_recp[SIZ];
+       char *errormsg;
+       char *recp_local;
+       char *recp_internet;
+       char *recp_ignet;
+       char *recp_room;
+       char *display_recp;
 };
 
+#define RECPTYPES_MAGIC 0xfeeb
+
 /*
  * This is a list of "harvested" email addresses that we might want to
  * stick into someone's address book.  But we defer this operaiton so
@@ -155,6 +158,8 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums,
 void CtdlGetSeen(char *buf, int which_set);
 
 struct recptypes *validate_recipients(char *recipients);
+void free_recipients(struct recptypes *);
+
 struct CtdlMessage *CtdlMakeMessage(
         struct ctdluser *author,        /* author's user structure */
         char *recipient,                /* NULL if it's not mail */
index ec3f6f99036c9d4bf515ccd327c1c31447e3d052..91570069c4e37dcc60a152e03d36ca7e21163521 100644 (file)
@@ -240,7 +240,7 @@ void ical_send_a_reply(icalcomponent *request, char *action) {
                                                        if (me_attend) icalproperty_free(me_attend);
                                                        me_attend = icalproperty_new_clone(attendee);
                                                }
-                                               free(recp);
+                                               free_recipients(recp);
                                        }
                                }
                        }
@@ -323,7 +323,7 @@ void ical_send_a_reply(icalcomponent *request, char *action) {
                        valid = validate_recipients(organizer_string);
                        CtdlSubmitMsg(msg, valid, "");
                        CtdlFreeMessage(msg);
-                       free (valid);
+                       free_recipients(valid);
                }
        }
        free(serialized_reply);
@@ -1190,7 +1190,7 @@ void ical_freebusy(char *who) {
                        if (recp->num_local == 1) {
                                found_user = getuser(&usbuf, recp->recp_local);
                        }
-                       free(recp);
+                       free_recipients(recp);
                }
        }
 
@@ -1205,7 +1205,7 @@ void ical_freebusy(char *who) {
                        if (recp->num_local == 1) {
                                found_user = getuser(&usbuf, recp->recp_local);
                        }
-                       free(recp);
+                       free_recipients(recp);
                }
        }
 
@@ -1228,7 +1228,7 @@ void ical_freebusy(char *who) {
                                        if (recp->num_local == 1) {
                                                found_user = getuser(&usbuf, recp->recp_local);
                                        }
-                                       free(recp);
+                                       free_recipients(recp);
                                }
                        }
                }
@@ -1768,7 +1768,7 @@ void ical_send_out_invitations(icalcomponent *cal) {
                        valid = validate_recipients(attendees_string);
                        CtdlSubmitMsg(msg, valid, "");
                        CtdlFreeMessage(msg);
-                       free (valid);
+                       free_recipients(valid);
                }
        }
        free(serialized_request);
index 09f4ec321a0de05739faa992aff24fcf8a55ea38..930dae78528a727bde193d8cbacce1cc6c422bc0 100644 (file)
@@ -749,7 +749,7 @@ void network_spool_msg(long msgnum, void *userdata) {
        
                                        valid = validate_recipients(nptr->name);
                                        CtdlSubmitMsg(msg, valid, "");
-                                       free(valid);
+                                       free_recipients(valid);
                                }
                        
                        }
@@ -1328,7 +1328,7 @@ void network_bounce(struct CtdlMessage *msg, char *reason) {
        /* Now submit the message */
        valid = validate_recipients(recipient);
        if (valid != NULL) if (valid->num_error != 0) {
-               free(valid);
+               free_recipients(valid);
                valid = NULL;
        }
        if ( (valid == NULL) || (!strcasecmp(recipient, bouncesource)) ) {
@@ -1343,7 +1343,7 @@ void network_bounce(struct CtdlMessage *msg, char *reason) {
        CtdlSubmitMsg(msg, valid, force_room);
 
        /* Clean up */
-       if (valid != NULL) free(valid);
+       if (valid != NULL) free_recipients(valid);
        CtdlFreeMessage(msg);
        lprintf(CTDL_DEBUG, "leaving network_bounce()\n");
 }
@@ -1490,7 +1490,7 @@ void network_process_buffer(char *buffer, long size) {
                                "A message you sent could not be delivered due to an invalid address.\n"
                                "Please check the address and try sending the message again.\n");
                        msg = NULL;
-                       free(recp);
+                       free_recipients(recp);
                        return;
                }
                strcpy(target_room, "");        /* no target room if mail */
@@ -1521,7 +1521,7 @@ void network_process_buffer(char *buffer, long size) {
                CtdlSubmitMsg(msg, recp, target_room);
        }
        CtdlFreeMessage(msg);
-       free(recp);
+       free_recipients(recp);
 }
 
 
index 7ea3aa28c59a9ae51a9e37459e156b716ffba671..e8277d697324ff5dc7061fc13bab3a066dd82b5e 100644 (file)
@@ -122,20 +122,20 @@ int ctdl_redirect(sieve2_context_t *s, void *my)
        }
        if (valid->num_error > 0) {
                lprintf(CTDL_WARNING, "REDIRECT failed: bad recipient <%s>\n", recp);
-               free(valid);
+               free_recipients(valid);
                return SIEVE2_ERROR_BADARGS;
        }
 
        msg = CtdlFetchMessage(cs->msgnum, 1);
        if (msg == NULL) {
                lprintf(CTDL_WARNING, "REDIRECT failed: unable to fetch msg %ld\n", cs->msgnum);
-               free(valid);
+               free_recipients(valid);
                return SIEVE2_ERROR_BADARGS;
        }
 
        CtdlSubmitMsg(msg, valid, NULL);
        cs->cancel_implicit_keep = 1;
-       free(valid);
+       free_recipients(valid);
        CtdlFreeMessage(msg);
        return SIEVE2_OK;
 }
index a3bcd4b665b9a72c7ccb95c984e2820db8a17418..21934d256d361c812a7321785ee1d30292295b19 100644 (file)
@@ -145,7 +145,7 @@ void smtp_greeting(int is_msa)
                if (rbl_check(message_to_spammer)) {
                        cprintf("550 %s\r\n", message_to_spammer);
                        CC->kill_me = 1;
-                       /* no need to free(valid), it's not allocated yet */
+                       /* no need to free_recipients(valid), it's not allocated yet */
                        return;
                }
        }
@@ -157,7 +157,7 @@ void smtp_greeting(int is_msa)
                        config.c_maxsessions
                );
                CC->kill_me = 1;
-               /* no need to free(valid), it's not allocated yet */
+               /* no need to free_recipients(valid), it's not allocated yet */
                return;
        }
 
@@ -670,7 +670,7 @@ void smtp_rcpt(char *argbuf) {
                if (config.c_rbl_at_greeting == 0) {    /* Don't RBL again if we already did it */
                        if (rbl_check(message_to_spammer)) {
                                cprintf("550 %s\r\n", message_to_spammer);
-                               /* no need to free(valid), it's not allocated yet */
+                               /* no need to free_recipients(valid), it's not allocated yet */
                                return;
                        }
                }
@@ -679,7 +679,7 @@ void smtp_rcpt(char *argbuf) {
        valid = validate_recipients(recp);
        if (valid->num_error != 0) {
                cprintf("599 5.1.1 Error: %s\r\n", valid->errormsg);
-               free(valid);
+               free_recipients(valid);
                return;
        }
 
@@ -687,7 +687,7 @@ void smtp_rcpt(char *argbuf) {
                if (CC->logged_in) {
                         if (CtdlCheckInternetMailPermission(&CC->user)==0) {
                                cprintf("551 5.7.1 <%s> - you do not have permission to send Internet mail\r\n", recp);
-                                free(valid);
+                                free_recipients(valid);
                                 return;
                         }
                 }
@@ -697,7 +697,7 @@ void smtp_rcpt(char *argbuf) {
                if ( (SMTP->message_originated_locally == 0)
                   && (SMTP->is_lmtp == 0) ) {
                        cprintf("551 5.7.1 <%s> - relaying denied\r\n", recp);
-                       free(valid);
+                       free_recipients(valid);
                        return;
                }
        }
@@ -709,7 +709,7 @@ void smtp_rcpt(char *argbuf) {
        strcat(SMTP->recipients, recp);
        SMTP->number_of_recipients += 1;
        if (valid != NULL) 
-               free(valid);
+               free_recipients(valid);
 }
 
 
@@ -863,7 +863,7 @@ void smtp_data(void) {
 
        /* Clean up */
        CtdlFreeMessage(msg);
-       free(valid);
+       free_recipients(valid);
        smtp_data_clear();      /* clear out the buffers now */
 }
 
@@ -1543,7 +1543,7 @@ void smtp_do_bounce(char *instr) {
 
                /* Free up the memory we used */
                if (valid != NULL) {
-                       free(valid);
+                       free_recipients(valid);
                }
        }
 
index 49b21360cbb6e09914082e16546a3e8415fb4b6f..cc3e49bd0ad759c3c61f4d642901f3efdb9e93c3 100644 (file)
@@ -1004,7 +1004,7 @@ void check_get(void) {
                        
                        lprintf(CTDL_INFO, "sending 500 REJECT noone here by that name: %s\n", internet_addr);
                }
-               if (rcpt != NULL) free (rcpt);
+               if (rcpt != NULL) free_recipients(rcpt);
        }
 }
 
index aa1330f1030476419db4c95cc054e6d7b8774bfb..a56fddcbeec0b205a9ed08a551e42edfba31548f 100644 (file)
@@ -405,7 +405,7 @@ int CtdlLoginExistingUser(char *trythisname)
                                if (valid->num_local == 1) {
                                        found_user = getuser(&CC->user, valid->recp_local);
                                }
-                               free(valid);
+                               free_recipients(valid);
                        }
                }
        }