9front - general discussion about 9front
 help / color / mirror / Atom feed
* upas/fs imap fixes and improvements.
@ 2019-11-19 21:44 ori
  0 siblings, 0 replies; only message in thread
From: ori @ 2019-11-19 21:44 UTC (permalink / raw)
  To: 9front

This change prevents us from repeatedly fetching the headers for every
single message in the inbox, instead only fetching incrementally.
There's still a full fetch on startup, to make sure we have everything
synced.

It also fixes validity handling, records flags correctly when we're
not attaching them immediately to a message, and will no longer
mis-index the list messages if we get unsolicited fetch responses, and
fixes an off-by-one error that turned unknown messages into Auth
messages (which we ignored as a no-op).

I've not spent much intimate time with the imap spec, so if someone
could review carefully, that'd be appreciated.

Again, running it and it seems to work.

diff -r 663578b51263 sys/src/cmd/upas/fs/imap.c
--- a/sys/src/cmd/upas/fs/imap.c	Tue Nov 19 12:31:42 2019 -0800
+++ b/sys/src/cmd/upas/fs/imap.c	Tue Nov 19 13:37:36 2019 -0800
@@ -35,6 +35,7 @@
 	uvlong	uid;
 	ulong	sizes;
 	ulong	dates;
+	ulong	flags;
 } Fetchi;
 
 typedef struct Imap Imap;
@@ -51,6 +52,7 @@
 
 	ulong	tag;
 	ulong	validity;
+	ulong	newvalidity;
 	int	nmsg;
 	int	size;
 
@@ -163,20 +165,22 @@
 	Fetch,
 	Cap,
 	Auth,
+	Expunge,
 
 	Unknown,
 };
 
 static char *verblist[] = {
-[Ok]	"ok",
-[No]	"no",
-[Bad]	"bad",
-[Bye]	"bye",
-[Exists]	"exists",
-[Status]	"status",
-[Fetch]	"fetch",
-[Cap]	"capability",
-[Auth]	"authenticate",
+	[Ok]		"ok",
+	[No]		"no",
+	[Bad]		"bad",
+	[Bye]		"bye",
+	[Exists]	"exists",
+	[Status]	"status",
+	[Fetch]		"fetch",
+	[Cap]		"capability",
+	[Auth]		"authenticate",
+	[Expunge]	"expunge",
 };
 
 static int
@@ -187,7 +191,7 @@
 
 	if(q = strchr(verb, ' '))
 		*q = '\0';
-	for(i = 0; i < nelem(verblist) - 1; i++)
+	for(i = 0; i < nelem(verblist); i++)
 		if(strcmp(verblist[i], verb) == 0)
 			break;
 	if(q)
@@ -230,26 +234,29 @@
 	"\\Stored",	Fstored,
 };
 
-static void
-parseflags(Message *m, char *s)
+static int
+parseflags(char *s)
 {
 	char *f[10];
-	int i, j, j0, n;
+	int i, j, j0, n, flg;
 
 	n = tokenize(s, f, nelem(f));
 	qsort(f, n, sizeof *f, (int (*)(void*,void*))strcmp);
 	j = 0;
-	for(i = 0; i < n; i++)
+	flg = 0;
+	for(i = 0; i < n; i++){
 		for(j0 = j;; j++){
 			if(j == nelem(ftab)){
 				j = j0;		/* restart search */
 				break;
 			}
-			if(strcmp(f[i], ftab[j].flag) == 0){
-				m->flags |= ftab[j].e;
+			if(cistrcmp(f[i], ftab[j].flag) == 0){
+				flg |= ftab[j].e;
 				break;
 			}
 		}
+	}
+	return flg;
 }
 
 /* "17-Jul-1996 02:44:25 -0700" */
@@ -311,7 +318,7 @@
 	int nargs;
 
 	for(nargs=0; nargs < maxargs; nargs++){
-		while(*s!='\0' && utfrune(qsep, *s)!=nil)
+		while(*s!='\0' && utfrune(qsep, *s) != nil)
 			s++;
 		if(*s == '\0')
 			break;
@@ -323,7 +330,7 @@
 }
 
 static char*
-fetchrsp(Imap *imap, char *p, Mailbox *, Message *m)
+fetchrsp(Imap *imap, char *p, Mailbox *, Message *m, int idx)
 {
 	char *f[15], *s, *q;
 	int i, n, a;
@@ -332,6 +339,11 @@
 	static char error[256];
 	extern void msgrealloc(Message*, ulong);
 
+	if(idx < 0 || idx >= imap->muid){
+		snprint(error, sizeof error, "fetchrsp: bad idx %d", idx);
+		return error;
+	}
+
 redux:
 	n = imaptokenize(p, f, nelem(f));
 	if(n%2)
@@ -341,23 +353,26 @@
 			l = internaltounix(f[i + 1]);
 			if(l < 418319360)
 				abort();
-			if(imap->nuid < imap->muid)
+			if(idx < imap->muid)
 				imap->f[imap->nuid].dates = l;
 		}else if(strcmp(f[i], "rfc822.size") == 0){
 			l = strtoul(f[i + 1], 0, 0);
 			if(m)
 				m->size = l;
-			else if(imap->nuid < imap->muid)
-				imap->f[imap->nuid].sizes = l;
+			else if(idx < imap->muid)
+				imap->f[idx].sizes = l;
 		}else if(strcmp(f[i], "uid") == 0){
 			v = mkuid(imap, f[1]);
 			if(m)
 				m->imapuid = v;
-			if(imap->nuid < imap->muid)
-				imap->f[imap->nuid].uid = v;
+			if(idx < imap->muid)
+				imap->f[idx].uid = v;
 		}else if(strcmp(f[i], "flags") == 0){
+			l = parseflags(f[i + 1]);
 			if(m)
-				parseflags(m, f[i + 1]);
+				m->flags = l;
+			if(idx < imap->muid)
+				imap->f[idx].flags = l;
 		}else if(strncmp(f[i], "body[]", 6) == 0){
 			s = f[i]+6;
 			o = 0;
@@ -396,7 +411,7 @@
 		}else
 			return confused;
 	}
-	return 0;
+	return nil;
 }
 
 void
@@ -428,7 +443,7 @@
 imap4resp0(Imap *imap, Mailbox *mb, Message *m)
 {
 	char *e, *line, *p, *ep, *op, *q, *verb;
-	int n, unexp;
+	int n, idx, unexp;
 	static char error[256];
 
 	unexp = 0;
@@ -484,7 +499,7 @@
 				if(q = strstr(p, "messages"))
 					imap->nmsg = strtoul(q + 8, 0, 10);
 				if(q = strstr(p, "uidvalidity"))
-					imap->validity = strtoul(q + 11, 0, 10);
+					imap->newvalidity = strtoul(q + 11, 0, 10);
 				break;
 			case Fetch:
 				if(*p == '('){
@@ -492,9 +507,23 @@
 					if(ep[-1] == ')')
 						*--ep = 0;
 				}
-				if(e = fetchrsp(imap, p, mb, m))
+				if(e = fetchrsp(imap, p, mb, m, n - 1))
 					eprint("imap: fetchrsp: %s\n", e);
-				imap->nuid++;
+				idprint(imap, "n = %d, muid = %d, nuid = %d\n", n, imap->muid, imap->nuid);
+				if(n > 0 && n <= imap->muid && n > imap->nuid)
+					imap->nuid = n;
+				break;
+			case Expunge:
+				if(n < 1 || n > imap->muid){
+					snprint(error, sizeof(error), "bad expunge %d (nmsg %d)", n, imap->nuid);
+					return error;
+				}
+				idx = n - 1;
+				memcpy(&imap->f[idx], &imap->f[idx + 1], imap->nmsg - idx - 1);
+				imap->nmsg--;
+				imap->nuid--;
+				if(imap->nuid == imap->muid)
+					imap->muid--;
 				break;
 			case Auth:
 				break;
@@ -903,15 +932,28 @@
 	Fetchi *f;
 	Message *m, **ll;
 
+again:
 	imap4cmd(imap, "status %Z (messages uidvalidity)", imap->mbox);
 	if(!isokay(s = imap4resp(imap)))
 		return s;
+	/* the world shifted: start over */
+	if(imap->validity != imap->newvalidity){
+		imap->validity = imap->newvalidity;
+		imap->nuid = 0;
+		goto again;
+	}
 
-	imap->nuid = 0;
+	imap->f = erealloc(imap->f, imap->nmsg*sizeof imap->f[0]);
+	if(imap->nmsg > imap->muid)
+		memset(&imap->f[imap->muid], 0, (imap->nmsg - imap->muid)*sizeof(imap->f[0]));
 	imap->muid = imap->nmsg;
-	imap->f = erealloc(imap->f, imap->nmsg*sizeof imap->f[0]);
 	if(imap->nmsg > 0){
-		imap4cmd(imap, "uid fetch 1:* (uid rfc822.size internaldate)");
+		n = imap->nuid;
+		if(n == 0)
+			n = 1;
+		if(n > imap->nmsg)
+			n = imap->nmsg;
+		imap4cmd(imap, "fetch %d:%d (uid flags rfc822.size internaldate)", n, imap->nmsg);
 		if(!isokay(s = imap4resp(imap)))
 			return s;
 	}
@@ -949,6 +991,7 @@
 			m->imapuid = f[i].uid;
 			m->fileid = datesec(imap, i);
 			m->size = f[i].sizes;
+			m->flags = f[i].flags;
 			m->next = *ll;
 			*ll = m;
 			ll = &m->next;



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2019-11-19 21:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-19 21:44 upas/fs imap fixes and improvements ori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).