NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
private.h File Reference

Shared constants/structs that are private to IMAP. More...

#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "config/lib.h"
#include "mutt.h"
+ Include dependency graph for private.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ImapList
 Items in an IMAP browser. More...
 
struct  ImapCommand
 IMAP command structure. More...
 
struct  SeqsetIterator
 UID Sequence Set Iterator. More...
 

Macros

#define IMAP_PORT   143
 Default port for IMAP. More...
 
#define IMAP_SSL_PORT   993
 Port for IMAP over SSL/TLS. More...
 
#define IMAP_LOG_CMD   2
 
#define IMAP_LOG_LTRL   3
 
#define IMAP_LOG_PASS   5
 
#define IMAP_RES_NO   -2
 <tag> NO ... More...
 
#define IMAP_RES_BAD   -1
 <tag> BAD ... More...
 
#define IMAP_RES_OK   0
 <tag> OK ... More...
 
#define IMAP_RES_CONTINUE   1
 * ... More...
 
#define IMAP_RES_RESPOND   2
 + More...
 
#define IMAP_RES_NEW   3
 ImapCommand.state additions. More...
 
#define SEQ_LEN   16
 
#define IMAP_MAX_CMDLEN   1024
 Maximum length of command lines before they must be split (for lazy servers) More...
 
#define IMAP_OPEN_NO_FLAGS   0
 No flags are set. More...
 
#define IMAP_REOPEN_ALLOW   (1 << 0)
 Allow re-opening a folder upon expunge. More...
 
#define IMAP_EXPUNGE_EXPECTED   (1 << 1)
 Messages will be expunged from the server. More...
 
#define IMAP_EXPUNGE_PENDING   (1 << 2)
 Messages on the server have been expunged. More...
 
#define IMAP_NEWMAIL_PENDING   (1 << 3)
 New mail is waiting on the server. More...
 
#define IMAP_FLAGS_PENDING   (1 << 4)
 Flags have changed on the server. More...
 
#define IMAP_CMD_NO_FLAGS   0
 No flags are set. More...
 
#define IMAP_CMD_PASS   (1 << 0)
 Command contains a password. Suppress logging. More...
 
#define IMAP_CMD_QUEUE   (1 << 1)
 Queue a command, do not execute. More...
 
#define IMAP_CMD_POLL   (1 << 2)
 Poll the tcp connection before running the imap command. More...
 
#define IMAP_CMD_SINGLE   (1 << 3)
 Run a single command. More...
 
#define IMAP_DATELEN   27
 
#define IMAP_CAP_NO_FLAGS   0
 No flags are set. More...
 
#define IMAP_CAP_IMAP4   (1 << 0)
 Server supports IMAP4. More...
 
#define IMAP_CAP_IMAP4REV1   (1 << 1)
 Server supports IMAP4rev1. More...
 
#define IMAP_CAP_STATUS   (1 << 2)
 Server supports STATUS command. More...
 
#define IMAP_CAP_ACL   (1 << 3)
 RFC2086: IMAP4 ACL extension. More...
 
#define IMAP_CAP_NAMESPACE   (1 << 4)
 RFC2342: IMAP4 Namespace. More...
 
#define IMAP_CAP_AUTH_CRAM_MD5   (1 << 5)
 RFC2195: CRAM-MD5 authentication. More...
 
#define IMAP_CAP_AUTH_GSSAPI   (1 << 6)
 RFC1731: GSSAPI authentication. More...
 
#define IMAP_CAP_AUTH_ANONYMOUS   (1 << 7)
 AUTH=ANONYMOUS. More...
 
#define IMAP_CAP_AUTH_OAUTHBEARER   (1 << 8)
 RFC7628: AUTH=OAUTHBEARER. More...
 
#define IMAP_CAP_STARTTLS   (1 << 9)
 RFC2595: STARTTLS. More...
 
#define IMAP_CAP_LOGINDISABLED   (1 << 10)
 RFC2595: LOGINDISABLED. More...
 
#define IMAP_CAP_IDLE   (1 << 11)
 RFC2177: IDLE. More...
 
#define IMAP_CAP_SASL_IR   (1 << 12)
 SASL initial response draft. More...
 
#define IMAP_CAP_ENABLE   (1 << 13)
 RFC5161. More...
 
#define IMAP_CAP_CONDSTORE   (1 << 14)
 RFC7162. More...
 
#define IMAP_CAP_QRESYNC   (1 << 15)
 RFC7162. More...
 
#define IMAP_CAP_LIST_EXTENDED   (1 << 16)
 RFC5258: IMAP4 LIST Command Extensions. More...
 
#define IMAP_CAP_COMPRESS   (1 << 17)
 RFC4978: COMPRESS=DEFLATE. More...
 
#define IMAP_CAP_X_GM_EXT_1   (1 << 18)
 https://developers.google.com/gmail/imap/imap-extensions More...
 
#define IMAP_CAP_ALL   ((1 << 19) - 1)
 

Typedefs

typedef uint8_t ImapOpenFlags
 Flags, e.g. MUTT_THREAD_COLLAPSE. More...
 
typedef uint8_t ImapCmdFlags
 Flags for imap_exec(), e.g. IMAP_CMD_PASS. More...
 
typedef uint32_t ImapCapFlags
 Capabilities we are interested in. More...
 

Enumerations

enum  ImapExecResult { IMAP_EXEC_SUCCESS = 0, IMAP_EXEC_ERROR, IMAP_EXEC_FATAL }
 imap_exec return code More...
 
enum  ImapFlags { IMAP_FATAL = 1, IMAP_BYE }
 IMAP server responses. More...
 
enum  ImapState {
  IMAP_DISCONNECTED = 0, IMAP_CONNECTED, IMAP_AUTHENTICATED, IMAP_SELECTED,
  IMAP_IDLE
}
 IMAP connection state. More...
 

Functions

int imap_create_mailbox (struct ImapAccountData *adata, char *mailbox)
 Create a new mailbox. More...
 
int imap_rename_mailbox (struct ImapAccountData *adata, char *oldname, const char *newname)
 Rename a mailbox. More...
 
int imap_exec_msgset (struct Mailbox *m, const char *pre, const char *post, enum MessageType flag, bool changed, bool invert)
 Prepare commands for all messages matching conditions. More...
 
int imap_open_connection (struct ImapAccountData *adata)
 Open an IMAP connection. More...
 
void imap_close_connection (struct ImapAccountData *adata)
 Close an IMAP connection. More...
 
int imap_read_literal (FILE *fp, struct ImapAccountData *adata, unsigned long bytes, struct Progress *pbar)
 Read bytes bytes from server into file. More...
 
void imap_expunge_mailbox (struct Mailbox *m)
 Purge messages from the server. More...
 
int imap_login (struct ImapAccountData *adata)
 Open an IMAP connection. More...
 
int imap_sync_message_for_copy (struct Mailbox *m, struct Email *e, struct Buffer *cmd, enum QuadOption *err_continue)
 Update server to reflect the flags of a single message. More...
 
bool imap_has_flag (struct ListHead *flag_list, const char *flag)
 Does the flag exist in the list. More...
 
int imap_adata_find (const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
 Find the Account data for this path. More...
 
int imap_authenticate (struct ImapAccountData *adata)
 Authenticate to an IMAP server. More...
 
int imap_cmd_start (struct ImapAccountData *adata, const char *cmdstr)
 Given an IMAP command, send it to the server. More...
 
int imap_cmd_step (struct ImapAccountData *adata)
 Reads server responses from an IMAP command. More...
 
void imap_cmd_finish (struct ImapAccountData *adata)
 Attempt to perform cleanup. More...
 
bool imap_code (const char *s)
 Was the command successful. More...
 
const char * imap_cmd_trailer (struct ImapAccountData *adata)
 Extra information after tagged command response if any. More...
 
int imap_exec (struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
 Execute a command and wait for the response from the server. More...
 
int imap_cmd_idle (struct ImapAccountData *adata)
 Enter the IDLE state. More...
 
int imap_read_headers (struct Mailbox *m, unsigned int msn_begin, unsigned int msn_end, bool initial_download)
 Read headers from the server. More...
 
char * imap_set_flags (struct Mailbox *m, struct Email *e, char *s, bool *server_changes)
 fill the message header according to the server flags More...
 
int imap_cache_del (struct Mailbox *m, struct Email *e)
 Delete an email from the body cache. More...
 
int imap_cache_clean (struct Mailbox *m)
 Delete all the entries in the message cache. More...
 
int imap_append_message (struct Mailbox *m, struct Message *msg)
 Write an email back to the server. More...
 
bool imap_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
int imap_msg_close (struct Mailbox *m, struct Message *msg)
 Close an email - Implements MxOps::msg_close() -. More...
 
int imap_msg_commit (struct Mailbox *m, struct Message *msg)
 Save changes to an email - Implements MxOps::msg_commit() -. More...
 
int imap_msg_save_hcache (struct Mailbox *m, struct Email *e)
 Save message to the header cache - Implements MxOps::msg_save_hcache() -. More...
 
void imap_hcache_open (struct ImapAccountData *adata, struct ImapMboxData *mdata)
 Open a header cache. More...
 
void imap_hcache_close (struct ImapMboxData *mdata)
 Close the header cache. More...
 
struct Emailimap_hcache_get (struct ImapMboxData *mdata, unsigned int uid)
 Get a header cache entry by its UID. More...
 
int imap_hcache_put (struct ImapMboxData *mdata, struct Email *e)
 Add an entry to the header cache. More...
 
int imap_hcache_del (struct ImapMboxData *mdata, unsigned int uid)
 Delete an item from the header cache. More...
 
int imap_hcache_store_uid_seqset (struct ImapMboxData *mdata)
 Store a UID Sequence Set in the header cache. More...
 
int imap_hcache_clear_uid_seqset (struct ImapMboxData *mdata)
 Delete a UID Sequence Set from the header cache. More...
 
char * imap_hcache_get_uid_seqset (struct ImapMboxData *mdata)
 Get a UID Sequence Set from the header cache. More...
 
enum QuadOption imap_continue (const char *msg, const char *resp)
 display a message and ask the user if they want to go on More...
 
void imap_error (const char *where, const char *msg)
 show an error and abort More...
 
void imap_mdata_cache_reset (struct ImapMboxData *mdata)
 Release and clear cache data of ImapMboxData structure. More...
 
char * imap_fix_path (char delim, const char *mailbox, char *path, size_t plen)
 Fix up the imap path. More...
 
void imap_cachepath (char delim, const char *mailbox, struct Buffer *dest)
 Generate a cache path for a mailbox. More...
 
int imap_get_literal_count (const char *buf, unsigned int *bytes)
 write number of bytes in an IMAP literal into bytes More...
 
char * imap_get_qualifier (char *buf)
 Get the qualifier from a tagged response. More...
 
char * imap_next_word (char *s)
 Find where the next IMAP word begins. More...
 
void imap_qualify_path (char *buf, size_t buflen, struct ConnAccount *conn_account, char *path)
 Make an absolute IMAP folder target. More...
 
void imap_quote_string (char *dest, size_t dlen, const char *src, bool quote_backtick)
 quote string according to IMAP rules More...
 
void imap_unquote_string (char *s)
 equally stupid unquoting routine More...
 
void imap_munge_mbox_name (bool unicode, char *dest, size_t dlen, const char *src)
 Quote awkward characters in a mailbox name. More...
 
void imap_unmunge_mbox_name (bool unicode, char *s)
 Remove quoting from a mailbox name. More...
 
struct SeqsetIteratormutt_seqset_iterator_new (const char *seqset)
 Create a new Sequence Set Iterator. More...
 
int mutt_seqset_iterator_next (struct SeqsetIterator *iter, unsigned int *next)
 Get the next UID from a Sequence Set. More...
 
void mutt_seqset_iterator_free (struct SeqsetIterator **ptr)
 Free a Sequence Set Iterator. More...
 
bool imap_account_match (const struct ConnAccount *a1, const struct ConnAccount *a2)
 Compare two Accounts. More...
 
void imap_get_parent (const char *mbox, char delim, char *buf, size_t buflen)
 Get an IMAP folder's parent. More...
 
bool mutt_account_match (const struct ConnAccount *a1, const struct ConnAccount *a2)
 
void imap_utf_encode (bool unicode, char **s)
 Encode email from local charset to UTF-8. More...
 
void imap_utf_decode (bool unicode, char **s)
 Decode email from UTF-8 to local charset. More...
 
void imap_allow_reopen (struct Mailbox *m)
 Allow re-opening a folder upon expunge. More...
 
void imap_disallow_reopen (struct Mailbox *m)
 Disallow re-opening a folder upon expunge. More...
 
void cmd_parse_search (struct ImapAccountData *adata, const char *s)
 store SEARCH response for later use More...
 

Detailed Description

Shared constants/structs that are private to IMAP.

Authors
  • Brandon Long
  • Brendan Cully
  • Richard Russon

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, see http://www.gnu.org/licenses/.

Definition in file private.h.

Macro Definition Documentation

◆ IMAP_PORT

#define IMAP_PORT   143

Default port for IMAP.

Definition at line 45 of file private.h.

◆ IMAP_SSL_PORT

#define IMAP_SSL_PORT   993

Port for IMAP over SSL/TLS.

Definition at line 46 of file private.h.

◆ IMAP_LOG_CMD

#define IMAP_LOG_CMD   2

Definition at line 49 of file private.h.

◆ IMAP_LOG_LTRL

#define IMAP_LOG_LTRL   3

Definition at line 50 of file private.h.

◆ IMAP_LOG_PASS

#define IMAP_LOG_PASS   5

Definition at line 51 of file private.h.

◆ IMAP_RES_NO

#define IMAP_RES_NO   -2

<tag> NO ...

Definition at line 54 of file private.h.

◆ IMAP_RES_BAD

#define IMAP_RES_BAD   -1

<tag> BAD ...

Definition at line 55 of file private.h.

◆ IMAP_RES_OK

#define IMAP_RES_OK   0

<tag> OK ...

Definition at line 56 of file private.h.

◆ IMAP_RES_CONTINUE

#define IMAP_RES_CONTINUE   1

* ...

Definition at line 57 of file private.h.

◆ IMAP_RES_RESPOND

#define IMAP_RES_RESPOND   2

+

Definition at line 58 of file private.h.

◆ IMAP_RES_NEW

#define IMAP_RES_NEW   3

ImapCommand.state additions.

Definition at line 59 of file private.h.

◆ SEQ_LEN

#define SEQ_LEN   16

Definition at line 61 of file private.h.

◆ IMAP_MAX_CMDLEN

#define IMAP_MAX_CMDLEN   1024

Maximum length of command lines before they must be split (for lazy servers)

Definition at line 62 of file private.h.

◆ IMAP_OPEN_NO_FLAGS

#define IMAP_OPEN_NO_FLAGS   0

No flags are set.

Definition at line 65 of file private.h.

◆ IMAP_REOPEN_ALLOW

#define IMAP_REOPEN_ALLOW   (1 << 0)

Allow re-opening a folder upon expunge.

Definition at line 66 of file private.h.

◆ IMAP_EXPUNGE_EXPECTED

#define IMAP_EXPUNGE_EXPECTED   (1 << 1)

Messages will be expunged from the server.

Definition at line 67 of file private.h.

◆ IMAP_EXPUNGE_PENDING

#define IMAP_EXPUNGE_PENDING   (1 << 2)

Messages on the server have been expunged.

Definition at line 68 of file private.h.

◆ IMAP_NEWMAIL_PENDING

#define IMAP_NEWMAIL_PENDING   (1 << 3)

New mail is waiting on the server.

Definition at line 69 of file private.h.

◆ IMAP_FLAGS_PENDING

#define IMAP_FLAGS_PENDING   (1 << 4)

Flags have changed on the server.

Definition at line 70 of file private.h.

◆ IMAP_CMD_NO_FLAGS

#define IMAP_CMD_NO_FLAGS   0

No flags are set.

Definition at line 73 of file private.h.

◆ IMAP_CMD_PASS

#define IMAP_CMD_PASS   (1 << 0)

Command contains a password. Suppress logging.

Definition at line 74 of file private.h.

◆ IMAP_CMD_QUEUE

#define IMAP_CMD_QUEUE   (1 << 1)

Queue a command, do not execute.

Definition at line 75 of file private.h.

◆ IMAP_CMD_POLL

#define IMAP_CMD_POLL   (1 << 2)

Poll the tcp connection before running the imap command.

Definition at line 76 of file private.h.

◆ IMAP_CMD_SINGLE

#define IMAP_CMD_SINGLE   (1 << 3)

Run a single command.

Definition at line 77 of file private.h.

◆ IMAP_DATELEN

#define IMAP_DATELEN   27

Definition at line 90 of file private.h.

◆ IMAP_CAP_NO_FLAGS

#define IMAP_CAP_NO_FLAGS   0

No flags are set.

Definition at line 122 of file private.h.

◆ IMAP_CAP_IMAP4

#define IMAP_CAP_IMAP4   (1 << 0)

Server supports IMAP4.

Definition at line 123 of file private.h.

◆ IMAP_CAP_IMAP4REV1

#define IMAP_CAP_IMAP4REV1   (1 << 1)

Server supports IMAP4rev1.

Definition at line 124 of file private.h.

◆ IMAP_CAP_STATUS

#define IMAP_CAP_STATUS   (1 << 2)

Server supports STATUS command.

Definition at line 125 of file private.h.

◆ IMAP_CAP_ACL

#define IMAP_CAP_ACL   (1 << 3)

RFC2086: IMAP4 ACL extension.

Definition at line 126 of file private.h.

◆ IMAP_CAP_NAMESPACE

#define IMAP_CAP_NAMESPACE   (1 << 4)

RFC2342: IMAP4 Namespace.

Definition at line 127 of file private.h.

◆ IMAP_CAP_AUTH_CRAM_MD5

#define IMAP_CAP_AUTH_CRAM_MD5   (1 << 5)

RFC2195: CRAM-MD5 authentication.

Definition at line 128 of file private.h.

◆ IMAP_CAP_AUTH_GSSAPI

#define IMAP_CAP_AUTH_GSSAPI   (1 << 6)

RFC1731: GSSAPI authentication.

Definition at line 129 of file private.h.

◆ IMAP_CAP_AUTH_ANONYMOUS

#define IMAP_CAP_AUTH_ANONYMOUS   (1 << 7)

AUTH=ANONYMOUS.

Definition at line 130 of file private.h.

◆ IMAP_CAP_AUTH_OAUTHBEARER

#define IMAP_CAP_AUTH_OAUTHBEARER   (1 << 8)

RFC7628: AUTH=OAUTHBEARER.

Definition at line 131 of file private.h.

◆ IMAP_CAP_STARTTLS

#define IMAP_CAP_STARTTLS   (1 << 9)

RFC2595: STARTTLS.

Definition at line 132 of file private.h.

◆ IMAP_CAP_LOGINDISABLED

#define IMAP_CAP_LOGINDISABLED   (1 << 10)

RFC2595: LOGINDISABLED.

Definition at line 133 of file private.h.

◆ IMAP_CAP_IDLE

#define IMAP_CAP_IDLE   (1 << 11)

RFC2177: IDLE.

Definition at line 134 of file private.h.

◆ IMAP_CAP_SASL_IR

#define IMAP_CAP_SASL_IR   (1 << 12)

SASL initial response draft.

Definition at line 135 of file private.h.

◆ IMAP_CAP_ENABLE

#define IMAP_CAP_ENABLE   (1 << 13)

RFC5161.

Definition at line 136 of file private.h.

◆ IMAP_CAP_CONDSTORE

#define IMAP_CAP_CONDSTORE   (1 << 14)

RFC7162.

Definition at line 137 of file private.h.

◆ IMAP_CAP_QRESYNC

#define IMAP_CAP_QRESYNC   (1 << 15)

RFC7162.

Definition at line 138 of file private.h.

◆ IMAP_CAP_LIST_EXTENDED

#define IMAP_CAP_LIST_EXTENDED   (1 << 16)

RFC5258: IMAP4 LIST Command Extensions.

Definition at line 139 of file private.h.

◆ IMAP_CAP_COMPRESS

#define IMAP_CAP_COMPRESS   (1 << 17)

RFC4978: COMPRESS=DEFLATE.

Definition at line 140 of file private.h.

◆ IMAP_CAP_X_GM_EXT_1

#define IMAP_CAP_X_GM_EXT_1   (1 << 18)

◆ IMAP_CAP_ALL

#define IMAP_CAP_ALL   ((1 << 19) - 1)

Definition at line 143 of file private.h.

Typedef Documentation

◆ ImapOpenFlags

typedef uint8_t ImapOpenFlags

Flags, e.g. MUTT_THREAD_COLLAPSE.

Definition at line 64 of file private.h.

◆ ImapCmdFlags

typedef uint8_t ImapCmdFlags

Flags for imap_exec(), e.g. IMAP_CMD_PASS.

Definition at line 72 of file private.h.

◆ ImapCapFlags

typedef uint32_t ImapCapFlags

Capabilities we are interested in.

Note
This must be kept in the same order as Capabilities.Flags, e.g. IMAP_CAP_IMAP4

Definition at line 121 of file private.h.

Enumeration Type Documentation

◆ ImapExecResult

imap_exec return code

Enumerator
IMAP_EXEC_SUCCESS 

Imap command executed or queued successfully.

IMAP_EXEC_ERROR 

Imap command failure.

IMAP_EXEC_FATAL 

Imap connection failure.

Definition at line 82 of file private.h.

83 {
84  IMAP_EXEC_SUCCESS = 0,
87 };
Imap connection failure.
Definition: private.h:86
Imap command executed or queued successfully.
Definition: private.h:84
Imap command failure.
Definition: private.h:85

◆ ImapFlags

enum ImapFlags

IMAP server responses.

Enumerator
IMAP_FATAL 

Unrecoverable error occurred.

IMAP_BYE 

Logged out from server.

Definition at line 95 of file private.h.

96 {
97  IMAP_FATAL = 1,
98  IMAP_BYE,
99 };
Logged out from server.
Definition: private.h:98
Unrecoverable error occurred.
Definition: private.h:97

◆ ImapState

enum ImapState

IMAP connection state.

Enumerator
IMAP_DISCONNECTED 

Disconnected from server.

IMAP_CONNECTED 

Connected to server.

IMAP_AUTHENTICATED 

Connection is authenticated.

IMAP_SELECTED 

Mailbox is selected.

IMAP_IDLE 

Connection is idle.

Definition at line 104 of file private.h.

105 {
106  /* States */
107  IMAP_DISCONNECTED = 0,
110  IMAP_SELECTED,
111 
112  /* and pseudo-states */
113  IMAP_IDLE,
114 };
Connection is authenticated.
Definition: private.h:109
Disconnected from server.
Definition: private.h:107
Mailbox is selected.
Definition: private.h:110
Connected to server.
Definition: private.h:108
Connection is idle.
Definition: private.h:113

Function Documentation

◆ imap_create_mailbox()

int imap_create_mailbox ( struct ImapAccountData adata,
char *  mailbox 
)

Create a new mailbox.

Parameters
adataImap Account data
mailboxMailbox to create
Return values
0Success
-1Failure

Definition at line 448 of file imap.c.

449 {
450  char buf[2048], mbox[1024];
451 
452  imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), mailbox);
453  snprintf(buf, sizeof(buf), "CREATE %s", mbox);
454 
455  if (imap_exec(adata, buf, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
456  {
457  mutt_error(_("CREATE failed: %s"), imap_cmd_trailer(adata));
458  return -1;
459  }
460 
461  return 0;
462 }
#define mutt_error(...)
Definition: logging.h:88
void imap_munge_mbox_name(bool unicode, char *dest, size_t dlen, const char *src)
Quote awkward characters in a mailbox name.
Definition: util.c:914
#define _(a)
Definition: message.h:28
const char * imap_cmd_trailer(struct ImapAccountData *adata)
Extra information after tagged command response if any.
Definition: command.c:1213
Imap command executed or queued successfully.
Definition: private.h:84
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition: command.c:1250
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:73
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition: adata.h:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_rename_mailbox()

int imap_rename_mailbox ( struct ImapAccountData adata,
char *  oldname,
const char *  newname 
)

Rename a mailbox.

Parameters
adataImap Account data
oldnameExisting mailbox
newnameNew name for mailbox
Return values
0Success
-1Failure

Definition at line 489 of file imap.c.

490 {
491  char oldmbox[1024];
492  char newmbox[1024];
493  int rc = 0;
494 
495  imap_munge_mbox_name(adata->unicode, oldmbox, sizeof(oldmbox), oldname);
496  imap_munge_mbox_name(adata->unicode, newmbox, sizeof(newmbox), newname);
497 
498  struct Buffer *buf = mutt_buffer_pool_get();
499  mutt_buffer_printf(buf, "RENAME %s %s", oldmbox, newmbox);
500 
502  rc = -1;
503 
505 
506  return rc;
507 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void imap_munge_mbox_name(bool unicode, char *dest, size_t dlen, const char *src)
Quote awkward characters in a mailbox name.
Definition: util.c:914
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Imap command executed or queued successfully.
Definition: private.h:84
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition: command.c:1250
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:73
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition: adata.h:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_exec_msgset()

int imap_exec_msgset ( struct Mailbox m,
const char *  pre,
const char *  post,
enum MessageType  flag,
bool  changed,
bool  invert 
)

Prepare commands for all messages matching conditions.

Parameters
mSelected Imap Mailbox
preprefix commands
postpostfix commands
flagflag type on which to filter, e.g. MUTT_REPLIED
changedinclude only changed messages in message set
invertinvert sense of flag, eg MUTT_READ matches unread messages
Return values
numMatched messages
-1Failure

pre/post: commands are of the form "%s %s %s %s", tag, pre, message set, post Prepares commands for all messages matching conditions (must be flushed with imap_exec)

Definition at line 927 of file imap.c.

929 {
930  struct ImapAccountData *adata = imap_adata_get(m);
931  if (!adata || (adata->mailbox != m))
932  return -1;
933 
934  struct Email **emails = NULL;
935  int pos;
936  int rc;
937  int count = 0;
938 
939  struct Buffer cmd = mutt_buffer_make(0);
940 
941  /* We make a copy of the headers just in case resorting doesn't give
942  exactly the original order (duplicate messages?), because other parts of
943  the ctx are tied to the header order. This may be overkill. */
944  const short c_sort = cs_subset_sort(NeoMutt->sub, "sort");
945  if (c_sort != SORT_ORDER)
946  {
947  emails = m->emails;
948  // We overcommit here, just in case new mail arrives whilst we're sync-ing
949  m->emails = mutt_mem_malloc(m->email_max * sizeof(struct Email *));
950  memcpy(m->emails, emails, m->email_max * sizeof(struct Email *));
951 
953  qsort(m->emails, m->msg_count, sizeof(struct Email *), compare_uid);
954  }
955 
956  pos = 0;
957 
958  do
959  {
960  mutt_buffer_reset(&cmd);
961  mutt_buffer_add_printf(&cmd, "%s ", pre);
962  rc = make_msg_set(m, &cmd, flag, changed, invert, &pos);
963  if (rc > 0)
964  {
965  mutt_buffer_add_printf(&cmd, " %s", post);
966  if (imap_exec(adata, cmd.data, IMAP_CMD_QUEUE) != IMAP_EXEC_SUCCESS)
967  {
968  rc = -1;
969  goto out;
970  }
971  count += rc;
972  }
973  } while (rc > 0);
974 
975  rc = count;
976 
977 out:
978  mutt_buffer_dealloc(&cmd);
979  if (c_sort != SORT_ORDER)
980  {
981  cs_subset_str_native_set(NeoMutt->sub, "sort", c_sort, NULL);
982  FREE(&m->emails);
983  m->emails = emails;
984  }
985 
986  return rc;
987 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
int msg_count
Total number of messages.
Definition: mailbox.h:91
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
The envelope/body of an email.
Definition: email.h:37
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
Container for Accounts, Notifications.
Definition: neomutt.h:36
Imap command executed or queued successfully.
Definition: private.h:84
static int make_msg_set(struct Mailbox *m, struct Buffer *buf, enum MessageType flag, bool changed, bool invert, int *pos)
Make a message set.
Definition: imap.c:197
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:48
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition: command.c:1250
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * data
Pointer to data.
Definition: buffer.h:35
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
IMAP-specific Account data -.
Definition: adata.h:39
#define FREE(x)
Definition: memory.h:40
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:75
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
static int compare_uid(const void *a, const void *b)
Compare two Emails by UID - Implements sort_t.
Definition: imap.c:904
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_open_connection()

int imap_open_connection ( struct ImapAccountData adata)

Open an IMAP connection.

Parameters
adataImap Account data
Return values
0Success
-1Failure

Definition at line 745 of file imap.c.

746 {
747  if (mutt_socket_open(adata->conn) < 0)
748  return -1;
749 
750  adata->state = IMAP_CONNECTED;
751 
752  if (imap_cmd_step(adata) != IMAP_RES_OK)
753  {
754  imap_close_connection(adata);
755  return -1;
756  }
757 
758  if (mutt_istr_startswith(adata->buf, "* OK"))
759  {
760  if (!mutt_istr_startswith(adata->buf, "* OK [CAPABILITY") && check_capabilities(adata))
761  {
762  goto bail;
763  }
764 #ifdef USE_SSL
765  /* Attempt STARTTLS if available and desired. */
766  const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
767  if ((adata->conn->ssf == 0) &&
768  (c_ssl_force_tls || (adata->capabilities & IMAP_CAP_STARTTLS)))
769  {
770  enum QuadOption ans;
771 
772  const enum QuadOption c_ssl_starttls =
773  cs_subset_quad(NeoMutt->sub, "ssl_starttls");
774  if (c_ssl_force_tls)
775  ans = MUTT_YES;
776  else if ((ans = query_quadoption(c_ssl_starttls,
777  _("Secure connection with TLS?"))) == MUTT_ABORT)
778  {
779  goto bail;
780  }
781  if (ans == MUTT_YES)
782  {
783  enum ImapExecResult rc = imap_exec(adata, "STARTTLS", IMAP_CMD_SINGLE);
784  // Clear any data after the STARTTLS acknowledgement
785  mutt_socket_empty(adata->conn);
786 
787  if (rc == IMAP_EXEC_FATAL)
788  goto bail;
789  if (rc != IMAP_EXEC_ERROR)
790  {
791  if (mutt_ssl_starttls(adata->conn))
792  {
793  mutt_error(_("Could not negotiate TLS connection"));
794  goto bail;
795  }
796  else
797  {
798  /* RFC2595 demands we recheck CAPABILITY after TLS completes. */
799  if (imap_exec(adata, "CAPABILITY", IMAP_CMD_NO_FLAGS))
800  goto bail;
801  }
802  }
803  }
804  }
805 
806  if (c_ssl_force_tls && (adata->conn->ssf == 0))
807  {
808  mutt_error(_("Encrypted connection unavailable"));
809  goto bail;
810  }
811 #endif
812  }
813  else if (mutt_istr_startswith(adata->buf, "* PREAUTH"))
814  {
815 #ifdef USE_SSL
816  /* Unless using a secure $tunnel, an unencrypted PREAUTH response may be a
817  * MITM attack. The only way to stop "STARTTLS" MITM attacks is via
818  * $ssl_force_tls: an attacker can easily spoof "* OK" and strip the
819  * STARTTLS capability. So consult $ssl_force_tls, not $ssl_starttls, to
820  * decide whether to abort. Note that if using $tunnel and
821  * $tunnel_is_secure, adata->conn->ssf will be set to 1. */
822  const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
823  if ((adata->conn->ssf == 0) && c_ssl_force_tls)
824  {
825  mutt_error(_("Encrypted connection unavailable"));
826  goto bail;
827  }
828 #endif
829 
830  adata->state = IMAP_AUTHENTICATED;
831  if (check_capabilities(adata) != 0)
832  goto bail;
833  FREE(&adata->capstr);
834  }
835  else
836  {
837  imap_error("imap_open_connection()", adata->buf);
838  goto bail;
839  }
840 
841  return 0;
842 
843 bail:
844  imap_close_connection(adata);
845  FREE(&adata->capstr);
846  return -1;
847 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:56
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1079
Imap connection failure.
Definition: private.h:86
unsigned int ssf
Security strength factor, in bits (see below)
Definition: connection.h:41
#define mutt_error(...)
Definition: logging.h:88
Connection is authenticated.
Definition: private.h:109
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: adata.h:44
#define _(a)
Definition: message.h:28
void imap_close_connection(struct ImapAccountData *adata)
Close an IMAP connection.
Definition: imap.c:853
char * capstr
Definition: adata.h:54
ImapExecResult
imap_exec return code
Definition: private.h:82
#define IMAP_CAP_STARTTLS
RFC2595: STARTTLS.
Definition: private.h:132
Container for Accounts, Notifications.
Definition: neomutt.h:36
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:76
Connected to server.
Definition: private.h:108
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:347
User aborted the question (with Ctrl-G)
Definition: quad.h:37
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition: command.c:1250
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:665
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
ImapCapFlags capabilities
Definition: adata.h:55
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:73
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
Imap command failure.
Definition: private.h:85
void mutt_socket_empty(struct Connection *conn)
Clear out any queued data.
Definition: socket.c:313
char * buf
Definition: adata.h:59
#define FREE(x)
Definition: memory.h:40
static int check_capabilities(struct ImapAccountData *adata)
Make sure we can log in to this server.
Definition: imap.c:94
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define IMAP_CMD_SINGLE
Run a single command.
Definition: private.h:77
int mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
Definition: gnutls.c:1167
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
struct Connection * conn
Definition: adata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_close_connection()

void imap_close_connection ( struct ImapAccountData adata)

Close an IMAP connection.

Parameters
adataImap Account data

Definition at line 853 of file imap.c.

854 {
855  if (adata->state != IMAP_DISCONNECTED)
856  {
857  mutt_socket_close(adata->conn);
858  adata->state = IMAP_DISCONNECTED;
859  }
860  adata->seqno = 0;
861  adata->nextcmd = 0;
862  adata->lastcmd = 0;
863  adata->status = 0;
864  memset(adata->cmds, 0, sizeof(struct ImapCommand) * adata->cmdslots);
865 }
struct ImapCommand * cmds
Definition: adata.h:69
unsigned int seqno
tag sequence number, e.g. &#39;{seqid}0001&#39;
Definition: adata.h:57
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: adata.h:44
int lastcmd
Definition: adata.h:72
int nextcmd
Definition: adata.h:71
Disconnected from server.
Definition: private.h:107
IMAP command structure.
Definition: private.h:159
int cmdslots
Definition: adata.h:70
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: adata.h:45
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:97
struct Connection * conn
Definition: adata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_read_literal()

int imap_read_literal ( FILE *  fp,
struct ImapAccountData adata,
unsigned long  bytes,
struct Progress pbar 
)

Read bytes bytes from server into file.

Parameters
fpFile handle for email file
adataImap Account data
bytesNumber of bytes to read
pbarProgress bar
Return values
0Success
-1Failure

Not explicitly buffered, relies on FILE buffering.

Note
Strips \r from \r\n. Apparently even literals use \r\n-terminated strings ?!

Definition at line 600 of file imap.c.

602 {
603  char c;
604  bool r = false;
605  struct Buffer buf = { 0 }; // Do not allocate, maybe it won't be used
606 
607  const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
608  if (c_debug_level >= IMAP_LOG_LTRL)
609  mutt_buffer_alloc(&buf, bytes + 10);
610 
611  mutt_debug(LL_DEBUG2, "reading %ld bytes\n", bytes);
612 
613  for (unsigned long pos = 0; pos < bytes; pos++)
614  {
615  if (mutt_socket_readchar(adata->conn, &c) != 1)
616  {
617  mutt_debug(LL_DEBUG1, "error during read, %ld bytes read\n", pos);
618  adata->status = IMAP_FATAL;
619 
620  mutt_buffer_dealloc(&buf);
621  return -1;
622  }
623 
624  if (r && (c != '\n'))
625  fputc('\r', fp);
626 
627  if (c == '\r')
628  {
629  r = true;
630  continue;
631  }
632  else
633  r = false;
634 
635  fputc(c, fp);
636 
637  if (pbar && !(pos % 1024))
638  progress_update(pbar, pos, -1);
639  if (c_debug_level >= IMAP_LOG_LTRL)
640  mutt_buffer_addch(&buf, c);
641  }
642 
643  if (c_debug_level >= IMAP_LOG_LTRL)
644  {
645  mutt_debug(IMAP_LOG_LTRL, "\n%s", buf.data);
646  mutt_buffer_dealloc(&buf);
647  }
648  return 0;
649 }
Unrecoverable error occurred.
Definition: private.h:97
String manipulation buffer.
Definition: buffer.h:33
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
int mutt_socket_readchar(struct Connection *conn, char *c)
simple read buffering to speed things up
Definition: socket.c:210
Log at debug level 2.
Definition: logging.h:41
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: adata.h:45
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:175
Log at debug level 1.
Definition: logging.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define IMAP_LOG_LTRL
Definition: private.h:50
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
struct Connection * conn
Definition: adata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_expunge_mailbox()

void imap_expunge_mailbox ( struct Mailbox m)

Purge messages from the server.

Parameters
mMailbox

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.

Definition at line 676 of file imap.c.

677 {
678  struct ImapAccountData *adata = imap_adata_get(m);
679  struct ImapMboxData *mdata = imap_mdata_get(m);
680  if (!adata || !mdata)
681  return;
682 
683  struct Email *e = NULL;
684 
685 #ifdef USE_HCACHE
686  imap_hcache_open(adata, mdata);
687 #endif
688 
689  for (int i = 0; i < m->msg_count; i++)
690  {
691  e = m->emails[i];
692  if (!e)
693  break;
694 
695  if (e->index == INT_MAX)
696  {
697  mutt_debug(LL_DEBUG2, "Expunging message UID %u\n", imap_edata_get(e)->uid);
698 
699  e->deleted = true;
700 
701  imap_cache_del(m, e);
702 #ifdef USE_HCACHE
703  imap_hcache_del(mdata, imap_edata_get(e)->uid);
704 #endif
705 
706  mutt_hash_int_delete(mdata->uid_hash, imap_edata_get(e)->uid, e);
707 
708  imap_edata_free((void **) &e->edata);
709  }
710  else
711  {
712  /* NeoMutt has several places where it turns off e->active as a
713  * hack. For example to avoid FLAG updates, or to exclude from
714  * imap_exec_msgset.
715  *
716  * Unfortunately, when a reopen is allowed and the IMAP_EXPUNGE_PENDING
717  * flag becomes set (e.g. a flag update to a modified header),
718  * this function will be called by imap_cmd_finish().
719  *
720  * The ctx_update_tables() will free and remove these "inactive" headers,
721  * despite that an EXPUNGE was not received for them.
722  * This would result in memory leaks and segfaults due to dangling
723  * pointers in the msn_index and uid_hash.
724  *
725  * So this is another hack to work around the hacks. We don't want to
726  * remove the messages, so make sure active is on. */
727  e->active = true;
728  }
729  }
730 
731 #ifdef USE_HCACHE
732  imap_hcache_close(mdata);
733 #endif
734 
737 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
Update internal tables.
Definition: mailbox.h:183
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition: util.c:399
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition: message.c:1819
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:64
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:340
Log at debug level 2.
Definition: logging.h:41
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:59
void imap_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: edata.c:38
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct HashTable * uid_hash
Definition: mdata.h:58
Email list needs resorting.
Definition: mailbox.h:181
bool active
Message is not to be removed.
Definition: email.h:59
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
void mutt_hash_int_delete(struct HashTable *table, unsigned int intkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:436
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
IMAP-specific Account data -.
Definition: adata.h:39
IMAP-specific Mailbox data -.
Definition: mdata.h:38
bool deleted
Email is deleted.
Definition: email.h:45
void * edata
Driver-specific data.
Definition: email.h:111
int index
The absolute (unsorted) message number.
Definition: email.h:86
void imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
Open a header cache.
Definition: util.c:297
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:208
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_login()

int imap_login ( struct ImapAccountData adata)

Open an IMAP connection.

Parameters
adataImap Account data
Return values
0Success
-1Failure

Ensure ImapAccountData is connected and logged into the imap server.

Definition at line 1849 of file imap.c.

1850 {
1851  if (!adata)
1852  return -1;
1853 
1854  if (adata->state == IMAP_DISCONNECTED)
1855  {
1856  mutt_buffer_reset(&adata->cmdbuf); // purge outstanding queued commands
1857  imap_open_connection(adata);
1858  }
1859  if (adata->state == IMAP_CONNECTED)
1860  {
1861  if (imap_authenticate(adata) == IMAP_AUTH_SUCCESS)
1862  {
1863  adata->state = IMAP_AUTHENTICATED;
1864  FREE(&adata->capstr);
1865  if (adata->conn->ssf != 0)
1866  {
1867  mutt_debug(LL_DEBUG2, "Communication encrypted at %d bits\n",
1868  adata->conn->ssf);
1869  }
1870  }
1871  else
1873  }
1874  if (adata->state == IMAP_AUTHENTICATED)
1875  {
1876  /* capabilities may have changed */
1877  imap_exec(adata, "CAPABILITY", IMAP_CMD_PASS);
1878 
1879 #ifdef USE_ZLIB
1880  /* RFC4978 */
1881  const bool c_imap_deflate = cs_subset_bool(NeoMutt->sub, "imap_deflate");
1882  if ((adata->capabilities & IMAP_CAP_COMPRESS) && c_imap_deflate &&
1883  (imap_exec(adata, "COMPRESS DEFLATE", IMAP_CMD_PASS) == IMAP_EXEC_SUCCESS))
1884  {
1885  mutt_debug(LL_DEBUG2, "IMAP compression is enabled on connection to %s\n",
1886  adata->conn->account.host);
1887  mutt_zstrm_wrap_conn(adata->conn);
1888  }
1889 #endif
1890 
1891  /* enable RFC6855, if the server supports that */
1892  const bool c_imap_rfc5161 = cs_subset_bool(NeoMutt->sub, "imap_rfc5161");
1893  if (c_imap_rfc5161 && (adata->capabilities & IMAP_CAP_ENABLE))
1894  imap_exec(adata, "ENABLE UTF8=ACCEPT", IMAP_CMD_QUEUE);
1895 
1896  /* enable QRESYNC. Advertising QRESYNC also means CONDSTORE
1897  * is supported (even if not advertised), so flip that bit. */
1898  if (adata->capabilities & IMAP_CAP_QRESYNC)
1899  {
1900  adata->capabilities |= IMAP_CAP_CONDSTORE;
1901  const bool c_imap_qresync = cs_subset_bool(NeoMutt->sub, "imap_qresync");
1902  if (c_imap_rfc5161 && c_imap_qresync)
1903  imap_exec(adata, "ENABLE QRESYNC", IMAP_CMD_QUEUE);
1904  }
1905 
1906  /* get root delimiter, '/' as default */
1907  adata->delim = '/';
1908  imap_exec(adata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
1909 
1910  /* we may need the root delimiter before we open a mailbox */
1911  imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1912 
1913  /* select the mailbox that used to be open before disconnect */
1914  if (adata->mailbox)
1915  {
1916  imap_mbox_select(adata->mailbox);
1917  }
1918  }
1919 
1920  if (adata->state < IMAP_AUTHENTICATED)
1921  return -1;
1922 
1923  return 0;
1924 }
#define IMAP_CAP_COMPRESS
RFC4978: COMPRESS=DEFLATE.
Definition: private.h:140
void mutt_zstrm_wrap_conn(struct Connection *conn)
Wrap a compression layer around a Connection.
Definition: zstrm.c:288
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
unsigned int ssf
Security strength factor, in bits (see below)
Definition: connection.h:41
int imap_open_connection(struct ImapAccountData *adata)
Open an IMAP connection.
Definition: imap.c:745
Connection is authenticated.
Definition: private.h:109
#define IMAP_CAP_ENABLE
RFC5161.
Definition: private.h:136
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: adata.h:44
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
char * capstr
Definition: adata.h:54
Container for Accounts, Notifications.
Definition: neomutt.h:36
Imap command executed or queued successfully.
Definition: private.h:84
char host[128]
Server to login to.
Definition: connaccount.h:53
Disconnected from server.
Definition: private.h:107
Log at debug level 2.
Definition: logging.h:41
struct Buffer cmdbuf
Definition: adata.h:73
Connected to server.
Definition: private.h:108
char delim
Definition: adata.h:75
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition: command.c:1250
void mutt_account_unsetpass(struct ConnAccount *cac)
Unset ConnAccount&#39;s password.
Definition: connaccount.c:140
#define IMAP_CMD_PASS
Command contains a password. Suppress logging.
Definition: private.h:74
ImapCapFlags capabilities
Definition: adata.h:55
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:73
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
static void imap_mbox_select(struct Mailbox *m)
Select a Mailbox.
Definition: imap.c:1816
#define IMAP_CAP_CONDSTORE
RFC7162.
Definition: private.h:137
#define IMAP_CAP_QRESYNC
RFC7162.
Definition: private.h:138
#define FREE(x)
Definition: memory.h:40
int imap_authenticate(struct ImapAccountData *adata)
Authenticate to an IMAP server.
Definition: auth.c:107
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:75
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Authentication successful.
Definition: auth.h:39
struct Connection * conn
Definition: adata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_sync_message_for_copy()

int imap_sync_message_for_copy ( struct Mailbox m,
struct Email e,
struct Buffer cmd,
enum QuadOption err_continue 
)

Update server to reflect the flags of a single message.

Parameters
[in]mMailbox
[in]eEmail
[in]cmdBuffer for the command string
[out]err_continueDid the user force a continue?
Return values
0Success
-1Failure

Update the IMAP server to reflect the flags for a single message before performing a "UID COPY".

Note
This does not sync the "deleted" flag state, because it is not desirable to propagate that flag into the copy.

Definition at line 1004 of file imap.c.

1006 {
1007  struct ImapAccountData *adata = imap_adata_get(m);
1008  if (!adata || (adata->mailbox != m))
1009  return -1;
1010 
1011  char flags[1024];
1012  char *tags = NULL;
1013  char uid[11];
1014 
1015  if (!compare_flags_for_copy(e))
1016  {
1017  if (e->deleted == imap_edata_get(e)->deleted)
1018  e->changed = false;
1019  return 0;
1020  }
1021 
1022  snprintf(uid, sizeof(uid), "%u", imap_edata_get(e)->uid);
1023  mutt_buffer_reset(cmd);
1024  mutt_buffer_addstr(cmd, "UID STORE ");
1025  mutt_buffer_addstr(cmd, uid);
1026 
1027  flags[0] = '\0';
1028 
1029  set_flag(m, MUTT_ACL_SEEN, e->read, "\\Seen ", flags, sizeof(flags));
1030  set_flag(m, MUTT_ACL_WRITE, e->old, "Old ", flags, sizeof(flags));
1031  set_flag(m, MUTT_ACL_WRITE, e->flagged, "\\Flagged ", flags, sizeof(flags));
1032  set_flag(m, MUTT_ACL_WRITE, e->replied, "\\Answered ", flags, sizeof(flags));
1033  set_flag(m, MUTT_ACL_DELETE, imap_edata_get(e)->deleted, "\\Deleted ", flags,
1034  sizeof(flags));
1035 
1036  if (m->rights & MUTT_ACL_WRITE)
1037  {
1038  /* restore system flags */
1039  if (imap_edata_get(e)->flags_system)
1040  mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_system);
1041  /* set custom flags */
1042  tags = driver_tags_get_with_hidden(&e->tags);
1043  if (tags)
1044  {
1045  mutt_str_cat(flags, sizeof(flags), tags);
1046  FREE(&tags);
1047  }
1048  }
1049 
1051 
1052  /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
1053  * explicitly revoke all system flags (if we have permission) */
1054  if (*flags == '\0')
1055  {
1056  set_flag(m, MUTT_ACL_SEEN, true, "\\Seen ", flags, sizeof(flags));
1057  set_flag(m, MUTT_ACL_WRITE, true, "Old ", flags, sizeof(flags));
1058  set_flag(m, MUTT_ACL_WRITE, true, "\\Flagged ", flags, sizeof(flags));
1059  set_flag(m, MUTT_ACL_WRITE, true, "\\Answered ", flags, sizeof(flags));
1060  set_flag(m, MUTT_ACL_DELETE, !imap_edata_get(e)->deleted, "\\Deleted ",
1061  flags, sizeof(flags));
1062 
1063  /* erase custom flags */
1064  if ((m->rights & MUTT_ACL_WRITE) && imap_edata_get(e)->flags_remote)
1065  mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_remote);
1066 
1068 
1069  mutt_buffer_addstr(cmd, " -FLAGS.SILENT (");
1070  }
1071  else
1072  mutt_buffer_addstr(cmd, " FLAGS.SILENT (");
1073 
1074  mutt_buffer_addstr(cmd, flags);
1075  mutt_buffer_addstr(cmd, ")");
1076 
1077  /* after all this it's still possible to have no flags, if you
1078  * have no ACL rights */
1079  if (*flags && (imap_exec(adata, cmd->data, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS) &&
1080  err_continue && (*err_continue != MUTT_YES))
1081  {
1082  *err_continue = imap_continue("imap_sync_message: STORE failed", adata->buf);
1083  if (*err_continue != MUTT_YES)
1084  return -1;
1085  }
1086 
1087  /* server have now the updated flags */
1088  FREE(&imap_edata_get(e)->flags_remote);
1090 
1091  if (e->deleted == imap_edata_get(e)->deleted)
1092  e->changed = false;
1093 
1094  return 0;
1095 }
enum QuadOption imap_continue(const char *msg, const char *resp)
display a message and ask the user if they want to go on
Definition: util.c:654
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
static void set_flag(struct Mailbox *m, AclFlags aclflag, bool flag, const char *str, char *flags, size_t flsize)
append str to flags if we currently have permission according to aclflag
Definition: imap.c:176
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
bool changed
Email has been edited.
Definition: email.h:48
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:64
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
Imap command executed or queued successfully.
Definition: private.h:84
bool read
Email is read.
Definition: email.h:51
bool old
Email is seen, but unread.
Definition: email.h:50
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
struct TagList tags
For drivers that support server tagging.
Definition: email.h:109
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition: command.c:1250
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
char * flags_remote
Definition: edata.h:48
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:733
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * data
Pointer to data.
Definition: buffer.h:35
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:73
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:385
IMAP-specific Account data -.
Definition: adata.h:39
char * driver_tags_get_with_hidden(struct TagList *list)
Get tags with hiddens.
Definition: tags.c:158
static bool compare_flags_for_copy(struct Email *e)
Compare local flags against the server.
Definition: imap.c:299
bool flagged
Marked important?
Definition: email.h:43
char * buf
Definition: adata.h:59
bool deleted
Email is deleted.
Definition: email.h:45
bool replied
Email has been replied to.
Definition: email.h:54
#define FREE(x)
Definition: memory.h:40
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_has_flag()

bool imap_has_flag ( struct ListHead *  flag_list,
const char *  flag 
)

Does the flag exist in the list.

Parameters
flag_listList of server flags
flagFlag to find
Return values
trueFlag exists

Do a caseless comparison of the flag against a flag list, return true if found or flag list has '*'. Note that "flag" might contain additional whitespace at the end, so we really need to compare up to the length of each element in "flag_list".

Definition at line 878 of file imap.c.

879 {
880  if (STAILQ_EMPTY(flag_list))
881  return false;
882 
883  const size_t flaglen = mutt_str_len(flag);
884  struct ListNode *np = NULL;
885  STAILQ_FOREACH(np, flag_list, entries)
886  {
887  const size_t nplen = strlen(np->data);
888  if ((flaglen >= nplen) && ((flag[nplen] == '\0') || (flag[nplen] == ' ')) &&
889  mutt_istrn_equal(np->data, flag, nplen))
890  {
891  return true;
892  }
893 
894  if (mutt_str_equal(np->data, "\\*"))
895  return true;
896  }
897 
898  return false;
899 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:621
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
char * data
String.
Definition: list.h:36
#define STAILQ_EMPTY(head)
Definition: queue.h:348
A List node for strings.
Definition: list.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_adata_find()

int imap_adata_find ( const char *  path,
struct ImapAccountData **  adata,
struct ImapMboxData **  mdata 
)

Find the Account data for this path.

Parameters
pathPath to search for
adataImap Account data
mdataImap Mailbox data
Return values
0Success
-1Failure

Definition at line 72 of file util.c.

74 {
75  struct ConnAccount cac = { { 0 } };
76  struct ImapAccountData *tmp_adata = NULL;
77  char tmp[1024];
78 
79  if (imap_parse_path(path, &cac, tmp, sizeof(tmp)) < 0)
80  return -1;
81 
82  struct Account *np = NULL;
83  TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
84  {
85  if (np->type != MUTT_IMAP)
86  continue;
87 
88  tmp_adata = np->adata;
89  if (!tmp_adata)
90  continue;
91  if (imap_account_match(&tmp_adata->conn->account, &cac))
92  {
93  *mdata = imap_mdata_new(tmp_adata, tmp);
94  *adata = tmp_adata;
95  return 0;
96  }
97  }
98  mutt_debug(LL_DEBUG3, "no ImapAccountData found\n");
99  return -1;
100 }
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
A group of associated Mailboxes.
Definition: account.h:36
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
struct ImapMboxData * imap_mdata_new(struct ImapAccountData *adata, const char *name)
Allocate and initialise a new ImapMboxData structure.
Definition: mdata.c:72
Container for Accounts, Notifications.
Definition: neomutt.h:36
int imap_parse_path(const char *path, struct ConnAccount *cac, char *mailbox, size_t mailboxlen)
Parse an IMAP mailbox name into ConnAccount, name.
Definition: util.c:483
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1049
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Login details for a remote server.
Definition: connaccount.h:51
IMAP-specific Account data -.
Definition: adata.h:39
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
Log at debug level 3.
Definition: logging.h:42
struct Connection * conn
Definition: adata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_authenticate()

int imap_authenticate ( struct ImapAccountData adata)

Authenticate to an IMAP server.

Parameters
adataImap Account data
Return values
numResult, e.g. IMAP_AUTH_SUCCESS

Attempt to authenticate using either user-specified authentication method if specified, or any.

Definition at line 107 of file auth.c.

108 {
109  int rc = IMAP_AUTH_FAILURE;
110 
111  const struct Slist *c_imap_authenticators =
112  cs_subset_slist(NeoMutt->sub, "imap_authenticators");
113  if (c_imap_authenticators && (c_imap_authenticators->count > 0))
114  {
115  mutt_debug(LL_DEBUG2, "Trying user-defined imap_authenticators\n");
116 
117  /* Try user-specified list of authentication methods */
118  struct ListNode *np = NULL;
119  STAILQ_FOREACH(np, &c_imap_authenticators->head, entries)
120  {
121  mutt_debug(LL_DEBUG2, "Trying method %s\n", np->data);
122 
123  for (size_t i = 0; i < mutt_array_size(imap_authenticators); i++)
124  {
125  const struct ImapAuth *auth = &imap_authenticators[i];
126  if (!auth->method || mutt_istr_equal(auth->method, np->data))
127  {
128  rc = auth->authenticate(adata, np->data);
129  if (rc == IMAP_AUTH_SUCCESS)
130  {
131  return rc;
132  }
133  }
134  }
135  }
136  }
137  else
138  {
139  /* Fall back to default: any authenticator */
140  mutt_debug(LL_DEBUG2, "Trying pre-defined imap_authenticators\n");
141 
142  for (size_t i = 0; i < mutt_array_size(imap_authenticators); i++)
143  {
144  rc = imap_authenticators[i].authenticate(adata, NULL);
145  if (rc == IMAP_AUTH_SUCCESS)
146  return rc;
147  }
148  }
149 
150  mutt_error(_("No authenticators available or wrong credentials"));
151  return rc;
152 }
const char * method
Name of authentication method supported, NULL means variable.
Definition: auth.c:52
#define mutt_error(...)
Definition: logging.h:88
#define _(a)
Definition: message.h:28
String list.
Definition: slist.h:46
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define mutt_array_size(x)
Definition: memory.h:33
Log at debug level 2.
Definition: logging.h:41
struct ListHead head
Definition: slist.h:48
Authentication failed.
Definition: auth.h:40
static const struct ImapAuth imap_authenticators[]
Accepted authentication methods.
Definition: auth.c:59
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
size_t count
Definition: slist.h:49
enum ImapAuthRes(* authenticate)(struct ImapAccountData *adata, const char *method)
Authenticate an IMAP connection.
Definition: auth.c:50
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
IMAP authentication multiplexor.
Definition: auth.c:42
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Definition: helpers.c:268
char * data
String.
Definition: list.h:36
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A List node for strings.
Definition: list.h:34
Authentication successful.
Definition: auth.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_cmd_start()

int imap_cmd_start ( struct ImapAccountData adata,
const char *  cmdstr 
)

Given an IMAP command, send it to the server.

Parameters
adataImap Account data
cmdstrCommand string to send
Return values
0Success
<0Failure, e.g. IMAP_RES_BAD

If cmdstr is NULL, sends queued commands.

Definition at line 1065 of file command.c.

1066 {
1067  return cmd_start(adata, cmdstr, IMAP_CMD_NO_FLAGS);
1068 }
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:73
static int cmd_start(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Start a new IMAP command.
Definition: command.c:200
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_cmd_step()

int imap_cmd_step ( struct ImapAccountData adata)

Reads server responses from an IMAP command.

Parameters
adataImap Account data
Return values
0Success
<0Failure, e.g. IMAP_RES_BAD

detects tagged completion response, handles untagged messages, can read arbitrarily large strings (using malloc, so don't make it too large!).

Definition at line 1079 of file command.c.

1080 {
1081  if (!adata)
1082  return -1;
1083 
1084  size_t len = 0;
1085  int c;
1086  int rc;
1087  int stillrunning = 0;
1088  struct ImapCommand *cmd = NULL;
1089 
1090  if (adata->status == IMAP_FATAL)
1091  {
1092  cmd_handle_fatal(adata);
1093  return IMAP_RES_BAD;
1094  }
1095 
1096  /* read into buffer, expanding buffer as necessary until we have a full
1097  * line */
1098  do
1099  {
1100  if (len == adata->blen)
1101  {
1102  mutt_mem_realloc(&adata->buf, adata->blen + IMAP_CMD_BUFSIZE);
1103  adata->blen = adata->blen + IMAP_CMD_BUFSIZE;
1104  mutt_debug(LL_DEBUG3, "grew buffer to %lu bytes\n", adata->blen);
1105  }
1106 
1107  /* back up over '\0' */
1108  if (len)
1109  len--;
1110  c = mutt_socket_readln_d(adata->buf + len, adata->blen - len, adata->conn, MUTT_SOCK_LOG_FULL);
1111  if (c <= 0)
1112  {
1113  mutt_debug(LL_DEBUG1, "Error reading server response\n");
1114  cmd_handle_fatal(adata);
1115  return IMAP_RES_BAD;
1116  }
1117 
1118  len += c;
1119  }
1120  /* if we've read all the way to the end of the buffer, we haven't read a
1121  * full line (mutt_socket_readln strips the \r, so we always have at least
1122  * one character free when we've read a full line) */
1123  while (len == adata->blen);
1124 
1125  /* don't let one large string make cmd->buf hog memory forever */
1126  if ((adata->blen > IMAP_CMD_BUFSIZE) && (len <= IMAP_CMD_BUFSIZE))
1127  {
1129  adata->blen = IMAP_CMD_BUFSIZE;
1130  mutt_debug(LL_DEBUG3, "shrank buffer to %lu bytes\n", adata->blen);
1131  }
1132 
1133  adata->lastread = mutt_date_epoch();
1134 
1135  /* handle untagged messages. The caller still gets its shot afterwards. */
1136  if ((mutt_str_startswith(adata->buf, "* ") ||
1137  mutt_str_startswith(imap_next_word(adata->buf), "OK [")) &&
1138  cmd_handle_untagged(adata))
1139  {
1140  return IMAP_RES_BAD;
1141  }
1142 
1143  /* server demands a continuation response from us */
1144  if (adata->buf[0] == '+')
1145  return IMAP_RES_RESPOND;
1146 
1147  /* Look for tagged command completions.
1148  *
1149  * Some response handlers can end up recursively calling
1150  * imap_cmd_step() and end up handling all tagged command
1151  * completions.
1152  * (e.g. FETCH->set_flag->set_header_color->~h pattern match.)
1153  *
1154  * Other callers don't even create an adata->cmds entry.
1155  *
1156  * For both these cases, we default to returning OK */
1157  rc = IMAP_RES_OK;
1158  c = adata->lastcmd;
1159  do
1160  {
1161  cmd = &adata->cmds[c];
1162  if (cmd->state == IMAP_RES_NEW)
1163  {
1164  if (mutt_str_startswith(adata->buf, cmd->seq))
1165  {
1166  if (!stillrunning)
1167  {
1168  /* first command in queue has finished - move queue pointer up */
1169  adata->lastcmd = (adata->lastcmd + 1) % adata->cmdslots;
1170  }
1171  cmd->state = cmd_status(adata->buf);
1172  rc = cmd->state;
1173  if (cmd->state == IMAP_RES_NO || cmd->state == IMAP_RES_BAD)
1174  {
1175  mutt_message(_("IMAP command failed: %s"), adata->buf);
1176  }
1177  }
1178  else
1179  stillrunning++;
1180  }
1181 
1182  c = (c + 1) % adata->cmdslots;
1183  } while (c != adata->nextcmd);
1184 
1185  if (stillrunning)
1186  rc = IMAP_RES_CONTINUE;
1187  else
1188  {
1189  mutt_debug(LL_DEBUG3, "IMAP queue drained\n");
1190  imap_cmd_finish(adata);
1191  }
1192 
1193  return rc;
1194 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
struct ImapCommand * cmds
Definition: adata.h:69
#define IMAP_RES_RESPOND
+
Definition: private.h:58
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:56
#define IMAP_RES_NEW
ImapCommand.state additions.
Definition: private.h:59
Unrecoverable error occurred.
Definition: private.h:97
int lastcmd
Definition: adata.h:72
#define _(a)
Definition: message.h:28
static void cmd_handle_fatal(struct ImapAccountData *adata)
When ImapAccountData is in fatal state, do what we can.
Definition: command.c:164
size_t blen
Definition: adata.h:60
#define MUTT_SOCK_LOG_FULL
Definition: mutt_socket.h:31
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:792
int nextcmd
Definition: adata.h:71
IMAP command structure.
Definition: private.h:159
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
int cmdslots
Definition: adata.h:70
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: adata.h:45
void imap_cmd_finish(struct ImapAccountData *adata)
Attempt to perform cleanup.
Definition: command.c:1316
#define IMAP_CMD_BUFSIZE
Definition: command.c:57
char seq[SEQ_LEN+1]
Command tag, e.g. &#39;a0001&#39;.
Definition: private.h:161
#define IMAP_RES_NO
<tag> NO ...
Definition: private.h:54
time_t lastread
last time we read a command for the server
Definition: adata.h:58
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
int state
Command state, e.g. IMAP_RES_NEW.
Definition: private.h:162
char * buf
Definition: adata.h:59
static int cmd_handle_untagged(struct ImapAccountData *adata)
fallback parser for otherwise unhandled messages
Definition: command.c:987
#define mutt_message(...)
Definition: logging.h:87
int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
Read a line from a socket.
Definition: socket.c:246
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:57
Log at debug level 3.
Definition: logging.h:42
struct Connection * conn
Definition: adata.h:41
#define IMAP_RES_BAD
<tag> BAD ...
Definition: private.h:55
static int cmd_status(const char *s)
parse response line for tagged OK/NO/BAD
Definition: command.c:236
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_cmd_finish()

void imap_cmd_finish ( struct ImapAccountData adata)

Attempt to perform cleanup.

Parameters
adataImap Account data

If a reopen is allowed, it attempts to perform cleanup (eg fetch new mail if detected, do expunge). Called automatically by imap_cmd_step(), but may be called at any time.

mdata->check_status is set and will be used later by imap_check_mailbox().

Definition at line 1316 of file command.c.

1317 {
1318  if (!adata)
1319  return;
1320 
1321  if (adata->status == IMAP_FATAL)
1322  {
1323  adata->closing = false;
1324  cmd_handle_fatal(adata);
1325  return;
1326  }
1327 
1328  if (!(adata->state >= IMAP_SELECTED) || (adata->mailbox && adata->closing))
1329  {
1330  adata->closing = false;
1331  return;
1332  }
1333 
1334  adata->closing = false;
1335 
1336  struct ImapMboxData *mdata = imap_mdata_get(adata->mailbox);
1337 
1338  if (mdata && mdata->reopen & IMAP_REOPEN_ALLOW)
1339  {
1340  // First remove expunged emails from the msn_index
1341  if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1342  {
1343  mutt_debug(LL_DEBUG2, "Expunging mailbox\n");
1344  imap_expunge_mailbox(adata->mailbox);
1345  /* Detect whether we've gotten unexpected EXPUNGE messages */
1346  if (!(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1349  }
1350 
1351  // Then add new emails to it
1352  if (mdata->reopen & IMAP_NEWMAIL_PENDING)
1353  {
1354  const size_t max_msn = imap_msn_highest(&mdata->msn);
1355  if (mdata->new_mail_count > max_msn)
1356  {
1357  if (!(mdata->reopen & IMAP_EXPUNGE_PENDING))
1359 
1360  mutt_debug(LL_DEBUG2, "Fetching new mails from %d to %d\n", max_msn + 1,
1361  mdata->new_mail_count);
1362  imap_read_headers(adata->mailbox, max_msn + 1, mdata->new_mail_count, false);
1363  }
1364  }
1365 
1366  // And to finish inform about MUTT_REOPEN if needed
1367  if (mdata->reopen & IMAP_EXPUNGE_PENDING && !(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1369 
1370  if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1372  }
1373 
1374  adata->status = 0;
1375 }
Unrecoverable error occurred.
Definition: private.h:97
void imap_expunge_mailbox(struct Mailbox *m)
Purge messages from the server.
Definition: imap.c:676
#define IMAP_REOPEN_ALLOW
Allow re-opening a folder upon expunge.
Definition: private.h:66
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: adata.h:44
ImapOpenFlags reopen
Flags, e.g. IMAP_REOPEN_ALLOW.
Definition: mdata.h:44
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
static void cmd_handle_fatal(struct ImapAccountData *adata)
When ImapAccountData is in fatal state, do what we can.
Definition: command.c:164
unsigned int new_mail_count
Set when EXISTS notifies of new mail.
Definition: mdata.h:46
Log at debug level 2.
Definition: logging.h:41
int imap_read_headers(struct Mailbox *m, unsigned int msn_begin, unsigned int msn_end, bool initial_download)
Read headers from the server.
Definition: message.c:1299
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:59
ImapOpenFlags check_status
Flags, e.g. IMAP_NEWMAIL_PENDING.
Definition: mdata.h:45
Mailbox is selected.
Definition: private.h:110
void * mdata
Driver specific data.
Definition: mailbox.h:136
bool closing
If true, we are waiting for CLOSE completion.
Definition: adata.h:43
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: adata.h:45
#define IMAP_EXPUNGE_EXPECTED
Messages will be expunged from the server.
Definition: private.h:67
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
size_t imap_msn_highest(const struct MSN *msn)
Return the highest MSN in use.
Definition: msn.c:68
IMAP-specific Mailbox data -.
Definition: mdata.h:38
#define IMAP_NEWMAIL_PENDING
New mail is waiting on the server.
Definition: private.h:69
#define IMAP_EXPUNGE_PENDING
Messages on the server have been expunged.
Definition: private.h:68
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_code()

bool imap_code ( const char *  s)

Was the command successful.

Parameters
sIMAP command status
Return values
1Command result was OK
0NO or BAD

Definition at line 1202 of file command.c.

1203 {
1204  return cmd_status(s) == IMAP_RES_OK;
1205 }
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:56
static int cmd_status(const char *s)
parse response line for tagged OK/NO/BAD
Definition: command.c:236
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_cmd_trailer()

const char* imap_cmd_trailer ( struct ImapAccountData adata)

Extra information after tagged command response if any.

Parameters
adataImap Account data
Return values
ptrExtra command information (pointer into adata->buf)
""Error (static string)

Definition at line 1213 of file command.c.

1214 {
1215  static const char *notrailer = "";
1216  const char *s = adata->buf;
1217 
1218  if (!s)
1219  {
1220  mutt_debug(LL_DEBUG2, "not a tagged response\n");
1221  return notrailer;
1222  }
1223 
1224  s = imap_next_word((char *) s);
1225  if (!s || (!mutt_istr_startswith(s, "OK") && !mutt_istr_startswith(s, "NO") &&
1226  !mutt_istr_startswith(s, "BAD")))
1227  {
1228  mutt_debug(LL_DEBUG2, "not a command completion: %s\n", adata->buf);
1229  return notrailer;
1230  }
1231 
1232  s = imap_next_word((char *) s);
1233  if (!s)
1234  return notrailer;
1235 
1236  return s;
1237 }
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:792
Log at debug level 2.
Definition: logging.h:41
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
char * buf
Definition: adata.h:59
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_exec()

int imap_exec ( struct ImapAccountData adata,
const char *  cmdstr,
ImapCmdFlags  flags 
)

Execute a command and wait for the response from the server.

Parameters
adataImap Account data
cmdstrCommand to execute
flagsFlags, see ImapCmdFlags
Return values
IMAP_EXEC_SUCCESSCommand successful or queued
IMAP_EXEC_ERRORCommand returned an error
IMAP_EXEC_FATALImap connection failure

Also, handle untagged responses.

Definition at line 1250 of file command.c.

1251 {
1252  int rc;
1253 
1254  if (flags & IMAP_CMD_SINGLE)
1255  {
1256  // Process any existing commands
1257  if (adata->nextcmd != adata->lastcmd)
1258  imap_exec(adata, NULL, IMAP_CMD_POLL);
1259  }
1260 
1261  rc = cmd_start(adata, cmdstr, flags);
1262  if (rc < 0)
1263  {
1264  cmd_handle_fatal(adata);
1265  return IMAP_EXEC_FATAL;
1266  }
1267 
1268  if (flags & IMAP_CMD_QUEUE)
1269  return IMAP_EXEC_SUCCESS;
1270 
1271  const short c_imap_poll_timeout =
1272  cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1273  if ((flags & IMAP_CMD_POLL) && (c_imap_poll_timeout > 0) &&
1274  ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1275  {
1276  mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1277  cmd_handle_fatal(adata);
1278  return IMAP_EXEC_FATAL;
1279  }
1280 
1281  /* Allow interruptions, particularly useful if there are network problems. */
1283  do
1284  {
1285  rc = imap_cmd_step(adata);
1286  // The queue is empty, so the single command has been processed
1287  if ((flags & IMAP_CMD_SINGLE) && (adata->nextcmd == adata->lastcmd))
1288  break;
1289  } while (rc == IMAP_RES_CONTINUE);
1290  mutt_sig_allow_interrupt(false);
1291 
1292  if (rc == IMAP_RES_NO)
1293  return IMAP_EXEC_ERROR;
1294  if (rc != IMAP_RES_OK)
1295  {
1296  if (adata->status != IMAP_FATAL)
1297  return IMAP_EXEC_ERROR;
1298 
1299  mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1300  return IMAP_EXEC_FATAL;
1301  }
1302 
1303  return IMAP_EXEC_SUCCESS;
1304 }
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:56
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1079
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
Imap connection failure.
Definition: private.h:86
#define mutt_error(...)
Definition: logging.h:88
Unrecoverable error occurred.
Definition: private.h:97
int lastcmd
Definition: adata.h:72
#define IMAP_CMD_POLL
Poll the tcp connection before running the imap command.
Definition: private.h:76
#define _(a)
Definition: message.h:28
static void cmd_handle_fatal(struct ImapAccountData *adata)
When ImapAccountData is in fatal state, do what we can.
Definition: command.c:164
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
Imap command executed or queued successfully.
Definition: private.h:84
char host[128]
Server to login to.
Definition: connaccount.h:53
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:192
int nextcmd
Definition: adata.h:71
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition: command.c:1250
struct ListHead flags
Definition: mdata.h:49
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: adata.h:45
#define IMAP_RES_NO
<tag> NO ...
Definition: private.h:54
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Imap command failure.
Definition: private.h:85
Log at debug level 1.
Definition: logging.h:40
char * buf
Definition: adata.h:59
static int cmd_start(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Start a new IMAP command.
Definition: command.c:200
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:75
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:57
#define IMAP_CMD_SINGLE
Run a single command.
Definition: private.h:77
struct Connection * conn
Definition: adata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_cmd_idle()

int imap_cmd_idle ( struct ImapAccountData adata)

Enter the IDLE state.

Parameters
adataImap Account data
Return values
0Success
<0Failure, e.g. IMAP_RES_BAD

Definition at line 1383 of file command.c.

1384 {
1385  int rc;
1386 
1387  if (cmd_start(adata, "IDLE", IMAP_CMD_POLL) < 0)
1388  {
1389  cmd_handle_fatal(adata);
1390  return -1;
1391  }
1392 
1393  const short c_imap_poll_timeout =
1394  cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1395  if ((c_imap_poll_timeout > 0) &&
1396  ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1397  {
1398  mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1399  cmd_handle_fatal(adata);
1400  return -1;
1401  }
1402 
1403  do
1404  {
1405  rc = imap_cmd_step(adata);
1406  } while (rc == IMAP_RES_CONTINUE);
1407 
1408  if (rc == IMAP_RES_RESPOND)
1409  {
1410  /* successfully entered IDLE state */
1411  adata->state = IMAP_IDLE;
1412  /* queue automatic exit when next command is issued */
1413  mutt_buffer_addstr(&adata->cmdbuf, "DONE\r\n");
1414  rc = IMAP_RES_OK;
1415  }
1416  if (rc != IMAP_RES_OK)
1417  {
1418  mutt_debug(LL_DEBUG1, "error starting IDLE\n");
1419  return -1;
1420  }
1421 
1422  return 0;
1423 }
#define IMAP_RES_RESPOND
+
Definition: private.h:58
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:56
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1079
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
#define mutt_error(...)
Definition: logging.h:88
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: adata.h:44
#define IMAP_CMD_POLL
Poll the tcp connection before running the imap command.
Definition: private.h:76
#define _(a)
Definition: message.h:28
static void cmd_handle_fatal(struct ImapAccountData *adata)
When ImapAccountData is in fatal state, do what we can.
Definition: command.c:164
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
char host[128]
Server to login to.
Definition: connaccount.h:53
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:192
struct Buffer cmdbuf
Definition: adata.h:73
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Connection is idle.
Definition: private.h:113
Log at debug level 1.
Definition: logging.h:40
static int cmd_start(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Start a new IMAP command.
Definition: command.c:200
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:57
struct Connection * conn
Definition: adata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_read_headers()

int imap_read_headers ( struct Mailbox m,
unsigned int  msn_begin,
unsigned int  msn_end,
bool  initial_download 
)

Read headers from the server.

Parameters
mImap Selected Mailbox
msn_beginFirst Message Sequence Number
msn_endLast Message Sequence Number
initial_downloadtrue, if this is the first opening of the mailbox
Return values
numLast MSN
-1Failure

Changed to read many headers instead of just one. It will return the msn of the last message read. It will return a value other than msn_end if mail comes in while downloading headers (in theory).

Definition at line 1299 of file message.c.

1301 {
1302  int oldmsgcount;
1303  unsigned int maxuid = 0;
1304  int retval = -1;
1305  bool evalhc = false;
1306 
1307 #ifdef USE_HCACHE
1308  void *uidvalidity = NULL;
1309  void *puid_next = NULL;
1310  unsigned int uid_next = 0;
1311  bool has_condstore = false;
1312  bool has_qresync = false;
1313  bool eval_condstore = false;
1314  bool eval_qresync = false;
1315  unsigned long long *pmodseq = NULL;
1316  unsigned long long hc_modseq = 0;
1317  char *uid_seqset = NULL;
1318 #endif /* USE_HCACHE */
1319 
1320  struct ImapAccountData *adata = imap_adata_get(m);
1321  struct ImapMboxData *mdata = imap_mdata_get(m);
1322  if (!adata || (adata->mailbox != m))
1323  return -1;
1324 
1325 #ifdef USE_HCACHE
1326 retry:
1327 #endif /* USE_HCACHE */
1328 
1329  /* make sure context has room to hold the mailbox */
1330  while (msn_end > m->email_max)
1331  mx_alloc_memory(m);
1332  imap_msn_reserve(&mdata->msn, msn_end);
1333  imap_alloc_uid_hash(adata, msn_end);
1334 
1335  oldmsgcount = m->msg_count;
1337  mdata->new_mail_count = 0;
1338 
1339 #ifdef USE_HCACHE
1340  imap_hcache_open(adata, mdata);
1341 
1342  if (mdata->hcache && initial_download)
1343  {
1344  size_t dlen = 0;
1345  uidvalidity = mutt_hcache_fetch_raw(mdata->hcache, "/UIDVALIDITY", 12, &dlen);
1346  puid_next = mutt_hcache_fetch_raw(mdata->hcache, "/UIDNEXT", 8, &dlen);
1347  if (puid_next)
1348  {
1349  uid_next = *(unsigned int *) puid_next;
1350  mutt_hcache_free_raw(mdata->hcache, &puid_next);
1351  }
1352 
1353  if (mdata->modseq)
1354  {
1355  const bool c_imap_condstore =
1356  cs_subset_bool(NeoMutt->sub, "imap_condstore");
1357  if ((adata->capabilities & IMAP_CAP_CONDSTORE) && c_imap_condstore)
1358  has_condstore = true;
1359 
1360  /* If IMAP_CAP_QRESYNC and ImapQResync then NeoMutt sends ENABLE QRESYNC.
1361  * If we receive an ENABLED response back, then adata->qresync is set. */
1362  if (adata->qresync)
1363  has_qresync = true;
1364  }
1365 
1366  if (uidvalidity && uid_next && (*(uint32_t *) uidvalidity == mdata->uidvalidity))
1367  {
1368  size_t dlen2 = 0;
1369  evalhc = true;
1370  pmodseq = mutt_hcache_fetch_raw(mdata->hcache, "/MODSEQ", 7, &dlen2);
1371  if (pmodseq)
1372  {
1373  hc_modseq = *pmodseq;
1374  mutt_hcache_free_raw(mdata->hcache, (void **) &pmodseq);
1375  }
1376  if (hc_modseq)
1377  {
1378  if (has_qresync)
1379  {
1380  uid_seqset = imap_hcache_get_uid_seqset(mdata);
1381  if (uid_seqset)
1382  eval_qresync = true;
1383  }
1384 
1385  if (!eval_qresync && has_condstore)
1386  eval_condstore = true;
1387  }
1388  }
1389  mutt_hcache_free_raw(mdata->hcache, &uidvalidity);
1390  }
1391  if (evalhc)
1392  {
1393  if (eval_qresync)
1394  {
1395  if (read_headers_qresync_eval_cache(adata, uid_seqset) < 0)
1396  goto bail;
1397  }
1398  else
1399  {
1400  if (read_headers_normal_eval_cache(adata, msn_end, uid_next, has_condstore || has_qresync,
1401  eval_condstore) < 0)
1402  goto bail;
1403  }
1404 
1405  if ((eval_condstore || eval_qresync) && (hc_modseq != mdata->modseq))
1406  {
1407  if (read_headers_condstore_qresync_updates(adata, msn_end, uid_next,
1408  hc_modseq, eval_qresync) < 0)
1409  {
1410  goto bail;
1411  }
1412  }
1413 
1414  /* Look for the first empty MSN and start there */
1415  while (msn_begin <= msn_end)
1416  {
1417  if (!imap_msn_get(&mdata->msn, msn_begin - 1))
1418  break;
1419  msn_begin++;
1420  }
1421  }
1422 #endif /* USE_HCACHE */
1423 
1424  if (read_headers_fetch_new(m, msn_begin, msn_end, evalhc, &maxuid, initial_download) < 0)
1425  goto bail;
1426 
1427 #ifdef USE_HCACHE
1428  if (eval_qresync && initial_download)
1429  {
1430  if (imap_verify_qresync(m) != 0)
1431  {
1432  eval_qresync = false;
1433  eval_condstore = false;
1434  evalhc = false;
1435  hc_modseq = 0;
1436  maxuid = 0;
1437  FREE(&uid_seqset);
1438  uidvalidity = NULL;
1439  uid_next = 0;
1440 
1441  goto retry;
1442  }
1443  }
1444 #endif /* USE_HCACHE */
1445 
1446  if (maxuid && (mdata->uid_next < maxuid + 1))
1447  mdata->uid_next = maxuid + 1;
1448 
1449 #ifdef USE_HCACHE
1450  mutt_hcache_store_raw(mdata->hcache, "/UIDVALIDITY", 12, &mdata->uidvalidity,
1451  sizeof(mdata->uidvalidity));
1452  if (maxuid && (mdata->uid_next < maxuid + 1))
1453  {
1454  mutt_debug(LL_DEBUG2, "Overriding UIDNEXT: %u -> %u\n", mdata->uid_next, maxuid + 1);
1455  mdata->uid_next = maxuid + 1;
1456  }
1457  if (mdata->uid_next > 1)
1458  {
1459  mutt_hcache_store_raw(mdata->hcache, "/UIDNEXT", 8, &mdata->uid_next,
1460  sizeof(mdata->uid_next));
1461  }
1462 
1463  /* We currently only sync CONDSTORE and QRESYNC on the initial download.
1464  * To do it more often, we'll need to deal with flag updates combined with
1465  * unsync'ed local flag changes. We'll also need to properly sync flags to
1466  * the header cache on close. I'm not sure it's worth the added complexity. */
1467  if (initial_download)
1468  {
1469  if (has_condstore || has_qresync)
1470  {
1471  mutt_hcache_store_raw(mdata->hcache, "/MODSEQ", 7, &mdata->modseq,
1472  sizeof(mdata->modseq));
1473  }
1474  else
1475  mutt_hcache_delete_record(mdata->hcache, "/MODSEQ", 7);
1476 
1477  if (has_qresync)
1479  else
1481  }
1482 #endif /* USE_HCACHE */
1483 
1484  if (m->msg_count > oldmsgcount)
1485  {
1486  /* TODO: it's not clear to me why we are calling mx_alloc_memory
1487  * yet again. */
1488  mx_alloc_memory(m);
1489  }
1490 
1491  mdata->reopen |= IMAP_REOPEN_ALLOW;
1492 
1493  retval = msn_end;
1494 
1495 bail:
1496 #ifdef USE_HCACHE
1497  imap_hcache_close(mdata);
1498  FREE(&uid_seqset);
1499 #endif /* USE_HCACHE */
1500 
1501  return retval;
1502 }
int msg_count
Total number of messages.
Definition: mailbox.h:91
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
static int read_headers_normal_eval_cache(struct ImapAccountData *adata, unsigned int msn_end, unsigned int uid_next, bool store_flag_updates, bool eval_condstore)
Retrieve data from the header cache.
Definition: message.c:660
uint32_t uidvalidity
Definition: mdata.h:50
#define IMAP_REOPEN_ALLOW
Allow re-opening a folder upon expunge.
Definition: private.h:66
int imap_hcache_store_uid_seqset(struct ImapMboxData *mdata)
Store a UID Sequence Set in the header cache.
Definition: util.c:416
ImapOpenFlags reopen
Flags, e.g. IMAP_REOPEN_ALLOW.
Definition: mdata.h:44
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
Definition: mx.c:1212
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
struct HeaderCache * hcache
Definition: mdata.h:62
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:541
char * imap_hcache_get_uid_seqset(struct ImapMboxData *mdata)
Get a UID Sequence Set from the header cache.
Definition: util.c:452
Container for Accounts, Notifications.
Definition: neomutt.h:36
unsigned int new_mail_count
Set when EXISTS notifies of new mail.
Definition: mdata.h:46
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:340
Log at debug level 2.
Definition: logging.h:41
struct Email * imap_msn_get(const struct MSN *msn, size_t idx)
Return the Email associated with an msn.
Definition: msn.c:79
static void imap_alloc_uid_hash(struct ImapAccountData *adata, unsigned int msn_count)
Create a Hash Table for the UIDs.
Definition: message.c:509
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:59
void * mdata
Driver specific data.
Definition: mailbox.h:136
unsigned long long modseq
Definition: mdata.h:52
void imap_msn_reserve(struct MSN *msn, size_t num)
Create / reallocate the cache.
Definition: msn.c:40
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:637
bool qresync
true, if QRESYNC is successfully ENABLE&#39;d
Definition: adata.h:63
ImapCapFlags capabilities
Definition: adata.h:55
static int read_headers_fetch_new(struct Mailbox *m, unsigned int msn_begin, unsigned int msn_end, bool evalhc, unsigned int *maxuid, bool initial_download)
Retrieve new messages from the server.
Definition: message.c:1050
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *uid_seqset)
Retrieve data from the header cache.
Definition: message.c:806
IMAP-specific Account data -.
Definition: adata.h:39
unsigned int uid_next
Definition: mdata.h:51
static int read_headers_condstore_qresync_updates(struct ImapAccountData *adata, unsigned int msn_end, unsigned int uid_next, unsigned long long hc_modseq, bool eval_qresync)
Retrieve updates from the server.
Definition: message.c:878
#define IMAP_CAP_CONDSTORE
RFC7162.
Definition: private.h:137
IMAP-specific Mailbox data -.
Definition: mdata.h:38
#define IMAP_NEWMAIL_PENDING
New mail is waiting on the server.
Definition: private.h:69
#define FREE(x)
Definition: memory.h:40
static int imap_verify_qresync(struct Mailbox *m)
Check to see if QRESYNC got jumbled.
Definition: message.c:977
int mutt_hcache_store_raw(struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
store a key / data pair
Definition: hcache.c:615
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int imap_hcache_clear_uid_seqset(struct ImapMboxData *mdata)
Delete a UID Sequence Set from the header cache.
Definition: util.c:438
void * mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message&#39;s header from the cache.
Definition: hcache.c:521
void imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
Open a header cache.
Definition: util.c:297
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_set_flags()

char* imap_set_flags ( struct Mailbox m,
struct Email e,
char *  s,
bool *  server_changes 
)

fill the message header according to the server flags

Parameters
[in]mImap Selected Mailbox
[in]eEmail
[in]sCommand string
[out]server_changesSet to true if the flags have changed
Return values
ptrThe end of flags string
NULLFailure

Expects a flags line of the form "FLAGS (flag flag ...)"

imap_set_flags: fill out the message header according to the flags from the server. Expects a flags line of the form "FLAGS (flag flag ...)"

Sets server_changes to 1 if a change to a flag is made, or in the case of e->changed, if a change to a flag would have been made.

Definition at line 1870 of file message.c.

1871 {
1872  struct ImapAccountData *adata = imap_adata_get(m);
1873  if (!adata || (adata->mailbox != m))
1874  return NULL;
1875 
1876  struct ImapHeader newh = { 0 };
1877  struct ImapEmailData old_edata = { 0 };
1878  int local_changes = e->changed;
1879 
1880  struct ImapEmailData *edata = e->edata;
1881  newh.edata = edata;
1882 
1883  mutt_debug(LL_DEBUG2, "parsing FLAGS\n");
1884  s = msg_parse_flags(&newh, s);
1885  if (!s)
1886  return NULL;
1887 
1888  /* Update tags system */
1889  /* We take a copy of the tags so we can split the string */
1890  char *tags_copy = mutt_str_dup(edata->flags_remote);
1891  driver_tags_replace(&e->tags, tags_copy);
1892  FREE(&tags_copy);
1893 
1894  /* YAUH (yet another ugly hack): temporarily set context to
1895  * read-write even if it's read-only, so *server* updates of
1896  * flags can be processed by mutt_set_flag. mailbox->changed must
1897  * be restored afterwards */
1898  bool readonly = m->readonly;
1899  m->readonly = false;
1900 
1901  /* This is redundant with the following two checks. Removing:
1902  * mutt_set_flag (m, e, MUTT_NEW, !(edata->read || edata->old)); */
1903  set_changed_flag(m, e, local_changes, server_changes, MUTT_OLD, old_edata.old,
1904  edata->old, e->old);
1905  set_changed_flag(m, e, local_changes, server_changes, MUTT_READ,
1906  old_edata.read, edata->read, e->read);
1907  set_changed_flag(m, e, local_changes, server_changes, MUTT_DELETE,
1908  old_edata.deleted, edata->deleted, e->deleted);
1909  set_changed_flag(m, e, local_changes, server_changes, MUTT_FLAG,
1910  old_edata.flagged, edata->flagged, e->flagged);
1911  set_changed_flag(m, e, local_changes, server_changes, MUTT_REPLIED,
1912  old_edata.replied, edata->replied, e->replied);
1913 
1914  /* this message is now definitively *not* changed (mutt_set_flag
1915  * marks things changed as a side-effect) */
1916  if (local_changes == 0)
1917  e->changed = false;
1918  m->changed &= !readonly;
1919  m->readonly = readonly;
1920 
1921  return s;
1922 }
Flagged messages.
Definition: mutt.h:98
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
bool changed
Email has been edited.
Definition: email.h:48
Messages that have been replied to.
Definition: mutt.h:91
bool flagged
Definition: edata.h:39
bool deleted
Definition: edata.h:38
bool read
Email is read.
Definition: email.h:51
Log at debug level 2.
Definition: logging.h:41
bool old
Email is seen, but unread.
Definition: email.h:50
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
static void set_changed_flag(struct Mailbox *m, struct Email *e, int local_changes, bool *server_changes, enum MessageType flag_name, bool old_hd_flag, bool new_hd_flag, bool h_flag)
Have the flags of an email changed.
Definition: message.c:620
struct TagList tags
For drivers that support server tagging.
Definition: email.h:109
char * flags_remote
Definition: edata.h:48
Old messages.
Definition: mutt.h:90
Messages to be deleted.
Definition: mutt.h:94
IMAP-specific header.
Definition: message.h:32
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
Messages that have been read.
Definition: mutt.h:92
bool replied
Definition: edata.h:40
bool old
Definition: edata.h:37
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
IMAP-specific Account data -.
Definition: adata.h:39
bool flagged
Marked important?
Definition: email.h:43
bool deleted
Email is deleted.
Definition: email.h:45
void * edata
Driver-specific data.
Definition: email.h:111
bool replied
Email has been replied to.
Definition: email.h:54
#define FREE(x)
Definition: memory.h:40
bool read
Definition: edata.h:36
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
IMAP-specific Email data -.
Definition: edata.h:33
bool driver_tags_replace(struct TagList *head, char *tags)
Replace all tags.
Definition: tags.c:186
static char * msg_parse_flags(struct ImapHeader *h, char *s)
read a FLAGS token into an ImapHeader
Definition: message.c:191
struct ImapEmailData * edata
Definition: message.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_cache_del()

int imap_cache_del ( struct Mailbox m,
struct Email e 
)

Delete an email from the body cache.

Parameters
mSelected Imap Mailbox
eEmail
Return values
0Success
-1Failure

Definition at line 1819 of file message.c.

1820 {
1821  struct ImapAccountData *adata = imap_adata_get(m);
1822  struct ImapMboxData *mdata = imap_mdata_get(m);
1823 
1824  if (!e || !adata || (adata->mailbox != m))
1825  return -1;
1826 
1827  mdata->bcache = msg_cache_open(m);
1828  char id[64];
1829  snprintf(id, sizeof(id), "%u-%u", mdata->uidvalidity, imap_edata_get(e)->uid);
1830  return mutt_bcache_del(mdata->bcache, id);
1831 }
uint32_t uidvalidity
Definition: mdata.h:50
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:64
struct BodyCache * bcache
Definition: mdata.h:60
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:59
void * mdata
Driver specific data.
Definition: mailbox.h:136
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
static struct BodyCache * msg_cache_open(struct Mailbox *m)
Open a message cache.
Definition: message.c:79
int mutt_bcache_del(struct BodyCache *bcache, const char *id)
Delete a file from the Body Cache.
Definition: bcache.c:264
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
IMAP-specific Account data -.
Definition: adata.h:39
IMAP-specific Mailbox data -.
Definition: mdata.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_cache_clean()

int imap_cache_clean ( struct Mailbox m)

Delete all the entries in the message cache.

Parameters
mSelectedImap Mailbox
Return values
0Always

Definition at line 1838 of file message.c.

1839 {
1840  struct ImapAccountData *adata = imap_adata_get(m);
1841  struct ImapMboxData *mdata = imap_mdata_get(m);
1842 
1843  if (!adata || (adata->mailbox != m))
1844  return -1;
1845 
1846  mdata->bcache = msg_cache_open(m);
1847  mutt_bcache_list(mdata->bcache, msg_cache_clean_cb, mdata);
1848 
1849  return 0;
1850 }
static int msg_cache_clean_cb(const char *id, struct BodyCache *bcache, void *data)
Delete an entry from the message cache - Implements bcache_list_t.
Definition: message.c:168
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
Definition: bcache.c:329
struct BodyCache * bcache
Definition: mdata.h:60
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:59
void * mdata
Driver specific data.
Definition: mailbox.h:136
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
static struct BodyCache * msg_cache_open(struct Mailbox *m)
Open a message cache.
Definition: message.c:79
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
IMAP-specific Account data -.
Definition: adata.h:39
IMAP-specific Mailbox data -.
Definition: mdata.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_append_message()

int imap_append_message ( struct Mailbox m,
struct Message msg 
)

Write an email back to the server.

Parameters
mMailbox
msgMessage to save
Return values
0Success
-1Failure

Definition at line 1511 of file message.c.

1512 {
1513  if (!m || !msg)
1514  return -1;
1515 
1516  FILE *fp = NULL;
1517  char buf[1024 * 2];
1518  char internaldate[IMAP_DATELEN];
1519  char imap_flags[128];
1520  size_t len;
1521  struct Progress *progress = NULL;
1522  size_t sent;
1523  int c, last;
1524  int rc;
1525 
1526  struct ImapAccountData *adata = imap_adata_get(m);
1527  struct ImapMboxData *mdata = imap_mdata_get(m);
1528 
1529  fp = fopen(msg->path, "r");
1530  if (!fp)
1531  {
1532  mutt_perror(msg->path);
1533  goto fail;
1534  }
1535 
1536  /* currently we set the \Seen flag on all messages, but probably we
1537  * should scan the message Status header for flag info. Since we're
1538  * already rereading the whole file for length it isn't any more
1539  * expensive (it'd be nice if we had the file size passed in already
1540  * by the code that writes the file, but that's a lot of changes.
1541  * Ideally we'd have an Email structure with flag info here... */
1542  for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c)
1543  {
1544  if ((c == '\n') && (last != '\r'))
1545  len++;
1546 
1547  len++;
1548  }
1549  rewind(fp);
1550 
1551  if (m->verbose)
1552  progress = progress_new(_("Uploading message..."), MUTT_PROGRESS_NET, len);
1553 
1554  mutt_date_make_imap(internaldate, sizeof(internaldate), msg->received);
1555 
1556  imap_flags[0] = '\0';
1557  imap_flags[1] = '\0';
1558 
1559  if (msg->flags.read)
1560  mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Seen");
1561  if (msg->flags.replied)
1562  mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Answered");
1563  if (msg->flags.flagged)
1564  mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Flagged");
1565  if (msg->flags.draft)
1566  mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Draft");
1567 
1568  snprintf(buf, sizeof(buf), "APPEND %s (%s) \"%s\" {%lu}", mdata->munge_name,
1569  imap_flags + 1, internaldate, (unsigned long) len);
1570 
1571  imap_cmd_start(adata, buf);
1572 
1573  do
1574  {
1575  rc = imap_cmd_step(adata);
1576  } while (rc == IMAP_RES_CONTINUE);
1577 
1578  if (rc != IMAP_RES_RESPOND)
1579  goto cmd_step_fail;
1580 
1581  for (last = EOF, sent = len = 0; (c = fgetc(fp)) != EOF; last = c)
1582  {
1583  if ((c == '\n') && (last != '\r'))
1584  buf[len++] = '\r';
1585 
1586  buf[len++] = c;
1587 
1588  if (len > sizeof(buf) - 3)
1589  {
1590  sent += len;
1591  if (flush_buffer(buf, &len, adata->conn) < 0)
1592  goto fail;
1593  if (m->verbose)
1594  progress_update(progress, sent, -1);
1595  }
1596  }
1597 
1598  if (len)
1599  if (flush_buffer(buf, &len, adata->conn) < 0)
1600  goto fail;
1601 
1602  if (mutt_socket_send(adata->conn, "\r\n") < 0)
1603  goto fail;
1604  mutt_file_fclose(&fp);
1605 
1606  do
1607  {
1608  rc = imap_cmd_step(adata);
1609  } while (rc == IMAP_RES_CONTINUE);
1610 
1611  if (rc != IMAP_RES_OK)
1612  goto cmd_step_fail;
1613 
1614  progress_free(&progress);
1615  return 0;
1616 
1617 cmd_step_fail:
1618  mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1619  if (rc != IMAP_RES_BAD)
1620  {
1621  char *pc = imap_next_word(adata->buf); /* skip sequence number or token */
1622  pc = imap_next_word(pc); /* skip response code */
1623  if (*pc != '\0')
1624  mutt_error("%s", pc);
1625  }
1626 
1627 fail:
1628  mutt_file_fclose(&fp);
1629  progress_free(&progress);
1630  return -1;
1631 }
#define IMAP_RES_RESPOND
+
Definition: private.h:58
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:56
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1079
#define mutt_socket_send(conn, buf)
Definition: mutt_socket.h:37
#define mutt_error(...)
Definition: logging.h:88
bool replied
Definition: mxapi.h:51
#define _(a)
Definition: message.h:28
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1065
#define mutt_perror(...)
Definition: logging.h:89
A Progress Bar.
Definition: progress.c:47
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:792
static int flush_buffer(char *buf, size_t *len, struct Connection *conn)
Write data to a connection.
Definition: message.c:469
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:59
void * mdata
Driver specific data.
Definition: mailbox.h:136
bool flagged
Definition: mxapi.h:50
struct Message::@1 flags
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
bool verbose
Display status messages?
Definition: mailbox.h:118
bool draft
Definition: mxapi.h:52
Progress tracks bytes, according to $net_inc
Definition: lib.h:48
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:228
void progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:175
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:385
IMAP-specific Account data -.
Definition: adata.h:39
Log at debug level 1.
Definition: logging.h:40
IMAP-specific Mailbox data -.
Definition: mdata.h:38
char * buf
Definition: adata.h:59
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:246
int mutt_date_make_imap(char *buf, size_t buflen, time_t timestamp)
Format date in IMAP style: DD-MMM-YYYY HH:MM:SS +ZZzz.
Definition: date.c:557
time_t received
the time at which this message was received
Definition: mxapi.h:54
#define IMAP_DATELEN
Definition: private.h:90
bool read
Definition: mxapi.h:49
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:57
char * munge_name
Munged version of the mailbox name.
Definition: mdata.h:41
char * path
path to temp file
Definition: mxapi.h:44
struct Connection * conn
Definition: adata.h:41
#define IMAP_RES_BAD
<tag> BAD ...
Definition: private.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_open()

void imap_hcache_open ( struct ImapAccountData adata,
struct ImapMboxData mdata 
)

Open a header cache.

Parameters
adataImap Account data
mdataImap Mailbox data

Definition at line 297 of file util.c.

298 {
299  if (!adata || !mdata)
300  return;
301 
302  if (mdata->hcache)
303  return;
304 
305  struct HeaderCache *hc = NULL;
306  struct Buffer *mbox = mutt_buffer_pool_get();
307  struct Buffer *cachepath = mutt_buffer_pool_get();
308 
309  imap_cachepath(adata->delim, mdata->name, mbox);
310 
311  if (strstr(mutt_buffer_string(mbox), "/../") ||
312  mutt_str_equal(mutt_buffer_string(mbox), "..") ||
313  mutt_strn_equal(mutt_buffer_string(mbox), "../", 3))
314  {
315  goto cleanup;
316  }
317  size_t len = mutt_buffer_len(mbox);
318  if ((len > 3) && (strcmp(mutt_buffer_string(mbox) + len - 3, "/..") == 0))
319  goto cleanup;
320 
321  struct Url url = { 0 };
322  mutt_account_tourl(&adata->conn->account, &url);
323  url.path = mbox->data;
324  url_tobuffer(&url, cachepath, U_PATH);
325 
326  const char *const c_header_cache =
327  cs_subset_path(NeoMutt->sub, "header_cache");
328  hc = mutt_hcache_open(c_header_cache, mutt_buffer_string(cachepath), imap_hcache_namer);
329 
330 cleanup:
332  mutt_buffer_pool_release(&cachepath);
333  mdata->hcache = hc;
334 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
static void imap_hcache_namer(const char *path, struct Buffer *dest)
Generate a filename for the header cache - Implements hcache_namer_t.
Definition: util.c:287
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:68
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
header cache structure
Definition: lib.h:84
String manipulation buffer.
Definition: buffer.h:33
struct HeaderCache * hcache
Definition: mdata.h:62
struct HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:332
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void imap_cachepath(char delim, const char *mailbox, struct Buffer *dest)
Generate a cache path for a mailbox.
Definition: util.c:719
int url_tobuffer(struct Url *url, struct Buffer *buf, uint8_t flags)
Output the URL string for a given Url object.
Definition: url.c:353
char delim
Definition: adata.h:75
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
char * data
Pointer to data.
Definition: buffer.h:35
char * name
Mailbox name.
Definition: mdata.h:40
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
char * path
Path.
Definition: url.h:75
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define U_PATH
Definition: url.h:50
struct Connection * conn
Definition: adata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_close()

void imap_hcache_close ( struct ImapMboxData mdata)

Close the header cache.

Parameters
mdataImap Mailbox data

Definition at line 340 of file util.c.

341 {
342  if (!mdata->hcache)
343  return;
344 
345  mutt_hcache_close(mdata->hcache);
346  mdata->hcache = NULL;
347 }
struct HeaderCache * hcache
Definition: mdata.h:62
void mutt_hcache_close(struct HeaderCache *hc)
Multiplexor for StoreOps::close.
Definition: hcache.c:435
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_get()

struct Email* imap_hcache_get ( struct ImapMboxData mdata,
unsigned int  uid 
)

Get a header cache entry by its UID.

Parameters
mdataImap Mailbox data
uidUID to find
Return values
ptrEmail
NULLFailure

Definition at line 356 of file util.c.

357 {
358  if (!mdata->hcache)
359  return NULL;
360 
361  char key[16];
362 
363  sprintf(key, "/%u", uid);
364  struct HCacheEntry hce =
365  mutt_hcache_fetch(mdata->hcache, key, mutt_str_len(key), mdata->uidvalidity);
366  if (!hce.email && hce.uidvalidity)
367  {
368  mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %u\n", hce.uidvalidity);
369  }
370 
371  return hce.email;
372 }
Wrapper for Email retrieved from the header cache.
Definition: lib.h:95
uint32_t uidvalidity
Definition: mdata.h:50
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:97
struct HeaderCache * hcache
Definition: mdata.h:62
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
struct HCacheEntry mutt_hcache_fetch(struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:461
struct Email * email
Retrieved email.
Definition: lib.h:99
Log at debug level 3.
Definition: logging.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_put()

int imap_hcache_put ( struct ImapMboxData mdata,
struct Email e 
)

Add an entry to the header cache.

Parameters
mdataImap Mailbox data
eEmail
Return values
0Success
-1Failure

Definition at line 381 of file util.c.

382 {
383  if (!mdata->hcache)
384  return -1;
385 
386  char key[16];
387 
388  sprintf(key, "/%u", imap_edata_get(e)->uid);
389  return mutt_hcache_store(mdata->hcache, key, mutt_str_len(key), e, mdata->uidvalidity);
390 }
uint32_t uidvalidity
Definition: mdata.h:50
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:64
struct HeaderCache * hcache
Definition: mdata.h:62
int mutt_hcache_store(struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
Multiplexor for StoreOps::store.
Definition: hcache.c:556
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_del()

int imap_hcache_del ( struct ImapMboxData mdata,
unsigned int  uid 
)

Delete an item from the header cache.

Parameters
mdataImap Mailbox data
uidUID of entry to delete
Return values
0Success
-1Failure

Definition at line 399 of file util.c.

400 {
401  if (!mdata->hcache)
402  return -1;
403 
404  char key[16];
405 
406  sprintf(key, "/%u", uid);
407  return mutt_hcache_delete_record(mdata->hcache, key, mutt_str_len(key));
408 }
struct HeaderCache * hcache
Definition: mdata.h:62
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:637
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_store_uid_seqset()

int imap_hcache_store_uid_seqset ( struct ImapMboxData mdata)

Store a UID Sequence Set in the header cache.

Parameters
mdataImap Mailbox data
Return values
0Success
-1Error

Definition at line 416 of file util.c.

417 {
418  if (!mdata->hcache)
419  return -1;
420 
421  /* The seqset is likely large. Preallocate to reduce reallocs */
422  struct Buffer buf = mutt_buffer_make(8192);
423  imap_msn_index_to_uid_seqset(&buf, mdata);
424 
425  int rc = mutt_hcache_store_raw(mdata->hcache, "/UIDSEQSET", 10, buf.data,
426  mutt_buffer_len(&buf) + 1);
427  mutt_debug(LL_DEBUG3, "Stored /UIDSEQSET %s\n", buf.data);
428  mutt_buffer_dealloc(&buf);
429  return rc;
430 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
struct HeaderCache * hcache
Definition: mdata.h:62
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
char * data
Pointer to data.
Definition: buffer.h:35
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int mutt_hcache_store_raw(struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
store a key / data pair
Definition: hcache.c:615
static void imap_msn_index_to_uid_seqset(struct Buffer *buf, struct ImapMboxData *mdata)
Convert MSN index of UIDs to Seqset.
Definition: util.c:231
Log at debug level 3.
Definition: logging.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_clear_uid_seqset()

int imap_hcache_clear_uid_seqset ( struct ImapMboxData mdata)

Delete a UID Sequence Set from the header cache.

Parameters
mdataImap Mailbox data
Return values
0Success
-1Error

Definition at line 438 of file util.c.

439 {
440  if (!mdata->hcache)
441  return -1;
442 
443  return mutt_hcache_delete_record(mdata->hcache, "/UIDSEQSET", 10);
444 }
struct HeaderCache * hcache
Definition: mdata.h:62
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:637
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_get_uid_seqset()

char* imap_hcache_get_uid_seqset ( struct ImapMboxData mdata)

Get a UID Sequence Set from the header cache.

Parameters
mdataImap Mailbox data
Return values
ptrUID Sequence Set
NULLError

Definition at line 452 of file util.c.

453 {
454  if (!mdata->hcache)
455  return NULL;
456 
457  char *seqset = NULL;
458  size_t dlen = 0;
459  char *hc_seqset = mutt_hcache_fetch_raw(mdata->hcache, "/UIDSEQSET", 10, &dlen);
460  if (hc_seqset)
461  {
462  seqset = mutt_strn_dup(hc_seqset, dlen);
463  mutt_hcache_free_raw(mdata->hcache, (void **) &hc_seqset);
464  }
465  mutt_debug(LL_DEBUG3, "Retrieved /UIDSEQSET %s\n", NONULL(seqset));
466 
467  return seqset;
468 }
#define NONULL(x)
Definition: string2.h:37
struct HeaderCache * hcache
Definition: mdata.h:62
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:541
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void * mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message&#39;s header from the cache.
Definition: hcache.c:521
Log at debug level 3.
Definition: logging.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_continue()

enum QuadOption imap_continue ( const char *  msg,
const char *  resp 
)

display a message and ask the user if they want to go on

Parameters
msgLocation of the error
respMessage for user
Return values
QuadOptionResult, e.g. MUTT_NO

Definition at line 654 of file util.c.

655 {
656  imap_error(msg, resp);
657  return mutt_yesorno(_("Continue?"), MUTT_NO);
658 }
#define _(a)
Definition: message.h:28
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:665
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_error()

void imap_error ( const char *  where,
const char *  msg 
)

show an error and abort

Parameters
whereLocation of the error
msgMessage for user

Definition at line 665 of file util.c.

666 {
667  mutt_error("%s [%s]", where, msg);
668 }
#define mutt_error(...)
Definition: logging.h:88
+ Here is the caller graph for this function:

◆ imap_mdata_cache_reset()

void imap_mdata_cache_reset ( struct ImapMboxData mdata)

Release and clear cache data of ImapMboxData structure.

Parameters
mdataImap Mailbox data

Definition at line 106 of file util.c.

107 {
108  mutt_hash_free(&mdata->uid_hash);
109  imap_msn_free(&mdata->msn);
110  mutt_bcache_close(&mdata->bcache);
111 }
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:449
struct BodyCache * bcache
Definition: mdata.h:60
void imap_msn_free(struct MSN *msn)
Free the cache.
Definition: msn.c:58
struct HashTable * uid_hash
Definition: mdata.h:58
void mutt_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
Definition: bcache.c:164
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_fix_path()

char* imap_fix_path ( char  delim,
const char *  mailbox,
char *  path,
size_t  plen 
)

Fix up the imap path.

Parameters
delimDelimiter specified by the server, '\0' for $imap_delim_chars
mailboxMailbox path
pathBuffer for the result
plenLength of buffer
Return values
ptrFixed-up path
Note
if delim is '\0', the first character in mailbox matching any of the characters in $imap_delim_chars is used as a delimiter.

This is necessary because the rest of neomutt 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. Moreover, IMAP servers may dislike the path ending with the delimiter.

Definition at line 687 of file util.c.

688 {
689  int i = 0;
690  for (; mailbox && *mailbox && (i < plen - 1); i++)
691  {
692  const char *const c_imap_delim_chars =
693  cs_subset_string(NeoMutt->sub, "imap_delim_chars");
694  if (*mailbox == delim || (!delim && strchr(NONULL(c_imap_delim_chars), *mailbox)))
695  {
696  delim = *mailbox;
697  /* Skip multiple occurrences of delim */
698  while (*mailbox && *(mailbox + 1) == delim)
699  mailbox++;
700  }
701  path[i] = *mailbox++;
702  }
703 
704  /* Do not terminate with a delimiter */
705  if (i && path[i - 1] == delim)
706  i--;
707 
708  /* Ensure null termination */
709  path[i] = '\0';
710  return path;
711 }
#define NONULL(x)
Definition: string2.h:37
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
Container for Accounts, Notifications.
Definition: neomutt.h:36
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_cachepath()

void imap_cachepath ( char  delim,
const char *  mailbox,
struct Buffer dest 
)

Generate a cache path for a mailbox.

Parameters
delimImap server delimiter
mailboxMailbox name
destBuffer to store cache path

Definition at line 719 of file util.c.

720 {
721  const char *p = mailbox;
722  mutt_buffer_reset(dest);
723  if (!p)
724  return;
725 
726  while (*p)
727  {
728  if (p[0] == delim)
729  {
730  mutt_buffer_addch(dest, '/');
731  /* simple way to avoid collisions with UIDs */
732  if ((p[1] >= '0') && (p[1] <= '9'))
733  mutt_buffer_addch(dest, '_');
734  }
735  else
736  mutt_buffer_addch(dest, *p);
737  p++;
738  }
739 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_get_literal_count()

int imap_get_literal_count ( const char *  buf,
unsigned int *  bytes 
)

write number of bytes in an IMAP literal into bytes

Parameters
[in]bufNumber as a string
[out]bytesResulting number
Return values
0Success
-1Failure

Definition at line 748 of file util.c.

749 {
750  char *pc = NULL;
751  char *pn = NULL;
752 
753  if (!buf || !(pc = strchr(buf, '{')))
754  return -1;
755 
756  pc++;
757  pn = pc;
758  while (isdigit((unsigned char) *pc))
759  pc++;
760  *pc = '\0';
761  if (mutt_str_atoui(pn, bytes) < 0)
762  return -1;
763 
764  return 0;
765 }
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:282
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_get_qualifier()

char* imap_get_qualifier ( char *  buf)

Get the qualifier from a tagged response.

Parameters
bufCommand string to process
Return values
ptrStart of the qualifier

In a tagged response, skip tag and status for the qualifier message. Used by imap_copy_message for TRYCREATE

Definition at line 775 of file util.c.

776 {
777  char *s = buf;
778 
779  /* skip tag */
780  s = imap_next_word(s);
781  /* skip OK/NO/BAD response */
782  s = imap_next_word(s);
783 
784  return s;
785 }
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:792
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_next_word()

char* imap_next_word ( char *  s)

Find where the next IMAP word begins.

Parameters
sCommand string to process
Return values
ptrNext IMAP word

Definition at line 792 of file util.c.

793 {
794  bool quoted = false;
795 
796  while (*s)
797  {
798  if (*s == '\\')
799  {
800  s++;
801  if (*s)
802  s++;
803  continue;
804  }
805  if (*s == '\"')
806  quoted = !quoted;
807  if (!quoted && IS_SPACE(*s))
808  break;
809  s++;
810  }
811 
812  SKIPWS(s);
813  return s;
814 }
#define SKIPWS(ch)
Definition: string2.h:46
#define IS_SPACE(ch)
Definition: string2.h:38
+ Here is the caller graph for this function:

◆ imap_qualify_path()

void imap_qualify_path ( char *  buf,
size_t  buflen,
struct ConnAccount cac,
char *  path 
)

Make an absolute IMAP folder target.

Parameters
bufBuffer for the result
buflenLength of buffer
cacConnAccount of the account
pathPath relative to the mailbox

Definition at line 823 of file util.c.

824 {
825  struct Url url = { 0 };
826  mutt_account_tourl(cac, &url);
827  url.path = path;
828  url_tostring(&url, buf, buflen, U_NO_FLAGS);
829 }
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:68
#define U_NO_FLAGS
Definition: url.h:49
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
int url_tostring(struct Url *url, char *dest, size_t len, uint8_t flags)
Output the URL string for a given Url object.
Definition: url.c:418
char * path
Path.
Definition: url.h:75
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_quote_string()

void imap_quote_string ( char *  dest,
size_t  dlen,
const char *  src,
bool  quote_backtick 
)

quote string according to IMAP rules

Parameters
destBuffer for the result
dlenLength of the buffer
srcString to be quoted
quote_backtickIf true, quote backticks too

Surround string with quotes, escape " and \ with backslash

Definition at line 840 of file util.c.

841 {
842  const char *quote = "`\"\\";
843  if (!quote_backtick)
844  quote++;
845 
846  char *pt = dest;
847  const char *s = src;
848 
849  *pt++ = '"';
850  /* save room for quote-chars */
851  dlen -= 3;
852 
853  for (; *s && dlen; s++)
854  {
855  if (strchr(quote, *s))
856  {
857  if (dlen < 2)
858  break;
859  dlen -= 2;
860  *pt++ = '\\';
861  *pt++ = *s;
862  }
863  else
864  {
865  *pt++ = *s;
866  dlen--;
867  }
868  }
869  *pt++ = '"';
870  *pt = '\0';
871 }
char * src
Raw URL string.
Definition: url.h:77
+ Here is the caller graph for this function:

◆ imap_unquote_string()

void imap_unquote_string ( char *  s)

equally stupid unquoting routine

Parameters
sString to be unquoted

Definition at line 877 of file util.c.

878 {
879  char *d = s;
880 
881  if (*s == '\"')
882  s++;
883  else
884  return;
885 
886  while (*s)
887  {
888  if (*s == '\"')
889  {
890  *d = '\0';
891  return;
892  }
893  if (*s == '\\')
894  {
895  s++;
896  }
897  if (*s)
898  {
899  *d = *s;
900  d++;
901  s++;
902  }
903  }
904  *d = '\0';
905 }
+ Here is the caller graph for this function:

◆ imap_munge_mbox_name()

void imap_munge_mbox_name ( bool  unicode,
char *  dest,
size_t  dlen,
const char *  src 
)

Quote awkward characters in a mailbox name.

Parameters
unicodetrue if Unicode is allowed
destBuffer to store safe mailbox name
dlenLength of buffer
srcMailbox name

Definition at line 914 of file util.c.

915 {
916  char *buf = mutt_str_dup(src);
917  imap_utf_encode(unicode, &buf);
918 
919  imap_quote_string(dest, dlen, buf, false);
920 
921  FREE(&buf);
922 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
void imap_utf_encode(bool unicode, char **s)
Encode email from local charset to UTF-8.
Definition: utf7.c:318
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
quote string according to IMAP rules
Definition: util.c:840
#define FREE(x)
Definition: memory.h:40
char * src
Raw URL string.
Definition: url.h:77
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_unmunge_mbox_name()

void imap_unmunge_mbox_name ( bool  unicode,
char *  s 
)

Remove quoting from a mailbox name.

Parameters
unicodetrue if Unicode is allowed
sMailbox name

The string will be altered in-place.

Definition at line 931 of file util.c.

932 {
934 
935  char *buf = mutt_str_dup(s);
936  if (buf)
937  {
938  imap_utf_decode(unicode, &buf);
939  strncpy(s, buf, strlen(s));
940  }
941 
942  FREE(&buf);
943 }
void imap_unquote_string(char *s)
equally stupid unquoting routine
Definition: util.c:877
void imap_utf_decode(bool unicode, char **s)
Decode email from UTF-8 to local charset.
Definition: utf7.c:348
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_seqset_iterator_new()

struct SeqsetIterator* mutt_seqset_iterator_new ( const char *  seqset)

Create a new Sequence Set Iterator.

Parameters
seqsetSource Sequence Set
Return values
ptrNewly allocated Sequence Set Iterator

Definition at line 1081 of file util.c.

1082 {
1083  if (!seqset || (*seqset == '\0'))
1084  return NULL;
1085 
1086  struct SeqsetIterator *iter = mutt_mem_calloc(1, sizeof(struct SeqsetIterator));
1087  iter->full_seqset = mutt_str_dup(seqset);
1088  iter->eostr = strchr(iter->full_seqset, '\0');
1089  iter->substr_cur = iter->substr_end = iter->full_seqset;
1090 
1091  return iter;
1092 }
char * eostr
Definition: private.h:171
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
char * substr_cur
Definition: private.h:176
char * substr_end
Definition: private.h:177
char * full_seqset
Definition: private.h:170
UID Sequence Set Iterator.
Definition: private.h:168
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_seqset_iterator_next()

int mutt_seqset_iterator_next ( struct SeqsetIterator iter,
unsigned int *  next 
)

Get the next UID from a Sequence Set.

Parameters
[in]iterSequence Set Iterator
[out]nextNext UID in set
Return values
0Next sequence is generated
1Iterator is finished
-1error

Definition at line 1102 of file util.c.

1103 {
1104  if (!iter || !next)
1105  return -1;
1106 
1107  if (iter->in_range)
1108  {
1109  if ((iter->down && (iter->range_cur == (iter->range_end - 1))) ||
1110  (!iter->down && (iter->range_cur == (iter->range_end + 1))))
1111  {
1112  iter->in_range = 0;
1113  }
1114  }
1115 
1116  if (!iter->in_range)
1117  {
1118  iter->substr_cur = iter->substr_end;
1119  if (iter->substr_cur == iter->eostr)
1120  return 1;
1121 
1122  iter->substr_end = strchr(iter->substr_cur, ',');
1123  if (!iter->substr_end)
1124  iter->substr_end = iter->eostr;
1125  else
1126  *(iter->substr_end++) = '\0';
1127 
1128  char *range_sep = strchr(iter->substr_cur, ':');
1129  if (range_sep)
1130  *range_sep++ = '\0';
1131 
1132  if (mutt_str_atoui(iter->substr_cur, &iter->range_cur) != 0)
1133  return -1;
1134  if (range_sep)
1135  {
1136  if (mutt_str_atoui(range_sep, &iter->range_end) != 0)
1137  return -1;
1138  }
1139  else
1140  iter->range_end = iter->range_cur;
1141 
1142  iter->down = (iter->range_end < iter->range_cur);
1143  iter->in_range = 1;
1144  }
1145 
1146  *next = iter->range_cur;
1147  if (iter->down)
1148  iter->range_cur--;
1149  else
1150  iter->range_cur++;
1151 
1152  return 0;
1153 }
char * eostr
Definition: private.h:171
unsigned int range_end
Definition: private.h:175
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:282
char * substr_cur
Definition: private.h:176
char * substr_end
Definition: private.h:177
unsigned int range_cur
Definition: private.h:174
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_seqset_iterator_free()

void mutt_seqset_iterator_free ( struct SeqsetIterator **  ptr)

Free a Sequence Set Iterator.

Parameters
[out]ptrIterator to free

Definition at line 1159 of file util.c.

1160 {
1161  if (!ptr || !*ptr)
1162  return;
1163 
1164  struct SeqsetIterator *iter = *ptr;
1165  FREE(&iter->full_seqset);
1166  FREE(ptr);
1167 }
#define FREE(x)
Definition: memory.h:40
char * full_seqset
Definition: private.h:170
UID Sequence Set Iterator.
Definition: private.h:168
+ Here is the caller graph for this function:

◆ imap_account_match()

bool imap_account_match ( const struct ConnAccount a1,
const struct ConnAccount a2 
)

Compare two Accounts.

Parameters
a1First ConnAccount
a2Second ConnAccount
Return values
trueAccounts match

Definition at line 1049 of file util.c.

1050 {
1051  if (!a1 || !a2)
1052  return false;
1053  if (a1->type != a2->type)
1054  return false;
1055  if (!mutt_istr_equal(a1->host, a2->host))
1056  return false;
1057  if ((a1->port != 0) && (a2->port != 0) && (a1->port != a2->port))
1058  return false;
1059  if (a1->flags & a2->flags & MUTT_ACCT_USER)
1060  return strcmp(a1->user, a2->user) == 0;
1061 
1062  const char *user = NONULL(Username);
1063 
1064  const char *const c_imap_user = cs_subset_string(NeoMutt->sub, "imap_user");
1065  if ((a1->type == MUTT_ACCT_TYPE_IMAP) && c_imap_user)
1066  user = c_imap_user;
1067 
1068  if (a1->flags & MUTT_ACCT_USER)
1069  return strcmp(a1->user, user) == 0;
1070  if (a2->flags & MUTT_ACCT_USER)
1071  return strcmp(a2->user, user) == 0;
1072 
1073  return true;
1074 }
#define NONULL(x)
Definition: string2.h:37
char user[128]
Username.
Definition: connaccount.h:55
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:43
char host[128]
Server to login to.
Definition: connaccount.h:53
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:48
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
unsigned short port
Port to connect to.
Definition: connaccount.h:57
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
Definition: connaccount.h:58
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Imap Account.
Definition: mutt_account.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:59
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_get_parent()

void imap_get_parent ( const char *  mbox,
char  delim,
char *  buf,
size_t  buflen 
)

Get an IMAP folder's parent.

Parameters
mboxMailbox whose parent is to be determined
delimPath delimiter
bufBuffer for the result
buflenLength of the buffer

Definition at line 120 of file util.c.

121 {
122  /* Make a copy of the mailbox name, but only if the pointers are different */
123  if (mbox != buf)
124  mutt_str_copy(buf, mbox, buflen);
125 
126  int n = mutt_str_len(buf);
127 
128  /* Let's go backwards until the next delimiter
129  *
130  * If buf[n] is a '/', the first n-- will allow us
131  * to ignore it. If it isn't, then buf looks like
132  * "/aaaaa/bbbb". There is at least one "b", so we can't skip
133  * the "/" after the 'a's.
134  *
135  * If buf == '/', then n-- => n == 0, so the loop ends
136  * immediately */
137  for (n--; (n >= 0) && (buf[n] != delim); n--)
138  ; // do nothing
139 
140  /* We stopped before the beginning. There is a trailing slash. */
141  if (n > 0)
142  {
143  /* Strip the trailing delimiter. */
144  buf[n] = '\0';
145  }
146  else
147  {
148  buf[0] = (n == 0) ? delim : '\0';
149  }
150 }
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_account_match()

bool mutt_account_match ( const struct ConnAccount a1,
const struct ConnAccount a2 
)

◆ imap_utf_encode()

void imap_utf_encode ( bool  unicode,
char **  s 
)

Encode email from local charset to UTF-8.

Parameters
[in]unicodetrue if Unicode is allowed
[out]sEmail to convert

Definition at line 318 of file utf7.c.

319 {
320  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
321  if (!c_charset || !s || !*s)
322  return;
323 
324  if (unicode && mutt_ch_is_utf8(c_charset))
325  {
326  return;
327  }
328 
329  if (mutt_ch_convert_string(s, c_charset, "utf-8", MUTT_ICONV_NO_FLAGS) != 0)
330  {
331  FREE(s);
332  return;
333  }
334 
335  if (!unicode)
336  {
337  char *utf7 = utf8_to_utf7(*s, strlen(*s), NULL, 0);
338  FREE(s);
339  *s = utf7;
340  }
341 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:758
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
Container for Accounts, Notifications.
Definition: neomutt.h:36
static char * utf8_to_utf7(const char *u8, size_t u8len, char **u7, size_t *u7len)
Convert data from UTF-8 to RFC2060&#39;s UTF-7.
Definition: utf7.c:195
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_ch_is_utf8(str)
Definition: charset.h:95
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_utf_decode()

void imap_utf_decode ( bool  unicode,
char **  s 
)

Decode email from UTF-8 to local charset.

Parameters
[in]unicodetrue if Unicode is allowed
[out]sEmail to convert

Definition at line 348 of file utf7.c.

349 {
350  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
351  if (!c_charset || !s || !*s)
352  return;
353 
354  if (unicode && mutt_ch_is_utf8(c_charset))
355  {
356  return;
357  }
358 
359  if (!unicode)
360  {
361  char *utf8 = utf7_to_utf8(*s, strlen(*s), 0, 0);
362  FREE(s);
363  *s = utf8;
364  }
365 
366  if (mutt_ch_convert_string(s, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS) != 0)
367  {
368  FREE(s);
369  }
370 }
static char * utf7_to_utf8(const char *u7, size_t u7len, char **u8, size_t *u8len)
Convert data from RFC2060&#39;s UTF-7 to UTF-8.
Definition: utf7.c:85
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:758
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
Container for Accounts, Notifications.
Definition: neomutt.h:36
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_ch_is_utf8(str)
Definition: charset.h:95
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_allow_reopen()

void imap_allow_reopen ( struct Mailbox m)

Allow re-opening a folder upon expunge.

Parameters
mMailbox

Definition at line 1021 of file util.c.

1022 {
1023  struct ImapAccountData *adata = imap_adata_get(m);
1024  struct ImapMboxData *mdata = imap_mdata_get(m);
1025  if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1026  return;
1027  mdata->reopen |= IMAP_REOPEN_ALLOW;
1028 }
#define IMAP_REOPEN_ALLOW
Allow re-opening a folder upon expunge.
Definition: private.h:66
ImapOpenFlags reopen
Flags, e.g. IMAP_REOPEN_ALLOW.
Definition: mdata.h:44
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:59
void * mdata
Driver specific data.
Definition: mailbox.h:136
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
IMAP-specific Account data -.
Definition: adata.h:39
IMAP-specific Mailbox data -.
Definition: mdata.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_disallow_reopen()

void imap_disallow_reopen ( struct Mailbox m)

Disallow re-opening a folder upon expunge.

Parameters
mMailbox

Definition at line 1034 of file util.c.

1035 {
1036  struct ImapAccountData *adata = imap_adata_get(m);
1037  struct ImapMboxData *mdata = imap_mdata_get(m);
1038  if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1039  return;
1040  mdata->reopen &= ~IMAP_REOPEN_ALLOW;
1041 }
#define IMAP_REOPEN_ALLOW
Allow re-opening a folder upon expunge.
Definition: private.h:66
ImapOpenFlags reopen
Flags, e.g. IMAP_REOPEN_ALLOW.
Definition: mdata.h:44
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:59
void * mdata
Driver specific data.
Definition: mailbox.h:136
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
IMAP-specific Account data -.
Definition: adata.h:39
IMAP-specific Mailbox data -.
Definition: mdata.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cmd_parse_search()

void cmd_parse_search ( struct ImapAccountData adata,
const char *  s 
)

store SEARCH response for later use

Parameters
adataImap Account data
sCommand string with search results

Definition at line 259 of file search.c.

260 {
261  unsigned int uid;
262  struct Email *e = NULL;
263  struct ImapMboxData *mdata = adata->mailbox->mdata;
264 
265  mutt_debug(LL_DEBUG2, "Handling SEARCH\n");
266 
267  while ((s = imap_next_word((char *) s)) && (*s != '\0'))
268  {
269  if (mutt_str_atoui(s, &uid) < 0)
270  continue;
271  e = mutt_hash_int_find(mdata->uid_hash, uid);
272  if (e)
273  e->matched = true;
274  }
275 }
The envelope/body of an email.
Definition: email.h:37
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
void * mutt_hash_int_find(const struct HashTable *table, unsigned int intkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:384
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:792
Log at debug level 2.
Definition: logging.h:41
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct HashTable * uid_hash
Definition: mdata.h:58
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:282
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
IMAP-specific Mailbox data -.
Definition: mdata.h:38
bool matched
Search matches this Email.
Definition: email.h:68
+ Here is the call graph for this function:
+ Here is the caller graph for this function: