NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
private.h File Reference

Usenet network mailbox type; talk to an NNTP server. More...

#include <stdbool.h>
#include <stdint.h>
#include "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.

Macros

#define NNTP_PORT   119
 
#define NNTP_SSL_PORT   563
 

Enumerations

enum  NntpStatus { NNTP_NONE = 0 , NNTP_OK , NNTP_BYE }
 NNTP server return values. More...
 

Functions

void nntp_acache_free (struct NntpMboxData *mdata)
 Remove all temporarily cache files.
 
int nntp_active_save_cache (struct NntpAccountData *adata)
 Save list of all newsgroups to cache.
 
int nntp_add_group (char *line, void *data)
 Parse newsgroup.
 
void nntp_article_status (struct Mailbox *m, struct Email *e, char *group, anum_t anum)
 Get status of articles from .newsrc.
 
void nntp_bcache_update (struct NntpMboxData *mdata)
 Remove stale cached messages.
 
int nntp_check_new_groups (struct Mailbox *m, struct NntpAccountData *adata)
 Check for new groups/articles in subscribed groups.
 
void nntp_delete_group_cache (struct NntpMboxData *mdata)
 Remove hcache and bcache of newsgroup.
 
void nntp_group_unread_stat (struct NntpMboxData *mdata)
 Count number of unread articles using .newsrc data.
 
void nntp_hash_destructor_t (int type, void *obj, intptr_t data)
 
void nntp_hashelem_free (int type, void *obj, intptr_t data)
 Free our hash table data - Implements hash_hdata_free_t -.
 
struct HeaderCachenntp_hcache_open (struct NntpMboxData *mdata)
 Open newsgroup hcache.
 
void nntp_hcache_update (struct NntpMboxData *mdata, struct HeaderCache *hc)
 Remove stale cached headers.
 
void nntp_newsrc_gen_entries (struct Mailbox *m)
 Generate array of .newsrc entries.
 
int nntp_open_connection (struct NntpAccountData *adata)
 Connect to server, authenticate and get capabilities.
 

Detailed Description

Usenet network mailbox type; talk to an NNTP server.

Authors
  • Richard Russon

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

◆ NNTP_PORT

#define NNTP_PORT   119

Definition at line 36 of file private.h.

◆ NNTP_SSL_PORT

#define NNTP_SSL_PORT   563

Definition at line 37 of file private.h.

Enumeration Type Documentation

◆ NntpStatus

enum NntpStatus

NNTP server return values.

Enumerator
NNTP_NONE 

No connection to server.

NNTP_OK 

Connected to server.

NNTP_BYE 

Disconnected from server.

Definition at line 42 of file private.h.

43{
44 NNTP_NONE = 0,
45 NNTP_OK,
46 NNTP_BYE,
47};
@ NNTP_NONE
No connection to server.
Definition private.h:44
@ NNTP_BYE
Disconnected from server.
Definition private.h:46
@ NNTP_OK
Connected to server.
Definition private.h:45

Function Documentation

◆ nntp_acache_free()

void nntp_acache_free ( struct NntpMboxData * mdata)

Remove all temporarily cache files.

Parameters
mdataNNTP Mailbox data

Definition at line 105 of file newsrc.c.

106{
107 for (int i = 0; i < NNTP_ACACHE_LEN; i++)
108 {
109 if (mdata->acache[i].path)
110 {
111 unlink(mdata->acache[i].path);
112 FREE(&mdata->acache[i].path);
113 }
114 }
115}
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define NNTP_ACACHE_LEN
Definition lib.h:85
char * path
Cache path.
Definition lib.h:72
struct NntpAcache acache[NNTP_ACACHE_LEN]
Article cache.
Definition mdata.h:49
+ Here is the caller graph for this function:

◆ nntp_active_save_cache()

int nntp_active_save_cache ( struct NntpAccountData * adata)

Save list of all newsgroups to cache.

Parameters
adataNNTP server
Return values
0Success
-1Failure

Definition at line 651 of file newsrc.c.

652{
653 if (!adata->cacheable)
654 return 0;
655
656 size_t buflen = 10240;
657 char *buf = MUTT_MEM_CALLOC(buflen, char);
658 snprintf(buf, buflen, "%lu\n", (unsigned long) adata->newgroups_time);
659 size_t off = strlen(buf);
660
661 for (unsigned int i = 0; i < adata->groups_num; i++)
662 {
663 struct NntpMboxData *mdata = adata->groups_list[i];
664
665 if (!mdata || mdata->deleted)
666 continue;
667
668 if ((off + strlen(mdata->group) + (mdata->desc ? strlen(mdata->desc) : 0) + 50) > buflen)
669 {
670 buflen *= 2;
671 MUTT_MEM_REALLOC(&buf, buflen, char);
672 }
673 snprintf(buf + off, buflen - off, "%s " ANUM_FMT " " ANUM_FMT " %c%s%s\n",
674 mdata->group, mdata->last_message, mdata->first_message,
675 mdata->allowed ? 'y' : 'n', mdata->desc ? " " : "",
676 mdata->desc ? mdata->desc : "");
677 off += strlen(buf + off);
678 }
679
680 char file[PATH_MAX] = { 0 };
681 cache_expand(file, sizeof(file), &adata->conn->account, ".active");
682 mutt_debug(LL_DEBUG1, "Updating %s\n", file);
683 int rc = update_file(file, buf);
684 FREE(&buf);
685 return rc;
686}
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition memory.h:55
#define PATH_MAX
Definition mutt.h:49
static int update_file(char *filename, char *buf)
Update file with new contents.
Definition newsrc.c:396
static void cache_expand(char *dst, size_t dstlen, struct ConnAccount *cac, const char *src)
Make fully qualified cache file name.
Definition newsrc.c:527
#define ANUM_FMT
Definition lib.h:64
struct ConnAccount account
Account details: username, password, etc.
Definition connection.h:49
void * mdata
Driver specific data.
Definition mailbox.h:134
time_t newgroups_time
Last newgroups request time.
Definition adata.h:56
struct NntpMboxData ** groups_list
List of newsgroups.
Definition adata.h:60
struct Connection * conn
Connection to NNTP Server.
Definition adata.h:63
unsigned int groups_num
Number of newsgroups.
Definition adata.h:58
bool cacheable
Can be cached.
Definition adata.h:48
NNTP-specific Mailbox data -.
Definition mdata.h:34
struct NntpAccountData * adata
Account data.
Definition mdata.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_add_group()

int nntp_add_group ( char * line,
void * data )

Parse newsgroup.

Parameters
lineString to parse
dataNNTP data
Return values
0Always

Definition at line 575 of file newsrc.c.

576{
577 struct NntpAccountData *adata = data;
578 struct NntpMboxData *mdata = NULL;
579 char group[1024] = { 0 };
580 char desc[8192] = { 0 };
581 char mod = '\0';
582 anum_t first = 0;
583 anum_t last = 0;
584
585 if (!adata || !line)
586 return 0;
587
588 /* These sscanf limits must match the sizes of the group and desc arrays */
589 if (sscanf(line, "%1023s " ANUM_FMT " " ANUM_FMT " %c %8191[^\n]", group,
590 &last, &first, &mod, desc) < 4)
591 {
592 mutt_debug(LL_DEBUG2, "Can't parse server line: %s\n", line);
593 return 0;
594 }
595
597 mdata->deleted = false;
598 mdata->first_message = first;
599 mdata->last_message = last;
600 mdata->allowed = (mod == 'y') || (mod == 'm');
601 mutt_str_replace(&mdata->desc, desc);
602 if (mdata->newsrc_ent || (mdata->last_cached != 0))
604 else if (mdata->last_message && (mdata->first_message <= mdata->last_message))
605 mdata->unread = mdata->last_message - mdata->first_message + 1;
606 else
607 mdata->unread = 0;
608 return 0;
609}
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
static struct NntpMboxData * mdata_find(struct NntpAccountData *adata, const char *group)
Find NntpMboxData for given newsgroup or add it.
Definition newsrc.c:75
void nntp_group_unread_stat(struct NntpMboxData *mdata)
Count number of unread articles using .newsrc data.
Definition newsrc.c:135
#define anum_t
Definition lib.h:63
void * adata
Private data (for Mailbox backends)
Definition account.h:42
NNTP-specific Account data -.
Definition adata.h:36
char * group
Name of newsgroup.
Definition mdata.h:35
char * desc
Description of newsgroup.
Definition mdata.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_article_status()

