#include "internet_addressing.h"
#include "serv_fulltext.h"
#include "vcard.h"
+#include "euidindex.h"
long config_msgnum;
-
+struct addresses_to_be_filed *atbf = NULL;
/*
* This really belongs in serv_network.c, but I don't know how to export
* Save a message pointer into a specified room
* (Returns 0 for success, nonzero for failure)
* roomname may be NULL to use the current room
+ *
+ * Note that the 'supplied_msg' field may be set to NULL, in which case
+ * the message will be fetched from disk, by number, if we need to perform
+ * replication checks. This adds an additional database read, so if the
+ * caller already has the message in memory then it should be supplied.
*/
-int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags) {
+int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int do_repl_check,
+ struct CtdlMessage *supplied_msg) {
int i;
char hold_rm[ROOMNAMELEN];
struct cdbdata *cdbfr;
long highest_msg = 0L;
struct CtdlMessage *msg = NULL;
- lprintf(CTDL_DEBUG, "CtdlSaveMsgPointerInRoom(%s, %ld, %d)\n",
- roomname, msgid, flags);
+ lprintf(CTDL_DEBUG, "CtdlSaveMsgPointerInRoom(roomname=%s, msgid=%ld, do_repl_check=%d)\n",
+ roomname, msgid, do_repl_check);
strcpy(hold_rm, CC->room.QRname);
/* We may need to check to see if this message is real */
- if ( (flags & SM_VERIFY_GOODNESS)
- || (flags & SM_DO_REPL_CHECK)
- ) {
- msg = CtdlFetchMessage(msgid, 1);
+ if (do_repl_check) {
+ if (supplied_msg != NULL) {
+ msg = supplied_msg;
+ }
+ else {
+ msg = CtdlFetchMessage(msgid, 0);
+ }
if (msg == NULL) return(ERROR + ILLEGAL_VALUE);
}
/* Perform replication checks if necessary */
- if ( (flags & SM_DO_REPL_CHECK) && (msg != NULL) ) {
+ if ( (do_repl_check) && (msg != NULL) ) {
if (getroom(&CC->room,
((roomname != NULL) ? roomname : CC->room.QRname) )
!= 0) {
lprintf(CTDL_ERR, "No such room <%s>\n", roomname);
- if (msg != NULL) CtdlFreeMessage(msg);
+ if ( (msg != NULL) && (msg != supplied_msg) ) CtdlFreeMessage(msg);
return(ERROR + ROOM_NOT_FOUND);
}
- if (ReplicationChecks(msg) != 0) {
- getroom(&CC->room, hold_rm);
- if (msg != NULL) CtdlFreeMessage(msg);
- lprintf(CTDL_DEBUG,
- "Did replication, and newer exists\n");
- return(0);
- }
+ ReplicationChecks(msg);
}
/* Now the regular stuff */
((roomname != NULL) ? roomname : CC->room.QRname) )
!= 0) {
lprintf(CTDL_ERR, "No such room <%s>\n", roomname);
- if (msg != NULL) CtdlFreeMessage(msg);
+ if ( (msg != NULL) && (msg != supplied_msg) ) CtdlFreeMessage(msg);
return(ERROR + ROOM_NOT_FOUND);
}
if (msglist[i] == msgid) {
lputroom(&CC->room); /* unlock the room */
getroom(&CC->room, hold_rm);
- if (msg != NULL) CtdlFreeMessage(msg);
+ if ( (msg != NULL) && (msg != supplied_msg) ) CtdlFreeMessage(msg);
free(msglist);
return(ERROR + ALREADY_EXISTS);
}
getroom(&CC->room, hold_rm);
/* Bump the reference count for this message. */
- if ((flags & SM_DONT_BUMP_REF)==0) {
- AdjRefCount(msgid, +1);
+ AdjRefCount(msgid, +1);
+
+ /* If the message has an Exclusive ID, index that... */
+ if (msg != NULL) {
+ if (msg->cm_fields['E'] != NULL) {
+ index_message_by_euid(msg->cm_fields['E'], &CC->room, msgid);
+ }
}
/* Return success. */
- if (msg != NULL) CtdlFreeMessage(msg);
+ if ( (msg != NULL) && (msg != supplied_msg) ) CtdlFreeMessage(msg);
return (0);
}
/*
- * Back end for the ReplicationChecks() function
+ * Check to see if any messages already exist in the current room which
+ * carry the same Exclusive ID as this one. If any are found, delete them.
*/
-void check_repl(long msgnum, void *userdata) {
- lprintf(CTDL_DEBUG, "check_repl() replacing message %ld\n", msgnum);
- CtdlDeleteMessages(CC->room.QRname, msgnum, "", 0);
-}
-
-
-/*
- * Check to see if any messages already exist which carry the same Exclusive ID
- * as this one. If any are found, delete them.
- *
- */
-int ReplicationChecks(struct CtdlMessage *msg) {
- struct CtdlMessage *template;
- int abort_this = 0;
+void ReplicationChecks(struct CtdlMessage *msg) {
+ long old_msgnum = (-1L);
/* No exclusive id? Don't do anything. */
- if (msg->cm_fields['E'] == NULL) return 0;
- if (strlen(msg->cm_fields['E']) == 0) return 0;
+ if (msg == NULL) return;
+ if (msg->cm_fields['E'] == NULL) return;
+ if (strlen(msg->cm_fields['E']) == 0) return;
lprintf(CTDL_DEBUG, "Exclusive ID: <%s>\n", msg->cm_fields['E']);
- template = (struct CtdlMessage *) malloc(sizeof(struct CtdlMessage));
- memset(template, 0, sizeof(struct CtdlMessage));
- template->cm_fields['E'] = strdup(msg->cm_fields['E']);
-
- CtdlForEachMessage(MSGS_ALL, 0L, NULL, template, check_repl, NULL);
-
- CtdlFreeMessage(template);
- lprintf(CTDL_DEBUG, "ReplicationChecks() returning %d\n", abort_this);
- return(abort_this);
-}
-
-
-
-/*
- * Turn an arbitrary RFC822 address into a struct vCard for possible
- * inclusion into an address book.
- */
-struct vCard *vcard_new_from_rfc822_addr(char *addr) {
- struct vCard *v;
- char user[256], node[256], name[256], email[256], n[256], uid[256];
- int i;
-
- v = vcard_new();
- if (v == NULL) return(NULL);
-
- process_rfc822_addr(addr, user, node, name);
- vcard_set_prop(v, "fn", name, 0);
-
- vcard_fn_to_n(n, name, sizeof n);
- vcard_set_prop(v, "n", n, 0);
-
- snprintf(email, sizeof email, "%s@%s", user, node);
- vcard_set_prop(v, "email;internet", email, 0);
-
- snprintf(uid, sizeof uid, "collected: %s %s@%s", name, user, node);
- for (i=0; i<strlen(uid); ++i) {
- if (isspace(uid[i])) uid[i] = '_';
- uid[i] = tolower(uid[i]);
+ old_msgnum = locate_message_by_euid(msg->cm_fields['E'], &CC->room);
+ if (old_msgnum > 0L) {
+ lprintf(CTDL_DEBUG, "ReplicationChecks() replacing message %ld\n", old_msgnum);
+ CtdlDeleteMessages(CC->room.QRname, old_msgnum, "", 0);
}
- vcard_set_prop(v, "UID", uid, 0);
-
- return(v);
}
+
/*
* Save a message to disk and submit it into the delivery system.
*/
FILE *network_fp = NULL;
static int seqnum = 1;
struct CtdlMessage *imsg = NULL;
- struct CtdlMessage *vmsg = NULL;
- long vmsgnum = (-1L);
- char *ser = NULL;
- struct vCard *v = NULL;
char *instr;
struct ser_ret smr;
char *hold_R, *hold_D;
char *collected_addresses = NULL;
+ struct addresses_to_be_filed *aptr = NULL;
lprintf(CTDL_DEBUG, "CtdlSubmitMsg() called\n");
if (is_valid_message(msg) == 0) return(-1); /* self check */
/* If this message has an Exclusive ID, perform replication checks */
lprintf(CTDL_DEBUG, "Performing replication checks\n");
- if (ReplicationChecks(msg) > 0) return(-4);
+ ReplicationChecks(msg);
/* Save it to disk */
lprintf(CTDL_DEBUG, "Saving to disk\n");
* is no local sender; it would otherwise go to the Trashcan).
*/
if ((!CC->internal_pgm) || (recps == NULL)) {
- if (CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0) != 0) {
+ if (CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 1, msg) != 0) {
lprintf(CTDL_ERR, "ERROR saving message pointer!\n");
- CtdlSaveMsgPointerInRoom(config.c_aideroom,
- newmsgid, 0);
+ CtdlSaveMsgPointerInRoom(config.c_aideroom, newmsgid, 0, msg);
}
}
/* For internet mail, drop a copy in the outbound queue room */
if (recps != NULL)
if (recps->num_internet > 0) {
- CtdlSaveMsgPointerInRoom(SMTP_SPOOLOUT_ROOM, newmsgid, 0);
+ CtdlSaveMsgPointerInRoom(SMTP_SPOOLOUT_ROOM, newmsgid, 0, msg);
}
/* If other rooms are specified, drop them there too. */
extract_token(recipient, recps->recp_room, i,
'|', sizeof recipient);
lprintf(CTDL_DEBUG, "Delivering to room <%s>\n", recipient);
- CtdlSaveMsgPointerInRoom(recipient, newmsgid, 0);
+ CtdlSaveMsgPointerInRoom(recipient, newmsgid, 0, msg);
}
/* Bump this user's messages posted counter. */
if (getuser(&userbuf, recipient) == 0) {
MailboxName(actual_rm, sizeof actual_rm,
&userbuf, MAILROOM);
- CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0);
+ CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0, msg);
BumpNewMailCounter(userbuf.usernum);
}
else {
lprintf(CTDL_DEBUG, "No user <%s>\n", recipient);
- CtdlSaveMsgPointerInRoom(config.c_aideroom,
- newmsgid, 0);
+ CtdlSaveMsgPointerInRoom(config.c_aideroom, newmsgid, 0, msg);
}
}
/*
* Any addresses to harvest for someone's address book?
- * (Don't do this if this is not a message with recipients, otherwise we will
- * send this function into infinite recursion!!!!!)
- * FIXME do this differently
*/
if ( (CC->logged_in) && (recps != NULL) ) {
collected_addresses = harvest_collected_addresses(msg);
}
if (collected_addresses != NULL) {
- for (i=0; i<num_tokens(collected_addresses, ','); ++i) {
-
- /* Make a vCard out of each address */
- extract_token(recipient, collected_addresses, i, ',', sizeof recipient);
- striplt(recipient);
- v = vcard_new_from_rfc822_addr(recipient);
- if (v != NULL) {
- vmsg = malloc(sizeof(struct CtdlMessage));
- memset(vmsg, 0, sizeof(struct CtdlMessage));
- vmsg->cm_magic = CTDLMESSAGE_MAGIC;
- vmsg->cm_anon_type = MES_NORMAL;
- vmsg->cm_format_type = FMT_RFC822;
- vmsg->cm_fields['A'] = strdup("Citadel");
- vmsg->cm_fields['E'] = strdup(vcard_get_prop(v, "UID", 0, 0, 0));
- ser = vcard_serialize(v);
- if (ser != NULL) {
- vmsg->cm_fields['M'] = malloc(strlen(ser) + 1024);
- sprintf(vmsg->cm_fields['M'],
- "Content-type: text/x-vcard"
- "\r\n\r\n%s\r\n", ser);
- free(ser);
- }
- vcard_free(v);
-
- lprintf(CTDL_DEBUG, "Adding contact: %s\n", recipient);
- MailboxName(actual_rm, sizeof actual_rm, &CC->user, USERCONTACTSROOM);
- vmsgnum = CtdlSubmitMsg(vmsg, NULL, actual_rm);
- CtdlFreeMessage(vmsg);
- }
- }
- free(collected_addresses);
+ begin_critical_section(S_ATBF);
+ aptr = (struct addresses_to_be_filed *) malloc(sizeof(struct addresses_to_be_filed));
+ aptr->next = atbf;
+ MailboxName(actual_rm, sizeof actual_rm, &CC->user, USERCONTACTSROOM);
+ aptr->roomname = strdup(actual_rm);
+ aptr->collected_addresses = collected_addresses;
+ atbf = aptr;
+ end_critical_section(S_ATBF);
}
return(newmsgid);
}
int CtdlCopyMsgToRoom(long msgnum, char *dest) {
int err;
- err = CtdlSaveMsgPointerInRoom(dest, msgnum,
- (SM_VERIFY_GOODNESS | SM_DO_REPL_CHECK) );
+ err = CtdlSaveMsgPointerInRoom(dest, msgnum, 1, NULL);
if (err != 0) return(err);
return(0);