$Log$
+ Revision 573.129 2001/04/21 04:55:51 ajc
+ * Began implementation of per-message seen/unseen attribute
+
Revision 573.128 2001/04/20 03:39:54 ajc
* IMAP LIST/LSUB: made it case insensitive. Also minor IMAP code cleanup.
Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
* Initial CVS import
-
#define INTERNETCFG "application/x-citadel-internet-config"
#define TRACE lprintf(9, "Checkpoint: %s, %d\n", __FILE__, __LINE__)
+
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647L
+#endif
void imap_fetch_flags(int seq) {
cprintf("FLAGS (");
if (IMAP->flags[seq] & IMAP_DELETED) cprintf("\\Deleted ");
+ if (IMAP->flags[seq] & IMAP_SEEN) cprintf("\\Seen ");
cprintf(")");
}
long thismsg;
struct SuppMsgInfo smi;
struct CtdlMessage *msg;
+ int is_seen;
/* Learn about the user and room in question */
get_mm();
if (num_msgs > 0)
for (a = 0; a < num_msgs; ++a) {
thismsg = msglist[a];
+ is_seen = is_msg_in_mset(vbuf.v_seen, thismsg);
if ((thismsg > 0)
&& (
(mode == MSGS_ALL)
- || ((mode == MSGS_OLD) && (thismsg <= vbuf.v_lastseen))
- || ((mode == MSGS_NEW) && (thismsg > vbuf.v_lastseen))
- || ((mode == MSGS_NEW) && (thismsg >= vbuf.v_lastseen)
- && (CC->usersupp.flags & US_LASTOLD))
+ || ((mode == MSGS_OLD) && (is_seen))
+ || ((mode == MSGS_NEW) && (!is_seen))
+ /* FIXME handle lastold mode */
|| ((mode == MSGS_LAST) && (a >= (num_msgs - ref)))
|| ((mode == MSGS_FIRST) && (a < ref))
|| ((mode == MSGS_GT) && (thismsg > ref))
}
NEWMSG: /* By the way, we also check for the presence of new messages */
- if ((roombuf->QRhighest) > (vbuf.v_lastseen)) {
+ if (is_msg_in_mset(vbuf.v_seen, roombuf->QRhighest) == 0) {
retval = retval | UA_HASNEWMSGS;
}
return (retval);
if (num_msgs > 0) for (a = 0; a < num_msgs; ++a) {
if (msglist[a] > 0L) {
++total_messages;
- if (msglist[a] > vbuf.v_lastseen) {
+ if (is_msg_in_mset(vbuf.v_seen, msglist[a]) == 0) {
++new_messages;
}
}
#include "tools.h"
-struct oldvisit {
- char v_roomname[ROOMNAMELEN];
- long v_generation;
- long v_lastseen;
- unsigned int v_flags;
-};
-
struct PurgeList {
struct PurgeList *next;
char name[ROOMNAMELEN]; /* use the larger of username or roomname */
}
+/*
+ * Set the \\Seen flag for messages which aren't new
+ */
+void imap_set_seen_flags(void) {
+ struct visit vbuf;
+ int i;
+
+ CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
+ if (IMAP->num_msgs > 0) {
+ for (i=0; i<IMAP->num_msgs; ++i) {
+ if (is_msg_in_mset(vbuf.v_seen, IMAP->msgids[i])) {
+ IMAP->flags[i] |= IMAP_SEEN;
+ }
+ }
+ }
+}
+
+
+
+
/*
* Back end for imap_load_msgids()
*
CtdlForEachMessage(MSGS_ALL, 0L, (-63), NULL, NULL,
imap_add_single_msgid, NULL);
+ imap_set_seen_flags();
lprintf(9, "imap_load_msgids() mapped %d messages\n", IMAP->num_msgs);
}
CtdlForEachMessage(MSGS_GT, original_highest, (-63), NULL, NULL,
imap_add_single_msgid, NULL);
+ imap_set_seen_flags();
+
/*
* If new messages have arrived, tell the client about them.
*/
/* FIXME ... much more info needs to be supplied here */
cprintf("* %d EXISTS\r\n", msgs);
cprintf("* %d RECENT\r\n", new);
- cprintf("* FLAGS (\\Deleted)\r\n");
- cprintf("* OK [PERMANENTFLAGS (\\Deleted)] permanent flags\r\n");
+ cprintf("* FLAGS (\\Deleted \\Seen)\r\n");
+ cprintf("* OK [PERMANENTFLAGS (\\Deleted \\Seen)] permanent flags\r\n");
cprintf("* OK [UIDVALIDITY 0] UIDs valid\r\n");
cprintf("%s OK [%s] %s completed\r\n",
parms[0],
CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
POP3->lastseen = (-1);
if (POP3->num_msgs) for (i=0; i<POP3->num_msgs; ++i) {
- if ((POP3->msgs[POP3->num_msgs-1].msgnum) <= vbuf.v_lastseen) {
+ if (is_msg_in_mset(vbuf.v_seen,
+ (POP3->msgs[POP3->num_msgs-1].msgnum) )) {
POP3->lastseen = i;
}
}
lgetuser(&CC->usersupp, CC->curr_user);
CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
- vbuf.v_lastseen = POP3->msgs[POP3->num_msgs-1].msgnum;
+ sprintf(vbuf.v_seen, "*:%ld",
+ POP3->msgs[POP3->num_msgs-1].msgnum);
CtdlSetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
lputuser(&CC->usersupp);
long v_usernum;
long v_lastseen;
unsigned int v_flags;
+ char v_seen[SIZ];
};
#define V_FORGET 1 /* User has zapped this room */
SLRP (Set Last-message-Read Pointer)
- This command is used to mark messages as having been read. Its sole parameter
+ This command marks all messages in the current room as read (seen) up to and
+including the specified number. Its sole parameter
is the number of the last message that has been read. This allows the pointer
to be set at any arbitrary point in the room. Optionally, the parameter
"highest" may be used instead of a message number, to set the pointer to the
+/*
+ * Determine whether the specified message number is contained within the
+ * specified set.
+ */
+int is_msg_in_mset(char *mset, long msgnum) {
+ int num_sets;
+ int s;
+ char setstr[SIZ], lostr[SIZ], histr[SIZ]; /* was 1024 */
+ long lo, hi;
+
+ /*
+ * Now set it for all specified messages.
+ */
+ num_sets = num_tokens(mset, ',');
+ for (s=0; s<num_sets; ++s) {
+ extract_token(setstr, mset, s, ',');
+
+ extract_token(lostr, setstr, 0, ':');
+ if (num_tokens(setstr, ':') >= 2) {
+ extract_token(histr, setstr, 1, ':');
+ if (!strcmp(histr, "*")) {
+ sprintf(histr, "%ld", LONG_MAX);
+ }
+ }
+ else {
+ strcpy(histr, lostr);
+ }
+ lo = atol(lostr);
+ hi = atol(histr);
+ if ((msgnum >= lo) && (msgnum <= hi)) return(1);
+ }
-
+ return(0);
+}
int collapsed_strcmp(char *s1, char *s2);
void remove_token(char *source, int parmnum, char separator);
void fmt_date(char *buf, time_t thetime);
+int is_msg_in_mset(char *mset, long msgnum);
#ifndef HAVE_STRNCASECMP
int strncasecmp(char *, char *, int)
((cdbvisit->len > sizeof(struct visit)) ?
sizeof(struct visit) : cdbvisit->len));
cdb_free(cdbvisit);
- return;
+ }
+
+ /* Set v_seen if necessary */
+ if (vbuf->v_seen[0] == 0) {
+ sprintf(vbuf->v_seen, "*:%ld", vbuf->v_lastseen);
}
}
long newlr;
struct visit vbuf;
- if (CtdlAccessCheck(ac_logged_in))
+ if (CtdlAccessCheck(ac_logged_in)) {
return;
+ }
if (!strncasecmp(new_ptr, "highest", 7)) {
newlr = CC->quickroom.QRhighest;
CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
vbuf.v_lastseen = newlr;
+ sprintf(vbuf.v_seen, "*:%ld", newlr);
CtdlSetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
lputuser(&CC->usersupp);