Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH] more IMAP browser fixes

0 views
Skip to first unread message

Brendan Cully

unread,
Feb 19, 2000, 3:00:00 AM2/19/00
to

--MfFXiAuoTsnnDAfZ
Content-Type: multipart/mixed; boundary="W/nzBZO5zC0uMSeA"
Content-Disposition: inline


--W/nzBZO5zC0uMSeA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Here is the IMAP browser cleanup I mentioned yesterday. Finally I
think it behaves more or less correctly on both Cyrus and UW-style
IMAP servers. Most of the fixes had to do with namespace handling. I
also cleaned up the appearance of the browser a bit from my last
patch. Folders which contain messages and subfolders are listed once,
with a plus next to them and terminated by the folder
delimiter. Folders which only have subfolders are terminated by the
delimiter. So for UW-IMAP users, the browser will look the same as it
always did.

I also removed the empty namespace entries (those namespaces are
listed as part of the home namespace). Some optimisation could still
be done - judicious caching could make the browser a lot faster. But
that can wait for 1.3. I just wanted to make the browser more or less
correct and sane for 1.2. I think it's there now. Please give the
browser a once over once this patch is applied, especially if you have
an unusual IMAP server.

Thanks,
Brendan
--W/nzBZO5zC0uMSeA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="browser.diff"
Content-Transfer-Encoding: quoted-printable

Index: browser.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/roessler/cvs/mutt/browser.c,v
retrieving revision 2.18
diff -u -p -r2.18 browser.c
--- browser.c 2000/02/14 16:07:54 2.18
+++ browser.c 2000/02/19 05:41:48
@@ -209,9 +209,9 @@ folder_format_str (char *dest, size_t de
#ifdef USE_IMAP
if (folder->ff->imap)
{
- sprintf (permission, "IMAP %c%c",
- folder->ff->inferiors ? '+' : ' ',
- folder->ff->selectable ? 'S' : ' ');
+ /* mark folders with subfolders AND mail */
+ sprintf (permission, "IMAP %c",
+ (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
snprintf (dest, destlen, tmp, permission);
} =20
@@ -688,8 +688,12 @@ void _mutt_select_file (char *f, size_t=20
strfcpy (LastDir, state.entry[menu->current].name,
sizeof (LastDir));
/* tack on delimiter here */
- if ((state.entry[menu->current].delim !=3D '\0') &&
- (n =3D strlen (LastDir)+1) < sizeof (LastDir))
+ n =3D strlen (LastDir)+1;
+ =20
+ /* special case "" needs no delimiter */
+ if ((strlen (strchr (LastDir, '}')) > 0) &&
+ (state.entry[menu->current].delim !=3D '\0') &&
+ (n < sizeof (LastDir)))
{
LastDir[n] =3D '\0';
LastDir[n-1] =3D state.entry[menu->current].delim;
Index: doc/manual.sgml.head
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/roessler/cvs/mutt/doc/manual.sgml.head,v
retrieving revision 1.23
diff -u -p -r1.23 manual.sgml.head
--- doc/manual.sgml.head 2000/02/15 08:59:41 1.23
+++ doc/manual.sgml.head 2000/02/19 05:42:06
@@ -2041,11 +2041,9 @@ server. This is mostly the same as the l
following differences:
<itemize>
<item>In lieu of file permissions, mutt displays the string "IMAP",
- possibly followed by the symbol "S", indicating that the entry is
- selectable (contains messages), and/or the symbol "+", indicating
- that the entry may contain subfolders. If your server is like the
- UW-IMAP server, you won't see both symbols, but if you are using a
- Cyrus-like server folders will often contain both messages and
+ possibly followed by the symbol the symbol "+", indicating
+ that the entry contains both messages and subfolders. On
+ Cyrus-like servers folders will often contain both messages and
subfolders.=20
<item>For the case where an entry can contain both messages and
subfolders, the selection key (bound to <tt>enter</tt> by default)
Index: imap/browse.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/roessler/cvs/mutt/imap/browse.c,v
retrieving revision 1.10
diff -u -p -r1.10 browse.c
--- imap/browse.c 2000/02/14 16:08:02 1.10
+++ imap/browse.c 2000/02/19 05:42:08
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1996-9 Brandon Long <bl...@fiction.net>
- * Copyright (C) 1999 Brendan Cully <bre...@kublai.com>
+ * Copyright (C) 1999-2000 Brendan Cully <bre...@kublai.com>
*=20
* 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
@@ -79,24 +79,29 @@ int imap_init_browse (char *path, struct
idata->conn =3D conn;
}
if (imap_open_connection (idata, conn))
- return (-1);
+ return -1;
}
=20
if (mx.mbox[0] =3D=3D '\0')
{
home_namespace =3D 1;
- mbox[0] =3D 0; /* Do not replace "" with "INBOX" here */
+ mbox[0] =3D '\0'; /* Do not replace "" with "INBOX" here */
mx.mbox =3D ImapHomeNamespace;
nns =3D 0;
if (mutt_bit_isset(idata->capabilities,NAMESPACE))
{
+ mutt_message _("Getting namespaces...");
if (get_namespace (idata, nsbuf, sizeof (nsbuf),=20
nsi, sizeof (nsi), &nns) !=3D 0)
- return (-1);
+ return -1;
if (verify_namespace (conn, nsi, nns) !=3D 0)
- return (-1);
+ return -1;
}
- if (!mx.mbox) /* Any explicitly set imap_home_namespace wins */
+ /* What if you have a shared namespace of ""? You'll never be
+ * able to browse it. This isn't conjecture: connect to the Cyrus
+ * reference server (cyrus.andrew.cmu.edu) as anonymous. argh! */
+#if 0
+ if (!mx.mbox) /* Any explicitly set imap_home_namespace wins */
{=20
for (i =3D 0; i < nns; i++)
if (nsi[i].listable &&
@@ -107,10 +112,14 @@ int imap_init_browse (char *path, struct
break;
}
}
+ else
+ dprint (4, (debugfile, "Home namespace: %s\n", mx.mbox));
+#endif
}
=20
- mutt_message _("Contacted server, getting folder list...");
+ mutt_message _("Getting folder list...");
=20
+ /* skip check for parents when at the root */
if (mx.mbox && mx.mbox[0] !=3D '\0')
{
imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox));
@@ -118,7 +127,7 @@ int imap_init_browse (char *path, struct
=20
dprint (3, (debugfile, "imap_init_browse: mbox: %s\n", mbox));
=20
- /* if our target exists, has inferiors and isn't selectable, enter it =
if we
+ /* if our target exists and has inferiors, enter it if we
* aren't already going to */
if (mbox[n-1] !=3D idata->delim)
{
@@ -136,7 +145,7 @@ int imap_init_browse (char *path, struct
{
imap_unquote_string (cur_folder);
=20
- if (noselect && !noinferiors && cur_folder[0] &&
+ if (!noinferiors && cur_folder[0] &&
(n =3D strlen (mbox)) < LONG_STRING-1)
{
mbox[n++] =3D idata->delim;
@@ -150,7 +159,9 @@ int imap_init_browse (char *path, struct
/* if we're descending a folder, mark it as current in browser_state */
if (mbox[n-1] =3D=3D idata->delim)
{
- showparents =3D 1;
+ /* don't show parents in the home namespace */
+ if (!home_namespace)
+ showparents =3D 1;
imap_qualify_path (buf, sizeof (buf), &mx, mbox, NULL);
state->folder =3D safe_strdup (buf);
n--;
@@ -159,12 +170,17 @@ int imap_init_browse (char *path, struct
/* Find superiors to list
* Note: UW-IMAP servers return folder + delimiter when asked to list
* folder + delimiter. Cyrus servers don't. So we ask for folder,
- * and tack on delimiter ourselves. */
+ * and tack on delimiter ourselves.
+ * Further note: UW-IMAP servers return nothing when asked for=20
+ * NAMESPACES without delimiters at the end. Argh! */
for (n--; n >=3D 0 && mbox[n] !=3D idata->delim ; n--);
if (n > 0) /* "aaaa/bbbb/" -> "aaaa" */
{
+ /* forget the check, it is too delicate (see above). Have we ever
+ * had the parent not exist? */
ctmp =3D mbox[n];
mbox[n] =3D '\0';
+#if 0
/* List it to see if it can be selected */
dprint (2, (debugfile, "imap_init_browse: listing possible parent %s=
\n", mbox));
imap_make_sequence (seq, sizeof (seq));
@@ -173,6 +189,10 @@ int imap_init_browse (char *path, struct
/* add this entry as a superior, if we aren't tab-completing */
if (showparents && add_list_result (conn, seq, buf, state, 1))
return -1;
+#else
+ dprint (2, (debugfile, "imap_init_browse: adding parent %s\n", mbox)=
);
+ imap_add_folder (idata->delim, mbox, 1, 0, state, 1);
+#endif =20
/* if our target isn't a folder, we are in our superior */
if (!state->folder)
{
@@ -213,6 +233,7 @@ int imap_init_browse (char *path, struct
/* Listing the home namespace, so INBOX should be included. Home=20
* namespace is not "", so we have to list it explicitly. We ask the=
=20
* server to see if it has descendants. */
+ dprint (4, (debugfile, "imap_init_browse: adding INBOX\n"));
imap_make_sequence (seq, sizeof (seq));
snprintf (buf, sizeof (buf), "%s LIST \"\" \"INBOX\"\r\n", seq);
if (add_list_result (conn, seq, buf, state, 0))
@@ -232,9 +253,12 @@ int imap_init_browse (char *path, struct
if (home_namespace)
{ /* List additional namespaces */
for (i =3D 0; i < nns; i++)
- if (nsi[i].listable && !nsi[i].home_namespace)
+ if (nsi[i].listable && !nsi[i].home_namespace) {
imap_add_folder(nsi[i].delim, nsi[i].prefix, nsi[i].noselect,
- nsi[i].noinferiors, state, 0);
+ nsi[i].noinferiors, state, 0);
+ dprint (4, (debugfile, "imap_init_browse: adding namespace: %s\n",
+ nsi[i].prefix));
+ }
}
=20
mutt_clear_error ();
@@ -322,6 +346,13 @@ static void imap_add_folder (char delim,
imap_qualify_path (tmp, sizeof (tmp), &mx, folder, NULL);
(state->entry)[state->entrylen].name =3D safe_strdup (tmp);
=20
+ /* mark desc with delim in browser if it can have subfolders */
+ if (!isparent && !noinferiors && strlen (relpath) < sizeof (relpath) - 1)
+ {
+ relpath[strlen (relpath) + 1] =3D '\0';
+ relpath[strlen (relpath)] =3D delim;
+ }
+ =20
(state->entry)[state->entrylen].desc =3D safe_strdup (relpath);
=20
(state->entry)[state->entrylen].imap =3D 1;
@@ -381,6 +412,8 @@ static int get_namespace (IMAP_DATA *ida
s++; /* skip ( */
/* copy namespace */
n =3D 0;
+ delim =3D '\0';
+
if (*s =3D=3D '\"')
{
s++;
@@ -401,17 +434,25 @@ static int get_namespace (IMAP_DATA *ida
ns[n] =3D '\0';
/* delim? */
s =3D imap_next_word (s);
- if (*s && *s =3D=3D '\"')
+ /* delimiter is meaningless if namespace is "". Why does
+ * Cyrus provide one?! */
+ if (n && *s && *s =3D=3D '\"')
{
if (s[1] && s[2] =3D=3D '\"')
delim =3D s[1];
else if (s[1] && s[1] =3D=3D '\\' && s[2] && s[3] =3D=3D '\"')
delim =3D s[2];
}
- /* Save result (if space) */
- if ((nsbused < nsblen) && (*nns < nsilen))
+ /* skip "" namespaces, they are already listed at the root */
+ if ((ns[0] !=3D '\0') && (nsbused < nsblen) && (*nns < nsilen))
{
+ dprint (4, (debugfile, "get_namespace: adding %s\n", ns));
nsi->type =3D type;
+ /* Cyrus doesn't append the delimiter to the namespace,
+ * but UW-IMAP does. We'll strip it here and add it back
+ * as if it were a normal directory, from the browser */
+ if (n && (ns[n-1] =3D=3D delim))
+ ns[--n] =3D '\0';
strncpy(nsbuf+nsbused,ns,nsblen-nsbused-1);
nsi->prefix =3D nsbuf+nsbused;
nsbused +=3D n+1;
@@ -452,8 +493,14 @@ static int verify_namespace (CONNECTION=20
/* Cyrus gives back nothing if the % isn't added. This may return lots
* of data in some cases, I guess, but I currently feel that's better
* than invisible namespaces */
- snprintf (buf, sizeof (buf), "%s %s \"\" \"%s%c%%\"\r\n", seq,=20
- option (OPTIMAPLSUB) ? "LSUB" : "LIST", nsi->prefix, nsi->delim);
+ if (nsi->delim)
+ snprintf (buf, sizeof (buf), "%s %s \"\" \"%s%c%%\"\r\n", seq,
+ option (OPTIMAPLSUB) ? "LSUB" : "LIST", nsi->prefix,
+ nsi->delim);
+ else
+ snprintf (buf, sizeof (buf), "%s %s \"\" \"%s%%\"\r\n", seq,
+ option (OPTIMAPLSUB) ? "LSUB" : "LIST", nsi->prefix);
+ =20
mutt_socket_write (conn, buf);
=20
nsi->listable =3D 0;

--W/nzBZO5zC0uMSeA--

--MfFXiAuoTsnnDAfZ
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.1 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE4ri/BIigsijWFMDIRAgPrAJ45rgcancFc3jLNXUj7z7dTlSKUMACgkntL
R3OFDc1CRdRpZtLj8+CYJAw=
=/sBJ
-----END PGP SIGNATURE-----

--MfFXiAuoTsnnDAfZ--

0 new messages