NeoMutt  2021-10-29-43-g6b8931
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 103 of file newsrc.c.

104 {
105  for (int i = 0; i < NNTP_ACACHE_LEN; i++)
106  {
107  if (mdata->acache[i].path)
108  {
109  unlink(mdata->acache[i].path);
110  FREE(&mdata->acache[i].path);
111  }
112  }
113 }
#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:390
static void cache_expand(char *dst, size_t dstlen, struct ConnAccount *cac, const char *src)
Make fully qualified cache file name.
Definition: newsrc.c:519
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
void * mdata
Driver specific data.
Definition: mailbox.h:136
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 576 of file newsrc.c.

577 {
578  struct NntpAccountData *adata = data;
579  struct NntpMboxData *mdata = NULL;
580  char group[1024] = { 0 };
581  char desc[8192] = { 0 };
582  char mod;
583  anum_t first, last;
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 " " ANUM " %c %8191[^\n]", group, &last,
590  &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: logging.h:41
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:257
void nntp_group_unread_stat(struct NntpMboxData *mdata)
Count number of unread articles using .newsrc data.
Definition: newsrc.c:133
static struct NntpMboxData * mdata_find(struct NntpAccountData *adata, const char *group)
Find NntpMboxData for given newsgroup or add it.
Definition: newsrc.c:73
#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 1221 of file newsrc.c.

1222 {
1223  struct NntpMboxData *mdata = m->mdata;
1224 
1225  if (group)
1226  mdata = mutt_hash_find(mdata->adata->groups_hash, group);
1227 
1228  if (!mdata)
1229  return;
1230 
1231  for (unsigned int i = 0; i < mdata->newsrc_len; i++)
1232  {
1233  if ((anum >= mdata->newsrc_ent[i].first) && (anum <= mdata->newsrc_ent[i].last))
1234  {
1235  /* can't use mutt_set_flag() because ctx_update() didn't get called yet */
1236  e->read = true;
1237  return;
1238  }
1239  }
1240 
1241  /* article was not cached yet, it's new */
1242  if (anum > mdata->last_cached)
1243  return;
1244 
1245  /* article isn't read but cached, it's old */
1246  const bool c_mark_old = cs_subset_bool(NeoMutt->sub, "mark_old");
1247  if (c_mark_old)
1248  e->old = true;
1249 }
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 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:329
static int nntp_bcache_delete(const char *id, struct BodyCache *bcache, void *data)
Remove bcache file - Implements bcache_list_t -.
Definition: newsrc.c:785
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 2032 of file nntp.c.

2033 {
2034  struct NntpMboxData tmp_mdata = { 0 };
2035  time_t now;
2036  char buf[1024];
2037  char *msg = _("Checking for new newsgroups...");
2038  unsigned int i;
2039  int rc, update_active = false;
2040 
2041  if (!adata || !adata->newgroups_time)
2042  return -1;
2043 
2044  /* check subscribed newsgroups for new articles */
2045  const bool c_show_new_news = cs_subset_bool(NeoMutt->sub, "show_new_news");
2046  if (c_show_new_news)
2047  {
2048  mutt_message(_("Checking for new messages..."));
2049  for (i = 0; i < adata->groups_num; i++)
2050  {
2051  struct NntpMboxData *mdata = adata->groups_list[i];
2052 
2053  if (mdata && mdata->subscribed)
2054  {
2055  rc = nntp_group_poll(mdata, true);
2056  if (rc < 0)
2057  return -1;
2058  if (rc > 0)
2059  update_active = true;
2060  }
2061  }
2062  }
2063  else if (adata->newgroups_time)
2064  return 0;
2065 
2066  /* get list of new groups */
2067  mutt_message(msg);
2068  if (nntp_date(adata, &now) < 0)
2069  return -1;
2070  tmp_mdata.adata = adata;
2071  if (m && m->mdata)
2072  tmp_mdata.group = ((struct NntpMboxData *) m->mdata)->group;
2073  else
2074  tmp_mdata.group = NULL;
2075  i = adata->groups_num;
2076  struct tm tm = mutt_date_gmtime(adata->newgroups_time);
2077  snprintf(buf, sizeof(buf), "NEWGROUPS %02d%02d%02d %02d%02d%02d GMT\r\n",
2078  tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
2079  rc = nntp_fetch_lines(&tmp_mdata, buf, sizeof(buf), msg, nntp_add_group, adata);
2080  if (rc)
2081  {
2082  if (rc > 0)
2083  {
2084  mutt_error("NEWGROUPS: %s", buf);
2085  }
2086  return -1;
2087  }
2088 
2089  /* new groups found */
2090  rc = 0;
2091  if (adata->groups_num != i)
2092  {
2093  int groups_num = i;
2094 
2095  adata->newgroups_time = now;
2096  for (; i < adata->groups_num; i++)
2097  {
2098  struct NntpMboxData *mdata = adata->groups_list[i];
2099  mdata->has_new_mail = true;
2100  }
2101 
2102  /* loading descriptions */
2103  const bool c_nntp_load_description =
2104  cs_subset_bool(NeoMutt->sub, "nntp_load_description");
2105  if (c_nntp_load_description)
2106  {
2107  unsigned int count = 0;
2108  struct Progress *progress = progress_new(
2109  _("Loading descriptions..."), MUTT_PROGRESS_READ, adata->groups_num - i);
2110 
2111  for (i = groups_num; i < adata->groups_num; i++)
2112  {
2113  struct NntpMboxData *mdata = adata->groups_list[i];
2114 
2115  if (get_description(mdata, NULL, NULL) < 0)
2116  {
2117  progress_free(&progress);
2118  return -1;
2119  }
2120  progress_update(progress, ++count, -1);
2121  }
2122  progress_free(&progress);
2123  }
2124  update_active = true;
2125  rc = 1;
2126  }
2127  if (update_active)
2129  mutt_clear_error();
2130  return rc;
2131 }
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:113
int nntp_add_group(char *line, void *data)
Parse newsgroup.
Definition: newsrc.c:576
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:1645
static int nntp_group_poll(struct NntpMboxData *mdata, bool update_stat)
Check newsgroup for new articles.
Definition: nntp.c:1388
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:768
static int get_description(struct NntpMboxData *mdata, const char *wildmat, const char *msg)
Fetch newsgroups descriptions.
Definition: nntp.c:884
@ 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:177
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:232
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:252
A Progress Bar.
Definition: progress.c:49
+ 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  struct Buffer file = mutt_buffer_make(PATH_MAX);
821  nntp_hcache_namer(mdata->group, &file);
822  cache_expand(file.data, file.dsize, &mdata->adata->conn->account,
823  mutt_buffer_string(&file));
824  unlink(mutt_buffer_string(&file));
825  mdata->last_cached = 0;
826  mutt_debug(LL_DEBUG2, "%s\n", mutt_buffer_string(&file));
827  mutt_buffer_dealloc(&file);
828 #endif
829 
830  if (!mdata->bcache)
831  {
832  mdata->bcache = mutt_bcache_open(&mdata->adata->conn->account, mdata->group);
833  }
834  if (mdata->bcache)
835  {
836  mutt_debug(LL_DEBUG2, "%s/*\n", mdata->group);
838  mutt_bcache_close(&mdata->bcache);
839  }
840 }
struct BodyCache * mutt_bcache_open(struct ConnAccount *account, const char *mailbox)
Open an Email-Body Cache.
Definition: bcache.c:143
void mutt_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
Definition: bcache.c:164
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 133 of file newsrc.c.

134 {
135  mdata->unread = 0;
136  if ((mdata->last_message == 0) ||
137  (mdata->first_message > mdata->last_message) || !mdata->newsrc_ent)
138  {
139  return;
140  }
141 
142  mdata->unread = mdata->last_message - mdata->first_message + 1;
143  for (unsigned int i = 0; i < mdata->newsrc_len; i++)
144  {
145  anum_t first = mdata->newsrc_ent[i].first;
146  if (first < mdata->first_message)
147  first = mdata->first_message;
148  anum_t last = mdata->newsrc_ent[i].last;
149  if (last > mdata->last_message)
150  last = mdata->last_message;
151  if (first <= last)
152  mdata->unread -= last - first + 1;
153  }
154 }
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 =
717  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  mutt_account_tourl(&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 =
728  cs_subset_path(NeoMutt->sub, "news_cache_dir");
729  return mutt_hcache_open(c_news_cache_dir, file, nntp_hcache_namer);
730 }
struct HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:334
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 737 of file newsrc.c.

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

298 {
299  if (!m)
300  return;
301 
302  struct NntpMboxData *mdata = m->mdata;
303  anum_t last = 0, first = 1;
304  bool series;
305  unsigned int entries;
306 
307  const short c_sort = cs_subset_sort(NeoMutt->sub, "sort");
308  if (c_sort != SORT_ORDER)
309  {
312  }
313 
314  entries = mdata->newsrc_len;
315  if (!entries)
316  {
317  entries = 5;
318  mdata->newsrc_ent = mutt_mem_calloc(entries, sizeof(struct NewsrcEntry));
319  }
320 
321  /* Set up to fake initial sequence from 1 to the article before the
322  * first article in our list */
323  mdata->newsrc_len = 0;
324  series = true;
325  for (int i = 0; i < m->msg_count; i++)
326  {
327  struct Email *e = m->emails[i];
328  if (!e)
329  break;
330 
331  /* search for first unread */
332  if (series)
333  {
334  /* We don't actually check sequential order, since we mark
335  * "missing" entries as read/deleted */
336  last = nntp_edata_get(e)->article_num;
337  if ((last >= mdata->first_message) && !e->deleted && !e->read)
338  {
339  if (mdata->newsrc_len >= entries)
340  {
341  entries *= 2;
342  mutt_mem_realloc(&mdata->newsrc_ent, entries * sizeof(struct NewsrcEntry));
343  }
344  mdata->newsrc_ent[mdata->newsrc_len].first = first;
345  mdata->newsrc_ent[mdata->newsrc_len].last = last - 1;
346  mdata->newsrc_len++;
347  series = false;
348  }
349  }
350 
351  /* search for first read */
352  else
353  {
354  if (e->deleted || e->read)
355  {
356  first = last + 1;
357  series = true;
358  }
359  last = nntp_edata_get(e)->article_num;
360  }
361  }
362 
363  if (series && (first <= mdata->last_loaded))
364  {
365  if (mdata->newsrc_len >= entries)
366  {
367  entries++;
368  mutt_mem_realloc(&mdata->newsrc_ent, entries * sizeof(struct NewsrcEntry));
369  }
370  mdata->newsrc_ent[mdata->newsrc_len].first = first;
371  mdata->newsrc_ent[mdata->newsrc_len].last = mdata->last_loaded;
372  mdata->newsrc_len++;
373  }
374  mutt_mem_realloc(&mdata->newsrc_ent, mdata->newsrc_len * sizeof(struct NewsrcEntry));
375 
376  if (c_sort != SORT_ORDER)
377  {
378  cs_subset_str_native_set(NeoMutt->sub, "sort", c_sort, NULL);
380  }
381 }
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:211
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:181
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:91
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
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 1712 of file nntp.c.

1713 {
1714  struct Connection *conn = adata->conn;
1715  char buf[256];
1716  int cap;
1717  bool posting = false, auth = true;
1718 
1719  if (adata->status == NNTP_OK)
1720  return 0;
1721  if (adata->status == NNTP_BYE)
1722  return -1;
1723  adata->status = NNTP_NONE;
1724 
1725  if (mutt_socket_open(conn) < 0)
1726  return -1;
1727 
1728  if (mutt_socket_readln(buf, sizeof(buf), conn) < 0)
1729  return nntp_connect_error(adata);
1730 
1731  if (mutt_str_startswith(buf, "200"))
1732  posting = true;
1733  else if (!mutt_str_startswith(buf, "201"))
1734  {
1735  mutt_socket_close(conn);
1737  mutt_error("%s", buf);
1738  return -1;
1739  }
1740 
1741  /* get initial capabilities */
1742  cap = nntp_capabilities(adata);
1743  if (cap < 0)
1744  return -1;
1745 
1746  /* tell news server to switch to mode reader if it isn't so */
1747  if (cap > 0)
1748  {
1749  if ((mutt_socket_send(conn, "MODE READER\r\n") < 0) ||
1750  (mutt_socket_readln(buf, sizeof(buf), conn) < 0))
1751  {
1752  return nntp_connect_error(adata);
1753  }
1754 
1755  if (mutt_str_startswith(buf, "200"))
1756  posting = true;
1757  else if (mutt_str_startswith(buf, "201"))
1758  posting = false;
1759  /* error if has capabilities, ignore result if no capabilities */
1760  else if (adata->hasCAPABILITIES)
1761  {
1762  mutt_socket_close(conn);
1763  mutt_error(_("Could not switch to reader mode"));
1764  return -1;
1765  }
1766 
1767  /* recheck capabilities after MODE READER */
1768  if (adata->hasCAPABILITIES)
1769  {
1770  cap = nntp_capabilities(adata);
1771  if (cap < 0)
1772  return -1;
1773  }
1774  }
1775 
1776  mutt_message(_("Connected to %s. %s"), conn->account.host,
1777  posting ? _("Posting is ok") : _("Posting is NOT ok"));
1778  mutt_sleep(1);
1779 
1780 #ifdef USE_SSL
1781  /* Attempt STARTTLS if available and desired. */
1782  const bool c_ssl_force_tls = cs_subset_bool(NeoMutt->sub, "ssl_force_tls");
1783  if ((adata->use_tls != 1) && (adata->hasSTARTTLS || c_ssl_force_tls))
1784  {
1785  if (adata->use_tls == 0)
1786  {
1787  const enum QuadOption c_ssl_starttls =
1788  cs_subset_quad(NeoMutt->sub, "ssl_starttls");
1789  adata->use_tls =
1790  c_ssl_force_tls ||
1791  (query_quadoption(c_ssl_starttls,
1792  _("Secure connection with TLS?")) == MUTT_YES) ?
1793  2 :
1794  1;
1795  }
1796  if (adata->use_tls == 2)
1797  {
1798  if ((mutt_socket_send(conn, "STARTTLS\r\n") < 0) ||
1799  (mutt_socket_readln(buf, sizeof(buf), conn) < 0))
1800  {
1801  return nntp_connect_error(adata);
1802  }
1803  // Clear any data after the STARTTLS acknowledgement
1804  mutt_socket_empty(conn);
1805  if (!mutt_str_startswith(buf, "382"))
1806  {
1807  adata->use_tls = 0;
1808  mutt_error("STARTTLS: %s", buf);
1809  }
1810  else if (mutt_ssl_starttls(conn))
1811  {
1812  adata->use_tls = 0;
1813  adata->status = NNTP_NONE;
1814  mutt_socket_close(adata->conn);
1815  mutt_error(_("Could not negotiate TLS connection"));
1816  return -1;
1817  }
1818  else
1819  {
1820  /* recheck capabilities after STARTTLS */
1821  cap = nntp_capabilities(adata);
1822  if (cap < 0)
1823  return -1;
1824  }
1825  }
1826  }
1827 #endif
1828 
1829  /* authentication required? */
1830  if (conn->account.flags & MUTT_ACCT_USER)
1831  {
1832  if (!conn->account.user[0])
1833  auth = false;
1834  }
1835  else
1836  {
1837  if ((mutt_socket_send(conn, "STAT\r\n") < 0) ||
1838  (mutt_socket_readln(buf, sizeof(buf), conn) < 0))
1839  {
1840  return nntp_connect_error(adata);
1841  }
1842  if (!mutt_str_startswith(buf, "480"))
1843  auth = false;
1844  }
1845 
1846  /* authenticate */
1847  if (auth && (nntp_auth(adata) < 0))
1848  return -1;
1849 
1850  /* get final capabilities after authentication */
1851  if (adata->hasCAPABILITIES && (auth || (cap > 0)))
1852  {
1853  cap = nntp_capabilities(adata);
1854  if (cap < 0)
1855  return -1;
1856  if (cap > 0)
1857  {
1858  mutt_socket_close(conn);
1859  mutt_error(_("Could not switch to reader mode"));
1860  return -1;
1861  }
1862  }
1863 
1864  /* attempt features */
1865  if (nntp_attempt_features(adata) < 0)
1866  return -1;
1867 
1868  adata->status = NNTP_OK;
1869  return 0;
1870 }
#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:1168
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:544
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:158
#define mutt_socket_readln(buf, buflen, conn)
Definition: mutt_socket.h:36
#define mutt_socket_send(conn, buf)
Definition: mutt_socket.h:37
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1461
static int nntp_auth(struct NntpAccountData *adata)
Get login, password and authenticate.
Definition: nntp.c:427
static int nntp_capabilities(struct NntpAccountData *adata)
Get capabilities.
Definition: nntp.c:141
static int nntp_connect_error(struct NntpAccountData *adata)
Signal a failed connection.
Definition: nntp.c:127
static int nntp_attempt_features(struct NntpAccountData *adata)
Detect supported commands.
Definition: nntp.c:244
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:349
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
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: