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

📄 imap.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 4 页
字号:
        dprint (1, (debugfile, "Error polling mailboxes\n"));      lastdata = NULL;    }    if (!mutt_bit_isset (idata->capabilities, IMAP4REV1) &&        !mutt_bit_isset (idata->capabilities, STATUS))    {      dprint (2, (debugfile, "Server doesn't support STATUS\n"));      continue;    }        imap_munge_mbox_name (munged, sizeof (munged), name);    snprintf (command, sizeof (command), "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN)", munged);    if (imap_cmd_queue (idata, command) < 0)    {      /* pipeline must be full, drain it */      dprint (2, (debugfile, "IMAP command pipeline full, draining\n"));      if (imap_exec (idata, NULL, 0) != IMAP_CMD_OK)        dprint (1, (debugfile, "Error polling mailboxes\n"));            if (imap_cmd_queue (idata, command) < 0) {        /* real trouble */        dprint (1, (debugfile, "Error queueing command\n"));        return 0;      }    }  }  if (lastdata && (imap_exec (lastdata, NULL, 0) != IMAP_CMD_OK))  {    dprint (1, (debugfile, "Error polling mailboxes"));    return 0;  }  /* collect results */  for (mailbox = Incoming; mailbox; mailbox = mailbox->next)  {    if (mailbox->magic == M_IMAP && mailbox->new)      buffies++;  }  return buffies;}/* imap_status: returns count of messages in mailbox, or -1 on error. * if queue != 0, queue the command and expect it to have been run * on the next call (for pipelining the postponed count) */int imap_status (char* path, int queue){  static int queued = 0;  IMAP_DATA *idata;  char buf[LONG_STRING];  char mbox[LONG_STRING];  IMAP_STATUS* status;  if (imap_get_mailbox (path, &idata, buf, sizeof (buf)) < 0)    return -1;  if (!imap_mxcmp (buf, idata->mailbox))    /* We are in the folder we're polling - just return the mailbox count */    return idata->ctx->msgcount;  else if (mutt_bit_isset(idata->capabilities,IMAP4REV1) ||	   mutt_bit_isset(idata->capabilities,STATUS))  {    imap_munge_mbox_name (mbox, sizeof(mbox), buf);    snprintf (buf, sizeof (buf), "STATUS %s (%s)", mbox, "MESSAGES");    imap_unmunge_mbox_name (mbox);  }  else    /* Server does not support STATUS, and this is not the current mailbox.     * There is no lightweight way to check recent arrivals */    return -1;  if (queue)  {    imap_cmd_queue (idata, buf);    queued = 1;    return 0;  }  else if (!queued)    imap_exec (idata, buf, 0);  queued = 0;  if ((status = imap_mboxcache_get (idata, mbox)))    return status->messages;    return 0;}/* return cached mailbox stats or NULL */IMAP_STATUS* imap_mboxcache_get (IMAP_DATA* idata, const char* mbox){  LIST* cur;  IMAP_STATUS* status;    for (cur = idata->mboxcache; cur; cur = cur->next)  {    status = (IMAP_STATUS*)cur->data;    if (!imap_mxcmp (mbox, status->name))      return status;  }    return NULL;}void imap_mboxcache_free (IMAP_DATA* idata){  LIST* cur;  IMAP_STATUS* status;  for (cur = idata->mboxcache; cur; cur = cur->next)  {    status = (IMAP_STATUS*)cur->data;    FREE (&status->name);  }  mutt_free_list (&idata->mboxcache);}/* returns number of patterns in the search that should be done server-side * (eg are full-text) */static int do_search (const pattern_t* search, int allpats){  int rc = 0;  const pattern_t* pat;  for (pat = search; pat; pat = pat->next)  {    switch (pat->op)    {      case M_BODY:      case M_HEADER:      case M_WHOLE_MSG:        if (pat->stringmatch)          rc++;        break;      default:        if (pat->child && do_search (pat->child, 1))          rc++;    }        if (!allpats)      break;  }    return rc;}/* convert mutt pattern_t to IMAP SEARCH command containing only elements * that require full-text search (mutt already has what it needs for most * match types, and does a better job (eg server doesn't support regexps). */static int imap_compile_search (const pattern_t* pat, BUFFER* buf){  if (! do_search (pat, 0))    return 0;  if (pat->not)    mutt_buffer_addstr (buf, "NOT ");  if (pat->child)  {    int clauses;    if ((clauses = do_search (pat->child, 1)) > 0)    {      const pattern_t* clause = pat->child;      mutt_buffer_addch (buf, '(');      while (clauses)      {        if (do_search (clause, 0))        {          if (pat->op == M_OR && clauses > 1)            mutt_buffer_addstr (buf, "OR ");          clauses--;                    if (imap_compile_search (clause, buf) < 0)            return -1;          if (clauses)            mutt_buffer_addch (buf, ' ');                    clause = clause->next;        }      }      mutt_buffer_addch (buf, ')');    }  }  else  {    char term[STRING];    char *delim;    switch (pat->op)    {      case M_HEADER:        mutt_buffer_addstr (buf, "HEADER ");        /* extract header name */        if (! (delim = strchr (pat->p.str, ':')))        {          mutt_error (_("Header search without header name: %s"), pat->p.str);          return -1;        }        *delim = '\0';        imap_quote_string (term, sizeof (term), pat->p.str);        mutt_buffer_addstr (buf, term);        mutt_buffer_addch (buf, ' ');                /* and field */        *delim = ':';        delim++;        SKIPWS(delim);        imap_quote_string (term, sizeof (term), delim);        mutt_buffer_addstr (buf, term);        break;      case M_BODY:        mutt_buffer_addstr (buf, "BODY ");        imap_quote_string (term, sizeof (term), pat->p.str);        mutt_buffer_addstr (buf, term);        break;      case M_WHOLE_MSG:        mutt_buffer_addstr (buf, "TEXT ");        imap_quote_string (term, sizeof (term), pat->p.str);        mutt_buffer_addstr (buf, term);        break;    }  }  return 0;}int imap_search (CONTEXT* ctx, const pattern_t* pat){  BUFFER buf;  IMAP_DATA* idata = (IMAP_DATA*)ctx->data;  int i;  for (i = 0; i < ctx->msgcount; i++)    ctx->hdrs[i]->matched = 0;  if (!do_search (pat, 1))    return 0;  memset (&buf, 0, sizeof (buf));  mutt_buffer_addstr (&buf, "UID SEARCH ");  if (imap_compile_search (pat, &buf) < 0)  {    FREE (&buf.data);    return -1;  }  if (imap_exec (idata, buf.data, 0) < 0)  {    FREE (&buf.data);    return -1;  }  FREE (&buf.data);  return 0;}int imap_subscribe (char *path, int subscribe){  CONNECTION *conn;  IMAP_DATA *idata;  char buf[LONG_STRING];  char mbox[LONG_STRING];  char errstr[STRING];  BUFFER err, token;  IMAP_MBOX mx;  if (!mx_is_imap (path) || imap_parse_path (path, &mx))  {    mutt_error (_("Bad mailbox name"));    return -1;  }  if (!(idata = imap_conn_find (&(mx.account), 0)))    goto fail;    conn = idata->conn;  imap_fix_path (idata, mx.mbox, buf, sizeof (buf));  if (option (OPTIMAPCHECKSUBSCRIBED))  {    memset (&token, 0, sizeof (token));    err.data = errstr;    err.dsize = sizeof (errstr);    snprintf (mbox, sizeof (mbox), "%smailboxes \"%s\"",              subscribe ? "" : "un", path);    if (mutt_parse_rc_line (mbox, &token, &err))      dprint (1, (debugfile, "Error adding subscribed mailbox: %s\n", errstr));    FREE (&token.data);  }    if (subscribe)    mutt_message (_("Subscribing to %s..."), buf);  else    mutt_message (_("Unsubscribing from %s..."), buf);  imap_munge_mbox_name (mbox, sizeof(mbox), buf);  snprintf (buf, sizeof (buf), "%sSUBSCRIBE %s", subscribe ? "" : "UN", mbox);  if (imap_exec (idata, buf, 0) < 0)    goto fail;  imap_unmunge_mbox_name(mx.mbox);  if (subscribe)    mutt_message (_("Subscribed to %s"), mx.mbox);  else    mutt_message (_("Unsubscribed from %s"), mx.mbox);  FREE (&mx.mbox);  return 0; fail:  FREE (&mx.mbox);  return -1;}/* trim dest to the length of the longest prefix it shares with src, * returning the length of the trimmed string */static intlongest_common_prefix (char *dest, const char* src, int start, size_t dlen){  int pos = start;    while (pos < dlen && dest[pos] && dest[pos] == src[pos])    pos++;  dest[pos] = '\0';  return pos;}/* look for IMAP URLs to complete from defined mailboxes. Could be extended * to complete over open connections and account/folder hooks too. */static intimap_complete_hosts (char *dest, size_t len){  BUFFY* mailbox;  CONNECTION* conn;  int rc = -1;  int matchlen;    matchlen = mutt_strlen (dest);  for (mailbox = Incoming; mailbox && mailbox->next; mailbox = mailbox->next)  {    if (!mutt_strncmp (dest, mailbox->path, matchlen))    {      if (rc)      {        strfcpy (dest, mailbox->path, len);        rc = 0;      }      else        longest_common_prefix (dest, mailbox->path, matchlen, len);    }  }    for (conn = mutt_socket_head (); conn && conn->next; conn = conn->next)  {    ciss_url_t url;    char urlstr[LONG_STRING];    if (conn->account.type != M_ACCT_TYPE_IMAP)      continue;    mutt_account_tourl (&conn->account, &url);    /* FIXME: how to handle multiple users on the same host? */    url.user = NULL;    url.path = NULL;    url_ciss_tostring (&url, urlstr, sizeof (urlstr), 0);    if (!mutt_strncmp (dest, urlstr, matchlen))    {      if (rc)      {        strfcpy (dest, urlstr, len);        rc = 0;      }      else        longest_common_prefix (dest, urlstr, matchlen, len);    }  }  return rc;}/* 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, size_t dlen, char* path) {  CONNECTION* conn;  IMAP_DATA* idata;  char list[LONG_STRING];  char buf[LONG_STRING];  IMAP_LIST listresp;  char completion[LONG_STRING];  int clen, matchlen = 0;  int completions = 0;  IMAP_MBOX mx;  int rc;  if (imap_parse_path (path, &mx) || !mx.mbox)  {    strfcpy (dest, path, dlen);    return imap_complete_hosts (dest, dlen);  }  /* don't open a new socket just for completion. Instead complete over   * known mailboxes/hooks/etc */  if (!(idata = imap_conn_find (&(mx.account), M_IMAP_CONN_NONEW)))  {    FREE (&mx.mbox);    strfcpy (dest, path, dlen);    return imap_complete_hosts (dest, dlen);  }  conn = idata->conn;  /* reformat path for IMAP list, and append wildcard */  /* don't use INBOX in place of "" */  if (mx.mbox && mx.mbox[0])    imap_fix_path (idata, mx.mbox, list, sizeof(list));  else    list[0] = '\0';  /* fire off command */  snprintf (buf, sizeof(buf), "%s \"\" \"%s%%\"",    option (OPTIMAPLSUB) ? "LSUB" : "LIST", list);  imap_cmd_start (idata, buf);  /* and see what the results are */  strfcpy (completion, NONULL(mx.mbox), sizeof(completion));  idata->cmddata = &listresp;  do  {    listresp.name = NULL;    rc = imap_cmd_step (idata);    if (rc == IMAP_CMD_CONTINUE && listresp.name)    {      /* if the folder isn't selectable, append delimiter to force browse       * to enter it on second tab. */      if (listresp.noselect)      {        clen = strlen(listresp.name);        listresp.name[clen++] = listresp.delim;        listresp.name[clen] = '\0';      }      /* copy in first word */      if (!completions)      {        strfcpy (completion, listresp.name, sizeof(completion));        matchlen = strlen (completion);        completions++;        continue;      }      matchlen = longest_common_prefix (completion, listresp.name, 0, matchlen);      completions++;    }  }  while (rc == IMAP_CMD_CONTINUE);  idata->cmddata = NULL;  if (completions)  {    /* reformat output */    imap_qualify_path (dest, dlen, &mx, completion);    mutt_pretty_mailbox (dest);    FREE (&mx.mbox);    return 0;  }    return -1;}

⌨️ 快捷键说明

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