-/*
- * Implements the FETCH command in IMAP.
- * This is a good example of the protocol's gratuitous complexity.
- *
- * Copyright (c) 2001-2020 by the citadel.org team
- *
- * This program is open source software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
+// Implements the FETCH command in IMAP.
+// This is a good example of the protocol's gratuitous complexity.
+//
+// Copyright (c) 2001-2024 by the citadel.org team
+// This program is open source software. Use, duplication, or disclosure is subject to the GNU General Public License v3.
#include "../../sysdep.h"
#include <stdlib.h>
-/*
- * Individual field functions for imap_do_fetch_msg() ...
- */
+// Individual field functions for imap_do_fetch_msg() ...
void imap_fetch_uid(int seq) {
IAPrintf("UID %ld", IMAP->msgids[seq-1]);
}
-void imap_fetch_flags(int seq)
-{
+
+void imap_fetch_flags(int seq) {
citimap *Imap = IMAP;
int num_flags_printed = 0;
IAPuts("FLAGS (");
}
-/*
- * Fetch RFC822-formatted messages.
- *
- * 'whichfmt' should be set to one of:
- * "RFC822" entire message
- * "RFC822.HEADER" headers only (with trailing blank line)
- * "RFC822.SIZE" size of translated message
- * "RFC822.TEXT" body only (without leading blank line)
- */
+// Fetch RFC822-formatted messages.
+//
+// 'whichfmt' should be set to one of:
+// "RFC822" entire message
+// "RFC822.HEADER" headers only (with trailing blank line)
+// "RFC822.SIZE" size of translated message
+// "RFC822.TEXT" body only (without leading blank line)
void imap_fetch_rfc822(long msgnum, const char *whichfmt) {
citimap *Imap = IMAP;
const char *ptr = NULL;
int need_to_rewrite_metadata = 0;
int need_body = 0;
- /* Determine whether this particular fetch operation requires
- * us to fetch the message body from disk. If not, we can save
- * on some disk operations...
- */
+ // Determine whether this particular fetch operation requires
+ // us to fetch the message body from disk. If not, we can save
+ // on some disk operations...
if ( (!strcasecmp(whichfmt, "RFC822")) || (!strcasecmp(whichfmt, "RFC822.TEXT")) ) {
need_body = 1;
}
- /* If this is an RFC822.SIZE fetch, first look in the message's
- * metadata record to see if we've saved that information.
- */
+ // If this is an RFC822.SIZE fetch, first look in the message's
+ // metadata record to see if we've saved that information.
if (!strcasecmp(whichfmt, "RFC822.SIZE")) {
GetMetaData(&smi, msgnum);
if (smi.meta_rfc822_length > 0L) {
need_body = 1;
}
- /* Cache the most recent RFC822 FETCH because some clients like to
- * fetch in pieces, and we don't want to have to go back to the
- * message store for each piece. We also burn the cache if the
- * client requests something that involves reading the message
- * body, but we haven't fetched the body yet.
- */
+ // Cache the most recent RFC822 FETCH because some clients like to
+ // fetch in pieces, and we don't want to have to go back to the
+ // message store for each piece. We also burn the cache if the
+ // client requests something that involves reading the message
+ // body, but we haven't fetched the body yet.
if ((Imap->cached_rfc822 != NULL)
&& (Imap->cached_rfc822_msgnum == msgnum)
&& (Imap->cached_rfc822_withbody || (!need_body)) ) {
- /* Good to go! */
+ // Good to go!
}
else if (Imap->cached_rfc822 != NULL) {
- /* Some other message is cached -- free it */
+ // Some other message is cached -- free it
FreeStrBuf(&Imap->cached_rfc822);
Imap->cached_rfc822_msgnum = (-1);
}
- /* At this point, we now can fetch and convert the message iff it's not
- * the one we had cached.
- */
+ // At this point, we now can fetch and convert the message iff it's not the one we had cached.
if (Imap->cached_rfc822 == NULL) {
- /*
- * Load the message into memory for translation & measurement
- */
+ // Load the message into memory for translation & measurement
CC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
CtdlOutputMsg(msgnum, MT_RFC822,
(need_body ? HEADERS_ALL : HEADERS_FAST),
0, 1, NULL, SUPPRESS_ENV_TO, NULL, NULL, NULL
);
if (!need_body) {
- client_write(HKEY("\r\n")); // extra trailing newline -- to the redirect_buffer, *not* to the client
+ client_write(HKEY("\r\n")); // extra trailing newline -- to the redirect_buffer, *not* to the client
}
Imap->cached_rfc822 = CC->redirect_buffer;
CC->redirect_buffer = NULL;
}
}
- /*
- * Now figure out where the headers/text break is. IMAP considers the
- * intervening blank line to be part of the headers, not the text.
- */
+ // Now figure out where the headers/text break is. IMAP considers the
+ // intervening blank line to be part of the headers, not the text.
headers_size = 0;
if (need_body) {
}
-/*
- * Load a specific part of a message into the temp file to be output to a
- * client. FIXME we can handle parts like "2" and "2.1" and even "2.MIME"
- * but we still can't handle "2.HEADER" (which might not be a problem).
- *
- * Note: mime_parser() was called with dont_decode set to 1, so we have the
- * luxury of simply spewing without having to re-encode.
- */
+// Load a specific part of a message into the temp file to be output to a
+// client. FIXME we can handle parts like "2" and "2.1" and even "2.MIME"
+// but we still can't handle "2.HEADER" (which might not be a problem).
+//
+// Note: mime_parser() was called with dont_decode set to 1, so we have the
+// luxury of simply spewing without having to re-encode.
void imap_load_part(char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
- char *cbid, void *cbuserdata)
-{
+ char *cbid, void *cbuserdata
+) {
char mimebuf2[SIZ];
StrBuf *desired_section;
}
-/*
- * 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.
- */
+// 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[SIZ], node[SIZ], name[SIZ];
if (!msg) return;
- /* For anonymous messages, it's so easy! */
+ // For anonymous messages, it's so easy!
if (!is_room_aide() && (msg->cm_anon_type == MES_ANONONLY)) {
IAPuts("((\"----\" NIL \"x\" \"x.org\")) ");
return;
return;
}
- /* For everything else, we do stuff. */
+ // For everything else, we do stuff.
IAPuts("(("); // open double-parens
IPutMsgField(eAuthor); // display name
IAPuts(" NIL "); // source route (not used)
if (!CM_IsEmpty(msg, erFc822Addr)) {
process_rfc822_addr(msg->cm_fields[erFc822Addr], user, node, name);
- IPutStr(user, strlen(user)); /* mailbox name (user id) */
+ IPutStr(user, strlen(user)); // mailbox name (user id)
IAPuts(" ");
- IPutStr(node, strlen(node)); /* host name */
+ IPutStr(node, strlen(node)); // host name
}
else {
- IPutMsgField(eAuthor); /* Make up a synthetic address */
+ IPutMsgField(eAuthor); // Make up a synthetic address
IAPuts(" ");
IPutStr(CtdlGetConfigStr("c_fqdn"), strlen(CtdlGetConfigStr("c_fqdn")));
}
- IAPuts(")) "); /* close double-parens */
+ IAPuts(")) "); // close double-parens
}
-/*
- * Output an envelope address (or set of addresses) in the official,
- * convoluted, braindead format. (Note that we can't use this for
- * the "From" address because its data may come from a number of different
- * fields. But we can use it for "To" and possibly others.
- */
+// Output an envelope address (or set of addresses) in the official,
+// convoluted, braindead format. (Note that we can't use this for
+// the "From" address because its data may come from a number of different
+// fields. But we can use it for "To" and possibly others.
void imap_output_envelope_addr(char *addr) {
char individual_addr[256];
int num_addrs;
IAPuts("(");
- /* How many addresses are listed here? */
+ // How many addresses are listed here?
num_addrs = num_tokens(addr, ',');
- /* Output them one by one. */
+ // Output them one by one.
for (i=0; i<num_addrs; ++i) {
extract_token(individual_addr, addr, i, ',', sizeof individual_addr);
string_trim(individual_addr);
}
-/*
- * Implements the ENVELOPE fetch item
- *
- * 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.
- */
+// Implements the ENVELOPE fetch item
+//
+// 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(struct CtdlMessage *msg) {
char datestringbuf[SIZ];
time_t msgdate;
if (!msg) return;
- /* Parse the message date into an IMAP-format date string */
+ // Parse the message date into an IMAP-format date string
if (!CM_IsEmpty(msg, eTimestamp)) {
msgdate = atol(msg->cm_fields[eTimestamp]);
}
}
len = datestring(datestringbuf, sizeof 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.
- */
+ // 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.
IAPuts("ENVELOPE (");
- /* Date */
+ // Date
IPutStr(datestringbuf, len);
IAPuts(" ");
- /* Subject */
+ // Subject
IPutMsgField(eMsgSubject);
IAPuts(" ");
- /* From */
+ // From
imap_output_envelope_from(msg);
- /* Sender (default to same as 'From' if not present) */
+ // Sender (default to same as 'From' if not present)
fieldptr = rfc822_fetch_field(msg->cm_fields[eMessageText], "Sender");
if (fieldptr != NULL) {
imap_output_envelope_addr(fieldptr);
imap_output_envelope_from(msg);
}
- /* Reply-to */
+ // Reply-to
fieldptr = rfc822_fetch_field(msg->cm_fields[eMessageText], "Reply-to");
if (fieldptr != NULL) {
imap_output_envelope_addr(fieldptr);
imap_output_envelope_from(msg);
}
- /* To */
+ // To
imap_output_envelope_addr(msg->cm_fields[eRecipient]);
- /* Cc (we do it this way because there might be a legacy non-Citadel Cc: field present) */
+ // Cc (we do it this way because there might be a legacy non-Citadel Cc: field present)
fieldptr = msg->cm_fields[eCarbonCopY];
if (fieldptr != NULL) {
imap_output_envelope_addr(fieldptr);
if (fieldptr != NULL) free(fieldptr);
}
- /* Bcc */
+ // Bcc
fieldptr = rfc822_fetch_field(msg->cm_fields[eMessageText], "Bcc");
imap_output_envelope_addr(fieldptr);
if (fieldptr != NULL) free(fieldptr);
- /* In-reply-to */
+ // In-reply-to
fieldptr = rfc822_fetch_field(msg->cm_fields[eMessageText], "In-reply-to");
IPutStr(fieldptr, (fieldptr)?strlen(fieldptr):0);
IAPuts(" ");
if (fieldptr != NULL) free(fieldptr);
- /* message ID */
+ // message ID
len = msg->cm_lengths[emessageId];
if ((len == 0) || (
) {
IPutMsgField(emessageId);
}
- else
- {
+ else {
char *Buf = malloc(len + 3);
long pos = 0;
- if (msg->cm_fields[emessageId][0] != '<')
- {
+ if (msg->cm_fields[emessageId][0] != '<') {
Buf[pos] = '<';
pos ++;
}
memcpy(&Buf[pos], msg->cm_fields[emessageId], len);
pos += len;
- if (msg->cm_fields[emessageId][len] != '>')
- {
+ if (msg->cm_fields[emessageId][len] != '>') {
Buf[pos] = '>';
pos++;
}
}
-/*
- * This function is called only when CC->redirect_buffer contains a set of
- * RFC822 headers with no body attached. Its job is to strip that set of
- * headers down to *only* the ones we're interested in.
- */
+// This function is called only when CC->redirect_buffer contains a set of
+// RFC822 headers with no body attached. Its job is to strip that set of
+// headers down to *only* the ones we're interested in.
void imap_strip_headers(StrBuf *section) {
citimap_command Cmd;
StrBuf *which_fields = NULL;
if (doing_headers == 0) ok = 1;
else {
- /* we're supposed to print all headers that are not matching the filter list */
+ // we're supposed to print all headers that are not matching the filter list
if (headers_not) for (i=0, ok = 1; (i < num_parms) && (ok == 1); ++i) {
if ( (!strncasecmp(ChrPtr(Line),
Cmd.Params[i].Key,
ok = 0;
}
}
- /* we're supposed to print all headers matching the filterlist */
+ // we're supposed to print all headers matching the filterlist
else for (i=0, ok = 0; ((i < num_parms) && (ok == 0)); ++i) {
if ( (!strncasecmp(ChrPtr(Line),
Cmd.Params[i].Key,
StrBufAppendBufPlain(boiled_headers, HKEY("\r\n"), 0);
- /* Now save it back (it'll always be smaller) */
+ // Now save it back (it'll always be smaller)
FreeStrBuf(&CC->redirect_buffer);
CC->redirect_buffer = boiled_headers;
}
-/*
- * Implements the BODY and BODY.PEEK fetch items
- */
+// Implements the BODY and BODY.PEEK fetch items
void imap_fetch_body(long msgnum, ConstStr item, int is_peek) {
struct CtdlMessage *msg = NULL;
StrBuf *section;
int burn_the_cache = 0;
citimap *Imap = IMAP;
- /* extract section */
+ // extract section
section = NewStrBufPlain(CKEY(item));
if (strchr(ChrPtr(section), '[') != NULL) {
}
syslog(LOG_DEBUG, "imap: selected section is [%s]", (StrLength(section) == 0) ? "(empty)" : ChrPtr(section));
- /* Burn the cache if we don't have the same section of the
- * same message again.
- */
+ // Burn the cache if we don't have the same section of the same message again.
if (Imap->cached_body != NULL) {
if (Imap->cached_bodymsgnum != msgnum) {
burn_the_cache = 1;
burn_the_cache = 1;
}
if (burn_the_cache) {
- /* Yup, go ahead and burn the cache. */
+ // Yup, go ahead and burn the cache.
free(Imap->cached_body);
Imap->cached_body_len = 0;
Imap->cached_body = NULL;
}
}
- /* extract partial */
+ // extract partial
partial = NewStrBufPlain(CKEY(item));
if (strchr(ChrPtr(partial), '<') != NULL) {
StrBufStripAllBut(partial, '<', '>');
msg = CtdlFetchMessage(msgnum, (need_body ? 1 : 0));
}
- /* Now figure out what the client wants, and get it */
+ // Now figure out what the client wants, and get it
if (!loading_body_now) {
- /* What we want is already in memory */
+ // What we want is already in memory
}
else if ( (!strcmp(ChrPtr(section), "1")) && (msg->cm_format_type != 4) ) {
CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1, SUPPRESS_ENV_TO);
}
- /*
- * If the client asked for just headers, or just particular header
- * fields, strip it down.
- */
+ // If the client asked for just headers, or just particular header fields, strip it down.
else if (!strncasecmp(ChrPtr(section), "HEADER", 6)) {
- /* This used to work with HEADERS_FAST, but then Apple got stupid with their
- * IMAP library and this broke Mail.App and iPhone Mail, so we had to change it
- * to HEADERS_ONLY so the trendy hipsters with their iPhones can read mail.
- */
+ // This used to work with HEADERS_FAST, but then Apple got stupid with their
+ // IMAP library and this broke Mail.App and iPhone Mail, so we had to change it
+ // to HEADERS_ONLY so the trendy hipsters with their iPhones can read mail.
CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ONLY, 0, 1, SUPPRESS_ENV_TO);
imap_strip_headers(section);
}
- /*
- * Strip it down if the client asked for everything _except_ headers.
- */
+ // Strip it down if the client asked for everything _except_ headers.
else if (!strncasecmp(ChrPtr(section), "TEXT", 4)) {
CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_NONE, 0, 1, SUPPRESS_ENV_TO);
}
- /*
- * Anything else must be a part specifier.
- * (Note value of 1 passed as 'dont_decode' so client gets it encoded)
- */
+ // Anything else must be a part specifier.
+ // (Note value of 1 passed as 'dont_decode' so client gets it encoded)
else {
- mime_parser(CM_RANGE(msg, eMessageText),
- *imap_load_part, NULL, NULL,
- section,
- 1
- );
+ mime_parser(CM_RANGE(msg, eMessageText), *imap_load_part, NULL, NULL, section, 1);
}
if (loading_body_now) {
FreeStrBuf(&partial);
- /* Here we go -- output it */
+ // Here we go -- output it
iaputs(&Imap->cached_body[pstart], pbytes);
if (msg != NULL) {
CM_Free(msg);
}
- /* Mark this message as "seen" *unless* this is a "peek" operation */
+ // Mark this message as "seen" *unless* this is a "peek" operation
if (is_peek == 0) {
CtdlSetSeen(&msgnum, 1, 1, ctdlsetseen_seen, NULL, NULL);
}
FreeStrBuf(§ion);
}
-/*
- * Called immediately before outputting a multipart bodystructure
- */
+
+// Called immediately before outputting a multipart bodystructure
void imap_fetch_bodystructure_pre(
char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
char *cbid, void *cbuserdata
- ) {
-
+) {
IAPuts("(");
}
-
-/*
- * Called immediately after outputting a multipart bodystructure
- */
+// Called immediately after outputting a multipart bodystructure
void imap_fetch_bodystructure_post(
char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
char *cbid, void *cbuserdata
- ) {
+) {
long len;
char subtype[128];
IAPuts(" ");
- /* disposition */
+ // disposition
len = extract_token(subtype, cbtype, 1, '/', sizeof subtype);
IPutStr(subtype, len);
- /* body language */
- /* IAPuts(" NIL"); We thought we needed this at one point, but maybe we don't... */
+ // body language
+ // IAPuts(" NIL"); We thought we needed this at one point, but maybe we don't...
IAPuts(")");
}
-
-/*
- * Output the info for a MIME part in the format required by BODYSTRUCTURE.
- *
- */
+// Output the info for a MIME part in the format required by BODYSTRUCTURE.
void imap_fetch_bodystructure_part(
char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
char *cbid, void *cbuserdata
- ) {
-
+) {
int have_cbtype = 0;
int have_encoding = 0;
int lines = 0;
}
IAPuts("(");
- IPutStr(cbmaintype, cbmaintype_len); /* body type */
+ IPutStr(cbmaintype, cbmaintype_len); // body type
IAPuts(" ");
- IPutStr(cbsubtype, cbsubtype_len); /* body subtype */
+ IPutStr(cbsubtype, cbsubtype_len); // body subtype
IAPuts(" ");
- IAPuts("("); /* begin body parameter list */
+ IAPuts("("); // begin body parameter list
- /* "NAME" must appear as the first parameter. This is not required by IMAP,
- * but the Asterisk voicemail application blindly assumes that NAME will be in
- * the first position. If it isn't, it rejects the message.
- */
+ // "NAME" must appear as the first parameter. This is not required by IMAP,
+ // but the Asterisk voicemail application blindly assumes that NAME will be in
+ // the first position. If it isn't, it rejects the message.
if ((name != NULL) && (!IsEmptyStr(name))) {
IAPuts("\"NAME\" ");
IPutStr(name, strlen(name));
else {
IPutStr(cbcharset, strlen(cbcharset));
}
- IAPuts(") "); /* end body parameter list */
+ IAPuts(") "); // end body parameter list
- IAPuts("NIL "); /* Body ID */
- IAPuts("NIL "); /* Body description */
+ IAPuts("NIL "); // Body ID
+ IAPuts("NIL "); // Body description
if ((encoding != NULL) && (encoding[0] != 0)) have_encoding = 1;
if (have_encoding) {
}
IAPuts(" ");
- /* The next field is the size of the part in bytes. */
- IAPrintf("%ld ", (long)length); /* bytes */
+ // The next field is the size of the part in bytes.
+ IAPrintf("%ld ", (long)length); // bytes
- /* The next field is the number of lines in the part, if and only
- * if the part is TEXT. More gratuitous complexity.
- */
+ // The next field is the number of lines in the part, if and only if the part is TEXT. More gratuitous complexity.
if (!strcasecmp(cbmaintype, "TEXT")) {
if (length) for (i=0; i<length; ++i) {
if (((char *)content)[i] == '\n') ++lines;
IAPrintf("%d ", lines);
}
- /* More gratuitous complexity */
- if ((!strcasecmp(cbmaintype, "MESSAGE"))
- && (!strcasecmp(cbsubtype, "RFC822"))) {
- /* FIXME: message/rfc822 also needs to output the envelope structure,
- * body structure, and line count of the encapsulated message. Fortunately
- * there are not yet any clients depending on this, so we can get away
- * with not implementing it for now.
- */
+ // More gratuitous complexity
+ if ((!strcasecmp(cbmaintype, "MESSAGE")) && (!strcasecmp(cbsubtype, "RFC822"))) {
+ // FIXME: message/rfc822 also needs to output the envelope structure,
+ // body structure, and line count of the encapsulated message. Fortunately
+ // there are not yet any clients depending on this, so we can get away
+ // with not implementing it for now.
}
- /* MD5 value of body part; we can get away with NIL'ing this */
+ // MD5 value of body part; we can get away with NIL'ing this
IAPuts("NIL ");
- /* Disposition */
+ // Disposition
if ((disp == NULL) || IsEmptyStr(disp)) {
IAPuts("NIL");
}
IAPuts(")");
}
- /* Body language (not defined yet) */
+ // Body language (not defined yet)
IAPuts(" NIL)");
}
-
-/*
- * Spew the BODYSTRUCTURE data for a message.
- *
- */
-void imap_fetch_bodystructure (long msgnum, const char *item,
- struct CtdlMessage *msg) {
+// Spew the BODYSTRUCTURE data for a message.
+void imap_fetch_bodystructure (long msgnum, const char *item, struct CtdlMessage *msg) {
const char *rfc822 = NULL;
const char *rfc822_body = NULL;
size_t rfc822_len;
char buf[SIZ];
int lines = 0;
- /* Handle NULL message gracefully */
+ // Handle NULL message gracefully
if (msg == NULL) {
IAPuts("BODYSTRUCTURE (\"TEXT\" \"PLAIN\" "
"(\"CHARSET\" \"US-ASCII\") NIL NIL "
return;
}
- /* For non-RFC822 (ordinary Citadel) messages, this is short and
- * sweet...
- */
+ // 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. FIXME use smi cached fields if possible
- */
+ // *sigh* We have to RFC822-format the message just to be able
+ // to measure it. FIXME use smi cached fields if possible
CC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
CtdlOutputPreLoadedMsg(msg, MT_RFC822, 0, 0, 1, SUPPRESS_ENV_TO);
return;
}
- /* For messages already stored in RFC822 format, we have to parse. */
+ // For messages already stored in RFC822 format, we have to parse.
IAPuts("BODYSTRUCTURE ");
mime_parser(CM_RANGE(msg, eMessageText),
- *imap_fetch_bodystructure_part, /* part */
- *imap_fetch_bodystructure_pre, /* pre-multi */
- *imap_fetch_bodystructure_post, /* post-multi */
+ *imap_fetch_bodystructure_part, // part
+ *imap_fetch_bodystructure_pre, // pre-multi
+ *imap_fetch_bodystructure_post, // post-multi
NULL,
- 1); /* don't decode -- we want it as-is */
+ 1 // don't decode -- we want it as-is
+ );
}
-/*
- * imap_do_fetch() calls imap_do_fetch_msg() to output the data of an
- * individual message, once it has been selected for output.
- */
+// imap_do_fetch() calls imap_do_fetch_msg() to output the data of an
+// individual message, once it has been selected for output.
void imap_do_fetch_msg(int seq, citimap_command *Cmd) {
int i;
citimap *Imap = IMAP;
struct CtdlMessage *msg = NULL;
int body_loaded = 0;
- /* Don't attempt to fetch bogus messages or UID's */
+ // Don't attempt to fetch bogus messages or UID's
if (seq < 1) return;
if (Imap->msgids[seq-1] < 1L) return;
for (i=0; i<Cmd->num_parms; ++i) {
- /* Fetchable without going to the message store at all */
+ // Fetchable without going to the message store at all
if (!strcasecmp(Cmd->Params[i].Key, "UID")) {
imap_fetch_uid(seq);
}
imap_fetch_flags(seq-1);
}
- /* Potentially fetchable from cache, if the client requests
- * stuff from the same message several times in a row.
- */
+ // Potentially fetchable from cache, if the client requests stuff from the same message several times in a row.
else if (!strcasecmp(Cmd->Params[i].Key, "RFC822")) {
imap_fetch_rfc822(Imap->msgids[seq-1], Cmd->Params[i].Key);
}
imap_fetch_rfc822(Imap->msgids[seq-1], Cmd->Params[i].Key);
}
- /* BODY fetches do their own fetching and caching too. */
+ // BODY fetches do their own fetching and caching too.
else if (!strncasecmp(Cmd->Params[i].Key, "BODY[", 5)) {
imap_fetch_body(Imap->msgids[seq-1], Cmd->Params[i], 0);
}
imap_fetch_body(Imap->msgids[seq-1], Cmd->Params[i], 1);
}
- /* Otherwise, load the message into memory.
- */
+ // Otherwise, load the message into memory.
else if (!strcasecmp(Cmd->Params[i].Key, "BODYSTRUCTURE")) {
if ((msg != NULL) && (!body_loaded)) {
- CM_Free(msg); /* need the whole thing */
+ CM_Free(msg); // need the whole thing
msg = NULL;
}
if (msg == NULL) {
}
-
-/*
- * imap_fetch() calls imap_do_fetch() to do its actual work, once it's
- * validated and boiled down the request a bit.
- */
+// imap_fetch() calls imap_do_fetch() to do its actual work, once it's
+// validated and boiled down the request a bit.
void imap_do_fetch(citimap_command *Cmd) {
citimap *Imap = IMAP;
int i;
#if 0
-/* debug output the parsed vector */
+// debug output the parsed vector
{
int i;
syslog(LOG_DEBUG, "imap: ----- %ld params", Cmd->num_parms);
if (Imap->num_msgs > 0) {
for (i = 0; i < Imap->num_msgs; ++i) {
- /* Abort the fetch loop if the session breaks.
- * This is important for users who keep mailboxes
- * that are too big *and* are too impatient to
- * let them finish loading. :)
- */
+ // Abort the fetch loop if the session breaks.
+ // This is important for users who keep mailboxes
+ // that are too big *and* are too impatient to
+ // let them finish loading. :)
if (CC->kill_me) return;
- /* Get any message marked for fetch. */
+ // Get any message marked for fetch.
if (Imap->flags[i] & IMAP_SELECTED) {
imap_do_fetch_msg(i+1, Cmd);
}
}
-
-/*
- * Back end for imap_handle_macros()
- * Note that this function *only* looks at the beginning of the string. It
- * is not a generic search-and-replace function.
- */
+// Back end for imap_handle_macros()
+// Note that this function *only* looks at the beginning of the string. It
+// is not a generic search-and-replace function.
void imap_macro_replace(StrBuf *Buf, long where,
StrBuf *TmpBuf,
char *find, long findlen,
- char *replace, long replacelen)
-{
-
- if (StrLength(Buf) - where > findlen)
+ char *replace, long replacelen
+) {
+ if (StrLength(Buf) - where > findlen) {
return;
+ }
if (!strncasecmp(ChrPtr(Buf) + where, find, findlen)) {
if (ChrPtr(Buf)[where + findlen] == ' ') {
StrBufPlain(TmpBuf, replace, replacelen);
StrBufAppendBufPlain(TmpBuf, HKEY(" "), 0);
- StrBufReplaceToken(Buf, where, findlen,
- SKEY(TmpBuf));
+ StrBufReplaceToken(Buf, where, findlen, SKEY(TmpBuf));
}
if (where + findlen == StrLength(Buf)) {
- StrBufReplaceToken(Buf, where, findlen,
- replace, replacelen);
+ StrBufReplaceToken(Buf, where, findlen, replace, replacelen);
}
}
}
-
-/*
- * Handle macros embedded in FETCH data items.
- * (What the heck are macros doing in a wire protocol? Are we trying to save
- * the computer at the other end the trouble of typing a lot of characters?)
- */
+// Handle macros embedded in FETCH data items.
+// (What the heck are macros doing in a wire protocol? Are we trying to save
+// the computer at the other end the trouble of typing a lot of characters?)
void imap_handle_macros(citimap_command *Cmd) {
long i;
int nest = 0;
}
-/*
- * Break out the data items requested, possibly a parenthesized list.
- * Returns the number of data items, or -1 if the list is invalid.
- * NOTE: this function alters the string it is fed, and uses it as a buffer
- * to hold the data for the pointers it returns.
- */
-int imap_extract_data_items(citimap_command *Cmd)
-{
+// Break out the data items requested, possibly a parenthesized list.
+// Returns the number of data items, or -1 if the list is invalid.
+// NOTE: this function alters the string it is fed, and uses it as a buffer
+// to hold the data for the pointers it returns.
+int imap_extract_data_items(citimap_command *Cmd) {
int nArgs;
int nest = 0;
const char *pch, *end;
- /* Convert all whitespace to ordinary space characters. */
+ // Convert all whitespace to ordinary space characters.
pch = ChrPtr(Cmd->CmdBuf);
end = pch + StrLength(Cmd->CmdBuf);
- while (pch < end)
- {
+ while (pch < end) {
if (isspace(*pch))
StrBufPeek(Cmd->CmdBuf, pch, 0, ' ');
pch++;
}
- /* Strip leading and trailing whitespace, then strip leading and
- * trailing parentheses if it's a list
- */
+ // Strip leading and trailing whitespace, then strip leading and trailing parentheses if it's a list
StrBufTrim(Cmd->CmdBuf);
pch = ChrPtr(Cmd->CmdBuf);
- if ( (pch[0]=='(') &&
- (pch[StrLength(Cmd->CmdBuf)-1]==')') )
- {
+ if ( (pch[0]=='(') && (pch[StrLength(Cmd->CmdBuf)-1]==')') ) {
StrBufCutRight(Cmd->CmdBuf, 1);
StrBufCutLeft(Cmd->CmdBuf, 1);
StrBufTrim(Cmd->CmdBuf);
}
- /* Parse any macro data items */
+ // Parse any macro data items
imap_handle_macros(Cmd);
- /*
- * Now break out the data items. We throw in one trailing space in
- * order to avoid having to break out the last one manually.
- */
+ // Now break out the data items.
+ // We throw in one trailing space in order to avoid having to break out the last one manually.
nArgs = StrLength(Cmd->CmdBuf) / 10 + 10;
nArgs = CmdAdjust(Cmd, nArgs, 0);
Cmd->num_parms = 0;
Cmd->Params[Cmd->num_parms].Key = pch = ChrPtr(Cmd->CmdBuf);
end = Cmd->Params[Cmd->num_parms].Key + StrLength(Cmd->CmdBuf);
- while (pch < end)
- {
+ while (pch < end) {
if ((*pch=='(') ||
(*pch=='[') ||
(*pch=='<') ||
}
-/*
- * One particularly hideous aspect of IMAP is that we have to allow the client
- * to specify arbitrary ranges and/or sets of messages to fetch. Citadel IMAP
- * handles this by setting the IMAP_SELECTED flag for each message specified in
- * the ranges/sets, then looping through the message array, outputting messages
- * with the flag set. We don't bother returning an error if an out-of-range
- * number is specified (we just return quietly) because any client braindead
- * enough to request a bogus message number isn't going to notice the
- * difference anyway.
- *
- * This function clears out the IMAP_SELECTED bits, then sets that bit for each
- * message included in the specified range.
- *
- * Set is_uid to 1 to fetch by UID instead of sequence number.
- */
+// One particularly hideous aspect of IMAP is that we have to allow the client
+// to specify arbitrary ranges and/or sets of messages to fetch. Citadel IMAP
+// handles this by setting the IMAP_SELECTED flag for each message specified in
+// the ranges/sets, then looping through the message array, outputting messages
+// with the flag set. We don't bother returning an error if an out-of-range
+// number is specified (we just return quietly) because any client braindead
+// enough to request a bogus message number isn't going to notice the
+// difference anyway.
+//
+// This function clears out the IMAP_SELECTED bits, then sets that bit for each
+// message included in the specified range.
+//
+// Set is_uid to 1 to fetch by UID instead of sequence number.
void imap_pick_range(const char *supplied_range, int is_uid) {
citimap *Imap = IMAP;
int i;
long lo, hi;
char actual_range[SIZ];
- /*
- * Handle the "ALL" macro
- */
+ // Handle the "ALL" macro
if (!strcasecmp(supplied_range, "ALL")) {
safestrncpy(actual_range, "1:*", sizeof actual_range);
}
safestrncpy(actual_range, supplied_range, sizeof actual_range);
}
- /*
- * Clear out the IMAP_SELECTED flags for all messages.
- */
+ // Clear out the IMAP_SELECTED flags for all messages.
for (i = 0; i < Imap->num_msgs; ++i) {
Imap->flags[i] = Imap->flags[i] & ~IMAP_SELECTED;
}
- /*
- * Now set it for all specified messages.
- */
+ // Now set it for all specified messages.
num_sets = num_tokens(actual_range, ',');
for (s=0; s<num_sets; ++s) {
extract_token(setstr, actual_range, s, ',', sizeof setstr);
lo = atol(lostr);
hi = atol(histr);
- /* Loop through the array, flipping bits where appropriate */
+ // Loop through the array, flipping bits where appropriate
for (i = 1; i <= Imap->num_msgs; ++i) {
- if (is_uid) { /* fetch by sequence number */
+ if (is_uid) { // fetch by sequence number
if ( (Imap->msgids[i-1]>=lo)
&& (Imap->msgids[i-1]<=hi)) {
Imap->flags[i-1] |= IMAP_SELECTED;
}
}
- else { /* fetch by uid */
+ else { // fetch by uid
if ( (i>=lo) && (i<=hi)) {
Imap->flags[i-1] |= IMAP_SELECTED;
}
}
-
-/*
- * This function is called by the main command loop.
- */
+// This function is called by the main command loop.
void imap_fetch(int num_parms, ConstStr *Params) {
citimap_command Cmd;
int num_items;
free(Cmd.Params);
}
-/*
- * This function is called by the main command loop.
- */
+
+// This function is called by the main command loop.
void imap_uidfetch(int num_parms, ConstStr *Params) {
citimap_command Cmd;
int num_items;
return;
}
- /* If the "UID" item was not included, we include it implicitly
- * (at the beginning) because this is a UID FETCH command
- */
+ // If the "UID" item was not included, we include it implicitly
+ // (at the beginning) because this is a UID FETCH command
for (i=0; i<num_items; ++i) {
if (!strcasecmp(Cmd.Params[i].Key, "UID")) ++have_uid_item;
}
FreeStrBuf(&Cmd.CmdBuf);
free(Cmd.Params);
}
-
-