NeoMutt  2022-04-29-247-gc6aae8
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 *progress)
 Read bytes bytes from server into file. More...
 
void imap_expunge_mailbox (struct Mailbox *m, bool resort)
 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{
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 */
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 447 of file imap.c.

448{
449 char buf[2048], mbox[1024];
450
451 imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), mailbox);
452 snprintf(buf, sizeof(buf), "CREATE %s", mbox);
453
455 {
456 mutt_error(_("CREATE failed: %s"), imap_cmd_trailer(adata));
457 return -1;
458 }
459
460 return 0;
461}
#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:1210
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:1247
#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:911
#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 488 of file imap.c.

489{
490 char oldmbox[1024] = { 0 };
491 char newmbox[1024] = { 0 };
492 int rc = 0;
493
494 imap_munge_mbox_name(adata->unicode, oldmbox, sizeof(oldmbox), oldname);
495 imap_munge_mbox_name(adata->unicode, newmbox, sizeof(newmbox), newname);
496
497 struct Buffer *buf = mutt_buffer_pool_get();
498 mutt_buffer_printf(buf, "RENAME %s %s", oldmbox, newmbox);
499
501 rc = -1;
502
504
505 return rc;
506}
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
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{
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 mv 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);
970 {
971 rc = -1;
972 goto out;
973 }
974 count += rc;
975 }
976 } while (rc > 0);
977
978 rc = count;
979
980out:
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:67
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:211
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
static int compare_uid(const void *a, const void *b)
Compare two Emails by UID - Implements sort_t -.
Definition: imap.c:904
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:89
#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:197
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:43
@ 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:88
int email_max
Number of pointers in emails.
Definition: mailbox.h:97
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
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 747 of file imap.c.

748{
749 if (mutt_socket_open(adata->conn) < 0)
750 return -1;
751
752 adata->state = IMAP_CONNECTED;
753
754 if (imap_cmd_step(adata) != IMAP_RES_OK)
755 {
757 return -1;
758 }
759
760 if (mutt_istr_startswith(adata->buf, "* OK"))
761 {
762 if (!mutt_istr_startswith(adata->buf, "* OK [CAPABILITY") && check_capabilities(adata))
763 {
764 goto bail;
765 }
766#ifdef USE_SSL
767 /* Attempt STARTTLS if available and desired. */
768 const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
769 if ((adata->conn->ssf == 0) &&
770 (c_ssl_force_tls || (adata->capabilities & IMAP_CAP_STARTTLS)))
771 {
772 enum QuadOption ans;
773
774 const enum QuadOption c_ssl_starttls = cs_subset_quad(NeoMutt->sub, "ssl_starttls");
775 if (c_ssl_force_tls)
776 ans = MUTT_YES;
777 else if ((ans = query_quadoption(c_ssl_starttls, _("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
843bail:
845 FREE(&adata->capstr);
846 return -1;
847}
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 mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
Definition: gnutls.c:1143
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1076
#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:663
#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:239
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:386
void mutt_socket_empty(struct Connection *conn)
Clear out any queued data.
Definition: socket.c:314
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:77
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:98
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 *  progress 
)

Read bytes bytes from server into file.

Parameters
fpFile handle for email file
adataImap Account data
bytesNumber of bytes to read
progressProgress 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 598 of file imap.c.

600{
601 char c;
602 bool r = false;
603 struct Buffer buf = { 0 }; // Do not allocate, maybe it won't be used
604
605 const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
606 if (c_debug_level >= IMAP_LOG_LTRL)
607 mutt_buffer_alloc(&buf, bytes + 1);
608
609 mutt_debug(LL_DEBUG2, "reading %lu bytes\n", bytes);
610
611 for (unsigned long pos = 0; pos < bytes; pos++)
612 {
613 if (mutt_socket_readchar(adata->conn, &c) != 1)
614 {
615 mutt_debug(LL_DEBUG1, "error during read, %lu bytes read\n", pos);
616 adata->status = IMAP_FATAL;
617
619 return -1;
620 }
621
622 if (r && (c != '\n'))
623 fputc('\r', fp);
624
625 if (c == '\r')
626 {
627 r = true;
628 continue;
629 }
630 else
631 r = false;
632
633 fputc(c, fp);
634
635 if (progress && !(pos % 1024))
636 progress_update(progress, pos, -1);
637 if (c_debug_level >= IMAP_LOG_LTRL)
638 mutt_buffer_addch(&buf, c);
639 }
640
641 if (c_debug_level >= IMAP_LOG_LTRL)
642 {
643 mutt_debug(IMAP_LOG_LTRL, "\n%s", buf.data);
645 }
646 return 0;
647}
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:275
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
#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
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:73
int mutt_socket_readchar(struct Connection *conn, char *c)
Simple read buffering to speed things up.
Definition: socket.c:211
+ 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,
bool  resort 
)

Purge messages from the server.

Parameters
mMailbox
resortTrigger a resort?

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 675 of file imap.c.

676{
678 struct ImapMboxData *mdata = imap_mdata_get(m);
679 if (!adata || !mdata)
680 return;
681
682 struct Email *e = NULL;
683
684#ifdef USE_HCACHE
685 imap_hcache_open(adata, mdata);
686#endif
687
688 for (int i = 0; i < m->msg_count; i++)
689 {
690 e = m->emails[i];
691 if (!e)
692 break;
693
694 if (e->index == INT_MAX)
695 {
696 mutt_debug(LL_DEBUG2, "Expunging message UID %u\n", imap_edata_get(e)->uid);
697
698 e->deleted = true;
699
700 imap_cache_del(m, e);
701#ifdef USE_HCACHE
702 imap_hcache_del(mdata, imap_edata_get(e)->uid);
703#endif
704
705 mutt_hash_int_delete(mdata->uid_hash, imap_edata_get(e)->uid, e);
706
707 imap_edata_free((void **) &e->edata);
708 }
709 else
710 {
711 /* NeoMutt has several places where it turns off e->active as a
712 * hack. For example to avoid FLAG updates, or to exclude from
713 * imap_exec_msgset.
714 *
715 * Unfortunately, when a reopen is allowed and the IMAP_EXPUNGE_PENDING
716 * flag becomes set (e.g. a flag update to a modified header),
717 * this function will be called by imap_cmd_finish().
718 *
719 * The ctx_update_tables() will free and remove these "inactive" headers,
720 * despite that an EXPUNGE was not received for them.
721 * This would result in memory leaks and segfaults due to dangling
722 * pointers in the msn_index and uid_hash.
723 *
724 * So this is another hack to work around the hacks. We don't want to
725 * remove the messages, so make sure active is on. */
726 e->active = true;
727 }
728 }
729
730#ifdef USE_HCACHE
731 imap_hcache_close(mdata);
732#endif
733
735 if (resort)
736 {
738 }
739}
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:65
void imap_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: edata.c:39
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:1857
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:339
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition: util.c:398
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:222
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:177
@ NT_MAILBOX_UPDATE
Update internal tables.
Definition: mailbox.h:178
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:132
+ 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 1848 of file imap.c.

1849{
1850 if (!adata)
1851 return -1;
1852
1853 if (adata->state == IMAP_DISCONNECTED)
1854 {
1855 mutt_buffer_reset(&adata->cmdbuf); // purge outstanding queued commands
1856 imap_open_connection(adata);
1857 }
1858 if (adata->state == IMAP_CONNECTED)
1859 {
1861 {
1862 adata->state = IMAP_AUTHENTICATED;
1863 FREE(&adata->capstr);
1864 if (adata->conn->ssf != 0)
1865 {
1866 mutt_debug(LL_DEBUG2, "Communication encrypted at %d bits\n",
1867 adata->conn->ssf);
1868 }
1869 }
1870 else
1872 }
1873 if (adata->state == IMAP_AUTHENTICATED)
1874 {
1875 /* capabilities may have changed */
1876 imap_exec(adata, "CAPABILITY", IMAP_CMD_PASS);
1877
1878#ifdef USE_ZLIB
1879 /* RFC4978 */
1880 const bool c_imap_deflate = cs_subset_bool(NeoMutt->sub, "imap_deflate");
1881 if ((adata->capabilities & IMAP_CAP_COMPRESS) && c_imap_deflate &&
1882 (imap_exec(adata, "COMPRESS DEFLATE", IMAP_CMD_PASS) == IMAP_EXEC_SUCCESS))
1883 {
1884 mutt_debug(LL_DEBUG2, "IMAP compression is enabled on connection to %s\n",
1885 adata->conn->account.host);
1886 mutt_zstrm_wrap_conn(adata->conn);
1887 }
1888#endif
1889
1890 /* enable RFC6855, if the server supports that */
1891 const bool c_imap_rfc5161 = cs_subset_bool(NeoMutt->sub, "imap_rfc5161");
1892 if (c_imap_rfc5161 && (adata->capabilities & IMAP_CAP_ENABLE))
1893 imap_exec(adata, "ENABLE UTF8=ACCEPT", IMAP_CMD_QUEUE);
1894
1895 /* enable QRESYNC. Advertising QRESYNC also means CONDSTORE
1896 * is supported (even if not advertised), so flip that bit. */
1897 if (adata->capabilities & IMAP_CAP_QRESYNC)
1898 {
1900 const bool c_imap_qresync = cs_subset_bool(NeoMutt->sub, "imap_qresync");
1901 if (c_imap_rfc5161 && c_imap_qresync)
1902 imap_exec(adata, "ENABLE QRESYNC", IMAP_CMD_QUEUE);
1903 }
1904
1905 /* get root delimiter, '/' as default */
1906 adata->delim = '/';
1907 imap_exec(adata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
1908
1909 /* we may need the root delimiter before we open a mailbox */
1910 imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1911
1912 /* select the mailbox that used to be open before disconnect */
1913 if (adata->mailbox)
1914 {
1915 imap_mbox_select(adata->mailbox);
1916 }
1917 }
1918
1919 if (adata->state < IMAP_AUTHENTICATED)
1920 return -1;
1921
1922 return 0;
1923}
@ IMAP_AUTH_SUCCESS
Authentication successful.
Definition: auth.h:39
void mutt_account_unsetpass(struct ConnAccount *cac)
Unset ConnAccount's password.
Definition: connaccount.c:177
int imap_authenticate(struct ImapAccountData *adata)
Authenticate to an IMAP server.
Definition: auth.c:110
#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:747
static void imap_mbox_select(struct Mailbox *m)
Select a Mailbox.
Definition: imap.c:1815
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{
1011 if (!adata || (adata->mailbox != m))
1012 return -1;
1013
1014 char flags[1024] = { 0 };
1015 char *tags = NULL;
1016 char uid[11] = { 0 };
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 */
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:233
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:652
static void set_flag(struct Mailbox *m, AclFlags aclflag, bool flag, const char *str, char *flags, size_t flsize)
Append str to flags if we currently have permission according to aclflag.
Definition: imap.c:176
static bool compare_flags_for_copy(struct Email *e)
Compare local flags against the server.
Definition: imap.c:298
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:63
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:71
#define MUTT_ACL_SEEN
Change the 'seen' status of a message.
Definition: mailbox.h:70
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:636
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:265
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:117
char * driver_tags_get_with_hidden(struct TagList *list)
Get tags with hiddens.
Definition: tags.c:158
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_has_flag()

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

Does the flag exist in the list.

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

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

Definition at line 878 of file imap.c.

879{
880 if (STAILQ_EMPTY(flag_list))
881 return false;
882
883 const size_t flaglen = mutt_str_len(flag);
884 struct ListNode *np = NULL;
885 STAILQ_FOREACH(np, flag_list, entries)
886 {
887 const size_t nplen = strlen(np->data);
888 if ((flaglen >= nplen) && ((flag[nplen] == '\0') || (flag[nplen] == ' ')) &&
889 mutt_istrn_equal(np->data, flag, nplen))
890 {
891 return true;
892 }
893
894 if (mutt_str_equal(np->data, "\\*"))
895 return true;
896 }
897
898 return false;
899}
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
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:524
#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] = { 0 };
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:50
#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:482
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1044
+ 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 110 of file auth.c.

111{
112 int rc = IMAP_AUTH_FAILURE;
113
114 const struct Slist *c_imap_authenticators = cs_subset_slist(NeoMutt->sub, "imap_authenticators");
115 if (c_imap_authenticators && (c_imap_authenticators->count > 0))
116 {
117 mutt_debug(LL_DEBUG2, "Trying user-defined imap_authenticators\n");
118
119 /* Try user-specified list of authentication methods */
120 struct ListNode *np = NULL;
121 STAILQ_FOREACH(np, &c_imap_authenticators->head, entries)
122 {
123 mutt_debug(LL_DEBUG2, "Trying method %s\n", np->data);
124
125 for (size_t i = 0; i < mutt_array_size(ImapAuthenticators); i++)
126 {
127 const struct ImapAuth *auth = &ImapAuthenticators[i];
128 if (!auth->method || mutt_istr_equal(auth->method, np->data))
129 {
130 rc = auth->authenticate(adata, np->data);
131 if (rc == IMAP_AUTH_SUCCESS)
132 {
133 return rc;
134 }
135 }
136 }
137 }
138 }
139 else
140 {
141 /* Fall back to default: any authenticator */
142 mutt_debug(LL_DEBUG2, "Trying pre-defined imap_authenticators\n");
143
144 for (size_t i = 0; i < mutt_array_size(ImapAuthenticators); i++)
145 {
146 rc = ImapAuthenticators[i].authenticate(adata, NULL);
147 if (rc == IMAP_AUTH_SUCCESS)
148 return rc;
149 }
150 }
151
152 mutt_error(_("No authenticators available or wrong credentials"));
153 return rc;
154}
@ 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:36
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
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 1062 of file command.c.

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

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

1313{
1314 if (!adata)
1315 return;
1316
1317 if (adata->status == IMAP_FATAL)
1318 {
1319 adata->closing = false;
1320 cmd_handle_fatal(adata);
1321 return;
1322 }
1323
1324 if (!(adata->state >= IMAP_SELECTED) || (adata->mailbox && adata->closing))
1325 {
1326 adata->closing = false;
1327 return;
1328 }
1329
1330 adata->closing = false;
1331
1332 struct ImapMboxData *mdata = imap_mdata_get(adata->mailbox);
1333
1334 if (mdata && mdata->reopen & IMAP_REOPEN_ALLOW)
1335 {
1336 // First remove expunged emails from the msn_index
1337 if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1338 {
1339 mutt_debug(LL_DEBUG2, "Expunging mailbox\n");
1340 imap_expunge_mailbox(adata->mailbox, true);
1341 /* Detect whether we've gotten unexpected EXPUNGE messages */
1342 if (!(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1343 mdata->check_status |= IMAP_EXPUNGE_PENDING;
1345 }
1346
1347 // Then add new emails to it
1348 if (mdata->reopen & IMAP_NEWMAIL_PENDING)
1349 {
1350 const size_t max_msn = imap_msn_highest(&mdata->msn);
1351 if (mdata->new_mail_count > max_msn)
1352 {
1353 if (!(mdata->reopen & IMAP_EXPUNGE_PENDING))
1354 mdata->check_status |= IMAP_NEWMAIL_PENDING;
1355
1356 mutt_debug(LL_DEBUG2, "Fetching new mails from %ld to %u\n",
1357 max_msn + 1, mdata->new_mail_count);
1358 imap_read_headers(adata->mailbox, max_msn + 1, mdata->new_mail_count, false);
1359 }
1360 }
1361
1362 // And to finish inform about MUTT_REOPEN if needed
1363 if (mdata->reopen & IMAP_EXPUNGE_PENDING && !(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1364 mdata->check_status |= IMAP_EXPUNGE_PENDING;
1365
1366 if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1368 }
1369
1370 adata->status = 0;
1371}
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:1327
#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, bool resort)
Purge messages from the server.
Definition: imap.c:675
size_t imap_msn_highest(const struct MSN *msn)
Return the highest MSN in use.
Definition: msn.c:69
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 1199 of file command.c.

1200{
1201 return cmd_status(s) == IMAP_RES_OK;
1202}
+ 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 1210 of file command.c.

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

1248{
1249 int rc;
1250
1251 if (flags & IMAP_CMD_SINGLE)
1252 {
1253 // Process any existing commands
1254 if (adata->nextcmd != adata->lastcmd)
1255 imap_exec(adata, NULL, IMAP_CMD_POLL);
1256 }
1257
1258 rc = cmd_start(adata, cmdstr, flags);
1259 if (rc < 0)
1260 {
1261 cmd_handle_fatal(adata);
1262 return IMAP_EXEC_FATAL;
1263 }
1264
1265 if (flags & IMAP_CMD_QUEUE)
1266 return IMAP_EXEC_SUCCESS;
1267
1268 const short c_imap_poll_timeout = cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1269 if ((flags & IMAP_CMD_POLL) && (c_imap_poll_timeout > 0) &&
1270 ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1271 {
1272 mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1273 cmd_handle_fatal(adata);
1274 return IMAP_EXEC_FATAL;
1275 }
1276
1277 /* Allow interruptions, particularly useful if there are network problems. */
1279 do
1280 {
1281 rc = imap_cmd_step(adata);
1282 // The queue is empty, so the single command has been processed
1283 if ((flags & IMAP_CMD_SINGLE) && (adata->nextcmd == adata->lastcmd))
1284 break;
1285 } while (rc == IMAP_RES_CONTINUE);
1287
1288 if (rc == IMAP_RES_NO)
1289 return IMAP_EXEC_ERROR;
1290 if (rc != IMAP_RES_OK)
1291 {
1292 if (adata->status != IMAP_FATAL)
1293 return IMAP_EXEC_ERROR;
1294
1295 mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1296 return IMAP_EXEC_FATAL;
1297 }
1298
1299 return IMAP_EXEC_SUCCESS;
1300}
#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:193
+ 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 1379 of file command.c.

1380{
1381 int rc;
1382
1383 if (cmd_start(adata, "IDLE", IMAP_CMD_POLL) < 0)
1384 {
1385 cmd_handle_fatal(adata);
1386 return -1;
1387 }
1388
1389 const short c_imap_poll_timeout = cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1390 if ((c_imap_poll_timeout > 0) &&
1391 ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1392 {
1393 mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1394 cmd_handle_fatal(adata);
1395 return -1;
1396 }
1397
1398 do
1399 {
1400 rc = imap_cmd_step(adata);
1401 } while (rc == IMAP_RES_CONTINUE);
1402
1403 if (rc == IMAP_RES_RESPOND)
1404 {
1405 /* successfully entered IDLE state */
1406 adata->state = IMAP_IDLE;
1407 /* queue automatic exit when next command is issued */
1408 mutt_buffer_addstr(&adata->cmdbuf, "DONE\r\n");
1409 rc = IMAP_RES_OK;
1410 }
1411 if (rc != IMAP_RES_OK)
1412 {
1413 mutt_debug(LL_DEBUG1, "error starting IDLE\n");
1414 return -1;
1415 }
1416
1417 return 0;
1418}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_read_headers()

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

Read headers from the server.

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

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

Definition at line 1327 of file message.c.

1329{
1330 int oldmsgcount;
1331 unsigned int maxuid = 0;
1332 int retval = -1;
1333 bool evalhc = false;
1334
1335#ifdef USE_HCACHE
1336 void *uidvalidity = NULL;
1337 void *puid_next = NULL;
1338 unsigned int uid_next = 0;
1339 bool has_condstore = false;
1340 bool has_qresync = false;
1341 bool eval_condstore = false;
1342 bool eval_qresync = false;
1343 unsigned long long hc_modseq = 0;
1344 char *uid_seqset = NULL;
1345 const unsigned int msn_begin_save = msn_begin;
1346#endif /* USE_HCACHE */
1347
1349 struct ImapMboxData *mdata = imap_mdata_get(m);
1350 if (!adata || (adata->mailbox != m))
1351 return -1;
1352
1353#ifdef USE_HCACHE
1354retry:
1355#endif /* USE_HCACHE */
1356
1357 /* make sure context has room to hold the mailbox */
1358 while (msn_end > m->email_max)
1359 mx_alloc_memory(m);
1360 imap_msn_reserve(&mdata->msn, msn_end);
1361 imap_alloc_uid_hash(adata, msn_end);
1362
1363 oldmsgcount = m->msg_count;
1365 mdata->new_mail_count = 0;
1366
1367#ifdef USE_HCACHE
1368 imap_hcache_open(adata, mdata);
1369
1370 if (mdata->hcache && initial_download)
1371 {
1372 size_t dlen = 0;
1373 uidvalidity = mutt_hcache_fetch_raw(mdata->hcache, "/UIDVALIDITY", 12, &dlen);
1374 if (uidvalidity && (dlen < sizeof(uint32_t)))
1375 {
1377 uidvalidity = NULL;
1378 }
1379 puid_next = mutt_hcache_fetch_raw(mdata->hcache, "/UIDNEXT", 8, &dlen);
1380 if (puid_next)
1381 {
1382 if (dlen >= sizeof(unsigned int))
1383 {
1384 uid_next = *(unsigned int *) puid_next;
1385 }
1386 mutt_hcache_free_raw(mdata->hcache, &puid_next);
1387 }
1388
1389 if (mdata->modseq)
1390 {
1391 const bool c_imap_condstore = cs_subset_bool(NeoMutt->sub, "imap_condstore");
1392 if ((adata->capabilities & IMAP_CAP_CONDSTORE) && c_imap_condstore)
1393 has_condstore = true;
1394
1395 /* If IMAP_CAP_QRESYNC and ImapQResync then NeoMutt sends ENABLE QRESYNC.
1396 * If we receive an ENABLED response back, then adata->qresync is set. */
1397 if (adata->qresync)
1398 has_qresync = true;
1399 }
1400
1401 if (uidvalidity && uid_next && (*(uint32_t *) uidvalidity == mdata->uidvalidity))
1402 {
1403 size_t dlen2 = 0;
1404 evalhc = true;
1405 const unsigned long long *pmodseq = mutt_hcache_fetch_raw(mdata->hcache,
1406 "/MODSEQ", 7, &dlen2);
1407 if (pmodseq)
1408 {
1409 if (dlen2 >= sizeof(unsigned long long))
1410 {
1411 hc_modseq = *pmodseq;
1412 }
1413 mutt_hcache_free_raw(mdata->hcache, (void **) &pmodseq);
1414 }
1415 if (hc_modseq)
1416 {
1417 if (has_qresync)
1418 {
1419 uid_seqset = imap_hcache_get_uid_seqset(mdata);
1420 if (uid_seqset)
1421 eval_qresync = true;
1422 }
1423
1424 if (!eval_qresync && has_condstore)
1425 eval_condstore = true;
1426 }
1427 }
1429 }
1430 if (evalhc)
1431 {
1432 if (eval_qresync)
1433 {
1434 if (read_headers_qresync_eval_cache(adata, uid_seqset) < 0)
1435 goto bail;
1436 }
1437 else
1438 {
1439 if (read_headers_normal_eval_cache(adata, msn_end, uid_next, has_condstore || has_qresync,
1440 eval_condstore) < 0)
1441 goto bail;
1442 }
1443
1444 if ((eval_condstore || eval_qresync) && (hc_modseq != mdata->modseq))
1445 {
1447 hc_modseq, eval_qresync) < 0)
1448 {
1449 goto bail;
1450 }
1451 }
1452
1453 /* Look for the first empty MSN and start there */
1454 while (msn_begin <= msn_end)
1455 {
1456 if (!imap_msn_get(&mdata->msn, msn_begin - 1))
1457 break;
1458 msn_begin++;
1459 }
1460 }
1461#endif /* USE_HCACHE */
1462
1463 if (read_headers_fetch_new(m, msn_begin, msn_end, evalhc, &maxuid, initial_download) < 0)
1464 goto bail;
1465
1466#ifdef USE_HCACHE
1467 if (eval_qresync && initial_download)
1468 {
1469 if (imap_verify_qresync(m) != 0)
1470 {
1471 eval_qresync = false;
1472 eval_condstore = false;
1473 evalhc = false;
1474 hc_modseq = 0;
1475 maxuid = 0;
1476 FREE(&uid_seqset);
1477 uidvalidity = NULL;
1478 uid_next = 0;
1479 msn_begin = msn_begin_save;
1480
1481 goto retry;
1482 }
1483 }
1484#endif /* USE_HCACHE */
1485
1486 if (maxuid && (mdata->uid_next < maxuid + 1))
1487 mdata->uid_next = maxuid + 1;
1488
1489#ifdef USE_HCACHE
1490 mutt_hcache_store_raw(mdata->hcache, "/UIDVALIDITY", 12, &mdata->uidvalidity,
1491 sizeof(mdata->uidvalidity));
1492 if (maxuid && (mdata->uid_next < maxuid + 1))
1493 {
1494 mutt_debug(LL_DEBUG2, "Overriding UIDNEXT: %u -> %u\n", mdata->uid_next, maxuid + 1);
1495 mdata->uid_next = maxuid + 1;
1496 }
1497 if (mdata->uid_next > 1)
1498 {
1499 mutt_hcache_store_raw(mdata->hcache, "/UIDNEXT", 8, &mdata->uid_next,
1500 sizeof(mdata->uid_next));
1501 }
1502
1503 /* We currently only sync CONDSTORE and QRESYNC on the initial download.
1504 * To do it more often, we'll need to deal with flag updates combined with
1505 * unsync'ed local flag changes. We'll also need to properly sync flags to
1506 * the header cache on close. I'm not sure it's worth the added complexity. */
1507 if (initial_download)
1508 {
1509 if (has_condstore || has_qresync)
1510 {
1511 mutt_hcache_store_raw(mdata->hcache, "/MODSEQ", 7, &mdata->modseq,
1512 sizeof(mdata->modseq));
1513 }
1514 else
1515 mutt_hcache_delete_record(mdata->hcache, "/MODSEQ", 7);
1516
1517 if (has_qresync)
1519 else
1521 }
1522#endif /* USE_HCACHE */
1523
1524 if (m->msg_count > oldmsgcount)
1525 {
1526 /* TODO: it's not clear to me why we are calling mx_alloc_memory
1527 * yet again. */
1528 mx_alloc_memory(m);
1529 }
1530
1531 mdata->reopen |= IMAP_REOPEN_ALLOW;
1532
1533 retval = msn_end;
1534
1535bail:
1536#ifdef USE_HCACHE
1538 FREE(&uid_seqset);
1539#endif /* USE_HCACHE */
1540
1541 return retval;
1542}
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:519
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:631
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:610
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:538
static int imap_verify_qresync(struct Mailbox *m)
Check to see if QRESYNC got jumbled.
Definition: message.c:995
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:896
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:1072
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:664
static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *uid_seqset)
Retrieve data from the header cache.
Definition: message.c:809
static void imap_alloc_uid_hash(struct ImapAccountData *adata, unsigned int msn_count)
Create a Hash Table for the UIDs.
Definition: message.c:509
int imap_hcache_store_uid_seqset(struct ImapMboxData *mdata)
Store a UID Sequence Set in the header cache.
Definition: util.c:415
char * imap_hcache_get_uid_seqset(struct ImapMboxData *mdata)
Get a UID Sequence Set from the header cache.
Definition: util.c:451
int imap_hcache_clear_uid_seqset(struct ImapMboxData *mdata)
Delete a UID Sequence Set from the header cache.
Definition: util.c:437
void imap_msn_reserve(struct MSN *msn, size_t num)
Create / reallocate the cache.
Definition: msn.c:41
struct Email * imap_msn_get(const struct MSN *msn, size_t idx)
Return the Email associated with an msn.
Definition: msn.c:80
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
Definition: mx.c:1219
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 1908 of file message.c.

1909{
1911 if (!adata || (adata->mailbox != m))
1912 return NULL;
1913
1914 struct ImapHeader newh = { 0 };
1915 struct ImapEmailData old_edata = { 0 };
1916 int local_changes = e->changed;
1917
1918 struct ImapEmailData *edata = e->edata;
1919 newh.edata = edata;
1920
1921 mutt_debug(LL_DEBUG2, "parsing FLAGS\n");
1922 s = msg_parse_flags(&newh, s);
1923 if (!s)
1924 return NULL;
1925
1926 /* Update tags system */
1927 /* We take a copy of the tags so we can split the string */
1928 char *tags_copy = mutt_str_dup(edata->flags_remote);
1929 driver_tags_replace(&e->tags, tags_copy);
1930 FREE(&tags_copy);
1931
1932 /* YAUH (yet another ugly hack): temporarily set context to
1933 * read-write even if it's read-only, so *server* updates of
1934 * flags can be processed by mutt_set_flag. mailbox->changed must
1935 * be restored afterwards */
1936 bool readonly = m->readonly;
1937 m->readonly = false;
1938
1939 /* This is redundant with the following two checks. Removing:
1940 * mutt_set_flag (m, e, MUTT_NEW, !(edata->read || edata->old)); */
1941 set_changed_flag(m, e, local_changes, server_changes, MUTT_OLD, old_edata.old,
1942 edata->old, e->old);
1943 set_changed_flag(m, e, local_changes, server_changes, MUTT_READ,
1944 old_edata.read, edata->read, e->read);
1945 set_changed_flag(m, e, local_changes, server_changes, MUTT_DELETE,
1946 old_edata.deleted, edata->deleted, e->deleted);
1947 set_changed_flag(m, e, local_changes, server_changes, MUTT_FLAG,
1948 old_edata.flagged, edata->flagged, e->flagged);
1949 set_changed_flag(m, e, local_changes, server_changes, MUTT_REPLIED,
1950 old_edata.replied, edata->replied, e->replied);
1951
1952 /* this message is now definitively *not* changed (mutt_set_flag
1953 * marks things changed as a side-effect) */
1954 if (local_changes == 0)
1955 e->changed = false;
1956 m->changed &= !readonly;
1957 m->readonly = readonly;
1958
1959 return s;
1960}
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:624
static char * msg_parse_flags(struct ImapHeader *h, char *s)
Read a FLAGS token into an ImapHeader.
Definition: message.c:190
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:93
@ MUTT_OLD
Old messages.
Definition: mutt.h:91
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:99
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:95
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:92
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:110
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:115
bool driver_tags_replace(struct TagList *head, const char *tags)
Replace all tags.
Definition: tags.c:186
+ 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 1857 of file message.c.

1858{
1860 struct ImapMboxData *mdata = imap_mdata_get(m);
1861
1862 if (!e || !adata || (adata->mailbox != m))
1863 return -1;
1864
1865 mdata->bcache = msg_cache_open(m);
1866 char id[64] = { 0 };
1867 snprintf(id, sizeof(id), "%u-%u", mdata->uidvalidity, imap_edata_get(e)->uid);
1868 return mutt_bcache_del(mdata->bcache, id);
1869}
int mutt_bcache_del(struct BodyCache *bcache, const char *id)
Delete a file from the Body Cache.
Definition: bcache.c:265
static struct BodyCache * msg_cache_open(struct Mailbox *m)
Open a message cache.
Definition: message.c:78
+ 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 1876 of file message.c.

1877{
1879 struct ImapMboxData *mdata = imap_mdata_get(m);
1880
1881 if (!adata || (adata->mailbox != m))
1882 return -1;
1883
1884 mdata->bcache = msg_cache_open(m);
1886
1887 return 0;
1888}
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
Definition: bcache.c:330
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:167
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_append_message()

int imap_append_message ( struct Mailbox m,
struct Message msg 
)

Write an email back to the server.

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

Definition at line 1551 of file message.c.

1552{
1553 if (!m || !msg)
1554 return -1;
1555
1556 FILE *fp = NULL;
1557 char buf[1024 * 2];
1558 char internaldate[IMAP_DATELEN] = { 0 };
1559 char imap_flags[128] = { 0 };
1560 size_t len;
1561 struct Progress *progress = NULL;
1562 size_t sent;
1563 int c, last;
1564 int rc;
1565
1567 struct ImapMboxData *mdata = imap_mdata_get(m);
1568
1569 fp = fopen(msg->path, "r");
1570 if (!fp)
1571 {
1572 mutt_perror(msg->path);
1573 goto fail;
1574 }
1575
1576 /* currently we set the \Seen flag on all messages, but probably we
1577 * should scan the message Status header for flag info. Since we're
1578 * already rereading the whole file for length it isn't any more
1579 * expensive (it'd be nice if we had the file size passed in already
1580 * by the code that writes the file, but that's a lot of changes.
1581 * Ideally we'd have an Email structure with flag info here... */
1582 for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c)
1583 {
1584 if ((c == '\n') && (last != '\r'))
1585 len++;
1586
1587 len++;
1588 }
1589 rewind(fp);
1590
1591 if (m->verbose)
1592 progress = progress_new(_("Uploading message..."), MUTT_PROGRESS_NET, len);
1593
1594 mutt_date_make_imap(internaldate, sizeof(internaldate), msg->received);
1595
1596 imap_flags[0] = '\0';
1597 imap_flags[1] = '\0';
1598
1599 if (msg->flags.read)
1600 mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Seen");
1601 if (msg->flags.replied)
1602 mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Answered");
1603 if (msg->flags.flagged)
1604 mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Flagged");
1605 if (msg->flags.draft)
1606 mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Draft");
1607
1608 snprintf(buf, sizeof(buf), "APPEND %s (%s) \"%s\" {%lu}", mdata->munge_name,
1609 imap_flags + 1, internaldate, (unsigned long) len);
1610
1611 imap_cmd_start(adata, buf);
1612
1613 do
1614 {
1615 rc = imap_cmd_step(adata);
1616 } while (rc == IMAP_RES_CONTINUE);
1617
1618 if (rc != IMAP_RES_RESPOND)
1619 goto cmd_step_fail;
1620
1621 for (last = EOF, sent = len = 0; (c = fgetc(fp)) != EOF; last = c)
1622 {
1623 if ((c == '\n') && (last != '\r'))
1624 buf[len++] = '\r';
1625
1626 buf[len++] = c;
1627
1628 if (len > sizeof(buf) - 3)
1629 {
1630 sent += len;
1631 if (flush_buffer(buf, &len, adata->conn) < 0)
1632 goto fail;
1633 if (m->verbose)
1634 progress_update(progress, sent, -1);
1635 }
1636 }
1637
1638 if (len)
1639 if (flush_buffer(buf, &len, adata->conn) < 0)
1640 goto fail;
1641
1642 if (mutt_socket_send(adata->conn, "\r\n") < 0)
1643 goto fail;
1644 mutt_file_fclose(&fp);
1645
1646 do
1647 {
1648 rc = imap_cmd_step(adata);
1649 } while (rc == IMAP_RES_CONTINUE);
1650
1651 if (rc != IMAP_RES_OK)
1652 goto cmd_step_fail;
1653
1654 progress_free(&progress);
1655 return 0;
1656
1657cmd_step_fail:
1658 mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1659 if (rc != IMAP_RES_BAD)
1660 {
1661 char *pc = imap_next_word(adata->buf); /* skip sequence number or token */
1662 pc = imap_next_word(pc); /* skip response code */
1663 if (*pc != '\0')
1664 mutt_error("%s", pc);
1665 }
1666
1667fail:
1668 mutt_file_fclose(&fp);
1669 progress_free(&progress);
1670 return -1;
1671}
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:558
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#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:1062
static int flush_buffer(char *buf, size_t *len, struct Connection *conn)
Write data to a connection.
Definition: message.c:469
#define IMAP_DATELEN
Definition: private.h:90
@ MUTT_PROGRESS_NET
Progress tracks bytes, according to $net_inc
Definition: lib.h:51
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:86
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:118
#define mutt_socket_send(conn, buf)
Definition: socket.h:59
bool verbose
Display status messages?
Definition: mailbox.h:114
char * path
path to temp file
Definition: mxapi.h:45
bool draft
Message has been read.
Definition: mxapi.h:53
bool replied
Message has been replied to.
Definition: mxapi.h:52
time_t received
Time at which this message was received.
Definition: mxapi.h:55
bool flagged
Message is flagged.
Definition: mxapi.h:51
bool read
Message has been read.
Definition: mxapi.h:50
struct Message::@0 flags
Flags for the Message.
+ 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 = cs_subset_path(NeoMutt->sub, "header_cache");
327 hc = mutt_hcache_open(c_header_cache, mutt_buffer_string(cachepath), imap_hcache_namer);
328
329cleanup:
331 mutt_buffer_pool_release(&cachepath);
332 mdata->hcache = hc;
333}
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:371
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
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:332
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:496
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:716
+ 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 339 of file util.c.

340{
341 if (!mdata->hcache)
342 return;
343
345 mdata->hcache = NULL;
346}
void mutt_hcache_close(struct HeaderCache *hc)
Multiplexor for StoreOps::close.
Definition: hcache.c:432
+ 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 355 of file util.c.

356{
357 if (!mdata->hcache)
358 return NULL;
359
360 char key[16] = { 0 };
361
362 sprintf(key, "/%u", uid);
363 struct HCacheEntry hce = mutt_hcache_fetch(mdata->hcache, key, mutt_str_len(key),
364 mdata->uidvalidity);
365 if (!hce.email && hce.uidvalidity)
366 {
367 mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %u\n", hce.uidvalidity);
368 }
369
370 return hce.email;
371}
struct HCacheEntry mutt_hcache_fetch(struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:456
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 380 of file util.c.

381{
382 if (!mdata->hcache)
383 return -1;
384
385 char key[16] = { 0 };
386
387 sprintf(key, "/%u", imap_edata_get(e)->uid);
388 return mutt_hcache_store(mdata->hcache, key, mutt_str_len(key), e, mdata->uidvalidity);
389}
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:552
+ 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 398 of file util.c.

399{
400 if (!mdata->hcache)
401 return -1;
402
403 char key[16] = { 0 };
404
405 sprintf(key, "/%u", uid);
406 return mutt_hcache_delete_record(mdata->hcache, key, mutt_str_len(key));
407}
+ 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 415 of file util.c.

416{
417 if (!mdata->hcache)
418 return -1;
419
420 /* The seqset is likely large. Preallocate to reduce reallocs */
421 struct Buffer buf = mutt_buffer_make(8192);
422 imap_msn_index_to_uid_seqset(&buf, mdata);
423
424 int rc = mutt_hcache_store_raw(mdata->hcache, "/UIDSEQSET", 10, buf.data,
425 mutt_buffer_len(&buf) + 1);
426 mutt_debug(LL_DEBUG3, "Stored /UIDSEQSET %s\n", buf.data);
428 return rc;
429}
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 437 of file util.c.

438{
439 if (!mdata->hcache)
440 return -1;
441
442 return mutt_hcache_delete_record(mdata->hcache, "/UIDSEQSET", 10);
443}
+ 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 451 of file util.c.

452{
453 if (!mdata->hcache)
454 return NULL;
455
456 char *seqset = NULL;
457 size_t dlen = 0;
458 char *hc_seqset = mutt_hcache_fetch_raw(mdata->hcache, "/UIDSEQSET", 10, &dlen);
459 if (hc_seqset)
460 {
461 seqset = mutt_strn_dup(hc_seqset, dlen);
462 mutt_hcache_free_raw(mdata->hcache, (void **) &hc_seqset);
463 }
464 mutt_debug(LL_DEBUG3, "Retrieved /UIDSEQSET %s\n", NONULL(seqset));
465
466 return seqset;
467}
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:451
#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 652 of file util.c.

653{
654 imap_error(msg, resp);
655 return mutt_yesorno(_("Continue?"), MUTT_NO);
656}
@ 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:194
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition: util.c:663
+ 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 663 of file util.c.

664{
665 mutt_error("%s [%s]", where, msg);
666}
+ 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:165
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:59
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 685 of file util.c.

686{
687 int i = 0;
688 for (; mailbox && *mailbox && (i < plen - 1); i++)
689 {
690 const char *const c_imap_delim_chars = cs_subset_string(NeoMutt->sub, "imap_delim_chars");
691 if (*mailbox == delim || (!delim && strchr(NONULL(c_imap_delim_chars), *mailbox)))
692 {
693 delim = *mailbox;
694 /* Skip multiple occurrences of delim */
695 while (*mailbox && *(mailbox + 1) == delim)
696 mailbox++;
697 }
698 path[i] = *mailbox++;
699 }
700
701 /* Do not terminate with a delimiter */
702 if (i && path[i - 1] == delim)
703 i--;
704
705 /* Ensure null termination */
706 path[i] = '\0';
707 return path;
708}
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 716 of file util.c.

717{
718 const char *p = mailbox;
719 mutt_buffer_reset(dest);
720 if (!p)
721 return;
722
723 while (*p)
724 {
725 if (p[0] == delim)
726 {
727 mutt_buffer_addch(dest, '/');
728 /* simple way to avoid collisions with UIDs */
729 if ((p[1] >= '0') && (p[1] <= '9'))
730 mutt_buffer_addch(dest, '_');
731 }
732 else
733 mutt_buffer_addch(dest, *p);
734 p++;
735 }
736}
+ 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 745 of file util.c.

746{
747 char *pc = NULL;
748 char *pn = NULL;
749
750 if (!buf || !(pc = strchr(buf, '{')))
751 return -1;
752
753 pc++;
754 pn = pc;
755 while (isdigit((unsigned char) *pc))
756 pc++;
757 *pc = '\0';
758 if (!mutt_str_atoui(pn, bytes))
759 return -1;
760
761 return 0;
762}
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 772 of file util.c.

773{
774 char *s = buf;
775
776 /* skip tag */
777 s = imap_next_word(s);
778 /* skip OK/NO/BAD response */
779 s = imap_next_word(s);
780
781 return s;
782}
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:789
+ 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 789 of file util.c.

790{
791 bool quoted = false;
792
793 while (*s)
794 {
795 if (*s == '\\')
796 {
797 s++;
798 if (*s)
799 s++;
800 continue;
801 }
802 if (*s == '\"')
803 quoted = !quoted;
804 if (!quoted && IS_SPACE(*s))
805 break;
806 s++;
807 }
808
809 SKIPWS(s);
810 return s;
811}
#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 820 of file util.c.

821{
822 struct Url url = { 0 };
823 mutt_account_tourl(cac, &url);
824 url.path = path;
825 url_tostring(&url, buf, buflen, U_NO_FLAGS);
826}
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 837 of file util.c.

838{
839 const char *quote = "`\"\\";
840 if (!quote_backtick)
841 quote++;
842
843 char *pt = dest;
844 const char *s = src;
845
846 *pt++ = '"';
847 /* save room for quote-chars */
848 dlen -= 3;
849
850 for (; *s && dlen; s++)
851 {
852 if (strchr(quote, *s))
853 {
854 if (dlen < 2)
855 break;
856 dlen -= 2;
857 *pt++ = '\\';
858 *pt++ = *s;
859 }
860 else
861 {
862 *pt++ = *s;
863 dlen--;
864 }
865 }
866 *pt++ = '"';
867 *pt = '\0';
868}
+ 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 874 of file util.c.

875{
876 char *d = s;
877
878 if (*s == '\"')
879 s++;
880 else
881 return;
882
883 while (*s)
884 {
885 if (*s == '\"')
886 {
887 *d = '\0';
888 return;
889 }
890 if (*s == '\\')
891 {
892 s++;
893 }
894 if (*s)
895 {
896 *d = *s;
897 d++;
898 s++;
899 }
900 }
901 *d = '\0';
902}
+ 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 911 of file util.c.

912{
913 char *buf = mutt_str_dup(src);
914 imap_utf_encode(unicode, &buf);
915
916 imap_quote_string(dest, dlen, buf, false);
917
918 FREE(&buf);
919}
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:837
+ 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 928 of file util.c.

929{
931
932 char *buf = mutt_str_dup(s);
933 if (buf)
934 {
935 imap_utf_decode(unicode, &buf);
936 strncpy(s, buf, strlen(s));
937 }
938
939 FREE(&buf);
940}
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:874
+ 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 1076 of file util.c.

1077{
1078 if (!seqset || (*seqset == '\0'))
1079 return NULL;
1080
1081 struct SeqsetIterator *iter = mutt_mem_calloc(1, sizeof(struct SeqsetIterator));
1082 iter->full_seqset = mutt_str_dup(seqset);
1083 iter->eostr = strchr(iter->full_seqset, '\0');
1084 iter->substr_cur = iter->substr_end = iter->full_seqset;
1085
1086 return iter;
1087}
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 1097 of file util.c.

1098{
1099 if (!iter || !next)
1100 return -1;
1101
1102 if (iter->in_range)
1103 {
1104 if ((iter->down && (iter->range_cur == (iter->range_end - 1))) ||
1105 (!iter->down && (iter->range_cur == (iter->range_end + 1))))
1106 {
1107 iter->in_range = 0;
1108 }
1109 }
1110
1111 if (!iter->in_range)
1112 {
1113 iter->substr_cur = iter->substr_end;
1114 if (iter->substr_cur == iter->eostr)
1115 return 1;
1116
1117 iter->substr_end = strchr(iter->substr_cur, ',');
1118 if (!iter->substr_end)
1119 iter->substr_end = iter->eostr;
1120 else
1121 *(iter->substr_end++) = '\0';
1122
1123 char *range_sep = strchr(iter->substr_cur, ':');
1124 if (range_sep)
1125 *range_sep++ = '\0';
1126
1127 if (!mutt_str_atoui_full(iter->substr_cur, &iter->range_cur))
1128 return -1;
1129 if (range_sep)
1130 {
1131 if (!mutt_str_atoui_full(range_sep, &iter->range_end))
1132 return -1;
1133 }
1134 else
1135 iter->range_end = iter->range_cur;
1136
1137 iter->down = (iter->range_end < iter->range_cur);
1138 iter->in_range = 1;
1139 }
1140
1141 *next = iter->range_cur;
1142 if (iter->down)
1143 iter->range_cur--;
1144 else
1145 iter->range_cur++;
1146
1147 return 0;
1148}
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 1154 of file util.c.

1155{
1156 if (!ptr || !*ptr)
1157 return;
1158
1159 struct SeqsetIterator *iter = *ptr;
1160 FREE(&iter->full_seqset);
1161 FREE(ptr);
1162}
+ 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 1044 of file util.c.

1045{
1046 if (!a1 || !a2)
1047 return false;
1048 if (a1->type != a2->type)
1049 return false;
1050 if (!mutt_istr_equal(a1->host, a2->host))
1051 return false;
1052 if ((a1->port != 0) && (a2->port != 0) && (a1->port != a2->port))
1053 return false;
1054 if (a1->flags & a2->flags & MUTT_ACCT_USER)
1055 return strcmp(a1->user, a2->user) == 0;
1056
1057 const char *user = NONULL(Username);
1058
1059 const char *const c_imap_user = cs_subset_string(NeoMutt->sub, "imap_user");
1060 if ((a1->type == MUTT_ACCT_TYPE_IMAP) && c_imap_user)
1061 user = c_imap_user;
1062
1063 if (a1->flags & MUTT_ACCT_USER)
1064 return strcmp(a1->user, user) == 0;
1065 if (a2->flags & MUTT_ACCT_USER)
1066 return strcmp(a2->user, user) == 0;
1067
1068 return true;
1069}
#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:652
+ 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:752
#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 1016 of file util.c.

1017{
1019 struct ImapMboxData *mdata = imap_mdata_get(m);
1020 if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1021 return;
1022 mdata->reopen |= IMAP_REOPEN_ALLOW;
1023}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_disallow_reopen()

void imap_disallow_reopen ( struct Mailbox m)

Disallow re-opening a folder upon expunge.

Parameters
mMailbox

Definition at line 1029 of file util.c.

1030{
1032 struct ImapMboxData *mdata = imap_mdata_get(m);
1033 if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1034 return;
1035 mdata->reopen &= ~IMAP_REOPEN_ALLOW;
1036}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cmd_parse_search()

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

Store SEARCH response for later use.

Parameters
adataImap Account data
sCommand string with search results

Definition at line 259 of file search.c.

260{
261 unsigned int uid;
262 struct Email *e = NULL;
263 struct ImapMboxData *mdata = adata->mailbox->mdata;
264
265 mutt_debug(LL_DEBUG2, "Handling SEARCH\n");
266
267 while ((s = imap_next_word((char *) s)) && (*s != '\0'))
268 {
269 if (!mutt_str_atoui(s, &uid))
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: