#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;
+/*
+ * Callback function for mime parser that outputs a section all at once
+ */
+void mime_spew_section(char *name, char *filename, char *partnum, char *disp,
+ void *content, char *cbtype, char *cbcharset, size_t length,
+ char *encoding, void *cbuserdata)
+{
+ int *found_it = (int *)cbuserdata;
+
+ /* ...or if this is not the desired section */
+ if (strcasecmp(CC->download_desired_section, partnum))
+ return;
+
+ *found_it = 1;
+
+ cprintf("%d %d\n", BINARY_FOLLOWS, length);
+ client_write(content, length);
+}
+
+
+
/*
* Load a message from disk into memory.
* This is used by CtdlOutputMsg() and other fetch functions.
* The client is elegant and sophisticated and wants to be choosy about
* MIME content types, so figure out which multipart/alternative part
* we're going to send.
+ *
+ * We use a system of weights. When we find a part that matches one of the
+ * MIME types we've declared as preferential, we can store it in ma->chosen_part
+ * and then set ma->chosen_pref to that MIME type's position in our preference
+ * list. If we then hit another match, we only replace the first match if
+ * the preference value is lower.
*/
void choose_preferred(char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length,
if (ma->is_ma > 0) {
for (i=0; i<num_tokens(CC->preferred_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) ) {
- safestrncpy(ma->chosen_part, partnum, sizeof ma->chosen_part);
+ if (i < ma->chosen_pref) {
+ safestrncpy(ma->chosen_part, partnum, sizeof ma->chosen_part);
+ ma->chosen_pref = i;
+ }
}
}
}
return((CC->download_fp != NULL) ? om_ok : om_mime_error);
}
+ /* MT_SPEW_SECTION is like MT_DOWNLOAD except it outputs the whole MIME part
+ * in a single server operation instead of opening a download file.
+ */
+ if (mode == MT_SPEW_SECTION) {
+ if (TheMessage->cm_format_type != FMT_RFC822) {
+ if (do_proto)
+ cprintf("%d This is not a MIME message.\n",
+ ERROR + ILLEGAL_VALUE);
+ } else {
+ /* Parse the message text component */
+ int found_it = 0;
+
+ mptr = TheMessage->cm_fields['M'];
+ mime_parser(mptr, NULL, *mime_spew_section, NULL, NULL, (void *)&found_it, 0);
+ /* If section wasn't found, print an error
+ */
+ if (!found_it) {
+ if (do_proto) cprintf(
+ "%d Section %s not found.\n",
+ ERROR + FILE_NOT_FOUND,
+ CC->download_desired_section);
+ }
+ }
+ return((CC->download_fp != NULL) ? om_ok : om_mime_error);
+ }
+
/* now for the user-mode message reading loops */
if (do_proto) cprintf("%d msg:\n", LISTING_FOLLOWS);
else if (i == 'Y') {
cprintf("CC: %s%s", mptr, nl);
}
+ else if (i == 'P') {
+ cprintf("Return-Path: %s%s", mptr, nl);
+ }
+ else if (i == 'V') {
+ cprintf("Envelope-To: %s%s", mptr, nl);
+ }
else if (i == 'U') {
cprintf("Subject: %s%s", mptr, nl);
subject_found = 1;
if (mode == MT_MIME) {
ma.use_fo_hooks = 0;
strcpy(ma.chosen_part, "1");
+ ma.chosen_pref = 9999;
mime_parser(mptr, NULL,
*choose_preferred, *fixed_output_pre,
*fixed_output_post, (void *)&ma, 0);
CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1, NULL);
}
+
+/*
+ * Open a component of a MIME message and transmit it all at once
+ */
+void cmd_dlat(char *cmdbuf)
+{
+ long msgid;
+ char desired_section[128];
+
+ msgid = extract_long(cmdbuf, 0);
+ extract_token(desired_section, cmdbuf, 1, '|', sizeof desired_section);
+ safestrncpy(CC->download_desired_section, desired_section,
+ sizeof CC->download_desired_section);
+ CtdlOutputMsg(msgid, MT_SPEW_SECTION, 0, 1, 1, NULL);
+}
+
+
/*
* Save one or more message pointers into a specified room
* (Returns 0 for success, nonzero for failure)
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 */
+
/* Go back to the room we were in before we wandered here... */
getroom(&CC->room, hold_rm);
/*
* Convenience function for generating small administrative messages.
*/
-void quickie_message(char *from, char *to, char *room, char *text,
+void quickie_message(char *from, char *fromaddr, char *to, char *room, char *text,
int format_type, char *subject)
{
struct CtdlMessage *msg;
msg->cm_magic = CTDLMESSAGE_MAGIC;
msg->cm_anon_type = MES_NORMAL;
msg->cm_format_type = format_type;
- msg->cm_fields['A'] = strdup(from);
+
+ if (from != NULL) {
+ msg->cm_fields['A'] = strdup(from);
+ }
+ else if (fromaddr != NULL) {
+ msg->cm_fields['A'] = strdup(fromaddr);
+ if (strchr(msg->cm_fields['A'], '@')) {
+ *strchr(msg->cm_fields['A'], '@') = 0;
+ }
+ }
+ else {
+ msg->cm_fields['A'] = strdup("Citadel");
+ }
+
+ if (fromaddr != NULL) msg->cm_fields['F'] = strdup(fromaddr);
if (room != NULL) msg->cm_fields['O'] = strdup(room);
msg->cm_fields['N'] = strdup(NODENAME);
if (to != NULL) {