X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmsgbase.c;h=ccee9818d2574549e63cd821cc49a1a3c0ff6ade;hb=6eb43187a82c686ce1855d15b7ba8485d1c461bb;hp=15fbd3993b02c2f031e069207882d6a096147a6c;hpb=c6696c37e50f7c75adcf79e561ba97f55977b072;p=citadel.git diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 15fbd3993..ccee9818d 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -45,7 +45,6 @@ #include "file_ops.h" #include "config.h" #include "control.h" -#include "html.h" #include "genstamp.h" #include "internet_addressing.h" #include "euidindex.h" @@ -101,7 +100,7 @@ char *msgkeys[] = { "time", "subj", NULL, - NULL, + "wefw", NULL, "cccc", NULL @@ -183,7 +182,7 @@ int alias(char *name) } if (strcasecmp(original_name, name)) { - lprintf(CTDL_INFO, "%s is being forwarded to %s\n", original_name, name); + CtdlLogPrintf(CTDL_INFO, "%s is being forwarded to %s\n", original_name, name); } /* Change "user @ xxx" to "user" if xxx is an alias for this host */ @@ -191,7 +190,7 @@ int alias(char *name) if (name[a] == '@') { if (CtdlHostAlias(&name[a+1]) == hostalias_localhost) { name[a] = 0; - lprintf(CTDL_INFO, "Changed to <%s>\n", name); + CtdlLogPrintf(CTDL_INFO, "Changed to <%s>\n", name); } } } @@ -357,7 +356,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, return; } - lprintf(CTDL_DEBUG, "CtdlSetSeen(%d msgs starting with %ld, %d, %d)\n", + CtdlLogPrintf(CTDL_DEBUG, "CtdlSetSeen(%d msgs starting with %ld, %d, %d)\n", num_target_msgnums, target_msgnums[0], target_setting, which_set); @@ -391,7 +390,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, break; } - /* lprintf(CTDL_DEBUG, "before optimize: %s\n", vset); */ + /* CtdlLogPrintf(CTDL_DEBUG, "before optimize: %s\n", vset); */ /* Translate the existing sequence set into an array of booleans */ num_sets = num_tokens(vset, ','); @@ -490,7 +489,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, } free(is_set); - /* lprintf(CTDL_DEBUG, " after optimize: %s\n", vset); */ + /* CtdlLogPrintf(CTDL_DEBUG, " after optimize: %s\n", vset); */ free(msglist); CtdlSetRelationship(&vbuf, ((which_user != NULL) ? which_user : &CC->user), @@ -745,7 +744,7 @@ void cmd_msgs(char *cmdbuf) template->cm_magic = CTDLMESSAGE_MAGIC; template->cm_anon_type = MES_NORMAL; - while(client_getln(buf, sizeof buf), strcmp(buf,"000")) { + while(client_getln(buf, sizeof buf) >= 0 && strcmp(buf,"000")) { extract_token(tfield, buf, 0, '|', sizeof tfield); extract_token(tvalue, buf, 1, '|', sizeof tvalue); for (i='A'; i<='Z'; ++i) if (msgkeys[i]!=NULL) { @@ -806,7 +805,7 @@ void do_help_subst(char *buffer) help_subst(buffer, "^variantname", CITADEL); snprintf(buf2, sizeof buf2, "%d", config.c_maxsessions); help_subst(buffer, "^maxsessions", buf2); - help_subst(buffer, "^bbsdir", ctdl_bbsbase_dir); + help_subst(buffer, "^bbsdir", ctdl_message_dir); } @@ -1017,7 +1016,7 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) cit_uint8_t ch; cit_uint8_t field_header; - lprintf(CTDL_DEBUG, "CtdlFetchMessage(%ld, %d)\n", msgnum, with_body); + CtdlLogPrintf(CTDL_DEBUG, "CtdlFetchMessage(%ld, %d)\n", msgnum, with_body); dmsgtext = cdb_fetch(CDB_MSGMAIN, &msgnum, sizeof(long)); if (dmsgtext == NULL) { @@ -1033,7 +1032,7 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body) */ ch = *mptr++; if (ch != 255) { - lprintf(CTDL_ERR, "Message %ld appears to be corrupted.\n", msgnum); + CtdlLogPrintf(CTDL_ERR, "Message %ld appears to be corrupted.\n", msgnum); cdb_free(dmsgtext); return NULL; } @@ -1096,7 +1095,7 @@ int is_valid_message(struct CtdlMessage *msg) { if (msg == NULL) return 0; if ((msg->cm_magic) != CTDLMESSAGE_MAGIC) { - lprintf(CTDL_WARNING, "is_valid_message() -- self-check failed\n"); + CtdlLogPrintf(CTDL_WARNING, "is_valid_message() -- self-check failed\n"); return 0; } return 1; @@ -1143,7 +1142,7 @@ void fixed_output_pre(char *name, char *filename, char *partnum, char *disp, struct ma_info *ma; ma = (struct ma_info *)cbuserdata; - lprintf(CTDL_DEBUG, "fixed_output_pre() type=<%s>\n", cbtype); + CtdlLogPrintf(CTDL_DEBUG, "fixed_output_pre() type=<%s>\n", cbtype); if (!strcasecmp(cbtype, "multipart/alternative")) { ++ma->is_ma; ma->did_print = 0; @@ -1163,7 +1162,7 @@ void fixed_output_post(char *name, char *filename, char *partnum, char *disp, struct ma_info *ma; ma = (struct ma_info *)cbuserdata; - lprintf(CTDL_DEBUG, "fixed_output_post() type=<%s>\n", cbtype); + CtdlLogPrintf(CTDL_DEBUG, "fixed_output_post() type=<%s>\n", cbtype); if (!strcasecmp(cbtype, "multipart/alternative")) { --ma->is_ma; ma->did_print = 0; @@ -1187,7 +1186,7 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp, ma = (struct ma_info *)cbuserdata; - lprintf(CTDL_DEBUG, + CtdlLogPrintf(CTDL_DEBUG, "fixed_output() part %s: %s (%s) (%ld bytes)\n", partnum, filename, cbtype, (long)length); @@ -1196,7 +1195,7 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp, * we've already printed another section, skip this one. */ if ( (ma->is_ma) && (ma->did_print) ) { - lprintf(CTDL_DEBUG, "Skipping part %s (%s)\n", partnum, cbtype); + CtdlLogPrintf(CTDL_DEBUG, "Skipping part %s (%s)\n", partnum, cbtype); return; } ma->did_print = 1; @@ -1268,7 +1267,7 @@ void choose_preferred(char *name, char *filename, char *partnum, char *disp, extract_token(buf, CC->preferred_formats, i, '|', sizeof buf); if ( (!strcasecmp(buf, cbtype)) && (!ma->freeze) ) { if (i < ma->chosen_pref) { - lprintf(CTDL_DEBUG, "Setting chosen part: <%s>\n", partnum); + CtdlLogPrintf(CTDL_DEBUG, "Setting chosen part: <%s>\n", partnum); safestrncpy(ma->chosen_part, partnum, sizeof ma->chosen_part); ma->chosen_pref = i; } @@ -1369,17 +1368,18 @@ void extract_encapsulated_message(char *name, char *filename, char *partnum, cha * */ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ - 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? */ - char *section /* NULL or a message/rfc822 section */ + 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? */ + char *section, /* NULL or a message/rfc822 section */ + int flags /* should the bessage be exported clean? */ ) { struct CtdlMessage *TheMessage = NULL; int retcode = om_no_such_msg; struct encapmsg encap; - lprintf(CTDL_DEBUG, "CtdlOutputMsg() msgnum=%ld, mode=%d, section=%s\n", + CtdlLogPrintf(CTDL_DEBUG, "CtdlOutputMsg() msgnum=%ld, mode=%d, section=%s\n", msg_num, mode, (section ? section : "<>") ); @@ -1445,13 +1445,129 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ } /* Ok, output the message now */ - retcode = CtdlOutputPreLoadedMsg(TheMessage, mode, headers_only, do_proto, crlf); + retcode = CtdlOutputPreLoadedMsg(TheMessage, mode, headers_only, do_proto, crlf, flags); CtdlFreeMessage(TheMessage); return(retcode); } +char *qp_encode_email_addrs(char *source) +{ + char user[256], node[256], name[256]; + const char headerStr[] = "=?UTF-8?Q?"; + char *Encoded; + char *EncodedName; + char *nPtr; + int need_to_encode = 0; + long SourceLen; + long EncodedMaxLen; + long nColons = 0; + long *AddrPtr; + long *AddrUtf8; + long nAddrPtrMax = 50; + long nmax; + int InQuotes = 0; + int i, n; + + if (source == NULL) return source; + if (IsEmptyStr(source)) return source; + + AddrPtr = malloc (sizeof (long) * nAddrPtrMax); + AddrUtf8 = malloc (sizeof (long) * nAddrPtrMax); + memset(AddrUtf8, 0, sizeof (long) * nAddrPtrMax); + *AddrPtr = 0; + i = 0; + while (!IsEmptyStr (&source[i])) { + if (nColons >= nAddrPtrMax){ + long *ptr; + + ptr = (long *) malloc(sizeof (long) * nAddrPtrMax * 2); + memcpy (ptr, AddrPtr, sizeof (long) * nAddrPtrMax); + free (AddrPtr), AddrPtr = ptr; + + ptr = (long *) malloc(sizeof (long) * nAddrPtrMax * 2); + memset(&ptr[nAddrPtrMax], 0, + sizeof (long) * nAddrPtrMax); + + memcpy (ptr, AddrUtf8, sizeof (long) * nAddrPtrMax); + free (AddrUtf8), AddrUtf8 = ptr; + nAddrPtrMax *= 2; + } + if (((unsigned char) source[i] < 32) || + ((unsigned char) source[i] > 126)) { + need_to_encode = 1; + AddrUtf8[nColons] = 1; + } + if (source[i] == '"') + InQuotes = !InQuotes; + if (!InQuotes && source[i] == ',') { + AddrPtr[nColons] = i; + nColons++; + } + i++; + } + if (need_to_encode == 0) { + free(AddrPtr); + free(AddrUtf8); + return source; + } + + SourceLen = i; + EncodedMaxLen = nColons * (sizeof(headerStr) + 3) + SourceLen * 3; + Encoded = (char*) malloc (EncodedMaxLen); + + for (i = 1; i <= nColons; i++) + source[AddrPtr[i]++] = '\0'; + + nPtr = Encoded; + *nPtr = '\0'; + for (i = 0; i <= nColons && nPtr != NULL; i++) { + nmax = EncodedMaxLen - (nPtr - Encoded); + if (AddrUtf8[i]) { + process_rfc822_addr(&source[AddrPtr[i]], + user, + node, + name); + /* TODO: libIDN here ! */ + if (IsEmptyStr(name)) { + n = snprintf(nPtr, nmax, + (i==0)?"%s@%s" : ",%s@%s", + user, node); + } + else { + EncodedName = rfc2047encode(name, strlen(name)); + n = snprintf(nPtr, nmax, + (i==0)?"%s <%s@%s>" : ",%s <%s@%s>", + EncodedName, user, node); + free(EncodedName); + } + } + else { + n = snprintf(nPtr, nmax, + (i==0)?"%s" : ",%s", + &source[AddrPtr[i]]); + } + if (n > 0 ) + nPtr += n; + else { + char *ptr, *nnPtr; + ptr = (char*) malloc(EncodedMaxLen * 2); + memcpy(ptr, Encoded, EncodedMaxLen); + nnPtr = ptr + (nPtr - Encoded), nPtr = nnPtr; + free(Encoded), Encoded = ptr; + EncodedMaxLen *= 2; + i--; /* do it once more with properly lengthened buffer */ + } + } + for (i = 1; i <= nColons; i++) + source[--AddrPtr[i]] = ','; + free(AddrUtf8); + free(AddrPtr); + return Encoded; +} + + /* * Get a message off disk. (returns om_* values found in msgbase.h) */ @@ -1460,14 +1576,15 @@ int CtdlOutputPreLoadedMsg( 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 crlf, /* Use CRLF newlines instead of LF? */ + int flags /* should the bessage be exported clean? */ ) { - int i, k; + int i, j, k; char buf[SIZ]; - cit_uint8_t ch; + cit_uint8_t ch, prev_ch; char allkeys[30]; char display_name[256]; - char *mptr; + char *mptr, *mpptr; char *nl; /* newline string */ int suppress_f = 0; int subject_found = 0; @@ -1485,7 +1602,7 @@ int CtdlOutputPreLoadedMsg( char mid[100]; char datestamp[100]; - lprintf(CTDL_DEBUG, "CtdlOutputPreLoadedMsg(TheMessage=%s, %d, %d, %d, %d\n", + CtdlLogPrintf(CTDL_DEBUG, "CtdlOutputPreLoadedMsg(TheMessage=%s, %d, %d, %d, %d\n", ((TheMessage == NULL) ? "NULL" : "not null"), mode, headers_only, do_proto, crlf); @@ -1493,8 +1610,9 @@ int CtdlOutputPreLoadedMsg( nl = (crlf ? "\r\n" : "\n"); if (!is_valid_message(TheMessage)) { - lprintf(CTDL_ERR, + CtdlLogPrintf(CTDL_ERR, "ERROR: invalid preloaded message for output\n"); + cit_backtrace (); return(om_no_such_msg); } @@ -1644,19 +1762,23 @@ int CtdlOutputPreLoadedMsg( if (mode == MT_RFC822) { for (i = 0; i < 256; ++i) { if (TheMessage->cm_fields[i]) { - mptr = 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); cprintf("CC: %s%s", mptr, nl); } else if (i == 'P') { cprintf("Return-Path: %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') { @@ -1682,6 +1804,8 @@ int CtdlOutputPreLoadedMsg( } else { + if ((flags & QP_EADDR) != 0) + mptr = qp_encode_email_addrs(mptr); cprintf("To: %s%s", mptr, nl); } } @@ -1690,6 +1814,22 @@ int CtdlOutputPreLoadedMsg( atol(mptr), DATESTRING_RFC822); cprintf("Date: %s%s", datestamp, nl); } + else if (i == 'W') { + cprintf("References: "); + k = num_tokens(mptr, '|'); + for (j=0; j", buf); + if (j == (k-1)) { + cprintf("%s", nl); + } + else { + cprintf(" "); + } + } + } + if (mptr != mpptr) + free (mptr); } } if (subject_found == 0) { @@ -1762,6 +1902,7 @@ START_TEXT: char outbuf[1024]; int outlen = 0; int nllen = strlen(nl); + prev_ch = 0; while (ch=*mptr, ch!=0) { if (ch==13) { /* do nothing */ @@ -1781,6 +1922,14 @@ START_TEXT: } } } + 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); @@ -1893,7 +2042,7 @@ void cmd_msg0(char *cmdbuf) msgid = extract_long(cmdbuf, 0); headers_only = extract_int(cmdbuf, 1); - CtdlOutputMsg(msgid, MT_CITADEL, headers_only, 1, 0, NULL); + CtdlOutputMsg(msgid, MT_CITADEL, headers_only, 1, 0, NULL, 0); return; } @@ -1909,7 +2058,7 @@ void cmd_msg2(char *cmdbuf) msgid = extract_long(cmdbuf, 0); headers_only = extract_int(cmdbuf, 1); - CtdlOutputMsg(msgid, MT_RFC822, headers_only, 1, 1, NULL); + CtdlOutputMsg(msgid, MT_RFC822, headers_only, 1, 1, NULL, 0); } @@ -1963,7 +2112,7 @@ void cmd_msg4(char *cmdbuf) msgid = extract_long(cmdbuf, 0); extract_token(section, cmdbuf, 1, '|', sizeof section); - CtdlOutputMsg(msgid, MT_MIME, 0, 1, 0, (section[0] ? section : NULL) ); + CtdlOutputMsg(msgid, MT_MIME, 0, 1, 0, (section[0] ? section : NULL) , 0); } @@ -1996,7 +2145,7 @@ void cmd_opna(char *cmdbuf) extract_token(desired_section, cmdbuf, 1, '|', sizeof desired_section); safestrncpy(CC->download_desired_section, desired_section, sizeof CC->download_desired_section); - CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1, NULL); + CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1, NULL, 0); } @@ -2012,7 +2161,7 @@ void cmd_dlat(char *cmdbuf) extract_token(desired_section, cmdbuf, 1, '|', sizeof desired_section); safestrncpy(CC->download_desired_section, desired_section, sizeof CC->download_desired_section); - CtdlOutputMsg(msgid, MT_SPEW_SECTION, 0, 1, 1, NULL); + CtdlOutputMsg(msgid, MT_SPEW_SECTION, 0, 1, 1, NULL, 0); } @@ -2043,7 +2192,7 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms long *msgs_to_be_merged = NULL; int num_msgs_to_be_merged = 0; - lprintf(CTDL_DEBUG, + CtdlLogPrintf(CTDL_DEBUG, "CtdlSaveMsgPointersInRoom(room=%s, num_msgs=%d, repl=%d)\n", roomname, num_newmsgs, do_repl_check); @@ -2058,7 +2207,7 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms if (lgetroom(&CC->room, ((roomname != NULL) ? roomname : CC->room.QRname) ) != 0) { - lprintf(CTDL_ERR, "No such room <%s>\n", roomname); + CtdlLogPrintf(CTDL_ERR, "No such room <%s>\n", roomname); return(ERROR + ROOM_NOT_FOUND); } @@ -2095,14 +2244,14 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms } } - lprintf(9, "%d unique messages to be merged\n", num_msgs_to_be_merged); + CtdlLogPrintf(9, "%d unique messages to be merged\n", num_msgs_to_be_merged); /* * Now merge the new messages */ msglist = realloc(msglist, (sizeof(long) * (num_msgs + num_msgs_to_be_merged)) ); if (msglist == NULL) { - lprintf(CTDL_ALERT, "ERROR: can't realloc message list!\n"); + CtdlLogPrintf(CTDL_ALERT, "ERROR: can't realloc message list!\n"); } memcpy(&msglist[num_msgs], msgs_to_be_merged, (sizeof(long) * num_msgs_to_be_merged) ); num_msgs += num_msgs_to_be_merged; @@ -2126,7 +2275,7 @@ int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newms /* Perform replication checks if necessary */ if ( (DoesThisRoomNeedEuidIndexing(&CC->room)) && (do_repl_check) ) { - lprintf(CTDL_DEBUG, "CtdlSaveMsgPointerInRoom() doing repl checks\n"); + CtdlLogPrintf(CTDL_DEBUG, "CtdlSaveMsgPointerInRoom() doing repl checks\n"); for (i=0; ilen = 0; ret->ser = NULL; return; @@ -2299,7 +2448,7 @@ void serialize_message(struct ser_ret *ret, /* return values */ ret->ser = malloc(ret->len); if (ret->ser == NULL) { - lprintf(CTDL_ERR, "serialize_message() malloc(%ld) failed: %s\n", + CtdlLogPrintf(CTDL_ERR, "serialize_message() malloc(%ld) failed: %s\n", (long)ret->len, strerror(errno)); ret->len = 0; ret->ser = NULL; @@ -2317,7 +2466,7 @@ void serialize_message(struct ser_ret *ret, /* return values */ safestrncpy((char *)&ret->ser[wlen], msg->cm_fields[(int)forder[i]], fieldlen+1); wlen = wlen + fieldlen + 1; } - if (ret->len != wlen) lprintf(CTDL_ERR, "ERROR: len=%ld wlen=%ld\n", + if (ret->len != wlen) CtdlLogPrintf(CTDL_ERR, "ERROR: len=%ld wlen=%ld\n", (long)ret->len, (long)wlen); return; @@ -2343,7 +2492,7 @@ void dump_message(struct CtdlMessage *msg, /* unserialized msg */ * Check for valid message format */ if (is_valid_message(msg) == 0) { - lprintf(CTDL_ERR, "dump_message() aborting due to invalid message\n"); + CtdlLogPrintf(CTDL_ERR, "dump_message() aborting due to invalid message\n"); return; } @@ -2371,19 +2520,19 @@ void ReplicationChecks(struct CtdlMessage *msg) { if (DoesThisRoomNeedEuidIndexing(&CC->room) == 0) return; - lprintf(CTDL_DEBUG, "Performing replication checks in <%s>\n", + CtdlLogPrintf(CTDL_DEBUG, "Performing replication checks in <%s>\n", CC->room.QRname); /* No exclusive id? Don't do anything. */ if (msg == NULL) return; if (msg->cm_fields['E'] == NULL) return; if (IsEmptyStr(msg->cm_fields['E'])) return; - /*lprintf(CTDL_DEBUG, "Exclusive ID: <%s> for room <%s>\n", + /*CtdlLogPrintf(CTDL_DEBUG, "Exclusive ID: <%s> for room <%s>\n", msg->cm_fields['E'], CC->room.QRname);*/ old_msgnum = locate_message_by_euid(msg->cm_fields['E'], &CC->room); if (old_msgnum > 0L) { - lprintf(CTDL_DEBUG, "ReplicationChecks() replacing message %ld\n", old_msgnum); + CtdlLogPrintf(CTDL_DEBUG, "ReplicationChecks() replacing message %ld\n", old_msgnum); CtdlDeleteMessages(CC->room.QRname, &old_msgnum, 1, ""); } } @@ -2394,8 +2543,9 @@ void ReplicationChecks(struct CtdlMessage *msg) { * Save a message to disk and submit it into the delivery system. */ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ - struct recptypes *recps, /* recipients (if mail) */ - char *force /* force a particular room? */ + struct recptypes *recps, /* recipients (if mail) */ + char *force, /* force a particular room? */ + int flags /* should the bessage be exported clean? */ ) { char submit_filename[128]; char generated_timestamp[32]; @@ -2421,8 +2571,9 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ char *saved_rfc822_version = NULL; int qualified_for_journaling = 0; struct CitContext *CCC = CC; /* CachedCitContext - performance boost */ + char bounce_to[1024] = ""; - lprintf(CTDL_DEBUG, "CtdlSubmitMsg() called\n"); + CtdlLogPrintf(CTDL_DEBUG, "CtdlSubmitMsg() called\n"); if (is_valid_message(msg) == 0) return(-1); /* self check */ /* If this message has no timestamp, we take the liberty of @@ -2458,7 +2609,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ /* Learn about what's inside, because it's what's inside that counts */ if (msg->cm_fields['M'] == NULL) { - lprintf(CTDL_ERR, "ERROR: attempt to save message with NULL body\n"); + CtdlLogPrintf(CTDL_ERR, "ERROR: attempt to save message with NULL body\n"); return(-2); } @@ -2473,21 +2624,24 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ strcpy(content_type, "text/plain"); mptr = bmstrcasestr(msg->cm_fields['M'], "Content-type:"); if (mptr != NULL) { + char *aptr; safestrncpy(content_type, &mptr[13], sizeof content_type); striplt(content_type); - for (a = 0; a < strlen(content_type); ++a) { - if ((content_type[a] == ';') - || (content_type[a] == ' ') - || (content_type[a] == 13) - || (content_type[a] == 10)) { - content_type[a] = 0; + aptr = content_type; + while (!IsEmptyStr(aptr)) { + if ((*aptr == ';') + || (*aptr == ' ') + || (*aptr == 13) + || (*aptr == 10)) { + *aptr = 0; } + else aptr++; } } } /* Goto the correct room */ - lprintf(CTDL_DEBUG, "Selected room %s\n", (recps) ? CCC->room.QRname : SENTITEMS); + CtdlLogPrintf(CTDL_DEBUG, "Selected room %s\n", (recps) ? CCC->room.QRname : SENTITEMS); strcpy(hold_rm, CCC->room.QRname); strcpy(actual_rm, CCC->room.QRname); if (recps != NULL) { @@ -2499,7 +2653,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ if (CCC->user.axlevel == 2) { strcpy(hold_rm, actual_rm); strcpy(actual_rm, config.c_twitroom); - lprintf(CTDL_DEBUG, "Diverting to twit room\n"); + CtdlLogPrintf(CTDL_DEBUG, "Diverting to twit room\n"); } } @@ -2508,7 +2662,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ strcpy(actual_rm, force_room); } - lprintf(CTDL_DEBUG, "Final selection: %s\n", actual_rm); + CtdlLogPrintf(CTDL_DEBUG, "Final selection: %s\n", actual_rm); if (strcasecmp(actual_rm, CCC->room.QRname)) { /* getroom(&CCC->room, actual_rm); */ usergoto(actual_rm, 0, 1, NULL, NULL); @@ -2522,7 +2676,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ } /* Perform "before save" hooks (aborting if any return nonzero) */ - lprintf(CTDL_DEBUG, "Performing before-save hooks\n"); + CtdlLogPrintf(CTDL_DEBUG, "Performing before-save hooks\n"); if (PerformMessageHooks(msg, EVT_BEFORESAVE) > 0) return(-3); /* @@ -2534,7 +2688,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ } /* Save it to disk */ - lprintf(CTDL_DEBUG, "Saving to disk\n"); + CtdlLogPrintf(CTDL_DEBUG, "Saving to disk\n"); newmsgid = send_message(msg); if (newmsgid <= 0L) return(-5); @@ -2542,7 +2696,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ * be a critical section because nobody else knows about this message * yet. */ - lprintf(CTDL_DEBUG, "Creating MetaData record\n"); + CtdlLogPrintf(CTDL_DEBUG, "Creating MetaData record\n"); memset(&smi, 0, sizeof(struct MetaData)); smi.meta_msgnum = newmsgid; smi.meta_refcount = 0; @@ -2560,13 +2714,13 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ * message to attach to the journalized copy. */ if (CCC->redirect_buffer != NULL) { - lprintf(CTDL_ALERT, "CCC->redirect_buffer is not NULL during message submission!\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; - CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1); + CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1, QP_EADDR); smi.meta_rfc822_length = CCC->redirect_len; saved_rfc822_version = CCC->redirect_buffer; CCC->redirect_buffer = NULL; @@ -2576,7 +2730,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ PutMetaData(&smi); /* Now figure out where to store the pointers */ - lprintf(CTDL_DEBUG, "Storing pointers\n"); + CtdlLogPrintf(CTDL_DEBUG, "Storing pointers\n"); /* If this is being done by the networker delivering a private * message, we want to BYPASS saving the sender's copy (because there @@ -2584,7 +2738,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ */ if ((!CCC->internal_pgm) || (recps == NULL)) { if (CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 1, msg) != 0) { - lprintf(CTDL_ERR, "ERROR saving message pointer!\n"); + CtdlLogPrintf(CTDL_ERR, "ERROR saving message pointer!\n"); CtdlSaveMsgPointerInRoom(config.c_aideroom, newmsgid, 0, msg); } } @@ -2601,16 +2755,24 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ for (i=0; irecp_room, '|'); ++i) { extract_token(recipient, recps->recp_room, i, '|', sizeof recipient); - lprintf(CTDL_DEBUG, "Delivering to room <%s>\n", recipient); + CtdlLogPrintf(CTDL_DEBUG, "Delivering to room <%s>\n", recipient); CtdlSaveMsgPointerInRoom(recipient, newmsgid, 0, msg); } /* Bump this user's messages posted counter. */ - lprintf(CTDL_DEBUG, "Updating user\n"); + CtdlLogPrintf(CTDL_DEBUG, "Updating user\n"); lgetuser(&CCC->user, CCC->curr_user); CCC->user.posted = CCC->user.posted + 1; lputuser(&CCC->user); + /* Decide where bounces need to be delivered */ + if (CCC->logged_in) { + snprintf(bounce_to, sizeof bounce_to, "%s@%s", CCC->user.fullname, config.c_nodename); + } + else { + snprintf(bounce_to, sizeof bounce_to, "%s@%s", msg->cm_fields['A'], msg->cm_fields['N']); + } + /* If this is private, local mail, make a copy in the * recipient's mailbox and bump the reference count. */ @@ -2619,7 +2781,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ for (i=0; irecp_local, '|'); ++i) { extract_token(recipient, recps->recp_local, i, '|', sizeof recipient); - lprintf(CTDL_DEBUG, "Delivering private local mail to <%s>\n", + CtdlLogPrintf(CTDL_DEBUG, "Delivering private local mail to <%s>\n", recipient); if (getuser(&userbuf, recipient) == 0) { // Add a flag so the Funambol module knows its mail @@ -2635,9 +2797,9 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ instr = malloc(instr_alloc); snprintf(instr, instr_alloc, "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" - "bounceto|%s@%s\n", + "bounceto|%s\n", SPOOLMIME, newmsgid, (long)time(NULL), - msg->cm_fields['A'], msg->cm_fields['N'] + bounce_to ); imsg = malloc(sizeof(struct CtdlMessage)); @@ -2649,19 +2811,19 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ imsg->cm_fields['J'] = strdup("do not journal"); imsg->cm_fields['M'] = instr; /* imsg owns this memory now */ imsg->cm_fields['W'] = strdup(recipient); - CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM); + CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM, 0); CtdlFreeMessage(imsg); } } else { - lprintf(CTDL_DEBUG, "No user <%s>\n", recipient); + CtdlLogPrintf(CTDL_DEBUG, "No user <%s>\n", recipient); CtdlSaveMsgPointerInRoom(config.c_aideroom, newmsgid, 0, msg); } } /* Perform "after save" hooks */ - lprintf(CTDL_DEBUG, "Performing after-save hooks\n"); + CtdlLogPrintf(CTDL_DEBUG, "Performing after-save hooks\n"); PerformMessageHooks(msg, EVT_AFTERSAVE); /* For IGnet mail, we have to save a new copy into the spooler for @@ -2706,7 +2868,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ } /* Go back to the room we started from */ - lprintf(CTDL_DEBUG, "Returning to original room %s\n", hold_rm); + CtdlLogPrintf(CTDL_DEBUG, "Returning to original room %s\n", hold_rm); if (strcasecmp(hold_rm, CCC->room.QRname)) usergoto(hold_rm, 0, 1, NULL, NULL); @@ -2717,14 +2879,14 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ */ if (recps != NULL) if (recps->num_internet > 0) { - lprintf(CTDL_DEBUG, "Generating delivery instructions\n"); + CtdlLogPrintf(CTDL_DEBUG, "Generating delivery instructions\n"); instr_alloc = 1024; instr = malloc(instr_alloc); snprintf(instr, instr_alloc, "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" - "bounceto|%s@%s\n", + "bounceto|%s\n", SPOOLMIME, newmsgid, (long)time(NULL), - msg->cm_fields['A'], msg->cm_fields['N'] + bounce_to ); for (i=0; irecp_internet, '|'); ++i) { @@ -2745,7 +2907,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ imsg->cm_fields['A'] = strdup("Citadel"); imsg->cm_fields['J'] = strdup("do not journal"); imsg->cm_fields['M'] = instr; /* imsg owns this memory now */ - CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM); + CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM, QP_EADDR); CtdlFreeMessage(imsg); } @@ -2757,14 +2919,14 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ } if (collected_addresses != NULL) { - begin_critical_section(S_ATBF); aptr = (struct addresses_to_be_filed *) malloc(sizeof(struct addresses_to_be_filed)); - aptr->next = atbf; MailboxName(actual_rm, sizeof actual_rm, &CCC->user, USERCONTACTSROOM); aptr->roomname = strdup(actual_rm); aptr->collected_addresses = collected_addresses; + begin_critical_section(S_ATBF); + aptr->next = atbf; atbf = aptr; end_critical_section(S_ATBF); } @@ -2849,7 +3011,7 @@ void quickie_message(char *from, char *fromaddr, char *to, char *room, char *tex } msg->cm_fields['M'] = strdup(text); - CtdlSubmitMsg(msg, recp, room); + CtdlSubmitMsg(msg, recp, room, 0); CtdlFreeMessage(msg); if (recp != NULL) free_recipients(recp); } @@ -2937,7 +3099,7 @@ char *CtdlReadMessageBody(char *terminator, /* token signalling EOT */ } else { buffer_len = (buffer_len * 2); m = ptr; - lprintf(CTDL_DEBUG, "buffer_len is now %ld\n", (long)buffer_len); + CtdlLogPrintf(CTDL_DEBUG, "buffer_len is now %ld\n", (long)buffer_len); } } @@ -2979,12 +3141,12 @@ struct CtdlMessage *CtdlMakeMessage( char *my_email, /* which of my email addresses to use (empty is ok) */ char *subject, /* Subject (optional) */ char *supplied_euid, /* ...or NULL if this is irrelevant */ - char *preformatted_text /* ...or NULL to read text from client */ + char *preformatted_text, /* ...or NULL to read text from client */ + char *references /* Thread references */ ) { char dest_node[256]; char buf[1024]; struct CtdlMessage *msg; - int i; msg = malloc(sizeof(struct CtdlMessage)); memset(msg, 0, sizeof(struct CtdlMessage)); @@ -3008,11 +3170,7 @@ struct CtdlMessage *CtdlMakeMessage( snprintf(buf, sizeof buf, "%s", author->fullname); msg->cm_fields['P'] = strdup(buf); } - for (i=0; (msg->cm_fields['P'][i]!=0); ++i) { - if (isspace(msg->cm_fields['P'][i])) { - msg->cm_fields['P'][i] = '_'; - } - } + convert_spaces_to_underscores(msg->cm_fields['P']); snprintf(buf, sizeof buf, "%ld", (long)time(NULL)); /* timestamp */ msg->cm_fields['T'] = strdup(buf); @@ -3075,6 +3233,12 @@ struct CtdlMessage *CtdlMakeMessage( msg->cm_fields['E'] = strdup(supplied_euid); } + if (references != NULL) { + if (!IsEmptyStr(references)) { + msg->cm_fields['W'] = strdup(references); + } + } + if (preformatted_text != NULL) { msg->cm_fields['M'] = preformatted_text; } @@ -3106,6 +3270,7 @@ int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, return (0); // We're Evaling whether a recipient exists } else if (!(CC->logged_in)) { + if ((CC->room.QRflags & QR_READONLY)) { snprintf(errmsgbuf, n, "Not logged in."); return (ERROR + NOT_LOGGED_IN); @@ -3114,7 +3279,7 @@ int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, snprintf(errmsgbuf, n, "Not logged in Moderation feature not yet implemented!"); return (ERROR + NOT_LOGGED_IN); } - if (CC->room.QRflags2 & QR2_SMTP_PUBLIC == 0){ + if ((PostPublic!=POST_LMTP) &&(CC->room.QRflags2 & QR2_SMTP_PUBLIC) == 0) { SpoolControl *sc; char filename[SIZ]; int found; @@ -3130,16 +3295,21 @@ int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, if (!read_spoolcontrol_file(&sc, filename)) { end_critical_section(S_NETCONFIGS); - snprintf(errmsgbuf, n, "No Subscribers found."); + snprintf(errmsgbuf, n, + "This mailing list only accepts posts from subscribers."); return (ERROR + NO_SUCH_USER); } end_critical_section(S_NETCONFIGS); found = is_recipient (sc, RemoteIdentifier); free_spoolcontrol_struct(&sc); - if (found) + if (found) { return (0); - else + } + else { + snprintf(errmsgbuf, n, + "This mailing list only accepts posts from subscribers."); return (ERROR + NO_SUCH_USER); + } } return (0); @@ -3276,7 +3446,9 @@ struct recptypes *validate_recipients(char *supplied_recipients, } striplt(this_recp); - lprintf(CTDL_DEBUG, "Evaluating recipient #%d: %s\n", num_recps, this_recp); + if (IsEmptyStr(this_recp)) + break; + CtdlLogPrintf(CTDL_DEBUG, "Evaluating recipient #%d: %s\n", num_recps, this_recp); ++num_recps; mailtype = alias(this_recp); mailtype = alias(this_recp); @@ -3292,6 +3464,7 @@ struct recptypes *validate_recipients(char *supplied_recipients, } this_recp_cooked[j] = '\0'; invalid = 0; + errmsg[0] = 0; switch(mailtype) { case MES_LOCAL: if (!strcasecmp(this_recp, "sysop")) { @@ -3302,22 +3475,6 @@ struct recptypes *validate_recipients(char *supplied_recipients, } strcat(ret->recp_room, this_recp); } - else if (getuser(&tempUS, this_recp) == 0) { - ++ret->num_local; - strcpy(this_recp, tempUS.fullname); - if (!IsEmptyStr(ret->recp_local)) { - strcat(ret->recp_local, "|"); - } - strcat(ret->recp_local, this_recp); - } - else if (getuser(&tempUS, this_recp_cooked) == 0) { - ++ret->num_local; - strcpy(this_recp, tempUS.fullname); - if (!IsEmptyStr(ret->recp_local)) { - strcat(ret->recp_local, "|"); - } - strcat(ret->recp_local, this_recp); - } else if ( (!strncasecmp(this_recp, "room_", 5)) && (!getroom(&tempQR, &this_recp_cooked[5])) ) { @@ -3329,10 +3486,10 @@ struct recptypes *validate_recipients(char *supplied_recipients, err = CtdlDoIHavePermissionToPostInThisRoom(errmsg, sizeof errmsg, RemoteIdentifier, - Flags); + Flags + ); if (err) { - cprintf("%d %s\n", err, errmsg); ++ret->num_error; invalid = 1; } @@ -3348,6 +3505,22 @@ struct recptypes *validate_recipients(char *supplied_recipients, CC->room = tempQR2; } + else if (getuser(&tempUS, this_recp) == 0) { + ++ret->num_local; + strcpy(this_recp, tempUS.fullname); + if (!IsEmptyStr(ret->recp_local)) { + strcat(ret->recp_local, "|"); + } + strcat(ret->recp_local, this_recp); + } + else if (getuser(&tempUS, this_recp_cooked) == 0) { + ++ret->num_local; + strcpy(this_recp, tempUS.fullname); + if (!IsEmptyStr(ret->recp_local)) { + strcat(ret->recp_local, "|"); + } + strcat(ret->recp_local, this_recp); + } else { ++ret->num_error; invalid = 1; @@ -3385,15 +3558,16 @@ struct recptypes *validate_recipients(char *supplied_recipients, break; } if (invalid) { - if (IsEmptyStr(ret->errormsg)) { - snprintf(append, sizeof append, - "Invalid recipient: %s", - this_recp); + if (IsEmptyStr(errmsg)) { + snprintf(append, sizeof append, "Invalid recipient: %s", this_recp); } else { - snprintf(append, sizeof append, ", %s", this_recp); + snprintf(append, sizeof append, "%s", errmsg); } - if ( (strlen(ret->errormsg) + strlen(append)) < SIZ) { + if ( (strlen(ret->errormsg) + strlen(append) + 3) < SIZ) { + if (!IsEmptyStr(ret->errormsg)) { + strcat(ret->errormsg, "; "); + } strcat(ret->errormsg, append); } } @@ -3416,12 +3590,12 @@ struct recptypes *validate_recipients(char *supplied_recipients, strcpy(ret->errormsg, "No recipients specified."); } - lprintf(CTDL_DEBUG, "validate_recipients()\n"); - lprintf(CTDL_DEBUG, " local: %d <%s>\n", ret->num_local, ret->recp_local); - lprintf(CTDL_DEBUG, " room: %d <%s>\n", ret->num_room, ret->recp_room); - lprintf(CTDL_DEBUG, " inet: %d <%s>\n", ret->num_internet, ret->recp_internet); - lprintf(CTDL_DEBUG, " ignet: %d <%s>\n", ret->num_ignet, ret->recp_ignet); - lprintf(CTDL_DEBUG, " error: %d <%s>\n", ret->num_error, ret->errormsg); + CtdlLogPrintf(CTDL_DEBUG, "validate_recipients()\n"); + CtdlLogPrintf(CTDL_DEBUG, " local: %d <%s>\n", ret->num_local, ret->recp_local); + CtdlLogPrintf(CTDL_DEBUG, " room: %d <%s>\n", ret->num_room, ret->recp_room); + CtdlLogPrintf(CTDL_DEBUG, " inet: %d <%s>\n", ret->num_internet, ret->recp_internet); + CtdlLogPrintf(CTDL_DEBUG, " ignet: %d <%s>\n", ret->num_ignet, ret->recp_ignet); + CtdlLogPrintf(CTDL_DEBUG, " error: %d <%s>\n", ret->num_error, ret->errormsg); free(recipients); return(ret); @@ -3438,7 +3612,7 @@ void free_recipients(struct recptypes *valid) { } if (valid->recptypes_magic != RECPTYPES_MAGIC) { - lprintf(CTDL_EMERG, "Attempt to call free_recipients() on some other data type!\n"); + CtdlLogPrintf(CTDL_EMERG, "Attempt to call free_recipients() on some other data type!\n"); abort(); } @@ -3482,6 +3656,8 @@ void cmd_ent0(char *entargs) int i, j; char buf[256]; int newuseremail_ok = 0; + char references[SIZ]; + char *ptr; unbuffer_output(); @@ -3504,6 +3680,10 @@ void cmd_ent0(char *entargs) break; } extract_token(newuseremail, entargs, 10, '|', sizeof newuseremail); + extract_token(references, entargs, 11, '|', sizeof references); + for (ptr=references; *ptr != 0; ++ptr) { + if (*ptr == '!') *ptr = '|'; + } /* first check to make sure the request is valid. */ @@ -3577,14 +3757,14 @@ void cmd_ent0(char *entargs) valid_to = validate_recipients(recp, NULL, 0); if (valid_to->num_error > 0) { - cprintf("%d Invalid recipient (To)\n", ERROR + NO_SUCH_USER); + cprintf("%d %s\n", ERROR + NO_SUCH_USER, valid_to->errormsg); free_recipients(valid_to); return; } valid_cc = validate_recipients(cc, NULL, 0); if (valid_cc->num_error > 0) { - cprintf("%d Invalid recipient (CC)\n", ERROR + NO_SUCH_USER); + cprintf("%d %s\n", ERROR + NO_SUCH_USER, valid_cc->errormsg); free_recipients(valid_to); free_recipients(valid_cc); return; @@ -3592,7 +3772,7 @@ void cmd_ent0(char *entargs) valid_bcc = validate_recipients(bcc, NULL, 0); if (valid_bcc->num_error > 0) { - cprintf("%d Invalid recipient (BCC)\n", ERROR + NO_SUCH_USER); + cprintf("%d %s\n", ERROR + NO_SUCH_USER, valid_bcc->errormsg); free_recipients(valid_to); free_recipients(valid_cc); free_recipients(valid_bcc); @@ -3697,7 +3877,7 @@ void cmd_ent0(char *entargs) CC->room.QRname, anonymous, format_type, newusername, newuseremail, subject, ((!IsEmptyStr(supplied_euid)) ? supplied_euid : NULL), - NULL); + NULL, references); /* Put together one big recipients struct containing to/cc/bcc all in * one. This is for the envelope. @@ -3725,7 +3905,7 @@ void cmd_ent0(char *entargs) free(all_recps); if (msg != NULL) { - msgnum = CtdlSubmitMsg(msg, valid, ""); + msgnum = CtdlSubmitMsg(msg, valid, "", QP_EADDR); if (do_confirm) { cprintf("%ld\n", msgnum); @@ -3780,12 +3960,12 @@ int CtdlDeleteMessages(char *room_name, /* which room */ regcomp(&re, content_type, 0); need_to_free_re = 1; } - lprintf(CTDL_DEBUG, "CtdlDeleteMessages(%s, %d msgs, %s)\n", + CtdlLogPrintf(CTDL_DEBUG, "CtdlDeleteMessages(%s, %d msgs, %s)\n", room_name, num_dmsgnums, content_type); /* get room record, obtaining a lock... */ if (lgetroom(&qrbuf, room_name) != 0) { - lprintf(CTDL_ERR, "CtdlDeleteMessages(): Room <%s> not found\n", + CtdlLogPrintf(CTDL_ERR, "CtdlDeleteMessages(): Room <%s> not found\n", room_name); if (need_to_free_re) regfree(&re); return (0); /* room not found */ @@ -3859,7 +4039,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ /* Now free the memory we used, and go away. */ if (msglist != NULL) free(msglist); if (dellist != NULL) free(dellist); - lprintf(CTDL_DEBUG, "%d message(s) deleted.\n", num_deleted); + CtdlLogPrintf(CTDL_DEBUG, "%d message(s) deleted.\n", num_deleted); if (need_to_free_re) regfree(&re); return (num_deleted); } @@ -4003,6 +4183,10 @@ void cmd_move(char *args) /* Permit message removal from collaborative delete rooms */ if (CC->room.QRflags2 & QR2_COLLABDEL) permit = 1; + /* Users allowed to post into the target room may move into it too. */ + if ((CC->room.QRflags & QR_MAILBOX) && + (qtemp.QRflags & UA_POSTALLOWED)) permit = 1; + /* User must have access to target room */ if (!(ra & UA_KNOWN)) permit = 0; @@ -4105,7 +4289,7 @@ void AdjRefCount(long msgnum, int incr) /* msgnum < 0 means that we're trying to close the file */ if (msgnum < 0) { - lprintf(CTDL_DEBUG, "Closing the AdjRefCount queue file\n"); + CtdlLogPrintf(CTDL_DEBUG, "Closing the AdjRefCount queue file\n"); begin_critical_section(S_SUPPMSGMAIN); if (arcfp != NULL) { fclose(arcfp); @@ -4157,7 +4341,7 @@ int TDAP_ProcessAdjRefCountQueue(void) r = link(file_arcq, file_arcq_temp); if (r != 0) { - lprintf(CTDL_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); + CtdlLogPrintf(CTDL_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); end_critical_section(S_SUPPMSGMAIN); return(num_records_processed); } @@ -4167,7 +4351,7 @@ int TDAP_ProcessAdjRefCountQueue(void) fp = fopen(file_arcq_temp, "rb"); if (fp == NULL) { - lprintf(CTDL_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); + CtdlLogPrintf(CTDL_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); return(num_records_processed); } @@ -4179,7 +4363,7 @@ int TDAP_ProcessAdjRefCountQueue(void) fclose(fp); r = unlink(file_arcq_temp); if (r != 0) { - lprintf(CTDL_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); + CtdlLogPrintf(CTDL_CRIT, "%s: %s\n", file_arcq_temp, strerror(errno)); } return(num_records_processed); @@ -4210,14 +4394,14 @@ void TDAP_AdjRefCount(long msgnum, int incr) smi.meta_refcount += incr; PutMetaData(&smi); end_critical_section(S_SUPPMSGMAIN); - lprintf(CTDL_DEBUG, "msg %ld ref count delta %d, is now %d\n", + CtdlLogPrintf(CTDL_DEBUG, "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). */ if (smi.meta_refcount == 0) { - lprintf(CTDL_DEBUG, "Deleting message <%ld>\n", msgnum); + CtdlLogPrintf(CTDL_DEBUG, "Deleting message <%ld>\n", msgnum); /* Call delete hooks with NULL room to show it has gone altogether */ PerformDeleteHooks(NULL, msgnum); @@ -4240,24 +4424,21 @@ void TDAP_AdjRefCount(long msgnum, int incr) * Note: this could be much more efficient. Right now we use two temporary * files, and still pull the message into memory as with all others. */ -void CtdlWriteObject(char *req_room, /* Room to stuff it in */ - char *content_type, /* MIME type of this object */ - char *tempfilename, /* Where to fetch it from */ +void CtdlWriteObject(char *req_room, /* Room to stuff it in */ + char *content_type, /* MIME type of this object */ + char *raw_message, /* Data to be written */ + off_t raw_length, /* Size of raw_message */ struct ctdluser *is_mailbox, /* Mailbox room? */ - int is_binary, /* Is encoding necessary? */ - int is_unique, /* Del others of this type? */ - unsigned int flags /* Internal save flags */ + int is_binary, /* Is encoding necessary? */ + int is_unique, /* Del others of this type? */ + unsigned int flags /* Internal save flags */ ) { - FILE *fp; struct ctdlroom qrbuf; char roomname[ROOMNAMELEN]; struct CtdlMessage *msg; - - char *raw_message = NULL; char *encoded_message = NULL; - off_t raw_length = 0; if (is_mailbox != NULL) { MailboxName(roomname, sizeof roomname, is_mailbox, req_room); @@ -4266,24 +4447,10 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ safestrncpy(roomname, req_room, sizeof(roomname)); } - fp = fopen(tempfilename, "rb"); - if (fp == NULL) { - lprintf(CTDL_CRIT, "Cannot open %s: %s\n", - tempfilename, strerror(errno)); - return; - } - fseek(fp, 0L, SEEK_END); - raw_length = ftell(fp); - rewind(fp); - lprintf(CTDL_DEBUG, "Raw length is %ld\n", (long)raw_length); - - raw_message = malloc((size_t)raw_length + 2); - fread(raw_message, (size_t)raw_length, 1, fp); - fclose(fp); + CtdlLogPrintf(CTDL_DEBUG, "Raw length is %ld\n", (long)raw_length); if (is_binary) { - encoded_message = malloc((size_t) - (((raw_length * 134) / 100) + 4096 ) ); + encoded_message = malloc((size_t) (((raw_length * 134) / 100) + 4096 ) ); } else { encoded_message = malloc((size_t)(raw_length + 4096)); @@ -4311,7 +4478,6 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ ); } else { - raw_message[raw_length] = 0; memcpy( &encoded_message[strlen(encoded_message)], raw_message, @@ -4319,9 +4485,7 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ ); } - free(raw_message); - - lprintf(CTDL_DEBUG, "Allocating\n"); + CtdlLogPrintf(CTDL_DEBUG, "Allocating\n"); msg = malloc(sizeof(struct CtdlMessage)); memset(msg, 0, sizeof(struct CtdlMessage)); msg->cm_magic = CTDLMESSAGE_MAGIC; @@ -4345,12 +4509,12 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ * other objects of this type that are currently in the room. */ if (is_unique) { - lprintf(CTDL_DEBUG, "Deleted %d other msgs of this type\n", + CtdlLogPrintf(CTDL_DEBUG, "Deleted %d other msgs of this type\n", CtdlDeleteMessages(roomname, NULL, 0, content_type) ); } /* Now write the data */ - CtdlSubmitMsg(msg, NULL, roomname); + CtdlSubmitMsg(msg, NULL, roomname, 0); CtdlFreeMessage(msg); } @@ -4410,20 +4574,9 @@ char *CtdlGetSysConfig(char *sysconfname) { return(conf); } -void CtdlPutSysConfig(char *sysconfname, char *sysconfdata) { - char temp[PATH_MAX]; - FILE *fp; - - CtdlMakeTempFileName(temp, sizeof temp); - fp = fopen(temp, "w"); - if (fp == NULL) return; - fprintf(fp, "%s", sysconfdata); - fclose(fp); - - /* this handy API function does all the work for us */ - CtdlWriteObject(SYSCONFIGROOM, sysconfname, temp, NULL, 0, 1, 0); - unlink(temp); +void CtdlPutSysConfig(char *sysconfname, char *sysconfdata) { + CtdlWriteObject(SYSCONFIGROOM, sysconfname, sysconfdata, (strlen(sysconfdata)+1), NULL, 0, 1, 0); }