78 size_t len = strlen(
group) + 1;
84 mdata->deleted =
true;
106 if (
mdata->acache[i].path)
108 unlink(
mdata->acache[i].path);
135 if ((
mdata->last_message == 0) ||
142 for (
unsigned int i = 0; i <
mdata->newsrc_len; i++)
146 first =
mdata->first_message;
148 if (last >
mdata->last_message)
149 last =
mdata->last_message;
151 mdata->unread -= last - first + 1;
168 struct stat st = { 0 };
205 if ((adata->
size == st.st_size) && (adata->
mtime == st.st_mtime))
208 adata->
size = st.st_size;
209 adata->
mtime = st.st_mtime;
214 for (
unsigned int i = 0; i < adata->
groups_num; i++)
220 mdata->subscribed =
false;
221 mdata->newsrc_len = 0;
226 while (st.st_size && fgets(line, st.st_size + 1,
adata->
fp_newsrc))
228 char *b = NULL, *h = NULL;
233 char *p = strpbrk(line,
":!");
252 mdata->subscribed = subs;
272 if ((sscanf(b,
ANUM, &
mdata->newsrc_ent[j].first) == 1) &&
273 (sscanf(h,
ANUM, &
mdata->newsrc_ent[j].last) == 1))
280 mdata->newsrc_ent[j].first = 1;
281 mdata->newsrc_ent[j].last = 0;
284 if (
mdata->last_message == 0)
285 mdata->last_message =
mdata->newsrc_ent[j - 1].last;
286 mdata->newsrc_len = j;
305 anum_t last = 0, first = 1;
307 unsigned int entries;
316 entries =
mdata->newsrc_len;
325 mdata->newsrc_len = 0;
364 if (series && (first <= mdata->last_loaded))
399 snprintf(tmpfile,
sizeof(tmpfile),
"%s.tmp", filename);
407 if (fputs(buf, fp) == EOF)
419 if (rename(tmpfile, filename) < 0)
448 size_t buflen = 10240;
453 for (
unsigned int i = 0; i < adata->
groups_num; i++)
461 if (off + strlen(
mdata->group) + 3 > buflen)
466 snprintf(buf + off, buflen - off,
"%s%c ",
mdata->group,
mdata->subscribed ?
':' :
'!');
467 off += strlen(buf + off);
470 for (
unsigned int j = 0; j <
mdata->newsrc_len; j++)
472 if (off + 1024 > buflen)
479 if (
mdata->newsrc_ent[j].first ==
mdata->newsrc_ent[j].last)
481 snprintf(buf + off, buflen - off,
ANUM,
mdata->newsrc_ent[j].first);
483 else if (
mdata->newsrc_ent[j].first <
mdata->newsrc_ent[j].last)
485 snprintf(buf + off, buflen - off,
ANUM "-" ANUM,
486 mdata->newsrc_ent[j].first,
mdata->newsrc_ent[j].last);
488 off += strlen(buf + off);
498 struct stat st = { 0 };
503 adata->
size = st.st_size;
504 adata->
mtime = st.st_mtime;
530 struct Url url = { 0 };
543 snprintf(dst, dstlen,
"%s/%s", c_news_cache_dir, file);
546 c = dst + strlen(dst) - 1;
566 struct Url url = { 0 };
584 char group[1024] = { 0 };
585 char desc[8192] = { 0 };
593 if (sscanf(line,
"%1023s " ANUM " " ANUM " %c %8191[^\n]",
group, &last,
594 &first, &mod,
desc) < 4)
601 mdata->deleted =
false;
602 mdata->first_message = first;
603 mdata->last_message = last;
604 mdata->allowed = (mod ==
'y') || (mod ==
'm');
606 if (
mdata->newsrc_ent || (
mdata->last_cached != 0))
608 else if (
mdata->last_message && (
mdata->first_message <=
mdata->last_message))
623 char buf[8192] = { 0 };
624 char file[4096] = { 0 };
633 if (!fgets(buf,
sizeof(buf), fp) || (sscanf(buf,
"%jd%4095s", &t, file) != 1) || (t == 0))
641 while (fgets(buf,
sizeof(buf), fp))
660 size_t buflen = 10240;
663 size_t off = strlen(buf);
672 if ((off + strlen(
mdata->group) + (
mdata->desc ? strlen(
mdata->desc) : 0) + 50) > buflen)
677 snprintf(buf + off, buflen - off,
"%s " ANUM " " ANUM " %c%s%s\n",
mdata->group,
680 off += strlen(buf + off);
702 if (first && last && (last > first))
704 memmove(first, last, strlen(last) + 1);
716 struct Url url = { 0 };
743 char buf[32] = { 0 };
745 anum_t first = 0, last = 0;
752 if (sscanf(hdata,
ANUM " " ANUM, &first, &last) == 2)
758 for (
anum_t current = first; current <= last; current++)
760 if ((current >= mdata->
first_message) && (current <= mdata->last_message))
763 snprintf(buf,
sizeof(buf),
ANUM, current);
791 if (!
mdata || (sscanf(
id,
ANUM "%c", &anum, &c) != 1) ||
851 struct dirent *de = NULL;
862 fp = file + strlen(file);
863 while ((de = readdir(dir)))
865 char *group = de->d_name;
866 struct stat st = { 0 };
874 if (stat(file, &st) != 0)
878 if (S_ISREG(st.st_mode))
887 if (!S_ISDIR(st.st_mode))
897 mdata->bcache = NULL;
899 else if (
mdata->newsrc_ent ||
mdata->subscribed || c_save_unsubscribed)
905 if (S_ISDIR(st.st_mode))
928 const char *src,
const char *prec,
const char *if_str,
933 char fn[128], fmt[128];
939 struct Url url = { 0 };
942 char *p = strchr(fn,
'/');
945 snprintf(fmt,
sizeof(fmt),
"%%%ss", prec);
946 snprintf(buf, buflen, fmt, fn);
950 snprintf(fmt,
sizeof(fmt),
"%%%su", prec);
951 snprintf(buf, buflen, fmt, cac->
port);
957 snprintf(fmt,
sizeof(fmt),
"%%%su", prec);
958 snprintf(buf, buflen, fmt, cac->
port);
964 snprintf(fmt,
sizeof(fmt),
"%%%ss", prec);
965 snprintf(buf, buflen, fmt, fn);
969 struct Url url = { 0 };
972 char *p = strchr(fn,
':');
975 snprintf(fmt,
sizeof(fmt),
"%%%ss", prec);
976 snprintf(buf, buflen, fmt, fn);
980 snprintf(fmt,
sizeof(fmt),
"%%%ss", prec);
981 snprintf(buf, buflen, fmt, cac->
user);
1029 if (!server || (*server ==
'\0'))
1042 snprintf(file,
sizeof(file),
"%s%s", strstr(server,
"://") ?
"" :
"news://", server);
1044 if (!url || (url->
path && *url->
path) ||
1049 mutt_error(
_(
"%s is an invalid news server specification"), server);
1060 const char *
user = NULL;
1061 const char *
pass = NULL;
1102 if ((rc < 0) || !leave_lock)
1104 return (rc < 0) ? NULL : adata;
1115 if ((rc >= 0) && c_news_cache_dir)
1120 mutt_error(
_(
"Can't create %s: %s"), file, strerror(errno));
1156 struct dirent *de = NULL;
1161 while ((de = readdir(dir)))
1164 char *group = de->d_name;
1166 char *p = group + strlen(group) - 7;
1184 if (sscanf(hdata,
ANUM " " ANUM, &first, &last) == 2)
1188 mdata->first_message = first;
1189 mdata->last_message = last;
1193 mdata->last_cached = last;
1206 if ((rc < 0) || !leave_lock)
1246 for (
unsigned int i = 0; i <
mdata->newsrc_len; i++)
1257 if (anum >
mdata->last_cached)
1279 mdata->subscribed =
true;
1280 if (!
mdata->newsrc_ent)
1283 mdata->newsrc_len = 1;
1284 mdata->newsrc_ent[0].first = 1;
1285 mdata->newsrc_ent[0].last = 0;
1306 mdata->subscribed =
false;
1308 if (!c_save_unsubscribed)
1310 mdata->newsrc_len = 0;
1334 if (
mdata->newsrc_ent)
1337 mdata->newsrc_len = 1;
1338 mdata->newsrc_ent[0].first = 1;
1339 mdata->newsrc_ent[0].last =
mdata->last_message;
1344 for (
unsigned int i = 0; i < m->
msg_count; i++)
1373 if (
mdata->newsrc_ent)
1376 mdata->newsrc_len = 1;
1377 mdata->newsrc_ent[0].first = 1;
1378 mdata->newsrc_ent[0].last =
mdata->first_message - 1;
1383 for (
unsigned int i = 0; i < m->
msg_count; i++)
1423 for (
unsigned int j = 0; j < m->
msg_count; j++)
Body Caching (local copies of email bodies)
struct BodyCache * mutt_bcache_open(struct ConnAccount *account, const char *mailbox)
Open an Email-Body Cache.
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
int mutt_bcache_del(struct BodyCache *bcache, const char *id)
Delete a file from the Body Cache.
void mutt_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Convenience wrapper for the config headers.
ConnAccountField
Login credentials.
@ MUTT_CA_OAUTH_CMD
OAuth refresh command.
@ MUTT_CA_LOGIN
Login name.
@ MUTT_CA_HOST
Server name.
#define MUTT_ACCT_SSL
Account uses SSL/TLS.
#define MUTT_ACCT_PASS
Password field has been set.
#define MUTT_ACCT_USER
User field has been set.
#define MUTT_ACCT_PORT
Port field has been set.
Convenience wrapper for the core headers.
Structs that make up an email.
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
DIR * mutt_file_opendir(const char *path, enum MuttOpenDirMode mode)
Open a directory.
@ MUTT_OPENDIR_NONE
Plain opendir()
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
static int nntp_bcache_delete(const char *id, struct BodyCache *bcache, void *data)
Remove bcache file - Implements bcache_list_t -.
const char * nntp_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Expand the newsrc filename - Implements format_t -.
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
static void nntp_hcache_namer(const char *path, struct Buffer *dest)
Compose hcache file names - Implements hcache_namer_t -.
#define mutt_message(...)
#define mutt_debug(LEVEL,...)
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Header cache multiplexor.
void mutt_hcache_close(struct HeaderCache *hc)
Multiplexor for StoreOps::close.
struct HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
int mutt_hcache_store_raw(struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
Store a key / data pair.
char * mutt_hcache_fetch_str(struct HeaderCache *hc, const char *key, size_t keylen)
Fetch a string from the cache.
@ LL_DEBUG2
Log at debug level 2.
@ LL_DEBUG1
Log at debug level 1.
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
@ NT_MAILBOX_RESORT
Email list needs resorting.
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
char * mutt_strn_cat(char *d, size_t l, const char *s, size_t sl)
Concatenate two strings.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Many unsorted constants and some structs.
@ MUTT_READ
Messages that have been read.
int mutt_account_fromurl(struct ConnAccount *cac, const struct Url *url)
Fill ConnAccount with information from url.
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
ConnAccount object used by POP and IMAP.
@ MUTT_ACCT_TYPE_NNTP
Nntp (Usenet) Account.
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
struct Connection * mutt_conn_find(const struct ConnAccount *cac)
Find a connection from a list.
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
Some miscellaneous functions.
struct HeaderCache * nntp_hcache_open(struct NntpMboxData *mdata)
Open newsgroup hcache.
void nntp_clear_cache(struct NntpAccountData *adata)
Clear the NNTP cache.
void nntp_delete_group_cache(struct NntpMboxData *mdata)
Remove hcache and bcache of newsgroup.
void nntp_newsrc_gen_entries(struct Mailbox *m)
Generate array of .newsrc entries.
void nntp_hcache_update(struct NntpMboxData *mdata, struct HeaderCache *hc)
Remove stale cached headers.
void nntp_article_status(struct Mailbox *m, struct Email *e, char *group, anum_t anum)
Get status of articles from .newsrc.
static int update_file(char *filename, char *buf)
Update file with new contents.
int nntp_add_group(char *line, void *data)
Parse newsgroup.
int nntp_newsrc_parse(struct NntpAccountData *adata)
Parse .newsrc file.
void nntp_mailbox(struct Mailbox *m, char *buf, size_t buflen)
Get first newsgroup with new messages.
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
int nntp_newsrc_update(struct NntpAccountData *adata)
Update .newsrc file.
struct NntpMboxData * mutt_newsgroup_subscribe(struct NntpAccountData *adata, char *group)
Subscribe newsgroup.
static const char * nntp_get_field(enum ConnAccountField field, void *gf_data)
Get connection login credentials - Implements ConnAccount::get_field()
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *cac)
Make fully qualified url from newsgroup name.
static int active_get_cache(struct NntpAccountData *adata)
Load list of all newsgroups from cache.
static void cache_expand(char *dst, size_t dstlen, struct ConnAccount *cac, const char *src)
Make fully qualified cache file name.
static struct NntpMboxData * mdata_find(struct NntpAccountData *adata, const char *group)
Find NntpMboxData for given newsgroup or add it.
struct NntpMboxData * mutt_newsgroup_uncatchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Uncatchup newsgroup.
int nntp_active_save_cache(struct NntpAccountData *adata)
Save list of all newsgroups to cache.
void nntp_bcache_update(struct NntpMboxData *mdata)
Remove stale cached messages.
void nntp_group_unread_stat(struct NntpMboxData *mdata)
Count number of unread articles using .newsrc data.
void nntp_acache_free(struct NntpMboxData *mdata)
Remove all temporarily cache files.
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
struct NntpMboxData * mutt_newsgroup_unsubscribe(struct NntpAccountData *adata, char *group)
Unsubscribe newsgroup.
struct NntpAccountData * nntp_adata_new(struct Connection *conn)
Allocate and initialise a new NntpAccountData structure.
struct NntpEmailData * nntp_edata_get(struct Email *e)
Get the private data for this Email.
int nntp_active_fetch(struct NntpAccountData *adata, bool mark_new)
Fetch list of all newsgroups from server.
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
@ NNTP_NONE
No connection to server.
@ NNTP_BYE
Disconnected from server.
int nntp_check_new_groups(struct Mailbox *m, struct NntpAccountData *adata)
Check for new groups/articles in subscribed groups.
int nntp_open_connection(struct NntpAccountData *adata)
Connect to server, authenticate and get capabilities.
Notmuch-specific Mailbox data.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Pop-specific Account data.
Prototypes for many functions.
int mutt_socket_close(struct Connection *conn)
Close a socket.
SortType
Methods for sorting.
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
void * adata
Private data (for Mailbox backends)
Local cache of email bodies.
String manipulation buffer.
size_t dsize
Length of data.
char * data
Pointer to data.
Login details for a remote server.
const char * service
Name of the service, e.g. "imap".
char host[128]
Server to login to.
const char *(* get_field)(enum ConnAccountField field, void *gf_data)
Function to get some login credentials.
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
unsigned short port
Port to connect to.
struct ConnAccount account
Account details: username, password, etc.
The envelope/body of an email.
bool old
Email is seen, but unread.
bool deleted
Email is deleted.
int msg_count
Total number of messages.
enum MailboxType type
Mailbox type.
void * mdata
Driver specific data.
struct Email ** emails
Array of Emails.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.
An entry in a .newsrc (subscribed newsgroups)
anum_t last
Last article number in run.
anum_t first
First article number in run.
NNTP-specific Account data -.
struct HashTable * groups_hash
Hash Table: "newsgroup" -> NntpMboxData.
struct Connection * conn
Connection to NNTP Server.
anum_t article_num
NNTP article number.
NNTP-specific Mailbox data -.
struct BodyCache * bcache
char * group
Name of newsgroup.
struct NntpAccountData * adata
char * desc
Description of newsgroup.
struct NewsrcEntry * newsrc_ent
A parsed URL proto://user:password@host:port/path?a=1&b=2
char * src
Raw URL string.
enum UrlScheme scheme
Scheme, e.g. U_SMTPS.
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
struct Url * url_parse(const char *src)
Fill in Url.
int url_tostring(struct Url *url, char *dest, size_t len, uint8_t flags)
Output the URL string for a given Url object.
void url_free(struct Url **ptr)
Free the contents of a URL.
@ U_NNTPS
Url is nntps://.