NeoMutt  2021-10-29-220-g2b1eec
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_AUTH_XOAUTH2   (1 << 9)
 AUTH=XOAUTH2, deprecated but used by OWA. More...
 
#define IMAP_CAP_STARTTLS   (1 << 10)
 RFC2595: STARTTLS. More...
 
#define IMAP_CAP_LOGINDISABLED   (1 << 11)
 RFC2595: LOGINDISABLED. More...
 
#define IMAP_CAP_IDLE   (1 << 12)
 RFC2177: IDLE. More...
 
#define IMAP_CAP_SASL_IR   (1 << 13)
 SASL initial response draft. More...
 
#define IMAP_CAP_ENABLE   (1 << 14)
 RFC5161. More...
 
#define IMAP_CAP_CONDSTORE   (1 << 15)
 RFC7162. More...
 
#define IMAP_CAP_QRESYNC   (1 << 16)
 RFC7162. More...
 
#define IMAP_CAP_LIST_EXTENDED   (1 << 17)
 RFC5258: IMAP4 LIST Command Extensions. More...
 
#define IMAP_CAP_COMPRESS   (1 << 18)
 RFC4978: COMPRESS=DEFLATE. More...
 
#define IMAP_CAP_X_GM_EXT_1   (1 << 19)
 https://developers.google.com/gmail/imap/imap-extensions More...
 
#define IMAP_CAP_ALL   ((1 << 20) - 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, const 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_AUTH_XOAUTH2

#define IMAP_CAP_AUTH_XOAUTH2   (1 << 9)

AUTH=XOAUTH2, deprecated but used by OWA.

Definition at line 132 of file private.h.

◆ IMAP_CAP_STARTTLS

#define IMAP_CAP_STARTTLS   (1 << 10)

RFC2595: STARTTLS.

Definition at line 133 of file private.h.

◆ IMAP_CAP_LOGINDISABLED

#define IMAP_CAP_LOGINDISABLED   (1 << 11)

RFC2595: LOGINDISABLED.

Definition at line 134 of file private.h.

◆ IMAP_CAP_IDLE

#define IMAP_CAP_IDLE   (1 << 12)

RFC2177: IDLE.

Definition at line 135 of file private.h.

◆ IMAP_CAP_SASL_IR

#define IMAP_CAP_SASL_IR   (1 << 13)

SASL initial response draft.

Definition at line 136 of file private.h.

◆ IMAP_CAP_ENABLE

#define IMAP_CAP_ENABLE   (1 << 14)

RFC5161.

Definition at line 137 of file private.h.

◆ IMAP_CAP_CONDSTORE

#define IMAP_CAP_CONDSTORE   (1 << 15)

RFC7162.

Definition at line 138 of file private.h.

◆ IMAP_CAP_QRESYNC

#define IMAP_CAP_QRESYNC   (1 << 16)

RFC7162.

Definition at line 139 of file private.h.

◆ IMAP_CAP_LIST_EXTENDED

#define IMAP_CAP_LIST_EXTENDED   (1 << 17)

RFC5258: IMAP4 LIST Command Extensions.

Definition at line 140 of file private.h.

◆ IMAP_CAP_COMPRESS

#define IMAP_CAP_COMPRESS   (1 << 18)

RFC4978: COMPRESS=DEFLATE.

Definition at line 141 of file private.h.

◆ IMAP_CAP_X_GM_EXT_1

#define IMAP_CAP_X_GM_EXT_1   (1 << 19)

◆ IMAP_CAP_ALL

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

Definition at line 144 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_EXEC_SUCCESS
Imap command executed or queued successfully.
Definition: private.h:84
@ IMAP_EXEC_ERROR
Imap command failure.
Definition: private.h:85
@ IMAP_EXEC_FATAL
Imap connection failure.
Definition: private.h:86

◆ 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 };
@ IMAP_BYE
Logged out from server.
Definition: private.h:98
@ IMAP_FATAL
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 };
@ IMAP_DISCONNECTED
Disconnected from server.
Definition: private.h:107
@ IMAP_IDLE
Connection is idle.
Definition: private.h:113
@ IMAP_AUTHENTICATED
Connection is authenticated.
Definition: private.h:109
@ IMAP_SELECTED
Mailbox is selected.
Definition: private.h:110
@ IMAP_CONNECTED
Connected to server.
Definition: private.h:108

Function Documentation

◆ imap_create_mailbox()

int imap_create_mailbox ( struct ImapAccountData adata,
const 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:87
const char * imap_cmd_trailer(struct ImapAccountData *adata)
Extra information after tagged command response if any.
Definition: command.c:1216
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:1253
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:73
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
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 }
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
String manipulation buffer.
Definition: buffer.h:34
+ 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 930 of file imap.c.

932 {
933  struct ImapAccountData *adata = imap_adata_get(m);
934  if (!adata || (adata->mailbox != m))
935  return -1;
936 
937  struct Email **emails = NULL;
938  int pos;
939  int rc;
940  int count = 0;
941 
942  struct Buffer cmd = mutt_buffer_make(0);
943 
944  /* We make a copy of the headers just in case resorting doesn't give
945  exactly the original order (duplicate messages?), because other parts of
946  the ctx are tied to the header order. This may be overkill. */
947  const short c_sort = cs_subset_sort(NeoMutt->sub, "sort");
948  if (c_sort != SORT_ORDER)
949  {
950  emails = m->emails;
951  // We overcommit here, just in case new mail arrives whilst we're sync-ing
952  m->emails = mutt_mem_malloc(m->email_max * sizeof(struct Email *));
953  memcpy(m->emails, emails, m->email_max * sizeof(struct Email *));
954 
956  qsort(m->emails, m->msg_count, sizeof(struct Email *), compare_uid);
957  }
958 
959  pos = 0;
960 
961  do
962  {
963  mutt_buffer_reset(&cmd);
964  mutt_buffer_add_printf(&cmd, "%s ", pre);
965  rc = make_msg_set(m, &cmd, flag, changed, invert, &pos);
966  if (rc > 0)
967  {
968  mutt_buffer_add_printf(&cmd, " %s", post);
969  if (imap_exec(adata, cmd.data, IMAP_CMD_QUEUE) != IMAP_EXEC_SUCCESS)
970  {
971  rc = -1;
972  goto out;
973  }
974  count += rc;
975  }
976  } while (rc > 0);
977 
978  rc = count;
979 
980 out:
981  mutt_buffer_dealloc(&cmd);
982  if (c_sort != SORT_ORDER)
983  {
984  cs_subset_str_native_set(NeoMutt->sub, "sort", c_sort, NULL);
985  FREE(&m->emails);
986  m->emails = emails;
987  }
988 
989  return rc;
990 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
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
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
static int compare_uid(const void *a, const void *b)
Compare two Emails by UID - Implements sort_t -.
Definition: imap.c:904
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:75
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:198
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:40
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:48
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * data
Pointer to data.
Definition: buffer.h:35
The envelope/body of an email.
Definition: email.h:37
IMAP-specific Account data -.
Definition: adata.h:40
int msg_count
Total number of messages.
Definition: mailbox.h:91
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
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
+ 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 }
int mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
Definition: gnutls.c:1168
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1082
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:56
#define IMAP_CAP_STARTTLS
RFC2595: STARTTLS.
Definition: private.h:133
ImapExecResult
Imap_exec return code.
Definition: private.h:83
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition: util.c:665
#define IMAP_CMD_SINGLE
Run a single command.
Definition: private.h:77
void imap_close_connection(struct ImapAccountData *adata)
Close an IMAP connection.
Definition: imap.c:853
static int check_capabilities(struct ImapAccountData *adata)
Make sure we can log in to this server.
Definition: imap.c:95
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:170
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:349
void mutt_socket_empty(struct Connection *conn)
Clear out any queued data.
Definition: socket.c:313
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:76
unsigned int ssf
Security strength factor, in bits (see notes)
Definition: connection.h:51
ImapCapFlags capabilities
Capability flags.
Definition: adata.h:55
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: adata.h:44
char * capstr
Capability string from the server.
Definition: adata.h:54
char * buf
Definition: adata.h:59
struct Connection * conn
Connection to IMAP server.
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 }
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:97
int lastcmd
Last command in the queue.
Definition: adata.h:72
int nextcmd
Next command to be sent.
Definition: adata.h:71
struct ImapCommand * cmds
Queue of commands for the server.
Definition: adata.h:69
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: adata.h:45
int cmdslots
Size of the command queue.
Definition: adata.h:70
unsigned int seqno
tag sequence number, e.g. '{seqid}0001'
Definition: adata.h:57
IMAP command structure.
Definition: private.h:161
+ 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 }
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
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:84
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
#define IMAP_LOG_LTRL
Definition: private.h:50
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:177
int mutt_socket_readchar(struct Connection *conn, char *c)
Simple read buffering to speed things up.
Definition: socket.c:210
+ 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 }
void mutt_hash_int_delete(struct HashTable *table, unsigned int intkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:444
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:64
void imap_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: edata.c:38
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:60
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition: message.c:1825
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:340
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition: util.c:399
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:211
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:181
@ NT_MAILBOX_UPDATE
Update internal tables.
Definition: mailbox.h:183
void * edata
Driver-specific data.
Definition: email.h:72
bool active
Message is not to be removed.
Definition: email.h:74
bool deleted
Email is deleted.
Definition: email.h:76
int index
The absolute (unsorted) message number.
Definition: email.h:110
IMAP-specific Mailbox data -.
Definition: mdata.h:39
struct HashTable * uid_hash
Definition: mdata.h:58
void * mdata
Driver specific data.
Definition: mailbox.h:136
+ 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 1852 of file imap.c.

1853 {
1854  if (!adata)
1855  return -1;
1856 
1857  if (adata->state == IMAP_DISCONNECTED)
1858  {
1859  mutt_buffer_reset(&adata->cmdbuf); // purge outstanding queued commands
1860  imap_open_connection(adata);
1861  }
1862  if (adata->state == IMAP_CONNECTED)
1863  {
1864  if (imap_authenticate(adata) == IMAP_AUTH_SUCCESS)
1865  {
1866  adata->state = IMAP_AUTHENTICATED;
1867  FREE(&adata->capstr);
1868  if (adata->conn->ssf != 0)
1869  {
1870  mutt_debug(LL_DEBUG2, "Communication encrypted at %d bits\n",
1871  adata->conn->ssf);
1872  }
1873  }
1874  else
1876  }
1877  if (adata->state == IMAP_AUTHENTICATED)
1878  {
1879  /* capabilities may have changed */
1880  imap_exec(adata, "CAPABILITY", IMAP_CMD_PASS);
1881 
1882 #ifdef USE_ZLIB
1883  /* RFC4978 */
1884  const bool c_imap_deflate = cs_subset_bool(NeoMutt->sub, "imap_deflate");
1885  if ((adata->capabilities & IMAP_CAP_COMPRESS) && c_imap_deflate &&
1886  (imap_exec(adata, "COMPRESS DEFLATE", IMAP_CMD_PASS) == IMAP_EXEC_SUCCESS))
1887  {
1888  mutt_debug(LL_DEBUG2, "IMAP compression is enabled on connection to %s\n",
1889  adata->conn->account.host);
1890  mutt_zstrm_wrap_conn(adata->conn);
1891  }
1892 #endif
1893 
1894  /* enable RFC6855, if the server supports that */
1895  const bool c_imap_rfc5161 = cs_subset_bool(NeoMutt->sub, "imap_rfc5161");
1896  if (c_imap_rfc5161 && (adata->capabilities & IMAP_CAP_ENABLE))
1897  imap_exec(adata, "ENABLE UTF8=ACCEPT", IMAP_CMD_QUEUE);
1898 
1899  /* enable QRESYNC. Advertising QRESYNC also means CONDSTORE
1900  * is supported (even if not advertised), so flip that bit. */
1901  if (adata->capabilities & IMAP_CAP_QRESYNC)
1902  {
1903  adata->capabilities |= IMAP_CAP_CONDSTORE;
1904  const bool c_imap_qresync = cs_subset_bool(NeoMutt->sub, "imap_qresync");
1905  if (c_imap_rfc5161 && c_imap_qresync)
1906  imap_exec(adata, "ENABLE QRESYNC", IMAP_CMD_QUEUE);
1907  }
1908 
1909  /* get root delimiter, '/' as default */
1910  adata->delim = '/';
1911  imap_exec(adata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
1912 
1913  /* we may need the root delimiter before we open a mailbox */
1914  imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1915 
1916  /* select the mailbox that used to be open before disconnect */
1917  if (adata->mailbox)
1918  {
1919  imap_mbox_select(adata->mailbox);
1920  }
1921  }
1922 
1923  if (adata->state < IMAP_AUTHENTICATED)
1924  return -1;
1925 
1926  return 0;
1927 }
@ IMAP_AUTH_SUCCESS
Authentication successful.
Definition: auth.h:39
void mutt_account_unsetpass(struct ConnAccount *cac)
Unset ConnAccount's password.
Definition: connaccount.c:151
int imap_authenticate(struct ImapAccountData *adata)
Authenticate to an IMAP server.
Definition: auth.c:108
#define IMAP_CAP_ENABLE
RFC5161.
Definition: private.h:137
#define IMAP_CMD_PASS
Command contains a password. Suppress logging.
Definition: private.h:74
#define IMAP_CAP_QRESYNC
RFC7162.
Definition: private.h:139
#define IMAP_CAP_COMPRESS
RFC4978: COMPRESS=DEFLATE.
Definition: private.h:141
#define IMAP_CAP_CONDSTORE
RFC7162.
Definition: private.h:138
int imap_open_connection(struct ImapAccountData *adata)
Open an IMAP connection.
Definition: imap.c:745
static void imap_mbox_select(struct Mailbox *m)
Select a Mailbox.
Definition: imap.c:1819
char host[128]
Server to login to.
Definition: connaccount.h:54
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
char delim
Path delimiter.
Definition: adata.h:75
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
struct Buffer cmdbuf
Definition: adata.h:73
void mutt_zstrm_wrap_conn(struct Connection *conn)
Wrap a compression layer around a Connection.
Definition: zstrm.c:288
+ 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 1007 of file imap.c.

1009 {
1010  struct ImapAccountData *adata = imap_adata_get(m);
1011  if (!adata || (adata->mailbox != m))
1012  return -1;
1013 
1014  char flags[1024];
1015  char *tags = NULL;
1016  char uid[11];
1017 
1018  if (!compare_flags_for_copy(e))
1019  {
1020  if (e->deleted == imap_edata_get(e)->deleted)
1021  e->changed = false;
1022  return 0;
1023  }
1024 
1025  snprintf(uid, sizeof(uid), "%u", imap_edata_get(e)->uid);
1026  mutt_buffer_reset(cmd);
1027  mutt_buffer_addstr(cmd, "UID STORE ");
1028  mutt_buffer_addstr(cmd, uid);
1029 
1030  flags[0] = '\0';
1031 
1032  set_flag(m, MUTT_ACL_SEEN, e->read, "\\Seen ", flags, sizeof(flags));
1033  set_flag(m, MUTT_ACL_WRITE, e->old, "Old ", flags, sizeof(flags));
1034  set_flag(m, MUTT_ACL_WRITE, e->flagged, "\\Flagged ", flags, sizeof(flags));
1035  set_flag(m, MUTT_ACL_WRITE, e->replied, "\\Answered ", flags, sizeof(flags));
1036  set_flag(m, MUTT_ACL_DELETE, imap_edata_get(e)->deleted, "\\Deleted ", flags,
1037  sizeof(flags));
1038 
1039  if (m->rights & MUTT_ACL_WRITE)
1040  {
1041  /* restore system flags */
1042  if (imap_edata_get(e)->flags_system)
1043  mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_system);
1044  /* set custom flags */
1045  tags = driver_tags_get_with_hidden(&e->tags);
1046  if (tags)
1047  {
1048  mutt_str_cat(flags, sizeof(flags), tags);
1049  FREE(&tags);
1050  }
1051  }
1052 
1054 
1055  /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
1056  * explicitly revoke all system flags (if we have permission) */
1057  if (*flags == '\0')
1058  {
1059  set_flag(m, MUTT_ACL_SEEN, true, "\\Seen ", flags, sizeof(flags));
1060  set_flag(m, MUTT_ACL_WRITE, true, "Old ", flags, sizeof(flags));
1061  set_flag(m, MUTT_ACL_WRITE, true, "\\Flagged ", flags, sizeof(flags));
1062  set_flag(m, MUTT_ACL_WRITE, true, "\\Answered ", flags, sizeof(flags));
1063  set_flag(m, MUTT_ACL_DELETE, !imap_edata_get(e)->deleted, "\\Deleted ",
1064  flags, sizeof(flags));
1065 
1066  /* erase custom flags */
1067  if ((m->rights & MUTT_ACL_WRITE) && imap_edata_get(e)->flags_remote)
1068  mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_remote);
1069 
1071 
1072  mutt_buffer_addstr(cmd, " -FLAGS.SILENT (");
1073  }
1074  else
1075  mutt_buffer_addstr(cmd, " FLAGS.SILENT (");
1076 
1077  mutt_buffer_addstr(cmd, flags);
1078  mutt_buffer_addstr(cmd, ")");
1079 
1080  /* after all this it's still possible to have no flags, if you
1081  * have no ACL rights */
1082  if (*flags && (imap_exec(adata, cmd->data, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS) &&
1083  err_continue && (*err_continue != MUTT_YES))
1084  {
1085  *err_continue = imap_continue("imap_sync_message: STORE failed", adata->buf);
1086  if (*err_continue != MUTT_YES)
1087  return -1;
1088  }
1089 
1090  /* server have now the updated flags */
1091  FREE(&imap_edata_get(e)->flags_remote);
1093 
1094  if (e->deleted == imap_edata_get(e)->deleted)
1095  e->changed = false;
1096 
1097  return 0;
1098 }
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
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
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:177
static bool compare_flags_for_copy(struct Email *e)
Compare local flags against the server.
Definition: imap.c:299
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
#define MUTT_ACL_SEEN
Change the 'seen' status of a message.
Definition: mailbox.h:73
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:544
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:196
bool read
Email is read.
Definition: email.h:48
bool old
Email is seen, but unread.
Definition: email.h:47
bool changed
Email has been edited.
Definition: email.h:75
bool flagged
Marked important?
Definition: email.h:45
bool replied
Email has been replied to.
Definition: email.h:49
struct TagList tags
For drivers that support server tagging.
Definition: email.h:70
char * flags_remote
Definition: edata.h:48
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
char * driver_tags_get_with_hidden(struct TagList *list)
Get tags with hiddens.
Definition: tags.c:157
+ 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:715
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:475
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:432
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_EMPTY(head)
Definition: queue.h:348
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
+ 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 ImapMboxData * imap_mdata_new(struct ImapAccountData *adata, const char *name)
Allocate and initialise a new ImapMboxData structure.
Definition: mdata.c:73
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:53
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
A group of associated Mailboxes.
Definition: account.h:37
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
Login details for a remote server.
Definition: connaccount.h:53
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
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
+ 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 108 of file auth.c.

109 {
110  int rc = IMAP_AUTH_FAILURE;
111 
112  const struct Slist *c_imap_authenticators =
113  cs_subset_slist(NeoMutt->sub, "imap_authenticators");
114  if (c_imap_authenticators && (c_imap_authenticators->count > 0))
115  {
116  mutt_debug(LL_DEBUG2, "Trying user-defined imap_authenticators\n");
117 
118  /* Try user-specified list of authentication methods */
119  struct ListNode *np = NULL;
120  STAILQ_FOREACH(np, &c_imap_authenticators->head, entries)
121  {
122  mutt_debug(LL_DEBUG2, "Trying method %s\n", np->data);
123 
124  for (size_t i = 0; i < mutt_array_size(ImapAuthenticators); i++)
125  {
126  const struct ImapAuth *auth = &ImapAuthenticators[i];
127  if (!auth->method || mutt_istr_equal(auth->method, np->data))
128  {
129  rc = auth->authenticate(adata, np->data);
130  if (rc == IMAP_AUTH_SUCCESS)
131  {
132  return rc;
133  }
134  }
135  }
136  }
137  }
138  else
139  {
140  /* Fall back to default: any authenticator */
141  mutt_debug(LL_DEBUG2, "Trying pre-defined imap_authenticators\n");
142 
143  for (size_t i = 0; i < mutt_array_size(ImapAuthenticators); i++)
144  {
145  rc = ImapAuthenticators[i].authenticate(adata, NULL);
146  if (rc == IMAP_AUTH_SUCCESS)
147  return rc;
148  }
149  }
150 
151  mutt_error(_("No authenticators available or wrong credentials"));
152  return rc;
153 }
@ IMAP_AUTH_FAILURE
Authentication failed.
Definition: auth.h:40
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
static const struct ImapAuth ImapAuthenticators[]
Accepted authentication methods.
Definition: auth.c:59
#define mutt_array_size(x)
Definition: memory.h:33
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:727
IMAP authentication multiplexor.
Definition: auth.c:43
enum ImapAuthRes(* authenticate)(struct ImapAccountData *adata, const char *method)
Authenticate an IMAP connection.
Definition: auth.c:50
const char * method
Name of authentication method supported, NULL means variable.
Definition: auth.c:52
String list.
Definition: slist.h:47
struct ListHead head
List containing values.
Definition: slist.h:48
size_t count
Number of values in list.
Definition: slist.h:49
+ 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 1068 of file command.c.

1069 {
1070  return cmd_start(adata, cmdstr, IMAP_CMD_NO_FLAGS);
1071 }
static int cmd_start(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Start a new IMAP command.
Definition: command.c:199
+ 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 1082 of file command.c.

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

1320 {
1321  if (!adata)
1322  return;
1323 
1324  if (adata->status == IMAP_FATAL)
1325  {
1326  adata->closing = false;
1327  cmd_handle_fatal(adata);
1328  return;
1329  }
1330 
1331  if (!(adata->state >= IMAP_SELECTED) || (adata->mailbox && adata->closing))
1332  {
1333  adata->closing = false;
1334  return;
1335  }
1336 
1337  adata->closing = false;
1338 
1339  struct ImapMboxData *mdata = imap_mdata_get(adata->mailbox);
1340 
1341  if (mdata && mdata->reopen & IMAP_REOPEN_ALLOW)
1342  {
1343  // First remove expunged emails from the msn_index
1344  if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1345  {
1346  mutt_debug(LL_DEBUG2, "Expunging mailbox\n");
1347  imap_expunge_mailbox(adata->mailbox);
1348  /* Detect whether we've gotten unexpected EXPUNGE messages */
1349  if (!(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1350  mdata->check_status |= IMAP_EXPUNGE_PENDING;
1352  }
1353 
1354  // Then add new emails to it
1355  if (mdata->reopen & IMAP_NEWMAIL_PENDING)
1356  {
1357  const size_t max_msn = imap_msn_highest(&mdata->msn);
1358  if (mdata->new_mail_count > max_msn)
1359  {
1360  if (!(mdata->reopen & IMAP_EXPUNGE_PENDING))
1361  mdata->check_status |= IMAP_NEWMAIL_PENDING;
1362 
1363  mutt_debug(LL_DEBUG2, "Fetching new mails from %d to %d\n", max_msn + 1,
1364  mdata->new_mail_count);
1365  imap_read_headers(adata->mailbox, max_msn + 1, mdata->new_mail_count, false);
1366  }
1367  }
1368 
1369  // And to finish inform about MUTT_REOPEN if needed
1370  if (mdata->reopen & IMAP_EXPUNGE_PENDING && !(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1371  mdata->check_status |= IMAP_EXPUNGE_PENDING;
1372 
1373  if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1375  }
1376 
1377  adata->status = 0;
1378 }
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:1305
#define IMAP_EXPUNGE_PENDING
Messages on the server have been expunged.
Definition: private.h:68
#define IMAP_EXPUNGE_EXPECTED
Messages will be expunged from the server.
Definition: private.h:67
#define IMAP_REOPEN_ALLOW
Allow re-opening a folder upon expunge.
Definition: private.h:66
#define IMAP_NEWMAIL_PENDING
New mail is waiting on the server.
Definition: private.h:69
void imap_expunge_mailbox(struct Mailbox *m)
Purge messages from the server.
Definition: imap.c:676
size_t imap_msn_highest(const struct MSN *msn)
Return the highest MSN in use.
Definition: msn.c:68
bool closing
If true, we are waiting for CLOSE completion.
Definition: adata.h:43
+ 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 1205 of file command.c.

1206 {
1207  return cmd_status(s) == IMAP_RES_OK;
1208 }
+ 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 1216 of file command.c.

1217 {
1218  static const char *notrailer = "";
1219  const char *s = adata->buf;
1220 
1221  if (!s)
1222  {
1223  mutt_debug(LL_DEBUG2, "not a tagged response\n");
1224  return notrailer;
1225  }
1226 
1227  s = imap_next_word((char *) s);
1228  if (!s || (!mutt_istr_startswith(s, "OK") && !mutt_istr_startswith(s, "NO") &&
1229  !mutt_istr_startswith(s, "BAD")))
1230  {
1231  mutt_debug(LL_DEBUG2, "not a command completion: %s\n", adata->buf);
1232  return notrailer;
1233  }
1234 
1235  s = imap_next_word((char *) s);
1236  if (!s)
1237  return notrailer;
1238 
1239  return s;
1240 }
+ 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 1253 of file command.c.

1254 {
1255  int rc;
1256 
1257  if (flags & IMAP_CMD_SINGLE)
1258  {
1259  // Process any existing commands
1260  if (adata->nextcmd != adata->lastcmd)
1261  imap_exec(adata, NULL, IMAP_CMD_POLL);
1262  }
1263 
1264  rc = cmd_start(adata, cmdstr, flags);
1265  if (rc < 0)
1266  {
1267  cmd_handle_fatal(adata);
1268  return IMAP_EXEC_FATAL;
1269  }
1270 
1271  if (flags & IMAP_CMD_QUEUE)
1272  return IMAP_EXEC_SUCCESS;
1273 
1274  const short c_imap_poll_timeout =
1275  cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1276  if ((flags & IMAP_CMD_POLL) && (c_imap_poll_timeout > 0) &&
1277  ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1278  {
1279  mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1280  cmd_handle_fatal(adata);
1281  return IMAP_EXEC_FATAL;
1282  }
1283 
1284  /* Allow interruptions, particularly useful if there are network problems. */
1286  do
1287  {
1288  rc = imap_cmd_step(adata);
1289  // The queue is empty, so the single command has been processed
1290  if ((flags & IMAP_CMD_SINGLE) && (adata->nextcmd == adata->lastcmd))
1291  break;
1292  } while (rc == IMAP_RES_CONTINUE);
1293  mutt_sig_allow_interrupt(false);
1294 
1295  if (rc == IMAP_RES_NO)
1296  return IMAP_EXEC_ERROR;
1297  if (rc != IMAP_RES_OK)
1298  {
1299  if (adata->status != IMAP_FATAL)
1300  return IMAP_EXEC_ERROR;
1301 
1302  mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1303  return IMAP_EXEC_FATAL;
1304  }
1305 
1306  return IMAP_EXEC_SUCCESS;
1307 }
#define IMAP_CMD_POLL
Poll the tcp connection before running the imap command.
Definition: private.h:76
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:192
+ 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 1386 of file command.c.

1387 {
1388  int rc;
1389 
1390  if (cmd_start(adata, "IDLE", IMAP_CMD_POLL) < 0)
1391  {
1392  cmd_handle_fatal(adata);
1393  return -1;
1394  }
1395 
1396  const short c_imap_poll_timeout =
1397  cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1398  if ((c_imap_poll_timeout > 0) &&
1399  ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1400  {
1401  mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1402  cmd_handle_fatal(adata);
1403  return -1;
1404  }
1405 
1406  do
1407  {
1408  rc = imap_cmd_step(adata);
1409  } while (rc == IMAP_RES_CONTINUE);
1410 
1411  if (rc == IMAP_RES_RESPOND)
1412  {
1413  /* successfully entered IDLE state */
1414  adata->state = IMAP_IDLE;
1415  /* queue automatic exit when next command is issued */
1416  mutt_buffer_addstr(&adata->cmdbuf, "DONE\r\n");
1417  rc = IMAP_RES_OK;
1418  }
1419  if (rc != IMAP_RES_OK)
1420  {
1421  mutt_debug(LL_DEBUG1, "error starting IDLE\n");
1422  return -1;
1423  }
1424 
1425  return 0;
1426 }
+ Here is the call 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 1305 of file message.c.

1307 {
1308  int oldmsgcount;
1309  unsigned int maxuid = 0;
1310  int retval = -1;
1311  bool evalhc = false;
1312 
1313 #ifdef USE_HCACHE
1314  void *uidvalidity = NULL;
1315  void *puid_next = NULL;
1316  unsigned int uid_next = 0;
1317  bool has_condstore = false;
1318  bool has_qresync = false;
1319  bool eval_condstore = false;
1320  bool eval_qresync = false;
1321  unsigned long long *pmodseq = NULL;
1322  unsigned long long hc_modseq = 0;
1323  char *uid_seqset = NULL;
1324 #endif /* USE_HCACHE */
1325 
1326  struct ImapAccountData *adata = imap_adata_get(m);
1327  struct ImapMboxData *mdata = imap_mdata_get(m);
1328  if (!adata || (adata->mailbox != m))
1329  return -1;
1330 
1331 #ifdef USE_HCACHE
1332 retry:
1333 #endif /* USE_HCACHE */
1334 
1335  /* make sure context has room to hold the mailbox */
1336  while (msn_end > m->email_max)
1337  mx_alloc_memory(m);
1338  imap_msn_reserve(&mdata->msn, msn_end);
1339  imap_alloc_uid_hash(adata, msn_end);
1340 
1341  oldmsgcount = m->msg_count;
1343  mdata->new_mail_count = 0;
1344 
1345 #ifdef USE_HCACHE
1346  imap_hcache_open(adata, mdata);
1347 
1348  if (mdata->hcache && initial_download)
1349  {
1350  size_t dlen = 0;
1351  uidvalidity = mutt_hcache_fetch_raw(mdata->hcache, "/UIDVALIDITY", 12, &dlen);
1352  puid_next = mutt_hcache_fetch_raw(mdata->hcache, "/UIDNEXT", 8, &dlen);
1353  if (puid_next)
1354  {
1355  uid_next = *(unsigned int *) puid_next;
1356  mutt_hcache_free_raw(mdata->hcache, &puid_next);
1357  }
1358 
1359  if (mdata->modseq)
1360  {
1361  const bool c_imap_condstore =
1362  cs_subset_bool(NeoMutt->sub, "imap_condstore");
1363  if ((adata->capabilities & IMAP_CAP_CONDSTORE) && c_imap_condstore)
1364  has_condstore = true;
1365 
1366  /* If IMAP_CAP_QRESYNC and ImapQResync then NeoMutt sends ENABLE QRESYNC.
1367  * If we receive an ENABLED response back, then adata->qresync is set. */
1368  if (adata->qresync)
1369  has_qresync = true;
1370  }
1371 
1372  if (uidvalidity && uid_next && (*(uint32_t *) uidvalidity == mdata->uidvalidity))
1373  {
1374  size_t dlen2 = 0;
1375  evalhc = true;
1376  pmodseq = mutt_hcache_fetch_raw(mdata->hcache, "/MODSEQ", 7, &dlen2);
1377  if (pmodseq)
1378  {
1379  hc_modseq = *pmodseq;
1380  mutt_hcache_free_raw(mdata->hcache, (void **) &pmodseq);
1381  }
1382  if (hc_modseq)
1383  {
1384  if (has_qresync)
1385  {
1386  uid_seqset = imap_hcache_get_uid_seqset(mdata);
1387  if (uid_seqset)
1388  eval_qresync = true;
1389  }
1390 
1391  if (!eval_qresync && has_condstore)
1392  eval_condstore = true;
1393  }
1394  }
1396  }
1397  if (evalhc)
1398  {
1399  if (eval_qresync)
1400  {
1401  if (read_headers_qresync_eval_cache(adata, uid_seqset) < 0)
1402  goto bail;
1403  }
1404  else
1405  {
1406  if (read_headers_normal_eval_cache(adata, msn_end, uid_next, has_condstore || has_qresync,
1407  eval_condstore) < 0)
1408  goto bail;
1409  }
1410 
1411  if ((eval_condstore || eval_qresync) && (hc_modseq != mdata->modseq))
1412  {
1414  hc_modseq, eval_qresync) < 0)
1415  {
1416  goto bail;
1417  }
1418  }
1419 
1420  /* Look for the first empty MSN and start there */
1421  while (msn_begin <= msn_end)
1422  {
1423  if (!imap_msn_get(&mdata->msn, msn_begin - 1))
1424  break;
1425  msn_begin++;
1426  }
1427  }
1428 #endif /* USE_HCACHE */
1429 
1430  if (read_headers_fetch_new(m, msn_begin, msn_end, evalhc, &maxuid, initial_download) < 0)
1431  goto bail;
1432 
1433 #ifdef USE_HCACHE
1434  if (eval_qresync && initial_download)
1435  {
1436  if (imap_verify_qresync(m) != 0)
1437  {
1438  eval_qresync = false;
1439  eval_condstore = false;
1440  evalhc = false;
1441  hc_modseq = 0;
1442  maxuid = 0;
1443  FREE(&uid_seqset);
1444  uidvalidity = NULL;
1445  uid_next = 0;
1446 
1447  goto retry;
1448  }
1449  }
1450 #endif /* USE_HCACHE */
1451 
1452  if (maxuid && (mdata->uid_next < maxuid + 1))
1453  mdata->uid_next = maxuid + 1;
1454 
1455 #ifdef USE_HCACHE
1456  mutt_hcache_store_raw(mdata->hcache, "/UIDVALIDITY", 12, &mdata->uidvalidity,
1457  sizeof(mdata->uidvalidity));
1458  if (maxuid && (mdata->uid_next < maxuid + 1))
1459  {
1460  mutt_debug(LL_DEBUG2, "Overriding UIDNEXT: %u -> %u\n", mdata->uid_next, maxuid + 1);
1461  mdata->uid_next = maxuid + 1;
1462  }
1463  if (mdata->uid_next > 1)
1464  {
1465  mutt_hcache_store_raw(mdata->hcache, "/UIDNEXT", 8, &mdata->uid_next,
1466  sizeof(mdata->uid_next));
1467  }
1468 
1469  /* We currently only sync CONDSTORE and QRESYNC on the initial download.
1470  * To do it more often, we'll need to deal with flag updates combined with
1471  * unsync'ed local flag changes. We'll also need to properly sync flags to
1472  * the header cache on close. I'm not sure it's worth the added complexity. */
1473  if (initial_download)
1474  {
1475  if (has_condstore || has_qresync)
1476  {
1477  mutt_hcache_store_raw(mdata->hcache, "/MODSEQ", 7, &mdata->modseq,
1478  sizeof(mdata->modseq));
1479  }
1480  else
1481  mutt_hcache_delete_record(mdata->hcache, "/MODSEQ", 7);
1482 
1483  if (has_qresync)
1485  else
1487  }
1488 #endif /* USE_HCACHE */
1489 
1490  if (m->msg_count > oldmsgcount)
1491  {
1492  /* TODO: it's not clear to me why we are calling mx_alloc_memory
1493  * yet again. */
1494  mx_alloc_memory(m);
1495  }
1496 
1497  mdata->reopen |= IMAP_REOPEN_ALLOW;
1498 
1499  retval = msn_end;
1500 
1501 bail:
1502 #ifdef USE_HCACHE
1504  FREE(&uid_seqset);
1505 #endif /* USE_HCACHE */
1506 
1507  return retval;
1508 }
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:640
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:618
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:544
void * mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message's header from the cache.
Definition: hcache.c:524
static int imap_verify_qresync(struct Mailbox *m)
Check to see if QRESYNC got jumbled.
Definition: message.c:983
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:884
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:1056
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:667
static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *uid_seqset)
Retrieve data from the header cache.
Definition: message.c:812
static void imap_alloc_uid_hash(struct ImapAccountData *adata, unsigned int msn_count)
Create a Hash Table for the UIDs.
Definition: message.c:511
char * imap_hcache_get_uid_seqset(struct ImapMboxData *mdata)
Get a UID Sequence Set from the header cache.
Definition: util.c:452
int imap_hcache_store_uid_seqset(struct ImapMboxData *mdata)
Store a UID Sequence Set in the header cache.
Definition: util.c:416
int imap_hcache_clear_uid_seqset(struct ImapMboxData *mdata)
Delete a UID Sequence Set from the header cache.
Definition: util.c:438
void imap_msn_reserve(struct MSN *msn, size_t num)
Create / reallocate the cache.
Definition: msn.c:40
struct Email * imap_msn_get(const struct MSN *msn, size_t idx)
Return the Email associated with an msn.
Definition: msn.c:79
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
Definition: mx.c:1218
bool qresync
true, if QRESYNC is successfully ENABLE'd
Definition: adata.h:63
unsigned int uid_next
Definition: mdata.h:51
uint32_t uidvalidity
Definition: mdata.h:50
+ 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 1876 of file message.c.

1877 {
1878  struct ImapAccountData *adata = imap_adata_get(m);
1879  if (!adata || (adata->mailbox != m))
1880  return NULL;
1881 
1882  struct ImapHeader newh = { 0 };
1883  struct ImapEmailData old_edata = { 0 };
1884  int local_changes = e->changed;
1885 
1886  struct ImapEmailData *edata = e->edata;
1887  newh.edata = edata;
1888 
1889  mutt_debug(LL_DEBUG2, "parsing FLAGS\n");
1890  s = msg_parse_flags(&newh, s);
1891  if (!s)
1892  return NULL;
1893 
1894  /* Update tags system */
1895  /* We take a copy of the tags so we can split the string */
1896  char *tags_copy = mutt_str_dup(edata->flags_remote);
1897  driver_tags_replace(&e->tags, tags_copy);
1898  FREE(&tags_copy);
1899 
1900  /* YAUH (yet another ugly hack): temporarily set context to
1901  * read-write even if it's read-only, so *server* updates of
1902  * flags can be processed by mutt_set_flag. mailbox->changed must
1903  * be restored afterwards */
1904  bool readonly = m->readonly;
1905  m->readonly = false;
1906 
1907  /* This is redundant with the following two checks. Removing:
1908  * mutt_set_flag (m, e, MUTT_NEW, !(edata->read || edata->old)); */
1909  set_changed_flag(m, e, local_changes, server_changes, MUTT_OLD, old_edata.old,
1910  edata->old, e->old);
1911  set_changed_flag(m, e, local_changes, server_changes, MUTT_READ,
1912  old_edata.read, edata->read, e->read);
1913  set_changed_flag(m, e, local_changes, server_changes, MUTT_DELETE,
1914  old_edata.deleted, edata->deleted, e->deleted);
1915  set_changed_flag(m, e, local_changes, server_changes, MUTT_FLAG,
1916  old_edata.flagged, edata->flagged, e->flagged);
1917  set_changed_flag(m, e, local_changes, server_changes, MUTT_REPLIED,
1918  old_edata.replied, edata->replied, e->replied);
1919 
1920  /* this message is now definitively *not* changed (mutt_set_flag
1921  * marks things changed as a side-effect) */
1922  if (local_changes == 0)
1923  e->changed = false;
1924  m->changed &= !readonly;
1925  m->readonly = readonly;
1926 
1927  return s;
1928 }
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:627
static char * msg_parse_flags(struct ImapHeader *h, char *s)
Read a FLAGS token into an ImapHeader.
Definition: message.c:191
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:181
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:92
@ MUTT_OLD
Old messages.
Definition: mutt.h:90
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:98
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:94
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:91
IMAP-specific Email data -.
Definition: edata.h:34
bool deleted
Email has been deleted.
Definition: edata.h:38
bool old
Email has been seen.
Definition: edata.h:37
bool read
Email has been read.
Definition: edata.h:36
bool flagged
Email has been flagged.
Definition: edata.h:39
bool replied
Email has been replied to.
Definition: edata.h:40
IMAP-specific header.
Definition: message.h:33
struct ImapEmailData * edata
Definition: message.h:34
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:119
bool driver_tags_replace(struct TagList *head, const char *tags)
Replace all tags.
Definition: tags.c:185
+ 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 1825 of file message.c.

1826 {
1827  struct ImapAccountData *adata = imap_adata_get(m);
1828  struct ImapMboxData *mdata = imap_mdata_get(m);
1829 
1830  if (!e || !adata || (adata->mailbox != m))
1831  return -1;
1832 
1833  mdata->bcache = msg_cache_open(m);
1834  char id[64];
1835  snprintf(id, sizeof(id), "%u-%u", mdata->uidvalidity, imap_edata_get(e)->uid);
1836  return mutt_bcache_del(mdata->bcache, id);
1837 }
int mutt_bcache_del(struct BodyCache *bcache, const char *id)
Delete a file from the Body Cache.
Definition: bcache.c:266
static struct BodyCache * msg_cache_open(struct Mailbox *m)
Open a message cache.
Definition: message.c:79
+ 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 1844 of file message.c.

1845 {
1846  struct ImapAccountData *adata = imap_adata_get(m);
1847  struct ImapMboxData *mdata = imap_mdata_get(m);
1848 
1849  if (!adata || (adata->mailbox != m))
1850  return -1;
1851 
1852  mdata->bcache = msg_cache_open(m);
1854 
1855  return 0;
1856 }
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
Definition: bcache.c:331
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
+ Here is the call 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 1517 of file message.c.

1518 {
1519  if (!m || !msg)
1520  return -1;
1521 
1522  FILE *fp = NULL;
1523  char buf[1024 * 2];
1524  char internaldate[IMAP_DATELEN];
1525  char imap_flags[128];
1526  size_t len;
1527  struct Progress *progress = NULL;
1528  size_t sent;
1529  int c, last;
1530  int rc;
1531 
1532  struct ImapAccountData *adata = imap_adata_get(m);
1533  struct ImapMboxData *mdata = imap_mdata_get(m);
1534 
1535  fp = fopen(msg->path, "r");
1536  if (!fp)
1537  {
1538  mutt_perror(msg->path);
1539  goto fail;
1540  }
1541 
1542  /* currently we set the \Seen flag on all messages, but probably we
1543  * should scan the message Status header for flag info. Since we're
1544  * already rereading the whole file for length it isn't any more
1545  * expensive (it'd be nice if we had the file size passed in already
1546  * by the code that writes the file, but that's a lot of changes.
1547  * Ideally we'd have an Email structure with flag info here... */
1548  for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c)
1549  {
1550  if ((c == '\n') && (last != '\r'))
1551  len++;
1552 
1553  len++;
1554  }
1555  rewind(fp);
1556 
1557  if (m->verbose)
1558  progress = progress_new(_("Uploading message..."), MUTT_PROGRESS_NET, len);
1559 
1560  mutt_date_make_imap(internaldate, sizeof(internaldate), msg->received);
1561 
1562  imap_flags[0] = '\0';
1563  imap_flags[1] = '\0';
1564 
1565  if (msg->flags.read)
1566  mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Seen");
1567  if (msg->flags.replied)
1568  mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Answered");
1569  if (msg->flags.flagged)
1570  mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Flagged");
1571  if (msg->flags.draft)
1572  mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Draft");
1573 
1574  snprintf(buf, sizeof(buf), "APPEND %s (%s) \"%s\" {%lu}", mdata->munge_name,
1575  imap_flags + 1, internaldate, (unsigned long) len);
1576 
1577  imap_cmd_start(adata, buf);
1578 
1579  do
1580  {
1581  rc = imap_cmd_step(adata);
1582  } while (rc == IMAP_RES_CONTINUE);
1583 
1584  if (rc != IMAP_RES_RESPOND)
1585  goto cmd_step_fail;
1586 
1587  for (last = EOF, sent = len = 0; (c = fgetc(fp)) != EOF; last = c)
1588  {
1589  if ((c == '\n') && (last != '\r'))
1590  buf[len++] = '\r';
1591 
1592  buf[len++] = c;
1593 
1594  if (len > sizeof(buf) - 3)
1595  {
1596  sent += len;
1597  if (flush_buffer(buf, &len, adata->conn) < 0)
1598  goto fail;
1599  if (m->verbose)
1600  progress_update(progress, sent, -1);
1601  }
1602  }
1603 
1604  if (len)
1605  if (flush_buffer(buf, &len, adata->conn) < 0)
1606  goto fail;
1607 
1608  if (mutt_socket_send(adata->conn, "\r\n") < 0)
1609  goto fail;
1610  mutt_file_fclose(&fp);
1611 
1612  do
1613  {
1614  rc = imap_cmd_step(adata);
1615  } while (rc == IMAP_RES_CONTINUE);
1616 
1617  if (rc != IMAP_RES_OK)
1618  goto cmd_step_fail;
1619 
1620  progress_free(&progress);
1621  return 0;
1622 
1623 cmd_step_fail:
1624  mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1625  if (rc != IMAP_RES_BAD)
1626  {
1627  char *pc = imap_next_word(adata->buf); /* skip sequence number or token */
1628  pc = imap_next_word(pc); /* skip response code */
1629  if (*pc != '\0')
1630  mutt_error("%s", pc);
1631  }
1632 
1633 fail:
1634  mutt_file_fclose(&fp);
1635  progress_free(&progress);
1636  return -1;
1637 }
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
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_perror(...)
Definition: logging.h:88
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1068
static int flush_buffer(char *buf, size_t *len, struct Connection *conn)
Write data to a connection.
Definition: message.c:471
#define IMAP_DATELEN
Definition: private.h:90
#define mutt_socket_send(conn, buf)
Definition: mutt_socket.h:37
@ MUTT_PROGRESS_NET
Progress tracks bytes, according to $net_inc
Definition: lib.h:48
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:232
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:252
bool verbose
Display status messages?
Definition: mailbox.h:118
char * path
path to temp file
Definition: mxapi.h:44
bool draft
Message has been read.
Definition: mxapi.h:52
bool replied
Message has been replied to.
Definition: mxapi.h:51
time_t received
Time at which this message was received.
Definition: mxapi.h:54
bool flagged
Message is flagged.
Definition: mxapi.h:50
bool read
Message has been read.
Definition: mxapi.h:49
struct Message::@0 flags
Flags for the Message.
A Progress Bar.
Definition: progress.c:49
+ 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 }
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
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 HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:335
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
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:404
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
Header cache structure.
Definition: lib.h:87
struct HeaderCache * hcache
Email header cache.
Definition: mdata.h:62
char * name
Mailbox name.
Definition: mdata.h:40
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:69
char * path
Path.
Definition: url.h:75
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
#define U_PATH
Definition: url.h:50
void imap_cachepath(char delim, const char *mailbox, struct Buffer *dest)
Generate a cache path for a mailbox.
Definition: util.c:719
+ 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 }
void mutt_hcache_close(struct HeaderCache *hc)
Multiplexor for StoreOps::close.
Definition: hcache.c:438
+ 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 }
struct HCacheEntry mutt_hcache_fetch(struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:464
Wrapper for Email retrieved from the header cache.
Definition: lib.h:98
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:99
struct Email * email
Retrieved email.
Definition: lib.h:101
+ 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 }
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:559
+ 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 }
+ 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 }
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
+ 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 }
+ 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 }
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:359
#define NONULL(x)
Definition: string2.h:37
+ 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 590 of file util.c.

655 {
656  imap_error(msg, resp);
657  return mutt_yesorno(_("Continue?"), MUTT_NO);
658 }
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:38
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:182
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition: util.c:665
+ 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 }
+ 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_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
Definition: bcache.c:166
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
void imap_msn_free(struct MSN *msn)
Free the cache.
Definition: msn.c:58
struct BodyCache * bcache
Email body cache.
Definition: mdata.h:60
+ 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 }
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
static size_t plen
Length of cached packet.
Definition: pgppacket.c: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 }
+ 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))
762  return -1;
763 
764  return 0;
765 }
const char * mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: atoi.c:202
+ 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 IS_SPACE(ch)
Definition: string2.h:38
#define SKIPWS(ch)
Definition: string2.h:46
+ 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 }
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
#define U_NO_FLAGS
Definition: url.h:49
+ 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 }
+ 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 }
void imap_utf_encode(bool unicode, char **s)
Encode email from local charset to UTF-8.
Definition: utf7.c:390
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
+ 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_utf_decode(bool unicode, char **s)
Decode email from UTF-8 to local charset.
Definition: utf7.c:420
void imap_unquote_string(char *s)
Equally stupid unquoting routine.
Definition: util.c:877
+ 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 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
UID Sequence Set Iterator.
Definition: private.h:170
char * eostr
Definition: private.h:172
char * substr_end
Definition: private.h:178
char * substr_cur
Definition: private.h:177
char * full_seqset
Definition: private.h:171
+ 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_full(iter->substr_cur, &iter->range_cur))
1133  return -1;
1134  if (range_sep)
1135  {
1136  if (!mutt_str_atoui_full(range_sep, &iter->range_end))
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 }
unsigned int range_end
Definition: private.h:176
unsigned int range_cur
Definition: private.h:175
+ 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 }
+ 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 MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:44
@ MUTT_ACCT_TYPE_IMAP
Imap Account.
Definition: mutt_account.h:37
char * Username
User's login name.
Definition: mutt_globals.h:52
char user[128]
Username.
Definition: connaccount.h:56
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
Definition: connaccount.h:59
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:60
unsigned short port
Port to connect to.
Definition: connaccount.h:58
+ 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_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:560
+ 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 390 of file utf7.c.

391 {
392  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
393  if (!c_charset || !s || !*s)
394  return;
395 
396  if (unicode && mutt_ch_is_utf8(c_charset))
397  {
398  return;
399  }
400 
401  if (mutt_ch_convert_string(s, c_charset, "utf-8", MUTT_ICONV_NO_FLAGS) != 0)
402  {
403  FREE(s);
404  return;
405  }
406 
407  if (!unicode)
408  {
409  char *utf7 = utf8_to_utf7(*s, strlen(*s), NULL, 0);
410  FREE(s);
411  *s = utf7;
412  }
413 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:764
#define mutt_ch_is_utf8(str)
Definition: charset.h:95
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
static char * utf8_to_utf7(const char *u8, size_t u8len, char **u7, size_t *u7len)
Convert data from UTF-8 to RFC2060's UTF-7.
Definition: utf7.c:249
+ 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 420 of file utf7.c.

421 {
422  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
423  if (!c_charset || !s || !*s)
424  return;
425 
426  if (unicode && mutt_ch_is_utf8(c_charset))
427  {
428  return;
429  }
430 
431  if (!unicode)
432  {
433  char *utf8 = utf7_to_utf8(*s, strlen(*s), 0, 0);
434  FREE(s);
435  *s = utf8;
436  }
437 
438  if (mutt_ch_convert_string(s, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS) != 0)
439  {
440  FREE(s);
441  }
442 }
static char * utf7_to_utf8(const char *u7, size_t u7len, char **u8, size_t *u8len)
Convert data from RFC2060's UTF-7 to UTF-8.
Definition: utf7.c:105
+ 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 }
+ Here is the call 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 }
+ Here is the call 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))
270  continue;
271  e = mutt_hash_int_find(mdata->uid_hash, uid);
272  if (e)
273  e->matched = true;
274  }
275 }
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:392
bool matched
Search matches this Email.
Definition: email.h:102
+ Here is the call graph for this function:
+ Here is the caller graph for this function: