NeoMutt  2022-04-29-70-g0c028c
Teaching an old dog new tricks
DOXYGEN
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. More...
 
int nntp_active_save_cache (struct NntpAccountData *adata)
 Save list of all newsgroups to cache. More...
 
int nntp_add_group (char *line, void *data)
 Parse newsgroup. More...
 
void nntp_article_status (struct Mailbox *m, struct Email *e, char *group, anum_t anum)
 Get status of articles from .newsrc. More...
 
void nntp_bcache_update (struct NntpMboxData *mdata)
 Remove stale cached messages. More...
 
int nntp_check_new_groups (struct Mailbox *m, struct NntpAccountData *adata)
 Check for new groups/articles in subscribed groups. More...
 
void nntp_delete_group_cache (struct NntpMboxData *mdata)
 Remove hcache and bcache of newsgroup. More...
 
void nntp_group_unread_stat (struct NntpMboxData *mdata)
 Count number of unread articles using .newsrc data. More...
 
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 -. More...
 
struct HeaderCachenntp_hcache_open (struct NntpMboxData *mdata)
 Open newsgroup hcache. More...
 
void nntp_hcache_update (struct NntpMboxData *mdata, struct HeaderCache *hc)
 Remove stale cached headers. More...
 
void nntp_newsrc_gen_entries (struct Mailbox *m)
 Generate array of .newsrc entries. More...
 
int nntp_open_connection (struct NntpAccountData *adata)
 Connect to server, authenticate and get capabilities. More...
 

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 102 of file newsrc.c.

103 {
104  for (int i = 0; i < NNTP_ACACHE_LEN; i++)
105  {
106  if (mdata->acache[i].path)
107  {
108  unlink(mdata->acache[i].path);
109  FREE(&mdata->acache[i].path);
110  }
111  }
112 }
#define FREE(x)
Definition: memory.h:40
#define NNTP_ACACHE_LEN
Definition: lib.h:82
char * path
Cache path.
Definition: lib.h:69
struct NntpAcache acache[NNTP_ACACHE_LEN]
Definition: mdata.h:48
+ 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 652 of file newsrc.c.

