NeoMutt  2023-05-17-56-ga67199
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 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_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_ID   (1 << 20)
 RFC2971: IMAP4 ID extension. More...
 
#define IMAP_CAP_ALL   ((1 << 21) - 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_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, struct Email *e)
 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 44 of file private.h.

◆ IMAP_SSL_PORT

#define IMAP_SSL_PORT   993

Port for IMAP over SSL/TLS.

Definition at line 45 of file private.h.

◆ IMAP_LOG_CMD

#define IMAP_LOG_CMD   2

Definition at line 48 of file private.h.

◆ IMAP_LOG_LTRL

#define IMAP_LOG_LTRL   3

Definition at line 49 of file private.h.

◆ IMAP_LOG_PASS

#define IMAP_LOG_PASS   5

Definition at line 50 of file private.h.

◆ IMAP_RES_NO

#define IMAP_RES_NO   -2

<tag> NO ...

Definition at line 53 of file private.h.

◆ IMAP_RES_BAD

#define IMAP_RES_BAD   -1

<tag> BAD ...

Definition at line 54 of file private.h.

◆ IMAP_RES_OK

#define IMAP_RES_OK   0

<tag> OK ...

Definition at line 55 of file private.h.

◆ IMAP_RES_CONTINUE

#define IMAP_RES_CONTINUE   1

* ...

Definition at line 56 of file private.h.

◆ IMAP_RES_RESPOND

#define IMAP_RES_RESPOND   2

+

Definition at line 57 of file private.h.

◆ IMAP_RES_NEW

#define IMAP_RES_NEW   3

ImapCommand.state additions.

Definition at line 58 of file private.h.

◆ SEQ_LEN

#define SEQ_LEN   16

Definition at line 60 of file private.h.

◆ IMAP_OPEN_NO_FLAGS

#define IMAP_OPEN_NO_FLAGS   0

No flags are set.

Definition at line 63 of file private.h.

◆ IMAP_REOPEN_ALLOW

#define IMAP_REOPEN_ALLOW   (1 << 0)

Allow re-opening a folder upon expunge.

Definition at line 64 of file private.h.

◆ IMAP_EXPUNGE_EXPECTED

#define IMAP_EXPUNGE_EXPECTED   (1 << 1)

Messages will be expunged from the server.

Definition at line 65 of file private.h.

◆ IMAP_EXPUNGE_PENDING

#define IMAP_EXPUNGE_PENDING   (1 << 2)

Messages on the server have been expunged.

Definition at line 66 of file private.h.

◆ IMAP_NEWMAIL_PENDING

#define IMAP_NEWMAIL_PENDING   (1 << 3)

New mail is waiting on the server.

Definition at line 67 of file private.h.

◆ IMAP_FLAGS_PENDING

#define IMAP_FLAGS_PENDING   (1 << 4)

Flags have changed on the server.

Definition at line 68 of file private.h.

◆ IMAP_CMD_NO_FLAGS

#define IMAP_CMD_NO_FLAGS   0

No flags are set.

Definition at line 71 of file private.h.

◆ IMAP_CMD_PASS

#define IMAP_CMD_PASS   (1 << 0)

Command contains a password. Suppress logging.

Definition at line 72 of file private.h.

◆ IMAP_CMD_QUEUE

#define IMAP_CMD_QUEUE   (1 << 1)

Queue a command, do not execute.

Definition at line 73 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 74 of file private.h.

◆ IMAP_CMD_SINGLE

#define IMAP_CMD_SINGLE   (1 << 3)

Run a single command.

Definition at line 75 of file private.h.

◆ IMAP_DATELEN

#define IMAP_DATELEN   27

Definition at line 88 of file private.h.

◆ IMAP_CAP_NO_FLAGS

#define IMAP_CAP_NO_FLAGS   0

No flags are set.

Definition at line 120 of file private.h.

◆ IMAP_CAP_IMAP4

#define IMAP_CAP_IMAP4   (1 << 0)

Server supports IMAP4.

Definition at line 121 of file private.h.

◆ IMAP_CAP_IMAP4REV1

#define IMAP_CAP_IMAP4REV1   (1 << 1)

Server supports IMAP4rev1.

Definition at line 122 of file private.h.

◆ IMAP_CAP_STATUS

#define IMAP_CAP_STATUS   (1 << 2)

Server supports STATUS command.

Definition at line 123 of file private.h.

◆ IMAP_CAP_ACL

#define IMAP_CAP_ACL   (1 << 3)

RFC2086: IMAP4 ACL extension.

Definition at line 124 of file private.h.

◆ IMAP_CAP_NAMESPACE

#define IMAP_CAP_NAMESPACE   (1 << 4)

RFC2342: IMAP4 Namespace.

Definition at line 125 of file private.h.

◆ IMAP_CAP_AUTH_CRAM_MD5

#define IMAP_CAP_AUTH_CRAM_MD5   (1 << 5)

RFC2195: CRAM-MD5 authentication.

Definition at line 126 of file private.h.

◆ IMAP_CAP_AUTH_GSSAPI

#define IMAP_CAP_AUTH_GSSAPI   (1 << 6)

RFC1731: GSSAPI authentication.

Definition at line 127 of file private.h.

◆ IMAP_CAP_AUTH_ANONYMOUS

#define IMAP_CAP_AUTH_ANONYMOUS   (1 << 7)

AUTH=ANONYMOUS.

Definition at line 128 of file private.h.

◆ IMAP_CAP_AUTH_OAUTHBEARER

#define IMAP_CAP_AUTH_OAUTHBEARER   (1 << 8)

RFC7628: AUTH=OAUTHBEARER.

Definition at line 129 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 130 of file private.h.

◆ IMAP_CAP_STARTTLS

#define IMAP_CAP_STARTTLS   (1 << 10)

RFC2595: STARTTLS.

Definition at line 131 of file private.h.

◆ IMAP_CAP_LOGINDISABLED

#define IMAP_CAP_LOGINDISABLED   (1 << 11)

RFC2595: LOGINDISABLED.

Definition at line 132 of file private.h.

◆ IMAP_CAP_IDLE

#define IMAP_CAP_IDLE   (1 << 12)

RFC2177: IDLE.

Definition at line 133 of file private.h.

◆ IMAP_CAP_SASL_IR

#define IMAP_CAP_SASL_IR   (1 << 13)

SASL initial response draft.

Definition at line 134 of file private.h.

◆ IMAP_CAP_ENABLE

#define IMAP_CAP_ENABLE   (1 << 14)

RFC5161.

Definition at line 135 of file private.h.

◆ IMAP_CAP_CONDSTORE

#define IMAP_CAP_CONDSTORE   (1 << 15)

RFC7162.

Definition at line 136 of file private.h.

◆ IMAP_CAP_QRESYNC

#define IMAP_CAP_QRESYNC   (1 << 16)

RFC7162.

Definition at line 137 of file private.h.

◆ IMAP_CAP_LIST_EXTENDED

#define IMAP_CAP_LIST_EXTENDED   (1 << 17)

RFC5258: IMAP4 LIST Command Extensions.

Definition at line 138 of file private.h.

◆ IMAP_CAP_COMPRESS

#define IMAP_CAP_COMPRESS   (1 << 18)

RFC4978: COMPRESS=DEFLATE.

Definition at line 139 of file private.h.

◆ IMAP_CAP_X_GM_EXT_1

#define IMAP_CAP_X_GM_EXT_1   (1 << 19)

◆ IMAP_CAP_ID

#define IMAP_CAP_ID   (1 << 20)

RFC2971: IMAP4 ID extension.

Definition at line 141 of file private.h.

◆ IMAP_CAP_ALL

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

Definition at line 143 of file private.h.

Typedef Documentation

◆ ImapOpenFlags

typedef uint8_t ImapOpenFlags

Flags, e.g. MUTT_THREAD_COLLAPSE.

Definition at line 62 of file private.h.

◆ ImapCmdFlags

typedef uint8_t ImapCmdFlags

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

Definition at line 70 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 119 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 80 of file private.h.

81{
85};
@ IMAP_EXEC_SUCCESS
Imap command executed or queued successfully.
Definition: private.h:82
@ IMAP_EXEC_ERROR
Imap command failure.
Definition: private.h:83
@ IMAP_EXEC_FATAL
Imap connection failure.
Definition: private.h:84

◆ ImapFlags

enum ImapFlags

IMAP server responses.

Enumerator
IMAP_FATAL 

Unrecoverable error occurred.

IMAP_BYE 

Logged out from server.

Definition at line 93 of file private.h.

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

◆ 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 102 of file private.h.

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

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

429{
430 char buf[2048], mbox[1024];
431
432 imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), mailbox);
433 snprintf(buf, sizeof(buf), "CREATE %s", mbox);
434
436 {
437 mutt_error(_("CREATE failed: %s"), imap_cmd_trailer(adata));
438 return -1;
439 }
440
441 return 0;
442}
#define mutt_error(...)
Definition: logging2.h:90
const char * imap_cmd_trailer(struct ImapAccountData *adata)
Extra information after tagged command response if any.
Definition: command.c:1247
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:1284
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:71
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:906
#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 469 of file imap.c.

470{
471 char oldmbox[1024] = { 0 };
472 char newmbox[1024] = { 0 };
473 int rc = 0;
474
475 imap_munge_mbox_name(adata->unicode, oldmbox, sizeof(oldmbox), oldname);
476 imap_munge_mbox_name(adata->unicode, newmbox, sizeof(newmbox), newname);
477
478 struct Buffer *buf = buf_pool_get();
479 buf_printf(buf, "RENAME %s %s", oldmbox, newmbox);
480
482 rc = -1;
483
484 buf_pool_release(&buf);
485
486 return rc;
487}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:90
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
String manipulation buffer.
Definition: buffer.h:34
+ 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 732 of file imap.c.

