-/* $Id$ */
+/*
+ * $Id$
+ *
+ * Implements the message store.
+ *
+ */
#include "sysdep.h"
#include <stdlib.h>
{
int i;
- for (i = 0; i < strlen(name); ++i)
+ for (i = 0; i < strlen(name); ++i) {
if (name[i] == '@') {
- if (i > 0)
- if (isspace(name[i - 1])) {
- strcpy(&name[i - 1], &name[i]);
- i = 0;
- }
+ while (isspace(name[i - 1]) && i > 0) {
+ strcpy(&name[i - 1], &name[i]);
+ --i;
+ }
while (isspace(name[i + 1])) {
strcpy(&name[i + 1], &name[i + 2]);
}
}
+ }
}
strcpy(bbb, &bbb[1]);
fp = fopen("network/mail.sysinfo", "r");
if (fp == NULL)
- return (MES_ERROR);
+ return (MES_ERROR);
GETSN: do {
a = getstring(fp, aaa);
} while ((a >= 0) && (strcasecmp(aaa, bbb)));
-void simple_listing(long msgnum)
+void simple_listing(long msgnum, void *userdata)
{
cprintf("%ld\n", msgnum);
}
/*
* API function to perform an operation for each qualifying message in the
- * current room.
+ * current room. (Returns the number of messages processed.)
*/
-void CtdlForEachMessage(int mode, long ref,
+int CtdlForEachMessage(int mode, long ref,
+ int moderation_level,
char *content_type,
struct CtdlMessage *compare,
- void (*CallBack) (long msgnum))
+ void (*CallBack) (long, void *),
+ void *userdata)
{
int a;
struct cdbdata *cdbfr;
long *msglist = NULL;
int num_msgs = 0;
+ int num_processed = 0;
long thismsg;
struct SuppMsgInfo smi;
struct CtdlMessage *msg;
num_msgs = cdbfr->len / sizeof(long);
cdb_free(cdbfr);
} else {
- return; /* No messages at all? No further action. */
+ return 0; /* No messages at all? No further action. */
}
- /* If the caller is looking for a specific MIME type, then filter
- * out all messages which are not of the type requested.
- */
- if (num_msgs > 0)
- if (content_type != NULL)
- if (strlen(content_type) > 0)
- for (a = 0; a < num_msgs; ++a) {
- GetSuppMsgInfo(&smi, msglist[a]);
- if (strcasecmp(smi.smi_content_type, content_type)) {
- msglist[a] = 0L;
- }
- }
+ if (num_msgs > 0) for (a = 0; a < num_msgs; ++a) {
+ GetSuppMsgInfo(&smi, msglist[a]);
+
+ /* Filter out messages that are moderated below the level
+ * currently being viewed at.
+ */
+ if (smi.smi_mod < moderation_level) {
+ msglist[a] = 0L;
+ }
+
+ /* If the caller is looking for a specific MIME type, filter
+ * out all messages which are not of the type requested.
+ */
+ if (content_type != NULL) if (strlen(content_type) > 0) {
+ if (strcasecmp(smi.smi_content_type, content_type)) {
+ msglist[a] = 0L;
+ }
+ }
+ }
num_msgs = sort_msglist(msglist, num_msgs);
|| ((mode == MSGS_LAST) && (a >= (num_msgs - ref)))
|| ((mode == MSGS_FIRST) && (a < ref))
|| ((mode == MSGS_GT) && (thismsg > ref))
+ || ((mode == MSGS_EQ) && (thismsg == ref))
)
) {
- CallBack(thismsg);
+ if (CallBack) CallBack(thismsg, userdata);
+ ++num_processed;
}
}
phree(msglist); /* Clean up */
+ return num_processed;
}
void cmd_msgs(char *cmdbuf)
{
int mode = 0;
- char which[256];
- char buf[256];
- char tfield[256];
- char tvalue[256];
+ char which[SIZ];
+ char buf[SIZ];
+ char tfield[SIZ];
+ char tvalue[SIZ];
int cm_ref = 0;
int i;
int with_template = 0;
cprintf("%d Message list...\n", LISTING_FOLLOWS);
}
- CtdlForEachMessage(mode, cm_ref, NULL, template, simple_listing);
+ CtdlForEachMessage(mode, cm_ref,
+ CC->usersupp.moderation_filter,
+ NULL, template, simple_listing, NULL);
if (template != NULL) CtdlFreeMessage(template);
cprintf("000\n");
}
*/
void help_subst(char *strbuf, char *source, char *dest)
{
- char workbuf[256];
+ char workbuf[SIZ];
int p;
while (p = pattern2(strbuf, source), (p >= 0)) {
int old = 0;
CIT_UBYTE ch;
char aaa[140];
- char buffer[256];
+ char buffer[SIZ];
strcpy(aaa, "");
old = 255;
strcpy(buffer, "");
c = 1; /* c is the current pos */
-FMTA: if (subst) {
- while (ch = *mptr, ((ch != 0) && (strlen(buffer) < 126))) {
- ch = *mptr++;
- buffer[strlen(buffer) + 1] = 0;
- buffer[strlen(buffer)] = ch;
- }
+ do {
+ if (subst) {
+ while (ch = *mptr, ((ch != 0) && (strlen(buffer) < 126))) {
+ ch = *mptr++;
+ buffer[strlen(buffer) + 1] = 0;
+ buffer[strlen(buffer)] = ch;
+ }
- if (buffer[0] == '^')
- do_help_subst(buffer);
+ if (buffer[0] == '^')
+ do_help_subst(buffer);
- buffer[strlen(buffer) + 1] = 0;
- a = buffer[0];
- strcpy(buffer, &buffer[1]);
- } else {
- ch = *mptr++;
- }
-
- old = real;
- real = ch;
- if (ch <= 0)
- goto FMTEND;
+ buffer[strlen(buffer) + 1] = 0;
+ a = buffer[0];
+ strcpy(buffer, &buffer[1]);
+ } else {
+ ch = *mptr++;
+ }
- if (((ch == 13) || (ch == 10)) && (old != 13) && (old != 10))
- ch = 32;
- if (((old == 13) || (old == 10)) && (isspace(real))) {
- cprintf("%s", nl);
- c = 1;
- }
- if (ch > 126)
- goto FMTA;
+ old = real;
+ real = ch;
- if (ch > 32) {
- if (((strlen(aaa) + c) > (width - 5)) && (strlen(aaa) > (width - 5))) {
- cprintf("%s%s", nl, aaa);
- c = strlen(aaa);
- aaa[0] = 0;
- }
- b = strlen(aaa);
- aaa[b] = ch;
- aaa[b + 1] = 0;
- }
- if (ch == 32) {
- if ((strlen(aaa) + c) > (width - 5)) {
+ if (((ch == 13) || (ch == 10)) && (old != 13) && (old != 10))
+ ch = 32;
+ if (((old == 13) || (old == 10)) && (isspace(real))) {
cprintf("%s", nl);
c = 1;
}
- cprintf("%s ", aaa);
- ++c;
- c = c + strlen(aaa);
- strcpy(aaa, "");
- goto FMTA;
- }
- if ((ch == 13) || (ch == 10)) {
- cprintf("%s%s", aaa, nl);
- c = 1;
- strcpy(aaa, "");
- goto FMTA;
- }
- goto FMTA;
+ if (ch > 126)
+ continue;
+
+ if (ch > 32) {
+ if (((strlen(aaa) + c) > (width - 5)) && (strlen(aaa) > (width - 5))) {
+ cprintf("%s%s", nl, aaa);
+ c = strlen(aaa);
+ aaa[0] = 0;
+ }
+ b = strlen(aaa);
+ aaa[b] = ch;
+ aaa[b + 1] = 0;
+ }
+ if (ch == 32) {
+ if ((strlen(aaa) + c) > (width - 5)) {
+ cprintf("%s", nl);
+ c = 1;
+ }
+ cprintf("%s ", aaa);
+ ++c;
+ c = c + strlen(aaa);
+ strcpy(aaa, "");
+ }
+ if ((ch == 13) || (ch == 10)) {
+ cprintf("%s%s", aaa, nl);
+ c = 1;
+ strcpy(aaa, "");
+ }
-FMTEND: cprintf("%s%s", aaa, nl);
+ } while (ch > 0);
+
+ cprintf("%s%s", aaa, nl);
}
* Callback function for mime parser that simply lists the part
*/
void list_this_part(char *name, char *filename, char *partnum, char *disp,
- void *content, char *cbtype, size_t length)
+ void *content, char *cbtype, size_t length, char *encoding,
+ void *cbuserdata)
{
cprintf("part=%s|%s|%s|%s|%s|%d\n",
* Callback function for mime parser that opens a section for downloading
*/
void mime_download(char *name, char *filename, char *partnum, char *disp,
- void *content, char *cbtype, size_t length)
+ void *content, char *cbtype, size_t length, char *encoding,
+ void *cbuserdata)
{
/* Silently go away if there's already a download open... */
if (is_valid_message(msg) == 0) return;
- for (i = 0; i < 256; ++i)
+ for (i = 0; i < SIZ; ++i)
if (msg->cm_fields[i] != NULL) {
phree(msg->cm_fields[i]);
}
* Callback function for mime parser that wants to display text
*/
void fixed_output(char *name, char *filename, char *partnum, char *disp,
- void *content, char *cbtype, size_t length)
+ void *content, char *cbtype, size_t length, char *encoding,
+ void *cbuserdata)
{
char *ptr;
char *wptr;
int do_proto, /* do Citadel protocol responses? */
int crlf /* Use CRLF newlines instead of LF? */
) {
- int i, k;
- char buf[1024];
- CIT_UBYTE ch;
- char allkeys[256];
- char display_name[256];
struct CtdlMessage *TheMessage;
- char *mptr;
- char *nl; /* newline string */
-
- /* buffers needed for RFC822 translation */
- char suser[256];
- char luser[256];
- char fuser[256];
- char snode[256];
- char lnode[256];
- char mid[256];
- char datestamp[256];
- /* */
+ int retcode;
lprintf(7, "CtdlOutputMsg() msgnum=%ld, mode=%d\n",
msg_num, mode);
TheMessage = NULL;
- sprintf(mid, "%ld", msg_num);
- nl = (crlf ? "\r\n" : "\n");
if ((!(CC->logged_in)) && (!(CC->internal_pgm))) {
if (do_proto) cprintf("%d Not logged in.\n",
ERROR, msg_num);
return(om_no_such_msg);
}
+
+ retcode = CtdlOutputPreLoadedMsg(
+ TheMessage, msg_num, mode,
+ headers_only, do_proto, crlf);
+
+ CtdlFreeMessage(TheMessage);
+ return(retcode);
+}
+
+
+/*
+ * Get a message off disk. (returns om_* values found in msgbase.h)
+ *
+ */
+int CtdlOutputPreLoadedMsg(struct CtdlMessage *TheMessage,
+ long msg_num,
+ 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 i, k;
+ char buf[1024];
+ CIT_UBYTE ch;
+ char allkeys[SIZ];
+ char display_name[SIZ];
+ char *mptr;
+ char *nl; /* newline string */
+
+ /* buffers needed for RFC822 translation */
+ char suser[SIZ];
+ char luser[SIZ];
+ char fuser[SIZ];
+ char snode[SIZ];
+ char lnode[SIZ];
+ char mid[SIZ];
+ char datestamp[SIZ];
+ /* */
+
+ sprintf(mid, "%ld", msg_num);
+ nl = (crlf ? "\r\n" : "\n");
+
+ if (!is_valid_message(TheMessage)) {
+ lprintf(1, "ERROR: invalid preloaded message for output\n");
+ return(om_no_such_msg);
+ }
/* Are we downloading a MIME component? */
if (mode == MT_DOWNLOAD) {
} else {
/* Parse the message text component */
mptr = TheMessage->cm_fields['M'];
- mime_parser(mptr, NULL, *mime_download);
+ mime_parser(mptr, NULL, *mime_download, NULL, 0);
/* If there's no file open by this time, the requested
* section wasn't found, so print an error
*/
desired_section);
}
}
- CtdlFreeMessage(TheMessage);
return((CC->download_fp != NULL) ? om_ok : om_mime_error);
}
strcpy(lnode, HUMANNODE);
if (mode == MT_RFC822) {
cprintf("X-UIDL: %ld%s", msg_num, nl);
- for (i = 0; i < 256; ++i) {
+ for (i = 0; i < SIZ; ++i) {
if (TheMessage->cm_fields[i]) {
mptr = TheMessage->cm_fields[i];
else if (i == 'R')
cprintf("To: %s%s", mptr, nl);
else if (i == 'T') {
- generate_rfc822_datestamp(datestamp,
- atol(mptr) );
+ datestring(datestamp, atol(mptr),
+ DATESTRING_RFC822 );
cprintf("Date: %s%s", datestamp, nl);
}
}
/* Tell the client about the MIME parts in this message */
if (TheMessage->cm_format_type == FMT_RFC822) {
if (mode == MT_CITADEL) {
- mime_parser(mptr, NULL, *list_this_part);
+ mime_parser(mptr, NULL, *list_this_part, NULL, 0);
}
else if (mode == MT_MIME) { /* list parts only */
- mime_parser(mptr, NULL, *list_this_part);
+ mime_parser(mptr, NULL, *list_this_part, NULL, 0);
if (do_proto) cprintf("000\n");
- CtdlFreeMessage(TheMessage);
return(om_ok);
}
else if (mode == MT_RFC822) { /* unparsed RFC822 dump */
else cprintf("%c", ch);
}
if (do_proto) cprintf("000\n");
- CtdlFreeMessage(TheMessage);
return(om_ok);
}
}
if (headers_only) {
if (do_proto) cprintf("000\n");
- CtdlFreeMessage(TheMessage);
return(om_ok);
}
if (TheMessage->cm_format_type == FMT_RFC822) {
CtdlAllocUserData(SYM_MA_INFO, sizeof(struct ma_info));
memset(ma, 0, sizeof(struct ma_info));
- mime_parser(mptr, NULL, *fixed_output);
+ mime_parser(mptr, NULL, *fixed_output, NULL, 0);
}
/* now we're done */
if (do_proto) cprintf("000\n");
- CtdlFreeMessage(TheMessage);
return(om_ok);
}
{
long msgid;
- CtdlAllocUserData(SYM_DESIRED_SECTION, 64);
+ CtdlAllocUserData(SYM_DESIRED_SECTION, SIZ);
msgid = extract_long(cmdbuf, 0);
extract(desired_section, cmdbuf, 1);
{
long newmsgid;
long retval;
- char msgidbuf[256];
+ char msgidbuf[SIZ];
struct ser_ret smr;
/* Get a new message number */
/*
* Back end for the ReplicationChecks() function
*/
-void check_repl(long msgnum) {
+void check_repl(long msgnum, void *userdata) {
struct CtdlMessage *msg;
time_t timestamp = (-1L);
lprintf(9, "older!\n");
/* Existing isn't newer? Then delete the old one(s). */
- CtdlDeleteMessages(CC->quickroom.QRname, msgnum, NULL);
+ CtdlDeleteMessages(CC->quickroom.QRname, msgnum, "");
}
memset(template, 0, sizeof(struct CtdlMessage));
template->cm_fields['E'] = strdoop(msg->cm_fields['E']);
- CtdlForEachMessage(MSGS_ALL, 0L, NULL, template, check_repl);
+ CtdlForEachMessage(MSGS_ALL, 0L, (-127), NULL, template,
+ check_repl, NULL);
/* If a newer message exists with the same Extended ID, abort
* this save.
char hold_rm[ROOMNAMELEN];
char actual_rm[ROOMNAMELEN];
char force_room[ROOMNAMELEN];
- char content_type[256]; /* We have to learn this */
- char recipient[256];
+ char content_type[SIZ]; /* We have to learn this */
+ char recipient[SIZ];
long newmsgid;
char *mptr = NULL;
struct usersupp userbuf;
/* advance past header fields */
mptr = msg->cm_fields['M'];
a = strlen(mptr);
- while (--a) {
+ while ((--a) > 0) {
if (!strncasecmp(mptr, "Content-type: ", 14)) {
safestrncpy(content_type, mptr,
sizeof(content_type));
char *exist /* if non-null, append to it;
exist is ALWAYS freed */
) {
- char buf[256];
+ char buf[SIZ];
+ int linelen;
size_t message_len = 0;
size_t buffer_len = 0;
- char *ptr, *append;
+ char *ptr;
char *m;
if (exist == NULL) {
message_len = 0;
}
/* read in the lines of message text one by one */
- append = NULL;
while ( (client_gets(buf)>0) && strcmp(buf, terminator) ) {
+ /* strip trailing newline type stuff */
+ if (buf[strlen(buf)-1]==10) buf[strlen(buf)-1]=0;
+ if (buf[strlen(buf)-1]==13) buf[strlen(buf)-1]=0;
+
+ linelen = strlen(buf);
+
/* augment the buffer if we have to */
- if ((message_len + strlen(buf) + 2) > buffer_len) {
+ if ((message_len + linelen + 2) > buffer_len) {
lprintf(9, "realloking\n");
ptr = reallok(m, (buffer_len * 2) );
if (ptr == NULL) { /* flush if can't allocate */
} else {
buffer_len = (buffer_len * 2);
m = ptr;
- append = NULL;
lprintf(9, "buffer_len is %d\n", buffer_len);
}
}
- if (append == NULL) append = m;
- while (strlen(append) > 0) ++append;
- strcpy(append, buf);
- strcat(append, "\n");
- message_len = message_len + strlen(buf) + 1;
+ /* Add the new line to the buffer. We avoid using strcat()
+ * because that would involve traversing the entire message
+ * after each line, and this function needs to run fast.
+ */
+ strcpy(&m[message_len], buf);
+ m[message_len + linelen] = '\n';
+ m[message_len + linelen + 1] = 0;
+ message_len = message_len + linelen + 1;
/* if we've hit the max msg length, flush the rest */
if (message_len >= maxlen) {
- while ( (client_gets(buf)>0) && strcmp(buf, terminator)) ;;
+ while ( (client_gets(buf)>0)
+ && strcmp(buf, terminator)) ;;
return(m);
}
}
int a;
char dest_node[32];
- char buf[256];
+ char buf[SIZ];
struct CtdlMessage *msg;
msg = mallok(sizeof(struct CtdlMessage));
void cmd_ent0(char *entargs)
{
int post = 0;
- char recipient[256];
+ char recipient[SIZ];
int anon_flag = 0;
int format_type = 0;
- char newusername[256];
+ char newusername[SIZ];
struct CtdlMessage *msg;
int a, b;
int e = 0;
int mtsflag = 0;
struct usersupp tempUS;
- char buf[256];
+ char buf[SIZ];
post = extract_int(entargs, 0);
extract(recipient, entargs, 1);
}
if (!strcasecmp(buf, "sysop")) {
mtsflag = 1;
- goto SKFALL;
}
- if (e != MES_LOCAL)
- goto SKFALL; /* don't search local file */
- if (!strcasecmp(buf, CC->usersupp.fullname)) {
- cprintf("%d Can't send mail to yourself!\n",
- ERROR + NO_SUCH_USER);
- return;
- }
- /* Check to make sure the user exists; also get the correct
- * upper/lower casing of the name.
- */
- a = getuser(&tempUS, buf);
- if (a != 0) {
- cprintf("%d No such user.\n", ERROR + NO_SUCH_USER);
- return;
+ else if (e == MES_LOCAL) { /* don't search local file */
+ if (!strcasecmp(buf, CC->usersupp.fullname)) {
+ cprintf("%d Can't send mail to yourself!\n",
+ ERROR + NO_SUCH_USER);
+ return;
+ }
+ /* Check to make sure the user exists; also get the correct
+ * upper/lower casing of the name.
+ */
+ a = getuser(&tempUS, buf);
+ if (a != 0) {
+ cprintf("%d No such user.\n", ERROR + NO_SUCH_USER);
+ return;
+ }
+ strcpy(buf, tempUS.fullname);
}
- strcpy(buf, tempUS.fullname);
}
-SKFALL: b = MES_NORMAL;
+ b = MES_NORMAL;
if (CC->quickroom.QRflags & QR_ANONONLY)
b = MES_ANON;
if (CC->quickroom.QRflags & QR_ANONOPT) {
*/
void cmd_ent3(char *entargs)
{
- char recp[256];
+ char recp[SIZ];
int a;
int e = 0;
int valid_msg = 1;
*/
int CtdlDeleteMessages(char *room_name, /* which room */
long dmsgnum, /* or "0" for any */
- char *content_type /* or NULL for any */
+ char *content_type /* or "" for any */
)
{
if ((dmsgnum == 0L) || (msglist[i] == dmsgnum)) {
delete_this |= 0x01;
}
- if (content_type == NULL) {
+ if (strlen(content_type) == 0) {
delete_this |= 0x02;
} else {
GetSuppMsgInfo(&smi, msglist[i]);
}
delnum = extract_long(delstr, 0);
- num_deleted = CtdlDeleteMessages(CC->quickroom.QRname, delnum, NULL);
+ num_deleted = CtdlDeleteMessages(CC->quickroom.QRname, delnum, "");
if (num_deleted) {
cprintf("%d %d message%s deleted.\n", OK,
void cmd_move(char *args)
{
long num;
- char targ[256];
+ char targ[SIZ];
struct quickroom qtemp;
int err;
int is_copy = 0;
/* Now delete the message from the source room,
* if this is a 'move' rather than a 'copy' operation.
*/
- if (is_copy == 0) CtdlDeleteMessages(CC->quickroom.QRname, num, NULL);
+ if (is_copy == 0) CtdlDeleteMessages(CC->quickroom.QRname, num, "");
cprintf("%d Message %s.\n", OK, (is_copy ? "copied" : "moved") );
}
FILE *fp, *tempfp;
char filename[PATH_MAX];
- char cmdbuf[256];
+ char cmdbuf[SIZ];
char ch;
struct quickroom qrbuf;
char roomname[ROOMNAMELEN];
-void CtdlGetSysConfigBackend(long msgnum) {
+void CtdlGetSysConfigBackend(long msgnum, void *userdata) {
config_msgnum = msgnum;
}
long msgnum;
char *conf;
struct CtdlMessage *msg;
- char buf[256];
+ char buf[SIZ];
strcpy(hold_rm, CC->quickroom.QRname);
if (getroom(&CC->quickroom, SYSCONFIGROOM) != 0) {
/* We want the last (and probably only) config in this room */
begin_critical_section(S_CONFIG);
config_msgnum = (-1L);
- CtdlForEachMessage(MSGS_LAST, 1, sysconfname, NULL,
- CtdlGetSysConfigBackend);
+ CtdlForEachMessage(MSGS_LAST, 1, (-127), sysconfname, NULL,
+ CtdlGetSysConfigBackend, NULL);
msgnum = config_msgnum;
end_critical_section(S_CONFIG);