NeoMutt  2025-12-11-58-g09398d
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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.
 
#define IMAP_SSL_PORT   993
 Port for IMAP over SSL/TLS.
 
#define IMAP_LOG_CMD   2
 
#define IMAP_LOG_LTRL   3
 
#define IMAP_LOG_PASS   5
 
#define IMAP_RES_NO   -2
 <tag> NO ...
 
#define IMAP_RES_BAD   -1
 <tag> BAD ...
 
#define IMAP_RES_OK   0
 <tag> OK ...
 
#define IMAP_RES_CONTINUE   1
 * ...
 
#define IMAP_RES_RESPOND   2
 +
 
#define IMAP_RES_NEW   3
 ImapCommand.state additions.
 
#define SEQ_LEN   16
 
#define IMAP_OPEN_NO_FLAGS   0
 No flags are set.
 
#define IMAP_REOPEN_ALLOW   (1 << 0)
 Allow re-opening a folder upon expunge.
 
#define IMAP_EXPUNGE_EXPECTED   (1 << 1)
 Messages will be expunged from the server.
 
#define IMAP_EXPUNGE_PENDING   (1 << 2)
 Messages on the server have been expunged.
 
#define IMAP_NEWMAIL_PENDING   (1 << 3)
 New mail is waiting on the server.
 
#define IMAP_FLAGS_PENDING   (1 << 4)
 Flags have changed on the server.
 
#define IMAP_CMD_NO_FLAGS   0
 No flags are set.
 
#define IMAP_CMD_PASS   (1 << 0)
 Command contains a password. Suppress logging.
 
#define IMAP_CMD_QUEUE   (1 << 1)
 Queue a command, do not execute.
 
#define IMAP_CMD_POLL   (1 << 2)
 Poll the tcp connection before running the imap command.
 
#define IMAP_CMD_SINGLE   (1 << 3)
 Run a single command.
 
#define IMAP_DATELEN   27
 
#define IMAP_CAP_NO_FLAGS   0
 No flags are set.
 
#define IMAP_CAP_IMAP4   (1 << 0)
 Server supports IMAP4.
 
#define IMAP_CAP_IMAP4REV1   (1 << 1)
 Server supports IMAP4rev1.
 
#define IMAP_CAP_STATUS   (1 << 2)
 Server supports STATUS command.
 
#define IMAP_CAP_ACL   (1 << 3)
 RFC2086: IMAP4 ACL extension.
 
#define IMAP_CAP_NAMESPACE   (1 << 4)
 RFC2342: IMAP4 Namespace.
 
#define IMAP_CAP_AUTH_CRAM_MD5   (1 << 5)
 RFC2195: CRAM-MD5 authentication.
 
#define IMAP_CAP_AUTH_GSSAPI   (1 << 6)
 RFC1731: GSSAPI authentication.
 
#define IMAP_CAP_AUTH_ANONYMOUS   (1 << 7)
 AUTH=ANONYMOUS.
 
#define IMAP_CAP_AUTH_OAUTHBEARER   (1 << 8)
 RFC7628: AUTH=OAUTHBEARER.
 
#define IMAP_CAP_AUTH_XOAUTH2   (1 << 9)
 AUTH=XOAUTH2, deprecated but used by OWA.
 
#define IMAP_CAP_STARTTLS   (1 << 10)
 RFC2595: STARTTLS.
 
#define IMAP_CAP_LOGINDISABLED   (1 << 11)
 RFC2595: LOGINDISABLED.
 
#define IMAP_CAP_IDLE   (1 << 12)
 RFC2177: IDLE.
 
#define IMAP_CAP_SASL_IR   (1 << 13)
 SASL initial response draft.
 
#define IMAP_CAP_ENABLE   (1 << 14)
 RFC5161.
 
#define IMAP_CAP_CONDSTORE   (1 << 15)
 RFC7162.
 
#define IMAP_CAP_QRESYNC   (1 << 16)
 RFC7162.
 
#define IMAP_CAP_LIST_EXTENDED   (1 << 17)
 RFC5258: IMAP4 LIST Command Extensions.
 
#define IMAP_CAP_COMPRESS   (1 << 18)
 RFC4978: COMPRESS=DEFLATE.
 
#define IMAP_CAP_X_GM_EXT_1   (1 << 19)
 https://developers.google.com/gmail/imap/imap-extensions
 
#define IMAP_CAP_ID   (1 << 20)
 RFC2971: IMAP4 ID extension.
 
#define IMAP_CAP_ALL   ((1 << 21) - 1)
 

Typedefs

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

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

Detailed Description

Shared constants/structs that are private to IMAP.

Authors
  • Pietro Cerutti
  • Richard Russon
  • Mehdi Abaakouk

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

449{
450 char buf[2048] = { 0 };
451 char mbox[1024] = { 0 };
452
453 imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), mailbox);
454 snprintf(buf, sizeof(buf), "CREATE %s", mbox);
455
457 {
458 mutt_error(_("CREATE failed: %s"), imap_cmd_trailer(adata));
459 return -1;
460 }
461
462 return 0;
463}
#define mutt_error(...)
Definition logging2.h:93
const char * imap_cmd_trailer(struct ImapAccountData *adata)
Extra information after tagged command response if any.
Definition command.c:1285
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:1322
#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:960
#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 490 of file imap.c.

491{
492 char oldmbox[1024] = { 0 };
493 char newmbox[1024] = { 0 };
494 int rc = 0;
495
496 imap_munge_mbox_name(adata->unicode, oldmbox, sizeof(oldmbox), oldname);
497 imap_munge_mbox_name(adata->unicode, newmbox, sizeof(newmbox), newname);
498
499 struct Buffer *buf = buf_pool_get();
500 buf_printf(buf, "RENAME %s %s", oldmbox, newmbox);
501
503 rc = -1;
504
505 buf_pool_release(&buf);
506
507 return rc;
508}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
String manipulation buffer.
Definition buffer.h:36
+ 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 761 of file imap.c.

762{
763 if (mutt_socket_open(adata->conn) < 0)
764 return -1;
765
766 adata->state = IMAP_CONNECTED;
767
768 if (imap_cmd_step(adata) != IMAP_RES_OK)
769 {
771 return -1;
772 }
773
774 if (mutt_istr_startswith(adata->buf, "* OK"))
775 {
776 if (!mutt_istr_startswith(adata->buf, "* OK [CAPABILITY") && check_capabilities(adata))
777 {
778 goto bail;
779 }
780#ifdef USE_SSL
781 /* Attempt STARTTLS if available and desired. */
782 const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
783 if ((adata->conn->ssf == 0) &&
784 (c_ssl_force_tls || (adata->capabilities & IMAP_CAP_STARTTLS)))
785 {
786 enum QuadOption ans;
787
788 if (c_ssl_force_tls)
789 {
790 ans = MUTT_YES;
791 }
792 else if ((ans = query_quadoption(_("Secure connection with TLS?"),
793 NeoMutt->sub, "ssl_starttls")) == MUTT_ABORT)
794 {
795 goto bail;
796 }
797 if (ans == MUTT_YES)
798 {
799 enum ImapExecResult rc = imap_exec(adata, "STARTTLS", IMAP_CMD_SINGLE);
800 // Clear any data after the STARTTLS acknowledgement
801 mutt_socket_empty(adata->conn);
802
803 if (rc == IMAP_EXEC_FATAL)
804 goto bail;
805 if (rc != IMAP_EXEC_ERROR)
806 {
807 if (mutt_ssl_starttls(adata->conn))
808 {
809 mutt_error(_("Could not negotiate TLS connection"));
810 goto bail;
811 }
812 else
813 {
814 /* RFC2595 demands we recheck CAPABILITY after TLS completes. */
815 if (imap_exec(adata, "CAPABILITY", IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
816 goto bail;
817 }
818 }
819 }
820 }
821
822 if (c_ssl_force_tls && (adata->conn->ssf == 0))
823 {
824 mutt_error(_("Encrypted connection unavailable"));
825 goto bail;
826 }
827#endif
828 }
829 else if (mutt_istr_startswith(adata->buf, "* PREAUTH"))
830 {
831#ifdef USE_SSL
832 /* Unless using a secure $tunnel, an unencrypted PREAUTH response may be a
833 * MITM attack. The only way to stop "STARTTLS" MITM attacks is via
834 * $ssl_force_tls: an attacker can easily spoof "* OK" and strip the
835 * STARTTLS capability. So consult $ssl_force_tls, not $ssl_starttls, to
836 * decide whether to abort. Note that if using $tunnel and
837 * $tunnel_is_secure, adata->conn->ssf will be set to 1. */
838 const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
839 if ((adata->conn->ssf == 0) && c_ssl_force_tls)
840 {
841 mutt_error(_("Encrypted connection unavailable"));
842 goto bail;
843 }
844#endif
845
846 adata->state = IMAP_AUTHENTICATED;
847 if (check_capabilities(adata) != 0)
848 goto bail;
849 FREE(&adata->capstr);
850 }
851 else
852 {
853 imap_error("imap_open_connection()", adata->buf);
854 goto bail;
855 }
856
857 return 0;
858
859bail:
861 FREE(&adata->capstr);
862 return -1;
863}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
int mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
Definition gnutls.c:1171
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition command.c:1147
#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:660
#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:869
static int check_capabilities(struct ImapAccountData *adata)
Make sure we can log in to this server.
Definition imap.c:113
#define FREE(x)
Definition memory.h:62
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:244
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(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition question.c:377
void mutt_socket_empty(struct Connection *conn)
Clear out any queued data.
Definition socket.c:306
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition socket.c:76
unsigned int ssf
Security strength factor, in bits (see notes)
Definition connection.h:50
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:43
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
+ 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 869 of file imap.c.

870{
871 if (adata->state != IMAP_DISCONNECTED)
872 {
873 mutt_socket_close(adata->conn);
874 adata->state = IMAP_DISCONNECTED;
875 }
876 adata->seqno = 0;
877 adata->nextcmd = 0;
878 adata->lastcmd = 0;
879 adata->status = 0;
880 memset(adata->cmds, 0, sizeof(struct ImapCommand) * adata->cmdslots);
881}
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition socket.c:100
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 610 of file imap.c.

612{
613 char c;
614 bool r = false;
615 struct Buffer buf = { 0 }; // Do not allocate, maybe it won't be used
616
617 const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
618 if (c_debug_level >= IMAP_LOG_LTRL)
619 buf_alloc(&buf, bytes + 1);
620
621 mutt_debug(LL_DEBUG2, "reading %lu bytes\n", bytes);
622
623 for (unsigned long pos = 0; pos < bytes; pos++)
624 {
625 if (mutt_socket_readchar(adata->conn, &c) != 1)
626 {
627 mutt_debug(LL_DEBUG1, "error during read, %lu bytes read\n", pos);
628 adata->status = IMAP_FATAL;
629
630 buf_dealloc(&buf);
631 return -1;
632 }
633
634 if (r && (c != '\n'))
635 fputc('\r', fp);
636
637 if (c == '\r')
638 {
639 r = true;
640 continue;
641 }
642 else
643 {
644 r = false;
645 }
646
647 fputc(c, fp);
648
649 if ((pos % 1024) == 0)
650 progress_update(progress, pos, -1);
651 if (c_debug_level >= IMAP_LOG_LTRL)
652 buf_addch(&buf, c);
653 }
654
655 if (c_debug_level >= IMAP_LOG_LTRL)
656 {
657 mutt_debug(IMAP_LOG_LTRL, "\n%s", buf.data);
658 buf_dealloc(&buf);
659 }
660 return 0;
661}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition buffer.c:377
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:337
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
#define mutt_debug(LEVEL,...)
Definition logging2.h:90
#define IMAP_LOG_LTRL
Definition private.h:49
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:45
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:44
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition progress.c:80
int mutt_socket_readchar(struct Connection *conn, char *c)
Simple read buffering to speed things up.
Definition socket.c:200
char * data
Pointer to data.
Definition buffer.h:37
+ 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 689 of file imap.c.

690{
692 struct ImapMboxData *mdata = imap_mdata_get(m);
693 if (!adata || !mdata)
694 return;
695
696 struct Email *e = NULL;
697
698#ifdef USE_HCACHE
699 imap_hcache_open(adata, mdata, false);
700#endif
701
702 for (int i = 0; i < m->msg_count; i++)
703 {
704 e = m->emails[i];
705 if (!e)
706 break;
707
708 if (e->index == INT_MAX)
709 {
710 mutt_debug(LL_DEBUG2, "Expunging message UID %u\n", imap_edata_get(e)->uid);
711
712 e->deleted = true;
713
714 imap_cache_del(m, e);
715#ifdef USE_HCACHE
716 imap_hcache_del(mdata, imap_edata_get(e)->uid);
717#endif
718
719 mutt_hash_int_delete(mdata->uid_hash, imap_edata_get(e)->uid, e);
720
721 imap_edata_free((void **) &e->edata);
722 }
723 else
724 {
725 /* NeoMutt has several places where it turns off e->active as a
726 * hack. For example to avoid FLAG updates, or to exclude from
727 * imap_exec_msg_set.
728 *
729 * Unfortunately, when a reopen is allowed and the IMAP_EXPUNGE_PENDING
730 * flag becomes set (e.g. a flag update to a modified header),
731 * this function will be called by imap_cmd_finish().
732 *
733 * The ctx_update_tables() will free and remove these "inactive" headers,
734 * despite that an EXPUNGE was not received for them.
735 * This would result in memory leaks and segfaults due to dangling
736 * pointers in the msn_index and uid_hash.
737 *
738 * So this is another hack to work around the hacks. We don't want to
739 * remove the messages, so make sure active is on. */
740 e->active = true;
741 }
742 }
743
744#ifdef USE_HCACHE
745 imap_hcache_close(mdata);
746#endif
747
749 if (resort)
750 {
752 }
753}
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition mailbox.c:231
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition mailbox.h:181
@ NT_MAILBOX_UPDATE
Update internal tables.
Definition mailbox.h:182
void imap_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free() -.
Definition edata.c:39
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:123
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition edata.c:66
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition mdata.c:61
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition message.c:1888
void imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool create)
Open a header cache.
Definition util.c:302
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition util.c:343
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition util.c:401
void * adata
Private data (for Mailbox backends)
Definition account.h:42
The envelope/body of an email.
Definition email.h:39
void * edata
Driver-specific data.
Definition email.h:74
bool active
Message is not to be removed.
Definition email.h:76
bool deleted
Email is deleted.
Definition email.h:78
int index
The absolute (unsorted) message number.
Definition email.h:110
IMAP-specific Account data -.
Definition adata.h:40
IMAP-specific Mailbox data -.
Definition mdata.h:40
struct HashTable * uid_hash
Hash Table: "uid" -> Email.
Definition mdata.h:59
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 1808 of file imap.c.

1809{
1810 if (!adata)
1811 return -1;
1812
1813 if (adata->state == IMAP_DISCONNECTED)
1814 {
1815 buf_reset(&adata->cmdbuf); // purge outstanding queued commands
1816 imap_open_connection(adata);
1817 }
1818 if (adata->state == IMAP_CONNECTED)
1819 {
1821 {
1822 adata->state = IMAP_AUTHENTICATED;
1823 FREE(&adata->capstr);
1824 if (adata->conn->ssf != 0)
1825 {
1826 mutt_debug(LL_DEBUG2, "Communication encrypted at %d bits\n",
1827 adata->conn->ssf);
1828 }
1829 }
1830 else
1831 {
1833 }
1834 }
1835 if (adata->state == IMAP_AUTHENTICATED)
1836 {
1837 /* capabilities may have changed */
1838 imap_exec(adata, "CAPABILITY", IMAP_CMD_PASS);
1839
1840#ifdef USE_ZLIB
1841 /* RFC4978 */
1842 const bool c_imap_deflate = cs_subset_bool(NeoMutt->sub, "imap_deflate");
1843 if ((adata->capabilities & IMAP_CAP_COMPRESS) && c_imap_deflate &&
1844 (imap_exec(adata, "COMPRESS DEFLATE", IMAP_CMD_PASS) == IMAP_EXEC_SUCCESS))
1845 {
1846 mutt_debug(LL_DEBUG2, "IMAP compression is enabled on connection to %s\n",
1847 adata->conn->account.host);
1848 mutt_zstrm_wrap_conn(adata->conn);
1849 }
1850#endif
1851
1852 /* enable RFC2971, if the server supports that */
1853 const bool c_imap_send_id = cs_subset_bool(NeoMutt->sub, "imap_send_id");
1854 if (c_imap_send_id && (adata->capabilities & IMAP_CAP_ID))
1855 {
1856 imap_exec(adata, "ID (\"name\" \"NeoMutt\" \"version\" \"" PACKAGE_VERSION "\")",
1858 }
1859
1860 /* enable RFC6855, if the server supports that */
1861 const bool c_imap_rfc5161 = cs_subset_bool(NeoMutt->sub, "imap_rfc5161");
1862 if (c_imap_rfc5161 && (adata->capabilities & IMAP_CAP_ENABLE))
1863 imap_exec(adata, "ENABLE UTF8=ACCEPT", IMAP_CMD_QUEUE);
1864
1865 /* enable QRESYNC. Advertising QRESYNC also means CONDSTORE
1866 * is supported (even if not advertised), so flip that bit. */
1867 if (adata->capabilities & IMAP_CAP_QRESYNC)
1868 {
1870 const bool c_imap_qresync = cs_subset_bool(NeoMutt->sub, "imap_qresync");
1871 if (c_imap_rfc5161 && c_imap_qresync)
1872 imap_exec(adata, "ENABLE QRESYNC", IMAP_CMD_QUEUE);
1873 }
1874
1875 /* get root delimiter, '/' as default */
1876 adata->delim = '/';
1877 imap_exec(adata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
1878
1879 /* we may need the root delimiter before we open a mailbox */
1880 imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1881
1882 /* select the mailbox that used to be open before disconnect */
1883 if (adata->mailbox)
1884 {
1885 imap_mbox_select(adata->mailbox);
1886 }
1887 }
1888
1889 if (adata->state < IMAP_AUTHENTICATED)
1890 return -1;
1891
1892 return 0;
1893}
@ IMAP_AUTH_SUCCESS
Authentication successful.
Definition auth.h:40
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
void mutt_account_unsetpass(struct ConnAccount *cac)
Unset ConnAccount's password.
int imap_authenticate(struct ImapAccountData *adata)
Authenticate to an IMAP server.
Definition auth.c:115
#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:761
static void imap_mbox_select(struct Mailbox *m)
Select a Mailbox.
Definition imap.c:1775
char host[128]
Server to login to.
Definition connaccount.h:54
struct ConnAccount account
Account details: username, password, etc.
Definition connection.h:49
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:291
+ 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 946 of file imap.c.

948{
951
952 if (!adata || (adata->mailbox != m) || !e)
953 return -1;
954
956 {
957 if (e->deleted == edata->deleted)
958 e->changed = false;
959 return 0;
960 }
961
962 buf_printf(cmd, "UID STORE %u", edata->uid);
963
964 struct Buffer *flags = buf_pool_get();
965
966 set_flag(m, MUTT_ACL_SEEN, e->read, "\\Seen ", flags);
967 set_flag(m, MUTT_ACL_WRITE, e->old, "Old ", flags);
968 set_flag(m, MUTT_ACL_WRITE, e->flagged, "\\Flagged ", flags);
969 set_flag(m, MUTT_ACL_WRITE, e->replied, "\\Answered ", flags);
970 set_flag(m, MUTT_ACL_DELETE, edata->deleted, "\\Deleted ", flags);
971
972 if (m->rights & MUTT_ACL_WRITE)
973 {
974 /* restore system flags */
975 if (edata->flags_system)
976 buf_addstr(flags, edata->flags_system);
977
978 /* set custom flags */
979 struct Buffer *tags = buf_pool_get();
981 if (!buf_is_empty(tags))
982 buf_addstr(flags, buf_string(tags));
983 buf_pool_release(&tags);
984 }
985
987 buf_fix_dptr(flags);
988
989 /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
990 * explicitly revoke all system flags (if we have permission) */
991 if (buf_is_empty(flags))
992 {
993 set_flag(m, MUTT_ACL_SEEN, true, "\\Seen ", flags);
994 set_flag(m, MUTT_ACL_WRITE, true, "Old ", flags);
995 set_flag(m, MUTT_ACL_WRITE, true, "\\Flagged ", flags);
996 set_flag(m, MUTT_ACL_WRITE, true, "\\Answered ", flags);
997 set_flag(m, MUTT_ACL_DELETE, !edata->deleted, "\\Deleted ", flags);
998
999 /* erase custom flags */
1000 if ((m->rights & MUTT_ACL_WRITE) && edata->flags_remote)
1001 buf_addstr(flags, edata->flags_remote);
1002
1004 buf_fix_dptr(flags);
1005
1006 buf_addstr(cmd, " -FLAGS.SILENT (");
1007 }
1008 else
1009 {
1010 buf_addstr(cmd, " FLAGS.SILENT (");
1011 }
1012
1013 buf_addstr(cmd, buf_string(flags));
1014 buf_addstr(cmd, ")");
1015
1016 int rc = -1;
1017
1018 /* after all this it's still possible to have no flags, if you
1019 * have no ACL rights */
1020 if (!buf_is_empty(flags) &&
1022 err_continue && (*err_continue != MUTT_YES))
1023 {
1024 *err_continue = imap_continue("imap_sync_message: STORE failed", adata->buf);
1025 if (*err_continue != MUTT_YES)
1026 goto done;
1027 }
1028
1029 /* server have now the updated flags */
1030 FREE(&edata->flags_remote);
1031 struct Buffer *flags_remote = buf_pool_get();
1032 driver_tags_get_with_hidden(&e->tags, flags_remote);
1033 edata->flags_remote = buf_strdup(flags_remote);
1034 buf_pool_release(&flags_remote);
1035
1036 if (e->deleted == edata->deleted)
1037 e->changed = false;
1038
1039 rc = 0;
1040
1041done:
1042 buf_pool_release(&flags);
1043 return rc;
1044}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition buffer.c:182
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
#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
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:649
static void set_flag(struct Mailbox *m, AclFlags aclflag, bool flag, const char *str, struct Buffer *flags)
Append str to flags if we currently have permission according to aclflag.
Definition imap.c:193
static bool compare_flags_for_copy(struct Email *e)
Compare local flags against the server.
Definition imap.c:213
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition string.c:565
bool read
Email is read.
Definition email.h:50
bool old
Email is seen, but unread.
Definition email.h:49
bool changed
Email has been edited.
Definition email.h:77
bool flagged
Marked important?
Definition email.h:47
bool replied
Email has been replied to.
Definition email.h:51
struct TagList tags
For drivers that support server tagging.
Definition email.h:72
IMAP-specific Email data -.
Definition edata.h:35
char * flags_remote
Definition edata.h:49
bool deleted
Email has been deleted.
Definition edata.h:39
char * flags_system
Definition edata.h:48
AclFlags rights
ACL bits, see AclFlags.
Definition mailbox.h:119
void driver_tags_get_with_hidden(struct TagList *tl, struct Buffer *tags)
Get all tags, also hidden ones, separated by space.
Definition tags.c:174
+ 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 894 of file imap.c.

895{
896 if (STAILQ_EMPTY(flag_list))
897 return false;
898
899 const size_t flaglen = mutt_str_len(flag);
900 struct ListNode *np = NULL;
901 STAILQ_FOREACH(np, flag_list, entries)
902 {
903 const size_t nplen = strlen(np->data);
904 if ((flaglen >= nplen) && ((flag[nplen] == '\0') || (flag[nplen] == ' ')) &&
905 mutt_istrn_equal(np->data, flag, nplen))
906 {
907 return true;
908 }
909
910 if (mutt_str_equal(np->data, "\\*"))
911 return true;
912 }
913
914 return false;
915}
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:660
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:498
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:455
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
#define STAILQ_EMPTY(head)
Definition queue.h:382
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
+ 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 **ap = NULL;
83 {
84 struct Account *a = *ap;
85 if (a->type != MUTT_IMAP)
86 continue;
87
88 tmp_adata = a->adata;
89 if (!tmp_adata)
90 continue;
91 if (imap_account_match(&tmp_adata->conn->account, &cac))
92 {
93 if (mdata)
94 {
95 *mdata = imap_mdata_new(tmp_adata, tmp);
96 }
97 *adata = tmp_adata;
98 return 0;
99 }
100 }
101 mutt_debug(LL_DEBUG3, "no ImapAccountData found\n");
102 return -1;
103}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:214
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:50
struct ImapMboxData * imap_mdata_new(struct ImapAccountData *adata, const char *name)
Allocate and initialise a new ImapMboxData structure.
Definition mdata.c:74
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:46
A group of associated Mailboxes.
Definition account.h:36
enum MailboxType type
Type of Mailboxes this Account contains.
Definition account.h:37
Login details for a remote server.
Definition connaccount.h:53
struct AccountArray accounts
All Accounts.
Definition neomutt.h:48
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:477
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition util.c:1095
+ 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 115 of file auth.c.

116{
117 int rc = IMAP_AUTH_FAILURE;
118
119 const struct Slist *c_imap_authenticators = cs_subset_slist(NeoMutt->sub, "imap_authenticators");
120 if (c_imap_authenticators && (c_imap_authenticators->count > 0))
121 {
122 mutt_debug(LL_DEBUG2, "Trying user-defined imap_authenticators\n");
123
124 /* Try user-specified list of authentication methods */
125 struct ListNode *np = NULL;
126 STAILQ_FOREACH(np, &c_imap_authenticators->head, entries)
127 {
128 mutt_debug(LL_DEBUG2, "Trying method %s\n", np->data);
129
130 for (size_t i = 0; i < countof(ImapAuthenticators); i++)
131 {
132 const struct ImapAuth *auth = &ImapAuthenticators[i];
133 if (!auth->method || mutt_istr_equal(auth->method, np->data))
134 {
135 rc = auth->authenticate(adata, np->data);
136 if (rc == IMAP_AUTH_SUCCESS)
137 {
138 return rc;
139 }
140 }
141 }
142 }
143 }
144 else
145 {
146 /* Fall back to default: any authenticator */
147 mutt_debug(LL_DEBUG2, "Trying pre-defined imap_authenticators\n");
148
149 for (size_t i = 0; i < countof(ImapAuthenticators); i++)
150 {
151 rc = ImapAuthenticators[i].authenticate(adata, NULL);
152 if (rc == IMAP_AUTH_SUCCESS)
153 return rc;
154 }
155 }
156
157 mutt_error(_("No authenticators available or wrong credentials"));
158 return rc;
159}
@ IMAP_AUTH_FAILURE
Authentication failed.
Definition auth.h:41
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Definition helpers.c:242
static const struct ImapAuth ImapAuthenticators[]
Accepted authentication methods.
Definition auth.c:64
#define countof(x)
Definition memory.h:44
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:672
IMAP authentication multiplexor.
Definition auth.c:46
enum ImapAuthRes(* authenticate)(struct ImapAccountData *adata, const char *method)
Definition auth.c:55
const char * method
Name of authentication method supported, NULL means variable.
Definition auth.c:57
String list.
Definition slist.h:37
struct ListHead head
List containing values.
Definition slist.h:38
size_t count
Number of values in list.
Definition slist.h:39
+ 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 1133 of file command.c.

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

1148{
1149 if (!adata)
1150 return -1;
1151
1152 size_t len = 0;
1153 int c;
1154 int rc;
1155 int stillrunning = 0;
1156 struct ImapCommand *cmd = NULL;
1157
1158 if (adata->status == IMAP_FATAL)
1159 {
1160 cmd_handle_fatal(adata);
1161 return IMAP_RES_BAD;
1162 }
1163
1164 /* read into buffer, expanding buffer as necessary until we have a full
1165 * line */
1166 do
1167 {
1168 if (len == adata->blen)
1169 {
1170 MUTT_MEM_REALLOC(&adata->buf, adata->blen + IMAP_CMD_BUFSIZE, char);
1171 adata->blen = adata->blen + IMAP_CMD_BUFSIZE;
1172 mutt_debug(LL_DEBUG3, "grew buffer to %zu bytes\n", adata->blen);
1173 }
1174
1175 /* back up over '\0' */
1176 if (len)
1177 len--;
1178 c = mutt_socket_readln_d(adata->buf + len, adata->blen - len, adata->conn, MUTT_SOCK_LOG_FULL);
1179 if (c <= 0)
1180 {
1181 mutt_debug(LL_DEBUG1, "Error reading server response\n");
1182 cmd_handle_fatal(adata);
1183 return IMAP_RES_BAD;
1184 }
1185
1186 len += c;
1187 }
1188 /* if we've read all the way to the end of the buffer, we haven't read a
1189 * full line (mutt_socket_readln strips the \r, so we always have at least
1190 * one character free when we've read a full line) */
1191 while (len == adata->blen);
1192
1193 /* don't let one large string make cmd->buf hog memory forever */
1194 if ((adata->blen > IMAP_CMD_BUFSIZE) && (len <= IMAP_CMD_BUFSIZE))
1195 {
1196 MUTT_MEM_REALLOC(&adata->buf, IMAP_CMD_BUFSIZE, char);
1197 adata->blen = IMAP_CMD_BUFSIZE;
1198 mutt_debug(LL_DEBUG3, "shrank buffer to %zu bytes\n", adata->blen);
1199 }
1200
1201 adata->lastread = mutt_date_now();
1202
1203 /* handle untagged messages. The caller still gets its shot afterwards. */
1204 if ((mutt_str_startswith(adata->buf, "* ") ||
1205 mutt_str_startswith(imap_next_word(adata->buf), "OK [")) &&
1206 cmd_handle_untagged(adata))
1207 {
1208 return IMAP_RES_BAD;
1209 }
1210
1211 /* server demands a continuation response from us */
1212 if (adata->buf[0] == '+')
1213 return IMAP_RES_RESPOND;
1214
1215 /* Look for tagged command completions.
1216 *
1217 * Some response handlers can end up recursively calling
1218 * imap_cmd_step() and end up handling all tagged command
1219 * completions.
1220 * (e.g. FETCH->set_flag->set_header_color->~h pattern match.)
1221 *
1222 * Other callers don't even create an adata->cmds entry.
1223 *
1224 * For both these cases, we default to returning OK */
1225 rc = IMAP_RES_OK;
1226 c = adata->lastcmd;
1227 do
1228 {
1229 cmd = &adata->cmds[c];
1230 if (cmd->state == IMAP_RES_NEW)
1231 {
1232 if (mutt_str_startswith(adata->buf, cmd->seq))
1233 {
1234 if (!stillrunning)
1235 {
1236 /* first command in queue has finished - move queue pointer up */
1237 adata->lastcmd = (adata->lastcmd + 1) % adata->cmdslots;
1238 }
1239 cmd->state = cmd_status(adata->buf);
1240 rc = cmd->state;
1241 if (cmd->state == IMAP_RES_NO || cmd->state == IMAP_RES_BAD)
1242 {
1243 mutt_message(_("IMAP command failed: %s"), adata->buf);
1244 }
1245 }
1246 else
1247 {
1248 stillrunning++;
1249 }
1250 }
1251
1252 c = (c + 1) % adata->cmdslots;
1253 } while (c != adata->nextcmd);
1254
1255 if (stillrunning)
1256 {
1257 rc = IMAP_RES_CONTINUE;
1258 }
1259 else
1260 {
1261 mutt_debug(LL_DEBUG3, "IMAP queue drained\n");
1262 imap_cmd_finish(adata);
1263 }
1264
1265 return rc;
1266}
#define mutt_message(...)
Definition logging2.h:92
static int cmd_handle_untagged(struct ImapAccountData *adata)
Fallback parser for otherwise unhandled messages.
Definition command.c:1037
static int cmd_status(const char *s)
Parse response line for tagged OK/NO/BAD.
Definition command.c:240
static void cmd_handle_fatal(struct ImapAccountData *adata)
When ImapAccountData is in fatal state, do what we can.
Definition command.c:168
#define IMAP_CMD_BUFSIZE
Definition command.c:59
void imap_cmd_finish(struct ImapAccountData *adata)
Attempt to perform cleanup.
Definition command.c:1388
#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:824
#define IMAP_RES_BAD
<tag> BAD ...
Definition private.h:54
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition memory.h:50
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:455
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:232
int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
Read a line from a socket.
Definition socket.c:238
#define MUTT_SOCK_LOG_FULL
Definition socket.h:54
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 1388 of file command.c.

1389{
1390 if (!adata)
1391 return;
1392
1393 if (adata->status == IMAP_FATAL)
1394 {
1395 adata->closing = false;
1396 cmd_handle_fatal(adata);
1397 return;
1398 }
1399
1400 if (!(adata->state >= IMAP_SELECTED) || (adata->mailbox && adata->closing))
1401 {
1402 adata->closing = false;
1403 return;
1404 }
1405
1406 adata->closing = false;
1407
1408 struct ImapMboxData *mdata = imap_mdata_get(adata->mailbox);
1409
1410 if (mdata && mdata->reopen & IMAP_REOPEN_ALLOW)
1411 {
1412 // First remove expunged emails from the msn_index
1413 if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1414 {
1415 mutt_debug(LL_DEBUG2, "Expunging mailbox\n");
1416 imap_expunge_mailbox(adata->mailbox, true);
1417 /* Detect whether we've gotten unexpected EXPUNGE messages */
1418 if (!(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1419 mdata->check_status |= IMAP_EXPUNGE_PENDING;
1421 }
1422
1423 // Then add new emails to it
1424 if (mdata->reopen & IMAP_NEWMAIL_PENDING)
1425 {
1426 const size_t max_msn = imap_msn_highest(&mdata->msn);
1427 if (mdata->new_mail_count > max_msn)
1428 {
1429 if (!(mdata->reopen & IMAP_EXPUNGE_PENDING))
1430 mdata->check_status |= IMAP_NEWMAIL_PENDING;
1431
1432 mutt_debug(LL_DEBUG2, "Fetching new mails from %zd to %u\n",
1433 max_msn + 1, mdata->new_mail_count);
1434 imap_read_headers(adata->mailbox, max_msn + 1, mdata->new_mail_count, false);
1435 }
1436 }
1437
1438 // And to finish inform about MUTT_REOPEN if needed
1439 if (mdata->reopen & IMAP_EXPUNGE_PENDING && !(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1440 mdata->check_status |= IMAP_EXPUNGE_PENDING;
1441
1442 if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1444 }
1445
1446 adata->status = 0;
1447}
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:1354
#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:689
size_t imap_msn_highest(const struct MSNArray *msn)
Return the highest MSN in use.
Definition msn.c:72
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 1274 of file command.c.

1275{
1276 return cmd_status(s) == IMAP_RES_OK;
1277}
+ 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 1285 of file command.c.

1286{
1287 static const char *notrailer = "";
1288 const char *s = adata->buf;
1289
1290 if (!s)
1291 {
1292 mutt_debug(LL_DEBUG2, "not a tagged response\n");
1293 return notrailer;
1294 }
1295
1296 s = imap_next_word((char *) s);
1297 if (!s || (!mutt_istr_startswith(s, "OK") && !mutt_istr_startswith(s, "NO") &&
1298 !mutt_istr_startswith(s, "BAD")))
1299 {
1300 mutt_debug(LL_DEBUG2, "not a command completion: %s\n", adata->buf);
1301 return notrailer;
1302 }
1303
1304 s = imap_next_word((char *) s);
1305 if (!s)
1306 return notrailer;
1307
1308 return s;
1309}
+ 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 1322 of file command.c.

1323{
1324 if (!adata)
1325 return IMAP_EXEC_ERROR;
1326
1327 if (flags & IMAP_CMD_SINGLE)
1328 {
1329 // Process any existing commands
1330 if (adata->nextcmd != adata->lastcmd)
1331 imap_exec(adata, NULL, IMAP_CMD_POLL);
1332 }
1333
1334 int rc = cmd_start(adata, cmdstr, flags);
1335 if (rc < 0)
1336 {
1337 cmd_handle_fatal(adata);
1338 return IMAP_EXEC_FATAL;
1339 }
1340
1341 if (flags & IMAP_CMD_QUEUE)
1342 return IMAP_EXEC_SUCCESS;
1343
1344 const short c_imap_poll_timeout = cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1345 if ((flags & IMAP_CMD_POLL) && (c_imap_poll_timeout > 0) &&
1346 ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1347 {
1348 mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1349 cmd_handle_fatal(adata);
1350 return IMAP_EXEC_FATAL;
1351 }
1352
1353 /* Allow interruptions, particularly useful if there are network problems. */
1355 do
1356 {
1357 rc = imap_cmd_step(adata);
1358 // The queue is empty, so the single command has been processed
1359 if ((flags & IMAP_CMD_SINGLE) && (adata->nextcmd == adata->lastcmd))
1360 break;
1361 } while (rc == IMAP_RES_CONTINUE);
1363
1364 if (rc == IMAP_RES_NO)
1365 return IMAP_EXEC_ERROR;
1366 if (rc != IMAP_RES_OK)
1367 {
1368 if (adata->status != IMAP_FATAL)
1369 return IMAP_EXEC_ERROR;
1370
1371 mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1372 return IMAP_EXEC_FATAL;
1373 }
1374
1375 return IMAP_EXEC_SUCCESS;
1376}
#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:315
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition socket.c:182
+ 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 1455 of file command.c.

1456{
1457 int rc;
1458
1459 if (cmd_start(adata, "IDLE", IMAP_CMD_POLL) < 0)
1460 {
1461 cmd_handle_fatal(adata);
1462 return -1;
1463 }
1464
1465 const short c_imap_poll_timeout = cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1466 if ((c_imap_poll_timeout > 0) &&
1467 ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1468 {
1469 mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1470 cmd_handle_fatal(adata);
1471 return -1;
1472 }
1473
1474 do
1475 {
1476 rc = imap_cmd_step(adata);
1477 } while (rc == IMAP_RES_CONTINUE);
1478
1479 if (rc == IMAP_RES_RESPOND)
1480 {
1481 /* successfully entered IDLE state */
1482 adata->state = IMAP_IDLE;
1483 /* queue automatic exit when next command is issued */
1484 buf_addstr(&adata->cmdbuf, "DONE\r\n");
1485 rc = IMAP_RES_OK;
1486 }
1487 if (rc != IMAP_RES_OK)
1488 {
1489 mutt_debug(LL_DEBUG1, "error starting IDLE\n");
1490 return -1;
1491 }
1492
1493 return 0;
1494}
+ 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 1354 of file message.c.

1356{
1357 unsigned int maxuid = 0;
1358 int rc = -1;
1359 bool evalhc = false;
1360
1361#ifdef USE_HCACHE
1362 uint32_t uidvalidity = 0;
1363 unsigned int uid_next = 0;
1364 unsigned long long modseq = 0;
1365 bool has_condstore = false;
1366 bool has_qresync = false;
1367 bool eval_condstore = false;
1368 bool eval_qresync = false;
1369 char *uid_seqset = NULL;
1370 const unsigned int msn_begin_save = msn_begin;
1371#endif /* USE_HCACHE */
1372
1374 struct ImapMboxData *mdata = imap_mdata_get(m);
1375 if (!adata || (adata->mailbox != m) || !mdata)
1376 return -1;
1377
1378#ifdef USE_HCACHE
1379retry:
1380#endif /* USE_HCACHE */
1381
1382 /* make sure context has room to hold the mailbox */
1383 mx_alloc_memory(m, msn_end);
1384 imap_msn_reserve(&mdata->msn, msn_end);
1385 imap_alloc_uid_hash(adata, msn_end);
1386
1388 mdata->new_mail_count = 0;
1389
1390#ifdef USE_HCACHE
1391 imap_hcache_open(adata, mdata, true);
1392
1393 if (mdata->hcache && initial_download)
1394 {
1395 hcache_fetch_raw_obj(mdata->hcache, "UIDVALIDITY", 11, &uidvalidity);
1396 hcache_fetch_raw_obj(mdata->hcache, "UIDNEXT", 7, &uid_next);
1397 if (mdata->modseq)
1398 {
1399 const bool c_imap_condstore = cs_subset_bool(NeoMutt->sub, "imap_condstore");
1400 if ((adata->capabilities & IMAP_CAP_CONDSTORE) && c_imap_condstore)
1401 has_condstore = true;
1402
1403 /* If IMAP_CAP_QRESYNC and ImapQResync then NeoMutt sends ENABLE QRESYNC.
1404 * If we receive an ENABLED response back, then adata->qresync is set. */
1405 if (adata->qresync)
1406 has_qresync = true;
1407 }
1408
1409 if (uidvalidity && uid_next && (uidvalidity == mdata->uidvalidity))
1410 {
1411 evalhc = true;
1412 if (hcache_fetch_raw_obj(mdata->hcache, "MODSEQ", 6, &modseq))
1413 {
1414 if (has_qresync)
1415 {
1416 uid_seqset = imap_hcache_get_uid_seqset(mdata);
1417 if (uid_seqset)
1418 eval_qresync = true;
1419 }
1420
1421 if (!eval_qresync && has_condstore)
1422 eval_condstore = true;
1423 }
1424 }
1425 }
1426 if (evalhc)
1427 {
1428 if (eval_qresync)
1429 {
1430 if (read_headers_qresync_eval_cache(adata, uid_seqset) < 0)
1431 goto bail;
1432 }
1433 else
1434 {
1435 if (read_headers_normal_eval_cache(adata, msn_end, uid_next, has_condstore || has_qresync,
1436 eval_condstore) < 0)
1437 goto bail;
1438 }
1439
1440 if ((eval_condstore || eval_qresync) && (modseq != mdata->modseq))
1441 {
1443 modseq, eval_qresync) < 0)
1444 {
1445 goto bail;
1446 }
1447 }
1448
1449 /* Look for the first empty MSN and start there */
1450 while (msn_begin <= msn_end)
1451 {
1452 if (!imap_msn_get(&mdata->msn, msn_begin - 1))
1453 break;
1454 msn_begin++;
1455 }
1456 }
1457#endif /* USE_HCACHE */
1458
1459 if (read_headers_fetch_new(m, msn_begin, msn_end, evalhc, &maxuid, initial_download) < 0)
1460 goto bail;
1461
1462#ifdef USE_HCACHE
1463 if (eval_qresync && initial_download)
1464 {
1465 if (imap_verify_qresync(m) != 0)
1466 {
1467 eval_qresync = false;
1468 eval_condstore = false;
1469 evalhc = false;
1470 modseq = 0;
1471 maxuid = 0;
1472 FREE(&uid_seqset);
1473 uidvalidity = 0;
1474 uid_next = 0;
1475 msn_begin = msn_begin_save;
1476
1477 goto retry;
1478 }
1479 }
1480#endif /* USE_HCACHE */
1481
1482 if (maxuid && (mdata->uid_next < maxuid + 1))
1483 mdata->uid_next = maxuid + 1;
1484
1485#ifdef USE_HCACHE
1486 hcache_store_raw(mdata->hcache, "UIDVALIDITY", 11, &mdata->uidvalidity,
1487 sizeof(mdata->uidvalidity));
1488 if (maxuid && (mdata->uid_next < maxuid + 1))
1489 {
1490 mutt_debug(LL_DEBUG2, "Overriding UIDNEXT: %u -> %u\n", mdata->uid_next, maxuid + 1);
1491 mdata->uid_next = maxuid + 1;
1492 }
1493 if (mdata->uid_next > 1)
1494 {
1495 hcache_store_raw(mdata->hcache, "UIDNEXT", 7, &mdata->uid_next, sizeof(mdata->uid_next));
1496 }
1497
1498 /* We currently only sync CONDSTORE and QRESYNC on the initial download.
1499 * To do it more often, we'll need to deal with flag updates combined with
1500 * unsync'ed local flag changes. We'll also need to properly sync flags to
1501 * the header cache on close. I'm not sure it's worth the added complexity. */
1502 if (initial_download)
1503 {
1504 if (has_condstore || has_qresync)
1505 {
1506 hcache_store_raw(mdata->hcache, "MODSEQ", 6, &mdata->modseq, sizeof(mdata->modseq));
1507 }
1508 else
1509 {
1510 hcache_delete_raw(mdata->hcache, "MODSEQ", 6);
1511 }
1512
1513 if (has_qresync)
1515 else
1517 }
1518#endif /* USE_HCACHE */
1519
1520 /* TODO: it's not clear to me why we are calling mx_alloc_memory yet again. */
1522
1523 mdata->reopen |= IMAP_REOPEN_ALLOW;
1524
1525 rc = msn_end;
1526
1527bail:
1528#ifdef USE_HCACHE
1530 FREE(&uid_seqset);
1531#endif /* USE_HCACHE */
1532
1533 return rc;
1534}
int hcache_delete_raw(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition hcache.c:754
int 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:726
#define hcache_fetch_raw_obj(hc, key, keylen, dst)
Definition lib.h:162
static int imap_verify_qresync(struct Mailbox *m)
Check to see if QRESYNC got jumbled.
Definition message.c:1027
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:926
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:1104
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:690
static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *uid_seqset)
Retrieve data from the header cache.
Definition message.c:838
static void imap_alloc_uid_hash(struct ImapAccountData *adata, unsigned int msn_count)
Create a Hash Table for the UIDs.
Definition message.c:531
int imap_hcache_store_uid_seqset(struct ImapMboxData *mdata)
Store a UID Sequence Set in the header cache.
Definition util.c:418
char * imap_hcache_get_uid_seqset(struct ImapMboxData *mdata)
Get a UID Sequence Set from the header cache.
Definition util.c:453
int imap_hcache_clear_uid_seqset(struct ImapMboxData *mdata)
Delete a UID Sequence Set from the header cache.
Definition util.c:439
struct Email * imap_msn_get(const struct MSNArray *msn, int idx)
Return the Email associated with an msn.
Definition msn.c:83
void imap_msn_reserve(struct MSNArray *msn, size_t num)
Create / reallocate the cache.
Definition msn.c:44
void mx_alloc_memory(struct Mailbox *m, int req_size)
Create storage for the emails.
Definition mx.c:1211
bool qresync
true, if QRESYNC is successfully ENABLE'd
Definition adata.h:63
unsigned int uid_next
Definition mdata.h:52
unsigned long long modseq
Definition mdata.h:53
uint32_t uidvalidity
Definition mdata.h:51
+ 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 1939 of file message.c.

1940{
1942 if (!adata || (adata->mailbox != m))
1943 return NULL;
1944
1945 struct ImapHeader newh = { 0 };
1946 struct ImapEmailData old_edata = { 0 };
1947 int local_changes = e->changed;
1948
1949 struct ImapEmailData *edata = e->edata;
1950 newh.edata = edata;
1951
1952 mutt_debug(LL_DEBUG2, "parsing FLAGS\n");
1953 s = msg_parse_flags(&newh, s);
1954 if (!s)
1955 return NULL;
1956
1957 /* Update tags system */
1958 /* We take a copy of the tags so we can split the string */
1959 char *tags_copy = mutt_str_dup(edata->flags_remote);
1960 driver_tags_replace(&e->tags, tags_copy);
1961 FREE(&tags_copy);
1962
1963 /* YAUH (yet another ugly hack): temporarily set context to
1964 * read-write even if it's read-only, so *server* updates of
1965 * flags can be processed by mutt_set_flag. mailbox->changed must
1966 * be restored afterwards */
1967 bool readonly = m->readonly;
1968 m->readonly = false;
1969
1970 /* This is redundant with the following two checks. Removing:
1971 * mutt_set_flag (m, e, MUTT_NEW, !(edata->read || edata->old), true); */
1972 set_changed_flag(m, e, local_changes, server_changes, MUTT_OLD, old_edata.old,
1973 edata->old, e->old);
1974 set_changed_flag(m, e, local_changes, server_changes, MUTT_READ,
1975 old_edata.read, edata->read, e->read);
1976 set_changed_flag(m, e, local_changes, server_changes, MUTT_DELETE,
1977 old_edata.deleted, edata->deleted, e->deleted);
1978 set_changed_flag(m, e, local_changes, server_changes, MUTT_FLAG,
1979 old_edata.flagged, edata->flagged, e->flagged);
1980 set_changed_flag(m, e, local_changes, server_changes, MUTT_REPLIED,
1981 old_edata.replied, edata->replied, e->replied);
1982
1983 /* this message is now definitively *not* changed (mutt_set_flag
1984 * marks things changed as a side-effect) */
1985 if (local_changes == 0)
1986 e->changed = false;
1987 m->changed &= !readonly;
1988 m->readonly = readonly;
1989
1990 return s;
1991}
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:650
static char * msg_parse_flags(struct ImapHeader *h, char *s)
Read a FLAGS token into an ImapHeader.
Definition message.c:194
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:255
@ MUTT_READ
Messages that have been read.
Definition mutt.h:73
@ MUTT_OLD
Old messages.
Definition mutt.h:71
@ MUTT_FLAG
Flagged messages.
Definition mutt.h:79
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:75
@ MUTT_REPLIED
Messages that have been replied to.
Definition mutt.h:72
bool old
Email has been seen.
Definition edata.h:38
bool read
Email has been read.
Definition edata.h:37
bool flagged
Email has been flagged.
Definition edata.h:40
bool replied
Email has been replied to.
Definition edata.h:41
IMAP-specific header.
Definition message.h:34
struct ImapEmailData * edata
Definition message.h:35
bool changed
Mailbox has been modified.
Definition mailbox.h:110
bool readonly
Don't allow changes to the mailbox.
Definition mailbox.h:116
bool driver_tags_replace(struct TagList *tl, const char *tags)
Replace all tags.
Definition tags.c:201
+ 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 1888 of file message.c.

1889{
1891 struct ImapMboxData *mdata = imap_mdata_get(m);
1892
1893 if (!e || !adata || (adata->mailbox != m) || !mdata)
1894 return -1;
1895
1896 mdata->bcache = imap_bcache_open(m);
1897 char id[64] = { 0 };
1898 snprintf(id, sizeof(id), "%u-%u", mdata->uidvalidity, imap_edata_get(e)->uid);
1899 return mutt_bcache_del(mdata->bcache, id);
1900}
int mutt_bcache_del(struct BodyCache *bcache, const char *id)
Delete a file from the Body Cache.
Definition bcache.c:269
static struct BodyCache * imap_bcache_open(struct Mailbox *m)
Open a message cache.
Definition message.c:81
+ 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 1907 of file message.c.

1908{
1910 struct ImapMboxData *mdata = imap_mdata_get(m);
1911
1912 if (!adata || (adata->mailbox != m) || !mdata)
1913 return -1;
1914
1915 mdata->bcache = imap_bcache_open(m);
1917
1918 return 0;
1919}
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
Definition bcache.c:334
static int imap_bcache_delete(const char *id, struct BodyCache *bcache, void *data)
Delete an entry from the message cache - Implements bcache_list_t -.
Definition message.c:169
+ 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 1543 of file message.c.

1544{
1545 if (!m || !msg)
1546 return -1;
1547
1549 struct ImapMboxData *mdata = imap_mdata_get(m);
1550 if (!adata || !mdata)
1551 return -1;
1552
1553 FILE *fp = NULL;
1554 char buf[2048] = { 0 };
1555 struct Buffer *internaldate = NULL;
1556 struct Buffer *imap_flags = NULL;
1557 size_t len;
1558 struct Progress *progress = NULL;
1559 size_t sent;
1560 int c, last;
1561 int rc;
1562
1563 fp = mutt_file_fopen(msg->path, "r");
1564 if (!fp)
1565 {
1566 mutt_perror("%s", msg->path);
1567 goto fail;
1568 }
1569
1570 /* currently we set the \Seen flag on all messages, but probably we
1571 * should scan the message Status header for flag info. Since we're
1572 * already rereading the whole file for length it isn't any more
1573 * expensive (it'd be nice if we had the file size passed in already
1574 * by the code that writes the file, but that's a lot of changes.
1575 * Ideally we'd have an Email structure with flag info here... */
1576 for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c)
1577 {
1578 if ((c == '\n') && (last != '\r'))
1579 len++;
1580
1581 len++;
1582 }
1583 rewind(fp);
1584
1585 if (m->verbose)
1586 {
1587 progress = progress_new(MUTT_PROGRESS_NET, len);
1588 progress_set_message(progress, _("Uploading message..."));
1589 }
1590
1591 internaldate = buf_pool_get();
1592 mutt_date_make_imap(internaldate, msg->received);
1593
1594 imap_flags = buf_pool_get();
1595
1596 if (msg->flags.read)
1597 buf_addstr(imap_flags, " \\Seen");
1598 if (msg->flags.replied)
1599 buf_addstr(imap_flags, " \\Answered");
1600 if (msg->flags.flagged)
1601 buf_addstr(imap_flags, " \\Flagged");
1602 if (msg->flags.draft)
1603 buf_addstr(imap_flags, " \\Draft");
1604
1605 snprintf(buf, sizeof(buf), "APPEND %s (%s) \"%s\" {%lu}", mdata->munge_name,
1606 imap_flags->data + 1, buf_string(internaldate), (unsigned long) len);
1607 buf_pool_release(&internaldate);
1608
1609 imap_cmd_start(adata, buf);
1610
1611 do
1612 {
1613 rc = imap_cmd_step(adata);
1614 } while (rc == IMAP_RES_CONTINUE);
1615
1616 if (rc != IMAP_RES_RESPOND)
1617 goto cmd_step_fail;
1618
1619 for (last = EOF, sent = len = 0; (c = fgetc(fp)) != EOF; last = c)
1620 {
1621 if ((c == '\n') && (last != '\r'))
1622 buf[len++] = '\r';
1623
1624 buf[len++] = c;
1625
1626 if (len > sizeof(buf) - 3)
1627 {
1628 sent += len;
1629 if (flush_buffer(buf, &len, adata->conn) < 0)
1630 goto fail;
1631 progress_update(progress, sent, -1);
1632 }
1633 }
1634
1635 if (len > 0)
1636 if (flush_buffer(buf, &len, adata->conn) < 0)
1637 goto fail;
1638
1639 if (mutt_socket_send(adata->conn, "\r\n") < 0)
1640 goto fail;
1641 mutt_file_fclose(&fp);
1642
1643 do
1644 {
1645 rc = imap_cmd_step(adata);
1646 } while (rc == IMAP_RES_CONTINUE);
1647
1648 if (rc != IMAP_RES_OK)
1649 goto cmd_step_fail;
1650
1651 progress_free(&progress);
1652 buf_pool_release(&imap_flags);
1653 return 0;
1654
1655cmd_step_fail:
1656 mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1657 if (rc != IMAP_RES_BAD)
1658 {
1659 char *pc = imap_next_word(adata->buf); /* skip sequence number or token */
1660 pc = imap_next_word(pc); /* skip response code */
1661 if (*pc != '\0')
1662 mutt_error("%s", pc);
1663 }
1664
1665fail:
1666 mutt_file_fclose(&fp);
1667 progress_free(&progress);
1668 buf_pool_release(&imap_flags);
1669 return -1;
1670}
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
#define mutt_perror(...)
Definition logging2.h:94
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition command.c:1133
static int flush_buffer(char *buf, size_t *len, struct Connection *conn)
Write data to a connection.
Definition message.c:491
int mutt_date_make_imap(struct Buffer *buf, time_t timestamp)
Format date in IMAP style: DD-MMM-YYYY HH:MM:SS +ZZzz.
Definition date.c:810
@ MUTT_PROGRESS_NET
Progress tracks bytes, according to $net_inc
Definition lib.h:82
struct Progress * progress_new(enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition progress.c:139
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition progress.c:110
void progress_set_message(struct Progress *progress, const char *fmt,...) __attribute__((__format__(__printf__
#define mutt_socket_send(conn, buf)
Definition socket.h:57
char * munge_name
Munged version of the mailbox name.
Definition mdata.h:42
bool verbose
Display status messages?
Definition mailbox.h:117
char * path
path to temp file
Definition message.h:36
struct Message::@264267271004327071125374067057142037276212342100 flags
Flags for the Message.
bool draft
Message has been read.
Definition message.h:44
bool replied
Message has been replied to.
Definition message.h:43
time_t received
Time at which this message was received.
Definition message.h:46
bool flagged
Message is flagged.
Definition message.h:42
bool read
Message has been read.
Definition message.h:41
+ 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,
bool create )

Open a header cache.

Parameters
adataImap Account data
mdataImap Mailbox data
createCreate a new header cache if missing?

Definition at line 302 of file util.c.

303{
304 if (!adata || !mdata)
305 return;
306
307 if (mdata->hcache)
308 return;
309
310 struct HeaderCache *hc = NULL;
311 struct Buffer *mbox = buf_pool_get();
312 struct Buffer *cachepath = buf_pool_get();
313
314 imap_cachepath(adata->delim, mdata->name, mbox);
315
316 if (strstr(buf_string(mbox), "/../") || mutt_str_equal(buf_string(mbox), "..") ||
317 mutt_strn_equal(buf_string(mbox), "../", 3))
318 {
319 goto cleanup;
320 }
321 size_t len = buf_len(mbox);
322 if ((len > 3) && (mutt_str_equal(buf_string(mbox) + len - 3, "/..")))
323 goto cleanup;
324
325 struct Url url = { 0 };
326 account_to_url(&adata->conn->account, &url);
327 url.path = mbox->data;
328 url_tobuffer(&url, cachepath, U_PATH);
329
330 const char *const c_header_cache = cs_subset_path(NeoMutt->sub, "header_cache");
331 hc = hcache_open(c_header_cache, buf_string(cachepath), imap_hcache_namer, create);
332
333cleanup:
334 buf_pool_release(&mbox);
335 buf_pool_release(&cachepath);
336 mdata->hcache = hc;
337}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:491
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
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:291
struct HeaderCache * hcache_open(const char *path, const char *folder, hcache_namer_t namer, bool create)
Multiplexor for StoreOps::open.
Definition hcache.c:473
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:427
void account_to_url(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Header Cache.
Definition lib.h:86
struct HeaderCache * hcache
Email header cache.
Definition mdata.h:63
char * name
Mailbox name.
Definition mdata.h:41
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(const 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:749
+ 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 343 of file util.c.

344{
345 if (!mdata->hcache)
346 return;
347
348 hcache_close(&mdata->hcache);
349}
void hcache_close(struct HeaderCache **ptr)
Multiplexor for StoreOps::close.
Definition hcache.c:544
+ 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 358 of file util.c.

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

384{
385 if (!mdata->hcache)
386 return -1;
387
388 char key[16] = { 0 };
389
390 snprintf(key, sizeof(key), "%u", imap_edata_get(e)->uid);
391 return hcache_store_email(mdata->hcache, key, mutt_str_len(key), e, mdata->uidvalidity);
392}
int hcache_store_email(struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
Multiplexor for StoreOps::store.
Definition hcache.c:672
+ 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 401 of file util.c.

402{
403 if (!mdata->hcache)
404 return -1;
405
406 char key[16] = { 0 };
407
408 snprintf(key, sizeof(key), "%u", uid);
409 return hcache_delete_email(mdata->hcache, key, mutt_str_len(key));
410}
int hcache_delete_email(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition hcache.c:741
+ 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 418 of file util.c.

419{
420 if (!mdata->hcache)
421 return -1;
422
423 struct Buffer *buf = buf_pool_get();
424 buf_alloc(buf, 8192); // The seqset is likely large. Preallocate to reduce reallocs
426
427 int rc = hcache_store_raw(mdata->hcache, "UIDSEQSET", 9, buf->data, buf_len(buf) + 1);
428 mutt_debug(LL_DEBUG3, "Stored UIDSEQSET %s\n", buf_string(buf));
429 buf_pool_release(&buf);
430 return rc;
431}
static void imap_msn_index_to_uid_seqset(struct Buffer *buf, struct ImapMboxData *mdata)
Convert MSN index of UIDs to Seqset.
Definition util.c:234
+ 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 439 of file util.c.

440{
441 if (!mdata->hcache)
442 return -1;
443
444 return hcache_delete_raw(mdata->hcache, "UIDSEQSET", 9);
445}
+ 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 453 of file util.c.

454{
455 if (!mdata->hcache)
456 return NULL;
457
458 char *seqset = hcache_fetch_raw_str(mdata->hcache, "UIDSEQSET", 9);
459 mutt_debug(LL_DEBUG3, "Retrieved UIDSEQSET %s\n", NONULL(seqset));
460
461 return seqset;
462}
char * hcache_fetch_raw_str(struct HeaderCache *hc, const char *key, size_t keylen)
Fetch a string from the cache.
Definition hcache.c:654
#define NONULL(x)
Definition string2.h:43
+ 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 649 of file util.c.

650{
651 imap_error(msg, resp);
652 return query_yesorno(_("Continue?"), MUTT_NO);
653}
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition quad.h:38
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:325
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition util.c:660
+ 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 660 of file util.c.

661{
662 mutt_error("%s [%s]", where, msg);
663}
+ 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 109 of file util.c.

110{
111 mutt_hash_free(&mdata->uid_hash);
112 imap_msn_free(&mdata->msn);
113 mutt_bcache_close(&mdata->bcache);
114}
void mutt_bcache_close(struct BodyCache **ptr)
Close an Email-Body Cache.
Definition bcache.c:167
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition hash.c:457
void imap_msn_free(struct MSNArray *msn)
Free the cache.
Definition msn.c:62
struct BodyCache * bcache
Email body cache.
Definition mdata.h:61
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_fix_path()

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

Fix up the imap path.

Parameters
mailboxMailbox path
pathBuffer for the result
plenLength of buffer
Return values
ptrFixed-up path
Note
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 681 of file util.c.

682{
683 const char *const c_imap_delim_chars = cs_subset_string(NeoMutt->sub, "imap_delim_chars");
684
685 char *out = path;
686 size_t space_left = plen - 1;
687
688 if (mailbox)
689 {
690 for (const char *c = mailbox; *c && space_left; c++, space_left--)
691 {
692 if (strchr(NONULL(c_imap_delim_chars), *c))
693 {
694 return imap_fix_path_with_delim(*c, mailbox, path, plen);
695 }
696 *out++ = *c;
697 }
698 }
699
700 *out = '\0';
701 return path;
702}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
char * imap_fix_path_with_delim(const char delim, const char *mailbox, char *path, size_t plen)
Fix up the imap path.
Definition util.c:713
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_fix_path_with_delim()

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

Fix up the imap path.

Parameters
delimDelimiter specified by the server
mailboxMailbox path
pathBuffer for the result
plenLength of buffer
Return values
ptrFixed-up path

Definition at line 713 of file util.c.

714{
715 char *out = path;
716 size_t space_left = plen - 1;
717
718 if (mailbox)
719 {
720 for (const char *c = mailbox; *c && space_left; c++, space_left--)
721 {
722 if (*c == delim || *c == '/')
723 {
724 while (*c && *(c + 1) == *c)
725 c++;
726 *out++ = delim;
727 }
728 else
729 {
730 *out++ = *c;
731 }
732 }
733 }
734
735 if (out != path && *(out - 1) == delim)
736 {
737 out--;
738 }
739 *out = '\0';
740 return path;
741}
+ 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 749 of file util.c.

750{
751 const char *p = mailbox;
752 buf_reset(dest);
753 if (!p)
754 return;
755
756 while (*p)
757 {
758 if (p[0] == delim)
759 {
760 buf_addch(dest, '/');
761 /* simple way to avoid collisions with UIDs */
762 if ((p[1] >= '0') && (p[1] <= '9'))
763 buf_addch(dest, '_');
764 }
765 else
766 {
767 buf_addch(dest, *p);
768 }
769 p++;
770 }
771}
+ 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 780 of file util.c.

781{
782 char *pc = NULL;
783 char *pn = NULL;
784
785 if (!buf || !(pc = strchr(buf, '{')))
786 return -1;
787
788 pc++;
789 pn = pc;
790 while (mutt_isdigit(*pc))
791 pc++;
792 *pc = '\0';
793 if (!mutt_str_atoui(pn, bytes))
794 return -1;
795
796 return 0;
797}
const char * mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition atoi.c:217
bool mutt_isdigit(int arg)
Wrapper for isdigit(3)
Definition ctype.c:65
+ 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 807 of file util.c.

808{
809 char *s = buf;
810
811 /* skip tag */
812 s = imap_next_word(s);
813 /* skip OK/NO/BAD response */
814 s = imap_next_word(s);
815
816 return s;
817}
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition util.c:824
+ 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 824 of file util.c.

825{
826 bool quoted = false;
827
828 while (*s)
829 {
830 if (*s == '\\')
831 {
832 s++;
833 if (*s)
834 s++;
835 continue;
836 }
837 if (*s == '\"')
838 quoted = !quoted;
839 if (!quoted && mutt_isspace(*s))
840 break;
841 s++;
842 }
843
844 SKIPWS(s);
845 return s;
846}
bool mutt_isspace(int arg)
Wrapper for isspace(3)
Definition ctype.c:95
#define SKIPWS(ch)
Definition string2.h:51
+ Here is the call graph for this function:
+ 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 855 of file util.c.

856{
857 struct Url url = { 0 };
858 account_to_url(cac, &url);
859 url.path = path;
860 url_tostring(&url, buf, buflen, U_NO_FLAGS);
861}
int url_tostring(const 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_buf_qualify_path()

void imap_buf_qualify_path ( struct Buffer * buf,
struct ConnAccount * cac,
char * path )

Make an absolute IMAP folder target to a buffer.

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

Definition at line 869 of file util.c.

870{
871 struct Url url = { 0 };
872 account_to_url(cac, &url);
873 url.path = path;
874 url_tobuffer(&url, buf, U_NO_FLAGS);
875}
+ 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 886 of file util.c.

887{
888 const char *quote = "`\"\\";
889 if (!quote_backtick)
890 quote++;
891
892 char *pt = dest;
893 const char *s = src;
894
895 *pt++ = '"';
896 /* save room for quote-chars */
897 dlen -= 3;
898
899 for (; *s && dlen; s++)
900 {
901 if (strchr(quote, *s))
902 {
903 if (dlen < 2)
904 break;
905 dlen -= 2;
906 *pt++ = '\\';
907 *pt++ = *s;
908 }
909 else
910 {
911 *pt++ = *s;
912 dlen--;
913 }
914 }
915 *pt++ = '"';
916 *pt = '\0';
917}
+ 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 923 of file util.c.

924{
925 char *d = s;
926
927 if (*s == '\"')
928 s++;
929 else
930 return;
931
932 while (*s)
933 {
934 if (*s == '\"')
935 {
936 *d = '\0';
937 return;
938 }
939 if (*s == '\\')
940 {
941 s++;
942 }
943 if (*s)
944 {
945 *d = *s;
946 d++;
947 s++;
948 }
949 }
950 *d = '\0';
951}
+ 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 960 of file util.c.

961{
962 char *buf = mutt_str_dup(src);
963 imap_utf_encode(unicode, &buf);
964
965 imap_quote_string(dest, dlen, buf, false);
966
967 FREE(&buf);
968}
void imap_utf_encode(bool unicode, char **s)
Encode email from local charset to UTF-8.
Definition utf7.c:397
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
Quote string according to IMAP rules.
Definition util.c:886
+ 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 977 of file util.c.

978{
980
981 char *buf = mutt_str_dup(s);
982 if (buf)
983 {
984 imap_utf_decode(unicode, &buf);
985 strncpy(s, buf, strlen(s));
986 }
987
988 FREE(&buf);
989}
void imap_utf_decode(bool unicode, char **s)
Decode email from UTF-8 to local charset.
Definition utf7.c:430
void imap_unquote_string(char *s)
Equally stupid unquoting routine.
Definition util.c:923
+ 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 1127 of file util.c.

1128{
1129 if (!seqset || (*seqset == '\0'))
1130 return NULL;
1131
1132 struct SeqsetIterator *iter = MUTT_MEM_CALLOC(1, struct SeqsetIterator);
1133 iter->full_seqset = mutt_str_dup(seqset);
1134 iter->eostr = strchr(iter->full_seqset, '\0');
1135 iter->substr_cur = iter->substr_end = iter->full_seqset;
1136
1137 return iter;
1138}
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:47
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 1148 of file util.c.

1149{
1150 if (!iter || !next)
1151 return -1;
1152
1153 if (iter->in_range)
1154 {
1155 if ((iter->down && (iter->range_cur == (iter->range_end - 1))) ||
1156 (!iter->down && (iter->range_cur == (iter->range_end + 1))))
1157 {
1158 iter->in_range = 0;
1159 }
1160 }
1161
1162 if (!iter->in_range)
1163 {
1164 iter->substr_cur = iter->substr_end;
1165 if (iter->substr_cur == iter->eostr)
1166 return 1;
1167
1168 iter->substr_end = strchr(iter->substr_cur, ',');
1169 if (!iter->substr_end)
1170 iter->substr_end = iter->eostr;
1171 else
1172 *(iter->substr_end++) = '\0';
1173
1174 char *range_sep = strchr(iter->substr_cur, ':');
1175 if (range_sep)
1176 *range_sep++ = '\0';
1177
1178 if (!mutt_str_atoui_full(iter->substr_cur, &iter->range_cur))
1179 return -1;
1180 if (range_sep)
1181 {
1182 if (!mutt_str_atoui_full(range_sep, &iter->range_end))
1183 return -1;
1184 }
1185 else
1186 {
1187 iter->range_end = iter->range_cur;
1188 }
1189
1190 iter->down = (iter->range_end < iter->range_cur);
1191 iter->in_range = 1;
1192 }
1193
1194 *next = iter->range_cur;
1195 if (iter->down)
1196 iter->range_cur--;
1197 else
1198 iter->range_cur++;
1199
1200 return 0;
1201}
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 1207 of file util.c.

1208{
1209 if (!ptr || !*ptr)
1210 return;
1211
1212 struct SeqsetIterator *iter = *ptr;
1213 FREE(&iter->full_seqset);
1214 FREE(ptr);
1215}
+ 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 1095 of file util.c.

1096{
1097 if (!a1 || !a2)
1098 return false;
1099 if (a1->type != a2->type)
1100 return false;
1101 if (!mutt_istr_equal(a1->host, a2->host))
1102 return false;
1103 if ((a1->port != 0) && (a2->port != 0) && (a1->port != a2->port))
1104 return false;
1105 if (a1->flags & a2->flags & MUTT_ACCT_USER)
1106 return mutt_str_equal(a1->user, a2->user);
1107
1108 const char *user = NONULL(NeoMutt->username);
1109
1110 const char *const c_imap_user = cs_subset_string(NeoMutt->sub, "imap_user");
1111 if ((a1->type == MUTT_ACCT_TYPE_IMAP) && c_imap_user)
1112 user = c_imap_user;
1113
1114 if (a1->flags & MUTT_ACCT_USER)
1115 return mutt_str_equal(a1->user, user);
1116 if (a2->flags & MUTT_ACCT_USER)
1117 return mutt_str_equal(a2->user, user);
1118
1119 return true;
1120}
#define MUTT_ACCT_USER
User field has been set.
Definition connaccount.h:44
@ MUTT_ACCT_TYPE_IMAP
Imap Account.
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
char * username
User's login name.
Definition neomutt.h:55
+ 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 123 of file util.c.

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

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

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

1068{
1070 struct ImapMboxData *mdata = imap_mdata_get(m);
1071 if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1072 return;
1073 mdata->reopen |= IMAP_REOPEN_ALLOW;
1074}
+ 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 1080 of file util.c.

1081{
1083 struct ImapMboxData *mdata = imap_mdata_get(m);
1084 if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1085 return;
1086 mdata->reopen &= ~IMAP_REOPEN_ALLOW;
1087}
+ 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 if (!mdata)
265 return;
266
267 mutt_debug(LL_DEBUG2, "Handling SEARCH\n");
268
269 while ((s = imap_next_word((char *) s)) && (*s != '\0'))
270 {
271 if (!mutt_str_atoui(s, &uid))
272 continue;
273 e = mutt_hash_int_find(mdata->uid_hash, uid);
274 if (e)
275 e->matched = true;
276 }
277}
void * mutt_hash_int_find(const struct HashTable *table, unsigned int intkey)
Find the HashElem data in a Hash Table element using a key.
Definition hash.c:392
bool matched
Search matches this Email.
Definition email.h:102
+ Here is the call graph for this function:
+ Here is the caller graph for this function: