NeoMutt  2025-09-05-7-geaa2bd
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 435 of file imap.c.

436{
437 char buf[2048] = { 0 };
438 char mbox[1024] = { 0 };
439
440 imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), mailbox);
441 snprintf(buf, sizeof(buf), "CREATE %s", mbox);
442
444 {
445 mutt_error(_("CREATE failed: %s"), imap_cmd_trailer(adata));
446 return -1;
447 }
448
449 return 0;
450}
#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:1265
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:1302
#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:959
#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 477 of file imap.c.

478{
479 char oldmbox[1024] = { 0 };
480 char newmbox[1024] = { 0 };
481 int rc = 0;
482
483 imap_munge_mbox_name(adata->unicode, oldmbox, sizeof(oldmbox), oldname);
484 imap_munge_mbox_name(adata->unicode, newmbox, sizeof(newmbox), newname);
485
486 struct Buffer *buf = buf_pool_get();
487 buf_printf(buf, "RENAME %s %s", oldmbox, newmbox);
488
490 rc = -1;
491
492 buf_pool_release(&buf);
493
494 return rc;
495}
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 743 of file imap.c.

744{
745 if (mutt_socket_open(adata->conn) < 0)
746 return -1;
747
748 adata->state = IMAP_CONNECTED;
749
750 if (imap_cmd_step(adata) != IMAP_RES_OK)
751 {
753 return -1;
754 }
755
756 if (mutt_istr_startswith(adata->buf, "* OK"))
757 {
758 if (!mutt_istr_startswith(adata->buf, "* OK [CAPABILITY") && check_capabilities(adata))
759 {
760 goto bail;
761 }
762#ifdef USE_SSL
763 /* Attempt STARTTLS if available and desired. */
764 const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
765 if ((adata->conn->ssf == 0) &&
766 (c_ssl_force_tls || (adata->capabilities & IMAP_CAP_STARTTLS)))
767 {
768 enum QuadOption ans;
769
770 if (c_ssl_force_tls)
771 {
772 ans = MUTT_YES;
773 }
774 else if ((ans = query_quadoption(_("Secure connection with TLS?"),
775 NeoMutt->sub, "ssl_starttls")) == MUTT_ABORT)
776 {
777 goto bail;
778 }
779 if (ans == MUTT_YES)
780 {
781 enum ImapExecResult rc = imap_exec(adata, "STARTTLS", IMAP_CMD_SINGLE);
782 // Clear any data after the STARTTLS acknowledgement
783 mutt_socket_empty(adata->conn);
784
785 if (rc == IMAP_EXEC_FATAL)
786 goto bail;
787 if (rc != IMAP_EXEC_ERROR)
788 {
789 if (mutt_ssl_starttls(adata->conn))
790 {
791 mutt_error(_("Could not negotiate TLS connection"));
792 goto bail;
793 }
794 else
795 {
796 /* RFC2595 demands we recheck CAPABILITY after TLS completes. */
797 if (imap_exec(adata, "CAPABILITY", IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
798 goto bail;
799 }
800 }
801 }
802 }
803
804 if (c_ssl_force_tls && (adata->conn->ssf == 0))
805 {
806 mutt_error(_("Encrypted connection unavailable"));
807 goto bail;
808 }
809#endif
810 }
811 else if (mutt_istr_startswith(adata->buf, "* PREAUTH"))
812 {
813#ifdef USE_SSL
814 /* Unless using a secure $tunnel, an unencrypted PREAUTH response may be a
815 * MITM attack. The only way to stop "STARTTLS" MITM attacks is via
816 * $ssl_force_tls: an attacker can easily spoof "* OK" and strip the
817 * STARTTLS capability. So consult $ssl_force_tls, not $ssl_starttls, to
818 * decide whether to abort. Note that if using $tunnel and
819 * $tunnel_is_secure, adata->conn->ssf will be set to 1. */
820 const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
821 if ((adata->conn->ssf == 0) && c_ssl_force_tls)
822 {
823 mutt_error(_("Encrypted connection unavailable"));
824 goto bail;
825 }
826#endif
827
828 adata->state = IMAP_AUTHENTICATED;
829 if (check_capabilities(adata) != 0)
830 goto bail;
831 FREE(&adata->capstr);
832 }
833 else
834 {
835 imap_error("imap_open_connection()", adata->buf);
836 goto bail;
837 }
838
839 return 0;
840
841bail:
843 FREE(&adata->capstr);
844 return -1;
845}
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:1149
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1127
#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:659
#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:851
static int check_capabilities(struct ImapAccountData *adata)
Make sure we can log in to this server.
Definition: imap.c:106
#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:243
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:378
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 851 of file imap.c.

852{
853 if (adata->state != IMAP_DISCONNECTED)
854 {
855 mutt_socket_close(adata->conn);
856 adata->state = IMAP_DISCONNECTED;
857 }
858 adata->seqno = 0;
859 adata->nextcmd = 0;
860 adata->lastcmd = 0;
861 adata->status = 0;
862 memset(adata->cmds, 0, sizeof(struct ImapCommand) * adata->cmdslots);
863}
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 592 of file imap.c.

594{
595 char c;
596 bool r = false;
597 struct Buffer buf = { 0 }; // Do not allocate, maybe it won't be used
598
599 const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
600 if (c_debug_level >= IMAP_LOG_LTRL)
601 buf_alloc(&buf, bytes + 1);
602
603 mutt_debug(LL_DEBUG2, "reading %lu bytes\n", bytes);
604
605 for (unsigned long pos = 0; pos < bytes; pos++)
606 {
607 if (mutt_socket_readchar(adata->conn, &c) != 1)
608 {
609 mutt_debug(LL_DEBUG1, "error during read, %lu bytes read\n", pos);
610 adata->status = IMAP_FATAL;
611
612 buf_dealloc(&buf);
613 return -1;
614 }
615
616 if (r && (c != '\n'))
617 fputc('\r', fp);
618
619 if (c == '\r')
620 {
621 r = true;
622 continue;
623 }
624 else
625 {
626 r = false;
627 }
628
629 fputc(c, fp);
630
631 if ((pos % 1024) == 0)
632 progress_update(progress, pos, -1);
633 if (c_debug_level >= IMAP_LOG_LTRL)
634 buf_addch(&buf, c);
635 }
636
637 if (c_debug_level >= IMAP_LOG_LTRL)
638 {
639 mutt_debug(IMAP_LOG_LTRL, "\n%s", buf.data);
640 buf_dealloc(&buf);
641 }
642 return 0;
643}
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 671 of file imap.c.

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

1782{
1783 if (!adata)
1784 return -1;
1785
1786 if (adata->state == IMAP_DISCONNECTED)
1787 {
1788 buf_reset(&adata->cmdbuf); // purge outstanding queued commands
1789 imap_open_connection(adata);
1790 }
1791 if (adata->state == IMAP_CONNECTED)
1792 {
1794 {
1795 adata->state = IMAP_AUTHENTICATED;
1796 FREE(&adata->capstr);
1797 if (adata->conn->ssf != 0)
1798 {
1799 mutt_debug(LL_DEBUG2, "Communication encrypted at %d bits\n",
1800 adata->conn->ssf);
1801 }
1802 }
1803 else
1804 {
1806 }
1807 }
1808 if (adata->state == IMAP_AUTHENTICATED)
1809 {
1810 /* capabilities may have changed */
1811 imap_exec(adata, "CAPABILITY", IMAP_CMD_PASS);
1812
1813#ifdef USE_ZLIB
1814 /* RFC4978 */
1815 const bool c_imap_deflate = cs_subset_bool(NeoMutt->sub, "imap_deflate");
1816 if ((adata->capabilities & IMAP_CAP_COMPRESS) && c_imap_deflate &&
1817 (imap_exec(adata, "COMPRESS DEFLATE", IMAP_CMD_PASS) == IMAP_EXEC_SUCCESS))
1818 {
1819 mutt_debug(LL_DEBUG2, "IMAP compression is enabled on connection to %s\n",
1820 adata->conn->account.host);
1821 mutt_zstrm_wrap_conn(adata->conn);
1822 }
1823#endif
1824
1825 /* enable RFC2971, if the server supports that */
1826 const bool c_imap_send_id = cs_subset_bool(NeoMutt->sub, "imap_send_id");
1827 if (c_imap_send_id && (adata->capabilities & IMAP_CAP_ID))
1828 {
1829 imap_exec(adata, "ID (\"name\" \"NeoMutt\" \"version\" \"" PACKAGE_VERSION "\")",
1831 }
1832
1833 /* enable RFC6855, if the server supports that */
1834 const bool c_imap_rfc5161 = cs_subset_bool(NeoMutt->sub, "imap_rfc5161");
1835 if (c_imap_rfc5161 && (adata->capabilities & IMAP_CAP_ENABLE))
1836 imap_exec(adata, "ENABLE UTF8=ACCEPT", IMAP_CMD_QUEUE);
1837
1838 /* enable QRESYNC. Advertising QRESYNC also means CONDSTORE
1839 * is supported (even if not advertised), so flip that bit. */
1840 if (adata->capabilities & IMAP_CAP_QRESYNC)
1841 {
1843 const bool c_imap_qresync = cs_subset_bool(NeoMutt->sub, "imap_qresync");
1844 if (c_imap_rfc5161 && c_imap_qresync)
1845 imap_exec(adata, "ENABLE QRESYNC", IMAP_CMD_QUEUE);
1846 }
1847
1848 /* get root delimiter, '/' as default */
1849 adata->delim = '/';
1850 imap_exec(adata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
1851
1852 /* we may need the root delimiter before we open a mailbox */
1853 imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1854
1855 /* select the mailbox that used to be open before disconnect */
1856 if (adata->mailbox)
1857 {
1858 imap_mbox_select(adata->mailbox);
1859 }
1860 }
1861
1862 if (adata->state < IMAP_AUTHENTICATED)
1863 return -1;
1864
1865 return 0;
1866}
@ 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.
Definition: connaccount.c:178
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:743
static void imap_mbox_select(struct Mailbox *m)
Select a Mailbox.
Definition: imap.c:1748
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 928 of file imap.c.

930{
933
934 if (!adata || (adata->mailbox != m) || !e)
935 return -1;
936
938 {
939 if (e->deleted == edata->deleted)
940 e->changed = false;
941 return 0;
942 }
943
944 buf_printf(cmd, "UID STORE %u", edata->uid);
945
946 struct Buffer *flags = buf_pool_get();
947
948 set_flag(m, MUTT_ACL_SEEN, e->read, "\\Seen ", flags);
949 set_flag(m, MUTT_ACL_WRITE, e->old, "Old ", flags);
950 set_flag(m, MUTT_ACL_WRITE, e->flagged, "\\Flagged ", flags);
951 set_flag(m, MUTT_ACL_WRITE, e->replied, "\\Answered ", flags);
952 set_flag(m, MUTT_ACL_DELETE, edata->deleted, "\\Deleted ", flags);
953
954 if (m->rights & MUTT_ACL_WRITE)
955 {
956 /* restore system flags */
957 if (edata->flags_system)
958 buf_addstr(flags, edata->flags_system);
959
960 /* set custom flags */
961 struct Buffer *tags = buf_pool_get();
963 if (!buf_is_empty(tags))
964 buf_addstr(flags, buf_string(tags));
965 buf_pool_release(&tags);
966 }
967
969 buf_fix_dptr(flags);
970
971 /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
972 * explicitly revoke all system flags (if we have permission) */
973 if (buf_is_empty(flags))
974 {
975 set_flag(m, MUTT_ACL_SEEN, true, "\\Seen ", flags);
976 set_flag(m, MUTT_ACL_WRITE, true, "Old ", flags);
977 set_flag(m, MUTT_ACL_WRITE, true, "\\Flagged ", flags);
978 set_flag(m, MUTT_ACL_WRITE, true, "\\Answered ", flags);
979 set_flag(m, MUTT_ACL_DELETE, !edata->deleted, "\\Deleted ", flags);
980
981 /* erase custom flags */
982 if ((m->rights & MUTT_ACL_WRITE) && edata->flags_remote)
983 buf_addstr(flags, edata->flags_remote);
984
986 buf_fix_dptr(flags);
987
988 buf_addstr(cmd, " -FLAGS.SILENT (");
989 }
990 else
991 {
992 buf_addstr(cmd, " FLAGS.SILENT (");
993 }
994
995 buf_addstr(cmd, buf_string(flags));
996 buf_addstr(cmd, ")");
997
998 int rc = -1;
999
1000 /* after all this it's still possible to have no flags, if you
1001 * have no ACL rights */
1002 if (!buf_is_empty(flags) &&
1004 err_continue && (*err_continue != MUTT_YES))
1005 {
1006 *err_continue = imap_continue("imap_sync_message: STORE failed", adata->buf);
1007 if (*err_continue != MUTT_YES)
1008 goto done;
1009 }
1010
1011 /* server have now the updated flags */
1012 FREE(&edata->flags_remote);
1013 struct Buffer *flags_remote = buf_pool_get();
1014 driver_tags_get_with_hidden(&e->tags, flags_remote);
1015 edata->flags_remote = buf_strdup(flags_remote);
1016 buf_pool_release(&flags_remote);
1017
1018 if (e->deleted == edata->deleted)
1019 e->changed = false;
1020
1021 rc = 0;
1022
1023done:
1024 buf_pool_release(&flags);
1025 return rc;
1026}
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:648
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:186
static bool compare_flags_for_copy(struct Email *e)
Compare local flags against the server.
Definition: imap.c:202
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:564
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 876 of file imap.c.

877{
878 if (STAILQ_EMPTY(flag_list))
879 return false;
880
881 const size_t flaglen = mutt_str_len(flag);
882 struct ListNode *np = NULL;
883 STAILQ_FOREACH(np, flag_list, entries)
884 {
885 const size_t nplen = strlen(np->data);
886 if ((flaglen >= nplen) && ((flag[nplen] == '\0') || (flag[nplen] == ' ')) &&
887 mutt_istrn_equal(np->data, flag, nplen))
888 {
889 return true;
890 }
891
892 if (mutt_str_equal(np->data, "\\*"))
893 return true;
894 }
895
896 return false;
897}
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:659
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:497
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:454
#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 *np = NULL;
82 TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
83 {
84 if (np->type != MUTT_IMAP)
85 continue;
86
87 tmp_adata = np->adata;
88 if (!tmp_adata)
89 continue;
90 if (imap_account_match(&tmp_adata->conn->account, &cac))
91 {
92 if (mdata)
93 {
94 *mdata = imap_mdata_new(tmp_adata, tmp);
95 }
96 *adata = tmp_adata;
97 return 0;
98 }
99 }
100 mutt_debug(LL_DEBUG3, "no ImapAccountData found\n");
101 return -1;
102}
@ 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
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:782
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 AccountList accounts
List of 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:476
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1092
+ 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:671
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 1113 of file command.c.

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

1128{
1129 if (!adata)
1130 return -1;
1131
1132 size_t len = 0;
1133 int c;
1134 int rc;
1135 int stillrunning = 0;
1136 struct ImapCommand *cmd = NULL;
1137
1138 if (adata->status == IMAP_FATAL)
1139 {
1140 cmd_handle_fatal(adata);
1141 return IMAP_RES_BAD;
1142 }
1143
1144 /* read into buffer, expanding buffer as necessary until we have a full
1145 * line */
1146 do
1147 {
1148 if (len == adata->blen)
1149 {
1150 MUTT_MEM_REALLOC(&adata->buf, adata->blen + IMAP_CMD_BUFSIZE, char);
1151 adata->blen = adata->blen + IMAP_CMD_BUFSIZE;
1152 mutt_debug(LL_DEBUG3, "grew buffer to %zu bytes\n", adata->blen);
1153 }
1154
1155 /* back up over '\0' */
1156 if (len)
1157 len--;
1158 c = mutt_socket_readln_d(adata->buf + len, adata->blen - len, adata->conn, MUTT_SOCK_LOG_FULL);
1159 if (c <= 0)
1160 {
1161 mutt_debug(LL_DEBUG1, "Error reading server response\n");
1162 cmd_handle_fatal(adata);
1163 return IMAP_RES_BAD;
1164 }
1165
1166 len += c;
1167 }
1168 /* if we've read all the way to the end of the buffer, we haven't read a
1169 * full line (mutt_socket_readln strips the \r, so we always have at least
1170 * one character free when we've read a full line) */
1171 while (len == adata->blen);
1172
1173 /* don't let one large string make cmd->buf hog memory forever */
1174 if ((adata->blen > IMAP_CMD_BUFSIZE) && (len <= IMAP_CMD_BUFSIZE))
1175 {
1176 MUTT_MEM_REALLOC(&adata->buf, IMAP_CMD_BUFSIZE, char);
1177 adata->blen = IMAP_CMD_BUFSIZE;
1178 mutt_debug(LL_DEBUG3, "shrank buffer to %zu bytes\n", adata->blen);
1179 }
1180
1181 adata->lastread = mutt_date_now();
1182
1183 /* handle untagged messages. The caller still gets its shot afterwards. */
1184 if ((mutt_str_startswith(adata->buf, "* ") ||
1185 mutt_str_startswith(imap_next_word(adata->buf), "OK [")) &&
1186 cmd_handle_untagged(adata))
1187 {
1188 return IMAP_RES_BAD;
1189 }
1190
1191 /* server demands a continuation response from us */
1192 if (adata->buf[0] == '+')
1193 return IMAP_RES_RESPOND;
1194
1195 /* Look for tagged command completions.
1196 *
1197 * Some response handlers can end up recursively calling
1198 * imap_cmd_step() and end up handling all tagged command
1199 * completions.
1200 * (e.g. FETCH->set_flag->set_header_color->~h pattern match.)
1201 *
1202 * Other callers don't even create an adata->cmds entry.
1203 *
1204 * For both these cases, we default to returning OK */
1205 rc = IMAP_RES_OK;
1206 c = adata->lastcmd;
1207 do
1208 {
1209 cmd = &adata->cmds[c];
1210 if (cmd->state == IMAP_RES_NEW)
1211 {
1212 if (mutt_str_startswith(adata->buf, cmd->seq))
1213 {
1214 if (!stillrunning)
1215 {
1216 /* first command in queue has finished - move queue pointer up */
1217 adata->lastcmd = (adata->lastcmd + 1) % adata->cmdslots;
1218 }
1219 cmd->state = cmd_status(adata->buf);
1220 rc = cmd->state;
1221 if (cmd->state == IMAP_RES_NO || cmd->state == IMAP_RES_BAD)
1222 {
1223 mutt_message(_("IMAP command failed: %s"), adata->buf);
1224 }
1225 }
1226 else
1227 {
1228 stillrunning++;
1229 }
1230 }
1231
1232 c = (c + 1) % adata->cmdslots;
1233 } while (c != adata->nextcmd);
1234
1235 if (stillrunning)
1236 {
1237 rc = IMAP_RES_CONTINUE;
1238 }
1239 else
1240 {
1241 mutt_debug(LL_DEBUG3, "IMAP queue drained\n");
1242 imap_cmd_finish(adata);
1243 }
1244
1245 return rc;
1246}
#define mutt_message(...)
Definition: logging2.h:92
static int cmd_handle_untagged(struct ImapAccountData *adata)
Fallback parser for otherwise unhandled messages.
Definition: command.c:1017
static int cmd_status(const char *s)
Parse response line for tagged OK/NO/BAD.
Definition: command.c:238
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:1367
#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:823
#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:456
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:231
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 1367 of file command.c.

1368{
1369 if (!adata)
1370 return;
1371
1372 if (adata->status == IMAP_FATAL)
1373 {
1374 adata->closing = false;
1375 cmd_handle_fatal(adata);
1376 return;
1377 }
1378
1379 if (!(adata->state >= IMAP_SELECTED) || (adata->mailbox && adata->closing))
1380 {
1381 adata->closing = false;
1382 return;
1383 }
1384
1385 adata->closing = false;
1386
1387 struct ImapMboxData *mdata = imap_mdata_get(adata->mailbox);
1388
1389 if (mdata && mdata->reopen & IMAP_REOPEN_ALLOW)
1390 {
1391 // First remove expunged emails from the msn_index
1392 if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1393 {
1394 mutt_debug(LL_DEBUG2, "Expunging mailbox\n");
1395 imap_expunge_mailbox(adata->mailbox, true);
1396 /* Detect whether we've gotten unexpected EXPUNGE messages */
1397 if (!(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1398 mdata->check_status |= IMAP_EXPUNGE_PENDING;
1400 }
1401
1402 // Then add new emails to it
1403 if (mdata->reopen & IMAP_NEWMAIL_PENDING)
1404 {
1405 const size_t max_msn = imap_msn_highest(&mdata->msn);
1406 if (mdata->new_mail_count > max_msn)
1407 {
1408 if (!(mdata->reopen & IMAP_EXPUNGE_PENDING))
1409 mdata->check_status |= IMAP_NEWMAIL_PENDING;
1410
1411 mutt_debug(LL_DEBUG2, "Fetching new mails from %zd to %u\n",
1412 max_msn + 1, mdata->new_mail_count);
1413 imap_read_headers(adata->mailbox, max_msn + 1, mdata->new_mail_count, false);
1414 }
1415 }
1416
1417 // And to finish inform about MUTT_REOPEN if needed
1418 if (mdata->reopen & IMAP_EXPUNGE_PENDING && !(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
1419 mdata->check_status |= IMAP_EXPUNGE_PENDING;
1420
1421 if (mdata->reopen & IMAP_EXPUNGE_PENDING)
1423 }
1424
1425 adata->status = 0;
1426}
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:1339
#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:671
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 1254 of file command.c.

1255{
1256 return cmd_status(s) == IMAP_RES_OK;
1257}
+ 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 1265 of file command.c.

1266{
1267 static const char *notrailer = "";
1268 const char *s = adata->buf;
1269
1270 if (!s)
1271 {
1272 mutt_debug(LL_DEBUG2, "not a tagged response\n");
1273 return notrailer;
1274 }
1275
1276 s = imap_next_word((char *) s);
1277 if (!s || (!mutt_istr_startswith(s, "OK") && !mutt_istr_startswith(s, "NO") &&
1278 !mutt_istr_startswith(s, "BAD")))
1279 {
1280 mutt_debug(LL_DEBUG2, "not a command completion: %s\n", adata->buf);
1281 return notrailer;
1282 }
1283
1284 s = imap_next_word((char *) s);
1285 if (!s)
1286 return notrailer;
1287
1288 return s;
1289}
+ 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 1302 of file command.c.

1303{
1304 int rc;
1305
1306 if (flags & IMAP_CMD_SINGLE)
1307 {
1308 // Process any existing commands
1309 if (adata->nextcmd != adata->lastcmd)
1310 imap_exec(adata, NULL, IMAP_CMD_POLL);
1311 }
1312
1313 rc = cmd_start(adata, cmdstr, flags);
1314 if (rc < 0)
1315 {
1316 cmd_handle_fatal(adata);
1317 return IMAP_EXEC_FATAL;
1318 }
1319
1320 if (flags & IMAP_CMD_QUEUE)
1321 return IMAP_EXEC_SUCCESS;
1322
1323 const short c_imap_poll_timeout = cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1324 if ((flags & IMAP_CMD_POLL) && (c_imap_poll_timeout > 0) &&
1325 ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1326 {
1327 mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1328 cmd_handle_fatal(adata);
1329 return IMAP_EXEC_FATAL;
1330 }
1331
1332 /* Allow interruptions, particularly useful if there are network problems. */
1334 do
1335 {
1336 rc = imap_cmd_step(adata);
1337 // The queue is empty, so the single command has been processed
1338 if ((flags & IMAP_CMD_SINGLE) && (adata->nextcmd == adata->lastcmd))
1339 break;
1340 } while (rc == IMAP_RES_CONTINUE);
1342
1343 if (rc == IMAP_RES_NO)
1344 return IMAP_EXEC_ERROR;
1345 if (rc != IMAP_RES_OK)
1346 {
1347 if (adata->status != IMAP_FATAL)
1348 return IMAP_EXEC_ERROR;
1349
1350 mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1351 return IMAP_EXEC_FATAL;
1352 }
1353
1354 return IMAP_EXEC_SUCCESS;
1355}
#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:316
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 1434 of file command.c.

1435{
1436 int rc;
1437
1438 if (cmd_start(adata, "IDLE", IMAP_CMD_POLL) < 0)
1439 {
1440 cmd_handle_fatal(adata);
1441 return -1;
1442 }
1443
1444 const short c_imap_poll_timeout = cs_subset_number(NeoMutt->sub, "imap_poll_timeout");
1445 if ((c_imap_poll_timeout > 0) &&
1446 ((mutt_socket_poll(adata->conn, c_imap_poll_timeout)) == 0))
1447 {
1448 mutt_error(_("Connection to %s timed out"), adata->conn->account.host);
1449 cmd_handle_fatal(adata);
1450 return -1;
1451 }
1452
1453 do
1454 {
1455 rc = imap_cmd_step(adata);
1456 } while (rc == IMAP_RES_CONTINUE);
1457
1458 if (rc == IMAP_RES_RESPOND)
1459 {
1460 /* successfully entered IDLE state */
1461 adata->state = IMAP_IDLE;
1462 /* queue automatic exit when next command is issued */
1463 buf_addstr(&adata->cmdbuf, "DONE\r\n");
1464 rc = IMAP_RES_OK;
1465 }
1466 if (rc != IMAP_RES_OK)
1467 {
1468 mutt_debug(LL_DEBUG1, "error starting IDLE\n");
1469 return -1;
1470 }
1471
1472 return 0;
1473}
+ 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 1339 of file message.c.

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

1920{
1922 if (!adata || (adata->mailbox != m))
1923 return NULL;
1924
1925 struct ImapHeader newh = { 0 };
1926 struct ImapEmailData old_edata = { 0 };
1927 int local_changes = e->changed;
1928
1929 struct ImapEmailData *edata = e->edata;
1930 newh.edata = edata;
1931
1932 mutt_debug(LL_DEBUG2, "parsing FLAGS\n");
1933 s = msg_parse_flags(&newh, s);
1934 if (!s)
1935 return NULL;
1936
1937 /* Update tags system */
1938 /* We take a copy of the tags so we can split the string */
1939 char *tags_copy = mutt_str_dup(edata->flags_remote);
1940 driver_tags_replace(&e->tags, tags_copy);
1941 FREE(&tags_copy);
1942
1943 /* YAUH (yet another ugly hack): temporarily set context to
1944 * read-write even if it's read-only, so *server* updates of
1945 * flags can be processed by mutt_set_flag. mailbox->changed must
1946 * be restored afterwards */
1947 bool readonly = m->readonly;
1948 m->readonly = false;
1949
1950 /* This is redundant with the following two checks. Removing:
1951 * mutt_set_flag (m, e, MUTT_NEW, !(edata->read || edata->old), true); */
1952 set_changed_flag(m, e, local_changes, server_changes, MUTT_OLD, old_edata.old,
1953 edata->old, e->old);
1954 set_changed_flag(m, e, local_changes, server_changes, MUTT_READ,
1955 old_edata.read, edata->read, e->read);
1956 set_changed_flag(m, e, local_changes, server_changes, MUTT_DELETE,
1957 old_edata.deleted, edata->deleted, e->deleted);
1958 set_changed_flag(m, e, local_changes, server_changes, MUTT_FLAG,
1959 old_edata.flagged, edata->flagged, e->flagged);
1960 set_changed_flag(m, e, local_changes, server_changes, MUTT_REPLIED,
1961 old_edata.replied, edata->replied, e->replied);
1962
1963 /* this message is now definitively *not* changed (mutt_set_flag
1964 * marks things changed as a side-effect) */
1965 if (local_changes == 0)
1966 e->changed = false;
1967 m->changed &= !readonly;
1968 m->readonly = readonly;
1969
1970 return s;
1971}
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:642
static char * msg_parse_flags(struct ImapHeader *h, char *s)
Read a FLAGS token into an ImapHeader.
Definition: message.c:191
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
@ 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 1868 of file message.c.

1869{
1871 struct ImapMboxData *mdata = imap_mdata_get(m);
1872
1873 if (!e || !adata || (adata->mailbox != m))
1874 return -1;
1875
1876 mdata->bcache = imap_bcache_open(m);
1877 char id[64] = { 0 };
1878 snprintf(id, sizeof(id), "%u-%u", mdata->uidvalidity, imap_edata_get(e)->uid);
1879 return mutt_bcache_del(mdata->bcache, id);
1880}
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:80
+ 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 1887 of file message.c.

1888{
1890 struct ImapMboxData *mdata = imap_mdata_get(m);
1891
1892 if (!adata || (adata->mailbox != m))
1893 return -1;
1894
1895 mdata->bcache = imap_bcache_open(m);
1897
1898 return 0;
1899}
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:168
+ 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 1528 of file message.c.

1529{
1530 if (!m || !msg)
1531 return -1;
1532
1533 FILE *fp = NULL;
1534 char buf[2048] = { 0 };
1535 struct Buffer *internaldate = NULL;
1536 struct Buffer *imap_flags = NULL;
1537 size_t len;
1538 struct Progress *progress = NULL;
1539 size_t sent;
1540 int c, last;
1541 int rc;
1542
1544 struct ImapMboxData *mdata = imap_mdata_get(m);
1545
1546 fp = mutt_file_fopen(msg->path, "r");
1547 if (!fp)
1548 {
1549 mutt_perror("%s", msg->path);
1550 goto fail;
1551 }
1552
1553 /* currently we set the \Seen flag on all messages, but probably we
1554 * should scan the message Status header for flag info. Since we're
1555 * already rereading the whole file for length it isn't any more
1556 * expensive (it'd be nice if we had the file size passed in already
1557 * by the code that writes the file, but that's a lot of changes.
1558 * Ideally we'd have an Email structure with flag info here... */
1559 for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c)
1560 {
1561 if ((c == '\n') && (last != '\r'))
1562 len++;
1563
1564 len++;
1565 }
1566 rewind(fp);
1567
1568 if (m->verbose)
1569 {
1570 progress = progress_new(MUTT_PROGRESS_NET, len);
1571 progress_set_message(progress, _("Uploading message..."));
1572 }
1573
1574 internaldate = buf_pool_get();
1575 mutt_date_make_imap(internaldate, msg->received);
1576
1577 imap_flags = buf_pool_get();
1578
1579 if (msg->flags.read)
1580 buf_addstr(imap_flags, " \\Seen");
1581 if (msg->flags.replied)
1582 buf_addstr(imap_flags, " \\Answered");
1583 if (msg->flags.flagged)
1584 buf_addstr(imap_flags, " \\Flagged");
1585 if (msg->flags.draft)
1586 buf_addstr(imap_flags, " \\Draft");
1587
1588 snprintf(buf, sizeof(buf), "APPEND %s (%s) \"%s\" {%lu}", mdata->munge_name,
1589 imap_flags->data + 1, buf_string(internaldate), (unsigned long) len);
1590 buf_pool_release(&internaldate);
1591
1592 imap_cmd_start(adata, buf);
1593
1594 do
1595 {
1596 rc = imap_cmd_step(adata);
1597 } while (rc == IMAP_RES_CONTINUE);
1598
1599 if (rc != IMAP_RES_RESPOND)
1600 goto cmd_step_fail;
1601
1602 for (last = EOF, sent = len = 0; (c = fgetc(fp)) != EOF; last = c)
1603 {
1604 if ((c == '\n') && (last != '\r'))
1605 buf[len++] = '\r';
1606
1607 buf[len++] = c;
1608
1609 if (len > sizeof(buf) - 3)
1610 {
1611 sent += len;
1612 if (flush_buffer(buf, &len, adata->conn) < 0)
1613 goto fail;
1614 progress_update(progress, sent, -1);
1615 }
1616 }
1617
1618 if (len > 0)
1619 if (flush_buffer(buf, &len, adata->conn) < 0)
1620 goto fail;
1621
1622 if (mutt_socket_send(adata->conn, "\r\n") < 0)
1623 goto fail;
1624 mutt_file_fclose(&fp);
1625
1626 do
1627 {
1628 rc = imap_cmd_step(adata);
1629 } while (rc == IMAP_RES_CONTINUE);
1630
1631 if (rc != IMAP_RES_OK)
1632 goto cmd_step_fail;
1633
1634 progress_free(&progress);
1635 buf_pool_release(&imap_flags);
1636 return 0;
1637
1638cmd_step_fail:
1639 mutt_debug(LL_DEBUG1, "command failed: %s\n", adata->buf);
1640 if (rc != IMAP_RES_BAD)
1641 {
1642 char *pc = imap_next_word(adata->buf); /* skip sequence number or token */
1643 pc = imap_next_word(pc); /* skip response code */
1644 if (*pc != '\0')
1645 mutt_error("%s", pc);
1646 }
1647
1648fail:
1649 mutt_file_fclose(&fp);
1650 progress_free(&progress);
1651 buf_pool_release(&imap_flags);
1652 return -1;
1653}
#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:1113
static int flush_buffer(char *buf, size_t *len, struct Connection *conn)
Write data to a connection.
Definition: message.c:486
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:811
@ 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
bool verbose
Display status messages?
Definition: mailbox.h:117
char * path
path to temp file
Definition: message.h:36
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
struct Message::@0 flags
Flags for the Message.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_open()

void imap_hcache_open ( struct ImapAccountData adata,
struct ImapMboxData mdata,
bool  create 
)

Open a header cache.

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

Definition at line 301 of file util.c.

302{
303 if (!adata || !mdata)
304 return;
305
306 if (mdata->hcache)
307 return;
308
309 struct HeaderCache *hc = NULL;
310 struct Buffer *mbox = buf_pool_get();
311 struct Buffer *cachepath = buf_pool_get();
312
313 imap_cachepath(adata->delim, mdata->name, mbox);
314
315 if (strstr(buf_string(mbox), "/../") || mutt_str_equal(buf_string(mbox), "..") ||
316 mutt_strn_equal(buf_string(mbox), "../", 3))
317 {
318 goto cleanup;
319 }
320 size_t len = buf_len(mbox);
321 if ((len > 3) && (mutt_str_equal(buf_string(mbox) + len - 3, "/..")))
322 goto cleanup;
323
324 struct Url url = { 0 };
325 account_to_url(&adata->conn->account, &url);
326 url.path = mbox->data;
327 url_tobuffer(&url, cachepath, U_PATH);
328
329 const char *const c_header_cache = cs_subset_path(NeoMutt->sub, "header_cache");
330 hc = hcache_open(c_header_cache, buf_string(cachepath), imap_hcache_namer, create);
331
332cleanup:
333 buf_pool_release(&mbox);
334 buf_pool_release(&cachepath);
335 mdata->hcache = hc;
336}
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:290
struct HeaderCache * hcache_open(const char *path, const char *folder, hcache_namer_t namer, bool create)
Multiplexor for StoreOps::open.
Definition: hcache.c:471
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:426
void account_to_url(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:80
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:748
+ 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 342 of file util.c.

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

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

383{
384 if (!mdata->hcache)
385 return -1;
386
387 char key[16] = { 0 };
388
389 snprintf(key, sizeof(key), "%u", imap_edata_get(e)->uid);
390 return hcache_store_email(mdata->hcache, key, mutt_str_len(key), e, mdata->uidvalidity);
391}
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:670
+ 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 400 of file util.c.

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

418{
419 if (!mdata->hcache)
420 return -1;
421
422 struct Buffer *buf = buf_pool_get();
423 buf_alloc(buf, 8192); // The seqset is likely large. Preallocate to reduce reallocs
425
426 int rc = hcache_store_raw(mdata->hcache, "UIDSEQSET", 9, buf->data, buf_len(buf) + 1);
427 mutt_debug(LL_DEBUG3, "Stored UIDSEQSET %s\n", buf_string(buf));
428 buf_pool_release(&buf);
429 return rc;
430}
static void imap_msn_index_to_uid_seqset(struct Buffer *buf, struct ImapMboxData *mdata)
Convert MSN index of UIDs to Seqset.
Definition: util.c:233
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_clear_uid_seqset()

int imap_hcache_clear_uid_seqset ( struct ImapMboxData mdata)

Delete a UID Sequence Set from the header cache.

Parameters
mdataImap Mailbox data
Return values
0Success
-1Error

Definition at line 438 of file util.c.

439{
440 if (!mdata->hcache)
441 return -1;
442
443 return hcache_delete_raw(mdata->hcache, "UIDSEQSET", 9);
444}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_get_uid_seqset()

char * imap_hcache_get_uid_seqset ( struct ImapMboxData mdata)

Get a UID Sequence Set from the header cache.

Parameters
mdataImap Mailbox data
Return values
ptrUID Sequence Set
NULLError

Definition at line 452 of file util.c.

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

649{
650 imap_error(msg, resp);
651 return query_yesorno(_("Continue?"), MUTT_NO);
652}
@ 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:326
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition: util.c:659
+ 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 659 of file util.c.

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

109{
110 mutt_hash_free(&mdata->uid_hash);
111 imap_msn_free(&mdata->msn);
112 mutt_bcache_close(&mdata->bcache);
113}
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 680 of file util.c.

681{
682 const char *const c_imap_delim_chars = cs_subset_string(NeoMutt->sub, "imap_delim_chars");
683
684 char *out = path;
685 size_t space_left = plen - 1;
686
687 if (mailbox)
688 {
689 for (const char *c = mailbox; *c && space_left; c++, space_left--)
690 {
691 if (strchr(NONULL(c_imap_delim_chars), *c))
692 {
693 return imap_fix_path_with_delim(*c, mailbox, path, plen);
694 }
695 *out++ = *c;
696 }
697 }
698
699 *out = '\0';
700 return path;
701}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c: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:712
+ 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 712 of file util.c.

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

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

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

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

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

855{
856 struct Url url = { 0 };
857 account_to_url(cac, &url);
858 url.path = path;
859 url_tostring(&url, buf, buflen, U_NO_FLAGS);
860}
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 868 of file util.c.

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

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

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

960{
961 char *buf = mutt_str_dup(src);
962 imap_utf_encode(unicode, &buf);
963
964 imap_quote_string(dest, dlen, buf, false);
965
966 FREE(&buf);
967}
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:885
+ 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 976 of file util.c.

977{
979
980 char *buf = mutt_str_dup(s);
981 if (buf)
982 {
983 imap_utf_decode(unicode, &buf);
984 strncpy(s, buf, strlen(s));
985 }
986
987 FREE(&buf);
988}
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:922
+ 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 1124 of file util.c.

1125{
1126 if (!seqset || (*seqset == '\0'))
1127 return NULL;
1128
1129 struct SeqsetIterator *iter = MUTT_MEM_CALLOC(1, struct SeqsetIterator);
1130 iter->full_seqset = mutt_str_dup(seqset);
1131 iter->eostr = strchr(iter->full_seqset, '\0');
1132 iter->substr_cur = iter->substr_end = iter->full_seqset;
1133
1134 return iter;
1135}
#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 1145 of file util.c.

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

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

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

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

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

1078{
1080 struct ImapMboxData *mdata = imap_mdata_get(m);
1081 if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1082 return;
1083 mdata->reopen &= ~IMAP_REOPEN_ALLOW;
1084}
+ 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 256 of file search.c.

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