733{
734 if (mutt_socket_open(adata->conn) < 0)
735 return -1;
736
737 adata->state = IMAP_CONNECTED;
738
739 if (imap_cmd_step(adata) != IMAP_RES_OK)
740 {
742 return -1;
743 }
744
745 if (mutt_istr_startswith(adata->buf, "* OK"))
746 {
747 if (!mutt_istr_startswith(adata->buf, "* OK [CAPABILITY") && check_capabilities(adata))
748 {
749 goto bail;
750 }
751#ifdef USE_SSL
752 /* Attempt STARTTLS if available and desired. */
753 const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
754 if ((adata->conn->ssf == 0) &&
755 (c_ssl_force_tls || (adata->capabilities & IMAP_CAP_STARTTLS)))
756 {
757 enum QuadOption ans;
758
759 const enum QuadOption c_ssl_starttls = cs_subset_quad(NeoMutt->sub, "ssl_starttls");
760 if (c_ssl_force_tls)
761 {
762 ans = MUTT_YES;
763 }
764 else if ((ans = query_quadoption(c_ssl_starttls, _("Secure connection with TLS?"))) == MUTT_ABORT)
765 {
766 goto bail;
767 }
768 if (ans == MUTT_YES)
769 {
770 enum ImapExecResult rc = imap_exec(adata, "STARTTLS", IMAP_CMD_SINGLE);
771 // Clear any data after the STARTTLS acknowledgement
772 mutt_socket_empty(adata->conn);
773
774 if (rc == IMAP_EXEC_FATAL)
775 goto bail;
776 if (rc != IMAP_EXEC_ERROR)
777 {
778 if (mutt_ssl_starttls(adata->conn))
779 {
780 mutt_error(_("Could not negotiate TLS connection"));
781 goto bail;
782 }
783 else
784 {
785 /* RFC2595 demands we recheck CAPABILITY after TLS completes. */
786 if (imap_exec(adata, "CAPABILITY", IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
787 goto bail;
788 }
789 }
790 }
791 }
792
793 if (c_ssl_force_tls && (adata->conn->ssf == 0))
794 {
795 mutt_error(_("Encrypted connection unavailable"));
796 goto bail;
797 }
798#endif
799 }
800 else if (mutt_istr_startswith(adata->buf, "* PREAUTH"))
801 {
802#ifdef USE_SSL
803 /* Unless using a secure $tunnel, an unencrypted PREAUTH response may be a
804 * MITM attack. The only way to stop "STARTTLS" MITM attacks is via
805 * $ssl_force_tls: an attacker can easily spoof "* OK" and strip the
806 * STARTTLS capability. So consult $ssl_force_tls, not $ssl_starttls, to
807 * decide whether to abort. Note that if using $tunnel and
808 * $tunnel_is_secure, adata->conn->ssf will be set to 1. */
809 const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
810 if ((adata->conn->ssf == 0) && c_ssl_force_tls)
811 {
812 mutt_error(_("Encrypted connection unavailable"));
813 goto bail;
814 }
815#endif
816
817 adata->state = IMAP_AUTHENTICATED;
818 if (check_capabilities(adata) != 0)
819 goto bail;
820 FREE(&adata->capstr);
821 }
822 else
823 {
824 imap_error("imap_open_connection()", adata->buf);
825 goto bail;
826 }
827
828 return 0;
829
830bail:
832 FREE(&adata->capstr);
833 return -1;
834}
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:1140
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1109
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:55
#define IMAP_CAP_STARTTLS
RFC2595: STARTTLS.
Definition: private.h:131
ImapExecResult
Imap_exec return code.
Definition: private.h:81
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition: util.c:656
#define IMAP_CMD_SINGLE
Run a single command.
Definition: private.h:75
void imap_close_connection(struct ImapAccountData *adata)
Close an IMAP connection.
Definition: imap.c:840
static int check_capabilities(struct ImapAccountData *adata)
Make sure we can log in to this server.
Definition: imap.c:99
#define FREE(x)
Definition: memory.h:43
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:240
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:320
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
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_close_connection()

void imap_close_connection ( struct ImapAccountData adata)

Close an IMAP connection.

Parameters
adataImap Account data

Definition at line 840 of file imap.c.

841{
842 if (adata->state != IMAP_DISCONNECTED)
843 {
844 mutt_socket_close(adata->conn);
845 adata->state = IMAP_DISCONNECTED;
846 }
847 adata->seqno = 0;
848 adata->nextcmd = 0;
849 adata->lastcmd = 0;
850 adata->status = 0;
851 memset(adata->cmds, 0, sizeof(struct ImapCommand) * adata->cmdslots);
852}
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:101
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:160
+ 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 581 of file imap.c.

583{
584 char c;
585 bool r = false;
586 struct Buffer buf = { 0 }; // Do not allocate, maybe it won't be used
587
588 const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
589 if (c_debug_level >= IMAP_LOG_LTRL)
590 buf_alloc(&buf, bytes + 1);
591
592 mutt_debug(LL_DEBUG2, "reading %lu bytes\n", bytes);
593
594 for (unsigned long pos = 0; pos < bytes; pos++)
595 {
596 if (mutt_socket_readchar(adata->conn, &c) != 1)
597 {
598 mutt_debug(LL_DEBUG1, "error during read, %lu bytes read\n", pos);
599 adata->status = IMAP_FATAL;
600
601 buf_dealloc(&buf);
602 return -1;
603 }
604
605 if (r && (c != '\n'))
606 fputc('\r', fp);
607
608 if (c == '\r')
609 {
610 r = true;
611 continue;
612 }
613 else
614 {
615 r = false;
616 }
617
618 fputc(c, fp);
619
620 if (progress && !(pos % 1024))
621 progress_update(progress, pos, -1);
622 if (c_debug_level >= IMAP_LOG_LTRL)
623 buf_addch(&buf, c);
624 }
625
626 if (c_debug_level >= IMAP_LOG_LTRL)
627 {
628 mutt_debug(IMAP_LOG_LTRL, "\n%s", buf.data);
629 buf_dealloc(&buf);
630 }
631 return 0;
632}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:383
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:253
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:347
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: logging2.h:87
#define IMAP_LOG_LTRL
Definition: private.h:49
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
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:214
char * data
Pointer to data.
Definition: buffer.h:35
+ 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 660 of file imap.c.

661{
663 struct ImapMboxData *mdata = imap_mdata_get(m);
664 if (!adata || !mdata)
665 return;
666
667 struct Email *e = NULL;
668
669#ifdef USE_HCACHE
670 imap_hcache_open(adata, mdata);
671#endif
672
673 for (int i = 0; i < m->msg_count; i++)
674 {
675 e = m->emails[i];
676 if (!e)
677 break;
678
679 if (e->index == INT_MAX)
680 {
681 mutt_debug(LL_DEBUG2, "Expunging message UID %u\n", imap_edata_get(e)->uid);
682
683 e->deleted = true;
684
685 imap_cache_del(m, e);
686#ifdef USE_HCACHE
687 imap_hcache_del(mdata, imap_edata_get(e)->uid);
688#endif
689
690 mutt_hash_int_delete(mdata->uid_hash, imap_edata_get(e)->uid, e);
691
692 imap_edata_free((void **) &e->edata);
693 }
694 else
695 {
696 /* NeoMutt has several places where it turns off e->active as a
697 * hack. For example to avoid FLAG updates, or to exclude from
698 * imap_exec_msg_set.
699 *
700 * Unfortunately, when a reopen is allowed and the IMAP_EXPUNGE_PENDING
701 * flag becomes set (e.g. a flag update to a modified header),
702 * this function will be called by imap_cmd_finish().
703 *
704 * The ctx_update_tables() will free and remove these "inactive" headers,
705 * despite that an EXPUNGE was not received for them.
706 * This would result in memory leaks and segfaults due to dangling
707 * pointers in the msn_index and uid_hash.
708 *
709 * So this is another hack to work around the hacks. We don't want to
710 * remove the messages, so make sure active is on. */
711 e->active = true;
712 }
713 }
714
715#ifdef USE_HCACHE
716 imap_hcache_close(mdata);
717#endif
718
720 if (resort)
721 {
723 }
724}
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 ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
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:1854
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:337
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition: util.c:396
void imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
Open a header cache.
Definition: util.c:296
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:223
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:176
@ NT_MAILBOX_UPDATE
Update internal tables.
Definition: mailbox.h:177
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
The envelope/body of an email.
Definition: email.h:37
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:109
IMAP-specific Account data -.
Definition: adata.h:40
IMAP-specific Mailbox data -.
Definition: mdata.h:39
struct HashTable * uid_hash
Hash Table: "uid" -> Email.
Definition: mdata.h:58
int msg_count
Total number of messages.
Definition: mailbox.h:88
void * mdata
Driver specific data.
Definition: mailbox.h:132
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
+ 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 1762 of file imap.c.

1763{
1764 if (!adata)
1765 return -1;
1766
1767 if (adata->state == IMAP_DISCONNECTED)
1768 {
1769 buf_reset(&adata->cmdbuf); // purge outstanding queued commands
1770 imap_open_connection(adata);
1771 }
1772 if (adata->state == IMAP_CONNECTED)
1773 {
1775 {
1776 adata->state = IMAP_AUTHENTICATED;
1777 FREE(&adata->capstr);
1778 if (adata->conn->ssf != 0)
1779 {
1780 mutt_debug(LL_DEBUG2, "Communication encrypted at %d bits\n",
1781 adata->conn->ssf);
1782 }
1783 }
1784 else
1785 {
1787 }
1788 }
1789 if (adata->state == IMAP_AUTHENTICATED)
1790 {
1791 /* capabilities may have changed */
1792 imap_exec(adata, "CAPABILITY", IMAP_CMD_PASS);
1793
1794#ifdef USE_ZLIB
1795 /* RFC4978 */
1796 const bool c_imap_deflate = cs_subset_bool(NeoMutt->sub, "imap_deflate");
1797 if ((adata->capabilities & IMAP_CAP_COMPRESS) && c_imap_deflate &&
1798 (imap_exec(adata, "COMPRESS DEFLATE", IMAP_CMD_PASS) == IMAP_EXEC_SUCCESS))
1799 {
1800 mutt_debug(LL_DEBUG2, "IMAP compression is enabled on connection to %s\n",
1801 adata->conn->account.host);
1802 mutt_zstrm_wrap_conn(adata->conn);
1803 }
1804#endif
1805
1806 /* enable RFC2971, if the server supports that */
1807 const bool c_imap_send_id = cs_subset_bool(NeoMutt->sub, "imap_send_id");
1808 if (c_imap_send_id && (adata->capabilities & IMAP_CAP_ID))
1809 {
1810 imap_exec(adata, "ID (\"name\" \"NeoMutt\" \"version\" \"" PACKAGE_VERSION "\")",
1812 }
1813
1814 /* enable RFC6855, if the server supports that */
1815 const bool c_imap_rfc5161 = cs_subset_bool(NeoMutt->sub, "imap_rfc5161");
1816 if (c_imap_rfc5161 && (adata->capabilities & IMAP_CAP_ENABLE))
1817 imap_exec(adata, "ENABLE UTF8=ACCEPT", IMAP_CMD_QUEUE);
1818
1819 /* enable QRESYNC. Advertising QRESYNC also means CONDSTORE
1820 * is supported (even if not advertised), so flip that bit. */
1821 if (adata->capabilities & IMAP_CAP_QRESYNC)
1822 {
1824 const bool c_imap_qresync = cs_subset_bool(NeoMutt->sub, "imap_qresync");
1825 if (c_imap_rfc5161 && c_imap_qresync)
1826 imap_exec(adata, "ENABLE QRESYNC", IMAP_CMD_QUEUE);
1827 }
1828
1829 /* get root delimiter, '/' as default */
1830 adata->delim = '/';
1831 imap_exec(adata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
1832
1833 /* we may need the root delimiter before we open a mailbox */
1834 imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1835
1836 /* select the mailbox that used to be open before disconnect */
1837 if (adata->mailbox)
1838 {
1839 imap_mbox_select(adata->mailbox);
1840 }
1841 }
1842
1843 if (adata->state < IMAP_AUTHENTICATED)
1844 return -1;
1845
1846 return 0;
1847}
@ IMAP_AUTH_SUCCESS
Authentication successful.
Definition: auth.h:39
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
void mutt_account_unsetpass(struct ConnAccount *cac)
Unset ConnAccount's password.
Definition: connaccount.c:175
int imap_authenticate(struct ImapAccountData *adata)
Authenticate to an IMAP server.
Definition: auth.c:110
#define IMAP_CAP_ENABLE
RFC5161.
Definition: private.h:135
#define IMAP_CAP_ID
RFC2971: IMAP4 ID extension.
Definition: private.h:141
#define IMAP_CMD_PASS
Command contains a password. Suppress logging.
Definition: private.h:72
#define IMAP_CAP_QRESYNC
RFC7162.
Definition: private.h:137
#define IMAP_CAP_COMPRESS
RFC4978: COMPRESS=DEFLATE.
Definition: private.h:139
#define IMAP_CAP_CONDSTORE
RFC7162.
Definition: private.h:136
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:73
int imap_open_connection(struct ImapAccountData *adata)
Open an IMAP connection.
Definition: imap.c:732
static void imap_mbox_select(struct Mailbox *m)
Select a Mailbox.
Definition: imap.c:1729
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 917 of file imap.c.

919{
921 if (!adata || (adata->mailbox != m))
922 return -1;
923
924 char flags[1024] = { 0 };
925 char *tags = NULL;
926 char uid[11] = { 0 };
927
929 {
930 if (e->deleted == imap_edata_get(e)->deleted)
931 e->changed = false;
932 return 0;
933 }
934
935 snprintf(uid, sizeof(uid), "%u", imap_edata_get(e)->uid);
936 buf_reset(cmd);
937 buf_addstr(cmd, "UID STORE ");
938 buf_addstr(cmd, uid);
939
940 flags[0] = '\0';
941
942 set_flag(m, MUTT_ACL_SEEN, e->read, "\\Seen ", flags, sizeof(flags));
943 set_flag(m, MUTT_ACL_WRITE, e->old, "Old ", flags, sizeof(flags));
944 set_flag(m, MUTT_ACL_WRITE, e->flagged, "\\Flagged ", flags, sizeof(flags));
945 set_flag(m, MUTT_ACL_WRITE, e->replied, "\\Answered ", flags, sizeof(flags));
946 set_flag(m, MUTT_ACL_DELETE, imap_edata_get(e)->deleted, "\\Deleted ", flags,
947 sizeof(flags));
948
949 if (m->rights & MUTT_ACL_WRITE)
950 {
951 /* restore system flags */
952 if (imap_edata_get(e)->flags_system)
953 mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_system);
954 /* set custom flags */
956 if (tags)
957 {
958 mutt_str_cat(flags, sizeof(flags), tags);
959 FREE(&tags);
960 }
961 }
962
964
965 /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
966 * explicitly revoke all system flags (if we have permission) */
967 if (*flags == '\0')
968 {
969 set_flag(m, MUTT_ACL_SEEN, true, "\\Seen ", flags, sizeof(flags));
970 set_flag(m, MUTT_ACL_WRITE, true, "Old ", flags, sizeof(flags));
971 set_flag(m, MUTT_ACL_WRITE, true, "\\Flagged ", flags, sizeof(flags));
972 set_flag(m, MUTT_ACL_WRITE, true, "\\Answered ", flags, sizeof(flags));
973 set_flag(m, MUTT_ACL_DELETE, !imap_edata_get(e)->deleted, "\\Deleted ",
974 flags, sizeof(flags));
975
976 /* erase custom flags */
977 if ((m->rights & MUTT_ACL_WRITE) && imap_edata_get(e)->flags_remote)
978 mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_remote);
979
981
982 buf_addstr(cmd, " -FLAGS.SILENT (");
983 }
984 else
985 {
986 buf_addstr(cmd, " FLAGS.SILENT (");
987 }
988
989 buf_addstr(cmd, flags);
990 buf_addstr(cmd, ")");
991
992 /* after all this it's still possible to have no flags, if you
993 * have no ACL rights */
994 if (*flags && (imap_exec(adata, cmd->data, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS) &&
995 err_continue && (*err_continue != MUTT_YES))
996 {
997 *err_continue = imap_continue("imap_sync_message: STORE failed", adata->buf);
998 if (*err_continue != MUTT_YES)
999 return -1;
1000 }
1001
1002 /* server have now the updated flags */
1003 FREE(&imap_edata_get(e)->flags_remote);
1005
1006 if (e->deleted == imap_edata_get(e)->deleted)
1007 e->changed = false;
1008
1009 return 0;
1010}
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:238
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:645
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:180
static bool compare_flags_for_copy(struct Email *e)
Compare local flags against the server.
Definition: imap.c:196
#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:637
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:266
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 865 of file imap.c.

866{
867 if (STAILQ_EMPTY(flag_list))
868 return false;
869
870 const size_t flaglen = mutt_str_len(flag);
871 struct ListNode *np = NULL;
872 STAILQ_FOREACH(np, flag_list, entries)
873 {
874 const size_t nplen = strlen(np->data);
875 if ((flaglen >= nplen) && ((flag[nplen] == '\0') || (flag[nplen] == ' ')) &&
876 mutt_istrn_equal(np->data, flag, nplen))
877 {
878 return true;
879 }
880
881 if (mutt_str_equal(np->data, "\\*"))
882 return true;
883 }
884
885 return false;
886}
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
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:525
#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 71 of file util.c.

73{
74 struct ConnAccount cac = { { 0 } };
75 struct ImapAccountData *tmp_adata = NULL;
76 char tmp[1024] = { 0 };
77
78 if (imap_parse_path(path, &cac, tmp, sizeof(tmp)) < 0)
79 return -1;
80
81 struct Account *np = NULL;
82 TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
83 {
84 if (np->type != MUTT_IMAP)
85 continue;
86
87 tmp_adata = np->adata;
88 if (!tmp_adata)
89 continue;
90 if (imap_account_match(&tmp_adata->conn->account, &cac))
91 {
92 *mdata = imap_mdata_new(tmp_adata, tmp);
93 *adata = tmp_adata;
94 return 0;
95 }
96 }
97 mutt_debug(LL_DEBUG3, "no ImapAccountData found\n");
98 return -1;
99}
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: logging2.h:45
@ 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:473
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1039
+ 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
enumImapAuthRes, 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:810
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 1095 of file command.c.

1096{
1097 return cmd_start(adata, cmdstr, IMAP_CMD_NO_FLAGS);
1098}
static int cmd_start(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Start a new IMAP command.
Definition: command.c:199
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_cmd_step()

int imap_cmd_step ( struct ImapAccountData adata)

Reads server responses from an IMAP command.

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

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

Definition at line 1109 of file command.c.

1110{
1111 if (!adata)
1112 return -1;
1113
1114 size_t len = 0;
1115 int c;
1116 int rc;
1117 int stillrunning = 0;
1118 struct ImapCommand *cmd = NULL;
1119
1120 if (adata->status == IMAP_FATAL)
1121 {
1122 cmd_handle_fatal(adata);
1123 return IMAP_RES_BAD;
1124 }
1125
1126 /* read into buffer, expanding buffer as necessary until we have a full
1127 * line */
1128 do
1129 {
1130 if (len == adata->blen)
1131 {
1132 mutt_mem_realloc(&adata->buf, adata->blen + IMAP_CMD_BUFSIZE);
1133 adata->blen = adata->blen + IMAP_CMD_BUFSIZE;
1134 mutt_debug(LL_DEBUG3, "grew buffer to %lu bytes\n", adata->blen);
1135 }
1136
1137 /* back up over '\0' */
1138 if (len)
1139 len--;
1140 c = mutt_socket_readln_d(adata->buf + len, adata->blen - len, adata->conn, MUTT_SOCK_LOG_FULL);
1141 if (c <= 0)
1142 {
1143 mutt_debug(LL_DEBUG1, "Error reading server response\n");
1144 cmd_handle_fatal(adata);
1145 return IMAP_RES_BAD;
1146 }
1147
1148 len += c;
1149 }
1150 /* if we've read all the way to the end of the buffer, we haven't read a
1151 * full line (mutt_socket_readln strips the \r, so we always have at least
1152 * one character free when we've read a full line) */
1153 while (len == adata->blen);
1154
1155 /* don't let one large string make cmd->buf hog memory forever */
1156 if ((adata->blen > IMAP_CMD_BUFSIZE) && (len <= IMAP_CMD_BUFSIZE))
1157 {
1159 adata->blen = IMAP_CMD_BUFSIZE;
1160 mutt_debug(LL_DEBUG3, "shrank buffer to %lu bytes\n", adata->blen);
1161 }
1162
1163 adata->lastread = mutt_date_now();
1164
1165 /* handle untagged messages. The caller still gets its shot afterwards. */
1166 if ((mutt_str_startswith(adata->buf, "* ") ||
1167 mutt_str_startswith(imap_next_word(adata->buf), "OK [")) &&
1168 cmd_handle_untagged(adata))
1169 {
1170 return IMAP_RES_BAD;
1171 }
1172
1173 /* server demands a continuation response from us */
1174 if (adata->buf[0] == '+')
1175 return IMAP_RES_RESPOND;
1176
1177 /* Look for tagged command completions.
1178 *
1179 * Some response handlers can end up recursively calling
1180 * imap_cmd_step() and end up handling all tagged command
1181 * completions.
1182 * (e.g. FETCH->set_flag->set_header_color->~h pattern match.)
1183 *
1184 * Other callers don't even create an adata->cmds entry.
1185 *
1186 * For both these cases, we default to returning OK */
1187 rc = IMAP_RES_OK;
1188 c = adata->lastcmd;
1189 do
1190 {
1191 cmd = &adata->cmds[c];
1192 if (cmd->state == IMAP_RES_NEW)
1193 {
1194 if (mutt_str_startswith(adata->buf, cmd->seq))
1195 {
1196 if (!stillrunning)
1197 {
1198 /* first command in queue has finished - move queue pointer up */
1199 adata->lastcmd = (adata->lastcmd + 1) % adata->cmdslots;
1200 }
1201 cmd->state = cmd_status(adata->buf);
1202 rc = cmd->state;
1203 if (cmd->state == IMAP_RES_NO || cmd->state == IMAP_RES_BAD)
1204 {
1205 mutt_message(_("IMAP command failed: %s"), adata->buf);
1206 }
1207 }
1208 else
1209 {
1210 stillrunning++;
1211 }
1212 }
1213
1214 c = (c + 1) % adata->cmdslots;
1215 } while (c != adata->nextcmd);
1216
1217 if (stillrunning)
1218 {
1219 rc = IMAP_RES_CONTINUE;
1220 }
1221 else
1222 {
1223 mutt_debug(LL_DEBUG3, "IMAP queue drained\n");
1224 imap_cmd_finish(adata);
1225 }
1226
1227 return rc;
1228}
#define mutt_message(...)
Definition: logging2.h:89
static int cmd_handle_untagged(struct ImapAccountData *adata)
Fallback parser for otherwise unhandled messages.
Definition: command.c:999
static int cmd_status(const char *s)
Parse response line for tagged OK/NO/BAD.
Definition: command.c:235
static void cmd_handle_fatal(struct ImapAccountData *adata)
When ImapAccountData is in fatal state, do what we can.
Definition: command.c:165
#define IMAP_CMD_BUFSIZE
Definition: command.c:56
void imap_cmd_finish(struct ImapAccountData *adata)
Attempt to perform cleanup.
Definition: command.c:1349
#define IMAP_RES_RESPOND
+
Definition: private.h:57
#define IMAP_RES_NEW
ImapCommand.state additions.
Definition: private.h:58
#define IMAP_RES_NO
<tag> NO ...
Definition: private.h:53
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:56
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:784
#define IMAP_RES_BAD
<tag> BAD ...
Definition: private.h:54
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:446
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:228
int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
Read a line from a socket.
Definition: socket.c:252
#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:162
char seq[SEQ_LEN+1]
Command tag, e.g. 'a0001'.
Definition: private.h:161
+ 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 1349 of file command.c.

1350{
1351 if (!adata)
1352 return;
1353
1354 if (adata->status == IMAP_FATAL)
1355 {
1356 adata->closing = false;
1357 cmd_handle_fatal(adata);
1358 return;
1359 }
1360
1361 if (!(adata->state >= IMAP_SELECTED) || (adata->mailbox && adata->closing))
1362 {
1363 adata->closing = false;
1364 return;
1365 }
1366
1367 adata->closing = false;
1368
1369 struct ImapMboxData *mdata = imap_mdata_get(adata->mailbox);
1370
1371 if (mdata && mdata->reopen & IMAP_REOPEN_ALLOW)
1372 {
1373 // First remove expunged emails from the msn_index
1374 if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1375 {
1376 mutt_debug(LL_DEBUG2, "Expunging mailbox\n");
1377 imap_expunge_mailbox(adata->mailbox, true);
1378 /* Detect whether we've gotten unexpected EXPUNGE messages */
1379 if (!(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1380 mdata->check_status |= IMAP_EXPUNGE_PENDING;
1382 }
1383
1384 // Then add new emails to it
1385 if (mdata->reopen & IMAP_NEWMAIL_PENDING)
1386 {
1387 const size_t max_msn = imap_msn_highest(&mdata->msn);
1388 if (mdata->new_mail_count > max_msn)
1389 {
1390 if (!(mdata->reopen & IMAP_EXPUNGE_PENDING))
1391 mdata->check_status |= IMAP_NEWMAIL_PENDING;
1392
1393 mutt_debug(LL_DEBUG2, "Fetching new mails from %ld to %u\n",
1394 max_msn + 1, mdata->new_mail_count);
1395 imap_read_headers(adata->mailbox, max_msn + 1, mdata->new_mail_count, false);
1396 }
1397 }
1398
1399 // And to finish inform about MUTT_REOPEN if needed
1400 if (mdata->reopen & IMAP_EXPUNGE_PENDING && !(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1401 mdata->check_status |= IMAP_EXPUNGE_PENDING;
1402
1403 if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1405 }
1406
1407 adata->status = 0;
1408}
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:1331
#define IMAP_EXPUNGE_PENDING
Messages on the server have been expunged.
Definition: private.h:66
#define IMAP_EXPUNGE_EXPECTED
Messages will be expunged from the server.
Definition: private.h:65
#define IMAP_REOPEN_ALLOW
Allow re-opening a folder upon expunge.
Definition: private.h:64
#define IMAP_NEWMAIL_PENDING
New mail is waiting on the server.
Definition: private.h:67
void imap_expunge_mailbox(struct Mailbox *m, bool resort)
Purge messages from the server.
Definition: imap.c:660
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 1236 of file command.c.

1237{
1238 return cmd_status(s) == IMAP_RES_OK;
1239}
+ 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 1247 of file command.c.

1248{
1249 static const char *notrailer = "";
1250 const char *s = adata->buf;
1251
1252 if (!s)
1253 {
1254 mutt_debug(LL_DEBUG2, "not a tagged response\n");
1255 return notrailer;
1256 }
1257
1258 s = imap_next_word((char *) s);
1259 if (!s || (!mutt_istr_startswith(s, "OK") && !mutt_istr_startswith(s, "NO") &&
1260 !mutt_istr_startswith(s, "BAD")))
1261 {
1262 mutt_debug(LL_DEBUG2, "not a command completion: %s\n", adata->buf);
1263 return notrailer;
1264 }
1265
1266 s = imap_next_word((char *) s);
1267 if (!s)
1268 return notrailer;
1269
1270 return s;
1271}
+ 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 1284 of file command.c.

1285{
1286 int rc;
1287
1288 if (flags & IMAP_CMD_SINGLE)
1289 {
1290 // Process any existing commands
1291 if (adata->nextcmd != adata->lastcmd)
1292 imap_exec(adata, NULL, IMAP_CMD_POLL);
1293 }
1294
1295 rc = cmd_start(adata, cmdstr, flags);
1296 if (rc < 0)
1297 {
1298 cmd_handle_fatal(adata);
1299 return IMAP_EXEC_FATAL;
1300 }
1301
1302 if (flags & IMAP_CMD_QUEUE)
1303 return IMAP_EXEC_SUCCESS;
1304
1305 const short c_imap_poll_timeout = cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1306 if ((flags & IMAP_CMD_POLL) && (c_imap_poll_timeout > 0) &&
1307 ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1308 {
1309 mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1310 cmd_handle_fatal(adata);
1311 return IMAP_EXEC_FATAL;
1312 }
1313
1314 /* Allow interruptions, particularly useful if there are network problems. */
1316 do
1317 {
1318 rc = imap_cmd_step(adata);
1319 // The queue is empty, so the single command has been processed
1320 if ((flags & IMAP_CMD_SINGLE) && (adata->nextcmd == adata->lastcmd))
1321 break;
1322 } while (rc == IMAP_RES_CONTINUE);
1324
1325 if (rc == IMAP_RES_NO)
1326 return IMAP_EXEC_ERROR;
1327 if (rc != IMAP_RES_OK)
1328 {
1329 if (adata->status != IMAP_FATAL)
1330 return IMAP_EXEC_ERROR;
1331
1332 mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1333 return IMAP_EXEC_FATAL;
1334 }
1335
1336 return IMAP_EXEC_SUCCESS;
1337}
#define IMAP_CMD_POLL
Poll the tcp connection before running the imap command.
Definition: private.h:74
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:252
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:196
+ 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 1416 of file command.c.

1417{
1418 int rc;
1419
1420 if (cmd_start(adata, "IDLE", IMAP_CMD_POLL) < 0)
1421 {
1422 cmd_handle_fatal(adata);
1423 return -1;
1424 }
1425
1426 const short c_imap_poll_timeout = cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1427 if ((c_imap_poll_timeout > 0) &&
1428 ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1429 {
1430 mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1431 cmd_handle_fatal(adata);
1432 return -1;
1433 }
1434
1435 do
1436 {
1437 rc = imap_cmd_step(adata);
1438 } while (rc == IMAP_RES_CONTINUE);
1439
1440 if (rc == IMAP_RES_RESPOND)
1441 {
1442 /* successfully entered IDLE state */
1443 adata->state = IMAP_IDLE;
1444 /* queue automatic exit when next command is issued */
1445 buf_addstr(&adata->cmdbuf, "DONE\r\n");
1446 rc = IMAP_RES_OK;
1447 }
1448 if (rc != IMAP_RES_OK)
1449 {
1450 mutt_debug(LL_DEBUG1, "error starting IDLE\n");
1451 return -1;
1452 }
1453
1454 return 0;
1455}
+ 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 1331 of file message.c.

1333{
1334 unsigned int maxuid = 0;
1335 int retval = -1;
1336 bool evalhc = false;
1337
1338#ifdef USE_HCACHE
1339 uint32_t uidvalidity = 0;
1340 unsigned int uid_next = 0;
1341 unsigned long long modseq = 0;
1342 bool has_condstore = false;
1343 bool has_qresync = false;
1344 bool eval_condstore = false;
1345 bool eval_qresync = false;
1346 char *uid_seqset = NULL;
1347 const unsigned int msn_begin_save = msn_begin;
1348#endif /* USE_HCACHE */
1349
1351 struct ImapMboxData *mdata = imap_mdata_get(m);
1352 if (!adata || (adata->mailbox != m))
1353 return -1;
1354
1355#ifdef USE_HCACHE
1356retry:
1357#endif /* USE_HCACHE */
1358
1359 /* make sure context has room to hold the mailbox */
1360 mx_alloc_memory(m, msn_end);
1361 imap_msn_reserve(&mdata->msn, msn_end);
1362 imap_alloc_uid_hash(adata, msn_end);
1363
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 mutt_hcache_fetch_obj(mdata->hcache, "/UIDVALIDITY", 12, &uidvalidity);
1373 mutt_hcache_fetch_obj(mdata->hcache, "/UIDNEXT", 8, &uid_next);
1374 if (mdata->modseq)
1375 {
1376 const bool c_imap_condstore = cs_subset_bool(NeoMutt->sub, "imap_condstore");
1377 if ((adata->capabilities & IMAP_CAP_CONDSTORE) && c_imap_condstore)
1378 has_condstore = true;
1379
1380 /* If IMAP_CAP_QRESYNC and ImapQResync then NeoMutt sends ENABLE QRESYNC.
1381 * If we receive an ENABLED response back, then adata->qresync is set. */
1382 if (adata->qresync)
1383 has_qresync = true;
1384 }
1385
1386 if (uidvalidity && uid_next && uidvalidity == mdata->uidvalidity)
1387 {
1388 evalhc = true;
1389 if (mutt_hcache_fetch_obj(mdata->hcache, "/MODSEQ", 7, &modseq))
1390 {
1391 if (has_qresync)
1392 {
1393 uid_seqset = imap_hcache_get_uid_seqset(mdata);
1394 if (uid_seqset)
1395 eval_qresync = true;
1396 }
1397
1398 if (!eval_qresync && has_condstore)
1399 eval_condstore = true;
1400 }
1401 }
1402 }
1403 if (evalhc)
1404 {
1405 if (eval_qresync)
1406 {
1407 if (read_headers_qresync_eval_cache(adata, uid_seqset) < 0)
1408 goto bail;
1409 }
1410 else
1411 {
1412 if (read_headers_normal_eval_cache(adata, msn_end, uid_next, has_condstore || has_qresync,
1413 eval_condstore) < 0)
1414 goto bail;
1415 }
1416
1417 if ((eval_condstore || eval_qresync) && (modseq != mdata->modseq))
1418 {
1420 modseq, eval_qresync) < 0)
1421 {
1422 goto bail;
1423 }
1424 }
1425
1426 /* Look for the first empty MSN and start there */
1427 while (msn_begin <= msn_end)
1428 {
1429 if (!imap_msn_get(&mdata->msn, msn_begin - 1))
1430 break;
1431 msn_begin++;
1432 }
1433 }
1434#endif /* USE_HCACHE */
1435
1436 if (read_headers_fetch_new(m, msn_begin, msn_end, evalhc, &maxuid, initial_download) < 0)
1437 goto bail;
1438
1439#ifdef USE_HCACHE
1440 if (eval_qresync && initial_download)
1441 {
1442 if (imap_verify_qresync(m) != 0)
1443 {
1444 eval_qresync = false;
1445 eval_condstore = false;
1446 evalhc = false;
1447 modseq = 0;
1448 maxuid = 0;
1449 FREE(&uid_seqset);
1450 uidvalidity = 0;
1451 uid_next = 0;
1452 msn_begin = msn_begin_save;
1453
1454 goto retry;
1455 }
1456 }
1457#endif /* USE_HCACHE */
1458
1459 if (maxuid && (mdata->uid_next < maxuid + 1))
1460 mdata->uid_next = maxuid + 1;
1461
1462#ifdef USE_HCACHE
1463 mutt_hcache_store_raw(mdata->hcache, "/UIDVALIDITY", 12, &mdata->uidvalidity,
1464 sizeof(mdata->uidvalidity));
1465 if (maxuid && (mdata->uid_next < maxuid + 1))
1466 {
1467 mutt_debug(LL_DEBUG2, "Overriding UIDNEXT: %u -> %u\n", mdata->uid_next, maxuid + 1);
1468 mdata->uid_next = maxuid + 1;
1469 }
1470 if (mdata->uid_next > 1)
1471 {
1472 mutt_hcache_store_raw(mdata->hcache, "/UIDNEXT", 8, &mdata->uid_next,
1473 sizeof(mdata->uid_next));
1474 }
1475
1476 /* We currently only sync CONDSTORE and QRESYNC on the initial download.
1477 * To do it more often, we'll need to deal with flag updates combined with
1478 * unsync'ed local flag changes. We'll also need to properly sync flags to
1479 * the header cache on close. I'm not sure it's worth the added complexity. */
1480 if (initial_download)
1481 {
1482 if (has_condstore || has_qresync)
1483 {
1484 mutt_hcache_store_raw(mdata->hcache, "/MODSEQ", 7, &mdata->modseq,
1485 sizeof(mdata->modseq));
1486 }
1487 else
1488 {
1489 mutt_hcache_delete_record(mdata->hcache, "/MODSEQ", 7);
1490 }
1491
1492 if (has_qresync)
1494 else
1496 }
1497#endif /* USE_HCACHE */
1498
1499 /* TODO: it's not clear to me why we are calling mx_alloc_memory yet again. */
1501
1502 mdata->reopen |= IMAP_REOPEN_ALLOW;
1503
1504 retval = msn_end;
1505
1506bail:
1507#ifdef USE_HCACHE
1509 FREE(&uid_seqset);
1510#endif /* USE_HCACHE */
1511
1512 return retval;
1513}
#define mutt_hcache_fetch_obj(hc, key, keylen, dst)
Definition: lib.h:160
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:695
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:674
static int imap_verify_qresync(struct Mailbox *m)
Check to see if QRESYNC got jumbled.
Definition: message.c:1003
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:904
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:1080
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:673
static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *uid_seqset)
Retrieve data from the header cache.
Definition: message.c:818
static void imap_alloc_uid_hash(struct ImapAccountData *adata, unsigned int msn_count)
Create a Hash Table for the UIDs.
Definition: message.c:518
int imap_hcache_store_uid_seqset(struct ImapMboxData *mdata)
Store a UID Sequence Set in the header cache.
Definition: util.c:413
char * imap_hcache_get_uid_seqset(struct ImapMboxData *mdata)
Get a UID Sequence Set from the header cache.
Definition: util.c:449
int imap_hcache_clear_uid_seqset(struct ImapMboxData *mdata)
Delete a UID Sequence Set from the header cache.
Definition: util.c:435
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, int req_size)
Create storage for the emails.
Definition: mx.c:1237
bool qresync
true, if QRESYNC is successfully ENABLE'd
Definition: adata.h:63
unsigned int uid_next
Definition: mdata.h:51
unsigned long long modseq
Definition: mdata.h:52
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 1905 of file message.c.

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

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

1874{
1876 struct ImapMboxData *mdata = imap_mdata_get(m);
1877
1878 if (!adata || (adata->mailbox != m))
1879 return -1;
1880
1881 mdata->bcache = msg_cache_open(m);
1883
1884 return 0;
1885}
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
Definition: bcache.c:328
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:166
+ 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 1522 of file message.c.

1523{
1524 if (!m || !msg)
1525 return -1;
1526
1527 FILE *fp = NULL;
1528 char buf[2048];
1529 char internaldate[IMAP_DATELEN] = { 0 };
1530 char imap_flags[128] = { 0 };
1531 size_t len;
1532 struct Progress *progress = NULL;
1533 size_t sent;
1534 int c, last;
1535 int rc;
1536
1538 struct ImapMboxData *mdata = imap_mdata_get(m);
1539
1540 fp = fopen(msg->path, "r");
1541 if (!fp)
1542 {
1543 mutt_perror(msg->path);
1544 goto fail;
1545 }
1546
1547 /* currently we set the \Seen flag on all messages, but probably we
1548 * should scan the message Status header for flag info. Since we're
1549 * already rereading the whole file for length it isn't any more
1550 * expensive (it'd be nice if we had the file size passed in already
1551 * by the code that writes the file, but that's a lot of changes.
1552 * Ideally we'd have an Email structure with flag info here... */
1553 for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c)
1554 {
1555 if ((c == '\n') && (last != '\r'))
1556 len++;
1557
1558 len++;
1559 }
1560 rewind(fp);
1561
1562 if (m->verbose)
1563 progress = progress_new(_("Uploading message..."), MUTT_PROGRESS_NET, len);
1564
1565 mutt_date_make_imap(internaldate, sizeof(internaldate), msg->received);
1566
1567 imap_flags[0] = '\0';
1568 imap_flags[1] = '\0';
1569
1570 if (msg->flags.read)
1571 mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Seen");
1572 if (msg->flags.replied)
1573 mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Answered");
1574 if (msg->flags.flagged)
1575 mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Flagged");
1576 if (msg->flags.draft)
1577 mutt_str_cat(imap_flags, sizeof(imap_flags), " \\Draft");
1578
1579 snprintf(buf, sizeof(buf), "APPEND %s (%s) \"%s\" {%lu}", mdata->munge_name,
1580 imap_flags + 1, internaldate, (unsigned long) len);
1581
1582 imap_cmd_start(adata, buf);
1583
1584 do
1585 {
1586 rc = imap_cmd_step(adata);
1587 } while (rc == IMAP_RES_CONTINUE);
1588
1589 if (rc != IMAP_RES_RESPOND)
1590 goto cmd_step_fail;
1591
1592 for (last = EOF, sent = len = 0; (c = fgetc(fp)) != EOF; last = c)
1593 {
1594 if ((c == '\n') && (last != '\r'))
1595 buf[len++] = '\r';
1596
1597 buf[len++] = c;
1598
1599 if (len > sizeof(buf) - 3)
1600 {
1601 sent += len;
1602 if (flush_buffer(buf, &len, adata->conn) < 0)
1603 goto fail;
1604 if (m->verbose)
1605 progress_update(progress, sent, -1);
1606 }
1607 }
1608
1609 if (len)
1610 if (flush_buffer(buf, &len, adata->conn) < 0)
1611 goto fail;
1612
1613 if (mutt_socket_send(adata->conn, "\r\n") < 0)
1614 goto fail;
1615 mutt_file_fclose(&fp);
1616
1617 do
1618 {
1619 rc = imap_cmd_step(adata);
1620 } while (rc == IMAP_RES_CONTINUE);
1621
1622 if (rc != IMAP_RES_OK)
1623 goto cmd_step_fail;
1624
1625 progress_free(&progress);
1626 return 0;
1627
1628cmd_step_fail:
1629 mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1630 if (rc != IMAP_RES_BAD)
1631 {
1632 char *pc = imap_next_word(adata->buf); /* skip sequence number or token */
1633 pc = imap_next_word(pc); /* skip response code */
1634 if (*pc != '\0')
1635 mutt_error("%s", pc);
1636 }
1637
1638fail:
1639 mutt_file_fclose(&fp);
1640 progress_free(&progress);
1641 return -1;
1642}
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
#define mutt_perror(...)
Definition: logging2.h:91
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1095
static int flush_buffer(char *buf, size_t *len, struct Connection *conn)
Write data to a connection.
Definition: message.c:478
#define IMAP_DATELEN
Definition: private.h:88
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:784
@ 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:89
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:121
#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 296 of file util.c.

297{
298 if (!adata || !mdata)
299 return;
300
301 if (mdata->hcache)
302 return;
303
304 struct HeaderCache *hc = NULL;
305 struct Buffer *mbox = buf_pool_get();
306 struct Buffer *cachepath = buf_pool_get();
307
308 imap_cachepath(adata->delim, mdata->name, mbox);
309
310 if (strstr(buf_string(mbox), "/../") || mutt_str_equal(buf_string(mbox), "..") ||
311 mutt_strn_equal(buf_string(mbox), "../", 3))
312 {
313 goto cleanup;
314 }
315 size_t len = buf_len(mbox);
316 if ((len > 3) && (mutt_str_equal(buf_string(mbox) + len - 3, "/..")))
317 goto cleanup;
318
319 struct Url url = { 0 };
320 mutt_account_tourl(&adata->conn->account, &url);
321 url.path = mbox->data;
322 url_tobuffer(&url, cachepath, U_PATH);
323
324 const char *const c_header_cache = cs_subset_path(NeoMutt->sub, "header_cache");
325 hc = mutt_hcache_open(c_header_cache, buf_string(cachepath), imap_hcache_namer);
326
327cleanup:
328 buf_pool_release(&mbox);
329 buf_pool_release(&cachepath);
330 mdata->hcache = hc;
331}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:460
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:286
struct HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:379
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:497
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:88
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:357
#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:709
+ 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 337 of file util.c.

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

354{
355 if (!mdata->hcache)
356 return NULL;
357
358 char key[16] = { 0 };
359
360 sprintf(key, "/%u", uid);
361 struct HCacheEntry hce = mutt_hcache_fetch(mdata->hcache, key, mutt_str_len(key),
362 mdata->uidvalidity);
363 if (!hce.email && hce.uidvalidity)
364 {
365 mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %u\n", hce.uidvalidity);
366 }
367
368 return hce.email;
369}
struct HCacheEntry mutt_hcache_fetch(struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:513
Wrapper for Email retrieved from the header cache.
Definition: lib.h:99
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:100
struct Email * email
Retrieved email.
Definition: lib.h:102
+ 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 378 of file util.c.

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

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

414{
415 if (!mdata->hcache)
416 return -1;
417
418 /* The seqset is likely large. Preallocate to reduce reallocs */
419 struct Buffer buf = buf_make(8192);
420 imap_msn_index_to_uid_seqset(&buf, mdata);
421
422 int rc = mutt_hcache_store_raw(mdata->hcache, "/UIDSEQSET", 10, buf.data,
423 buf_len(&buf) + 1);
424 mutt_debug(LL_DEBUG3, "Stored /UIDSEQSET %s\n", buf.data);
425 buf_dealloc(&buf);
426 return rc;
427}
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:70
static void imap_msn_index_to_uid_seqset(struct Buffer *buf, struct ImapMboxData *mdata)
Convert MSN index of UIDs to Seqset.
Definition: util.c:230
+ 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 435 of file util.c.

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

450{
451 if (!mdata->hcache)
452 return NULL;
453
454 char *seqset = mutt_hcache_fetch_str(mdata->hcache, "/UIDSEQSET", 10);
455 mutt_debug(LL_DEBUG3, "Retrieved /UIDSEQSET %s\n", NONULL(seqset));
456
457 return seqset;
458}
char * mutt_hcache_fetch_str(struct HeaderCache *hc, const char *key, size_t keylen)
Fetch a string from the cache.
Definition: hcache.c:600
#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 645 of file util.c.

646{
647 imap_error(msg, resp);
648 return mutt_yesorno(_("Continue?"), MUTT_NO);
649}
@ 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:656
+ 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 656 of file util.c.

657{
658 mutt_error("%s [%s]", where, msg);
659}
+ 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 105 of file util.c.

106{
107 mutt_hash_free(&mdata->uid_hash);
108 imap_msn_free(&mdata->msn);
109 mutt_bcache_close(&mdata->bcache);
110}
void mutt_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
Definition: bcache.c:164
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 678 of file util.c.

679{
680 int i = 0;
681 const char *const c_imap_delim_chars = cs_subset_string(NeoMutt->sub, "imap_delim_chars");
682 for (; mailbox && *mailbox && (i < plen - 1); i++)
683 {
684 if (*mailbox == delim || (!delim && strchr(NONULL(c_imap_delim_chars), *mailbox)))
685 {
686 delim = *mailbox;
687 /* Skip multiple occurrences of delim */
688 while (*mailbox && *(mailbox + 1) == delim)
689 mailbox++;
690 }
691 path[i] = *mailbox++;
692 }
693
694 /* Do not terminate with a delimiter */
695 if (i && path[i - 1] == delim)
696 i--;
697
698 /* Ensure null termination */
699 path[i] = '\0';
700 return path;
701}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
+ 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 709 of file util.c.

710{
711 const char *p = mailbox;
712 buf_reset(dest);
713 if (!p)
714 return;
715
716 while (*p)
717 {
718 if (p[0] == delim)
719 {
720 buf_addch(dest, '/');
721 /* simple way to avoid collisions with UIDs */
722 if ((p[1] >= '0') && (p[1] <= '9'))
723 buf_addch(dest, '_');
724 }
725 else
726 {
727 buf_addch(dest, *p);
728 }
729 p++;
730 }
731}
+ 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 740 of file util.c.

741{
742 char *pc = NULL;
743 char *pn = NULL;
744
745 if (!buf || !(pc = strchr(buf, '{')))
746 return -1;
747
748 pc++;
749 pn = pc;
750 while (isdigit((unsigned char) *pc))
751 pc++;
752 *pc = '\0';
753 if (!mutt_str_atoui(pn, bytes))
754 return -1;
755
756 return 0;
757}
const char * mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: atoi.c:203
+ 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 767 of file util.c.

768{
769 char *s = buf;
770
771 /* skip tag */
772 s = imap_next_word(s);
773 /* skip OK/NO/BAD response */
774 s = imap_next_word(s);
775
776 return s;
777}
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:784
+ 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 784 of file util.c.

785{
786 bool quoted = false;
787
788 while (*s)
789 {
790 if (*s == '\\')
791 {
792 s++;
793 if (*s)
794 s++;
795 continue;
796 }
797 if (*s == '\"')
798 quoted = !quoted;
799 if (!quoted && isspace(*s))
800 break;
801 s++;
802 }
803
804 SKIPWS(s);
805 return s;
806}
#define SKIPWS(ch)
Definition: string2.h:45
+ 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 815 of file util.c.

816{
817 struct Url url = { 0 };
818 mutt_account_tourl(cac, &url);
819 url.path = path;
820 url_tostring(&url, buf, buflen, U_NO_FLAGS);
821}
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:422
#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 832 of file util.c.

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

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

907{
908 char *buf = mutt_str_dup(src);
909 imap_utf_encode(unicode, &buf);
910
911 imap_quote_string(dest, dlen, buf, false);
912
913 FREE(&buf);
914}
void imap_utf_encode(bool unicode, char **s)
Encode email from local charset to UTF-8.
Definition: utf7.c:395
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
Quote string according to IMAP rules.
Definition: util.c:832
+ 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 923 of file util.c.

924{
926
927 char *buf = mutt_str_dup(s);
928 if (buf)
929 {
930 imap_utf_decode(unicode, &buf);
931 strncpy(s, buf, strlen(s));
932 }
933
934 FREE(&buf);
935}
void imap_utf_decode(bool unicode, char **s)
Decode email from UTF-8 to local charset.
Definition: utf7.c:428
void imap_unquote_string(char *s)
Equally stupid unquoting routine.
Definition: util.c:869
+ 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 1071 of file util.c.

1072{
1073 if (!seqset || (*seqset == '\0'))
1074 return NULL;
1075
1076 struct SeqsetIterator *iter = mutt_mem_calloc(1, sizeof(struct SeqsetIterator));
1077 iter->full_seqset = mutt_str_dup(seqset);
1078 iter->eostr = strchr(iter->full_seqset, '\0');
1079 iter->substr_cur = iter->substr_end = iter->full_seqset;
1080
1081 return iter;
1082}
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:169
char * eostr
Definition: private.h:171
char * substr_end
Definition: private.h:177
char * substr_cur
Definition: private.h:176
char * full_seqset
Definition: private.h:170
+ 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 1092 of file util.c.

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

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

1040{
1041 if (!a1 || !a2)
1042 return false;
1043 if (a1->type != a2->type)
1044 return false;
1045 if (!mutt_istr_equal(a1->host, a2->host))
1046 return false;
1047 if ((a1->port != 0) && (a2->port != 0) && (a1->port != a2->port))
1048 return false;
1049 if (a1->flags & a2->flags & MUTT_ACCT_USER)
1050 return mutt_str_equal(a1->user, a2->user);
1051
1052 const char *user = NONULL(Username);
1053
1054 const char *const c_imap_user = cs_subset_string(NeoMutt->sub, "imap_user");
1055 if ((a1->type == MUTT_ACCT_TYPE_IMAP) && c_imap_user)
1056 user = c_imap_user;
1057
1058 if (a1->flags & MUTT_ACCT_USER)
1059 return mutt_str_equal(a1->user, user);
1060 if (a2->flags & MUTT_ACCT_USER)
1061 return mutt_str_equal(a2->user, user);
1062
1063 return true;
1064}
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:44
char * Username
User's login name.
Definition: globals.c:42
@ MUTT_ACCT_TYPE_IMAP
Imap Account.
Definition: mutt_account.h:37
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 119 of file util.c.

120{
121 /* Make a copy of the mailbox name, but only if the pointers are different */
122 if (mbox != buf)
123 mutt_str_copy(buf, mbox, buflen);
124
125 int n = mutt_str_len(buf);
126
127 /* Let's go backwards until the next delimiter
128 *
129 * If buf[n] is a '/', the first n-- will allow us
130 * to ignore it. If it isn't, then buf looks like
131 * "/aaaaa/bbbb". There is at least one "b", so we can't skip
132 * the "/" after the 'a's.
133 *
134 * If buf == '/', then n-- => n == 0, so the loop ends
135 * immediately */
136 for (n--; (n >= 0) && (buf[n] != delim); n--)
137 ; // do nothing
138
139 /* We stopped before the beginning. There is a trailing slash. */
140 if (n > 0)
141 {
142 /* Strip the trailing delimiter. */
143 buf[n] = '\0';
144 }
145 else
146 {
147 buf[0] = (n == 0) ? delim : '\0';
148 }
149}
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:653
+ 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 395 of file utf7.c.

396{
397 if (!s || !*s)
398 return;
399
400 const char *c_charset = cc_charset();
401 if (!c_charset)
402 return;
403
404 if (unicode && mutt_ch_is_utf8(c_charset))
405 {
406 return;
407 }
408
409 if (mutt_ch_convert_string(s, c_charset, "utf-8", MUTT_ICONV_NO_FLAGS) != 0)
410 {
411 FREE(s);
412 return;
413 }
414
415 if (!unicode)
416 {
417 char *utf7 = utf8_to_utf7(*s, strlen(*s), NULL, 0);
418 FREE(s);
419 *s = utf7;
420 }
421}
const char * cc_charset(void)
Get the cached value of $charset.
Definition: cache.c:106
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:822
#define mutt_ch_is_utf8(str)
Definition: charset.h:96
#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:250
+ 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 428 of file utf7.c.

429{
430 if (!s || !*s)
431 return;
432
433 const char *c_charset = cc_charset();
434 if (!c_charset)
435 return;
436
437 if (unicode && mutt_ch_is_utf8(c_charset))
438 {
439 return;
440 }
441
442 if (!unicode)
443 {
444 char *utf8 = utf7_to_utf8(*s, strlen(*s), 0, 0);
445 FREE(s);
446 *s = utf8;
447 }
448
449 if (mutt_ch_convert_string(s, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS) != 0)
450 {
451 FREE(s);
452 }
453}
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:104
+ 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 1011 of file util.c.

1012{
1014 struct ImapMboxData *mdata = imap_mdata_get(m);
1015 if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1016 return;
1017 mdata->reopen |= IMAP_REOPEN_ALLOW;
1018}
+ 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 1024 of file util.c.

1025{
1027 struct ImapMboxData *mdata = imap_mdata_get(m);
1028 if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1029 return;
1030 mdata->reopen &= ~IMAP_REOPEN_ALLOW;
1031}
+ 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:101
+ Here is the call graph for this function:
+ Here is the caller graph for this function: