X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmsgbase.c;h=e110a11e90b9a21319f0024493cfa07998caadd0;hb=2345c71f8c52251f37ee07f881419629dd2a4620;hp=f8a9791b50ef55fd50a8950f39617a78fd519815;hpb=9590fb796e361392256ff255d6ba2ffff10751a3;p=citadel.git diff --git a/citadel/msgbase.c b/citadel/msgbase.c index f8a9791b5..e110a11e9 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "citadel.h" #include "server.h" #include "serv_extensions.h" @@ -54,9 +56,6 @@ #include "citadel_dirs.h" #include "serv_network.h" -#ifdef HAVE_LIBSIEVE -# include "serv_sieve.h" -#endif /* HAVE_LIBSIEVE */ long config_msgnum; struct addresses_to_be_filed *atbf = NULL; @@ -148,6 +147,9 @@ int alias(char *name) char testnode[64]; char buf[SIZ]; + char original_name[256]; + safestrncpy(original_name, name, sizeof original_name); + striplt(name); remove_any_whitespace_to_the_left_or_right_of_at_symbol(name); stripallbut(name, '<', '>'); @@ -182,7 +184,9 @@ int alias(char *name) strcpy(name, aaa); } - lprintf(CTDL_INFO, "Mail is being forwarded to %s\n", name); + if (strcasecmp(original_name, name)) { + lprintf(CTDL_INFO, "%s is being forwarded to %s\n", original_name, name); + } /* Change "user @ xxx" to "user" if xxx is an alias for this host */ for (a=0; a 0) { + regcomp(&re, content_type, 0); + need_to_free_re = 1; + } /* Learn about the user and room in question */ getuser(&CC->user, CC->curr_user); @@ -535,6 +547,7 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, num_msgs = cdbfr->len / sizeof(long); cdb_free(cdbfr); } else { + if (need_to_free_re) regfree(&re); return 0; /* No messages at all? No further action. */ } @@ -560,7 +573,8 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, */ GetMetaData(&smi, msglist[a]); - if (strcasecmp(smi.meta_content_type, content_type)) { + /* if (strcasecmp(smi.meta_content_type, content_type)) { old non-regex way */ + if (regexec(&re, smi.meta_content_type, 1, &pm, 0) != 0) { msglist[a] = 0L; } } @@ -662,6 +676,7 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, } } free(msglist); /* Clean up */ + if (need_to_free_re) regfree(&re); return num_processed; } @@ -978,7 +993,7 @@ void mime_spew_section(char *name, char *filename, char *partnum, char *disp, *found_it = 1; - cprintf("%d %d\n", BINARY_FOLLOWS, length); + cprintf("%d %d\n", BINARY_FOLLOWS, (int)length); client_write(content, length); } @@ -1248,7 +1263,6 @@ void choose_preferred(char *name, char *filename, char *partnum, char *disp, if (ma->is_ma > 0) { for (i=0; ipreferred_formats, '|'); ++i) { extract_token(buf, CC->preferred_formats, i, '|', sizeof buf); - lprintf(CTDL_DEBUG, "Is <%s> == <%s> ??\n", buf, cbtype); if ( (!strcasecmp(buf, cbtype)) && (!ma->freeze) ) { if (i < ma->chosen_pref) { safestrncpy(ma->chosen_part, partnum, sizeof ma->chosen_part); @@ -1289,7 +1303,6 @@ void output_preferred(char *name, char *filename, char *partnum, char *disp, if (text_content[length-1] != '\n') { ++add_newline; } - cprintf("Content-type: %s", cbtype); if (strlen(cbcharset) > 0) { cprintf("; charset=%s", cbcharset); @@ -1302,6 +1315,7 @@ void output_preferred(char *name, char *filename, char *partnum, char *disp, else { cprintf("Content-transfer-encoding: 7bit\n"); } + cprintf("X-Citadel-MSG4-Partnum: %s\n", partnum); cprintf("\n"); client_write(content, length); if (add_newline) cprintf("\n"); @@ -2126,15 +2140,8 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms lprintf(CTDL_DEBUG, "CtdlSaveMsgPointerInRoom() skips repl checks\n"); } - /* Submit this room for net processing */ - network_queue_room(&CC->room, NULL); - -#ifdef HAVE_LIBSIEVE - /* If this is someone's inbox, submit the room for sieve processing */ - if (!strcasecmp(&CC->room.QRname[11], MAILROOM)) { - sieve_queue_room(&CC->room); - } -#endif /* HAVE_LIBSIEVE */ + /* Submit this room for processing by hooks */ + PerformRoomHooks(&CC->room); /* Go back to the room we were in before we wandered here... */ getroom(&CC->room, hold_rm); @@ -2349,7 +2356,8 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ FILE *network_fp = NULL; static int seqnum = 1; struct CtdlMessage *imsg = NULL; - char *instr; + char *instr = NULL; + size_t instr_alloc = 0; struct ser_ret smr; char *hold_R, *hold_D; char *collected_addresses = NULL; @@ -2406,10 +2414,10 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ break; case 4: strcpy(content_type, "text/plain"); - mptr = bmstrcasestr(msg->cm_fields['M'], "Content-type: "); + mptr = bmstrcasestr(msg->cm_fields['M'], "Content-type:"); if (mptr != NULL) { - safestrncpy(content_type, &mptr[14], - sizeof content_type); + safestrncpy(content_type, &mptr[13], sizeof content_type); + striplt(content_type); for (a = 0; a < strlen(content_type); ++a) { if ((content_type[a] == ';') || (content_type[a] == ' ') @@ -2559,15 +2567,16 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ if (getuser(&userbuf, recipient) == 0) { // Add a flag so the Funambol module knows its mail msg->cm_fields['W'] = strdup(recipient); - MailboxName(actual_rm, sizeof actual_rm, - &userbuf, MAILROOM); + MailboxName(actual_rm, sizeof actual_rm, &userbuf, MAILROOM); CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0, msg); BumpNewMailCounter(userbuf.usernum); if (strlen(config.c_funambol_host) > 0) { /* Generate a instruction message for the Funambol notification - server, in the same style as the SMTP queue */ - instr = malloc(SIZ * 2); - snprintf(instr, SIZ * 2, + * server, in the same style as the SMTP queue + */ + instr_alloc = 1024; + instr = malloc(instr_alloc); + snprintf(instr, instr_alloc, "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" "bounceto|%s@%s\n", SPOOLMIME, newmsgid, (long)time(NULL), @@ -2581,7 +2590,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ imsg->cm_format_type = FMT_RFC822; imsg->cm_fields['A'] = strdup("Citadel"); imsg->cm_fields['J'] = strdup("do not journal"); - imsg->cm_fields['M'] = instr; + imsg->cm_fields['M'] = instr; /* imsg owns this memory now */ imsg->cm_fields['W'] = strdup(recipient); CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM); CtdlFreeMessage(imsg); @@ -2642,7 +2651,6 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* Go back to the room we started from */ lprintf(CTDL_DEBUG, "Returning to original room %s\n", hold_rm); if (strcasecmp(hold_rm, CC->room.QRname)) - /* getroom(&CC->room, hold_rm); */ usergoto(hold_rm, 0, 1, NULL, NULL); /* For internet mail, generate delivery instructions. @@ -2653,8 +2661,9 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ if (recps != NULL) if (recps->num_internet > 0) { lprintf(CTDL_DEBUG, "Generating delivery instructions\n"); - instr = malloc(SIZ * 2); - snprintf(instr, SIZ * 2, + instr_alloc = 1024; + instr = malloc(instr_alloc); + snprintf(instr, instr_alloc, "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" "bounceto|%s@%s\n", SPOOLMIME, newmsgid, (long)time(NULL), @@ -2663,10 +2672,12 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ for (i=0; irecp_internet, '|'); ++i) { size_t tmp = strlen(instr); - extract_token(recipient, recps->recp_internet, - i, '|', sizeof recipient); - snprintf(&instr[tmp], SIZ * 2 - tmp, - "remote|%s|0||\n", recipient); + extract_token(recipient, recps->recp_internet, i, '|', sizeof recipient); + if ((tmp + strlen(recipient) + 32) > instr_alloc) { + instr_alloc = instr_alloc * 2; + instr = realloc(instr, instr_alloc); + } + snprintf(&instr[tmp], instr_alloc - tmp, "remote|%s|0||\n", recipient); } imsg = malloc(sizeof(struct CtdlMessage)); @@ -2676,7 +2687,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ imsg->cm_format_type = FMT_RFC822; imsg->cm_fields['A'] = strdup("Citadel"); imsg->cm_fields['J'] = strdup("do not journal"); - imsg->cm_fields['M'] = instr; + imsg->cm_fields['M'] = instr; /* imsg owns this memory now */ CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM); CtdlFreeMessage(imsg); } @@ -2783,7 +2794,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); } @@ -2902,6 +2913,7 @@ struct CtdlMessage *CtdlMakeMessage( 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 */ @@ -2909,6 +2921,7 @@ struct CtdlMessage *CtdlMakeMessage( char dest_node[256]; char buf[1024]; struct CtdlMessage *msg; + int i; msg = malloc(sizeof(struct CtdlMessage)); memset(msg, 0, sizeof(struct CtdlMessage)); @@ -2922,8 +2935,21 @@ struct CtdlMessage *CtdlMakeMessage( striplt(recipient); striplt(recp_cc); - snprintf(buf, sizeof buf, "cit%ld", author->usernum); /* Path */ - msg->cm_fields['P'] = strdup(buf); + /* Path or Return-Path */ + if (my_email == NULL) my_email = ""; + + if (strlen(my_email) > 0) { + msg->cm_fields['P'] = strdup(my_email); + } + else { + snprintf(buf, sizeof buf, "%s", author->fullname); + msg->cm_fields['P'] = strdup(buf); + } + for (i=0; (msg->cm_fields['P'][i]!=0); ++i) { + if (isspace(msg->cm_fields['P'][i])) { + msg->cm_fields['P'][i] = '_'; + } + } snprintf(buf, sizeof buf, "%ld", (long)time(NULL)); /* timestamp */ msg->cm_fields['T'] = strdup(buf); @@ -2953,7 +2979,10 @@ struct CtdlMessage *CtdlMakeMessage( msg->cm_fields['D'] = strdup(dest_node); } - if ( (author == &CC->user) && (strlen(CC->cs_inet_email) > 0) ) { + if (strlen(my_email) > 0) { + msg->cm_fields['F'] = strdup(my_email); + } + else if ( (author == &CC->user) && (strlen(CC->cs_inet_email) > 0) ) { msg->cm_fields['F'] = strdup(CC->cs_inet_email); } @@ -3051,13 +3080,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]; @@ -3072,21 +3103,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; inum_error; invalid = 1; } @@ -3205,8 +3253,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); @@ -3217,8 +3264,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); @@ -3239,10 +3285,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) @@ -3257,6 +3328,7 @@ void cmd_ent0(char *entargs) int anon_flag = 0; int format_type = 0; char newusername[256]; + char newuseremail[256]; struct CtdlMessage *msg; int anonymous = 0; char errmsg[SIZ]; @@ -3266,8 +3338,12 @@ void cmd_ent0(char *entargs) struct recptypes *valid_cc = NULL; struct recptypes *valid_bcc = NULL; char subject[SIZ]; + int subject_required = 0; int do_confirm = 0; long msgnum; + int i, j; + char buf[256]; + int newuseremail_ok = 0; unbuffer_output(); @@ -3289,17 +3365,22 @@ void cmd_ent0(char *entargs) supplied_euid[0] = 0; break; } + extract_token(newuseremail, entargs, 10, '|', sizeof newuseremail); /* first check to make sure the request is valid. */ err = CtdlDoIHavePermissionToPostInThisRoom(errmsg, sizeof errmsg); - if (err) { + if (err) + { cprintf("%d %s\n", err, errmsg); return; } /* Check some other permission type things. */ + if (strlen(newusername) == 0) { + strcpy(newusername, CC->user.fullname); + } if ( (CC->user.axlevel < 6) && (strcasecmp(newusername, CC->user.fullname)) && (strcasecmp(newusername, CC->cs_inet_fn)) @@ -3311,15 +3392,45 @@ void cmd_ent0(char *entargs) return; } + + if (strlen(newuseremail) == 0) { + newuseremail_ok = 1; + } + + if (strlen(newuseremail) > 0) { + if (!strcasecmp(newuseremail, CC->cs_inet_email)) { + newuseremail_ok = 1; + } + else if (strlen(CC->cs_inet_other_emails) > 0) { + j = num_tokens(CC->cs_inet_other_emails, '|'); + for (i=0; ics_inet_other_emails, i, '|', sizeof buf); + if (!strcasecmp(newuseremail, buf)) { + newuseremail_ok = 1; + } + } + } + } + + if (!newuseremail_ok) { + cprintf("%d You don't have permission to author messages as '%s'.\n", + ERROR + HIGHER_ACCESS_REQUIRED, + newuseremail + ); + return; + } + CC->cs_flags |= CS_POSTING; - /* In the Mail> room we have to behave a little differently -- + /* In mailbox rooms we have to behave a little differently -- * make sure the user has specified at least one recipient. Then - * validate the recipient(s). + * validate the recipient(s). We do this for the Mail> room, as + * well as any room which has the "Mailbox" view set. */ - if ( (CC->room.QRflags & QR_MAILBOX) - && (!strcasecmp(&CC->room.QRname[11], MAILROOM)) ) { + if ( ( (CC->room.QRflags & QR_MAILBOX) && (!strcasecmp(&CC->room.QRname[11], MAILROOM)) ) + || ( (CC->room.QRflags & QR_MAILBOX) && (CC->curr_view == VIEW_MAILBOX) ) + ) { if (CC->user.axlevel < 2) { strcpy(recp, "sysop"); strcpy(cc, ""); @@ -3329,32 +3440,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; } @@ -3364,9 +3475,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; } } @@ -3375,9 +3486,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; } @@ -3387,9 +3498,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; } @@ -3410,22 +3521,32 @@ void cmd_ent0(char *entargs) recp[0] = 0; } + /* Recommend to the client that the use of a message subject is + * strongly recommended in this room, if either the SUBJECTREQ flag + * is set, or if there is one or more Internet email recipients. + */ + if (CC->room.QRflags2 & QR2_SUBJECTREQ) subject_required = 1; + if (valid_to) if (valid_to->num_internet > 0) subject_required = 1; + if (valid_cc) if (valid_cc->num_internet > 0) subject_required = 1; + if (valid_bcc) if (valid_bcc->num_internet > 0) subject_required = 1; + /* If we're only checking the validity of the request, return * success without creating the message. */ 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); + cprintf("%d %s|%d\n", CIT_OK, + ((valid_to != NULL) ? valid_to->display_recp : ""), + subject_required); + 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) { @@ -3436,7 +3557,7 @@ void cmd_ent0(char *entargs) msg = CtdlMakeMessage(&CC->user, recp, cc, CC->room.QRname, anonymous, format_type, - newusername, subject, + newusername, newuseremail, subject, ((strlen(supplied_euid) > 0) ? supplied_euid : NULL), NULL); @@ -3487,7 +3608,7 @@ void cmd_ent0(char *entargs) CtdlFreeMessage(msg); } if (valid != NULL) { - free(valid); + free_recipients(valid); } return; } @@ -3501,10 +3622,9 @@ void cmd_ent0(char *entargs) int CtdlDeleteMessages(char *room_name, /* which room */ long *dmsgnums, /* array of msg numbers to be deleted */ int num_dmsgnums, /* number of msgs to be deleted, or 0 for "any" */ - char *content_type /* or "" for any */ + char *content_type /* or "" for any. regular expressions expected. */ ) { - struct ctdlroom qrbuf; struct cdbdata *cdbfr; long *msglist = NULL; @@ -3514,7 +3634,14 @@ int CtdlDeleteMessages(char *room_name, /* which room */ int num_deleted = 0; int delete_this; struct MetaData smi; + regex_t re; + regmatch_t pm; + int need_to_free_re = 0; + if (content_type) if (strlen(content_type) > 0) { + regcomp(&re, content_type, 0); + need_to_free_re = 1; + } lprintf(CTDL_DEBUG, "CtdlDeleteMessages(%s, %d msgs, %s)\n", room_name, num_dmsgnums, content_type); @@ -3522,6 +3649,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ if (lgetroom(&qrbuf, room_name) != 0) { lprintf(CTDL_ERR, "CtdlDeleteMessages(): Room <%s> not found\n", room_name); + if (need_to_free_re) regfree(&re); return (0); /* room not found */ } cdbfr = cdb_fetch(CDB_MSGLISTS, &qrbuf.QRnumber, sizeof(long)); @@ -3557,8 +3685,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ delete_this |= 0x02; } else { GetMetaData(&smi, msglist[i]); - if (!strcasecmp(smi.meta_content_type, - content_type)) { + if (regexec(&re, smi.meta_content_type, 1, &pm, 0) == 0) { delete_this |= 0x02; } } @@ -3595,6 +3722,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ if (msglist != NULL) free(msglist); if (dellist != NULL) free(dellist); lprintf(CTDL_DEBUG, "%d message(s) deleted.\n", num_deleted); + if (need_to_free_re) regfree(&re); return (num_deleted); } @@ -3734,6 +3862,9 @@ void cmd_move(char *args) && (!(CC->room.QRflags & QR_MAILBOX)) && (qtemp.QRflags & QR_MAILBOX)) permit = 1; + /* Permit message removal from collaborative delete rooms */ + if (CC->room.QRflags2 & QR2_COLLABDEL) permit = 1; + /* User must have access to target room */ if (!(ra & UA_KNOWN)) permit = 0; @@ -4171,19 +4302,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); }