diff options
author | Thomas Roessler <roessler@does-not-exist.org> | 1999-07-29 09:13:03 +0000 |
---|---|---|
committer | Thomas Roessler <roessler@does-not-exist.org> | 1999-07-29 09:13:03 +0000 |
commit | 40cfb6124603363a1f62a6a0c04985ac39aebf8e (patch) | |
tree | 17e99a594345686a3994f19a8b075db99fd6b6f1 | |
parent | 0744dc97d7ba45a938e6b2934703f93078c79eeb (diff) |
Brendan Cully's latest IMAP patches.
-rw-r--r-- | browser.c | 23 | ||||
-rw-r--r-- | complete.c | 4 | ||||
-rw-r--r-- | enter.c | 4 | ||||
-rw-r--r-- | imap.c | 223 | ||||
-rw-r--r-- | imap.h | 4 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | protos.h | 2 |
7 files changed, 160 insertions, 101 deletions
@@ -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 @@ -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 @@ -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 */ @@ -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; @@ -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 @@ -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\ @@ -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); |