]> granicus.if.org Git - neomutt/commitdiff
Brandon's IMAP clean-up; new czech translation.
authorThomas Roessler <roessler@does-not-exist.org>
Tue, 9 Feb 1999 20:50:36 +0000 (20:50 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Tue, 9 Feb 1999 20:50:36 +0000 (20:50 +0000)
15 files changed:
OPS
browser.c
browser.h [new file with mode: 0644]
complete.c
doc/manual.sgml.in
functions.h
imap.c
imap.h
init.h
menu.c
mutt.h
mutt_socket.h
mx.c
po/cs.po
socket.c

diff --git a/OPS b/OPS
index e5add27a0162b8a288febceaf4a6b0171048020f..23a60feeba77556049dd79a7d259b056d2e71ad6 100644 (file)
--- a/OPS
+++ b/OPS
@@ -6,6 +6,9 @@ OP_BOUNCE_MESSAGE "remail a message to another user"
 OP_BROWSER_NEW_FILE "select a new file in this directory"
 OP_BROWSER_VIEW_FILE "view file"
 OP_BROWSER_TELL "display the currently selected file's name"
+OP_BROWSER_SUBSCRIBE "subscribe to current mailbox (IMAP Only)"
+OP_BROWSER_UNSUBSCRIBE "unsubscribe to current mailbox (IMAP Only)"
+OP_BROWSER_TOGGLE_LSUB "toggle view all/subscribed mailboxes (IMAP Only)"
 OP_CHANGE_DIRECTORY "change directories"
 OP_CHECK_NEW "check mailboxes for new mail"
 OP_COMPOSE_ATTACH_FILE "attach a file(s) to this message"
@@ -143,7 +146,7 @@ OP_TAG_SUBTHREAD "tag the current subthread"
 OP_TAG_THREAD "tag the current thread"
 OP_TOGGLE_NEW "toggle a message's 'new' flag"
 OP_TOGGLE_WRITE "toggle whether the mailbox will be rewritten"
-OP_TOGGLE_MAILBOXES "toggle wether to browse mailboxes or all files"
+OP_TOGGLE_MAILBOXES "toggle whether to browse mailboxes or all files"
 OP_TOP_PAGE "move to the top of the page"
 OP_UNDELETE "undelete the current entry"
 OP_UNDELETE_THREAD "undelete all messages in thread"
index ae4a29d9b8bd9450346e0383a709cb5636306771..e6264561f81b6ce86a0b30a0ce13dd23b42cf3d3 100644 (file)
--- a/browser.c
+++ b/browser.c
 #include "mapping.h"
 #include "sort.h"
 #include "mailbox.h"
+#include "browser.h"
+#ifdef USE_IMAP
+#include "imap.h"
+#endif
 
 #include <stdlib.h>
 #include <dirent.h>
 #include <pwd.h>
 #include <grp.h>
 
-struct folder_file
-{
-  mode_t mode;
-  time_t mtime;
-  off_t size;
-  char *name;
-  char *desc;
-  short tagged;
-};
-
-struct browser_state
-{
-  struct folder_file *entry;
-  short entrylen; /* number of real entries */
-  short entrymax;  /* max entry */
-};
-
 static struct mapping_t FolderHelp[] = {
   { N_("Exit"),  OP_EXIT },
   { N_("Chdir"), OP_CHANGE_DIRECTORY },
@@ -456,6 +443,12 @@ static void init_menu (struct browser_state *state, MUTTMENU *menu, char *title,
   {
     strfcpy (path, LastDir, sizeof (path));
     mutt_pretty_mailbox (path);
+#ifdef USE_IMAP
+  if (state->imap_browse && option (OPTIMAPLSUB))
+    snprintf (title, titlelen, _("Subscribed [%s], File mask: %s"),
+             path, Mask.pattern);
+  else
+#endif
     snprintf (title, titlelen, _("Directory [%s], File mask: %s"),
              path, Mask.pattern);
   }
@@ -491,6 +484,17 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
   if (*f)
   {
     mutt_expand_path (f, flen);
+#ifdef USE_IMAP
+    if (mx_is_imap (f))
+    {
+      init_state (&state, NULL);
+      state.imap_browse = 1;
+      imap_init_browse (f, &state);
+      strfcpy (LastDir, f, sizeof (LastDir));
+    }
+    else
+    {
+#endif
     for (i = mutt_strlen (f) - 1; i > 0 && f[i] != '/' ; i--);
     if (i > 0)
     {
@@ -520,9 +524,23 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
     else
       strfcpy (prefix, f + i + 1, sizeof (prefix));
     killPrefix = 1;
+#ifdef USE_IMAP
+    }
+#endif
+  }
+  else 
+  {
+    if (!LastDir[0])
+      strfcpy (LastDir, NONULL(Maildir), sizeof (LastDir));
+#ifdef USE_IMAP
+    if (!buffy && mx_is_imap (LastDir))
+    {
+      init_state (&state, NULL);
+      state.imap_browse = 1;
+      imap_init_browse (LastDir, &state);
+    }
+#endif
   }
-  else if (!LastDir[0])
-    strfcpy (LastDir, NONULL(Maildir), sizeof (LastDir));
 
   *f = 0;
 
@@ -531,7 +549,11 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
     if (examine_mailboxes (NULL, &state) == -1)
       return;
   }
-  else if (examine_directory (NULL, &state, LastDir, prefix) == -1)
+  else
+#ifdef USE_IMAP
+  if (!state.imap_browse)
+#endif
+  if (examine_directory (NULL, &state, LastDir, prefix) == -1)
     return;
 
   menu = mutt_new_menu ();
@@ -561,7 +583,11 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
 
         if (S_ISDIR (state.entry[menu->current].mode) ||
            (S_ISLNK (state.entry[menu->current].mode) &&
-           link_is_dir (state.entry[menu->current].name)))
+           link_is_dir (state.entry[menu->current].name)) 
+#ifdef USE_IMAP
+           || state.entry[menu->current].notfolder
+#endif
+           )
        {
          /* make sure this isn't a MH or maildir mailbox */
          if (buffy)
@@ -569,11 +595,21 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
            strfcpy (buf, state.entry[menu->current].name, sizeof (buf));
            mutt_expand_path (buf, sizeof (buf));
          }
+#ifdef USE_IMAP
+         else if (state.imap_browse)
+         {
+           strfcpy (buf, state.entry[menu->current].name, sizeof (buf));
+         }
+#endif
          else
            snprintf (buf, sizeof (buf), "%s/%s", LastDir, 
                      state.entry[menu->current].name);
 
-         if (mx_get_magic (buf) <= 0)
+         if ((mx_get_magic (buf) <= 0)
+#ifdef USE_IMAP
+           || state.entry[menu->current].notfolder
+#endif
+           )
          {
            char OldLastDir[_POSIX_PATH_MAX];
 
@@ -604,6 +640,13 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
              sprintf (LastDir, "%s", state.entry[menu->current].name);
              mutt_expand_path (LastDir, sizeof (LastDir));
            }
+#ifdef USE_IMAP
+           else if (state.imap_browse)
+           {
+             strfcpy (LastDir, state.entry[menu->current].name, 
+                 sizeof (LastDir));
+           }
+#endif
            else
              sprintf (LastDir + mutt_strlen (LastDir), "/%s",
                       state.entry[menu->current].name);
@@ -615,6 +658,16 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
              killPrefix = 0;
            }
            buffy = 0;
+#ifdef USE_IMAP
+           if (state.imap_browse)
+           {
+             init_state (&state, NULL);
+             state.imap_browse = 1;
+             imap_init_browse (LastDir, &state);
+             menu->data = state.entry;
+           }
+           else
+#endif
            if (examine_directory (menu, &state, LastDir, prefix) == -1)
            {
              /* try to restore the old values */
@@ -637,6 +690,12 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
          strfcpy (f, state.entry[menu->current].name, flen);
          mutt_expand_path (f, flen);
        }
+#ifdef USE_IMAP
+       else if (state.imap_browse)
+       {
+         strfcpy (f, state.entry[menu->current].name, flen);
+       }
+#endif
        else
          snprintf (f, flen, "%s/%s", LastDir, state.entry[menu->current].name);
 
@@ -684,10 +743,35 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
         if(state.entrylen)
          mutt_message(state.entry[menu->current].name);
         break;
+
+#ifdef USE_IMAP
+      case OP_BROWSER_SUBSCRIBE:
+       imap_subscribe (state.entry[menu->current].name, 1);
+       break;
+
+      case OP_BROWSER_UNSUBSCRIBE:
+       imap_subscribe (state.entry[menu->current].name, 0);
+       break;
+
+      case OP_BROWSER_TOGGLE_LSUB:
+       if (option (OPTIMAPLSUB))
+       {
+         unset_option (OPTIMAPLSUB);
+       }
+       else
+       {
+         set_option (OPTIMAPLSUB);
+       }
+       mutt_ungetch (0, OP_CHECK_NEW);
+       break;
+#endif
       
       case OP_CHANGE_DIRECTORY:
 
        strfcpy (buf, LastDir, sizeof (buf));
+#ifdef USE_IMAP
+       if (!state.imap_browse)
+#endif
        {/* add '/' at the end of the directory name */
        int len=mutt_strlen(LastDir);
        if (sizeof (buf) > len)
@@ -699,6 +783,21 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
        {
          buffy = 0;      
          mutt_expand_path (buf, sizeof (buf));
+#ifdef USE_IMAP
+         if (mx_is_imap (buf))
+         {
+           strfcpy (LastDir, buf, sizeof (LastDir));
+           destroy_state (&state);
+           init_state (&state, NULL);
+           state.imap_browse = 1;
+           imap_init_browse (LastDir, &state);
+           menu->data = state.entry;
+           menu->current = 0; 
+           menu->top = 0; 
+           init_menu (&state, menu, title, sizeof (title), buffy);
+         }
+         else
+#endif
          if (stat (buf, &st) == 0)
          {
            if (S_ISDIR (st.st_mode))
@@ -834,11 +933,21 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
        destroy_state (&state);
        prefix[0] = 0;
        killPrefix = 0;
+
        if (buffy)
        {
          if (examine_mailboxes (menu, &state) == -1)
            return;
        }
+#ifdef USE_IMAP
+       else if (mx_is_imap (LastDir))
+       {
+         init_state (&state, NULL);
+         state.imap_browse = 1;
+         imap_init_browse (LastDir, &state);
+         menu->data = state.entry;
+       }
+#endif
        else if (examine_directory (menu, &state, LastDir, prefix) == -1)
          return;
        init_menu (&state, menu, title, sizeof (title), buffy);
diff --git a/browser.h b/browser.h
new file mode 100644 (file)
index 0000000..b19fb5b
--- /dev/null
+++ b/browser.h
@@ -0,0 +1,48 @@
+/* $Id$ */
+/*
+ * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
+ * 
+ *     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
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */ 
+
+#ifndef _BROWSER_H
+#define _BROWSER_H 1
+
+struct folder_file
+{
+  mode_t mode;
+  time_t mtime;
+  off_t size;
+  char *name;
+  char *desc;
+#ifdef USE_IMAP
+  short notfolder;
+#endif
+};
+
+struct browser_state
+{
+  struct folder_file *entry;
+  short entrylen; /* number of real entries */
+  short entrymax;  /* max entry */
+#ifdef USE_IMAP
+  short imap_browse;
+  int noselect : 1;
+  int marked : 1;
+  int unmarked : 1;
+#endif
+};
+
+#endif /* _BROWSER_H */
index f8d708f52fa7c8fcb87a7c95f58900a2e9631fc0..f3f58f5746371869bd8f0e94db46d681672b3a40 100644 (file)
@@ -32,7 +32,7 @@
 int mutt_complete (char *s)
 {
   char *p;
-  DIR *dirp;
+  DIR *dirp = NULL;
   struct dirent *de;
   int i ,init=0;
   size_t len;
@@ -85,12 +85,23 @@ int mutt_complete (char *s)
       /* no directory name, so assume current directory. */
       dirpart[0] = 0;
       strfcpy (filepart, s, sizeof (filepart));
-      dirp = opendir (".");
+#ifdef USE_IMAP
+      if (s[0] != '{')
+#endif
+       dirp = opendir (".");
     }
   }
 
   if (dirp == NULL)
   {
+#ifdef USE_IMAP
+    /* If we are trying to complete an IMAP folder, it will start with {
+     * in which case, we just return 0 at this point.  Eventually, we
+     * might complete the actually folder name from the server
+     */
+    if ((s[0] == '{') || (exp_dirpart[0] == '{'))
+      return 0;
+#endif
     dprint (1, (debugfile, "mutt_complete(): %s: %s (errno %d).\n", exp_dirpart, strerror (errno), errno));
     return (-1);
   }
index d49d133775b4c7e0f334d35db913af81d3deac9d..7ddcdb3f8e34a5488a6b775e242de1304332f13d 100644 (file)
@@ -1811,7 +1811,7 @@ url="http://www.ccil.org/~esr/fetchmail" name="fetchmail">
 
 If Mutt was compiled with IMAP support (by running the <em/configure/
 script with the <em/--enable-imap/ flag), it has the ability to work
-with folders located on a remote imap server.
+with folders located on a remote IMAP server.
 
 You can access the remote inbox by selecting the folder
 <tt/{imapserver}inbox/, where <tt/imapserver/ is the name of the IMAP
@@ -1821,8 +1821,30 @@ server, you should use <tt>{imapserver}path/to/folder</tt> where
 <tt>path/to/folder</tt> is the path of the folder you want to access
 relative to your home directory.
 
-<bf/Note:/ The IMAP support is in a very early state and quite
-unstable at the moment. If you need a more stable way to access your
+You can select an alternative port by specifying it with the server, ie:
+<tt/{imapserver:port}inbox/.
+
+Note that not all servers use / as the hierarchy separator.  Mutt should
+correctly notice which separator is being used by the server and convert
+paths accordingly.
+
+When browsing folders on an IMAP server, you can toggle whether to look
+at only the folders you are subscribed to, or all folders with the
+<em/toggle-subscribed/ command.  See also the 
+<ref id="imap&lowbar;list&lowbar;subscribed" name="&dollar;imap&lowbar;list&lowbar;subscribed"> variable.
+
+Mutt was designed to work with IMAP4rev1 servers, and has been tested
+with both the UWash IMAP server v11.241 and the Cyrus IMAP server v1.5.14.
+Note that if you are using mbox as the mail store on the UWash server,
+the server will disconnect a client if another client selects the same
+folder.
+
+Mutt currently does not support completion of IMAP folder names.  Hit
+the <em/complete/ key again to go to the IMAP browser.
+
+<bf/Note:/ The IMAP support has had very limited testing due to a lack
+of developers using it.  It should work with the reference servers
+mentioned above, but if you need a more stable way to access your
 IMAP folder, consider using a specialized program, such as <htmlurl
 url="http://www.ccil.org/~esr/fetchmail" name="fetchmail">.
 
@@ -2953,6 +2975,15 @@ Default: 0
 This variable configures how often (in seconds) IMAP should look for
 new mail.
 
+<sect2>imap&lowbar;list&lowbar;subscribed<label id="imap_list_subscribed">
+<p>
+Type: boolean<newline>
+Default: unset
+
+This variable configures whether IMAP folder browsing will look for only
+subscribed folders or all folders.  This can be toggled in the IMAP
+browser with the <em/toggle-subscribed/ command.
+
 <sect2>imap&lowbar;pass<label id="imap_pass">
 <p>
 Type: string<newline>
@@ -2964,6 +2995,16 @@ you should only use this option when you are on a fairly secure machine,
 because the superuser can read your muttrc even if you are the only one who
 can read the file.
 
+<sect2>imap&lowbar;passive<label id="imap_passive">
+<p>
+Type: boolean<newline>
+Default: set
+
+When set, mutt will not open new IMAP connections to check for new mail.
+Mutt will only check for new mail over existing IMAP connections.  This
+is useful if you don't want to be prompted to user/password pairs on
+mutt invocation, or if opening the connection is slow.
+
 <sect2>imap&lowbar;user<label id="imap_user">
 <p>
 Type: string<newline>
@@ -4604,6 +4645,11 @@ search-reverse         ESC /   search backwards for a regular expression
 select-new                 N   select a new file in this directory
 sort                       o   sort messages
 sort-reverse               O   sort messages in reverse order
+toggle-mailboxes         TAB   toggle whether to browse mailboxes or all files
+view-file              SPACE   view file
+subscribe                  s   subscribe to current mailbox (IMAP Only)
+unsubscribe                u   unsubscribe to current mailbox (IMAP Only)
+toggle-subscribed          T   toggle view all/subscribed mailboxes (IMAP Only)
 </verb>
 <sect2>pgp
 <p>
index 125dedcf9e049ad75b7bfd2c9064dedd2d515f68..4b5ec6c3ee244f2bd69130f3159ba8108ecc49b4 100644 (file)
@@ -323,6 +323,11 @@ struct binding_t OpBrowser[] = {
   { "check-new",       OP_CHECK_NEW,           NULL },
   { "toggle-mailboxes", OP_TOGGLE_MAILBOXES,   "\t" },
   { "view-file",       OP_BROWSER_VIEW_FILE,   " " },
+#ifdef USE_IMAP
+  { "subscribe",       OP_BROWSER_SUBSCRIBE,   "s" },
+  { "unsubscribe",     OP_BROWSER_UNSUBSCRIBE, "u" },
+  { "toggle-subscribed", OP_BROWSER_TOGGLE_LSUB, "T" },
+#endif
   { NULL,              0,                      NULL }
 };
 
diff --git a/imap.c b/imap.c
index 92ac8e2a1f7e0559e5ddaa84108fc32949723f32..b45b8b0325870d836601c53da92cf8abe4503446 100644 (file)
--- a/imap.c
+++ b/imap.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
+ * Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
  * 
  *     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
@@ -23,6 +24,7 @@
 #include "globals.h"
 #include "mutt_socket.h"
 #include "sort.h"
+#include "browser.h"
 
 #include <unistd.h>
 #include <netinet/in.h>
@@ -65,6 +67,15 @@ enum
   IMAP_OK_FAIL
 };
 
+enum
+{
+  /* States */
+  IMAP_DISCONNECTED = 0,
+  IMAP_CONNECTED,
+  IMAP_AUTHENTICATED,
+  IMAP_SELECTED
+};
+
 typedef struct
 {
   unsigned int index;
@@ -73,15 +84,21 @@ typedef struct
 
 typedef struct
 {
+  /* This data is specific to a CONNECTION to an IMAP server */
   short status;
-  unsigned short newMailCount;
-  char *mailbox;
-  short xxx;
-  IMAP_CACHE cache[IMAP_CACHE_LEN];
+  short state;
+  char delim;
   CONNECTION *conn;
+
+  /* The following data is all specific to the currently SELECTED mbox */
+  CONTEXT *selected_ctx;
+  char *selected_mailbox;
+  unsigned int newMailCount;
+  IMAP_CACHE cache[IMAP_CACHE_LEN];
 } IMAP_DATA;
 
 #define CTX_DATA ((IMAP_DATA *) ctx->data)
+#define CONN_DATA ((IMAP_DATA *) conn->data)
 #define SELCTX_DATA ((IMAP_DATA *) selctx->data)
 
 /* Linked list to hold header information while downloading message
@@ -102,14 +119,15 @@ typedef struct imap_header_info
   struct imap_header_info *next;
 } IMAP_HEADER_INFO;
 
-
 static void imap_make_sequence (char *buf, size_t buflen)
 {
   static int sequence = 0;
   
   snprintf (buf, buflen, "a%04d", sequence++);
-}
 
+  if (sequence > 9999)
+    sequence = 0;
+}
 
 static void imap_error (const char *where, const char *msg)
 {
@@ -307,6 +325,36 @@ static void imap_quote_string (char *dest, size_t slen, const char *src)
   *pt = 0;
 }
 
+static void imap_unquote_string (char *s)
+{
+  char *d = s;
+
+  if (*s == '\"')
+    s++;
+  else
+    return;
+
+  while (*s)
+  {
+    if (*s == '\"')
+    {
+      *d = '\0';
+      return;
+    }
+    if (*s == '\\')
+    {
+      s++;
+    }
+    if (*s)
+    {
+      *d = *s;
+      d++;
+      s++;
+    }
+  }
+  *d = '\0';
+}
+
 static int imap_read_bytes (FILE *fp, CONNECTION *conn, long bytes)
 {
   long pos;
@@ -342,15 +390,14 @@ static char *imap_next_word (char *s)
   return s;
 }
 
-static int imap_handle_untagged (CONTEXT *ctx, char *s)
+static int imap_handle_untagged (IMAP_DATA *idata, char *s)
 {
   char *pn;
   int count;
-  CONTEXT *selctx = (CONTEXT *)(CTX_DATA->conn->data);
 
   s = imap_next_word (s);
 
-  if (isdigit (*s))
+  if ((idata->state == IMAP_SELECTED) && isdigit (*s))
   {
     pn = s;
     s = imap_next_word (s);
@@ -363,30 +410,27 @@ static int imap_handle_untagged (CONTEXT *ctx, char *s)
       /* new mail arrived */
       count = atoi (pn);
 
-      if ( (SELCTX_DATA->status != IMAP_EXPUNGE) && 
-       count < selctx->msgcount)
+      if ( (idata->status != IMAP_EXPUNGE) && 
+       count < idata->selected_ctx->msgcount)
       {
        /* something is wrong because the server reported fewer messages
         * than we previously saw
         */
        mutt_error _("Fatal error.  Message count is out of sync!");
-       SELCTX_DATA->status = IMAP_FATAL;
-       CTX_DATA->status = IMAP_FATAL;
-       mx_fastclose_mailbox (ctx);
-       if (ctx != selctx)
-         mx_fastclose_mailbox (selctx);
+       idata->status = IMAP_FATAL;
+       mx_fastclose_mailbox (idata->selected_ctx);
        return (-1);
       }
       else
       {
-       if (SELCTX_DATA->status != IMAP_EXPUNGE)
-         SELCTX_DATA->status = IMAP_NEW_MAIL;
-       SELCTX_DATA->newMailCount = count;
+       if (idata->status != IMAP_EXPUNGE)
+         idata->status = IMAP_NEW_MAIL;
+       idata->newMailCount = count;
       }
     }
     else if (mutt_strncasecmp ("EXPUNGE", s, 7) == 0)
     {
-       SELCTX_DATA->status = IMAP_EXPUNGE;
+       idata->status = IMAP_EXPUNGE;
     }
   }
   else if (mutt_strncasecmp ("BYE", s, 3) == 0)
@@ -395,11 +439,9 @@ static int imap_handle_untagged (CONTEXT *ctx, char *s)
     s += 3;
     SKIPWS (s);
     mutt_error (s);
-    SELCTX_DATA->status = IMAP_BYE;
-    CTX_DATA->status = IMAP_BYE;
-    mx_fastclose_mailbox (ctx);
-    if (ctx != selctx)
-      mx_fastclose_mailbox (selctx);
+    idata->status = IMAP_BYE;
+    if (idata->state == IMAP_SELECTED)
+      mx_fastclose_mailbox (idata->selected_ctx);
     return (-1);
   }
   else
@@ -515,7 +557,7 @@ static int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend)
             pc = buf;
           }
         }
-        else if (imap_handle_untagged (ctx, buf) != 0)
+        else if (imap_handle_untagged (CTX_DATA, buf) != 0)
           return (-1);
       }
     }
@@ -643,8 +685,8 @@ static int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint)
   ctx->id_hash = hash_create (1031);
   ctx->subj_hash = hash_create (1031);
 
-  mutt_message (_("Reopening mailbox..."), CTX_DATA->mailbox);
-  imap_quote_string (buf, sizeof(buf), CTX_DATA->mailbox);
+  mutt_message (_("Reopening mailbox... %s"), CTX_DATA->selected_mailbox);
+  imap_quote_string (buf, sizeof(buf), CTX_DATA->selected_mailbox);
   imap_make_sequence (seq, sizeof (seq));
   snprintf (bufout, sizeof (bufout), "%s SELECT %s\r\n", seq, buf);
   mutt_socket_write (CTX_DATA->conn, bufout);
@@ -670,12 +712,23 @@ static int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint)
        if (mutt_strncasecmp ("EXISTS", pc, 6) == 0)
          count = n;
       }
-      else if (imap_handle_untagged (ctx, buf) != 0)
+      else if (imap_handle_untagged (CTX_DATA, buf) != 0)
        return (-1);
     }
   }
   while (mutt_strncmp (seq, buf, mutt_strlen (seq)) != 0);
 
+  if (!imap_code (buf))
+  {
+    char *s;
+    s = imap_next_word (buf); /* skip seq */
+    s = imap_next_word (s); /* Skip response */
+    CTX_DATA->state = IMAP_AUTHENTICATED;
+    mutt_error (s);
+    sleep (1);
+    return (-1);
+  }
+
   ctx->hdrmax = count;
   ctx->hdrs = safe_malloc (count * sizeof (HEADER *));
   ctx->v2r = safe_malloc (count * sizeof (int));
@@ -768,47 +821,48 @@ static int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint)
  * failing, this is used for checking for a mailbox on append and login
  * Return 0 on success, -1 on Failure, -2 on OK Failure
  */
-static int imap_exec (char *buf, size_t buflen,
-                     CONTEXT *ctx, const char *seq, const char *cmd, int flags)
+static int imap_exec (char *buf, size_t buflen, IMAP_DATA *idata,
+                     const char *seq, const char *cmd, int flags)
 {
   int count;
-  CONTEXT *selctx = (CONTEXT *)(CTX_DATA->conn->data);
 
-  mutt_socket_write (CTX_DATA->conn, cmd);
+  mutt_socket_write (idata->conn, cmd);
 
   do
   {
-    if (mutt_socket_read_line_d (buf, buflen, CTX_DATA->conn) < 0)
+    if (mutt_socket_read_line_d (buf, buflen, idata->conn) < 0)
       return (-1);
 
-    if (buf[0] == '*' && imap_handle_untagged (ctx, buf) != 0)
+    if (buf[0] == '*' && imap_handle_untagged (idata, buf) != 0)
       return (-1);
   }
   while (mutt_strncmp (buf, seq, SEQLEN) != 0);
 
-  if (!selctx->closing && 
-      (SELCTX_DATA->status == IMAP_NEW_MAIL || 
-       SELCTX_DATA->status == IMAP_EXPUNGE))
+  if ((idata->state == IMAP_SELECTED) && 
+      !idata->selected_ctx->closing && 
+      (idata->status == IMAP_NEW_MAIL || 
+       idata->status == IMAP_EXPUNGE))
   {
 
-    count = SELCTX_DATA->newMailCount;
+    count = idata->newMailCount;
 
-    if (SELCTX_DATA->status == IMAP_NEW_MAIL && count > selctx->msgcount)
+    if (idata->status == IMAP_NEW_MAIL && count > idata->selected_ctx->msgcount)
     {
       /* read new mail messages */
       dprint (1, (debugfile, "imap_exec(): new mail detected\n"));
 
-      while (count > selctx->hdrmax)
-       mx_alloc_memory (selctx);
+      while (count > idata->selected_ctx->hdrmax)
+       mx_alloc_memory (idata->selected_ctx);
 
-      count = imap_read_headers (selctx, selctx->msgcount, count - 1) + 1;
+      count = imap_read_headers (idata->selected_ctx, 
+         idata->selected_ctx->msgcount, count - 1) + 1;
     }
     else
     {
-      imap_reopen_mailbox (selctx, NULL);
+      imap_reopen_mailbox (idata->selected_ctx, NULL);
     }
 
-    SELCTX_DATA->status = 0;
+    idata->status = 0;
 
     mutt_clear_error ();
   }
@@ -831,153 +885,240 @@ static int imap_exec (char *buf, size_t buflen,
   return 0;
 }
 
-static int imap_parse_path (char *path, char *host, size_t hlen, char **mbox)
+static int imap_get_delim (IMAP_DATA *idata, CONNECTION *conn)
+{
+  char buf[LONG_STRING];
+  char seq[8];
+  char *s;
+
+  /* assume that the delim is /.  If this fails, we're in bigger trouble
+   * than getting the delim wrong */
+  idata->delim = '/';
+
+  imap_make_sequence (seq, sizeof (seq));
+  snprintf (buf, sizeof (buf), "%s LIST \"\" \"\"\r\n", seq);
+
+  mutt_socket_write (conn, buf);
+
+  do 
+  {
+    if (mutt_socket_read_line_d (buf, sizeof (buf), conn) < 0)
+    {
+      return (-1);
+    }
+
+    if (buf[0] == '*') 
+    {
+      s = imap_next_word (buf);
+      if (mutt_strncasecmp ("LIST", s, 4) == 0)
+      {
+       s = imap_next_word (s);
+       s = imap_next_word (s);
+       if (s && s[0] == '\"' && s[1] && s[2] == '\"')
+         idata->delim = s[1];
+       else if (s && s[0] == '\"' && s[1] && s[1] == '\\' && s[2] && s[3] == '\"')
+         idata->delim = s[2];
+      }
+      else
+      {
+       if (conn->data && 
+           imap_handle_untagged (idata, buf) != 0)
+         return (-1);
+      }
+    }
+  }
+  while ((mutt_strncmp (buf, seq, SEQLEN) != 0));
+  return 0;
+}
+
+static int imap_parse_path (char *path, char *host, size_t hlen, int *port, 
+    char **mbox)
 {
   int n;
   char *pc;
+  char *pt;
 
+  /* set default port */
+  *port = IMAP_PORT;
   pc = path;
   if (*pc != '{')
     return (-1);
   pc++;
   n = 0;
-  while (*pc && *pc != '}' && (n < hlen-1))
+  while (*pc && *pc != '}' && *pc != ':' && (n < hlen-1))
     host[n++] = *pc++;
   host[n] = 0;
   if (!*pc)
     return (-1);
+  if (*pc == ':')
+  {
+    pc++;
+    pt = pc;
+    while (*pc && *pc != '}') pc++;
+    if (!*pc)
+      return (-1);
+    *pc = '\0';
+    *port = atoi (pt);
+    *pc = '}';
+  }
   pc++;
 
   *mbox = pc;
   return 0;
 }
 
-static int imap_open_connection (CONTEXT *ctx, CONNECTION *conn)
+/*
+ * Fix up the imap path.  This is necessary because the rest of mutt
+ * assumes a hierarchy delimiter of '/', which is not necessarily true
+ * in IMAP.  Additionally, the filesystem converts multiple hierarchy
+ * delimiters into a single one, ie "///" is equal to "/".  IMAP servers
+ * are not required to do this.
+ */
+static char *imap_fix_path (IMAP_DATA *idata, char *mailbox, char *path, 
+    size_t plen)
+{
+  int x = 0;
+
+  if (!mailbox || !*mailbox)
+  {
+    strfcpy (path, "INBOX", plen);
+    return path;
+  }
+
+  while (mailbox && *mailbox && (x < (plen - 1)))
+  {
+    if ((*mailbox == '/') || (*mailbox == idata->delim))
+    {
+      while ((*mailbox == '/') || (*mailbox == idata->delim)) mailbox++;
+      path[x] = idata->delim;
+    }
+    else
+    {
+      path[x] = *mailbox;
+      mailbox++;
+    }
+    x++;
+  }
+  path[x] = '\0';
+  return path;
+}
+
+static int imap_authenticate (IMAP_DATA *idata, CONNECTION *conn)
 {
-  char *portnum, *hostname;
-  struct sockaddr_in sin;
-  struct hostent *he;
   char buf[LONG_STRING];
   char user[SHORT_STRING], q_user[SHORT_STRING];
   char pass[SHORT_STRING], q_pass[SHORT_STRING];
   char seq[16];
 
-  memset (&sin, 0, sizeof (sin));
-  hostname = safe_strdup (conn->server);
-  portnum = strrchr (hostname, ':');
-  if (portnum) 
-  { 
-    *portnum=0; 
-    portnum++; 
-  }
-  sin.sin_port = htons (portnum ? atoi(portnum) : IMAP_PORT);
-  sin.sin_family = AF_INET;
-  if ((he = gethostbyname (hostname)) == NULL)
-  {
-    safe_free ((void*)&hostname);
-    mutt_perror (conn->server);
-    return (-1);
-  }
-  safe_free ((void*)&hostname);
-  memcpy (&sin.sin_addr, he->h_addr_list[0], he->h_length);
+  int r = 1;
 
-  if ((conn->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
+  while (r != 0)
   {
-    mutt_perror ("socket");
-    return (-1);
+    if (!ImapUser)
+    {
+      strfcpy (user, NONULL(Username), sizeof (user));
+      if (mutt_get_field (_("IMAP Username: "), user, sizeof (user), 0) != 0 ||
+         !user[0])
+      {
+       user[0] = 0;
+       return (-1);
+      }
+    }
+    else
+      strfcpy (user, ImapUser, sizeof (user));
+
+    if (!ImapPass)
+    {
+      pass[0]=0;
+      snprintf (buf, sizeof (buf), _("Password for %s@%s: "), user, conn->server);
+      if (mutt_get_field (buf, pass, sizeof (pass), M_PASS) != 0 ||
+         !pass[0])
+      {
+       return (-1);
+      }
+    }
+    else
+      strfcpy (pass, ImapPass, sizeof (pass));
+
+    imap_quote_string (q_user, sizeof (q_user), user);
+    imap_quote_string (q_pass, sizeof (q_pass), pass);
+
+    mutt_message _("Logging in...");
+    imap_make_sequence (seq, sizeof (seq));
+    snprintf (buf, sizeof (buf), "%s LOGIN %s %s\r\n", seq, q_user, q_pass);
+    r = imap_exec (buf, sizeof (buf), idata, seq, buf, IMAP_OK_FAIL);
+    if (r == -1)
+    {
+      /* connection or protocol problem */
+      imap_error ("imap_open_connection()", buf);
+      return (-1);
+    }
+    else if (r == -2)
+    {
+      /* Login failed, try again */
+      mutt_error _("Login failed.");
+      sleep (1);
+      FREE (&ImapUser);
+      FREE (&ImapPass);
+    }
+    else
+    {
+      /* If they have a successful login, we may as well cache the 
+       * user/password. */
+      if (!ImapUser)
+       ImapUser = safe_strdup (user);
+      if (!ImapPass)
+       ImapPass = safe_strdup (pass);
+    }
   }
+  return 0;
+}
 
-  mutt_message (_("Connecting to %s..."), conn->server);
+static int imap_open_connection (IMAP_DATA *idata, CONNECTION *conn)
+{
+  char buf[LONG_STRING];
 
-  if (connect (conn->fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
+  if (mutt_socket_open_connection (conn) < 0)
   {
-    mutt_perror ("connect");
-    close (conn->fd);
+    return (-1);
   }
 
+  idata->state = IMAP_CONNECTED;
+
   if (mutt_socket_read_line_d (buf, sizeof (buf), conn) < 0)
   {
     close (conn->fd);
+    idata->state = IMAP_DISCONNECTED;
     return (-1);
   }
 
   if (mutt_strncmp ("* OK", buf, 4) == 0)
   {
-    int r = 1;
-
-    while (r != 0)
+    if (imap_authenticate (idata, conn) != 0)
     {
-      if (!ImapUser)
-      {
-       strfcpy (user, NONULL(Username), sizeof (user));
-       if (mutt_get_field (_("IMAP Username: "), user, sizeof (user), 0) != 0 ||
-           !user[0])
-       {
-         user[0] = 0;
-         return (-1);
-       }
-      }
-      else
-       strfcpy (user, ImapUser, sizeof (user));
-
-      if (!ImapPass)
-      {
-       pass[0]=0;
-       snprintf (buf, sizeof (buf), _("Password for %s@%s: "), user, conn->server);
-       if (mutt_get_field (buf, pass, sizeof (pass), M_PASS) != 0 ||
-           !pass[0])
-       {
-         return (-1);
-       }
-      }
-      else
-       strfcpy (pass, ImapPass, sizeof (pass));
-
-      imap_quote_string (q_user, sizeof (q_user), user);
-      imap_quote_string (q_pass, sizeof (q_pass), pass);
-
-      mutt_message _("Logging in...");
-      imap_make_sequence (seq, sizeof (seq));
-      snprintf (buf, sizeof (buf), "%s LOGIN %s %s\r\n", seq, q_user, q_pass);
-      r = imap_exec (buf, sizeof (buf), ctx, seq, buf, IMAP_OK_FAIL);
-      if (r == -1)
-      {
-       /* connection or protocol problem */
-       imap_error ("imap_open_connection()", buf);
-       return (-1);
-      }
-      else if (r == -2)
-      {
-       /* Login failed, try again */
-       mutt_error _("Login failed.");
-       sleep (1);
-       FREE (&ImapUser);
-       FREE (&ImapPass);
-      }
-      else
-      {
-       /* If they have a successful login, we may as well cache the 
-        * user/password. */
-       if (!ImapUser)
-         ImapUser = safe_strdup (user);
-       if (!ImapPass)
-         ImapPass = safe_strdup (pass);
-      }
+      close (conn->fd);
+      idata->state = IMAP_DISCONNECTED;
+      return (-1);
     }
   }
   else if (mutt_strncmp ("* PREAUTH", buf, 9) != 0)
   {
     imap_error ("imap_open_connection()", buf);
     close (conn->fd);
+    idata->state = IMAP_DISCONNECTED;
     return (-1);
   }
 
+  idata->state = IMAP_AUTHENTICATED;
+
+  imap_get_delim (idata, conn);
   return 0;
 }
 
 int imap_open_mailbox (CONTEXT *ctx)
 {
   CONNECTION *conn;
+  IMAP_DATA *idata;
   char buf[LONG_STRING];
   char bufout[LONG_STRING];
   char host[SHORT_STRING];
@@ -985,36 +1126,56 @@ int imap_open_mailbox (CONTEXT *ctx)
   char *pc = NULL;
   int count = 0;
   int n;
+  int port;
 
-  if (imap_parse_path (ctx->path, host, sizeof (host), &pc))
+  if (imap_parse_path (ctx->path, host, sizeof (host), &port, &pc))
     return (-1);
 
-  /* create IMAP-specific state struct */
-  ctx->data = safe_malloc (sizeof (IMAP_DATA));
-  memset (ctx->data, 0, sizeof (IMAP_DATA));
-
-  CTX_DATA->mailbox = safe_strdup (*pc?pc:"INBOX");
+  conn = mutt_socket_select_connection (host, port, 0);
+  idata = CONN_DATA;
 
-  conn = mutt_socket_select_connection (host, IMAP_PORT, M_NEW_SOCKET);
-  CTX_DATA->conn = conn;
-
-  if (conn->uses == 0)
+  if (!idata || (idata->state != IMAP_AUTHENTICATED))
   {
-    conn->data = (void *)ctx;
-    if (imap_open_connection (ctx, conn))
+    if (!idata || (idata->state == IMAP_SELECTED) || 
+       (idata->state == IMAP_CONNECTED))
+    {
+      /* We need to create a new connection, the current one isn't useful */
+      idata = safe_calloc (1, sizeof (IMAP_DATA));
+
+      conn = mutt_socket_select_connection (host, port, M_NEW_SOCKET);
+      conn->data = idata;
+      idata->conn = conn;
+    }
+    if (imap_open_connection (idata, conn))
       return (-1);
   }
-  conn->uses++;
+  ctx->data = (void *) idata;
+
+  /* Clean up path and replace the one in the ctx */
+  imap_fix_path (idata, pc, buf, sizeof (buf));
+  idata->selected_mailbox = safe_strdup (buf);
+  if (port != IMAP_PORT)
+    snprintf (buf, sizeof (buf), "{%s:%d}%s", host, port, 
+       idata->selected_mailbox);
+  else
+    snprintf (buf, sizeof (buf), "{%s}%s", host, idata->selected_mailbox);
+
+  FREE (&(ctx->path));
+  ctx->path = safe_strdup (buf);
 
-  mutt_message (_("Selecting %s..."), CTX_DATA->mailbox);
-  imap_quote_string(buf, sizeof(buf), CTX_DATA->mailbox);
+  idata->selected_ctx = ctx;
+
+  mutt_message (_("Selecting %s..."), idata->selected_mailbox);
+  imap_quote_string (buf, sizeof(buf), idata->selected_mailbox);
   imap_make_sequence (seq, sizeof (seq));
   snprintf (bufout, sizeof (bufout), "%s SELECT %s\r\n", seq, buf);
-  mutt_socket_write (CTX_DATA->conn, bufout);
+  mutt_socket_write (conn, bufout);
+
+  idata->state = IMAP_SELECTED;
 
   do
   {
-    if (mutt_socket_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0)
+    if (mutt_socket_read_line_d (buf, sizeof (buf), conn) < 0)
       break;
 
     if (buf[0] == '*')
@@ -1033,32 +1194,43 @@ int imap_open_mailbox (CONTEXT *ctx)
        if (mutt_strncasecmp ("EXISTS", pc, 6) == 0)
          count = n;
       }
-      else if (imap_handle_untagged (ctx, buf) != 0)
+      else if (imap_handle_untagged (idata, buf) != 0)
        return (-1);
     }
   }
   while (mutt_strncmp (seq, buf, mutt_strlen (seq)) != 0);
 
+  if (!imap_code (buf))
+  {
+    char *s;
+    s = imap_next_word (buf); /* skip seq */
+    s = imap_next_word (s); /* Skip response */
+    mutt_error (s);
+    idata->state = IMAP_AUTHENTICATED;
+    sleep (1);
+    return (-1);
+  }
+
   ctx->hdrmax = count;
   ctx->hdrs = safe_malloc (count * sizeof (HEADER *));
   ctx->v2r = safe_malloc (count * sizeof (int));
   ctx->msgcount = 0;
-  count=imap_read_headers (ctx, 0, count - 1) + 1;
+  count = imap_read_headers (ctx, 0, count - 1) + 1;
 
   dprint (1, (debugfile, "imap_open_mailbox(): msgcount is %d\n", ctx->msgcount));
   return 0;
 }
 
-static int imap_create_mailbox (CONTEXT *ctx)
+static int imap_create_mailbox (IMAP_DATA *idata, char *mailbox)
 {
   char seq[8];
   char buf[LONG_STRING], mbox[LONG_STRING];
 
   imap_make_sequence (seq, sizeof (seq));
-  imap_quote_string (mbox, sizeof (mbox), CTX_DATA->mailbox);
+  imap_quote_string (mbox, sizeof (mbox), mailbox);
   snprintf (buf, sizeof (buf), "%s CREATE %s\r\n", seq, mbox);
       
-  if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
+  if (imap_exec (buf, sizeof (buf), idata, seq, buf, 0) != 0)
   {
     imap_error ("imap_create_mailbox()", buf);
     return (-1);
@@ -1069,49 +1241,61 @@ static int imap_create_mailbox (CONTEXT *ctx)
 int imap_open_mailbox_append (CONTEXT *ctx)
 {
   CONNECTION *conn;
+  IMAP_DATA *idata;
   char host[SHORT_STRING];
   char buf[LONG_STRING], mbox[LONG_STRING];
+  char mailbox[LONG_STRING];
   char seq[16];
   char *pc;
   int r;
+  int port;
 
-  if (imap_parse_path (ctx->path, host, sizeof (host), &pc))
+  if (imap_parse_path (ctx->path, host, sizeof (host), &port, &pc))
     return (-1);
 
-  /* create IMAP-specific state struct */
-  ctx->data = safe_malloc (sizeof (IMAP_DATA));
-  memset (ctx->data, 0, sizeof (IMAP_DATA));
   ctx->magic = M_IMAP;
 
-  CTX_DATA->mailbox = pc;
-
-  conn = mutt_socket_select_connection (host, IMAP_PORT, 0);
-  CTX_DATA->conn = conn;
+  conn = mutt_socket_select_connection (host, port, 0);
+  idata = CONN_DATA;
 
-  if (conn->uses == 0)
-    if (imap_open_connection (ctx, conn))
+  if (!idata || (idata->state == IMAP_DISCONNECTED))
+  {
+    if (!idata)
+    {
+      /* The current connection is a new connection */
+      idata = safe_calloc (1, sizeof (IMAP_DATA));
+      conn->data = idata;
+      idata->conn = conn;
+    }
+    if (imap_open_connection (idata, conn))
       return (-1);
-  conn->uses++;
+  }
+  ctx->data = (void *) idata;
 
   /* check mailbox existance */
 
-  imap_quote_string (mbox, sizeof (mbox), CTX_DATA->mailbox);
+  imap_fix_path (idata, pc, mailbox, sizeof (mailbox));
+
+  imap_quote_string (mbox, sizeof (mbox), mailbox);
   imap_make_sequence (seq, sizeof (seq));
   snprintf (buf, sizeof (buf), "%s STATUS %s (UIDVALIDITY)\r\n", seq, mbox);
       
-  r = imap_exec (buf, sizeof (buf), ctx, seq, 
-      buf, IMAP_OK_FAIL);
+  r = imap_exec (buf, sizeof (buf), idata, seq, buf, IMAP_OK_FAIL);
   if (r == -2)
   {
     /* command failed cause folder doesn't exist */
     if (option (OPTCONFIRMCREATE))
     {
-      snprintf (buf, sizeof (buf), _("Create %s?"), CTX_DATA->mailbox);
+      snprintf (buf, sizeof (buf), _("Create %s?"), mailbox);
       if (mutt_yesorno (buf, 1) < 1)
+      {
+       return (-1);
+      }
+      if (imap_create_mailbox (idata, mailbox) < 0)
+      {
        return (-1);
+      }
     }
-    if (imap_create_mailbox (ctx) < 0)
-      return (-1);
   }
   else if (r == -1)
   {
@@ -1205,7 +1389,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
          fputs ("\n", msg->fp);
        }
       }
-      else if (imap_handle_untagged (ctx, buf) != 0)
+      else if (imap_handle_untagged (CTX_DATA, buf) != 0)
        return (-1);
     }
   }
@@ -1247,10 +1431,20 @@ flush_buffer(char *buf, size_t *len, CONNECTION *conn)
 int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
 {
   FILE *fp;
-  char seq[8];
   char buf[LONG_STRING];
+  char host[SHORT_STRING];
+  char mbox[LONG_STRING];
+  char mailbox[LONG_STRING]; 
+  char seq[16];
+  char *pc;
+  int port;
   size_t len;
   int c, last;
+
+  if (imap_parse_path (ctx->path, host, sizeof (host), &port, &pc))
+    return (-1);
+
+  imap_fix_path (CTX_DATA, pc, mailbox, sizeof (mailbox));
   
   if ((fp = fopen (msg->path, "r")) == NULL)
   {
@@ -1268,9 +1462,10 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
   rewind(fp);
   
   mutt_message _("Sending APPEND command ...");
+
+  imap_quote_string (mbox, sizeof (mbox), mailbox);
   imap_make_sequence (seq, sizeof (seq));
-  snprintf (buf, sizeof (buf), "%s APPEND %s {%d}\r\n", seq, 
-      CTX_DATA->mailbox, len);
+  snprintf (buf, sizeof (buf), "%s APPEND %s {%d}\r\n", seq, mbox, len);
 
   mutt_socket_write (CTX_DATA->conn, buf);
 
@@ -1282,8 +1477,7 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
       return (-1);
     }
 
-    if (buf[0] == '*' && ctx->data && 
-       imap_handle_untagged (ctx, buf) != 0)
+    if (buf[0] == '*' && imap_handle_untagged (CTX_DATA, buf) != 0)
     {
       fclose (fp);
       return (-1);
@@ -1331,7 +1525,7 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
     if (mutt_socket_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0)
       return (-1);
 
-    if (buf[0] == '*' && imap_handle_untagged (ctx, buf) != 0)
+    if (buf[0] == '*' && imap_handle_untagged (CTX_DATA, buf) != 0)
       return (-1);
   }
   while (mutt_strncmp (buf, seq, SEQLEN) != 0);
@@ -1374,6 +1568,7 @@ int imap_close_connection (CONTEXT *ctx)
     mutt_clear_error ();
   }
   close (CTX_DATA->conn->fd);
+  CTX_DATA->state = IMAP_DISCONNECTED;
   CTX_DATA->conn->uses = 0;
   CTX_DATA->conn->data = NULL;
   return 0;
@@ -1409,7 +1604,7 @@ int imap_sync_mailbox (CONTEXT *ctx)
       imap_make_sequence (seq, sizeof (seq));
       snprintf (buf, sizeof (buf), "%s STORE %d FLAGS.SILENT (%s)\r\n", seq, 
        ctx->hdrs[n]->index + 1, tmp);
-      if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
+      if (imap_exec (buf, sizeof (buf), CTX_DATA, seq, buf, 0) != 0)
       {
        imap_error ("imap_sync_mailbox()", buf);
        return (-1);
@@ -1421,7 +1616,7 @@ int imap_sync_mailbox (CONTEXT *ctx)
   CTX_DATA->status = IMAP_EXPUNGE;
   imap_make_sequence (seq, sizeof (seq));
   snprintf (buf, sizeof (buf), "%s EXPUNGE\r\n", seq);
-  if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
+  if (imap_exec (buf, sizeof (buf), CTX_DATA, seq, buf, 0) != 0)
   {
     imap_error ("imap_sync_mailbox()", buf);
     return (-1);
@@ -1440,6 +1635,27 @@ int imap_sync_mailbox (CONTEXT *ctx)
   return 0;
 }
 
+/* commit changes and terminate connection */
+static int imap_close_mailbox (IMAP_DATA *idata)
+{
+  char seq[8];
+  char buf[LONG_STRING];
+
+  /* tell the server to commit changes */
+  mutt_message _("Closing mailbox...");
+  imap_make_sequence (seq, sizeof (seq));
+  snprintf (buf, sizeof (buf), "%s CLOSE\r\n", seq);
+  if (imap_exec (buf, sizeof (buf), idata, seq, buf, 0) != 0)
+  {
+    imap_error ("imap_close_mailbox()", buf);
+    idata->status = IMAP_FATAL;
+    return (-1);
+  }
+  idata->state = IMAP_AUTHENTICATED;
+  return 0;
+}
+
+
 void imap_fastclose_mailbox (CONTEXT *ctx)
 {
   int i;
@@ -1447,9 +1663,10 @@ void imap_fastclose_mailbox (CONTEXT *ctx)
   /* Check to see if the mailbox is actually open */
   if (!ctx->data)
     return;
-  CTX_DATA->conn->uses--;
-  if ((CTX_DATA->conn->uses == 0) || (CTX_DATA->status == IMAP_BYE))
-    imap_close_connection (ctx);
+
+  if ((CTX_DATA->state == IMAP_SELECTED) && (ctx == CTX_DATA->selected_ctx))
+    if (imap_close_mailbox (CTX_DATA) != 0)
+
   for (i = 0; i < IMAP_CACHE_LEN; i++)
   {
     if (CTX_DATA->cache[i].path)
@@ -1458,25 +1675,12 @@ void imap_fastclose_mailbox (CONTEXT *ctx)
       safe_free ((void **) &CTX_DATA->cache[i].path);
     }
   }
-  safe_free ((void **) &ctx->data);
-}
-
-/* commit changes and terminate connection */
-int imap_close_mailbox (CONTEXT *ctx)
-{
-  char seq[8];
-  char buf[LONG_STRING];
-
-  /* tell the server to commit changes */
-  mutt_message _("Closing mailbox...");
-  imap_make_sequence (seq, sizeof (seq));
-  snprintf (buf, sizeof (buf), "%s CLOSE\r\n", seq);
-  if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
+  if (CTX_DATA->status == IMAP_BYE || CTX_DATA->status == IMAP_FATAL)
   {
-    imap_error ("imap_close_mailbox()", buf);
-    return (-1);
+    imap_close_connection (ctx);
+    CTX_DATA->conn->data = NULL;
+    safe_free ((void **) &ctx->data);
   }
-  return 0;
 }
 
 /* use the NOOP command to poll for new mail */
@@ -1496,7 +1700,7 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint)
 
   imap_make_sequence (seq, sizeof (seq));
   snprintf (buf, sizeof (buf), "%s NOOP\r\n", seq);
-  if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
+  if (imap_exec (buf, sizeof (buf), CTX_DATA, seq, buf, 0) != 0)
   {
     imap_error ("imap_check_mailbox()", buf);
     return (-1);
@@ -1508,25 +1712,46 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint)
 int imap_buffy_check (char *path)
 {
   CONNECTION *conn;
+  IMAP_DATA *idata;
   char host[SHORT_STRING];
   char buf[LONG_STRING];
+  char mbox[LONG_STRING];
   char seq[8];
-  char *mbox;
   char *s;
+  char *pc;
   char recent = FALSE;
+  int port;
 
-  if (imap_parse_path (path, host, sizeof (host), &mbox))
+  if (imap_parse_path (path, host, sizeof (host), &port, &pc))
     return -1;
 
-  conn = mutt_socket_select_connection (host, IMAP_PORT, 0);
+  conn = mutt_socket_select_connection (host, port, 0);
+  idata = CONN_DATA;
 
-  /* Currently, we don't open a connection to check, but we'll check
-   * over an existing connection */
-  if (conn->uses == 0)
+  if (!idata || (idata->state == IMAP_DISCONNECTED))
+  {
+    /* If passive is selected, then we don't open connections to check
+     * for new mail */
+    if (option (OPTIMAPPASSIVE))
+      return (-1);
+    if (!idata)
+    {
+      /* The current connection is a new connection */
+      idata = safe_calloc (1, sizeof (IMAP_DATA));
+      conn->data = idata;
+      idata->conn = conn;
+    }
+    if (imap_open_connection (idata, conn))
       return (-1);
-  conn->uses++;
+  }
+
+  imap_fix_path (idata, pc, buf, sizeof (buf));
+  /* Update the path, if it fits */
+  if (strlen (buf) < strlen (pc))
+      strcpy (pc, buf);
 
   imap_make_sequence (seq, sizeof (seq));
+  imap_quote_string (mbox, sizeof(mbox), buf);
   snprintf (buf, sizeof (buf), "%s STATUS %s (RECENT)\r\n", seq, mbox);
 
   mutt_socket_write (conn, buf);
@@ -1538,16 +1763,6 @@ int imap_buffy_check (char *path)
       return (-1);
     }
 
-    /* BUG: We don't handle other untagged messages here.  This is
-     * actually because of a more general problem in that this
-     * connection is being used for a different mailbox, and all
-     * untagged messages we don't handle here (ie, STATUS) need to be
-     * sent to imap_handle_untagged() but with the CONTEXT of the
-     * currently selected mailbox.  The same is broken in the APPEND
-     * stuff above.
-     * FIXED?  We now store the "real" CTX in the CONNECTION structure
-     * and use that here and in append.
-     */
     if (buf[0] == '*') 
     {
       s = imap_next_word (buf);
@@ -1571,7 +1786,7 @@ int imap_buffy_check (char *path)
       else
       {
        if (conn->data && 
-           imap_handle_untagged ((CONTEXT *)(conn->data), buf) != 0)
+           imap_handle_untagged (idata, buf) != 0)
          return (-1);
       }
     }
@@ -1582,3 +1797,332 @@ int imap_buffy_check (char *path)
 
   return recent;
 }
+
+static void add_folder (char delim, char *folder, char *host, int port, 
+    int noselect, int noinferiors, struct browser_state *state)
+{
+  char tmp[LONG_STRING];
+  char idir[LONG_STRING];
+  int flen = strlen (folder);
+  int x;
+  char *f;
+
+  imap_unquote_string (folder);
+  for (x = 0; x < state->entrylen; x++)
+  {
+    f = strchr ((state->entry)[x].name, '}');
+    if (f)
+    {
+      int len = strlen (folder);
+
+      f++;
+      if (!strncmp (f, folder, len) && (f[len] == '\0' || f[len] == delim))
+       return;
+    }
+  }
+  if (state->entrylen + 1 == state->entrymax)
+  {
+    safe_realloc ((void **) &state->entry,
+       sizeof (struct folder_file) * (state->entrymax += 256));
+  }
+  if (!noselect)
+  {
+    if (port == IMAP_PORT)
+      snprintf (tmp, sizeof (tmp), "{%s}%s", host, folder);
+    else
+      snprintf (tmp, sizeof (tmp), "{%s:%d}%s", host, port, folder);
+    (state->entry)[state->entrylen].name = safe_strdup (tmp);
+    snprintf (tmp, sizeof (tmp), "IMAP %-25s %-25s", host, folder);
+    (state->entry)[state->entrylen].desc = safe_strdup (tmp);
+    (state->entry)[state->entrylen].notfolder = 0;
+    (state->entrylen)++;
+  }
+  if (!noinferiors)
+  {
+    int nodelim = 0;
+
+    if (delim == folder[flen - 1])
+      nodelim = 1;
+    if (port == IMAP_PORT)
+      snprintf (tmp, sizeof (tmp), "{%s}%s%c", host, folder, 
+         nodelim ? '\0' : delim);
+    else
+      snprintf (tmp, sizeof (tmp), "{%s:%d}%s%c", host, port, folder, 
+         nodelim ? '\0' : delim);
+    (state->entry)[state->entrylen].name = safe_strdup (tmp);
+    snprintf (idir, sizeof (idir), "%s%c", folder, 
+       nodelim ? '\0' : delim);
+    snprintf (tmp, sizeof (tmp), "IMAP %-25s %-25s", host, idir);
+    (state->entry)[state->entrylen].desc = safe_strdup (tmp);
+    (state->entry)[state->entrylen].notfolder = 1;
+    (state->entrylen)++;
+  }
+}
+
+static int add_namespace (IMAP_DATA *idata, char *host, int port, 
+    struct browser_state *state)
+{
+  char buf[LONG_STRING];
+  char seq[16];
+  char *s;
+  int n;
+  char ns[LONG_STRING];
+  char delim = '/';
+
+  imap_make_sequence (seq, sizeof (seq));
+  snprintf (buf, sizeof (buf), "%s NAMESPACE\r\n", seq);
+
+  mutt_socket_write (idata->conn, buf);
+  do 
+  {
+    if (mutt_socket_read_line_d (buf, sizeof (buf), idata->conn) < 0)
+    {
+      return (-1);
+    }
+
+    if (buf[0] == '*') 
+    {
+      s = imap_next_word (buf);
+      if (mutt_strncasecmp ("NAMESPACE", s, 9) == 0)
+      {
+       /* There are three sections to the response, User, Other, Shared,
+        * and maybe more by extension */
+       while (*s)
+       {
+         s = imap_next_word (s);
+         if (strncmp (s, "NIL", 3))
+         {
+           s++;
+           while (*s && *s != ')')
+           {
+             s++; /* skip ( */
+             /* copy namespace */
+             n = 0;
+             if (*s == '\"')
+             {
+               s++;
+               while (*s && *s != '\"') 
+               {
+                 if (*s == '\\')
+                   s++;
+                 ns[n++] = *s;
+                 s++;
+               }
+             }
+             else
+               while (*s && !ISSPACE (*s)) 
+               {
+                 ns[n++] = *s;
+                 s++;
+               }
+             ns[n] = '\0';
+             /* delim? */
+             s = imap_next_word (s);
+             if (*s && *s == '\"')
+               if (s[1] && s[2] == '\"')
+                 delim = s[1];
+               else if (s[1] && s[1] == '\\' && s[2] && s[3] == '\"')
+                 delim = s[2];
+             if (strcmp (ns, "INBOX"))
+               add_folder (delim, ns, host, port, 1, 0, state);
+             while (*s && *s != ')') s++;
+             s++;
+           }
+         }
+       }
+      }
+      else
+      {
+       if (imap_handle_untagged (idata, buf) != 0)
+         return (-1);
+      }
+    }
+  }
+  while ((mutt_strncmp (buf, seq, SEQLEN) != 0));
+  return 0;
+}
+
+int imap_init_browse (char *path, struct browser_state *state)
+{
+  CONNECTION *conn;
+  IMAP_DATA *idata;
+  char buf[LONG_STRING];
+  char mbox[LONG_STRING];
+  char host[SHORT_STRING];
+  char seq[16];
+  char *ipath = NULL;
+  int n;
+  int port;
+  char *s;
+
+  if (imap_parse_path (path, host, sizeof (host), &port, &ipath))
+    return (-1);
+
+  conn = mutt_socket_select_connection (host, port, 0);
+  idata = CONN_DATA;
+
+  if (!idata || (idata->state == IMAP_DISCONNECTED))
+  {
+    if (!idata)
+    {
+      /* The current connection is a new connection */
+      idata = safe_calloc (1, sizeof (IMAP_DATA));
+      conn->data = idata;
+      idata->conn = conn;
+    }
+    if (imap_open_connection (idata, conn))
+      return (-1);
+  }
+
+  imap_fix_path (idata, ipath, mbox, sizeof (mbox));
+  for (n = mutt_strlen (mbox) - 1; n > 0 && mbox[n] != idata->delim ; n--);
+  if (n > 0)
+  {
+    int i;
+    for (i = n - 1; i > 0 && mbox[i] != idata->delim ; i--);
+    if (i > 0)
+    {
+      mbox[i] = '\0';
+      add_folder (idata->delim, mbox, host, port, 1, 0, state);
+      mbox[i] = idata->delim;
+    }
+    else if (i != 0)
+      add_folder (idata->delim, "INBOX", host, port, 0, 0, state);
+    else
+      add_folder (idata->delim, "/", host, port, 1, 0, state);
+
+    mbox[n] = '\0';
+    /* Don't duplicate INBOX here */
+    if (strcmp ("INBOX", mbox))
+      add_folder (idata->delim, mbox, host, port, 0, 1, state);
+    mbox[n] = idata->delim;
+    mbox[n+1] = '\0';
+  }
+  else
+  {
+    if (mbox[0] != '#')
+    {
+      if (idata->delim == '/')
+       strcpy (mbox, "/");
+      else if (idata->delim == '\\')
+       strcpy (mbox, "\\");
+      else
+       mbox[0] = '\0';
+      if (add_namespace (idata, host, port, state) < 0)
+       return (-1);
+      add_folder (idata->delim, "INBOX", host, port, 0, 0, state);
+    }
+  }
+  imap_make_sequence (seq, sizeof (seq));
+
+  mutt_message _("Contacted server, getting folder list...");
+  snprintf (buf, sizeof (buf), "%s %s \"\" \"%s%%\"\r\n", seq, 
+      option (OPTIMAPLSUB) ? "LSUB" : "LIST", mbox);
+
+  mutt_socket_write (conn, buf);
+
+  do 
+  {
+    if (mutt_socket_read_line_d (buf, sizeof (buf), conn) < 0)
+    {
+      return (-1);
+    }
+
+    if (buf[0] == '*') 
+    {
+      s = imap_next_word (buf);
+      if ((mutt_strncasecmp ("LIST", s, 4) == 0) ||
+         (mutt_strncasecmp ("LSUB", s, 4) == 0))
+      {
+       int noselect = 0;
+       int noinferiors = 0;
+
+       s = imap_next_word (s); /* flags */
+       if (*s == '(')
+       {
+         char *ep;
+
+         s++;
+         ep = s;
+         while (*ep && *ep != ')') ep++;
+         do {
+           if (!strncmp (s, "\\NoSelect", 9))
+             noselect = 1;
+           if (!strncmp (s, "\\NoInferiors", 12))
+             noinferiors = 1;
+           if (*s != ')')
+             s++;
+           while (*s && *s != '\\' && *s != ')') s++;
+         } while (s != ep);
+       }
+       else
+         break;
+       s = imap_next_word (s); /* delim */
+       /* Reset the delimiter, this can change */
+       if (strncmp (s, "NIL", 3))
+       if (s && s[0] == '\"' && s[1] && s[2] == '\"')
+         idata->delim = s[1];
+       else if (s && s[0] == '\"' && s[1] && s[1] == '\\' && s[2] && s[3] == '\"')
+         idata->delim = s[2];
+       s = imap_next_word (s); /* name */
+       add_folder (idata->delim, s, host, port, noselect, noinferiors, state);
+      }
+      else
+      {
+       if (imap_handle_untagged (idata, buf) != 0)
+         return (-1);
+      }
+    }
+  }
+  while ((mutt_strncmp (buf, seq, SEQLEN) != 0));
+  mutt_clear_error ();
+  return 0;
+}
+
+int imap_subscribe (char *path, int subscribe)
+{
+  CONNECTION *conn;
+  IMAP_DATA *idata;
+  char buf[LONG_STRING];
+  char mbox[LONG_STRING];
+  char host[SHORT_STRING];
+  char seq[16];
+  char *ipath = NULL;
+  int port;
+
+  if (imap_parse_path (path, host, sizeof (host), &port, &ipath))
+    return (-1);
+
+  conn = mutt_socket_select_connection (host, port, 0);
+  idata = CONN_DATA;
+
+  if (!idata || (idata->state == IMAP_DISCONNECTED))
+  {
+    if (!idata)
+    {
+      /* The current connection is a new connection */
+      idata = safe_calloc (1, sizeof (IMAP_DATA));
+      conn->data = idata;
+      idata->conn = conn;
+    }
+    if (imap_open_connection (idata, conn))
+      return (-1);
+  }
+
+  imap_fix_path (idata, ipath, buf, sizeof (buf));
+  if (subscribe)
+    mutt_message (_("Subscribing to %s..."), buf);
+  else
+    mutt_message (_("Unsubscribing to %s..."), buf);
+  imap_quote_string (mbox, sizeof(mbox), buf);
+  imap_make_sequence (seq, sizeof (seq));
+
+  snprintf (buf, sizeof (buf), "%s %s %s\r\n", seq, 
+      subscribe ? "SUBSCRIBE" : "UNSUBSCRIBE", mbox);
+
+  if (imap_exec (buf, sizeof (buf), idata, seq, buf, 0) < 0)
+  {
+    return (-1);
+  }
+  return 0;
+}
diff --git a/imap.h b/imap.h
index d7c1357c612e83fd7b5acb0692fe25c7fbffa1d2..fc0c98a45b4887ef9320a3ea4dc88468e03fa53e 100644 (file)
--- a/imap.h
+++ b/imap.h
  */ 
 
 #ifndef _IMAP_H
-#define _IMAP_H
+#define _IMAP_H 1
 
-extern int imap_append_message (CONTEXT *ctx, MESSAGE *msg);
-extern int imap_check_mailbox (CONTEXT *ctx, int *index_hint);
-extern int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno);
-extern int imap_open_mailbox (CONTEXT *ctx);
-extern int imap_open_mailbox_append (CONTEXT *ctx);
-extern int imap_sync_mailbox (CONTEXT *ctx);
-extern void imap_fastclose_mailbox (CONTEXT *ctx);
-extern int imap_buffy_check (char *path);
+#include "browser.h"
+
+int imap_append_message (CONTEXT *ctx, MESSAGE *msg);
+int imap_check_mailbox (CONTEXT *ctx, int *index_hint);
+int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno);
+int imap_open_mailbox (CONTEXT *ctx);
+int imap_open_mailbox_append (CONTEXT *ctx);
+int imap_sync_mailbox (CONTEXT *ctx);
+void imap_fastclose_mailbox (CONTEXT *ctx);
+int imap_buffy_check (char *path);
+int imap_subscribe (char *path, int subscribe);
+int imap_init_browse (char *path, struct browser_state *state);
 
 #endif
diff --git a/init.h b/init.h
index a4a03688ce841cf57757c7841073ba6144fb8828..5875e8ef5c334d67a8139659dc58846e649b14cb 100644 (file)
--- a/init.h
+++ b/init.h
@@ -123,9 +123,11 @@ struct option_t MuttVars[] = {
   { "history",         DT_NUM,  R_NONE, UL &HistSize, 10 },
   { "hostname",                DT_STR,  R_NONE, UL &Fqdn, 0 },
 #ifdef USE_IMAP
+  { "imap_checkinterval",      DT_NUM,  R_NONE, UL &ImapCheckTime, 0 },
+  { "imap_list_subscribed",    DT_BOOL, R_NONE, OPTIMAPLSUB, 0 },
   { "imap_user",       DT_STR,  R_NONE, UL &ImapUser, UL 0 },
   { "imap_pass",       DT_STR,  R_NONE, UL &ImapPass, UL 0 },
-  { "imap_checkinterval",      DT_NUM,  R_NONE, UL &ImapCheckTime, 0 },
+  { "imap_passive",            DT_BOOL, R_NONE, OPTIMAPPASSIVE, 1 },
 #endif
   { "implicit_autoview", DT_BOOL,R_NONE, OPTIMPLICITAUTOVIEW, 0},
   { "in_reply_to",     DT_STR,  R_NONE, UL &InReplyTo, UL "%i; from %n on %{!%a, %b %d, %Y at %I:%M:%S%p %Z}" },
diff --git a/menu.c b/menu.c
index 1cc74c756a3c3a1aa45f209258758ef658a81a4f..3a983357c43abf5b8aa2661800b93966a5fc9248 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -102,8 +102,15 @@ void menu_redraw_full (MUTTMENU *menu)
 {
   SETCOLOR (MT_COLOR_NORMAL);
   /* clear() doesn't optimize screen redraws */
+#if 0
   move (0, 0);
   clrtobot ();
+#else
+  /* my ncurses library seems to run into
+   * endless loops in clrtobot...
+   */
+  clear();
+#endif
 
   if (option (OPTHELP))
   {
diff --git a/mutt.h b/mutt.h
index 08dbc350e03313fb5c4267c5ac1f2e340b1d510a..8e7cd0263fe9b19130ded6520c1088d989cb4747 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -303,6 +303,10 @@ enum
   OPTHELP,
   OPTHIDDENHOST,
   OPTIGNORELISTREPLYTO,
+#ifdef USE_IMAP
+  OPTIMAPLSUB,
+  OPTIMAPPASSIVE,
+#endif
   OPTIMPLICITAUTOVIEW,
   OPTMARKERS,
   OPTMARKOLD,
index 66b55d6906726c4a00764a34cd17a58116653ca9..cff57b7e53c32cb9be255941131043f42427660a 100644 (file)
@@ -37,5 +37,7 @@ int mutt_socket_read_line (char *buf, size_t buflen, CONNECTION *conn);
 int mutt_socket_read_line_d (char *buf, size_t buflen, CONNECTION *conn);
 int mutt_socket_write (CONNECTION *conn, const char *buf);
 CONNECTION *mutt_socket_select_connection (char *host, int port, int flags);
+int mutt_socket_open_connection (CONNECTION *conn);
+
 
 #endif /* _MUTT_SOCKET_H_ */
diff --git a/mx.c b/mx.c
index f5deb166bb4cbe4a4ac289328c971dc13ac6dc6c..93f39b2a329da5f666326669d4f56e3b02265bfc 100644 (file)
--- a/mx.c
+++ b/mx.c
@@ -786,6 +786,10 @@ int mx_close_mailbox (CONTEXT *ctx)
       return (-1);
   }
 
+#ifdef USE_IMAP
+  /* IMAP doesn't support an OLD flag */
+  if (ctx->magic != M_IMAP)
+#endif
   if (option (OPTMARKOLD))
   {
     for (i = 0; i < ctx->msgcount; i++)
index 042718476f8155cdf3b559442083c8450a023bd4..498e58f4a77f2b475ce26d6258e102df8058ffd2 100644 (file)
--- a/po/cs.po
+++ b/po/cs.po
@@ -164,11 +164,11 @@ msgstr "Souborov
 
 #: browser.c:745
 msgid "Reverse sort by (d)ate, (a)lpha, si(z)e or do(n)'t sort? "
-msgstr "Obrácené øazení dle (d)ata, písmen(a), ro(z)mìru nebo (n)eøadit?"
+msgstr "Obrácené øazení dle (d)ata, (p)ísmena, (v)elikosti èi (n)eøadit?"
 
 #: browser.c:746
 msgid "Sort by (d)ate, (a)lpha, si(z)e or do(n)'t sort? "
-msgstr "Øadit dle (d)ata, (p)ísmena, (v)elikosti nebo (n)eøadit?"
+msgstr "Øadit dle (d)ata, (p)ísmena, (v)elikosti èi (n)eøadit?"
 
 #: browser.c:747
 msgid "dazn"
@@ -306,13 +306,13 @@ msgid ""
 "Rev-Sort (d)ate/(f)rm/(r)ecv/(s)ubj/t(o)/(t)hread/(u)nsort/si(z)e/s(c)ore?: "
 msgstr ""
 "Øadit opaènì "
-"(d)at/(o)d/pøí(j)/(v)ìc/(p)ro/v(l)ákno/(n)eseø/veli(k)/s(k)óre?: "
+"(d)at/(o)d/pøí(j)/(v)ìc/(p)ro/v(l)ákno/(n)eseø/veli(k)/(s)kóre?: "
 
 #: commands.c:402
 msgid ""
 "Sort (d)ate/(f)rm/(r)ecv/(s)ubj/t(o)/(t)hread/(u)nsort/si(z)e/s(c)ore?: "
 msgstr ""
-"Øadit (d)at/(o)d/pøí(j)/(v)ìc/(p)ro/v(l)ákno/(n)eseø/veli(k)/s(k)óre?: "
+"Øadit (d)at/(o)d/pøí(j)/(v)ìc/(p)ro/v(l)ákno/(n)eseø/veli(k)/(s)kóre?: "
 
 #: commands.c:403
 msgid "dfrsotuzc"
@@ -353,7 +353,7 @@ msgstr "Kop
 
 #: commands.c:575
 msgid " tagged"
-msgstr " oznaèeno"
+msgstr " oznaèené"
 
 #: commands.c:644
 #, c-format
@@ -386,7 +386,7 @@ msgstr "Zru
 
 #: compose.c:82 compose.c:539
 msgid "Attach file"
-msgstr "Pøipojit soubor"
+msgstr "Pøilo¾it soubor"
 
 #: compose.c:83
 msgid "Descrip"
@@ -848,7 +848,7 @@ msgstr "[-- P
 #: handler.c:1082
 #, c-format
 msgid "[-- Type: %s/%s, Encoding: %s, Size: %s --]\n"
-msgstr "[-- Typ: %s%s, Kódování: %s, Velikost: %s --]\n"
+msgstr "[-- Typ: %s/%s, Kódování: %s, Velikost: %s --]\n"
 
 #: handler.c:1141
 #, c-format
@@ -1891,7 +1891,7 @@ msgid "To contact the developers, please mail to <mutt-dev@mutt.org>.\n"
 msgstr ""
 "Vývojáøe programu mù¾ete kontaktovat na adrese <mutt-dev@mutt.org> "
 "(anglicky).\n"
-"Pøipomínky k pøekladu zasílejte na adresu <cs@li.org> (èwsky).\n"
+"Pøipomínky k pøekladu zasílejte na adresu <cs@li.org> (èesky).\n"
 
 #: main.c:43
 msgid ""
@@ -1973,6 +1973,19 @@ msgid ""
 "    You should have received a copy of the full distribution terms\n"
 "    along with this program; if not, write to the program's developers.\n"
 msgstr ""
+"\n"
+"Implementace SHA1 Copyright (C) 1995-7 Eric A. Young <eay@cryptsoft.com>\n"
+"\n"
+"    ©íøení a u¾ívání ve zdrojové èi binární formì (a» ji¾ s úpravami èi bez\n"
+"    nich) je pøi dodr¾ení jistých podmínek povoleno.\n"
+"\n"
+"    Na implementaci SHA1 NENÍ poskytována JAKÁKOLI ZÁRUKA; neposkytují se\n"
+"    ani odvozené záruky PRODEJNOSTI anebo VHODNOSTI PRO NÌJAKÝ KONKRÉTNÍ\n"
+"    ÚÈEL.\n"
+"\n"
+"    Kopie podmínek ¹íøení mìla být dodána spolu s tímto programem; pokud se\n"
+"    tak nestalo, napi¹te o ni vývojáøùm programu.\n"
+
 
 #: main.c:100
 msgid ""
@@ -2760,7 +2773,7 @@ msgstr "Chyba p
 #: pop.c:306
 #, c-format
 msgid "%s [%d messages read]"
-msgstr "%s [poèet pøeètených zpráv - %d]"
+msgstr "%s [poèet pøeètených zpráv: %d]"
 
 #: postpone.c:112
 msgid "Postponed Messages"
@@ -2856,7 +2869,7 @@ msgstr "Vytisknout p
 
 #: recvattach.c:654
 msgid "You may only bounce message/rfc822 parts."
-msgstr "Pøeposlat lze pouze zprávu nebo její èásti vyhovující rfc 822."
+msgstr "Pøeposlat lze pouze èásti typu 'message/rfc822'."
 
 #: recvattach.c:690
 #, c-format
index 1ffd17c3698cfc2ba5b3916ce9082d1b4350e271..b8b7b42bf1702a9d3ed3688141bf50947e2c129c 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <string.h>
 
 /* support for multiple socket connections */
 
@@ -105,3 +106,34 @@ CONNECTION *mutt_socket_select_connection (char *host, int port, int flags)
   return conn;
 }
 
+int mutt_socket_open_connection (CONNECTION *conn)
+{
+  struct sockaddr_in sin;
+  struct hostent *he;
+
+  memset (&sin, 0, sizeof (sin));
+  sin.sin_port = htons (conn->port);
+  sin.sin_family = AF_INET;
+  if ((he = gethostbyname (conn->server)) == NULL)
+  {
+    mutt_perror (conn->server);
+    return (-1);
+  }
+  memcpy (&sin.sin_addr, he->h_addr_list[0], he->h_length);
+
+  if ((conn->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
+  {
+    mutt_perror ("socket");
+    return (-1);
+  }
+
+  mutt_message (_("Connecting to %s..."), conn->server); 
+
+  if (connect (conn->fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
+  {
+    mutt_perror ("connect");
+    close (conn->fd);
+  }
+
+  return 0;
+}