NeoMutt  2024-03-23-147-g885fbc
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)
 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 (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 437 of file imap.c.

438{
439 char buf[2048] = { 0 };
440 char mbox[1024] = { 0 };
441
442 imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), mailbox);
443 snprintf(buf, sizeof(buf), "CREATE %s", mbox);
444
446 {
447 mutt_error(_("CREATE failed: %s"), imap_cmd_trailer(adata));
448 return -1;
449 }
450
451 return 0;
452}
#define mutt_error(...)
Definition: logging2.h:92
const char * imap_cmd_trailer(struct ImapAccountData *adata)
Extra information after tagged command response if any.
Definition: command.c:1270
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:1307
#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:921
#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 479 of file imap.c.

480{
481 char oldmbox[1024] = { 0 };
482 char newmbox[1024] = { 0 };
483 int rc = 0;
484
485 imap_munge_mbox_name(adata->unicode, oldmbox, sizeof(oldmbox), oldname);
486 imap_munge_mbox_name(adata->unicode, newmbox, sizeof(newmbox), newname);
487
488 struct Buffer *buf = buf_pool_get();
489 buf_printf(buf, "RENAME %s %s", oldmbox, newmbox);
490
492 rc = -1;
493
494 buf_pool_release(&buf);
495
496 return rc;
497}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
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:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
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 742 of file imap.c.

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

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

593{
594 char c;
595 bool r = false;
596 struct Buffer buf = { 0 }; // Do not allocate, maybe it won't be used
597
598 const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
599 if (c_debug_level >= IMAP_LOG_LTRL)
600 buf_alloc(&buf, bytes + 1);
601
602 mutt_debug(LL_DEBUG2, "reading %lu bytes\n", bytes);
603
604 for (unsigned long pos = 0; pos < bytes; pos++)
605 {
606 if (mutt_socket_readchar(adata->conn, &c) != 1)
607 {
608 mutt_debug(LL_DEBUG1, "error during read, %lu bytes read\n", pos);
609 adata->status = IMAP_FATAL;
610
611 buf_dealloc(&buf);
612 return -1;
613 }
614
615 if (r && (c != '\n'))
616 fputc('\r', fp);
617
618 if (c == '\r')
619 {
620 r = true;
621 continue;
622 }
623 else
624 {
625 r = false;
626 }
627
628 fputc(c, fp);
629
630 if ((pos % 1024) == 0)
631 progress_update(progress, pos, -1);
632 if (c_debug_level >= IMAP_LOG_LTRL)
633 buf_addch(&buf, c);
634 }
635
636 if (c_debug_level >= IMAP_LOG_LTRL)
637 {
638 mutt_debug(IMAP_LOG_LTRL, "\n%s", buf.data);
639 buf_dealloc(&buf);
640 }
641 return 0;
642}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:376
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:336
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:144
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
#define IMAP_LOG_LTRL
Definition: private.h:49
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c: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 670 of file imap.c.

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

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

929{
931 if (!adata || (adata->mailbox != m))
932 return -1;
933
934 char flags[1024] = { 0 };
935 char uid[11] = { 0 };
936
938 {
939 if (e->deleted == imap_edata_get(e)->deleted)
940 e->changed = false;
941 return 0;
942 }
943
944 snprintf(uid, sizeof(uid), "%u", imap_edata_get(e)->uid);
945 buf_reset(cmd);
946 buf_addstr(cmd, "UID STORE ");
947 buf_addstr(cmd, uid);
948
949 flags[0] = '\0';
950
951 set_flag(m, MUTT_ACL_SEEN, e->read, "\\Seen ", flags, sizeof(flags));
952 set_flag(m, MUTT_ACL_WRITE, e->old, "Old ", flags, sizeof(flags));
953 set_flag(m, MUTT_ACL_WRITE, e->flagged, "\\Flagged ", flags, sizeof(flags));
954 set_flag(m, MUTT_ACL_WRITE, e->replied, "\\Answered ", flags, sizeof(flags));
955 set_flag(m, MUTT_ACL_DELETE, imap_edata_get(e)->deleted, "\\Deleted ", flags,
956 sizeof(flags));
957
958 if (m->rights & MUTT_ACL_WRITE)
959 {
960 /* restore system flags */
961 if (imap_edata_get(e)->flags_system)
962 mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_system);
963 /* set custom flags */
964 struct Buffer *tags = buf_pool_get();
966 if (!buf_is_empty(tags))
967 {
968 mutt_str_cat(flags, sizeof(flags), buf_string(tags));
969 }
970 buf_pool_release(&tags);
971 }
972
974
975 /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
976 * explicitly revoke all system flags (if we have permission) */
977 if (*flags == '\0')
978 {
979 set_flag(m, MUTT_ACL_SEEN, true, "\\Seen ", flags, sizeof(flags));
980 set_flag(m, MUTT_ACL_WRITE, true, "Old ", flags, sizeof(flags));
981 set_flag(m, MUTT_ACL_WRITE, true, "\\Flagged ", flags, sizeof(flags));
982 set_flag(m, MUTT_ACL_WRITE, true, "\\Answered ", flags, sizeof(flags));
983 set_flag(m, MUTT_ACL_DELETE, !imap_edata_get(e)->deleted, "\\Deleted ",
984 flags, sizeof(flags));
985
986 /* erase custom flags */
987 if ((m->rights & MUTT_ACL_WRITE) && imap_edata_get(e)->flags_remote)
988 mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_remote);
989
991
992 buf_addstr(cmd, " -FLAGS.SILENT (");
993 }
994 else
995 {
996 buf_addstr(cmd, " FLAGS.SILENT (");
997 }
998
999 buf_addstr(cmd, flags);
1000 buf_addstr(cmd, ")");
1001
1002 /* after all this it's still possible to have no flags, if you
1003 * have no ACL rights */
1004 if (*flags && (imap_exec(adata, cmd->data, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS) &&
1005 err_continue && (*err_continue != MUTT_YES))
1006 {
1007 *err_continue = imap_continue("imap_sync_message: STORE failed", adata->buf);
1008 if (*err_continue != MUTT_YES)
1009 return -1;
1010 }
1011
1012 /* server have now the updated flags */
1013 FREE(&imap_edata_get(e)->flags_remote);
1014 struct Buffer *flags_remote = buf_pool_get();
1015 driver_tags_get_with_hidden(&e->tags, flags_remote);
1016 imap_edata_get(e)->flags_remote = buf_strdup(flags_remote);
1017 buf_pool_release(&flags_remote);
1018
1019 if (e->deleted == imap_edata_get(e)->deleted)
1020 e->changed = false;
1021
1022 return 0;
1023}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:290
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:570
#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:646
static void set_flag(struct Mailbox *m, AclFlags aclflag, bool flag, const char *str, char *flags, size_t flsize)
Append str to flags if we currently have permission according to aclflag.
Definition: imap.c:188
static bool compare_flags_for_copy(struct Email *e)
Compare local flags against the server.
Definition: imap.c:204
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:614
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:268
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
char * flags_remote
Definition: edata.h:49
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 875 of file imap.c.

876{
877 if (STAILQ_EMPTY(flag_list))
878 return false;
879
880 const size_t flaglen = mutt_str_len(flag);
881 struct ListNode *np = NULL;
882 STAILQ_FOREACH(np, flag_list, entries)
883 {
884 const size_t nplen = strlen(np->data);
885 if ((flaglen >= nplen) && ((flag[nplen] == '\0') || (flag[nplen] == ' ')) &&
886 mutt_istrn_equal(np->data, flag, nplen))
887 {
888 return true;
889 }
890
891 if (mutt_str_equal(np->data, "\\*"))
892 return true;
893 }
894
895 return false;
896}
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:709
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:545
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:502
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_EMPTY(head)
Definition: queue.h:348
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_adata_find()

int imap_adata_find ( const char *  path,
struct ImapAccountData **  adata,
struct ImapMboxData **  mdata 
)

Find the Account data for this path.

Parameters
pathPath to search for
adataImap Account data
mdataImap Mailbox data
Return values
0Success
-1Failure

Definition at line 73 of file util.c.