653 {
654  if (!adata->cacheable)
655  return 0;
656 
657  size_t buflen = 10240;
658  char *buf = mutt_mem_calloc(1, buflen);
659  snprintf(buf, buflen, "%lu\n", (unsigned long) adata->newgroups_time);
660  size_t off = strlen(buf);
661 
662  for (unsigned int i = 0; i < adata->groups_num; i++)
663  {
664  struct NntpMboxData *mdata = adata->groups_list[i];
665 
666  if (!mdata || mdata->deleted)
667  continue;
668 
669  if ((off + strlen(mdata->group) + (mdata->desc ? strlen(mdata->desc) : 0) + 50) > buflen)
670  {
671  buflen *= 2;
672  mutt_mem_realloc(&buf, buflen);
673  }
674  snprintf(buf + off, buflen - off, "%s %u %u %c%s%s\n", mdata->group,
675  mdata->last_message, mdata->first_message, mdata->allowed ? 'y' : 'n',
676  mdata->desc ? " " : "", mdata->desc ? mdata->desc : "");
677  off += strlen(buf + off);
678  }
679 
680  char file[PATH_MAX];
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: logging.h:84
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define PATH_MAX
Definition: mutt.h:40
static int update_file(char *filename, char *buf)
Update file with new contents.
Definition: newsrc.c:392
static void cache_expand(char *dst, size_t dstlen, struct ConnAccount *cac, const char *src)
Make fully qualified cache file name.
Definition: newsrc.c:521
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
void * mdata
Driver specific data.
Definition: mailbox.h:133
time_t newgroups_time
Definition: adata.h:57
struct Connection * conn
Connection to NNTP Server.
Definition: adata.h:63
unsigned int groups_num
Definition: adata.h:59
void ** groups_list
Definition: adata.h:61
bool cacheable
Definition: adata.h:49
NNTP-specific Mailbox data -.
Definition: mdata.h:33
struct NntpAccountData * adata
Definition: mdata.h:47
+ 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 577 of file newsrc.c.

578 {
579  struct NntpAccountData *adata = data;
580  struct NntpMboxData *mdata = NULL;
581  char group[1024] = { 0 };
582  char desc[8192] = { 0 };
583  char mod;
584  anum_t first, last;
585 
586  if (!adata || !line)
587  return 0;
588 
589  /* These sscanf limits must match the sizes of the group and desc arrays */
590  if (sscanf(line, "%1023s " ANUM " " ANUM " %c %8191[^\n]", group, &last,
591  &first, &mod, desc) < 4)
592  {
593  mutt_debug(LL_DEBUG2, "Can't parse server line: %s\n", line);
594  return 0;
595  }
596 
598  mdata->deleted = false;
599  mdata->first_message = first;
600  mdata->last_message = last;
601  mdata->allowed = (mod == 'y') || (mod == 'm');
602  mutt_str_replace(&mdata->desc, desc);
603  if (mdata->newsrc_ent || (mdata->last_cached != 0))
605  else if (mdata->last_message && (mdata->first_message <= mdata->last_message))
606  mdata->unread = mdata->last_message - mdata->first_message + 1;
607  else
608  mdata->unread = 0;
609  return 0;
610 }
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
void nntp_group_unread_stat(struct NntpMboxData *mdata)
Count number of unread articles using .newsrc data.
Definition: newsrc.c:132
static struct NntpMboxData * mdata_find(struct NntpAccountData *adata, const char *group)
Find NntpMboxData for given newsgroup or add it.
Definition: newsrc.c:72
#define ANUM
Definition: lib.h:61
#define anum_t
Definition: lib.h:60
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
NNTP-specific Account data -.
Definition: adata.h:37
char * group
Name of newsgroup.
Definition: mdata.h:34
char * desc
Description of newsgroup.
Definition: mdata.h:35
+ 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 1233 of file newsrc.c.

1234 {
1235  struct NntpMboxData *mdata = m->mdata;
1236 
1237  if (group)
1238  mdata = mutt_hash_find(mdata->adata->groups_hash, group);
1239 
1240  if (!mdata)
1241  return;
1242 
1243  for (unsigned int i = 0; i < mdata->newsrc_len; i++)
1244  {
1245  if ((anum >= mdata->newsrc_ent[i].first) && (anum <= mdata->newsrc_ent[i].last))
1246  {
1247  /* can't use mutt_set_flag() because mview_update() didn't get called yet */
1248  e->read = true;
1249  return;
1250  }
1251  }
1252 
1253  /* article was not cached yet, it's new */
1254  if (anum > mdata->last_cached)
1255  return;
1256 
1257  /* article isn't read but cached, it's old */
1258  const bool c_mark_old = cs_subset_bool(NeoMutt->sub, "mark_old");
1259  if (c_mark_old)
1260  e->old = true;
1261 }
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:362
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
bool read
Email is read.
Definition: email.h:48
bool old
Email is seen, but unread.
Definition: email.h:47
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
anum_t last
Last article number in run.
Definition: lib.h:78
struct NewsrcEntry * newsrc_ent
Definition: mdata.h:46
+ 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 803 of file newsrc.c.

804 {
806 }
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
Definition: bcache.c:330
static int nntp_bcache_delete(const char *id, struct BodyCache *bcache, void *data)
Remove bcache file - Implements bcache_list_t -.
Definition: newsrc.c:783
struct BodyCache * bcache
Definition: mdata.h:49
+ Here is the call 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 2022 of file nntp.c.

2023 {
2024  struct NntpMboxData tmp_mdata = { 0 };
2025  time_t now;
2026  char buf[1024];
2027  char *msg = _("Checking for new newsgroups...");
2028  unsigned int i;
2029  int rc, update_active = false;
2030 
2031  if (!adata || !adata->newgroups_time)
2032  return -1;
2033 
2034  /* check subscribed newsgroups for new articles */
2035  const bool c_show_new_news = cs_subset_bool(NeoMutt->sub, "show_new_news");
2036  if (c_show_new_news)
2037  {
2038  mutt_message(_("Checking for new messages..."));
2039  for (i = 0; i < adata->groups_num; i++)
2040  {
2041  struct NntpMboxData *mdata = adata->groups_list[i];
2042 
2043  if (mdata && mdata->subscribed)
2044  {
2045  rc = nntp_group_poll(mdata, true);
2046  if (rc < 0)
2047  return -1;
2048  if (rc > 0)
2049  update_active = true;
2050  }
2051  }
2052  }
2053  else if (adata->newgroups_time)
2054  return 0;
2055 
2056  /* get list of new groups */
2057  mutt_message(msg);
2058  if (nntp_date(adata, &now) < 0)
2059  return -1;
2060  tmp_mdata.adata = adata;
2061  if (m && m->mdata)
2062  tmp_mdata.group = ((struct NntpMboxData *) m->mdata)->group;
2063  else
2064  tmp_mdata.group = NULL;
2065  i = adata->groups_num;
2066  struct tm tm = mutt_date_gmtime(adata->newgroups_time);
2067  snprintf(buf, sizeof(buf), "NEWGROUPS %02d%02d%02d %02d%02d%02d GMT\r\n",
2068  tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
2069  rc = nntp_fetch_lines(&tmp_mdata, buf, sizeof(buf), msg, nntp_add_group, adata);
2070  if (rc)
2071  {
2072  if (rc > 0)
2073  {
2074  mutt_error("NEWGROUPS: %s", buf);
2075  }
2076  return -1;
2077  }
2078 
2079  /* new groups found */
2080  rc = 0;
2081  if (adata->groups_num != i)
2082  {
2083  int groups_num = i;
2084 
2085  adata->newgroups_time = now;
2086  for (; i < adata->groups_num; i++)
2087  {
2088  struct NntpMboxData *mdata = adata->groups_list[i];
2089  mdata->has_new_mail = true;
2090  }
2091 
2092  /* loading descriptions */
2093  const bool c_nntp_load_description = cs_subset_bool(NeoMutt->sub, "nntp_load_description");
2094  if (c_nntp_load_description)
2095  {
2096  unsigned int count = 0;
2097  struct Progress *progress = progress_new(_("Loading descriptions..."), MUTT_PROGRESS_READ,
2098  adata->groups_num - i);
2099 
2100  for (i = groups_num; i < adata->groups_num; i++)
2101  {
2102  struct NntpMboxData *mdata = adata->groups_list[i];
2103 
2104  if (get_description(mdata, NULL, NULL) < 0)
2105  {
2106  progress_free(&progress);
2107  return -1;
2108  }
2109  progress_update(progress, ++count, -1);
2110  }
2111  progress_free(&progress);
2112  }
2113  update_active = true;
2114  rc = 1;
2115  }
2116  if (update_active)
2118  mutt_clear_error();
2119  return rc;
2120 }
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone.
Definition: date.c:672
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define _(a)
Definition: message.h:28
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
int nntp_add_group(char *line, void *data)
Parse newsgroup.
Definition: newsrc.c:577
int nntp_active_save_cache(struct NntpAccountData *adata)
Save list of all newsgroups to cache.
Definition: newsrc.c:652
static int nntp_date(struct NntpAccountData *adata, time_t *now)
Get date and time from server.
Definition: nntp.c:1639
static int nntp_group_poll(struct NntpMboxData *mdata, bool update_stat)
Check newsgroup for new articles.
Definition: nntp.c:1383
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:763
static int get_description(struct NntpMboxData *mdata, const char *wildmat, const char *msg)
Fetch newsgroups descriptions.
Definition: nntp.c:879
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc
Definition: lib.h:46
void progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:176
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:231
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:251
A Progress Bar.
Definition: progress.c:48
+ 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 812 of file newsrc.c.

813 {
814  if (!mdata || !mdata->adata || !mdata->adata->cacheable)
815  return;
816 
817 #ifdef USE_HCACHE
818  struct Buffer file = mutt_buffer_make(PATH_MAX);
819  nntp_hcache_namer(mdata->group, &file);
820  cache_expand(file.data, file.dsize, &mdata->adata->conn->account,
821  mutt_buffer_string(&file));
822  unlink(mutt_buffer_string(&file));
823  mdata->last_cached = 0;
824  mutt_debug(LL_DEBUG2, "%s\n", mutt_buffer_string(&file));
825  mutt_buffer_dealloc(&file);
826 #endif
827 
828  if (!mdata->bcache)
829  {
830  mdata->bcache = mutt_bcache_open(&mdata->adata->conn->account, mdata->group);
831  }
832  if (mdata->bcache)
833  {
834  mutt_debug(LL_DEBUG2, "%s/*\n", mdata->group);
836  mutt_bcache_close(&mdata->bcache);
837  }
838 }
struct BodyCache * mutt_bcache_open(struct ConnAccount *account, const char *mailbox)
Open an Email-Body Cache.
Definition: bcache.c:144
void mutt_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
Definition: bcache.c:165
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
static void nntp_hcache_namer(const char *path, struct Buffer *dest)
Compose hcache file names - Implements hcache_namer_t -.
Definition: newsrc.c:692
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
anum_t last_cached
Definition: mdata.h:39
+ 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 132 of file newsrc.c.

133 {
134  mdata->unread = 0;
135  if ((mdata->last_message == 0) ||
136  (mdata->first_message > mdata->last_message) || !mdata->newsrc_ent)
137  {
138  return;
139  }
140 
141  mdata->unread = mdata->last_message - mdata->first_message + 1;
142  for (unsigned int i = 0; i < mdata->newsrc_len; i++)
143  {
144  anum_t first = mdata->newsrc_ent[i].first;
145  if (first < mdata->first_message)
146  first = mdata->first_message;
147  anum_t last = mdata->newsrc_ent[i].last;
148  if (last > mdata->last_message)
149  last = mdata->last_message;
150  if (first <= last)
151  mdata->unread -= last - first + 1;
152  }
153 }
anum_t first
First article number in run.
Definition: lib.h:77
anum_t last_message
Definition: mdata.h:37
anum_t unread
Definition: mdata.h:40
unsigned int newsrc_len
Definition: mdata.h:45
anum_t first_message
Definition: mdata.h:36
+ 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 711 of file newsrc.c.

712 {
713  struct Url url = { 0 };
714  char file[PATH_MAX];
715 
716  const bool c_save_unsubscribed = cs_subset_bool(NeoMutt->sub, "save_unsubscribed");
717  if (!mdata->adata || !mdata->adata->cacheable || !mdata->adata->conn || !mdata->group ||
718  !(mdata->newsrc_ent || mdata->subscribed || c_save_unsubscribed))
719  {
720  return NULL;
721  }
722 
723  mutt_account_tourl(&mdata->adata->conn->account, &url);
724  url.path = mdata->group;
725  url_tostring(&url, file, sizeof(file), U_PATH);
726  const char *const c_news_cache_dir = cs_subset_path(NeoMutt->sub, "news_cache_dir");
727  return mutt_hcache_open(c_news_cache_dir, file, nntp_hcache_namer);
728 }
struct HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:332
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
bool subscribed
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_tostring(struct Url *url, char *dest, size_t len, uint8_t flags)
Output the URL string for a given Url object.
Definition: url.c:418
#define U_PATH
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 735 of file newsrc.c.

736 {
737  if (!hc)
738  return;
739 
740  char buf[32];
741  bool old = false;
742  anum_t first = 0, last = 0;
743 
744  /* fetch previous values of first and last */
745  size_t dlen = 0;
746  void *hdata = mutt_hcache_fetch_raw(hc, "index", 5, &dlen);
747  if (hdata)
748  {
749  mutt_debug(LL_DEBUG2, "mutt_hcache_fetch index: %s\n", (char *) hdata);
750  if (sscanf(hdata, ANUM " " ANUM, &first, &last) == 2)
751  {
752  old = true;
753  mdata->last_cached = last;
754 
755  /* clean removed headers from cache */
756  for (anum_t current = first; current <= last; current++)
757  {
758  if ((current >= mdata->first_message) && (current <= mdata->last_message))
759  continue;
760 
761  snprintf(buf, sizeof(buf), "%u", current);
762  mutt_debug(LL_DEBUG2, "mutt_hcache_delete_record %s\n", buf);
763  mutt_hcache_delete_record(hc, buf, strlen(buf));
764  }
765  }
766  mutt_hcache_free_raw(hc, &hdata);
767  }
768 
769  /* store current values of first and last */
770  if (!old || (mdata->first_message != first) || (mdata->last_message != last))
771  {
772  snprintf(buf, sizeof(buf), "%u %u", mdata->first_message, mdata->last_message);
773  mutt_debug(LL_DEBUG2, "mutt_hcache_store index: %s\n", buf);
774  mutt_hcache_store_raw(hc, "index", 5, buf, strlen(buf) + 1);
775  }
776 }
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:627
int mutt_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:606
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:534
void * mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message's header from the cache.
Definition: hcache.c:515
+ Here is the call 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 299 of file newsrc.c.

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

1707 {
1708  struct Connection *conn = adata->conn;
1709  char buf[256];
1710  int cap;
1711  bool posting = false, auth = true;
1712 
1713  if (adata->status == NNTP_OK)
1714  return 0;
1715  if (adata->status == NNTP_BYE)
1716  return -1;
1717  adata->status = NNTP_NONE;
1718 
1719  if (mutt_socket_open(conn) < 0)
1720  return -1;
1721 
1722  if (mutt_socket_readln(buf, sizeof(buf), conn) < 0)
1723  return nntp_connect_error(adata);
1724 
1725  if (mutt_str_startswith(buf, "200"))
1726  posting = true;
1727  else if (!mutt_str_startswith(buf, "201"))
1728  {
1729  mutt_socket_close(conn);
1731  mutt_error("%s", buf);
1732  return -1;
1733  }
1734 
1735  /* get initial capabilities */
1736  cap = nntp_capabilities(adata);
1737  if (cap < 0)
1738  return -1;
1739 
1740  /* tell news server to switch to mode reader if it isn't so */
1741  if (cap > 0)
1742  {
1743  if ((mutt_socket_send(conn, "MODE READER\r\n") < 0) ||
1744  (mutt_socket_readln(buf, sizeof(buf), conn) < 0))
1745  {
1746  return nntp_connect_error(adata);
1747  }
1748 
1749  if (mutt_str_startswith(buf, "200"))
1750  posting = true;
1751  else if (mutt_str_startswith(buf, "201"))
1752  posting = false;
1753  /* error if has capabilities, ignore result if no capabilities */
1754  else if (adata->hasCAPABILITIES)
1755  {
1756  mutt_socket_close(conn);
1757  mutt_error(_("Could not switch to reader mode"));
1758  return -1;
1759  }
1760 
1761  /* recheck capabilities after MODE READER */
1762  if (adata->hasCAPABILITIES)
1763  {
1764  cap = nntp_capabilities(adata);
1765  if (cap < 0)
1766  return -1;
1767  }
1768  }
1769 
1770  mutt_message(_("Connected to %s. %s"), conn->account.host,
1771  posting ? _("Posting is ok") : _("Posting is NOT ok"));
1772  mutt_sleep(1);
1773 
1774 #ifdef USE_SSL
1775  /* Attempt STARTTLS if available and desired. */
1776  const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
1777  if ((adata->use_tls != 1) && (adata->hasSTARTTLS || c_ssl_force_tls))
1778  {
1779  if (adata->use_tls == 0)
1780  {
1781  const enum QuadOption c_ssl_starttls = cs_subset_quad(NeoMutt->sub, "ssl_starttls");
1782  adata->use_tls = c_ssl_force_tls ||
1783  (query_quadoption(c_ssl_starttls,
1784  _("Secure connection with TLS?")) == MUTT_YES) ?
1785  2 :
1786  1;
1787  }
1788  if (adata->use_tls == 2)
1789  {
1790  if ((mutt_socket_send(conn, "STARTTLS\r\n") < 0) ||
1791  (mutt_socket_readln(buf, sizeof(buf), conn) < 0))
1792  {
1793  return nntp_connect_error(adata);
1794  }
1795  // Clear any data after the STARTTLS acknowledgement
1796  mutt_socket_empty(conn);
1797  if (!mutt_str_startswith(buf, "382"))
1798  {
1799  adata->use_tls = 0;
1800  mutt_error("STARTTLS: %s", buf);
1801  }
1802  else if (mutt_ssl_starttls(conn))
1803  {
1804  adata->use_tls = 0;
1805  adata->status = NNTP_NONE;
1806  mutt_socket_close(adata->conn);
1807  mutt_error(_("Could not negotiate TLS connection"));
1808  return -1;
1809  }
1810  else
1811  {
1812  /* recheck capabilities after STARTTLS */
1813  cap = nntp_capabilities(adata);
1814  if (cap < 0)
1815  return -1;
1816  }
1817  }
1818  }
1819 #endif
1820 
1821  /* authentication required? */
1822  if (conn->account.flags & MUTT_ACCT_USER)
1823  {
1824  if (!conn->account.user[0])
1825  auth = false;
1826  }
1827  else
1828  {
1829  if ((mutt_socket_send(conn, "STAT\r\n") < 0) ||
1830  (mutt_socket_readln(buf, sizeof(buf), conn) < 0))
1831  {
1832  return nntp_connect_error(adata);
1833  }
1834  if (!mutt_str_startswith(buf, "480"))
1835  auth = false;
1836  }
1837 
1838  /* authenticate */
1839  if (auth && (nntp_auth(adata) < 0))
1840  return -1;
1841 
1842  /* get final capabilities after authentication */
1843  if (adata->hasCAPABILITIES && (auth || (cap > 0)))
1844  {
1845  cap = nntp_capabilities(adata);
1846  if (cap < 0)
1847  return -1;
1848  if (cap > 0)
1849  {
1850  mutt_socket_close(conn);
1851  mutt_error(_("Could not switch to reader mode"));
1852  return -1;
1853  }
1854  }
1855 
1856  /* attempt features */
1857  if (nntp_attempt_features(adata) < 0)
1858  return -1;
1859 
1860  adata->status = NNTP_OK;
1861  return 0;
1862 }
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:44
int mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
Definition: gnutls.c:1143
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:613
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1454
static int nntp_auth(struct NntpAccountData *adata)
Get login, password and authenticate.
Definition: nntp.c:426
static int nntp_capabilities(struct NntpAccountData *adata)
Get capabilities.
Definition: nntp.c:140
static int nntp_connect_error(struct NntpAccountData *adata)
Signal a failed connection.
Definition: nntp.c:126
static int nntp_attempt_features(struct NntpAccountData *adata)
Detect supported commands.
Definition: nntp.c:243
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:386
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:97
void mutt_socket_empty(struct Connection *conn)
Clear out any queued data.
Definition: socket.c:313
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:76
#define mutt_socket_readln(buf, buflen, conn)
Definition: socket.h:57
#define mutt_socket_send(conn, buf)
Definition: socket.h:58
char user[128]
Username.
Definition: connaccount.h:56
char host[128]
Server to login to.
Definition: connaccount.h:54
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:60
unsigned int status
Definition: adata.h:48
bool hasCAPABILITIES
Server supports CAPABILITIES command.
Definition: adata.h:38
bool hasSTARTTLS
Server supports STARTTLS command.
Definition: adata.h:39
unsigned int use_tls
Definition: adata.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function: