]> granicus.if.org Git - neomutt/commitdiff
Brendan Cully's latest IMAP patches.
authorThomas Roessler <roessler@does-not-exist.org>
Thu, 29 Jul 1999 09:13:03 +0000 (09:13 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Thu, 29 Jul 1999 09:13:03 +0000 (09:13 +0000)
browser.c
complete.c
enter.c
imap.c
imap.h
main.c
protos.h

index 620e47790bc57e9ac4090e1aef5e22a95a13c763..932bf40bc4a9b9053ba964292a44ae26fd86d50b 100644 (file)
--- a/browser.c
+++ b/browser.c
@@ -496,7 +496,7 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
       init_state (&state, NULL);
       state.imap_browse = 1;
       imap_init_browse (f, &state);
-      strfcpy (LastDir, f, sizeof (LastDir));
+      strfcpy (LastDir, state.folder, sizeof (LastDir));
     }
     else
     {
@@ -604,7 +604,7 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
 #ifdef USE_IMAP
          else if (state.imap_browse)
          {
-           strfcpy (buf, state.entry[menu->current].name, sizeof (buf));
+            strfcpy (buf, state.entry[menu->current].name, sizeof (buf));
          }
 #endif
          else
@@ -649,8 +649,8 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
 #ifdef USE_IMAP
            else if (state.imap_browse)
            {
-             strfcpy (LastDir, state.entry[menu->current].name, 
-                 sizeof (LastDir));
+              strfcpy (LastDir, state.entry[menu->current].name,
+                sizeof (LastDir));
            }
 #endif
            else
@@ -698,9 +698,7 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
        }
 #ifdef USE_IMAP
        else if (state.imap_browse)
-       {
-         strfcpy (f, state.entry[menu->current].name, flen);
-       }
+          strfcpy (f, state.entry[menu->current].name, flen);
 #endif
        else
          snprintf (f, flen, "%s/%s", LastDir, state.entry[menu->current].name);
@@ -871,6 +869,17 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
            Mask.not = not;
 
            destroy_state (&state);
+#ifdef USE_IMAP
+           if (state.imap_browse)
+           {
+             init_state (&state, NULL);
+             state.imap_browse = 1;
+             imap_init_browse (LastDir, &state);
+             menu->data = state.entry;
+             init_menu (&state, menu, title, sizeof (title), buffy);
+           }
+           else
+#endif
            if (examine_directory (menu, &state, LastDir, NULL) == 0)
              init_menu (&state, menu, title, sizeof (title), buffy);
            else
index 6f577e07265764839c56f210dc493617d7ea3cce..d9e1c011ac8a4050540239411e8fc7ff73dd213e 100644 (file)
@@ -33,7 +33,7 @@
  *
  * return 0 if ok, -1 if no matches
  */
-int mutt_complete (char *s)
+int mutt_complete (char *s, size_t slen)
 {
   char *p;
   DIR *dirp = NULL;
@@ -63,7 +63,7 @@ int mutt_complete (char *s)
 
   if (mx_is_imap (imap_path))
   {
-    return imap_complete (s, imap_path);
+    return imap_complete (s, slen, imap_path);
   }
 #endif
   
diff --git a/enter.c b/enter.c
index 337bb0bd1feebc722cea8b06575e07465e120d70..239f7f84bac659a82078df682b861160282c4006 100644 (file)
--- a/enter.c
+++ b/enter.c
@@ -326,7 +326,7 @@ int _mutt_enter_string (unsigned char *buf, size_t buflen, int y, int x,
              set_option (OPTNEEDREDRAW);
              return (1);
            }
-           if (mutt_complete ((char *) buf + j + 1) == 0)
+           if (mutt_complete ((char *) buf + j + 1, buflen - (j + 1)) == 0)
              strfcpy (tempbuf, (char *) buf + j + 1, sizeof (tempbuf));
            else
              BEEP ();
@@ -380,7 +380,7 @@ int _mutt_enter_string (unsigned char *buf, size_t buflen, int y, int x,
              return (-1);
            }
 
-           if (mutt_complete ((char *) buf) == 0)
+           if (mutt_complete ((char *) buf, buflen) == 0)
              strfcpy (tempbuf, (char *) buf, sizeof (tempbuf));
            else
              BEEP (); /* let the user know that nothing matched */
diff --git a/imap.c b/imap.c
index 107e27a20cb59c4af4d9ca66afea4b3562e5cf1c..efb3379eac301859f3cbc0c765dc6d4e953bf437 100644 (file)
--- a/imap.c
+++ b/imap.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  * Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
+ * Copyright (C) 1999 Brendan Cully <brendan@kublai.com>
  * 
  *     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
@@ -203,6 +204,28 @@ static void imap_unquote_string (char *s);
 static int imap_read_bytes (FILE *fp, CONNECTION *conn, long bytes);
 static int imap_code (const char *s);
 static char *imap_next_word (char *s);
+static int imap_wordcasecmp(const char *a, const char *b);
+static void imap_parse_capabilities (IMAP_DATA *idata, char *s);
+static int imap_handle_untagged (IMAP_DATA *idata, char *s);
+static int get_literal_count(const char *buf, long *bytes);
+static int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend);
+static int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint);
+static int imap_exec (char *buf, size_t buflen, IMAP_DATA *idata,
+  const char *seq, const char *cmd, int flags);
+static int imap_get_delim (IMAP_DATA *idata, CONNECTION *conn);
+static int imap_parse_path (char *path, char *host, size_t hlen, int *port, 
+  char **mbox);
+static char *imap_fix_path (IMAP_DATA *idata, char *mailbox, char *path, 
+  size_t plen);
+static int imap_check_acl (IMAP_DATA *idata);
+static int imap_check_capabilities (IMAP_DATA *idata);
+static int imap_authenticate (IMAP_DATA *idata, CONNECTION *conn);
+static int imap_open_connection (IMAP_DATA *idata, CONNECTION *conn);
+int imap_open_mailbox (CONTEXT *ctx);
+int imap_select_mailbox (CONTEXT* ctx, const char* path);
+static int imap_create_mailbox (IMAP_DATA *idata, char *mailbox);
+int imap_open_mailbox_append (CONTEXT *ctx);
+int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno);
 
 /* everything above should be moved into a separate imap header file */
 
@@ -351,7 +374,7 @@ static int imap_parse_fetch (IMAP_HEADER_INFO *h, char *s)
        {
          s++;
           /* if a message is neither seen nor recent, it is OLD. */
-          if (OPTMARKOLD && !recent && !(h->read))
+          if (option (OPTMARKOLD) && !recent && !(h->read))
             h->old = 1;
          state = 0;
        }
@@ -842,7 +865,7 @@ static int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend)
 /* reopen an imap mailbox.  This is used when the server sends an
  * EXPUNGE message, indicating that some messages may have been deleted.
  * This is a heavy handed approach, as it reparses all of the headers,
- * but it should guaruntee correctness.  Later, we might implement
+ * but it should guarantee correctness.  Later, we might implement
  * something to actually only remove the messages taht are marked
  * EXPUNGE.
  */
@@ -1225,6 +1248,19 @@ static char *imap_fix_path (IMAP_DATA *idata, char *mailbox, char *path,
   return path;
 }
 
+/* imap_qualify_path: make an absolute IMAP folder target, given host, port
+ *   and relative path. Use this and maybe it will be easy to convert to
+ *   IMAP URLs */
+void imap_qualify_path (char* dest, size_t len, const char* host, int port,
+  const char* path, const char* name)
+{
+  if (port == IMAP_PORT)
+    snprintf (dest, len, "{%s}%s%s", host, NONULL (path), NONULL (name));
+  else
+    snprintf (dest, len, "{%s:%d}%s%s", host, port, NONULL (path),
+      NONULL (name));
+}
+
 static int imap_check_acl (IMAP_DATA *idata)
 {
   char buf[LONG_STRING];
@@ -1426,11 +1462,8 @@ int imap_open_mailbox (CONTEXT *ctx)
   imap_fix_path (idata, pc, buf, sizeof (buf));
   FREE(&(idata->selected_mailbox));
   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);
+  imap_qualify_path (buf, sizeof (buf), host, port, idata->selected_mailbox,
+    NULL);
 
   FREE (&(ctx->path));
   ctx->path = safe_strdup (buf);
@@ -1782,8 +1815,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
   return 0;
 }
 
-static void
-flush_buffer(char *buf, size_t *len, CONNECTION *conn)
+static void flush_buffer(char *buf, size_t *len, CONNECTION *conn)
 {
   buf[*len] = '\0';
   mutt_socket_write(conn, buf);
@@ -2248,75 +2280,73 @@ int imap_buffy_check (char *path)
   return (retcode > 0) ? TRUE : retcode;
 }
 
-/* add_folder: add a folder name to the browser list, formatting it as
- *   necessary. */
-static void add_folder (char delim, char *folder, char *host, int port, 
-    int noselect, int noinferiors, struct browser_state *state, short isparent)
+/* imap_add_folder: add a folder name to the browser list, formatting it as
+ *   necessary. NOTE: check for duplicate folders removed, believed to be
+ *   useless. Tell me if otherwise (brendan@kublai.com) */
+static void imap_add_folder (char delim, char *folder, int noselect,
+  int noinferiors, struct browser_state *state, short isparent)
 {
   char tmp[LONG_STRING];
-  char idir[LONG_STRING];
+  char relpath[LONG_STRING];
+  char host[SHORT_STRING];
+  int port;
+  char *curfolder;
   int flen = strlen (folder);
-  int x;
-  char *f, *relpath;
 
-  imap_unquote_string (folder);
-  for (x = 0; x < state->entrylen; x++)
-  {
-    f = strchr ((state->entry)[x].name, '}');
-    if (f)
-    {
-      int len = strlen (folder);
+  if (imap_parse_path (state->folder, host, sizeof (host), &port, &curfolder))
+    return;
 
-      f++;
-      if (!strncmp (f, folder, len) && (f[len] == '\0' || f[len] == delim))
-       return;
-    }
-  }
+  imap_unquote_string (folder);
 
-  if (state->entrylen + 1 == state->entrymax)
+  /* plus 2: folder may be selectable AND have inferiors */
+  if (state->entrylen + 2 == state->entrymax)
   {
     safe_realloc ((void **) &state->entry,
        sizeof (struct folder_file) * (state->entrymax += 256));
   }
 
-  relpath = folder;
-  /* render superiors as unix-standard "..", namespace root as "." */
+  /* render superiors as unix-standard ".." */
   if (isparent)
-    relpath = flen ? ".." : "." ;
+    strfcpy (relpath, "../", sizeof (relpath));
   /* strip current folder from target, to render a relative path */
-  else if (state->folder)
-    if (!strncmp (state->folder, folder, strlen (state->folder)))
-      relpath = folder + strlen (state->folder);
+  else if (!strncmp (curfolder, folder, strlen (curfolder)))
+    strfcpy (relpath, folder + strlen (curfolder), sizeof (relpath));
+  else
+    strfcpy (relpath, folder, sizeof (relpath));
+
+  /* apply filemask filter. This should really be done at menu setup rather
+   * than at scan, since it's so expensive to scan. But that's big changes
+   * to browser.c */
+  if (!((regexec (Mask.rx, relpath, 0, NULL, 0) == 0) ^ Mask.not))
+    return;
 
   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);
+    imap_qualify_path (tmp, sizeof (tmp), host, port, folder, NULL);
     (state->entry)[state->entrylen].name = safe_strdup (tmp);
+
     snprintf (tmp, sizeof (tmp), "IMAP %-25s %-25s", host, relpath);
     (state->entry)[state->entrylen].desc = safe_strdup (tmp);
+
     (state->entry)[state->entrylen].notfolder = 0;
     (state->entrylen)++;
   }
   if (!noinferiors)
   {
-    int nodelim = 0;
+    char trailing_delim[2];
 
-    if (flen == 0 || 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);
+    /* create trailing delimiter if necessary */
+    trailing_delim[1] = '\0';
+    trailing_delim[0] = (flen && folder[flen - 1] != delim) ? delim : '\0';
+
+    imap_qualify_path (tmp, sizeof (tmp), host, port, folder, trailing_delim);
     (state->entry)[state->entrylen].name = safe_strdup (tmp);
-    snprintf (idir, sizeof (idir), "%s%c", relpath, 
-       nodelim ? '\0' : delim);
-    snprintf (tmp, sizeof (tmp), "IMAP %-25s %-25s", host, idir);
+
+    if (strlen (relpath) < sizeof (relpath) - 2)
+      strcat (relpath, trailing_delim);
+    snprintf (tmp, sizeof (tmp), "IMAP %-25s %-25s", host, relpath);
     (state->entry)[state->entrylen].desc = safe_strdup (tmp);
+
     (state->entry)[state->entrylen].notfolder = 1;
     (state->entrylen)++;
   }
@@ -2398,15 +2428,24 @@ static int imap_parse_list_response(CONNECTION *conn, char *buf, int buflen,
 }
 
 static int add_list_result (CONNECTION *conn, const char *seq, const char *cmd,
-                           char *host, int port, struct browser_state *state,
-                            short isparent)
+                           struct browser_state *state, short isparent)
 {
   IMAP_DATA *idata = CONN_DATA;
   char buf[LONG_STRING];
+  char host[SHORT_STRING];
+  int port;
+  char *curfolder;
   char *name;
   int noselect;
   int noinferiors;
 
+  if (imap_parse_path (state->folder, host, sizeof (host), &port, &curfolder))
+  {
+    dprint (2, (debugfile,
+      "add_list_result: current folder %s makes no sense\n", state->folder));
+    return -1;
+  }
+
   mutt_socket_write (conn, cmd);
 
   do 
@@ -2419,10 +2458,9 @@ static int add_list_result (CONNECTION *conn, const char *seq, const char *cmd,
     {
       imap_unquote_string (name);
       /* prune current folder from output */
-      if (isparent || !state->folder || strncmp (name, state->folder,
-          strlen (name)))
-        add_folder (idata->delim, name, host, port, noselect, noinferiors,
-          state, isparent);
+      if (isparent || strncmp (name, curfolder, strlen (name)))
+        imap_add_folder (idata->delim, name, noselect, noinferiors, state,
+          isparent);
     }
   }
   while ((mutt_strncmp (buf, seq, SEQLEN) != 0));
@@ -2572,18 +2610,18 @@ int imap_init_browse (char *path, struct browser_state *state)
   char buf[LONG_STRING];
   char nsbuf[LONG_STRING];
   char mbox[LONG_STRING];
-  char *prune_path = NULL;
   char host[SHORT_STRING];
+  int port;
   char list_cmd[5];
   char seq[16];
   char *ipath = NULL;
+  IMAP_NAMESPACE_INFO nsi[16];
+  int home_namespace = 0;
   int n;
   int i;
   int nsup;
-  int port;
-  IMAP_NAMESPACE_INFO nsi[16];
+  char ctmp;
   int nns;
-  int home_namespace = 0;
   char *cur_folder;
   short showparents = 0;
   int noselect;
@@ -2679,40 +2717,57 @@ int imap_init_browse (char *path, struct browser_state *state)
     if (mbox[n-1] == idata->delim)
     {
       showparents = 1;
-      state->folder = safe_strdup (mbox);
+      imap_qualify_path (buf, sizeof (buf), host, port, mbox, NULL);
+      state->folder = safe_strdup (buf);
       n--;
     }
 
-    /* Find superiors to list, handling trailing delimiter */
+    /* Find superiors to list */
     for (n--; n >= 0 && mbox[n] != idata->delim ; n--);
-    if (n > 0)                 /* "aaaa/bbbb/" -> add "aaaa" */
+    if (n > 0)                 /* "aaaa/bbbb/" -> "aaaa/" */
     {
+      n++;
+      ctmp = mbox[n];
       mbox[n] = '\0';
       /* List it to see if it can be selected */
       dprint (2, (debugfile, "imap_init_browse: listing %s\n", mbox));
       imap_make_sequence (seq, sizeof (seq));
       snprintf (buf, sizeof (buf), "%s %s \"\" \"%s\"\r\n", seq, 
         list_cmd, mbox);
-      /* mark this entry as a superior, if we aren't tab-completing */
-      if (showparents && add_list_result (conn, seq, buf, host, port, state, 1))
+      /* add this entry as a superior, if we aren't tab-completing */
+      if (showparents && add_list_result (conn, seq, buf, state, 1))
           return -1;
+      /* if our target isn't a folder, we are in our superior */
       if (!state->folder)
       {
-        state->folder = safe_malloc (n+2);
-        strfcpy (state->folder, mbox, n+1);
-        state->folder[n] = idata->delim;
-        state->folder[n+1] = '\0';
+        imap_qualify_path (buf, sizeof (buf), host, port, mbox, NULL);
+        state->folder = safe_strdup (buf);
       }
-      mbox[n] = idata->delim;
+      mbox[n] = ctmp;
     } 
     /* "/bbbb/" -> add  "/", "aaaa/" -> add "" */
-    else if (showparents)
+    else
     {
-      snprintf (buf, sizeof (buf), "%c" , n<0 ? '\0' :idata->delim);
-      add_folder (idata->delim, buf, host, port, 1, 0, state, 1); 
+      char relpath[2];
+      /* folder may be "/" */
+      snprintf (relpath, sizeof (relpath), "%c" , n < 0 ? '\0' : idata->delim);
+      if (showparents)
+        imap_add_folder (idata->delim, relpath, 1, 0, state, 1); 
+      if (!state->folder)
+      {
+        imap_qualify_path (buf, sizeof (buf), host, port, relpath, NULL);
+        state->folder = safe_strdup (buf);
+      }
     }
   }
 
+  /* no namespace, no folder: set folder to host only */
+  if (!state->folder)
+  {
+    imap_qualify_path (buf, sizeof (buf), host, port, NULL, NULL);
+    state->folder = safe_strdup (buf);
+  }
+
   if (home_namespace && mbox[0] != '\0')
   {
     /* Listing the home namespace, so INBOX should be included. Home 
@@ -2720,20 +2775,16 @@ int imap_init_browse (char *path, struct browser_state *state)
      * server to see if it has descendants. */
     imap_make_sequence (seq, sizeof (seq));
     snprintf (buf, sizeof (buf), "%s LIST \"\" \"INBOX\"\r\n", seq);
-    if (add_list_result(conn, seq, buf, host, port, state, 0) != 0)
+    if (add_list_result (conn, seq, buf, state, 0))
       return -1;
   }
 
-
   nsup = state->entrylen;
 
   imap_make_sequence (seq, sizeof (seq));
   snprintf (buf, sizeof (buf), "%s %s \"\" \"%s%%\"\r\n", seq, 
     list_cmd, mbox);
-  /* if we are viewing a folder's contents, prune the folder */
-  if (mbox[strlen (mbox) - 1] == idata->delim)
-    prune_path = mbox;
-  if (add_list_result(conn, seq, buf, host, port, state, 0) != 0)
+  if (add_list_result (conn, seq, buf, state, 0))
     return -1;
 
   qsort(&(state->entry[nsup]),state->entrylen-nsup,sizeof(state->entry[0]),
@@ -2742,8 +2793,8 @@ int imap_init_browse (char *path, struct browser_state *state)
   {                            /* List additional namespaces */
     for (i = 0; i < nns; i++)
       if (nsi[i].listable && !nsi[i].home_namespace)
-       add_folder(nsi[i].delim, nsi[i].prefix, host, port, 
-                  nsi[i].noselect, nsi[i].noinferiors, state, 0);
+       imap_add_folder(nsi[i].delim, nsi[i].prefix, nsi[i].noselect,
+          nsi[i].noinferiors, state, 0);
   }
 
   mutt_clear_error ();
@@ -2800,7 +2851,7 @@ int imap_subscribe (char *path, int subscribe)
 
 /* imap_complete: given a partial IMAP folder path, return a string which
  *   adds as much to the path as is unique */
-int imap_complete(char* dest, char* path) {
+int imap_complete(char* dest, size_t dlen, char* path) {
   CONNECTION* conn;
   IMAP_DATA* idata;
   char host[SHORT_STRING];
@@ -2890,11 +2941,7 @@ int imap_complete(char* dest, char* path) {
   if (completions)
   {
     /* reformat output */
-    if (port != IMAP_PORT)
-      sprintf (dest, "{%s:%d}%s", host, port, completion);
-    else
-      sprintf (dest, "{%s}%s", host, completion);
-    
+    imap_qualify_path (dest, dlen, host, port, completion, NULL);
     mutt_pretty_mailbox (dest);
 
     return 0;
diff --git a/imap.h b/imap.h
index bf16c8b04d685498cc757e765f68856be6304324..40a9f027c956e5e94ab0e6d1d6cc31d8f9cac500 100644 (file)
--- a/imap.h
+++ b/imap.h
@@ -33,6 +33,8 @@ int imap_buffy_check (char *path);
 int imap_mailbox_check (char *path, int new);
 int imap_subscribe (char *path, int subscribe);
 int imap_init_browse (char *path, struct browser_state *state);
-int imap_complete(char* dest, char* path);
+int imap_complete (char* dest, size_t dlen, char* path);
+void imap_qualify_path (char* dest, size_t len, const char* host, int port,
+  const char* path, const char* name);
 
 #endif
diff --git a/main.c b/main.c
index 024f57e33005c8c0344c18c9654beca4be184eea..565bcae75dcbaaacbad69c808f4026b0c42c2b8d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -51,6 +51,7 @@ Copyright (C) 1996-9 Michael R. Elkins <me@cs.hmc.edu>\n\
 Copyright (C) 1996-9 Brandon Long <blong@fiction.net>\n\
 Copyright (C) 1997-9 Thomas Roessler <roessler@guug.de>\n\
 Copyright (C) 1998-9 Werner Koch <wk@isil.d.shuttle.de>\n\
+Copyright (C) 1999   Brendan Cully <brendan@kublai.com>\n\
 \n\
 Lots of others not mentioned here contributed lots of code,\n\
 fixes, and suggestions.\n\
index a3433ba020ef7b2b51a91b51f72b0656ef232047..a4cd7350485099f5283966a360e219840c4ffd1f 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -210,7 +210,7 @@ int mutt_check_month (const char *);
 int mutt_check_overwrite (const char *, const char *, char *, size_t, int *);
 int mutt_command_complete (char *, size_t, int, int);
 int mutt_var_value_complete (char *, size_t, int);
-int mutt_complete (char *);
+int mutt_complete (char *, size_t);
 int mutt_compose_attachment (BODY *a);
 int mutt_decode_save_attachment (FILE *, BODY *, char *, int, int);
 int mutt_display_message (HEADER *h);