struct imap_fetch_part {
- char desired_section[256];
+ char desired_section[SIZ];
FILE *output_fp;
};
}
void imap_fetch_internaldate(struct CtdlMessage *msg) {
- char buf[256];
+ char buf[SIZ];
time_t msgdate;
if (msg->cm_fields['T'] != NULL) {
* "RFC822.SIZE" size of translated message
* "RFC822.TEXT" body only (without leading blank line)
*/
-void imap_fetch_rfc822(int msgnum, char *whichfmt) {
+void imap_fetch_rfc822(int msgnum, char *whichfmt, struct CtdlMessage *msg) {
FILE *tmp;
char buf[1024];
char *ptr;
* Load the message into a temp file for translation and measurement
*/
CtdlRedirectOutput(tmp, -1);
- CtdlOutputMsg(msgnum, MT_RFC822, 0, 0, 1);
+ CtdlOutputPreLoadedMsg(msg, msgnum, MT_RFC822, 0, 0, 1);
CtdlRedirectOutput(NULL, -1);
+ if (!is_valid_message(msg)) {
+ lprintf(1, "WARNING: output clobbered the message!\n");
+ }
/*
* Now figure out where the headers/text break is. IMAP considers the
}
+/*
+ * Called by imap_fetch_envelope() to output the "From" field.
+ * This is in its own function because its logic is kind of complex. We
+ * really need to make this suck less.
+ */
+void imap_output_envelope_from(struct CtdlMessage *msg) {
+ char user[1024], node[1024], name[1024];
+
+ cprintf("(("); /* open double-parens */
+ imap_strout(msg->cm_fields['A']); /* personal name */
+ cprintf(" NIL "); /* source route (not used) */
+
+ if (msg->cm_fields['F'] != NULL) {
+ process_rfc822_addr(msg->cm_fields['F'], user, node, name);
+ imap_strout(user); /* mailbox name (user id) */
+ cprintf(" ");
+ if (!strcasecmp(node, config.c_nodename)) {
+ imap_strout(config.c_fqdn);
+ }
+ else {
+ imap_strout(node); /* host name */
+ }
+ }
+ else {
+ imap_strout(msg->cm_fields['A']); /* mailbox name (user id) */
+ cprintf(" ");
+ imap_strout(msg->cm_fields['N']); /* host name */
+ }
+
+ cprintf(")) "); /* close double-parens */
+}
+
+
/*
* Implements the ENVELOPE fetch item
*
- * FIXME ... we have to actually do something useful here.
+ * FIXME ... we only output some of the fields right now. Definitely need
+ * to do all of them. Accurately, too.
+ *
+ * Note that the imap_strout() function can cleverly output NULL fields as NIL,
+ * so we don't have to check for that condition like we do elsewhere.
*/
void imap_fetch_envelope(long msgnum, struct CtdlMessage *msg) {
+ char datestringbuf[SIZ];
+ time_t msgdate;
+ char *fieldptr = NULL;
+
+ /* Parse the message date into an IMAP-format date string */
+ if (msg->cm_fields['T'] != NULL) {
+ msgdate = atol(msg->cm_fields['T']);
+ }
+ else {
+ msgdate = time(NULL);
+ }
+ datestring(datestringbuf, msgdate, DATESTRING_IMAP);
+
+ /* Now start spewing data fields. The order is important, as it is
+ * defined by the protocol specification. Nonexistent fields must
+ * be output as NIL, existent fields must be quoted or literalled.
+ * The imap_strout() function conveniently does all this for us.
+ */
cprintf("ENVELOPE (");
- cprintf("NIL "); /* date */
- cprintf("NIL "); /* subject */
- cprintf("NIL "); /* from */
- cprintf("NIL "); /* sender */
- cprintf("NIL "); /* reply-to */
+
+ /* Date */
+ imap_strout(datestringbuf);
+ cprintf(" ");
+
+ /* Subject */
+ imap_strout(msg->cm_fields['U']);
+ cprintf(" ");
+
+ /* From */
+ imap_output_envelope_from(msg);
+
+ /* Sender */
+ if (0) {
+ /* FIXME ... check for a *real* Sender: field */
+ }
+ else {
+ imap_output_envelope_from(msg);
+ }
+
+ /* Reply-to */
+ if (0) {
+ /* FIXME ... check for a *real* Reply-to: field */
+ }
+ else {
+ imap_output_envelope_from(msg);
+ }
+
cprintf("NIL "); /* to */
+
cprintf("NIL "); /* cc */
+
cprintf("NIL "); /* bcc */
- cprintf("NIL "); /* in-reply-to */
- cprintf("NIL"); /* message-id */
- cprintf(")\r\n");
+
+ /* In-reply-to */
+ fieldptr = rfc822_fetch_field(msg->cm_fields['M'], "In-reply-to");
+ imap_strout(fieldptr);
+ cprintf(" ");
+ if (fieldptr != NULL) phree(fieldptr);
+
+ /* message ID */
+ imap_strout(msg->cm_fields['I']);
+
+ cprintf(") ");
}
while (fgets(buf, sizeof buf, fp) != NULL) {
striplt(buf);
if (strlen(buf) == 0) {
+ fflush(fp);
ftruncate(fileno(fp), ftell(fp));
}
}
for (i=0; i<strlen(partial); ++i) {
if (partial[i]=='>') partial[i] = 0;
}
+ if (is_partial == 0) strcpy(partial, "");
lprintf(9, "Partial is %s\n", partial);
tmp = tmpfile();
if (!strcmp(section, "")) { /* the whole thing */
CtdlRedirectOutput(tmp, -1);
- CtdlOutputMsg(msgnum, MT_RFC822, 0, 0, 1);
+ CtdlOutputPreLoadedMsg(msg, msgnum, MT_RFC822, 0, 0, 1);
CtdlRedirectOutput(NULL, -1);
}
*/
else if (!strncasecmp(section, "HEADER", 6)) {
CtdlRedirectOutput(tmp, -1);
- CtdlOutputMsg(msgnum, MT_RFC822, 1, 0, 1);
+ CtdlOutputPreLoadedMsg(msg, msgnum, MT_RFC822, 1, 0, 1);
CtdlRedirectOutput(NULL, -1);
imap_strip_headers(tmp);
}
}
+/*
+ * Spew the BODYSTRUCTURE data for a message. (Do you need a silencer if
+ * you're going to shoot a MIME? Do you need a reason to shoot Mark Crispin?
+ * No, and no.)
+ *
+ * FIXME finish the implementation
+ */
+void imap_fetch_bodystructure (long msgnum, char *item,
+ struct CtdlMessage *msg) {
+ FILE *tmp;
+ char buf[1024];
+ long lines = 0L;
+ long bytes = 0L;
+
+
+ /* For non-RFC822 (ordinary Citadel) messages, this is short and
+ * sweet...
+ */
+ if (msg->cm_format_type != FMT_RFC822) {
+
+ /* *sigh* We have to RFC822-format the message just to be able
+ * to measure it.
+ */
+ tmp = tmpfile();
+ if (tmp == NULL) return;
+ CtdlRedirectOutput(tmp, -1);
+ CtdlOutputPreLoadedMsg(msg, msgnum, MT_RFC822, 0, 0, 1);
+ CtdlRedirectOutput(NULL, -1);
+
+ rewind(tmp);
+ while (fgets(buf, sizeof buf, tmp) != NULL) ++lines;
+ bytes = ftell(tmp);
+ fclose(tmp);
+
+ cprintf("BODYSTRUCTURE (\"TEXT\" \"PLAIN\" "
+ "(\"CHARSET\" \"US-ASCII\") NIL NIL "
+ "\"7BIT\" %ld %ld) ", bytes, lines);
+
+ return;
+ }
+
+ /* For messages already stored in RFC822 format, we have to parse. */
+ /* FIXME do this! */
+
+
+}
+
+
+
+
+
/*
* imap_do_fetch() calls imap_do_fetch_msg() to output the deta of an
1, msg);
}
else if (!strcasecmp(itemlist[i], "BODYSTRUCTURE")) {
- /* FIXME do something here */
+ imap_fetch_bodystructure(IMAP->msgids[seq-1],
+ itemlist[i], msg);
}
else if (!strcasecmp(itemlist[i], "ENVELOPE")) {
imap_fetch_envelope(IMAP->msgids[seq-1], msg);
imap_fetch_internaldate(msg);
}
else if (!strcasecmp(itemlist[i], "RFC822")) {
- imap_fetch_rfc822(IMAP->msgids[seq-1], itemlist[i]);
+ imap_fetch_rfc822(IMAP->msgids[seq-1], itemlist[i], msg);
}
else if (!strcasecmp(itemlist[i], "RFC822.HEADER")) {
- imap_fetch_rfc822(IMAP->msgids[seq-1], itemlist[i]);
+ imap_fetch_rfc822(IMAP->msgids[seq-1], itemlist[i], msg);
}
else if (!strcasecmp(itemlist[i], "RFC822.SIZE")) {
- imap_fetch_rfc822(IMAP->msgids[seq-1], itemlist[i]);
+ imap_fetch_rfc822(IMAP->msgids[seq-1], itemlist[i], msg);
}
else if (!strcasecmp(itemlist[i], "RFC822.TEXT")) {
- imap_fetch_rfc822(IMAP->msgids[seq-1], itemlist[i]);
+ imap_fetch_rfc822(IMAP->msgids[seq-1], itemlist[i], msg);
}
else if (!strcasecmp(itemlist[i], "UID")) {
imap_fetch_uid(seq);
int s;
char setstr[1024], lostr[1024], histr[1024];
int lo, hi;
+ char *actual_range;
+
+ actual_range = range;
+ if (!strcasecmp(range, "ALL")) actual_range = "1:*";
/*
* Clear out the IMAP_FETCHED flags for all messages.
/*
* Now set it for all specified messages.
*/
- num_sets = num_tokens(range, ',');
+ num_sets = num_tokens(actual_range, ',');
for (s=0; s<num_sets; ++s) {
- extract_token(setstr, range, s, ',');
+ extract_token(setstr, actual_range, s, ',');
extract_token(lostr, setstr, 0, ':');
if (num_tokens(setstr, ':') >= 2) {
*/
void imap_fetch(int num_parms, char *parms[]) {
char items[1024];
- char *itemlist[256];
+ char *itemlist[SIZ];
int num_items;
int i;
*/
void imap_uidfetch(int num_parms, char *parms[]) {
char items[1024];
- char *itemlist[256];
+ char *itemlist[SIZ];
int num_items;
int i;
int have_uid_item = 0;