1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
|
/*
* Copyright (C) 1996-1999 Brandon Long <blong@fiction.net>
* Copyright (C) 1999-2009 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _IMAP_PRIVATE_H
#define _IMAP_PRIVATE_H 1
#include "imap.h"
#include "mutt_curses.h"
#include "mutt_socket.h"
#include "bcache.h"
#ifdef USE_HCACHE
#include "hcache.h"
#endif
#include "message.h" /* for IMAP_HEADER_DATA */
/* -- symbols -- */
#define IMAP_PORT 143
#define IMAP_SSL_PORT 993
/* logging levels */
#define IMAP_LOG_CMD 2
#define IMAP_LOG_LTRL 4
#define IMAP_LOG_PASS 5
/* IMAP command responses. Used in IMAP_COMMAND.state too */
/* <tag> OK ... */
#define IMAP_CMD_OK (0)
/* <tag> BAD ... */
#define IMAP_CMD_BAD (-1)
/* <tag> NO ... */
#define IMAP_CMD_NO (-2)
/* * ... */
#define IMAP_CMD_CONTINUE (1)
/* + */
#define IMAP_CMD_RESPOND (2)
/* IMAP_COMMAND.state additions */
#define IMAP_CMD_NEW (3)
/* number of entries in the hash table */
#define IMAP_CACHE_LEN 10
#define SEQLEN 5
/* maximum length of command lines before they must be split (for
* lazy servers) */
#define IMAP_MAX_CMDLEN 1024
#define IMAP_REOPEN_ALLOW (1<<0)
#define IMAP_EXPUNGE_EXPECTED (1<<1)
#define IMAP_EXPUNGE_PENDING (1<<2)
#define IMAP_NEWMAIL_PENDING (1<<3)
#define IMAP_FLAGS_PENDING (1<<4)
/* imap_exec flags (see imap_exec) */
#define IMAP_CMD_FAIL_OK (1<<0)
#define IMAP_CMD_PASS (1<<1)
#define IMAP_CMD_QUEUE (1<<2)
#define IMAP_CMD_POLL (1<<3)
enum
{
IMAP_FATAL = 1,
IMAP_BYE
};
enum
{
/* States */
IMAP_DISCONNECTED = 0,
IMAP_CONNECTED,
IMAP_AUTHENTICATED,
IMAP_SELECTED,
/* and pseudo-states */
IMAP_IDLE
};
enum
{
/* Namespace types */
IMAP_NS_PERSONAL = 0,
IMAP_NS_OTHER,
IMAP_NS_SHARED
};
/* Capabilities we are interested in */
enum
{
IMAP4 = 0,
IMAP4REV1,
STATUS,
ACL, /* RFC 2086: IMAP4 ACL extension */
NAMESPACE, /* RFC 2342: IMAP4 Namespace */
ACRAM_MD5, /* RFC 2195: CRAM-MD5 authentication */
AGSSAPI, /* RFC 1731: GSSAPI authentication */
AUTH_ANON, /* AUTH=ANONYMOUS */
AUTH_OAUTHBEARER, /* RFC 7628: AUTH=OAUTHBEARER */
AUTH_XOAUTH2, /* Deprecated precursor to OAUTHBEARER */
STARTTLS, /* RFC 2595: STARTTLS */
LOGINDISABLED, /* LOGINDISABLED */
IDLE, /* RFC 2177: IDLE */
SASL_IR, /* SASL initial response draft */
ENABLE, /* RFC 5161 */
CONDSTORE, /* RFC 7162 */
QRESYNC, /* RFC 7162 */
LIST_EXTENDED, /* RFC 5258: IMAP4 - LIST Command Extensions */
COMPRESS_DEFLATE, /* RFC 4978: COMPRESS=DEFLATE */
CAPMAX
};
/* imap_conn_find flags */
#define MUTT_IMAP_CONN_NONEW (1<<0)
#define MUTT_IMAP_CONN_NOSELECT (1<<1)
/* -- data structures -- */
typedef struct
{
unsigned int uid;
char* path;
} IMAP_CACHE;
typedef struct
{
char* name;
unsigned int messages;
unsigned int recent;
unsigned int uidnext;
unsigned int uidvalidity;
unsigned int unseen;
unsigned long long modseq; /* Used by CONDSTORE. 1 <= modseq < 2^63 */
} IMAP_STATUS;
typedef struct
{
char* name;
char delim;
/* if we end up storing a lot of these we could turn this into a bitfield */
unsigned char noselect;
unsigned char noinferiors;
} IMAP_LIST;
/* IMAP command structure */
typedef struct
{
char seq[SEQLEN+1];
int state;
} IMAP_COMMAND;
typedef enum
{
IMAP_CT_NONE = 0,
IMAP_CT_LIST,
IMAP_CT_STATUS
} IMAP_COMMAND_TYPE;
typedef struct
{
/* This data is specific to a CONNECTION to an IMAP server */
CONNECTION *conn;
unsigned char state;
unsigned char status;
/* let me explain capstr: SASL needs the capability string (not bits).
* we have 3 options:
* 1. rerun CAPABILITY inside SASL function.
* 2. build appropriate CAPABILITY string by reverse-engineering from bits.
* 3. keep a copy until after authentication.
* I've chosen (3) for now. (2) might not be too bad, but it involves
* tracking all possible capabilities. bah. (1) I don't like because
* it's just no fun to get the same information twice */
char* capstr;
unsigned char capabilities[(CAPMAX + 7)/8];
unsigned int seqno;
time_t lastread; /* last time we read a command for the server */
char* buf;
unsigned int blen;
/* If nonzero, we can send UTF-8, and the server will use UTF8 rather
* than mUTF7 */
int unicode;
int qresync; /* Set to 1 if QRESYNC is successfully ENABLE'd */
/* if set, the response parser will store results for complicated commands
* here. */
IMAP_COMMAND_TYPE cmdtype;
void* cmddata;
/* command queue */
IMAP_COMMAND* cmds;
int cmdslots;
int nextcmd;
int lastcmd;
BUFFER* cmdbuf;
/* cache IMAP_STATUS of visited mailboxes */
LIST* mboxcache;
/* The following data is all specific to the currently SELECTED mbox */
char delim;
CONTEXT *ctx;
char *mailbox;
unsigned short check_status;
unsigned char reopen;
unsigned int newMailCount; /* Set when EXISTS notifies of new mail */
IMAP_CACHE cache[IMAP_CACHE_LEN];
HASH *uid_hash;
unsigned int uid_validity;
unsigned int uidnext;
unsigned long long modseq;
HEADER **msn_index; /* look up headers by (MSN-1) */
unsigned int msn_index_size; /* allocation size */
unsigned int max_msn; /* the largest MSN fetched so far */
body_cache_t *bcache;
/* all folder flags - system flags AND keywords */
LIST *flags;
#ifdef USE_HCACHE
header_cache_t *hcache;
#endif
} IMAP_DATA;
/* I wish that were called IMAP_CONTEXT :( */
typedef struct
{
char *full_seqset;
char *eostr;
int in_range;
int down;
unsigned int range_cur, range_end;
char *substr_cur, *substr_end;
} SEQSET_ITERATOR;
/* -- macros -- */
#define CTX_DATA ((IMAP_DATA *) ctx->data)
/* -- private IMAP functions -- */
/* imap.c */
int imap_create_mailbox (IMAP_DATA* idata, char* mailbox);
int imap_rename_mailbox (IMAP_DATA* idata, IMAP_MBOX* mx, const char* newname);
IMAP_STATUS* imap_mboxcache_get (IMAP_DATA* idata, const char* mbox,
int create);
void imap_mboxcache_free (IMAP_DATA* idata);
int imap_exec_msgset (IMAP_DATA* idata, const char* pre, const char* post,
int flag, int changed, int invert);
int imap_open_connection (IMAP_DATA* idata);
void imap_close_connection (IMAP_DATA* idata);
IMAP_DATA* imap_conn_find (const ACCOUNT* account, int flags);
int imap_read_literal (FILE* fp, IMAP_DATA* idata, unsigned int bytes, progress_t*);
void imap_expunge_mailbox (IMAP_DATA* idata);
void imap_logout (IMAP_DATA** idata);
int imap_sync_message_for_copy (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd,
int *err_continue);
int imap_has_flag (LIST* flag_list, const char* flag);
int imap_reconnect (IMAP_DATA **p_idata);
/* auth.c */
int imap_authenticate (IMAP_DATA* idata);
/* command.c */
int imap_cmd_start (IMAP_DATA* idata, const char* cmd);
int imap_cmd_step (IMAP_DATA* idata);
void imap_cmd_finish (IMAP_DATA* idata);
int imap_code (const char* s);
const char* imap_cmd_trailer (IMAP_DATA* idata);
int imap_exec (IMAP_DATA* idata, const char* cmd, int flags);
int imap_cmd_idle (IMAP_DATA* idata);
/* message.c */
void imap_add_keywords (char* s, HEADER* keywords, LIST* mailbox_flags, size_t slen);
void imap_free_header_data (IMAP_HEADER_DATA** data);
int imap_read_headers (IMAP_DATA* idata, unsigned int msn_begin, unsigned int msn_end,
int initial_download);
char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s, int *server_changes);
int imap_cache_del (IMAP_DATA* idata, HEADER* h);
int imap_cache_clean (IMAP_DATA* idata);
int imap_fetch_message (CONTEXT *ctx, MESSAGE *msg, int msgno, int headers);
int imap_close_message (CONTEXT *ctx, MESSAGE *msg);
int imap_commit_message (CONTEXT *ctx, MESSAGE *msg);
/* util.c */
#ifdef USE_HCACHE
header_cache_t* imap_hcache_open (IMAP_DATA* idata, const char* path);
void imap_hcache_close (IMAP_DATA* idata);
HEADER* imap_hcache_get (IMAP_DATA* idata, unsigned int uid);
int imap_hcache_put (IMAP_DATA* idata, HEADER* h);
int imap_hcache_del (IMAP_DATA* idata, unsigned int uid);
int imap_hcache_store_uid_seqset (IMAP_DATA *idata);
int imap_hcache_clear_uid_seqset (IMAP_DATA *idata);
char *imap_hcache_get_uid_seqset (IMAP_DATA *idata);
#endif
int imap_continue (const char* msg, const char* resp);
void imap_error (const char* where, const char* msg);
IMAP_DATA* imap_new_idata (void);
void imap_free_idata (IMAP_DATA** idata);
char* imap_fix_path (IMAP_DATA* idata, const char* mailbox, char* path,
size_t plen);
void imap_cachepath(IMAP_DATA *idata, const char *mailbox, BUFFER *dest);
int imap_get_literal_count (const char* buf, unsigned int* bytes);
char* imap_get_qualifier (char*
|