"hnod",
"msgn",
"jrnl",
- NULL, NULL,
+ NULL,
+ "list",
"text",
"node",
"room",
int was_seen = 0;
long lo = (-1L);
long hi = (-1L);
- long t = (-1L);
- int trimming = 0;
struct visit vbuf;
long *msglist;
int num_msgs = 0;
char *is_set; /* actually an array of booleans */
int num_sets;
int s;
+ int w = 0;
char setstr[SIZ], lostr[SIZ], histr[SIZ];
- size_t tmp;
/* Don't bother doing *anything* if we were passed a list of zero messages */
if (num_target_msgnums < 1) {
return;
}
- CtdlLogPrintf(CTDL_DEBUG, "CtdlSetSeen(%d msgs starting with %ld, %d, %d)\n",
+ /* If no room was specified, we go with the current room. */
+ if (!which_room) {
+ which_room = &CC->room;
+ }
+
+ /* If no user was specified, we go with the current user. */
+ if (!which_user) {
+ which_user = &CC->user;
+ }
+
+ CtdlLogPrintf(CTDL_DEBUG, "CtdlSetSeen(%d msgs starting with %ld, %s, %d) in <%s>\n",
num_target_msgnums, target_msgnums[0],
- target_setting, which_set);
+ (target_setting ? "SET" : "CLEAR"),
+ which_set,
+ which_room->QRname);
/* Learn about the user and room in question */
- CtdlGetRelationship(&vbuf,
- ((which_user != NULL) ? which_user : &CC->user),
- ((which_room != NULL) ? which_room : &CC->room)
- );
+ CtdlGetRelationship(&vbuf, which_user, which_room);
/* Load the message list */
- cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &which_room->QRnumber, sizeof(long));
if (cdbfr != NULL) {
msglist = (long *) cdbfr->ptr;
cdbfr->ptr = NULL; /* CtdlSetSeen() now owns this memory */
break;
}
- /* CtdlLogPrintf(CTDL_DEBUG, "before optimize: %s\n", vset); */
+
+#if 0 /* This is a special diagnostic section. Do not allow it to run during normal operation. */
+ CtdlLogPrintf(CTDL_DEBUG, "There are %d messages in the room.\n", num_msgs);
+ for (i=0; i<num_msgs; ++i) {
+ if (i > 0) if (msglist[i] <= msglist[i-1]) abort();
+ }
+ CtdlLogPrintf(CTDL_DEBUG, "We are twiddling %d of them.\n", num_target_msgnums);
+ for (k=0; k<num_target_msgnums; ++k) {
+ if (k > 0) if (target_msgnums[k] <= target_msgnums[k-1]) abort();
+ }
+#endif
+
+ CtdlLogPrintf(CTDL_DEBUG, "before update: %s\n", vset);
/* Translate the existing sequence set into an array of booleans */
num_sets = num_tokens(vset, ',');
extract_token(lostr, setstr, 0, ':', sizeof lostr);
if (num_tokens(setstr, ':') >= 2) {
extract_token(histr, setstr, 1, ':', sizeof histr);
- if (!strcmp(histr, "*")) {
- snprintf(histr, sizeof histr, "%ld", LONG_MAX);
- }
}
else {
strcpy(histr, lostr);
}
lo = atol(lostr);
- hi = atol(histr);
+ if (!strcmp(histr, "*")) {
+ hi = LONG_MAX;
+ }
+ else {
+ hi = atol(histr);
+ }
for (i = 0; i < num_msgs; ++i) {
if ((msglist[i] >= lo) && (msglist[i] <= hi)) {
}
}
+
/* Now translate the array of booleans back into a sequence set */
strcpy(vset, "");
- lo = (-1L);
- hi = (-1L);
+ was_seen = 0;
+ lo = (-1);
+ hi = (-1);
for (i=0; i<num_msgs; ++i) {
+ is_seen = is_set[i];
- is_seen = is_set[i]; /* Default to existing setting */
-
+ /* Apply changes */
for (k=0; k<num_target_msgnums; ++k) {
if (msglist[i] == target_msgnums[k]) {
is_seen = target_setting;
}
}
- if (is_seen) {
- if (lo < 0L) lo = msglist[i];
- hi = msglist[i];
- }
+ w = 0; /* set to 1 if we write something to the string */
- if ( ((is_seen == 0) && (was_seen == 1))
- || ((is_seen == 1) && (i == num_msgs-1)) ) {
+ if ((was_seen == 0) && (is_seen == 1)) {
+ lo = msglist[i];
+ }
+ else if ((was_seen == 1) && (is_seen == 0)) {
+ hi = msglist[i-1];
+ w = 1;
- /* begin trim-o-matic code */
- j=9;
- trimming = 0;
- while ( (strlen(vset) + 20) > sizeof vset) {
- remove_token(vset, 0, ',');
- trimming = 1;
- if (j--) break; /* loop no more than 9 times */
+ if (!IsEmptyStr(vset)) {
+ strcat(vset, ",");
}
- if ( (trimming) && (which_set == ctdlsetseen_seen) ) {
- t = atol(vset);
- if (t<2) t=2;
- --t;
- snprintf(lostr, sizeof lostr,
- "1:%ld,%s", t, vset);
- safestrncpy(vset, lostr, sizeof vset);
+ if (lo == hi) {
+ sprintf(&vset[strlen(vset)], "%ld", hi);
}
- /* end trim-o-matic code */
-
- tmp = strlen(vset);
- if (tmp > 0) {
+ else {
+ sprintf(&vset[strlen(vset)], "%ld:%ld", lo, hi);
+ }
+ }
+ else if ((is_seen) && (i == num_msgs - 1)) {
+ w = 1;
+ if (!IsEmptyStr(vset)) {
strcat(vset, ",");
- ++tmp;
}
- if (lo == hi) {
- snprintf(&vset[tmp], (sizeof vset) - tmp,
- "%ld", lo);
+ if ((i==0) || (was_seen == 0)) {
+ sprintf(&vset[strlen(vset)], "%ld", msglist[i]);
}
else {
- snprintf(&vset[tmp], (sizeof vset) - tmp,
- "%ld:%ld", lo, hi);
+ sprintf(&vset[strlen(vset)], "%ld:%ld", lo, msglist[i]);
}
- lo = (-1L);
- hi = (-1L);
}
+
+ /* If the string is getting too long, truncate it at the beginning; repeat up to 9 times */
+ if (w) for (j=0; j<9; ++j) {
+ if ((strlen(vset) + 20) > sizeof vset) {
+ remove_token(vset, 0, ',');
+ if (which_set == ctdlsetseen_seen) {
+ char temp[SIZ];
+ sprintf(temp, "1:%ld,", atol(vset)-1L);
+ strcat(temp, vset);
+ strcpy(vset, temp);
+ }
+ }
+ }
+
was_seen = is_seen;
}
+ CtdlLogPrintf(CTDL_DEBUG, " after update: %s\n", vset);
+
/* Decide which message set we're manipulating */
switch (which_set) {
case ctdlsetseen_seen:
safestrncpy(vbuf.v_seen, vset, sizeof vbuf.v_seen);
break;
case ctdlsetseen_answered:
- safestrncpy(vbuf.v_answered, vset,
- sizeof vbuf.v_answered);
+ safestrncpy(vbuf.v_answered, vset, sizeof vbuf.v_answered);
break;
}
- free(is_set);
- /* CtdlLogPrintf(CTDL_DEBUG, " after optimize: %s\n", vset); */
+ free(is_set);
free(msglist);
- CtdlSetRelationship(&vbuf,
- ((which_user != NULL) ? which_user : &CC->user),
- ((which_room != NULL) ? which_room : &CC->room)
- );
+ CtdlSetRelationship(&vbuf, which_user, which_room);
}
/* FIXME: check message id against msglist for this room */
/*
- * Fetch the message from disk. If we're in any sort of headers
- * only mode, request that we don't even bother loading the body
- * into memory.
+ * Fetch the message from disk. If we're in HEADERS_FAST mode,
+ * request that we don't even bother loading the body into memory.
*/
- if ( (headers_only == HEADERS_FAST) || (headers_only == HEADERS_ONLY) ) {
+ if (headers_only == HEADERS_FAST) {
TheMessage = CtdlFetchMessage(msg_num, 0);
}
else {
*AddrPtr = 0;
i = 0;
while (!IsEmptyStr (&source[i])) {
- if (nColons > nAddrPtrMax){
+ 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 + sizeof (long) * nAddrPtrMax, 0, sizeof (long) * nAddrPtrMax - 1);
+ memset(&ptr[nAddrPtrMax], 0,
+ sizeof (long) * nAddrPtrMax);
+
memcpy (ptr, AddrUtf8, sizeof (long) * nAddrPtrMax);
free (AddrUtf8), AddrUtf8 = ptr;
nAddrPtrMax *= 2;
if (source[i] == '"')
InQuotes = !InQuotes;
if (!InQuotes && source[i] == ',') {
- nColons++;
AddrPtr[nColons] = i;
+ nColons++;
}
i++;
}
EncodedMaxLen = nColons * (sizeof(headerStr) + 3) + SourceLen * 3;
Encoded = (char*) malloc (EncodedMaxLen);
- for (i = 1; i <= nColons; i++)
+ for (i = 0; i < nColons; i++)
source[AddrPtr[i]++] = '\0';
nPtr = Encoded;
*nPtr = '\0';
- for (i = 0; i <= nColons && nPtr != NULL; i++) {
+ for (i = 0; i < nColons && nPtr != NULL; i++) {
nmax = EncodedMaxLen - (nPtr - Encoded);
if (AddrUtf8[i]) {
process_rfc822_addr(&source[AddrPtr[i]],
i--; /* do it once more with properly lengthened buffer */
}
}
- for (i = 1; i <= nColons; i++)
+ for (i = 0; i < nColons; i++)
source[--AddrPtr[i]] = ',';
free(AddrUtf8);
free(AddrPtr);
if (!is_valid_message(TheMessage)) {
CtdlLogPrintf(CTDL_ERR,
"ERROR: invalid preloaded message for output\n");
+ cit_backtrace ();
return(om_no_such_msg);
}
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);
struct arcq arcq_rec;
int num_records_processed = 0;
- snprintf(file_arcq_temp, sizeof file_arcq_temp, "%s2", file_arcq);
+ snprintf(file_arcq_temp, sizeof file_arcq_temp, "%s.%04x", file_arcq, rand());
begin_critical_section(S_SUPPMSGMAIN);
if (arcfp != NULL) {
smi.meta_refcount += incr;
PutMetaData(&smi);
end_critical_section(S_SUPPMSGMAIN);
- CtdlLogPrintf(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
* 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);
safestrncpy(roomname, req_room, sizeof(roomname));
}
- fp = fopen(tempfilename, "rb");
- if (fp == NULL) {
- CtdlLogPrintf(CTDL_CRIT, "Cannot open %s: %s\n",
- tempfilename, strerror(errno));
- return;
- }
- fseek(fp, 0L, SEEK_END);
- raw_length = ftell(fp);
- rewind(fp);
CtdlLogPrintf(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);
-
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));
);
}
else {
- raw_message[raw_length] = 0;
memcpy(
&encoded_message[strlen(encoded_message)],
raw_message,
);
}
- free(raw_message);
-
CtdlLogPrintf(CTDL_DEBUG, "Allocating\n");
msg = malloc(sizeof(struct CtdlMessage));
memset(msg, 0, sizeof(struct CtdlMessage));
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);
}