/*
- * $Id$
- *
* Implements the message store.
- *
+ *
* Copyright (c) 1987-2010 by the citadel.org team
*
- * This program is free 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 free 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.
+ * 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.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "sysdep.h"
return;
}
- cprintf("%ld|%s|\n", msgnum, (msg->cm_fields['E'] ? msg->cm_fields['E'] : ""));
+ cprintf("%ld|%s|%s\n",
+ msgnum,
+ (msg->cm_fields['E'] ? msg->cm_fields['E'] : ""),
+ (msg->cm_fields['T'] ? msg->cm_fields['T'] : "0"));
CtdlFreeMessage(msg);
}
* Retrieve the "seen" message list for the current room.
*/
void CtdlGetSeen(char *buf, int which_set) {
- struct visit vbuf;
+ visit vbuf;
/* Learn about the user and room in question */
CtdlGetRelationship(&vbuf, &CC->user, &CC->room);
int was_seen = 0;
long lo = (-1L);
long hi = (-1L);
- struct visit vbuf;
+ visit vbuf;
long *msglist;
int num_msgs = 0;
StrBuf *vset;
{
int a, i, j;
- struct visit vbuf;
+ visit vbuf;
struct cdbdata *cdbfr;
long *msglist = NULL;
int num_msgs = 0;
char search_string[1024];
ForEachMsgCallback CallBack;
+ if (CtdlAccessCheck(ac_logged_in_or_guest)) return;
+
extract_token(which, cmdbuf, 0, '|', sizeof which);
cm_ref = extract_int(cmdbuf, 1);
extract_token(search_string, cmdbuf, 1, '|', sizeof search_string);
else
mode = MSGS_ALL;
- if ((!(CC->logged_in)) && (!(CC->internal_pgm))) {
- cprintf("%d not logged in\n", ERROR + NOT_LOGGED_IN);
- return;
- }
-
if ( (mode == MSGS_SEARCH) && (!config.c_enable_fulltext) ) {
cprintf("%d Full text index is not enabled on this server.\n",
ERROR + CMD_NOT_SUPPORTED);
*/
void memfmout(
char *mptr, /* where are we going to get our text from? */
- const char *nl) /* string to terminate lines with */
-{
- StrBuf *OutBuf;
- char *LineStart;
- char *LastBlank;
- size_t len;
- size_t NLLen;
- char *eptr;
- int NLFound, NLFoundLastTime;
- int Found;
-
- len = strlen (mptr);
- NLLen = strlen (nl);
- eptr = mptr + len;
-
- OutBuf = NewStrBufPlain(NULL, 200);
-
- NLFound = NLFoundLastTime = 0;
- do {
- size_t i;
-
- LineStart = LastBlank = mptr;
- Found = 'x';
- i = 0;
- while (Found == 'x')
- {
- if (LineStart[i] == '\n')
- Found = '\n';
- else if (LineStart[i] == '\r')
- Found = '\r';
- else if (LineStart[i] == ' ')
- {
- LastBlank = &LineStart[i];
- i++;
+ const char *nl /* string to terminate lines with */
+) {
+ int column = 0;
+ unsigned char ch = 0;
+ char outbuf[1024];
+ int len = 0;
+ int nllen = 0;
+
+ if (!mptr) return;
+ nllen = strlen(nl);
+ while (ch=*(mptr++), ch != 0) {
+
+ if (ch == '\n') {
+ client_write(outbuf, len);
+ len = 0;
+ client_write(nl, nllen);
+ column = 0;
+ }
+ else if (ch == '\r') {
+ /* Ignore carriage returns. Newlines are always LF or CRLF but never CR. */
+ }
+ else if (isspace(ch)) {
+ if (column > 72) { /* Beyond 72 columns, break on the next space */
+ client_write(outbuf, len);
+ len = 0;
+ client_write(nl, nllen);
+ column = 0;
+ }
+ else {
+ outbuf[len++] = ch;
+ ++column;
}
- else if ((i > 80) && (LineStart != LastBlank))
- Found = ' ';
- else if (LineStart[i] == '\0')
- Found = '\0';
- else i++;
}
- switch (Found)
- {
- case '\n':
- if (LineStart[i + 1] == '\r')
- mptr = &LineStart[i + 2];
- else
- mptr = &LineStart[i + 1];
- i--;
- NLFound = 1;
- break;
- case '\r':
- if (LineStart[i + 1] == '\n')
- mptr = &LineStart[i + 2];
- else
- mptr = &LineStart[i + 1];
- i--;
- NLFound = 1;
- break;
- case '\0':
- mptr = &LineStart[i + 1];
- i--;
- NLFound = 0;
- break;
- case ' ':
- mptr = LastBlank + 1;
- i = LastBlank - LineStart;
- NLFound = 0;
- break;
- case 'x':
- /* WHUT? */
- while (*mptr != '\0') mptr++;
- break;
+ else {
+ outbuf[len++] = ch;
+ ++column;
+ if (column > 1000) { /* Beyond 1000 columns, break anywhere */
+ client_write(outbuf, len);
+ len = 0;
+ client_write(nl, nllen);
+ column = 0;
+ }
}
- if (NLFoundLastTime)
- StrBufPlain(OutBuf, HKEY(" "));
- else
- FlushStrBuf(OutBuf);
- StrBufAppendBufPlain(OutBuf, LineStart, i, 0);
- StrBufAppendBufPlain(OutBuf, nl, NLLen, 0);
-
- cputbuf(OutBuf);
- NLFoundLastTime = NLFound;
- } while (*mptr != '\0');
-
- FreeStrBuf(&OutBuf);
+ }
+ if (len) {
+ client_write(outbuf, len);
+ len = 0;
+ client_write(nl, nllen);
+ column = 0;
+ }
}
if ( (ret->cm_fields['M'] == NULL) && (with_body) ) {
dmsgtext = cdb_fetch(CDB_BIGMSGS, &msgnum, sizeof(long));
if (dmsgtext != NULL) {
- ret->cm_fields['M'] = strdup(dmsgtext->ptr);
+ ret->cm_fields['M'] = dmsgtext->ptr;
+ dmsgtext->ptr = NULL;
cdb_free(dmsgtext);
}
}
char *qp_encode_email_addrs(char *source)
{
- char user[256], node[256], name[256];
+ char *user, *node, *name;
const char headerStr[] = "=?UTF-8?Q?";
char *Encoded;
char *EncodedName;
if (source == NULL) return source;
if (IsEmptyStr(source)) return source;
+ cit_backtrace();
+ CtdlLogPrintf(CTDL_DEBUG, "qp_encode_email_addrs: [%s]\n", source);
AddrPtr = malloc (sizeof (long) * nAddrPtrMax);
AddrUtf8 = malloc (sizeof (long) * nAddrPtrMax);
for (i = 0; i < nColons; i++)
source[AddrPtr[i]++] = '\0';
+ /* TODO: if libidn, this might get larger*/
+ user = malloc(SourceLen + 1);
+ node = malloc(SourceLen + 1);
+ name = malloc(SourceLen + 1);
nPtr = Encoded;
*nPtr = '\0';
}
for (i = 0; i < nColons; i++)
source[--AddrPtr[i]] = ',';
+
+ free(user);
+ free(node);
+ free(name);
free(AddrUtf8);
free(AddrPtr);
return Encoded;
}
+void OutputCtdlMsgHeaders(
+ struct CtdlMessage *TheMessage,
+ int do_proto) /* do Citadel protocol responses? */
+{
+ char allkeys[30];
+ int i, k, n;
+ int suppress_f = 0;
+ char buf[SIZ];
+ char display_name[256];
+
+ /* begin header processing loop for Citadel message format */
+ safestrncpy(display_name, "<unknown>", sizeof display_name);
+ if (TheMessage->cm_fields['A']) {
+ strcpy(buf, TheMessage->cm_fields['A']);
+ if (TheMessage->cm_anon_type == MES_ANONONLY) {
+ safestrncpy(display_name, "****", sizeof display_name);
+ }
+ else if (TheMessage->cm_anon_type == MES_ANONOPT) {
+ safestrncpy(display_name, "anonymous", sizeof display_name);
+ }
+ else {
+ safestrncpy(display_name, buf, sizeof display_name);
+ }
+ if ((is_room_aide())
+ && ((TheMessage->cm_anon_type == MES_ANONONLY)
+ || (TheMessage->cm_anon_type == MES_ANONOPT))) {
+ size_t tmp = strlen(display_name);
+ snprintf(&display_name[tmp],
+ sizeof display_name - tmp,
+ " [%s]", buf);
+ }
+ }
+
+ /* Don't show Internet address for users on the
+ * local Citadel network.
+ */
+ suppress_f = 0;
+ if (TheMessage->cm_fields['N'] != NULL)
+ if (!IsEmptyStr(TheMessage->cm_fields['N']))
+ if (haschar(TheMessage->cm_fields['N'], '.') == 0) {
+ suppress_f = 1;
+ }
+
+ /* Now spew the header fields in the order we like them. */
+ n = safestrncpy(allkeys, FORDER, sizeof allkeys);
+ for (i=0; i<n; ++i) {
+ k = (int) allkeys[i];
+ if (k != 'M') {
+ if ( (TheMessage->cm_fields[k] != NULL)
+ && (msgkeys[k] != NULL) ) {
+ if ((k == 'V') || (k == 'R') || (k == 'Y')) {
+ sanitize_truncated_recipient(TheMessage->cm_fields[k]);
+ }
+ if (k == 'A') {
+ if (do_proto) cprintf("%s=%s\n",
+ msgkeys[k],
+ display_name);
+ }
+ else if ((k == 'F') && (suppress_f)) {
+ /* do nothing */
+ }
+ /* Masquerade display name if needed */
+ else {
+ if (do_proto) cprintf("%s=%s\n",
+ msgkeys[k],
+ TheMessage->cm_fields[k]
+ );
+ }
+ }
+ }
+ }
+
+}
+
+void OutputRFC822MsgHeaders(
+ struct CtdlMessage *TheMessage,
+ int flags, /* should the bessage be exported clean */
+ const char *nl,
+ char *mid, long sizeof_mid,
+ char *suser, long sizeof_suser,
+ char *luser, long sizeof_luser,
+ char *fuser, long sizeof_fuser,
+ char *snode, long sizeof_snode)
+{
+ char datestamp[100];
+ int subject_found = 0;
+ char buf[SIZ];
+ int i, j, k;
+ char *mptr = NULL;
+ char *mpptr = NULL;
+
+ for (i = 0; i < 256; ++i) {
+ if (TheMessage->cm_fields[i]) {
+ mptr = mpptr = TheMessage->cm_fields[i];
+
+ if (i == 'A') {
+ safestrncpy(luser, mptr, sizeof_luser);
+ safestrncpy(suser, mptr, sizeof_suser);
+ }
+ else if (i == 'Y') {
+ if ((flags & QP_EADDR) != 0) {
+ mptr = qp_encode_email_addrs(mptr);
+ }
+ sanitize_truncated_recipient(mptr);
+ cprintf("CC: %s%s", mptr, nl);
+ }
+ else if (i == 'P') {
+ cprintf("Return-Path: %s%s", mptr, nl);
+ }
+ else if (i == 'L') {
+ cprintf("List-ID: %s%s", mptr, nl);
+ }
+ else if (i == 'V') {
+ if ((flags & QP_EADDR) != 0)
+ mptr = qp_encode_email_addrs(mptr);
+ cprintf("Envelope-To: %s%s", mptr, nl);
+ }
+ else if (i == 'U') {
+ cprintf("Subject: %s%s", mptr, nl);
+ subject_found = 1;
+ }
+ else if (i == 'I')
+ safestrncpy(mid, mptr, sizeof_mid); /// TODO: detect @ here and copy @nodename in if not found.
+ else if (i == 'F')
+ safestrncpy(fuser, mptr, sizeof_fuser);
+ /* else if (i == 'O')
+ cprintf("X-Citadel-Room: %s%s",
+ mptr, nl); */
+ else if (i == 'N')
+ safestrncpy(snode, mptr, sizeof_snode);
+ else if (i == 'R')
+ {
+ if (haschar(mptr, '@') == 0)
+ {
+ sanitize_truncated_recipient(mptr);
+ cprintf("To: %s@%s", mptr, config.c_fqdn);
+ cprintf("%s", nl);
+ }
+ else
+ {
+ if ((flags & QP_EADDR) != 0) {
+ mptr = qp_encode_email_addrs(mptr);
+ }
+ sanitize_truncated_recipient(mptr);
+ cprintf("To: %s", mptr);
+ cprintf("%s", nl);
+ }
+ }
+ else if (i == 'T') {
+ datestring(datestamp, sizeof datestamp,
+ atol(mptr), DATESTRING_RFC822);
+ cprintf("Date: %s%s", datestamp, nl);
+ }
+ else if (i == 'W') {
+ cprintf("References: ");
+ k = num_tokens(mptr, '|');
+ for (j=0; j<k; ++j) {
+ extract_token(buf, mptr, j, '|', sizeof buf);
+ cprintf("<%s>", buf);
+ if (j == (k-1)) {
+ cprintf("%s", nl);
+ }
+ else {
+ cprintf(" ");
+ }
+ }
+ }
+ else if (i == 'K') {
+ cprintf("Reply-To: <%s>%s", mptr, nl);
+ }
+ if (mptr != mpptr)
+ free (mptr);
+ }
+ }
+ if (subject_found == 0) {
+ cprintf("Subject: (no subject)%s", nl);
+ }
+}
+
+
+void Dump_RFC822HeadersBody(
+ struct CtdlMessage *TheMessage,
+ int headers_only, /* eschew the message body? */
+ int flags, /* should the bessage be exported clean? */
+
+ const char *nl)
+{
+ cit_uint8_t prev_ch;
+ int eoh = 0;
+ const char *StartOfText = StrBufNOTNULL;
+ char outbuf[1024];
+ int outlen = 0;
+ int nllen = strlen(nl);
+ char *mptr;
+
+ mptr = TheMessage->cm_fields['M'];
+
+
+ prev_ch = '\0';
+ while (*mptr != '\0') {
+ if (*mptr == '\r') {
+ /* do nothing */
+ }
+ else {
+ if ((!eoh) &&
+ (*mptr == '\n'))
+ {
+ eoh = (*(mptr+1) == '\r') && (*(mptr+2) == '\n');
+ if (!eoh)
+ eoh = *(mptr+1) == '\n';
+ if (eoh)
+ {
+ StartOfText = mptr;
+ StartOfText = strchr(StartOfText, '\n');
+ StartOfText = strchr(StartOfText, '\n');
+ }
+ }
+ if (((headers_only == HEADERS_NONE) && (mptr >= StartOfText)) ||
+ ((headers_only == HEADERS_ONLY) && (mptr < StartOfText)) ||
+ ((headers_only != HEADERS_NONE) &&
+ (headers_only != HEADERS_ONLY))
+ ) {
+ if (*mptr == '\n') {
+ memcpy(&outbuf[outlen], nl, nllen);
+ outlen += nllen;
+ outbuf[outlen] = '\0';
+ }
+ else {
+ outbuf[outlen++] = *mptr;
+ }
+ }
+ }
+ if (flags & ESC_DOT)
+ {
+ if ((prev_ch == '\n') &&
+ (*mptr == '.') &&
+ ((*(mptr+1) == '\r') || (*(mptr+1) == '\n')))
+ {
+ outbuf[outlen++] = '.';
+ }
+ prev_ch = *mptr;
+ }
+ ++mptr;
+ if (outlen > 1000) {
+ client_write(outbuf, outlen);
+ outlen = 0;
+ }
+ }
+ if (outlen > 0) {
+ client_write(outbuf, outlen);
+ outlen = 0;
+ }
+}
+
+
+
+/* If the format type on disk is 1 (fixed-format), then we want
+ * everything to be output completely literally ... regardless of
+ * what message transfer format is in use.
+ */
+void DumpFormatFixed(
+ struct CtdlMessage *TheMessage,
+ int mode, /* how would you like that message? */
+ const char *nl)
+{
+ cit_uint8_t ch;
+ char buf[SIZ];
+ int buflen;
+ int xlline = 0;
+ int nllen = strlen (nl);
+ char *mptr;
+
+ mptr = TheMessage->cm_fields['M'];
+
+ if (mode == MT_MIME) {
+ cprintf("Content-type: text/plain\n\n");
+ }
+ *buf = '\0';
+ buflen = 0;
+ while (ch = *mptr++, ch > 0) {
+ if (ch == '\n')
+ ch = '\r';
+
+ if ((buflen > 250) && (!xlline)){
+ int tbuflen;
+ tbuflen = buflen;
+
+ while ((buflen > 0) &&
+ (!isspace(buf[buflen])))
+ buflen --;
+ if (buflen == 0) {
+ xlline = 1;
+ }
+ else {
+ mptr -= tbuflen - buflen;
+ buf[buflen] = '\0';
+ ch = '\r';
+ }
+ }
+ /* if we reach the outer bounds of our buffer,
+ abort without respect what whe purge. */
+ if (xlline &&
+ ((isspace(ch)) ||
+ (buflen > SIZ - nllen - 2)))
+ ch = '\r';
+
+ if (ch == '\r') {
+ memcpy (&buf[buflen], nl, nllen);
+ buflen += nllen;
+ buf[buflen] = '\0';
+
+ client_write(buf, buflen);
+ *buf = '\0';
+ buflen = 0;
+ xlline = 0;
+ } else {
+ buf[buflen] = ch;
+ buflen++;
+ }
+ }
+ buf[buflen] = '\0';
+ if (!IsEmptyStr(buf))
+ cprintf("%s%s", buf, nl);
+}
/*
* Get a message off disk. (returns om_* values found in msgbase.h)
int crlf, /* Use CRLF newlines instead of LF? */
int flags /* should the bessage be exported clean? */
) {
- int i, j, k;
- char buf[SIZ];
- cit_uint8_t ch, prev_ch;
- char allkeys[30];
- char display_name[256];
- char *mptr, *mpptr;
+ int i;
+ char *mptr = NULL;
const char *nl; /* newline string */
- int suppress_f = 0;
- int subject_found = 0;
struct ma_info ma;
/* Buffers needed for RFC822 translation. These are all filled
char fuser[100];
char snode[100];
char mid[100];
- char datestamp[100];
CtdlLogPrintf(CTDL_DEBUG, "CtdlOutputPreLoadedMsg(TheMessage=%s, %d, %d, %d, %d\n",
((TheMessage == NULL) ? "NULL" : "not null"),
cprintf("nhdr=yes\n");
}
- /* begin header processing loop for Citadel message format */
-
- if ((mode == MT_CITADEL) || (mode == MT_MIME)) {
-
- safestrncpy(display_name, "<unknown>", sizeof display_name);
- if (TheMessage->cm_fields['A']) {
- strcpy(buf, TheMessage->cm_fields['A']);
- if (TheMessage->cm_anon_type == MES_ANONONLY) {
- safestrncpy(display_name, "****", sizeof display_name);
- }
- else if (TheMessage->cm_anon_type == MES_ANONOPT) {
- safestrncpy(display_name, "anonymous", sizeof display_name);
- }
- else {
- safestrncpy(display_name, buf, sizeof display_name);
- }
- if ((is_room_aide())
- && ((TheMessage->cm_anon_type == MES_ANONONLY)
- || (TheMessage->cm_anon_type == MES_ANONOPT))) {
- size_t tmp = strlen(display_name);
- snprintf(&display_name[tmp],
- sizeof display_name - tmp,
- " [%s]", buf);
- }
- }
-
- /* Don't show Internet address for users on the
- * local Citadel network.
- */
- suppress_f = 0;
- if (TheMessage->cm_fields['N'] != NULL)
- if (!IsEmptyStr(TheMessage->cm_fields['N']))
- if (haschar(TheMessage->cm_fields['N'], '.') == 0) {
- suppress_f = 1;
- }
+ if ((mode == MT_CITADEL) || (mode == MT_MIME))
+ OutputCtdlMsgHeaders(TheMessage, do_proto);
- /* Now spew the header fields in the order we like them. */
- safestrncpy(allkeys, FORDER, sizeof allkeys);
- for (i=0; i<strlen(allkeys); ++i) {
- k = (int) allkeys[i];
- if (k != 'M') {
- if ( (TheMessage->cm_fields[k] != NULL)
- && (msgkeys[k] != NULL) ) {
- if ((k == 'V') || (k == 'R') || (k == 'Y')) {
- sanitize_truncated_recipient(TheMessage->cm_fields[k]);
- }
- if (k == 'A') {
- if (do_proto) cprintf("%s=%s\n",
- msgkeys[k],
- display_name);
- }
- else if ((k == 'F') && (suppress_f)) {
- /* do nothing */
- }
- /* Masquerade display name if needed */
- else {
- if (do_proto) cprintf("%s=%s\n",
- msgkeys[k],
- TheMessage->cm_fields[k]
- );
- }
- }
- }
- }
-
- }
/* begin header processing loop for RFC822 transfer format */
-
strcpy(suser, "");
strcpy(luser, "");
strcpy(fuser, "");
strcpy(snode, NODENAME);
- if (mode == MT_RFC822) {
- for (i = 0; i < 256; ++i) {
- if (TheMessage->cm_fields[i]) {
- mptr = mpptr = TheMessage->cm_fields[i];
-
- if (i == 'A') {
- safestrncpy(luser, mptr, sizeof luser);
- safestrncpy(suser, mptr, sizeof suser);
- }
- else if (i == 'Y') {
- if ((flags & QP_EADDR) != 0) {
- mptr = qp_encode_email_addrs(mptr);
- }
- sanitize_truncated_recipient(mptr);
- cprintf("CC: %s%s", mptr, nl);
- }
- else if (i == 'P') {
- cprintf("Return-Path: %s%s", mptr, nl);
- }
- else if (i == 'L') {
- cprintf("List-ID: %s%s", mptr, nl);
- }
- else if (i == 'V') {
- if ((flags & QP_EADDR) != 0)
- mptr = qp_encode_email_addrs(mptr);
- cprintf("Envelope-To: %s%s", mptr, nl);
- }
- else if (i == 'U') {
- cprintf("Subject: %s%s", mptr, nl);
- subject_found = 1;
- }
- else if (i == 'I')
- safestrncpy(mid, mptr, sizeof mid);
- else if (i == 'F')
- safestrncpy(fuser, mptr, sizeof fuser);
- /* else if (i == 'O')
- cprintf("X-Citadel-Room: %s%s",
- mptr, nl); */
- else if (i == 'N')
- safestrncpy(snode, mptr, sizeof snode);
- else if (i == 'R')
- {
- if (haschar(mptr, '@') == 0)
- {
- sanitize_truncated_recipient(mptr);
- cprintf("To: %s@%s", mptr, config.c_fqdn);
- cprintf("%s", nl);
- }
- else
- {
- if ((flags & QP_EADDR) != 0) {
- mptr = qp_encode_email_addrs(mptr);
- }
- sanitize_truncated_recipient(mptr);
- cprintf("To: %s", mptr);
- cprintf("%s", nl);
- }
- }
- else if (i == 'T') {
- datestring(datestamp, sizeof datestamp,
- atol(mptr), DATESTRING_RFC822);
- cprintf("Date: %s%s", datestamp, nl);
- }
- else if (i == 'W') {
- cprintf("References: ");
- k = num_tokens(mptr, '|');
- for (j=0; j<k; ++j) {
- extract_token(buf, mptr, j, '|', sizeof buf);
- cprintf("<%s>", buf);
- if (j == (k-1)) {
- cprintf("%s", nl);
- }
- else {
- cprintf(" ");
- }
- }
- }
- if (mptr != mpptr)
- free (mptr);
- }
- }
- if (subject_found == 0) {
- cprintf("Subject: (no subject)%s", nl);
- }
- }
+ if (mode == MT_RFC822)
+ OutputRFC822MsgHeaders(
+ TheMessage,
+ flags,
+ nl,
+ mid, sizeof(mid),
+ suser, sizeof(suser),
+ luser, sizeof(luser),
+ fuser, sizeof(fuser),
+ snode, sizeof(snode)
+ );
+
for (i=0; !IsEmptyStr(&suser[i]); ++i) {
suser[i] = tolower(suser[i]);
/* end header processing loop ... at this point, we're in the text */
START_TEXT:
if (headers_only == HEADERS_FAST) goto DONE;
- mptr = TheMessage->cm_fields['M'];
/* Tell the client about the MIME parts in this message */
if (TheMessage->cm_format_type == FMT_RFC822) {
if ( (mode == MT_CITADEL) || (mode == MT_MIME) ) {
+ mptr = TheMessage->cm_fields['M'];
memset(&ma, 0, sizeof(struct ma_info));
mime_parser(mptr, NULL,
(do_proto ? *list_this_part : NULL),
(void *)&ma, 0);
}
else if (mode == MT_RFC822) { /* unparsed RFC822 dump */
- char *start_of_text = NULL;
- start_of_text = strstr(mptr, "\n\r\n");
- if (start_of_text == NULL) start_of_text = strstr(mptr, "\n\n");
- if (start_of_text == NULL) start_of_text = mptr;
- ++start_of_text;
- start_of_text = strstr(start_of_text, "\n");
- ++start_of_text;
-
- char outbuf[1024];
- int outlen = 0;
- int nllen = strlen(nl);
- prev_ch = 0;
- while (ch=*mptr, ch!=0) {
- if (ch==13) {
- /* do nothing */
- }
- else {
- if (
- ((headers_only == HEADERS_NONE) && (mptr >= start_of_text))
- || ((headers_only == HEADERS_ONLY) && (mptr < start_of_text))
- || ((headers_only != HEADERS_NONE) && (headers_only != HEADERS_ONLY))
- ) {
- if (ch == 10) {
- sprintf(&outbuf[outlen], "%s", nl);
- outlen += nllen;
- }
- else {
- outbuf[outlen++] = ch;
- }
- }
- }
- if (flags & ESC_DOT)
- {
- if ((prev_ch == 10) && (ch == '.') && ((*(mptr+1) == 13) || (*(mptr+1) == 10)))
- {
- outbuf[outlen++] = '.';
- }
- }
- prev_ch = ch;
- ++mptr;
- if (outlen > 1000) {
- client_write(outbuf, outlen);
- outlen = 0;
- }
- }
- if (outlen > 0) {
- client_write(outbuf, outlen);
- outlen = 0;
- }
-
+ Dump_RFC822HeadersBody(
+ TheMessage,
+ headers_only,
+ flags,
+ nl);
goto DONE;
}
}
if (do_proto) cprintf("text\n");
}
- /* If the format type on disk is 1 (fixed-format), then we want
- * everything to be output completely literally ... regardless of
- * what message transfer format is in use.
- */
- if (TheMessage->cm_format_type == FMT_FIXED) {
- int buflen;
- int xlline = 0;
- int nllen = strlen (nl);
- if (mode == MT_MIME) {
- cprintf("Content-type: text/plain\n\n");
- }
- *buf = '\0';
- buflen = 0;
- while (ch = *mptr++, ch > 0) {
- if (ch == '\n')
- ch = '\r';
-
- if ((buflen > 250) && (!xlline)){
- int tbuflen;
- tbuflen = buflen;
-
- while ((buflen > 0) &&
- (!isspace(buf[buflen])))
- buflen --;
- if (buflen == 0) {
- xlline = 1;
- }
- else {
- mptr -= tbuflen - buflen;
- buf[buflen] = '\0';
- ch = '\r';
- }
- }
- /* if we reach the outer bounds of our buffer,
- abort without respect what whe purge. */
- if (xlline &&
- ((isspace(ch)) ||
- (buflen > SIZ - nllen - 2)))
- ch = '\r';
-
- if (ch == '\r') {
- memcpy (&buf[buflen], nl, nllen);
- buflen += nllen;
- buf[buflen] = '\0';
-
- client_write(buf, buflen);
- *buf = '\0';
- buflen = 0;
- xlline = 0;
- } else {
- buf[buflen] = ch;
- buflen++;
- }
- }
- buf[buflen] = '\0';
- if (!IsEmptyStr(buf))
- cprintf("%s%s", buf, nl);
- }
+ if (TheMessage->cm_format_type == FMT_FIXED)
+ DumpFormatFixed(
+ TheMessage,
+ mode, /* how would you like that message? */
+ nl);
/* If the message on disk is format 0 (Citadel vari-format), we
* output using the formatter at 80 columns. This is the final output
* message to the reader's screen width.
*/
if (TheMessage->cm_format_type == FMT_CITADEL) {
+ mptr = TheMessage->cm_fields['M'];
+
if (mode == MT_MIME) {
cprintf("Content-type: text/x-citadel-variformat\n\n");
}
}
-
/*
* display a message (mode 0 - Citadel proprietary)
*/
* this mode of operation only works if we're saving a single message.)
*/
int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newmsgs,
- int do_repl_check, struct CtdlMessage *supplied_msg)
-{
+ int do_repl_check, struct CtdlMessage *supplied_msg, int suppress_refcount_adj
+) {
int i, j, unique;
char hold_rm[ROOMNAMELEN];
struct cdbdata *cdbfr;
int num_msgs_to_be_merged = 0;
CtdlLogPrintf(CTDL_DEBUG,
- "CtdlSaveMsgPointersInRoom(room=%s, num_msgs=%d, repl=%d)\n",
- roomname, num_newmsgs, do_repl_check);
+ "CtdlSaveMsgPointersInRoom(room=%s, num_msgs=%d, repl=%d, suppress_rca=%d)\n",
+ roomname, num_newmsgs, do_repl_check, suppress_refcount_adj
+ );
strcpy(hold_rm, CC->room.QRname);
CtdlGetRoom(&CC->room, hold_rm);
/* Bump the reference count for all messages which were merged */
- for (i=0; i<num_msgs_to_be_merged; ++i) {
- AdjRefCount(msgs_to_be_merged[i], +1);
+ if (!suppress_refcount_adj) {
+ for (i=0; i<num_msgs_to_be_merged; ++i) {
+ AdjRefCount(msgs_to_be_merged[i], +1);
+ }
}
/* Free up memory... */
int CtdlSaveMsgPointerInRoom(char *roomname, long msgid,
int do_repl_check, struct CtdlMessage *supplied_msg)
{
- return CtdlSaveMsgPointersInRoom(roomname, &msgid, 1, do_repl_check, supplied_msg);
+ return CtdlSaveMsgPointersInRoom(roomname, &msgid, 1, do_repl_check, supplied_msg, 0);
}
char content_type[SIZ]; /* We have to learn this */
char recipient[SIZ];
long newmsgid;
- char *mptr = NULL;
+ const char *mptr = NULL;
struct ctdluser userbuf;
int a, i;
struct MetaData smi;
char *hold_R, *hold_D;
char *collected_addresses = NULL;
struct addresses_to_be_filed *aptr = NULL;
- char *saved_rfc822_version = NULL;
+ StrBuf *saved_rfc822_version = NULL;
int qualified_for_journaling = 0;
- CitContext *CCC = CC; /* CachedCitContext - performance boost */
+ CitContext *CCC = MyContext();
char bounce_to[1024] = "";
size_t tmp = 0;
int rv = 0;
/* If the user is a twit, move to the twit room for posting */
if (TWITDETECT) {
- if (CCC->user.axlevel == 2) {
+ if (CCC->user.axlevel == AxProbU) {
strcpy(hold_rm, actual_rm);
strcpy(actual_rm, config.c_twitroom);
CtdlLogPrintf(CTDL_DEBUG, "Diverting to twit room\n");
CtdlLogPrintf(CTDL_ALERT, "CCC->redirect_buffer is not NULL during message submission!\n");
abort();
}
- CCC->redirect_buffer = malloc(SIZ);
- CCC->redirect_len = 0;
- CCC->redirect_alloc = SIZ;
+ CCC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1, QP_EADDR);
- smi.meta_rfc822_length = CCC->redirect_len;
+ smi.meta_rfc822_length = StrLength(CCC->redirect_buffer);
saved_rfc822_version = CCC->redirect_buffer;
CCC->redirect_buffer = NULL;
- CCC->redirect_len = 0;
- CCC->redirect_alloc = 0;
PutMetaData(&smi);
JournalBackgroundSubmit(msg, saved_rfc822_version, recps);
}
else {
- free(saved_rfc822_version);
+ FreeStrBuf(&saved_rfc822_version);
}
}
}
- if ((CC->user.axlevel < 2)
+ if ((CC->user.axlevel < AxProbU)
&& ((CC->room.QRflags & QR_MAILBOX) == 0)) {
snprintf(errmsgbuf, n, "Need to be validated to enter "
"(except in %s> to sysop)", MAILROOM);
int CtdlCheckInternetMailPermission(struct ctdluser *who) {
/* Do not allow twits to send Internet mail */
- if (who->axlevel <= 2) return(0);
+ if (who->axlevel <= AxProbU) return(0);
/* Globally enabled? */
if (config.c_restrict == 0) return(1);
if (who->flags & US_INTERNET) return(2);
/* Aide level access? */
- if (who->axlevel >= 6) return(3);
+ if (who->axlevel >= AxAideU) return(3);
/* No mail for you! */
return(0);
*
* Caller needs to free the result using free_recipients()
*/
-struct recptypes *validate_recipients(char *supplied_recipients,
+struct recptypes *validate_recipients(const char *supplied_recipients,
const char *RemoteIdentifier,
int Flags) {
struct recptypes *ret;
if (IsEmptyStr(newusername)) {
strcpy(newusername, CC->user.fullname);
}
- if ( (CC->user.axlevel < 6)
+ if ( (CC->user.axlevel < AxAideU)
&& (strcasecmp(newusername, CC->user.fullname))
&& (strcasecmp(newusername, CC->cs_inet_fn))
) {
if ( ( (CC->room.QRflags & QR_MAILBOX) && (!strcasecmp(&CC->room.QRname[11], MAILROOM)) )
|| ( (CC->room.QRflags & QR_MAILBOX) && (CC->curr_view == VIEW_MAILBOX) )
) {
- if (CC->user.axlevel < 2) {
+ if (CC->user.axlevel < AxProbU) {
strcpy(recp, "sysop");
strcpy(cc, "");
strcpy(bcc, "");
}
if ( ( (valid_to->num_internet + valid_to->num_ignet + valid_cc->num_internet + valid_cc->num_ignet + valid_bcc->num_internet + valid_bcc->num_ignet) > 0)
- && (CC->user.axlevel < 4) ) {
+ && (CC->user.axlevel < AxNetU) ) {
cprintf("%d Higher access required for network mail.\n",
ERROR + HIGHER_ACCESS_REQUIRED);
free_recipients(valid_to);
permit = 0;
/* Aides can move/copy */
- if (CC->user.axlevel >= 6) permit = 1;
+ if (CC->user.axlevel >= AxAideU) permit = 1;
/* Room aides can move/copy */
if (CC->user.usernum == CC->room.QRroomaide) permit = 1;
/*
* Do the copy
*/
- err = CtdlSaveMsgPointersInRoom(targ, msgs, num_msgs, 1, NULL);
+ err = CtdlSaveMsgPointersInRoom(targ, msgs, num_msgs, 1, NULL, 0);
if (err != 0) {
cprintf("%d Cannot store message(s) in %s: error %d\n",
err, targ, err);
struct arcq new_arcq;
int rv = 0;
+ CtdlLogPrintf(CTDL_DEBUG, "AdjRefCount() msg %ld ref count delta %+d\n",
+ msgnum, incr
+ );
+
begin_critical_section(S_SUPPMSGMAIN);
if (arcfp == NULL) {
arcfp = fopen(file_arcq, "ab+");
smi.meta_refcount += incr;
PutMetaData(&smi);
end_critical_section(S_SUPPMSGMAIN);
- CtdlLogPrintf(CTDL_DEBUG, "msg %ld ref count delta %+d, is now %d\n",
- msgnum, incr, smi.meta_refcount);
+ CtdlLogPrintf(CTDL_DEBUG, "TDAP_AdjRefCount() msg %ld ref count delta %+d, is now %d\n",
+ msgnum, incr, smi.meta_refcount
+ );
/* If the reference count is now zero, delete the message
* (and its supplementary record as well).
}
/* return our Subversion id for the Log */
- return "$Id$";
+ return "msgbase";
}