Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 198242 | Differences between
and this patch

Collapse All | Expand All

(-)mutt-1.5.17.orig/ChangeLog.nntp (+356 lines)
Line 0 Link Here
1
* Sun Nov  4 2007 Vsevolod Volkov <vvv@mutt.org.ua>
2
- update to 1.5.17
3
4
* Tue Jul  3 2007 Vsevolod Volkov <vvv@mutt.org.ua>
5
- fixed arguments of nntp_format_str()
6
7
* Fri Jun 15 2007 Vsevolod Volkov <vvv@mutt.org.ua>
8
- fixed error selecting news group
9
10
* Tue Jun 12 2007 Vsevolod Volkov <vvv@mutt.org.ua>
11
- update to 1.5.16
12
13
* Wed Apr 11 2007 Vsevolod Volkov <vvv@mutt.org.ua>
14
- fixed posting error if $smtp_url is set
15
- added support of print-style sequence %R (x-comment-to)
16
17
* Sun Apr  8 2007 Vsevolod Volkov <vvv@mutt.org.ua>
18
- update to 1.5.15
19
- nntp://... url changed to news://...
20
- added indicator of fetching descriptions progress
21
22
* Tue Feb 28 2007 Vsevolod Volkov <vvv@mutt.org.ua>
23
- update to 1.5.14
24
25
* Tue Aug 15 2006 Vsevolod Volkov <vvv@mutt.org.ua>
26
- update to 1.5.13
27
28
* Mon Jul 17 2006 Vsevolod Volkov <vvv@mutt.org.ua>
29
- update to 1.5.12
30
- fixed reading empty .newsrc
31
32
* Sat Sep 17 2005 Vsevolod Volkov <vvv@mutt.org.ua>
33
- update to 1.5.11
34
35
* Sat Aug 13 2005 Vsevolod Volkov <vvv@mutt.org.ua>
36
- update to 1.5.10
37
38
* Sun Mar 13 2005 Vsevolod Volkov <vvv@mutt.org.ua>
39
- update to 1.5.9
40
41
* Sun Feb 13 2005 Vsevolod Volkov <vvv@mutt.org.ua>
42
- update to 1.5.8
43
44
* Sat Feb  5 2005 Vsevolod Volkov <vvv@mutt.org.ua>
45
- update to 1.5.7
46
- function mutt_update_list_file() moved to newsrc.c and changed algorithm
47
48
* Thu Jul  8 2004 Vsevolod Volkov <vvv@mutt.org.ua>
49
- fixed error in nntp_logout_all()
50
51
* Sat Apr  3 2004 Vsevolod Volkov <vvv@mutt.org.ua>
52
- fixed debug output in mutt_newsrc_update()
53
- added optional support of LISTGROUP command
54
- fixed typo in nntp_parse_xref()
55
56
* Tue Feb  3 2004 Vsevolod Volkov <vvv@mutt.org.ua>
57
- update to 1.5.6
58
59
* Thu Dec 18 2003 Vsevolod Volkov <vvv@mutt.org.ua>
60
- fixed compose menu
61
62
* Thu Nov  6 2003 Vsevolod Volkov <vvv@mutt.org.ua>
63
- update to 1.5.5.1
64
65
* Wed Nov  5 2003 Vsevolod Volkov <vvv@mutt.org.ua>
66
- update to 1.5.5
67
- added space after newsgroup name in .newsrc file
68
69
* Sun May 18 2003 Vsevolod Volkov <vvv@mutt.org.ua>
70
- nntp patch: fixed SIGSEGV when posting article
71
72
* Sat Mar 22 2003 Vsevolod Volkov <vvv@mutt.org.ua>
73
- update to 1.5.4
74
75
* Sat Dec 21 2002 Vsevolod Volkov <vvv@mutt.org.ua>
76
- update to 1.5.3
77
- replace safe_free calls by the FREE macro
78
79
* Fri Dec  6 2002 Vsevolod Volkov <vvv@mutt.org.ua>
80
- update to 1.5.2
81
- nntp authentication can be passed after any command
82
83
* Sat May  4 2002 Vsevolod Volkov <vvv@mutt.org.ua>
84
- update to 1.5.1
85
86
* Thu May  2 2002 Vsevolod Volkov <vvv@mutt.org.ua>
87
- update to 1.3.99
88
89
* Wed Mar 13 2002 Vsevolod Volkov <vvv@mutt.org.ua>
90
- update to 1.3.28
91
- fixed SIGSEGV in <get-message>, <get-parent>, <get-children>,
92
  <reconstruct-thread> functions
93
- fixed message about nntp reconnect
94
- fixed <attach-news-message> function using browser
95
- added support of Followup-To: poster
96
- added %n (new articles) in group_index_format
97
- posting articles without inews by default
98
99
* Wed Jan 23 2002 Vsevolod Volkov <vvv@mutt.org.ua>
100
- update to 1.3.27
101
102
* Fri Jan 18 2002 Vsevolod Volkov <vvv@mutt.org.ua>
103
- update to 1.3.26
104
105
* Thu Jan  3 2002 Vsevolod Volkov <vvv@mutt.org.ua>
106
- update to 1.3.25
107
- accelerated speed of access to news->newsgroups hash (by <gul@gul.kiev.ua>)
108
- added default content disposition
109
110
* Mon Dec  3 2001 Vsevolod Volkov <vvv@mutt.org.ua>
111
- update to 1.3.24
112
113
* Fri Nov  9 2001 Vsevolod Volkov <vvv@mutt.org.ua>
114
- update to 1.3.23.2
115
- fixed segfault if mutt_conn_find() returns null
116
117
* Wed Oct 31 2001 Vsevolod Volkov <vvv@mutt.org.ua>
118
- update to 1.3.23.1
119
- added support of LISTGROUP command
120
- added support for servers with broken overview
121
- disabled <flag-message> function on news server
122
- fixed error storing bad authentication information
123
124
* Wed Oct 10 2001 Vsevolod Volkov <vvv@mutt.org.ua>
125
- update to 1.3.23
126
- fixed typo in buffy.c
127
- added substitution of %s parameter in $inews variable
128
129
* Fri Aug 31 2001 Vsevolod Volkov <vvv@mutt.org.ua>
130
- update to 1.3.22.1
131
- update to 1.3.22
132
133
* Thu Aug 23 2001 Vsevolod Volkov <vvv@mutt.org.ua>
134
- update to 1.3.21
135
136
* Wed Jul 25 2001 Vsevolod Volkov <vvv@mutt.org.ua>
137
- update to 1.3.20
138
- removed 'server-hook', use 'account-hook' instead
139
- fixed error opening NNTP server without newsgroup using -f option
140
141
* Fri Jun  8 2001 Vsevolod Volkov <vvv@mutt.org.ua>
142
- update to 1.3.19
143
144
* Sat May  5 2001 Vsevolod Volkov <vvv@mutt.org.ua>
145
- update to 1.3.18
146
- fixed typo in nntp_attempt_features()
147
- changed algorithm of XGTITLE command testing
148
- disabled writing of NNTP password in debug file
149
- fixed reading and writing of long newsrc lines
150
- changed checking of last line while reading lines from server
151
- fixed possible buffer overrun in nntp_parse_newsrc_line()
152
- removed checking of XHDR command
153
- compare NNTP return codes without trailing space
154
155
* Thu Mar 29 2001 Vsevolod Volkov <vvv@mutt.org.ua>
156
- update to 1.3.17
157
- support for 'LIST NEWSGROUPS' command to read descriptions
158
159
* Fri Mar  2 2001 Vsevolod Volkov <vvv@mutt.org.ua>
160
- update to 1.3.16
161
162
* Wed Feb 14 2001 Vsevolod Volkov <vvv@mutt.org.ua>
163
- update to 1.3.15
164
165
* Sun Jan 28 2001 Vsevolod Volkov <vvv@mutt.org.ua>
166
- update to 1.3.14
167
- show number of tagged messages patch from Felix von Leitner <leitner@fefe.de>
168
169
* Sun Dec 31 2000 Vsevolod Volkov <vvv@mutt.org.ua>
170
- update to 1.3.13
171
172
* Sat Dec 30 2000 Vsevolod Volkov <vvv@mutt.org.ua>
173
- Fixed problem if last article in group is deleted
174
175
* Fri Dec 22 2000 Vsevolod Volkov <vvv@mutt.org.ua>
176
- Fixed checking of XGTITLE command on some servers
177
178
* Mon Dec 18 2000 Vsevolod Volkov <vvv@mutt.org.ua>
179
- Added \r in AUTHINFO commands
180
181
* Mon Nov 27 2000 Vsevolod Volkov <vvv@mutt.org.ua>
182
- update to 1.3.12
183
184
* Wed Nov  1 2000 Vsevolod Volkov <vvv@mutt.org.ua>
185
- update to 1.3.11
186
- fixed error opening newsgroup from mutt started with -g or -G
187
188
* Thu Oct 12 2000 Vsevolod Volkov <vvv@mutt.org.ua>
189
- update to 1.3.10
190
- hotkey 'G' (get-message) replaced with '^G'
191
192
* Thu Sep 21 2000 Vsevolod Volkov <vvv@mutt.org.ua>
193
- update to 1.3.9
194
- changed delay displaying error messages from 1 to 2 seconds
195
- fixed error compiling with nntp and without imap
196
197
* Wed Sep  6 2000 Vsevolod Volkov <vvv@mutt.org.ua>
198
- fixed catchup in index
199
- fixed nntp_open_mailbox()
200
201
* Sat Sep  2 2000 Vsevolod Volkov <vvv@mutt.org.ua>
202
- functions <edit> and <delete-entry> disabled
203
- format of news mailbox names changed to url form
204
- option nntp_attempts removed
205
- option reconnect_news renamed to nntp_reconnect
206
- default value of nntp_poll changed from 30 to 60
207
- error handling improved
208
209
* Wed Aug 30 2000 Vsevolod Volkov <vvv@mutt.org.ua>
210
- update to 1.3.8
211
- new option show_only_unread
212
- add newsgroup completion
213
214
* Fri Aug  4 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
215
- update to 1.3.7
216
217
* Sat Jul 29 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
218
- update to 1.3.6
219
220
* Sun Jul  9 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
221
- update to 1.3.5
222
- authentication code update
223
- fix for changing to newsgroup from mailbox with read messages
224
- socket code optimization
225
226
* Wed Jun 21 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
227
- update to 1.3.4
228
229
* Wed Jun 14 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
230
- don't substitute current newsgroup with deleted new messages
231
232
* Mon Jun 12 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
233
- update to 1.3.3
234
- fix for substitution of newsgroup after reconnection
235
- fix for loading newsgroups with very long names
236
- fix for loading more than 32768 newsgroups
237
238
* Wed May 24 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
239
- update to 1.3.2
240
241
* Sat May 20 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
242
- update to 1.3.1
243
244
* Fri May 12 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
245
- update to 1.3
246
247
* Thu May 11 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
248
- update to 1.2
249
250
* Thu May  4 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
251
- update to 1.1.14
252
253
* Sun Apr 23 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
254
- update to 1.1.12
255
256
* Fri Apr  7 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
257
- add substitution of newsgroup with new messages by default
258
259
* Wed Apr  5 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
260
- add attach message from newsgroup
261
- add one-line help in newsreader mode
262
- disable 'change-dir' command in newsgroups browser
263
- add -G option
264
265
* Tue Apr  4 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
266
- get default newsserver name from file /etc/nntpserver
267
- use case insensitive server names
268
- add print-style sequence %s to $newsrc
269
- add -g option
270
271
* Sat Apr  1 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
272
- remove 'X-FTN-Origin' header processing
273
274
* Thu Mar 30 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
275
- update to 1.1.11
276
- update to 1.1.10
277
278
* Thu Mar 23 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
279
- fix mutt_select_newsserver()
280
- remove 'toggle-mode' function
281
- add 'change-newsgroup' function
282
283
* Wed Mar 22 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
284
- fix server-hook
285
286
* Tue Mar 21 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
287
- fix error 'bounce' function after 'post'
288
- add 'forward to newsgroup' function
289
290
* Mon Mar 20 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
291
- 'forward' function works in newsreader mode
292
- add 'post' and 'followup' functions to pager and attachment menu
293
- fix active descriptions and allowed flag reload
294
295
* Tue Mar 14 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
296
- update to 1.1.9
297
- remove deleted newsgroups from list
298
299
* Mon Mar 13 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
300
- update .newsrc in browser
301
302
* Sun Mar 12 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
303
- reload .newsrc if externally modified
304
- fix active cache update
305
306
* Sun Mar  5 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
307
- update to 1.1.8
308
309
* Sat Mar  4 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
310
- patch *.update_list_file is not required
311
- count lines when loading descriptions
312
- remove cache of unsubscribed newsgroups
313
314
* Thu Mar  2 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
315
- load list of newsgroups from cache faster
316
317
* Wed Mar  1 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
318
- update to 1.1.7
319
320
* Tue Feb 29 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
321
- fix unread messages in browser
322
- fix newsrc_gen_entries()
323
324
* Mon Feb 28 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
325
- fix mutt_newsgroup_stat()
326
- fix nntp_delete_cache()
327
- fix nntp_get_status()
328
- fix check_children()
329
- fix nntp_fetch_headers()
330
331
* Fri Feb 25 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
332
- update to 1.1.5
333
334
* Thu Feb 24 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
335
- fix updating new messages in cache
336
337
* Mon Feb 21 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
338
- change default cache filenames
339
- fix updating new messages in cache
340
341
* Fri Feb 18 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
342
- fix segmentation fault in news groups browser
343
344
* Tue Feb 15 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
345
- update to 1.1.4
346
347
* Thu Feb 10 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
348
- update to 1.1.3
349
350
* Sun Jan 30 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
351
- add X-Comment-To editing
352
- add my_hdr support for Newsgroups:, Followup-To: and X-Comment-To: headers
353
- add variables $ask_followup_to and $ask_x_comment_to
354
355
* Fri Jan 28 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
356
- update to 1.1.2
(-)mutt-1.5.17.orig/OPS (-2 / +21 lines)
Lines 8-21 OP_BOUNCE_MESSAGE "remail a message to a Link Here
8
OP_BROWSER_NEW_FILE "select a new file in this directory"
8
OP_BROWSER_NEW_FILE "select a new file in this directory"
9
OP_BROWSER_VIEW_FILE "view file"
9
OP_BROWSER_VIEW_FILE "view file"
10
OP_BROWSER_TELL "display the currently selected file's name"
10
OP_BROWSER_TELL "display the currently selected file's name"
11
OP_BROWSER_SUBSCRIBE "subscribe to current mailbox (IMAP only)"
11
OP_BROWSER_SUBSCRIBE "subscribe to current mbox (IMAP/NNTP only)"
12
OP_BROWSER_UNSUBSCRIBE "unsubscribe from current mailbox (IMAP only)"
12
OP_BROWSER_UNSUBSCRIBE "unsubscribe from current mbox (IMAP/NNTP only)"
13
OP_BROWSER_TOGGLE_LSUB "toggle view all/subscribed mailboxes (IMAP only)"
13
OP_BROWSER_TOGGLE_LSUB "toggle view all/subscribed mailboxes (IMAP only)"
14
OP_BUFFY_LIST "list mailboxes with new mail"
14
OP_BUFFY_LIST "list mailboxes with new mail"
15
OP_CATCHUP "mark all articles in newsgroup as read"
15
OP_CHANGE_DIRECTORY "change directories"
16
OP_CHANGE_DIRECTORY "change directories"
16
OP_CHECK_NEW "check mailboxes for new mail"
17
OP_CHECK_NEW "check mailboxes for new mail"
17
OP_COMPOSE_ATTACH_FILE "attach file(s) to this message"
18
OP_COMPOSE_ATTACH_FILE "attach file(s) to this message"
18
OP_COMPOSE_ATTACH_MESSAGE "attach message(s) to this message"
19
OP_COMPOSE_ATTACH_MESSAGE "attach message(s) to this message"
20
OP_COMPOSE_ATTACH_NEWS_MESSAGE "attach newsmessage(s) to this message"
19
OP_COMPOSE_EDIT_BCC "edit the BCC list"
21
OP_COMPOSE_EDIT_BCC "edit the BCC list"
20
OP_COMPOSE_EDIT_CC "edit the CC list"
22
OP_COMPOSE_EDIT_CC "edit the CC list"
21
OP_COMPOSE_EDIT_DESCRIPTION "edit attachment description"
23
OP_COMPOSE_EDIT_DESCRIPTION "edit attachment description"
Lines 26-32 OP_COMPOSE_EDIT_FROM "edit the from fiel Link Here
26
OP_COMPOSE_EDIT_HEADERS "edit the message with headers"
28
OP_COMPOSE_EDIT_HEADERS "edit the message with headers"
27
OP_COMPOSE_EDIT_MESSAGE "edit the message"
29
OP_COMPOSE_EDIT_MESSAGE "edit the message"
28
OP_COMPOSE_EDIT_MIME "edit attachment using mailcap entry"
30
OP_COMPOSE_EDIT_MIME "edit attachment using mailcap entry"
31
OP_COMPOSE_EDIT_NEWSGROUPS "edit the newsgroups list"
29
OP_COMPOSE_EDIT_REPLY_TO "edit the Reply-To field"
32
OP_COMPOSE_EDIT_REPLY_TO "edit the Reply-To field"
33
OP_COMPOSE_EDIT_FOLLOWUP_TO "edit the Followup-To field"
34
OP_COMPOSE_EDIT_X_COMMENT_TO "edit the X-Comment-To field"
30
OP_COMPOSE_EDIT_SUBJECT "edit the subject of this message"
35
OP_COMPOSE_EDIT_SUBJECT "edit the subject of this message"
31
OP_COMPOSE_EDIT_TO "edit the TO list"
36
OP_COMPOSE_EDIT_TO "edit the TO list"
32
OP_CREATE_MAILBOX "create a new mailbox (IMAP only)"
37
OP_CREATE_MAILBOX "create a new mailbox (IMAP only)"
Lines 85-92 OP_EXIT "exit this menu" Link Here
85
OP_FILTER "filter attachment through a shell command"
90
OP_FILTER "filter attachment through a shell command"
86
OP_FIRST_ENTRY "move to the first entry"
91
OP_FIRST_ENTRY "move to the first entry"
87
OP_FLAG_MESSAGE "toggle a message's 'important' flag"
92
OP_FLAG_MESSAGE "toggle a message's 'important' flag"
93
OP_FOLLOWUP "followup to newsgroup"
94
OP_FORWARD_TO_GROUP "forward to newsgroup"
88
OP_FORWARD_MESSAGE "forward a message with comments"
95
OP_FORWARD_MESSAGE "forward a message with comments"
89
OP_GENERIC_SELECT_ENTRY "select the current entry"
96
OP_GENERIC_SELECT_ENTRY "select the current entry"
97
OP_GET_CHILDREN "get all children of the current message"
98
OP_GET_MESSAGE "get message with Message-Id"
99
OP_GET_PARENT "get parent of the current message"
90
OP_GROUP_REPLY "reply to all recipients"
100
OP_GROUP_REPLY "reply to all recipients"
91
OP_HALF_DOWN "scroll down 1/2 page"
101
OP_HALF_DOWN "scroll down 1/2 page"
92
OP_HALF_UP "scroll up 1/2 page"
102
OP_HALF_UP "scroll up 1/2 page"
Lines 94-104 OP_HELP "this screen" Link Here
94
OP_JUMP "jump to an index number"
104
OP_JUMP "jump to an index number"
95
OP_LAST_ENTRY "move to the last entry"
105
OP_LAST_ENTRY "move to the last entry"
96
OP_LIST_REPLY "reply to specified mailing list"
106
OP_LIST_REPLY "reply to specified mailing list"
107
OP_LOAD_ACTIVE "load active file from NNTP server"
97
OP_MACRO "execute a macro"
108
OP_MACRO "execute a macro"
98
OP_MAIL "compose a new mail message"
109
OP_MAIL "compose a new mail message"
99
OP_MAIN_BREAK_THREAD "break the thread in two"
110
OP_MAIN_BREAK_THREAD "break the thread in two"
100
OP_MAIN_CHANGE_FOLDER "open a different folder"
111
OP_MAIN_CHANGE_FOLDER "open a different folder"
101
OP_MAIN_CHANGE_FOLDER_READONLY "open a different folder in read only mode"
112
OP_MAIN_CHANGE_FOLDER_READONLY "open a different folder in read only mode"
113
OP_MAIN_CHANGE_GROUP "open a different newsgroup"
114
OP_MAIN_CHANGE_GROUP_READONLY "open a different newsgroup in read only mode"
102
OP_MAIN_CLEAR_FLAG "clear a status flag from a message"
115
OP_MAIN_CLEAR_FLAG "clear a status flag from a message"
103
OP_MAIN_DELETE_PATTERN "delete messages matching a pattern"
116
OP_MAIN_DELETE_PATTERN "delete messages matching a pattern"
104
OP_MAIN_IMAP_FETCH "force retrieval of mail from IMAP server"
117
OP_MAIN_IMAP_FETCH "force retrieval of mail from IMAP server"
Lines 137-142 OP_PAGER_HIDE_QUOTED "toggle display of Link Here
137
OP_PAGER_SKIP_QUOTED "skip beyond quoted text"
150
OP_PAGER_SKIP_QUOTED "skip beyond quoted text"
138
OP_PAGER_TOP "jump to the top of the message"
151
OP_PAGER_TOP "jump to the top of the message"
139
OP_PIPE "pipe message/attachment to a shell command"
152
OP_PIPE "pipe message/attachment to a shell command"
153
OP_POST "post message to newsgroup"
140
OP_PREV_ENTRY "move to the previous entry"
154
OP_PREV_ENTRY "move to the previous entry"
141
OP_PREV_LINE "scroll up one line"
155
OP_PREV_LINE "scroll up one line"
142
OP_PREV_PAGE "move to the previous page"
156
OP_PREV_PAGE "move to the previous page"
Lines 145-150 OP_QUERY "query external program for add Link Here
145
OP_QUERY_APPEND "append new query results to current results"
159
OP_QUERY_APPEND "append new query results to current results"
146
OP_QUIT "save changes to mailbox and quit"
160
OP_QUIT "save changes to mailbox and quit"
147
OP_RECALL_MESSAGE "recall a postponed message"
161
OP_RECALL_MESSAGE "recall a postponed message"
162
OP_RECONSTRUCT_THREAD "reconstruct thread containing current message"
148
OP_REDRAW "clear and redraw the screen"
163
OP_REDRAW "clear and redraw the screen"
149
OP_REFORMAT_WINCH "{internal}"
164
OP_REFORMAT_WINCH "{internal}"
150
OP_RENAME_MAILBOX "rename the current mailbox (IMAP only)"
165
OP_RENAME_MAILBOX "rename the current mailbox (IMAP only)"
Lines 159-176 OP_SEARCH_TOGGLE "toggle search pattern Link Here
159
OP_SHELL_ESCAPE "invoke a command in a subshell"
174
OP_SHELL_ESCAPE "invoke a command in a subshell"
160
OP_SORT "sort messages"
175
OP_SORT "sort messages"
161
OP_SORT_REVERSE "sort messages in reverse order"
176
OP_SORT_REVERSE "sort messages in reverse order"
177
OP_SUBSCRIBE_PATTERN "subscribe to newsgroups matching a pattern"
162
OP_TAG "tag the current entry"
178
OP_TAG "tag the current entry"
163
OP_TAG_PREFIX "apply next function to tagged messages"
179
OP_TAG_PREFIX "apply next function to tagged messages"
164
OP_TAG_PREFIX_COND "apply next function ONLY to tagged messages"
180
OP_TAG_PREFIX_COND "apply next function ONLY to tagged messages"
165
OP_TAG_SUBTHREAD "tag the current subthread"
181
OP_TAG_SUBTHREAD "tag the current subthread"
166
OP_TAG_THREAD "tag the current thread"
182
OP_TAG_THREAD "tag the current thread"
167
OP_TOGGLE_NEW "toggle a message's 'new' flag"
183
OP_TOGGLE_NEW "toggle a message's 'new' flag"
184
OP_TOGGLE_READ "toggle view of read messages"
168
OP_TOGGLE_WRITE "toggle whether the mailbox will be rewritten"
185
OP_TOGGLE_WRITE "toggle whether the mailbox will be rewritten"
169
OP_TOGGLE_MAILBOXES "toggle whether to browse mailboxes or all files"
186
OP_TOGGLE_MAILBOXES "toggle whether to browse mailboxes or all files"
170
OP_TOP_PAGE "move to the top of the page"
187
OP_TOP_PAGE "move to the top of the page"
188
OP_UNCATCHUP "mark all articles in newsgroup as unread"
171
OP_UNDELETE "undelete the current entry"
189
OP_UNDELETE "undelete the current entry"
172
OP_UNDELETE_THREAD "undelete all messages in thread"
190
OP_UNDELETE_THREAD "undelete all messages in thread"
173
OP_UNDELETE_SUBTHREAD "undelete all messages in subthread"
191
OP_UNDELETE_SUBTHREAD "undelete all messages in subthread"
192
OP_UNSUBSCRIBE_PATTERN "unsubscribe from newsgroups matching a pattern"
174
OP_VERSION "show the Mutt version number and date"
193
OP_VERSION "show the Mutt version number and date"
175
OP_VIEW_ATTACH "view attachment using mailcap entry if necessary"
194
OP_VIEW_ATTACH "view attachment using mailcap entry if necessary"
176
OP_VIEW_ATTACHMENTS "show MIME attachments"
195
OP_VIEW_ATTACHMENTS "show MIME attachments"
(-)mutt-1.5.17.orig/PATCHES (+1 lines)
Line 0 Link Here
1
vvv.nntp
(-)mutt-1.5.17.orig/account.c (+23 lines)
Lines 54-59 int mutt_account_match (const ACCOUNT* a Link Here
54
    user = PopUser;
54
    user = PopUser;
55
#endif
55
#endif
56
  
56
  
57
#ifdef USE_NNTP
58
  if (a1->type == M_ACCT_TYPE_NNTP && NntpUser)
59
    user = NntpUser;
60
#endif
61
57
  if (a1->flags & a2->flags & M_ACCT_USER)
62
  if (a1->flags & a2->flags & M_ACCT_USER)
58
    return (!strcmp (a1->user, a2->user));
63
    return (!strcmp (a1->user, a2->user));
59
  if (a1->flags & M_ACCT_USER)
64
  if (a1->flags & M_ACCT_USER)
Lines 133-138 void mutt_account_tourl (ACCOUNT* accoun Link Here
133
  }
138
  }
134
#endif
139
#endif
135
140
141
#ifdef USE_NNTP
142
  if (account->type == M_ACCT_TYPE_NNTP)
143
  {
144
    if (account->flags & M_ACCT_SSL)
145
      url->scheme = U_NNTPS;
146
    else
147
      url->scheme = U_NNTP;
148
  }
149
#endif
150
136
  url->host = account->host;
151
  url->host = account->host;
137
  if (account->flags & M_ACCT_PORT)
152
  if (account->flags & M_ACCT_PORT)
138
    url->port = account->port;
153
    url->port = account->port;
Lines 158-163 int mutt_account_getuser (ACCOUNT* accou Link Here
158
  else if ((account->type == M_ACCT_TYPE_POP) && PopUser)
173
  else if ((account->type == M_ACCT_TYPE_POP) && PopUser)
159
    strfcpy (account->user, PopUser, sizeof (account->user));
174
    strfcpy (account->user, PopUser, sizeof (account->user));
160
#endif
175
#endif
176
#ifdef USE_NNTP
177
  else if ((account->type == M_ACCT_TYPE_NNTP) && NntpUser)
178
    strfcpy (account->user, NntpUser, sizeof (account->user));
179
#endif
161
  /* prompt (defaults to unix username), copy into account->user */
180
  /* prompt (defaults to unix username), copy into account->user */
162
  else
181
  else
163
  {
182
  {
Lines 218-223 int mutt_account_getpass (ACCOUNT* accou Link Here
218
  else if ((account->type == M_ACCT_TYPE_SMTP) && SmtpPass)
237
  else if ((account->type == M_ACCT_TYPE_SMTP) && SmtpPass)
219
    strfcpy (account->pass, SmtpPass, sizeof (account->pass));
238
    strfcpy (account->pass, SmtpPass, sizeof (account->pass));
220
#endif
239
#endif
240
#ifdef USE_NNTP
241
  else if ((account->type == M_ACCT_TYPE_NNTP) && NntpPass)
242
    strfcpy (account->pass, NntpPass, sizeof (account->pass));
243
#endif
221
  else
244
  else
222
  {
245
  {
223
    snprintf (prompt, sizeof (prompt), _("Password for %s@%s: "),
246
    snprintf (prompt, sizeof (prompt), _("Password for %s@%s: "),
(-)mutt-1.5.17.orig/account.h (-1 / +2 lines)
Lines 29-35 enum Link Here
29
  M_ACCT_TYPE_NONE = 0,
29
  M_ACCT_TYPE_NONE = 0,
30
  M_ACCT_TYPE_IMAP,
30
  M_ACCT_TYPE_IMAP,
31
  M_ACCT_TYPE_POP,
31
  M_ACCT_TYPE_POP,
32
  M_ACCT_TYPE_SMTP
32
  M_ACCT_TYPE_SMTP,
33
  M_ACCT_TYPE_NNTP
33
};
34
};
34
35
35
/* account flags */
36
/* account flags */
(-)mutt-1.5.17.orig/attach.h (-1 / +1 lines)
Lines 50-56 void mutt_print_attachment_list (FILE *f Link Here
50
50
51
void mutt_attach_bounce (FILE *, HEADER *, ATTACHPTR **, short, BODY *);
51
void mutt_attach_bounce (FILE *, HEADER *, ATTACHPTR **, short, BODY *);
52
void mutt_attach_resend (FILE *, HEADER *, ATTACHPTR **, short, BODY *);
52
void mutt_attach_resend (FILE *, HEADER *, ATTACHPTR **, short, BODY *);
53
void mutt_attach_forward (FILE *, HEADER *, ATTACHPTR **, short, BODY *);
53
void mutt_attach_forward (FILE *, HEADER *, ATTACHPTR **, short, BODY *, int);
54
void mutt_attach_reply (FILE *, HEADER *, ATTACHPTR **, short, BODY *, int);
54
void mutt_attach_reply (FILE *, HEADER *, ATTACHPTR **, short, BODY *, int);
55
55
56
#endif /* _ATTACH_H_ */
56
#endif /* _ATTACH_H_ */
(-)mutt-1.5.17.orig/browser.c (-14 / +431 lines)
Lines 32-37 Link Here
32
#ifdef USE_IMAP
32
#ifdef USE_IMAP
33
#include "imap.h"
33
#include "imap.h"
34
#endif
34
#endif
35
#ifdef USE_NNTP
36
#include "nntp.h"
37
#endif
35
38
36
#include <stdlib.h>
39
#include <stdlib.h>
37
#include <dirent.h>
40
#include <dirent.h>
Lines 49-54 static struct mapping_t FolderHelp[] = { Link Here
49
  { NULL }
52
  { NULL }
50
};
53
};
51
54
55
#ifdef USE_NNTP
56
static struct mapping_t FolderNewsHelp[] = {
57
  { N_("Exit"),        OP_EXIT },
58
  { N_("List"),        OP_TOGGLE_MAILBOXES },
59
  { N_("Subscribe"),   OP_BROWSER_SUBSCRIBE },
60
  { N_("Unsubscribe"), OP_BROWSER_UNSUBSCRIBE },
61
  { N_("Catchup"),     OP_CATCHUP },
62
  { N_("Mask"),        OP_ENTER_MASK },
63
  { N_("Help"),        OP_HELP },
64
  { NULL }
65
};
66
#endif
67
52
typedef struct folder_t
68
typedef struct folder_t
53
{
69
{
54
  struct folder_file *ff;
70
  struct folder_file *ff;
Lines 114-122 static void browser_sort (struct browser Link Here
114
    case SORT_ORDER:
130
    case SORT_ORDER:
115
      return;
131
      return;
116
    case SORT_DATE:
132
    case SORT_DATE:
133
#ifdef USE_NNTP
134
      if (option (OPTNEWS))
135
	return;
136
#endif
117
      f = browser_compare_date;
137
      f = browser_compare_date;
118
      break;
138
      break;
119
    case SORT_SIZE:
139
    case SORT_SIZE:
140
#ifdef USE_NNTP
141
      if (option (OPTNEWS))
142
	return;
143
#endif
120
      f = browser_compare_size;
144
      f = browser_compare_size;
121
      break;
145
      break;
122
    case SORT_SUBJECT:
146
    case SORT_SUBJECT:
Lines 307-314 folder_format_str (char *dest, size_t de Link Here
307
  return (src);
331
  return (src);
308
}
332
}
309
333
334
#ifdef USE_NNTP
335
static const char *
336
newsgroup_format_str (char *dest, size_t destlen, size_t col, char op, const char *src,
337
		       const char *fmt, const char *ifstring, const char *elsestring,
338
		       unsigned long data, format_flag flags)
339
{
340
  char fn[SHORT_STRING], tmp[SHORT_STRING];
341
  FOLDER *folder = (FOLDER *) data;
342
343
  switch (op)
344
  {
345
    case 'C':
346
      snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
347
      snprintf (dest, destlen, tmp, folder->num + 1);
348
      break;
349
      
350
    case 'f':
351
      strncpy (fn, folder->ff->name, sizeof(fn) - 1);
352
      snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
353
      snprintf (dest, destlen, tmp, fn);
354
      break;
355
356
    case 'N':
357
      snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
358
      if (folder->ff->nd->subscribed)
359
	snprintf (dest, destlen, tmp, ' ');
360
      else
361
	snprintf (dest, destlen, tmp, folder->ff->new ? 'N' : 'u');
362
      break;
363
364
    case 'M':
365
      snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
366
      if (folder->ff->nd->deleted)
367
	snprintf (dest, destlen, tmp, 'D');
368
      else
369
	snprintf (dest, destlen, tmp, folder->ff->nd->allowed ? ' ' : '-');
370
      break;
371
372
    case 's':
373
      if (flags & M_FORMAT_OPTIONAL)
374
      {
375
	if (folder->ff->nd->unread != 0)
376
	  mutt_FormatString (dest, destlen, col, ifstring, newsgroup_format_str,
377
		data, flags);
378
	else
379
	  mutt_FormatString (dest, destlen, col, elsestring, newsgroup_format_str,
380
		data, flags);
381
      }
382
      else if (Context && Context->data == folder->ff->nd)
383
      {
384
	snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
385
	snprintf (dest, destlen, tmp, Context->unread);
386
      }
387
      else
388
      {
389
	snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
390
	snprintf (dest, destlen, tmp, folder->ff->nd->unread);
391
      }
392
      break;
393
394
    case 'n':
395
      if (Context && Context->data == folder->ff->nd)
396
      {
397
	snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
398
	snprintf (dest, destlen, tmp, Context->new);
399
      }
400
      else if (option (OPTMARKOLD) &&
401
		folder->ff->nd->lastCached >= folder->ff->nd->firstMessage &&
402
		folder->ff->nd->lastCached <= folder->ff->nd->lastMessage)
403
      {
404
	snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
405
	snprintf (dest, destlen, tmp, folder->ff->nd->lastMessage - folder->ff->nd->lastCached);
406
      }
407
      else
408
      {
409
	snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
410
	snprintf (dest, destlen, tmp, folder->ff->nd->unread);
411
      }
412
      break;
413
414
    case 'd':
415
      if (folder->ff->nd->desc != NULL)
416
      {
417
	snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
418
	snprintf (dest, destlen, tmp, folder->ff->nd->desc);
419
      }
420
      else
421
      {
422
	snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
423
	snprintf (dest, destlen, tmp, "");
424
      }
425
      break;
426
  }
427
  return (src);
428
}
429
#endif /* USE_NNTP */
430
310
static void add_folder (MUTTMENU *m, struct browser_state *state,
431
static void add_folder (MUTTMENU *m, struct browser_state *state,
311
			const char *name, const struct stat *s, int new)
432
			const char *name, const struct stat *s,
433
			void *data, int new)
312
{
434
{
313
  if (state->entrylen == state->entrymax)
435
  if (state->entrylen == state->entrymax)
314
  {
436
  {
Lines 337-342 static void add_folder (MUTTMENU *m, str Link Here
337
#ifdef USE_IMAP
459
#ifdef USE_IMAP
338
  (state->entry)[state->entrylen].imap = 0;
460
  (state->entry)[state->entrylen].imap = 0;
339
#endif
461
#endif
462
#ifdef USE_NNTP
463
  if (option (OPTNEWS))
464
    (state->entry)[state->entrylen].nd = (NNTP_DATA *) data;
465
#endif
340
  (state->entrylen)++;
466
  (state->entrylen)++;
341
}
467
}
342
468
Lines 352-360 static void init_state (struct browser_s Link Here
352
    menu->data = state->entry;
478
    menu->data = state->entry;
353
}
479
}
354
480
481
/* get list of all files/newsgroups with mask */
355
static int examine_directory (MUTTMENU *menu, struct browser_state *state,
482
static int examine_directory (MUTTMENU *menu, struct browser_state *state,
356
			      char *d, const char *prefix)
483
			      char *d, const char *prefix)
357
{
484
{
485
#ifdef USE_NNTP
486
  if (option (OPTNEWS))
487
  {
488
    LIST *tmp;
489
    NNTP_DATA *data;
490
    NNTP_SERVER *news = CurrentNewsSrv;
491
492
/*  mutt_buffy_check (0); */
493
    init_state (state, menu);
494
495
    for (tmp = news->list; tmp; tmp = tmp->next)
496
    {
497
      if (!(data = (NNTP_DATA *)tmp->data))
498
	continue;
499
      if (prefix && *prefix && strncmp (prefix, data->group,
500
	    strlen (prefix)) != 0)
501
	continue;
502
      if (!((regexec (Mask.rx, data->group, 0, NULL, 0) == 0) ^ Mask.not))
503
	continue;
504
      add_folder (menu, state, data->group, NULL, data, data->new);
505
    }
506
  }
507
  else
508
#endif /* USE_NNTP */
509
  {
358
  struct stat s;
510
  struct stat s;
359
  DIR *dp;
511
  DIR *dp;
360
  struct dirent *de;
512
  struct dirent *de;
Lines 415-431 static int examine_directory (MUTTMENU * Link Here
415
    tmp = Incoming;
567
    tmp = Incoming;
416
    while (tmp && mutt_strcmp (buffer, tmp->path))
568
    while (tmp && mutt_strcmp (buffer, tmp->path))
417
      tmp = tmp->next;
569
      tmp = tmp->next;
418
    add_folder (menu, state, de->d_name, &s, (tmp) ? tmp->new : 0);
570
    add_folder (menu, state, de->d_name, &s, NULL, (tmp) ? tmp->new : 0);
571
  }
572
  closedir (dp);
419
  }
573
  }
420
  closedir (dp);  
421
  browser_sort (state);
574
  browser_sort (state);
422
  return 0;
575
  return 0;
423
}
576
}
424
577
578
/* get list of mailboxes/subscribed newsgroups */
425
static int examine_mailboxes (MUTTMENU *menu, struct browser_state *state)
579
static int examine_mailboxes (MUTTMENU *menu, struct browser_state *state)
426
{
580
{
427
  struct stat s;
581
  struct stat s;
428
  char buffer[LONG_STRING];
582
  char buffer[LONG_STRING];
583
584
#ifdef USE_NNTP
585
  if (option (OPTNEWS))
586
  {
587
    LIST *tmp;
588
    NNTP_DATA *data;
589
    NNTP_SERVER *news = CurrentNewsSrv;
590
591
/*  mutt_buffy_check (0); */
592
    init_state (state, menu);
593
594
    for (tmp = news->list; tmp; tmp = tmp->next)
595
    {
596
      if ((data = (NNTP_DATA *) tmp->data) != NULL && (data->new ||
597
	  (data->subscribed && (!option (OPTSHOWONLYUNREAD) || data->unread))))
598
        add_folder (menu, state, data->group, NULL, data, data->new);
599
    }
600
  }
601
  else
602
#endif
603
  {
429
  BUFFY *tmp = Incoming;
604
  BUFFY *tmp = Incoming;
430
#ifdef USE_IMAP
605
#ifdef USE_IMAP
431
  struct mailbox_state mbox;
606
  struct mailbox_state mbox;
Lines 443-456 static int examine_mailboxes (MUTTMENU * Link Here
443
    if (mx_is_imap (tmp->path))
618
    if (mx_is_imap (tmp->path))
444
    {
619
    {
445
      imap_mailbox_state (tmp->path, &mbox);
620
      imap_mailbox_state (tmp->path, &mbox);
446
      add_folder (menu, state, tmp->path, NULL, mbox.new);
621
      add_folder (menu, state, tmp->path, NULL, NULL, mbox.new);
447
      continue;
622
      continue;
448
    }
623
    }
449
#endif
624
#endif
450
#ifdef USE_POP
625
#ifdef USE_POP
451
    if (mx_is_pop (tmp->path))
626
    if (mx_is_pop (tmp->path))
452
    {
627
    {
453
      add_folder (menu, state, tmp->path, NULL, tmp->new);
628
      add_folder (menu, state, tmp->path, NULL, NULL, tmp->new);
629
      continue;
630
    }
631
#endif
632
#ifdef USE_NNTP
633
    if (mx_is_nntp (tmp->path))
634
    {
635
      add_folder (menu, state, tmp->path, NULL, NULL, tmp->new);
454
      continue;
636
      continue;
455
    }
637
    }
456
#endif
638
#endif
Lines 464-478 static int examine_mailboxes (MUTTMENU * Link Here
464
    strfcpy (buffer, NONULL(tmp->path), sizeof (buffer));
646
    strfcpy (buffer, NONULL(tmp->path), sizeof (buffer));
465
    mutt_pretty_mailbox (buffer);
647
    mutt_pretty_mailbox (buffer);
466
648
467
    add_folder (menu, state, buffer, &s, tmp->new);
649
    add_folder (menu, state, buffer, &s, NULL, tmp->new);
468
  }
650
  }
469
  while ((tmp = tmp->next));
651
  while ((tmp = tmp->next));
652
  }
470
  browser_sort (state);
653
  browser_sort (state);
471
  return 0;
654
  return 0;
472
}
655
}
473
656
474
static int select_file_search (MUTTMENU *menu, regex_t *re, int n)
657
static int select_file_search (MUTTMENU *menu, regex_t *re, int n)
475
{
658
{
659
#ifdef USE_NNTP
660
  if (option (OPTNEWS))
661
    return (regexec (re, ((struct folder_file *) menu->data)[n].desc, 0, NULL, 0));
662
#endif
476
  return (regexec (re, ((struct folder_file *) menu->data)[n].name, 0, NULL, 0));
663
  return (regexec (re, ((struct folder_file *) menu->data)[n].name, 0, NULL, 0));
477
}
664
}
478
665
Lines 483-488 static void folder_entry (char *s, size_ Link Here
483
  folder.ff = &((struct folder_file *) menu->data)[num];
670
  folder.ff = &((struct folder_file *) menu->data)[num];
484
  folder.num = num;
671
  folder.num = num;
485
  
672
  
673
#ifdef USE_NNTP
674
  if (option (OPTNEWS))
675
    mutt_FormatString (s, slen, 0, NONULL(GroupFormat), newsgroup_format_str, 
676
      (unsigned long) &folder, M_FORMAT_ARROWCURSOR);
677
  else
678
#endif
486
  mutt_FormatString (s, slen, 0, NONULL(FolderFormat), folder_format_str, 
679
  mutt_FormatString (s, slen, 0, NONULL(FolderFormat), folder_format_str, 
487
      (unsigned long) &folder, M_FORMAT_ARROWCURSOR);
680
      (unsigned long) &folder, M_FORMAT_ARROWCURSOR);
488
}
681
}
Lines 503-508 static void init_menu (struct browser_st Link Here
503
696
504
  menu->tagged = 0;
697
  menu->tagged = 0;
505
  
698
  
699
#ifdef USE_NNTP
700
  if (option (OPTNEWS))
701
  {
702
    if (buffy)
703
      snprintf (title, titlelen, _("Subscribed newsgroups"));
704
    else
705
      snprintf (title, titlelen, _("Newsgroups on server [%s]"),
706
		CurrentNewsSrv->conn->account.host);
707
  }
708
  else
709
#endif
506
  if (buffy)
710
  if (buffy)
507
    snprintf (title, titlelen, _("Mailboxes [%d]"), mutt_buffy_check (0));
711
    snprintf (title, titlelen, _("Mailboxes [%d]"), mutt_buffy_check (0));
508
  else
712
  else
Lines 558-563 void _mutt_select_file (char *f, size_t Link Here
558
  if (!folder)
762
  if (!folder)
559
    strfcpy (LastDirBackup, LastDir, sizeof (LastDirBackup));
763
    strfcpy (LastDirBackup, LastDir, sizeof (LastDirBackup));
560
764
765
#ifdef USE_NNTP
766
  if (option (OPTNEWS))
767
  {
768
    if (*f)
769
      strfcpy (prefix, f, sizeof (prefix));
770
    else
771
    {
772
      LIST *list;
773
774
      /* default state for news reader mode is browse subscribed newsgroups */
775
      buffy = 0;
776
      for (list = CurrentNewsSrv->list; list; list = list->next)
777
      {
778
	NNTP_DATA *data = (NNTP_DATA *) list->data;
779
780
	if (data && data->subscribed)
781
	{
782
	  buffy = 1;
783
	  break;
784
	}
785
      }
786
    }
787
  }
788
  else
789
#endif
561
  if (*f)
790
  if (*f)
562
  {
791
  {
563
    mutt_expand_path (f, flen);
792
    mutt_expand_path (f, flen);
Lines 655-660 void _mutt_select_file (char *f, size_t Link Here
655
    menu->tag = file_tag;
884
    menu->tag = file_tag;
656
885
657
  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_FOLDER,
886
  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_FOLDER,
887
#ifdef USE_NNTP
888
    (option (OPTNEWS)) ? FolderNewsHelp :
889
#endif
658
    FolderHelp);
890
    FolderHelp);
659
891
660
  init_menu (&state, menu, title, sizeof (title), buffy);
892
  init_menu (&state, menu, title, sizeof (title), buffy);
Lines 793-799 void _mutt_select_file (char *f, size_t Link Here
793
	  }
1025
	  }
794
	}
1026
	}
795
1027
1028
#ifdef USE_NNTP
1029
	if (buffy || option (OPTNEWS)) /* news have not path */
1030
#else
796
	if (buffy)
1031
	if (buffy)
1032
#endif
797
	{
1033
	{
798
	  strfcpy (f, state.entry[menu->current].name, flen);
1034
	  strfcpy (f, state.entry[menu->current].name, flen);
799
	  mutt_expand_path (f, flen);
1035
	  mutt_expand_path (f, flen);
Lines 851-864 void _mutt_select_file (char *f, size_t Link Here
851
        break;
1087
        break;
852
1088
853
#ifdef USE_IMAP
1089
#ifdef USE_IMAP
854
      case OP_BROWSER_SUBSCRIBE:
855
	imap_subscribe (state.entry[menu->current].name, 1);
856
	break;
857
858
      case OP_BROWSER_UNSUBSCRIBE:
859
	imap_subscribe (state.entry[menu->current].name, 0);
860
	break;
861
862
      case OP_BROWSER_TOGGLE_LSUB:
1090
      case OP_BROWSER_TOGGLE_LSUB:
863
	if (option (OPTIMAPLSUB))
1091
	if (option (OPTIMAPLSUB))
864
	{
1092
	{
Lines 957-962 void _mutt_select_file (char *f, size_t Link Here
957
      
1185
      
958
      case OP_CHANGE_DIRECTORY:
1186
      case OP_CHANGE_DIRECTORY:
959
1187
1188
#ifdef USE_NNTP
1189
	if (option (OPTNEWS))
1190
	  break;
1191
#endif
1192
960
	strfcpy (buf, LastDir, sizeof (buf));
1193
	strfcpy (buf, LastDir, sizeof (buf));
961
#ifdef USE_IMAP
1194
#ifdef USE_IMAP
962
	if (!state.imap_browse)
1195
	if (!state.imap_browse)
Lines 1223-1228 void _mutt_select_file (char *f, size_t Link Here
1223
	  else
1456
	  else
1224
	    mutt_error _("Error trying to view file");
1457
	    mutt_error _("Error trying to view file");
1225
	}
1458
	}
1459
	break;
1460
1461
#ifdef USE_NNTP
1462
      case OP_CATCHUP:
1463
      case OP_UNCATCHUP:
1464
	if (option (OPTNEWS))
1465
	{
1466
	  struct folder_file *f = &state.entry[menu->current];
1467
	  NNTP_DATA *nd;
1468
1469
	  if (i == OP_CATCHUP)
1470
	    nd = mutt_newsgroup_catchup (CurrentNewsSrv, f->name);
1471
	  else
1472
	    nd = mutt_newsgroup_uncatchup (CurrentNewsSrv, f->name);
1473
1474
	  if (nd)
1475
	  {
1476
/*	    FOLDER folder;
1477
	    struct folder_file ff;
1478
	    char buffer[_POSIX_PATH_MAX + SHORT_STRING];
1479
1480
	    folder.ff = &ff;
1481
	    folder.ff->name = f->name;
1482
	    folder.ff->st = NULL;
1483
	    folder.ff->is_new = nd->new;
1484
	    folder.ff->nd = nd;
1485
	    FREE (&f->desc);
1486
	    mutt_FormatString (buffer, sizeof (buffer), 0, NONULL(GroupFormat),
1487
		  newsgroup_format_str, (unsigned long) &folder,
1488
		  M_FORMAT_ARROWCURSOR);
1489
	    f->desc = safe_strdup (buffer); */
1490
	    if (menu->current + 1 < menu->max)
1491
	      menu->current++;
1492
	    menu->redraw = REDRAW_MOTION_RESYNCH;
1493
	  }
1494
	}
1495
	break;
1496
1497
      case OP_LOAD_ACTIVE:
1498
	if (!option (OPTNEWS))
1499
	  break;
1500
1501
	{
1502
	  LIST *tmp;
1503
	  NNTP_DATA *data;
1504
1505
	  for (tmp = CurrentNewsSrv->list; tmp; tmp = tmp->next)
1506
	  {
1507
	    if ((data = (NNTP_DATA *)tmp->data))
1508
	      data->deleted = 1;
1509
	  }
1510
	}
1511
	nntp_get_active (CurrentNewsSrv);
1512
1513
	destroy_state (&state);
1514
	if (buffy)
1515
	  examine_mailboxes (menu, &state);
1516
	else
1517
	  examine_directory (menu, &state, NULL, NULL);
1518
	init_menu (&state, menu, title, sizeof (title), buffy);
1519
	break;
1520
#endif /* USE_NNTP */
1521
1522
#if defined USE_IMAP || defined USE_NNTP
1523
      case OP_BROWSER_SUBSCRIBE:
1524
      case OP_BROWSER_UNSUBSCRIBE:
1525
#endif
1526
#ifdef USE_NNTP
1527
      case OP_SUBSCRIBE_PATTERN:
1528
      case OP_UNSUBSCRIBE_PATTERN:
1529
        if (option (OPTNEWS))
1530
	{
1531
	  regex_t *rx = (regex_t *) safe_malloc (sizeof (regex_t));
1532
	  char *s = buf;
1533
	  int j = menu->current;
1534
	  NNTP_DATA *nd;
1535
	  NNTP_SERVER *news = CurrentNewsSrv;
1536
1537
	  if (i == OP_SUBSCRIBE_PATTERN || i == OP_UNSUBSCRIBE_PATTERN)
1538
	  {
1539
	    char tmp[STRING];
1540
	    int err;
1541
1542
	    buf[0] = 0;
1543
	    if (i == OP_SUBSCRIBE_PATTERN)
1544
	      snprintf (tmp, sizeof (tmp), _("Subscribe pattern: "));
1545
	    else
1546
	      snprintf (tmp, sizeof (tmp), _("Unsubscribe pattern: "));
1547
	    if (mutt_get_field (tmp, buf, sizeof (buf), 0) != 0 || !buf[0])
1548
	    {
1549
	      FREE (&rx);
1550
	      break;
1551
	    }
1552
1553
	    if ((err = REGCOMP (rx, s, REG_NOSUB)) != 0)
1554
	    {
1555
	      regerror (err, rx, buf, sizeof (buf));
1556
	      regfree (rx);
1557
	      FREE (&rx);
1558
	      mutt_error ("%s", buf);
1559
	      break;
1560
	    }
1561
	    menu->redraw = REDRAW_FULL;
1562
	    j = 0;
1563
	  }
1564
	  else if (!state.entrylen)
1565
	  {
1566
	    mutt_error _("No newsgroups match the mask");
1567
	    break;
1568
	  }
1569
1570
	  for ( ; j < state.entrylen; j++)
1571
	  {
1572
	    struct folder_file *f = &state.entry[j];
1573
1574
	    if (i == OP_BROWSER_SUBSCRIBE || i == OP_BROWSER_UNSUBSCRIBE ||
1575
		  regexec (rx, f->name, 0, NULL, 0) == 0)
1576
	    {
1577
	      if (i == OP_BROWSER_SUBSCRIBE || i == OP_SUBSCRIBE_PATTERN)
1578
		nd = mutt_newsgroup_subscribe (news, f->name);
1579
	      else
1580
		nd = mutt_newsgroup_unsubscribe (news, f->name);
1581
/*	      if (nd)
1582
	      {
1583
		FOLDER folder;
1584
		char buffer[_POSIX_PATH_MAX + SHORT_STRING];
1585
1586
		folder.name = f->name;
1587
		folder.f = NULL;
1588
		folder.new = nd->new;
1589
		folder.nd = nd;
1590
		FREE (&f->desc);
1591
		mutt_FormatString (buffer, sizeof (buffer), 0, NONULL(GroupFormat),
1592
			newsgroup_format_str, (unsigned long) &folder,
1593
			M_FORMAT_ARROWCURSOR);
1594
		f->desc = safe_strdup (buffer);
1595
	      } */
1596
	    }
1597
	    if (i == OP_BROWSER_SUBSCRIBE || i == OP_BROWSER_UNSUBSCRIBE)
1598
	    {
1599
	      if (menu->current + 1 < menu->max)
1600
		menu->current++;
1601
	      menu->redraw = REDRAW_MOTION_RESYNCH;
1602
	      break;
1603
	    }
1604
	  }
1605
	  if (i == OP_SUBSCRIBE_PATTERN)
1606
	  {
1607
	    LIST *grouplist = NULL;
1608
1609
	    if (news)
1610
	      grouplist = news->list;
1611
	    for (; grouplist; grouplist = grouplist->next)
1612
	    {
1613
	      nd = (NNTP_DATA *) grouplist->data;
1614
	      if (nd && nd->group && !nd->subscribed)
1615
	      {
1616
		if (regexec (rx, nd->group, 0, NULL, 0) == 0)
1617
		{
1618
		  mutt_newsgroup_subscribe (news, nd->group);
1619
		  add_folder (menu, &state, nd->group, NULL, nd, nd->new);
1620
		}
1621
	      }
1622
	    }
1623
	    init_menu (&state, menu, title, sizeof (title), buffy);
1624
	  }
1625
	  mutt_newsrc_update (news);
1626
	  nntp_clear_cacheindex (news);
1627
	  if (i != OP_BROWSER_SUBSCRIBE && i != OP_BROWSER_UNSUBSCRIBE)
1628
	    regfree (rx);
1629
	  FREE (&rx);
1630
	}
1631
#ifdef USE_IMAP
1632
	else
1633
#endif /* USE_IMAP && USE_NNTP */
1634
#endif /* USE_NNTP */
1635
#ifdef USE_IMAP
1636
	{
1637
	  if (i == OP_BROWSER_SUBSCRIBE)
1638
	    imap_subscribe (state.entry[menu->current].name, 1);
1639
	  else
1640
	    imap_subscribe (state.entry[menu->current].name, 0);
1641
	}
1642
#endif /* USE_IMAP */
1226
    }
1643
    }
1227
  }
1644
  }
1228
  
1645
  
(-)mutt-1.5.17.orig/browser.h (-2 / +9 lines)
Lines 20-25 Link Here
20
#ifndef _BROWSER_H
20
#ifndef _BROWSER_H
21
#define _BROWSER_H 1
21
#define _BROWSER_H 1
22
22
23
#ifdef USE_NNTP
24
#include "nntp.h"
25
#endif
26
23
struct folder_file
27
struct folder_file
24
{
28
{
25
  mode_t mode;
29
  mode_t mode;
Lines 38-51 struct folder_file Link Here
38
  unsigned selectable : 1;
42
  unsigned selectable : 1;
39
  unsigned inferiors : 1;
43
  unsigned inferiors : 1;
40
#endif
44
#endif
45
#ifdef USE_NNTP
46
  NNTP_DATA *nd;
47
#endif
41
  unsigned tagged : 1;
48
  unsigned tagged : 1;
42
};
49
};
43
50
44
struct browser_state
51
struct browser_state
45
{
52
{
46
  struct folder_file *entry;
53
  struct folder_file *entry;
47
  short entrylen; /* number of real entries */
54
  unsigned int entrylen; /* number of real entries */
48
  short entrymax;  /* max entry */
55
  unsigned int entrymax; /* max entry */
49
#ifdef USE_IMAP
56
#ifdef USE_IMAP
50
  short imap_browse;
57
  short imap_browse;
51
  char *folder;
58
  char *folder;
(-)mutt-1.5.17.orig/buffy.c (-14 / +18 lines)
Lines 285-290 int mutt_buffy_check (int force) Link Here
285
#ifdef USE_POP
285
#ifdef USE_POP
286
  if (!Context || Context->magic != M_POP)
286
  if (!Context || Context->magic != M_POP)
287
#endif
287
#endif
288
#ifdef USE_NNTP
289
  if (!Context || Context->magic != M_NNTP)
290
#endif
288
  /* check device ID and serial number instead of comparing paths */
291
  /* check device ID and serial number instead of comparing paths */
289
  if (!Context || !Context->path || stat (Context->path, &contex_sb) != 0)
292
  if (!Context || !Context->path || stat (Context->path, &contex_sb) != 0)
290
  {
293
  {
Lines 308-313 int mutt_buffy_check (int force) Link Here
308
      tmp->magic = M_POP;
311
      tmp->magic = M_POP;
309
    else
312
    else
310
#endif
313
#endif
314
#ifdef USE_NNTP
315
    if ((tmp->magic == M_NNTP) || mx_is_nntp (tmp->path))
316
      tmp->magic = M_NNTP;
317
    else
318
#endif
311
    if (stat (tmp->path, &sb) != 0 || sb.st_size == 0 ||
319
    if (stat (tmp->path, &sb) != 0 || sb.st_size == 0 ||
312
	(!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0))
320
	(!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0))
313
    {
321
    {
Lines 325-349 int mutt_buffy_check (int force) Link Here
325
    /* check to see if the folder is the currently selected folder
333
    /* check to see if the folder is the currently selected folder
326
     * before polling */
334
     * before polling */
327
    if (!Context || !Context->path ||
335
    if (!Context || !Context->path ||
328
#if defined USE_IMAP || defined USE_POP
336
	 (
329
	((
337
	   (0
330
#ifdef USE_IMAP
338
#ifdef USE_IMAP
331
	tmp->magic == M_IMAP
339
	    || tmp->magic == M_IMAP
332
#endif
340
#endif
333
#ifdef USE_POP
341
#ifdef USE_POP
334
#ifdef USE_IMAP
342
	    || tmp->magic == M_POP
335
	||
336
#endif
337
	tmp->magic == M_POP
338
#endif
339
	) ? mutt_strcmp (tmp->path, Context->path) :
340
#endif
343
#endif
341
	 (sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino)
344
#ifdef USE_NNTP
342
#if defined USE_IMAP || defined USE_POP	 
345
	    || tmp->magic == M_NNTP
343
	    )
344
#endif
346
#endif
345
	)
347
	   ) ? mutt_strcmp (tmp->path, Context->path) :
346
	
348
	       (sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino)
349
	 )
350
       )
347
    {
351
    {
348
      switch (tmp->magic)
352
      switch (tmp->magic)
349
      {
353
      {
(-)mutt-1.5.17.orig/complete.c (+65 lines)
Lines 25-30 Link Here
25
#include "mailbox.h"
25
#include "mailbox.h"
26
#include "imap.h"
26
#include "imap.h"
27
#endif
27
#endif
28
#ifdef USE_NNTP
29
#include "nntp.h"
30
#endif
28
31
29
#include <dirent.h>
32
#include <dirent.h>
30
#include <string.h>
33
#include <string.h>
Lines 48-56 int mutt_complete (char *s, size_t slen) Link Here
48
  char filepart[_POSIX_PATH_MAX];
51
  char filepart[_POSIX_PATH_MAX];
49
#ifdef USE_IMAP
52
#ifdef USE_IMAP
50
  char imap_path[LONG_STRING];
53
  char imap_path[LONG_STRING];
54
#endif
51
55
52
  dprint (2, (debugfile, "mutt_complete: completing %s\n", s));
56
  dprint (2, (debugfile, "mutt_complete: completing %s\n", s));
53
57
58
#ifdef USE_NNTP
59
  if (option (OPTNEWS))
60
  {
61
    LIST *l = CurrentNewsSrv->list;
62
63
    strfcpy (filepart, s, sizeof (filepart));
64
65
    /*
66
     * special case to handle when there is no filepart yet.
67
     * find the first subscribed newsgroup
68
     */
69
    if ((len = mutt_strlen (filepart)) == 0)
70
    {
71
      for (; l; l = l->next)
72
      {
73
	NNTP_DATA *data = (NNTP_DATA *)l->data;
74
75
	if (data && data->subscribed)
76
	{
77
	  strfcpy (filepart, data->group, sizeof (filepart));
78
	  init++;
79
	  l = l->next;
80
	  break;
81
	}
82
      }
83
    }
84
85
    for (; l; l = l->next)
86
    {
87
      NNTP_DATA *data = (NNTP_DATA *)l->data;
88
89
      if (data && data->subscribed &&
90
	  mutt_strncmp (data->group, filepart, len) == 0)
91
      {
92
	if (init)
93
	{
94
	  for (i = 0; filepart[i] && data->group[i]; i++)
95
	  {
96
	    if (filepart[i] != data->group[i])
97
	    {
98
	      filepart[i] = 0;
99
	      break;
100
	    }
101
	  }
102
	  filepart[i] = 0;
103
	}
104
	else
105
	{
106
	  strfcpy (filepart, data->group, sizeof (filepart));
107
	  init = 1;
108
	}
109
      }
110
    }
111
112
    strcpy (s, filepart);
113
114
    return (init ? 0 : -1);
115
  }
116
#endif
117
118
#ifdef USE_IMAP
54
  /* we can use '/' as a delimiter, imap_complete rewrites it */
119
  /* we can use '/' as a delimiter, imap_complete rewrites it */
55
  if (*s == '=' || *s == '+' || *s == '!')
120
  if (*s == '=' || *s == '+' || *s == '!')
56
  {
121
  {
(-)mutt-1.5.17.orig/compose.c (-10 / +170 lines)
Lines 32-41 Link Here
32
#include "mailbox.h"
32
#include "mailbox.h"
33
#include "sort.h"
33
#include "sort.h"
34
#include "charset.h"
34
#include "charset.h"
35
#include "mx.h"
35
36
36
#ifdef MIXMASTER
37
#ifdef MIXMASTER
37
#include "remailer.h"
38
#include "remailer.h"
38
#endif
39
#endif
40
  
41
#ifdef USE_NNTP
42
#include "nntp.h"
43
#endif
39
44
40
#include <errno.h>
45
#include <errno.h>
41
#include <string.h>
46
#include <string.h>
Lines 60-77 enum Link Here
60
  HDR_REPLYTO,
65
  HDR_REPLYTO,
61
  HDR_FCC,
66
  HDR_FCC,
62
67
63
#ifdef MIXMASTER
64
  HDR_MIX,
65
#endif
66
68
67
  HDR_CRYPT,
69
  HDR_CRYPT,
68
  HDR_CRYPTINFO,
70
  HDR_CRYPTINFO,
69
71
72
#ifdef USE_NNTP
73
  HDR_NEWSGROUPS,
74
  HDR_FOLLOWUPTO,
75
  HDR_XCOMMENTTO,
76
#endif
77
70
  HDR_ATTACH  = (HDR_FCC + 5) /* where to start printing the attachments */
78
  HDR_ATTACH  = (HDR_FCC + 5) /* where to start printing the attachments */
71
};
79
};
72
80
73
#define HDR_XOFFSET 10
81
#define HDR_XOFFSET 14
74
#define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */
82
#define TITLE_FMT "%14s" /* Used for Prompts, which are ASCII */
75
#define W (COLS - HDR_XOFFSET)
83
#define W (COLS - HDR_XOFFSET)
76
84
77
static char *Prompts[] =
85
static char *Prompts[] =
Lines 83-88 static char *Prompts[] = Link Here
83
  "Subject: ",
91
  "Subject: ",
84
  "Reply-To: ",
92
  "Reply-To: ",
85
  "Fcc: "
93
  "Fcc: "
94
#ifdef USE_NNTP
95
#ifdef MIXMASTER
96
  ,""
97
#endif
98
  ,""
99
  ,""
100
  ,"Newsgroups: "
101
  ,"Followup-To: "
102
  ,"X-Comment-To: "
103
#endif
86
};
104
};
87
105
88
static struct mapping_t ComposeHelp[] = {
106
static struct mapping_t ComposeHelp[] = {
Lines 97-102 static struct mapping_t ComposeHelp[] = Link Here
97
  { NULL }
115
  { NULL }
98
};
116
};
99
117
118
#ifdef USE_NNTP
119
static struct mapping_t ComposeNewsHelp[] = {
120
  { N_("Send"),    OP_COMPOSE_SEND_MESSAGE },
121
  { N_("Abort"),   OP_EXIT },
122
  { "Newsgroups",  OP_COMPOSE_EDIT_NEWSGROUPS },
123
  { "Subj",        OP_COMPOSE_EDIT_SUBJECT },
124
  { N_("Attach file"),  OP_COMPOSE_ATTACH_FILE },
125
  { N_("Descrip"), OP_COMPOSE_EDIT_DESCRIPTION },
126
  { N_("Help"),    OP_HELP },
127
  { NULL }
128
};
129
#endif
130
100
static void snd_entry (char *b, size_t blen, MUTTMENU *menu, int num)
131
static void snd_entry (char *b, size_t blen, MUTTMENU *menu, int num)
101
{
132
{
102
    mutt_FormatString (b, blen, 0, NONULL (AttachFormat), mutt_attach_fmt,
133
    mutt_FormatString (b, blen, 0, NONULL (AttachFormat), mutt_attach_fmt,
Lines 115-130 static void redraw_crypt_lines (HEADER * Link Here
115
  if ((WithCrypto & APPLICATION_PGP) && (WithCrypto & APPLICATION_SMIME))
146
  if ((WithCrypto & APPLICATION_PGP) && (WithCrypto & APPLICATION_SMIME))
116
  {     
147
  {     
117
    if (!msg->security)
148
    if (!msg->security)
118
      mvaddstr (HDR_CRYPT, 0,     "Security: ");
149
      mvaddstr (HDR_CRYPT, 0,     "    Security: ");
119
    else if (msg->security & APPLICATION_SMIME)
150
    else if (msg->security & APPLICATION_SMIME)
120
      mvaddstr (HDR_CRYPT, 0,     "  S/MIME: ");
151
      mvaddstr (HDR_CRYPT, 0,     "      S/MIME: ");
121
    else if (msg->security & APPLICATION_PGP)
152
    else if (msg->security & APPLICATION_PGP)
122
      mvaddstr (HDR_CRYPT, 0,     "     PGP: ");
153
      mvaddstr (HDR_CRYPT, 0,     "         PGP: ");
123
  }
154
  }
124
  else if ((WithCrypto & APPLICATION_SMIME))
155
  else if ((WithCrypto & APPLICATION_SMIME))
125
    mvaddstr (HDR_CRYPT, 0,     "  S/MIME: ");
156
    mvaddstr (HDR_CRYPT, 0,     "      S/MIME: ");
126
  else if ((WithCrypto & APPLICATION_PGP))
157
  else if ((WithCrypto & APPLICATION_PGP))
127
    mvaddstr (HDR_CRYPT, 0,     "     PGP: ");
158
    mvaddstr (HDR_CRYPT, 0,     "         PGP: ");
128
  else
159
  else
129
    return;
160
    return;
130
161
Lines 252-260 static void draw_envelope_addr (int line Link Here
252
static void draw_envelope (HEADER *msg, char *fcc)
283
static void draw_envelope (HEADER *msg, char *fcc)
253
{
284
{
254
  draw_envelope_addr (HDR_FROM, msg->env->from);
285
  draw_envelope_addr (HDR_FROM, msg->env->from);
286
#ifdef USE_NNTP
287
  if (!option (OPTNEWSSEND))
288
  {
289
#endif
255
  draw_envelope_addr (HDR_TO, msg->env->to);
290
  draw_envelope_addr (HDR_TO, msg->env->to);
256
  draw_envelope_addr (HDR_CC, msg->env->cc);
291
  draw_envelope_addr (HDR_CC, msg->env->cc);
257
  draw_envelope_addr (HDR_BCC, msg->env->bcc);
292
  draw_envelope_addr (HDR_BCC, msg->env->bcc);
293
#ifdef USE_NNTP
294
  }
295
  else
296
  {
297
    mvprintw (HDR_TO, 0, TITLE_FMT , Prompts[HDR_NEWSGROUPS - 1]);
298
    mutt_paddstr (W, NONULL (msg->env->newsgroups));
299
    mvprintw (HDR_CC, 0, TITLE_FMT , Prompts[HDR_FOLLOWUPTO - 1]);
300
    mutt_paddstr (W, NONULL (msg->env->followup_to));
301
    if (option (OPTXCOMMENTTO))
302
    {
303
      mvprintw (HDR_BCC, 0, TITLE_FMT , Prompts[HDR_XCOMMENTTO - 1]);
304
      mutt_paddstr (W, NONULL (msg->env->x_comment_to));
305
    }
306
  }
307
#endif
258
  mvprintw (HDR_SUBJECT, 0, TITLE_FMT, Prompts[HDR_SUBJECT - 1]);
308
  mvprintw (HDR_SUBJECT, 0, TITLE_FMT, Prompts[HDR_SUBJECT - 1]);
259
  mutt_paddstr (W, NONULL (msg->env->subject));
309
  mutt_paddstr (W, NONULL (msg->env->subject));
260
  draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to);
310
  draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to);
Lines 507-512 int mutt_compose_menu (HEADER *msg, /* Link Here
507
  /* Sort, SortAux could be changed in mutt_index_menu() */
557
  /* Sort, SortAux could be changed in mutt_index_menu() */
508
  int oldSort, oldSortAux;
558
  int oldSort, oldSortAux;
509
  struct stat st;
559
  struct stat st;
560
#ifdef USE_NNTP
561
  int news = 0;               /* is it a news article ? */
562
563
  if (option (OPTNEWSSEND))
564
    news++;
565
#endif
510
566
511
  mutt_attach_init (msg->content);
567
  mutt_attach_init (msg->content);
512
  idx = mutt_gen_attach_list (msg->content, -1, idx, &idxlen, &idxmax, 0, 1);
568
  idx = mutt_gen_attach_list (msg->content, -1, idx, &idxlen, &idxmax, 0, 1);
Lines 518-527 int mutt_compose_menu (HEADER *msg, /* Link Here
518
  menu->make_entry = snd_entry;
574
  menu->make_entry = snd_entry;
519
  menu->tag = mutt_tag_attach;
575
  menu->tag = mutt_tag_attach;
520
  menu->data = idx;
576
  menu->data = idx;
577
#ifdef USE_NNTP
578
  if (news)
579
  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeNewsHelp);
580
  else
581
#endif
521
  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeHelp);
582
  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeHelp);
522
  
583
  
523
  while (loop)
584
  while (loop)
524
  {
585
  {
586
#ifdef USE_NNTP
587
    unset_option (OPTNEWS);	/* for any case */
588
#endif
525
    switch (op = mutt_menuLoop (menu))
589
    switch (op = mutt_menuLoop (menu))
526
    {
590
    {
527
      case OP_REDRAW:
591
      case OP_REDRAW:
Lines 534-550 int mutt_compose_menu (HEADER *msg, /* Link Here
534
        mutt_message_hook (NULL, msg, M_SEND2HOOK);
598
        mutt_message_hook (NULL, msg, M_SEND2HOOK);
535
	break;
599
	break;
536
      case OP_COMPOSE_EDIT_TO:
600
      case OP_COMPOSE_EDIT_TO:
601
#ifdef USE_NNTP
602
	if (news)
603
	  break;
604
#endif
537
	menu->redraw = edit_address_list (HDR_TO, &msg->env->to);
605
	menu->redraw = edit_address_list (HDR_TO, &msg->env->to);
538
        mutt_message_hook (NULL, msg, M_SEND2HOOK);
606
        mutt_message_hook (NULL, msg, M_SEND2HOOK);
539
        break;
607
        break;
540
      case OP_COMPOSE_EDIT_BCC:
608
      case OP_COMPOSE_EDIT_BCC:
609
#ifdef USE_NNTP
610
	if (news)
611
	  break;
612
#endif
541
	menu->redraw = edit_address_list (HDR_BCC, &msg->env->bcc);
613
	menu->redraw = edit_address_list (HDR_BCC, &msg->env->bcc);
542
        mutt_message_hook (NULL, msg, M_SEND2HOOK);
614
        mutt_message_hook (NULL, msg, M_SEND2HOOK);
543
	break;
615
	break;
544
      case OP_COMPOSE_EDIT_CC:
616
      case OP_COMPOSE_EDIT_CC:
617
#ifdef USE_NNTP
618
	if (news)
619
	  break;
620
#endif
545
	menu->redraw = edit_address_list (HDR_CC, &msg->env->cc);
621
	menu->redraw = edit_address_list (HDR_CC, &msg->env->cc);
546
        mutt_message_hook (NULL, msg, M_SEND2HOOK);	
622
        mutt_message_hook (NULL, msg, M_SEND2HOOK);	
547
        break;
623
        break;
624
#ifdef USE_NNTP
625
      case OP_COMPOSE_EDIT_NEWSGROUPS:
626
	if (news)
627
	{
628
	  if (msg->env->newsgroups)
629
	    strfcpy (buf, msg->env->newsgroups, sizeof (buf));
630
	  else
631
	    buf[0] = 0;
632
	  if (mutt_get_field ("Newsgroups: ", buf, sizeof (buf), 0) == 0 && buf[0])
633
	  {
634
	    FREE (&msg->env->newsgroups);
635
	    mutt_remove_trailing_ws (buf);
636
	    msg->env->newsgroups = safe_strdup (mutt_skip_whitespace (buf));
637
	    move (HDR_TO, HDR_XOFFSET);
638
	    clrtoeol ();
639
	    if (msg->env->newsgroups)
640
	      printw ("%-*.*s", W, W, msg->env->newsgroups);
641
	  }
642
	}
643
	break;
644
645
      case OP_COMPOSE_EDIT_FOLLOWUP_TO:
646
	if (news)
647
	{
648
	  buf[0] = 0;
649
	  if (msg->env->followup_to)
650
	    strfcpy (buf, msg->env->followup_to, sizeof (buf));
651
	  if (mutt_get_field ("Followup-To: ", buf, sizeof (buf), 0) == 0 && buf[0])
652
	  {
653
	    FREE (&msg->env->followup_to);
654
	    mutt_remove_trailing_ws (buf);
655
	    msg->env->followup_to = safe_strdup (mutt_skip_whitespace (buf));
656
	    move (HDR_CC, HDR_XOFFSET);
657
	    clrtoeol();
658
	    if (msg->env->followup_to)
659
	      printw ("%-*.*s", W, W, msg->env->followup_to);
660
	  }
661
	}
662
  	break;
663
664
      case OP_COMPOSE_EDIT_X_COMMENT_TO:
665
	if (news && option (OPTXCOMMENTTO))
666
	{
667
	  buf[0] = 0;
668
	  if (msg->env->x_comment_to)
669
	    strfcpy (buf, msg->env->x_comment_to, sizeof (buf));
670
	  if (mutt_get_field ("X-Comment-To: ", buf, sizeof (buf), 0) == 0 && buf[0])
671
	  {
672
	    FREE (&msg->env->x_comment_to);
673
	    msg->env->x_comment_to = safe_strdup (buf);
674
	    move (HDR_BCC, HDR_XOFFSET);
675
	    clrtoeol();
676
	    if (msg->env->x_comment_to)
677
	      printw ("%-*.*s", W, W, msg->env->x_comment_to);
678
	  }
679
	}
680
	break;
681
#endif
548
      case OP_COMPOSE_EDIT_SUBJECT:
682
      case OP_COMPOSE_EDIT_SUBJECT:
549
	if (msg->env->subject)
683
	if (msg->env->subject)
550
	  strfcpy (buf, msg->env->subject, sizeof (buf));
684
	  strfcpy (buf, msg->env->subject, sizeof (buf));
Lines 707-712 int mutt_compose_menu (HEADER *msg, /* Link Here
707
        break;
841
        break;
708
842
709
      case OP_COMPOSE_ATTACH_MESSAGE:
843
      case OP_COMPOSE_ATTACH_MESSAGE:
844
#ifdef USE_NNTP
845
      case OP_COMPOSE_ATTACH_NEWS_MESSAGE:
846
#endif
710
	{
847
	{
711
	  char *prompt;
848
	  char *prompt;
712
	  HEADER *h;
849
	  HEADER *h;
Lines 714-720 int mutt_compose_menu (HEADER *msg, /* Link Here
714
	  fname[0] = 0;
851
	  fname[0] = 0;
715
	  prompt = _("Open mailbox to attach message from");
852
	  prompt = _("Open mailbox to attach message from");
716
853
854
#ifdef USE_NNTP
855
	  unset_option (OPTNEWS);
856
	  if (op == OP_COMPOSE_ATTACH_NEWS_MESSAGE)
857
	  {
858
	    if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)))
859
	      break;
860
861
	    prompt = _("Open newsgroup to attach message from");
862
	    set_option (OPTNEWS);
863
	  }
864
#endif
865
717
	  if (Context)
866
	  if (Context)
867
#ifdef USE_NNTP
868
	  if ((op == OP_COMPOSE_ATTACH_MESSAGE) ^ (Context->magic == M_NNTP))
869
#endif
718
	  {
870
	  {
719
	    strfcpy (fname, NONULL (Context->path), sizeof (fname));
871
	    strfcpy (fname, NONULL (Context->path), sizeof (fname));
720
	    mutt_pretty_mailbox (fname);
872
	    mutt_pretty_mailbox (fname);
Lines 723-728 int mutt_compose_menu (HEADER *msg, /* Link Here
723
	  if (mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, 1) == -1 || !fname[0])
875
	  if (mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, 1) == -1 || !fname[0])
724
	    break;
876
	    break;
725
877
878
#ifdef USE_NNTP
879
	  if (option (OPTNEWS))
880
	    nntp_expand_path (fname, sizeof (fname), &CurrentNewsSrv->conn->account);
881
	  else
882
#endif
726
	  mutt_expand_path (fname, sizeof (fname));
883
	  mutt_expand_path (fname, sizeof (fname));
727
#ifdef USE_IMAP
884
#ifdef USE_IMAP
728
          if (!mx_is_imap (fname))
885
          if (!mx_is_imap (fname))
Lines 730-735 int mutt_compose_menu (HEADER *msg, /* Link Here
730
#ifdef USE_POP
887
#ifdef USE_POP
731
          if (!mx_is_pop (fname))
888
          if (!mx_is_pop (fname))
732
#endif
889
#endif
890
#ifdef USE_NNTP
891
          if (!mx_is_nntp (fname) && !option (OPTNEWS))
892
#endif
733
	  /* check to make sure the file exists and is readable */
893
	  /* check to make sure the file exists and is readable */
734
	  if (access (fname, R_OK) == -1)
894
	  if (access (fname, R_OK) == -1)
735
	  {
895
	  {
(-)mutt-1.5.17.orig/config.h.in (+3 lines)
Lines 34-39 Link Here
34
   significant more memory when defined. */
34
   significant more memory when defined. */
35
#undef EXACT_ADDRESS
35
#undef EXACT_ADDRESS
36
36
37
/* Compiling with newsreading support with NNTP */
38
#undef USE_NNTP
39
37
/* program to use for shell commands */
40
/* program to use for shell commands */
38
#undef EXECSHELL
41
#undef EXECSHELL
39
42
(-)mutt-1.5.17.orig/configure.ac (+8 lines)
Lines 585-590 if test x"$need_imap" = xyes -o x"$need_ Link Here
585
  MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS bcache.o"
585
  MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS bcache.o"
586
fi
586
fi
587
587
588
AC_ARG_ENABLE(nntp, [  --enable-nntp              Enable NNTP support],
589
[	if test x$enableval = xyes ; then
590
		AC_DEFINE(USE_NNTP,1,[ Define if you want support for the NNTP protocol. ])
591
		MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS nntp.o newsrc.o"
592
		need_socket="yes"
593
	fi
594
])
595
588
dnl -- end socket dependencies --
596
dnl -- end socket dependencies --
589
597
590
if test "$need_socket" = "yes"
598
if test "$need_socket" = "yes"
(-)mutt-1.5.17.orig/curs_main.c (-12 / +274 lines)
Lines 22-27 Link Here
22
22
23
#include "mutt.h"
23
#include "mutt.h"
24
#include "mutt_curses.h"
24
#include "mutt_curses.h"
25
#include "mx.h"
25
#include "mutt_menu.h"
26
#include "mutt_menu.h"
26
#include "attach.h"
27
#include "attach.h"
27
#include "mailbox.h"
28
#include "mailbox.h"
Lines 40-45 Link Here
40
41
41
#include "mutt_crypt.h"
42
#include "mutt_crypt.h"
42
43
44
#ifdef USE_NNTP
45
#include "nntp.h"
46
#endif
47
43
48
44
#include <ctype.h>
49
#include <ctype.h>
45
#include <stdlib.h>
50
#include <stdlib.h>
Lines 415-426 struct mapping_t IndexHelp[] = { Link Here
415
  { NULL }
420
  { NULL }
416
};
421
};
417
422
423
#ifdef USE_NNTP
424
struct mapping_t IndexNewsHelp[] = {
425
  { N_("Quit"),     OP_QUIT },
426
  { N_("Del"),      OP_DELETE },
427
  { N_("Undel"),    OP_UNDELETE },
428
  { N_("Save"),     OP_SAVE },
429
  { N_("Post"),     OP_POST },
430
  { N_("Followup"), OP_FOLLOWUP },
431
  { N_("Catchup"),  OP_CATCHUP },
432
  { N_("Help"),     OP_HELP },
433
  { NULL }
434
};
435
#endif
436
418
/* This function handles the message index window as well as commands returned
437
/* This function handles the message index window as well as commands returned
419
 * from the pager (MENU_PAGER).
438
 * from the pager (MENU_PAGER).
420
 */
439
 */
421
int mutt_index_menu (void)
440
int mutt_index_menu (void)
422
{
441
{
423
  char buf[LONG_STRING], helpstr[LONG_STRING];
442
  char buf[LONG_STRING], helpstr[LONG_STRING];
443
  int flags;
424
  int op = OP_NULL;
444
  int op = OP_NULL;
425
  int done = 0;                /* controls when to exit the "event" loop */
445
  int done = 0;                /* controls when to exit the "event" loop */
426
  int i = 0, j;
446
  int i = 0, j;
Lines 442-448 int mutt_index_menu (void) Link Here
442
  menu->make_entry = index_make_entry;
462
  menu->make_entry = index_make_entry;
443
  menu->color = index_color;
463
  menu->color = index_color;
444
  menu->current = ci_first_message ();
464
  menu->current = ci_first_message ();
445
  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN, IndexHelp);
465
  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN,
466
#ifdef USE_NNTP
467
	(Context && (Context->magic == M_NNTP)) ? IndexNewsHelp :
468
#endif
469
	IndexHelp);
446
  
470
  
447
  if (!attach_msg) 
471
  if (!attach_msg) 
448
    mutt_buffy_check(1); /* force the buffy check after we enter the folder */
472
    mutt_buffy_check(1); /* force the buffy check after we enter the folder */
Lines 694-699 int mutt_index_menu (void) Link Here
694
      mutt_curs_set (1);	/* fallback from the pager */
718
      mutt_curs_set (1);	/* fallback from the pager */
695
    }
719
    }
696
720
721
#ifdef USE_NNTP
722
    unset_option (OPTNEWS);	/* for any case */
723
#endif
697
    switch (op)
724
    switch (op)
698
    {
725
    {
699
726
Lines 744-749 int mutt_index_menu (void) Link Here
744
	menu_current_bottom (menu);
771
	menu_current_bottom (menu);
745
	break;
772
	break;
746
773
774
#ifdef USE_NNTP
775
      case OP_GET_MESSAGE:
776
      case OP_GET_PARENT:
777
	CHECK_MSGCOUNT;
778
	if (Context->magic == M_NNTP)
779
	{
780
	  HEADER *h;
781
782
	  if (op == OP_GET_MESSAGE)
783
	  {
784
	    buf[0] = 0;
785
	    if (mutt_get_field (_("Enter Message-Id: "), buf, sizeof (buf), 0) != 0
786
		  || !buf[0])
787
	      break;
788
	  }
789
	  else
790
	  {
791
	    LIST *ref = CURHDR->env->references;
792
	    if (!ref)
793
	    {
794
	      mutt_error _("Article has no parent reference!");
795
	      break;
796
	    }
797
	    strfcpy (buf, ref->data, sizeof (buf));
798
	  }
799
	  if (!Context->id_hash)
800
	    Context->id_hash = mutt_make_id_hash (Context);
801
	  if ((h = hash_find (Context->id_hash, buf)))
802
	  {
803
	    if (h->virtual != -1)
804
	    {
805
	      menu->current = h->virtual;
806
	      menu->redraw = REDRAW_MOTION_RESYNCH;
807
	    }
808
	    else if (h->collapsed)
809
	    {
810
	      mutt_uncollapse_thread (Context, h);
811
	      mutt_set_virtual (Context);
812
	      menu->current = h->virtual;
813
	      menu->redraw = REDRAW_MOTION_RESYNCH;
814
	    }
815
	    else
816
	      mutt_error _("Message not visible in limited view.");
817
	  }
818
	  else
819
	  {
820
	    if (nntp_check_msgid (Context, buf) == 0)
821
	    {
822
	      h = Context->hdrs[Context->msgcount-1];
823
	      mutt_sort_headers (Context, 0);
824
	      menu->current = h->virtual;
825
	      menu->redraw = REDRAW_FULL;
826
	    }
827
	    else
828
	      mutt_error (_("Article %s not found on server"), buf); 
829
	  }
830
	}
831
	break;
832
833
      case OP_GET_CHILDREN:
834
      case OP_RECONSTRUCT_THREAD:
835
	CHECK_MSGCOUNT;
836
	if (Context->magic == M_NNTP)
837
	{
838
	  HEADER *h;
839
	  int old = CURHDR->index, i;
840
841
	  if (!CURHDR->env->message_id)
842
	  {
843
	    mutt_error _("No Message-Id. Unable to perform operation");
844
	    break;
845
	  }
846
847
	  if (!Context->id_hash)
848
	    Context->id_hash = mutt_make_id_hash (Context);
849
	  strfcpy (buf, CURHDR->env->message_id, sizeof (buf));
850
851
	  if (op == OP_RECONSTRUCT_THREAD)
852
	  {
853
	    LIST *ref = CURHDR->env->references;
854
	    while (ref)
855
	    {
856
	      nntp_check_msgid (Context, ref->data);
857
	      /* the last msgid in References is the root message */
858
	      if (!ref->next)
859
		strfcpy (buf, ref->data, sizeof (buf));
860
	      ref = ref->next;
861
	    }
862
	  }
863
	  mutt_message _("Check for children of message...");
864
	  if (nntp_check_children (Context, buf) == 0)
865
	  {
866
	    mutt_sort_headers (Context, (op == OP_RECONSTRUCT_THREAD));
867
	    h = hash_find (Context->id_hash, buf);
868
	    /* if the root message was retrieved, move to it */
869
	    if (h)
870
	      menu->current = h->virtual;
871
	    else /* try to restore old position */
872
	      for (i = 0; i < Context->msgcount; i++)
873
		if (Context->hdrs[i]->index == old)
874
		{
875
		  menu->current = Context->hdrs[i]->virtual;
876
		  /* As an added courtesy, recenter the menu
877
		   * with the current entry at the middle of the screen */
878
		  menu_check_recenter (menu);
879
		  menu_current_middle (menu);
880
		}
881
	  }
882
	  menu->redraw = REDRAW_FULL;
883
	  mutt_clear_error ();
884
	}
885
	break;
886
#endif
887
747
      case OP_JUMP:
888
      case OP_JUMP:
748
889
749
	CHECK_MSGCOUNT;
890
	CHECK_MSGCOUNT;
Lines 841-851 int mutt_index_menu (void) Link Here
841
        break;
982
        break;
842
983
843
      case OP_MAIN_LIMIT:
984
      case OP_MAIN_LIMIT:
985
      case OP_TOGGLE_READ:
844
986
845
	CHECK_IN_MAILBOX;
987
	CHECK_IN_MAILBOX;
846
	menu->oldcurrent = (Context->vcount && menu->current >= 0 && menu->current < Context->vcount) ?
988
	menu->oldcurrent = (Context->vcount && menu->current >= 0 && menu->current < Context->vcount) ?
847
		CURHDR->index : -1;
989
		CURHDR->index : -1;
848
	if (mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0)
990
	if (op == OP_TOGGLE_READ)
991
	{
992
	  char buf[LONG_STRING];
993
994
	  if (!Context->pattern || strncmp (Context->pattern, "!~R!~D~s", 8) != 0)
995
	  {
996
	    snprintf (buf, sizeof (buf), "!~R!~D~s%s",
997
		      Context->pattern ? Context->pattern : ".*");
998
	    set_option (OPTHIDEREAD);
999
	  }
1000
	  else
1001
	  {
1002
	    strfcpy (buf, Context->pattern + 8, sizeof(buf));
1003
	    if (!*buf || strncmp (buf, ".*", 2) == 0)
1004
	      snprintf (buf, sizeof(buf), "~A");
1005
	    unset_option (OPTHIDEREAD);
1006
	  }
1007
	  FREE (&Context->pattern);
1008
	  Context->pattern = safe_strdup (buf);
1009
	}
1010
	if ((op == OP_TOGGLE_READ && mutt_pattern_func (M_LIMIT, NULL) == 0) ||
1011
	    mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0)
849
	{
1012
	{
850
	  if (menu->oldcurrent >= 0)
1013
	  if (menu->oldcurrent >= 0)
851
	  {
1014
	  {
Lines 1053-1067 int mutt_index_menu (void) Link Here
1053
1216
1054
      case OP_MAIN_CHANGE_FOLDER:
1217
      case OP_MAIN_CHANGE_FOLDER:
1055
      case OP_MAIN_NEXT_UNREAD_MAILBOX:
1218
      case OP_MAIN_NEXT_UNREAD_MAILBOX:
1056
      
1057
	if (attach_msg)
1058
	  op = OP_MAIN_CHANGE_FOLDER_READONLY;
1059
1060
	/* fallback to the readonly case */
1061
1062
      case OP_MAIN_CHANGE_FOLDER_READONLY:
1219
      case OP_MAIN_CHANGE_FOLDER_READONLY:
1220
#ifdef USE_NNTP
1221
      case OP_MAIN_CHANGE_GROUP:
1222
      case OP_MAIN_CHANGE_GROUP_READONLY:
1223
	unset_option (OPTNEWS);
1224
#endif
1225
	if (attach_msg || option (OPTREADONLY) ||
1226
#ifdef USE_NNTP
1227
	    op == OP_MAIN_CHANGE_GROUP_READONLY ||
1228
#endif
1229
	    op == OP_MAIN_CHANGE_FOLDER_READONLY)
1230
	  flags = M_READONLY;
1231
	else
1232
	  flags = 0;
1063
1233
1064
        if ((op == OP_MAIN_CHANGE_FOLDER_READONLY) || option (OPTREADONLY))
1234
	if (flags)
1065
          cp = _("Open mailbox in read-only mode");
1235
          cp = _("Open mailbox in read-only mode");
1066
        else
1236
        else
1067
          cp = _("Open mailbox");
1237
          cp = _("Open mailbox");
Lines 1080-1085 int mutt_index_menu (void) Link Here
1080
	}
1250
	}
1081
	else
1251
	else
1082
	{
1252
	{
1253
#ifdef USE_NNTP
1254
	  if (op == OP_MAIN_CHANGE_GROUP ||
1255
	      op == OP_MAIN_CHANGE_GROUP_READONLY)
1256
	  {
1257
	    set_option (OPTNEWS);
1258
	    if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)))
1259
	      break;
1260
	    if (flags)
1261
	      cp = _("Open newsgroup in read-only mode");
1262
	    else
1263
	      cp = _("Open newsgroup");
1264
	    nntp_buffy (buf);
1265
	  }
1266
	  else
1267
#endif
1083
	  mutt_buffy (buf, sizeof (buf));
1268
	  mutt_buffy (buf, sizeof (buf));
1084
1269
1085
	  if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1)
1270
	  if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1)
Lines 1099-1104 int mutt_index_menu (void) Link Here
1099
	  }
1284
	  }
1100
	}
1285
	}
1101
1286
1287
#ifdef USE_NNTP
1288
	if (option (OPTNEWS))
1289
	{
1290
	  unset_option (OPTNEWS);
1291
	  nntp_expand_path (buf, sizeof (buf), &CurrentNewsSrv->conn->account);
1292
	}
1293
	else
1294
#endif
1102
	mutt_expand_path (buf, sizeof (buf));
1295
	mutt_expand_path (buf, sizeof (buf));
1103
	if (mx_get_magic (buf) <= 0)
1296
	if (mx_get_magic (buf) <= 0)
1104
	{
1297
	{
Lines 1136-1150 int mutt_index_menu (void) Link Here
1136
	CurrentMenu = MENU_MAIN;
1329
	CurrentMenu = MENU_MAIN;
1137
	mutt_folder_hook (buf);
1330
	mutt_folder_hook (buf);
1138
1331
1139
	if ((Context = mx_open_mailbox (buf, 
1332
	if ((Context = mx_open_mailbox (buf, flags, NULL)) != NULL)
1140
					(option (OPTREADONLY) || op == OP_MAIN_CHANGE_FOLDER_READONLY) ?
1141
					M_READONLY : 0, NULL)) != NULL)
1142
	{
1333
	{
1143
	  menu->current = ci_first_message ();
1334
	  menu->current = ci_first_message ();
1144
	}
1335
	}
1145
	else
1336
	else
1146
	  menu->current = 0;
1337
	  menu->current = 0;
1147
1338
1339
#ifdef USE_NNTP
1340
	/* mutt_buffy_check() must be done with mail-reader mode! */
1341
	menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN,
1342
	  (Context && (Context->magic == M_NNTP)) ? IndexNewsHelp : IndexHelp);
1343
#endif
1148
	mutt_clear_error ();
1344
	mutt_clear_error ();
1149
	mutt_buffy_check(1); /* force the buffy check after we have changed
1345
	mutt_buffy_check(1); /* force the buffy check after we have changed
1150
			      the folder */
1346
			      the folder */
Lines 1515-1520 int mutt_index_menu (void) Link Here
1515
	CHECK_READONLY;
1711
	CHECK_READONLY;
1516
	CHECK_ACL(M_ACL_WRITE, _("flag message"));
1712
	CHECK_ACL(M_ACL_WRITE, _("flag message"));
1517
1713
1714
#ifdef USE_NNTP
1715
	if (Context->magic == M_NNTP)
1716
	{
1717
	  mutt_flushinp ();
1718
	  mutt_error _("Can't change 'important' flag on NNTP server.");
1719
	  break;
1720
	}
1721
#endif
1722
1518
        if (tag)
1723
        if (tag)
1519
        {
1724
        {
1520
	  for (j = 0; j < Context->vcount; j++)
1725
	  for (j = 0; j < Context->vcount; j++)
Lines 1862-1867 int mutt_index_menu (void) Link Here
1862
	}
2067
	}
1863
	break;
2068
	break;
1864
2069
2070
#ifdef USE_NNTP
2071
      case OP_CATCHUP:
2072
	if (Context && Context->magic == M_NNTP)
2073
	{
2074
	  if (mutt_newsgroup_catchup (CurrentNewsSrv,
2075
		((NNTP_DATA *)Context->data)->group))
2076
	    menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
2077
	}
2078
	break;
2079
#endif
2080
1865
      case OP_DISPLAY_ADDRESS:
2081
      case OP_DISPLAY_ADDRESS:
1866
2082
1867
	CHECK_MSGCOUNT;
2083
	CHECK_MSGCOUNT;
Lines 1989-1994 int mutt_index_menu (void) Link Here
1989
	  menu->redraw = (tag ? REDRAW_INDEX : REDRAW_CURRENT) | REDRAW_STATUS;
2205
	  menu->redraw = (tag ? REDRAW_INDEX : REDRAW_CURRENT) | REDRAW_STATUS;
1990
	}
2206
	}
1991
#endif
2207
#endif
2208
  
2209
#ifdef USE_NNTP
2210
	if (Context->magic == M_NNTP)
2211
	{
2212
	  mutt_flushinp ();
2213
	  mutt_error _("Can't edit message on newsserver.");
2214
	  break;
2215
	}
2216
#endif
1992
2217
1993
	MAYBE_REDRAW (menu->redraw);
2218
	MAYBE_REDRAW (menu->redraw);
1994
	break;
2219
	break;
Lines 2060-2065 int mutt_index_menu (void) Link Here
2060
      
2285
      
2061
        menu->redraw = REDRAW_FULL;
2286
        menu->redraw = REDRAW_FULL;
2062
        break;
2287
        break;
2288
2289
#ifdef USE_NNTP
2290
      case OP_POST:
2291
      case OP_FOLLOWUP:
2292
      case OP_FORWARD_TO_GROUP:
2293
2294
	CHECK_ATTACH;
2295
	if (op != OP_FOLLOWUP || !CURHDR->env->followup_to ||
2296
	    mutt_strcasecmp (CURHDR->env->followup_to, "poster") ||
2297
	    query_quadoption (OPT_FOLLOWUPTOPOSTER,_("Reply by mail as poster prefers?")) != M_YES)
2298
	{
2299
	  if (Context && Context->magic == M_NNTP &&
2300
	      !((NNTP_DATA *)Context->data)->allowed &&
2301
	      query_quadoption (OPT_TOMODERATED, _("Posting to this group not allowed, may be moderated. Continue?")) != M_YES)
2302
	    break;
2303
	  if (op == OP_POST)
2304
	    ci_send_message (SENDNEWS, NULL, NULL, Context, NULL);
2305
	  else
2306
	  {
2307
	    CHECK_MSGCOUNT;
2308
	    if (op == OP_FOLLOWUP)
2309
	      ci_send_message (SENDNEWS|SENDREPLY, NULL, NULL, Context,
2310
			       tag ? NULL : CURHDR);
2311
	    else
2312
	      ci_send_message (SENDNEWS|SENDFORWARD, NULL, NULL, Context,
2313
			       tag ? NULL : CURHDR);
2314
	  }
2315
	  menu->redraw = REDRAW_FULL;
2316
	  break;
2317
	}
2318
#endif
2063
      
2319
      
2064
      case OP_REPLY:
2320
      case OP_REPLY:
2065
2321
Lines 2136-2141 int mutt_index_menu (void) Link Here
2136
	CHECK_READONLY;
2392
	CHECK_READONLY;
2137
	CHECK_ACL(M_ACL_DELETE, _("undelete message(s)"));
2393
	CHECK_ACL(M_ACL_DELETE, _("undelete message(s)"));
2138
2394
2395
#ifdef USE_NNTP
2396
	/* Close all open NNTP connections */
2397
	if (!attach_msg)
2398
	  nntp_logout_all ();
2399
#endif
2400
2139
	rc = mutt_thread_set_flag (CURHDR, M_DELETE, 0,
2401
	rc = mutt_thread_set_flag (CURHDR, M_DELETE, 0,
2140
				   op == OP_UNDELETE_THREAD ? 0 : 1);
2402
				   op == OP_UNDELETE_THREAD ? 0 : 1);
2141
2403
(-)mutt-1.5.17.orig/doc/manual.xml.head (+16 lines)
Lines 1319-1324 fo-table</literal> for details. Link Here
1319
1319
1320
</sect2>
1320
</sect2>
1321
1321
1322
<sect2>
1323
<title>Reading news via NNTP</title>
1324
1325
<para>
1326
If compiled with <emphasis>--enable-nntp</emphasis> option, Mutt can
1327
read news from newsserver via NNTP.  You can open a newsgroup with
1328
function ``change-newsgroup'' (default: ``i'').  Default newsserver
1329
can be obtained from <emphasis>NNTPSERVER</emphasis> environment
1330
variable.  Like other news readers, info about subscribed newsgroups
1331
is saved in file by <link linkend="newsrc">&dollar;newsrc</link>
1332
variable.  Article headers are cached and can be loaded from file when
1333
newsgroup entered instead loading from newsserver.
1334
</para>
1335
1336
</sect2>
1337
1322
</sect1>
1338
</sect1>
1323
1339
1324
<sect1 id="forwarding-mail">
1340
<sect1 id="forwarding-mail">
(-)mutt-1.5.17.orig/doc/mutt.man (-2 / +6 lines)
Lines 23-30 mutt \- The Mutt Mail User Agent Link Here
23
.SH SYNOPSIS
23
.SH SYNOPSIS
24
.PP
24
.PP
25
.B mutt
25
.B mutt
26
[-nRyzZ] 
26
[-GnRyzZ] 
27
[-e \fIcmd\fP] [-F \fIfile\fP] [-m \fItype\fP] [-f \fIfile\fP]
27
[-e \fIcmd\fP] [-F \fIfile\fP] [-g \fIserver\fP] [-m \fItype\fP] [-f \fIfile\fP]
28
.PP
28
.PP
29
.B mutt 
29
.B mutt 
30
[-nx] 
30
[-nx] 
Lines 83-88 files. Link Here
83
Specify which mailbox to load.
83
Specify which mailbox to load.
84
.IP "-F \fImuttrc\fP"
84
.IP "-F \fImuttrc\fP"
85
Specify an initialization file to read instead of ~/.muttrc
85
Specify an initialization file to read instead of ~/.muttrc
86
.IP "-g \fIserver\fP"
87
Start Mutt with a listing of subscribed newsgroups at specified newsserver.
88
.IP "-G"
89
Start Mutt with a listing of subscribed newsgroups.
86
.IP "-h"
90
.IP "-h"
87
Display help.
91
Display help.
88
.IP "-H \fIdraft\fP"
92
.IP "-H \fIdraft\fP"
(-)mutt-1.5.17.orig/functions.h (-4 / +55 lines)
Lines 88-93 struct binding_t OpMain[] = { /* map: in Link Here
88
  { "break-thread",		OP_MAIN_BREAK_THREAD,		"#" },
88
  { "break-thread",		OP_MAIN_BREAK_THREAD,		"#" },
89
  { "change-folder",		OP_MAIN_CHANGE_FOLDER,		"c" },
89
  { "change-folder",		OP_MAIN_CHANGE_FOLDER,		"c" },
90
  { "change-folder-readonly",	OP_MAIN_CHANGE_FOLDER_READONLY,	"\033c" },
90
  { "change-folder-readonly",	OP_MAIN_CHANGE_FOLDER_READONLY,	"\033c" },
91
#ifdef USE_NNTP
92
  { "change-newsgroup",		OP_MAIN_CHANGE_GROUP,		"i" },
93
  { "change-newsgroup-readonly",OP_MAIN_CHANGE_GROUP_READONLY,	"\033i" },
94
#endif
91
  { "next-unread-mailbox",	OP_MAIN_NEXT_UNREAD_MAILBOX,    NULL },
95
  { "next-unread-mailbox",	OP_MAIN_NEXT_UNREAD_MAILBOX,    NULL },
92
  { "collapse-thread",		OP_MAIN_COLLAPSE_THREAD,	"\033v" },
96
  { "collapse-thread",		OP_MAIN_COLLAPSE_THREAD,	"\033v" },
93
  { "collapse-all",		OP_MAIN_COLLAPSE_ALL,		"\033V" },
97
  { "collapse-all",		OP_MAIN_COLLAPSE_ALL,		"\033V" },
Lines 101-107 struct binding_t OpMain[] = { /* map: in Link Here
101
  { "edit",			OP_EDIT_MESSAGE,		"e" },
105
  { "edit",			OP_EDIT_MESSAGE,		"e" },
102
  { "edit-type",		OP_EDIT_TYPE,			"\005" },
106
  { "edit-type",		OP_EDIT_TYPE,			"\005" },
103
  { "forward-message",		OP_FORWARD_MESSAGE,		"f" },
107
  { "forward-message",		OP_FORWARD_MESSAGE,		"f" },
104
  { "flag-message",		OP_FLAG_MESSAGE,		"F" },
108
#ifdef USE_NNTP
109
  { "forward-to-group",		OP_FORWARD_TO_GROUP,		"\033F" },
110
  { "followup-message",		OP_FOLLOWUP,			"F" },
111
  { "get-children",		OP_GET_CHILDREN,		NULL },
112
  { "get-message",		OP_GET_MESSAGE,			"\007" },
113
  { "get-parent",		OP_GET_PARENT,			"\033G" },
114
  { "reconstruct-thread",	OP_RECONSTRUCT_THREAD,		NULL },
115
#endif
116
  { "flag-message",		OP_FLAG_MESSAGE,		"\033f" },
105
  { "group-reply",		OP_GROUP_REPLY,			"g" },
117
  { "group-reply",		OP_GROUP_REPLY,			"g" },
106
#ifdef USE_POP
118
#ifdef USE_POP
107
  { "fetch-mail",		OP_MAIN_FETCH_MAIL,		"G" },
119
  { "fetch-mail",		OP_MAIN_FETCH_MAIL,		"G" },
Lines 127-132 struct binding_t OpMain[] = { /* map: in Link Here
127
  { "sort-mailbox",		OP_SORT,			"o" },
139
  { "sort-mailbox",		OP_SORT,			"o" },
128
  { "sort-reverse",		OP_SORT_REVERSE,		"O" },
140
  { "sort-reverse",		OP_SORT_REVERSE,		"O" },
129
  { "print-message",		OP_PRINT,			"p" },
141
  { "print-message",		OP_PRINT,			"p" },
142
#ifdef USE_NNTP
143
  { "post-message",		OP_POST,			"P" },
144
#endif
130
  { "previous-thread",		OP_MAIN_PREV_THREAD,		"\020" },
145
  { "previous-thread",		OP_MAIN_PREV_THREAD,		"\020" },
131
  { "previous-subthread",	OP_MAIN_PREV_SUBTHREAD,		"\033p" },
146
  { "previous-subthread",	OP_MAIN_PREV_SUBTHREAD,		"\033p" },
132
  { "recall-message",		OP_RECALL_MESSAGE,		"R" },
147
  { "recall-message",		OP_RECALL_MESSAGE,		"R" },
Lines 146-151 struct binding_t OpMain[] = { /* map: in Link Here
146
  { "show-version",		OP_VERSION,			"V" },
161
  { "show-version",		OP_VERSION,			"V" },
147
  { "set-flag",			OP_MAIN_SET_FLAG,		"w" },
162
  { "set-flag",			OP_MAIN_SET_FLAG,		"w" },
148
  { "clear-flag",		OP_MAIN_CLEAR_FLAG,		"W" },
163
  { "clear-flag",		OP_MAIN_CLEAR_FLAG,		"W" },
164
  { "toggle-read",		OP_TOGGLE_READ,			"X" },
165
#ifdef USE_NNTP
166
  { "catchup",			OP_CATCHUP,			"y" },
167
#endif
149
  { "display-message",		OP_DISPLAY_MESSAGE,		M_ENTER_S },
168
  { "display-message",		OP_DISPLAY_MESSAGE,		M_ENTER_S },
150
  { "buffy-list",		OP_BUFFY_LIST,			"." },
169
  { "buffy-list",		OP_BUFFY_LIST,			"." },
151
  { "sync-mailbox",		OP_MAIN_SYNC_FOLDER,		"$" },
170
  { "sync-mailbox",		OP_MAIN_SYNC_FOLDER,		"$" },
Lines 157-163 struct binding_t OpMain[] = { /* map: in Link Here
157
  { "previous-new-then-unread",	OP_MAIN_PREV_NEW_THEN_UNREAD,	"\033\t" },
176
  { "previous-new-then-unread",	OP_MAIN_PREV_NEW_THEN_UNREAD,	"\033\t" },
158
  { "next-unread",		OP_MAIN_NEXT_UNREAD,		NULL },
177
  { "next-unread",		OP_MAIN_NEXT_UNREAD,		NULL },
159
  { "previous-unread",		OP_MAIN_PREV_UNREAD,		NULL },
178
  { "previous-unread",		OP_MAIN_PREV_UNREAD,		NULL },
160
  { "parent-message",		OP_MAIN_PARENT_MESSAGE,		"P" },
179
  { "parent-message",		OP_MAIN_PARENT_MESSAGE,		NULL },
161
180
162
181
163
  { "extract-keys",		OP_EXTRACT_KEYS,		"\013" },
182
  { "extract-keys",		OP_EXTRACT_KEYS,		"\013" },
Lines 177-182 struct binding_t OpPager[] = { /* map: p Link Here
177
  { "bounce-message",	OP_BOUNCE_MESSAGE,		"b" },
196
  { "bounce-message",	OP_BOUNCE_MESSAGE,		"b" },
178
  { "change-folder",	OP_MAIN_CHANGE_FOLDER,		"c" },
197
  { "change-folder",	OP_MAIN_CHANGE_FOLDER,		"c" },
179
  { "change-folder-readonly",	OP_MAIN_CHANGE_FOLDER_READONLY,	"\033c" },
198
  { "change-folder-readonly",	OP_MAIN_CHANGE_FOLDER_READONLY,	"\033c" },
199
#ifdef USE_NNTP
200
  { "change-newsgroup",		OP_MAIN_CHANGE_GROUP,		"i" },
201
  { "change-newsgroup-readonly",OP_MAIN_CHANGE_GROUP_READONLY,	"\033i" },
202
#endif
180
  { "next-unread-mailbox",	OP_MAIN_NEXT_UNREAD_MAILBOX, NULL },
203
  { "next-unread-mailbox",	OP_MAIN_NEXT_UNREAD_MAILBOX, NULL },
181
  { "copy-message",	OP_COPY_MESSAGE,		"C" },
204
  { "copy-message",	OP_COPY_MESSAGE,		"C" },
182
  { "decode-copy",	OP_DECODE_COPY,			"\033C" },
205
  { "decode-copy",	OP_DECODE_COPY,			"\033C" },
Lines 185-192 struct binding_t OpPager[] = { /* map: p Link Here
185
  { "delete-subthread",	OP_DELETE_SUBTHREAD,		"\033d" },
208
  { "delete-subthread",	OP_DELETE_SUBTHREAD,		"\033d" },
186
  { "edit",		OP_EDIT_MESSAGE,		"e" },
209
  { "edit",		OP_EDIT_MESSAGE,		"e" },
187
  { "edit-type",	OP_EDIT_TYPE,			"\005" },
210
  { "edit-type",	OP_EDIT_TYPE,			"\005" },
211
#ifdef USE_NNTP
212
  { "followup-message",	OP_FOLLOWUP,			"F" },
213
  { "forward-to-group",	OP_FORWARD_TO_GROUP,		"\033F" },
214
#endif
188
  { "forward-message",	OP_FORWARD_MESSAGE,		"f" },
215
  { "forward-message",	OP_FORWARD_MESSAGE,		"f" },
189
  { "flag-message",	OP_FLAG_MESSAGE,		"F" },
216
  { "flag-message",	OP_FLAG_MESSAGE,		"\033f" },
190
  { "group-reply",	OP_GROUP_REPLY,			"g" },
217
  { "group-reply",	OP_GROUP_REPLY,			"g" },
191
#ifdef USE_IMAP
218
#ifdef USE_IMAP
192
  { "imap-fetch-mail",  OP_MAIN_IMAP_FETCH,		NULL },
219
  { "imap-fetch-mail",  OP_MAIN_IMAP_FETCH,		NULL },
Lines 205-210 struct binding_t OpPager[] = { /* map: p Link Here
205
  { "next-thread",	OP_MAIN_NEXT_THREAD,		"\016" },
232
  { "next-thread",	OP_MAIN_NEXT_THREAD,		"\016" },
206
  { "next-subthread",	OP_MAIN_NEXT_SUBTHREAD,		"\033n" },
233
  { "next-subthread",	OP_MAIN_NEXT_SUBTHREAD,		"\033n" },
207
  { "print-message",	OP_PRINT,			"p" },
234
  { "print-message",	OP_PRINT,			"p" },
235
#ifdef USE_NNTP
236
  { "post-message",	OP_POST,			"P" },
237
#endif
208
  { "previous-thread",	OP_MAIN_PREV_THREAD,		"\020" },
238
  { "previous-thread",	OP_MAIN_PREV_THREAD,		"\020" },
209
  { "previous-subthread",OP_MAIN_PREV_SUBTHREAD,	"\033p" },
239
  { "previous-subthread",OP_MAIN_PREV_SUBTHREAD,	"\033p" },
210
  { "quit",		OP_QUIT,			"Q" },
240
  { "quit",		OP_QUIT,			"Q" },
Lines 252-258 struct binding_t OpPager[] = { /* map: p Link Here
252
  { "half-down",	OP_HALF_DOWN,			NULL },
282
  { "half-down",	OP_HALF_DOWN,			NULL },
253
  { "previous-line",	OP_PREV_LINE,			NULL },
283
  { "previous-line",	OP_PREV_LINE,			NULL },
254
  { "bottom",		OP_PAGER_BOTTOM,		NULL },
284
  { "bottom",		OP_PAGER_BOTTOM,		NULL },
255
  { "parent-message",	OP_MAIN_PARENT_MESSAGE,		"P" },
285
  { "parent-message",	OP_MAIN_PARENT_MESSAGE,		NULL },
256
286
257
287
258
288
Lines 272-277 struct binding_t OpAttach[] = { /* map: Link Here
272
  { "bounce-message",	OP_BOUNCE_MESSAGE,		"b" },
302
  { "bounce-message",	OP_BOUNCE_MESSAGE,		"b" },
273
  { "display-toggle-weed",	OP_DISPLAY_HEADERS,	"h" },
303
  { "display-toggle-weed",	OP_DISPLAY_HEADERS,	"h" },
274
  { "edit-type",	OP_EDIT_TYPE,			"\005" },
304
  { "edit-type",	OP_EDIT_TYPE,			"\005" },
305
#ifdef USE_NNTP
306
  { "followup-message",	OP_FOLLOWUP,			"F" },
307
  { "forward-to-group",	OP_FORWARD_TO_GROUP,		"\033F" },
308
#endif
275
  { "print-entry",	OP_PRINT,			"p" },
309
  { "print-entry",	OP_PRINT,			"p" },
276
  { "save-entry",	OP_SAVE,			"s" },
310
  { "save-entry",	OP_SAVE,			"s" },
277
  { "pipe-entry",	OP_PIPE,			"|" },
311
  { "pipe-entry",	OP_PIPE,			"|" },
Lines 297-302 struct binding_t OpAttach[] = { /* map: Link Here
297
struct binding_t OpCompose[] = { /* map: compose */
331
struct binding_t OpCompose[] = { /* map: compose */
298
  { "attach-file",	OP_COMPOSE_ATTACH_FILE,		"a" },
332
  { "attach-file",	OP_COMPOSE_ATTACH_FILE,		"a" },
299
  { "attach-message",	OP_COMPOSE_ATTACH_MESSAGE,	"A" },
333
  { "attach-message",	OP_COMPOSE_ATTACH_MESSAGE,	"A" },
334
  { "attach-news-message",OP_COMPOSE_ATTACH_NEWS_MESSAGE,"\033a" },
300
  { "edit-bcc",		OP_COMPOSE_EDIT_BCC,		"b" },
335
  { "edit-bcc",		OP_COMPOSE_EDIT_BCC,		"b" },
301
  { "edit-cc",		OP_COMPOSE_EDIT_CC,		"c" },
336
  { "edit-cc",		OP_COMPOSE_EDIT_CC,		"c" },
302
  { "copy-file",	OP_SAVE,			"C" },
337
  { "copy-file",	OP_SAVE,			"C" },
Lines 316-321 struct binding_t OpCompose[] = { /* map: Link Here
316
  { "print-entry",	OP_PRINT,			"l" },
351
  { "print-entry",	OP_PRINT,			"l" },
317
  { "edit-mime",	OP_COMPOSE_EDIT_MIME,		"m" },
352
  { "edit-mime",	OP_COMPOSE_EDIT_MIME,		"m" },
318
  { "new-mime",		OP_COMPOSE_NEW_MIME,		"n" },
353
  { "new-mime",		OP_COMPOSE_NEW_MIME,		"n" },
354
#ifdef USE_NNTP
355
  { "edit-newsgroups",	OP_COMPOSE_EDIT_NEWSGROUPS,	"N" },
356
  { "edit-followup-to",	OP_COMPOSE_EDIT_FOLLOWUP_TO,	"o" },
357
  { "edit-x-comment-to",OP_COMPOSE_EDIT_X_COMMENT_TO,	"x" },
358
#endif
319
  { "postpone-message",	OP_COMPOSE_POSTPONE_MESSAGE,	"P" },
359
  { "postpone-message",	OP_COMPOSE_POSTPONE_MESSAGE,	"P" },
320
  { "edit-reply-to",	OP_COMPOSE_EDIT_REPLY_TO,	"r" },
360
  { "edit-reply-to",	OP_COMPOSE_EDIT_REPLY_TO,	"r" },
321
  { "rename-file",	OP_COMPOSE_RENAME_FILE,		"R" },
361
  { "rename-file",	OP_COMPOSE_RENAME_FILE,		"R" },
Lines 367-380 struct binding_t OpBrowser[] = { /* map: Link Here
367
  { "select-new",	OP_BROWSER_NEW_FILE,	"N" },
407
  { "select-new",	OP_BROWSER_NEW_FILE,	"N" },
368
  { "check-new",	OP_CHECK_NEW,		NULL },
408
  { "check-new",	OP_CHECK_NEW,		NULL },
369
  { "toggle-mailboxes", OP_TOGGLE_MAILBOXES, 	"\t" },
409
  { "toggle-mailboxes", OP_TOGGLE_MAILBOXES, 	"\t" },
410
#ifdef USE_NNTP
411
  { "reload-active",	OP_LOAD_ACTIVE,		"g" },
412
  { "subscribe-pattern", OP_SUBSCRIBE_PATTERN,	"S" },
413
  { "unsubscribe-pattern", OP_UNSUBSCRIBE_PATTERN, "U" },
414
  { "catchup",		OP_CATCHUP,		"y" },
415
  { "uncatchup",	OP_UNCATCHUP,		"Y" },
416
#endif
370
  { "view-file",	OP_BROWSER_VIEW_FILE,	" " },
417
  { "view-file",	OP_BROWSER_VIEW_FILE,	" " },
371
  { "buffy-list",	OP_BUFFY_LIST,		"." },
418
  { "buffy-list",	OP_BUFFY_LIST,		"." },
372
#ifdef USE_IMAP
419
#ifdef USE_IMAP
373
  { "create-mailbox",   OP_CREATE_MAILBOX,      "C" },
420
  { "create-mailbox",   OP_CREATE_MAILBOX,      "C" },
374
  { "delete-mailbox",   OP_DELETE_MAILBOX,      "d" },
421
  { "delete-mailbox",   OP_DELETE_MAILBOX,      "d" },
375
  { "rename-mailbox",   OP_RENAME_MAILBOX,      "r" },
422
  { "rename-mailbox",   OP_RENAME_MAILBOX,      "r" },
423
#endif
424
#if defined USE_IMAP || defined USE_NNTP
376
  { "subscribe",	OP_BROWSER_SUBSCRIBE,	"s" },
425
  { "subscribe",	OP_BROWSER_SUBSCRIBE,	"s" },
377
  { "unsubscribe",	OP_BROWSER_UNSUBSCRIBE,	"u" },
426
  { "unsubscribe",	OP_BROWSER_UNSUBSCRIBE,	"u" },
427
#endif
428
#ifdef USE_IMAP
378
  { "toggle-subscribed", OP_BROWSER_TOGGLE_LSUB, "T" },
429
  { "toggle-subscribed", OP_BROWSER_TOGGLE_LSUB, "T" },
379
#endif
430
#endif
380
  { NULL,		0,			NULL }
431
  { NULL,		0,			NULL }
(-)mutt-1.5.17.orig/globals.h (+14 lines)
Lines 95-100 WHERE char *MixEntryFormat; Link Here
95
#endif
95
#endif
96
96
97
WHERE char *Muttrc INITVAL (NULL);
97
WHERE char *Muttrc INITVAL (NULL);
98
#ifdef USE_NNTP
99
WHERE char *NewsCacheDir;
100
WHERE char *GroupFormat;
101
WHERE char *Inews;
102
WHERE char *NewsServer;
103
WHERE char *NntpUser;
104
WHERE char *NntpPass;
105
WHERE char *NewsRc;
106
#endif
98
WHERE char *Outbox;
107
WHERE char *Outbox;
99
WHERE char *Pager;
108
WHERE char *Pager;
100
WHERE char *PagerFmt;
109
WHERE char *PagerFmt;
Lines 190-195 extern unsigned char QuadOptions[]; Link Here
190
199
191
WHERE unsigned short Counter INITVAL (0);
200
WHERE unsigned short Counter INITVAL (0);
192
201
202
#ifdef USE_NNTP
203
WHERE short NewsPollTimeout;
204
WHERE short NntpContext;
205
#endif
206
193
WHERE short ConnectTimeout;
207
WHERE short ConnectTimeout;
194
WHERE short HistSize;
208
WHERE short HistSize;
195
WHERE short MenuContext;
209
WHERE short MenuContext;
(-)mutt-1.5.17.orig/hash.c (+28 lines)
Lines 51-60 HASH *hash_create (int nelem) Link Here
51
  if (nelem == 0)
51
  if (nelem == 0)
52
    nelem = 2;
52
    nelem = 2;
53
  table->nelem = nelem;
53
  table->nelem = nelem;
54
  table->curnelem = 0;
54
  table->table = safe_calloc (nelem, sizeof (struct hash_elem *));
55
  table->table = safe_calloc (nelem, sizeof (struct hash_elem *));
55
  return table;
56
  return table;
56
}
57
}
57
58
59
HASH *hash_resize (HASH *ptr, int nelem)
60
{
61
  HASH *table;
62
  struct hash_elem *elem, *tmp;
63
  int i;
64
65
  table = hash_create (nelem);
66
67
  for (i = 0; i < ptr->nelem; i++)
68
  {
69
    for (elem = ptr->table[i]; elem; )
70
    {
71
      tmp = elem;
72
      elem = elem->next;
73
      hash_insert (table, tmp->key, tmp->data, 1);
74
      FREE (&tmp);
75
    }
76
  }
77
  FREE (&ptr->table);
78
  FREE (&ptr);
79
80
  return table;
81
}
82
58
/* table        hash table to update
83
/* table        hash table to update
59
 * key          key to hash on
84
 * key          key to hash on
60
 * data         data to associate with `key'
85
 * data         data to associate with `key'
Lines 74-79 int hash_insert (HASH * table, const cha Link Here
74
  {
99
  {
75
    ptr->next = table->table[h];
100
    ptr->next = table->table[h];
76
    table->table[h] = ptr;
101
    table->table[h] = ptr;
102
    table->curnelem++;
77
  }
103
  }
78
  else
104
  else
79
  {
105
  {
Lines 96-101 int hash_insert (HASH * table, const cha Link Here
96
    else
122
    else
97
      table->table[h] = ptr;
123
      table->table[h] = ptr;
98
    ptr->next = tmp;
124
    ptr->next = tmp;
125
    table->curnelem++;
99
  }
126
  }
100
  return h;
127
  return h;
101
}
128
}
Lines 126-131 void hash_delete_hash (HASH * table, int Link Here
126
      if (destroy)
153
      if (destroy)
127
	destroy (ptr->data);
154
	destroy (ptr->data);
128
      FREE (&ptr);
155
      FREE (&ptr);
156
      table->curnelem--;
129
      
157
      
130
      ptr = *last;
158
      ptr = *last;
131
    }
159
    }
(-)mutt-1.5.17.orig/hash.h (-1 / +2 lines)
Lines 28-34 struct hash_elem Link Here
28
28
29
typedef struct
29
typedef struct
30
{
30
{
31
  int nelem;
31
  int nelem, curnelem;
32
  struct hash_elem **table;
32
  struct hash_elem **table;
33
}
33
}
34
HASH;
34
HASH;
Lines 40-45 HASH; Link Here
40
HASH *hash_create (int nelem);
40
HASH *hash_create (int nelem);
41
int hash_string (const unsigned char *s, int n);
41
int hash_string (const unsigned char *s, int n);
42
int hash_insert (HASH * table, const char *key, void *data, int allow_dup);
42
int hash_insert (HASH * table, const char *key, void *data, int allow_dup);
43
HASH *hash_resize (HASH * table, int nelem);
43
void *hash_find_hash (const HASH * table, int hash, const char *key);
44
void *hash_find_hash (const HASH * table, int hash, const char *key);
44
void hash_delete_hash (HASH * table, int hash, const char *key, const void *data,
45
void hash_delete_hash (HASH * table, int hash, const char *key, const void *data,
45
		       void (*destroy) (void *));
46
		       void (*destroy) (void *));
(-)mutt-1.5.17.orig/hdrline.c (+25 lines)
Lines 209-214 int mutt_user_is_recipient (HEADER *h) Link Here
209
 * %E = number of messages in current thread
209
 * %E = number of messages in current thread
210
 * %f = entire from line
210
 * %f = entire from line
211
 * %F = like %n, unless from self
211
 * %F = like %n, unless from self
212
 * %g = newsgroup name (if compiled with nntp support)
212
 * %i = message-id
213
 * %i = message-id
213
 * %l = number of lines in the message
214
 * %l = number of lines in the message
214
 * %L = like %F, except `lists' are displayed first
215
 * %L = like %F, except `lists' are displayed first
Lines 217-228 int mutt_user_is_recipient (HEADER *h) Link Here
217
 * %N = score
218
 * %N = score
218
 * %O = like %L, except using address instead of name
219
 * %O = like %L, except using address instead of name
219
 * %P = progress indicator for builtin pager
220
 * %P = progress indicator for builtin pager
221
 * %R = `x-comment-to:' field (if present and compiled with nntp support)
220
 * %s = subject
222
 * %s = subject
221
 * %S = short message status (e.g., N/O/D/!/r/-)
223
 * %S = short message status (e.g., N/O/D/!/r/-)
222
 * %t = `to:' field (recipients)
224
 * %t = `to:' field (recipients)
223
 * %T = $to_chars
225
 * %T = $to_chars
224
 * %u = user (login) name of author
226
 * %u = user (login) name of author
225
 * %v = first name of author, unless from self
227
 * %v = first name of author, unless from self
228
 * %W = where user is (organization)
226
 * %X = number of MIME attachments
229
 * %X = number of MIME attachments
227
 * %y = `x-label:' field (if present)
230
 * %y = `x-label:' field (if present)
228
 * %Y = `x-label:' field (if present, tree unfolded, and != parent's x-label)
231
 * %Y = `x-label:' field (if present, tree unfolded, and != parent's x-label)
Lines 455-460 hdr_format_str (char *dest, Link Here
455
458
456
      break;
459
      break;
457
460
461
#ifdef USE_NNTP
462
    case 'g':
463
      mutt_format_s (dest, destlen, prefix, hdr->env->newsgroups ? hdr->env->newsgroups : "");
464
      break;
465
#endif
466
458
    case 'i':
467
    case 'i':
459
      mutt_format_s (dest, destlen, prefix, hdr->env->message_id ? hdr->env->message_id : "<no.id>");
468
      mutt_format_s (dest, destlen, prefix, hdr->env->message_id ? hdr->env->message_id : "<no.id>");
460
      break;
469
      break;
Lines 546-551 hdr_format_str (char *dest, Link Here
546
      strfcpy(dest, NONULL(hfi->pager_progress), destlen);
555
      strfcpy(dest, NONULL(hfi->pager_progress), destlen);
547
      break;
556
      break;
548
557
558
#ifdef USE_NNTP
559
    case 'R':
560
      if (!optional)
561
	mutt_format_s (dest, destlen, prefix, hdr->env->x_comment_to ? hdr->env->x_comment_to : "");
562
      else if (!hdr->env->x_comment_to)
563
	optional = 0;
564
      break;
565
#endif
566
549
    case 's':
567
    case 's':
550
      
568
      
551
      if (flags & M_FORMAT_TREE && !hdr->collapsed)
569
      if (flags & M_FORMAT_TREE && !hdr->collapsed)
Lines 635-640 hdr_format_str (char *dest, Link Here
635
      mutt_format_s (dest, destlen, prefix, buf2);
653
      mutt_format_s (dest, destlen, prefix, buf2);
636
      break;
654
      break;
637
655
656
    case 'W':
657
      if (!optional)
658
	mutt_format_s (dest, destlen, prefix, hdr->env->organization ? hdr->env->organization : "");
659
      else if (!hdr->env->organization)
660
	optional = 0;
661
      break;
662
638
    case 'Z':
663
    case 'Z':
639
    
664
    
640
      ch = ' ';
665
      ch = ' ';
(-)mutt-1.5.17.orig/headers.c (+3 lines)
Lines 118-123 void mutt_edit_headers (const char *edit Link Here
118
  msg->env = n; n = NULL;
118
  msg->env = n; n = NULL;
119
119
120
  if (!msg->env->in_reply_to)
120
  if (!msg->env->in_reply_to)
121
#ifdef USE_NNTP
122
  if (!option (OPTNEWSSEND))
123
#endif
121
    mutt_free_list (&msg->env->references);
124
    mutt_free_list (&msg->env->references);
122
125
123
  mutt_expand_aliases_env (msg->env);
126
  mutt_expand_aliases_env (msg->env);
(-)mutt-1.5.17.orig/init.c (+22 lines)
Lines 2921-2926 void mutt_init (int skip_sys_rc, LIST *c Link Here
2921
  else
2921
  else
2922
    Fqdn = safe_strdup(NONULL(Hostname));
2922
    Fqdn = safe_strdup(NONULL(Hostname));
2923
2923
2924
#ifdef USE_NNTP
2925
  {
2926
    FILE *f;
2927
    char *i;
2928
2929
    if ((f = safe_fopen (SYSCONFDIR "/nntpserver", "r")))
2930
    {
2931
      buffer[0] = '\0';
2932
      fgets (buffer, sizeof (buffer), f);
2933
      p = &buffer;
2934
      SKIPWS (p);
2935
      i = p;
2936
      while (*i && (*i != ' ') && (*i != '\t') && (*i != '\r') && (*i != '\n')) i++;
2937
      *i = '\0';
2938
      NewsServer = safe_strdup (p);
2939
      fclose (f);
2940
    }
2941
  }
2942
  if ((p = getenv ("NNTPSERVER")))
2943
    NewsServer = safe_strdup (p);
2944
#endif
2945
2924
  if ((p = getenv ("MAIL")))
2946
  if ((p = getenv ("MAIL")))
2925
    Spoolfile = safe_strdup (p);
2947
    Spoolfile = safe_strdup (p);
2926
  else if ((p = getenv ("MAILDIR")))
2948
  else if ((p = getenv ("MAILDIR")))
(-)mutt-1.5.17.orig/init.h (+192 lines)
Lines 169-174 struct option_t MuttVars[] = { Link Here
169
  ** If set, Mutt will prompt you for carbon-copy (Cc) recipients before
169
  ** If set, Mutt will prompt you for carbon-copy (Cc) recipients before
170
  ** editing the body of an outgoing message.
170
  ** editing the body of an outgoing message.
171
  */  
171
  */  
172
#ifdef USE_NNTP
173
  { "ask_follow_up",	DT_BOOL, R_NONE, OPTASKFOLLOWUP, 0 },
174
  /*
175
  ** .pp
176
  ** If set, Mutt will prompt you for follow-up groups before editing
177
  ** the body of an outgoing message.
178
  */  
179
  { "ask_x_comment_to",	DT_BOOL, R_NONE, OPTASKXCOMMENTTO, 0 },
180
  /*
181
  ** .pp
182
  ** If set, Mutt will prompt you for x-comment-to field before editing
183
  ** the body of an outgoing message.
184
  */  
185
#endif
172
  { "assumed_charset", DT_STR, R_NONE, UL &AssumedCharset, UL 0},
186
  { "assumed_charset", DT_STR, R_NONE, UL &AssumedCharset, UL 0},
173
  /*
187
  /*
174
  ** .pp
188
  ** .pp
Lines 311-316 struct option_t MuttVars[] = { Link Here
311
  ** When this variable is set, mutt will use file size attribute instead of
325
  ** When this variable is set, mutt will use file size attribute instead of
312
  ** access time when checking for new mail.
326
  ** access time when checking for new mail.
313
  */
327
  */
328
#ifdef USE_NNTP
329
  { "catchup_newsgroup", DT_QUAD, R_NONE, OPT_CATCHUP, M_ASKYES },
330
  /*
331
  ** .pp
332
  ** If this variable is \fIset\fP, Mutt will mark all articles in newsgroup
333
  ** as read when you quit the newsgroup (catchup newsgroup).
334
  */
335
#endif
314
  { "charset",		DT_STR,	 R_NONE, UL &Charset, UL 0 },
336
  { "charset",		DT_STR,	 R_NONE, UL &Charset, UL 0 },
315
  /*
337
  /*
316
  ** .pp
338
  ** .pp
Lines 642-647 struct option_t MuttVars[] = { Link Here
642
  ** sent to both the list and your address, resulting in two copies
664
  ** sent to both the list and your address, resulting in two copies
643
  ** of the same email for you.
665
  ** of the same email for you.
644
  */
666
  */
667
#ifdef USE_NNTP
668
  { "followup_to_poster", DT_QUAD, R_NONE, OPT_FOLLOWUPTOPOSTER, M_ASKYES },
669
  /*
670
  ** .pp
671
  ** If this variable is \fIset\fP and the keyword "poster" is present in
672
  ** \fIFollowup-To\fP header, follow-up to newsgroup function is not
673
  ** permitted.  The message will be mailed to the submitter of the
674
  ** message via mail.
675
  */
676
#endif
645
  { "force_name",	DT_BOOL, R_NONE, OPTFORCENAME, 0 },
677
  { "force_name",	DT_BOOL, R_NONE, OPTFORCENAME, 0 },
646
  /*
678
  /*
647
  ** .pp
679
  ** .pp
Lines 713-718 struct option_t MuttVars[] = { Link Here
713
  ** a regular expression that will match the whole name so mutt will expand
745
  ** a regular expression that will match the whole name so mutt will expand
714
  ** "Franklin" to "Franklin, Steve".
746
  ** "Franklin" to "Franklin, Steve".
715
  */
747
  */
748
#ifdef USE_NNTP
749
  { "group_index_format", DT_STR, R_BOTH, UL &GroupFormat, UL "%4C %M%N %5s  %-45.45f %d" },
750
  /*
751
  ** .pp
752
  ** This variable allows you to customize the newsgroup browser display to
753
  ** your personal taste.  This string is similar to ``$index_format'', but
754
  ** has its own set of printf()-like sequences:
755
  ** .pp
756
  ** .ts
757
  ** %C      current newsgroup number
758
  ** %d      description of newsgroup (becomes from server)
759
  ** %f      newsgroup name
760
  ** %M      - if newsgroup not allowed for direct post (moderated for example)
761
  ** %N      N if newsgroup is new, u if unsubscribed, blank otherwise
762
  ** %n      number of new articles in newsgroup
763
  ** %s      number of unread articles in newsgroup
764
  ** %>X     right justify the rest of the string and pad with character "X"
765
  ** %|X     pad to the end of the line with character "X"
766
  ** .te
767
  */
768
#endif
716
  { "hdr_format",	DT_SYN,  R_NONE, UL "index_format", 0 },
769
  { "hdr_format",	DT_SYN,  R_NONE, UL "index_format", 0 },
717
  /*
770
  /*
718
  */
771
  */
Lines 1006-1011 struct option_t MuttVars[] = { Link Here
1006
  ** .dt %E .dd number of messages in current thread
1059
  ** .dt %E .dd number of messages in current thread
1007
  ** .dt %f .dd entire From: line (address + real name)
1060
  ** .dt %f .dd entire From: line (address + real name)
1008
  ** .dt %F .dd author name, or recipient name if the message is from you
1061
  ** .dt %F .dd author name, or recipient name if the message is from you
1062
  ** .dt %g .dd newsgroup name (if compiled with nntp support)
1009
  ** .dt %H .dd spam attribute(s) of this message
1063
  ** .dt %H .dd spam attribute(s) of this message
1010
  ** .dt %i .dd message-id of the current message
1064
  ** .dt %i .dd message-id of the current message
1011
  ** .dt %l .dd number of lines in the message (does not work with maildir,
1065
  ** .dt %l .dd number of lines in the message (does not work with maildir,
Lines 1020-1031 struct option_t MuttVars[] = { Link Here
1020
  ** .dt %O .dd (_O_riginal save folder)  Where mutt would formerly have
1074
  ** .dt %O .dd (_O_riginal save folder)  Where mutt would formerly have
1021
  **            stashed the message: list name or recipient name if no list
1075
  **            stashed the message: list name or recipient name if no list
1022
  ** .dt %P .dd progress indicator for the builtin pager (how much of the file has been displayed)
1076
  ** .dt %P .dd progress indicator for the builtin pager (how much of the file has been displayed)
1077
  ** .dt %R .dd `x-comment-to:' field (if present and compiled with nntp support)
1023
  ** .dt %s .dd subject of the message
1078
  ** .dt %s .dd subject of the message
1024
  ** .dt %S .dd status of the message (N/D/d/!/r/\(as)
1079
  ** .dt %S .dd status of the message (N/D/d/!/r/\(as)
1025
  ** .dt %t .dd `to:' field (recipients)
1080
  ** .dt %t .dd `to:' field (recipients)
1026
  ** .dt %T .dd the appropriate character from the $$to_chars string
1081
  ** .dt %T .dd the appropriate character from the $$to_chars string
1027
  ** .dt %u .dd user (login) name of the author
1082
  ** .dt %u .dd user (login) name of the author
1028
  ** .dt %v .dd first name of the author, or the recipient if the message is from you
1083
  ** .dt %v .dd first name of the author, or the recipient if the message is from you
1084
  ** .dt %W .dd name of organization of author (`organization:' field)
1029
  ** .dt %X .dd number of attachments
1085
  ** .dt %X .dd number of attachments
1030
  **            (please see the ``$attachments'' section for possible speed effects)
1086
  **            (please see the ``$attachments'' section for possible speed effects)
1031
  ** .dt %y .dd `x-label:' field, if present
1087
  ** .dt %y .dd `x-label:' field, if present
Lines 1059-1064 struct option_t MuttVars[] = { Link Here
1059
  ** .pp
1115
  ** .pp
1060
  ** See also: ``$$to_chars''.
1116
  ** See also: ``$$to_chars''.
1061
  */
1117
  */
1118
#ifdef USE_NNTP
1119
  { "inews",          DT_PATH, R_NONE, UL &Inews, UL "" },
1120
  /*
1121
  ** .pp
1122
  ** If set, specifies the program and arguments used to deliver news posted
1123
  ** by Mutt.  Otherwise, mutt posts article using current connection to
1124
  ** news server.  The following printf-style sequence is understood:
1125
  ** .pp
1126
  ** .ts
1127
  ** %s      newsserver name
1128
  ** .te
1129
  ** .pp
1130
  ** Example: set inews="/usr/local/bin/inews -hS"
1131
  */
1132
#endif
1062
  { "ispell",		DT_PATH, R_NONE, UL &Ispell, UL ISPELL },
1133
  { "ispell",		DT_PATH, R_NONE, UL &Ispell, UL ISPELL },
1063
  /*
1134
  /*
1064
  ** .pp
1135
  ** .pp
Lines 1273-1278 struct option_t MuttVars[] = { Link Here
1273
  ** be attached to the newly composed message if this option is set.
1344
  ** be attached to the newly composed message if this option is set.
1274
  */
1345
  */
1275
1346
1347
#ifdef USE_NNTP
1348
  { "mime_subject",   DT_BOOL, R_NONE, OPTMIMESUBJECT, 1 },
1349
  /*
1350
  ** .pp
1351
  ** If \fIunset\fP, 8-bit ``subject:'' line in article header will not be
1352
  ** encoded according to RFC2047 to base64.  This is useful when message
1353
  ** is Usenet article, because MIME for news is nonstandard feature.
1354
  */
1355
#endif
1356
1276
#ifdef MIXMASTER
1357
#ifdef MIXMASTER
1277
  { "mix_entry_format", DT_STR,  R_NONE, UL &MixEntryFormat, UL "%4n %c %-16s %a" },
1358
  { "mix_entry_format", DT_STR,  R_NONE, UL &MixEntryFormat, UL "%4n %c %-16s %a" },
1278
  /*
1359
  /*
Lines 1350-1355 struct option_t MuttVars[] = { Link Here
1350
   ** See also ``$$read_inc'' and ``$$write_inc''.
1431
   ** See also ``$$read_inc'' and ``$$write_inc''.
1351
   */
1432
   */
1352
#endif  
1433
#endif  
1434
#ifdef USE_NNTP
1435
  { "news_cache_dir", DT_PATH, R_NONE, UL &NewsCacheDir, UL "~/.mutt" },
1436
  /*
1437
  ** .pp
1438
  ** This variable pointing to directory where Mutt will save cached news
1439
  ** articles headers in. If \fIunset\fP, headers will not be saved at all
1440
  ** and will be reloaded each time when you enter to newsgroup.
1441
  */
1442
  { "news_server",    DT_STR,  R_NONE, UL &NewsServer, 0 },
1443
  /*
1444
  ** .pp
1445
  ** This variable specifies domain name or address of NNTP server. It
1446
  ** defaults to the newsserver specified in the environment variable
1447
  ** $$$NNTPSERVER or contained in the file /etc/nntpserver.  You can also
1448
  ** specify username and an alternative port for each newsserver, ie:
1449
  ** .pp
1450
  ** [news[s]://][username[:password]@]newsserver[:port]
1451
  */
1452
  { "newsrc",         DT_PATH, R_NONE, UL &NewsRc, UL "~/.newsrc" },
1453
  /*
1454
  ** .pp
1455
  ** The file, containing info about subscribed newsgroups - names and
1456
  ** indexes of read articles.  The following printf-style sequence
1457
  ** is understood:
1458
  ** .pp
1459
  ** .ts
1460
  ** %s      newsserver name
1461
  ** .te
1462
  */
1463
  { "nntp_context",   DT_NUM,  R_NONE, UL &NntpContext, 1000 },
1464
  /*
1465
  ** .pp
1466
  ** This variable defines number of articles which will be in index when
1467
  ** newsgroup entered.  If active newsgroup have more articles than this
1468
  ** number, oldest articles will be ignored.  Also controls how many
1469
  ** articles headers will be saved in cache when you quit newsgroup.
1470
  */
1471
  { "nntp_load_description", DT_BOOL, R_NONE, OPTLOADDESC, 1 },
1472
  /*
1473
  ** .pp
1474
  ** This variable controls whether or not descriptions for each newsgroup
1475
  ** must be loaded when newsgroup is added to list (first time list
1476
  ** loading or new newsgroup adding).
1477
  */
1478
  { "nntp_user",      DT_STR,  R_NONE, UL &NntpUser, UL "" },
1479
  /*
1480
  ** .pp
1481
  ** Your login name on the NNTP server.  If \fIunset\fP and NNTP server requires
1482
  ** authentification, Mutt will prompt you for your account name when you
1483
  ** connect to newsserver.
1484
  */
1485
  { "nntp_pass",      DT_STR,  R_NONE, UL &NntpPass, UL "" },
1486
  /*
1487
  ** .pp
1488
  ** Your password for NNTP account.
1489
  */
1490
  { "nntp_poll",      DT_NUM,  R_NONE, UL &NewsPollTimeout, 60 },
1491
  /*
1492
  ** .pp
1493
  ** The time in seconds until any operations on newsgroup except post new
1494
  ** article will cause recheck for new news.  If set to 0, Mutt will
1495
  ** recheck newsgroup on each operation in index (stepping, read article,
1496
  ** etc.).
1497
  */
1498
  { "nntp_reconnect", DT_QUAD, R_NONE, OPT_NNTPRECONNECT, M_ASKYES },
1499
  /*
1500
  ** .pp
1501
  ** Controls whether or not Mutt will try to reconnect to newsserver when
1502
  ** connection lost.
1503
  */
1504
#endif
1353
  { "pager",		DT_PATH, R_NONE, UL &Pager, UL "builtin" },
1505
  { "pager",		DT_PATH, R_NONE, UL &Pager, UL "builtin" },
1354
  /*
1506
  /*
1355
  ** .pp
1507
  ** .pp
Lines 2160-2165 struct option_t MuttVars[] = { Link Here
2160
  { "post_indent_str",  DT_SYN,  R_NONE, UL "post_indent_string", 0 },
2312
  { "post_indent_str",  DT_SYN,  R_NONE, UL "post_indent_string", 0 },
2161
  /*
2313
  /*
2162
  */
2314
  */
2315
#ifdef USE_NNTP
2316
  { "post_moderated", DT_QUAD, R_NONE, OPT_TOMODERATED, M_ASKYES },
2317
  /*
2318
  ** .pp
2319
  ** If set to \fIyes\fP, Mutt will post article to newsgroup that have
2320
  ** not permissions to posting (e.g. moderated).  \fBNote:\fP if newsserver
2321
  ** does not support posting to that newsgroup or totally read-only, that
2322
  ** posting will not have an effect.
2323
  */
2324
#endif
2163
  { "postpone",		DT_QUAD, R_NONE, OPT_POSTPONE, M_ASKYES },
2325
  { "postpone",		DT_QUAD, R_NONE, OPT_POSTPONE, M_ASKYES },
2164
  /*
2326
  /*
2165
  ** .pp
2327
  ** .pp
Lines 2519-2524 struct option_t MuttVars[] = { Link Here
2519
  ** Command to use when spawning a subshell.  By default, the user's login
2681
  ** Command to use when spawning a subshell.  By default, the user's login
2520
  ** shell from /etc/passwd is used.
2682
  ** shell from /etc/passwd is used.
2521
  */
2683
  */
2684
#ifdef USE_NNTP
2685
  { "save_unsubscribed",DT_BOOL, R_NONE, OPTSAVEUNSUB, 0 },
2686
  /*
2687
  ** .pp
2688
  ** When \fIset\fP, info about unsubscribed newsgroups will be saved into
2689
  ** ``newsrc'' file and into cache.
2690
  */
2691
  { "show_new_news",  DT_BOOL, R_NONE, OPTSHOWNEWNEWS, 1 },
2692
  /*
2693
  ** .pp
2694
  ** If \fIset\fP, newsserver will be asked for new newsgroups on entering
2695
  ** the browser.  Otherwise, it will be done only once for a newsserver.
2696
  ** Also controls whether or not number of new articles of subscribed
2697
  ** newsgroups will be then checked.
2698
  */
2699
  { "show_only_unread",  DT_BOOL, R_NONE, OPTSHOWONLYUNREAD, 0 },
2700
  /*
2701
  ** .pp
2702
  ** If \fIset\fP, only subscribed newsgroups that contain unread articles
2703
  ** will be displayed in browser.
2704
  */
2705
#endif
2522
  { "sig_dashes",	DT_BOOL, R_NONE, OPTSIGDASHES, 1 },
2706
  { "sig_dashes",	DT_BOOL, R_NONE, OPTSIGDASHES, 1 },
2523
  /*
2707
  /*
2524
  ** .pp
2708
  ** .pp
Lines 3032-3037 struct option_t MuttVars[] = { Link Here
3032
  ** option does nothing: mutt will never write out the BCC header
3216
  ** option does nothing: mutt will never write out the BCC header
3033
  ** in this case.
3217
  ** in this case.
3034
  */
3218
  */
3219
#ifdef USE_NNTP
3220
  { "x_comment_to",   DT_BOOL, R_NONE, OPTXCOMMENTTO, 0 },
3221
  /*
3222
  ** .pp
3223
  ** If \fIset\fP, Mutt will add ``X-Comment-To:'' field (that contains full
3224
  ** name of original article author) to article that followuped to newsgroup.
3225
  */
3226
#endif
3035
  /*--*/
3227
  /*--*/
3036
  { NULL }
3228
  { NULL }
3037
};
3229
};
(-)mutt-1.5.17.orig/keymap.c (-1 lines)
Lines 629-635 void km_init (void) Link Here
629
  km_bindkey ("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
629
  km_bindkey ("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
630
630
631
  km_bindkey ("x", MENU_PAGER, OP_EXIT);
631
  km_bindkey ("x", MENU_PAGER, OP_EXIT);
632
  km_bindkey ("i", MENU_PAGER, OP_EXIT);
633
  km_bindkey ("<backspace>", MENU_PAGER, OP_PREV_LINE);
632
  km_bindkey ("<backspace>", MENU_PAGER, OP_PREV_LINE);
634
  km_bindkey ("<pagedown>", MENU_PAGER, OP_NEXT_PAGE);
633
  km_bindkey ("<pagedown>", MENU_PAGER, OP_NEXT_PAGE);
635
  km_bindkey ("<pageup>", MENU_PAGER, OP_PREV_PAGE);
634
  km_bindkey ("<pageup>", MENU_PAGER, OP_PREV_PAGE);
(-)mutt-1.5.17.orig/mailbox.h (+3 lines)
Lines 74-79 int mx_is_imap (const char *); Link Here
74
#ifdef USE_POP
74
#ifdef USE_POP
75
int mx_is_pop (const char *);
75
int mx_is_pop (const char *);
76
#endif
76
#endif
77
#ifdef USE_NNTP
78
int mx_is_nntp (const char *);
79
#endif
77
80
78
int mx_access (const char*, int);
81
int mx_access (const char*, int);
79
int mx_check_empty (const char *);
82
int mx_check_empty (const char *);
(-)mutt-1.5.17.orig/main.c (+54 lines)
Lines 60-65 Link Here
60
#include <stringprep.h>
60
#include <stringprep.h>
61
#endif
61
#endif
62
62
63
#ifdef USE_NNTP
64
#include "nntp.h"
65
#endif
66
63
static const char *ReachingUs = N_("\
67
static const char *ReachingUs = N_("\
64
To contact the developers, please mail to <mutt-dev@mutt.org>.\n\
68
To contact the developers, please mail to <mutt-dev@mutt.org>.\n\
65
To report a bug, please visit http://bugs.mutt.org/.\n");
69
To report a bug, please visit http://bugs.mutt.org/.\n");
Lines 131-136 options:\n\ Link Here
131
"  -e <command>\tspecify a command to be executed after initialization\n\
135
"  -e <command>\tspecify a command to be executed after initialization\n\
132
  -f <file>\tspecify which mailbox to read\n\
136
  -f <file>\tspecify which mailbox to read\n\
133
  -F <file>\tspecify an alternate muttrc file\n\
137
  -F <file>\tspecify an alternate muttrc file\n\
138
  -g <server>\tspecify a newsserver (if compiled with NNTP)\n\
139
  -G\t\tselect a newsgroup (if compiled with NNTP)\n\
134
  -H <file>\tspecify a draft file to read header and body from\n\
140
  -H <file>\tspecify a draft file to read header and body from\n\
135
  -i <file>\tspecify a file which Mutt should include in the body\n\
141
  -i <file>\tspecify a file which Mutt should include in the body\n\
136
  -m <type>\tspecify a default mailbox type\n\
142
  -m <type>\tspecify a default mailbox type\n\
Lines 261-266 static void show_version (void) Link Here
261
	"-USE_POP  "
267
	"-USE_POP  "
262
#endif
268
#endif
263
269
270
#ifdef USE_NNTP
271
	"+USE_NNTP  "
272
#else
273
	"-USE_NNTP  "
274
#endif
275
264
#ifdef USE_IMAP
276
#ifdef USE_IMAP
265
        "+USE_IMAP  "
277
        "+USE_IMAP  "
266
#else
278
#else
Lines 529-534 static void start_curses (void) Link Here
529
#define M_NOSYSRC (1<<2)	/* -n */
541
#define M_NOSYSRC (1<<2)	/* -n */
530
#define M_RO      (1<<3)	/* -R */
542
#define M_RO      (1<<3)	/* -R */
531
#define M_SELECT  (1<<4)	/* -y */
543
#define M_SELECT  (1<<4)	/* -y */
544
#ifdef USE_NNTP
545
#define M_NEWS    (1<<5)	/* -g and -G */
546
#endif
532
547
533
int main (int argc, char **argv)
548
int main (int argc, char **argv)
534
{
549
{
Lines 585-591 int main (int argc, char **argv) Link Here
585
      break;
600
      break;
586
    }
601
    }
587
602
603
#ifdef USE_NNTP
604
  while ((i = getopt (argc, argv, "A:a:b:F:f:c:Dd:e:g:GH:s:i:hm:npQ:RvxyzZ")) != EOF)
605
#else
588
  while ((i = getopt (argc, argv, "A:a:b:F:f:c:Dd:e:H:s:i:hm:npQ:RvxyzZ")) != EOF)
606
  while ((i = getopt (argc, argv, "A:a:b:F:f:c:Dd:e:H:s:i:hm:npQ:RvxyzZ")) != EOF)
607
#endif
589
    switch (i)
608
    switch (i)
590
    {
609
    {
591
      case 'A':
610
      case 'A':
Lines 678-683 int main (int argc, char **argv) Link Here
678
	flags |= M_SELECT;
697
	flags |= M_SELECT;
679
	break;
698
	break;
680
699
700
#ifdef USE_NNTP
701
      case 'g': /* Specify a newsserver */
702
	{
703
	  char buf[LONG_STRING];
704
705
	  snprintf (buf, sizeof (buf), "set news_server=%s", optarg);
706
	  commands = mutt_add_list (commands, buf);
707
	}
708
709
      case 'G': /* List of newsgroups */
710
	flags |= M_SELECT | M_NEWS;
711
	break;
712
#endif
713
681
      case 'z':
714
      case 'z':
682
	flags |= M_IGNORE;
715
	flags |= M_IGNORE;
683
	break;
716
	break;
Lines 955-960 int main (int argc, char **argv) Link Here
955
    }
988
    }
956
    else if (flags & M_SELECT)
989
    else if (flags & M_SELECT)
957
    {
990
    {
991
#ifdef USE_NNTP
992
      if (flags & M_NEWS)
993
      {
994
	set_option (OPTNEWS);
995
	if(!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)))
996
	{
997
	  mutt_endwin (Errorbuf);
998
	  exit (1);
999
	}
1000
      }
1001
      else
1002
#endif
958
      if (!Incoming) {
1003
      if (!Incoming) {
959
	mutt_endwin _("No incoming mailboxes defined.");
1004
	mutt_endwin _("No incoming mailboxes defined.");
960
	exit (1);
1005
	exit (1);
Lines 970-975 int main (int argc, char **argv) Link Here
970
1015
971
    if (!folder[0])
1016
    if (!folder[0])
972
      strfcpy (folder, NONULL(Spoolfile), sizeof (folder));
1017
      strfcpy (folder, NONULL(Spoolfile), sizeof (folder));
1018
1019
#ifdef USE_NNTP
1020
    if (option (OPTNEWS))
1021
    {
1022
      unset_option (OPTNEWS);
1023
      nntp_expand_path (folder, sizeof (folder), &CurrentNewsSrv->conn->account);
1024
    }
1025
    else
1026
#endif
973
    mutt_expand_path (folder, sizeof (folder));
1027
    mutt_expand_path (folder, sizeof (folder));
974
1028
975
    mutt_str_replace (&CurrentFolder, folder);
1029
    mutt_str_replace (&CurrentFolder, folder);
(-)mutt-1.5.17.orig/mutt.h (-1 / +43 lines)
Lines 243-248 enum Link Here
243
  M_PGP_KEY,
243
  M_PGP_KEY,
244
  M_XLABEL,
244
  M_XLABEL,
245
  M_MIMEATTACH,
245
  M_MIMEATTACH,
246
#ifdef USE_NNTP
247
  M_NEWSGROUPS,
248
#endif
246
  
249
  
247
  /* Options for Mailcap lookup */
250
  /* Options for Mailcap lookup */
248
  M_EDIT,
251
  M_EDIT,
Lines 298-303 enum Link Here
298
#endif
301
#endif
299
  OPT_SUBJECT,
302
  OPT_SUBJECT,
300
  OPT_VERIFYSIG,      /* verify PGP signatures */
303
  OPT_VERIFYSIG,      /* verify PGP signatures */
304
#ifdef USE_NNTP
305
  OPT_TOMODERATED,
306
  OPT_NNTPRECONNECT,
307
  OPT_CATCHUP,
308
  OPT_FOLLOWUPTOPOSTER,
309
#endif /* USE_NNTP */
301
    
310
    
302
  /* THIS MUST BE THE LAST VALUE. */
311
  /* THIS MUST BE THE LAST VALUE. */
303
  OPT_MAX
312
  OPT_MAX
Lines 313-318 enum Link Here
313
#define SENDMAILX	(1<<6)
322
#define SENDMAILX	(1<<6)
314
#define SENDKEY		(1<<7)
323
#define SENDKEY		(1<<7)
315
#define SENDRESEND	(1<<8)
324
#define SENDRESEND	(1<<8)
325
#define SENDNEWS	(1<<9)
316
326
317
/* flags to _mutt_select_file() */
327
/* flags to _mutt_select_file() */
318
#define M_SEL_BUFFY	(1<<0)
328
#define M_SEL_BUFFY	(1<<0)
Lines 332-337 enum Link Here
332
  OPTASCIICHARS,
342
  OPTASCIICHARS,
333
  OPTASKBCC,
343
  OPTASKBCC,
334
  OPTASKCC,
344
  OPTASKCC,
345
  OPTASKFOLLOWUP,
346
  OPTASKXCOMMENTTO,
335
  OPTATTACHSPLIT,
347
  OPTATTACHSPLIT,
336
  OPTAUTOEDIT,
348
  OPTAUTOEDIT,
337
  OPTAUTOTAG,
349
  OPTAUTOTAG,
Lines 407-412 enum Link Here
407
  OPTMETOO,
419
  OPTMETOO,
408
  OPTMHPURGE,
420
  OPTMHPURGE,
409
  OPTMIMEFORWDECODE,
421
  OPTMIMEFORWDECODE,
422
#ifdef USE_NNTP
423
  OPTMIMESUBJECT,	/* encode subject line with RFC2047 */
424
#endif
410
  OPTNARROWTREE,
425
  OPTNARROWTREE,
411
  OPTPAGERSTOP,
426
  OPTPAGERSTOP,
412
  OPTPIPEDECODE,
427
  OPTPIPEDECODE,
Lines 488-493 enum Link Here
488
  OPTPGPAUTOINLINE,
503
  OPTPGPAUTOINLINE,
489
  OPTPGPREPLYINLINE,
504
  OPTPGPREPLYINLINE,
490
505
506
  /* news options */
507
508
#ifdef USE_NNTP
509
  OPTSHOWNEWNEWS,
510
  OPTSHOWONLYUNREAD,
511
  OPTSAVEUNSUB,
512
  OPTLOADDESC,
513
  OPTXCOMMENTTO,
514
#endif /* USE_NNTP */
515
491
  /* pseudo options */
516
  /* pseudo options */
492
517
493
  OPTAUXSORT,		/* (pseudo) using auxillary sort function */
518
  OPTAUXSORT,		/* (pseudo) using auxillary sort function */
Lines 508-513 enum Link Here
508
  OPTSORTSUBTHREADS,	/* (pseudo) used when $sort_aux changes */
533
  OPTSORTSUBTHREADS,	/* (pseudo) used when $sort_aux changes */
509
  OPTNEEDRESCORE,	/* (pseudo) set when the `score' command is used */
534
  OPTNEEDRESCORE,	/* (pseudo) set when the `score' command is used */
510
  OPTATTACHMSG,		/* (pseudo) used by attach-message */
535
  OPTATTACHMSG,		/* (pseudo) used by attach-message */
536
  OPTHIDEREAD,		/* (pseudo) whether or not hide read messages */
511
  OPTKEEPQUIET,		/* (pseudo) shut up the message and refresh
537
  OPTKEEPQUIET,		/* (pseudo) shut up the message and refresh
512
			 * 	    functions while we are executing an
538
			 * 	    functions while we are executing an
513
			 * 	    external program.
539
			 * 	    external program.
Lines 518-523 enum Link Here
518
  OPTDONTHANDLEPGPKEYS,	/* (pseudo) used to extract PGP keys */
544
  OPTDONTHANDLEPGPKEYS,	/* (pseudo) used to extract PGP keys */
519
  OPTUNBUFFEREDINPUT,   /* (pseudo) don't use key buffer */
545
  OPTUNBUFFEREDINPUT,   /* (pseudo) don't use key buffer */
520
546
547
#ifdef USE_NNTP
548
  OPTNEWS,		/* (pseudo) used to change reader mode */
549
  OPTNEWSSEND,		/* (pseudo) used to change behavior when posting */
550
  OPTNEWSCACHE,		/* (pseudo) used to indicate if news cache exist */
551
#endif
552
521
  OPTMAX
553
  OPTMAX
522
};
554
};
523
555
Lines 595-600 typedef struct envelope Link Here
595
  char *supersedes;
627
  char *supersedes;
596
  char *date;
628
  char *date;
597
  char *x_label;
629
  char *x_label;
630
  char *organization;
631
#ifdef USE_NNTP
632
  char *newsgroups;
633
  char *xref;
634
  char *followup_to;
635
  char *x_comment_to;
636
#endif
598
  BUFFER *spam;
637
  BUFFER *spam;
599
  LIST *references;		/* message references (in reverse order) */
638
  LIST *references;		/* message references (in reverse order) */
600
  LIST *in_reply_to;		/* in-reply-to header content */
639
  LIST *in_reply_to;		/* in-reply-to header content */
Lines 761-766 typedef struct header Link Here
761
  ENVELOPE *env;		/* envelope information */
800
  ENVELOPE *env;		/* envelope information */
762
  BODY *content;		/* list of MIME parts */
801
  BODY *content;		/* list of MIME parts */
763
  char *path;
802
  char *path;
803
#ifdef USE_NNTP
804
  int article_num;
805
#endif
764
  
806
  
765
  char *tree;           	/* character string to print thread tree */
807
  char *tree;           	/* character string to print thread tree */
766
  struct thread *thread;
808
  struct thread *thread;
Lines 776-782 typedef struct header Link Here
776
  int refno;			/* message number on server */
818
  int refno;			/* message number on server */
777
#endif
819
#endif
778
820
779
#if defined USE_POP || defined USE_IMAP
821
#if defined USE_POP || defined USE_IMAP || defined USE_NNTP
780
  void *data;            	/* driver-specific data */
822
  void *data;            	/* driver-specific data */
781
#endif
823
#endif
782
  
824
  
(-)mutt-1.5.17.orig/muttlib.c (-1 / +16 lines)
Lines 286-292 void mutt_free_header (HEADER **h) Link Here
286
#ifdef MIXMASTER
286
#ifdef MIXMASTER
287
  mutt_free_list (&(*h)->chain);
287
  mutt_free_list (&(*h)->chain);
288
#endif
288
#endif
289
#if defined USE_POP || defined USE_IMAP
289
#if defined USE_POP || defined USE_IMAP || defined USE_NNTP
290
  FREE (&(*h)->data);
290
  FREE (&(*h)->data);
291
#endif
291
#endif
292
  FREE (h);		/* __FREE_CHECKED__ */
292
  FREE (h);		/* __FREE_CHECKED__ */
Lines 674-679 void mutt_free_envelope (ENVELOPE **p) Link Here
674
  FREE (&(*p)->supersedes);
674
  FREE (&(*p)->supersedes);
675
  FREE (&(*p)->date);
675
  FREE (&(*p)->date);
676
  FREE (&(*p)->x_label);
676
  FREE (&(*p)->x_label);
677
  FREE (&(*p)->organization);
678
#ifdef USE_NNTP
679
  FREE (&(*p)->newsgroups);
680
  FREE (&(*p)->xref);
681
  FREE (&(*p)->followup_to);
682
  FREE (&(*p)->x_comment_to);
683
#endif
677
684
678
  mutt_buffer_free (&(*p)->spam);
685
  mutt_buffer_free (&(*p)->spam);
679
686
Lines 1444-1449 int mutt_save_confirm (const char *s, st Link Here
1444
    }
1451
    }
1445
  }
1452
  }
1446
1453
1454
#ifdef USE_NNTP
1455
  if (magic == M_NNTP)
1456
  {
1457
    mutt_error _("Can't save message to newsserver.");
1458
    return 0;
1459
  }
1460
#endif
1461
1447
  if (stat (s, st) != -1)
1462
  if (stat (s, st) != -1)
1448
  {
1463
  {
1449
    if (magic == -1)
1464
    if (magic == -1)
(-)mutt-1.5.17.orig/mx.c (+60 lines)
Lines 343-348 int mx_is_pop (const char *p) Link Here
343
}
343
}
344
#endif
344
#endif
345
345
346
#ifdef USE_NNTP
347
int mx_is_nntp (const char *p)
348
{
349
  url_scheme_t scheme;
350
351
  if (!p)
352
    return 0;
353
354
  scheme = url_check_scheme (p);
355
  if (scheme == U_NNTP || scheme == U_NNTPS)
356
    return 1;
357
358
  return 0;
359
}
360
#endif
361
346
int mx_get_magic (const char *path)
362
int mx_get_magic (const char *path)
347
{
363
{
348
  struct stat st;
364
  struct stat st;
Lines 360-365 int mx_get_magic (const char *path) Link Here
360
    return M_POP;
376
    return M_POP;
361
#endif /* USE_POP */
377
#endif /* USE_POP */
362
378
379
#ifdef USE_NNTP
380
  if (mx_is_nntp (path))
381
    return M_NNTP;
382
#endif /* USE_NNTP */
383
363
  if (stat (path, &st) == -1)
384
  if (stat (path, &st) == -1)
364
  {
385
  {
365
    dprint (1, (debugfile, "mx_get_magic(): unable to stat %s: %s (errno %d).\n",
386
    dprint (1, (debugfile, "mx_get_magic(): unable to stat %s: %s (errno %d).\n",
Lines 699-704 CONTEXT *mx_open_mailbox (const char *pa Link Here
699
      break;
720
      break;
700
#endif /* USE_POP */
721
#endif /* USE_POP */
701
722
723
#ifdef USE_NNTP
724
    case M_NNTP:
725
      rc = nntp_open_mailbox (ctx);
726
      break;
727
#endif /* USE_NNTP */
728
702
    default:
729
    default:
703
      rc = -1;
730
      rc = -1;
704
      break;
731
      break;
Lines 791-796 static int sync_mailbox (CONTEXT *ctx, i Link Here
791
      rc = pop_sync_mailbox (ctx, index_hint);
818
      rc = pop_sync_mailbox (ctx, index_hint);
792
      break;
819
      break;
793
#endif /* USE_POP */
820
#endif /* USE_POP */
821
822
#ifdef USE_NNTP
823
    case M_NNTP:
824
      rc = nntp_sync_mailbox (ctx);
825
      break;
826
#endif /* USE_NNTP */
794
  }
827
  }
795
828
796
#if 0
829
#if 0
Lines 817-822 int mx_close_mailbox (CONTEXT *ctx, int Link Here
817
850
818
  ctx->closing = 1;
851
  ctx->closing = 1;
819
852
853
#ifdef USE_NNTP
854
  if (ctx->magic == M_NNTP)
855
  {
856
    int ret;
857
858
    ret = nntp_close_mailbox (ctx);
859
    mx_fastclose_mailbox (ctx);
860
    return ret;
861
  }
862
#endif
820
  if (ctx->readonly || ctx->dontwrite)
863
  if (ctx->readonly || ctx->dontwrite)
821
  {
864
  {
822
    /* mailbox is readonly or we don't want to write */
865
    /* mailbox is readonly or we don't want to write */
Lines 1354-1359 int mx_check_mailbox (CONTEXT *ctx, int Link Here
1354
      case M_POP:
1397
      case M_POP:
1355
	return (pop_check_mailbox (ctx, index_hint));
1398
	return (pop_check_mailbox (ctx, index_hint));
1356
#endif /* USE_POP */
1399
#endif /* USE_POP */
1400
1401
#ifdef USE_NNTP
1402
      case M_NNTP:
1403
	return (nntp_check_mailbox (ctx));
1404
#endif /* USE_NNTP */
1357
    }
1405
    }
1358
  }
1406
  }
1359
1407
Lines 1414-1419 MESSAGE *mx_open_message (CONTEXT *ctx, Link Here
1414
    }
1462
    }
1415
#endif /* USE_POP */
1463
#endif /* USE_POP */
1416
1464
1465
#ifdef USE_NNTP
1466
    case M_NNTP:
1467
    {
1468
      if (nntp_fetch_message (msg, ctx, msgno) != 0)
1469
	FREE (&msg);
1470
      break;
1471
    }
1472
#endif /* USE_NNTP */
1473
1417
    default:
1474
    default:
1418
      dprint (1, (debugfile, "mx_open_message(): function not implemented for mailbox type %d.\n", ctx->magic));
1475
      dprint (1, (debugfile, "mx_open_message(): function not implemented for mailbox type %d.\n", ctx->magic));
1419
      FREE (&msg);
1476
      FREE (&msg);
Lines 1495-1500 int mx_close_message (MESSAGE **msg) Link Here
1495
#ifdef USE_POP
1552
#ifdef USE_POP
1496
      || (*msg)->magic == M_POP
1553
      || (*msg)->magic == M_POP
1497
#endif
1554
#endif
1555
#ifdef USE_NNTP
1556
      || (*msg)->magic == M_NNTP
1557
#endif
1498
      )
1558
      )
1499
  {
1559
  {
1500
    r = safe_fclose (&(*msg)->fp);
1560
    r = safe_fclose (&(*msg)->fp);
(-)mutt-1.5.17.orig/mx.h (+3 lines)
Lines 40-45 enum Link Here
40
#ifdef USE_POP
40
#ifdef USE_POP
41
  , M_POP
41
  , M_POP
42
#endif
42
#endif
43
#ifdef USE_NNTP
44
  , M_NNTP
45
#endif
43
};
46
};
44
47
45
WHERE short DefaultMagic INITVAL (M_MBOX);
48
WHERE short DefaultMagic INITVAL (M_MBOX);
(-)mutt-1.5.17.orig/newsrc.c (+1170 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 1998 Brandon Long <blong@fiction.net>
3
 * Copyright (C) 1999 Andrej Gritsenko <andrej@lucky.net>
4
 * Copyright (C) 2000-2007 Vsevolod Volkov <vvv@mutt.org.ua>
5
 * 
6
 *     This program is free software; you can redistribute it and/or modify
7
 *     it under the terms of the GNU General Public License as published by
8
 *     the Free Software Foundation; either version 2 of the License, or
9
 *     (at your option) any later version.
10
 * 
11
 *     This program is distributed in the hope that it will be useful,
12
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *     GNU General Public License for more details.
15
 * 
16
 *     You should have received a copy of the GNU General Public License
17
 *     along with this program; if not, write to the Free Software
18
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */ 
20
21
#if HAVE_CONFIG_H
22
# include "config.h"
23
#endif
24
25
#include "mutt.h"
26
#include "mutt_curses.h"
27
#include "sort.h"
28
#include "mx.h"
29
#include "mime.h"
30
#include "mailbox.h"
31
#include "nntp.h"
32
#include "rfc822.h"
33
#include "rfc1524.h"
34
#include "rfc2047.h"
35
36
#include <unistd.h>
37
#include <string.h>
38
#include <ctype.h>
39
#include <stdlib.h>
40
#include <sys/stat.h>
41
42
void nntp_add_to_list (NNTP_SERVER *s, NNTP_DATA *d)
43
{
44
  LIST *l;
45
46
  if (!s || !d)
47
    return;
48
49
  l = safe_calloc (1, sizeof (LIST));
50
  if (s->list)
51
    s->tail->next = l;
52
  else
53
    s->list = l;
54
  s->tail = l;
55
  l->data = (void *) d;
56
}
57
58
static int nntp_parse_newsrc_line (NNTP_SERVER *news, char *line)
59
{
60
  NNTP_DATA *data;
61
  char group[LONG_STRING];
62
  int x = 1;
63
  char *p = line, *b, *h;
64
  size_t len;
65
66
  while (*p)
67
  {
68
    if (*p++ == ',')
69
      x++;
70
  }
71
72
  p = line;
73
  while (*p && (*p != ':' && *p != '!')) p++;
74
  if (!*p)
75
    return -1;
76
  len = p + 1 - line;
77
  if (len > sizeof (group))
78
    len = sizeof (group);
79
  strfcpy (group, line, len);
80
  if ((data = (NNTP_DATA *)hash_find (news->newsgroups, group)) == NULL)
81
  {
82
    data = (NNTP_DATA *) safe_calloc (1, sizeof (NNTP_DATA) + strlen (group) + 1);
83
    data->group = (char *) data + sizeof (NNTP_DATA);
84
    strcpy (data->group, group);
85
    data->nserv = news;
86
    data->deleted = 1;
87
    if (news->newsgroups->nelem < news->newsgroups->curnelem * 2)
88
      news->newsgroups = hash_resize (news->newsgroups, news->newsgroups->nelem * 2);
89
    hash_insert (news->newsgroups, data->group, data, 0);
90
    nntp_add_to_list (news, data);
91
  }
92
  else
93
    FREE ((void **) &data->entries);
94
95
  data->rc = 1;
96
  data->entries = safe_calloc (x*2, sizeof (NEWSRC_ENTRY));
97
  data->max = x*2;
98
99
  if (*p == ':')
100
    data->subscribed = 1;
101
  else
102
    data->subscribed = 0;
103
104
  p++;
105
  b = p;
106
  x = 0;
107
  while (*b)
108
  {
109
    while (*p && *p != ',' && *p != '\n') p++;
110
    if (*p)
111
    {
112
      *p = '\0';
113
      p++;
114
    }
115
    if ((h = strchr(b, '-')))
116
    {
117
      *h = '\0';
118
      h++;
119
      data->entries[x].first = atoi(b);
120
      data->entries[x].last = atoi(h);
121
    }
122
    else
123
    {
124
      data->entries[x].first = atoi(b);
125
      data->entries[x].last = data->entries[x].first;
126
    }
127
    b = p;
128
    if (data->entries[x].last != 0)
129
      x++;
130
  }
131
  if (x && !data->lastMessage)
132
    data->lastMessage = data->entries[x-1].last;
133
  data->num = x;
134
  mutt_newsgroup_stat (data);
135
  dprint (2, (debugfile, "parse_line: Newsgroup %s\n", data->group));
136
  
137
  return 0;
138
}
139
140
static int slurp_newsrc (NNTP_SERVER *news)
141
{
142
  FILE *fp;
143
  char *buf;
144
  struct stat sb;
145
146
  news->stat = stat (news->newsrc, &sb);
147
  news->size = sb.st_size;
148
  news->mtime = sb.st_mtime;
149
150
  if ((fp = safe_fopen (news->newsrc, "r")) == NULL)
151
    return -1;
152
  /* hmm, should we use dotlock? */
153
  if (mx_lock_file (news->newsrc, fileno (fp), 0, 0, 1))
154
  {
155
    fclose (fp);
156
    return -1;
157
  }
158
159
  buf = safe_malloc (sb.st_size + 1);
160
  while (sb.st_size && fgets (buf, sb.st_size + 1, fp))
161
    nntp_parse_newsrc_line (news, buf);
162
  FREE (&buf);
163
164
  mx_unlock_file (news->newsrc, fileno (fp), 0);
165
  fclose (fp);
166
  return 0;
167
}
168
169
void nntp_cache_expand (char *dst, const char *src)
170
{
171
  snprintf (dst, _POSIX_PATH_MAX, "%s/%s", NewsCacheDir, src);
172
  mutt_expand_path (dst, _POSIX_PATH_MAX);
173
}
174
175
/* Loads $news_cache_dir/.index into memory, loads newsserver data
176
 * and newsgroup cache names */
177
static int nntp_parse_cacheindex (NNTP_SERVER *news)
178
{
179
  struct stat st;
180
  char buf[HUGE_STRING], *cp;
181
  char dir[_POSIX_PATH_MAX], file[_POSIX_PATH_MAX];
182
  FILE *index;
183
  NNTP_DATA *data;
184
  int l, m, t;
185
186
  /* check is server name defined or not */
187
  if (!news || !news->conn || !news->conn->account.host)
188
    return -1;
189
  unset_option (OPTNEWSCACHE);
190
  if (!NewsCacheDir || !*NewsCacheDir)
191
    return 0;
192
193
  strfcpy (dir, NewsCacheDir, sizeof (dir));
194
  mutt_expand_path (dir, sizeof(dir));
195
196
  if (lstat (dir, &st) || (st.st_mode & S_IFDIR) == 0)
197
  {
198
    snprintf (buf, sizeof(buf), _("Directory %s not exist. Create it?"), dir);
199
    if (mutt_yesorno (buf, M_YES) != M_YES || mkdir (dir, (S_IRWXU+S_IRWXG+
200
	  S_IRWXO)))
201
    {
202
      mutt_error _("Cache directory not created!");
203
      return -1;
204
    }
205
    mutt_clear_error();
206
  }
207
208
  set_option (OPTNEWSCACHE);
209
210
  FREE (&news->cache);
211
  snprintf (buf, sizeof(buf), "%s/.index", dir);
212
  if (!(index = safe_fopen (buf, "a+")))
213
    return 0;
214
  rewind (index);
215
  while (fgets (buf, sizeof(buf), index))
216
  {
217
    buf[strlen(buf) - 1] = 0;	/* strip ending '\n' */
218
    if (!mutt_strncmp (buf, "#: ", 3) &&
219
	!mutt_strcasecmp (buf+3, news->conn->account.host))
220
      break;
221
  }
222
  while (fgets (buf, sizeof(buf), index))
223
  {
224
    cp = buf;
225
    while (*cp && *cp != ' ') cp++;
226
    if (!*cp) continue;
227
    cp[0] = 0;
228
    if (!mutt_strcmp (buf, "#:"))
229
      break;
230
    sscanf (cp + 1, "%s %d %d", file, &l, &m);
231
    if (!mutt_strcmp (buf, "ALL"))
232
    {
233
      news->cache = safe_strdup (file);
234
      news->newgroups_time = m;
235
    }
236
    else if (news->newsgroups)
237
    {
238
      if ((data = (NNTP_DATA *)hash_find (news->newsgroups, buf)) == NULL)
239
      {
240
	data = (NNTP_DATA *) safe_calloc (1, sizeof (NNTP_DATA) + strlen (buf) + 1);
241
	data->group = (char *) data + sizeof (NNTP_DATA);
242
	strcpy(data->group, buf);
243
	data->nserv = news;
244
	data->deleted = 1;
245
	if (news->newsgroups->nelem < news->newsgroups->curnelem * 2)
246
	  news->newsgroups = hash_resize (news->newsgroups, news->newsgroups->nelem * 2);
247
	hash_insert (news->newsgroups, data->group, data, 0);
248
	nntp_add_to_list (news, data);
249
      }
250
      data->cache = safe_strdup (file);
251
      t = 0;
252
      if (!data->firstMessage || data->lastMessage < m)
253
	t = 1;
254
      if (!data->firstMessage)
255
	data->firstMessage = l;
256
      if (data->lastMessage < m)
257
	data->lastMessage = m;
258
      data->lastCached = m;
259
      if (t || !data->unread)
260
	mutt_newsgroup_stat (data);
261
    }
262
  }
263
  fclose (index);
264
  return 0;
265
}
266
267
const char *
268
nntp_format_str (char *dest, size_t destlen, size_t col, char op, const char *src,
269
		const char *fmt, const char *ifstring, const char *elsestring,
270
		unsigned long data, format_flag flags)
271
{
272
  char fn[SHORT_STRING], tmp[SHORT_STRING];
273
274
  switch (op)
275
  {
276
    case 's':
277
      strncpy (fn, NewsServer, sizeof(fn) - 1);
278
      mutt_strlower (fn);
279
      snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
280
      snprintf (dest, destlen, tmp, fn);
281
      break;
282
  }
283
  return (src);
284
}
285
286
/* nntp_parse_url: given an NNPT URL, return host, port,
287
 * username, password and newsgroup will recognise. */
288
int nntp_parse_url (const char *server, ACCOUNT *acct,
289
		    char *group, size_t group_len)
290
{
291
  ciss_url_t url;
292
  char *c;
293
  int ret = -1;
294
295
  /* Defaults */
296
  acct->flags = 0;
297
  acct->port = NNTP_PORT;
298
  acct->type = M_ACCT_TYPE_NNTP;
299
300
  c = safe_strdup (server);
301
  url_parse_ciss (&url, c);
302
303
  if (url.scheme == U_NNTP || url.scheme == U_NNTPS)
304
  {
305
    if (url.scheme == U_NNTPS)
306
    {
307
      acct->flags |= M_ACCT_SSL;
308
      acct->port = NNTP_SSL_PORT;
309
    }
310
311
    *group = '\0';
312
    if (url.path)
313
      strfcpy (group, url.path, group_len);
314
315
    ret = mutt_account_fromurl (acct, &url);
316
  }
317
318
  FREE (&c);
319
  return ret;
320
}
321
322
void nntp_expand_path (char *line, size_t len, ACCOUNT *acct)
323
{
324
  ciss_url_t url;
325
326
  url.path = safe_strdup (line);
327
  mutt_account_tourl (acct, &url);
328
  url_ciss_tostring (&url, line, len, 0);
329
  FREE (&url.path);
330
}
331
332
/*
333
 * Automatically loads a newsrc into memory, if necessary.
334
 * Checks the size/mtime of a newsrc file, if it doesn't match, load
335
 * again.  Hmm, if a system has broken mtimes, this might mean the file
336
 * is reloaded every time, which we'd have to fix.
337
 *
338
 * a newsrc file is a line per newsgroup, with the newsgroup, then a 
339
 * ':' denoting subscribed or '!' denoting unsubscribed, then a 
340
 * comma separated list of article numbers and ranges.
341
 */
342
NNTP_SERVER *mutt_select_newsserver (char *server)
343
{
344
  char file[_POSIX_PATH_MAX];
345
  char *buf, *p;
346
  LIST *list;
347
  ACCOUNT acct;
348
  NNTP_SERVER *serv;
349
  CONNECTION *conn;
350
351
  if (!server || !*server)
352
  {
353
    mutt_error _("No newsserver defined!");
354
    return NULL;
355
  }
356
357
  buf = p = safe_calloc (strlen (server) + 10, sizeof (char));
358
  if (url_check_scheme (server) == U_UNKNOWN)
359
  {
360
    strcpy (buf, "news://");
361
    p = strchr (buf, '\0');
362
  }
363
  strcpy (p, server);
364
365
  if ((nntp_parse_url (buf, &acct, file, sizeof (file))) < 0 || *file)
366
  {
367
    FREE (&buf);
368
    mutt_error (_("%s is an invalid newsserver specification!"), server);
369
    return NULL;
370
  }
371
  FREE (&buf);
372
373
  conn = mutt_conn_find (NULL, &acct);
374
  if (!conn)
375
    return NULL;
376
377
  mutt_FormatString (file, sizeof (file), 0, NONULL (NewsRc), nntp_format_str, 0, 0);
378
  mutt_expand_path (file, sizeof (file));
379
380
  serv = (NNTP_SERVER *)conn->data;
381
  if (serv)
382
  {
383
    struct stat sb;
384
385
    /* externally modified? */
386
    if (serv->stat != stat (file, &sb) || (!serv->stat &&
387
       (serv->size != sb.st_size || serv->mtime != sb.st_mtime)))
388
    {
389
      for (list = serv->list; list; list = list->next)
390
      {
391
	NNTP_DATA *data = (NNTP_DATA *) list->data;
392
393
	if (data)
394
	{
395
	  data->subscribed = 0;
396
	  data->rc = 0;
397
	  data->num = 0;
398
	}
399
      }
400
      slurp_newsrc (serv);
401
      nntp_clear_cacheindex (serv);
402
    }
403
404
    if (serv->status == NNTP_BYE)
405
      serv->status = NNTP_NONE;
406
    nntp_check_newgroups (serv, 0);
407
    return serv;
408
  }
409
410
  /* New newsserver */
411
  serv = safe_calloc (1, sizeof (NNTP_SERVER));
412
  serv->conn = conn;
413
  serv->newsrc = safe_strdup (file);
414
  serv->newsgroups = hash_create (1009);
415
  slurp_newsrc (serv);			/* load .newsrc */
416
  nntp_parse_cacheindex (serv);		/* load .index */
417
  if (option (OPTNEWSCACHE) && serv->cache && nntp_get_cache_all (serv) >= 0)
418
    nntp_check_newgroups (serv, 1);
419
  else if (nntp_get_active (serv) < 0)
420
  {
421
    hash_destroy (&serv->newsgroups, nntp_delete_data);
422
    for (list = serv->list; list; list = list->next)
423
      list->data = NULL;
424
    mutt_free_list (&serv->list);
425
    FREE (&serv->newsrc);
426
    FREE (&serv->cache);
427
    FREE (&serv);
428
    return NULL;
429
  }
430
  nntp_clear_cacheindex (serv);
431
  conn->data = (void *)serv;
432
433
  return serv;
434
}
435
436
/* 
437
 * full status flags are not supported by nntp, but we can fake some
438
 * of them.  This is how:
439
 * Read = a read message number is in the .newsrc
440
 * New = a message is new since we last read this newsgroup
441
 * Old = anything else
442
 * So, Read is marked as such in the newsrc, old is anything that is 
443
 * "skipped" in the newsrc, and new is anything not in the newsrc nor
444
 * in the cache. By skipped, I mean before the last unread message
445
 */
446
void nntp_get_status (CONTEXT *ctx, HEADER *h, char *group, int article)
447
{
448
  NNTP_DATA *data = (NNTP_DATA *) ctx->data;
449
  int x;
450
451
  if (group)
452
    data = (NNTP_DATA *) hash_find (data->nserv->newsgroups, group);
453
454
  if (!data)
455
  {
456
#ifdef DEBUG
457
    if (group)
458
      dprint (3, (debugfile, "newsgroup %s not found\n", group));
459
#endif
460
    return;
461
  }
462
463
  for (x = 0; x < data->num; x++)
464
  {
465
    if ((article >= data->entries[x].first) &&
466
	(article <= data->entries[x].last))
467
    {
468
      /* we cannot use mutt_set_flag() because mx_update_context()
469
	 didn't called yet */
470
      h->read = 1;
471
      return;
472
    }
473
  }
474
  /* If article was not cached yet, it is new! :) */
475
  if (!data->cache || article > data->lastCached)
476
    return;
477
  /* Old articles are articles which aren't read but an article after them
478
   * has been cached */
479
  if (option (OPTMARKOLD))
480
    h->old = 1;
481
}
482
483
void mutt_newsgroup_stat (NNTP_DATA *data)
484
{
485
  int i;
486
  unsigned int first, last;
487
488
  data->unread = 0;
489
  if (data->lastMessage == 0 || data->firstMessage > data->lastMessage)
490
    return;
491
492
  data->unread = data->lastMessage - data->firstMessage + 1;
493
  for (i = 0; i < data->num; i++)
494
  {
495
    first = data->entries[i].first;
496
    if (first < data->firstMessage)
497
      first = data->firstMessage;
498
    last = data->entries[i].last;
499
    if (last > data->lastMessage)
500
      last = data->lastMessage;
501
    if (first <= last)
502
      data->unread -= last - first + 1;
503
  }
504
}
505
506
static int puti (char *line, int num)
507
{
508
  char *p, s[32];
509
510
  for (p = s; num; )
511
  {
512
    *p++ = '0' + num % 10;
513
    num /= 10;
514
  }
515
  while (p > s)
516
    *line++ = *--p, num++;
517
  *line = '\0';
518
  return num;
519
}
520
521
static void nntp_create_newsrc_line (NNTP_DATA *data, char **buf, char **pline, size_t *buflen)
522
{
523
  char *line = *pline;
524
  size_t len = *buflen - (*pline - *buf);
525
  int x, i;
526
527
  if (len < LONG_STRING * 10)
528
  {
529
    len += *buflen;
530
    *buflen *= 2;
531
    line = *buf;
532
    safe_realloc (buf, *buflen);
533
    line = *buf + (*pline - line);
534
  }
535
  strcpy (line, data->group);
536
  len -= strlen (line) + 1;
537
  line += strlen (line);
538
  *line++ = data->subscribed ? ':' : '!';
539
  *line++ = ' ';
540
  *line = '\0';
541
542
  for (x = 0; x < data->num; x++)
543
  {
544
    if (len < LONG_STRING)
545
    {
546
      len += *buflen;
547
      *buflen *= 2;
548
      *pline = line;
549
      line = *buf;
550
      safe_realloc (buf, *buflen);
551
      line = *buf + (*pline - line);
552
    }
553
    if (x)
554
    {
555
      *line++ = ',';
556
      len--;
557
    }
558
559
#if 0
560
    if (data->entries[x].first == data->entries[x].last)
561
      snprintf (line, len, "%d%n", data->entries[x].first, &i);
562
    else
563
      snprintf (line, len, "%d-%d%n", 
564
	    data->entries[x].first, data->entries[x].last, &i);
565
    len -= i;
566
    line += i;
567
#else
568
    i = puti (line, data->entries[x].first);
569
    line +=i; len -= i;
570
    if (data->entries[x].first != data->entries[x].last)
571
    {
572
      *line++ = '-';
573
      len--;
574
      i = puti (line, data->entries[x].last);
575
      line +=i; len -= i;
576
    }
577
#endif
578
  }
579
  *line++ = '\n';
580
  *line = '\0';
581
  *pline = line;
582
}
583
584
void newsrc_gen_entries (CONTEXT *ctx)
585
{
586
  NNTP_DATA *data = (NNTP_DATA *)ctx->data;
587
  int series, x;
588
  unsigned int last = 0, first = 1;
589
  int save_sort = SORT_ORDER;
590
591
  if (Sort != SORT_ORDER)
592
  {
593
    save_sort = Sort;
594
    Sort = SORT_ORDER;
595
    mutt_sort_headers (ctx, 0);
596
  }
597
598
  if (!data->max)
599
  {
600
    data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY));
601
    data->max = 5;
602
  }
603
604
  /*
605
   * Set up to fake initial sequence from 1 to the article before the 
606
   * first article in our list
607
   */
608
  data->num = 0;
609
  series = 1;
610
611
  for (x = 0; x < ctx->msgcount; x++)
612
  {
613
    if (series) /* search for first unread */
614
    {
615
      /*
616
       * We don't actually check sequential order, since we mark 
617
       * "missing" entries as read/deleted
618
       */
619
      last = ctx->hdrs[x]->article_num;
620
      if (last >= data->firstMessage && !ctx->hdrs[x]->deleted &&
621
	    !ctx->hdrs[x]->read)
622
      {
623
	if (data->num >= data->max)
624
	{
625
	  data->max = data->max * 2;
626
	  safe_realloc (&data->entries, 
627
	      data->max * sizeof (NEWSRC_ENTRY));
628
	}
629
	data->entries[data->num].first = first;
630
	data->entries[data->num].last = last - 1;
631
	data->num++;
632
	series = 0;
633
      }
634
    }
635
    else /* search for first read */
636
    {
637
      if (ctx->hdrs[x]->deleted || ctx->hdrs[x]->read)
638
      {
639
	first = last + 1;
640
	series = 1;
641
      }
642
      last = ctx->hdrs[x]->article_num;
643
    }
644
  }
645
  if (series && first <= data->lastLoaded)
646
  {
647
    if (data->num >= data->max)
648
    {
649
      data->max = data->max * 2;
650
      safe_realloc (&data->entries, 
651
		    data->max * sizeof (NEWSRC_ENTRY));
652
    }
653
    data->entries[data->num].first = first;
654
    data->entries[data->num].last = data->lastLoaded;
655
    data->num++;
656
  }
657
658
  if (save_sort != Sort)
659
  {
660
    Sort = save_sort;
661
    mutt_sort_headers (ctx, 0);
662
  }
663
}
664
665
static int mutt_update_list_file (char *filename, char *section,
666
				  char *key, char *line)
667
{
668
  FILE *ifp;
669
  FILE *ofp;
670
  char buf[HUGE_STRING];
671
  char tmpfile[_POSIX_PATH_MAX];
672
  char *c;
673
  int ext = 0, done = 0, r = 0;
674
675
  /* if file not exist, create it */
676
  if ((ifp = safe_fopen (filename, "a")))
677
    fclose (ifp);
678
  dprint (1, (debugfile, "Opening %s\n", filename));
679
  if (!(ifp = safe_fopen (filename, "r")))
680
  {
681
    mutt_error (_("Unable to open %s for reading"), filename);
682
    return -1;
683
  }
684
  if (mx_lock_file (filename, fileno (ifp), 0, 0, 1))
685
  {
686
    fclose (ifp);
687
    mutt_error (_("Unable to lock %s"), filename);
688
    return -1;
689
  }
690
  snprintf (tmpfile, sizeof(tmpfile), "%s.tmp", filename);
691
  dprint (1, (debugfile, "Opening %s\n", tmpfile));
692
  if (!(ofp = fopen (tmpfile, "w")))
693
  {
694
    fclose (ifp);
695
    mutt_error (_("Unable to open %s for writing"), tmpfile);
696
    return -1;
697
  }
698
699
  if (section)
700
  {
701
    while (r != EOF && !done && fgets (buf, sizeof (buf), ifp))
702
    {
703
      r = fputs (buf, ofp);
704
      c = buf;
705
      while (*c && *c != '\n') c++;
706
      c[0] = 0;	/* strip EOL */
707
      if (!strncmp (buf, "#: ", 3) && !mutt_strcasecmp (buf+3, section))
708
	done++;
709
    }
710
    if (r != EOF && !done)
711
    {
712
      snprintf (buf, sizeof(buf), "#: %s\n", section);
713
      r = fputs (buf, ofp);
714
    }
715
    done = 0;
716
  }
717
718
  while (r != EOF && fgets (buf, sizeof (buf), ifp))
719
  {
720
    if (ext)
721
    {
722
      c = buf;
723
      while (*c && (*c != '\r') && (*c != '\n')) c++;
724
      c--;
725
      if (*c != '\\') ext = 0;
726
    }
727
    else if ((section && !strncmp (buf, "#: ", 3)))
728
    {
729
      if (!done && line)
730
      {
731
	fputs (line, ofp);
732
	fputc ('\n', ofp);
733
      }
734
      r = fputs (buf, ofp);
735
      done++;
736
      break;
737
    }
738
    else if (key && !strncmp (buf, key, strlen(key)) &&
739
	    (!*key || buf[strlen(key)] == ' '))
740
    {
741
      c = buf;
742
      ext = 0;
743
      while (*c && (*c != '\r') && (*c != '\n')) c++;
744
      c--;
745
      if (*c == '\\') ext = 1;
746
      if (!done && line)
747
      {
748
	r = fputs (line, ofp);
749
	if (*key)
750
	  r = fputc ('\n', ofp);
751
	done++;
752
      }
753
    }
754
    else
755
    {
756
      r = fputs (buf, ofp);
757
    }
758
  }
759
760
  while (r != EOF && fgets (buf, sizeof (buf), ifp))
761
    r = fputs (buf, ofp);
762
763
  /* If there wasn't a line to replace, put it on the end of the file */
764
  if (r != EOF && !done && line)
765
  {
766
    fputs (line, ofp);
767
    r = fputc ('\n', ofp);
768
  }
769
  mx_unlock_file (filename, fileno (ifp), 0);
770
  fclose (ofp);
771
  fclose (ifp);
772
  if (r == EOF)
773
  {
774
    unlink (tmpfile);
775
    mutt_error (_("Can't write %s"), tmpfile);
776
    return -1;
777
  }
778
  if (rename (tmpfile, filename) < 0)
779
  {
780
    unlink (tmpfile);
781
    mutt_error (_("Can't rename %s to %s"), tmpfile, filename);
782
    return -1;
783
  }
784
  return 0;
785
}
786
787
int mutt_newsrc_update (NNTP_SERVER *news)
788
{
789
  char *buf, *line;
790
  NNTP_DATA *data;
791
  LIST *tmp;
792
  int r = -1;
793
  size_t len, llen;
794
795
  if (!news)
796
    return -1;
797
  llen = len = 10 * LONG_STRING;
798
  line = buf = safe_calloc (1, len);
799
  /* we will generate full newsrc here */
800
  for (tmp = news->list; tmp; tmp = tmp->next)
801
  {
802
    data = (NNTP_DATA *) tmp->data;
803
    if (!data || !data->rc)
804
      continue;
805
    nntp_create_newsrc_line (data, &buf, &line, &llen);
806
    if (*line)
807
      dprint (2, (debugfile, "Added to newsrc: %s\n", line));
808
    line += strlen (line);
809
  }
810
  /* newrc being fully rewritten */
811
  if (news->newsrc &&
812
     (r = mutt_update_list_file (news->newsrc, NULL, "", buf)) == 0)
813
  {
814
    struct stat st;
815
816
    stat (news->newsrc, &st);
817
    news->size = st.st_size;
818
    news->mtime = st.st_mtime;
819
  }
820
  FREE (&buf);
821
  return r;
822
}
823
824
static FILE *mutt_mkname (char *s)
825
{
826
  char buf[_POSIX_PATH_MAX], *pc;
827
  int fd;
828
  FILE *fp;
829
830
  nntp_cache_expand (buf, s);
831
  if ((fp = safe_fopen (buf, "w")))
832
    return fp;
833
834
  nntp_cache_expand (buf, "cache-XXXXXX");
835
  pc = buf + strlen (buf) - 12;	/* positioning to "cache-XXXXXX" */
836
  if ((fd = mkstemp (buf)) == -1)
837
    return NULL;
838
  strcpy (s, pc);	/* generated name */
839
  return fdopen (fd, "w");
840
}
841
842
/* Updates info into .index file: ALL or about selected newsgroup */
843
static int nntp_update_cacheindex (NNTP_SERVER *serv, NNTP_DATA *data)
844
{
845
  char buf[LONG_STRING], *key = "ALL";
846
  char file[_POSIX_PATH_MAX];
847
848
  if (!serv || !serv->conn || !serv->conn->account.host)
849
    return -1;
850
851
  if (data && data->group)
852
  {
853
    key = data->group;
854
    snprintf (buf, sizeof (buf), "%s %s %d %d", key, data->cache,
855
	  data->firstMessage, data->lastLoaded);
856
  }
857
  else
858
  {
859
    strfcpy (file, serv->cache, sizeof (file));
860
    snprintf (buf, sizeof (buf), "ALL %s 0 %d", file, (int)serv->newgroups_time);
861
  }
862
  nntp_cache_expand (file, ".index");
863
  return mutt_update_list_file (file, serv->conn->account.host, key, buf);
864
}
865
866
/* Remove cache files of unsubscribed newsgroups */
867
void nntp_clear_cacheindex (NNTP_SERVER *news)
868
{
869
  NNTP_DATA *data;
870
  LIST *tmp;
871
872
  if (option (OPTSAVEUNSUB) || !news)
873
    return;
874
875
  for (tmp = news->list; tmp; tmp = tmp->next)
876
  {
877
    data = (NNTP_DATA *) tmp->data;
878
    if (!data || data->subscribed || !data->cache)
879
      continue;
880
    nntp_delete_cache (data);
881
    dprint (2, (debugfile, "Removed from .index: %s\n", data->group));
882
  }
883
  return;
884
}
885
886
int nntp_save_cache_index (NNTP_SERVER *news)
887
{
888
  char buf[HUGE_STRING];
889
  char file[_POSIX_PATH_MAX];
890
  NNTP_DATA *d;
891
  FILE *f;
892
  LIST *l;
893
894
  if (!news || !news->newsgroups)
895
    return -1;
896
  if (!option (OPTNEWSCACHE))
897
    return 0;
898
899
  if (news->cache)
900
  {
901
    nntp_cache_expand (file, news->cache);
902
    unlink (file);
903
    f = safe_fopen (file, "w");
904
  }
905
  else
906
  {
907
    strfcpy (buf, news->conn->account.host, sizeof(buf));
908
    f = mutt_mkname (buf);
909
    news->cache = safe_strdup (buf);
910
    nntp_cache_expand (file, buf);
911
  }
912
  if (!f)
913
    return -1;
914
915
  for (l = news->list; l; l = l->next)
916
  {
917
    if ((d = (NNTP_DATA *)l->data) && !d->deleted)
918
    {
919
      if (d->desc)
920
	snprintf (buf, sizeof(buf), "%s %d %d %c %s\n", d->group,
921
	      d->lastMessage, d->firstMessage, d->allowed ? 'y' : 'n',
922
 	      d->desc);
923
      else
924
	snprintf (buf, sizeof(buf), "%s %d %d %c\n", d->group,
925
	      d->lastMessage, d->firstMessage, d->allowed ? 'y' : 'n');
926
      if (fputs (buf, f) == EOF)
927
      {
928
	fclose (f);
929
	unlink (file);
930
	return -1;
931
      }
932
    }
933
  }
934
  fclose (f);
935
936
  if (nntp_update_cacheindex (news, NULL))
937
  {
938
    unlink (file);
939
    return -1;
940
  }
941
  return 0;
942
}
943
944
int nntp_save_cache_group (CONTEXT *ctx)
945
{
946
  char buf[HUGE_STRING], addr[STRING];
947
  char file[_POSIX_PATH_MAX];
948
  FILE *f;
949
  HEADER *h;
950
  struct tm *tm;
951
  int i = 0, save = SORT_ORDER;
952
  int prev = 0;
953
954
  if (!option (OPTNEWSCACHE))
955
    return 0;
956
  if (!ctx || !ctx->data || ctx->magic != M_NNTP)
957
    return -1;
958
959
  if (((NNTP_DATA *)ctx->data)->cache)
960
  {
961
    nntp_cache_expand (file, ((NNTP_DATA *)ctx->data)->cache);
962
    unlink (file);
963
    f = safe_fopen (file, "w");
964
  }
965
  else
966
  {
967
    snprintf (buf, sizeof(buf), "%s-%s",
968
	((NNTP_DATA *)ctx->data)->nserv->conn->account.host,
969
	((NNTP_DATA *)ctx->data)->group);
970
    f = mutt_mkname (buf);
971
    ((NNTP_DATA *)ctx->data)->cache = safe_strdup (buf);
972
    nntp_cache_expand (file, buf);
973
  }
974
  if (!f)
975
    return -1;
976
977
  if (Sort != SORT_ORDER)
978
  {
979
    save = Sort;
980
    Sort = SORT_ORDER;
981
    mutt_sort_headers (ctx, 0);
982
  }
983
984
  /* Save only $nntp_context messages... */
985
  ((NNTP_DATA *)ctx->data)->lastCached = 0;
986
  if (NntpContext && ctx->msgcount > NntpContext)
987
    i = ctx->msgcount - NntpContext;
988
  for (; i < ctx->msgcount; i++)
989
  {
990
    if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->article_num != prev)
991
    {
992
      h = ctx->hdrs[i];
993
      addr[0] = 0;
994
      rfc822_write_address (addr, sizeof(addr), h->env->from, 0);
995
      tm = gmtime (&h->date_sent);
996
      snprintf (buf, sizeof(buf),
997
	    "%d\t%s\t%s\t%d %s %d %02d:%02d:%02d GMT\t%s\t",
998
	    h->article_num, h->env->subject, addr, tm->tm_mday,
999
	    Months[tm->tm_mon], tm->tm_year+1900, tm->tm_hour, tm->tm_min,
1000
	    tm->tm_sec, h->env->message_id);
1001
      fputs (buf, f);
1002
      if (h->env->references)
1003
	mutt_write_references (h->env->references, f);
1004
      snprintf (buf, sizeof(buf), "\t%ld\t%d\tXref: %s\n", (long int) h->content->length,
1005
	    (int) h->lines, NONULL(h->env->xref));
1006
      if (fputs (buf, f) == EOF)
1007
      {
1008
	fclose (f);
1009
	unlink (file);
1010
	return -1;
1011
      }
1012
    }
1013
    prev = ctx->hdrs[i]->article_num;
1014
  }
1015
1016
  if (save != Sort)
1017
  {
1018
    Sort = save;
1019
    mutt_sort_headers (ctx, 0);
1020
  }
1021
  fclose (f);
1022
1023
  if (nntp_update_cacheindex (((NNTP_DATA *)ctx->data)->nserv,
1024
	(NNTP_DATA *)ctx->data))
1025
  {
1026
    unlink (file);
1027
    return -1;
1028
  }
1029
  ((NNTP_DATA *)ctx->data)->lastCached = ((NNTP_DATA *)ctx->data)->lastLoaded;
1030
  return 0;
1031
}
1032
1033
void nntp_delete_cache (NNTP_DATA *data)
1034
{
1035
  char buf[_POSIX_PATH_MAX];
1036
1037
  if (!option (OPTNEWSCACHE) || !data || !data->cache || !data->nserv)
1038
    return;
1039
1040
  nntp_cache_expand (buf, data->cache);
1041
  unlink (buf);
1042
  FREE (&data->cache);
1043
  data->lastCached = 0;
1044
  nntp_cache_expand (buf, ".index");
1045
  mutt_update_list_file (buf, data->nserv->conn->account.host, data->group, NULL);
1046
}
1047
1048
NNTP_DATA *mutt_newsgroup_subscribe (NNTP_SERVER *news, char *group)
1049
{
1050
  NNTP_DATA *data;
1051
1052
  if (!news || !news->newsgroups || !group || !*group)
1053
    return NULL;
1054
  if (!(data = (NNTP_DATA *)hash_find (news->newsgroups, group)))
1055
  {
1056
    data = (NNTP_DATA *) safe_calloc (1, sizeof (NNTP_DATA) + strlen (group) + 1);
1057
    data->group = (char *) data + sizeof (NNTP_DATA);
1058
    strcpy (data->group, group);
1059
    data->nserv = news;
1060
    data->deleted = 1;
1061
    if (news->newsgroups->nelem < news->newsgroups->curnelem * 2)
1062
      news->newsgroups = hash_resize (news->newsgroups, news->newsgroups->nelem * 2);
1063
    hash_insert (news->newsgroups, data->group, data, 0);
1064
    nntp_add_to_list (news, data);
1065
  }
1066
  if (!data->subscribed)
1067
  {
1068
    data->subscribed = 1;
1069
    data->rc = 1;
1070
  }
1071
  return data;
1072
}
1073
1074
NNTP_DATA *mutt_newsgroup_unsubscribe (NNTP_SERVER *news, char *group)
1075
{
1076
  NNTP_DATA *data;
1077
1078
  if (!news || !news->newsgroups || !group || !*group ||
1079
	!(data = (NNTP_DATA *)hash_find (news->newsgroups, group)))
1080
    return NULL;
1081
  if (data->subscribed)
1082
  {
1083
    data->subscribed = 0;
1084
    if (!option (OPTSAVEUNSUB))
1085
      data->rc = 0;
1086
  }
1087
  return data;
1088
}
1089
1090
NNTP_DATA *mutt_newsgroup_catchup (NNTP_SERVER *news, char *group)
1091
{
1092
  NNTP_DATA *data;
1093
1094
  if (!news || !news->newsgroups || !group || !*group ||
1095
      !(data = (NNTP_DATA *)hash_find (news->newsgroups, group)))
1096
    return NULL;
1097
  if (!data->max)
1098
  {
1099
    data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY));
1100
    data->max = 5;
1101
  }
1102
  data->num = 1;
1103
  data->entries[0].first = 1;
1104
  data->unread = 0;
1105
  data->entries[0].last = data->lastMessage;
1106
  if (Context && Context->data == data)
1107
  {
1108
    int x;
1109
1110
    for (x = 0; x < Context->msgcount; x++)
1111
      mutt_set_flag (Context, Context->hdrs[x], M_READ, 1);
1112
  }
1113
  return data;
1114
}
1115
1116
NNTP_DATA *mutt_newsgroup_uncatchup (NNTP_SERVER *news, char *group)
1117
{
1118
  NNTP_DATA *data;
1119
1120
  if (!news || !news->newsgroups || !group || !*group ||
1121
      !(data = (NNTP_DATA *)hash_find (news->newsgroups, group)))
1122
    return NULL;
1123
  if (!data->max)
1124
  {
1125
    data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY));
1126
    data->max = 5;
1127
  }
1128
  data->num = 1;
1129
  data->entries[0].first = 1;
1130
  data->entries[0].last = data->firstMessage - 1;
1131
  if (Context && Context->data == data)
1132
  {
1133
    int x;
1134
1135
    data->unread = Context->msgcount;
1136
    for (x = 0; x < Context->msgcount; x++)
1137
      mutt_set_flag (Context, Context->hdrs[x], M_READ, 0);
1138
  }
1139
  else
1140
    data->unread = data->lastMessage - data->entries[0].last;
1141
  return data;
1142
}
1143
1144
/* this routine gives the first newsgroup with new messages */
1145
void nntp_buffy (char *s)
1146
{
1147
  LIST *list;
1148
1149
  for (list = CurrentNewsSrv->list; list; list = list->next)
1150
  {
1151
    NNTP_DATA *data = (NNTP_DATA *) list->data;
1152
1153
    if (data && data->subscribed && data->unread)
1154
    {
1155
      if (Context && Context->magic == M_NNTP &&
1156
	  !mutt_strcmp (data->group, ((NNTP_DATA *) Context->data)->group))
1157
      {
1158
	unsigned int i, unread = 0;
1159
1160
	for (i = 0; i < Context->msgcount; i++)
1161
	  if (!Context->hdrs[i]->read && !Context->hdrs[i]->deleted)
1162
	    unread++;
1163
	if (!unread)
1164
	  continue;
1165
      }
1166
      strcpy (s, data->group);
1167
      break;
1168
    }
1169
  }
1170
}
(-)mutt-1.5.17.orig/nntp.c (+1588 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 1998 Brandon Long <blong@fiction.net>
3
 * Copyright (C) 1999 Andrej Gritsenko <andrej@lucky.net>
4
 * Copyright (C) 2000-2007 Vsevolod Volkov <vvv@mutt.org.ua>
5
 * 
6
 *     This program is free software; you can redistribute it and/or modify
7
 *     it under the terms of the GNU General Public License as published by
8
 *     the Free Software Foundation; either version 2 of the License, or
9
 *     (at your option) any later version.
10
 * 
11
 *     This program is distributed in the hope that it will be useful,
12
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *     GNU General Public License for more details.
15
 * 
16
 *     You should have received a copy of the GNU General Public License
17
 *     along with this program; if not, write to the Free Software
18
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */ 
20
21
#if HAVE_CONFIG_H
22
# include "config.h"
23
#endif
24
25
#include "mutt.h"
26
#include "mutt_curses.h"
27
#include "sort.h"
28
#include "mx.h"
29
#include "mime.h"
30
#include "rfc1524.h"
31
#include "rfc2047.h"
32
#include "mailbox.h"
33
#include "nntp.h"
34
35
#ifdef HAVE_PGP
36
#include "pgp.h"
37
#endif
38
39
#ifdef HAVE_SMIME
40
#include "smime.h"
41
#endif
42
43
#include <unistd.h>
44
#include <string.h>
45
#include <ctype.h>
46
#include <stdlib.h>
47
48
static unsigned int _checked = 0;
49
50
#ifdef DEBUG
51
static void nntp_error (const char *where, const char *msg)
52
{
53
  dprint (1, (debugfile, "nntp_error(): unexpected response in %s: %s\n", where, msg));
54
}
55
#endif /* DEBUG */
56
57
static int nntp_auth (NNTP_SERVER *serv)
58
{
59
  CONNECTION *conn = serv->conn;
60
  char buf[STRING];
61
  unsigned char flags = conn->account.flags;
62
63
  if (mutt_account_getuser (&conn->account) || !conn->account.user[0] ||
64
      mutt_account_getpass (&conn->account) || !conn->account.pass[0])
65
  {
66
    conn->account.flags = flags;
67
    return -2;
68
  }
69
70
  mutt_message _("Logging in...");
71
72
  snprintf (buf, sizeof (buf), "AUTHINFO USER %s\r\n", conn->account.user);
73
  mutt_socket_write (conn, buf);
74
  if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
75
  {
76
    conn->account.flags = flags;
77
    return -1;
78
  }
79
80
#ifdef DEBUG
81
  /* don't print the password unless we're at the ungodly debugging level */
82
  if (debuglevel < M_SOCK_LOG_FULL)
83
    dprint (M_SOCK_LOG_CMD, (debugfile, "> AUTHINFO PASS *\n"));
84
#endif
85
  snprintf (buf, sizeof (buf), "AUTHINFO PASS %s\r\n", conn->account.pass);
86
  mutt_socket_write_d (conn, buf, -1, M_SOCK_LOG_FULL);
87
  if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
88
  {
89
    conn->account.flags = flags;
90
    return -1;
91
  }
92
93
  if (mutt_strncmp ("281", buf, 3))
94
  {
95
    conn->account.flags = flags;
96
    mutt_error _("Login failed.");
97
    sleep (2);
98
    return -3;
99
  }
100
101
  return 0;
102
}
103
104
static int nntp_connect_error (NNTP_SERVER *serv)
105
{
106
  serv->status = NNTP_NONE;
107
  mutt_socket_close (serv->conn);
108
  mutt_error _("Server closed connection!");
109
  sleep (2);
110
  return -1;
111
}
112
113
static int nntp_connect_and_auth (NNTP_SERVER *serv)
114
{
115
  CONNECTION *conn = serv->conn;
116
  char buf[STRING];
117
  int rc;
118
119
  serv->status = NNTP_NONE;
120
121
  if (mutt_socket_open (conn) < 0)
122
    return -1;
123
124
  if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
125
    return nntp_connect_error (serv);
126
127
  if (!mutt_strncmp ("200", buf, 3))
128
    mutt_message (_("Connected to %s. Posting ok."), conn->account.host);
129
  else if (!mutt_strncmp ("201", buf, 3))
130
    mutt_message (_("Connected to %s. Posting NOT ok."), conn->account.host);
131
  else
132
  {
133
    mutt_socket_close (conn);
134
    mutt_remove_trailing_ws (buf);
135
    mutt_error ("%s", buf);
136
    sleep (2);
137
    return -1;
138
  }
139
140
  sleep (1);
141
142
  /* Tell INN to switch to mode reader if it isn't so. Ignore all
143
   returned codes and messages. */
144
  mutt_socket_write (conn, "MODE READER\r\n");
145
  if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
146
    return nntp_connect_error (serv);
147
148
  mutt_socket_write (conn, "STAT\r\n");
149
  if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
150
    return nntp_connect_error (serv);
151
152
  if (!(conn->account.flags & M_ACCT_USER) && mutt_strncmp ("480", buf, 3))
153
  {
154
    serv->status = NNTP_OK;
155
    return 0;
156
  }
157
158
  rc = nntp_auth (serv);
159
  if (rc == -1)
160
    return nntp_connect_error (serv);
161
  if (rc == -2)
162
  {
163
    mutt_socket_close (conn);
164
    serv->status = NNTP_BYE;
165
    return -1;
166
  }
167
  if (rc < 0)
168
  {
169
    mutt_socket_close (conn);
170
    mutt_error _("Login failed.");
171
    sleep (2);
172
    return -1;
173
  }
174
  serv->status = NNTP_OK;
175
  return 0;
176
}
177
178
static int nntp_attempt_features (NNTP_SERVER *serv)
179
{
180
  char buf[LONG_STRING];
181
  CONNECTION *conn = serv->conn;
182
183
  mutt_socket_write (conn, "XOVER\r\n");
184
  if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
185
    return nntp_connect_error (serv);
186
  if (mutt_strncmp ("500", buf, 3))
187
    serv->hasXOVER = 1;
188
189
  mutt_socket_write (conn, "XPAT\r\n");
190
  if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
191
    return nntp_connect_error (serv);
192
  if (mutt_strncmp ("500", buf, 3))
193
    serv->hasXPAT = 1;
194
195
  mutt_socket_write (conn, "LISTGROUP\r\n");
196
  if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
197
    return nntp_connect_error (serv);
198
  if (mutt_strncmp ("500", buf, 3))
199
    serv->hasLISTGROUP = 1;
200
201
  mutt_socket_write (conn, "XGTITLE +\r\n");
202
  if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
203
    return nntp_connect_error (serv);
204
  if (mutt_strncmp ("500", buf, 3))
205
    serv->hasXGTITLE = 1;
206
207
  if (!mutt_strncmp ("282", buf, 3))
208
  {
209
    do
210
    {
211
      if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
212
	return nntp_connect_error (serv);
213
    } while (!(buf[0] == '.' && buf[1] == '\0'));
214
  }
215
216
  return 0;
217
}
218
219
static int nntp_open_connection (NNTP_SERVER *serv)
220
{
221
  if (serv->status == NNTP_OK)
222
    return 0;
223
  if (serv->status == NNTP_BYE)
224
    return -1;
225
  if (nntp_connect_and_auth (serv) < 0)
226
    return -1;
227
  if (nntp_attempt_features (serv) < 0)
228
    return -1;
229
  return 0;
230
}
231
232
static int nntp_reconnect (NNTP_SERVER *serv)
233
{
234
  char buf[SHORT_STRING];
235
236
  mutt_socket_close (serv->conn);
237
238
  FOREVER
239
  {
240
    if (nntp_connect_and_auth (serv) == 0)
241
      return 0;
242
243
    snprintf (buf, sizeof (buf), _("Connection to %s lost. Reconnect?"),
244
				serv->conn->account.host);
245
    if (query_quadoption (OPT_NNTPRECONNECT, buf) != M_YES)
246
    {
247
      serv->status = NNTP_BYE;
248
      return -1;
249
    }
250
  }
251
}
252
253
/* Send data from line[LONG_STRING] and receive answer to same line */
254
static int mutt_nntp_query (NNTP_DATA *data, char *line, size_t linelen)
255
{
256
  char buf[LONG_STRING];
257
  int done = TRUE;
258
259
  if (data->nserv->status == NNTP_BYE)
260
    return -1;
261
262
  do
263
  {
264
    if (*line)
265
    {
266
      mutt_socket_write (data->nserv->conn, line);
267
    }
268
    else if (data->group)
269
    {
270
      snprintf (buf, sizeof (buf), "GROUP %s\r\n", data->group);
271
      mutt_socket_write (data->nserv->conn, buf);
272
    }
273
274
    done = TRUE;
275
    if (mutt_socket_readln (buf, sizeof (buf), data->nserv->conn) < 0)
276
    {
277
      if (nntp_reconnect (data->nserv) < 0)
278
 	return -1;
279
280
      if (data->group)
281
      {
282
	snprintf (buf, sizeof (buf), "GROUP %s\r\n", data->group);
283
	mutt_socket_write (data->nserv->conn, buf);
284
	if (mutt_socket_readln (buf, sizeof (buf), data->nserv->conn) < 0)
285
	  return -1;
286
      }
287
      if (*line)
288
	done = FALSE;
289
    }
290
    else if ((!mutt_strncmp ("480", buf, 3)) && nntp_auth (data->nserv) < 0)
291
      return -1;
292
  } while (!done);
293
294
  strfcpy (line, buf, linelen);
295
  return 0;
296
}
297
298
/*
299
 * This function calls  funct(*line, *data)  for each received line,
300
 * funct(NULL, *data)  if  rewind(*data)  needs, exits when fail or done.
301
 * Returned codes:
302
 *  0 - successful,
303
 *  1 - correct but not performed (may be, have to be continued),
304
 * -1 - conection lost,
305
 * -2 - invalid command or execution error,
306
 * -3 - error in funct(*line, *data).
307
 */
308
static int mutt_nntp_fetch (NNTP_DATA *nntp_data, char *query, char *msg,
309
		int (*funct) (char *, void *), void *data, int tagged)
310
{
311
  char buf[LONG_STRING];
312
  char *inbuf, *p;
313
  int done = FALSE;
314
  int chunk, line;
315
  size_t lenbuf = 0;
316
  int ret;
317
318
  do
319
  {
320
    strfcpy (buf, query, sizeof (buf));
321
    if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0)
322
      return -1;
323
    if (buf[0] == '5')
324
      return -2;
325
    if (buf[0] != '2')
326
      return 1;
327
328
    ret = 0;
329
    line = 0;
330
    inbuf = safe_malloc (sizeof (buf));
331
332
    FOREVER
333
    {
334
      chunk = mutt_socket_readln_d (buf, sizeof (buf), nntp_data->nserv->conn,
335
				    M_SOCK_LOG_HDR);
336
      if (chunk < 0)
337
	break;
338
339
      p = buf;
340
      if (!lenbuf && buf[0] == '.')
341
      {
342
	if (buf[1] == '\0')
343
	{
344
	  done = TRUE;
345
	  break;
346
	}
347
	if (buf[1] == '.')
348
	  p++;
349
      }
350
351
      strfcpy (inbuf + lenbuf, p, sizeof (buf));
352
353
      if (chunk >= sizeof (buf))
354
      {
355
	lenbuf += strlen (p);
356
      }
357
      else
358
      {
359
	line++;
360
	if (msg && ReadInc && (line % ReadInc == 0)) {
361
	  if (tagged)
362
	    mutt_message (_("%s (tagged: %d) %d"), msg, tagged, line);
363
	  else
364
	    mutt_message ("%s %d", msg, line);
365
	}
366
367
	if (ret == 0 && funct (inbuf, data) < 0)
368
	  ret = -3;
369
	lenbuf = 0;
370
      }
371
372
      safe_realloc (&inbuf, lenbuf + sizeof (buf));
373
    }
374
    FREE (&inbuf);
375
    funct (NULL, data);
376
  }
377
  while (!done);
378
  return ret;
379
}
380
381
static int nntp_read_tempfile (char *line, void *file)
382
{
383
  FILE *f = (FILE *)file;
384
385
  if (!line)
386
    rewind (f);
387
  else
388
  {
389
    fputs (line, f);
390
    if (fputc ('\n', f) == EOF)
391
      return -1;
392
  }
393
  return 0;
394
}
395
396
static void nntp_parse_xref (CONTEXT *ctx, char *group, char *xref, HEADER *h)
397
{
398
  register char *p, *b;
399
  register char *colon = NULL;
400
401
  b = p = xref;
402
  while (*p)
403
  {
404
    /* skip to next word */
405
    b = p;
406
    while (*b && ((*b == ' ') || (*b == '\t'))) b++;
407
    p = b;
408
    colon = NULL;
409
    /* skip to end of word */
410
    while (*p && (*p != ' ') && (*p != '\t')) 
411
    {
412
      if (*p == ':')
413
	colon = p;
414
      p++;
415
    }
416
    if (*p)
417
    {
418
      *p = '\0';
419
      p++;
420
    }
421
    if (colon)
422
    {
423
      *colon = '\0';
424
      colon++;
425
      nntp_get_status (ctx, h, b, atoi(colon));
426
      if (h && h->article_num == 0 && mutt_strcmp (group, b) == 0)
427
	h->article_num = atoi(colon);
428
    }
429
  }
430
}
431
432
/*
433
 * returns:
434
 *  0 on success
435
 *  1 if article not found
436
 * -1 if read or write error on tempfile or socket
437
 */
438
static int nntp_read_header (CONTEXT *ctx, const char *msgid, int article_num)
439
{
440
  NNTP_DATA *nntp_data = ((NNTP_DATA *)ctx->data);
441
  FILE *f;
442
  char buf[LONG_STRING];
443
  char tempfile[_POSIX_PATH_MAX];
444
  int ret;
445
  HEADER *h = ctx->hdrs[ctx->msgcount];
446
447
  mutt_mktemp (tempfile);
448
  if (!(f = safe_fopen (tempfile, "w+")))
449
    return -1;
450
451
  if (!msgid)
452
    snprintf (buf, sizeof (buf), "HEAD %d\r\n", article_num);
453
  else
454
    snprintf (buf, sizeof (buf), "HEAD %s\r\n", msgid);
455
456
  ret = mutt_nntp_fetch (nntp_data, buf, NULL, nntp_read_tempfile, f, 0);
457
  if (ret)
458
  {
459
#ifdef DEBUG
460
    if (ret != -1)
461
      dprint(1, (debugfile, "nntp_read_header: %s\n", buf));
462
#endif
463
    fclose (f);
464
    unlink (tempfile);
465
    return (ret == -1 ? -1 : 1);
466
  }
467
468
  h->article_num = article_num;
469
  h->env = mutt_read_rfc822_header (f, h, 0, 0);
470
  fclose (f);
471
  unlink (tempfile);
472
473
  if (h->env->xref != NULL)
474
    nntp_parse_xref (ctx, nntp_data->group, h->env->xref, h);
475
  else if (h->article_num == 0 && msgid)
476
  {
477
    snprintf (buf, sizeof (buf), "STAT %s\r\n", msgid);
478
    if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) == 0)
479
      h->article_num = atoi (buf + 4);
480
  }
481
482
  return 0;
483
}
484
485
static int parse_description (char *line, void *n)
486
{
487
#define news ((NNTP_SERVER *) n)
488
  register char *d = line;
489
  NNTP_DATA *data;
490
491
  if (!line)
492
    return 0;
493
  while (*d && *d != '\t' && *d != ' ') d++;
494
    *d = 0;
495
  d++;
496
  while (*d && (*d == '\t' || *d == ' ')) d++;
497
  dprint (2, (debugfile, "group: %s, desc: %s\n", line, d));
498
  if ((data = (NNTP_DATA *) hash_find (news->newsgroups, line)) != NULL &&
499
	mutt_strcmp (d, data->desc))
500
  {
501
    FREE (&data->desc);
502
    data->desc = safe_strdup (d);
503
  }
504
  return 0;
505
#undef news
506
}
507
508
static void nntp_get_desc (NNTP_DATA *data, char *mask, char *msg)
509
{
510
  char buf[STRING];
511
512
  if (!option (OPTLOADDESC) || !data || !data->nserv)
513
    return;
514
515
  /* Get newsgroup description, if we can */
516
  if (data->nserv->hasXGTITLE)
517
    snprintf (buf, sizeof (buf), "XGTITLE %s\r\n", mask);
518
  else
519
    snprintf (buf, sizeof (buf), "LIST NEWSGROUPS %s\r\n", mask);
520
  if (mutt_nntp_fetch (data, buf, msg, parse_description, data->nserv, 0) != 0)
521
  {
522
#ifdef DEBUG
523
    nntp_error ("nntp_get_desc()", buf);
524
#endif
525
  }
526
}
527
528
/*
529
 * XOVER returns a tab separated list of:
530
 * id|subject|from|date|Msgid|references|bytes|lines|xref
531
 *
532
 * This has to duplicate some of the functionality of 
533
 * mutt_read_rfc822_header(), since it replaces the call to that (albeit with
534
 * a limited number of headers which are "parsed" by placement in the list)
535
 */
536
static int nntp_parse_xover (CONTEXT *ctx, char *buf, HEADER *hdr)
537
{
538
  NNTP_DATA *nntp_data = (NNTP_DATA *) ctx->data;
539
  char *p, *b;
540
  int x, done = 0;
541
542
  hdr->env = mutt_new_envelope();
543
  hdr->env->newsgroups = safe_strdup (nntp_data->group);
544
  hdr->content = mutt_new_body();
545
  hdr->content->type = TYPETEXT;
546
  hdr->content->subtype = safe_strdup ("plain");
547
  hdr->content->encoding = ENC7BIT;
548
  hdr->content->disposition = DISPINLINE;
549
  hdr->content->length = -1;
550
  b = p = buf;
551
552
  for (x = 0; !done && x < 9; x++)
553
  {
554
    /* if from file, need to skip newline character */
555
    while (*p && *p != '\n' && *p != '\t') p++;
556
    if (!*p) done++;
557
    *p = '\0';
558
    p++;
559
    switch (x)
560
    {
561
      case 0:
562
563
	hdr->article_num = atoi (b);
564
	nntp_get_status (ctx, hdr, NULL, hdr->article_num);
565
	break;
566
      case 1:
567
	hdr->env->subject = safe_strdup (b);
568
	/* Now we need to do the things which would normally be done in 
569
	 * mutt_read_rfc822_header() */
570
	if (hdr->env->subject)
571
	{
572
	  regmatch_t pmatch[1];
573
574
	  rfc2047_decode (&hdr->env->subject);
575
576
	  if (regexec (ReplyRegexp.rx, hdr->env->subject, 1, pmatch, 0) == 0)
577
	    hdr->env->real_subj = hdr->env->subject + pmatch[0].rm_eo;
578
	  else
579
	    hdr->env->real_subj = hdr->env->subject;
580
	}
581
	break;
582
      case 2:
583
	rfc822_free_address (&hdr->env->from);
584
	hdr->env->from = rfc822_parse_adrlist (hdr->env->from, b);
585
	rfc2047_decode_adrlist (hdr->env->from);
586
	break;
587
      case 3:
588
	hdr->date_sent = mutt_parse_date (b, hdr);
589
	hdr->received = hdr->date_sent;
590
	break;
591
      case 4:
592
	FREE (&hdr->env->message_id);
593
	hdr->env->message_id = safe_strdup (b);
594
	break;
595
      case 5:
596
	mutt_free_list (&hdr->env->references);
597
	hdr->env->references = mutt_parse_references (b, 0);
598
	break;
599
      case 6:
600
	hdr->content->length = atoi (b);
601
	break;
602
      case 7:
603
	hdr->lines = atoi (b);
604
	break;
605
      case 8:
606
	if (!hdr->read)
607
	  FREE (&hdr->env->xref);
608
	  b = b + 6;	/* skips the "Xref: " */
609
	  hdr->env->xref = safe_strdup (b);
610
	  nntp_parse_xref (ctx, nntp_data->group, b, hdr);
611
    }
612
    if (!*p)
613
      return -1;
614
    b = p;
615
  }
616
  return 0;
617
}
618
619
typedef struct
620
{
621
  CONTEXT *ctx;
622
  unsigned int base;
623
  unsigned int first;
624
  unsigned int last;
625
  unsigned short *messages;
626
  char* msg;
627
} FETCH_CONTEXT;
628
629
#define fc ((FETCH_CONTEXT *) c)
630
static int nntp_fetch_numbers (char *line, void *c)
631
{
632
  unsigned int num;
633
634
  if (!line)
635
    return 0;
636
  num = atoi (line);
637
  if (num < fc->base || num > fc->last)
638
    return 0;
639
  fc->messages[num - fc->base] = 1;
640
  return 0;
641
}
642
643
static int add_xover_line (char *line, void *c)
644
{
645
  unsigned int num, total;
646
  CONTEXT *ctx = fc->ctx;
647
  NNTP_DATA *data = (NNTP_DATA *)ctx->data;
648
649
  if (!line)
650
    return 0;
651
652
  if (ctx->msgcount >= ctx->hdrmax)
653
    mx_alloc_memory (ctx);
654
  ctx->hdrs[ctx->msgcount] = mutt_new_header ();
655
  ctx->hdrs[ctx->msgcount]->index = ctx->msgcount;
656
657
  nntp_parse_xover (ctx, line, ctx->hdrs[ctx->msgcount]);
658
  num = ctx->hdrs[ctx->msgcount]->article_num;
659
660
  if (num >= fc->first && num <= fc->last && fc->messages[num - fc->base])
661
  {
662
    ctx->msgcount++;
663
    if (num > data->lastLoaded)
664
      data->lastLoaded = num;
665
    num = num - fc->first + 1;
666
    total = fc->last - fc->first + 1;
667
    if (!ctx->quiet && fc->msg && ReadInc && (num % ReadInc == 0))
668
      mutt_message ("%s %d/%d", fc->msg, num, total);
669
  }
670
  else
671
    mutt_free_header (&ctx->hdrs[ctx->msgcount]); /* skip it */
672
673
  return 0;
674
}
675
#undef fc
676
677
static int nntp_fetch_headers (CONTEXT *ctx, unsigned int first,
678
	unsigned int last)
679
{
680
  char buf[HUGE_STRING];
681
  char *msg = _("Fetching message headers...");
682
  NNTP_DATA *nntp_data = ((NNTP_DATA *)ctx->data);
683
  int ret;
684
  int num;
685
  int oldmsgcount;
686
  unsigned int current;
687
  FILE *f;
688
  FETCH_CONTEXT fc;
689
690
  /* if empty group or nothing to do */
691
  if (!last || first > last)
692
    return 0;
693
694
  /* fetch list of articles */
695
  fc.ctx = ctx;
696
  fc.base = first;
697
  fc.last = last;
698
  fc.messages = safe_calloc (last - first + 1, sizeof (unsigned short));
699
  if (nntp_data->nserv->hasLISTGROUP)
700
  {
701
    mutt_message _("Fetching list of articles...");
702
    snprintf (buf, sizeof (buf), "LISTGROUP %s\r\n", nntp_data->group);
703
    if (mutt_nntp_fetch (nntp_data, buf, NULL, nntp_fetch_numbers, &fc, 0) != 0)
704
    {
705
      mutt_error (_("LISTGROUP command failed: %s"), buf);
706
#ifdef DEBUG
707
      nntp_error ("nntp_fetch_headers()", buf);
708
#endif
709
      FREE (&fc.messages);
710
      return -1;
711
    }
712
  }
713
  else
714
  {
715
    for (num = 0; num < last - first + 1; num++)
716
      fc.messages[num] = 1;
717
  }
718
719
  /* CACHE: must be loaded xover cache here */
720
  num = nntp_data->lastCached - first + 1;
721
  if (option (OPTNEWSCACHE) && nntp_data->cache && num > 0)
722
  {
723
    nntp_cache_expand (buf, nntp_data->cache);
724
    mutt_message _("Fetching headers from cache...");
725
    if ((f = safe_fopen (buf, "r")))
726
    {
727
      int r = 0;
728
729
      /* counting number of lines */
730
      while (fgets (buf, sizeof (buf), f) != NULL)
731
	r++;
732
      rewind (f);
733
      while (r > num && fgets (buf, sizeof (buf), f) != NULL)
734
	r--;
735
      oldmsgcount = ctx->msgcount;
736
      fc.first = first;
737
      fc.last = first + num - 1;
738
      fc.msg = NULL;
739
      while (fgets (buf, sizeof (buf), f) != NULL)
740
	add_xover_line (buf, &fc);
741
      fclose (f);
742
      nntp_data->lastLoaded = fc.last;
743
      first = fc.last + 1;
744
      if (ctx->msgcount > oldmsgcount)
745
	mx_update_context (ctx, ctx->msgcount - oldmsgcount);
746
    }
747
    else
748
      nntp_delete_cache (nntp_data);
749
  }
750
  num = last - first + 1;
751
  if (num <= 0)
752
  {
753
    FREE (&fc.messages);
754
    return 0;
755
  }
756
757
  /*
758
   * Without XOVER, we have to fetch each article header and parse
759
   * it.  With XOVER, we ask for all of them
760
   */
761
  mutt_message (msg);
762
  if (nntp_data->nserv->hasXOVER)
763
  {
764
    oldmsgcount = ctx->msgcount;
765
    fc.first = first;
766
    fc.last = last;
767
    fc.msg = msg;
768
    snprintf (buf, sizeof (buf), "XOVER %d-%d\r\n", first, last);
769
    ret = mutt_nntp_fetch (nntp_data, buf, NULL, add_xover_line, &fc, 0);
770
    if (ctx->msgcount > oldmsgcount)
771
      mx_update_context (ctx, ctx->msgcount - oldmsgcount);
772
    if (ret != 0)
773
    {
774
      mutt_error (_("XOVER command failed: %s"), buf);
775
#ifdef DEBUG
776
      nntp_error ("nntp_fetch_headers()", buf);
777
#endif
778
      FREE (&fc.messages);
779
      return -1;
780
    }
781
    /* fetched OK */
782
  }
783
  else
784
  for (current = first; current <= last; current++)
785
  {
786
    HEADER *h;
787
788
    ret = current - first + 1;
789
    mutt_message ("%s %d/%d", msg, ret, num);
790
791
    if (!fc.messages[current - fc.base])
792
      continue;
793
794
    if (ctx->msgcount >= ctx->hdrmax)
795
      mx_alloc_memory (ctx);
796
    h = ctx->hdrs[ctx->msgcount] = mutt_new_header ();
797
    h->index = ctx->msgcount;
798
799
    ret = nntp_read_header (ctx, NULL, current);
800
    if (ret == 0) /* Got article. Fetch next header */
801
    {
802
      nntp_get_status (ctx, h, NULL, h->article_num);
803
      ctx->msgcount++;
804
      mx_update_context (ctx, 1);
805
    }
806
    else
807
      mutt_free_header (&h); /* skip it */
808
    if (ret == -1)
809
    {
810
      FREE (&fc.messages);
811
      return -1;
812
    }
813
814
    if (current > nntp_data->lastLoaded)
815
      nntp_data->lastLoaded = current;
816
  }
817
  FREE (&fc.messages);
818
  nntp_data->lastLoaded = last;
819
  mutt_clear_error ();
820
  return 0;
821
}
822
823
/* 
824
 * currently, nntp "mailbox" is "newsgroup"
825
 */
826
int nntp_open_mailbox (CONTEXT *ctx)
827
{
828
  NNTP_DATA *nntp_data;
829
  NNTP_SERVER *serv;
830
  char buf[HUGE_STRING];
831
  char server[LONG_STRING];
832
  int count = 0;
833
  unsigned int first;
834
  ACCOUNT acct;
835
836
  if (nntp_parse_url (ctx->path, &acct, buf, sizeof (buf)) < 0 || !*buf)
837
  {
838
    mutt_error (_("%s is an invalid newsgroup specification!"), ctx->path);
839
    mutt_sleep (2);
840
    return -1;
841
  }
842
843
  server[0] = '\0';
844
  nntp_expand_path (server, sizeof (server), &acct);
845
  if (!(serv = mutt_select_newsserver (server)) || serv->status != NNTP_OK)
846
    return -1;
847
848
  CurrentNewsSrv = serv;
849
850
  /* create NNTP-specific state struct if nof found in list */
851
  if ((nntp_data = (NNTP_DATA *) hash_find (serv->newsgroups, buf)) == NULL)
852
  {
853
    nntp_data = safe_calloc (1, sizeof (NNTP_DATA) + strlen (buf) + 1);
854
    nntp_data->group = (char *) nntp_data + sizeof (NNTP_DATA);
855
    strcpy (nntp_data->group, buf);
856
    hash_insert (serv->newsgroups, nntp_data->group, nntp_data, 0);
857
    nntp_add_to_list (serv, nntp_data);
858
  }
859
  ctx->data = nntp_data;
860
  ctx->mx_close = nntp_fastclose_mailbox;
861
  nntp_data->nserv = serv;
862
863
  mutt_message (_("Selecting %s..."), nntp_data->group);
864
865
  if (!nntp_data->desc)
866
  {
867
    nntp_get_desc (nntp_data, nntp_data->group, NULL);
868
    if (nntp_data->desc)
869
      nntp_save_cache_index (serv);
870
  }
871
872
  buf[0] = 0;
873
  if (mutt_nntp_query (nntp_data, buf, sizeof(buf)) < 0)
874
  {
875
#ifdef DEBUG
876
    nntp_error ("nntp_open_mailbox()", buf);
877
#endif
878
    return -1;
879
  }
880
881
  if (mutt_strncmp ("211", buf, 3))
882
  {
883
    LIST *l = serv->list;
884
885
    /* GROUP command failed */
886
    if (!mutt_strncmp ("411", buf, 3))
887
    {
888
      mutt_error (_("Newsgroup %s not found on server %s"),
889
		    nntp_data->group, serv->conn->account.host);
890
891
      /* CACHE: delete cache and line from .index */
892
      nntp_delete_cache (nntp_data);
893
      hash_delete (serv->newsgroups, nntp_data->group, NULL, nntp_delete_data);
894
      while (l && l->data != (void *) nntp_data) l = l->next;
895
      if (l)
896
	l->data = NULL;
897
898
      sleep (2);
899
    }
900
901
    return -1;
902
  }
903
904
  sscanf (buf + 4, "%d %u %u %s", &count, &nntp_data->firstMessage, 
905
	  &nntp_data->lastMessage, buf);
906
907
  nntp_data->deleted = 0;
908
909
  time (&serv->check_time);
910
911
  /*
912
   * Check for max adding context. If it is greater than $nntp_context,
913
   * strip off extra articles
914
   */
915
  first = nntp_data->firstMessage;
916
  if (NntpContext && nntp_data->lastMessage - first + 1 > NntpContext)
917
    first = nntp_data->lastMessage - NntpContext + 1;
918
  if (first)
919
    nntp_data->lastLoaded = first - 1;
920
  return nntp_fetch_headers (ctx, first, nntp_data->lastMessage);
921
}
922
923
int nntp_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
924
{
925
  char buf[LONG_STRING];
926
  char path[_POSIX_PATH_MAX];
927
  NNTP_CACHE *cache;
928
  char *m = _("Fetching message...");
929
  int ret;
930
931
  /* see if we already have the message in our cache */
932
  cache = &((NNTP_DATA *) ctx->data)->acache[ctx->hdrs[msgno]->index % NNTP_CACHE_LEN];
933
934
  /* if everything is fine, assign msg->fp and return */
935
  if (cache->path && cache->index == ctx->hdrs[msgno]->index &&
936
      (msg->fp = fopen (cache->path, "r")))
937
    return 0;
938
939
  /* clear the previous entry */
940
  unlink (cache->path);
941
  free (cache->path);
942
943
  mutt_message (m);
944
945
  cache->index = ctx->hdrs[msgno]->index;
946
  mutt_mktemp (path);
947
  cache->path = safe_strdup (path);
948
  if (!(msg->fp = safe_fopen (path, "w+")))
949
  {
950
    FREE (&cache->path);
951
    return -1;
952
  }
953
954
  if (ctx->hdrs[msgno]->article_num == 0)
955
    snprintf (buf, sizeof (buf), "ARTICLE %s\r\n",
956
	  ctx->hdrs[msgno]->env->message_id);
957
  else
958
    snprintf (buf, sizeof (buf), "ARTICLE %d\r\n",
959
	  ctx->hdrs[msgno]->article_num);
960
961
  ret = mutt_nntp_fetch ((NNTP_DATA *)ctx->data, buf, m, nntp_read_tempfile,
962
	msg->fp, ctx->tagged);
963
  if (ret == 1)
964
  {
965
    mutt_error (_("Article %d not found on server"), 
966
	  ctx->hdrs[msgno]->article_num);
967
    dprint (1, (debugfile, "nntp_fetch_message: %s\n", buf));
968
  }
969
970
  if (ret)
971
  {
972
    fclose (msg->fp);
973
    unlink (path);
974
    FREE (&cache->path);
975
    return -1;
976
  }
977
978
  mutt_free_envelope (&ctx->hdrs[msgno]->env);
979
  ctx->hdrs[msgno]->env = mutt_read_rfc822_header (msg->fp, ctx->hdrs[msgno], 0, 0);
980
  /* fix content length */
981
  fseek(msg->fp, 0, SEEK_END);
982
  ctx->hdrs[msgno]->content->length = ftell (msg->fp) - 
983
                                        ctx->hdrs[msgno]->content->offset;
984
985
  /* this is called in mutt before the open which fetches the message, 
986
   * which is probably wrong, but we just call it again here to handle
987
   * the problem instead of fixing it.
988
   */
989
  mutt_parse_mime_message (ctx, ctx->hdrs[msgno]);
990
991
  /* These would normally be updated in mx_update_context(), but the 
992
   * full headers aren't parsed with XOVER, so the information wasn't
993
   * available then.
994
   */
995
#if defined(HAVE_PGP) || defined(HAVE_SMIME)
996
  ctx->hdrs[msgno]->security = crypt_query (ctx->hdrs[msgno]->content);
997
#endif /* HAVE_PGP || HAVE_SMIME */
998
999
  mutt_clear_error();
1000
  rewind (msg->fp);
1001
1002
  return 0;
1003
}
1004
1005
/* Post article */
1006
int nntp_post (const char *msg) {
1007
  char buf[LONG_STRING];
1008
  size_t len;
1009
  FILE *f;
1010
  NNTP_DATA *nntp_data;
1011
1012
  if (Context && Context->magic == M_NNTP)
1013
    nntp_data = (NNTP_DATA *)Context->data;
1014
  else
1015
  {
1016
    if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)) ||
1017
	!CurrentNewsSrv->list || !CurrentNewsSrv->list->data)
1018
    {
1019
      mutt_error (_("Can't post article. No connection to news server."));
1020
      return -1;
1021
    }
1022
    nntp_data = (NNTP_DATA *)CurrentNewsSrv->list->data;
1023
  }
1024
1025
  if (!(f = safe_fopen (msg, "r")))
1026
  {
1027
    mutt_error (_("Can't post article. Unable to open %s"), msg);
1028
    return -1;
1029
  }
1030
1031
  strfcpy (buf, "POST\r\n", sizeof (buf));
1032
  if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0)
1033
  {
1034
    mutt_error (_("Can't post article. Connection to %s lost."),
1035
		nntp_data->nserv->conn->account.host);
1036
    return -1;
1037
  }
1038
  if (buf[0] != '3')
1039
  {
1040
    mutt_error (_("Can't post article: %s"), buf);
1041
    return -1;
1042
  }
1043
1044
  buf[0] = '.';
1045
  buf[1] = '\0';
1046
  while (fgets (buf + 1, sizeof (buf) - 2, f) != NULL)
1047
  {
1048
    len = strlen (buf);
1049
    if (buf[len - 1] == '\n')
1050
    {
1051
      buf[len - 1] = '\r';
1052
      buf[len] = '\n';
1053
      len++;
1054
      buf[len] = '\0';
1055
    }
1056
    if (buf[1] == '.')
1057
      mutt_socket_write_d (nntp_data->nserv->conn, buf, -1, M_SOCK_LOG_HDR);
1058
    else
1059
      mutt_socket_write_d (nntp_data->nserv->conn, buf + 1, -1, M_SOCK_LOG_HDR);
1060
  }
1061
  fclose (f);
1062
1063
  if (buf[strlen (buf) - 1] != '\n')
1064
    mutt_socket_write_d (nntp_data->nserv->conn, "\r\n", -1, M_SOCK_LOG_HDR);
1065
  mutt_socket_write_d (nntp_data->nserv->conn, ".\r\n", -1, M_SOCK_LOG_HDR);
1066
  if (mutt_socket_readln (buf, sizeof (buf), nntp_data->nserv->conn) < 0)
1067
  {
1068
    mutt_error (_("Can't post article. Connection to %s lost."),
1069
		nntp_data->nserv->conn->account.host);
1070
    return -1;
1071
  }
1072
  if (buf[0] != '2')
1073
  {
1074
    mutt_error (_("Can't post article: %s"), buf);
1075
    return -1;
1076
  }
1077
1078
  return 0;
1079
}
1080
1081
/* nntp_logout_all: close all open connections. */
1082
void nntp_logout_all (void)
1083
{
1084
  char buf[LONG_STRING];
1085
  CONNECTION* conn;
1086
1087
  conn = mutt_socket_head ();
1088
1089
  while (conn)
1090
  {
1091
    CONNECTION *next = conn->next;
1092
1093
    if (conn->account.type == M_ACCT_TYPE_NNTP)
1094
    {
1095
      mutt_message (_("Closing connection to %s..."), conn->account.host);
1096
      mutt_socket_write (conn, "QUIT\r\n");
1097
      mutt_socket_readln (buf, sizeof (buf), conn);
1098
      mutt_clear_error ();
1099
      mutt_socket_close (conn);
1100
      mutt_socket_free (conn);
1101
    }
1102
1103
    conn = next;
1104
  }
1105
}
1106
1107
static void nntp_free_acache (NNTP_DATA *data)
1108
{
1109
  int i;
1110
1111
  for (i = 0; i < NNTP_CACHE_LEN; i++)
1112
  {
1113
    if (data->acache[i].path)
1114
    {
1115
      unlink (data->acache[i].path);
1116
      FREE (&data->acache[i].path);
1117
    }
1118
  }
1119
}
1120
1121
void nntp_delete_data (void *p)
1122
{
1123
  NNTP_DATA *data = (NNTP_DATA *)p;
1124
1125
  if (!p)
1126
    return;
1127
  FREE (&data->entries);
1128
  FREE (&data->desc);
1129
  FREE (&data->cache);
1130
  nntp_free_acache (data);
1131
  FREE (p);
1132
}
1133
1134
int nntp_sync_mailbox (CONTEXT *ctx)
1135
{
1136
  NNTP_DATA *data = ctx->data;
1137
1138
  /* CACHE: update cache and .index files */
1139
  if ((option (OPTSAVEUNSUB) || data->subscribed))
1140
    nntp_save_cache_group (ctx);
1141
  nntp_free_acache (data);
1142
1143
  data->nserv->check_time = 0; /* next nntp_check_mailbox() will really check */
1144
  return 0;
1145
}
1146
1147
int nntp_fastclose_mailbox (CONTEXT *ctx)
1148
{
1149
  NNTP_DATA *data = (NNTP_DATA *) ctx->data, *tmp;
1150
1151
  if (!data)
1152
    return 0;
1153
  nntp_free_acache (data);
1154
  if (!data->nserv || !data->nserv->newsgroups || !data->group)
1155
    return 0;
1156
  nntp_save_cache_index (data->nserv);
1157
  if ((tmp = hash_find (data->nserv->newsgroups, data->group)) == NULL
1158
	|| tmp != data)
1159
    nntp_delete_data (data);
1160
  return 0;
1161
}
1162
1163
/* commit changes and terminate connection */
1164
int nntp_close_mailbox (CONTEXT *ctx)
1165
{
1166
  if (!ctx)
1167
    return -1;
1168
  mutt_message _("Quitting newsgroup...");
1169
  if (ctx->data)
1170
  {
1171
    NNTP_DATA *data = (NNTP_DATA *) ctx->data;
1172
    int ret;
1173
1174
    if (data->nserv && data->nserv->conn && ctx->unread)
1175
    {
1176
      ret = query_quadoption (OPT_CATCHUP, _("Mark all articles read?"));
1177
      if (ret == M_YES)
1178
	mutt_newsgroup_catchup (data->nserv, data->group);
1179
      else if (ret < 0)
1180
	return -1;
1181
    }
1182
  }
1183
  nntp_sync_mailbox (ctx);
1184
  if (ctx->data && ((NNTP_DATA *)ctx->data)->nserv)
1185
  {
1186
    NNTP_SERVER *news;
1187
1188
    news = ((NNTP_DATA *)ctx->data)->nserv;
1189
    newsrc_gen_entries (ctx);
1190
    ((NNTP_DATA *)ctx->data)->unread = ctx->unread;
1191
    mutt_newsrc_update (news);
1192
  }
1193
  mutt_clear_error();
1194
  return 0;
1195
}
1196
1197
/* use the GROUP command to poll for new mail */
1198
static int _nntp_check_mailbox (CONTEXT *ctx, NNTP_DATA *nntp_data)
1199
{
1200
  char buf[LONG_STRING];
1201
  int count = 0;
1202
1203
  if (nntp_data->nserv->check_time + NewsPollTimeout > time (NULL))
1204
    return 0;
1205
1206
  buf[0] = 0;
1207
  if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0)
1208
  {
1209
#ifdef DEBUG
1210
    nntp_error ("nntp_check_mailbox()", buf);
1211
#endif
1212
    return -1;
1213
  }
1214
  if (mutt_strncmp ("211", buf, 3))
1215
  {
1216
    buf[0] = 0;
1217
    if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0)
1218
    {
1219
#ifdef DEBUG
1220
      nntp_error ("nntp_check_mailbox()", buf);
1221
#endif
1222
      return -1;
1223
    }
1224
  }
1225
  if (!mutt_strncmp ("211", buf, 3))
1226
  {
1227
    int first;
1228
    int last;
1229
1230
    sscanf (buf + 4, "%d %d %d", &count, &first, &last);
1231
    nntp_data->firstMessage = first;
1232
    nntp_data->lastMessage = last;
1233
    if (ctx && last > nntp_data->lastLoaded)
1234
    {
1235
      nntp_fetch_headers (ctx, nntp_data->lastLoaded + 1, last);
1236
      time (&nntp_data->nserv->check_time);
1237
      return 1;
1238
    }
1239
    if (!last || (!nntp_data->rc && !nntp_data->lastCached))
1240
      nntp_data->unread = count;
1241
    else
1242
      mutt_newsgroup_stat (nntp_data);
1243
    /* active was renumbered? */
1244
    if (last < nntp_data->lastLoaded)
1245
    {
1246
      if (!nntp_data->max)
1247
      {
1248
	nntp_data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY));
1249
	nntp_data->max = 5;
1250
      }
1251
      nntp_data->lastCached = 0;
1252
      nntp_data->num = 1;
1253
      nntp_data->entries[0].first = 1;
1254
      nntp_data->entries[0].last = 0;
1255
    }
1256
  }
1257
1258
  time (&nntp_data->nserv->check_time);
1259
  return 0;
1260
}
1261
1262
int nntp_check_mailbox (CONTEXT *ctx)
1263
{
1264
  return _nntp_check_mailbox (ctx, (NNTP_DATA *)ctx->data);
1265
}
1266
1267
static int add_group (char *buf, void *serv)
1268
{
1269
#define s ((NNTP_SERVER *) serv)
1270
  char group[LONG_STRING], mod, desc[HUGE_STRING];
1271
  int first, last;
1272
  NNTP_DATA *nntp_data;
1273
  static int n = 0;
1274
1275
  _checked = n;	/* _checked have N, where N = number of groups */
1276
  if (!buf)	/* at EOF must be zerouth */
1277
    n = 0;
1278
1279
  if (!s || !buf)
1280
    return 0;
1281
1282
  *desc = 0;
1283
  sscanf (buf, "%s %d %d %c %[^\n]", group, &last, &first, &mod, desc);
1284
  if (!group)
1285
    return 0;
1286
  if ((nntp_data = (NNTP_DATA *) hash_find (s->newsgroups, group)) == NULL)
1287
  {
1288
    n++;
1289
    nntp_data = safe_calloc (1, sizeof (NNTP_DATA) + strlen (group) + 1);
1290
    nntp_data->group = (char *) nntp_data + sizeof (NNTP_DATA);
1291
    strcpy (nntp_data->group, group);
1292
    nntp_data->nserv = s;
1293
    if (s->newsgroups->nelem < s->newsgroups->curnelem * 2)
1294
      s->newsgroups = hash_resize (s->newsgroups, s->newsgroups->nelem * 2);
1295
    hash_insert (s->newsgroups, nntp_data->group, nntp_data, 0);
1296
    nntp_add_to_list (s, nntp_data);
1297
  }
1298
  nntp_data->deleted = 0;
1299
  nntp_data->firstMessage = first;
1300
  nntp_data->lastMessage = last;
1301
  if (mod == 'y')
1302
    nntp_data->allowed = 1;
1303
  else
1304
    nntp_data->allowed = 0;
1305
  if (nntp_data->desc)
1306
    FREE (&nntp_data->desc);
1307
  if (*desc)
1308
    nntp_data->desc = safe_strdup (desc);
1309
  if (nntp_data->rc || nntp_data->lastCached)
1310
    mutt_newsgroup_stat (nntp_data);
1311
  else if (nntp_data->lastMessage &&
1312
	nntp_data->firstMessage <= nntp_data->lastMessage)
1313
    nntp_data->unread = nntp_data->lastMessage - nntp_data->firstMessage + 1;
1314
  else
1315
    nntp_data->unread = 0;
1316
1317
  return 0;
1318
#undef s
1319
}
1320
1321
int nntp_check_newgroups (NNTP_SERVER *serv, int force)
1322
{
1323
  char buf[LONG_STRING];
1324
  char msg[SHORT_STRING];
1325
  NNTP_DATA nntp_data;
1326
  LIST *l;
1327
  LIST emp;
1328
  time_t now;
1329
  struct tm *t;
1330
  unsigned int count = 0;
1331
  unsigned int total = 0;
1332
1333
  if (!serv || !serv->newgroups_time)
1334
    return -1;
1335
1336
  if (nntp_open_connection (serv) < 0)
1337
    return -1;
1338
1339
  /* check subscribed groups for new news */
1340
  if (option (OPTSHOWNEWNEWS))
1341
  {
1342
    mutt_message _("Checking for new messages...");
1343
    for (l = serv->list; l; l = l->next)
1344
    {
1345
      serv->check_time = 0;	/* really check! */
1346
      if (l->data && ((NNTP_DATA *) l->data)->subscribed)
1347
	_nntp_check_mailbox (NULL, (NNTP_DATA *) l->data);
1348
    }
1349
  }
1350
  else if (!force)
1351
    return 0;
1352
1353
  mutt_message _("Checking for new newsgroups...");
1354
  now = serv->newgroups_time;
1355
  time (&serv->newgroups_time);
1356
  t = gmtime (&now);
1357
  snprintf (buf, sizeof (buf), "NEWGROUPS %02d%02d%02d %02d%02d%02d GMT\r\n",
1358
	(t->tm_year % 100), t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min,
1359
	t->tm_sec);
1360
  nntp_data.nserv = serv;
1361
  if (Context && Context->magic == M_NNTP)
1362
    nntp_data.group = ((NNTP_DATA *)Context->data)->group;
1363
  else
1364
    nntp_data.group = NULL;
1365
  l = serv->tail;
1366
  if (mutt_nntp_fetch (&nntp_data, buf, _("Adding new newsgroups..."),
1367
	add_group, serv, 0) != 0)
1368
  {
1369
#ifdef DEBUG
1370
    nntp_error ("nntp_check_newgroups()", buf);
1371
#endif
1372
    return -1;
1373
  }
1374
1375
  strfcpy (msg, _("Loading descriptions..."), sizeof (msg));
1376
  mutt_message (msg);
1377
  if (l)
1378
    emp.next = l->next;
1379
  else
1380
    emp.next = serv->list;
1381
  l = &emp;
1382
  while (l->next)
1383
  {
1384
    l = l->next;
1385
    ((NNTP_DATA *) l->data)->new = 1;
1386
    total++;
1387
  }
1388
  l = &emp;
1389
  while (l->next)
1390
  {
1391
    l = l->next;
1392
    nntp_get_desc ((NNTP_DATA *) l->data, ((NNTP_DATA *) l->data)->group, NULL);
1393
    count++;
1394
    if (ReadInc && (count % ReadInc == 0))
1395
      mutt_message ("%s %d/%d", msg, count, total);
1396
  }
1397
  if (emp.next)
1398
    nntp_save_cache_index (serv);
1399
  mutt_clear_error ();
1400
  return _checked;
1401
}
1402
1403
/* Load list of all newsgroups from cache ALL */
1404
int nntp_get_cache_all (NNTP_SERVER *serv)
1405
{
1406
  char buf[HUGE_STRING];
1407
  FILE *f;
1408
1409
  nntp_cache_expand (buf, serv->cache);
1410
  if ((f = safe_fopen (buf, "r")))
1411
  {
1412
    int i = 0;
1413
1414
    while (fgets (buf, sizeof(buf), f) != NULL)
1415
    {
1416
      if (ReadInc && (i % ReadInc == 0))
1417
	mutt_message (_("Loading list from cache... %d"), i);
1418
      add_group (buf, serv);
1419
      i++;
1420
    }
1421
    add_group (NULL, NULL);
1422
    fclose (f);
1423
    mutt_clear_error ();
1424
    return 0;
1425
  }
1426
  else
1427
  {
1428
    FREE (&serv->cache);
1429
    return -1;
1430
  }
1431
}
1432
1433
/* Load list of all newsgroups from active */
1434
int nntp_get_active (NNTP_SERVER *serv)
1435
{
1436
  char msg[SHORT_STRING];
1437
  NNTP_DATA nntp_data;
1438
  LIST *tmp;
1439
1440
  if (nntp_open_connection (serv) < 0)
1441
    return -1;
1442
1443
  snprintf (msg, sizeof(msg), _("Loading list of all newsgroups on server %s..."),
1444
		serv->conn->account.host);
1445
  mutt_message (msg);
1446
  time (&serv->newgroups_time);
1447
  nntp_data.nserv = serv;
1448
  nntp_data.group = NULL;
1449
1450
  if (mutt_nntp_fetch (&nntp_data, "LIST\r\n", msg, add_group, serv, 0) < 0)
1451
  {
1452
#ifdef DEBUG
1453
    nntp_error ("nntp_get_active()", "LIST\r\n");
1454
#endif
1455
    return -1;
1456
  }
1457
1458
  strfcpy (msg, _("Loading descriptions..."), sizeof (msg));
1459
  mutt_message (msg);
1460
  nntp_get_desc (&nntp_data, "*", msg);
1461
1462
  for (tmp = serv->list; tmp; tmp = tmp->next)
1463
  {
1464
    NNTP_DATA *data = (NNTP_DATA *)tmp->data;
1465
1466
    if (data && data->deleted && !data->rc)
1467
    {
1468
      nntp_delete_cache (data);
1469
      hash_delete (serv->newsgroups, data->group, NULL, nntp_delete_data);
1470
      tmp->data = NULL;
1471
    }
1472
  }
1473
  nntp_save_cache_index (serv);
1474
1475
  mutt_clear_error ();
1476
  return _checked;
1477
}
1478
1479
/*
1480
 * returns -1 if error ocurred while retrieving header,
1481
 * number of articles which ones exist in context on success.
1482
 */
1483
int nntp_check_msgid (CONTEXT *ctx, const char *msgid)
1484
{
1485
  int ret;
1486
1487
  /* if msgid is already in context, don't reload them */
1488
  if (hash_find (ctx->id_hash, msgid))
1489
    return 1;
1490
  if (ctx->msgcount == ctx->hdrmax)
1491
    mx_alloc_memory (ctx);
1492
  ctx->hdrs[ctx->msgcount] = mutt_new_header ();
1493
  ctx->hdrs[ctx->msgcount]->index = ctx->msgcount;
1494
  
1495
  mutt_message (_("Fetching %s from server..."), msgid);
1496
  ret = nntp_read_header (ctx, msgid, 0);
1497
  /* since nntp_read_header() may set read flag, we must reset it */
1498
  ctx->hdrs[ctx->msgcount]->read = 0;
1499
  if (ret != 0)
1500
    mutt_free_header (&ctx->hdrs[ctx->msgcount]);
1501
  else
1502
  {
1503
    ctx->msgcount++;
1504
    mx_update_context (ctx, 1);
1505
    ctx->changed = 1;
1506
  }
1507
  return ret;
1508
}
1509
1510
typedef struct
1511
{
1512
  CONTEXT *ctx;
1513
  unsigned int num;
1514
  unsigned int max;
1515
  unsigned int *child;
1516
} CHILD_CONTEXT;
1517
1518
static int check_children (char *s, void *c)
1519
{
1520
#define cc ((CHILD_CONTEXT *) c)
1521
  unsigned int i, n;
1522
1523
  if (!s || (n = atoi (s)) == 0)
1524
    return 0;
1525
  for (i = 0; i < cc->ctx->msgcount; i++)
1526
    if (cc->ctx->hdrs[i]->article_num == n)
1527
      return 0;
1528
  if (cc->num >= cc->max)
1529
    safe_realloc (&cc->child, sizeof (unsigned int) * (cc->max += 25));
1530
  cc->child[cc->num++] = n;
1531
1532
  return 0;
1533
#undef cc
1534
}
1535
1536
int nntp_check_children (CONTEXT *ctx, const char *msgid)
1537
{
1538
  NNTP_DATA *nntp_data = (NNTP_DATA *)ctx->data;
1539
  char buf[STRING];
1540
  int i, ret = 0, tmp = 0;
1541
  CHILD_CONTEXT cc;
1542
1543
  if (!nntp_data || !nntp_data->nserv || !nntp_data->nserv->conn ||
1544
	!nntp_data->nserv->conn->account.host)
1545
    return -1;
1546
  if (nntp_data->firstMessage > nntp_data->lastLoaded)
1547
    return 0;
1548
  if (!nntp_data->nserv->hasXPAT)
1549
  {
1550
    mutt_error (_("Server %s does not support this operation!"),
1551
	  nntp_data->nserv->conn->account.host);
1552
    return -1;
1553
  }
1554
1555
  snprintf (buf, sizeof (buf), "XPAT References %d-%d *%s*\r\n", 
1556
	nntp_data->firstMessage, nntp_data->lastLoaded, msgid);
1557
1558
  cc.ctx = ctx;
1559
  cc.num = 0;
1560
  cc.max = 25;
1561
  cc.child = safe_malloc (sizeof (unsigned int) * 25);
1562
  if (mutt_nntp_fetch (nntp_data, buf, NULL, check_children, &cc, 0))
1563
  {
1564
    FREE (&cc.child);
1565
    return -1;
1566
  }
1567
  /* dont try to read the xover cache. check_children() already
1568
   * made sure that we dont have the article, so we need to visit
1569
   * the server. Reading the cache at this point is also bad
1570
   * because it would duplicate messages */
1571
  if (option (OPTNEWSCACHE))
1572
  {
1573
    tmp++;
1574
    unset_option (OPTNEWSCACHE);
1575
  }
1576
  for (i = 0; i < cc.num; i++)
1577
  {
1578
    if ((ret = nntp_fetch_headers (ctx, cc.child[i], cc.child[i])))
1579
      break;
1580
    if (ctx->msgcount &&
1581
	  ctx->hdrs[ctx->msgcount - 1]->article_num == cc.child[i])
1582
      ctx->hdrs[ctx->msgcount - 1]->read = 0;
1583
  }
1584
  if (tmp)
1585
    set_option (OPTNEWSCACHE);
1586
  FREE (&cc.child);
1587
  return ret;
1588
}
(-)mutt-1.5.17.orig/nntp.h (+136 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 1998 Brandon Long <blong@fiction.net>
3
 * Copyright (C) 1999 Andrej Gritsenko <andrej@lucky.net>
4
 * Copyright (C) 2000-2007 Vsevolod Volkov <vvv@mutt.org.ua>
5
 * 
6
 *     This program is free software; you can redistribute it and/or modify
7
 *     it under the terms of the GNU General Public License as published by
8
 *     the Free Software Foundation; either version 2 of the License, or
9
 *     (at your option) any later version.
10
 * 
11
 *     This program is distributed in the hope that it will be useful,
12
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *     GNU General Public License for more details.
15
 * 
16
 *     You should have received a copy of the GNU General Public License
17
 *     along with this program; if not, write to the Free Software
18
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */ 
20
21
#ifndef _NNTP_H_
22
#define _NNTP_H_ 1
23
24
#include "mutt_socket.h"
25
#include "mailbox.h"
26
27
#include <time.h>
28
29
#define NNTP_PORT 119
30
#define NNTP_SSL_PORT 563
31
32
/* number of entries in the hash table */
33
#define NNTP_CACHE_LEN 10
34
35
enum
36
{
37
  NNTP_NONE = 0,
38
  NNTP_OK,
39
  NNTP_BYE
40
};
41
42
typedef struct
43
{
44
  int first;
45
  int last;
46
} NEWSRC_ENTRY;
47
48
typedef struct
49
{
50
  unsigned int hasXPAT : 1;
51
  unsigned int hasXGTITLE : 1;
52
  unsigned int hasXOVER : 1;
53
  unsigned int hasLISTGROUP : 1;
54
  unsigned int status : 3;
55
  char *newsrc;
56
  char *cache;
57
  int stat;
58
  off_t size;
59
  time_t mtime;
60
  time_t newgroups_time;
61
  time_t check_time;
62
  HASH *newsgroups;
63
  LIST *list;	/* list of newsgroups */
64
  LIST *tail;	/* last entry of list */
65
  CONNECTION *conn;
66
} NNTP_SERVER;
67
68
typedef struct
69
{
70
  unsigned int index;
71
  char *path;
72
} NNTP_CACHE;
73
74
typedef struct
75
{
76
  NEWSRC_ENTRY *entries;
77
  unsigned int num;	/* number of used entries */
78
  unsigned int max;	/* number of allocated entries */
79
  unsigned int unread;
80
  unsigned int firstMessage;
81
  unsigned int lastMessage;
82
  unsigned int lastLoaded;
83
  unsigned int lastCached;
84
  unsigned int subscribed : 1;
85
  unsigned int rc : 1;
86
  unsigned int new : 1;
87
  unsigned int allowed : 1;
88
  unsigned int deleted : 1;
89
  char *group;
90
  char *desc;
91
  char *cache;
92
  NNTP_SERVER *nserv;
93
  NNTP_CACHE acache[NNTP_CACHE_LEN];
94
} NNTP_DATA;
95
96
/* internal functions */
97
int nntp_get_active (NNTP_SERVER *);
98
int nntp_get_cache_all (NNTP_SERVER *);
99
int nntp_save_cache_index (NNTP_SERVER *);
100
int nntp_check_newgroups (NNTP_SERVER *, int);
101
int nntp_save_cache_group (CONTEXT *);
102
int nntp_parse_url (const char *, ACCOUNT *, char *, size_t);
103
void newsrc_gen_entries (CONTEXT *);
104
void nntp_get_status (CONTEXT *, HEADER *, char *, int);
105
void mutt_newsgroup_stat (NNTP_DATA *);
106
void nntp_delete_cache (NNTP_DATA *);
107
void nntp_add_to_list (NNTP_SERVER *, NNTP_DATA *);
108
void nntp_cache_expand (char *, const char *);
109
void nntp_delete_data (void *);
110
111
/* exposed interface */
112
NNTP_SERVER *mutt_select_newsserver (char *);
113
NNTP_DATA *mutt_newsgroup_subscribe (NNTP_SERVER *, char *);
114
NNTP_DATA *mutt_newsgroup_unsubscribe (NNTP_SERVER *, char *);
115
NNTP_DATA *mutt_newsgroup_catchup (NNTP_SERVER *, char *);
116
NNTP_DATA *mutt_newsgroup_uncatchup (NNTP_SERVER *, char *);
117
void nntp_clear_cacheindex (NNTP_SERVER *);
118
int mutt_newsrc_update (NNTP_SERVER *);
119
int nntp_open_mailbox (CONTEXT *);
120
int nntp_sync_mailbox (CONTEXT *);
121
int nntp_check_mailbox (CONTEXT *);
122
int nntp_close_mailbox (CONTEXT *);
123
int nntp_fastclose_mailbox (CONTEXT *);
124
int nntp_fetch_message (MESSAGE *, CONTEXT *, int);
125
int nntp_post (const char *);
126
int nntp_check_msgid (CONTEXT *, const char *);
127
int nntp_check_children (CONTEXT *, const char *);
128
void nntp_buffy (char *);
129
void nntp_expand_path (char *, size_t, ACCOUNT *);
130
void nntp_logout_all ();
131
const char *nntp_format_str (char *, size_t, size_t, char, const char *, const char *,
132
		const char *, const char *, unsigned long, format_flag);
133
134
NNTP_SERVER *CurrentNewsSrv INITVAL (NULL);
135
136
#endif /* _NNTP_H_ */
(-)mutt-1.5.17.orig/pager.c (-2 / +88 lines)
Lines 1055-1060 fill_buffer (FILE *f, LOFF_T *last_pos, Link Here
1055
  return b_read;
1055
  return b_read;
1056
}
1056
}
1057
1057
1058
#ifdef USE_NNTP
1059
#include "mx.h"
1060
#include "nntp.h"
1061
#endif
1062
1058
1063
1059
static int format_line (struct line_t **lineInfo, int n, unsigned char *buf,
1064
static int format_line (struct line_t **lineInfo, int n, unsigned char *buf,
1060
			int flags, ansi_attr *pa, int cnt,
1065
			int flags, ansi_attr *pa, int cnt,
Lines 1490-1495 static struct mapping_t PagerHelpExtra[] Link Here
1490
  { NULL,	0 }
1495
  { NULL,	0 }
1491
};
1496
};
1492
1497
1498
#ifdef USE_NNTP
1499
static struct mapping_t PagerNewsHelpExtra[] = {
1500
  { N_("Post"),     OP_POST },
1501
  { N_("Followup"), OP_FOLLOWUP },
1502
  { N_("Del"),      OP_DELETE },
1503
  { N_("Next"),     OP_MAIN_NEXT_UNDELETED },
1504
  { NULL,           0 }
1505
};
1506
#endif
1507
1493
1508
1494
1509
1495
/* This pager is actually not so simple as it once was.  It now operates in
1510
/* This pager is actually not so simple as it once was.  It now operates in