+ buf[buflen] = '\0';
+ if (!IsEmptyStr(buf))
+ cprintf("%s%s", buf, nl);
+}
+
+/*
+ * Get a message off disk. (returns om_* values found in msgbase.h)
+ */
+int CtdlOutputPreLoadedMsg(
+ struct CtdlMessage *TheMessage,
+ 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 flags /* should the bessage be exported clean? */
+) {
+ int i;
+ char *mptr = NULL;
+ const char *nl; /* newline string */
+ struct ma_info ma;
+
+ /* Buffers needed for RFC822 translation. These are all filled
+ * using functions that are bounds-checked, and therefore we can
+ * make them substantially smaller than SIZ.
+ */
+ char suser[100];
+ char luser[100];
+ char fuser[100];
+ char snode[100];
+ char mid[100];
+
+ syslog(LOG_DEBUG, "CtdlOutputPreLoadedMsg(TheMessage=%s, %d, %d, %d, %d\n",
+ ((TheMessage == NULL) ? "NULL" : "not null"),
+ mode, headers_only, do_proto, crlf);
+
+ strcpy(mid, "unknown");
+ nl = (crlf ? "\r\n" : "\n");
+
+ if (!is_valid_message(TheMessage)) {
+ syslog(LOG_ERR,
+ "ERROR: invalid preloaded message for output\n");
+ cit_backtrace ();
+ return(om_no_such_msg);
+ }
+
+ /* Suppress envelope recipients if required to avoid disclosing BCC addresses.
+ * Pad it with spaces in order to avoid changing the RFC822 length of the message.
+ */
+ if ( (flags & SUPPRESS_ENV_TO) && (TheMessage->cm_fields['V'] != NULL) ) {
+ memset(TheMessage->cm_fields['V'], ' ', strlen(TheMessage->cm_fields['V']));
+ }
+
+ /* Are we downloading a MIME component? */
+ if (mode == MT_DOWNLOAD) {
+ if (TheMessage->cm_format_type != FMT_RFC822) {
+ if (do_proto)
+ cprintf("%d This is not a MIME message.\n",
+ ERROR + ILLEGAL_VALUE);
+ } else if (CC->download_fp != NULL) {
+ if (do_proto) cprintf(
+ "%d You already have a download open.\n",
+ ERROR + RESOURCE_BUSY);
+ } else {
+ /* Parse the message text component */
+ mptr = TheMessage->cm_fields['M'];
+ mime_parser(mptr, NULL, *mime_download, NULL, NULL, NULL, 0);
+ /* If there's no file open by this time, the requested
+ * section wasn't found, so print an error
+ */
+ if (CC->download_fp == NULL) {
+ 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);
+ }
+
+ /* 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);
+
+ /* Does the caller want to skip the headers? */
+ if (headers_only == HEADERS_NONE) goto START_TEXT;
+
+ /* Tell the client which format type we're using. */
+ if ( (mode == MT_CITADEL) && (do_proto) ) {
+ cprintf("type=%d\n", TheMessage->cm_format_type);
+ }
+
+ /* nhdr=yes means that we're only displaying headers, no body */
+ if ( (TheMessage->cm_anon_type == MES_ANONONLY)
+ && ((mode == MT_CITADEL) || (mode == MT_MIME))
+ && (do_proto)
+ ) {
+ cprintf("nhdr=yes\n");
+ }
+
+ if ((mode == MT_CITADEL) || (mode == MT_MIME))
+ OutputCtdlMsgHeaders(TheMessage, do_proto);
+
+
+ /* begin header processing loop for RFC822 transfer format */
+ strcpy(suser, "");
+ strcpy(luser, "");
+ strcpy(fuser, "");
+ strcpy(snode, NODENAME);
+ if (mode == MT_RFC822)
+ OutputRFC822MsgHeaders(
+ TheMessage,
+ flags,
+ nl,
+ mid, sizeof(mid),
+ suser, sizeof(suser),
+ luser, sizeof(luser),
+ fuser, sizeof(fuser),
+ snode, sizeof(snode)
+ );
+