void nntp_article_status ( struct Mailbox * m,
struct Email * e,
char * group,
anum_t anum )

Get status of articles from .newsrc.

Parameters
mMailbox
eEmail
groupNewsgroup
anumArticle number

Full status flags are not supported by nntp, but we can fake some of them: Read = a read message number is in the .newsrc New = not read and not cached Old = not read but cached

Definition at line 1151 of file newsrc.c.

1152{
1153 struct NntpMboxData *mdata = m->mdata;
1154
1155 if (group)
1156 mdata = mutt_hash_find(mdata->adata->groups_hash, group);
1157
1158 if (!mdata)
1159 return;
1160
1161 for (unsigned int i = 0; i < mdata->newsrc_len; i++)
1162 {
1163 if ((anum >= mdata->newsrc_ent[i].first) && (anum <= mdata->newsrc_ent[i].last))
1164 {
1165 /* can't use mutt_set_flag() because mview_update() didn't get called yet */
1166 e->read = true;
1167 return;
1168 }
1169 }
1170
1171 /* article was not cached yet, it's new */
1172 if (anum > mdata->last_cached)
1173 return;
1174
1175 /* article isn't read but cached, it's old */
1176 const bool c_mark_old = cs_subset_bool(NeoMutt->sub, "mark_old");
1177 if (c_mark_old)
1178 e->old = true;
1179}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition hash.c:365
bool read
Email is read.
Definition email.h:50
bool old
Email is seen, but unread.
Definition email.h:49
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
anum_t last
Last article number in run.
Definition lib.h:81
struct NewsrcEntry * newsrc_ent
Newsrc entries.
Definition mdata.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_bcache_update()

void nntp_bcache_update ( struct NntpMboxData * mdata)

Remove stale cached messages.

Parameters
mdataNNTP Mailbox data

Definition at line 805 of file newsrc.c.

806{
808}
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
Definition bcache.c:355
static int nntp_bcache_delete(const char *id, struct BodyCache *bcache, void *data)
Delete an entry from the message cache - Implements bcache_list_t -.
Definition newsrc.c:785
struct BodyCache * bcache
Body cache.
Definition mdata.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_check_new_groups()

int nntp_check_new_groups ( struct Mailbox * m,
struct NntpAccountData * adata )

Check for new groups/articles in subscribed groups.

Parameters
mMailbox
adataNNTP server
Return values
1New groups found
0No new groups
-1Error

Definition at line 2112 of file nntp.c.

2113{
2114 struct NntpMboxData tmp_mdata = { 0 };
2115 time_t now = 0;
2116 char buf[1024] = { 0 };
2117 char *msg = _("Checking for new newsgroups...");
2118 unsigned int i;
2119 int rc;
2120 int update_active = false;
2121
2122 if (!adata || !adata->newgroups_time)
2123 return -1;
2124
2125 /* check subscribed newsgroups for new articles */
2126 const bool c_show_new_news = cs_subset_bool(NeoMutt->sub, "show_new_news");
2127 if (c_show_new_news)
2128 {
2129 mutt_message(_("Checking for new messages..."));
2130 for (i = 0; i < adata->groups_num; i++)
2131 {
2132 struct NntpMboxData *mdata = adata->groups_list[i];
2133
2134 if (mdata && mdata->subscribed)
2135 {
2136 rc = nntp_group_poll(mdata, true);
2137 if (rc < 0)
2138 return -1;
2139 if (rc > 0)
2140 update_active = true;
2141 }
2142 }
2143 }
2144 else if (adata->newgroups_time)
2145 {
2146 return 0;
2147 }
2148
2149 /* get list of new groups */
2150 mutt_message("%s", msg);
2151 if (nntp_date(adata, &now) < 0)
2152 return -1;
2153 tmp_mdata.adata = adata;
2154 if (m && m->mdata)
2155 tmp_mdata.group = ((struct NntpMboxData *) m->mdata)->group;
2156 else
2157 tmp_mdata.group = NULL;
2158 i = adata->groups_num;
2159 struct tm tm = mutt_date_gmtime(adata->newgroups_time);
2160 snprintf(buf, sizeof(buf), "NEWGROUPS %02d%02d%02d %02d%02d%02d GMT\r\n",
2161 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
2162 rc = nntp_fetch_lines(&tmp_mdata, buf, sizeof(buf), msg, nntp_add_group, adata);
2163 if (rc)
2164 {
2165 if (rc > 0)
2166 {
2167 mutt_error("NEWGROUPS: %s", buf);
2168 }
2169 return -1;
2170 }
2171
2172 /* new groups found */
2173 rc = 0;
2174 if (adata->groups_num != i)
2175 {
2176 int groups_num = i;
2177
2178 adata->newgroups_time = now;
2179 for (; i < adata->groups_num; i++)
2180 {
2181 struct NntpMboxData *mdata = adata->groups_list[i];
2182 mdata->has_new_mail = true;
2183 }
2184
2185 /* loading descriptions */
2186 const bool c_nntp_load_description = cs_subset_bool(NeoMutt->sub, "nntp_load_description");
2187 if (c_nntp_load_description)
2188 {
2189 unsigned int count = 0;
2190 struct Progress *progress = progress_new(MUTT_PROGRESS_READ, adata->groups_num - i);
2191 progress_set_message(progress, _("Loading descriptions..."));
2192
2193 for (i = groups_num; i < adata->groups_num; i++)
2194 {
2195 struct NntpMboxData *mdata = adata->groups_list[i];
2196
2197 if (get_description(mdata, NULL, NULL) < 0)
2198 {
2199 progress_free(&progress);
2200 return -1;
2201 }
2202 progress_update(progress, ++count, -1);
2203 }
2204 progress_free(&progress);
2205 }
2206 update_active = true;
2207 rc = 1;
2208 }
2209 if (update_active)
2212 return rc;
2213}
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone.
Definition date.c:933
#define _(a)
Definition message.h:28
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
int nntp_add_group(char *line, void *data)
Parse newsgroup.
Definition newsrc.c:575
int nntp_active_save_cache(struct NntpAccountData *adata)
Save list of all newsgroups to cache.
Definition newsrc.c:651
static int nntp_date(struct NntpAccountData *adata, time_t *now)
Get date and time from server.
Definition nntp.c:1705
static int nntp_group_poll(struct NntpMboxData *mdata, bool update_stat)
Check newsgroup for new articles.
Definition nntp.c:1445
static int nntp_fetch_lines(struct NntpMboxData *mdata, char *query, size_t qlen, const char *msg, int(*func)(char *, void *), void *data)
Read lines, calling a callback function for each.
Definition nntp.c:817
static int get_description(struct NntpMboxData *mdata, const char *wildmat, const char *msg)
Fetch newsgroups descriptions.
Definition nntp.c:939
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc
Definition lib.h:84
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__
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition progress.c:80
bool has_new_mail
Has new articles.
Definition mdata.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_delete_group_cache()

void nntp_delete_group_cache ( struct NntpMboxData * mdata)

Remove hcache and bcache of newsgroup.

Parameters
mdataNNTP Mailbox data

Definition at line 814 of file newsrc.c.

815{
816 if (!mdata || !mdata->adata || !mdata->adata->cacheable)
817 return;
818
819#ifdef USE_HCACHE
820 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
821 const struct StoreOps *store_ops = store_get_backend_ops(c_header_cache_backend);
822 if (store_ops)
823 {
824 struct Buffer *file = buf_pool_get();
825 nntp_hcache_namer(store_ops, mdata->group, file);
826 cache_expand(file->data, file->dsize, &mdata->adata->conn->account, buf_string(file));
827 unlink(buf_string(file));
828 mdata->last_cached = 0;
829 mutt_debug(LL_DEBUG2, "%s\n", buf_string(file));
830 buf_pool_release(&file);
831 }
832#endif
833
834 if (!mdata->bcache)
835 {
836 mdata->bcache = mutt_bcache_open(&mdata->adata->conn->account, mdata->group);
837 }
838 if (mdata->bcache)
839 {
840 mutt_debug(LL_DEBUG2, "%s/*\n", mdata->group);
842 mutt_bcache_close(&mdata->bcache);
843 }
844}
struct BodyCache * mutt_bcache_open(struct ConnAccount *account, const char *mailbox)
Open an Email-Body Cache.
Definition bcache.c:162
void mutt_bcache_close(struct BodyCache **ptr)
Close an Email-Body Cache.
Definition bcache.c:183
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
static void nntp_hcache_namer(const struct StoreOps *store_ops, const char *path, struct Buffer *dest)
Compose hcache file names - Implements hcache_namer_t -.
Definition newsrc.c:692
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition store.c:88
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
anum_t last_cached
Last cached article.
Definition mdata.h:40
Definition lib.h:66
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_group_unread_stat()

void nntp_group_unread_stat ( struct NntpMboxData * mdata)

Count number of unread articles using .newsrc data.

Parameters
mdataNNTP Mailbox data

Definition at line 135 of file newsrc.c.

136{
137 mdata->unread = 0;
138 if ((mdata->last_message == 0) ||
139 (mdata->first_message > mdata->last_message) || !mdata->newsrc_ent)
140 {
141 return;
142 }
143
144 mdata->unread = mdata->last_message - mdata->first_message + 1;
145 for (unsigned int i = 0; i < mdata->newsrc_len; i++)
146 {
147 anum_t first = mdata->newsrc_ent[i].first;
148 if (first < mdata->first_message)
149 first = mdata->first_message;
150 anum_t last = mdata->newsrc_ent[i].last;
151 if (last > mdata->last_message)
152 last = mdata->last_message;
153 if (first <= last)
154 mdata->unread -= last - first + 1;
155 }
156}
anum_t first
First article number in run.
Definition lib.h:80
anum_t last_message
Last article number.
Definition mdata.h:38
anum_t unread
Unread articles.
Definition mdata.h:41
unsigned int newsrc_len
Length of newsrc entry.
Definition mdata.h:46
anum_t first_message
First article number.
Definition mdata.h:37
+ Here is the caller graph for this function:

◆ nntp_hash_destructor_t()

void nntp_hash_destructor_t ( int type,
void * obj,
intptr_t data )

◆ nntp_hcache_open()

struct HeaderCache * nntp_hcache_open ( struct NntpMboxData * mdata)

Open newsgroup hcache.

Parameters
mdataNNTP Mailbox data
Return values
ptrHeader cache
NULLError

Definition at line 712 of file newsrc.c.

713{
714 struct Url url = { 0 };
715 char file[PATH_MAX] = { 0 };
716
717 const bool c_save_unsubscribed = cs_subset_bool(NeoMutt->sub, "save_unsubscribed");
718 if (!mdata->adata || !mdata->adata->cacheable || !mdata->adata->conn || !mdata->group ||
719 !(mdata->newsrc_ent || mdata->subscribed || c_save_unsubscribed))
720 {
721 return NULL;
722 }
723
724 account_to_url(&mdata->adata->conn->account, &url);
725 url.path = mdata->group;
726 url_tostring(&url, file, sizeof(file), U_PATH);
727 const char *const c_news_cache_dir = cs_subset_path(NeoMutt->sub, "news_cache_dir");
728 return hcache_open(c_news_cache_dir, file, nntp_hcache_namer, true);
729}
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
struct HeaderCache * hcache_open(const char *path, const char *folder, hcache_namer_t namer, bool create)
Multiplexor for StoreOps::open.
Definition hcache.c:492
void account_to_url(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
bool subscribed
Subscribed to this newsgroup.
Definition mdata.h:42
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_tostring(const struct Url *url, char *dest, size_t len, uint8_t flags)
Output the URL string for a given Url object.
Definition url.c:426
#define U_PATH
Path is included in URL.
Definition url.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_hcache_update()

void nntp_hcache_update ( struct NntpMboxData * mdata,
struct HeaderCache * hc )

Remove stale cached headers.

Parameters
mdataNNTP Mailbox data
hcHeader cache

Definition at line 736 of file newsrc.c.

737{
738 if (!hc)
739 return;
740
741 char buf[32] = { 0 };
742 bool old = false;
743 anum_t first = 0;
744 anum_t last = 0;
745
746 /* fetch previous values of first and last */
747 char *hdata = hcache_fetch_raw_str(hc, "index", 5);
748 if (hdata)
749 {
750 mutt_debug(LL_DEBUG2, "hcache_fetch_email index: %s\n", hdata);
751 if (sscanf(hdata, ANUM_FMT " " ANUM_FMT, &first, &last) == 2)
752 {
753 old = true;
754 mdata->last_cached = last;
755
756 /* clean removed headers from cache */
757 for (anum_t current = first; current <= last; current++)
758 {
759 if ((current >= mdata->first_message) && (current <= mdata->last_message))
760 continue;
761
762 snprintf(buf, sizeof(buf), ANUM_FMT, current);
763 mutt_debug(LL_DEBUG2, "hcache_delete_email %s\n", buf);
764 hcache_delete_email(hc, buf, strlen(buf));
765 }
766 }
767 FREE(&hdata);
768 }
769
770 /* store current values of first and last */
771 if (!old || (mdata->first_message != first) || (mdata->last_message != last))
772 {
773 snprintf(buf, sizeof(buf), ANUM_FMT " " ANUM_FMT, mdata->first_message,
774 mdata->last_message);
775 mutt_debug(LL_DEBUG2, "hcache_store_email index: %s\n", buf);
776 hcache_store_raw(hc, "index", 5, buf, strlen(buf) + 1);
777 }
778}
int hcache_delete_email(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition hcache.c:769
char * hcache_fetch_raw_str(struct HeaderCache *hc, const char *key, size_t keylen)
Fetch a string from the cache.
Definition hcache.c:679
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:754
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_newsrc_gen_entries()

void nntp_newsrc_gen_entries ( struct Mailbox * m)

Generate array of .newsrc entries.

Parameters
mMailbox

Definition at line 303 of file newsrc.c.

304{
305 if (!m)
306 return;
307
308 struct NntpMboxData *mdata = m->mdata;
309 anum_t last = 0;
310 anum_t first = 1;
311 bool series;
312 unsigned int entries;
313
314 const enum EmailSortType c_sort = cs_subset_sort(NeoMutt->sub, "sort");
315 if (c_sort != EMAIL_SORT_UNSORTED)
316 {
319 }
320
321 entries = mdata->newsrc_len;
322 if (!entries)
323 {
324 entries = 5;
325 mdata->newsrc_ent = MUTT_MEM_CALLOC(entries, struct NewsrcEntry);
326 }
327
328 /* Set up to fake initial sequence from 1 to the article before the
329 * first article in our list */
330 mdata->newsrc_len = 0;
331 series = true;
332 for (int i = 0; i < m->msg_count; i++)
333 {
334 struct Email *e = m->emails[i];
335 if (!e)
336 break;
337
338 /* search for first unread */
339 if (series)
340 {
341 /* We don't actually check sequential order, since we mark
342 * "missing" entries as read/deleted */
343 last = nntp_edata_get(e)->article_num;
344 if ((last >= mdata->first_message) && !e->deleted && !e->read)
345 {
346 if (mdata->newsrc_len >= entries)
347 {
348 entries *= 2;
349 MUTT_MEM_REALLOC(&mdata->newsrc_ent, entries, struct NewsrcEntry);
350 }
351 mdata->newsrc_ent[mdata->newsrc_len].first = first;
352 mdata->newsrc_ent[mdata->newsrc_len].last = last - 1;
353 mdata->newsrc_len++;
354 series = false;
355 }
356 }
357 else
358 {
359 /* search for first read */
360 if (e->deleted || e->read)
361 {
362 first = last + 1;
363 series = true;
364 }
365 last = nntp_edata_get(e)->article_num;
366 }
367 }
368
369 if (series && (first <= mdata->last_loaded))
370 {
371 if (mdata->newsrc_len >= entries)
372 {
373 entries++;
374 MUTT_MEM_REALLOC(&mdata->newsrc_ent, entries, struct NewsrcEntry);
375 }
376 mdata->newsrc_ent[mdata->newsrc_len].first = first;
377 mdata->newsrc_ent[mdata->newsrc_len].last = mdata->last_loaded;
378 mdata->newsrc_len++;
379 }
380 MUTT_MEM_REALLOC(&mdata->newsrc_ent, mdata->newsrc_len, struct NewsrcEntry);
381
382 if (c_sort != EMAIL_SORT_UNSORTED)
383 {
384 cs_subset_str_native_set(NeoMutt->sub, "sort", c_sort, NULL);
386 }
387}
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition helpers.c:266
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition mailbox.c:232
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition mailbox.h:183
EmailSortType
Methods for sorting Emails.
Definition sort.h:53
@ EMAIL_SORT_UNSORTED
Sort by the order the messages appear in the mailbox.
Definition sort.h:64
struct NntpEmailData * nntp_edata_get(struct Email *e)
Get the private data for this Email.
Definition edata.c:60
The envelope/body of an email.
Definition email.h:39
bool deleted
Email is deleted.
Definition email.h:78
int msg_count
Total number of messages.
Definition mailbox.h:90
struct Email ** emails
Array of Emails.
Definition mailbox.h:98
An entry in a .newsrc (subscribed newsgroups)
Definition lib.h:79
anum_t article_num
NNTP article number.
Definition edata.h:36
anum_t last_loaded
Last loaded article.
Definition mdata.h:39
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.
Definition subset.c:303
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_open_connection()

int nntp_open_connection ( struct NntpAccountData * adata)

Connect to server, authenticate and get capabilities.

Parameters
adataNNTP server
Return values
0Success
-1Failure

Definition at line 1772 of file nntp.c.

1773{
1774 if (adata->status == NNTP_OK)
1775 return 0;
1776 if (adata->status == NNTP_BYE)
1777 return -1;
1778 adata->status = NNTP_NONE;
1779
1780 struct Connection *conn = adata->conn;
1781 if (mutt_socket_open(conn) < 0)
1782 return -1;
1783
1784 char buf[256] = { 0 };
1785 int cap;
1786 bool posting = false, auth = true;
1787 int rc = -1;
1788
1789 if (mutt_socket_readln(buf, sizeof(buf), conn) < 0)
1790 {
1791 nntp_connect_error(adata);
1792 goto done;
1793 }
1794
1795 if (mutt_str_startswith(buf, "200"))
1796 {
1797 posting = true;
1798 }
1799 else if (!mutt_str_startswith(buf, "201"))
1800 {
1801 mutt_socket_close(conn);
1803 mutt_error("%s", buf);
1804 goto done;
1805 }
1806
1807 /* get initial capabilities */
1808 cap = nntp_capabilities(adata);
1809 if (cap < 0)
1810 goto done;
1811
1812 /* tell news server to switch to mode reader if it isn't so */
1813 if (cap > 0)
1814 {
1815 if ((mutt_socket_send(conn, "MODE READER\r\n") < 0) ||
1816 (mutt_socket_readln(buf, sizeof(buf), conn) < 0))
1817 {
1818 nntp_connect_error(adata);
1819 goto done;
1820 }
1821
1822 if (mutt_str_startswith(buf, "200"))
1823 {
1824 posting = true;
1825 }
1826 else if (mutt_str_startswith(buf, "201"))
1827 {
1828 posting = false;
1829 }
1830 else if (adata->hasCAPABILITIES)
1831 {
1832 /* error if has capabilities, ignore result if no capabilities */
1833 mutt_socket_close(conn);
1834 mutt_error(_("Could not switch to reader mode"));
1835 goto done;
1836 }
1837
1838 /* recheck capabilities after MODE READER */
1839 if (adata->hasCAPABILITIES)
1840 {
1841 cap = nntp_capabilities(adata);
1842 if (cap < 0)
1843 goto done;
1844 }
1845 }
1846
1847 mutt_message(_("Connected to %s. %s"), conn->account.host,
1848 posting ? _("Posting is ok") : _("Posting is NOT ok"));
1849 mutt_sleep(1);
1850
1851#ifdef USE_SSL
1852 /* Attempt STARTTLS if available and desired. */
1853 const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
1854 if ((adata->use_tls != 1) && (adata->hasSTARTTLS || c_ssl_force_tls))
1855 {
1856 if (adata->use_tls == 0)
1857 {
1858 adata->use_tls = c_ssl_force_tls ||
1859 (query_quadoption(_("Secure connection with TLS?"),
1860 NeoMutt->sub, "ssl_starttls") == MUTT_YES) ?
1861 2 :
1862 1;
1863 }
1864 if (adata->use_tls == 2)
1865 {
1866 if ((mutt_socket_send(conn, "STARTTLS\r\n") < 0) ||
1867 (mutt_socket_readln(buf, sizeof(buf), conn) < 0))
1868 {
1869 nntp_connect_error(adata);
1870 goto done;
1871 }
1872 // Clear any data after the STARTTLS acknowledgement
1873 mutt_socket_empty(conn);
1874 if (!mutt_str_startswith(buf, "382"))
1875 {
1876 adata->use_tls = 0;
1877 mutt_error("STARTTLS: %s", buf);
1878 }
1879 else if (mutt_ssl_starttls(conn) != 0)
1880 {
1881 adata->use_tls = 0;
1882 adata->status = NNTP_NONE;
1883 mutt_socket_close(adata->conn);
1884 mutt_error(_("Could not negotiate TLS connection"));
1885 goto done;
1886 }
1887 else
1888 {
1889 /* recheck capabilities after STARTTLS */
1890 cap = nntp_capabilities(adata);
1891 if (cap < 0)
1892 goto done;
1893 }
1894 }
1895 }
1896#endif
1897
1898 /* authentication required? */
1899 if (conn->account.flags & MUTT_ACCT_USER)
1900 {
1901 if (!conn->account.user[0])
1902 auth = false;
1903 }
1904 else
1905 {
1906 if ((mutt_socket_send(conn, "STAT\r\n") < 0) ||
1907 (mutt_socket_readln(buf, sizeof(buf), conn) < 0))
1908 {
1909 nntp_connect_error(adata);
1910 goto done;
1911 }
1912 if (!mutt_str_startswith(buf, "480"))
1913 auth = false;
1914 }
1915
1916 /* authenticate */
1917 if (auth && (nntp_auth(adata) < 0))
1918 goto done;
1919
1920 /* get final capabilities after authentication */
1921 if (adata->hasCAPABILITIES && (auth || (cap > 0)))
1922 {
1923 cap = nntp_capabilities(adata);
1924 if (cap < 0)
1925 goto done;
1926 if (cap > 0)
1927 {
1928 mutt_socket_close(conn);
1929 mutt_error(_("Could not switch to reader mode"));
1930 goto done;
1931 }
1932 }
1933
1934 /* attempt features */
1935 if (nntp_attempt_features(adata) < 0)
1936 goto done;
1937
1938 rc = 0;
1939 adata->status = NNTP_OK;
1940
1941done:
1942 return rc;
1943}
@ MUTT_ACCT_USER
User field has been set.
Definition connaccount.h:48
int mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
Definition gnutls.c:1175
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition string.c:571
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:234
void mutt_sleep(short s)
Sleep for a while.
Definition muttlib.c:787
static int nntp_auth(struct NntpAccountData *adata)
Get login, password and authenticate.
Definition nntp.c:453
static int nntp_capabilities(struct NntpAccountData *adata)
Get capabilities.
Definition nntp.c:136
static int nntp_connect_error(struct NntpAccountData *adata)
Signal a failed connection.
Definition nntp.c:122
static int nntp_attempt_features(struct NntpAccountData *adata)
Detect supported commands.
Definition nntp.c:255
@ 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:384
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition socket.c:100
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
#define mutt_socket_readln(buf, buflen, conn)
Definition socket.h:55
#define mutt_socket_send(conn, buf)
Definition socket.h:56
char user[128]
Username.
Definition connaccount.h:62
char host[128]
Server to login to.
Definition connaccount.h:60
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition connaccount.h:66
unsigned int status
Connection status.
Definition adata.h:47
bool hasCAPABILITIES
Server supports CAPABILITIES command.
Definition adata.h:37
bool hasSTARTTLS
Server supports STARTTLS command.
Definition adata.h:38
unsigned int use_tls
Use TLS.
Definition adata.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function: