⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imap.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 1996-8 Michael R. Elkins <me@mutt.org> * Copyright (C) 1996-9 Brandon Long <blong@fiction.net> * Copyright (C) 1999-2006 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 *     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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. */ /* Support for IMAP4rev1, with the occasional nod to IMAP 4. */#if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mx.h"#include "mailbox.h"#include "globals.h"#include "sort.h"#include "browser.h"#include "message.h"#include "imap_private.h"#if defined(USE_SSL)# include "mutt_ssl.h"#endif#include "buffy.h"#if USE_HCACHE#include "hcache.h"#endif#include <unistd.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>/* imap forward declarations */static char* imap_get_flags (LIST** hflags, char* s);static int imap_check_capabilities (IMAP_DATA* idata);static void imap_set_flag (IMAP_DATA* idata, int aclbit, int flag,			   const char* str, char* flags, size_t flsize);/* imap_access: Check permissions on an IMAP mailbox. * TODO: ACL checks. Right now we assume if it exists we can *       mess with it. */int imap_access (const char* path, int flags){  IMAP_DATA* idata;  IMAP_MBOX mx;  char buf[LONG_STRING];  char mailbox[LONG_STRING];  char mbox[LONG_STRING];  if (imap_parse_path (path, &mx))    return -1;  if (!(idata = imap_conn_find (&mx.account,    option (OPTIMAPPASSIVE) ? M_IMAP_CONN_NONEW : 0)))  {    FREE (&mx.mbox);    return -1;  }  imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox));  /* we may already be in the folder we're checking */  if (!ascii_strcmp(idata->mailbox, mx.mbox))  {    FREE (&mx.mbox);    return 0;  }  FREE (&mx.mbox);  imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);  if (mutt_bit_isset (idata->capabilities, IMAP4REV1))    snprintf (buf, sizeof (buf), "STATUS %s (UIDVALIDITY)", mbox);  else if (mutt_bit_isset (idata->capabilities, STATUS))    snprintf (buf, sizeof (buf), "STATUS %s (UID-VALIDITY)", mbox);  else  {    dprint (2, (debugfile, "imap_access: STATUS not supported?\n"));    return -1;  }  if (imap_exec (idata, buf, IMAP_CMD_FAIL_OK) < 0)  {    dprint (1, (debugfile, "imap_access: Can't check STATUS of %s\n", mbox));    return -1;  }  return 0;}int imap_create_mailbox (IMAP_DATA* idata, char* mailbox){  char buf[LONG_STRING], mbox[LONG_STRING];  imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);  snprintf (buf, sizeof (buf), "CREATE %s", mbox);        if (imap_exec (idata, buf, 0) != 0)    return -1;  return 0;}int imap_rename_mailbox (IMAP_DATA* idata, IMAP_MBOX* mx, const char* newname){  char oldmbox[LONG_STRING];  char newmbox[LONG_STRING];  char buf[LONG_STRING];  imap_munge_mbox_name (oldmbox, sizeof (oldmbox), mx->mbox);  imap_munge_mbox_name (newmbox, sizeof (newmbox), newname);  snprintf (buf, sizeof (buf), "RENAME %s %s", oldmbox, newmbox);  if (imap_exec (idata, buf, 0) != 0)    return -1;  return 0;}int imap_delete_mailbox (CONTEXT* ctx, IMAP_MBOX mx){  char buf[LONG_STRING], mbox[LONG_STRING];  IMAP_DATA *idata;  if (!ctx || !ctx->data) {    if (!(idata = imap_conn_find (&mx.account,          option (OPTIMAPPASSIVE) ? M_IMAP_CONN_NONEW : 0)))    {      FREE (&mx.mbox);      return -1;    }  } else {    idata = ctx->data;  }  imap_munge_mbox_name (mbox, sizeof (mbox), mx.mbox);  snprintf (buf, sizeof (buf), "DELETE %s", mbox);  if (imap_exec ((IMAP_DATA*) idata, buf, 0) != 0)    return -1;  return 0;}/* imap_logout_all: close all open connections. Quick and dirty until we can *   make sure we've got all the context we need. */void imap_logout_all (void) {  CONNECTION* conn;  CONNECTION* tmp;  conn = mutt_socket_head ();  while (conn)  {    tmp = conn->next;    if (conn->account.type == M_ACCT_TYPE_IMAP && conn->fd >= 0)    {      mutt_message (_("Closing connection to %s..."), conn->account.host);      imap_logout ((IMAP_DATA*) conn->data);      mutt_clear_error ();      mutt_socket_close (conn);      mutt_socket_free (conn);    }    conn = tmp;  }}/* imap_read_literal: read bytes bytes from server into file. Not explicitly *   buffered, relies on FILE buffering. NOTE: strips \r from \r\n. *   Apparently even literals use \r\n-terminated strings ?! */int imap_read_literal (FILE* fp, IMAP_DATA* idata, long bytes, progress_t* pbar){  long pos;  char c;  int r = 0;  dprint (2, (debugfile, "imap_read_literal: reading %ld bytes\n", bytes));   for (pos = 0; pos < bytes; pos++)  {    if (mutt_socket_readchar (idata->conn, &c) != 1)    {      dprint (1, (debugfile, "imap_read_literal: error during read, %ld bytes read\n", pos));      idata->status = IMAP_FATAL;            return -1;    }#if 1    if (r == 1 && c != '\n')      fputc ('\r', fp);    if (c == '\r')    {      r = 1;      continue;    }    else      r = 0;#endif    fputc (c, fp);        if (pbar && !(pos % 1024))      mutt_progress_bar (pbar, pos);#ifdef DEBUG    if (debuglevel >= IMAP_LOG_LTRL)      fputc (c, debugfile);#endif  }  return 0;}/* imap_expunge_mailbox: Purge IMAP portion of expunged messages from the *   context. Must not be done while something has a handle on any headers *   (eg inside pager or editor). That is, check IMAP_REOPEN_ALLOW. */void imap_expunge_mailbox (IMAP_DATA* idata){  HEADER* h;  int i, cacheno;#if USE_HCACHE  header_cache_t *hc;  char uidbuf[32];    hc = mutt_hcache_open (HeaderCache, idata->ctx->path);#endif  for (i = 0; i < idata->ctx->msgcount; i++)  {    h = idata->ctx->hdrs[i];    if (h->index == -1)    {      dprint (2, (debugfile, "Expunging message UID %d.\n", HEADER_DATA (h)->uid));      h->active = 0;      imap_cache_del (idata, h);#if USE_HCACHE      if (hc)      {        sprintf (uidbuf, "/%u", HEADER_DATA(h)->uid);        mutt_hcache_delete (hc, uidbuf, imap_hcache_keylen);      }#endif      /* free cached body from disk, if necessary */      cacheno = HEADER_DATA(h)->uid % IMAP_CACHE_LEN;      if (idata->cache[cacheno].uid == HEADER_DATA(h)->uid &&	  idata->cache[cacheno].path)      {	unlink (idata->cache[cacheno].path);	FREE (&idata->cache[cacheno].path);      }      imap_free_header_data (&h->data);    }  }#if USE_HCACHE  mutt_hcache_close (hc);#endif  /* We may be called on to expunge at any time. We can't rely on the caller   * to always know to rethread */  mx_update_tables (idata->ctx, 0);  mutt_sort_headers (idata->ctx, 1);}/* imap_check_capabilities: make sure we can log in to this server. */static int imap_check_capabilities (IMAP_DATA* idata){  if (imap_exec (idata, "CAPABILITY", 0) != 0)  {    imap_error ("imap_check_capabilities", idata->buf);    return -1;  }  if (!(mutt_bit_isset(idata->capabilities,IMAP4)      ||mutt_bit_isset(idata->capabilities,IMAP4REV1)))  {    mutt_error _("This IMAP server is ancient. Mutt does not work with it.");    mutt_sleep (2);	/* pause a moment to let the user see the error */    return -1;  }  return 0;}/* imap_conn_find: Find an open IMAP connection matching account, or open *   a new one if none can be found. */IMAP_DATA* imap_conn_find (const ACCOUNT* account, int flags){  CONNECTION* conn = NULL;  ACCOUNT* creds = NULL;  IMAP_DATA* idata = NULL;  int new = 0;  while ((conn = mutt_conn_find (conn, account)))  {    if (!creds)      creds = &conn->account;    else      memcpy (&conn->account, creds, sizeof (ACCOUNT));    idata = (IMAP_DATA*)conn->data;    if (flags & M_IMAP_CONN_NONEW)    {      if (!idata)      {        /* This should only happen if we've come to the end of the list */        mutt_socket_free (conn);        return NULL;      }      else if (idata->state < IMAP_AUTHENTICATED)        continue;    }    if (flags & M_IMAP_CONN_NOSELECT && idata && idata->state >= IMAP_SELECTED)      continue;    break;  }  if (!idata)  {    /* The current connection is a new connection */    if (! (idata = imap_new_idata ()))    {      mutt_socket_free (conn);      return NULL;    }    conn->data = idata;    idata->conn = conn;    new = 1;  }  if (idata->state == IMAP_DISCONNECTED)    imap_open_connection (idata);  if (idata->state == IMAP_CONNECTED)  {    if (!imap_authenticate (idata))    {      idata->state = IMAP_AUTHENTICATED;      if (idata->conn->ssf)	dprint (2, (debugfile, "Communication encrypted at %d bits\n",		    idata->conn->ssf));    }    else      mutt_account_unsetpass (&idata->conn->account);        FREE (&idata->capstr);  }  if (new && idata->state == IMAP_AUTHENTICATED)  {    /* get root delimiter, '/' as default */    idata->delim = '/';    imap_cmd_queue (idata, "LIST \"\" \"\"");    if (option (OPTIMAPCHECKSUBSCRIBED))      imap_cmd_queue (idata, "LSUB \"\" \"*\"");    /* we may need the root delimiter before we open a mailbox */    imap_exec (idata, NULL, IMAP_CMD_FAIL_OK);  }  return idata;}int imap_open_connection (IMAP_DATA* idata){  char buf[LONG_STRING];  if (mutt_socket_open (idata->conn) < 0)    return -1;  idata->state = IMAP_CONNECTED;  if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE)  {    mutt_socket_close (idata->conn);    idata->state = IMAP_DISCONNECTED;    return -1;  }  if (ascii_strncasecmp ("* OK", idata->buf, 4) == 0)  {    if (ascii_strncasecmp ("* OK [CAPABILITY", idata->buf, 16)        && imap_check_capabilities (idata))      goto bail;#if defined(USE_SSL)    /* Attempt STARTTLS if available and desired. */    if (!idata->conn->ssf && (option(OPTSSLFORCETLS) ||                              mutt_bit_isset (idata->capabilities, STARTTLS)))    {      int rc;            if (option(OPTSSLFORCETLS))        rc = M_YES;      else if ((rc = query_quadoption (OPT_SSLSTARTTLS,        _("Secure connection with TLS?"))) == -1)	goto err_close_conn;      if (rc == M_YES) {	if ((rc = imap_exec (idata, "STARTTLS", IMAP_CMD_FAIL_OK)) == -1)	  goto bail;	if (rc != -2)	{	  if (mutt_ssl_starttls (idata->conn))	  {	    mutt_error (_("Could not negotiate TLS connection"));	    mutt_sleep (1);	    goto err_close_conn;	  }	  else	  {	    /* RFC 2595 demands we recheck CAPABILITY after TLS completes. */	    if (imap_exec (idata, "CAPABILITY", 0))	      goto bail;	  }	}      }    }    if (option(OPTSSLFORCETLS) && ! idata->conn->ssf)    {      mutt_error _("Encrypted connection unavailable");      mutt_sleep (1);      goto err_close_conn;    }#endif      }  else if (ascii_strncasecmp ("* PREAUTH", idata->buf, 9) == 0)  {    idata->state = IMAP_AUTHENTICATED;    if (imap_check_capabilities (idata) != 0)      goto bail;    FREE (&idata->capstr);  }   else  {    imap_error ("imap_open_connection()", buf);    goto bail;  }  return 0;#if defined(USE_SSL) err_close_conn:  mutt_socket_close (idata->conn);  idata->state = IMAP_DISCONNECTED;#endif bail:  FREE (&idata->capstr);  return -1;}/* imap_get_flags: Make a simple list out of a FLAGS response. *   return stream following FLAGS response */static char* imap_get_flags (LIST** hflags, char* s){  LIST* flags;  char* flag_word;  char ctmp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -