server proper and in IMAP. Citadel protocol uses new "seen" command.
$Log$
+ Revision 573.130 2001/04/26 03:31:00 ajc
+ * Finished the implementation of per-message seen/unseen logic, both in the
+ server proper and in IMAP. Citadel protocol uses new "seen" command.
+
Revision 573.129 2001/04/21 04:55:51 ajc
* Began implementation of per-message seen/unseen attribute
Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
* Initial CVS import
+
cmd_conf(&cmdbuf[5]);
}
+ else if (!strncasecmp(cmdbuf, "SEEN", 4)) {
+ cmd_seen(&cmdbuf[5]);
+ }
+
#ifdef DEBUG_MEMORY_LEAKS
else if (!strncasecmp(cmdbuf, "LEAK", 4)) {
dump_tracked();
IMAP->flags[seq] &= (~bits_to_twiddle);
}
+ if (bits_to_twiddle & IMAP_SEEN) {
+ CtdlSetSeen(IMAP->msgids[seq],
+ ((IMAP->flags[seq] & IMAP_SEEN) ? 1 : 0) );
+ }
+
cprintf("* %d FETCH (", seq+1);
imap_fetch_flags(seq);
cprintf(")\r\n");
bits_to_twiddle |= IMAP_DELETED;
}
}
+
+ if (!strcasecmp(flag, "\\Seen")) {
+ bits_to_twiddle |= IMAP_SEEN;
+ }
}
if (IMAP->num_msgs > 0) {
}
+/*
+ * Manipulate the "seen msgs" string.
+ */
+void CtdlSetSeen(long target_msgnum, int target_setting) {
+ char newseen[SIZ];
+ struct cdbdata *cdbfr;
+ int i;
+ int is_seen = 0;
+ int was_seen = 1;
+ long lo = (-1L);
+ long hi = (-1L);
+ struct visit vbuf;
+ long *msglist;
+ int num_msgs = 0;
+
+ /* Learn about the user and room in question */
+ get_mm();
+ getuser(&CC->usersupp, CC->curr_user);
+ CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
+
+ /* Load the message list */
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->quickroom.QRnumber, sizeof(long));
+ if (cdbfr != NULL) {
+ msglist = mallok(cdbfr->len);
+ memcpy(msglist, cdbfr->ptr, cdbfr->len);
+ num_msgs = cdbfr->len / sizeof(long);
+ cdb_free(cdbfr);
+ } else {
+ return; /* No messages at all? No further action. */
+ }
+
+ lprintf(9, "before optimize: %s\n", vbuf.v_seen);
+ strcpy(newseen, "");
+
+ for (i=0; i<num_msgs; ++i) {
+ is_seen = 0;
+
+ if (msglist[i] == target_msgnum) {
+ is_seen = target_setting;
+ }
+ else {
+ if (is_msg_in_mset(vbuf.v_seen, msglist[i])) {
+ is_seen = 1;
+ }
+ }
+
+ if (is_seen == 1) {
+ if (lo < 0L) lo = msglist[i];
+ hi = msglist[i];
+ }
+ if ( ((is_seen == 0) && (was_seen == 1))
+ || ((is_seen == 1) && (i == num_msgs-1)) ) {
+ if ( (strlen(newseen) + 20) > SIZ) {
+ strcpy(newseen, &newseen[20]);
+ newseen[0] = '*';
+ }
+ if (strlen(newseen) > 0) strcat(newseen, ",");
+ if (lo == hi) {
+ sprintf(&newseen[strlen(newseen)], "%ld", lo);
+ }
+ else {
+ sprintf(&newseen[strlen(newseen)], "%ld:%ld",
+ lo, hi);
+ }
+ lo = (-1L);
+ hi = (-1L);
+ }
+ was_seen = is_seen;
+ }
+
+ safestrncpy(vbuf.v_seen, newseen, SIZ);
+ lprintf(9, " after optimize: %s\n", vbuf.v_seen);
+ phree(msglist);
+ CtdlSetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
+}
/*
}
+ /*
+ * Now begin the traversal.
+ */
if (num_msgs > 0) for (a = 0; a < num_msgs; ++a) {
GetSuppMsgInfo(&smi, msglist[a]);
int CtdlCopyMsgToRoom(long msgnum, char *dest);
int CtdlDoIHavePermissionToDeleteMessagesFromThisRoom(void);
int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf);
+void CtdlSetSeen(long target_msgnum, int target_setting);
minutes) for well-behaved clients to voluntarily terminate, and then issue a
TERM command to forcibly disconnect the client (or perhaps a DOWN command, if
you are logging off users for the purpose of shutting down the server).
-
+
+
+ SEEN (set or clear the SEEN flag for a message)
+
+ Beginning with version 5.80, Citadel supports the concept of setting or
+clearing the "seen" flag for each individual message, instead of only allowing
+a "last seen" pointer. In fact, the old semantics are implemented in terms
+of the new semantics. This command requires two arguments: the number of the
+message to be set, and a 1 or 0 to set or clear the "seen" bit.
+
+ This command returns OK, unless the user is not logged in or a usage error
+occurred, in which case it returns ERROR. Please note that no checking is
+done on the supplied data; if the requested message does not exist, the SEEN
+command simply returns OK without doing anything.
+
+
ASYN (ASYNchronous message support)
}
+void cmd_seen(char *argbuf) {
+ long target_msgnum = 0L;
+ int target_setting = 0;
+
+ if (CtdlAccessCheck(ac_logged_in)) {
+ return;
+ }
+
+ if (num_parms(argbuf) != 2) {
+ cprintf("%d Invalid parameters\n", ERROR);
+ return;
+ }
+
+ target_msgnum = extract_long(argbuf, 0);
+ target_setting = extract_int(argbuf, 1);
+
+ CtdlSetSeen(target_msgnum, target_setting);
+ cprintf("%d OK\n", OK);
+}
+
+
/*
* INVT and KICK commands
*/
};
-
int CtdlForgetThisRoom(void);
+void cmd_seen(char *argbuf);