75{
76 struct ConnAccount cac = { { 0 } };
77 struct ImapAccountData *tmp_adata = NULL;
78 char tmp[1024] = { 0 };
79
80 if (imap_parse_path(path, &cac, tmp, sizeof(tmp)) < 0)
81 return -1;
82
83 struct Account *np = NULL;
84 TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
85 {
86 if (np->type != MUTT_IMAP)
87 continue;
88
89 tmp_adata = np->adata;
90 if (!tmp_adata)
91 continue;
92 if (imap_account_match(&tmp_adata->conn->account, &cac))
93 {
94 *mdata = imap_mdata_new(tmp_adata, tmp);
95 *adata = tmp_adata;
96 return 0;
97 }
98 }
99 mutt_debug(LL_DEBUG3, "no ImapAccountData found\n");
100 return -1;
101}
@ 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:73
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
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:46
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:474
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1054
+ 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 < mutt_array_size(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 < mutt_array_size(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:243
static const struct ImapAuth ImapAuthenticators[]
Accepted authentication methods.
Definition: auth.c:64
#define mutt_array_size(x)
Definition: memory.h:38
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:721
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 1118 of file command.c.

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

◆ imap_cmd_step()

int imap_cmd_step ( struct ImapAccountData adata)

Reads server responses from an IMAP command.

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

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

Definition at line 1132 of file command.c.

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

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

1260{
1261 return cmd_status(s) == IMAP_RES_OK;
1262}
+ 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 1270 of file command.c.

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

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

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

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

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

1870{
1872 struct ImapMboxData *mdata = imap_mdata_get(m);
1873
1874 if (!e || !adata || (adata->mailbox != m))
1875 return -1;
1876
1877 mdata->bcache = imap_bcache_open(m);
1878 char id[64] = { 0 };
1879 snprintf(id, sizeof(id), "%u-%u", mdata->uidvalidity, imap_edata_get(e)->uid);
1880 return mutt_bcache_del(mdata->bcache, id);
1881}
int mutt_bcache_del(struct BodyCache *bcache, const char *id)
Delete a file from the Body Cache.
Definition: bcache.c:266
static struct BodyCache * imap_bcache_open(struct Mailbox *m)
Open a message cache.
Definition: message.c:82
+ 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 1888 of file message.c.

1889{
1891 struct ImapMboxData *mdata = imap_mdata_get(m);
1892
1893 if (!adata || (adata->mailbox != m))
1894 return -1;
1895
1896 mdata->bcache = imap_bcache_open(m);
1898
1899 return 0;
1900}
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
Definition: bcache.c:331
static int 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:170
+ 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 1530 of file message.c.

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

Open a header cache.

Parameters
adataImap Account data
mdataImap Mailbox data

Definition at line 299 of file util.c.

300{
301 if (!adata || !mdata)
302 return;
303
304 if (mdata->hcache)
305 return;
306
307 struct HeaderCache *hc = NULL;
308 struct Buffer *mbox = buf_pool_get();
309 struct Buffer *cachepath = buf_pool_get();
310
311 imap_cachepath(adata->delim, mdata->name, mbox);
312
313 if (strstr(buf_string(mbox), "/../") || mutt_str_equal(buf_string(mbox), "..") ||
314 mutt_strn_equal(buf_string(mbox), "../", 3))
315 {
316 goto cleanup;
317 }
318 size_t len = buf_len(mbox);
319 if ((len > 3) && (mutt_str_equal(buf_string(mbox) + len - 3, "/..")))
320 goto cleanup;
321
322 struct Url url = { 0 };
323 mutt_account_tourl(&adata->conn->account, &url);
324 url.path = mbox->data;
325 url_tobuffer(&url, cachepath, U_PATH);
326
327 const char *const c_header_cache = cs_subset_path(NeoMutt->sub, "header_cache");
328 hc = hcache_open(c_header_cache, buf_string(cachepath), imap_hcache_namer);
329
330cleanup:
331 buf_pool_release(&mbox);
332 buf_pool_release(&cachepath);
333 mdata->hcache = hc;
334}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:490
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
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:289
struct HeaderCache * hcache_open(const char *path, const char *folder, hcache_namer_t namer)
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:474
void mutt_account_tourl(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(struct Url *url, struct Buffer *buf, uint8_t flags)
Output the URL string for a given Url object.
Definition: url.c:358
#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:710
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_close()

void imap_hcache_close ( struct ImapMboxData mdata)

Close the header cache.

Parameters
mdataImap Mailbox data

Definition at line 340 of file util.c.

341{
342 if (!mdata->hcache)
343 return;
344
345 hcache_close(&mdata->hcache);
346}
void hcache_close(struct HeaderCache **ptr)
Multiplexor for StoreOps::close.
Definition: hcache.c:540
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_get()

struct Email * imap_hcache_get ( struct ImapMboxData mdata,
unsigned int  uid 
)

Get a header cache entry by its UID.

Parameters
mdataImap Mailbox data
uidUID to find
Return values
ptrEmail
NULLFailure

Definition at line 355 of file util.c.

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

381{
382 if (!mdata->hcache)
383 return -1;
384
385 char key[16] = { 0 };
386
387 snprintf(key, sizeof(key), "%u", imap_edata_get(e)->uid);
388 return hcache_store_email(mdata->hcache, key, mutt_str_len(key), e, mdata->uidvalidity);
389}
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:668
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_del()

int imap_hcache_del ( struct ImapMboxData mdata,
unsigned int  uid 
)

Delete an item from the header cache.

Parameters
mdataImap Mailbox data
uidUID of entry to delete
Return values
0Success
-1Failure

Definition at line 398 of file util.c.

399{
400 if (!mdata->hcache)
401 return -1;
402
403 char key[16] = { 0 };
404
405 snprintf(key, sizeof(key), "%u", uid);
406 return hcache_delete_email(mdata->hcache, key, mutt_str_len(key));
407}
int hcache_delete_email(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:737
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_hcache_store_uid_seqset()

int imap_hcache_store_uid_seqset ( struct ImapMboxData mdata)

Store a UID Sequence Set in the header cache.

Parameters
mdataImap Mailbox data
Return values
0Success
-1Error

Definition at line 415 of file util.c.

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

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

451{
452 if (!mdata->hcache)
453 return NULL;
454
455 char *seqset = hcache_fetch_raw_str(mdata->hcache, "UIDSEQSET", 9);
456 mutt_debug(LL_DEBUG3, "Retrieved UIDSEQSET %s\n", NONULL(seqset));
457
458 return seqset;
459}
char * hcache_fetch_raw_str(struct HeaderCache *hc, const char *key, size_t keylen)
Fetch a string from the cache.
Definition: hcache.c:650
#define NONULL(x)
Definition: string2.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_continue()

enum QuadOption imap_continue ( const char *  msg,
const char *  resp 
)

Display a message and ask the user if they want to go on.

Parameters
msgLocation of the error
respMessage for user
Return values
QuadOptionResult, e.g. MUTT_NO

Definition at line 646 of file util.c.

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

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

108{
109 mutt_hash_free(&mdata->uid_hash);
110 imap_msn_free(&mdata->msn);
111 mutt_bcache_close(&mdata->bcache);
112}
void mutt_bcache_close(struct BodyCache **ptr)
Close an Email-Body Cache.
Definition: bcache.c:164
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
void imap_msn_free(struct MSNArray *msn)
Free the cache.
Definition: msn.c:60
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 ( char  delim,
const char *  mailbox,
char *  path,
size_t  plen 
)

Fix up the imap path.

Parameters
delimDelimiter specified by the server, '\0' for $imap_delim_chars
mailboxMailbox path
pathBuffer for the result
plenLength of buffer
Return values
ptrFixed-up path
Note
if delim is '\0', the first character in mailbox matching any of the characters in $imap_delim_chars is used as a delimiter.

This is necessary because the rest of neomutt assumes a hierarchy delimiter of '/', which is not necessarily true in IMAP. Additionally, the filesystem converts multiple hierarchy delimiters into a single one, ie "///" is equal to "/". IMAP servers are not required to do this. Moreover, IMAP servers may dislike the path ending with the delimiter.

Definition at line 679 of file util.c.

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

◆ imap_cachepath()

void imap_cachepath ( char  delim,
const char *  mailbox,
struct Buffer dest 
)

Generate a cache path for a mailbox.

Parameters
delimImap server delimiter
mailboxMailbox name
destBuffer to store cache path

Definition at line 710 of file util.c.

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

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

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

786{
787 bool quoted = false;
788
789 while (*s)
790 {
791 if (*s == '\\')
792 {
793 s++;
794 if (*s)
795 s++;
796 continue;
797 }
798 if (*s == '\"')
799 quoted = !quoted;
800 if (!quoted && isspace(*s))
801 break;
802 s++;
803 }
804
805 SKIPWS(s);
806 return s;
807}
#define SKIPWS(ch)
Definition: string2.h:45
+ Here is the caller graph for this function:

◆ imap_qualify_path()

void imap_qualify_path ( char *  buf,
size_t  buflen,
struct ConnAccount cac,
char *  path 
)

Make an absolute IMAP folder target.

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

Definition at line 816 of file util.c.

817{
818 struct Url url = { 0 };
819 mutt_account_tourl(cac, &url);
820 url.path = path;
821 url_tostring(&url, buf, buflen, U_NO_FLAGS);
822}
int url_tostring(struct Url *url, char *dest, size_t len, uint8_t flags)
Output the URL string for a given Url object.
Definition: url.c:423
#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 830 of file util.c.

831{
832 struct Url url = { 0 };
833 mutt_account_tourl(cac, &url);
834 url.path = path;
835 url_tobuffer(&url, buf, U_NO_FLAGS);
836}
+ 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 847 of file util.c.

848{
849 const char *quote = "`\"\\";
850 if (!quote_backtick)
851 quote++;
852
853 char *pt = dest;
854 const char *s = src;
855
856 *pt++ = '"';
857 /* save room for quote-chars */
858 dlen -= 3;
859
860 for (; *s && dlen; s++)
861 {
862 if (strchr(quote, *s))
863 {
864 if (dlen < 2)
865 break;
866 dlen -= 2;
867 *pt++ = '\\';
868 *pt++ = *s;
869 }
870 else
871 {
872 *pt++ = *s;
873 dlen--;
874 }
875 }
876 *pt++ = '"';
877 *pt = '\0';
878}
+ 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 884 of file util.c.

885{
886 char *d = s;
887
888 if (*s == '\"')
889 s++;
890 else
891 return;
892
893 while (*s)
894 {
895 if (*s == '\"')
896 {
897 *d = '\0';
898 return;
899 }
900 if (*s == '\\')
901 {
902 s++;
903 }
904 if (*s)
905 {
906 *d = *s;
907 d++;
908 s++;
909 }
910 }
911 *d = '\0';
912}
+ 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 921 of file util.c.

922{
923 char *buf = mutt_str_dup(src);
924 imap_utf_encode(unicode, &buf);
925
926 imap_quote_string(dest, dlen, buf, false);
927
928 FREE(&buf);
929}
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:847
+ 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 938 of file util.c.

939{
941
942 char *buf = mutt_str_dup(s);
943 if (buf)
944 {
945 imap_utf_decode(unicode, &buf);
946 strncpy(s, buf, strlen(s));
947 }
948
949 FREE(&buf);
950}
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:884
+ 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 1086 of file util.c.

1087{
1088 if (!seqset || (*seqset == '\0'))
1089 return NULL;
1090
1091 struct SeqsetIterator *iter = mutt_mem_calloc(1, sizeof(struct SeqsetIterator));
1092 iter->full_seqset = mutt_str_dup(seqset);
1093 iter->eostr = strchr(iter->full_seqset, '\0');
1094 iter->substr_cur = iter->substr_end = iter->full_seqset;
1095
1096 return iter;
1097}
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
UID Sequence Set Iterator.
Definition: private.h:169
char * eostr
Definition: private.h:171
char * substr_end
Definition: private.h:177
char * substr_cur
Definition: private.h:176
char * full_seqset
Definition: private.h:170
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_seqset_iterator_next()

int mutt_seqset_iterator_next ( struct SeqsetIterator iter,
unsigned int *  next 
)

Get the next UID from a Sequence Set.

Parameters
[in]iterSequence Set Iterator
[out]nextNext UID in set
Return values
0Next sequence is generated
1Iterator is finished
-1error

Definition at line 1107 of file util.c.

1108{
1109 if (!iter || !next)
1110 return -1;
1111
1112 if (iter->in_range)
1113 {
1114 if ((iter->down && (iter->range_cur == (iter->range_end - 1))) ||
1115 (!iter->down && (iter->range_cur == (iter->range_end + 1))))
1116 {
1117 iter->in_range = 0;
1118 }
1119 }
1120
1121 if (!iter->in_range)
1122 {
1123 iter->substr_cur = iter->substr_end;
1124 if (iter->substr_cur == iter->eostr)
1125 return 1;
1126
1127 iter->substr_end = strchr(iter->substr_cur, ',');
1128 if (!iter->substr_end)
1129 iter->substr_end = iter->eostr;
1130 else
1131 *(iter->substr_end++) = '\0';
1132
1133 char *range_sep = strchr(iter->substr_cur, ':');
1134 if (range_sep)
1135 *range_sep++ = '\0';
1136
1137 if (!mutt_str_atoui_full(iter->substr_cur, &iter->range_cur))
1138 return -1;
1139 if (range_sep)
1140 {
1141 if (!mutt_str_atoui_full(range_sep, &iter->range_end))
1142 return -1;
1143 }
1144 else
1145 {
1146 iter->range_end = iter->range_cur;
1147 }
1148
1149 iter->down = (iter->range_end < iter->range_cur);
1150 iter->in_range = 1;
1151 }
1152
1153 *next = iter->range_cur;
1154 if (iter->down)
1155 iter->range_cur--;
1156 else
1157 iter->range_cur++;
1158
1159 return 0;
1160}
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 1166 of file util.c.

1167{
1168 if (!ptr || !*ptr)
1169 return;
1170
1171 struct SeqsetIterator *iter = *ptr;
1172 FREE(&iter->full_seqset);
1173 FREE(ptr);
1174}
+ 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 1054 of file util.c.

1055{
1056 if (!a1 || !a2)
1057 return false;
1058 if (a1->type != a2->type)
1059 return false;
1060 if (!mutt_istr_equal(a1->host, a2->host))
1061 return false;
1062 if ((a1->port != 0) && (a2->port != 0) && (a1->port != a2->port))
1063 return false;
1064 if (a1->flags & a2->flags & MUTT_ACCT_USER)
1065 return mutt_str_equal(a1->user, a2->user);
1066
1067 const char *user = NONULL(Username);
1068
1069 const char *const c_imap_user = cs_subset_string(NeoMutt->sub, "imap_user");
1070 if ((a1->type == MUTT_ACCT_TYPE_IMAP) && c_imap_user)
1071 user = c_imap_user;
1072
1073 if (a1->flags & MUTT_ACCT_USER)
1074 return mutt_str_equal(a1->user, user);
1075 if (a2->flags & MUTT_ACCT_USER)
1076 return mutt_str_equal(a2->user, user);
1077
1078 return true;
1079}
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:44
char * Username
User's login name.
Definition: globals.c:41
@ MUTT_ACCT_TYPE_IMAP
Imap Account.
Definition: mutt_account.h:38
char user[128]
Username.
Definition: connaccount.h:56
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
Definition: connaccount.h:59
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:60
unsigned short port
Port to connect to.
Definition: connaccount.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_get_parent()

void imap_get_parent ( const char *  mbox,
char  delim,
char *  buf,
size_t  buflen 
)

Get an IMAP folder's parent.

Parameters
mboxMailbox whose parent is to be determined
delimPath delimiter
bufBuffer for the result
buflenLength of the buffer

Definition at line 121 of file util.c.

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

1027{
1029 struct ImapMboxData *mdata = imap_mdata_get(m);
1030 if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1031 return;
1032 mdata->reopen |= IMAP_REOPEN_ALLOW;
1033}
+ 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 1039 of file util.c.

1040{
1042 struct ImapMboxData *mdata = imap_mdata_get(m);
1043 if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1044 return;
1045 mdata->reopen &= ~IMAP_REOPEN_ALLOW;
1046}
+ 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:105
+ Here is the call graph for this function:
+ Here is the caller graph for this function: