* $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"
*/
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;
+ 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;
int crlf, /* Use CRLF newlines instead of LF? */
int flags /* should the bessage be exported clean? */
) {
- int i, j, k;
+ int i, j, k, n;
char buf[SIZ];
cit_uint8_t ch, prev_ch;
char allkeys[30];
}
/* Now spew the header fields in the order we like them. */
- safestrncpy(allkeys, FORDER, sizeof allkeys);
- for (i=0; i<strlen(allkeys); ++i) {
+ 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)
(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;
+ int eoh = 0;
+ const char *StartOfText = StrBufNOTNULL;
char outbuf[1024];
int outlen = 0;
int nllen = strlen(nl);
- prev_ch = 0;
- while (ch=*mptr, ch!=0) {
- if (ch==13) {
+ prev_ch = '\0';
+ while (*mptr != '\0') {
+ if (*mptr == '\r') {
/* 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 ((!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 (ch == 10) {
- sprintf(&outbuf[outlen], "%s", nl);
+ if (*mptr == '\n') {
+ memcpy(&outbuf[outlen], nl, nllen);
outlen += nllen;
+ outbuf[outlen] = '\0';
}
else {
- outbuf[outlen++] = ch;
+ outbuf[outlen++] = *mptr;
}
}
}
if (flags & ESC_DOT)
{
- if ((prev_ch == 10) && (ch == '.') && ((*(mptr+1) == 13) || (*(mptr+1) == 10)))
+ if ((prev_ch == '\n') &&
+ (*mptr == '.') &&
+ ((*(mptr+1) == '\r') || (*(mptr+1) == '\n')))
{
outbuf[outlen++] = '.';
}
+ prev_ch = *mptr;
}
- prev_ch = ch;
++mptr;
if (outlen > 1000) {
client_write(outbuf, outlen);
*/
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 == 13)
- ch = 10;
- if ((ch == 10) || (buflen > 250)) {
+ 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';
- cprintf("%s%s", buf, nl);
+
+ client_write(buf, buflen);
*buf = '\0';
buflen = 0;
+ xlline = 0;
} else {
buf[buflen] = ch;
buflen++;
}
-
/*
* 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 */
char bounce_to[1024] = "";
/* 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);
}
}
/*
* Back end function used by CtdlMakeMessage() and similar functions
*/
-char *CtdlReadMessageBody(char *terminator, /* token signalling EOT */
- size_t maxlen, /* maximum message length */
- char *exist, /* if non-null, append to it;
- exist is ALWAYS freed */
- int crlf, /* CRLF newlines instead of LF */
- int sock /* socket handle or 0 for this session's client socket */
- ) {
- char buf[1024];
- int linelen;
- size_t message_len = 0;
- size_t buffer_len = 0;
- char *ptr;
- char *m;
+StrBuf *CtdlReadMessageBodyBuf(char *terminator, /* token signalling EOT */
+ long tlen,
+ size_t maxlen, /* maximum message length */
+ char *exist, /* if non-null, append to it;
+ exist is ALWAYS freed */
+ int crlf, /* CRLF newlines instead of LF */
+ int *sock /* socket handle or 0 for this session's client socket */
+ )
+{
+ StrBuf *Message;
+ StrBuf *LineBuf;
int flushing = 0;
int finished = 0;
int dotdot = 0;
+ LineBuf = NewStrBufPlain(NULL, SIZ);
if (exist == NULL) {
- m = malloc(4096);
- m[0] = 0;
- buffer_len = 4096;
- message_len = 0;
+ Message = NewStrBufPlain(NULL, 4 * SIZ);
}
else {
- message_len = strlen(exist);
- buffer_len = message_len + 4096;
- m = realloc(exist, buffer_len);
- if (m == NULL) {
- free(exist);
- return m;
- }
+ Message = NewStrBufPlain(exist, -1);
+ free(exist);
}
/* Do we need to change leading ".." to "." for SMTP escaping? */
- if (!strcmp(terminator, ".")) {
+ if ((tlen == 1) && (*terminator == '.')) {
dotdot = 1;
}
- /* flush the input if we have nowhere to store it */
- if (m == NULL) {
- flushing = 1;
- }
-
/* read in the lines of message text one by one */
do {
- if (sock > 0) {
- if (sock_getln(sock, buf, (sizeof buf - 3)) < 0) finished = 1;
+ if (sock != NULL) {
+ if ((CtdlSockGetLine(sock, LineBuf) < 0) ||
+ (*sock == -1))
+ finished = 1;
}
else {
- if (client_getln(buf, (sizeof buf - 3)) < 1) finished = 1;
- }
- if (!strcmp(buf, terminator)) finished = 1;
- if (crlf) {
- strcat(buf, "\r\n");
- }
- else {
- strcat(buf, "\n");
- }
-
- /* Unescape SMTP-style input of two dots at the beginning of the line */
- if (dotdot) {
- if (!strncmp(buf, "..", 2)) {
- strcpy(buf, &buf[1]);
- }
+ if (CtdlClientGetLine(LineBuf) < 0) finished = 1;
}
+ if ((StrLength(LineBuf) == tlen) &&
+ (!strcmp(ChrPtr(LineBuf), terminator)))
+ finished = 1;
if ( (!flushing) && (!finished) ) {
- /* Measure the line */
- linelen = strlen(buf);
-
- /* augment the buffer if we have to */
- if ((message_len + linelen) >= buffer_len) {
- ptr = realloc(m, (buffer_len * 2) );
- if (ptr == NULL) { /* flush if can't allocate */
- flushing = 1;
- } else {
- buffer_len = (buffer_len * 2);
- m = ptr;
- CtdlLogPrintf(CTDL_DEBUG, "buffer_len is now %ld\n", (long)buffer_len);
- }
+ if (crlf) {
+ StrBufAppendBufPlain(LineBuf, HKEY("\r\n"), 0);
}
-
- /* Add the new line to the buffer. NOTE: this loop must avoid
- * using functions like strcat() and strlen() because they
- * traverse the entire buffer upon every call, and doing that
- * for a multi-megabyte message slows it down beyond usability.
- */
- strcpy(&m[message_len], buf);
- message_len += linelen;
+ else {
+ StrBufAppendBufPlain(LineBuf, HKEY("\n"), 0);
+ }
+
+ /* Unescape SMTP-style input of two dots at the beginning of the line */
+ if ((dotdot) &&
+ (StrLength(LineBuf) == 2) &&
+ (!strcmp(ChrPtr(LineBuf), "..")))
+ {
+ StrBufCutLeft(LineBuf, 1);
+ }
+
+ StrBufAppendBuf(Message, LineBuf, 0);
}
/* if we've hit the max msg length, flush the rest */
- if (message_len >= maxlen) flushing = 1;
+ if (StrLength(Message) >= maxlen) flushing = 1;
} while (!finished);
- return(m);
+ FreeStrBuf(&LineBuf);
+ return Message;
}
+/*
+ * Back end function used by CtdlMakeMessage() and similar functions
+ */
+char *CtdlReadMessageBody(char *terminator, /* token signalling EOT */
+ long tlen,
+ size_t maxlen, /* maximum message length */
+ char *exist, /* if non-null, append to it;
+ exist is ALWAYS freed */
+ int crlf, /* CRLF newlines instead of LF */
+ int *sock /* socket handle or 0 for this session's client socket */
+ )
+{
+ StrBuf *Message;
+
+ Message = CtdlReadMessageBodyBuf(terminator,
+ tlen,
+ maxlen,
+ exist,
+ crlf,
+ sock);
+ if (Message == NULL)
+ return NULL;
+ else
+ return SmashStrBuf(&Message);
+}
/*
msg->cm_fields['M'] = preformatted_text;
}
else {
- msg->cm_fields['M'] = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0);
+ msg->cm_fields['M'] = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
}
return(msg);
}
- 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);
cdb_store(CDB_MSGLISTS, &qrbuf.QRnumber, (int)sizeof(long),
msglist, (int)(num_msgs * sizeof(long)));
- qrbuf.QRhighest = msglist[num_msgs - 1];
+ if (num_msgs > 0)
+ qrbuf.QRhighest = msglist[num_msgs - 1];
+ else
+ qrbuf.QRhighest = 0;
}
CtdlPutRoomLock(&qrbuf);
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).