#include "html.h"
#include "genstamp.h"
#include "internet_addressing.h"
-#include "serv_fulltext.h"
#include "vcard.h"
#include "euidindex.h"
#include "journaling.h"
#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;
int num_search_msgs = 0;
long *search_msgs = NULL;
regex_t re;
+ int need_to_free_re = 0;
regmatch_t pm;
- if (content_type) if (strlen(content_type) > 0) {
+ if (content_type) if (!IsEmptyStr(content_type)) {
regcomp(&re, content_type, 0);
+ need_to_free_re = 1;
}
/* Learn about the user and room in question */
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. */
}
/* If the caller is looking for a specific MIME type, filter
* out all messages which are not of the type requested.
*/
- if (content_type != NULL) if (strlen(content_type) > 0) {
+ if (content_type != NULL) if (!IsEmptyStr(content_type)) {
/* This call to GetMetaData() sits inside this loop
* so that we only do the extra database read per msg
* over again.
*/
if ( (num_msgs > 0) && (mode == MSGS_SEARCH) && (search_string) ) {
- ft_search(&num_search_msgs, &search_msgs, search_string);
+
+ /* Call search module via hook mechanism.
+ * NULL means use any search function available.
+ * otherwise replace with a char * to name of search routine
+ */
+ CtdlModuleDoSearch(&num_search_msgs, &search_msgs, search_string, "fulltext");
+
if (num_search_msgs > 0) {
int orig_num_msgs;
}
}
free(msglist); /* Clean up */
+ if (need_to_free_re) regfree(&re);
return num_processed;
}
*found_it = 1;
- cprintf("%d %d\n", BINARY_FOLLOWS, length);
+ cprintf("%d %d\n", BINARY_FOLLOWS, (int)length);
client_write(content, length);
}
ma->did_print = 1;
if ( (!strcasecmp(cbtype, "text/plain"))
- || (strlen(cbtype)==0) ) {
+ || (IsEmptyStr(cbtype)) ) {
wptr = content;
if (length > 0) {
client_write(wptr, length);
++add_newline;
}
cprintf("Content-type: %s", cbtype);
- if (strlen(cbcharset) > 0) {
+ if (!IsEmptyStr(cbcharset)) {
cprintf("; charset=%s", cbcharset);
}
cprintf("\nContent-length: %d\n",
(int)(length + add_newline) );
- if (strlen(encoding) > 0) {
+ if (!IsEmptyStr(encoding)) {
cprintf("Content-transfer-encoding: %s\n", encoding);
}
else {
/* Here is the weird form of this command, to process only an
* encapsulated message/rfc822 section.
*/
- if (section) if (strlen(section)>0) if (strcmp(section, "0")) {
+ if (section) if (!IsEmptyStr(section)) if (strcmp(section, "0")) {
memset(&encap, 0, sizeof encap);
safestrncpy(encap.desired_section, section, sizeof encap.desired_section);
mime_parser(TheMessage->cm_fields['M'],
*/
suppress_f = 0;
if (TheMessage->cm_fields['N'] != NULL)
- if (strlen(TheMessage->cm_fields['N']) > 0)
+ if (!IsEmptyStr(TheMessage->cm_fields['N']))
if (haschar(TheMessage->cm_fields['N'], '.') == 0) {
suppress_f = 1;
}
buf[strlen(buf)] = ch;
}
}
- if (strlen(buf) > 0)
+ if (!IsEmptyStr(buf))
cprintf("%s%s", buf, nl);
}
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);
/* No exclusive id? Don't do anything. */
if (msg == NULL) return;
if (msg->cm_fields['E'] == NULL) return;
- if (strlen(msg->cm_fields['E']) == 0) return;
+ if (IsEmptyStr(msg->cm_fields['E'])) return;
/*lprintf(CTDL_DEBUG, "Exclusive ID: <%s> for room <%s>\n",
msg->cm_fields['E'], CC->room.QRname);*/
}
/* ...or if this message is destined for Aide> then go there. */
- if (strlen(force_room) > 0) {
+ if (!IsEmptyStr(force_room)) {
strcpy(actual_rm, force_room);
}
MailboxName(actual_rm, sizeof actual_rm, &userbuf, MAILROOM);
CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0, msg);
BumpNewMailCounter(userbuf.usernum);
- if (strlen(config.c_funambol_host) > 0) {
+ if (!IsEmptyStr(config.c_funambol_host)) {
/* Generate a instruction message for the Funambol notification
* server, in the same style as the SMTP queue
*/
char dest_node[256];
char buf[1024];
struct CtdlMessage *msg;
+ int i;
msg = malloc(sizeof(struct CtdlMessage));
memset(msg, 0, sizeof(struct CtdlMessage));
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 (!IsEmptyStr(my_email)) {
+ 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);
msg->cm_fields['D'] = strdup(dest_node);
}
- if (strlen(my_email) > 0) {
+ if (!IsEmptyStr(my_email)) {
msg->cm_fields['F'] = strdup(my_email);
}
- else if ( (author == &CC->user) && (strlen(CC->cs_inet_email) > 0) ) {
+ else if ( (author == &CC->user) && (!IsEmptyStr(CC->cs_inet_email)) ) {
msg->cm_fields['F'] = strdup(CC->cs_inet_email);
}
/* Now start extracting recipients... */
- while (strlen(recipients) > 0) {
+ while (!IsEmptyStr(recipients)) {
for (i=0; i<=strlen(recipients); ++i) {
if (recipients[i] == '\"') in_quotes = 1 - in_quotes;
if (!strcasecmp(this_recp, "sysop")) {
++ret->num_room;
strcpy(this_recp, config.c_aideroom);
- if (strlen(ret->recp_room) > 0) {
+ if (!IsEmptyStr(ret->recp_room)) {
strcat(ret->recp_room, "|");
}
strcat(ret->recp_room, this_recp);
else if (getuser(&tempUS, this_recp) == 0) {
++ret->num_local;
strcpy(this_recp, tempUS.fullname);
- if (strlen(ret->recp_local) > 0) {
+ if (!IsEmptyStr(ret->recp_local)) {
strcat(ret->recp_local, "|");
}
strcat(ret->recp_local, this_recp);
else if (getuser(&tempUS, this_recp_cooked) == 0) {
++ret->num_local;
strcpy(this_recp, tempUS.fullname);
- if (strlen(ret->recp_local) > 0) {
+ if (!IsEmptyStr(ret->recp_local)) {
strcat(ret->recp_local, "|");
}
strcat(ret->recp_local, this_recp);
else if ( (!strncasecmp(this_recp, "room_", 5))
&& (!getroom(&tempQR, &this_recp_cooked[5])) ) {
++ret->num_room;
- if (strlen(ret->recp_room) > 0) {
+ if (!IsEmptyStr(ret->recp_room)) {
strcat(ret->recp_room, "|");
}
strcat(ret->recp_room, &this_recp_cooked[5]);
* because if the address were valid, we would have
* already translated it to a local address by now.
*/
- if (IsDirectory(this_recp)) {
+ if (IsDirectory(this_recp, 0)) {
++ret->num_error;
invalid = 1;
}
else {
++ret->num_internet;
- if (strlen(ret->recp_internet) > 0) {
+ if (!IsEmptyStr(ret->recp_internet)) {
strcat(ret->recp_internet, "|");
}
strcat(ret->recp_internet, this_recp);
break;
case MES_IGNET:
++ret->num_ignet;
- if (strlen(ret->recp_ignet) > 0) {
+ if (!IsEmptyStr(ret->recp_ignet)) {
strcat(ret->recp_ignet, "|");
}
strcat(ret->recp_ignet, this_recp);
break;
}
if (invalid) {
- if (strlen(ret->errormsg) == 0) {
+ if (IsEmptyStr(ret->errormsg)) {
snprintf(append, sizeof append,
"Invalid recipient: %s",
this_recp);
}
}
else {
- if (strlen(ret->display_recp) == 0) {
+ if (IsEmptyStr(ret->display_recp)) {
strcpy(append, this_recp);
}
else {
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;
/* Check some other permission type things. */
- if (strlen(newusername) == 0) {
+ if (IsEmptyStr(newusername)) {
strcpy(newusername, CC->user.fullname);
}
if ( (CC->user.axlevel < 6)
}
- if (strlen(newuseremail) == 0) {
+ if (IsEmptyStr(newuseremail)) {
newuseremail_ok = 1;
}
- if (strlen(newuseremail) > 0) {
+ if (!IsEmptyStr(newuseremail)) {
if (!strcasecmp(newuseremail, CC->cs_inet_email)) {
newuseremail_ok = 1;
}
- else if (strlen(CC->cs_inet_other_emails) > 0) {
+ else if (!IsEmptyStr(CC->cs_inet_other_emails)) {
j = num_tokens(CC->cs_inet_other_emails, '|');
for (i=0; i<j; ++i) {
extract_token(buf, CC->cs_inet_other_emails, i, '|', sizeof buf);
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, "");
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 : "") );
+ 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);
msg = CtdlMakeMessage(&CC->user, recp, cc,
CC->room.QRname, anonymous, format_type,
newusername, newuseremail, subject,
- ((strlen(supplied_euid) > 0) ? supplied_euid : NULL),
+ ((!IsEmptyStr(supplied_euid)) ? supplied_euid : NULL),
NULL);
/* Put together one big recipients struct containing to/cc/bcc all in
*/
char *all_recps = malloc(SIZ * 3);
strcpy(all_recps, recp);
- if (strlen(cc) > 0) {
- if (strlen(all_recps) > 0) {
+ if (!IsEmptyStr(cc)) {
+ if (!IsEmptyStr(all_recps)) {
strcat(all_recps, ",");
}
strcat(all_recps, cc);
}
- if (strlen(bcc) > 0) {
- if (strlen(all_recps) > 0) {
+ if (!IsEmptyStr(bcc)) {
+ if (!IsEmptyStr(all_recps)) {
strcat(all_recps, ",");
}
strcat(all_recps, bcc);
}
- if (strlen(all_recps) > 0) {
+ if (!IsEmptyStr(all_recps)) {
valid = validate_recipients(all_recps);
}
else {
struct MetaData smi;
regex_t re;
regmatch_t pm;
+ int need_to_free_re = 0;
- if (content_type) if (strlen(content_type) > 0) {
+ if (content_type) if (!IsEmptyStr(content_type)) {
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);
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));
}
}
- if (strlen(content_type) == 0) {
+ if (IsEmptyStr(content_type)) {
delete_this |= 0x02;
} else {
GetMetaData(&smi, msglist[i]);
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);
}
*/
if (smi.meta_refcount == 0) {
lprintf(CTDL_DEBUG, "Deleting message <%ld>\n", msgnum);
-
- /* Remove from fulltext index */
- if (config.c_enable_fulltext) {
- ft_index_message(msgnum, 0);
- }
+
+ /* Call delete hooks with NULL room to show it has gone altogether */
+ PerformDeleteHooks(NULL, msgnum);
/* Remove from message base */
delnum = msgnum;
if (conf != NULL) do {
extract_token(buf, conf, 0, '\n', sizeof buf);
strcpy(conf, &conf[strlen(buf)+1]);
- } while ( (strlen(conf)>0) && (strlen(buf)>0) );
+ } while ( (!IsEmptyStr(conf)) && (!IsEmptyStr(buf)) );
return(conf);
}