From d9f0c753cde3bdc98f536eed77308be9434b3ed5 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Wed, 4 Apr 2007 04:43:21 +0000 Subject: [PATCH] struct recptypes now uses dynamically allocated 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 | 2 +- citadel/journaling.c | 2 +- citadel/msgbase.c | 128 ++++++++++++++++++++++++++-------------- citadel/msgbase.h | 17 ++++-- citadel/serv_calendar.c | 12 ++-- citadel/serv_network.c | 10 ++-- citadel/serv_sieve.c | 6 +- citadel/serv_smtp.c | 18 +++--- citadel/serv_vcard.c | 2 +- citadel/user_ops.c | 2 +- 10 files changed, 123 insertions(+), 76 deletions(-) diff --git a/citadel/imap_acl.c b/citadel/imap_acl.c index fdda833bb..204b54739 100644 --- a/citadel/imap_acl.c +++ b/citadel/imap_acl.c @@ -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", diff --git a/citadel/journaling.c b/citadel/journaling.c index 7febabd0a..c30c5d63a 100644 --- a/citadel/journaling.c +++ b/citadel/journaling.c @@ -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. */ diff --git a/citadel/msgbase.c b/citadel/msgbase.c index c76c7fa8b..5161bef7d 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -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; ierrormsg) + 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; inum_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); } diff --git a/citadel/msgbase.h b/citadel/msgbase.h index 1e0616bbb..6a6f5e109 100644 --- a/citadel/msgbase.h +++ b/citadel/msgbase.h @@ -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 */ diff --git a/citadel/serv_calendar.c b/citadel/serv_calendar.c index ec3f6f990..91570069c 100644 --- a/citadel/serv_calendar.c +++ b/citadel/serv_calendar.c @@ -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); diff --git a/citadel/serv_network.c b/citadel/serv_network.c index 09f4ec321..930dae785 100644 --- a/citadel/serv_network.c +++ b/citadel/serv_network.c @@ -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); } diff --git a/citadel/serv_sieve.c b/citadel/serv_sieve.c index 7ea3aa28c..e8277d697 100644 --- a/citadel/serv_sieve.c +++ b/citadel/serv_sieve.c @@ -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; } diff --git a/citadel/serv_smtp.c b/citadel/serv_smtp.c index a3bcd4b66..21934d256 100644 --- a/citadel/serv_smtp.c +++ b/citadel/serv_smtp.c @@ -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); } } diff --git a/citadel/serv_vcard.c b/citadel/serv_vcard.c index 49b21360c..cc3e49bd0 100644 --- a/citadel/serv_vcard.c +++ b/citadel/serv_vcard.c @@ -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); } } diff --git a/citadel/user_ops.c b/citadel/user_ops.c index aa1330f10..a56fddcbe 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -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); } } } -- 2.30.2