+Fri Oct 21 15:12:45 EDT 2005 ajc
+* MSG4 (and CtdlOutputMsg() as well) now accepts an optional MIME part
+ specifier, allowing the client to fetch an encapsulated message
+ attached as message/rfc822 instead of the top-level message.
+
Thu Oct 20 17:55:12 EDT 2005 ajc
* ft_wordbreaker.c: added a list of "noise words" to ignore. This is
admittedly EN/US specific, so if anyone wants to contribute noise words
*
*/
-#ifdef DLL_EXPORT
-#define IN_LIBCIT
-#endif
-
#if defined(__linux) || defined(__sun) /* needed for crypt(): */
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED 1
*
*/
-#ifdef DLL_EXPORT
-#define IN_LIBCIT
-#endif
-
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
cmd_isme(&cmdbuf[5]);
}
- else if (!strncasecmp(cmdbuf, "FUCK", 4)) {
- cprintf("100\n");
-
- struct CtdlMessage *msg;
- msg = CtdlFetchMessage(3115, 1);
- cprintf("\nCtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ONLY, 0, 1);\n--\n");
- CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ONLY, 0, 1);
- cprintf("--\nCtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_NONE, 0, 1);\n--\n");
- CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_NONE, 0, 1);
- cprintf("--\nCtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1);\n--\n");
- CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1);
- cprintf("--\n");
- cprintf("000\n");
- CtdlFreeMessage(msg);
- }
-
else if (!DLoader_Exec_Cmd(cmdbuf)) {
cprintf("%d Unrecognized or unsupported command.\n",
ERROR + CMD_NOT_SUPPORTED);
*
*/
-#ifdef DLL_EXPORT
-#define IN_LIBCIT
-#endif
-
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
CC->redirect_alloc = SIZ;
CtdlOutputMsg(msgnum, MT_RFC822,
(need_body ? HEADERS_ALL : HEADERS_ONLY),
- 0, 1);
+ 0, 1, NULL);
if (!need_body) cprintf("\r\n"); /* extra trailing newline */
IMAP->cached_rfc822_data = CC->redirect_buffer;
IMAP->cached_rfc822_len = CC->redirect_len;
/*
* $Id$
*
- * This is the MIME parser for Citadel. Sometimes it actually works.
+ * This is the MIME parser for Citadel.
*
* Copyright (c) 1998-2005 by Art Cancro
* This code is distributed under the terms of the GNU General Public License.
*
*/
-#ifdef DLL_EXPORT
-#define IN_LIBCIT
-#endif
-
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
++length;
}
part_end = content_end;
- /* fix an off-by-one error */
- --part_end;
- --length;
+ /* fix an off-by-one error */
+ --part_end;
+ --length;
/* Truncate if the header told us to */
if ( (content_length > 0) && (length > content_length) ) {
/* lprintf(CTDL_DEBUG, "mime_decode part=%s, len=%d, type=%s, charset=%s, encoding=%s\n",
partnum, length, content_type, charset, encoding); */
+
+ /* Ok, we've got a non-multipart part here, so do something with it.
+ */
mime_decode(partnum,
- part_start, length,
- content_type, charset, encoding, disposition,
- name, filename,
- CallBack, NULL, NULL,
- userdata, dont_decode);
+ part_start, length,
+ content_type, charset, encoding, disposition,
+ name, filename,
+ CallBack, NULL, NULL,
+ userdata, dont_decode
+ );
}
end_parser: /* free the buffers! end the oppression!! */
}
+struct encapmsg {
+ char desired_section[64];
+ char *msg;
+ size_t msglen;
+};
+
+
+/*
+ * Callback function for
+ */
+void extract_encapsulated_message(char *name, char *filename, char *partnum, char *disp,
+ void *content, char *cbtype, char *cbcharset, size_t length,
+ char *encoding, void *cbuserdata)
+{
+ struct encapmsg *encap;
+
+ encap = (struct encapmsg *)cbuserdata;
+
+ /* Only proceed if this is the desired section... */
+ if (!strcasecmp(encap->desired_section, partnum)) {
+ encap->msglen = length;
+ encap->msg = malloc(length + 2);
+ memcpy(encap->msg, content, length);
+ return;
+ }
+
+}
+
+
+
+
/*
* Get a message off disk. (returns om_* values found in msgbase.h)
*
int mode, /* how would you like that message? */
int headers_only, /* eschew the message body? */
int do_proto, /* do Citadel protocol responses? */
- int crlf /* Use CRLF newlines instead of LF? */
+ int crlf, /* Use CRLF newlines instead of LF? */
+ char *section /* NULL or a message/rfc822 section */
) {
struct CtdlMessage *TheMessage = NULL;
int retcode = om_no_such_msg;
+ struct encapmsg encap;
- lprintf(CTDL_DEBUG, "CtdlOutputMsg() msgnum=%ld, mode=%d\n",
- msg_num, mode);
+ lprintf(CTDL_DEBUG, "CtdlOutputMsg() msgnum=%ld, mode=%d, section=%s\n",
+ msg_num, mode,
+ (section ? section : "<>")
+ );
if ((!(CC->logged_in)) && (!(CC->internal_pgm))) {
if (do_proto) cprintf("%d Not logged in.\n",
ERROR + MESSAGE_NOT_FOUND, msg_num);
return(om_no_such_msg);
}
-
- retcode = CtdlOutputPreLoadedMsg(
- TheMessage, mode,
- headers_only, do_proto, crlf);
+ /* Here is the weird form of this command, to process only an
+ * encapsulated message/rfc822 section.
+ */
+ if (section) {
+ memset(&encap, 0, sizeof encap);
+ safestrncpy(encap.desired_section, section, sizeof encap.desired_section);
+ mime_parser(TheMessage->cm_fields['M'],
+ NULL,
+ *extract_encapsulated_message,
+ NULL, NULL, (void *)&encap, 0
+ );
+ CtdlFreeMessage(TheMessage);
+ TheMessage = NULL;
+
+ if (encap.msg) {
+ encap.msg[encap.msglen] = 0;
+ TheMessage = convert_internet_message(encap.msg);
+ encap.msg = NULL; /* no free() here, TheMessage owns it now */
+
+ /* Now we let it fall through to the bottom of this
+ * function, because TheMessage now contains the
+ * encapsulated message instead of the top-level
+ * message. Isn't that neat?
+ */
+
+ }
+ else {
+ if (do_proto) cprintf("%d msg %ld has no part %s\n",
+ ERROR + MESSAGE_NOT_FOUND, msg_num, section);
+ retcode = om_no_such_msg;
+ }
+
+ }
+
+ /* Ok, output the message now */
+ retcode = CtdlOutputPreLoadedMsg(
+ TheMessage, mode,
+ headers_only, do_proto, crlf);
CtdlFreeMessage(TheMessage);
return(retcode);
msgid = extract_long(cmdbuf, 0);
headers_only = extract_int(cmdbuf, 1);
- CtdlOutputMsg(msgid, MT_CITADEL, headers_only, 1, 0);
+ CtdlOutputMsg(msgid, MT_CITADEL, headers_only, 1, 0, NULL);
return;
}
msgid = extract_long(cmdbuf, 0);
headers_only = extract_int(cmdbuf, 1);
- CtdlOutputMsg(msgid, MT_RFC822, headers_only, 1, 1);
+ CtdlOutputMsg(msgid, MT_RFC822, headers_only, 1, 1, NULL);
}
void cmd_msg4(char *cmdbuf)
{
long msgid;
+ char section[64];
msgid = extract_long(cmdbuf, 0);
- CtdlOutputMsg(msgid, MT_MIME, 0, 1, 0);
+ extract_token(section, cmdbuf, 1, '|', sizeof section);
+ CtdlOutputMsg(msgid, MT_MIME, 0, 1, 0, (section[0] ? section : NULL) );
}
extract_token(desired_section, cmdbuf, 1, '|', sizeof desired_section);
safestrncpy(CC->download_desired_section, desired_section,
sizeof CC->download_desired_section);
- CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1);
+ CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1, NULL);
}
int mode, /* how would you like that message? */
int headers_only, /* eschew the message body? */
int do_proto, /* do Citadel protocol responses? */
- int crlf);
+ int crlf, /* 0=LF, 1=CRLF */
+ char *section /* output a message/rfc822 section */
+);
int CtdlOutputPreLoadedMsg(struct CtdlMessage *,
int mode, /* how would you like that message? */
int headers_only, /* eschew the message body? */
int do_proto, /* do Citadel protocol responses? */
- int crlf);
+ int crlf /* 0=LF, 1=CRLF */
+);
int CtdlCopyMsgToRoom(long msgnum, char *dest);
int CtdlDoIHavePermissionToDeleteMessagesFromThisRoom(void);
int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, size_t n);
}
cprintf("000\n");
- if (strcmp(&CC->room.QRname, hold_rm)) {
+ if (strcmp(CC->room.QRname, hold_rm)) {
getroom(&CC->room, hold_rm); /* return to saved room */
}
}
CC->redirect_buffer = malloc(SIZ);
CC->redirect_len = 0;
CC->redirect_alloc = SIZ;
- CtdlOutputMsg(msgnum, MT_CITADEL, HEADERS_ALL, 0, 1);
+ CtdlOutputMsg(msgnum, MT_CITADEL, HEADERS_ALL, 0, 1, NULL);
msgtext = CC->redirect_buffer;
CC->redirect_buffer = NULL;
CC->redirect_len = 0;
CC->redirect_buffer = malloc(SIZ);
CC->redirect_len = 0;
CC->redirect_alloc = SIZ;
- CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1);
+ CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL);
smi.meta_rfc822_length = CC->redirect_len;
free(CC->redirect_buffer);
CC->redirect_buffer = NULL;
}
cprintf("+OK Message %d:\r\n", which_one);
- CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, MT_RFC822, HEADERS_ALL, 0, 1);
+ CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL);
cprintf(".\r\n");
}
CC->redirect_len = 0;
CC->redirect_alloc = SIZ;
CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum,
- MT_RFC822, HEADERS_ALL, 0, 1);
+ MT_RFC822, HEADERS_ALL, 0, 1, NULL);
msgtext = CC->redirect_buffer;
CC->redirect_buffer = NULL;
CC->redirect_len = 0;
CC->redirect_buffer = malloc(SIZ);
CC->redirect_len = 0;
CC->redirect_alloc = SIZ;
- CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1);
+ CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL);
msgtext = CC->redirect_buffer;
msg_size = CC->redirect_len;
CC->redirect_buffer = NULL;
"Content-length:". MIME formats are chosen and/or converted based on the
client's preferred format settings, which are set using the MSGP command,
described below.
+
+ The MSG4 command also accepts an optional second argument, which may be the
+MIME part specifier of an encapsulated message/rfc822 message. This is useful
+for fetching the encapsulated message instead of the top-level message, for
+example, when someone has forwarded a message as an attachment. Note that the
+only way for the client to know the part specifier is to fetch the top-level
+message and then look for attachments of type message/rfc822, and then call
+MSG4 again with that part specifier.
+