NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
lib.h File Reference

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

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "core/lib.h"
#include "format_flags.h"
+ Include dependency graph for lib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  NntpAcache
 NNTP article cache. More...
 
struct  NewsrcEntry
 An entry in a .newsrc (subscribed newsgroups) More...
 

Macros

#define anum_t   long
 
#define ANUM   "%ld"
 
#define NNTP_ACACHE_LEN   10
 

Functions

struct NntpAccountDatanntp_select_server (struct Mailbox *m, const char *server, bool leave_lock)
 Open a connection to an NNTP server.
 
struct NntpMboxDatamutt_newsgroup_subscribe (struct NntpAccountData *adata, char *group)
 Subscribe newsgroup.
 
struct NntpMboxDatamutt_newsgroup_unsubscribe (struct NntpAccountData *adata, char *group)
 Unsubscribe newsgroup.
 
struct NntpMboxDatamutt_newsgroup_catchup (struct Mailbox *m, struct NntpAccountData *adata, char *group)
 Catchup newsgroup.
 
struct NntpMboxDatamutt_newsgroup_uncatchup (struct Mailbox *m, struct NntpAccountData *adata, char *group)
 Uncatchup newsgroup.
 
int nntp_active_fetch (struct NntpAccountData *adata, bool mark_new)
 Fetch list of all newsgroups from server.
 
int nntp_newsrc_update (struct NntpAccountData *adata)
 Update .newsrc file.
 
int nntp_post (struct Mailbox *m, const char *msg)
 Post article.
 
int nntp_check_msgid (struct Mailbox *m, const char *msgid)
 Fetch article by Message-ID.
 
int nntp_check_children (struct Mailbox *m, const char *msgid)
 Fetch children of article with the Message-ID.
 
int nntp_newsrc_parse (struct NntpAccountData *adata)
 Parse .newsrc file.
 
void nntp_newsrc_close (struct NntpAccountData *adata)
 Unlock and close .newsrc file.
 
void nntp_mailbox (struct Mailbox *m, char *buf, size_t buflen)
 Get first newsgroup with new messages.
 
void nntp_expand_path (char *buf, size_t buflen, struct ConnAccount *acct)
 Make fully qualified url from newsgroup name.
 
void nntp_clear_cache (struct NntpAccountData *adata)
 Clear the NNTP cache.
 
const char * nntp_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Expand the newsrc filename - Implements format_t -.
 
int nntp_compare_order (const struct Email *a, const struct Email *b, bool reverse)
 Sort to mailbox order - Implements sort_mail_t -.
 
enum MailboxType nntp_path_probe (const char *path, const struct stat *st)
 Is this an NNTP Mailbox? - Implements MxOps::path_probe() -.
 
const char * group_index_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the newsgroup menu - Implements format_t -.
 
int nntp_complete (struct Buffer *buf)
 Auto-complete NNTP newsgroups.
 

Variables

struct NntpAccountDataCurrentNewsSrv
 Current NNTP news server.
 
const struct MxOps MxNntpOps
 NNTP Mailbox - Implements MxOps -.
 

Detailed Description

Usenet network mailbox type; talk to an NNTP server.

Authors
  • Brandon Long
  • Andrej Gritsenko
  • Vsevolod Volkov

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 lib.h.

Macro Definition Documentation

◆ anum_t

#define anum_t   long

Definition at line 61 of file lib.h.

◆ ANUM

#define ANUM   "%ld"

Definition at line 62 of file lib.h.

◆ NNTP_ACACHE_LEN

#define NNTP_ACACHE_LEN   10

Definition at line 83 of file lib.h.

Function Documentation

◆ nntp_select_server()

struct NntpAccountData * nntp_select_server ( struct Mailbox m,
const char *  server,
bool  leave_lock 
)

Open a connection to an NNTP server.

Parameters
mMailbox
serverServer URL
leave_lockLeave the server locked?
Return values
ptrNNTP server
NULLError

Automatically loads a newsrc into memory, if necessary. Checks the size/mtime of a newsrc file, if it doesn't match, load again. Hmm, if a system has broken mtimes, this might mean the file is reloaded every time, which we'd have to fix.

See also
$newsrc, nntp_format_str()

Definition at line 1021 of file newsrc.c.

1022{
1023 char file[PATH_MAX] = { 0 };
1024 int rc;
1025 struct ConnAccount cac = { { 0 } };
1026 struct NntpAccountData *adata = NULL;
1027 struct Connection *conn = NULL;
1028
1029 if (!server || (*server == '\0'))
1030 {
1031 mutt_error(_("No news server defined"));
1032 return NULL;
1033 }
1034
1035 /* create account from news server url */
1036 cac.flags = 0;
1037 cac.port = NNTP_PORT;
1039 cac.service = "nntp";
1041
1042 snprintf(file, sizeof(file), "%s%s", strstr(server, "://") ? "" : "news://", server);
1043 struct Url *url = url_parse(file);
1044 if (!url || (url->path && *url->path) ||
1045 !((url->scheme == U_NNTP) || (url->scheme == U_NNTPS)) || !url->host ||
1046 (mutt_account_fromurl(&cac, url) < 0))
1047 {
1048 url_free(&url);
1049 mutt_error(_("%s is an invalid news server specification"), server);
1050 return NULL;
1051 }
1052 if (url->scheme == U_NNTPS)
1053 {
1054 cac.flags |= MUTT_ACCT_SSL;
1055 cac.port = NNTP_SSL_PORT;
1056 }
1057 url_free(&url);
1058
1059 // If nntp_user and nntp_pass are specified in the config, use them to find the connection
1060 const char *user = NULL;
1061 const char *pass = NULL;
1062 if ((user = cac.get_field(MUTT_CA_USER, NULL)))
1063 {
1064 mutt_str_copy(cac.user, user, sizeof(cac.user));
1065 cac.flags |= MUTT_ACCT_USER;
1066 }
1067 if ((pass = cac.get_field(MUTT_CA_PASS, NULL)))
1068 {
1069 mutt_str_copy(cac.pass, pass, sizeof(cac.pass));
1070 cac.flags |= MUTT_ACCT_PASS;
1071 }
1072
1073 /* find connection by account */
1074 conn = mutt_conn_find(&cac);
1075 if (!conn)
1076 return NULL;
1077 if (!(conn->account.flags & MUTT_ACCT_USER) && cac.flags & MUTT_ACCT_USER)
1078 {
1079 conn->account.flags |= MUTT_ACCT_USER;
1080 conn->account.user[0] = '\0';
1081 }
1082
1083 /* new news server */
1084 adata = nntp_adata_new(conn);
1085
1086 rc = nntp_open_connection(adata);
1087
1088 /* try to create cache directory and enable caching */
1089 adata->cacheable = false;
1090 const char *const c_news_cache_dir = cs_subset_path(NeoMutt->sub, "news_cache_dir");
1091 if ((rc >= 0) && c_news_cache_dir)
1092 {
1093 cache_expand(file, sizeof(file), &conn->account, NULL);
1094 if (mutt_file_mkdir(file, S_IRWXU) < 0)
1095 {
1096 mutt_error(_("Can't create %s: %s"), file, strerror(errno));
1097 }
1098 adata->cacheable = true;
1099 }
1100
1101 /* load .newsrc */
1102 if (rc >= 0)
1103 {
1104 const char *const c_newsrc = cs_subset_path(NeoMutt->sub, "newsrc");
1105 mutt_expando_format(file, sizeof(file), 0, sizeof(file), NONULL(c_newsrc),
1106 nntp_format_str, (intptr_t) adata, MUTT_FORMAT_NO_FLAGS);
1107 mutt_expand_path(file, sizeof(file));
1108 adata->newsrc_file = mutt_str_dup(file);
1109 rc = nntp_newsrc_parse(adata);
1110 }
1111 if (rc >= 0)
1112 {
1113 /* try to load list of newsgroups from cache */
1114 if (adata->cacheable && (active_get_cache(adata) == 0))
1115 {
1116 rc = nntp_check_new_groups(m, adata);
1117 }
1118 else
1119 {
1120 /* load list of newsgroups from server */
1121 rc = nntp_active_fetch(adata, false);
1122 }
1123 }
1124
1125 if (rc >= 0)
1126 nntp_clear_cache(adata);
1127
1128#ifdef USE_HCACHE
1129 /* check cache files */
1130 if ((rc >= 0) && adata->cacheable)
1131 {
1132 struct dirent *de = NULL;
1133 DIR *dir = mutt_file_opendir(file, MUTT_OPENDIR_NONE);
1134
1135 if (dir)
1136 {
1137 while ((de = readdir(dir)))
1138 {
1139 struct HeaderCache *hc = NULL;
1140 char *group = de->d_name;
1141
1142 char *p = group + strlen(group) - 7;
1143 if ((strlen(group) < 8) || !mutt_str_equal(p, ".hcache"))
1144 continue;
1145 *p = '\0';
1147 if (!mdata)
1148 continue;
1149
1150 hc = nntp_hcache_open(mdata);
1151 if (!hc)
1152 continue;
1153
1154 /* fetch previous values of first and last */
1155 char *hdata = hcache_fetch_str(hc, "index", 5);
1156 if (hdata)
1157 {
1158 anum_t first, last;
1159
1160 if (sscanf(hdata, ANUM " " ANUM, &first, &last) == 2)
1161 {
1162 if (mdata->deleted)
1163 {
1164 mdata->first_message = first;
1165 mdata->last_message = last;
1166 }
1167 if ((last >= mdata->first_message) && (last <= mdata->last_message))
1168 {
1169 mdata->last_cached = last;
1170 mutt_debug(LL_DEBUG2, "%s last_cached=" ANUM "\n", mdata->group, last);
1171 }
1172 }
1173 FREE(&hdata);
1174 }
1175 hcache_close(&hc);
1176 }
1177 closedir(dir);
1178 }
1179 }
1180#endif
1181
1182 if ((rc < 0) || !leave_lock)
1184
1185 if (rc < 0)
1186 {
1191 FREE(&adata);
1192 mutt_socket_close(conn);
1193 FREE(&conn);
1194 return NULL;
1195 }
1196
1197 return adata;
1198}
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
@ MUTT_CA_USER
User name.
Definition: connaccount.h:36
@ MUTT_CA_PASS
Password.
Definition: connaccount.h:37
#define MUTT_ACCT_SSL
Account uses SSL/TLS.
Definition: connaccount.h:47
#define MUTT_ACCT_PASS
Password field has been set.
Definition: connaccount.h:46
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:44
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:977
DIR * mutt_file_opendir(const char *path, enum MuttOpenDirMode mode)
Open a directory.
Definition: file.c:616
@ MUTT_OPENDIR_NONE
Plain opendir()
Definition: file.h:73
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
const char * nntp_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Expand the newsrc filename - Implements format_t -.
Definition: newsrc.c:927
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:745
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
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
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
char * hcache_fetch_str(struct HeaderCache *hc, const char *key, size_t keylen)
Fetch a string from the cache.
Definition: hcache.c:670
void hcache_close(struct HeaderCache **ptr)
Multiplexor for StoreOps::close.
Definition: hcache.c:563
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
#define FREE(x)
Definition: memory.h:45
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:653
#define PATH_MAX
Definition: mutt.h:41
int mutt_account_fromurl(struct ConnAccount *cac, const struct Url *url)
Fill ConnAccount with information from url.
Definition: mutt_account.c:43
@ MUTT_ACCT_TYPE_NNTP
Nntp (Usenet) Account.
Definition: mutt_account.h:40
struct Connection * mutt_conn_find(const struct ConnAccount *cac)
Find a connection from a list.
Definition: mutt_socket.c:89
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:126
struct HeaderCache * nntp_hcache_open(struct NntpMboxData *mdata)
Open newsgroup hcache.
Definition: newsrc.c:714
void nntp_clear_cache(struct NntpAccountData *adata)
Clear the NNTP cache.
Definition: newsrc.c:847
int nntp_newsrc_parse(struct NntpAccountData *adata)
Parse .newsrc file.
Definition: newsrc.c:162
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition: newsrc.c:118
static const char * nntp_get_field(enum ConnAccountField field, void *gf_data)
Get connection login credentials - Implements ConnAccount::get_field()
Definition: newsrc.c:990
static int active_get_cache(struct NntpAccountData *adata)
Load list of all newsgroups from cache.
Definition: newsrc.c:621
static void cache_expand(char *dst, size_t dstlen, struct ConnAccount *cac, const char *src)
Make fully qualified cache file name.
Definition: newsrc.c:522
struct NntpAccountData * nntp_adata_new(struct Connection *conn)
Allocate and initialise a new NntpAccountData structure.
Definition: adata.c:65
int nntp_active_fetch(struct NntpAccountData *adata, bool mark_new)
Fetch list of all newsgroups from server.
Definition: nntp.c:1986
#define ANUM
Definition: lib.h:62
#define anum_t
Definition: lib.h:61
#define NNTP_SSL_PORT
Definition: private.h:37
#define NNTP_PORT
Definition: private.h:36
int nntp_check_new_groups(struct Mailbox *m, struct NntpAccountData *adata)
Check for new groups/articles in subscribed groups.
Definition: nntp.c:2054
int nntp_open_connection(struct NntpAccountData *adata)
Connect to server, authenticate and get capabilities.
Definition: nntp.c:1731
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:101
#define NONULL(x)
Definition: string2.h:37
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
Login details for a remote server.
Definition: connaccount.h:53
char user[128]
Username.
Definition: connaccount.h:56
char pass[256]
Password.
Definition: connaccount.h:57
const char * service
Name of the service, e.g. "imap".
Definition: connaccount.h:61
const char *(* get_field)(enum ConnAccountField field, void *gf_data)
Function to get some login credentials.
Definition: connaccount.h:68
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
Definition: connaccount.h:59
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:60
unsigned short port
Port to connect to.
Definition: connaccount.h:58
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
Header Cache.
Definition: lib.h:88
void * mdata
Driver specific data.
Definition: mailbox.h:133
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
NNTP-specific Account data -.
Definition: adata.h:36
struct HashTable * groups_hash
Hash Table: "newsgroup" -> NntpMboxData.
Definition: adata.h:61
char * authenticators
Definition: adata.h:52
void ** groups_list
Definition: adata.h:60
bool cacheable
Definition: adata.h:48
char * newsrc_file
Definition: adata.h:51
NNTP-specific Mailbox data -.
Definition: mdata.h:34
anum_t last_message
Definition: mdata.h:38
char * group
Name of newsgroup.
Definition: mdata.h:35
struct NntpAccountData * adata
Definition: mdata.h:48
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:69
char * user
Username.
Definition: url.h:71
char * host
Host.
Definition: url.h:73
char * pass
Password.
Definition: url.h:72
char * path
Path.
Definition: url.h:75
enum UrlScheme scheme
Scheme, e.g. U_SMTPS.
Definition: url.h:70
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:238
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
@ U_NNTPS
Url is nntps://.
Definition: url.h:42
@ U_NNTP
Url is nntp://.
Definition: url.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_newsgroup_subscribe()

struct NntpMboxData * mutt_newsgroup_subscribe ( struct NntpAccountData adata,
char *  group 
)

Subscribe newsgroup.

Parameters
adataNNTP server
groupNewsgroup
Return values
ptrNNTP data
NULLError

Definition at line 1249 of file newsrc.c.

1250{
1251 if (!adata || !adata->groups_hash || !group || (*group == '\0'))
1252 return NULL;
1253
1255 mdata->subscribed = true;
1256 if (!mdata->newsrc_ent)
1257 {
1258 mdata->newsrc_ent = mutt_mem_calloc(1, sizeof(struct NewsrcEntry));
1259 mdata->newsrc_len = 1;
1260 mdata->newsrc_ent[0].first = 1;
1261 mdata->newsrc_ent[0].last = 0;
1262 }
1263 return mdata;
1264}
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
static struct NntpMboxData * mdata_find(struct NntpAccountData *adata, const char *group)
Find NntpMboxData for given newsgroup or add it.
Definition: newsrc.c:72
An entry in a .newsrc (subscribed newsgroups)
Definition: lib.h:77
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_newsgroup_unsubscribe()

struct NntpMboxData * mutt_newsgroup_unsubscribe ( struct NntpAccountData adata,
char *  group 
)

Unsubscribe newsgroup.

Parameters
adataNNTP server
groupNewsgroup
Return values
ptrNNTP data
NULLError

Definition at line 1273 of file newsrc.c.

1274{
1275 if (!adata || !adata->groups_hash || !group || (*group == '\0'))
1276 return NULL;
1277
1279 if (!mdata)
1280 return NULL;
1281
1282 mdata->subscribed = false;
1283 const bool c_save_unsubscribed = cs_subset_bool(NeoMutt->sub, "save_unsubscribed");
1284 if (!c_save_unsubscribed)
1285 {
1286 mdata->newsrc_len = 0;
1287 FREE(&mdata->newsrc_ent);
1288 }
1289 return mdata;
1290}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_newsgroup_catchup()

struct NntpMboxData * mutt_newsgroup_catchup ( struct Mailbox m,
struct NntpAccountData adata,
char *  group 
)

Catchup newsgroup.

Parameters
mMailbox
adataNNTP server
groupNewsgroup
Return values
ptrNNTP data
NULLError

Definition at line 1300 of file newsrc.c.

1302{
1303 if (!adata || !adata->groups_hash || !group || (*group == '\0'))
1304 return NULL;
1305
1307 if (!mdata)
1308 return NULL;
1309
1310 if (mdata->newsrc_ent)
1311 {
1312 mutt_mem_realloc(&mdata->newsrc_ent, sizeof(struct NewsrcEntry));
1313 mdata->newsrc_len = 1;
1314 mdata->newsrc_ent[0].first = 1;
1315 mdata->newsrc_ent[0].last = mdata->last_message;
1316 }
1317 mdata->unread = 0;
1318 if (m && (m->mdata == mdata))
1319 {
1320 for (unsigned int i = 0; i < m->msg_count; i++)
1321 {
1322 struct Email *e = m->emails[i];
1323 if (!e)
1324 break;
1325 mutt_set_flag(m, e, MUTT_READ, true, true);
1326 }
1327 }
1328 return mdata;
1329}
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition: flags.c:53
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:72
The envelope/body of an email.
Definition: email.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:88
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_newsgroup_uncatchup()

struct NntpMboxData * mutt_newsgroup_uncatchup ( struct Mailbox m,
struct NntpAccountData adata,
char *  group 
)

Uncatchup newsgroup.

Parameters
mMailbox
adataNNTP server
groupNewsgroup
Return values
ptrNNTP data
NULLError

Definition at line 1339 of file newsrc.c.

1341{
1342 if (!adata || !adata->groups_hash || !group || (*group == '\0'))
1343 return NULL;
1344
1346 if (!mdata)
1347 return NULL;
1348
1349 if (mdata->newsrc_ent)
1350 {
1351 mutt_mem_realloc(&mdata->newsrc_ent, sizeof(struct NewsrcEntry));
1352 mdata->newsrc_len = 1;
1353 mdata->newsrc_ent[0].first = 1;
1354 mdata->newsrc_ent[0].last = mdata->first_message - 1;
1355 }
1356 if (m && (m->mdata == mdata))
1357 {
1358 mdata->unread = m->msg_count;
1359 for (unsigned int i = 0; i < m->msg_count; i++)
1360 {
1361 struct Email *e = m->emails[i];
1362 if (!e)
1363 break;
1364 mutt_set_flag(m, e, MUTT_READ, false, true);
1365 }
1366 }
1367 else
1368 {
1369 mdata->unread = mdata->last_message;
1370 if (mdata->newsrc_ent)
1371 mdata->unread -= mdata->newsrc_ent[0].last;
1372 }
1373 return mdata;
1374}
anum_t last
Last article number in run.
Definition: lib.h:79
struct NewsrcEntry * newsrc_ent
Definition: mdata.h:47
anum_t unread
Definition: mdata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_active_fetch()

int nntp_active_fetch ( struct NntpAccountData adata,
bool  mark_new 
)

Fetch list of all newsgroups from server.

Parameters
adataNNTP server
mark_newMark the groups as new
Return values
0Success
-1Failure

Definition at line 1986 of file nntp.c.

1987{
1988 struct NntpMboxData tmp_mdata = { 0 };
1989 char msg[256] = { 0 };
1990 char buf[1024] = { 0 };
1991 unsigned int i;
1992 int rc;
1993
1994 snprintf(msg, sizeof(msg), _("Loading list of groups from server %s..."),
1996 mutt_message("%s", msg);
1997 if (nntp_date(adata, &adata->newgroups_time) < 0)
1998 return -1;
1999
2000 tmp_mdata.adata = adata;
2001 tmp_mdata.group = NULL;
2002 i = adata->groups_num;
2003 mutt_str_copy(buf, "LIST\r\n", sizeof(buf));
2004 rc = nntp_fetch_lines(&tmp_mdata, buf, sizeof(buf), msg, nntp_add_group, adata);
2005 if (rc)
2006 {
2007 if (rc > 0)
2008 {
2009 mutt_error("LIST: %s", buf);
2010 }
2011 return -1;
2012 }
2013
2014 if (mark_new)
2015 {
2016 for (; i < adata->groups_num; i++)
2017 {
2018 struct NntpMboxData *mdata = adata->groups_list[i];
2019 mdata->has_new_mail = true;
2020 }
2021 }
2022
2023 for (i = 0; i < adata->groups_num; i++)
2024 {
2025 struct NntpMboxData *mdata = adata->groups_list[i];
2026
2027 if (mdata && mdata->deleted && !mdata->newsrc_ent)
2028 {
2030 mutt_hash_delete(adata->groups_hash, mdata->group, NULL);
2031 adata->groups_list[i] = NULL;
2032 }
2033 }
2034
2035 const bool c_nntp_load_description = cs_subset_bool(NeoMutt->sub, "nntp_load_description");
2036 if (c_nntp_load_description)
2037 rc = get_description(&tmp_mdata, "*", _("Loading descriptions..."));
2038
2040 if (rc < 0)
2041 return -1;
2043 return 0;
2044}
#define mutt_message(...)
Definition: logging2.h:91
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:427
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
void nntp_delete_group_cache(struct NntpMboxData *mdata)
Remove hcache and bcache of newsgroup.
Definition: newsrc.c:814
int nntp_add_group(char *line, void *data)
Parse newsgroup.
Definition: newsrc.c:580
int nntp_active_save_cache(struct NntpAccountData *adata)
Save list of all newsgroups to cache.
Definition: newsrc.c:655
static int nntp_date(struct NntpAccountData *adata, time_t *now)
Get date and time from server.
Definition: nntp.c:1664
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:782
static int get_description(struct NntpMboxData *mdata, const char *wildmat, const char *msg)
Fetch newsgroups descriptions.
Definition: nntp.c:901
char host[128]
Server to login to.
Definition: connaccount.h:54
time_t newgroups_time
Definition: adata.h:56
struct Connection * conn
Connection to NNTP Server.
Definition: adata.h:62
unsigned int groups_num
Definition: adata.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_newsrc_update()

int nntp_newsrc_update ( struct NntpAccountData adata)

Update .newsrc file.

Parameters
adataNNTP server
Return values
0Success
-1Failure

Definition at line 441 of file newsrc.c.

442{
443 if (!adata)
444 return -1;
445
446 int rc = -1;
447
448 size_t buflen = 10240;
449 char *buf = mutt_mem_calloc(1, buflen);
450 size_t off = 0;
451
452 /* we will generate full newsrc here */
453 for (unsigned int i = 0; i < adata->groups_num; i++)
454 {
455 struct NntpMboxData *mdata = adata->groups_list[i];
456
457 if (!mdata || !mdata->newsrc_ent)
458 continue;
459
460 /* write newsgroup name */
461 if ((off + strlen(mdata->group) + 3) > buflen)
462 {
463 buflen *= 2;
464 mutt_mem_realloc(&buf, buflen);
465 }
466 snprintf(buf + off, buflen - off, "%s%c ", mdata->group, mdata->subscribed ? ':' : '!');
467 off += strlen(buf + off);
468
469 /* write entries */
470 for (unsigned int j = 0; j < mdata->newsrc_len; j++)
471 {
472 if ((off + 1024) > buflen)
473 {
474 buflen *= 2;
475 mutt_mem_realloc(&buf, buflen);
476 }
477 if (j)
478 buf[off++] = ',';
479 if (mdata->newsrc_ent[j].first == mdata->newsrc_ent[j].last)
480 {
481 snprintf(buf + off, buflen - off, ANUM, mdata->newsrc_ent[j].first);
482 }
483 else if (mdata->newsrc_ent[j].first < mdata->newsrc_ent[j].last)
484 {
485 snprintf(buf + off, buflen - off, ANUM "-" ANUM,
486 mdata->newsrc_ent[j].first, mdata->newsrc_ent[j].last);
487 }
488 off += strlen(buf + off);
489 }
490 buf[off++] = '\n';
491 }
492 buf[off] = '\0';
493
494 /* newrc being fully rewritten */
495 mutt_debug(LL_DEBUG1, "Updating %s\n", adata->newsrc_file);
496 if (adata->newsrc_file && (update_file(adata->newsrc_file, buf) == 0))
497 {
498 struct stat st = { 0 };
499
500 rc = stat(adata->newsrc_file, &st);
501 if (rc == 0)
502 {
503 adata->size = st.st_size;
504 adata->mtime = st.st_mtime;
505 }
506 else
507 {
508 mutt_perror("%s", adata->newsrc_file);
509 }
510 }
511 FREE(&buf);
512 return rc;
513}
#define mutt_perror(...)
Definition: logging2.h:93
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
static int update_file(char *filename, char *buf)
Update file with new contents.
Definition: newsrc.c:391
off_t size
Definition: adata.h:54
time_t mtime
Definition: adata.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_post()

int nntp_post ( struct Mailbox m,
const char *  msg 
)

Post article.

Parameters
mMailbox
msgMessage to post
Return values
0Success
-1Failure

Definition at line 1901 of file nntp.c.

1902{
1903 struct NntpMboxData *mdata = NULL;
1904 struct NntpMboxData tmp_mdata = { 0 };
1905 char buf[1024] = { 0 };
1906
1907 if (m && (m->type == MUTT_NNTP))
1908 {
1909 mdata = m->mdata;
1910 }
1911 else
1912 {
1913 const char *const c_news_server = cs_subset_string(NeoMutt->sub, "news_server");
1914 CurrentNewsSrv = nntp_select_server(m, c_news_server, false);
1915 if (!CurrentNewsSrv)
1916 return -1;
1917
1918 mdata = &tmp_mdata;
1919 mdata->adata = CurrentNewsSrv;
1920 mdata->group = NULL;
1921 }
1922
1923 FILE *fp = mutt_file_fopen(msg, "r");
1924 if (!fp)
1925 {
1926 mutt_perror("%s", msg);
1927 return -1;
1928 }
1929
1930 mutt_str_copy(buf, "POST\r\n", sizeof(buf));
1931 if (nntp_query(mdata, buf, sizeof(buf)) < 0)
1932 {
1933 mutt_file_fclose(&fp);
1934 return -1;
1935 }
1936 if (buf[0] != '3')
1937 {
1938 mutt_error(_("Can't post article: %s"), buf);
1939 mutt_file_fclose(&fp);
1940 return -1;
1941 }
1942
1943 buf[0] = '.';
1944 buf[1] = '\0';
1945 while (fgets(buf + 1, sizeof(buf) - 2, fp))
1946 {
1947 size_t len = strlen(buf);
1948 if (buf[len - 1] == '\n')
1949 {
1950 buf[len - 1] = '\r';
1951 buf[len] = '\n';
1952 len++;
1953 buf[len] = '\0';
1954 }
1955 if (mutt_socket_send_d(mdata->adata->conn, (buf[1] == '.') ? buf : buf + 1,
1956 MUTT_SOCK_LOG_FULL) < 0)
1957 {
1958 mutt_file_fclose(&fp);
1959 return nntp_connect_error(mdata->adata);
1960 }
1961 }
1962 mutt_file_fclose(&fp);
1963
1964 if (((buf[strlen(buf) - 1] != '\n') &&
1965 (mutt_socket_send_d(mdata->adata->conn, "\r\n", MUTT_SOCK_LOG_FULL) < 0)) ||
1966 (mutt_socket_send_d(mdata->adata->conn, ".\r\n", MUTT_SOCK_LOG_FULL) < 0) ||
1967 (mutt_socket_readln(buf, sizeof(buf), mdata->adata->conn) < 0))
1968 {
1969 return nntp_connect_error(mdata->adata);
1970 }
1971 if (buf[0] != '2')
1972 {
1973 mutt_error(_("Can't post article: %s"), buf);
1974 return -1;
1975 }
1976 return 0;
1977}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:636
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:49
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:1021
static int nntp_connect_error(struct NntpAccountData *adata)
Signal a failed connection.
Definition: nntp.c:127
static int nntp_query(struct NntpMboxData *mdata, char *line, size_t linelen)
Send data from buffer and receive answer to same buffer.
Definition: nntp.c:703
struct NntpAccountData * CurrentNewsSrv
Current news server.
Definition: nntp.c:77
#define MUTT_SOCK_LOG_FULL
Definition: socket.h:56
#define mutt_socket_readln(buf, buflen, conn)
Definition: socket.h:58
#define mutt_socket_send_d(conn, buf, dbg)
Definition: socket.h:60
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_check_msgid()

int nntp_check_msgid ( struct Mailbox m,
const char *  msgid 
)

Fetch article by Message-ID.

Parameters
mMailbox
msgidMessage ID
Return values
0Success
1No such article
-1Error

Definition at line 2164 of file nntp.c.

2165{
2166 if (!m)
2167 return -1;
2168
2169 struct NntpMboxData *mdata = m->mdata;
2170 char buf[1024] = { 0 };
2171
2172 FILE *fp = mutt_file_mkstemp();
2173 if (!fp)
2174 {
2175 mutt_perror(_("Can't create temporary file"));
2176 return -1;
2177 }
2178
2179 snprintf(buf, sizeof(buf), "HEAD %s\r\n", msgid);
2180 int rc = nntp_fetch_lines(mdata, buf, sizeof(buf), NULL, fetch_tempfile, fp);
2181 if (rc)
2182 {
2183 mutt_file_fclose(&fp);
2184 if (rc < 0)
2185 return -1;
2186 if (mutt_str_startswith(buf, "430"))
2187 return 1;
2188 mutt_error("HEAD: %s", buf);
2189 return -1;
2190 }
2191
2192 /* parse header */
2194 m->emails[m->msg_count] = email_new();
2195 struct Email *e = m->emails[m->msg_count];
2196 e->edata = nntp_edata_new();
2198 e->env = mutt_rfc822_read_header(fp, e, false, false);
2199 mutt_file_fclose(&fp);
2200
2201 /* get article number */
2202 if (e->env->xref)
2203 {
2204 nntp_parse_xref(m, e);
2205 }
2206 else
2207 {
2208 snprintf(buf, sizeof(buf), "STAT %s\r\n", msgid);
2209 if (nntp_query(mdata, buf, sizeof(buf)) < 0)
2210 {
2211 email_free(&e);
2212 return -1;
2213 }
2214 sscanf(buf + 4, ANUM, &nntp_edata_get(e)->article_num);
2215 }
2216
2217 /* reset flags */
2218 e->read = false;
2219 e->old = false;
2220 e->deleted = false;
2221 e->changed = true;
2222 e->received = e->date_sent;
2223 e->index = m->msg_count++;
2225 return 0;
2226}
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
Parses an RFC822 header.
Definition: parse.c:1170
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:226
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:176
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:228
void mx_alloc_memory(struct Mailbox *m, int req_size)
Create storage for the emails.
Definition: mx.c:1232
struct NntpEmailData * nntp_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:60
void nntp_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: edata.c:38
struct NntpEmailData * nntp_edata_new(void)
Create a new NntpEmailData for an Email.
Definition: edata.c:50
static int fetch_tempfile(char *line, void *data)
Write line to temporary file.
Definition: nntp.c:974
static void nntp_parse_xref(struct Mailbox *m, struct Email *e)
Parse cross-reference.
Definition: nntp.c:933
bool read
Email is read.
Definition: email.h:48
struct Envelope * env
Envelope information.
Definition: email.h:66
void * edata
Driver-specific data.
Definition: email.h:72
bool old
Email is seen, but unread.
Definition: email.h:47
void(* edata_free)(void **ptr)
Free the private data attached to the Email.
Definition: email.h:86
bool changed
Email has been edited.
Definition: email.h:75
time_t date_sent
Time when the message was sent (UTC)
Definition: email.h:58
bool deleted
Email is deleted.
Definition: email.h:76
int index
The absolute (unsorted) message number.
Definition: email.h:109
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:59
char * xref
List of cross-references.
Definition: envelope.h:80
#define mutt_file_mkstemp()
Definition: tmp.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_check_children()

int nntp_check_children ( struct Mailbox m,
const char *  msgid 
)

Fetch children of article with the Message-ID.

Parameters
mMailbox
msgidMessage ID to find
Return values
0Success
-1Failure

Definition at line 2235 of file nntp.c.

2236{
2237 if (!m)
2238 return -1;
2239
2240 struct NntpMboxData *mdata = m->mdata;
2241 char buf[256] = { 0 };
2242 int rc;
2243 struct HeaderCache *hc = NULL;
2244
2245 if (!mdata || !mdata->adata)
2246 return -1;
2247 if (mdata->first_message > mdata->last_loaded)
2248 return 0;
2249
2250 /* init context */
2251 struct ChildCtx cc = { 0 };
2252 cc.mailbox = m;
2253 cc.num = 0;
2254 cc.max = 10;
2255 cc.child = mutt_mem_malloc(sizeof(anum_t) * cc.max);
2256
2257 /* fetch numbers of child messages */
2258 snprintf(buf, sizeof(buf), "XPAT References " ANUM "-" ANUM " *%s*\r\n",
2259 mdata->first_message, mdata->last_loaded, msgid);
2260 rc = nntp_fetch_lines(mdata, buf, sizeof(buf), NULL, fetch_children, &cc);
2261 if (rc)
2262 {
2263 FREE(&cc.child);
2264 if (rc > 0)
2265 {
2266 if (!mutt_str_startswith(buf, "500"))
2267 {
2268 mutt_error("XPAT: %s", buf);
2269 }
2270 else
2271 {
2272 mutt_error(_("Unable to find child articles because server does not support XPAT command"));
2273 }
2274 }
2275 return -1;
2276 }
2277
2278 /* fetch all found messages */
2279 bool verbose = m->verbose;
2280 m->verbose = false;
2281#ifdef USE_HCACHE
2282 hc = nntp_hcache_open(mdata);
2283#endif
2284 int old_msg_count = m->msg_count;
2285 for (int i = 0; i < cc.num; i++)
2286 {
2287 rc = nntp_fetch_headers(m, hc, cc.child[i], cc.child[i], true);
2288 if (rc < 0)
2289 break;
2290 }
2291 if (m->msg_count > old_msg_count)
2293
2294#ifdef USE_HCACHE
2295 hcache_close(&hc);
2296#endif
2297 m->verbose = verbose;
2298 FREE(&cc.child);
2299 return (rc < 0) ? -1 : 0;
2300}
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
static int fetch_children(char *line, void *data)
Parse XPAT line.
Definition: nntp.c:1701
static int nntp_fetch_headers(struct Mailbox *m, void *hc, anum_t first, anum_t last, bool restore)
Fetch headers.
Definition: nntp.c:1169
Keep track of the children of an article.
Definition: nntp.c:107
anum_t * child
Definition: nntp.c:111
struct Mailbox * mailbox
Definition: nntp.c:108
unsigned int max
Definition: nntp.c:110
unsigned int num
Definition: nntp.c:109
bool verbose
Display status messages?
Definition: mailbox.h:116
anum_t last_loaded
Definition: mdata.h:39
anum_t first_message
Definition: mdata.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_newsrc_parse()

int nntp_newsrc_parse ( struct NntpAccountData adata)

Parse .newsrc file.

Parameters
adataNNTP server
Return values
0Not changed
1Parsed
-1Error

Definition at line 162 of file newsrc.c.

163{
164 if (!adata)
165 return -1;
166
167 char *line = NULL;
168 struct stat st = { 0 };
169
170 if (adata->fp_newsrc)
171 {
172 /* if we already have a handle, close it and reopen */
174 }
175 else
176 {
177 /* if file doesn't exist, create it */
178 adata->fp_newsrc = mutt_file_fopen(adata->newsrc_file, "a");
180 }
181
182 /* open .newsrc */
183 adata->fp_newsrc = mutt_file_fopen(adata->newsrc_file, "r");
184 if (!adata->fp_newsrc)
185 {
186 mutt_perror("%s", adata->newsrc_file);
187 return -1;
188 }
189
190 /* lock it */
191 mutt_debug(LL_DEBUG1, "Locking %s\n", adata->newsrc_file);
192 if (mutt_file_lock(fileno(adata->fp_newsrc), false, true))
193 {
195 return -1;
196 }
197
198 if (stat(adata->newsrc_file, &st) != 0)
199 {
200 mutt_perror("%s", adata->newsrc_file);
201 nntp_newsrc_close(adata);
202 return -1;
203 }
204
205 if ((adata->size == st.st_size) && (adata->mtime == st.st_mtime))
206 return 0;
207
208 adata->size = st.st_size;
209 adata->mtime = st.st_mtime;
210 adata->newsrc_modified = true;
211 mutt_debug(LL_DEBUG1, "Parsing %s\n", adata->newsrc_file);
212
213 /* .newsrc has been externally modified or hasn't been loaded yet */
214 for (unsigned int i = 0; i < adata->groups_num; i++)
215 {
216 struct NntpMboxData *mdata = adata->groups_list[i];
217 if (!mdata)
218 continue;
219
220 mdata->subscribed = false;
221 mdata->newsrc_len = 0;
222 FREE(&mdata->newsrc_ent);
223 }
224
225 line = mutt_mem_malloc(st.st_size + 1);
226 while (st.st_size && fgets(line, st.st_size + 1, adata->fp_newsrc))
227 {
228 char *b = NULL, *h = NULL;
229 unsigned int j = 1;
230 bool subs = false;
231
232 /* find end of newsgroup name */
233 char *p = strpbrk(line, ":!");
234 if (!p)
235 continue;
236
237 /* ":" - subscribed, "!" - unsubscribed */
238 if (*p == ':')
239 subs = true;
240 *p++ = '\0';
241
242 /* get newsgroup data */
243 struct NntpMboxData *mdata = mdata_find(adata, line);
244 FREE(&mdata->newsrc_ent);
245
246 /* count number of entries */
247 b = p;
248 while (*b)
249 if (*b++ == ',')
250 j++;
251 mdata->newsrc_ent = mutt_mem_calloc(j, sizeof(struct NewsrcEntry));
252 mdata->subscribed = subs;
253
254 /* parse entries */
255 j = 0;
256 while (p)
257 {
258 b = p;
259
260 /* find end of entry */
261 p = strchr(p, ',');
262 if (p)
263 *p++ = '\0';
264
265 /* first-last or single number */
266 h = strchr(b, '-');
267 if (h)
268 *h++ = '\0';
269 else
270 h = b;
271
272 if ((sscanf(b, ANUM, &mdata->newsrc_ent[j].first) == 1) &&
273 (sscanf(h, ANUM, &mdata->newsrc_ent[j].last) == 1))
274 {
275 j++;
276 }
277 }
278 if (j == 0)
279 {
280 mdata->newsrc_ent[j].first = 1;
281 mdata->newsrc_ent[j].last = 0;
282 j++;
283 }
284 if (mdata->last_message == 0)
285 mdata->last_message = mdata->newsrc_ent[j - 1].last;
286 mdata->newsrc_len = j;
287 mutt_mem_realloc(&mdata->newsrc_ent, j * sizeof(struct NewsrcEntry));
289 mutt_debug(LL_DEBUG2, "%s\n", mdata->group);
290 }
291 FREE(&line);
292 return 1;
293}
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1243
void nntp_group_unread_stat(struct NntpMboxData *mdata)
Count number of unread articles using .newsrc data.
Definition: newsrc.c:132
bool newsrc_modified
Definition: adata.h:49
FILE * fp_newsrc
Definition: adata.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_newsrc_close()

void nntp_newsrc_close ( struct NntpAccountData adata)

Unlock and close .newsrc file.

Parameters
adataNNTP server

Definition at line 118 of file newsrc.c.

119{
120 if (!adata->fp_newsrc)
121 return;
122
123 mutt_debug(LL_DEBUG1, "Unlocking %s\n", adata->newsrc_file);
124 mutt_file_unlock(fileno(adata->fp_newsrc));
126}
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1290
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_mailbox()

void nntp_mailbox ( struct Mailbox m,
char *  buf,
size_t  buflen 
)

Get first newsgroup with new messages.

Parameters
mMailbox
bufBuffer for result
buflenLength of buffer

Definition at line 1382 of file newsrc.c.

1383{
1384 if (!m)
1385 return;
1386
1387 for (unsigned int i = 0; i < CurrentNewsSrv->groups_num; i++)
1388 {
1390
1391 if (!mdata || !mdata->subscribed || !mdata->unread)
1392 continue;
1393
1394 if ((m->type == MUTT_NNTP) &&
1395 mutt_str_equal(mdata->group, ((struct NntpMboxData *) m->mdata)->group))
1396 {
1397 unsigned int unread = 0;
1398
1399 for (unsigned int j = 0; j < m->msg_count; j++)
1400 {
1401 struct Email *e = m->emails[j];
1402 if (!e)
1403 break;
1404 if (!e->read && !e->deleted)
1405 unread++;
1406 }
1407 if (unread == 0)
1408 continue;
1409 }
1410 mutt_str_copy(buf, mdata->group, buflen);
1411 break;
1412 }
1413}
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:77
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_expand_path()

void nntp_expand_path ( char *  buf,
size_t  buflen,
struct ConnAccount cac 
)

Make fully qualified url from newsgroup name.

Parameters
bufBuffer for the result
buflenLength of buffer
cacAccount to serialise

Definition at line 564 of file newsrc.c.

565{
566 struct Url url = { 0 };
567
568 mutt_account_tourl(cac, &url);
569 url.path = mutt_str_dup(buf);
570 url_tostring(&url, buf, buflen, U_NO_FLAGS);
571 FREE(&url.path);
572}
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
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:422
#define U_NO_FLAGS
Definition: url.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_clear_cache()

void nntp_clear_cache ( struct NntpAccountData adata)

Clear the NNTP cache.

Parameters
adataNNTP server

Remove hcache and bcache of all unexistent and unsubscribed newsgroups

Definition at line 847 of file newsrc.c.

848{
849 char file[PATH_MAX] = { 0 };
850 char *fp = NULL;
851 struct dirent *de = NULL;
852 DIR *dir = NULL;
853
854 if (!adata || !adata->cacheable)
855 return;
856
857 cache_expand(file, sizeof(file), &adata->conn->account, NULL);
859 if (dir)
860 {
861 mutt_strn_cat(file, sizeof(file), "/", 1);
862 fp = file + strlen(file);
863 while ((de = readdir(dir)))
864 {
865 char *group = de->d_name;
866 struct stat st = { 0 };
867 struct NntpMboxData *mdata = NULL;
868 struct NntpMboxData tmp_mdata = { 0 };
869
870 if (mutt_str_equal(group, ".") || mutt_str_equal(group, ".."))
871 continue;
872 *fp = '\0';
873 mutt_strn_cat(file, sizeof(file), group, strlen(group));
874 if (stat(file, &st) != 0)
875 continue;
876
877#ifdef USE_HCACHE
878 if (S_ISREG(st.st_mode))
879 {
880 char *ext = group + strlen(group) - 7;
881 if ((strlen(group) < 8) || !mutt_str_equal(ext, ".hcache"))
882 continue;
883 *ext = '\0';
884 }
885 else
886#endif
887 if (!S_ISDIR(st.st_mode))
888 continue;
889
890 const bool c_save_unsubscribed = cs_subset_bool(NeoMutt->sub, "save_unsubscribed");
892 if (!mdata)
893 {
894 mdata = &tmp_mdata;
895 mdata->adata = adata;
896 mdata->group = group;
897 mdata->bcache = NULL;
898 }
899 else if (mdata->newsrc_ent || mdata->subscribed || c_save_unsubscribed)
900 {
901 continue;
902 }
903
905 if (S_ISDIR(st.st_mode))
906 {
907 rmdir(file);
908 mutt_debug(LL_DEBUG2, "%s\n", file);
909 }
910 }
911 closedir(dir);
912 }
913}
char * mutt_strn_cat(char *d, size_t l, const char *s, size_t sl)
Concatenate two strings.
Definition: string.c:295
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_complete()

int nntp_complete ( struct Buffer buf)

Auto-complete NNTP newsgroups.

Parameters
bufBuffer containing pathname
Return values
0Match found
-1No matches

XXX rules

Definition at line 45 of file complete.c.

46{
48 size_t n = 0;
49 struct Buffer *filepart = buf_new(buf_string(buf));
50 bool init = false;
51
52 /* special case to handle when there is no filepart yet
53 * find the first subscribed newsgroup */
54 int len = buf_len(filepart);
55 if (len == 0)
56 {
57 for (; n < adata->groups_num; n++)
58 {
59 struct NntpMboxData *mdata = adata->groups_list[n];
60
61 if (mdata && mdata->subscribed)
62 {
63 buf_strcpy(filepart, mdata->group);
64 init = true;
65 n++;
66 break;
67 }
68 }
69 }
70
71 for (; n < adata->groups_num; n++)
72 {
73 struct NntpMboxData *mdata = adata->groups_list[n];
74
75 if (mdata && mdata->subscribed &&
76 mutt_strn_equal(mdata->group, buf_string(filepart), len))
77 {
78 if (init)
79 {
80 char *str = filepart->data;
81 size_t i;
82 for (i = 0; (str[i] != '\0') && mdata->group[i]; i++)
83 {
84 if (str[i] != mdata->group[i])
85 break;
86 }
87 str[i] = '\0';
88 buf_fix_dptr(filepart);
89 }
90 else
91 {
92 buf_strcpy(filepart, mdata->group);
93 init = true;
94 }
95 }
96 }
97
98 buf_copy(buf, filepart);
99 buf_free(&filepart);
100 return init ? 0 : -1;
101}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:466
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:194
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition: buffer.c:331
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition: buffer.c:316
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:572
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:497
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ CurrentNewsSrv

struct NntpAccountData* CurrentNewsSrv
extern

Current NNTP news server.

Current NNTP news server.

Definition at line 77 of file nntp.c.