]> git.pld-linux.org Git - packages/mutt.git/blame - mutt-nntp.patch
- removed junk and autogenerated files - now 1.2MB less
[packages/mutt.git] / mutt-nntp.patch
CommitLineData
1b5dcea5 1diff -uNr mutt-1.4.orig/ChangeLog.nntp mutt-1.4/ChangeLog.nntp
2--- mutt-1.4.orig/ChangeLog.nntp Thu Jan 1 01:00:00 1970
3+++ mutt-1.4/ChangeLog.nntp Sun Nov 3 21:57:20 2002
4@@ -0,0 +1,422 @@
5+* Wed May 29 2002 Vsevolod Volkov <vvv@mutt.org.ua>
6+- update to 1.4
7+
8+* Thu May 2 2002 Vsevolod Volkov <vvv@mutt.org.ua>
9+- update to 1.3.99
10+
11+* Wed Mar 13 2002 Vsevolod Volkov <vvv@mutt.org.ua>
12+- update to 1.3.28
13+- fixed SIGSEGV in <get-message>, <get-parent>, <get-children>,
14+ <reconstruct-thread> functions
15+- fixed message about nntp reconnect
16+- fixed <attach-news-message> function using browser
17+- added support of Followup-To: poster
18+- added %n (new articles) in group_index_format
19+- posting articles without inews by default
20+
21+* Wed Jan 23 2002 Vsevolod Volkov <vvv@mutt.org.ua>
22+- update to 1.3.27
23+
24+* Fri Jan 18 2002 Vsevolod Volkov <vvv@mutt.org.ua>
25+- update to 1.3.26
26+
27+* Thu Jan 3 2002 Vsevolod Volkov <vvv@mutt.org.ua>
28+- update to 1.3.25
29+- accelerated speed of access to news->newsgroups hash (by <gul@gul.kiev.ua>)
30+- added default content disposition
31+
32+* Mon Dec 3 2001 Vsevolod Volkov <vvv@mutt.org.ua>
33+- update to 1.3.24
34+
35+* Fri Nov 9 2001 Vsevolod Volkov <vvv@mutt.org.ua>
36+- update to 1.3.23.2
37+- fixed segfault if mutt_conn_find() returns null
38+
39+* Wed Oct 31 2001 Vsevolod Volkov <vvv@mutt.org.ua>
40+- update to 1.3.23.1
41+- added support of LISTGROUP command
42+- added support for servers with broken overview
43+- disabled <flag-message> function on news server
44+- fixed error storing bad authentication information
45+
46+* Wed Oct 10 2001 Vsevolod Volkov <vvv@mutt.org.ua>
47+- update to 1.3.23
48+- fixed typo in buffy.c
49+- added substitution of %s parameter in $inews variable
50+
51+* Fri Aug 31 2001 Vsevolod Volkov <vvv@mutt.org.ua>
52+- update to 1.3.22.1
53+- update to 1.3.22
54+
55+* Thu Aug 23 2001 Vsevolod Volkov <vvv@mutt.org.ua>
56+- update to 1.3.21
57+
58+* Wed Jul 25 2001 Vsevolod Volkov <vvv@mutt.org.ua>
59+- update to 1.3.20
60+- removed 'server-hook', use 'account-hook' instead
61+- fixed error opening NNTP server without newsgroup using -f option
62+
63+* Fri Jun 8 2001 Vsevolod Volkov <vvv@mutt.org.ua>
64+- update to 1.3.19
65+
66+* Sat May 5 2001 Vsevolod Volkov <vvv@mutt.org.ua>
67+- update to 1.3.18
68+- fixed typo in nntp_attempt_features()
69+- changed algorithm of XGTITLE command testing
70+- disabled writing of NNTP password in debug file
71+- fixed reading and writing of long newsrc lines
72+- changed checking of last line while reading lines from server
73+- fixed possible buffer overrun in nntp_parse_newsrc_line()
74+- removed checking of XHDR command
75+- compare NNTP return codes without trailing space
76+
77+* Thu Mar 29 2001 Vsevolod Volkov <vvv@mutt.org.ua>
78+- update to 1.3.17
79+- support for 'LIST NEWSGROUPS' command to read descriptions
80+
81+* Fri Mar 2 2001 Vsevolod Volkov <vvv@mutt.org.ua>
82+- update to 1.3.16
83+
84+* Wed Feb 14 2001 Vsevolod Volkov <vvv@mutt.org.ua>
85+- update to 1.3.15
86+
87+* Sun Jan 28 2001 Vsevolod Volkov <vvv@mutt.org.ua>
88+- update to 1.3.14
89+- show number of tagged messages patch from Felix von Leitner <leitner@fefe.de>
90+
91+* Sun Dec 31 2000 Vsevolod Volkov <vvv@mutt.org.ua>
92+- update to 1.3.13
93+
94+* Sat Dec 30 2000 Vsevolod Volkov <vvv@mutt.org.ua>
95+- Fixed problem if last article in group is deleted
96+
97+* Fri Dec 22 2000 Vsevolod Volkov <vvv@mutt.org.ua>
98+- Fixed checking of XGTITLE command on some servers
99+
100+* Mon Dec 18 2000 Vsevolod Volkov <vvv@mutt.org.ua>
101+- Added \r in AUTHINFO commands
102+
103+* Mon Nov 27 2000 Vsevolod Volkov <vvv@mutt.org.ua>
104+- update to 1.3.12
105+
106+* Wed Nov 1 2000 Vsevolod Volkov <vvv@mutt.org.ua>
107+- update to 1.3.11
108+- fixed error opening newsgroup from mutt started with -g or -G
109+
110+* Thu Oct 12 2000 Vsevolod Volkov <vvv@mutt.org.ua>
111+- update to 1.3.10
112+- hotkey 'G' (get-message) replaced with '^G'
113+
114+* Thu Sep 21 2000 Vsevolod Volkov <vvv@mutt.org.ua>
115+- update to 1.3.9
116+- changed delay displaying error messages from 1 to 2 seconds
117+- fixed error compiling with nntp and without imap
118+
119+* Wed Sep 6 2000 Vsevolod Volkov <vvv@mutt.org.ua>
120+- fixed catchup in index
121+- fixed nntp_open_mailbox()
122+
123+* Sat Sep 2 2000 Vsevolod Volkov <vvv@mutt.org.ua>
124+- functions <edit> and <delete-entry> disabled
125+- format of news mailbox names changed to url form
126+- option nntp_attempts removed
127+- option reconnect_news renamed to nntp_reconnect
128+- default value of nntp_poll changed from 30 to 60
129+- error handling improved
130+
131+* Wed Aug 30 2000 Vsevolod Volkov <vvv@mutt.org.ua>
132+- update to 1.3.8
133+- new option show_only_unread
134+- add newsgroup completion
135+
136+* Fri Aug 4 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
137+- update to 1.3.7
138+
139+* Sat Jul 29 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
140+- update to 1.3.6
141+
142+* Sun Jul 9 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
143+- update to 1.3.5
144+- authentication code update
145+- fix for changing to newsgroup from mailbox with read messages
146+- socket code optimization
147+
148+* Wed Jun 21 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
149+- update to 1.3.4
150+
151+* Wed Jun 14 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
152+- don't substitute current newsgroup with deleted new messages
153+
154+* Mon Jun 12 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
155+- update to 1.3.3
156+- fix for substitution of newsgroup after reconnection
157+- fix for loading newsgroups with very long names
158+- fix for loading more than 32768 newsgroups
159+
160+* Wed May 24 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
161+- update to 1.3.2
162+
163+* Sat May 20 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
164+- update to 1.3.1
165+
166+* Fri May 12 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
167+- update to 1.3
168+
169+* Thu May 11 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
170+- update to 1.2
171+
172+* Thu May 4 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
173+- update to 1.1.14
174+
175+* Sun Apr 23 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
176+- update to 1.1.12
177+
178+* Fri Apr 7 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
179+- add substitution of newsgroup with new messages by default
180+
181+* Wed Apr 5 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
182+- add attach message from newsgroup
183+- add one-line help in newsreader mode
184+- disable 'change-dir' command in newsgroups browser
185+- add -G option
186+
187+* Tue Apr 4 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
188+- get default newsserver name from file /etc/nntpserver
189+- use case insensitive server names
190+- add print-style sequence %s to $newsrc
191+- add -g option
192+
193+* Sat Apr 1 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
194+- remove 'X-FTN-Origin' header processing
195+
196+* Thu Mar 30 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
197+- update to 1.1.11
198+- update to 1.1.10
199+
200+* Thu Mar 23 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
201+- fix mutt_select_newsserver()
202+- remove 'toggle-mode' function
203+- add 'change-newsgroup' function
204+
205+* Wed Mar 22 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
206+- fix server-hook
207+
208+* Tue Mar 21 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
209+- fix error 'bounce' function after 'post'
210+- add 'forward to newsgroup' function
211+
212+* Mon Mar 20 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
213+- 'forward' function works in newsreader mode
214+- add 'post' and 'followup' functions to pager and attachment menu
215+- fix active descriptions and allowed flag reload
216+
217+* Tue Mar 14 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
218+- update to 1.1.9
219+- remove deleted newsgroups from list
220+
221+* Mon Mar 13 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
222+- update .newsrc in browser
223+
224+* Sun Mar 12 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
225+- reload .newsrc if externally modified
226+- fix active cache update
227+
228+* Sun Mar 5 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
229+- update to 1.1.8
230+
231+* Sat Mar 4 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
232+- patch *.update_list_file is not required
233+- count lines when loading descriptions
234+- remove cache of unsubscribed newsgroups
235+
236+* Thu Mar 2 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
237+- load list of newsgroups from cache faster
238+
239+* Wed Mar 1 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
240+- update to 1.1.7
241+
242+* Tue Feb 29 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
243+- fix unread messages in browser
244+- fix newsrc_gen_entries()
245+
246+* Mon Feb 28 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
247+- fix mutt_newsgroup_stat()
248+- fix nntp_delete_cache()
249+- fix nntp_get_status()
250+- fix check_children()
251+- fix nntp_fetch_headers()
252+
253+* Fri Feb 25 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
254+- update to 1.1.5
255+
256+* Thu Feb 24 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
257+- fix updating new messages in cache
258+
259+* Mon Feb 21 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
260+- change default cache filenames
261+- fix updating new messages in cache
262+
263+* Fri Feb 18 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
264+- fix segmentation fault in news groups browser
265+
266+* Tue Feb 15 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
267+- update to 1.1.4
268+
269+* Thu Feb 10 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
270+- update to 1.1.3
271+
272+* Sun Jan 30 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
273+- add X-Comment-To editing
274+- add my_hdr support for Newsgroups:, Followup-To: and X-Comment-To: headers
275+- add variables $ask_followup_to and $ask_x_comment_to
276+
277+* Fri Jan 28 2000 Vsevolod Volkov <vvv@mutt.kiev.ua>
278+- update to 1.1.2
279+
280+* Wed Aug 23 2000 Andrej Gritsenko <andrej@lucky.net>
281+- nntp.c: inserted server hook when opened a newsgroup - for
282+ difference between mail and news reader environment
283+- parse.c: `X-FTN-Origin:' processed for bad Fido gates
284+
285+* Tue Aug 22 2000 Vsevolod Volkov <vvv@mutt.org.ua>
286+- browser.c, complete.c: newsgroup completion patch
287+
288+* Wed Dec 22 1999 Andrej Gritsenko <andrej@lucky.net>
289+- send.c: fixed bug with `Subject:' on followup
290+
291+* Sat Dec 18 1999 Andrej Gritsenko <andrej@lucky.net>
292+- updated to 1.1.1
293+
294+* Tue Oct 26 1999 Andrej Gritsenko <andrej@lucky.net>
295+- updated to 1.1
296+
297+* Mon Jun 14 1999 Andrej Gritsenko <andrej@lucky.net>
298+- sendlib.c: use $mime_subject for news articles only
299+
300+* Fri Jun 11 1999 Edouard G. Parmelan <Edouard.Parmelan@quadratec.fr>
301+- nntp.c: bugfix with number of new articles
302+
303+* Thu Jun 10 1999 Andrej Gritsenko <andrej@lucky.net>
304+- nntp.c: fixed incomplete creating of index file
305+
306+* Wed Jun 9 1999 Andrej Gritsenko <andrej@lucky.net>
307+- updated to 0.96.3
308+- doc/manual*: documentation updated
309+
310+* Sun Feb 21 1999 Andrej Gritsenko <andrej@lucky.net>
311+- browser.c, newsrc.c, nntp.c: couple of fixes
312+
313+* Wed Dec 16 1998 Andrej Gritsenko <andrej@lucky.net>
314+- curs_main.c, newsrc.c, nntp.c: fixes on number of read
315+ articles
316+
317+* Tue Dec 15 1998 Vikas Agnihotri <vikasa@att.com>
318+- nntp.c: fix with gone cache files
319+
320+* Tue Dec 15 1998 Andrej Gritsenko <andrej@lucky.net>
321+- newsrc.c, nntp.c: fixes on number of read articles
322+
323+* Mon Dec 14 1998 Andrej Gritsenko <andrej@lucky.net>
324+- browser.c, newsrc.c, nntp.c, nntp.h: changed then simplified
325+ nntp_parse_xover()
326+
327+* Mon Dec 14 1998 Vikas Agnihotri <vikasa@att.com>
328+- browser.c: cosmetic patch
329+- nntp.c: say "Fetching %s from server..."
330+
331+* Sun Dec 13 1998 Andrej Gritsenko <andrej@lucky.net>
332+- commands.c, newsrc.c, nntp.c, nntp.h: don't save newsrc file
333+ so often (noted by Vikas Agnihotri)
334+
335+* Sat Dec 12 1998 Andrej Gritsenko <andrej@lucky.net>
336+- browser.c, functions.h, nntp.c, nntp.h: fixed incorrect first
337+ active loading
338+
339+* Wed Dec 9 1998 Vikas Agnihotri <vikasa@att.com>
340+- nntp.c: fixed bug in `reconstruct-thread' function
341+- curs_main.c, nntp.c: fixed the bug in non-XOVER case of get
342+ headers
343+
344+* Tue Dec 8 1998 Andrej Gritsenko <andrej@lucky.net>
345+- nntp.c: fixed error in getting status of article
346+
347+* Tue Dec 8 1998 Vikas Agnihotri <vikasa@att.com>
348+- mutt.h, pattern.c: added `~w' search pattern
349+
350+* Tue Dec 8 1998 Andrej Gritsenko <andrej@lucky.net>
351+- nntp.c: bugfix when get children
352+
353+* Tue Dec 8 1998 Vikas Agnihotri <vikasa@att.com>
354+- newsrc.c: bugfix in mutt_newsgroup_catchup()
355+
356+* Tue Dec 8 1998 Andrej Gritsenko <andrej@lucky.net>
357+- browser.c: bugfix in _mutt_select_file()
358+
359+* Sat Dec 5 1998 Andrej Gritsenko <andrej@lucky.net>
360+- browser.c, newsrc.c, nntp.c, nntp.h: fix the sorting of
361+ newsgroups in browser (from Vikas Agnihotri)
362+
363+* Fri Dec 4 1998 Vikas Agnihotri <vikasa@att.com>
364+- OPS, curs_main.c, functions.h, nntp.c, nntp.h: new functions:
365+ `get-children' and `reconstruct-thread'
366+
367+* Thu Dec 3 1998 Vikas Agnihotri <vikasa@att.com>
368+- OPS, curs_main.c, functions.h, nntp.c, nntp.h: new functions:
369+ `get-message' and `get-parent'
370+
371+* Wed Dec 2 1998 Vikas Agnihotri <vikasa@att.com>
372+- OPS, compose.c, curs_main.c, functions.h, parse.c, send.c,
373+ sendlib.c: added `Followup-To:' field editing
374+
375+* Wed Dec 2 1998 Vikas Agnihotri <vikasa@att.com>
376+- OPS, browser.c, functions.h: new `load-active' function
377+
378+* Tue Dec 1 1998 Andrej Gritsenko <andrej@lucky.net>
379+- browser.c: added option for blank %s in $group_index_format
380+- hdrline.c, lib.c, mutt.h, parse.c: added %g and %W parameters
381+ to $pager_format
382+- hook.c, newsrc.c, nntp.c, sendlib.c: some small bugfixes
383+
384+* Mon Nov 30 1998 Andrej Gritsenko <andrej@lucky.net>
385+- send.c: bugfix in `Followup-To:' field
386+
387+* Sun Nov 29 1998 Vikas Agnihotri <vikasa@att.com>
388+- compose.c, lib.c, parse.c, protos.h: remove white spaces from
389+ `Newsgroup:' field to prevent a unnecessary rejection of article
390+
391+* Sat Nov 28 1998 Vikas Agnihotri <vikasa@att.com>
392+- newsrc.c: fixed bug in catchup
393+
394+* Sat Nov 28 1998 Vikas Agnihotri <vikasa@att.com>
395+- browser.c: make indicator advance when (un)subscribe
396+
397+* Sat Nov 28 1998 Andrej Gritsenko <andrej@lucky.net>
398+- newsrc.c: fixed segmentation fault in newsrc_update_line()
399+
400+* Sat Nov 28 1998 Andrej Gritsenko <andrej@lucky.net>
401+- OPS, browser.c, functions.h, init.h, mutt.h, mx.c, newsrc.c,
402+ nntp.c, nntp.h: corrected reading of newsrc file and added new
403+ `catchup' function
404+
405+* Thu Nov 26 1998 Andrej Gritsenko <andrej@lucky.net>
406+- browser.c, newsrc.c: implementation of `(un)subscribe-pattern'
407+ functions from Vikas Agnihotri
408+- globals.h, init.h, nntp.h, nntp.c: added variable $nntp_poll
409+ to avoid of polling newsserver on each keypressing
410+
411+* Thu Nov 26 1998 Andrej Gritsenko <andrej@lucky.net>
412+- nntp.c, socket.c: fixed parsing of long XOVER lines
413+- send.c: removed silly ask for newsgroup name (noted by Vikas
414+ Agnihotri)
415+
416+* Wed Nov 25 1998
417+- commands.c: bugfix in mutt_update_list_file()
418+
419+* Wed Nov 25 1998 Andrej Gritsenko <andrej@lucky.net>
420+- updated to mutt-0.94.17
421+- init.c, nntp.c, nntp.h, parse.c, send.c: couple of bugfixes
422+ from Vikas Agnihotri
423+
424+* Sat Nov 21 1998 Andrej Gritsenko <andrej@lucky.net>
425+- [mutt-0.94.13] couple of files: pre-alpha version of patch,
426+ partially based on code that written by Brandon Long
427diff -uNr mutt-1.4.orig/Makefile.am mutt-1.4/Makefile.am
428--- mutt-1.4.orig/Makefile.am Sun Nov 3 21:42:52 2002
429+++ mutt-1.4/Makefile.am Sun Nov 3 21:57:20 2002
430@@ -68,7 +68,8 @@
431 EXTRA_mutt_SOURCES = account.c md5c.c mutt_sasl.c mutt_socket.c mutt_ssl.c \
432 mutt_tunnel.c pop.c pop_auth.c pop_lib.c pgp.c pgpinvoke.c pgpkey.c \
433 pgplib.c sha1.c pgpmicalg.c gnupgparse.c resize.c dotlock.c remailer.c \
434- browser.h mbyte.h remailer.h url.h mutt_ssl_nss.c pgppacket.c
435+ browser.h mbyte.h remailer.h url.h mutt_ssl_nss.c pgppacket.c \
436+ nntp.c newsrc.c
437
438 EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP TODO configure acconfig.h account.h \
439 attach.h buffy.h charset.h compress.h copy.h dotlock.h functions.h \
440@@ -77,6 +78,7 @@
441 mutt_regex.h mutt_sasl.h mutt_socket.h mutt_ssl.h mutt_tunnel.h \
442 mx.h pager.h pgp.h pop.h protos.h reldate.h rfc1524.h rfc2047.h \
443 rfc2231.h rfc822.h sha1.h sort.h mime.types VERSION prepare \
444+ nntp.h ChangeLog.nntp \
445 _regex.h OPS.MIX README.SECURITY remailer.c remailer.h browser.h \
446 mbyte.h lib.h extlib.c pgpewrap.c pgplib.h Muttrc.head Muttrc \
447 makedoc.c stamp-doc-rc README.SSL \
1b5dcea5 448diff -uNr mutt-1.4.orig/Muttrc mutt-1.4/Muttrc
449--- mutt-1.4.orig/Muttrc Sun Nov 3 21:42:52 2002
450+++ mutt-1.4/Muttrc Sun Nov 3 21:57:20 2002
451@@ -185,6 +185,28 @@
452 # editing the body of an outgoing message.
453 #
454 #
455+# set ask_follow_up=no
456+#
457+# Name: ask_follow_up
458+# Type: boolean
459+# Default: no
460+#
461+#
462+# If set, Mutt will prompt you for follow-up groups before editing
463+# the body of an outgoing message.
464+#
465+#
466+# set ask_x_comment_to=no
467+#
468+# Name: ask_x_comment_to
469+# Type: boolean
470+# Default: no
471+#
472+#
473+# If set, Mutt will prompt you for x-comment-to field before editing
474+# the body of an outgoing message.
475+#
476+#
477 # set attach_format="%u%D%I %t%4n %T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] "
478 #
479 # Name: attach_format
480@@ -308,6 +330,17 @@
481 # bouncing messages. Postfix users may wish to unset this variable.
482 #
483 #
484+# set catchup_newsgroup=ask-yes
485+#
486+# Name: catchup_newsgroup
487+# Type: quadoption
488+# Default: ask-yes
489+#
490+#
491+# If this variable is set, Mutt will mark all articles in newsgroup
492+# as read when you quit the newsgroup (catchup newsgroup).
493+#
494+#
495 # set charset=""
496 #
497 # Name: charset
498@@ -734,6 +767,19 @@
499 # resulting in two copies of the same email for you.
500 #
501 #
502+# set followup_to_poster=ask-yes
503+#
504+# Name: followup_to_poster
505+# Type: quadoption
506+# Default: ask-yes
507+#
508+#
509+# If this variable is set and the keyword "poster" is present in
510+# Followup-To header, follow-up to newsgroup function is not
511+# permitted. The message will be mailed to the submitter of the
512+# message via mail.
513+#
514+#
515 # set force_name=no
516 #
517 # Name: force_name
518@@ -818,6 +864,28 @@
519 # "Franklin" to "Franklin, Steve".
520 #
521 #
522+# set group_index_format="%4C %M%N %5s %-45.45f %d"
523+#
524+# Name: group_index_format
525+# Type: string
526+# Default: "%4C %M%N %5s %-45.45f %d"
527+#
528+#
529+# This variable allows you to customize the newsgroup browser display to
530+# your personal taste. This string is similar to ``index_format'', but
531+# has its own set of printf()-like sequences:
532+#
533+# %C current newsgroup number
534+# %d description of newsgroup (becomes from server)
535+# %f newsgroup name
536+# %M - if newsgroup not allowed for direct post (moderated for example)
537+# %N N if newsgroup is new, u if unsubscribed, blank otherwise
538+# %n number of new articles in newsgroup
539+# %s number of unread articles in newsgroup
540+# %>X right justify the rest of the string and pad with character "X"
541+# %|X pad to the end of the line with character "X"
542+#
543+#
544 # set hdrs=yes
545 #
546 # Name: hdrs
547@@ -1187,6 +1255,7 @@
548 # %E number of messages in current thread
549 # %f entire From: line (address + real name)
550 # %F author name, or recipient name if the message is from you
551+# %g newsgroup name (if compiled with nntp support)
552 # %i message-id of the current message
553 # %l number of lines in the message
554 # %L If an address in the To or CC header field matches an address
555@@ -1204,6 +1273,7 @@
556 # %T the appropriate character from the $to_chars string
557 # %u user (login) name of the author
558 # %v first name of the author, or the recipient if the message is from you
559+# %W name of organization of author (`organization:' field)
560 # %y `x-label:' field, if present
561 # %Y `x-label' field, if present, and (1) not at part of a thread tree,
562 # (2) at the top of a thread, or (3) `x-label' is different from
563@@ -1227,6 +1297,22 @@
564 # See also: ``$to_chars''.
565 #
566 #
567+# set inews=""
568+#
569+# Name: inews
570+# Type: path
571+# Default: ""
572+#
573+#
574+# If set, specifies the program and arguments used to deliver news posted
575+# by Mutt. Otherwise, mutt posts article using current connection to
576+# news server. The following printf-style sequence is understood:
577+#
578+# %s newsserver name
579+#
580+# Example: set inews="/usr/local/bin/inews -hS"
581+#
582+#
583 # set ispell="/usr/bin/ispell"
584 #
585 # Name: ispell
586@@ -1496,6 +1582,18 @@
587 # be attached to the newly composed message if this option is set.
588 #
589 #
590+# set mime_subject=yes
591+#
592+# Name: mime_subject
593+# Type: boolean
594+# Default: yes
595+#
596+#
597+# If unset, 8-bit ``subject:'' line in article header will not be
598+# encoded according to RFC2047 to base64. This is useful when message
599+# is Usenet article, because MIME for news is nonstandard feature.
600+#
601+#
602 # set mix_entry_format="%4n %c %-16s %a"
603 #
604 # Name: mix_entry_format
605@@ -1550,6 +1648,118 @@
606 # escape sequences see the section on ``$index_format''.
607 #
608 #
609+# set news_cache_dir="~/.mutt"
610+#
611+# Name: news_cache_dir
612+# Type: path
613+# Default: "~/.mutt"
614+#
615+#
616+# This variable pointing to directory where Mutt will save cached news
617+# articles headers in. If unset, headers will not be saved at all
618+# and will be reloaded each time when you enter to newsgroup.
619+#
620+#
621+# set news_server=""
622+#
623+# Name: news_server
624+# Type: string
625+# Default: ""
626+#
627+#
628+# This variable specifies domain name or address of NNTP server. It
629+# defaults to the newsserver specified in the environment variable
630+# $NNTPSERVER or contained in the file /etc/nntpserver. You can also
631+# specify username and an alternative port for each newsserver, ie:
632+#
633+# [nntp[s]://][username[:password]@]newsserver[:port]
634+#
635+#
636+# set newsrc="~/.newsrc"
637+#
638+# Name: newsrc
639+# Type: path
640+# Default: "~/.newsrc"
641+#
642+#
643+# The file, containing info about subscribed newsgroups - names and
644+# indexes of read articles. The following printf-style sequence
645+# is understood:
646+#
647+# %s newsserver name
648+#
649+#
650+# set nntp_context=1000
651+#
652+# Name: nntp_context
653+# Type: number
654+# Default: 1000
655+#
656+#
657+# This variable defines number of articles which will be in index when
658+# newsgroup entered. If active newsgroup have more articles than this
659+# number, oldest articles will be ignored. Also controls how many
660+# articles headers will be saved in cache when you quit newsgroup.
661+#
662+#
663+# set nntp_load_description=yes
664+#
665+# Name: nntp_load_description
666+# Type: boolean
667+# Default: yes
668+#
669+#
670+# This variable controls whether or not descriptions for each newsgroup
671+# must be loaded when newsgroup is added to list (first time list
672+# loading or new newsgroup adding).
673+#
674+#
675+# set nntp_user=""
676+#
677+# Name: nntp_user
678+# Type: string
679+# Default: ""
680+#
681+#
682+# Your login name on the NNTP server. If unset and NNTP server requires
683+# authentification, Mutt will prompt you for your account name when you
684+# connect to newsserver.
685+#
686+#
687+# set nntp_pass=""
688+#
689+# Name: nntp_pass
690+# Type: string
691+# Default: ""
692+#
693+#
694+# Your password for NNTP account.
695+#
696+#
697+# set nntp_poll=60
698+#
699+# Name: nntp_poll
700+# Type: number
701+# Default: 60
702+#
703+#
704+# The time in seconds until any operations on newsgroup except post new
705+# article will cause recheck for new news. If set to 0, Mutt will
706+# recheck newsgroup on each operation in index (stepping, read article,
707+# etc.).
708+#
709+#
710+# set nntp_reconnect=ask-yes
711+#
712+# Name: nntp_reconnect
713+# Type: quadoption
714+# Default: ask-yes
715+#
716+#
717+# Controls whether or not Mutt will try to reconnect to newsserver when
718+# connection lost.
719+#
720+#
721 # set pager="builtin"
722 #
723 # Name: pager
724@@ -2293,6 +2503,19 @@
725 # string after the inclusion of a message which is being replied to.
726 #
727 #
728+# set post_moderated=ask-yes
729+#
730+# Name: post_moderated
731+# Type: quadoption
732+# Default: ask-yes
733+#
734+#
735+# If set to yes, Mutt will post article to newsgroup that have
736+# not permissions to posting (e.g. moderated). Note: if newsserver
737+# does not support posting to that newsgroup or totally read-only, that
738+# posting will not have an effect.
739+#
740+#
741 # set postpone=ask-yes
742 #
743 # Name: postpone
744@@ -2802,6 +3025,41 @@
745 # shell from /etc/passwd is used.
746 #
747 #
748+# set save_unsubscribed=no
749+#
750+# Name: save_unsubscribed
751+# Type: boolean
752+# Default: no
753+#
754+#
755+# When set, info about unsubscribed newsgroups will be saved into
756+# ``newsrc'' file and into cache.
757+#
758+#
759+# set show_new_news=yes
760+#
761+# Name: show_new_news
762+# Type: boolean
763+# Default: yes
764+#
765+#
766+# If set, newsserver will be asked for new newsgroups on entering
767+# the browser. Otherwise, it will be done only once for a newsserver.
768+# Also controls whether or not number of new articles of subscribed
769+# newsgroups will be then checked.
770+#
771+#
772+# set show_only_unread=no
773+#
774+# Name: show_only_unread
775+# Type: boolean
776+# Default: no
777+#
778+#
779+# If set, only subscribed newsgroups that contain unread articles
780+# will be displayed in browser.
781+#
782+#
783 # set sig_dashes=yes
784 #
785 # Name: sig_dashes
786@@ -3285,6 +3543,18 @@
787 # command.
788 #
789 #
790+# set use_ipv6=yes
791+#
792+# Name: use_ipv6
793+# Type: boolean
794+# Default: yes
795+#
796+#
797+# When set, Mutt will look for IPv6 addresses of hosts it tries to
798+# contact. If this option is unset, Mutt will restrict itself to IPv4 addresses.
799+# Normally, the default should work.
800+#
801+#
802 # set user_agent=yes
803 #
804 # Name: user_agent
805@@ -3387,3 +3657,14 @@
806 # messages to be sent. Exim users may wish to use this.
807 #
808 #
809+# set x_comment_to=no
810+#
811+# Name: x_comment_to
812+# Type: boolean
813+# Default: no
814+#
815+#
816+# If set, Mutt will add ``X-Comment-To:'' field (that contains full
817+# name of original article author) to article that followuped to newsgroup.
818+#
819+#
820diff -uNr mutt-1.4.orig/Muttrc.head mutt-1.4/Muttrc.head
821--- mutt-1.4.orig/Muttrc.head Sun Nov 3 21:42:51 2002
822+++ mutt-1.4/Muttrc.head Thu Jan 1 01:00:00 1970
823@@ -1,43 +0,0 @@
824-#
825-# System configuration file for Mutt
826-#
827-
828-# default list of header fields to weed when displaying
829-#
830-ignore "from " received content- mime-version status x-status message-id
831-ignore sender references return-path lines
832-
833-# imitate the old search-body function
834-macro index \eb '/~b ' 'search in message bodies'
835-
836-# simulate the old url menu
837-macro index \cb |urlview\n 'call urlview to extract URLs out of a message'
838-macro pager \cb |urlview\n 'call urlview to extract URLs out of a message'
839-
840-# Show documentation when pressing F1
841-macro generic <f1> "!less /usr/local/doc/mutt/manual.txt\n" "Show Mutt documentation"
842-macro index <f1> "!less /usr/local/doc/mutt/manual.txt\n" "Show Mutt documentation"
843-macro pager <f1> "!less /usr/local/doc/mutt/manual.txt\n" "Show Mutt documentation"
844-
845-# Use folders which match on \\.gz$ as gzipped folders:
846-# open-hook \\.gz$ "gzip -cd %f > %t"
847-# close-hook \\.gz$ "gzip -c %t > %f"
848-# append-hook \\.gz$ "gzip -c %t >> %f"
849-
850-# open-hook \\.bz2$ "bzip2 -cd %f > %t"
851-# close-hook \\.bz2$ "bzip2 -c %t > %f"
852-# append-hook \\.bz2$ "bzip2 -c %t >> %f"
853-
854-# If Mutt is unable to determine your site's domain name correctly, you can
855-# set the default here.
856-#
857-# set hostname=cs.hmc.edu
858-
859-# If your sendmail supports the -B8BITMIME flag, enable the following
860-#
861-# set use_8bitmime
862-
863-##
864-## More settings
865-##
866-
867diff -uNr mutt-1.4.orig/OPS mutt-1.4/OPS
868--- mutt-1.4.orig/OPS Sun Nov 3 21:42:52 2002
869+++ mutt-1.4/OPS Sun Nov 3 21:57:20 2002
870@@ -7,13 +7,15 @@
871 OP_BROWSER_NEW_FILE "select a new file in this directory"
872 OP_BROWSER_VIEW_FILE "view file"
873 OP_BROWSER_TELL "display the currently selected file's name"
874-OP_BROWSER_SUBSCRIBE "subscribe to current mailbox (IMAP only)"
875-OP_BROWSER_UNSUBSCRIBE "unsubscribe to current mailbox (IMAP only)"
876+OP_CATCHUP "mark all articles in newsgroup as read"
877+OP_BROWSER_SUBSCRIBE "subscribe to current (IMAP/NNTP only)"
878+OP_BROWSER_UNSUBSCRIBE "unsubscribe to current (IMAP/NNTP only)"
879 OP_BROWSER_TOGGLE_LSUB "toggle view all/subscribed mailboxes (IMAP only)"
880 OP_CHANGE_DIRECTORY "change directories"
881 OP_CHECK_NEW "check mailboxes for new mail"
882 OP_COMPOSE_ATTACH_FILE "attach a file(s) to this message"
883 OP_COMPOSE_ATTACH_MESSAGE "attach message(s) to this message"
884+OP_COMPOSE_ATTACH_NEWS_MESSAGE "attach newsmessage(s) to this message"
885 OP_COMPOSE_EDIT_BCC "edit the BCC list"
886 OP_COMPOSE_EDIT_CC "edit the CC list"
887 OP_COMPOSE_EDIT_DESCRIPTION "edit attachment description"
888@@ -24,7 +26,10 @@
889 OP_COMPOSE_EDIT_HEADERS "edit the message with headers"
890 OP_COMPOSE_EDIT_MESSAGE "edit the message"
891 OP_COMPOSE_EDIT_MIME "edit attachment using mailcap entry"
892+OP_COMPOSE_EDIT_NEWSGROUPS "edit the newsgroups list"
893 OP_COMPOSE_EDIT_REPLY_TO "edit the Reply-To field"
894+OP_COMPOSE_EDIT_FOLLOWUP_TO "edit the Followup-To field"
895+OP_COMPOSE_EDIT_X_COMMENT_TO "edit the X-Comment-To field"
896 OP_COMPOSE_EDIT_SUBJECT "edit the subject of this message"
897 OP_COMPOSE_EDIT_TO "edit the TO list"
898 OP_CREATE_MAILBOX "create a new mailbox (IMAP only)"
899@@ -84,8 +89,13 @@
900 OP_FILTER "filter attachment through a shell command"
901 OP_FIRST_ENTRY "move to the first entry"
902 OP_FLAG_MESSAGE "toggle a message's 'important' flag"
903+OP_FOLLOWUP "followup to newsgroup"
904+OP_FORWARD_TO_GROUP "forward to newsgroup"
905 OP_FORWARD_MESSAGE "forward a message with comments"
906 OP_GENERIC_SELECT_ENTRY "select the current entry"
907+OP_GET_CHILDREN "get all children of the current message"
908+OP_GET_MESSAGE "get message with Message-Id"
909+OP_GET_PARENT "get parent of the current message"
910 OP_GROUP_REPLY "reply to all recipients"
911 OP_HALF_DOWN "scroll down 1/2 page"
912 OP_HALF_UP "scroll up 1/2 page"
913@@ -93,13 +103,17 @@
914 OP_JUMP "jump to an index number"
915 OP_LAST_ENTRY "move to the last entry"
916 OP_LIST_REPLY "reply to specified mailing list"
917+OP_LOAD_ACTIVE "load active file from NNTP server"
918 OP_MACRO "execute a macro"
919 OP_MAIL "compose a new mail message"
920 OP_MAIN_BREAK_THREAD "break the thread in two"
921 OP_MAIN_CHANGE_FOLDER "open a different folder"
922 OP_MAIN_CHANGE_FOLDER_READONLY "open a different folder in read only mode"
923+OP_MAIN_CHANGE_GROUP "open a different newsgroup"
924+OP_MAIN_CHANGE_GROUP_READONLY "open a different newsgroup in read only mode"
925 OP_MAIN_CLEAR_FLAG "clear a status flag from a message"
926 OP_MAIN_DELETE_PATTERN "delete messages matching a pattern"
927+OP_RECONSTRUCT_THREAD "reconstruct thread containing current message"
928 OP_MAIN_IMAP_FETCH "force retrieval of mail from IMAP server"
929 OP_MAIN_FETCH_MAIL "retrieve mail from POP server"
930 OP_MAIN_FIRST_MESSAGE "move to the first message"
931@@ -134,6 +148,7 @@
932 OP_PAGER_SKIP_QUOTED "skip beyond quoted text"
933 OP_PAGER_TOP "jump to the top of the message"
934 OP_PIPE "pipe message/attachment to a shell command"
935+OP_POST "post message to newsgroup"
936 OP_PREV_ENTRY "move to the previous entry"
937 OP_PREV_LINE "scroll up one line"
938 OP_PREV_PAGE "move to the previous page"
939@@ -159,17 +174,21 @@
940 OP_SIG_SEARCH "search signatures matching a pattern"
941 OP_SORT "sort messages"
942 OP_SORT_REVERSE "sort messages in reverse order"
943+OP_SUBSCRIBE_PATTERN "subscribe to newsgroups matching a pattern"
944 OP_TAG "tag the current entry"
945 OP_TAG_PREFIX "apply next function to tagged messages"
946 OP_TAG_SUBTHREAD "tag the current subthread"
947 OP_TAG_THREAD "tag the current thread"
948 OP_TOGGLE_NEW "toggle a message's 'new' flag"
949+OP_TOGGLE_READ "toggle view of read messages"
950 OP_TOGGLE_WRITE "toggle whether the mailbox will be rewritten"
951 OP_TOGGLE_MAILBOXES "toggle whether to browse mailboxes or all files"
952 OP_TOP_PAGE "move to the top of the page"
953+OP_UNCATCHUP "mark all articles in newsgroup as unread"
954 OP_UNDELETE "undelete the current entry"
955 OP_UNDELETE_THREAD "undelete all messages in thread"
956 OP_UNDELETE_SUBTHREAD "undelete all messages in subthread"
957+OP_UNSUBSCRIBE_PATTERN "unsubscribe from newsgroups matching a pattern"
958 OP_VERSION "show the Mutt version number and date"
959 OP_VIEW_ATTACH "view attachment using mailcap entry if necessary"
960 OP_VIEW_ATTACHMENTS "show MIME attachments"
961diff -uNr mutt-1.4.orig/PATCHES mutt-1.4/PATCHES
962--- mutt-1.4.orig/PATCHES Sun Nov 3 21:42:52 2002
963+++ mutt-1.4/PATCHES Sun Nov 3 21:57:20 2002
964@@ -1,3 +1,4 @@
965+vvv.nntp
966 patch-1.3.28.dw.pgp-hook.3
967 vvv.quote
968 patch-1.3.27.cd.signatures_menu.2.1
969diff -uNr mutt-1.4.orig/acconfig.h mutt-1.4/acconfig.h
970--- mutt-1.4.orig/acconfig.h Tue Jan 15 23:08:12 2002
971+++ mutt-1.4/acconfig.h Sun Nov 3 21:57:20 2002
972@@ -14,6 +14,9 @@
973 */
974 #undef HOMESPOOL
975
976+/* Compiling with newsreading support with NNTP */
977+#undef USE_NNTP
978+
979 /* program to use for shell commands */
980 #define EXECSHELL "/bin/sh"
981
982diff -uNr mutt-1.4.orig/account.c mutt-1.4/account.c
983--- mutt-1.4.orig/account.c Thu Apr 26 15:36:33 2001
984+++ mutt-1.4/account.c Sun Nov 3 21:57:20 2002
985@@ -44,6 +44,11 @@
986 user = PopUser;
987 #endif
988
989+#ifdef USE_NNTP
990+ if (a1->type == M_ACCT_TYPE_NNTP && NntpUser)
991+ user = NntpUser;
992+#endif
993+
994 if (a1->flags & a2->flags & M_ACCT_USER)
995 return (!strcmp (a1->user, a2->user));
996 if (a1->flags & M_ACCT_USER)
997@@ -113,6 +118,16 @@
998 }
999 #endif
1000
1001+#ifdef USE_NNTP
1002+ if (account->type == M_ACCT_TYPE_NNTP)
1003+ {
1004+ if (account->flags & M_ACCT_SSL)
1005+ url->scheme = U_NNTPS;
1006+ else
1007+ url->scheme = U_NNTP;
1008+ }
1009+#endif
1010+
1011 url->host = account->host;
1012 if (account->flags & M_ACCT_PORT)
1013 url->port = account->port;
1014@@ -138,6 +153,10 @@
1015 else if ((account->type == M_ACCT_TYPE_POP) && PopUser)
1016 strfcpy (account->user, PopUser, sizeof (account->user));
1017 #endif
1018+#ifdef USE_NNTP
1019+ else if ((account->type == M_ACCT_TYPE_NNTP) && NntpUser)
1020+ strfcpy (account->user, NntpUser, sizeof (account->user));
1021+#endif
1022 /* prompt (defaults to unix username), copy into account->user */
1023 else
1024 {
1025@@ -167,6 +186,10 @@
1026 else if ((account->type == M_ACCT_TYPE_POP) && PopPass)
1027 strfcpy (account->pass, PopPass, sizeof (account->pass));
1028 #endif
1029+#ifdef USE_NNTP
1030+ else if ((account->type == M_ACCT_TYPE_NNTP) && NntpPass)
1031+ strfcpy (account->pass, NntpPass, sizeof (account->pass));
1032+#endif
1033 else
1034 {
1035 snprintf (prompt, sizeof (prompt), _("Password for %s@%s: "),
1036diff -uNr mutt-1.4.orig/account.h mutt-1.4/account.h
1037--- mutt-1.4.orig/account.h Tue Jan 2 10:34:30 2001
1038+++ mutt-1.4/account.h Sun Nov 3 21:57:20 2002
1039@@ -28,6 +28,7 @@
1040 {
1041 M_ACCT_TYPE_NONE = 0,
1042 M_ACCT_TYPE_IMAP,
1043+ M_ACCT_TYPE_NNTP,
1044 M_ACCT_TYPE_POP
1045 };
1046
1b5dcea5 1047diff -uNr mutt-1.4.orig/attach.h mutt-1.4/attach.h
1048--- mutt-1.4.orig/attach.h Tue Sep 11 13:20:34 2001
1049+++ mutt-1.4/attach.h Sun Nov 3 21:57:20 2002
1050@@ -30,5 +30,5 @@
1051
1052 void mutt_attach_bounce (FILE *, HEADER *, ATTACHPTR **, short, BODY *);
1053 void mutt_attach_resend (FILE *, HEADER *, ATTACHPTR **, short, BODY *);
1054-void mutt_attach_forward (FILE *, HEADER *, ATTACHPTR **, short, BODY *);
1055+void mutt_attach_forward (FILE *, HEADER *, ATTACHPTR **, short, BODY *, int);
1056 void mutt_attach_reply (FILE *, HEADER *, ATTACHPTR **, short, BODY *, int);
1057diff -uNr mutt-1.4.orig/browser.c mutt-1.4/browser.c
1058--- mutt-1.4.orig/browser.c Sun Nov 3 21:42:52 2002
1059+++ mutt-1.4/browser.c Sun Nov 3 22:00:14 2002
1060@@ -27,6 +27,9 @@
1061 #ifdef USE_IMAP
1062 #include "imap.h"
1063 #endif
1064+#ifdef USE_NNTP
1065+#include "nntp.h"
1066+#endif
1067
1068 #include <stdlib.h>
1069 #include <dirent.h>
1070@@ -44,6 +47,19 @@
1071 { NULL }
1072 };
1073
1074+#ifdef USE_NNTP
1075+static struct mapping_t FolderNewsHelp[] = {
1076+ { N_("Exit"), OP_EXIT },
1077+ { N_("List"), OP_TOGGLE_MAILBOXES },
1078+ { N_("Subscribe"), OP_BROWSER_SUBSCRIBE },
1079+ { N_("Unsubscribe"), OP_BROWSER_UNSUBSCRIBE },
1080+ { N_("Catchup"), OP_CATCHUP },
1081+ { N_("Mask"), OP_ENTER_MASK },
1082+ { N_("Help"), OP_HELP },
1083+ { NULL }
1084+};
1085+#endif
1086+
1087 typedef struct folder_t
1088 {
1089 struct folder_file *ff;
1090@@ -109,9 +125,17 @@
1091 case SORT_ORDER:
1092 return;
1093 case SORT_DATE:
1094+#ifdef USE_NNTP
1095+ if (option (OPTNEWS))
1096+ return;
1097+#endif
1098 f = browser_compare_date;
1099 break;
1100 case SORT_SIZE:
1101+#ifdef USE_NNTP
1102+ if (option (OPTNEWS))
1103+ return;
1104+#endif
1105 f = browser_compare_size;
1106 break;
1107 case SORT_SUBJECT:
1108@@ -299,8 +323,106 @@
1109 return (src);
1110 }
1111
1112+#ifdef USE_NNTP
1113+static const char *
1114+newsgroup_format_str (char *dest, size_t destlen, char op, const char *src,
1115+ const char *fmt, const char *ifstring, const char *elsestring,
1116+ unsigned long data, format_flag flags)
1117+{
1118+ char fn[SHORT_STRING], tmp[SHORT_STRING];
1119+ FOLDER *folder = (FOLDER *) data;
1120+
1121+ switch (op)
1122+ {
1123+ case 'C':
1124+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
1125+ snprintf (dest, destlen, tmp, folder->num + 1);
1126+ break;
1127+
1128+ case 'f':
1129+ strncpy (fn, folder->ff->name, sizeof(fn) - 1);
1130+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
1131+ snprintf (dest, destlen, tmp, fn);
1132+ break;
1133+
1134+ case 'N':
1135+ snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
1136+ if (folder->ff->nd->subscribed)
1137+ snprintf (dest, destlen, tmp, ' ');
1138+ else
1139+ snprintf (dest, destlen, tmp, folder->ff->new ? 'N' : 'u');
1140+ break;
1141+
1142+ case 'M':
1143+ snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
1144+ if (folder->ff->nd->deleted)
1145+ snprintf (dest, destlen, tmp, 'D');
1146+ else
1147+ snprintf (dest, destlen, tmp, folder->ff->nd->allowed ? ' ' : '-');
1148+ break;
1149+
1150+ case 's':
1151+ if (flags & M_FORMAT_OPTIONAL)
1152+ {
1153+ if (folder->ff->nd->unread != 0)
1154+ mutt_FormatString (dest, destlen, ifstring, newsgroup_format_str,
1155+ data, flags);
1156+ else
1157+ mutt_FormatString (dest, destlen, elsestring, newsgroup_format_str,
1158+ data, flags);
1159+ }
1160+ else if (Context && Context->data == folder->ff->nd)
1161+ {
1162+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
1163+ snprintf (dest, destlen, tmp, Context->unread);
1164+ }
1165+ else
1166+ {
1167+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
1168+ snprintf (dest, destlen, tmp, folder->ff->nd->unread);
1169+ }
1170+ break;
1171+
1172+ case 'n':
1173+ if (Context && Context->data == folder->ff->nd)
1174+ {
1175+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
1176+ snprintf (dest, destlen, tmp, Context->new);
1177+ }
1178+ else if (option (OPTMARKOLD) &&
1179+ folder->ff->nd->lastCached >= folder->ff->nd->firstMessage &&
1180+ folder->ff->nd->lastCached <= folder->ff->nd->lastMessage)
1181+ {
1182+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
1183+ snprintf (dest, destlen, tmp, folder->ff->nd->lastMessage - folder->ff->nd->lastCached);
1184+ }
1185+ else
1186+ {
1187+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
1188+ snprintf (dest, destlen, tmp, folder->ff->nd->unread);
1189+ }
1190+ break;
1191+
1192+ case 'd':
1193+ if (folder->ff->nd->desc != NULL)
1194+ {
1195+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
1196+ snprintf (dest, destlen, tmp, folder->ff->nd->desc);
1197+ }
1198+ else
1199+ {
1200+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
1201+ snprintf (dest, destlen, tmp, "");
1202+ }
1203+ break;
1204+ }
1205+ return (src);
1206+}
1207+#endif /* USE_NNTP */
1208+
1209 static void add_folder (MUTTMENU *m, struct browser_state *state,
1210- const char *name, const struct stat *s, int new)
1211+ const char *name, const struct stat *s,
1212+ void *data, int new)
1213 {
1214 if (state->entrylen == state->entrymax)
1215 {
1216@@ -329,6 +451,10 @@
1217 #ifdef USE_IMAP
1218 (state->entry)[state->entrylen].imap = 0;
1219 #endif
1220+#ifdef USE_NNTP
1221+ if (option (OPTNEWS))
1222+ (state->entry)[state->entrylen].nd = (NNTP_DATA *) data;
1223+#endif
1224 (state->entrylen)++;
1225 }
1226
1227@@ -344,9 +470,35 @@
1228 menu->data = state->entry;
1229 }
1230
1231+/* get list of all files/newsgroups with mask */
1232 static int examine_directory (MUTTMENU *menu, struct browser_state *state,
1233 char *d, const char *prefix)
1234 {
1235+#ifdef USE_NNTP
1236+ if (option (OPTNEWS))
1237+ {
1238+ LIST *tmp;
1239+ NNTP_DATA *data;
1240+ NNTP_SERVER *news = CurrentNewsSrv;
1241+
1242+/* mutt_buffy_check (0); */
1243+ init_state (state, menu);
1244+
1245+ for (tmp = news->list; tmp; tmp = tmp->next)
1246+ {
1247+ if (!(data = (NNTP_DATA *)tmp->data))
1248+ continue;
1249+ if (prefix && *prefix && strncmp (prefix, data->group,
1250+ strlen (prefix)) != 0)
1251+ continue;
1252+ if (!((regexec (Mask.rx, data->group, 0, NULL, 0) == 0) ^ Mask.not))
1253+ continue;
1254+ add_folder (menu, state, data->group, NULL, data, data->new);
1255+ }
1256+ }
1257+ else
1258+#endif /* USE_NNTP */
1259+ {
1260 struct stat s;
1261 DIR *dp;
1262 struct dirent *de;
1263@@ -411,60 +563,95 @@
1264 tmp = Incoming;
1265 while (tmp && mutt_strcmp (buffer, tmp->path))
1266 tmp = tmp->next;
1267- add_folder (menu, state, de->d_name, &s, (tmp) ? tmp->new : 0);
1268+ add_folder (menu, state, de->d_name, &s, NULL, (tmp) ? tmp->new : 0);
1269+ }
1270+ closedir (dp);
1271 }
1272- closedir (dp);
1273 browser_sort (state);
1274 return 0;
1275 }
1276
1277+/* get list of mailboxes/subscribed newsgroups */
1278 static int examine_mailboxes (MUTTMENU *menu, struct browser_state *state)
1279 {
1280 struct stat s;
1281 char buffer[LONG_STRING];
1282- BUFFY *tmp = Incoming;
1283
1284- if (!Incoming)
1285- return (-1);
1286- mutt_buffy_check (0);
1287+#ifdef USE_NNTP
1288+ if (option (OPTNEWS))
1289+ {
1290+ LIST *tmp;
1291+ NNTP_DATA *data;
1292+ NNTP_SERVER *news = CurrentNewsSrv;
1293
1294- init_state (state, menu);
1295+/* mutt_buffy_check (0); */
1296+ init_state (state, menu);
1297
1298- do
1299- {
1300-#ifdef USE_IMAP
1301- if (mx_is_imap (tmp->path))
1302+ for (tmp = news->list; tmp; tmp = tmp->next)
1303 {
1304- add_folder (menu, state, tmp->path, NULL, tmp->new);
1305- continue;
1306+ if ((data = (NNTP_DATA *) tmp->data) != NULL && (data->new ||
1307+ (data->subscribed && (!option (OPTSHOWONLYUNREAD) || data->unread))))
1308+ add_folder (menu, state, data->group, NULL, data, data->new);
1309 }
1310+ }
1311+ else
1312 #endif
1313-#ifdef USE_POP
1314- if (mx_is_pop (tmp->path))
1315+ {
1316+ BUFFY *tmp = Incoming;
1317+
1318+ if (!Incoming)
1319+ return (-1);
1320+ mutt_buffy_check (0);
1321+
1322+ init_state (state, menu);
1323+
1324+ do
1325 {
1326- add_folder (menu, state, tmp->path, NULL, tmp->new);
1327- continue;
1328- }
1329+#ifdef USE_IMAP
1330+ if (mx_is_imap (tmp->path))
1331+ {
1332+ add_folder (menu, state, tmp->path, NULL, NULL, tmp->new);
1333+ continue;
1334+ }
1335 #endif
1336- if (lstat (tmp->path, &s) == -1)
1337- continue;
1338+#ifdef USE_POP
1339+ if (mx_is_pop (tmp->path))
1340+ {
1341+ add_folder (menu, state, tmp->path, NULL, NULL, tmp->new);
1342+ continue;
1343+ }
1344+#endif
1345+#ifdef USE_NNTP
1346+ if (mx_is_nntp (tmp->path))
1347+ {
1348+ add_folder (menu, state, tmp->path, NULL, NULL, tmp->new);
1349+ continue;
1350+ }
1351+#endif
1352+ if (lstat (tmp->path, &s) == -1)
1353+ continue;
1354
1355- if ((! S_ISREG (s.st_mode)) && (! S_ISDIR (s.st_mode)) &&
1356- (! S_ISLNK (s.st_mode)))
1357- continue;
1358+ if ((! S_ISREG (s.st_mode)) && (! S_ISDIR (s.st_mode)) &&
1359+ (! S_ISLNK (s.st_mode)))
1360+ continue;
1361
1362- strfcpy (buffer, NONULL(tmp->path), sizeof (buffer));
1363- mutt_pretty_mailbox (buffer);
1364+ strfcpy (buffer, NONULL(tmp->path), sizeof (buffer));
1365+ mutt_pretty_mailbox (buffer);
1366
1367- add_folder (menu, state, buffer, &s, tmp->new);
1368+ add_folder (menu, state, buffer, &s, NULL, tmp->new);
1369+ }
1370+ while ((tmp = tmp->next));
1371 }
1372- while ((tmp = tmp->next));
1373 browser_sort (state);
1374 return 0;
1375 }
1376
1377 int select_file_search (MUTTMENU *menu, regex_t *re, int n)
1378 {
1379+#ifdef USE_NNTP
1380+ if (option (OPTNEWS))
1381+ return (regexec (re, ((struct folder_file *) menu->data)[n].desc, 0, NULL, 0));
1382+#endif
1383 return (regexec (re, ((struct folder_file *) menu->data)[n].name, 0, NULL, 0));
1384 }
1385
1386@@ -475,7 +662,13 @@
1387 folder.ff = &((struct folder_file *) menu->data)[num];
1388 folder.num = num;
1389
1390- mutt_FormatString (s, slen, NONULL(FolderFormat), folder_format_str,
1391+#ifdef USE_NNTP
1392+ if (option (OPTNEWS))
1393+ mutt_FormatString (s, slen, NONULL(GroupFormat), newsgroup_format_str,
1394+ (unsigned long) &folder, M_FORMAT_ARROWCURSOR);
1395+ else
1396+#endif
1397+ mutt_FormatString (s, slen, NONULL(FolderFormat), folder_format_str,
1398 (unsigned long) &folder, M_FORMAT_ARROWCURSOR);
1399 }
1400
1401@@ -495,7 +688,18 @@
1402 menu->top = 0;
1403
1404 menu->tagged = 0;
1405-
1406+
1407+#ifdef USE_NNTP
1408+ if (option (OPTNEWS))
1409+ {
1410+ if (buffy)
1411+ snprintf (title, titlelen, _("Subscribed newsgroups"));
1412+ else
1413+ snprintf (title, titlelen, _("Newsgroups on server [%s]"),
1414+ CurrentNewsSrv->conn->account.host);
1415+ }
1416+ else
1417+#endif
1418 if (buffy)
1419 snprintf (title, titlelen, _("Mailboxes [%d]"), mutt_buffy_check (0));
1420 else
1421@@ -551,6 +755,31 @@
1422 if (!folder)
1423 strfcpy (LastDirBackup, LastDir, sizeof (LastDirBackup));
1424
1425+#ifdef USE_NNTP
1426+ if (option (OPTNEWS))
1427+ {
1428+ if (*f)
1429+ strfcpy (prefix, f, sizeof (prefix));
1430+ else
1431+ {
1432+ LIST *list;
1433+
1434+ /* default state for news reader mode is browse subscribed newsgroups */
1435+ buffy = 0;
1436+ for (list = CurrentNewsSrv->list; list; list = list->next)
1437+ {
1438+ NNTP_DATA *data = (NNTP_DATA *) list->data;
1439+
1440+ if (data && data->subscribed)
1441+ {
1442+ buffy = 1;
1443+ break;
1444+ }
1445+ }
1446+ }
1447+ }
1448+ else
1449+#endif
1450 if (*f)
1451 {
1452 mutt_expand_path (f, flen);
1453@@ -639,6 +868,9 @@
1454 menu->tag = file_tag;
1455
1456 menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_FOLDER,
1457+#ifdef USE_NNTP
1458+ (option (OPTNEWS)) ? FolderNewsHelp :
1459+#endif
1460 FolderHelp);
1461
1462 init_menu (&state, menu, title, sizeof (title), buffy, FolderColumns);
1463@@ -777,7 +1009,11 @@
1464 }
1465 }
1466
1467+#ifdef USE_NNTP
1468+ if (buffy || option (OPTNEWS)) /* news have not path */
1469+#else
1470 if (buffy)
1471+#endif
1472 {
1473 strfcpy (f, state.entry[menu->current].name, flen);
1474 mutt_expand_path (f, flen);
1475@@ -835,14 +1071,6 @@
1476 break;
1477
1478 #ifdef USE_IMAP
1479- case OP_BROWSER_SUBSCRIBE:
1480- imap_subscribe (state.entry[menu->current].name, 1);
1481- break;
1482-
1483- case OP_BROWSER_UNSUBSCRIBE:
1484- imap_subscribe (state.entry[menu->current].name, 0);
1485- break;
1486-
1487 case OP_BROWSER_TOGGLE_LSUB:
1488 if (option (OPTIMAPLSUB))
1489 {
1490@@ -913,6 +1141,11 @@
1491
1492 case OP_CHANGE_DIRECTORY:
1493
1494+#ifdef USE_NNTP
1495+ if (option (OPTNEWS))
1496+ break;
1497+#endif
1498+
1499 strfcpy (buf, LastDir, sizeof (buf));
1500 #ifdef USE_IMAP
1501 if (!state.imap_browse)
1502@@ -1163,6 +1396,190 @@
1503 else
1504 mutt_error _("Error trying to view file");
1505 }
1506+ break;
1507+
1508+#ifdef USE_NNTP
1509+ case OP_CATCHUP:
1510+ case OP_UNCATCHUP:
1511+ if (option (OPTNEWS))
1512+ {
1513+ struct folder_file *f = &state.entry[menu->current];
1514+ NNTP_DATA *nd;
1515+
1516+ if (i == OP_CATCHUP)
1517+ nd = mutt_newsgroup_catchup (CurrentNewsSrv, f->name);
1518+ else
1519+ nd = mutt_newsgroup_uncatchup (CurrentNewsSrv, f->name);
1520+
1521+ if (nd)
1522+ {
1523+/* FOLDER folder;
1524+ struct folder_file ff;
1525+ char buffer[_POSIX_PATH_MAX + SHORT_STRING];
1526+
1527+ folder.ff = &ff;
1528+ folder.ff->name = f->name;
1529+ folder.ff->st = NULL;
1530+ folder.ff->is_new = nd->new;
1531+ folder.ff->nd = nd;
1532+ safe_free ((void **) &f->desc);
1533+ mutt_FormatString (buffer, sizeof (buffer), NONULL(GroupFormat),
1534+ newsgroup_format_str, (unsigned long) &folder,
1535+ M_FORMAT_ARROWCURSOR);
1536+ f->desc = safe_strdup (buffer); */
1537+ if (menu->current + 1 < menu->max)
1538+ menu->current++;
1539+ menu->redraw = REDRAW_MOTION_RESYNCH;
1540+ }
1541+ }
1542+ break;
1543+
1544+ case OP_LOAD_ACTIVE:
1545+ if (!option (OPTNEWS))
1546+ break;
1547+
1548+ {
1549+ LIST *tmp;
1550+ NNTP_DATA *data;
1551+
1552+ for (tmp = CurrentNewsSrv->list; tmp; tmp = tmp->next)
1553+ {
1554+ if ((data = (NNTP_DATA *)tmp->data))
1555+ data->deleted = 1;
1556+ }
1557+ }
1558+ nntp_get_active (CurrentNewsSrv);
1559+
1560+ destroy_state (&state);
1561+ if (buffy)
1562+ examine_mailboxes (menu, &state);
1563+ else
1564+ examine_directory (menu, &state, NULL, NULL);
1565+ init_menu (&state, menu, title, sizeof (title), buffy, 1);
1566+ break;
1567+#endif /* USE_NNTP */
1568+
1569+#if defined USE_IMAP || defined USE_NNTP
1570+ case OP_BROWSER_SUBSCRIBE:
1571+ case OP_BROWSER_UNSUBSCRIBE:
1572+#endif
1573+#ifdef USE_NNTP
1574+ case OP_SUBSCRIBE_PATTERN:
1575+ case OP_UNSUBSCRIBE_PATTERN:
1576+ if (option (OPTNEWS))
1577+ {
1578+ regex_t *rx = (regex_t *) safe_malloc (sizeof (regex_t));
1579+ char *s = buf;
1580+ int j = menu->current;
1581+ NNTP_DATA *nd;
1582+ NNTP_SERVER *news = CurrentNewsSrv;
1583+
1584+ if (i == OP_SUBSCRIBE_PATTERN || i == OP_UNSUBSCRIBE_PATTERN)
1585+ {
1586+ char tmp[STRING];
1587+ int err;
1588+
1589+ buf[0] = 0;
1590+ if (i == OP_SUBSCRIBE_PATTERN)
1591+ snprintf (tmp, sizeof (tmp), _("Subscribe pattern: "));
1592+ else
1593+ snprintf (tmp, sizeof (tmp), _("Unsubscribe pattern: "));
1594+ if (mutt_get_field (tmp, buf, sizeof (buf), 0) != 0 || !buf[0])
1595+ {
1596+ FREE (&rx);
1597+ break;
1598+ }
1599+
1600+ if ((err = REGCOMP (rx, s, REG_NOSUB)) != 0)
1601+ {
1602+ regerror (err, rx, buf, sizeof (buf));
1603+ regfree (rx);
1604+ safe_free ((void **) &rx);
1605+ mutt_error ("%s", buf);
1606+ break;
1607+ }
1608+ menu->redraw = REDRAW_FULL;
1609+ j = 0;
1610+ }
1611+ else if (!state.entrylen)
1612+ {
1613+ mutt_error _("No newsgroups match the mask");
1614+ break;
1615+ }
1616+
1617+ for ( ; j < state.entrylen; j++)
1618+ {
1619+ struct folder_file *f = &state.entry[j];
1620+
1621+ if (i == OP_BROWSER_SUBSCRIBE || i == OP_BROWSER_UNSUBSCRIBE ||
1622+ regexec (rx, f->name, 0, NULL, 0) == 0)
1623+ {
1624+ if (i == OP_BROWSER_SUBSCRIBE || i == OP_SUBSCRIBE_PATTERN)
1625+ nd = mutt_newsgroup_subscribe (news, f->name);
1626+ else
1627+ nd = mutt_newsgroup_unsubscribe (news, f->name);
1628+/* if (nd)
1629+ {
1630+ FOLDER folder;
1631+ char buffer[_POSIX_PATH_MAX + SHORT_STRING];
1632+
1633+ folder.name = f->name;
1634+ folder.f = NULL;
1635+ folder.new = nd->new;
1636+ folder.nd = nd;
1637+ safe_free ((void **) &f->desc);
1638+ mutt_FormatString (buffer, sizeof (buffer), NONULL(GroupFormat),
1639+ newsgroup_format_str, (unsigned long) &folder,
1640+ M_FORMAT_ARROWCURSOR);
1641+ f->desc = safe_strdup (buffer);
1642+ } */
1643+ }
1644+ if (i == OP_BROWSER_SUBSCRIBE || i == OP_BROWSER_UNSUBSCRIBE)
1645+ {
1646+ if (menu->current + 1 < menu->max)
1647+ menu->current++;
1648+ menu->redraw = REDRAW_MOTION_RESYNCH;
1649+ break;
1650+ }
1651+ }
1652+ if (i == OP_SUBSCRIBE_PATTERN)
1653+ {
1654+ LIST *grouplist = NULL;
1655+
1656+ if (news)
1657+ grouplist = news->list;
1658+ for (; grouplist; grouplist = grouplist->next)
1659+ {
1660+ nd = (NNTP_DATA *) grouplist->data;
1661+ if (nd && nd->group && !nd->subscribed)
1662+ {
1663+ if (regexec (rx, nd->group, 0, NULL, 0) == 0)
1664+ {
1665+ mutt_newsgroup_subscribe (news, nd->group);
1666+ add_folder (menu, &state, nd->group, NULL, nd, nd->new);
1667+ }
1668+ }
1669+ }
1670+ init_menu (&state, menu, title, sizeof (title), buffy, 1);
1671+ }
1672+ mutt_newsrc_update (news);
1673+ nntp_clear_cacheindex (news);
1674+ if (i != OP_BROWSER_SUBSCRIBE && i != OP_BROWSER_UNSUBSCRIBE)
1675+ regfree (rx);
1676+ safe_free ((void **) &rx);
1677+ }
1678+#ifdef USE_IMAP
1679+ else
1680+#endif /* USE_IMAP && USE_NNTP */
1681+#endif /* USE_NNTP */
1682+#ifdef USE_IMAP
1683+ {
1684+ if (i == OP_BROWSER_SUBSCRIBE)
1685+ imap_subscribe (state.entry[menu->current].name, 1);
1686+ else
1687+ imap_subscribe (state.entry[menu->current].name, 0);
1688+ }
1689+#endif /* USE_IMAP */
1690 }
1691 }
1692
1693diff -uNr mutt-1.4.orig/browser.h mutt-1.4/browser.h
1694--- mutt-1.4.orig/browser.h Mon Aug 21 17:42:20 2000
1695+++ mutt-1.4/browser.h Sun Nov 3 21:57:20 2002
1696@@ -20,6 +20,10 @@
1697 #ifndef _BROWSER_H
1698 #define _BROWSER_H 1
1699
1700+#ifdef USE_NNTP
1701+#include "nntp.h"
1702+#endif
1703+
1704 struct folder_file
1705 {
1706 mode_t mode;
1707@@ -38,14 +42,17 @@
1708 unsigned selectable : 1;
1709 unsigned inferiors : 1;
1710 #endif
1711+#ifdef USE_NNTP
1712+ NNTP_DATA *nd;
1713+#endif
1714 unsigned tagged : 1;
1715 };
1716
1717 struct browser_state
1718 {
1719 struct folder_file *entry;
1720- short entrylen; /* number of real entries */
1721- short entrymax; /* max entry */
1722+ unsigned int entrylen; /* number of real entries */
1723+ unsigned int entrymax; /* max entry */
1724 #ifdef USE_IMAP
1725 short imap_browse;
1726 char *folder;
1727diff -uNr mutt-1.4.orig/buffy.c mutt-1.4/buffy.c
1728--- mutt-1.4.orig/buffy.c Mon Mar 25 12:30:08 2002
1729+++ mutt-1.4/buffy.c Sun Nov 3 21:57:20 2002
1730@@ -257,6 +257,9 @@
1731 #ifdef USE_POP
1732 if (!Context || Context->magic != M_POP)
1733 #endif
1734+#ifdef USE_NNTP
1735+ if (!Context || Context->magic != M_NNTP)
1736+#endif
1737 /* check device ID and serial number instead of comparing paths */
1738 if (!Context || !Context->path || stat (Context->path, &contex_sb) != 0)
1739 {
1740@@ -278,6 +281,11 @@
1741 tmp->magic = M_POP;
1742 else
1743 #endif
1744+#ifdef USE_NNTP
1745+ if ((tmp->magic == M_NNTP) || mx_is_nntp (tmp->path))
1746+ tmp->magic = M_NNTP;
1747+ else
1748+#endif
1749 if (stat (tmp->path, &sb) != 0 || sb.st_size == 0 ||
1750 (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0))
1751 {
1752@@ -294,25 +302,21 @@
1753 /* check to see if the folder is the currently selected folder
1754 * before polling */
1755 if (!Context || !Context->path ||
1756-#if defined USE_IMAP || defined USE_POP
1757- ((
1758+ (
1759+ (0
1760 #ifdef USE_IMAP
1761- tmp->magic == M_IMAP
1762+ || tmp->magic == M_IMAP
1763 #endif
1764 #ifdef USE_POP
1765-#ifdef USE_IMAP
1766- ||
1767-#endif
1768- tmp->magic == M_POP
1769+ || tmp->magic == M_POP
1770 #endif
1771- ) ? mutt_strcmp (tmp->path, Context->path) :
1772+#ifdef USE_NNTP
1773+ || tmp->magic == M_NNTP
1774 #endif
1775- (sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino)
1776-#if defined USE_IMAP || defined USE_POP
1777- )
1778-#endif
1779- )
1780-
1781+ ) ? mutt_strcmp (tmp->path, Context->path) :
1782+ (sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino)
1783+ )
1784+ )
1785 {
1786 switch (tmp->magic)
1787 {
1788@@ -380,6 +384,11 @@
1789 case M_POP:
1790 break;
1791 #endif
1792+
1793+#ifdef USE_NNTP
1794+ case M_NNTP:
1795+ break;
1796+#endif
1797 }
1798 }
1799 #ifdef BUFFY_SIZE
1800diff -uNr mutt-1.4.orig/commands.c mutt-1.4/commands.c
1801--- mutt-1.4.orig/commands.c Sun Nov 3 21:42:52 2002
1802+++ mutt-1.4/commands.c Sun Nov 3 21:57:20 2002
1803@@ -26,6 +26,7 @@
1804 #include "copy.h"
1805 #include "mx.h"
1806 #include "pager.h"
1807+#include "rfc1524.h"
1808 #include <sys/types.h>
1809 #include <sys/stat.h>
1810 #include <fcntl.h>
1811@@ -791,6 +792,131 @@
1812 return -1;
1813 }
1814
1815+int mutt_update_list_file (char *filename, char *section, char *key, char *line)
1816+{
1817+ FILE *ifp;
1818+ FILE *ofp;
1819+ char buf[HUGE_STRING];
1820+ char oldfile[_POSIX_PATH_MAX];
1821+ char *c;
1822+ int ext = 0, done = 0, r = 0;
1823+
1824+ snprintf (oldfile, sizeof(oldfile), "%s.bak", filename);
1825+ dprint (1, (debugfile, "Renaming %s to %s\n", filename, oldfile));
1826+
1827+ /* if file not exist, create it */
1828+ if ((ifp = safe_fopen (filename, "a")))
1829+ fclose (ifp);
1830+ if (_mutt_rename_file (filename, oldfile, 1))
1831+ {
1832+ mutt_perror _("Unable to create backup file");
1833+ return (-1);
1834+ }
1835+ dprint (1, (debugfile, "Opening %s\n", oldfile));
1836+ if (!(ifp = safe_fopen (oldfile, "r")))
1837+ {
1838+ mutt_perror _("Unable to open backup file for reading");
1839+ return (-1);
1840+ }
1841+ dprint (1, (debugfile, "Opening %s\n", filename));
1842+ if (!(ofp = fopen (filename, "w")))
1843+ {
1844+ fclose (ifp);
1845+ mutt_perror _("Unable to open new file for writing");
1846+ return (-1);
1847+ }
1848+ if (mx_lock_file (filename, fileno (ofp), 1, 0, 1))
1849+ {
1850+ fclose (ofp);
1851+ fclose (ifp);
1852+ mutt_error (_("Unable to lock %s, old file saved as %s"), filename, oldfile);
1853+ return (-1);
1854+ }
1855+
1856+ if (section)
1857+ {
1858+ while (r != EOF && !done && fgets (buf, sizeof (buf), ifp))
1859+ {
1860+ r = fputs (buf, ofp);
1861+ c = buf;
1862+ while (*c && *c != '\n') c++;
1863+ c[0] = 0; /* strip EOL */
1864+ if (!strncmp (buf, "#: ", 3) && !mutt_strcasecmp (buf+3, section))
1865+ done++;
1866+ }
1867+ if (r != EOF && !done)
1868+ {
1869+ snprintf (buf, sizeof(buf), "#: %s\n", section);
1870+ r = fputs (buf, ofp);
1871+ }
1872+ done = 0;
1873+ }
1874+
1875+ while (r != EOF && fgets (buf, sizeof (buf), ifp))
1876+ {
1877+ if (ext)
1878+ {
1879+ c = buf;
1880+ while (*c && (*c != '\r') && (*c != '\n')) c++;
1881+ c--;
1882+ if (*c != '\\') ext = 0;
1883+ }
1884+ else if ((section && !strncmp (buf, "#: ", 3)))
1885+ {
1886+ if (!done && line)
1887+ {
1888+ fputs (line, ofp);
1889+ fputc ('\n', ofp);
1890+ }
1891+ r = fputs (buf, ofp);
1892+ done++;
1893+ break;
1894+ }
1895+ else if (key && !strncmp (buf, key, strlen(key)) &&
1896+ (!*key || buf[strlen(key)] == ' '))
1897+ {
1898+ c = buf;
1899+ ext = 0;
1900+ while (*c && (*c != '\r') && (*c != '\n')) c++;
1901+ c--;
1902+ if (*c == '\\') ext = 1;
1903+ if (!done && line)
1904+ {
1905+ r = fputs (line, ofp);
1906+ if (*key)
1907+ r = fputc ('\n', ofp);
1908+ done++;
1909+ }
1910+ }
1911+ else
1912+ {
1913+ r = fputs (buf, ofp);
1914+ }
1915+ }
1916+
1917+ while (r != EOF && fgets (buf, sizeof (buf), ifp))
1918+ r = fputs (buf, ofp);
1919+
1920+ /* If there wasn't a line to replace, put it on the end of the file */
1921+ if (r != EOF && !done && line)
1922+ {
1923+ fputs (line, ofp);
1924+ r = fputc ('\n', ofp);
1925+ }
1926+ mx_unlock_file (filename, fileno (ofp), 0);
1927+ fclose (ofp);
1928+ fclose (ifp);
1929+ if (r != EOF)
1930+ {
1931+ unlink (oldfile);
1932+ return 0;
1933+ }
1934+ unlink (filename);
1935+ mutt_error (_("Cannot write new %s, old file saved as %s"), filename,
1936+ oldfile);
1937+ return (-1);
1938+}
1939+
1940
1941 void mutt_version (void)
1942 {
1943diff -uNr mutt-1.4.orig/complete.c mutt-1.4/complete.c
1944--- mutt-1.4.orig/complete.c Wed Nov 7 11:22:08 2001
1945+++ mutt-1.4/complete.c Sun Nov 3 21:57:20 2002
1946@@ -21,6 +21,9 @@
1947 #include "mailbox.h"
1948 #include "imap.h"
1949 #endif
1950+#ifdef USE_NNTP
1951+#include "nntp.h"
1952+#endif
1953
1954 #include <dirent.h>
1955 #include <string.h>
1956@@ -44,9 +47,71 @@
1957 char filepart[_POSIX_PATH_MAX];
1958 #ifdef USE_IMAP
1959 char imap_path[LONG_STRING];
1960+#endif
1961
1962 dprint (2, (debugfile, "mutt_complete: completing %s\n", s));
1963
1964+#ifdef USE_NNTP
1965+ if (option (OPTNEWS))
1966+ {
1967+ LIST *l = CurrentNewsSrv->list;
1968+
1969+ strfcpy (filepart, s, sizeof (filepart));
1970+
1971+ /*
1972+ * special case to handle when there is no filepart yet.
1973+ * find the first subscribed newsgroup
1974+ */
1975+ if ((len = mutt_strlen (filepart)) == 0)
1976+ {
1977+ for (; l; l = l->next)
1978+ {
1979+ NNTP_DATA *data = (NNTP_DATA *)l->data;
1980+
1981+ if (data && data->subscribed)
1982+ {
1983+ strfcpy (filepart, data->group, sizeof (filepart));
1984+ init++;
1985+ l = l->next;
1986+ break;
1987+ }
1988+ }
1989+ }
1990+
1991+ for (; l; l = l->next)
1992+ {
1993+ NNTP_DATA *data = (NNTP_DATA *)l->data;
1994+
1995+ if (data && data->subscribed &&
1996+ mutt_strncmp (data->group, filepart, len) == 0)
1997+ {
1998+ if (init)
1999+ {
2000+ for (i = 0; filepart[i] && data->group[i]; i++)
2001+ {
2002+ if (filepart[i] != data->group[i])
2003+ {
2004+ filepart[i] = 0;
2005+ break;
2006+ }
2007+ }
2008+ filepart[i] = 0;
2009+ }
2010+ else
2011+ {
2012+ strfcpy (filepart, data->group, sizeof (filepart));
2013+ init = 1;
2014+ }
2015+ }
2016+ }
2017+
2018+ strcpy (s, filepart);
2019+
2020+ return (init ? 0 : -1);
2021+ }
2022+#endif
2023+
2024+#ifdef USE_IMAP
2025 /* we can use '/' as a delimiter, imap_complete rewrites it */
2026 if (*s == '=' || *s == '+' || *s == '!')
2027 {
2028diff -uNr mutt-1.4.orig/compose.c mutt-1.4/compose.c
2029--- mutt-1.4.orig/compose.c Sun Nov 3 21:42:52 2002
2030+++ mutt-1.4/compose.c Sun Nov 3 21:57:20 2002
2031@@ -26,10 +26,15 @@
2032 #include "mailbox.h"
2033 #include "sort.h"
2034 #include "charset.h"
2035+#include "mx.h"
2036
2037 #ifdef MIXMASTER
2038 #include "remailer.h"
2039 #endif
2040+
2041+#ifdef USE_NNTP
2042+#include "nntp.h"
2043+#endif
2044
2045 #include <errno.h>
2046 #include <string.h>
2047@@ -63,12 +68,18 @@
2048 HDR_PGPSIGINFO,
2049 #endif
2050
2051+#ifdef USE_NNTP
2052+ HDR_NEWSGROUPS,
2053+ HDR_FOLLOWUPTO,
2054+ HDR_XCOMMENTTO,
2055+#endif
2056+
2057
2058 HDR_ATTACH = (HDR_FCC + 5) /* where to start printing the attachments */
2059 };
2060
2061-#define HDR_XOFFSET 10
2062-#define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */
2063+#define HDR_XOFFSET 14
2064+#define TITLE_FMT "%14s" /* Used for Prompts, which are ASCII */
2065 #define W (COLS - HDR_XOFFSET)
2066
2067 static char *Prompts[] =
2068@@ -80,6 +91,15 @@
2069 "Subject: ",
2070 "Reply-To: ",
2071 "Fcc: "
2072+#ifdef HAVE_PGP
2073+ ,""
2074+ ,""
2075+#endif
2076+#ifdef USE_NNTP
2077+ ,"Newsgroups: "
2078+ ,"Followup-To: "
2079+ ,"X-Comment-To: "
2080+#endif
2081 };
2082
2083 static struct mapping_t ComposeHelp[] = {
2084@@ -94,6 +114,19 @@
2085 { NULL }
2086 };
2087
2088+#ifdef USE_NNTP
2089+static struct mapping_t ComposeNewsHelp[] = {
2090+ { N_("Send"), OP_COMPOSE_SEND_MESSAGE },
2091+ { N_("Abort"), OP_EXIT },
2092+ { "Newsgroups", OP_COMPOSE_EDIT_NEWSGROUPS },
2093+ { "Subj", OP_COMPOSE_EDIT_SUBJECT },
2094+ { N_("Attach file"), OP_COMPOSE_ATTACH_FILE },
2095+ { N_("Descrip"), OP_COMPOSE_EDIT_DESCRIPTION },
2096+ { N_("Help"), OP_HELP },
2097+ { NULL }
2098+};
2099+#endif
2100+
2101 static void snd_entry (char *b, size_t blen, MUTTMENU *menu, int num)
2102 {
2103 mutt_FormatString (b, blen, NONULL (AttachFormat), mutt_attach_fmt,
2104@@ -108,7 +141,7 @@
2105
2106 static void redraw_pgp_lines (int pgp)
2107 {
2108- mvaddstr (HDR_PGP, 0, " PGP: ");
2109+ mvaddstr (HDR_PGP, 0, " PGP: ");
2110 if ((pgp & (PGPENCRYPT | PGPSIGN)) == (PGPENCRYPT | PGPSIGN))
2111 addstr (_("Sign, Encrypt"));
2112 else if (pgp & PGPENCRYPT)
2113@@ -122,7 +155,7 @@
2114 move (HDR_PGPSIGINFO, 0);
2115 clrtoeol ();
2116 if (pgp & PGPSIGN)
2117- printw ("%s%s", _(" sign as: "), PgpSignAs ? PgpSignAs : _("<default>"));
2118+ printw (" %s%s", _(" sign as: "), PgpSignAs ? PgpSignAs : _("<default>"));
2119 }
2120
2121 static int pgp_send_menu (int bits, int *redraw)
2122@@ -258,9 +291,28 @@
2123 static void draw_envelope (HEADER *msg, char *fcc)
2124 {
2125 draw_envelope_addr (HDR_FROM, msg->env->from);
2126+#ifdef USE_NNTP
2127+ if (!option (OPTNEWSSEND))
2128+ {
2129+#endif
2130 draw_envelope_addr (HDR_TO, msg->env->to);
2131 draw_envelope_addr (HDR_CC, msg->env->cc);
2132 draw_envelope_addr (HDR_BCC, msg->env->bcc);
2133+#ifdef USE_NNTP
2134+ }
2135+ else
2136+ {
2137+ mvprintw (HDR_TO, 0, TITLE_FMT , Prompts[HDR_NEWSGROUPS - 1]);
2138+ mutt_paddstr (W, NONULL (msg->env->newsgroups));
2139+ mvprintw (HDR_CC, 0, TITLE_FMT , Prompts[HDR_FOLLOWUPTO - 1]);
2140+ mutt_paddstr (W, NONULL (msg->env->followup_to));
2141+ if (option (OPTXCOMMENTTO))
2142+ {
2143+ mvprintw (HDR_BCC, 0, TITLE_FMT , Prompts[HDR_XCOMMENTTO - 1]);
2144+ mutt_paddstr (W, NONULL (msg->env->x_comment_to));
2145+ }
2146+ }
2147+#endif
2148 mvprintw (HDR_SUBJECT, 0, TITLE_FMT, Prompts[HDR_SUBJECT - 1]);
2149 mutt_paddstr (W, NONULL (msg->env->subject));
2150 draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to);
2151@@ -506,6 +558,12 @@
2152 /* Sort, SortAux could be changed in mutt_index_menu() */
2153 int oldSort, oldSortAux;
2154 struct stat st;
2155+#ifdef USE_NNTP
2156+ int news = 0; /* is it a news article ? */
2157+
2158+ if (option (OPTNEWSSEND))
2159+ news++;
2160+#endif
2161
2162 mutt_attach_init (msg->content);
2163 idx = mutt_gen_attach_list (msg->content, -1, idx, &idxlen, &idxmax, 0, 1);
2164@@ -517,10 +575,18 @@
2165 menu->make_entry = snd_entry;
2166 menu->tag = mutt_tag_attach;
2167 menu->data = idx;
2168+#ifdef USE_NNTP
2169+ if (news)
2170+ menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeNewsHelp);
2171+ else
2172+#endif
2173 menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeHelp);
2174
2175 while (loop)
2176 {
2177+#ifdef USE_NNTP
2178+ unset_option (OPTNEWS); /* for any case */
2179+#endif
2180 switch (op = mutt_menuLoop (menu))
2181 {
2182 case OP_REDRAW:
2183@@ -532,14 +598,81 @@
2184 menu->redraw = edit_address_list (HDR_FROM, &msg->env->from);
2185 break;
2186 case OP_COMPOSE_EDIT_TO:
2187- menu->redraw = edit_address_list (HDR_TO, &msg->env->to);
2188+#ifdef USE_NNTP
2189+ if (!news)
2190+#endif
2191+ menu->redraw = edit_address_list (HDR_TO, &msg->env->to);
2192 break;
2193 case OP_COMPOSE_EDIT_BCC:
2194- menu->redraw = edit_address_list (HDR_BCC, &msg->env->bcc);
2195+#ifdef USE_NNTP
2196+ if (!news)
2197+#endif
2198+ menu->redraw = edit_address_list (HDR_BCC, &msg->env->bcc);
2199 break;
2200 case OP_COMPOSE_EDIT_CC:
2201- menu->redraw = edit_address_list (HDR_CC, &msg->env->cc);
2202+#ifdef USE_NNTP
2203+ if (!news)
2204+#endif
2205+ menu->redraw = edit_address_list (HDR_CC, &msg->env->cc);
2206+ break;
2207+#ifdef USE_NNTP
2208+ case OP_COMPOSE_EDIT_NEWSGROUPS:
2209+ if (news)
2210+ {
2211+ if (msg->env->newsgroups)
2212+ strfcpy (buf, msg->env->newsgroups, sizeof (buf));
2213+ else
2214+ buf[0] = 0;
2215+ if (mutt_get_field ("Newsgroups: ", buf, sizeof (buf), 0) == 0 && buf[0])
2216+ {
2217+ safe_free ((void **) &msg->env->newsgroups);
2218+ mutt_remove_trailing_ws (buf);
2219+ msg->env->newsgroups = safe_strdup (mutt_skip_whitespace (buf));
2220+ move (HDR_TO, HDR_XOFFSET);
2221+ clrtoeol ();
2222+ if (msg->env->newsgroups)
2223+ printw ("%-*.*s", W, W, msg->env->newsgroups);
2224+ }
2225+ }
2226+ break;
2227+
2228+ case OP_COMPOSE_EDIT_FOLLOWUP_TO:
2229+ if (news)
2230+ {
2231+ buf[0] = 0;
2232+ if (msg->env->followup_to)
2233+ strfcpy (buf, msg->env->followup_to, sizeof (buf));
2234+ if (mutt_get_field ("Followup-To: ", buf, sizeof (buf), 0) == 0 && buf[0])
2235+ {
2236+ safe_free ((void **) &msg->env->followup_to);
2237+ mutt_remove_trailing_ws (buf);
2238+ msg->env->followup_to = safe_strdup (mutt_skip_whitespace (buf));
2239+ move (HDR_CC, HDR_XOFFSET);
2240+ clrtoeol();
2241+ if (msg->env->followup_to)
2242+ printw ("%-*.*s", W, W, msg->env->followup_to);
2243+ }
2244+ }
2245 break;
2246+
2247+ case OP_COMPOSE_EDIT_X_COMMENT_TO:
2248+ if (news && option (OPTXCOMMENTTO))
2249+ {
2250+ buf[0] = 0;
2251+ if (msg->env->x_comment_to)
2252+ strfcpy (buf, msg->env->x_comment_to, sizeof (buf));
2253+ if (mutt_get_field ("X-Comment-To: ", buf, sizeof (buf), 0) == 0 && buf[0])
2254+ {
2255+ safe_free ((void **) &msg->env->x_comment_to);
2256+ msg->env->x_comment_to = safe_strdup (buf);
2257+ move (HDR_BCC, HDR_XOFFSET);
2258+ clrtoeol();
2259+ if (msg->env->x_comment_to)
2260+ printw ("%-*.*s", W, W, msg->env->x_comment_to);
2261+ }
2262+ }
2263+ break;
2264+#endif
2265 case OP_COMPOSE_EDIT_SUBJECT:
2266 if (msg->env->subject)
2267 strfcpy (buf, msg->env->subject, sizeof (buf));
2268@@ -695,6 +828,9 @@
2269 break;
2270
2271 case OP_COMPOSE_ATTACH_MESSAGE:
2272+#ifdef USE_NNTP
2273+ case OP_COMPOSE_ATTACH_NEWS_MESSAGE:
2274+#endif
2275 {
2276 char *prompt;
2277 HEADER *h;
2278@@ -702,7 +838,22 @@
2279 fname[0] = 0;
2280 prompt = _("Open mailbox to attach message from");
2281
2282+#ifdef USE_NNTP
2283+ unset_option (OPTNEWS);
2284+ if (op == OP_COMPOSE_ATTACH_NEWS_MESSAGE)
2285+ {
2286+ if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)))
2287+ break;
2288+
2289+ prompt = _("Open newsgroup to attach message from");
2290+ set_option (OPTNEWS);
2291+ }
2292+#endif
2293+
2294 if (Context)
2295+#ifdef USE_NNTP
2296+ if ((op == OP_COMPOSE_ATTACH_MESSAGE) ^ (Context->magic == M_NNTP))
2297+#endif
2298 {
2299 strfcpy (fname, NONULL (Context->path), sizeof (fname));
2300 mutt_pretty_mailbox (fname);
2301@@ -711,6 +862,11 @@
2302 if (mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, 1) == -1 || !fname[0])
2303 break;
2304
2305+#ifdef USE_NNTP
2306+ if (option (OPTNEWS))
2307+ nntp_expand_path (fname, sizeof (fname), &CurrentNewsSrv->conn->account);
2308+ else
2309+#endif
2310 mutt_expand_path (fname, sizeof (fname));
2311 #ifdef USE_IMAP
2312 if (!mx_is_imap (fname))
2313@@ -718,6 +874,9 @@
2314 #ifdef USE_POP
2315 if (!mx_is_pop (fname))
2316 #endif
2317+#ifdef USE_NNTP
2318+ if (!mx_is_nntp (fname) && !option (OPTNEWS))
2319+#endif
2320 /* check to make sure the file exists and is readable */
2321 if (access (fname, R_OK) == -1)
2322 {
9ac83ccd
JB
2323diff -uNr mutt-1.4.orig/configure.in mutt-1.4/configure.in
2324--- mutt-1.4.orig/configure.in Sun Nov 3 21:42:52 2002
2325+++ mutt-1.4/configure.in Sun Nov 3 21:57:20 2002
2326@@ -457,6 +457,14 @@
2327 ])
2328 AM_CONDITIONAL(BUILD_IMAP, test x$need_imap = xyes)
1b5dcea5 2329
9ac83ccd
JB
2330+AC_ARG_ENABLE(nntp, [ --enable-nntp Enable NNTP support],
2331+[ if test x$enableval = xyes ; then
2332+ AC_DEFINE(USE_NNTP)
2333+ MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS nntp.o newsrc.o"
2334+ need_socket="yes"
2335+ fi
2336+])
2337+
2338 dnl -- end socket dependencies --
1b5dcea5 2339
9ac83ccd
JB
2340 if test "$need_socket" = "yes"
2341diff -uNr mutt-1.4.orig/curs_main.c mutt-1.4/curs_main.c
2342--- mutt-1.4.orig/curs_main.c Sun Nov 3 21:42:52 2002
2343+++ mutt-1.4/curs_main.c Sun Nov 3 21:57:20 2002
2344@@ -18,6 +18,7 @@
1b5dcea5 2345
9ac83ccd
JB
2346 #include "mutt.h"
2347 #include "mutt_curses.h"
2348+#include "mx.h"
2349 #include "mutt_menu.h"
2350 #include "mailbox.h"
2351 #include "mapping.h"
2352@@ -33,6 +34,10 @@
2353 #include "imap.h"
2354 #endif
1b5dcea5 2355
9ac83ccd
JB
2356+#ifdef USE_NNTP
2357+#include "nntp.h"
2358+#endif
2359+
1b5dcea5 2360
1b5dcea5 2361
9ac83ccd
JB
2362 #ifdef HAVE_PGP
2363@@ -405,12 +410,27 @@
2364 { NULL }
2365 };
1b5dcea5 2366
9ac83ccd
JB
2367+#ifdef USE_NNTP
2368+struct mapping_t IndexNewsHelp[] = {
2369+ { N_("Quit"), OP_QUIT },
2370+ { N_("Del"), OP_DELETE },
2371+ { N_("Undel"), OP_UNDELETE },
2372+ { N_("Save"), OP_SAVE },
2373+ { N_("Post"), OP_POST },
2374+ { N_("Followup"), OP_FOLLOWUP },
2375+ { N_("Catchup"), OP_CATCHUP },
2376+ { N_("Help"), OP_HELP },
2377+ { NULL }
2378+};
2379+#endif
1b5dcea5 2380+
9ac83ccd
JB
2381 /* This function handles the message index window as well as commands returned
2382 * from the pager (MENU_PAGER).
2383 */
2384 int mutt_index_menu (void)
2385 {
2386 char buf[LONG_STRING], helpstr[SHORT_STRING];
2387+ int flags;
2388 int op = OP_NULL;
2389 int done = 0; /* controls when to exit the "event" loop */
2390 int i = 0, j;
2391@@ -432,7 +452,11 @@
2392 menu->make_entry = index_make_entry;
2393 menu->color = index_color;
2394 menu->current = ci_first_message ();
2395- menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN, IndexHelp);
2396+ menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN,
2397+#ifdef USE_NNTP
2398+ (Context && (Context->magic == M_NNTP)) ? IndexNewsHelp :
2399+#endif
2400+ IndexHelp);
2401
2402 if (!attach_msg)
2403 mutt_buffy_check(1); /* force the buffy check after we enter the folder */
2404@@ -633,6 +657,9 @@
2405 mutt_curs_set (1); /* fallback from the pager */
2406 }
1b5dcea5 2407
9ac83ccd
JB
2408+#ifdef USE_NNTP
2409+ unset_option (OPTNEWS); /* for any case */
2410+#endif
2411 switch (op)
2412 {
1b5dcea5 2413
9ac83ccd
JB
2414@@ -683,6 +710,120 @@
2415 menu_current_bottom (menu);
2416 break;
1b5dcea5 2417
9ac83ccd
JB
2418+#ifdef USE_NNTP
2419+ case OP_GET_MESSAGE:
2420+ case OP_GET_PARENT:
2421+ CHECK_MSGCOUNT;
2422+ if (Context->magic == M_NNTP)
2423+ {
2424+ HEADER *h;
1b5dcea5 2425+
9ac83ccd
JB
2426+ if (op == OP_GET_MESSAGE)
2427+ {
2428+ buf[0] = 0;
2429+ if (mutt_get_field (_("Enter Message-Id: "), buf, sizeof (buf), 0) != 0
2430+ || !buf[0])
2431+ break;
2432+ }
2433+ else
2434+ {
2435+ LIST *ref = CURHDR->env->references;
2436+ if (!ref)
2437+ {
2438+ mutt_error _("Article has no parent reference!");
2439+ break;
2440+ }
2441+ strfcpy (buf, ref->data, sizeof (buf));
2442+ }
2443+ if (!Context->id_hash)
2444+ Context->id_hash = mutt_make_id_hash (Context);
2445+ if ((h = hash_find (Context->id_hash, buf)))
2446+ {
2447+ if (h->virtual != -1)
2448+ {
2449+ menu->current = h->virtual;
2450+ menu->redraw = REDRAW_MOTION_RESYNCH;
2451+ }
2452+ else if (h->collapsed)
2453+ {
2454+ mutt_uncollapse_thread (Context, h);
2455+ mutt_set_virtual (Context);
2456+ menu->current = h->virtual;
2457+ menu->redraw = REDRAW_MOTION_RESYNCH;
2458+ }
2459+ else
2460+ mutt_error _("Message not visible in limited view.");
2461+ }
2462+ else
2463+ {
2464+ if (nntp_check_msgid (Context, buf) == 0)
2465+ {
2466+ h = Context->hdrs[Context->msgcount-1];
2467+ mutt_sort_headers (Context, 0);
2468+ menu->current = h->virtual;
2469+ menu->redraw = REDRAW_FULL;
2470+ }
2471+ else
2472+ mutt_error (_("Article %s not found on server"), buf);
2473+ }
2474+ }
2475+ break;
1b5dcea5 2476+
9ac83ccd
JB
2477+ case OP_GET_CHILDREN:
2478+ case OP_RECONSTRUCT_THREAD:
2479+ CHECK_MSGCOUNT;
2480+ if (Context->magic == M_NNTP)
2481+ {
2482+ HEADER *h;
2483+ int old = CURHDR->index, i;
1b5dcea5 2484+
9ac83ccd
JB
2485+ if (!CURHDR->env->message_id)
2486+ {
2487+ mutt_error _("No Message-Id. Unable to perform operation");
2488+ break;
2489+ }
1b5dcea5 2490+
9ac83ccd
JB
2491+ if (!Context->id_hash)
2492+ Context->id_hash = mutt_make_id_hash (Context);
2493+ strfcpy (buf, CURHDR->env->message_id, sizeof (buf));
1b5dcea5 2494+
9ac83ccd
JB
2495+ if (op == OP_RECONSTRUCT_THREAD)
2496+ {
2497+ LIST *ref = CURHDR->env->references;
2498+ while (ref)
2499+ {
2500+ nntp_check_msgid (Context, ref->data);
2501+ /* the last msgid in References is the root message */
2502+ if (!ref->next)
2503+ strfcpy (buf, ref->data, sizeof (buf));
2504+ ref = ref->next;
2505+ }
2506+ }
2507+ mutt_message _("Check for children of message...");
2508+ if (nntp_check_children (Context, buf) == 0)
2509+ {
2510+ mutt_sort_headers (Context, (op == OP_RECONSTRUCT_THREAD));
2511+ h = hash_find (Context->id_hash, buf);
2512+ /* if the root message was retrieved, move to it */
2513+ if (h)
2514+ menu->current = h->virtual;
2515+ else /* try to restore old position */
2516+ for (i = 0; i < Context->msgcount; i++)
2517+ if (Context->hdrs[i]->index == old)
2518+ {
2519+ menu->current = Context->hdrs[i]->virtual;
2520+ /* As an added courtesy, recenter the menu
2521+ * with the current entry at the middle of the screen */
2522+ menu_check_recenter (menu);
2523+ menu_current_middle (menu);
2524+ }
2525+ }
2526+ menu->redraw = REDRAW_FULL;
2527+ mutt_clear_error ();
2528+ }
2529+ break;
2530+#endif
1b5dcea5 2531+
9ac83ccd 2532 case OP_JUMP:
1b5dcea5 2533
9ac83ccd
JB
2534 CHECK_MSGCOUNT;
2535@@ -778,11 +919,33 @@
2536 break;
1b5dcea5 2537
9ac83ccd
JB
2538 case OP_MAIN_LIMIT:
2539+ case OP_TOGGLE_READ:
1b5dcea5 2540
9ac83ccd
JB
2541 CHECK_MSGCOUNT;
2542 menu->oldcurrent = (Context->vcount && menu->current >= 0 && menu->current < Context->vcount) ?
2543 CURHDR->index : -1;
2544- if (mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0)
2545+ if (op == OP_TOGGLE_READ)
2546+ {
2547+ char buf[LONG_STRING];
1b5dcea5 2548+
9ac83ccd
JB
2549+ if (!Context->pattern || strncmp (Context->pattern, "!~R!~D~s", 8) != 0)
2550+ {
2551+ snprintf (buf, sizeof (buf), "!~R!~D~s%s",
2552+ Context->pattern ? Context->pattern : ".*");
2553+ set_option (OPTHIDEREAD);
2554+ }
2555+ else
2556+ {
2557+ strfcpy (buf, Context->pattern + 8, sizeof(buf));
2558+ if (!*buf || strncmp (buf, ".*", 2) == 0)
2559+ snprintf (buf, sizeof(buf), "~A");
2560+ unset_option (OPTHIDEREAD);
2561+ }
2562+ FREE (&Context->pattern);
2563+ Context->pattern = safe_strdup (buf);
2564+ }
2565+ if ((op == OP_TOGGLE_READ && mutt_pattern_func (M_LIMIT, NULL) == 0) ||
2566+ mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0)
2567 {
2568 if (menu->oldcurrent >= 0)
2569 {
2570@@ -980,20 +1143,43 @@
2571 break;
1b5dcea5 2572
9ac83ccd
JB
2573 case OP_MAIN_CHANGE_FOLDER:
2574-
2575- if (attach_msg)
2576- op = OP_MAIN_CHANGE_FOLDER_READONLY;
2577-
2578- /* fallback to the readonly case */
2579-
2580 case OP_MAIN_CHANGE_FOLDER_READONLY:
2581+#ifdef USE_NNTP
2582+ case OP_MAIN_CHANGE_GROUP:
2583+ case OP_MAIN_CHANGE_GROUP_READONLY:
2584+#endif
2585+
2586+ if (attach_msg || option (OPTREADONLY) ||
2587+#ifdef USE_NNTP
2588+ op == OP_MAIN_CHANGE_GROUP_READONLY ||
2589+#endif
2590+ op == OP_MAIN_CHANGE_FOLDER_READONLY)
2591+ flags = M_READONLY;
2592+ else
2593+ flags = 0;
1b5dcea5 2594
9ac83ccd
JB
2595- if ((op == OP_MAIN_CHANGE_FOLDER_READONLY) || option (OPTREADONLY))
2596+ if (flags)
2597 cp = _("Open mailbox in read-only mode");
2598 else
2599 cp = _("Open mailbox");
1b5dcea5 2600
9ac83ccd
JB
2601 buf[0] = '\0';
2602+#ifdef USE_NNTP
2603+ unset_option (OPTNEWS);
2604+ if (op == OP_MAIN_CHANGE_GROUP ||
2605+ op == OP_MAIN_CHANGE_GROUP_READONLY)
2606+ {
2607+ set_option (OPTNEWS);
2608+ if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)))
2609+ break;
2610+ if (flags)
2611+ cp = _("Open newsgroup in read-only mode");
2612+ else
2613+ cp = _("Open newsgroup");
2614+ nntp_buffy (buf);
2615+ }
2616+ else
2617+#endif
2618 mutt_buffy (buf, sizeof (buf));
1b5dcea5 2619
9ac83ccd
JB
2620 if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1)
2621@@ -1004,6 +1190,14 @@
2622 break;
2623 }
1b5dcea5 2624
9ac83ccd
JB
2625+#ifdef USE_NNTP
2626+ if (option (OPTNEWS))
2627+ {
2628+ unset_option (OPTNEWS);
2629+ nntp_expand_path (buf, sizeof (buf), &CurrentNewsSrv->conn->account);
2630+ }
2631+ else
2632+#endif
2633 mutt_expand_path (buf, sizeof (buf));
2634 if (mx_get_magic (buf) <= 0)
2635 {
2636@@ -1039,15 +1233,18 @@
2637
2638 mutt_folder_hook (buf);
1b5dcea5 2639
9ac83ccd
JB
2640- if ((Context = mx_open_mailbox (buf,
2641- (option (OPTREADONLY) || op == OP_MAIN_CHANGE_FOLDER_READONLY) ?
2642- M_READONLY : 0, NULL)) != NULL)
2643+ if ((Context = mx_open_mailbox (buf, flags, NULL)) != NULL)
2644 {
2645 menu->current = ci_first_message ();
2646 }
2647 else
2648 menu->current = 0;
1b5dcea5 2649
9ac83ccd
JB
2650+#ifdef USE_NNTP
2651+ /* mutt_buffy_check() must be done with mail-reader mode! */
2652+ menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN,
2653+ (Context && (Context->magic == M_NNTP)) ? IndexNewsHelp : IndexHelp);
2654+#endif
2655 mutt_clear_error ();
2656 mutt_buffy_check(1); /* force the buffy check after we have changed
2657 the folder */
2658@@ -1422,6 +1619,15 @@
2659 }
2660 #endif
1b5dcea5 2661
9ac83ccd
JB
2662+#ifdef USE_NNTP
2663+ if (Context->magic == M_NNTP)
2664+ {
2665+ mutt_flushinp ();
2666+ mutt_error _("Can't change 'important' flag on NNTP server.");
2667+ break;
2668+ }
2669+#endif
2670+
2671 if (tag)
2672 {
2673 for (j = 0; j < Context->vcount; j++)
2674@@ -1767,6 +1973,17 @@
2675 }
2676 break;
1b5dcea5 2677
9ac83ccd
JB
2678+#ifdef USE_NNTP
2679+ case OP_CATCHUP:
2680+ if (Context && Context->magic == M_NNTP)
2681+ {
2682+ if (mutt_newsgroup_catchup (CurrentNewsSrv,
2683+ ((NNTP_DATA *)Context->data)->group))
2684+ menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
2685+ }
2686+ break;
2687+#endif
2688+
2689 case OP_DISPLAY_ADDRESS:
1b5dcea5 2690
9ac83ccd
JB
2691 CHECK_MSGCOUNT;
2692@@ -1801,6 +2018,15 @@
2693 }
2694 #endif
1b5dcea5 2695
9ac83ccd
JB
2696+#ifdef USE_NNTP
2697+ if (Context->magic == M_NNTP)
2698+ {
2699+ mutt_flushinp ();
2700+ mutt_error _("Can't edit message on newsserver.");
2701+ break;
2702+ }
2703+#endif
2704+
2705 mutt_edit_message (Context, tag ? NULL : CURHDR);
2706 menu->redraw = REDRAW_FULL;
1b5dcea5 2707
9ac83ccd
JB
2708@@ -1955,6 +2181,37 @@
2709
2710 menu->redraw = REDRAW_FULL;
2711 break;
2712+
2713+#ifdef USE_NNTP
2714+ case OP_POST:
2715+ case OP_FOLLOWUP:
2716+ case OP_FORWARD_TO_GROUP:
2717+
2718+ CHECK_ATTACH;
2719+ if (op != OP_FOLLOWUP || !CURHDR->env->followup_to ||
2720+ mutt_strcasecmp (CURHDR->env->followup_to, "poster") ||
2721+ query_quadoption (OPT_FOLLOWUPTOPOSTER,_("Reply by mail as poster prefers?")) != M_YES)
2722+ {
2723+ if (Context && Context->magic == M_NNTP &&
2724+ !((NNTP_DATA *)Context->data)->allowed &&
2725+ query_quadoption (OPT_TOMODERATED, _("Posting to this group not allowed, may be moderated. Continue?")) != M_YES)
2726+ break;
2727+ if (op == OP_POST)
2728+ ci_send_message (SENDNEWS, NULL, NULL, Context, NULL);
2729+ else
2730+ {
2731+ CHECK_MSGCOUNT;
2732+ if (op == OP_FOLLOWUP)
2733+ ci_send_message (SENDNEWS|SENDREPLY, NULL, NULL, Context,
2734+ tag ? NULL : CURHDR);
2735+ else
2736+ ci_send_message (SENDNEWS|SENDFORWARD, NULL, NULL, Context,
2737+ tag ? NULL : CURHDR);
2738+ }
2739+ menu->redraw = REDRAW_FULL;
2740+ break;
2741+ }
2742+#endif
2743
2744 case OP_REPLY:
1b5dcea5 2745
9ac83ccd
JB
2746@@ -2081,6 +2338,12 @@
2747 if (!attach_msg)
2748 imap_logout_all ();
2749 #endif
2750+#ifdef USE_NNTP
2751+ /* Close all open NNTP connections */
2752+ if (!attach_msg)
2753+ nntp_logout_all ();
2754+#endif
2755+
1b5dcea5 2756
9ac83ccd
JB
2757 mutt_menuDestroy (&menu);
2758 return (close);
2759diff -uNr mutt-1.4.orig/doc/manual.sgml mutt-1.4/doc/manual.sgml
2760--- mutt-1.4.orig/doc/manual.sgml Sun Nov 3 21:42:51 2002
2761+++ mutt-1.4/doc/manual.sgml Sun Nov 3 21:57:20 2002
2762@@ -723,6 +723,17 @@
1b5dcea5 2763
9ac83ccd 2764 See also the <ref id="postpone" name="&dollar;postpone"> quad-option.
1b5dcea5 2765
9ac83ccd
JB
2766+<sect1>Reading news via NNTP<label id="reading_news">
2767+<p>
1b5dcea5 2768+
9ac83ccd
JB
2769+If compiled with ``--enable-nntp'' option, Mutt can read news from newsserver
2770+via NNTP. You can open a newsgroup with function ``change-newsgroup''
2771+(default: i). Default newsserver can be obtained from <em/NNTPSERVER/
2772+environment variable. Like other news readers, info about subscribed
2773+newsgroups is saved in file by <ref id="newsrc" name="&dollar;newsrc">
2774+variable. Article headers are cached and can be loaded from file when
2775+newsgroup entered instead loading from newsserver.
1b5dcea5 2776+
9ac83ccd
JB
2777 <sect>Configuration
2778 <p>
1b5dcea5 2779
9ac83ccd
JB
2780@@ -3262,6 +3273,26 @@
2781 editing the body of an outgoing message.
1b5dcea5 2782
1b5dcea5 2783
9ac83ccd
JB
2784+<sect2>ask&lowbar;follow&lowbar;up<label id="ask_follow_up">
2785+<p>
2786+Type: boolean<newline>
2787+Default: no
1b5dcea5 2788+
9ac83ccd
JB
2789+<p>
2790+If set, Mutt will prompt you for follow-up groups before editing
2791+the body of an outgoing message.
1b5dcea5 2792+
1b5dcea5 2793+
9ac83ccd
JB
2794+<sect2>ask&lowbar;x&lowbar;comment&lowbar;to<label id="ask_x_comment_to">
2795+<p>
2796+Type: boolean<newline>
2797+Default: no
1b5dcea5 2798+
9ac83ccd
JB
2799+<p>
2800+If set, Mutt will prompt you for x-comment-to field before editing
2801+the body of an outgoing message.
1b5dcea5 2802+
1b5dcea5 2803+
9ac83ccd
JB
2804 <sect2>attach&lowbar;format<label id="attach_format">
2805 <p>
2806 Type: string<newline>
2807@@ -3379,6 +3410,16 @@
2808 bouncing messages. Postfix users may wish to unset this variable.
1b5dcea5 2809
1b5dcea5 2810
9ac83ccd
JB
2811+<sect2>catchup&lowbar;newsgroup<label id="catchup_newsgroup">
2812+<p>
2813+Type: quadoption<newline>
2814+Default: ask-yes
1b5dcea5 2815+
9ac83ccd
JB
2816+<p>
2817+If this variable is <em>set</em>, Mutt will mark all articles in newsgroup
2818+as read when you quit the newsgroup (catchup newsgroup).
2819+
2820+
2821 <sect2>charset<label id="charset">
2822 <p>
2823 Type: string<newline>
2824@@ -3781,6 +3822,18 @@
2825 resulting in two copies of the same email for you.
1b5dcea5 2826
1b5dcea5 2827
9ac83ccd
JB
2828+<sect2>followup&lowbar;to&lowbar;poster<label id="followup_to_poster">
2829+<p>
2830+Type: quadoption<newline>
2831+Default: ask-yes
1b5dcea5 2832+
9ac83ccd
JB
2833+<p>
2834+If this variable is <em>set</em> and the keyword &dquot;poster&dquot; is present in
2835+<em>Followup-To</em> header, follow-up to newsgroup function is not
2836+permitted. The message will be mailed to the submitter of the
2837+message via mail.
1b5dcea5 2838+
1b5dcea5 2839+
9ac83ccd
JB
2840 <sect2>force&lowbar;name<label id="force_name">
2841 <p>
2842 Type: boolean<newline>
2843@@ -3859,6 +3912,30 @@
2844 &dquot;Franklin&dquot; to &dquot;Franklin, Steve&dquot;.
1b5dcea5 2845
1b5dcea5 2846
9ac83ccd
JB
2847+<sect2>group&lowbar;index&lowbar;format<label id="group_index_format">
2848+<p>
2849+Type: string<newline>
2850+Default: &dquot;&percnt;4C &percnt;M&percnt;N &percnt;5s &percnt;-45.45f &percnt;d&dquot;
2851+
2852+<p>
2853+This variable allows you to customize the newsgroup browser display to
2854+your personal taste. This string is similar to ``<ref id="index_format" name="index&lowbar;format">'', but
2855+has its own set of printf()-like sequences:
2856+<p>
2857+
2858+<tscreen><verb>
2859+%C current newsgroup number
2860+%d description of newsgroup (becomes from server)
2861+%f newsgroup name
2862+%M - if newsgroup not allowed for direct post (moderated for example)
2863+%N N if newsgroup is new, u if unsubscribed, blank otherwise
2864+%n number of new articles in newsgroup
2865+%s number of unread articles in newsgroup
2866+%>X right justify the rest of the string and pad with character "X"
2867+%|X pad to the end of the line with character "X"
2868+
2869+</verb></tscreen>
2870+
2871 <sect2>hdrs<label id="hdrs">
2872 <p>
2873 Type: boolean<newline>
2874@@ -4203,6 +4280,7 @@
2875 <tag>&percnt;E </tag>number of messages in current thread
2876 <tag>&percnt;f </tag>entire From: line (address + real name)
2877 <tag>&percnt;F </tag>author name, or recipient name if the message is from you
2878+<tag>&percnt;g </tag>newsgroup name (if compiled with nntp support)
2879 <tag>&percnt;i </tag>message-id of the current message
2880 <tag>&percnt;l </tag>number of lines in the message
2881 <tag>&percnt;L </tag>If an address in the To or CC header field matches an address
2882@@ -4220,6 +4298,7 @@
2883 <tag>&percnt;T </tag>the appropriate character from the <ref id="to_chars" name="&dollar;to&lowbar;chars"> string
2884 <tag>&percnt;u </tag>user (login) name of the author
2885 <tag>&percnt;v </tag>first name of the author, or the recipient if the message is from you
2886+<tag>&percnt;W </tag>name of organization of author (`organization:' field)
2887 <tag>&percnt;y </tag>`x-label:' field, if present
2888 <tag>&percnt;Y </tag>`x-label' field, if present, and (1) not at part of a thread tree,
2889 (2) at the top of a thread, or (3) `x-label' is different from
2890@@ -4244,6 +4323,24 @@
2891 See also: ``<ref id="to_chars" name="&dollar;to&lowbar;chars">''.
1b5dcea5 2892
1b5dcea5 2893
9ac83ccd
JB
2894+<sect2>inews<label id="inews">
2895+<p>
2896+Type: path<newline>
2897+Default: &dquot;&dquot;
2898+
2899+<p>
2900+If set, specifies the program and arguments used to deliver news posted
2901+by Mutt. Otherwise, mutt posts article using current connection to
2902+news server. The following printf-style sequence is understood:
2903+<p>
2904+
2905+<tscreen><verb>
2906+%s newsserver name
2907+
2908+</verb></tscreen><p>
2909+Example: set inews=&dquot;/usr/local/bin/inews -hS&dquot;
2910+
2911+
2912 <sect2>ispell<label id="ispell">
2913 <p>
2914 Type: path<newline>
2915@@ -4491,6 +4588,17 @@
2916 be attached to the newly composed message if this option is set.
1b5dcea5 2917
1b5dcea5 2918
9ac83ccd
JB
2919+<sect2>mime&lowbar;subject<label id="mime_subject">
2920+<p>
2921+Type: boolean<newline>
2922+Default: yes
2923+
2924+<p>
2925+If <em>unset</em>, 8-bit ``subject:'' line in article header will not be
2926+encoded according to RFC2047 to base64. This is useful when message
2927+is Usenet article, because MIME for news is nonstandard feature.
2928+
2929+
2930 <sect2>mix&lowbar;entry&lowbar;format<label id="mix_entry_format">
2931 <p>
2932 Type: string<newline>
2933@@ -4544,6 +4652,112 @@
2934 escape sequences see the section on ``<ref id="index_format" name="&dollar;index&lowbar;format">''.
1b5dcea5 2935
1b5dcea5 2936
9ac83ccd
JB
2937+<sect2>news&lowbar;cache&lowbar;dir<label id="news_cache_dir">
2938+<p>
2939+Type: path<newline>
2940+Default: &dquot;&tilde;/.mutt&dquot;
1b5dcea5 2941+
9ac83ccd
JB
2942+<p>
2943+This variable pointing to directory where Mutt will save cached news
2944+articles headers in. If <em>unset</em>, headers will not be saved at all
2945+and will be reloaded each time when you enter to newsgroup.
1b5dcea5 2946+
1b5dcea5 2947+
9ac83ccd
JB
2948+<sect2>news&lowbar;server<label id="news_server">
2949+<p>
2950+Type: string<newline>
2951+Default: &dquot;&dquot;
1b5dcea5 2952+
9ac83ccd
JB
2953+<p>
2954+This variable specifies domain name or address of NNTP server. It
2955+defaults to the newsserver specified in the environment variable
2956+&dollar;NNTPSERVER or contained in the file /etc/nntpserver. You can also
2957+specify username and an alternative port for each newsserver, ie:
2958+<p>
2959+&lsqb;nntp&lsqb;s&rsqb;://&rsqb;&lsqb;username&lsqb;:password&rsqb;@&rsqb;newsserver&lsqb;:port&rsqb;
1b5dcea5 2960+
1b5dcea5 2961+
9ac83ccd
JB
2962+<sect2>newsrc<label id="newsrc">
2963+<p>
2964+Type: path<newline>
2965+Default: &dquot;&tilde;/.newsrc&dquot;
1b5dcea5 2966+
9ac83ccd
JB
2967+<p>
2968+The file, containing info about subscribed newsgroups - names and
2969+indexes of read articles. The following printf-style sequence
2970+is understood:
2971+<p>
1b5dcea5 2972+
9ac83ccd
JB
2973+<tscreen><verb>
2974+%s newsserver name
1b5dcea5 2975+
9ac83ccd 2976+</verb></tscreen>
1b5dcea5 2977+
9ac83ccd
JB
2978+<sect2>nntp&lowbar;context<label id="nntp_context">
2979+<p>
2980+Type: number<newline>
2981+Default: 1000
1b5dcea5 2982+
9ac83ccd
JB
2983+<p>
2984+This variable defines number of articles which will be in index when
2985+newsgroup entered. If active newsgroup have more articles than this
2986+number, oldest articles will be ignored. Also controls how many
2987+articles headers will be saved in cache when you quit newsgroup.
1b5dcea5 2988+
1b5dcea5 2989+
9ac83ccd
JB
2990+<sect2>nntp&lowbar;load&lowbar;description<label id="nntp_load_description">
2991+<p>
2992+Type: boolean<newline>
2993+Default: yes
1b5dcea5 2994+
9ac83ccd
JB
2995+<p>
2996+This variable controls whether or not descriptions for each newsgroup
2997+must be loaded when newsgroup is added to list (first time list
2998+loading or new newsgroup adding).
1b5dcea5 2999+
1b5dcea5 3000+
9ac83ccd
JB
3001+<sect2>nntp&lowbar;user<label id="nntp_user">
3002+<p>
3003+Type: string<newline>
3004+Default: &dquot;&dquot;
1b5dcea5 3005+
9ac83ccd
JB
3006+<p>
3007+Your login name on the NNTP server. If <em>unset</em> and NNTP server requires
3008+authentification, Mutt will prompt you for your account name when you
3009+connect to newsserver.
1b5dcea5 3010+
1b5dcea5 3011+
9ac83ccd
JB
3012+<sect2>nntp&lowbar;pass<label id="nntp_pass">
3013+<p>
3014+Type: string<newline>
3015+Default: &dquot;&dquot;
1b5dcea5 3016+
9ac83ccd
JB
3017+<p>
3018+Your password for NNTP account.
1b5dcea5 3019+
1b5dcea5 3020+
9ac83ccd
JB
3021+<sect2>nntp&lowbar;poll<label id="nntp_poll">
3022+<p>
3023+Type: number<newline>
3024+Default: 60
1b5dcea5 3025+
9ac83ccd
JB
3026+<p>
3027+The time in seconds until any operations on newsgroup except post new
3028+article will cause recheck for new news. If set to 0, Mutt will
3029+recheck newsgroup on each operation in index (stepping, read article,
3030+etc.).
1b5dcea5 3031+
1b5dcea5 3032+
9ac83ccd
JB
3033+<sect2>nntp&lowbar;reconnect<label id="nntp_reconnect">
3034+<p>
3035+Type: quadoption<newline>
3036+Default: ask-yes
1b5dcea5 3037+
9ac83ccd
JB
3038+<p>
3039+Controls whether or not Mutt will try to reconnect to newsserver when
3040+connection lost.
1b5dcea5 3041+
1b5dcea5 3042+
9ac83ccd
JB
3043 <sect2>pager<label id="pager">
3044 <p>
3045 Type: path<newline>
3046@@ -5240,6 +5454,18 @@
3047 string after the inclusion of a message which is being replied to.
1b5dcea5 3048
1b5dcea5 3049
9ac83ccd
JB
3050+<sect2>post&lowbar;moderated<label id="post_moderated">
3051+<p>
3052+Type: quadoption<newline>
3053+Default: ask-yes
1b5dcea5 3054+
9ac83ccd
JB
3055+<p>
3056+If set to <em>yes</em>, Mutt will post article to newsgroup that have
3057+not permissions to posting (e.g. moderated). <bf>Note:</bf> if newsserver
3058+does not support posting to that newsgroup or totally read-only, that
3059+posting will not have an effect.
1b5dcea5 3060+
1b5dcea5 3061+
9ac83ccd
JB
3062 <sect2>postpone<label id="postpone">
3063 <p>
3064 Type: quadoption<newline>
3065@@ -5723,6 +5949,38 @@
3066 shell from /etc/passwd is used.
1b5dcea5 3067
1b5dcea5 3068
9ac83ccd
JB
3069+<sect2>save&lowbar;unsubscribed<label id="save_unsubscribed">
3070+<p>
3071+Type: boolean<newline>
3072+Default: no
1b5dcea5 3073+
9ac83ccd
JB
3074+<p>
3075+When <em>set</em>, info about unsubscribed newsgroups will be saved into
3076+``newsrc'' file and into cache.
1b5dcea5 3077+
1b5dcea5 3078+
9ac83ccd
JB
3079+<sect2>show&lowbar;new&lowbar;news<label id="show_new_news">
3080+<p>
3081+Type: boolean<newline>
3082+Default: yes
1b5dcea5 3083+
9ac83ccd
JB
3084+<p>
3085+If <em>set</em>, newsserver will be asked for new newsgroups on entering
3086+the browser. Otherwise, it will be done only once for a newsserver.
3087+Also controls whether or not number of new articles of subscribed
3088+newsgroups will be then checked.
1b5dcea5 3089+
1b5dcea5 3090+
9ac83ccd
JB
3091+<sect2>show&lowbar;only&lowbar;unread<label id="show_only_unread">
3092+<p>
3093+Type: boolean<newline>
3094+Default: no
1b5dcea5 3095+
9ac83ccd
JB
3096+<p>
3097+If <em>set</em>, only subscribed newsgroups that contain unread articles
3098+will be displayed in browser.
1b5dcea5 3099+
1b5dcea5 3100+
9ac83ccd
JB
3101 <sect2>sig&lowbar;dashes<label id="sig_dashes">
3102 <p>
3103 Type: boolean<newline>
3104@@ -6189,6 +6447,17 @@
3105 command.
1b5dcea5 3106
1b5dcea5 3107
9ac83ccd
JB
3108+<sect2>use&lowbar;ipv6<label id="use_ipv6">
3109+<p>
3110+Type: boolean<newline>
3111+Default: yes
1b5dcea5 3112+
9ac83ccd
JB
3113+<p>
3114+When <em>set</em>, Mutt will look for IPv6 addresses of hosts it tries to
3115+contact. If this option is unset, Mutt will restrict itself to IPv4 addresses.
3116+Normally, the default should work.
3117+
3118+
3119 <sect2>user&lowbar;agent<label id="user_agent">
3120 <p>
3121 Type: boolean<newline>
3122@@ -6283,6 +6552,16 @@
3123 messages to be sent. Exim users may wish to use this.
1b5dcea5 3124
1b5dcea5 3125
9ac83ccd
JB
3126+<sect2>x&lowbar;comment&lowbar;to<label id="x_comment_to">
3127+<p>
3128+Type: boolean<newline>
3129+Default: no
1b5dcea5 3130+
9ac83ccd
JB
3131+<p>
3132+If <em>set</em>, Mutt will add ``X-Comment-To:'' field (that contains full
3133+name of original article author) to article that followuped to newsgroup.
1b5dcea5 3134+
1b5dcea5 3135+
9ac83ccd
JB
3136 <sect1>Functions<label id="functions">
3137 <p>
3138 The following is the list of available functions listed by the mapping
3139diff -uNr mutt-1.4.orig/doc/manual.sgml.head mutt-1.4/doc/manual.sgml.head
3140--- mutt-1.4.orig/doc/manual.sgml.head Sun Nov 3 21:42:52 2002
3141+++ mutt-1.4/doc/manual.sgml.head Sun Nov 3 21:57:20 2002
3142@@ -724,6 +724,17 @@
1b5dcea5 3143
9ac83ccd 3144 See also the <ref id="postpone" name="&dollar;postpone"> quad-option.
1b5dcea5 3145
9ac83ccd
JB
3146+<sect1>Reading news via NNTP<label id="reading_news">
3147+<p>
1b5dcea5 3148+
9ac83ccd
JB
3149+If compiled with ``--enable-nntp'' option, Mutt can read news from newsserver
3150+via NNTP. You can open a newsgroup with function ``change-newsgroup''
3151+(default: i). Default newsserver can be obtained from <em/NNTPSERVER/
3152+environment variable. Like other news readers, info about subscribed
3153+newsgroups is saved in file by <ref id="newsrc" name="&dollar;newsrc">
3154+variable. Article headers are cached and can be loaded from file when
3155+newsgroup entered instead loading from newsserver.
1b5dcea5 3156+
9ac83ccd
JB
3157 <sect>Configuration
3158 <p>
1b5dcea5 3159
1b5dcea5 3160diff -uNr mutt-1.4.orig/doc/mutt.man mutt-1.4/doc/mutt.man
3161--- mutt-1.4.orig/doc/mutt.man Thu Aug 30 14:55:37 2001
3162+++ mutt-1.4/doc/mutt.man Sun Nov 3 21:57:20 2002
3163@@ -24,8 +24,8 @@
3164 .SH SYNOPSIS
3165 .PP
3166 .B mutt
3167-[-nRyzZ]
3168-[-e \fIcmd\fP] [-F \fIfile\fP] [-m \fItype\fP] [-f \fIfile\fP]
3169+[-GnRyzZ]
3170+[-e \fIcmd\fP] [-F \fIfile\fP] [-g \fIserver\fP] [-m \fItype\fP] [-f \fIfile\fP]
3171 .PP
3172 .B mutt
3173 [-nx]
3174@@ -63,6 +63,10 @@
3175 Specify which mailbox to load.
3176 .IP "-F \fImuttrc\fP"
3177 Specify an initialization file to read instead of ~/.muttrc
3178+.IP "-g \fIserver\fP"
3179+Start Mutt with a listing of subscribed newsgroups at specified newsserver.
3180+.IP "-G"
3181+Start Mutt with a listing of subscribed newsgroups.
3182 .IP "-h"
3183 Display help.
3184 .IP "-H \fIdraft\fP"
3185diff -uNr mutt-1.4.orig/doc/muttrc.man mutt-1.4/doc/muttrc.man
3186--- mutt-1.4.orig/doc/muttrc.man Sun Nov 3 21:42:51 2002
3187+++ mutt-1.4/doc/muttrc.man Sun Nov 3 21:57:47 2002
3188@@ -257,7 +257,9 @@
3189 \fBpgp-hook\fP \fIpattern\fP \fIkey-id\fP
3190 The pgp-hook command provides a method by which you can
3191 specify the ID of the public key to be used when encrypting messages
3192-to a certain recipient.
3193+to a certain recipient. You may use multiple \fBpgp-hook\fPs with the
3194+same \fIpattern\fP; multiple matching \fBpgp-hook\fPs result in the use
3195+of multiple \fIkey-id\fPs for recipient.
3196 .PP
3197 .nf
3198 \fBopen-hook\fP \fIregexp\fP "\fIcommand\fP"
3199@@ -622,6 +624,28 @@
3200
3201
3202 .TP
3203+.B ask_follow_up
3204+.nf
3205+Type: boolean
3206+Default: no
3207+.fi
3208+.IP
3209+If set, Mutt will prompt you for follow-up groups before editing
3210+the body of an outgoing message.
3211+
3212+
3213+.TP
3214+.B ask_x_comment_to
3215+.nf
3216+Type: boolean
3217+Default: no
3218+.fi
3219+.IP
3220+If set, Mutt will prompt you for x-comment-to field before editing
3221+the body of an outgoing message.
3222+
3223+
3224+.TP
3225 .B attach_format
3226 .nf
3227 Type: string
3228@@ -773,6 +797,17 @@
3229
3230
3231 .TP
3232+.B catchup_newsgroup
3233+.nf
3234+Type: quadoption
3235+Default: ask-yes
3236+.fi
3237+.IP
3238+If this variable is \fIset\fP, Mutt will mark all articles in newsgroup
3239+as read when you quit the newsgroup (catchup newsgroup).
3240+
3241+
3242+.TP
3243 .B charset
3244 .nf
3245 Type: string
3246@@ -990,7 +1025,7 @@
3247 .B dotlock_program
3248 .nf
3249 Type: path
3250-Default: \(lq/usr/local/bin/mutt_dotlock\(rq
3251+Default: \(lq/usr/bin/mutt_dotlock\(rq
3252 .fi
3253 .IP
3254 Contains the path of the mutt_dotlock (8) binary to be used by
3255@@ -1161,6 +1196,16 @@
3256
3257
3258 .TP
3259+.B folder_columns
3260+.nf
3261+Type: number
3262+Default: 1
3263+.fi
3264+.IP
3265+Specifies the number of folder columns in folder browser.
3266+
3267+
3268+.TP
3269 .B folder_format
3270 .nf
3271 Type: string
3272@@ -1235,6 +1280,19 @@
3273
3274
3275 .TP
3276+.B followup_to_poster
3277+.nf
3278+Type: quadoption
3279+Default: ask-yes
3280+.fi
3281+.IP
3282+If this variable is \fIset\fP and the keyword \(rqposter\(rq is present in
3283+\fIFollowup-To\fP header, follow-up to newsgroup function is not
3284+permitted. The message will be mailed to the submitter of the
3285+message via mail.
3286+
3287+
3288+.TP
3289 .B force_name
3290 .nf
3291 Type: boolean
3292@@ -1319,6 +1377,39 @@
3293
3294
3295 .TP
3296+.B group_index_format
3297+.nf
3298+Type: string
3299+Default: \(lq%4C %M%N %5s %-45.45f %d\(rq
3300+.fi
3301+.IP
3302+This variable allows you to customize the newsgroup browser display to
3303+your personal taste. This string is similar to \(lqindex_format\(rq, but
3304+has its own set of printf()-like sequences:
3305+.IP
3306+
3307+.IP
3308+.DS
3309+.sp
3310+.ft CR
3311+.nf
3312+%C current newsgroup number
3313+%d description of newsgroup (becomes from server)
3314+%f newsgroup name
3315+%M - if newsgroup not allowed for direct post (moderated for example)
3316+%N N if newsgroup is new, u if unsubscribed, blank otherwise
3317+%n number of new articles in newsgroup
3318+%s number of unread articles in newsgroup
3319+%>X right justify the rest of the string and pad with character \(rqX\(rq
3320+%|X pad to the end of the line with character \(rqX\(rq
3321+
3322+.fi
3323+.ec
3324+.ft P
3325+.sp
3326+
3327+
3328+.TP
3329 .B hdrs
3330 .nf
3331 Type: boolean
3332@@ -1711,6 +1802,9 @@
3333 .IP %F
3334 author name, or recipient name if the message is from you
3335
3336+.IP %g
3337+newsgroup name (if compiled with nntp support)
3338+
3339 .IP %i
3340 message-id of the current message
3341
3342@@ -1756,6 +1850,9 @@
3343 .IP %v
3344 first name of the author, or the recipient if the message is from you
3345
3346+.IP %W
3347+name of organization of author (`organization:' field)
3348+
3349 .IP %y
3350 `x-label:' field, if present
3351
3352@@ -1798,10 +1895,37 @@
3353
3354
3355 .TP
3356+.B inews
3357+.nf
3358+Type: path
3359+Default: \(lq\(rq
3360+.fi
3361+.IP
3362+If set, specifies the program and arguments used to deliver news posted
3363+by Mutt. Otherwise, mutt posts article using current connection to
3364+news server. The following printf-style sequence is understood:
3365+.IP
3366+
3367+.IP
3368+.DS
3369+.sp
3370+.ft CR
3371+.nf
3372+%s newsserver name
3373+
3374+.fi
3375+.ec
3376+.ft P
3377+.sp
3378+.IP
3379+Example: set inews=\(rq/usr/local/bin/inews -hS\(rq
3380+
3381+
3382+.TP
3383 .B ispell
3384 .nf
3385 Type: path
3386-Default: \(lq/usr/bin/ispell\(rq
3387+Default: \(lqispell\(rq
3388 .fi
3389 .IP
3390 How to invoke ispell (GNU's spell-checking software).
3391@@ -2067,6 +2191,18 @@
3392
3393
3394 .TP
3395+.B mime_subject
3396+.nf
3397+Type: boolean
3398+Default: yes
3399+.fi
3400+.IP
3401+If \fIunset\fP, 8-bit \(lqsubject:\(rq line in article header will not be
3402+encoded according to RFC2047 to base64. This is useful when message
3403+is Usenet article, because MIME for news is nonstandard feature.
3404+
3405+
3406+.TP
3407 .B mix_entry_format
3408 .nf
3409 Type: string
3410@@ -2131,6 +2267,142 @@
3411
3412
3413 .TP
3414+.B narrow_tree
3415+.nf
3416+Type: boolean
3417+Default: no
3418+.fi
3419+.IP
3420+This variable controls the width of the thread tree when sorting by
3421+threads. When set, it makes the tree approximately twice as narrow,
3422+to allow more room the tree and message subjects. This is useful on
3423+narrow screens.
3424+
3425+
3426+.TP
3427+.B news_cache_dir
3428+.nf
3429+Type: path
3430+Default: \(lq~/.mutt\(rq
3431+.fi
3432+.IP
3433+This variable pointing to directory where Mutt will save cached news
3434+articles headers in. If \fIunset\fP, headers will not be saved at all
3435+and will be reloaded each time when you enter to newsgroup.
3436+
3437+
3438+.TP
3439+.B news_server
3440+.nf
3441+Type: string
3442+Default: \(lq\(rq
3443+.fi
3444+.IP
3445+This variable specifies domain name or address of NNTP server. It
3446+defaults to the newsserver specified in the environment variable
3447+$NNTPSERVER or contained in the file /etc/nntpserver. You can also
3448+specify username and an alternative port for each newsserver, ie:
3449+.IP
3450+[nntp[s]://][username[:password]@]newsserver[:port]
3451+
3452+
3453+.TP
3454+.B newsrc
3455+.nf
3456+Type: path
3457+Default: \(lq~/.newsrc\(rq
3458+.fi
3459+.IP
3460+The file, containing info about subscribed newsgroups - names and
3461+indexes of read articles. The following printf-style sequence
3462+is understood:
3463+.IP
3464+
3465+.IP
3466+.DS
3467+.sp
3468+.ft CR
3469+.nf
3470+%s newsserver name
3471+
3472+.fi
3473+.ec
3474+.ft P
3475+.sp
3476+
3477+
3478+.TP
3479+.B nntp_context
3480+.nf
3481+Type: number
3482+Default: 1000
3483+.fi
3484+.IP
3485+This variable defines number of articles which will be in index when
3486+newsgroup entered. If active newsgroup have more articles than this
3487+number, oldest articles will be ignored. Also controls how many
3488+articles headers will be saved in cache when you quit newsgroup.
3489+
3490+
3491+.TP
3492+.B nntp_load_description
3493+.nf
3494+Type: boolean
3495+Default: yes
3496+.fi
3497+.IP
3498+This variable controls whether or not descriptions for each newsgroup
3499+must be loaded when newsgroup is added to list (first time list
3500+loading or new newsgroup adding).
3501+
3502+
3503+.TP
3504+.B nntp_user
3505+.nf
3506+Type: string
3507+Default: \(lq\(rq
3508+.fi
3509+.IP
3510+Your login name on the NNTP server. If \fIunset\fP and NNTP server requires
3511+authentification, Mutt will prompt you for your account name when you
3512+connect to newsserver.
3513+
3514+
3515+.TP
3516+.B nntp_pass
3517+.nf
3518+Type: string
3519+Default: \(lq\(rq
3520+.fi
3521+.IP
3522+Your password for NNTP account.
3523+
3524+
3525+.TP
3526+.B nntp_poll
3527+.nf
3528+Type: number
3529+Default: 60
3530+.fi
3531+.IP
3532+The time in seconds until any operations on newsgroup except post new
3533+article will cause recheck for new news. If set to 0, Mutt will
3534+recheck newsgroup on each operation in index (stepping, read article,
3535+etc.).
3536+
3537+
3538+.TP
3539+.B nntp_reconnect
3540+.nf
3541+Type: quadoption
3542+Default: ask-yes
3543+.fi
3544+.IP
3545+Controls whether or not Mutt will try to reconnect to newsserver when
3546+connection lost.
3547+
3548+
3549+.TP
3550 .B pager
3551 .nf
3552 Type: path
3553@@ -2207,6 +2479,19 @@
3554
3555
3556 .TP
3557+.B pgp_autoselectkey
3558+.nf
3559+Type: boolean
3560+Default: no
3561+.fi
3562+.IP
3563+If set, then a list of keys is not presented for selection when only
3564+one matching key is available. This may be useful in conjunction with
3565+the \fIpgp-hook\fP command (with \(lq$pgp_confirmhook\(rq set) and the
3566+\(lq$pgp_ignore_subkeys\(rq variable.
3567+
3568+
3569+.TP
3570 .B pgp_autosign
3571 .nf
3572 Type: boolean
3573@@ -2234,6 +2519,19 @@
3574
3575
3576 .TP
3577+.B pgp_confirmhook
3578+.nf
3579+Type: boolean
3580+Default: yes
3581+.fi
3582+.IP
3583+If set, then you will be prompted for confirmation of keys when using
3584+the \fIpgp-hook\fP command. If unset, no such confirmation prompt will
3585+be presented. This is generally considered unsafe, especially where
3586+typos are concerned.
3587+
3588+
3589+.TP
3590 .B pgp_ignore_subkeys
3591 .nf
3592 Type: boolean
3593@@ -2916,6 +3214,19 @@
3594
3595
3596 .TP
3597+.B post_moderated
3598+.nf
3599+Type: quadoption
3600+Default: ask-yes
3601+.fi
3602+.IP
3603+If set to \fIyes\fP, Mutt will post article to newsgroup that have
3604+not permissions to posting (e.g. moderated). \fBNote:\fP if newsserver
3605+does not support posting to that newsgroup or totally read-only, that
3606+posting will not have an effect.
3607+
3608+
3609+.TP
3610 .B postpone
3611 .nf
3612 Type: quadoption
3613@@ -3056,6 +3367,29 @@
3614
3615
3616 .TP
3617+.B quote_empty
3618+.nf
3619+Type: boolean
3620+Default: yes
3621+.fi
3622+.IP
3623+Controls whether or not empty lines will be quoted using
3624+\(lqindent_string\(rq.
3625+
3626+
3627+.TP
3628+.B quote_quoted
3629+.nf
3630+Type: boolean
3631+Default: no
3632+.fi
3633+.IP
3634+Controls how quoted lines will be quoted. If set, one quote
3635+character will be added to the end of existing prefix. Otherwise,
3636+quoted lines will be prepended by \(lqindent_string\(rq.
3637+
3638+
3639+.TP
3640 .B quote_regexp
3641 .nf
3642 Type: regular expression
3643@@ -3455,6 +3789,41 @@
3644
3645
3646 .TP
3647+.B save_unsubscribed
3648+.nf
3649+Type: boolean
3650+Default: no
3651+.fi
3652+.IP
3653+When \fIset\fP, info about unsubscribed newsgroups will be saved into
3654+\(lqnewsrc\(rq file and into cache.
3655+
3656+
3657+.TP
3658+.B show_new_news
3659+.nf
3660+Type: boolean
3661+Default: yes
3662+.fi
3663+.IP
3664+If \fIset\fP, newsserver will be asked for new newsgroups on entering
3665+the browser. Otherwise, it will be done only once for a newsserver.
3666+Also controls whether or not number of new articles of subscribed
3667+newsgroups will be then checked.
3668+
3669+
3670+.TP
3671+.B show_only_unread
3672+.nf
3673+Type: boolean
3674+Default: no
3675+.fi
3676+.IP
3677+If \fIset\fP, only subscribed newsgroups that contain unread articles
3678+will be displayed in browser.
3679+
3680+
3681+.TP
3682 .B sig_dashes
3683 .nf
3684 Type: boolean
3685@@ -3496,6 +3865,19 @@
3686
3687
3688 .TP
3689+.B signatures_directory
3690+.nf
3691+Type: path
3692+Default: \(lq\(rq
3693+.fi
3694+.IP
3695+Specifies the path where your signatures are located. In the files of
3696+this directory, the signatures are separated by blank lines and/or
3697+sig_dashes (\(lq-- \(rq).
3698+You can choose between these signatures from the compose menu.
3699+
3700+
3701+.TP
3702 .B simple_search
3703 .nf
3704 Type: string
3705@@ -3788,6 +4170,11 @@
3706 .IP %V
3707 currently active limit pattern, if any *
3708
3709+.IP %[fmt]
3710+the current date and time. \(lqfmt\(rq is
3711+expanded by the system call \(lqstrftime\(rq;
3712+a leading bang disables locales
3713+
3714 .IP %>X
3715 right justify the rest of the string and pad with \(rqX\(rq
3716
3717@@ -3840,6 +4227,21 @@
3718
3719
3720 .TP
3721+.B status_update
3722+.nf
3723+Type: number
3724+Default: -1
3725+.fi
3726+.IP
3727+This variable controls, if positive, the maximum interval in seconds
3728+before the time in the status line is updated. It is checked at
3729+every key press and after a keyboard $timeout.
3730+If the value is zero, the status line will be updated at every check.
3731+If it is negative, the status time will only be updated
3732+if it necessary to update to the status line for some other reason.
3733+
3734+
3735+.TP
3736 .B strict_threads
3737 .nf
3738 Type: boolean
3739@@ -3960,6 +4362,18 @@
3740
3741
3742 .TP
3743+.B trash
3744+.nf
3745+Type: path
3746+Default: \(lq\(rq
3747+.fi
3748+.IP
3749+If set, this variable specifies the path of the trash folder where the
3750+mails marked for deletion will be moved, instead of being irremediably
3751+purged.
3752+
3753+
3754+.TP
3755 .B tunnel
3756 .nf
3757 Type: string
3758@@ -4017,6 +4431,18 @@
3759
3760
3761 .TP
3762+.B use_ipv6
3763+.nf
3764+Type: boolean
3765+Default: yes
3766+.fi
3767+.IP
3768+When \fIset\fP, Mutt will look for IPv6 addresses of hosts it tries to
3769+contact. If this option is unset, Mutt will restrict itself to IPv4 addresses.
3770+Normally, the default should work.
3771+
3772+
3773+.TP
3774 .B user_agent
3775 .nf
3776 Type: boolean
3777@@ -4118,6 +4544,17 @@
3778 messages to be sent. Exim users may wish to use this.
3779
3780
3781+.TP
3782+.B x_comment_to
3783+.nf
3784+Type: boolean
3785+Default: no
3786+.fi
3787+.IP
3788+If \fIset\fP, Mutt will add \(lqX-Comment-To:\(rq field (that contains full
3789+name of original article author) to article that followuped to newsgroup.
3790+
3791+
3792 .\" -*-nroff-*-
3793 .SH SEE ALSO
3794 .PP
3795diff -uNr mutt-1.4.orig/functions.h mutt-1.4/functions.h
3796--- mutt-1.4.orig/functions.h Sun Nov 3 21:42:52 2002
3797+++ mutt-1.4/functions.h Sun Nov 3 21:57:20 2002
3798@@ -69,6 +69,10 @@
3799 { "break-thread", OP_MAIN_BREAK_THREAD, "#" },
3800 { "change-folder", OP_MAIN_CHANGE_FOLDER, "c" },
3801 { "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" },
3802+#ifdef USE_NNTP
5d9cbba1 3803+ { "change-newsgroup", OP_MAIN_CHANGE_GROUP, NULL },
3804+ { "change-newsgroup-readonly",OP_MAIN_CHANGE_GROUP_READONLY, NULL },
1b5dcea5 3805+#endif
3806 { "collapse-thread", OP_MAIN_COLLAPSE_THREAD, "\033v" },
3807 { "collapse-all", OP_MAIN_COLLAPSE_ALL, "\033V" },
3808 { "copy-message", OP_COPY_MESSAGE, "C" },
3809@@ -81,7 +85,15 @@
3810 { "edit", OP_EDIT_MESSAGE, "e" },
3811 { "edit-type", OP_EDIT_TYPE, "\005" },
3812 { "forward-message", OP_FORWARD_MESSAGE, "f" },
3813- { "flag-message", OP_FLAG_MESSAGE, "F" },
3814+#ifdef USE_NNTP
5d9cbba1 3815+ { "forward-to-group", OP_FORWARD_TO_GROUP, NULL },
3816+ { "followup-message", OP_FOLLOWUP, NULL },
1b5dcea5 3817+ { "get-children", OP_GET_CHILDREN, NULL },
5d9cbba1 3818+ { "get-message", OP_GET_MESSAGE, NULL },
3819+ { "get-parent", OP_GET_PARENT, NULL },
1b5dcea5 3820+ { "reconstruct-thread", OP_RECONSTRUCT_THREAD, NULL },
3821+#endif
5d9cbba1 3822+ { "flag-message", OP_FLAG_MESSAGE, "F" },
1b5dcea5 3823 { "group-reply", OP_GROUP_REPLY, "g" },
3824 #ifdef USE_POP
3825 { "fetch-mail", OP_MAIN_FETCH_MAIL, "G" },
3826@@ -108,6 +120,9 @@
3827 { "sort-mailbox", OP_SORT, "o" },
3828 { "sort-reverse", OP_SORT_REVERSE, "O" },
3829 { "print-message", OP_PRINT, "p" },
3830+#ifdef USE_NNTP
5d9cbba1 3831+ { "post-message", OP_POST, NULL },
1b5dcea5 3832+#endif
3833 { "previous-thread", OP_MAIN_PREV_THREAD, "\020" },
3834 { "previous-subthread", OP_MAIN_PREV_SUBTHREAD, "\033p" },
3835 { "recall-message", OP_RECALL_MESSAGE, "R" },
3836@@ -127,6 +142,10 @@
3837 { "show-version", OP_VERSION, "V" },
3838 { "set-flag", OP_MAIN_SET_FLAG, "w" },
3839 { "clear-flag", OP_MAIN_CLEAR_FLAG, "W" },
5d9cbba1 3840+ { "toggle-read", OP_TOGGLE_READ, NULL },
1b5dcea5 3841+#ifdef USE_NNTP
5d9cbba1 3842+ { "catchup", OP_CATCHUP, NULL },
1b5dcea5 3843+#endif
3844 { "display-message", OP_DISPLAY_MESSAGE, M_ENTER_S },
3845 { "sync-mailbox", OP_MAIN_SYNC_FOLDER, "$" },
3846 { "display-address", OP_DISPLAY_ADDRESS, "@" },
1b5dcea5 3847@@ -158,6 +177,10 @@
3848 { "bounce-message", OP_BOUNCE_MESSAGE, "b" },
3849 { "change-folder", OP_MAIN_CHANGE_FOLDER, "c" },
3850 { "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" },
3851+#ifdef USE_NNTP
5d9cbba1 3852+ { "change-newsgroup", OP_MAIN_CHANGE_GROUP, NULL },
3853+ { "change-newsgroup-readonly",OP_MAIN_CHANGE_GROUP_READONLY, NULL },
1b5dcea5 3854+#endif
3855 { "copy-message", OP_COPY_MESSAGE, "C" },
3856 { "decode-copy", OP_DECODE_COPY, "\033C" },
3857 { "delete-message", OP_DELETE, "d" },
3858@@ -165,8 +188,12 @@
3859 { "delete-subthread", OP_DELETE_SUBTHREAD, "\033d" },
3860 { "edit", OP_EDIT_MESSAGE, "e" },
3861 { "edit-type", OP_EDIT_TYPE, "\005" },
3862+#ifdef USE_NNTP
5d9cbba1 3863+ { "followup-message", OP_FOLLOWUP, NULL },
3864+ { "forward-to-group", OP_FORWARD_TO_GROUP, NULL },
1b5dcea5 3865+#endif
3866 { "forward-message", OP_FORWARD_MESSAGE, "f" },
3867- { "flag-message", OP_FLAG_MESSAGE, "F" },
5d9cbba1 3868+ { "flag-message", OP_FLAG_MESSAGE, "F" },
1b5dcea5 3869 { "group-reply", OP_GROUP_REPLY, "g" },
3870 #ifdef USE_IMAP
3871 { "imap-fetch-mail", OP_MAIN_IMAP_FETCH, NULL },
3872@@ -185,6 +212,9 @@
3873 { "next-thread", OP_MAIN_NEXT_THREAD, "\016" },
3874 { "next-subthread", OP_MAIN_NEXT_SUBTHREAD, "\033n" },
3875 { "print-message", OP_PRINT, "p" },
3876+#ifdef USE_NNTP
5d9cbba1 3877+ { "post-message", OP_POST, NULL },
1b5dcea5 3878+#endif
3879 { "previous-thread", OP_MAIN_PREV_THREAD, "\020" },
3880 { "previous-subthread",OP_MAIN_PREV_SUBTHREAD, "\033p" },
3881 { "purge-message", OP_PURGE_MESSAGE, NULL },
1b5dcea5 3882@@ -252,6 +282,10 @@
3883 { "bounce-message", OP_BOUNCE_MESSAGE, "b" },
3884 { "display-toggle-weed", OP_DISPLAY_HEADERS, "h" },
3885 { "edit-type", OP_EDIT_TYPE, "\005" },
3886+#ifdef USE_NNTP
5d9cbba1 3887+ { "followup-message", OP_FOLLOWUP, NULL },
3888+ { "forward-to-group", OP_FORWARD_TO_GROUP, NULL },
1b5dcea5 3889+#endif
3890 { "print-entry", OP_PRINT, "p" },
3891 { "save-entry", OP_SAVE, "s" },
3892 { "pipe-entry", OP_PIPE, "|" },
3893@@ -282,6 +316,7 @@
3894 struct binding_t OpCompose[] = {
3895 { "attach-file", OP_COMPOSE_ATTACH_FILE, "a" },
3896 { "attach-message", OP_COMPOSE_ATTACH_MESSAGE, "A" },
5d9cbba1 3897+ { "attach-news-message",OP_COMPOSE_ATTACH_NEWS_MESSAGE,NULL },
1b5dcea5 3898 { "edit-bcc", OP_COMPOSE_EDIT_BCC, "b" },
3899 { "edit-cc", OP_COMPOSE_EDIT_CC, "c" },
3900 { "copy-file", OP_SAVE, "C" },
3901@@ -301,6 +336,11 @@
3902 { "print-entry", OP_PRINT, "l" },
3903 { "edit-mime", OP_COMPOSE_EDIT_MIME, "m" },
3904 { "new-mime", OP_COMPOSE_NEW_MIME, "n" },
3905+#ifdef USE_NNTP
5d9cbba1 3906+ { "edit-newsgroups", OP_COMPOSE_EDIT_NEWSGROUPS, NULL },
3907+ { "edit-followup-to", OP_COMPOSE_EDIT_FOLLOWUP_TO, NULL },
3908+ { "edit-x-comment-to",OP_COMPOSE_EDIT_X_COMMENT_TO, NULL },
1b5dcea5 3909+#endif
3910 { "postpone-message", OP_COMPOSE_POSTPONE_MESSAGE, "P" },
3911 { "edit-reply-to", OP_COMPOSE_EDIT_REPLY_TO, "r" },
3912 { "rename-file", OP_COMPOSE_RENAME_FILE, "R" },
3913@@ -352,12 +392,23 @@
3914 { "select-new", OP_BROWSER_NEW_FILE, "N" },
3915 { "check-new", OP_CHECK_NEW, NULL },
3916 { "toggle-mailboxes", OP_TOGGLE_MAILBOXES, "\t" },
3917+#ifdef USE_NNTP
5d9cbba1 3918+ { "reload-active", OP_LOAD_ACTIVE, NULL},
3919+ { "subscribe-pattern", OP_SUBSCRIBE_PATTERN, NULL },
3920+ { "unsubscribe-pattern", OP_UNSUBSCRIBE_PATTERN, NULL },
3921+ { "catchup", OP_CATCHUP, NULL },
3922+ { "uncatchup", OP_UNCATCHUP, NULL },
1b5dcea5 3923+#endif
3924 { "view-file", OP_BROWSER_VIEW_FILE, " " },
3925 #ifdef USE_IMAP
3926 { "create-mailbox", OP_CREATE_MAILBOX, "C" },
3927 { "delete-mailbox", OP_DELETE_MAILBOX, "d" },
3928+#endif
3929+#if defined USE_IMAP || defined USE_NNTP
3930 { "subscribe", OP_BROWSER_SUBSCRIBE, "s" },
3931 { "unsubscribe", OP_BROWSER_UNSUBSCRIBE, "u" },
3932+#endif
3933+#ifdef USE_IMAP
3934 { "toggle-subscribed", OP_BROWSER_TOGGLE_LSUB, "T" },
3935 #endif
3936 { NULL, 0, NULL }
3937diff -uNr mutt-1.4.orig/globals.h mutt-1.4/globals.h
3938--- mutt-1.4.orig/globals.h Sun Nov 3 21:42:52 2002
3939+++ mutt-1.4/globals.h Sun Nov 3 21:57:20 2002
3940@@ -80,6 +80,15 @@
3941 #endif
3942
3943 WHERE char *Muttrc INITVAL (NULL);
3944+#ifdef USE_NNTP
3945+WHERE char *NewsCacheDir;
3946+WHERE char *GroupFormat;
3947+WHERE char *Inews;
3948+WHERE char *NewsServer;
3949+WHERE char *NntpUser;
3950+WHERE char *NntpPass;
3951+WHERE char *NewsRc;
3952+#endif
3953 WHERE char *Outbox;
3954 WHERE char *Pager;
3955 WHERE char *PagerFmt;
3956@@ -146,6 +155,11 @@
3957
3958 WHERE unsigned short Counter INITVAL (0);
3959
3960+#ifdef USE_NNTP
3961+WHERE short NewsPollTimeout;
3962+WHERE short NntpContext;
3963+#endif
3964+
3965 WHERE short ConnectTimeout;
3966 WHERE short FolderColumns;
3967 WHERE short HistSize;
3968diff -uNr mutt-1.4.orig/hash.c mutt-1.4/hash.c
3969--- mutt-1.4.orig/hash.c Mon Nov 19 11:41:32 2001
3970+++ mutt-1.4/hash.c Sun Nov 3 21:57:20 2002
3971@@ -47,10 +47,35 @@
3972 if (nelem == 0)
3973 nelem = 2;
3974 table->nelem = nelem;
3975+ table->curnelem = 0;
3976 table->table = safe_calloc (nelem, sizeof (struct hash_elem *));
3977 return table;
3978 }
3979
3980+HASH *hash_resize (HASH *ptr, int nelem)
3981+{
3982+ HASH *table;
3983+ struct hash_elem *elem, *tmp;
3984+ int i;
3985+
3986+ table = hash_create (nelem);
3987+
3988+ for (i = 0; i < ptr->nelem; i++)
3989+ {
3990+ for (elem = ptr->table[i]; elem; )
3991+ {
3992+ tmp = elem;
3993+ elem = elem->next;
3994+ hash_insert (table, tmp->key, tmp->data, 1);
3995+ safe_free ((void **) &tmp);
3996+ }
3997+ }
3998+ safe_free ((void **) &ptr->table);
3999+ safe_free ((void **) &ptr);
4000+
4001+ return table;
4002+}
4003+
4004 /* table hash table to update
4005 * key key to hash on
4006 * data data to associate with `key'
4007@@ -70,6 +95,7 @@
4008 {
4009 ptr->next = table->table[h];
4010 table->table[h] = ptr;
4011+ table->curnelem++;
4012 }
4013 else
4014 {
4015@@ -92,6 +118,7 @@
4016 else
4017 table->table[h] = ptr;
4018 ptr->next = tmp;
4019+ table->curnelem++;
4020 }
4021 return h;
4022 }
4023@@ -124,6 +151,7 @@
4024 *last = ptr->next;
4025 if (destroy) destroy (ptr->data);
4026 FREE (&ptr);
4027+ table->curnelem--;
4028 return;
4029 }
4030 }
4031diff -uNr mutt-1.4.orig/hash.h mutt-1.4/hash.h
4032--- mutt-1.4.orig/hash.h Fri Mar 3 11:10:08 2000
4033+++ mutt-1.4/hash.h Sun Nov 3 21:57:20 2002
4034@@ -28,7 +28,7 @@
4035
4036 typedef struct
4037 {
4038- int nelem;
4039+ int nelem, curnelem;
4040 struct hash_elem **table;
4041 }
4042 HASH;
4043@@ -40,6 +40,7 @@
4044 HASH *hash_create (int nelem);
4045 int hash_string (const unsigned char *s, int n);
4046 int hash_insert (HASH * table, const char *key, void *data, int allow_dup);
4047+HASH *hash_resize (HASH * table, int nelem);
4048 void *hash_find_hash (const HASH * table, int hash, const char *key);
4049 void hash_delete_hash (HASH * table, int hash, const char *key, const void *data,
4050 void (*destroy) (void *));
4051diff -uNr mutt-1.4.orig/hdrline.c mutt-1.4/hdrline.c
4052--- mutt-1.4.orig/hdrline.c Sun Nov 3 21:42:52 2002
4053+++ mutt-1.4/hdrline.c Sun Nov 3 21:57:20 2002
4054@@ -255,6 +255,7 @@
4055 * %E = number of messages in current thread
4056 * %f = entire from line
4057 * %F = like %n, unless from self
4058+ * %g = newsgroup name (if compiled with nntp support)
4059 * %i = message-id
4060 * %l = number of lines in the message
4061 * %L = like %F, except `lists' are displayed first
4062@@ -268,6 +269,7 @@
4063 * %T = $to_chars
4064 * %u = user (login) name of author
4065 * %v = first name of author, unless from self
4066+ * %W = where user is (organization)
4067 * %y = `x-label:' field (if present)
4068 * %Y = `x-label:' field (if present, tree unfolded, and != parent's x-label)
4069 * %Z = status flags */
4070@@ -484,6 +486,12 @@
4071 optional = 0;
4072 break;
4073
4074+#ifdef USE_NNTP
4075+ case 'g':
4076+ mutt_format_s (dest, destlen, prefix, hdr->env->newsgroups ? hdr->env->newsgroups : "");
4077+ break;
4078+#endif
4079+
4080 case 'i':
4081 mutt_format_s (dest, destlen, prefix, hdr->env->message_id ? hdr->env->message_id : "<no.id>");
4082 break;
4083@@ -655,6 +663,13 @@
4084 mutt_format_s (dest, destlen, prefix, buf2);
4085 break;
4086
4087+ case 'W':
4088+ if (!optional)
4089+ mutt_format_s (dest, destlen, prefix, hdr->env->organization ? hdr->env->organization : "");
4090+ else if (!hdr->env->organization)
4091+ optional = 0;
4092+ break;
4093+
4094 case 'Z':
4095
4096 ch = ' ';
4097diff -uNr mutt-1.4.orig/headers.c mutt-1.4/headers.c
4098--- mutt-1.4.orig/headers.c Mon Nov 5 22:19:33 2001
4099+++ mutt-1.4/headers.c Sun Nov 3 21:57:20 2002
4100@@ -115,6 +115,9 @@
4101 msg->env = n; n = NULL;
4102
4103 if (!msg->env->in_reply_to)
4104+#ifdef USE_NNTP
4105+ if (!option (OPTNEWSSEND))
4106+#endif
4107 mutt_free_list (&msg->env->references);
4108
4109 mutt_expand_aliases_env (msg->env);
1b5dcea5 4110diff -uNr mutt-1.4.orig/init.c mutt-1.4/init.c
4111--- mutt-1.4.orig/init.c Sun Nov 3 21:42:51 2002
4112+++ mutt-1.4/init.c Sun Nov 3 21:57:20 2002
4113@@ -1789,6 +1789,28 @@
4114 else
4115 Fqdn = safe_strdup(NONULL(Hostname));
4116
4117+#ifdef USE_NNTP
4118+ {
4119+ FILE *f;
4120+ char *i;
4121+
4122+ if ((f = safe_fopen (SYSCONFDIR "/nntpserver", "r")))
4123+ {
4124+ buffer[0] = '\0';
4125+ fgets (buffer, sizeof (buffer), f);
4126+ p = &buffer;
4127+ SKIPWS (p);
4128+ i = p;
4129+ while (*i && (*i != ' ') && (*i != '\t') && (*i != '\r') && (*i != '\n')) i++;
4130+ *i = '\0';
4131+ NewsServer = safe_strdup (p);
4132+ fclose (f);
4133+ }
4134+ }
4135+ if ((p = getenv ("NNTPSERVER")))
4136+ NewsServer = safe_strdup (p);
4137+#endif
4138+
4139 if ((p = getenv ("MAIL")))
4140 Spoolfile = safe_strdup (p);
4141 else if ((p = getenv ("MAILDIR")))
4142diff -uNr mutt-1.4.orig/init.h mutt-1.4/init.h
4143--- mutt-1.4.orig/init.h Sun Nov 3 21:42:52 2002
4144+++ mutt-1.4/init.h Sun Nov 3 21:57:20 2002
4145@@ -193,6 +193,20 @@
4146 ** If set, Mutt will prompt you for carbon-copy (Cc) recipients before
4147 ** editing the body of an outgoing message.
4148 */
4149+#ifdef USE_NNTP
4150+ { "ask_follow_up", DT_BOOL, R_NONE, OPTASKFOLLOWUP, 0 },
4151+ /*
4152+ ** .pp
4153+ ** If set, Mutt will prompt you for follow-up groups before editing
4154+ ** the body of an outgoing message.
4155+ */
4156+ { "ask_x_comment_to", DT_BOOL, R_NONE, OPTASKXCOMMENTTO, 0 },
4157+ /*
4158+ ** .pp
4159+ ** If set, Mutt will prompt you for x-comment-to field before editing
4160+ ** the body of an outgoing message.
4161+ */
4162+#endif
4163 { "attach_format", DT_STR, R_NONE, UL &AttachFormat, UL "%u%D%I %t%4n %T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] " },
4164 /*
4165 ** .pp
4166@@ -273,6 +287,14 @@
4167 ** When this variable is set, mutt will include Delivered-To headers when
4168 ** bouncing messages. Postfix users may wish to unset this variable.
4169 */
4170+#ifdef USE_NNTP
4171+ { "catchup_newsgroup", DT_QUAD, R_NONE, OPT_CATCHUP, M_ASKYES },
4172+ /*
4173+ ** .pp
4174+ ** If this variable is \fIset\fP, Mutt will mark all articles in newsgroup
4175+ ** as read when you quit the newsgroup (catchup newsgroup).
4176+ */
4177+#endif
4178 { "charset", DT_STR, R_NONE, UL &Charset, UL 0 },
4179 /*
4180 ** .pp
4181@@ -565,6 +587,16 @@
4182 ** subscribed list will be sent to both the list and your address,
4183 ** resulting in two copies of the same email for you.
4184 */
4185+#ifdef USE_NNTP
4186+ { "followup_to_poster", DT_QUAD, R_NONE, OPT_FOLLOWUPTOPOSTER, M_ASKYES },
4187+ /*
4188+ ** .pp
4189+ ** If this variable is \fIset\fP and the keyword "poster" is present in
4190+ ** \fIFollowup-To\fP header, follow-up to newsgroup function is not
4191+ ** permitted. The message will be mailed to the submitter of the
4192+ ** message via mail.
4193+ */
4194+#endif
4195 { "force_name", DT_BOOL, R_NONE, OPTFORCENAME, 0 },
4196 /*
4197 ** .pp
4198@@ -628,6 +660,27 @@
4199 ** a regular expression that will match the whole name so mutt will expand
4200 ** "Franklin" to "Franklin, Steve".
4201 */
4202+#ifdef USE_NNTP
4203+ { "group_index_format", DT_STR, R_BOTH, UL &GroupFormat, UL "%4C %M%N %5s %-45.45f %d" },
4204+ /*
4205+ ** .pp
4206+ ** This variable allows you to customize the newsgroup browser display to
4207+ ** your personal taste. This string is similar to ``$index_format'', but
4208+ ** has its own set of printf()-like sequences:
4209+ ** .pp
4210+ ** .ts
4211+ ** %C current newsgroup number
4212+ ** %d description of newsgroup (becomes from server)
4213+ ** %f newsgroup name
4214+ ** %M - if newsgroup not allowed for direct post (moderated for example)
4215+ ** %N N if newsgroup is new, u if unsubscribed, blank otherwise
4216+ ** %n number of new articles in newsgroup
4217+ ** %s number of unread articles in newsgroup
4218+ ** %>X right justify the rest of the string and pad with character "X"
4219+ ** %|X pad to the end of the line with character "X"
4220+ ** .te
4221+ */
4222+#endif
4223 { "hdr_format", DT_SYN, R_NONE, UL "index_format", 0 },
4224 /*
4225 */
4226@@ -874,6 +927,7 @@
4227 ** .dt %E .dd number of messages in current thread
4228 ** .dt %f .dd entire From: line (address + real name)
4229 ** .dt %F .dd author name, or recipient name if the message is from you
4230+ ** .dt %g .dd newsgroup name (if compiled with nntp support)
4231 ** .dt %i .dd message-id of the current message
4232 ** .dt %l .dd number of lines in the message
4233 ** .dt %L .dd If an address in the To or CC header field matches an address
4234@@ -891,6 +945,7 @@
4235 ** .dt %T .dd the appropriate character from the $$to_chars string
4236 ** .dt %u .dd user (login) name of the author
4237 ** .dt %v .dd first name of the author, or the recipient if the message is from you
4238+ ** .dt %W .dd name of organization of author (`organization:' field)
4239 ** .dt %y .dd `x-label:' field, if present
4240 ** .dt %Y .dd `x-label' field, if present, and (1) not at part of a thread tree,
4241 ** (2) at the top of a thread, or (3) `x-label' is different from
4242@@ -913,6 +968,21 @@
4243 ** .pp
4244 ** See also: ``$$to_chars''.
4245 */
4246+#ifdef USE_NNTP
4247+ { "inews", DT_PATH, R_NONE, UL &Inews, UL "" },
4248+ /*
4249+ ** .pp
4250+ ** If set, specifies the program and arguments used to deliver news posted
4251+ ** by Mutt. Otherwise, mutt posts article using current connection to
4252+ ** news server. The following printf-style sequence is understood:
4253+ ** .pp
4254+ ** .ts
4255+ ** %s newsserver name
4256+ ** .te
4257+ ** .pp
4258+ ** Example: set inews="/usr/local/bin/inews -hS"
4259+ */
4260+#endif
4261 { "ispell", DT_PATH, R_NONE, UL &Ispell, UL ISPELL },
4262 /*
4263 ** .pp
4264@@ -1077,6 +1147,16 @@
4265 ** be attached to the newly composed message if this option is set.
4266 */
4267
4268+#ifdef USE_NNTP
4269+ { "mime_subject", DT_BOOL, R_NONE, OPTMIMESUBJECT, 1 },
4270+ /*
4271+ ** .pp
4272+ ** If \fIunset\fP, 8-bit ``subject:'' line in article header will not be
4273+ ** encoded according to RFC2047 to base64. This is useful when message
4274+ ** is Usenet article, because MIME for news is nonstandard feature.
4275+ */
4276+#endif
4277+
4278 #ifdef MIXMASTER
4279 { "mix_entry_format", DT_STR, R_NONE, UL &MixEntryFormat, UL "%4n %c %-16s %a" },
4280 /*
4281@@ -1128,6 +1208,77 @@
4282 ** to allow more room the tree and message subjects. This is useful on
4283 ** narrow screens.
4284 */
4285+#ifdef USE_NNTP
4286+ { "news_cache_dir", DT_PATH, R_NONE, UL &NewsCacheDir, UL "~/.mutt" },
4287+ /*
4288+ ** .pp
4289+ ** This variable pointing to directory where Mutt will save cached news
4290+ ** articles headers in. If \fIunset\fP, headers will not be saved at all
4291+ ** and will be reloaded each time when you enter to newsgroup.
4292+ */
4293+ { "news_server", DT_STR, R_NONE, UL &NewsServer, 0 },
4294+ /*
4295+ ** .pp
4296+ ** This variable specifies domain name or address of NNTP server. It
4297+ ** defaults to the newsserver specified in the environment variable
4298+ ** $$$NNTPSERVER or contained in the file /etc/nntpserver. You can also
4299+ ** specify username and an alternative port for each newsserver, ie:
4300+ ** .pp
4301+ ** [nntp[s]://][username[:password]@]newsserver[:port]
4302+ */
4303+ { "newsrc", DT_PATH, R_NONE, UL &NewsRc, UL "~/.newsrc" },
4304+ /*
4305+ ** .pp
4306+ ** The file, containing info about subscribed newsgroups - names and
4307+ ** indexes of read articles. The following printf-style sequence
4308+ ** is understood:
4309+ ** .pp
4310+ ** .ts
4311+ ** %s newsserver name
4312+ ** .te
4313+ */
4314+ { "nntp_context", DT_NUM, R_NONE, UL &NntpContext, 1000 },
4315+ /*
4316+ ** .pp
4317+ ** This variable defines number of articles which will be in index when
4318+ ** newsgroup entered. If active newsgroup have more articles than this
4319+ ** number, oldest articles will be ignored. Also controls how many
4320+ ** articles headers will be saved in cache when you quit newsgroup.
4321+ */
4322+ { "nntp_load_description", DT_BOOL, R_NONE, OPTLOADDESC, 1 },
4323+ /*
4324+ ** .pp
4325+ ** This variable controls whether or not descriptions for each newsgroup
4326+ ** must be loaded when newsgroup is added to list (first time list
4327+ ** loading or new newsgroup adding).
4328+ */
4329+ { "nntp_user", DT_STR, R_NONE, UL &NntpUser, UL "" },
4330+ /*
4331+ ** .pp
4332+ ** Your login name on the NNTP server. If \fIunset\fP and NNTP server requires
4333+ ** authentification, Mutt will prompt you for your account name when you
4334+ ** connect to newsserver.
4335+ */
4336+ { "nntp_pass", DT_STR, R_NONE, UL &NntpPass, UL "" },
4337+ /*
4338+ ** .pp
4339+ ** Your password for NNTP account.
4340+ */
4341+ { "nntp_poll", DT_NUM, R_NONE, UL &NewsPollTimeout, 60 },
4342+ /*
4343+ ** .pp
4344+ ** The time in seconds until any operations on newsgroup except post new
4345+ ** article will cause recheck for new news. If set to 0, Mutt will
4346+ ** recheck newsgroup on each operation in index (stepping, read article,
4347+ ** etc.).
4348+ */
4349+ { "nntp_reconnect", DT_QUAD, R_NONE, OPT_NNTPRECONNECT, M_ASKYES },
4350+ /*
4351+ ** .pp
4352+ ** Controls whether or not Mutt will try to reconnect to newsserver when
4353+ ** connection lost.
4354+ */
4355+#endif
4356 { "pager", DT_PATH, R_NONE, UL &Pager, UL "builtin" },
4357 /*
4358 ** .pp
4359@@ -1633,6 +1784,16 @@
4360 { "post_indent_str", DT_SYN, R_NONE, UL "post_indent_string", 0 },
4361 /*
4362 */
4363+#ifdef USE_NNTP
4364+ { "post_moderated", DT_QUAD, R_NONE, OPT_TOMODERATED, M_ASKYES },
4365+ /*
4366+ ** .pp
4367+ ** If set to \fIyes\fP, Mutt will post article to newsgroup that have
4368+ ** not permissions to posting (e.g. moderated). \fBNote:\fP if newsserver
4369+ ** does not support posting to that newsgroup or totally read-only, that
4370+ ** posting will not have an effect.
4371+ */
4372+#endif
4373 { "postpone", DT_QUAD, R_NONE, OPT_POSTPONE, M_ASKYES },
4374 /*
4375 ** .pp
4376@@ -1991,6 +2152,28 @@
4377 ** Command to use when spawning a subshell. By default, the user's login
4378 ** shell from /etc/passwd is used.
4379 */
4380+#ifdef USE_NNTP
4381+ { "save_unsubscribed",DT_BOOL, R_NONE, OPTSAVEUNSUB, 0 },
4382+ /*
4383+ ** .pp
4384+ ** When \fIset\fP, info about unsubscribed newsgroups will be saved into
4385+ ** ``newsrc'' file and into cache.
4386+ */
4387+ { "show_new_news", DT_BOOL, R_NONE, OPTSHOWNEWNEWS, 1 },
4388+ /*
4389+ ** .pp
4390+ ** If \fIset\fP, newsserver will be asked for new newsgroups on entering
4391+ ** the browser. Otherwise, it will be done only once for a newsserver.
4392+ ** Also controls whether or not number of new articles of subscribed
4393+ ** newsgroups will be then checked.
4394+ */
4395+ { "show_only_unread", DT_BOOL, R_NONE, OPTSHOWONLYUNREAD, 0 },
4396+ /*
4397+ ** .pp
4398+ ** If \fIset\fP, only subscribed newsgroups that contain unread articles
4399+ ** will be displayed in browser.
4400+ */
4401+#endif
4402 { "sig_dashes", DT_BOOL, R_NONE, OPTSIGDASHES, 1 },
4403 /*
4404 ** .pp
4405@@ -2437,6 +2620,14 @@
4406 ** Controls whether mutt writes out the Bcc header when preparing
9ac83ccd
JB
4407 ** messages to be sent. Exim users may wish to use this.
4408 */
4409+#ifdef USE_NNTP
4410+ { "x_comment_to", DT_BOOL, R_NONE, OPTXCOMMENTTO, 0 },
4411+ /*
4412+ ** .pp
4413+ ** If \fIset\fP, Mutt will add ``X-Comment-To:'' field (that contains full
4414+ ** name of original article author) to article that followuped to newsgroup.
4415+ */
4416+#endif
4417 /*--*/
4418 { NULL }
4419 };
1b5dcea5 4420diff -uNr mutt-1.4.orig/keymap.c mutt-1.4/keymap.c
4421--- mutt-1.4.orig/keymap.c Sun Nov 3 21:42:52 2002
4422+++ mutt-1.4/keymap.c Sun Nov 3 21:57:20 2002
4423@@ -593,7 +593,6 @@
4424 km_bindkey ("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
4425
4426 km_bindkey ("x", MENU_PAGER, OP_EXIT);
4427- km_bindkey ("i", MENU_PAGER, OP_EXIT);
4428 km_bindkey ("<backspace>", MENU_PAGER, OP_PREV_LINE);
4429 km_bindkey ("<pagedown>", MENU_PAGER, OP_NEXT_PAGE);
4430 km_bindkey ("<pageup>", MENU_PAGER, OP_PREV_PAGE);
1b5dcea5 4431diff -uNr mutt-1.4.orig/mailbox.h mutt-1.4/mailbox.h
4432--- mutt-1.4.orig/mailbox.h Wed Mar 20 10:53:34 2002
4433+++ mutt-1.4/mailbox.h Sun Nov 3 21:57:20 2002
4434@@ -73,6 +73,9 @@
4435 #ifdef USE_POP
4436 int mx_is_pop (const char *);
4437 #endif
4438+#ifdef USE_NNTP
4439+int mx_is_nntp (const char *);
4440+#endif
4441
4442 int mx_access (const char*, int);
4443
4444diff -uNr mutt-1.4.orig/main.c mutt-1.4/main.c
4445--- mutt-1.4.orig/main.c Sun Nov 3 21:42:51 2002
4446+++ mutt-1.4/main.c Sun Nov 3 21:57:20 2002
4447@@ -37,6 +37,10 @@
4448 #include <getopt.h>
4449 #endif
4450
4451+#ifdef USE_NNTP
4452+#include <nntp.h>
4453+#endif
4454+
4455 static const char *ReachingUs = N_("\
4456 To contact the developers, please mail to <mutt-dev@mutt.org>.\n\
4457 To report a bug, please use the flea(1) utility.\n");
4458@@ -97,6 +101,8 @@
4459 -e <command>\tspecify a command to be executed after initialization\n\
4460 -f <file>\tspecify which mailbox to read\n\
4461 -F <file>\tspecify an alternate muttrc file\n\
4462+ -g <server>\tspecify a newsserver (if compiled with NNTP)\n\
4463+ -G\t\tselect a newsgroup (if compiled with NNTP)\n\
4464 -H <file>\tspecify a draft file to read header from\n\
4465 -i <file>\tspecify a file which Mutt should include in the reply\n\
4466 -m <type>\tspecify a default mailbox type\n\
4467@@ -202,6 +208,12 @@
4468 "-USE_POP "
4469 #endif
4470
4471+#ifdef USE_NNTP
4472+ "+USE_NNTP "
4473+#else
4474+ "-USE_NNTP "
4475+#endif
4476+
4477 #ifdef USE_IMAP
4478 "+USE_IMAP "
4479 #else
4480@@ -444,6 +456,9 @@
4481 #define M_NOSYSRC (1<<2) /* -n */
4482 #define M_RO (1<<3) /* -R */
4483 #define M_SELECT (1<<4) /* -y */
4484+#ifdef USE_NNTP
4485+#define M_NEWS (1<<5) /* -g and -G */
4486+#endif
4487
4488 int main (int argc, char **argv)
4489 {
4490@@ -489,7 +504,11 @@
4491 memset (Options, 0, sizeof (Options));
4492 memset (QuadOptions, 0, sizeof (QuadOptions));
4493
4494+#ifdef USE_NNTP
4495+ while ((i = getopt (argc, argv, "a:b:F:f:c:d:e:H:s:i:hm:npRvxyg:GzZ")) != EOF)
4496+#else
4497 while ((i = getopt (argc, argv, "a:b:F:f:c:d:e:H:s:i:hm:npRvxyzZ")) != EOF)
4498+#endif
4499 switch (i)
4500 {
4501 case 'a':
4502@@ -571,6 +590,20 @@
4503 flags |= M_SELECT;
4504 break;
4505
4506+#ifdef USE_NNTP
4507+ case 'g': /* Specify a newsserver */
4508+ {
4509+ char buf[LONG_STRING];
4510+
4511+ snprintf (buf, sizeof (buf), "set news_server=%s", optarg);
4512+ commands = mutt_add_list (commands, buf);
4513+ }
4514+
4515+ case 'G': /* List of newsgroups */
4516+ flags |= M_SELECT | M_NEWS;
4517+ break;
4518+#endif
4519+
4520 case 'z':
4521 flags |= M_IGNORE;
4522 break;
4523@@ -802,6 +835,18 @@
4524 }
4525 else if (flags & M_SELECT)
4526 {
4527+#ifdef USE_NNTP
4528+ if (flags & M_NEWS)
4529+ {
4530+ set_option (OPTNEWS);
4531+ if(!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)))
4532+ {
4533+ mutt_endwin (Errorbuf);
4534+ exit (1);
4535+ }
4536+ }
4537+ else
4538+#endif
4539 if (!Incoming) {
4540 mutt_endwin _("No incoming mailboxes defined.");
4541 exit (1);
4542@@ -817,6 +862,15 @@
4543
4544 if (!folder[0])
4545 strfcpy (folder, NONULL(Spoolfile), sizeof (folder));
4546+
4547+#ifdef USE_NNTP
4548+ if (option (OPTNEWS))
4549+ {
4550+ unset_option (OPTNEWS);
4551+ nntp_expand_path (folder, sizeof (folder), &CurrentNewsSrv->conn->account);
4552+ }
4553+ else
4554+#endif
4555 mutt_expand_path (folder, sizeof (folder));
4556
4557 mutt_str_replace (&LastFolder, folder);
1b5dcea5 4558diff -uNr mutt-1.4.orig/mutt.h mutt-1.4/mutt.h
4559--- mutt-1.4.orig/mutt.h Sun Nov 3 21:42:52 2002
4560+++ mutt-1.4/mutt.h Sun Nov 3 21:57:20 2002
4561@@ -231,6 +231,9 @@
4562 M_PGP_KEY,
4563 #endif
4564 M_XLABEL,
4565+#ifdef USE_NNTP
4566+ M_NEWSGROUPS,
4567+#endif
4568
4569 /* Options for Mailcap lookup */
4570 M_EDIT,
4571@@ -266,6 +269,12 @@
4572 OPT_VERIFYSIG, /* verify PGP signatures */
4573 OPT_PGPTRADITIONAL, /* create old-style PGP messages */
4574 #endif
4575+#ifdef USE_NNTP
4576+ OPT_TOMODERATED,
4577+ OPT_NNTPRECONNECT,
4578+ OPT_CATCHUP,
4579+ OPT_FOLLOWUPTOPOSTER,
4580+#endif /* USE_NNTP */
4581
4582 #ifdef USE_SSL
4583 OPT_SSLSTARTTLS,
4584@@ -302,6 +311,7 @@
4585 #define SENDMAILX (1<<6)
4586 #define SENDKEY (1<<7)
4587 #define SENDRESEND (1<<8)
4588+#define SENDNEWS (1<<9)
4589
4590 /* flags to _mutt_select_file() */
4591 #define M_SEL_BUFFY (1<<0)
4592@@ -318,6 +328,8 @@
4593 OPTASCIICHARS,
4594 OPTASKBCC,
4595 OPTASKCC,
4596+ OPTASKFOLLOWUP,
4597+ OPTASKXCOMMENTTO,
4598 OPTATTACHSPLIT,
4599 OPTAUTOEDIT,
4600 OPTAUTOTAG,
4601@@ -376,6 +388,9 @@
4602 OPTMETOO,
4603 OPTMHPURGE,
4604 OPTMIMEFORWDECODE,
4605+#ifdef USE_NNTP
4606+ OPTMIMESUBJECT, /* encode subject line with RFC2047 */
4607+#endif
4608 OPTNARROWTREE,
4609 OPTPAGERSTOP,
4610 OPTPIPEDECODE,
4611@@ -445,6 +460,16 @@
4612 OPTPGPSHOWUNUSABLE,
4613 #endif
4614
4615+ /* news options */
4616+
4617+#ifdef USE_NNTP
4618+ OPTSHOWNEWNEWS,
4619+ OPTSHOWONLYUNREAD,
4620+ OPTSAVEUNSUB,
4621+ OPTLOADDESC,
4622+ OPTXCOMMENTTO,
4623+#endif /* USE_NNTP */
4624+
4625 /* pseudo options */
4626
4627 OPTAUXSORT, /* (pseudo) using auxillary sort function */
4628@@ -465,6 +490,7 @@
4629 OPTSORTSUBTHREADS, /* (pseudo) used when $sort_aux changes */
4630 OPTNEEDRESCORE, /* (pseudo) set when the `score' command is used */
4631 OPTATTACHMSG, /* (pseudo) used by attach-message */
4632+ OPTHIDEREAD, /* (pseudo) whether or not hide read messages */
4633 OPTKEEPQUIET, /* (pseudo) shut up the message and refresh
4634 * functions while we are executing an
4635 * external program.
4636@@ -475,6 +501,12 @@
4637 OPTDONTHANDLEPGPKEYS, /* (pseudo) used to extract PGP keys */
4638 #endif
4639
4640+#ifdef USE_NNTP
4641+ OPTNEWS, /* (pseudo) used to change reader mode */
4642+ OPTNEWSSEND, /* (pseudo) used to change behavior when posting */
4643+ OPTNEWSCACHE, /* (pseudo) used to indicate if news cache exist */
4644+#endif
4645+
4646
4647
4648
4649@@ -538,6 +570,13 @@
4650 char *supersedes;
4651 char *date;
4652 char *x_label;
4653+ char *organization;
4654+#ifdef USE_NNTP
4655+ char *newsgroups;
4656+ char *xref;
4657+ char *followup_to;
4658+ char *x_comment_to;
4659+#endif
4660 LIST *references; /* message references (in reverse order) */
4661 LIST *in_reply_to; /* in-reply-to header content */
4662 LIST *userhdrs; /* user defined headers */
4663@@ -685,6 +724,9 @@
4664 ENVELOPE *env; /* envelope information */
4665 BODY *content; /* list of MIME parts */
4666 char *path;
4667+#ifdef USE_NNTP
4668+ int article_num;
4669+#endif
4670
4671 char *tree; /* character string to print thread tree */
4672 struct thread *thread;
4673@@ -697,7 +739,7 @@
4674 int refno; /* message number on server */
4675 #endif
4676
4677-#if defined USE_POP || defined USE_IMAP
4678+#if defined USE_POP || defined USE_IMAP || defined USE_NNTP
4679 void *data; /* driver-specific data */
4680 #endif
4681 } HEADER;
4682@@ -768,7 +810,7 @@
4683 int appended; /* how many saved messages? */
4684 int flagged; /* how many flagged messages */
4685 int msgnotreadyet; /* which msg "new" in pager, -1 if none */
4686-#if defined USE_POP || defined USE_IMAP
4687+#if defined USE_POP || defined USE_IMAP || defined USE_NNTP
4688 void *data; /* driver specific data */
4689 #endif /* USE_IMAP */
4690
1b5dcea5 4691diff -uNr mutt-1.4.orig/muttlib.c mutt-1.4/muttlib.c
4692--- mutt-1.4.orig/muttlib.c Sun Nov 3 21:42:52 2002
4693+++ mutt-1.4/muttlib.c Sun Nov 3 21:57:20 2002
4694@@ -270,7 +270,7 @@
4695 #ifdef MIXMASTER
4696 mutt_free_list (&(*h)->chain);
4697 #endif
4698-#if defined USE_POP || defined USE_IMAP
4699+#if defined USE_POP || defined USE_IMAP || defined USE_NNTP
4700 safe_free ((void**) &(*h)->data);
4701 #endif
4702 safe_free ((void **) h);
4703@@ -648,6 +648,13 @@
4704 safe_free ((void **) &(*p)->message_id);
4705 safe_free ((void **) &(*p)->supersedes);
4706 safe_free ((void **) &(*p)->date);
4707+ safe_free ((void **) &(*p)->organization);
4708+#ifdef USE_NNTP
4709+ safe_free ((void **) &(*p)->newsgroups);
4710+ safe_free ((void **) &(*p)->xref);
4711+ safe_free ((void **) &(*p)->followup_to);
4712+ safe_free ((void **) &(*p)->x_comment_to);
4713+#endif
4714 mutt_free_list (&(*p)->references);
4715 mutt_free_list (&(*p)->in_reply_to);
4716 mutt_free_list (&(*p)->userhdrs);
4717@@ -1143,6 +1150,14 @@
4718 return 0;
4719 }
4720 #endif
4721+
4722+#ifdef USE_NNTP
4723+ if (magic == M_NNTP)
4724+ {
4725+ mutt_error _("Can't save message to newsserver.");
4726+ return 0;
4727+ }
4728+#endif
4729
4730 if (stat (s, st) != -1)
4731 {
4732diff -uNr mutt-1.4.orig/mx.c mutt-1.4/mx.c
4733--- mutt-1.4.orig/mx.c Sun Nov 3 21:42:52 2002
4734+++ mutt-1.4/mx.c Sun Nov 3 21:57:20 2002
4735@@ -42,6 +42,10 @@
4736 #include "pop.h"
4737 #endif
4738
4739+#ifdef USE_NNTP
4740+#include "nntp.h"
4741+#endif
4742+
4743 #ifdef BUFFY_SIZE
4744 #include "buffy.h"
4745 #endif
4746@@ -354,6 +358,22 @@
4747 }
4748 #endif
4749
4750+#ifdef USE_NNTP
4751+int mx_is_nntp (const char *p)
4752+{
4753+ url_scheme_t scheme;
4754+
4755+ if (!p)
4756+ return 0;
4757+
4758+ scheme = url_check_scheme (p);
4759+ if (scheme == U_NNTP || scheme == U_NNTPS)
4760+ return 1;
4761+
4762+ return 0;
4763+}
4764+#endif
4765+
4766 int mx_get_magic (const char *path)
4767 {
4768 struct stat st;
4769@@ -371,6 +391,11 @@
4770 return M_POP;
4771 #endif /* USE_POP */
4772
4773+#ifdef USE_NNTP
4774+ if (mx_is_nntp (path))
4775+ return M_NNTP;
4776+#endif /* USE_NNTP */
4777+
4778 if (stat (path, &st) == -1)
4779 {
4780 dprint (1, (debugfile, "mx_get_magic(): unable to stat %s: %s (errno %d).\n",
4781@@ -721,6 +746,12 @@
4782 break;
4783 #endif /* USE_POP */
4784
4785+#ifdef USE_NNTP
4786+ case M_NNTP:
4787+ rc = nntp_open_mailbox (ctx);
4788+ break;
4789+#endif /* USE_NNTP */
4790+
4791 default:
4792 rc = -1;
4793 break;
4794@@ -766,6 +797,10 @@
4795 if (ctx->magic == M_POP)
4796 pop_close_mailbox (ctx);
4797 #endif /* USE_POP */
4798+#ifdef USE_NNTP
4799+ if (ctx->magic == M_NNTP)
4800+ nntp_fastclose_mailbox (ctx);
4801+#endif /* USE_NNTP */
4802 if (ctx->id_hash)
4803 hash_destroy (&ctx->id_hash, NULL);
4804 mutt_clear_threads (ctx);
4805@@ -823,6 +858,12 @@
4806 rc = pop_sync_mailbox (ctx, index_hint);
4807 break;
4808 #endif /* USE_POP */
4809+
4810+#ifdef USE_NNTP
4811+ case M_NNTP:
4812+ rc = nntp_sync_mailbox (ctx);
4813+ break;
4814+#endif /* USE_NNTP */
4815 }
4816
4817 #if 0
4818@@ -899,6 +940,16 @@
4819
4820 ctx->closing = 1;
4821
4822+#ifdef USE_NNTP
4823+ if (ctx->magic == M_NNTP)
4824+ {
4825+ int ret;
4826+
4827+ ret = nntp_close_mailbox (ctx);
4828+ mx_fastclose_mailbox (ctx);
4829+ return ret;
4830+ }
4831+#endif
4832 if (ctx->readonly || ctx->dontwrite)
4833 {
4834 /* mailbox is readonly or we don't want to write */
4835@@ -1460,6 +1511,11 @@
4836 case M_POP:
4837 return (pop_check_mailbox (ctx, index_hint));
4838 #endif /* USE_POP */
4839+
4840+#ifdef USE_NNTP
4841+ case M_NNTP:
4842+ return (nntp_check_mailbox (ctx));
4843+#endif /* USE_NNTP */
4844 }
4845 }
4846
4847@@ -1520,6 +1576,15 @@
4848 }
4849 #endif /* USE_POP */
4850
4851+#ifdef USE_NNTP
4852+ case M_NNTP:
4853+ {
4854+ if (nntp_fetch_message (msg, ctx, msgno) != 0)
4855+ FREE (&msg);
4856+ break;
4857+ }
4858+#endif /* USE_NNTP */
4859+
4860 default:
4861 dprint (1, (debugfile, "mx_open_message(): function not implemented for mailbox type %d.\n", ctx->magic));
4862 FREE (&msg);
4863@@ -1608,6 +1673,9 @@
4864 #ifdef USE_POP
4865 || (*msg)->magic == M_POP
4866 #endif
4867+#ifdef USE_NNTP
4868+ || (*msg)->magic == M_NNTP
4869+#endif
4870 )
4871 {
4872 r = safe_fclose (&(*msg)->fp);
4873diff -uNr mutt-1.4.orig/mx.h mutt-1.4/mx.h
4874--- mutt-1.4.orig/mx.h Sun Nov 3 21:42:51 2002
4875+++ mutt-1.4/mx.h Sun Nov 3 21:57:20 2002
4876@@ -44,6 +44,9 @@
4877 #ifdef USE_COMPRESSED
4878 , M_COMPRESSED
4879 #endif
4880+#ifdef USE_NNTP
4881+ , M_NNTP
4882+#endif
4883 };
4884
4885 WHERE short DefaultMagic INITVAL (M_MBOX);
4886diff -uNr mutt-1.4.orig/newsrc.c mutt-1.4/newsrc.c
4887--- mutt-1.4.orig/newsrc.c Thu Jan 1 01:00:00 1970
4888+++ mutt-1.4/newsrc.c Sun Nov 3 21:57:20 2002
4889@@ -0,0 +1,1042 @@
4890+/*
4891+ * Copyright (C) 1998 Brandon Long <blong@fiction.net>
4892+ * Copyright (C) 1999 Andrej Gritsenko <andrej@lucky.net>
4893+ * Copyright (C) 2000-2001 Vsevolod Volkov <vvv@mutt.org.ua>
4894+ *
4895+ * This program is free software; you can redistribute it and/or modify
4896+ * it under the terms of the GNU General Public License as published by
4897+ * the Free Software Foundation; either version 2 of the License, or
4898+ * (at your option) any later version.
4899+ *
4900+ * This program is distributed in the hope that it will be useful,
4901+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4902+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4903+ * GNU General Public License for more details.
4904+ *
4905+ * You should have received a copy of the GNU General Public License
4906+ * along with this program; if not, write to the Free Software
4907+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4908+ */
4909+
4910+#include "mutt.h"
4911+#include "mutt_curses.h"
4912+#include "sort.h"
4913+#include "mx.h"
4914+#include "mime.h"
4915+#include "mailbox.h"
4916+#include "nntp.h"
4917+#include "rfc822.h"
4918+#include "rfc1524.h"
4919+#include "rfc2047.h"
4920+
4921+#include <unistd.h>
4922+#include <string.h>
4923+#include <ctype.h>
4924+#include <stdlib.h>
4925+#include <sys/stat.h>
4926+
4927+void nntp_add_to_list (NNTP_SERVER *s, NNTP_DATA *d)
4928+{
4929+ LIST *l;
4930+
4931+ if (!s || !d)
4932+ return;
4933+
4934+ l = safe_calloc (1, sizeof (LIST));
4935+ if (s->list)
4936+ s->tail->next = l;
4937+ else
4938+ s->list = l;
4939+ s->tail = l;
4940+ l->data = (void *) d;
4941+}
4942+
4943+static int nntp_parse_newsrc_line (NNTP_SERVER *news, char *line)
4944+{
4945+ NNTP_DATA *data;
4946+ char group[LONG_STRING];
4947+ int x = 1;
4948+ char *p = line, *b, *h;
4949+ size_t len;
4950+
4951+ while (*p)
4952+ {
4953+ if (*p++ == ',')
4954+ x++;
4955+ }
4956+
4957+ p = line;
4958+ while (*p && (*p != ':' && *p != '!')) p++;
4959+ if (!*p)
4960+ return -1;
4961+ len = p + 1 - line;
4962+ if (len > sizeof (group))
4963+ len = sizeof (group);
4964+ strfcpy (group, line, len);
4965+ if ((data = (NNTP_DATA *)hash_find (news->newsgroups, group)) == NULL)
4966+ {
4967+ data = (NNTP_DATA *) safe_calloc (1, sizeof (NNTP_DATA) + strlen (group) + 1);
4968+ data->group = (char *) data + sizeof (NNTP_DATA);
4969+ strcpy (data->group, group);
4970+ data->nserv = news;
4971+ data->deleted = 1;
4972+ if (news->newsgroups->nelem < news->newsgroups->curnelem * 2)
4973+ news->newsgroups = hash_resize (news->newsgroups, news->newsgroups->nelem * 2);
4974+ hash_insert (news->newsgroups, data->group, data, 0);
4975+ nntp_add_to_list (news, data);
4976+ }
4977+ else
4978+ FREE ((void **) &data->entries);
4979+
4980+ data->rc = 1;
4981+ data->entries = safe_calloc (x*2, sizeof (NEWSRC_ENTRY));
4982+ data->max = x*2;
4983+
4984+ if (*p == ':')
4985+ data->subscribed = 1;
4986+ else
4987+ data->subscribed = 0;
4988+
4989+ p++;
4990+ b = p;
4991+ x = 0;
4992+ while (*b)
4993+ {
4994+ while (*p && *p != ',' && *p != '\n') p++;
4995+ if (*p)
4996+ {
4997+ *p = '\0';
4998+ p++;
4999+ }
5000+ if ((h = strchr(b, '-')))
5001+ {
5002+ *h = '\0';
5003+ h++;
5004+ data->entries[x].first = atoi(b);
5005+ data->entries[x].last = atoi(h);
5006+ }
5007+ else
5008+ {
5009+ data->entries[x].first = atoi(b);
5010+ data->entries[x].last = data->entries[x].first;
5011+ }
5012+ b = p;
5013+ if (data->entries[x].last != 0)
5014+ x++;
5015+ }
5016+ if (x && !data->lastMessage)
5017+ data->lastMessage = data->entries[x-1].last;
5018+ data->num = x;
5019+ mutt_newsgroup_stat (data);
5020+ dprint (2, (debugfile, "parse_line: Newsgroup %s\n", data->group));
5021+
5022+ return 0;
5023+}
5024+
5025+static int slurp_newsrc (NNTP_SERVER *news)
5026+{
5027+ FILE *fp;
5028+ char *buf;
5029+ struct stat sb;
5030+
5031+ news->stat = stat (news->newsrc, &sb);
5032+ news->size = sb.st_size;
5033+ news->mtime = sb.st_mtime;
5034+
5035+ if ((fp = safe_fopen (news->newsrc, "r")) == NULL)
5036+ return -1;
5037+ /* hmm, should we use dotlock? */
5038+ if (mx_lock_file (news->newsrc, fileno (fp), 0, 0, 1))
5039+ {
5040+ fclose (fp);
5041+ return -1;
5042+ }
5043+
5044+ buf = safe_malloc (sb.st_size + 1);
5045+ while (fgets (buf, sb.st_size + 1, fp))
5046+ nntp_parse_newsrc_line (news, buf);
5047+ FREE (&buf);
5048+
5049+ mx_unlock_file (news->newsrc, fileno (fp), 0);
5050+ fclose (fp);
5051+ return 0;
5052+}
5053+
5054+void nntp_cache_expand (char *dst, const char *src)
5055+{
5056+ snprintf (dst, _POSIX_PATH_MAX, "%s/%s", NewsCacheDir, src);
5057+ mutt_expand_path (dst, _POSIX_PATH_MAX);
5058+}
5059+
5060+/* Loads $news_cache_dir/.index into memory, loads newsserver data
5061+ * and newsgroup cache names */
5062+static int nntp_parse_cacheindex (NNTP_SERVER *news)
5063+{
5064+ struct stat st;
5065+ char buf[HUGE_STRING], *cp;
5066+ char dir[_POSIX_PATH_MAX], file[_POSIX_PATH_MAX];
5067+ FILE *index;
5068+ NNTP_DATA *data;
5069+ int l, m, t;
5070+
5071+ /* check is server name defined or not */
5072+ if (!news || !news->conn || !news->conn->account.host)
5073+ return -1;
5074+ unset_option (OPTNEWSCACHE);
5075+ if (!NewsCacheDir || !*NewsCacheDir)
5076+ return 0;
5077+
5078+ strfcpy (dir, NewsCacheDir, sizeof (dir));
5079+ mutt_expand_path (dir, sizeof(dir));
5080+
5081+ if (lstat (dir, &st) || (st.st_mode & S_IFDIR) == 0)
5082+ {
5083+ snprintf (buf, sizeof(buf), _("Directory %s not exist. Create it?"), dir);
5084+ if (mutt_yesorno (buf, M_YES) != M_YES || mkdir (dir, (S_IRWXU+S_IRWXG+
5085+ S_IRWXO)))
5086+ {
5087+ mutt_error _("Cache directory not created!");
5088+ return -1;
5089+ }
5090+ mutt_clear_error();
5091+ }
5092+
5093+ set_option (OPTNEWSCACHE);
5094+
5095+ FREE (&news->cache);
5096+ snprintf (buf, sizeof(buf), "%s/.index", dir);
5097+ if (!(index = safe_fopen (buf, "a+")))
5098+ return 0;
5099+ rewind (index);
5100+ while (fgets (buf, sizeof(buf), index))
5101+ {
5102+ buf[strlen(buf) - 1] = 0; /* strip ending '\n' */
5103+ if (!mutt_strncmp (buf, "#: ", 3) &&
5104+ !mutt_strcasecmp (buf+3, news->conn->account.host))
5105+ break;
5106+ }
5107+ while (fgets (buf, sizeof(buf), index))
5108+ {
5109+ cp = buf;
5110+ while (*cp && *cp != ' ') cp++;
5111+ if (!*cp) continue;
5112+ cp[0] = 0;
5113+ if (!mutt_strcmp (buf, "#:"))
5114+ break;
5115+ sscanf (cp + 1, "%s %d %d", file, &l, &m);
5116+ if (!mutt_strcmp (buf, "ALL"))
5117+ {
5118+ news->cache = safe_strdup (file);
5119+ news->newgroups_time = m;
5120+ }
5121+ else if (news->newsgroups)
5122+ {
5123+ if ((data = (NNTP_DATA *)hash_find (news->newsgroups, buf)) == NULL)
5124+ {
5125+ data = (NNTP_DATA *) safe_calloc (1, sizeof (NNTP_DATA) + strlen (buf) + 1);
5126+ data->group = (char *) data + sizeof (NNTP_DATA);
5127+ strcpy(data->group, buf);
5128+ data->nserv = news;
5129+ data->deleted = 1;
5130+ if (news->newsgroups->nelem < news->newsgroups->curnelem * 2)
5131+ news->newsgroups = hash_resize (news->newsgroups, news->newsgroups->nelem * 2);
5132+ hash_insert (news->newsgroups, data->group, data, 0);
5133+ nntp_add_to_list (news, data);
5134+ }
5135+ data->cache = safe_strdup (file);
5136+ t = 0;
5137+ if (!data->firstMessage || data->lastMessage < m)
5138+ t = 1;
5139+ if (!data->firstMessage)
5140+ data->firstMessage = l;
5141+ if (data->lastMessage < m)
5142+ data->lastMessage = m;
5143+ data->lastCached = m;
5144+ if (t || !data->unread)
5145+ mutt_newsgroup_stat (data);
5146+ }
5147+ }
5148+ fclose (index);
5149+ return 0;
5150+}
5151+
5152+const char *
5153+nntp_format_str (char *dest, size_t destlen, char op, const char *src,
5154+ const char *fmt, const char *ifstring, const char *elsestring,
5155+ unsigned long data, format_flag flags)
5156+{
5157+ char fn[SHORT_STRING], tmp[SHORT_STRING];
5158+
5159+ switch (op)
5160+ {
5161+ case 's':
5162+ strncpy (fn, NewsServer, sizeof(fn) - 1);
5163+ mutt_strlower (fn);
5164+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
5165+ snprintf (dest, destlen, tmp, fn);
5166+ break;
5167+ }
5168+ return (src);
5169+}
5170+
5171+/* nntp_parse_url: given an NNPT URL, return host, port,
5172+ * username, password and newsgroup will recognise. */
5173+int nntp_parse_url (const char *server, ACCOUNT *acct,
5174+ char *group, size_t group_len)
5175+{
5176+ ciss_url_t url;
5177+ char *c;
5178+ int ret = -1;
5179+
5180+ /* Defaults */
5181+ acct->flags = 0;
5182+ acct->port = NNTP_PORT;
5183+ acct->type = M_ACCT_TYPE_NNTP;
5184+
5185+ c = safe_strdup (server);
5186+ url_parse_ciss (&url, c);
5187+
5188+ if (url.scheme == U_NNTP || url.scheme == U_NNTPS)
5189+ {
5190+ if (url.scheme == U_NNTPS)
5191+ {
5192+ acct->flags |= M_ACCT_SSL;
5193+ acct->port = NNTP_SSL_PORT;
5194+ }
5195+
5196+ *group = '\0';
5197+ if (url.path)
5198+ strfcpy (group, url.path, group_len);
5199+
5200+ ret = mutt_account_fromurl (acct, &url);
5201+ }
5202+
5203+ FREE (&c);
5204+ return ret;
5205+}
5206+
5207+void nntp_expand_path (char *line, size_t len, ACCOUNT *acct)
5208+{
5209+ ciss_url_t url;
5210+
5211+ url.path = safe_strdup (line);
5212+ mutt_account_tourl (acct, &url);
5213+ url_ciss_tostring (&url, line, len, 0);
5214+ FREE (&url.path);
5215+}
5216+
5217+/*
5218+ * Automatically loads a newsrc into memory, if necessary.
5219+ * Checks the size/mtime of a newsrc file, if it doesn't match, load
5220+ * again. Hmm, if a system has broken mtimes, this might mean the file
5221+ * is reloaded every time, which we'd have to fix.
5222+ *
5223+ * a newsrc file is a line per newsgroup, with the newsgroup, then a
5224+ * ':' denoting subscribed or '!' denoting unsubscribed, then a
5225+ * comma separated list of article numbers and ranges.
5226+ */
5227+NNTP_SERVER *mutt_select_newsserver (char *server)
5228+{
5229+ char file[_POSIX_PATH_MAX];
5230+ char *buf, *p;
5231+ LIST *list;
5232+ ACCOUNT acct;
5233+ NNTP_SERVER *serv;
5234+ CONNECTION *conn;
5235+
5236+ if (!server || !*server)
5237+ {
5238+ mutt_error _("No newsserver defined!");
5239+ return NULL;
5240+ }
5241+
5242+ buf = p = safe_calloc (strlen (server) + 10, sizeof (char));
5243+ if (url_check_scheme (server) == U_UNKNOWN)
5244+ {
5245+ strcpy (buf, "nntp://");
5246+ p = strchr (buf, '\0');
5247+ }
5248+ strcpy (p, server);
5249+
5250+ if ((nntp_parse_url (buf, &acct, file, sizeof (file))) < 0 || *file)
5251+ {
5252+ FREE (&buf);
5253+ mutt_error (_("%s is an invalid newsserver specification!"), server);
5254+ return NULL;
5255+ }
5256+ FREE (&buf);
5257+
5258+ conn = mutt_conn_find (NULL, &acct);
5259+ if (!conn)
5260+ return NULL;
5261+
5262+ mutt_FormatString (file, sizeof (file), NONULL (NewsRc), nntp_format_str, 0, 0);
5263+ mutt_expand_path (file, sizeof (file));
5264+
5265+ serv = (NNTP_SERVER *)conn->data;
5266+ if (serv)
5267+ {
5268+ struct stat sb;
5269+
5270+ /* externally modified? */
5271+ if (serv->stat != stat (file, &sb) || (!serv->stat &&
5272+ (serv->size != sb.st_size || serv->mtime != sb.st_mtime)))
5273+ {
5274+ for (list = serv->list; list; list = list->next)
5275+ {
5276+ NNTP_DATA *data = (NNTP_DATA *) list->data;
5277+
5278+ if (data)
5279+ {
5280+ data->subscribed = 0;
5281+ data->rc = 0;
5282+ data->num = 0;
5283+ }
5284+ }
5285+ slurp_newsrc (serv);
5286+ nntp_clear_cacheindex (serv);
5287+ }
5288+
5289+ if (serv->status == NNTP_BYE)
5290+ serv->status = NNTP_NONE;
5291+ nntp_check_newgroups (serv, 0);
5292+ return serv;
5293+ }
5294+
5295+ /* New newsserver */
5296+ serv = safe_calloc (1, sizeof (NNTP_SERVER));
5297+ serv->conn = conn;
5298+ serv->newsrc = safe_strdup (file);
5299+ serv->newsgroups = hash_create (1009);
5300+ slurp_newsrc (serv); /* load .newsrc */
5301+ nntp_parse_cacheindex (serv); /* load .index */
5302+ if (option (OPTNEWSCACHE) && serv->cache && nntp_get_cache_all (serv) >= 0)
5303+ nntp_check_newgroups (serv, 1);
5304+ else if (nntp_get_active (serv) < 0)
5305+ {
5306+ hash_destroy (&serv->newsgroups, nntp_delete_data);
5307+ for (list = serv->list; list; list = list->next)
5308+ list->data = NULL;
5309+ mutt_free_list (&serv->list);
5310+ FREE (&serv->newsrc);
5311+ FREE (&serv->cache);
5312+ FREE (&serv);
5313+ return NULL;
5314+ }
5315+ nntp_clear_cacheindex (serv);
5316+ conn->data = (void *)serv;
5317+
5318+ return serv;
5319+}
5320+
5321+/*
5322+ * full status flags are not supported by nntp, but we can fake some
5323+ * of them. This is how:
5324+ * Read = a read message number is in the .newsrc
5325+ * New = a message is new since we last read this newsgroup
5326+ * Old = anything else
5327+ * So, Read is marked as such in the newsrc, old is anything that is
5328+ * "skipped" in the newsrc, and new is anything not in the newsrc nor
5329+ * in the cache. By skipped, I mean before the last unread message
5330+ */
5331+void nntp_get_status (CONTEXT *ctx, HEADER *h, char *group, int article)
5332+{
5333+ NNTP_DATA *data = (NNTP_DATA *) ctx->data;
5334+ int x;
5335+
5336+ if (group)
5337+ data = (NNTP_DATA *) hash_find (data->nserv->newsgroups, group);
5338+
5339+ if (!data)
5340+ {
5341+#ifdef DEBUG
5342+ if (group)
5343+ dprint (3, (debugfile, "newsgroup %s not found\n", group));
5344+#endif
5345+ return;
5346+ }
5347+
5348+ for (x = 0; x < data->num; x++)
5349+ {
5350+ if ((article >= data->entries[x].first) &&
5351+ (article <= data->entries[x].last))
5352+ {
5353+ /* we cannot use mutt_set_flag() because mx_update_context()
5354+ didn't called yet */
5355+ h->read = 1;
5356+ return;
5357+ }
5358+ }
5359+ /* If article was not cached yet, it is new! :) */
5360+ if (!data->cache || article > data->lastCached)
5361+ return;
5362+ /* Old articles are articles which aren't read but an article after them
5363+ * has been cached */
5364+ if (option (OPTMARKOLD))
5365+ h->old = 1;
5366+}
5367+
5368+void mutt_newsgroup_stat (NNTP_DATA *data)
5369+{
5370+ int i;
5371+ unsigned int first, last;
5372+
5373+ data->unread = 0;
5374+ if (data->lastMessage == 0 || data->firstMessage > data->lastMessage)
5375+ return;
5376+
5377+ data->unread = data->lastMessage - data->firstMessage + 1;
5378+ for (i = 0; i < data->num; i++)
5379+ {
5380+ first = data->entries[i].first;
5381+ if (first < data->firstMessage)
5382+ first = data->firstMessage;
5383+ last = data->entries[i].last;
5384+ if (last > data->lastMessage)
5385+ last = data->lastMessage;
5386+ if (first <= last)
5387+ data->unread -= last - first + 1;
5388+ }
5389+}
5390+
5391+static int puti (char *line, int num)
5392+{
5393+ char *p, s[32];
5394+
5395+ for (p = s; num; )
5396+ {
5397+ *p++ = '0' + num % 10;
5398+ num /= 10;
5399+ }
5400+ while (p > s)
5401+ *line++ = *--p, num++;
5402+ *line = '\0';
5403+ return num;
5404+}
5405+
5406+static void nntp_create_newsrc_line (NNTP_DATA *data, char **buf, char **pline, size_t *buflen)
5407+{
5408+ char *line = *pline;
5409+ size_t len = *buflen - (*pline - *buf);
5410+ int x, i;
5411+
5412+ if (len < LONG_STRING * 10)
5413+ {
5414+ len += *buflen;
5415+ *buflen *= 2;
5416+ line = *buf;
5417+ safe_realloc ((void **) buf, *buflen);
5418+ line = *buf + (*pline - line);
5419+ }
5420+ strcpy (line, data->group);
5421+ len -= strlen (line) + 1;
5422+ line += strlen (line);
5423+ *line++ = data->subscribed ? ':' : '!';
5424+ *line = '\0';
5425+
5426+ for (x = 0; x < data->num; x++)
5427+ {
5428+ if (len < LONG_STRING)
5429+ {
5430+ len += *buflen;
5431+ *buflen *= 2;
5432+ *pline = line;
5433+ line = *buf;
5434+ safe_realloc ((void **) buf, *buflen);
5435+ line = *buf + (*pline - line);
5436+ }
5437+ if (x)
5438+ {
5439+ *line++ = ',';
5440+ len--;
5441+ }
5442+
5443+#if 0
5444+ if (data->entries[x].first == data->entries[x].last)
5445+ snprintf (line, len, "%d%n", data->entries[x].first, &i);
5446+ else
5447+ snprintf (line, len, "%d-%d%n",
5448+ data->entries[x].first, data->entries[x].last, &i);
5449+ len -= i;
5450+ line += i;
5451+#else
5452+ i = puti (line, data->entries[x].first);
5453+ line +=i; len -= i;
5454+ if (data->entries[x].first != data->entries[x].last)
5455+ {
5456+ *line++ = '-';
5457+ len--;
5458+ i = puti (line, data->entries[x].last);
5459+ line +=i; len -= i;
5460+ }
5461+#endif
5462+ }
5463+ *line++ = '\n';
5464+ *line = '\0';
5465+ *pline = line;
5466+}
5467+
5468+void newsrc_gen_entries (CONTEXT *ctx)
5469+{
5470+ NNTP_DATA *data = (NNTP_DATA *)ctx->data;
5471+ int series, x;
5472+ unsigned int last = 0, first = 1;
5473+ int save_sort = SORT_ORDER;
5474+
5475+ if (Sort != SORT_ORDER)
5476+ {
5477+ save_sort = Sort;
5478+ Sort = SORT_ORDER;
5479+ mutt_sort_headers (ctx, 0);
5480+ }
5481+
5482+ if (!data->max)
5483+ {
5484+ data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY));
5485+ data->max = 5;
5486+ }
5487+
5488+ /*
5489+ * Set up to fake initial sequence from 1 to the article before the
5490+ * first article in our list
5491+ */
5492+ data->num = 0;
5493+ series = 1;
5494+
5495+ for (x = 0; x < ctx->msgcount; x++)
5496+ {
5497+ if (series) /* search for first unread */
5498+ {
5499+ /*
5500+ * We don't actually check sequential order, since we mark
5501+ * "missing" entries as read/deleted
5502+ */
5503+ last = ctx->hdrs[x]->article_num;
5504+ if (last >= data->firstMessage && !ctx->hdrs[x]->deleted &&
5505+ !ctx->hdrs[x]->read)
5506+ {
5507+ if (data->num >= data->max)
5508+ {
5509+ data->max = data->max * 2;
5510+ safe_realloc ((void **)&data->entries,
5511+ data->max * sizeof (NEWSRC_ENTRY));
5512+ }
5513+ data->entries[data->num].first = first;
5514+ data->entries[data->num].last = last - 1;
5515+ data->num++;
5516+ series = 0;
5517+ }
5518+ }
5519+ else /* search for first read */
5520+ {
5521+ if (ctx->hdrs[x]->deleted || ctx->hdrs[x]->read)
5522+ {
5523+ first = last + 1;
5524+ series = 1;
5525+ }
5526+ last = ctx->hdrs[x]->article_num;
5527+ }
5528+ }
5529+ if (series && first <= data->lastLoaded)
5530+ {
5531+ if (data->num >= data->max)
5532+ {
5533+ data->max = data->max * 2;
5534+ safe_realloc ((void **)&data->entries,
5535+ data->max * sizeof (NEWSRC_ENTRY));
5536+ }
5537+ data->entries[data->num].first = first;
5538+ data->entries[data->num].last = data->lastLoaded;
5539+ data->num++;
5540+ }
5541+
5542+ if (save_sort != Sort)
5543+ {
5544+ Sort = save_sort;
5545+ mutt_sort_headers (ctx, 0);
5546+ }
5547+}
5548+
5549+int mutt_newsrc_update (NNTP_SERVER *news)
5550+{
5551+ char *buf, *line;
5552+ NNTP_DATA *data;
5553+ LIST *tmp;
5554+ int r = -1;
5555+ size_t len, llen;
5556+
5557+ if (!news)
5558+ return -1;
5559+ llen = len = 10 * LONG_STRING;
5560+ line = buf = safe_calloc (1, len);
5561+ /* we will generate full newsrc here */
5562+ for (tmp = news->list; tmp; tmp = tmp->next)
5563+ {
5564+ data = (NNTP_DATA *) tmp->data;
5565+ if (!data || !data->rc)
5566+ continue;
5567+ nntp_create_newsrc_line (data, &buf, &line, &llen);
5568+ dprint (2, (debugfile, "Added to newsrc: %s", line));
5569+ line += strlen (line);
5570+ }
5571+ /* newrc being fully rewritten */
5572+ if (news->newsrc &&
5573+ (r = mutt_update_list_file (news->newsrc, NULL, "", buf)) == 0)
5574+ {
5575+ struct stat st;
5576+
5577+ stat (news->newsrc, &st);
5578+ news->size = st.st_size;
5579+ news->mtime = st.st_mtime;
5580+ }
5581+ FREE (&buf);
5582+ return r;
5583+}
5584+
5585+static FILE *mutt_mkname (char *s)
5586+{
5587+ char buf[_POSIX_PATH_MAX], *pc;
5588+ int fd;
5589+ FILE *fp;
5590+
5591+ nntp_cache_expand (buf, s);
5592+ if ((fp = safe_fopen (buf, "w")))
5593+ return fp;
5594+
5595+ nntp_cache_expand (buf, "cache-XXXXXX");
5596+ pc = buf + strlen (buf) - 12; /* positioning to "cache-XXXXXX" */
5597+ if ((fd = mkstemp (buf)) == -1)
5598+ return NULL;
5599+ strcpy (s, pc); /* generated name */
5600+ return fdopen (fd, "w");
5601+}
5602+
5603+/* Updates info into .index file: ALL or about selected newsgroup */
5604+static int nntp_update_cacheindex (NNTP_SERVER *serv, NNTP_DATA *data)
5605+{
5606+ char buf[LONG_STRING], *key = "ALL";
5607+ char file[_POSIX_PATH_MAX];
5608+
5609+ if (!serv || !serv->conn || !serv->conn->account.host)
5610+ return -1;
5611+
5612+ if (data && data->group)
5613+ {
5614+ key = data->group;
5615+ snprintf (buf, sizeof (buf), "%s %s %d %d", key, data->cache,
5616+ data->firstMessage, data->lastLoaded);
5617+ }
5618+ else
5619+ {
5620+ strfcpy (file, serv->cache, sizeof (file));
5621+ snprintf (buf, sizeof (buf), "ALL %s 0 %d", file, (int)serv->newgroups_time);
5622+ }
5623+ nntp_cache_expand (file, ".index");
5624+ return mutt_update_list_file (file, serv->conn->account.host, key, buf);
5625+}
5626+
5627+/* Remove cache files of unsubscribed newsgroups */
5628+void nntp_clear_cacheindex (NNTP_SERVER *news)
5629+{
5630+ NNTP_DATA *data;
5631+ LIST *tmp;
5632+
5633+ if (option (OPTSAVEUNSUB) || !news)
5634+ return;
5635+
5636+ for (tmp = news->list; tmp; tmp = tmp->next)
5637+ {
5638+ data = (NNTP_DATA *) tmp->data;
5639+ if (!data || data->subscribed || !data->cache)
5640+ continue;
5641+ nntp_delete_cache (data);
5642+ dprint (2, (debugfile, "Removed from .index: %s\n", data->group));
5643+ }
5644+ return;
5645+}
5646+
5647+int nntp_save_cache_index (NNTP_SERVER *news)
5648+{
5649+ char buf[HUGE_STRING];
5650+ char file[_POSIX_PATH_MAX];
5651+ NNTP_DATA *d;
5652+ FILE *f;
5653+ LIST *l;
5654+
5655+ if (!news || !news->newsgroups)
5656+ return -1;
5657+ if (!option (OPTNEWSCACHE))
5658+ return 0;
5659+
5660+ if (news->cache)
5661+ {
5662+ nntp_cache_expand (file, news->cache);
5663+ unlink (file);
5664+ f = safe_fopen (file, "w");
5665+ }
5666+ else
5667+ {
5668+ strfcpy (buf, news->conn->account.host, sizeof(buf));
5669+ f = mutt_mkname (buf);
5670+ news->cache = safe_strdup (buf);
5671+ nntp_cache_expand (file, buf);
5672+ }
5673+ if (!f)
5674+ return -1;
5675+
5676+ for (l = news->list; l; l = l->next)
5677+ {
5678+ if ((d = (NNTP_DATA *)l->data) && !d->deleted)
5679+ {
5680+ if (d->desc)
5681+ snprintf (buf, sizeof(buf), "%s %d %d %c %s\n", d->group,
5682+ d->lastMessage, d->firstMessage, d->allowed ? 'y' : 'n',
5683+ d->desc);
5684+ else
5685+ snprintf (buf, sizeof(buf), "%s %d %d %c\n", d->group,
5686+ d->lastMessage, d->firstMessage, d->allowed ? 'y' : 'n');
5687+ if (fputs (buf, f) == EOF)
5688+ {
5689+ fclose (f);
5690+ unlink (file);
5691+ return -1;
5692+ }
5693+ }
5694+ }
5695+ fclose (f);
5696+
5697+ if (nntp_update_cacheindex (news, NULL))
5698+ {
5699+ unlink (file);
5700+ return -1;
5701+ }
5702+ return 0;
5703+}
5704+
5705+int nntp_save_cache_group (CONTEXT *ctx)
5706+{
5707+ char buf[HUGE_STRING], addr[STRING];
5708+ char file[_POSIX_PATH_MAX];
5709+ FILE *f;
5710+ HEADER *h;
5711+ struct tm *tm;
5712+ int i = 0, save = SORT_ORDER;
5713+ int prev = 0;
5714+
5715+ if (!option (OPTNEWSCACHE))
5716+ return 0;
5717+ if (!ctx || !ctx->data || ctx->magic != M_NNTP)
5718+ return -1;
5719+
5720+ if (((NNTP_DATA *)ctx->data)->cache)
5721+ {
5722+ nntp_cache_expand (file, ((NNTP_DATA *)ctx->data)->cache);
5723+ unlink (file);
5724+ f = safe_fopen (file, "w");
5725+ }
5726+ else
5727+ {
5728+ snprintf (buf, sizeof(buf), "%s-%s",
5729+ ((NNTP_DATA *)ctx->data)->nserv->conn->account.host,
5730+ ((NNTP_DATA *)ctx->data)->group);
5731+ f = mutt_mkname (buf);
5732+ ((NNTP_DATA *)ctx->data)->cache = safe_strdup (buf);
5733+ nntp_cache_expand (file, buf);
5734+ }
5735+ if (!f)
5736+ return -1;
5737+
5738+ if (Sort != SORT_ORDER)
5739+ {
5740+ save = Sort;
5741+ Sort = SORT_ORDER;
5742+ mutt_sort_headers (ctx, 0);
5743+ }
5744+
5745+ /* Save only $nntp_context messages... */
5746+ ((NNTP_DATA *)ctx->data)->lastCached = 0;
5747+ if (NntpContext && ctx->msgcount > NntpContext)
5748+ i = ctx->msgcount - NntpContext;
5749+ for (; i < ctx->msgcount; i++)
5750+ {
5751+ if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->article_num != prev)
5752+ {
5753+ h = ctx->hdrs[i];
5754+ addr[0] = 0;
5755+ rfc822_write_address (addr, sizeof(addr), h->env->from);
5756+ tm = gmtime (&h->date_sent);
5757+ snprintf (buf, sizeof(buf),
5758+ "%d\t%s\t%s\t%d %s %d %02d:%02d:%02d GMT\t%s\t",
5759+ h->article_num, h->env->subject, addr, tm->tm_mday,
5760+ Months[tm->tm_mon], tm->tm_year+1900, tm->tm_hour, tm->tm_min,
5761+ tm->tm_sec, h->env->message_id);
5762+ fputs (buf, f);
5763+ if (h->env->references)
5764+ mutt_write_references (h->env->references, f);
5765+ snprintf (buf, sizeof(buf), "\t%ld\t%d\tXref: %s\n", h->content->length,
5766+ h->lines, NONULL(h->env->xref));
5767+ if (fputs (buf, f) == EOF)
5768+ {
5769+ fclose (f);
5770+ unlink (file);
5771+ return -1;
5772+ }
5773+ }
5774+ prev = ctx->hdrs[i]->article_num;
5775+ }
5776+
5777+ if (save != Sort)
5778+ {
5779+ Sort = save;
5780+ mutt_sort_headers (ctx, 0);
5781+ }
5782+ fclose (f);
5783+
5784+ if (nntp_update_cacheindex (((NNTP_DATA *)ctx->data)->nserv,
5785+ (NNTP_DATA *)ctx->data))
5786+ {
5787+ unlink (file);
5788+ return -1;
5789+ }
5790+ ((NNTP_DATA *)ctx->data)->lastCached = ((NNTP_DATA *)ctx->data)->lastLoaded;
5791+ return 0;
5792+}
5793+
5794+void nntp_delete_cache (NNTP_DATA *data)
5795+{
5796+ char buf[_POSIX_PATH_MAX];
5797+
5798+ if (!option (OPTNEWSCACHE) || !data || !data->cache || !data->nserv)
5799+ return;
5800+
5801+ nntp_cache_expand (buf, data->cache);
5802+ unlink (buf);
5803+ FREE (&data->cache);
5804+ data->lastCached = 0;
5805+ nntp_cache_expand (buf, ".index");
5806+ mutt_update_list_file (buf, data->nserv->conn->account.host, data->group, NULL);
5807+}
5808+
5809+NNTP_DATA *mutt_newsgroup_subscribe (NNTP_SERVER *news, char *group)
5810+{
5811+ NNTP_DATA *data;
5812+
5813+ if (!news || !news->newsgroups || !group || !*group)
5814+ return NULL;
5815+ if (!(data = (NNTP_DATA *)hash_find (news->newsgroups, group)))
5816+ {
5817+ data = (NNTP_DATA *) safe_calloc (1, sizeof (NNTP_DATA) + strlen (group) + 1);
5818+ data->group = (char *) data + sizeof (NNTP_DATA);
5819+ strcpy (data->group, group);
5820+ data->nserv = news;
5821+ data->deleted = 1;
5822+ if (news->newsgroups->nelem < news->newsgroups->curnelem * 2)
5823+ news->newsgroups = hash_resize (news->newsgroups, news->newsgroups->nelem * 2);
5824+ hash_insert (news->newsgroups, data->group, data, 0);
5825+ nntp_add_to_list (news, data);
5826+ }
5827+ if (!data->subscribed)
5828+ {
5829+ data->subscribed = 1;
5830+ data->rc = 1;
5831+ }
5832+ return data;
5833+}
5834+
5835+NNTP_DATA *mutt_newsgroup_unsubscribe (NNTP_SERVER *news, char *group)
5836+{
5837+ NNTP_DATA *data;
5838+
5839+ if (!news || !news->newsgroups || !group || !*group ||
5840+ !(data = (NNTP_DATA *)hash_find (news->newsgroups, group)))
5841+ return NULL;
5842+ if (data->subscribed)
5843+ {
5844+ data->subscribed = 0;
5845+ if (!option (OPTSAVEUNSUB))
5846+ data->rc = 0;
5847+ }
5848+ return data;
5849+}
5850+
5851+NNTP_DATA *mutt_newsgroup_catchup (NNTP_SERVER *news, char *group)
5852+{
5853+ NNTP_DATA *data;
5854+
5855+ if (!news || !news->newsgroups || !group || !*group ||
5856+ !(data = (NNTP_DATA *)hash_find (news->newsgroups, group)))
5857+ return NULL;
5858+ if (!data->max)
5859+ {
5860+ data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY));
5861+ data->max = 5;
5862+ }
5863+ data->num = 1;
5864+ data->entries[0].first = 1;
5865+ data->unread = 0;
5866+ data->entries[0].last = data->lastMessage;
5867+ if (Context && Context->data == data)
5868+ {
5869+ int x;
5870+
5871+ for (x = 0; x < Context->msgcount; x++)
5872+ mutt_set_flag (Context, Context->hdrs[x], M_READ, 1);
5873+ }
5874+ return data;
5875+}
5876+
5877+NNTP_DATA *mutt_newsgroup_uncatchup (NNTP_SERVER *news, char *group)
5878+{
5879+ NNTP_DATA *data;
5880+
5881+ if (!news || !news->newsgroups || !group || !*group ||
5882+ !(data = (NNTP_DATA *)hash_find (news->newsgroups, group)))
5883+ return NULL;
5884+ if (!data->max)
5885+ {
5886+ data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY));
5887+ data->max = 5;
5888+ }
5889+ data->num = 1;
5890+ data->entries[0].first = 1;
5891+ data->entries[0].last = data->firstMessage - 1;
5892+ if (Context && Context->data == data)
5893+ {
5894+ int x;
5895+
5896+ data->unread = Context->msgcount;
5897+ for (x = 0; x < Context->msgcount; x++)
5898+ mutt_set_flag (Context, Context->hdrs[x], M_READ, 0);
5899+ }
5900+ else
5901+ data->unread = data->lastMessage - data->entries[0].last;
5902+ return data;
5903+}
5904+
5905+/* this routine gives the first newsgroup with new messages */
5906+void nntp_buffy (char *s)
5907+{
5908+ LIST *list;
5909+
5910+ for (list = CurrentNewsSrv->list; list; list = list->next)
5911+ {
5912+ NNTP_DATA *data = (NNTP_DATA *) list->data;
5913+
5914+ if (data && data->subscribed && data->unread)
5915+ {
5916+ if (Context && Context->magic == M_NNTP &&
5917+ !mutt_strcmp (data->group, ((NNTP_DATA *) Context->data)->group))
5918+ {
5919+ unsigned int i, unread = 0;
5920+
5921+ for (i = 0; i < Context->msgcount; i++)
5922+ if (!Context->hdrs[i]->read && !Context->hdrs[i]->deleted)
5923+ unread++;
5924+ if (!unread)
5925+ continue;
5926+ }
5927+ strcpy (s, data->group);
5928+ break;
5929+ }
5930+ }
5931+}
5932diff -uNr mutt-1.4.orig/nntp.c mutt-1.4/nntp.c
5933--- mutt-1.4.orig/nntp.c Thu Jan 1 01:00:00 1970
5934+++ mutt-1.4/nntp.c Sun Nov 3 21:57:20 2002
5935@@ -0,0 +1,1526 @@
5936+/*
5937+ * Copyright (C) 1998 Brandon Long <blong@fiction.net>
5938+ * Copyright (C) 1999 Andrej Gritsenko <andrej@lucky.net>
5939+ * Copyright (C) 2000-2002 Vsevolod Volkov <vvv@mutt.org.ua>
5940+ *
5941+ * This program is free software; you can redistribute it and/or modify
5942+ * it under the terms of the GNU General Public License as published by
5943+ * the Free Software Foundation; either version 2 of the License, or
5944+ * (at your option) any later version.
5945+ *
5946+ * This program is distributed in the hope that it will be useful,
5947+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5948+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5949+ * GNU General Public License for more details.
5950+ *
5951+ * You should have received a copy of the GNU General Public License
5952+ * along with this program; if not, write to the Free Software
5953+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5954+ */
5955+
5956+#include "mutt.h"
5957+#include "mutt_curses.h"
5958+#include "sort.h"
5959+#include "mx.h"
5960+#include "mime.h"
5961+#include "rfc1524.h"
5962+#include "rfc2047.h"
5963+#include "mailbox.h"
5964+#include "nntp.h"
5965+
5966+#ifdef HAVE_PGP
5967+#include "pgp.h"
5968+#endif
5969+
5970+#include <unistd.h>
5971+#include <string.h>
5972+#include <ctype.h>
5973+#include <stdlib.h>
5974+
5975+static unsigned int _checked = 0;
5976+
5977+#ifdef DEBUG
5978+static void nntp_error (const char *where, const char *msg)
5979+{
5980+ dprint (1, (debugfile, "nntp_error(): unexpected response in %s: %s\n", where, msg));
5981+}
5982+#endif /* DEBUG */
5983+
5984+static int nntp_connect_error (NNTP_SERVER *serv)
5985+{
5986+ serv->status = NNTP_NONE;
5987+ mutt_socket_close (serv->conn);
5988+ mutt_error _("Server closed connection!");
5989+ sleep (2);
5990+ return -1;
5991+}
5992+
5993+static int nntp_connect_and_auth (NNTP_SERVER *serv)
5994+{
5995+ CONNECTION *conn = serv->conn;
5996+ char buf[STRING];
5997+ unsigned char flags = conn->account.flags;
5998+
5999+ serv->status = NNTP_NONE;
6000+
6001+ if (mutt_socket_open (conn) < 0)
6002+ return -1;
6003+
6004+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
6005+ return nntp_connect_error (serv);
6006+
6007+ if (!mutt_strncmp ("200", buf, 3))
6008+ mutt_message (_("Connected to %s. Posting ok."), conn->account.host);
6009+ else if (!mutt_strncmp ("201", buf, 3))
6010+ mutt_message (_("Connected to %s. Posting NOT ok."), conn->account.host);
6011+ else
6012+ {
6013+ mutt_socket_close (conn);
6014+ mutt_remove_trailing_ws (buf);
6015+ mutt_error ("%s", buf);
6016+ sleep (2);
6017+ return -1;
6018+ }
6019+
6020+ sleep (1);
6021+
6022+ /* Tell INN to switch to mode reader if it isn't so. Ignore all
6023+ returned codes and messages. */
6024+ mutt_socket_write (conn, "MODE READER\r\n");
6025+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
6026+ return nntp_connect_error (serv);
6027+
6028+ mutt_socket_write (conn, "STAT\r\n");
6029+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
6030+ return nntp_connect_error (serv);
6031+
6032+ if (!(conn->account.flags & M_ACCT_USER) && mutt_strncmp ("480", buf, 3))
6033+ {
6034+ serv->status = NNTP_OK;
6035+ return 0;
6036+ }
6037+
6038+ if (mutt_account_getuser (&conn->account) || !conn->account.user[0] ||
6039+ mutt_account_getpass (&conn->account) || !conn->account.pass[0])
6040+ {
6041+ mutt_socket_close (conn);
6042+ serv->status = NNTP_BYE;
6043+ conn->account.flags = flags;
6044+ return -1;
6045+ }
6046+
6047+ mutt_message _("Logging in...");
6048+
6049+ snprintf (buf, sizeof (buf), "AUTHINFO USER %s\r\n", conn->account.user);
6050+ mutt_socket_write (conn, buf);
6051+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
6052+ {
6053+ conn->account.flags = flags;
6054+ return nntp_connect_error (serv);
6055+ }
6056+
6057+#ifdef DEBUG
6058+ /* don't print the password unless we're at the ungodly debugging level */
6059+ if (debuglevel < M_SOCK_LOG_FULL)
6060+ dprint (M_SOCK_LOG_CMD, (debugfile, "> AUTHINFO PASS *\n"));
6061+#endif
6062+ snprintf (buf, sizeof (buf), "AUTHINFO PASS %s\r\n", conn->account.pass);
6063+ mutt_socket_write_d (conn, buf, M_SOCK_LOG_FULL);
6064+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
6065+ {
6066+ conn->account.flags = flags;
6067+ return nntp_connect_error (serv);
6068+ }
6069+
6070+ if (!mutt_strncmp ("281", buf, 3))
6071+ {
6072+ serv->status = NNTP_OK;
6073+ return 0;
6074+ }
6075+
6076+ mutt_socket_close (conn);
6077+ conn->account.flags = flags;
6078+ mutt_error _("Login failed.");
6079+ sleep (2);
6080+ return -1;
6081+}
6082+
6083+static int nntp_attempt_features (NNTP_SERVER *serv)
6084+{
6085+ char buf[LONG_STRING];
6086+ CONNECTION *conn = serv->conn;
6087+
6088+ mutt_socket_write (conn, "XOVER\r\n");
6089+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
6090+ return nntp_connect_error (serv);
6091+ if (mutt_strncmp ("500", buf, 3))
6092+ serv->hasXOVER = 1;
6093+
6094+ mutt_socket_write (conn, "XPAT\r\n");
6095+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
6096+ return nntp_connect_error (serv);
6097+ if (mutt_strncmp ("500", buf, 3))
6098+ serv->hasXPAT = 1;
6099+
6100+ mutt_socket_write (conn, "XGTITLE +\r\n");
6101+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
6102+ return nntp_connect_error (serv);
6103+ if (mutt_strncmp ("500", buf, 3))
6104+ serv->hasXGTITLE = 1;
6105+
6106+ if (!mutt_strncmp ("282", buf, 3))
6107+ {
6108+ do
6109+ {
6110+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0)
6111+ return nntp_connect_error (serv);
6112+ } while (!(buf[0] == '.' && buf[1] == '\0'));
6113+ }
6114+
6115+ return 0;
6116+}
6117+
6118+static int nntp_open_connection (NNTP_SERVER *serv)
6119+{
6120+ if (serv->status == NNTP_OK)
6121+ return 0;
6122+ if (serv->status == NNTP_BYE)
6123+ return -1;
6124+ if (nntp_connect_and_auth (serv) < 0)
6125+ return -1;
6126+ if (nntp_attempt_features (serv) < 0)
6127+ return -1;
6128+ return 0;
6129+}
6130+
6131+static int nntp_reconnect (NNTP_SERVER *serv)
6132+{
6133+ char buf[SHORT_STRING];
6134+
6135+ mutt_socket_close (serv->conn);
6136+
6137+ FOREVER
6138+ {
6139+ if (nntp_connect_and_auth (serv) == 0)
6140+ return 0;
6141+
6142+ snprintf (buf, sizeof (buf), _("Connection to %s lost. Reconnect?"),
6143+ serv->conn->account.host);
6144+ if (query_quadoption (OPT_NNTPRECONNECT, buf) != M_YES)
6145+ {
6146+ serv->status = NNTP_BYE;
6147+ return -1;
6148+ }
6149+ }
6150+}
6151+
6152+/* Send data from line[LONG_STRING] and receive answer to same line */
6153+static int mutt_nntp_query (NNTP_DATA *data, char *line, size_t linelen)
6154+{
6155+ char buf[LONG_STRING];
6156+ int done = TRUE;
6157+
6158+ if (data->nserv->status == NNTP_BYE)
6159+ return -1;
6160+
6161+ do
6162+ {
6163+ if (!*line && data->group)
6164+ {
6165+ snprintf (buf, sizeof (buf), "GROUP %s\r\n", data->group);
6166+ mutt_socket_write (data->nserv->conn, buf);
6167+ }
6168+ else
6169+ mutt_socket_write (data->nserv->conn, line);
6170+
6171+ done = TRUE;
6172+ if (mutt_socket_readln (buf, sizeof (buf), data->nserv->conn) < 0)
6173+ {
6174+ if (nntp_reconnect (data->nserv) < 0)
6175+ return -1;
6176+
6177+ if (data->group)
6178+ {
6179+ snprintf (buf, sizeof (buf), "GROUP %s\r\n", data->group);
6180+ mutt_socket_write (data->nserv->conn, buf);
6181+ if (mutt_socket_readln (buf, sizeof (buf), data->nserv->conn) < 0)
6182+ return -1;
6183+ }
6184+ if (*line) done = FALSE;
6185+ }
6186+ } while (!done);
6187+
6188+ strfcpy (line, buf, linelen);
6189+ return 0;
6190+}
6191+
6192+/*
6193+ * This function calls funct(*line, *data) for each received line,
6194+ * funct(NULL, *data) if rewind(*data) needs, exits when fail or done.
6195+ * Returned codes:
6196+ * 0 - successful,
6197+ * 1 - correct but not performed (may be, have to be continued),
6198+ * -1 - conection lost,
6199+ * -2 - invalid command or execution error,
6200+ * -3 - error in funct(*line, *data).
6201+ */
6202+static int mutt_nntp_fetch (NNTP_DATA *nntp_data, char *query, char *msg,
6203+ int (*funct) (char *, void *), void *data, int tagged)
6204+{
6205+ char buf[LONG_STRING];
6206+ char *inbuf, *p;
6207+ int done = FALSE;
6208+ int chunk, line;
6209+ size_t lenbuf = 0;
6210+ int ret;
6211+
6212+ do
6213+ {
6214+ strfcpy (buf, query, sizeof (buf));
6215+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0)
6216+ return -1;
6217+ if (buf[0] == '5')
6218+ return -2;
6219+ if (buf[0] != '2')
6220+ return 1;
6221+
6222+ ret = 0;
6223+ line = 0;
6224+ inbuf = safe_malloc (sizeof (buf));
6225+
6226+ FOREVER
6227+ {
6228+ chunk = mutt_socket_readln_d (buf, sizeof (buf), nntp_data->nserv->conn,
6229+ M_SOCK_LOG_HDR);
6230+ if (chunk < 0)
6231+ break;
6232+
6233+ p = buf;
6234+ if (!lenbuf && buf[0] == '.')
6235+ {
6236+ if (buf[1] == '\0')
6237+ {
6238+ done = TRUE;
6239+ break;
6240+ }
6241+ if (buf[1] == '.')
6242+ p++;
6243+ }
6244+
6245+ strfcpy (inbuf + lenbuf, p, sizeof (buf));
6246+
6247+ if (chunk >= sizeof (buf))
6248+ {
6249+ lenbuf += strlen (p);
6250+ }
6251+ else
6252+ {
6253+ line++;
6254+ if (msg && ReadInc && (line % ReadInc == 0)) {
6255+ if (tagged)
6256+ mutt_message (_("%s (tagged: %d) %d"), msg, tagged, line);
6257+ else
6258+ mutt_message ("%s %d", msg, line);
6259+ }
6260+
6261+ if (ret == 0 && funct (inbuf, data) < 0)
6262+ ret = -3;
6263+ lenbuf = 0;
6264+ }
6265+
6266+ safe_realloc ((void **) &inbuf, lenbuf + sizeof (buf));
6267+ }
6268+ FREE (&inbuf);
6269+ funct (NULL, data);
6270+ }
6271+ while (!done);
6272+ return ret;
6273+}
6274+
6275+static int nntp_read_tempfile (char *line, void *file)
6276+{
6277+ FILE *f = (FILE *)file;
6278+
6279+ if (!line)
6280+ rewind (f);
6281+ else
6282+ {
6283+ fputs (line, f);
6284+ if (fputc ('\n', f) == EOF)
6285+ return -1;
6286+ }
6287+ return 0;
6288+}
6289+
6290+static void nntp_parse_xref (CONTEXT *ctx, char *group, char *xref, HEADER *h)
6291+{
6292+ register char *p, *b;
6293+ register char *colon = NULL;
6294+
6295+ b = p = xref;
6296+ while (*p)
6297+ {
6298+ /* skip to next word */
6299+ b = p;
6300+ while (*b && ((*b == ' ') || (*b == '\t'))) b++;
6301+ p = b;
6302+ colon = NULL;
6303+ /* skip to end of word */
6304+ while (*p && (*p != ' ') && (*p != '\t'))
6305+ {
6306+ if (*p == ':')
6307+ colon = p;
6308+ p++;
6309+ }
6310+ if (*p)
6311+ {
6312+ *p = '\0';
6313+ p++;
6314+ }
6315+ if (colon)
6316+ {
6317+ *colon = '\0';
6318+ colon++;
6319+ nntp_get_status (ctx, h, p, atoi(colon));
6320+ if (h && h->article_num == 0 && mutt_strcmp (group, b) == 0)
6321+ h->article_num = atoi(colon);
6322+ }
6323+ }
6324+}
6325+
6326+/*
6327+ * returns:
6328+ * 0 on success
6329+ * 1 if article not found
6330+ * -1 if read or write error on tempfile or socket
6331+ */
6332+static int nntp_read_header (CONTEXT *ctx, const char *msgid, int article_num)
6333+{
6334+ NNTP_DATA *nntp_data = ((NNTP_DATA *)ctx->data);
6335+ FILE *f;
6336+ char buf[LONG_STRING];
6337+ char tempfile[_POSIX_PATH_MAX];
6338+ int ret;
6339+ HEADER *h = ctx->hdrs[ctx->msgcount];
6340+
6341+ mutt_mktemp (tempfile);
6342+ if (!(f = safe_fopen (tempfile, "w+")))
6343+ return -1;
6344+
6345+ if (!msgid)
6346+ snprintf (buf, sizeof (buf), "HEAD %d\r\n", article_num);
6347+ else
6348+ snprintf (buf, sizeof (buf), "HEAD %s\r\n", msgid);
6349+
6350+ ret = mutt_nntp_fetch (nntp_data, buf, NULL, nntp_read_tempfile, f, 0);
6351+ if (ret)
6352+ {
6353+#ifdef DEBUG
6354+ if (ret != -1)
6355+ dprint(1, (debugfile, "nntp_read_header: %s\n", buf));
6356+#endif
6357+ fclose (f);
6358+ unlink (tempfile);
6359+ return (ret == -1 ? -1 : 1);
6360+ }
6361+
6362+ h->article_num = article_num;
6363+ h->env = mutt_read_rfc822_header (f, h, 0, 0);
6364+ fclose (f);
6365+ unlink (tempfile);
6366+
6367+ if (h->env->xref != NULL)
6368+ nntp_parse_xref (ctx, nntp_data->group, h->env->xref, h);
6369+ else if (h->article_num == 0 && msgid)
6370+ {
6371+ snprintf (buf, sizeof (buf), "STAT %s\r\n", msgid);
6372+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) == 0)
6373+ h->article_num = atoi (buf + 4);
6374+ }
6375+
6376+ return 0;
6377+}
6378+
6379+static int parse_description (char *line, void *n)
6380+{
6381+#define news ((NNTP_SERVER *) n)
6382+ register char *d = line;
6383+ NNTP_DATA *data;
6384+
6385+ if (!line)
6386+ return 0;
6387+ while (*d && *d != '\t' && *d != ' ') d++;
6388+ *d = 0;
6389+ d++;
6390+ while (*d && (*d == '\t' || *d == ' ')) d++;
6391+ dprint (2, (debugfile, "group: %s, desc: %s\n", line, d));
6392+ if ((data = (NNTP_DATA *) hash_find (news->newsgroups, line)) != NULL &&
6393+ mutt_strcmp (d, data->desc))
6394+ {
6395+ FREE (&data->desc);
6396+ data->desc = safe_strdup (d);
6397+ }
6398+ return 0;
6399+#undef news
6400+}
6401+
6402+static void nntp_get_desc (NNTP_DATA *data, char *mask, char *msg)
6403+{
6404+ char buf[STRING];
6405+
6406+ if (!option (OPTLOADDESC) || !data || !data->nserv)
6407+ return;
6408+
6409+ /* Get newsgroup description, if we can */
6410+ if (data->nserv->hasXGTITLE)
6411+ snprintf (buf, sizeof (buf), "XGTITLE %s\r\n", mask);
6412+ else
6413+ snprintf (buf, sizeof (buf), "LIST NEWSGROUPS %s\r\n", mask);
6414+ if (mutt_nntp_fetch (data, buf, msg, parse_description, data->nserv, 0) != 0)
6415+ {
6416+#ifdef DEBUG
6417+ nntp_error ("nntp_get_desc()", buf);
6418+#endif
6419+ }
6420+}
6421+
6422+/*
6423+ * XOVER returns a tab separated list of:
6424+ * id|subject|from|date|Msgid|references|bytes|lines|xref
6425+ *
6426+ * This has to duplicate some of the functionality of
6427+ * mutt_read_rfc822_header(), since it replaces the call to that (albeit with
6428+ * a limited number of headers which are "parsed" by placement in the list)
6429+ */
6430+static int nntp_parse_xover (CONTEXT *ctx, char *buf, HEADER *hdr)
6431+{
6432+ NNTP_DATA *nntp_data = (NNTP_DATA *) ctx->data;
6433+ char *p, *b;
6434+ int x, done = 0;
6435+
6436+ hdr->env = mutt_new_envelope();
6437+ hdr->env->newsgroups = safe_strdup (nntp_data->group);
6438+ hdr->content = mutt_new_body();
6439+ hdr->content->type = TYPETEXT;
6440+ hdr->content->subtype = safe_strdup ("plain");
6441+ hdr->content->encoding = ENC7BIT;
6442+ hdr->content->disposition = DISPINLINE;
6443+ hdr->content->length = -1;
6444+ b = p = buf;
6445+
6446+ for (x = 0; !done && x < 9; x++)
6447+ {
6448+ /* if from file, need to skip newline character */
6449+ while (*p && *p != '\n' && *p != '\t') p++;
6450+ if (!*p) done++;
6451+ *p = '\0';
6452+ p++;
6453+ switch (x)
6454+ {
6455+ case 0:
6456+
6457+ hdr->article_num = atoi (b);
6458+ nntp_get_status (ctx, hdr, NULL, hdr->article_num);
6459+ break;
6460+ case 1:
6461+ hdr->env->subject = safe_strdup (b);
6462+ /* Now we need to do the things which would normally be done in
6463+ * mutt_read_rfc822_header() */
6464+ if (hdr->env->subject)
6465+ {
6466+ regmatch_t pmatch[1];
6467+
6468+ rfc2047_decode (&hdr->env->subject);
6469+
6470+ if (regexec (ReplyRegexp.rx, hdr->env->subject, 1, pmatch, 0) == 0)
6471+ hdr->env->real_subj = hdr->env->subject + pmatch[0].rm_eo;
6472+ else
6473+ hdr->env->real_subj = hdr->env->subject;
6474+ }
6475+ break;
6476+ case 2:
6477+ rfc822_free_address (&hdr->env->from);
6478+ hdr->env->from = rfc822_parse_adrlist (hdr->env->from, b);
6479+ rfc2047_decode_adrlist (hdr->env->from);
6480+ break;
6481+ case 3:
6482+ hdr->date_sent = mutt_parse_date (b, hdr);
6483+ hdr->received = hdr->date_sent;
6484+ break;
6485+ case 4:
6486+ FREE (&hdr->env->message_id);
6487+ hdr->env->message_id = safe_strdup (b);
6488+ break;
6489+ case 5:
6490+ mutt_free_list (&hdr->env->references);
6491+ hdr->env->references = mutt_parse_references (b, 0);
6492+ break;
6493+ case 6:
6494+ hdr->content->length = atoi (b);
6495+ break;
6496+ case 7:
6497+ hdr->lines = atoi (b);
6498+ break;
6499+ case 8:
6500+ if (!hdr->read)
6501+ FREE (&hdr->env->xref);
6502+ b = b + 6; /* skips the "Xref: " */
6503+ hdr->env->xref = safe_strdup (b);
6504+ nntp_parse_xref (ctx, nntp_data->group, b, hdr);
6505+ }
6506+ if (!*p)
6507+ return -1;
6508+ b = p;
6509+ }
6510+ return 0;
6511+}
6512+
6513+typedef struct
6514+{
6515+ CONTEXT *ctx;
6516+ unsigned int base;
6517+ unsigned int first;
6518+ unsigned int last;
6519+ unsigned short *messages;
6520+ char* msg;
6521+} FETCH_CONTEXT;
6522+
6523+#define fc ((FETCH_CONTEXT *) c)
6524+static int nntp_fetch_numbers (char *line, void *c)
6525+{
6526+ unsigned int num;
6527+
6528+ if (!line)
6529+ return 0;
6530+ num = atoi (line);
6531+ if (num < fc->base || num > fc->last)
6532+ return 0;
6533+ fc->messages[num - fc->base] = 1;
6534+ return 0;
6535+}
6536+
6537+static int add_xover_line (char *line, void *c)
6538+{
6539+ unsigned int num, total;
6540+ CONTEXT *ctx = fc->ctx;
6541+ NNTP_DATA *data = (NNTP_DATA *)ctx->data;
6542+
6543+ if (!line)
6544+ return 0;
6545+
6546+ if (ctx->msgcount >= ctx->hdrmax)
6547+ mx_alloc_memory (ctx);
6548+ ctx->hdrs[ctx->msgcount] = mutt_new_header ();
6549+ ctx->hdrs[ctx->msgcount]->index = ctx->msgcount;
6550+
6551+ nntp_parse_xover (ctx, line, ctx->hdrs[ctx->msgcount]);
6552+ num = ctx->hdrs[ctx->msgcount]->article_num;
6553+
6554+ if (num >= fc->first && num <= fc->last && fc->messages[num - fc->base])
6555+ {
6556+ ctx->msgcount++;
6557+ if (num > data->lastLoaded)
6558+ data->lastLoaded = num;
6559+ num = num - fc->first + 1;
6560+ total = fc->last - fc->first + 1;
6561+ if (!ctx->quiet && fc->msg && ReadInc && (num % ReadInc == 0))
6562+ mutt_message ("%s %d/%d", fc->msg, num, total);
6563+ }
6564+ else
6565+ mutt_free_header (&ctx->hdrs[ctx->msgcount]); /* skip it */
6566+
6567+ return 0;
6568+}
6569+#undef fc
6570+
6571+static int nntp_fetch_headers (CONTEXT *ctx, unsigned int first,
6572+ unsigned int last)
6573+{
6574+ char buf[HUGE_STRING];
6575+ char *msg = _("Fetching message headers...");
6576+ NNTP_DATA *nntp_data = ((NNTP_DATA *)ctx->data);
6577+ int ret;
6578+ int num;
6579+ int oldmsgcount;
6580+ unsigned int current;
6581+ FILE *f;
6582+ FETCH_CONTEXT fc;
6583+
6584+ /* if empty group or nothing to do */
6585+ if (!last || first > last)
6586+ return 0;
6587+
6588+ /* fetch list of articles */
6589+ mutt_message _("Fetching list of articles...");
6590+ fc.ctx = ctx;
6591+ fc.base = first;
6592+ fc.last = last;
6593+ fc.messages = safe_calloc (last - first + 1, sizeof (unsigned short));
6594+ snprintf (buf, sizeof (buf), "LISTGROUP %s\r\n", nntp_data->group);
6595+ if (mutt_nntp_fetch (nntp_data, buf, NULL, nntp_fetch_numbers, &fc, 0) != 0)
6596+ {
6597+ mutt_error (_("LISTGROUP command failed: %s"), buf);
6598+#ifdef DEBUG
6599+ nntp_error ("nntp_fetch_headers()", buf);
6600+#endif
6601+ FREE (&fc.messages);
6602+ return -1;
6603+ }
6604+
6605+ /* CACHE: must be loaded xover cache here */
6606+ num = nntp_data->lastCached - first + 1;
6607+ if (option (OPTNEWSCACHE) && nntp_data->cache && num > 0)
6608+ {
6609+ nntp_cache_expand (buf, nntp_data->cache);
6610+ mutt_message _("Fetching headers from cache...");
6611+ if ((f = safe_fopen (buf, "r")))
6612+ {
6613+ int r = 0;
6614+
6615+ /* counting number of lines */
6616+ while (fgets (buf, sizeof (buf), f) != NULL)
6617+ r++;
6618+ rewind (f);
6619+ while (r > num && fgets (buf, sizeof (buf), f) != NULL)
6620+ r--;
6621+ oldmsgcount = ctx->msgcount;
6622+ fc.first = first;
6623+ fc.last = first + num - 1;
6624+ fc.msg = NULL;
6625+ while (fgets (buf, sizeof (buf), f) != NULL)
6626+ add_xover_line (buf, &fc);
6627+ fclose (f);
6628+ nntp_data->lastLoaded = fc.last;
6629+ first = fc.last + 1;
6630+ if (ctx->msgcount > oldmsgcount)
6631+ mx_update_context (ctx, ctx->msgcount - oldmsgcount);
6632+ }
6633+ else
6634+ nntp_delete_cache (nntp_data);
6635+ }
6636+ num = last - first + 1;
6637+ if (num <= 0)
6638+ {
6639+ FREE (&fc.messages);
6640+ return 0;
6641+ }
6642+
6643+ /*
6644+ * Without XOVER, we have to fetch each article header and parse
6645+ * it. With XOVER, we ask for all of them
6646+ */
6647+ mutt_message (msg);
6648+ if (nntp_data->nserv->hasXOVER)
6649+ {
6650+ oldmsgcount = ctx->msgcount;
6651+ fc.first = first;
6652+ fc.last = last;
6653+ fc.msg = msg;
6654+ snprintf (buf, sizeof (buf), "XOVER %d-%d\r\n", first, last);
6655+ ret = mutt_nntp_fetch (nntp_data, buf, NULL, add_xover_line, &fc, 0);
6656+ if (ctx->msgcount > oldmsgcount)
6657+ mx_update_context (ctx, ctx->msgcount - oldmsgcount);
6658+ if (ret != 0)
6659+ {
6660+ mutt_error (_("XOVER command failed: %s"), buf);
6661+#ifdef DEBUG
6662+ nntp_error ("nntp_fetch_headers()", buf);
6663+#endif
6664+ FREE (&fc.messages);
6665+ return -1;
6666+ }
6667+ /* fetched OK */
6668+ }
6669+ else
6670+ for (current = first; current <= last; current++)
6671+ {
6672+ HEADER *h;
6673+
6674+ ret = current - first + 1;
6675+ mutt_message ("%s %d/%d", msg, ret, num);
6676+
6677+ if (!fc.messages[current - fc.base])
6678+ continue;
6679+
6680+ if (ctx->msgcount >= ctx->hdrmax)
6681+ mx_alloc_memory (ctx);
6682+ h = ctx->hdrs[ctx->msgcount] = mutt_new_header ();
6683+ h->index = ctx->msgcount;
6684+
6685+ ret = nntp_read_header (ctx, NULL, current);
6686+ if (ret == 0) /* Got article. Fetch next header */
6687+ {
6688+ nntp_get_status (ctx, h, NULL, h->article_num);
6689+ ctx->msgcount++;
6690+ mx_update_context (ctx, 1);
6691+ }
6692+ else
6693+ mutt_free_header (&h); /* skip it */
6694+ if (ret == -1)
6695+ {
6696+ FREE (&fc.messages);
6697+ return -1;
6698+ }
6699+
6700+ if (current > nntp_data->lastLoaded)
6701+ nntp_data->lastLoaded = current;
6702+ }
6703+ FREE (&fc.messages);
6704+ nntp_data->lastLoaded = last;
6705+ mutt_clear_error ();
6706+ return 0;
6707+}
6708+
6709+/*
6710+ * currently, nntp "mailbox" is "newsgroup"
6711+ */
6712+int nntp_open_mailbox (CONTEXT *ctx)
6713+{
6714+ NNTP_DATA *nntp_data;
6715+ NNTP_SERVER *serv;
6716+ char buf[HUGE_STRING];
6717+ char server[LONG_STRING];
6718+ int count = 0;
6719+ unsigned int first;
6720+ ACCOUNT acct;
6721+
6722+ if (nntp_parse_url (ctx->path, &acct, buf, sizeof (buf)) < 0 || !*buf)
6723+ {
6724+ mutt_error (_("%s is an invalid newsgroup specification!"), ctx->path);
6725+ mutt_sleep (2);
6726+ return -1;
6727+ }
6728+
6729+ server[0] = '\0';
6730+ nntp_expand_path (server, sizeof (server), &acct);
6731+ if (!(serv = mutt_select_newsserver (server)) || serv->status != NNTP_OK)
6732+ return -1;
6733+
6734+ CurrentNewsSrv = serv;
6735+
6736+ /* create NNTP-specific state struct if nof found in list */
6737+ if ((nntp_data = (NNTP_DATA *) hash_find (serv->newsgroups, buf)) == NULL)
6738+ {
6739+ nntp_data = safe_calloc (1, sizeof (NNTP_DATA) + strlen (buf) + 1);
6740+ nntp_data->group = (char *) nntp_data + sizeof (NNTP_DATA);
6741+ strcpy (nntp_data->group, buf);
6742+ hash_insert (serv->newsgroups, nntp_data->group, nntp_data, 0);
6743+ nntp_add_to_list (serv, nntp_data);
6744+ }
6745+ ctx->data = nntp_data;
6746+ nntp_data->nserv = serv;
6747+
6748+ mutt_message (_("Selecting %s..."), nntp_data->group);
6749+
6750+ if (!nntp_data->desc)
6751+ {
6752+ nntp_get_desc (nntp_data, nntp_data->group, NULL);
6753+ if (nntp_data->desc)
6754+ nntp_save_cache_index (serv);
6755+ }
6756+
6757+ buf[0] = 0;
6758+ if (mutt_nntp_query (nntp_data, buf, sizeof(buf)) < 0)
6759+ {
6760+#ifdef DEBUG
6761+ nntp_error ("nntp_open_mailbox()", buf);
6762+#endif
6763+ return -1;
6764+ }
6765+
6766+ if (mutt_strncmp ("211", buf, 3))
6767+ {
6768+ LIST *l = serv->list;
6769+
6770+ /* GROUP command failed */
6771+ if (!mutt_strncmp ("411", buf, 3))
6772+ {
6773+ mutt_error (_("Newsgroup %s not found on server %s"),
6774+ nntp_data->group, serv->conn->account.host);
6775+
6776+ /* CACHE: delete cache and line from .index */
6777+ nntp_delete_cache (nntp_data);
6778+ hash_delete (serv->newsgroups, nntp_data->group, NULL, nntp_delete_data);
6779+ while (l && l->data != (void *) nntp_data) l = l->next;
6780+ if (l)
6781+ l->data = NULL;
6782+
6783+ sleep (2);
6784+ }
6785+
6786+ return -1;
6787+ }
6788+
6789+ sscanf (buf + 4, "%d %u %u %s", &count, &nntp_data->firstMessage,
6790+ &nntp_data->lastMessage, buf);
6791+
6792+ nntp_data->deleted = 0;
6793+
6794+ time (&serv->check_time);
6795+
6796+ /*
6797+ * Check for max adding context. If it is greater than $nntp_context,
6798+ * strip off extra articles
6799+ */
6800+ first = nntp_data->firstMessage;
6801+ if (NntpContext && nntp_data->lastMessage - first + 1 > NntpContext)
6802+ first = nntp_data->lastMessage - NntpContext + 1;
6803+ if (first)
6804+ nntp_data->lastLoaded = first - 1;
6805+ return nntp_fetch_headers (ctx, first, nntp_data->lastMessage);
6806+}
6807+
6808+int nntp_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
6809+{
6810+ char buf[LONG_STRING];
6811+ char path[_POSIX_PATH_MAX];
6812+ NNTP_CACHE *cache;
6813+ char *m = _("Fetching message...");
6814+ int ret;
6815+
6816+ /* see if we already have the message in our cache */
6817+ cache = &((NNTP_DATA *) ctx->data)->acache[ctx->hdrs[msgno]->index % NNTP_CACHE_LEN];
6818+
6819+ /* if everything is fine, assign msg->fp and return */
6820+ if (cache->path && cache->index == ctx->hdrs[msgno]->index &&
6821+ (msg->fp = fopen (cache->path, "r")))
6822+ return 0;
6823+
6824+ /* clear the previous entry */
6825+ unlink (cache->path);
6826+ free (cache->path);
6827+
6828+ mutt_message (m);
6829+
6830+ cache->index = ctx->hdrs[msgno]->index;
6831+ mutt_mktemp (path);
6832+ cache->path = safe_strdup (path);
6833+ if (!(msg->fp = safe_fopen (path, "w+")))
6834+ {
6835+ FREE (&cache->path);
6836+ return -1;
6837+ }
6838+
6839+ if (ctx->hdrs[msgno]->article_num == 0)
6840+ snprintf (buf, sizeof (buf), "ARTICLE %s\r\n",
6841+ ctx->hdrs[msgno]->env->message_id);
6842+ else
6843+ snprintf (buf, sizeof (buf), "ARTICLE %d\r\n",
6844+ ctx->hdrs[msgno]->article_num);
6845+
6846+ ret = mutt_nntp_fetch ((NNTP_DATA *)ctx->data, buf, m, nntp_read_tempfile,
6847+ msg->fp, ctx->tagged);
6848+ if (ret == 1)
6849+ {
6850+ mutt_error (_("Article %d not found on server"),
6851+ ctx->hdrs[msgno]->article_num);
6852+ dprint (1, (debugfile, "nntp_fetch_message: %s\n", buf));
6853+ }
6854+
6855+ if (ret)
6856+ {
6857+ fclose (msg->fp);
6858+ unlink (path);
6859+ FREE (&cache->path);
6860+ return -1;
6861+ }
6862+
6863+ mutt_free_envelope (&ctx->hdrs[msgno]->env);
6864+ ctx->hdrs[msgno]->env = mutt_read_rfc822_header (msg->fp, ctx->hdrs[msgno], 0, 0);
6865+ /* fix content length */
6866+ fseek(msg->fp, 0, SEEK_END);
6867+ ctx->hdrs[msgno]->content->length = ftell (msg->fp) -
6868+ ctx->hdrs[msgno]->content->offset;
6869+
6870+ /* this is called in mutt before the open which fetches the message,
6871+ * which is probably wrong, but we just call it again here to handle
6872+ * the problem instead of fixing it.
6873+ */
6874+ mutt_parse_mime_message (ctx, ctx->hdrs[msgno]);
6875+
6876+ /* These would normally be updated in mx_update_context(), but the
6877+ * full headers aren't parsed with XOVER, so the information wasn't
6878+ * available then.
6879+ */
6880+#ifdef HAVE_PGP
6881+ ctx->hdrs[msgno]->pgp = pgp_query (ctx->hdrs[msgno]->content);
6882+#endif /* HAVE_PGP */
6883+
6884+ mutt_clear_error();
6885+ rewind (msg->fp);
6886+
6887+ return 0;
6888+}
6889+
6890+/* Post article */
6891+int nntp_post (const char *msg) {
6892+ char buf[LONG_STRING];
6893+ size_t len;
6894+ FILE *f;
6895+ NNTP_DATA *nntp_data;
6896+
6897+ if (Context && Context->magic == M_NNTP)
6898+ nntp_data = (NNTP_DATA *)Context->data;
6899+ else
6900+ {
6901+ if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)) ||
6902+ !CurrentNewsSrv->list || !CurrentNewsSrv->list->data)
6903+ {
6904+ mutt_error (_("Can't post article. No connection to news server."));
6905+ return -1;
6906+ }
6907+ nntp_data = (NNTP_DATA *)CurrentNewsSrv->list->data;
6908+ }
6909+
6910+ if (!(f = safe_fopen (msg, "r")))
6911+ {
6912+ mutt_error (_("Can't post article. Unable to open %s"), msg);
6913+ return -1;
6914+ }
6915+
6916+ strfcpy (buf, "POST\r\n", sizeof (buf));
6917+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0)
6918+ {
6919+ mutt_error (_("Can't post article. Connection to %s lost."),
6920+ nntp_data->nserv->conn->account.host);
6921+ return -1;
6922+ }
6923+ if (buf[0] != '3')
6924+ {
6925+ mutt_error (_("Can't post article: %s"), buf);
6926+ return -1;
6927+ }
6928+
6929+ buf[0] = '.';
6930+ buf[1] = '\0';
6931+ while (fgets (buf + 1, sizeof (buf) - 2, f) != NULL)
6932+ {
6933+ len = strlen (buf);
6934+ if (buf[len - 1] == '\n')
6935+ {
6936+ buf[len - 1] = '\r';
6937+ buf[len] = '\n';
6938+ len++;
6939+ buf[len] = '\0';
6940+ }
6941+ if (buf[1] == '.')
6942+ mutt_socket_write_d (nntp_data->nserv->conn, buf, M_SOCK_LOG_HDR);
6943+ else
6944+ mutt_socket_write_d (nntp_data->nserv->conn, buf + 1, M_SOCK_LOG_HDR);
6945+ }
6946+ fclose (f);
6947+
6948+ if (buf[strlen (buf) - 1] != '\n')
6949+ mutt_socket_write_d (nntp_data->nserv->conn, "\r\n", M_SOCK_LOG_HDR);
6950+ mutt_socket_write_d (nntp_data->nserv->conn, ".\r\n", M_SOCK_LOG_HDR);
6951+ if (mutt_socket_readln (buf, sizeof (buf), nntp_data->nserv->conn) < 0)
6952+ {
6953+ mutt_error (_("Can't post article. Connection to %s lost."),
6954+ nntp_data->nserv->conn->account.host);
6955+ return -1;
6956+ }
6957+ if (buf[0] != '2')
6958+ {
6959+ mutt_error (_("Can't post article: %s"), buf);
6960+ return -1;
6961+ }
6962+
6963+ return 0;
6964+}
6965+
6966+/* nntp_logout_all: close all open connections. */
6967+void nntp_logout_all (void)
6968+{
6969+ char buf[LONG_STRING];
6970+ CONNECTION* conn;
6971+ CONNECTION* tmp;
6972+
6973+ conn = mutt_socket_head ();
6974+
6975+ while (conn)
6976+ {
6977+ tmp = conn;
6978+
6979+ if (conn->account.type == M_ACCT_TYPE_NNTP)
6980+ {
6981+ mutt_message (_("Closing connection to %s..."), conn->account.host);
6982+ mutt_socket_write (conn, "QUIT\r\n");
6983+ mutt_socket_readln (buf, sizeof (buf), conn);
6984+ mutt_clear_error ();
6985+ mutt_socket_close (conn);
6986+
6987+ mutt_socket_free (tmp);
6988+ }
6989+
6990+ conn = conn->next;
6991+ }
6992+}
6993+
6994+static void nntp_free_acache (NNTP_DATA *data)
6995+{
6996+ int i;
6997+
6998+ for (i = 0; i < NNTP_CACHE_LEN; i++)
6999+ {
7000+ if (data->acache[i].path)
7001+ {
7002+ unlink (data->acache[i].path);
7003+ FREE (&data->acache[i].path);
7004+ }
7005+ }
7006+}
7007+
7008+void nntp_delete_data (void *p)
7009+{
7010+ NNTP_DATA *data = (NNTP_DATA *)p;
7011+
7012+ if (!p)
7013+ return;
7014+ FREE (&data->entries);
7015+ FREE (&data->desc);
7016+ FREE (&data->cache);
7017+ nntp_free_acache (data);
7018+ FREE (p);
7019+}
7020+
7021+int nntp_sync_mailbox (CONTEXT *ctx)
7022+{
7023+ NNTP_DATA *data = ctx->data;
7024+
7025+ /* CACHE: update cache and .index files */
7026+ if ((option (OPTSAVEUNSUB) || data->subscribed))
7027+ nntp_save_cache_group (ctx);
7028+ nntp_free_acache (data);
7029+
7030+ data->nserv->check_time = 0; /* next nntp_check_mailbox() will really check */
7031+ return 0;
7032+}
7033+
7034+void nntp_fastclose_mailbox (CONTEXT *ctx)
7035+{
7036+ NNTP_DATA *data = (NNTP_DATA *) ctx->data, *tmp;
7037+
7038+ if (!data)
7039+ return;
7040+ nntp_free_acache (data);
7041+ if (!data->nserv || !data->nserv->newsgroups || !data->group)
7042+ return;
7043+ nntp_save_cache_index (data->nserv);
7044+ if ((tmp = hash_find (data->nserv->newsgroups, data->group)) == NULL
7045+ || tmp != data)
7046+ nntp_delete_data (data);
7047+}
7048+
7049+/* commit changes and terminate connection */
7050+int nntp_close_mailbox (CONTEXT *ctx)
7051+{
7052+ if (!ctx)
7053+ return -1;
7054+ mutt_message _("Quitting newsgroup...");
7055+ if (ctx->data)
7056+ {
7057+ NNTP_DATA *data = (NNTP_DATA *) ctx->data;
7058+ int ret;
7059+
7060+ if (data->nserv && data->nserv->conn && ctx->unread)
7061+ {
7062+ ret = query_quadoption (OPT_CATCHUP, _("Mark all articles read?"));
7063+ if (ret == M_YES)
7064+ mutt_newsgroup_catchup (data->nserv, data->group);
7065+ else if (ret < 0)
7066+ return -1;
7067+ }
7068+ }
7069+ nntp_sync_mailbox (ctx);
7070+ if (ctx->data && ((NNTP_DATA *)ctx->data)->nserv)
7071+ {
7072+ NNTP_SERVER *news;
7073+
7074+ news = ((NNTP_DATA *)ctx->data)->nserv;
7075+ newsrc_gen_entries (ctx);
7076+ ((NNTP_DATA *)ctx->data)->unread = ctx->unread;
7077+ mutt_newsrc_update (news);
7078+ }
7079+ mutt_clear_error();
7080+ return 0;
7081+}
7082+
7083+/* use the GROUP command to poll for new mail */
7084+static int _nntp_check_mailbox (CONTEXT *ctx, NNTP_DATA *nntp_data)
7085+{
7086+ char buf[LONG_STRING];
7087+ int count = 0;
7088+
7089+ if (nntp_data->nserv->check_time + NewsPollTimeout > time (NULL))
7090+ return 0;
7091+
7092+ buf[0] = 0;
7093+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0)
7094+ {
7095+#ifdef DEBUG
7096+ nntp_error ("nntp_check_mailbox()", buf);
7097+#endif
7098+ return -1;
7099+ }
7100+ if (mutt_strncmp ("211", buf, 3))
7101+ {
7102+ buf[0] = 0;
7103+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0)
7104+ {
7105+#ifdef DEBUG
7106+ nntp_error ("nntp_check_mailbox()", buf);
7107+#endif
7108+ return -1;
7109+ }
7110+ }
7111+ if (!mutt_strncmp ("211", buf, 3))
7112+ {
7113+ int first;
7114+ int last;
7115+
7116+ sscanf (buf + 4, "%d %d %d", &count, &first, &last);
7117+ nntp_data->firstMessage = first;
7118+ nntp_data->lastMessage = last;
7119+ if (ctx && last > nntp_data->lastLoaded)
7120+ {
7121+ nntp_fetch_headers (ctx, nntp_data->lastLoaded + 1, last);
7122+ time (&nntp_data->nserv->check_time);
7123+ return 1;
7124+ }
7125+ if (!last || (!nntp_data->rc && !nntp_data->lastCached))
7126+ nntp_data->unread = count;
7127+ else
7128+ mutt_newsgroup_stat (nntp_data);
7129+ /* active was renumbered? */
7130+ if (last < nntp_data->lastLoaded)
7131+ {
7132+ if (!nntp_data->max)
7133+ {
7134+ nntp_data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY));
7135+ nntp_data->max = 5;
7136+ }
7137+ nntp_data->lastCached = 0;
7138+ nntp_data->num = 1;
7139+ nntp_data->entries[0].first = 1;
7140+ nntp_data->entries[0].last = 0;
7141+ }
7142+ }
7143+
7144+ time (&nntp_data->nserv->check_time);
7145+ return 0;
7146+}
7147+
7148+int nntp_check_mailbox (CONTEXT *ctx)
7149+{
7150+ return _nntp_check_mailbox (ctx, (NNTP_DATA *)ctx->data);
7151+}
7152+
7153+static int add_group (char *buf, void *serv)
7154+{
7155+#define s ((NNTP_SERVER *) serv)
7156+ char group[LONG_STRING], mod, desc[HUGE_STRING];
7157+ int first, last;
7158+ NNTP_DATA *nntp_data;
7159+ static int n = 0;
7160+
7161+ _checked = n; /* _checked have N, where N = number of groups */
7162+ if (!buf) /* at EOF must be zerouth */
7163+ n = 0;
7164+
7165+ if (!s || !buf)
7166+ return 0;
7167+
7168+ *desc = 0;
7169+ sscanf (buf, "%s %d %d %c %[^\n]", group, &last, &first, &mod, desc);
7170+ if (!group)
7171+ return 0;
7172+ if ((nntp_data = (NNTP_DATA *) hash_find (s->newsgroups, group)) == NULL)
7173+ {
7174+ n++;
7175+ nntp_data = safe_calloc (1, sizeof (NNTP_DATA) + strlen (group) + 1);
7176+ nntp_data->group = (char *) nntp_data + sizeof (NNTP_DATA);
7177+ strcpy (nntp_data->group, group);
7178+ nntp_data->nserv = s;
7179+ if (s->newsgroups->nelem < s->newsgroups->curnelem * 2)
7180+ s->newsgroups = hash_resize (s->newsgroups, s->newsgroups->nelem * 2);
7181+ hash_insert (s->newsgroups, nntp_data->group, nntp_data, 0);
7182+ nntp_add_to_list (s, nntp_data);
7183+ }
7184+ nntp_data->deleted = 0;
7185+ nntp_data->firstMessage = first;
7186+ nntp_data->lastMessage = last;
7187+ if (mod == 'y')
7188+ nntp_data->allowed = 1;
7189+ else
7190+ nntp_data->allowed = 0;
7191+ if (nntp_data->desc)
7192+ FREE (&nntp_data->desc);
7193+ if (*desc)
7194+ nntp_data->desc = safe_strdup (desc);
7195+ if (nntp_data->rc || nntp_data->lastCached)
7196+ mutt_newsgroup_stat (nntp_data);
7197+ else if (nntp_data->lastMessage &&
7198+ nntp_data->firstMessage <= nntp_data->lastMessage)
7199+ nntp_data->unread = nntp_data->lastMessage - nntp_data->firstMessage + 1;
7200+ else
7201+ nntp_data->unread = 0;
7202+
7203+ return 0;
7204+#undef s
7205+}
7206+
7207+int nntp_check_newgroups (NNTP_SERVER *serv, int force)
7208+{
7209+ char buf[LONG_STRING];
7210+ NNTP_DATA nntp_data;
7211+ LIST *l;
7212+ LIST emp;
7213+ time_t now;
7214+ struct tm *t;
7215+
7216+ if (!serv || !serv->newgroups_time)
7217+ return -1;
7218+
7219+ if (nntp_open_connection (serv) < 0)
7220+ return -1;
7221+
7222+ /* check subscribed groups for new news */
7223+ if (option (OPTSHOWNEWNEWS))
7224+ {
7225+ mutt_message _("Checking for new messages...");
7226+ for (l = serv->list; l; l = l->next)
7227+ {
7228+ serv->check_time = 0; /* really check! */
7229+ if (l->data && ((NNTP_DATA *) l->data)->subscribed)
7230+ _nntp_check_mailbox (NULL, (NNTP_DATA *) l->data);
7231+ }
7232+ }
7233+ else if (!force)
7234+ return 0;
7235+
7236+ mutt_message _("Checking for new newsgroups...");
7237+ now = serv->newgroups_time;
7238+ time (&serv->newgroups_time);
7239+ t = gmtime (&now);
7240+ snprintf (buf, sizeof (buf), "NEWGROUPS %02d%02d%02d %02d%02d%02d GMT\r\n",
7241+ (t->tm_year % 100), t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min,
7242+ t->tm_sec);
7243+ nntp_data.nserv = serv;
7244+ if (Context && Context->magic == M_NNTP)
7245+ nntp_data.group = ((NNTP_DATA *)Context->data)->group;
7246+ else
7247+ nntp_data.group = NULL;
7248+ l = serv->tail;
7249+ if (mutt_nntp_fetch (&nntp_data, buf, _("Adding new newsgroups..."),
7250+ add_group, serv, 0) != 0)
7251+ {
7252+#ifdef DEBUG
7253+ nntp_error ("nntp_check_newgroups()", buf);
7254+#endif
7255+ return -1;
7256+ }
7257+
7258+ mutt_message _("Loading descriptions...");
7259+ if (l)
7260+ emp.next = l->next;
7261+ else
7262+ emp.next = serv->list;
7263+ l = &emp;
7264+ while (l->next)
7265+ {
7266+ l = l->next;
7267+ ((NNTP_DATA *) l->data)->new = 1;
7268+ nntp_get_desc ((NNTP_DATA *) l->data, ((NNTP_DATA *) l->data)->group, NULL);
7269+ }
7270+ if (emp.next)
7271+ nntp_save_cache_index (serv);
7272+ mutt_clear_error ();
7273+ return _checked;
7274+}
7275+
7276+/* Load list of all newsgroups from cache ALL */
7277+int nntp_get_cache_all (NNTP_SERVER *serv)
7278+{
7279+ char buf[HUGE_STRING];
7280+ FILE *f;
7281+
7282+ nntp_cache_expand (buf, serv->cache);
7283+ if ((f = safe_fopen (buf, "r")))
7284+ {
7285+ int i = 0;
7286+
7287+ while (fgets (buf, sizeof(buf), f) != NULL)
7288+ {
7289+ if (ReadInc && (i % ReadInc == 0))
7290+ mutt_message (_("Loading list from cache... %d"), i);
7291+ add_group (buf, serv);
7292+ i++;
7293+ }
7294+ add_group (NULL, NULL);
7295+ fclose (f);
7296+ mutt_clear_error ();
7297+ return 0;
7298+ }
7299+ else
7300+ {
7301+ FREE (&serv->cache);
7302+ return -1;
7303+ }
7304+}
7305+
7306+/* Load list of all newsgroups from active */
7307+int nntp_get_active (NNTP_SERVER *serv)
7308+{
7309+ char msg[SHORT_STRING];
7310+ NNTP_DATA nntp_data;
7311+ LIST *tmp;
7312+
7313+ if (nntp_open_connection (serv) < 0)
7314+ return -1;
7315+
7316+ snprintf (msg, sizeof(msg), _("Loading list of all newsgroups on server %s..."),
7317+ serv->conn->account.host);
7318+ mutt_message (msg);
7319+ time (&serv->newgroups_time);
7320+ nntp_data.nserv = serv;
7321+ nntp_data.group = NULL;
7322+
7323+ if (mutt_nntp_fetch (&nntp_data, "LIST\r\n", msg, add_group, serv, 0) < 0)
7324+ {
7325+#ifdef DEBUG
7326+ nntp_error ("nntp_get_active()", "LIST\r\n");
7327+#endif
7328+ return -1;
7329+ }
7330+
7331+ strfcpy (msg, _("Loading descriptions..."), sizeof (msg));
7332+ mutt_message (msg);
7333+ nntp_get_desc (&nntp_data, "*", msg);
7334+
7335+ for (tmp = serv->list; tmp; tmp = tmp->next)
7336+ {
7337+ NNTP_DATA *data = (NNTP_DATA *)tmp->data;
7338+
7339+ if (data && data->deleted && !data->rc)
7340+ {
7341+ nntp_delete_cache (data);
7342+ hash_delete (serv->newsgroups, data->group, NULL, nntp_delete_data);
7343+ tmp->data = NULL;
7344+ }
7345+ }
7346+ nntp_save_cache_index (serv);
7347+
7348+ mutt_clear_error ();
7349+ return _checked;
7350+}
7351+
7352+/*
7353+ * returns -1 if error ocurred while retrieving header,
7354+ * number of articles which ones exist in context on success.
7355+ */
7356+int nntp_check_msgid (CONTEXT *ctx, const char *msgid)
7357+{
7358+ int ret;
7359+
7360+ /* if msgid is already in context, don't reload them */
7361+ if (hash_find (ctx->id_hash, msgid))
7362+ return 1;
7363+ if (ctx->msgcount == ctx->hdrmax)
7364+ mx_alloc_memory (ctx);
7365+ ctx->hdrs[ctx->msgcount] = mutt_new_header ();
7366+ ctx->hdrs[ctx->msgcount]->index = ctx->msgcount;
7367+
7368+ mutt_message (_("Fetching %s from server..."), msgid);
7369+ ret = nntp_read_header (ctx, msgid, 0);
7370+ /* since nntp_read_header() may set read flag, we must reset it */
7371+ ctx->hdrs[ctx->msgcount]->read = 0;
7372+ if (ret != 0)
7373+ mutt_free_header (&ctx->hdrs[ctx->msgcount]);
7374+ else
7375+ {
7376+ ctx->msgcount++;
7377+ mx_update_context (ctx, 1);
7378+ ctx->changed = 1;
7379+ }
7380+ return ret;
7381+}
7382+
7383+typedef struct
7384+{
7385+ CONTEXT *ctx;
7386+ unsigned int num;
7387+ unsigned int max;
7388+ unsigned int *child;
7389+} CHILD_CONTEXT;
7390+
7391+static int check_children (char *s, void *c)
7392+{
7393+#define cc ((CHILD_CONTEXT *) c)
7394+ unsigned int i, n;
7395+
7396+ if (!s || (n = atoi (s)) == 0)
7397+ return 0;
7398+ for (i = 0; i < cc->ctx->msgcount; i++)
7399+ if (cc->ctx->hdrs[i]->article_num == n)
7400+ return 0;
7401+ if (cc->num >= cc->max)
7402+ safe_realloc ((void **) &cc->child, sizeof (unsigned int) * (cc->max += 25));
7403+ cc->child[cc->num++] = n;
7404+
7405+ return 0;
7406+#undef cc
7407+}
7408+
7409+int nntp_check_children (CONTEXT *ctx, const char *msgid)
7410+{
7411+ NNTP_DATA *nntp_data = (NNTP_DATA *)ctx->data;
7412+ char buf[STRING];
7413+ int i, ret = 0, tmp = 0;
7414+ CHILD_CONTEXT cc;
7415+
7416+ if (!nntp_data || !nntp_data->nserv || !nntp_data->nserv->conn ||
7417+ !nntp_data->nserv->conn->account.host)
7418+ return -1;
7419+ if (nntp_data->firstMessage > nntp_data->lastLoaded)
7420+ return 0;
7421+ if (!nntp_data->nserv->hasXPAT)
7422+ {
7423+ mutt_error (_("Server %s does not support this operation!"),
7424+ nntp_data->nserv->conn->account.host);
7425+ return -1;
7426+ }
7427+
7428+ snprintf (buf, sizeof (buf), "XPAT References %d-%d *%s*\r\n",
7429+ nntp_data->firstMessage, nntp_data->lastLoaded, msgid);
7430+
7431+ cc.ctx = ctx;
7432+ cc.num = 0;
7433+ cc.max = 25;
7434+ cc.child = safe_malloc (sizeof (unsigned int) * 25);
7435+ if (mutt_nntp_fetch (nntp_data, buf, NULL, check_children, &cc, 0))
7436+ {
7437+ safe_free ((void **) &cc.child);
7438+ return -1;
7439+ }
7440+ /* dont try to read the xover cache. check_children() already
7441+ * made sure that we dont have the article, so we need to visit
7442+ * the server. Reading the cache at this point is also bad
7443+ * because it would duplicate messages */
7444+ if (option (OPTNEWSCACHE))
7445+ {
7446+ tmp++;
7447+ unset_option (OPTNEWSCACHE);
7448+ }
7449+ for (i = 0; i < cc.num; i++)
7450+ {
7451+ if ((ret = nntp_fetch_headers (ctx, cc.child[i], cc.child[i])))
7452+ break;
7453+ if (ctx->msgcount &&
7454+ ctx->hdrs[ctx->msgcount - 1]->article_num == cc.child[i])
7455+ ctx->hdrs[ctx->msgcount - 1]->read = 0;
7456+ }
7457+ if (tmp)
7458+ set_option (OPTNEWSCACHE);
7459+ safe_free ((void **) &cc.child);
7460+ return ret;
7461+}
7462diff -uNr mutt-1.4.orig/nntp.h mutt-1.4/nntp.h
7463--- mutt-1.4.orig/nntp.h Thu Jan 1 01:00:00 1970
7464+++ mutt-1.4/nntp.h Sun Nov 3 21:57:20 2002
7465@@ -0,0 +1,135 @@
7466+/*
7467+ * Copyright (C) 1998 Brandon Long <blong@fiction.net>
7468+ * Copyright (C) 1999 Andrej Gritsenko <andrej@lucky.net>
7469+ * Copyright (C) 2000-2002 Vsevolod Volkov <vvv@mutt.org.ua>
7470+ *
7471+ * This program is free software; you can redistribute it and/or modify
7472+ * it under the terms of the GNU General Public License as published by
7473+ * the Free Software Foundation; either version 2 of the License, or
7474+ * (at your option) any later version.
7475+ *
7476+ * This program is distributed in the hope that it will be useful,
7477+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7478+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7479+ * GNU General Public License for more details.
7480+ *
7481+ * You should have received a copy of the GNU General Public License
7482+ * along with this program; if not, write to the Free Software
7483+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
7484+ */
7485+
7486+#ifndef _NNTP_H_
7487+#define _NNTP_H_ 1
7488+
7489+#include "mutt_socket.h"
7490+#include "mailbox.h"
7491+
7492+#include <time.h>
7493+
7494+#define NNTP_PORT 119
7495+#define NNTP_SSL_PORT 563
7496+
7497+/* number of entries in the hash table */
7498+#define NNTP_CACHE_LEN 10
7499+
7500+enum
7501+{
7502+ NNTP_NONE = 0,
7503+ NNTP_OK,
7504+ NNTP_BYE
7505+};
7506+
7507+typedef struct
7508+{
7509+ int first;
7510+ int last;
7511+} NEWSRC_ENTRY;
7512+
7513+typedef struct
7514+{
7515+ unsigned int hasXPAT : 1;
7516+ unsigned int hasXGTITLE : 1;
7517+ unsigned int hasXOVER : 1;
7518+ unsigned int status : 3;
7519+ char *newsrc;
7520+ char *cache;
7521+ int stat;
7522+ off_t size;
7523+ time_t mtime;
7524+ time_t newgroups_time;
7525+ time_t check_time;
7526+ HASH *newsgroups;
7527+ LIST *list; /* list of newsgroups */
7528+ LIST *tail; /* last entry of list */
7529+ CONNECTION *conn;
7530+} NNTP_SERVER;
7531+
7532+typedef struct
7533+{
7534+ unsigned int index;
7535+ char *path;
7536+} NNTP_CACHE;
7537+
7538+typedef struct
7539+{
7540+ NEWSRC_ENTRY *entries;
7541+ unsigned int num; /* number of used entries */
7542+ unsigned int max; /* number of allocated entries */
7543+ unsigned int unread;
7544+ unsigned int firstMessage;
7545+ unsigned int lastMessage;
7546+ unsigned int lastLoaded;
7547+ unsigned int lastCached;
7548+ unsigned int subscribed : 1;
7549+ unsigned int rc : 1;
7550+ unsigned int new : 1;
7551+ unsigned int allowed : 1;
7552+ unsigned int deleted : 1;
7553+ char *group;
7554+ char *desc;
7555+ char *cache;
7556+ NNTP_SERVER *nserv;
7557+ NNTP_CACHE acache[NNTP_CACHE_LEN];
7558+} NNTP_DATA;
7559+
7560+/* internal functions */
7561+int nntp_get_active (NNTP_SERVER *);
7562+int nntp_get_cache_all (NNTP_SERVER *);
7563+int nntp_save_cache_index (NNTP_SERVER *);
7564+int nntp_check_newgroups (NNTP_SERVER *, int);
7565+int nntp_save_cache_group (CONTEXT *);
7566+int nntp_parse_url (const char *, ACCOUNT *, char *, size_t);
7567+void newsrc_gen_entries (CONTEXT *);
7568+void nntp_get_status (CONTEXT *, HEADER *, char *, int);
7569+void mutt_newsgroup_stat (NNTP_DATA *);
7570+void nntp_delete_cache (NNTP_DATA *);
7571+void nntp_add_to_list (NNTP_SERVER *, NNTP_DATA *);
7572+void nntp_cache_expand (char *, const char *);
7573+void nntp_delete_data (void *);
7574+
7575+/* exposed interface */
7576+NNTP_SERVER *mutt_select_newsserver (char *);
7577+NNTP_DATA *mutt_newsgroup_subscribe (NNTP_SERVER *, char *);
7578+NNTP_DATA *mutt_newsgroup_unsubscribe (NNTP_SERVER *, char *);
7579+NNTP_DATA *mutt_newsgroup_catchup (NNTP_SERVER *, char *);
7580+NNTP_DATA *mutt_newsgroup_uncatchup (NNTP_SERVER *, char *);
7581+void nntp_clear_cacheindex (NNTP_SERVER *);
7582+int mutt_newsrc_update (NNTP_SERVER *);
7583+int nntp_open_mailbox (CONTEXT *);
7584+int nntp_sync_mailbox (CONTEXT *);
7585+int nntp_check_mailbox (CONTEXT *);
7586+int nntp_close_mailbox (CONTEXT *);
7587+void nntp_fastclose_mailbox (CONTEXT *);
7588+int nntp_fetch_message (MESSAGE *, CONTEXT *, int);
7589+int nntp_post (const char *);
7590+int nntp_check_msgid (CONTEXT *, const char *);
7591+int nntp_check_children (CONTEXT *, const char *);
7592+void nntp_buffy (char *);
7593+void nntp_expand_path (char *, size_t, ACCOUNT *);
7594+void nntp_logout_all ();
7595+const char *nntp_format_str (char *, size_t, char, const char *, const char *,
7596+ const char *, const char *, unsigned long, format_flag);
7597+
7598+NNTP_SERVER *CurrentNewsSrv INITVAL (NULL);
7599+
7600+#endif /* _NNTP_H_ */
7601diff -uNr mutt-1.4.orig/pager.c mutt-1.4/pager.c
7602--- mutt-1.4.orig/pager.c Sun Nov 3 21:42:52 2002
7603+++ mutt-1.4/pager.c Sun Nov 3 21:57:20 2002
7604@@ -33,6 +33,11 @@
7605 #include "imap.h"
7606 #endif
7607
7608+#ifdef USE_NNTP
7609+#include "mx.h"
7610+#include "nntp.h"
7611+#endif
7612+
7613
7614 #ifdef HAVE_PGP
7615 #include "pgp.h"
7616@@ -1445,6 +1450,16 @@
7617 { NULL, 0 }
7618 };
7619
7620+#ifdef USE_NNTP
7621+static struct mapping_t PagerNewsHelpExtra[] = {
7622+ { N_("Post"), OP_POST },
7623+ { N_("Followup"), OP_FOLLOWUP },
7624+ { N_("Del"), OP_DELETE },
7625+ { N_("Next"), OP_MAIN_NEXT_UNDELETED },
7626+ { NULL, 0 }
7627+};
7628+#endif
7629+
7630
7631
7632 /* This pager is actually not so simple as it once was. It now operates in
7633@@ -1486,6 +1501,10 @@
7634 int old_PagerIndexLines; /* some people want to resize it
7635 * while inside the pager... */
7636
7637+#ifdef USE_NNTP
7638+ char *followup_to;
7639+#endif
7640+
7641 if (!(flags & M_SHOWCOLOR))
7642 flags |= M_SHOWFLAT;
7643
7644@@ -1525,7 +1544,11 @@
7645 if (IsHeader (extra))
7646 {
7647 strfcpy (tmphelp, helpstr, sizeof (tmphelp));
7648- mutt_compile_help (buffer, sizeof (buffer), MENU_PAGER, PagerHelpExtra);
7649+ mutt_compile_help (buffer, sizeof (buffer), MENU_PAGER,
7650+#ifdef USE_NNTP
7651+ (Context && (Context->magic == M_NNTP)) ? PagerNewsHelpExtra :
7652+#endif
7653+ PagerHelpExtra);
7654 snprintf (helpstr, sizeof (helpstr), "%s %s", tmphelp, buffer);
7655 }
7656 if (!InHelp)
7657@@ -2300,6 +2323,15 @@
7658 }
7659 #endif
7660
7661+#ifdef USE_NNTP
7662+ if (Context->magic == M_NNTP)
7663+ {
7664+ mutt_flushinp ();
7665+ mutt_error _("Can't change 'important' flag on NNTP server.");
7666+ break;
7667+ }
7668+#endif
7669+
7670 mutt_set_flag (Context, extra->hdr, M_FLAG, !extra->hdr->flagged);
7671 redraw = REDRAW_STATUS | REDRAW_INDEX;
7672 if (option (OPTRESOLVE))
7673@@ -2333,6 +2365,60 @@
7674 redraw = REDRAW_FULL;
7675 break;
7676
7677+#ifdef USE_NNTP
7678+ case OP_POST:
7679+ CHECK_MODE(IsHeader (extra) && !IsAttach (extra));
7680+ CHECK_ATTACH;
7681+ if (extra->ctx && extra->ctx->magic == M_NNTP &&
7682+ !((NNTP_DATA *)extra->ctx->data)->allowed &&
7683+ query_quadoption (OPT_TOMODERATED,_("Posting to this group not allowed, may be moderated. Continue?")) != M_YES)
7684+ break;
7685+ ci_send_message (SENDNEWS, NULL, NULL, extra->ctx, NULL);
7686+ redraw = REDRAW_FULL;
7687+ break;
7688+
7689+ case OP_FORWARD_TO_GROUP:
7690+ CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra));
7691+ CHECK_ATTACH;
7692+ if (extra->ctx && extra->ctx->magic == M_NNTP &&
7693+ !((NNTP_DATA *)extra->ctx->data)->allowed &&
7694+ query_quadoption (OPT_TOMODERATED,_("Posting to this group not allowed, may be moderated. Continue?")) != M_YES)
7695+ break;
7696+ if (IsMsgAttach (extra))
7697+ mutt_attach_forward (extra->fp, extra->hdr, extra->idx,
7698+ extra->idxlen, extra->bdy, SENDNEWS);
7699+ else
7700+ ci_send_message (SENDNEWS|SENDFORWARD, NULL, NULL, extra->ctx, extra->hdr);
7701+ redraw = REDRAW_FULL;
7702+ break;
7703+
7704+ case OP_FOLLOWUP:
7705+ CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra));
7706+ CHECK_ATTACH;
7707+
7708+ if (IsMsgAttach (extra))
7709+ followup_to = extra->bdy->hdr->env->followup_to;
7710+ else
7711+ followup_to = extra->hdr->env->followup_to;
7712+
7713+ if (!followup_to || mutt_strcasecmp (followup_to, "poster") ||
7714+ query_quadoption (OPT_FOLLOWUPTOPOSTER,_("Reply by mail as poster prefers?")) != M_YES)
7715+ {
7716+ if (extra->ctx && extra->ctx->magic == M_NNTP &&
7717+ !((NNTP_DATA *)extra->ctx->data)->allowed &&
7718+ query_quadoption (OPT_TOMODERATED,_("Posting to this group not allowed, may be moderated. Continue?")) != M_YES)
7719+ break;
7720+ if (IsMsgAttach (extra))
7721+ mutt_attach_reply (extra->fp, extra->hdr, extra->idx,
7722+ extra->idxlen, extra->bdy, SENDNEWS|SENDREPLY);
7723+ else
7724+ ci_send_message (SENDNEWS|SENDREPLY, NULL, NULL,
7725+ extra->ctx, extra->hdr);
7726+ redraw = REDRAW_FULL;
7727+ break;
7728+ }
7729+#endif
7730+
7731 case OP_REPLY:
7732 CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra));
7733 CHECK_ATTACH;
7734@@ -2379,7 +2465,7 @@
7735 CHECK_ATTACH;
7736 if (IsMsgAttach (extra))
7737 mutt_attach_forward (extra->fp, extra->hdr, extra->idx,
7738- extra->idxlen, extra->bdy);
7739+ extra->idxlen, extra->bdy, 0);
7740 else
7741 ci_send_message (SENDFORWARD, NULL, NULL, extra->ctx, extra->hdr);
7742 redraw = REDRAW_FULL;
7743diff -uNr mutt-1.4.orig/parse.c mutt-1.4/parse.c
7744--- mutt-1.4.orig/parse.c Tue Jan 29 11:05:20 2002
7745+++ mutt-1.4/parse.c Sun Nov 3 21:57:20 2002
7746@@ -90,7 +90,7 @@
7747 /* not reached */
7748 }
7749
7750-static LIST *mutt_parse_references (char *s, int in_reply_to)
7751+LIST *mutt_parse_references (char *s, int in_reply_to)
7752 {
7753 LIST *t, *lst = NULL;
7754 int m, n = 0;
7755@@ -1047,6 +1047,17 @@
7756 e->from = rfc822_parse_adrlist (e->from, p);
7757 matched = 1;
7758 }
7759+#ifdef USE_NNTP
7760+ else if (!mutt_strcasecmp (line+1, "ollowup-to"))
7761+ {
7762+ if (!e->followup_to)
7763+ {
7764+ mutt_remove_trailing_ws (p);
7765+ e->followup_to = safe_strdup (mutt_skip_whitespace (p));
7766+ }
7767+ matched = 1;
7768+ }
7769+#endif
7770 break;
7771
7772 case 'i':
7773@@ -1098,6 +1109,27 @@
7774 }
7775 break;
7776
7777+#ifdef USE_NNTP
7778+ case 'n':
7779+ if (!mutt_strcasecmp (line + 1, "ewsgroups"))
7780+ {
7781+ safe_free ((void **)&e->newsgroups);
7782+ mutt_remove_trailing_ws (p);
7783+ e->newsgroups = safe_strdup (mutt_skip_whitespace (p));
7784+ matched = 1;
7785+ }
7786+ break;
7787+#endif
7788+
7789+ case 'o':
7790+ /* field `Organization:' saves only for pager! */
7791+ if (!mutt_strcasecmp (line + 1, "rganization"))
7792+ {
7793+ if (!e->organization && mutt_strcasecmp (p, "unknown"))
7794+ e->organization = safe_strdup (p);
7795+ }
7796+ break;
7797+
7798 case 'r':
7799 if (!ascii_strcasecmp (line + 1, "eferences"))
7800 {
7801@@ -1207,7 +1239,21 @@
7802 e->x_label = safe_strdup(p);
7803 matched = 1;
7804 }
7805-
7806+#ifdef USE_NNTP
7807+ else if (!mutt_strcasecmp (line + 1, "-comment-to"))
7808+ {
7809+ if (!e->x_comment_to)
7810+ e->x_comment_to = safe_strdup (p);
7811+ matched = 1;
7812+ }
7813+ else if (!mutt_strcasecmp (line + 1, "ref"))
7814+ {
7815+ if (!e->xref)
7816+ e->xref = safe_strdup (p);
7817+ matched = 1;
7818+ }
7819+#endif
7820+
7821 default:
7822 break;
7823 }
7824diff -uNr mutt-1.4.orig/pattern.c mutt-1.4/pattern.c
7825--- mutt-1.4.orig/pattern.c Sun Nov 3 21:42:52 2002
7826+++ mutt-1.4/pattern.c Sun Nov 3 21:57:20 2002
7827@@ -87,6 +87,9 @@
7828 { 't', M_TO, 0, eat_regexp },
7829 { 'U', M_UNREAD, 0, NULL },
7830 { 'v', M_COLLAPSED, 0, NULL },
7831+#ifdef USE_NNTP
7832+ { 'w', M_NEWSGROUPS, 0, eat_regexp },
7833+#endif
7834 { 'x', M_REFERENCE, 0, eat_regexp },
7835 { 'y', M_XLABEL, 0, eat_regexp },
7836 { 'z', M_SIZE, 0, eat_range },
7837@@ -1053,6 +1056,10 @@
7838 return (pat->not ^ (h->env->x_label && regexec (pat->rx, h->env->x_label, 0, NULL, 0) == 0));
7839 case M_DUPLICATED:
7840 return (pat->not ^ (h->thread && h->thread->duplicate_thread));
7841+#ifdef USE_NNTP
7842+ case M_NEWSGROUPS:
7843+ return (pat->not ^ (h->env->newsgroups && regexec (pat->rx, h->env->newsgroups, 0, NULL, 0) == 0));
7844+#endif
7845 }
7846 mutt_error (_("error: unknown op %d (report this error)."), pat->op);
7847 return (-1);
7848@@ -1120,6 +1127,7 @@
7849 int i;
7850
7851 strfcpy (buf, NONULL (Context->pattern), sizeof (buf));
7852+ if (prompt || op != M_LIMIT)
7853 if (mutt_get_field (prompt, buf, sizeof (buf), M_PATTERN | M_CLEAR) != 0 || !buf[0])
7854 return (-1);
7855
1b5dcea5 7856diff -uNr mutt-1.4.orig/po/POTFILES.in mutt-1.4/po/POTFILES.in
7857--- mutt-1.4.orig/po/POTFILES.in Sun Nov 3 21:42:51 2002
7858+++ mutt-1.4/po/POTFILES.in Sun Nov 3 21:57:20 2002
7859@@ -41,6 +41,8 @@
7860 mutt_socket.c
7861 mutt_ssl.c
7862 mx.c
7863+newsrc.c
7864+nntp.c
7865 pager.c
7866 parse.c
7867 pattern.c
1b5dcea5 7868diff -uNr mutt-1.4.orig/postpone.c mutt-1.4/postpone.c
7869--- mutt-1.4.orig/postpone.c Sun Nov 3 21:42:52 2002
7870+++ mutt-1.4/postpone.c Sun Nov 3 21:57:20 2002
7871@@ -125,15 +125,26 @@
7872
7873 if (LastModify < st.st_mtime)
7874 {
7875+#ifdef USE_NNTP
7876+ int optnews = option (OPTNEWS);
7877+#endif
7878 LastModify = st.st_mtime;
7879
7880 if (access (Postponed, R_OK | F_OK) != 0)
7881 return (PostCount = 0);
7882+#ifdef USE_NNTP
7883+ if (optnews)
7884+ unset_option (OPTNEWS);
7885+#endif
7886 if (mx_open_mailbox (Postponed, M_NOSORT | M_QUIET, &ctx) == NULL)
7887 PostCount = 0;
7888 else
7889 PostCount = ctx.msgcount;
7890 mx_fastclose_mailbox (&ctx);
7891+#ifdef USE_NNTP
7892+ if (optnews)
7893+ set_option (OPTNEWS);
7894+#endif
7895 }
7896
7897 return (PostCount);
7898diff -uNr mutt-1.4.orig/protos.h mutt-1.4/protos.h
7899--- mutt-1.4.orig/protos.h Sun Nov 3 21:42:52 2002
7900+++ mutt-1.4/protos.h Sun Nov 3 21:57:20 2002
7901@@ -95,6 +95,7 @@
7902 HASH *mutt_make_subj_hash (CONTEXT *);
7903
7904 LIST *mutt_make_references(ENVELOPE *e);
7905+LIST *mutt_parse_references (char *, int);
7906
7907 ENVELOPE *mutt_read_rfc822_header (FILE *, HEADER *, short, short);
7908 HEADER *mutt_dup_header (HEADER *);
7909@@ -230,6 +231,7 @@
7910 void mutt_update_tree (ATTACHPTR **, short);
7911 void mutt_version (void);
7912 void mutt_view_attachments (HEADER *);
7913+void mutt_write_references (LIST *, FILE *);
7914 void mutt_set_virtual (CONTEXT *);
7915
7916 int mutt_addr_is_user (ADDRESS *);
7917@@ -316,6 +318,7 @@
7918 int mutt_search_command (int, int);
7919 int mutt_compose_menu (HEADER *, char *, size_t, HEADER *);
7920 int mutt_thread_set_flag (HEADER *, int, int, int);
7921+int mutt_update_list_file (char *, char *, char *, char *);
7922 int mutt_user_is_recipient (HEADER *);
7923 void mutt_update_num_postponed (void);
7924 int mutt_view_attachment (FILE*, BODY *, int, HEADER *, ATTACHPTR **, short);
7925diff -uNr mutt-1.4.orig/recvattach.c mutt-1.4/recvattach.c
7926--- mutt-1.4.orig/recvattach.c Wed Sep 26 12:33:09 2001
7927+++ mutt-1.4/recvattach.c Sun Nov 3 21:57:20 2002
7928@@ -989,6 +989,15 @@
7929 }
7930 #endif
7931
7932+#ifdef USE_NNTP
7933+ if (Context->magic == M_NNTP)
7934+ {
7935+ mutt_flushinp ();
7936+ mutt_error _("Can't delete attachment from newsserver.");
7937+ break;
7938+ }
7939+#endif
7940+
7941
7942
7943 #ifdef HAVE_PGP
7944@@ -1084,10 +1093,33 @@
7945 case OP_FORWARD_MESSAGE:
7946 CHECK_ATTACH;
7947 mutt_attach_forward (fp, hdr, idx, idxlen,
7948- menu->tagprefix ? NULL : idx[menu->current]->content);
7949+ menu->tagprefix ? NULL : idx[menu->current]->content, 0);
7950 menu->redraw = REDRAW_FULL;
7951 break;
7952
7953+#ifdef USE_NNTP
7954+ case OP_FORWARD_TO_GROUP:
7955+ CHECK_ATTACH;
7956+ mutt_attach_forward (fp, hdr, idx, idxlen,
7957+ menu->tagprefix ? NULL : idx[menu->current]->content, SENDNEWS);
7958+ menu->redraw = REDRAW_FULL;
7959+ break;
7960+
7961+ case OP_FOLLOWUP:
7962+ CHECK_ATTACH;
7963+
7964+ if (!idx[menu->current]->content->hdr->env->followup_to ||
7965+ mutt_strcasecmp (idx[menu->current]->content->hdr->env->followup_to, "poster") ||
7966+ query_quadoption (OPT_FOLLOWUPTOPOSTER,_("Reply by mail as poster prefers?")) != M_YES)
7967+ {
7968+ mutt_attach_reply (fp, hdr, idx, idxlen,
7969+ menu->tagprefix ? NULL : idx[menu->current]->content,
7970+ SENDNEWS|SENDREPLY);
7971+ menu->redraw = REDRAW_FULL;
7972+ break;
7973+ }
7974+#endif
7975+
7976 case OP_REPLY:
7977 case OP_GROUP_REPLY:
7978 case OP_LIST_REPLY:
7979diff -uNr mutt-1.4.orig/recvcmd.c mutt-1.4/recvcmd.c
7980--- mutt-1.4.orig/recvcmd.c Wed Jan 2 10:33:38 2002
7981+++ mutt-1.4/recvcmd.c Sun Nov 3 21:57:20 2002
7982@@ -334,7 +334,7 @@
7983 static void attach_forward_bodies (FILE * fp, HEADER * hdr,
7984 ATTACHPTR ** idx, short idxlen,
7985 BODY * cur,
7986- short nattach)
7987+ short nattach, int flags)
7988 {
7989 short i;
7990 short mime_fwd_all = 0;
7991@@ -480,7 +480,7 @@
7992 tmpfp = NULL;
7993
7994 /* now that we have the template, send it. */
7995- ci_send_message (0, tmphdr, tmpbody, NULL, parent);
7996+ ci_send_message (flags, tmphdr, tmpbody, NULL, parent);
7997 return;
7998
7999 bail:
8000@@ -507,7 +507,7 @@
8001 */
8002
8003 static void attach_forward_msgs (FILE * fp, HEADER * hdr,
8004- ATTACHPTR ** idx, short idxlen, BODY * cur)
8005+ ATTACHPTR ** idx, short idxlen, BODY * cur, int flags)
8006 {
8007 HEADER *curhdr = NULL;
8008 HEADER *tmphdr;
8009@@ -612,23 +612,23 @@
8010 else
8011 mutt_free_header (&tmphdr);
8012
8013- ci_send_message (0, tmphdr, *tmpbody ? tmpbody : NULL,
8014+ ci_send_message (flags, tmphdr, *tmpbody ? tmpbody : NULL,
8015 NULL, curhdr);
8016
8017 }
8018
8019 void mutt_attach_forward (FILE * fp, HEADER * hdr,
8020- ATTACHPTR ** idx, short idxlen, BODY * cur)
8021+ ATTACHPTR ** idx, short idxlen, BODY * cur, int flags)
8022 {
8023 short nattach;
8024
8025
8026 if (check_all_msg (idx, idxlen, cur, 0) == 0)
8027- attach_forward_msgs (fp, hdr, idx, idxlen, cur);
8028+ attach_forward_msgs (fp, hdr, idx, idxlen, cur, flags);
8029 else
8030 {
8031 nattach = count_tagged (idx, idxlen);
8032- attach_forward_bodies (fp, hdr, idx, idxlen, cur, nattach);
8033+ attach_forward_bodies (fp, hdr, idx, idxlen, cur, nattach, flags);
8034 }
8035 }
8036
8037@@ -686,28 +686,40 @@
8038 return -1;
8039 }
8040
8041- if (parent)
8042+#ifdef USE_NNTP
8043+ if ((flags & SENDNEWS))
8044 {
8045- if (mutt_fetch_recips (env, curenv, flags) == -1)
8046- return -1;
8047+ /* in case followup set Newsgroups: with Followup-To: if it present */
8048+ if (!env->newsgroups && curenv &&
8049+ mutt_strcasecmp (curenv->followup_to, "poster"))
8050+ env->newsgroups = safe_strdup (curenv->followup_to);
8051 }
8052 else
8053+#endif
8054 {
8055- for (i = 0; i < idxlen; i++)
8056+ if (parent)
8057 {
8058- if (idx[i]->content->tagged
8059- && mutt_fetch_recips (env, idx[i]->content->hdr->env, flags) == -1)
8060+ if (mutt_fetch_recips (env, curenv, flags) == -1)
8061 return -1;
8062 }
8063+ else
8064+ {
8065+ for (i = 0; i < idxlen; i++)
8066+ {
8067+ if (idx[i]->content->tagged
8068+ && mutt_fetch_recips (env, idx[i]->content->hdr->env, flags) == -1)
8069+ return -1;
8070+ }
8071+ }
8072+
8073+ if ((flags & SENDLISTREPLY) && !env->to)
8074+ {
8075+ mutt_error _("No mailing lists found!");
8076+ return (-1);
8077+ }
8078+
8079+ mutt_fix_reply_recipients (env);
8080 }
8081-
8082- if ((flags & SENDLISTREPLY) && !env->to)
8083- {
8084- mutt_error _("No mailing lists found!");
8085- return (-1);
8086- }
8087-
8088- mutt_fix_reply_recipients (env);
8089 mutt_make_misc_reply_headers (env, Context, curhdr, curenv);
8090
8091 if (parent)
8092@@ -768,6 +780,13 @@
8093 char prefix[SHORT_STRING];
8094 int rc;
8095
8096+#ifdef USE_NNTP
8097+ if (flags & SENDNEWS)
8098+ set_option (OPTNEWSSEND);
8099+ else
8100+ unset_option (OPTNEWSSEND);
8101+#endif
8102+
8103 if (check_all_msg (idx, idxlen, cur, 0) == -1)
8104 {
8105 nattach = count_tagged (idx, idxlen);
8106diff -uNr mutt-1.4.orig/rfc1524.c mutt-1.4/rfc1524.c
8107--- mutt-1.4.orig/rfc1524.c Tue May 15 09:23:49 2001
8108+++ mutt-1.4/rfc1524.c Sun Nov 3 21:57:20 2002
8109@@ -563,13 +563,13 @@
8110 * safe_fopen().
8111 */
8112
8113-int mutt_rename_file (char *oldfile, char *newfile)
8114+int _mutt_rename_file (char *oldfile, char *newfile, int overwrite)
8115 {
8116 FILE *ofp, *nfp;
8117
8118 if (access (oldfile, F_OK) != 0)
8119 return 1;
8120- if (access (newfile, F_OK) == 0)
8121+ if (!overwrite && access (newfile, F_OK) == 0)
8122 return 2;
8123 if ((ofp = fopen (oldfile,"r")) == NULL)
8124 return 3;
8125@@ -584,3 +584,8 @@
8126 mutt_unlink (oldfile);
8127 return 0;
8128 }
8129+
8130+int mutt_rename_file (char *oldfile, char *newfile)
8131+{
8132+ return _mutt_rename_file (oldfile, newfile, 0);
8133+}
8134diff -uNr mutt-1.4.orig/rfc1524.h mutt-1.4/rfc1524.h
8135--- mutt-1.4.orig/rfc1524.h Fri Mar 3 11:10:13 2000
8136+++ mutt-1.4/rfc1524.h Sun Nov 3 21:57:20 2002
8137@@ -40,5 +40,6 @@
8138 int rfc1524_expand_filename (char *, char *, char *, size_t);
8139 int rfc1524_mailcap_lookup (BODY *, char *, rfc1524_entry *, int);
8140 int mutt_rename_file (char *, char *);
8141+int _mutt_rename_file (char *, char *, int);
8142
8143 #endif /* _RFC1524_H */
8144diff -uNr mutt-1.4.orig/send.c mutt-1.4/send.c
8145--- mutt-1.4.orig/send.c Wed Jan 30 23:50:40 2002
8146+++ mutt-1.4/send.c Sun Nov 3 21:57:20 2002
8147@@ -41,6 +41,10 @@
8148 #include "pgp.h"
8149 #endif
8150
8151+#ifdef USE_NNTP
8152+#include "nntp.h"
8153+#endif
8154+
8155 #ifdef MIXMASTER
8156 #include "remailer.h"
8157 #endif
8158@@ -196,17 +200,51 @@
8159 return 0;
8160 }
8161
8162-static int edit_envelope (ENVELOPE *en)
8163+static int edit_envelope (ENVELOPE *en, int flags)
8164 {
8165 char buf[HUGE_STRING];
8166 LIST *uh = UserHeader;
8167
8168- if (edit_address (&en->to, "To: ") == -1 || en->to == NULL)
8169- return (-1);
8170- if (option (OPTASKCC) && edit_address (&en->cc, "Cc: ") == -1)
8171- return (-1);
8172- if (option (OPTASKBCC) && edit_address (&en->bcc, "Bcc: ") == -1)
8173- return (-1);
8174+#ifdef USE_NNTP
8175+ if (option (OPTNEWSSEND))
8176+ {
8177+ if (en->newsgroups)
8178+ strfcpy (buf, en->newsgroups, sizeof (buf));
8179+ else
8180+ buf[0] = 0;
8181+ if (mutt_get_field ("Newsgroups: ", buf, sizeof (buf), 0) != 0)
8182+ return (-1);
8183+ safe_free ((void **)&en->newsgroups);
8184+ en->newsgroups = safe_strdup (buf);
8185+
8186+ if (en->followup_to)
8187+ strfcpy (buf, en->followup_to, sizeof (buf));
8188+ else
8189+ buf[0] = 0;
8190+ if (option (OPTASKFOLLOWUP) && mutt_get_field ("Followup-To: ", buf, sizeof (buf), 0) != 0)
8191+ return (-1);
8192+ safe_free ((void **)&en->followup_to);
8193+ en->followup_to = safe_strdup (buf);
8194+
8195+ if (en->x_comment_to)
8196+ strfcpy (buf, en->x_comment_to, sizeof (buf));
8197+ else
8198+ buf[0] = 0;
8199+ if (option (OPTXCOMMENTTO) && option (OPTASKXCOMMENTTO) && mutt_get_field ("X-Comment-To: ", buf, sizeof (buf), 0) != 0)
8200+ return (-1);
8201+ safe_free ((void **)&en->x_comment_to);
8202+ en->x_comment_to = safe_strdup (buf);
8203+ }
8204+ else
8205+#endif
8206+ {
8207+ if (edit_address (&en->to, "To: ") == -1 || en->to == NULL)
8208+ return (-1);
8209+ if (option (OPTASKCC) && edit_address (&en->cc, "Cc: ") == -1)
8210+ return (-1);
8211+ if (option (OPTASKBCC) && edit_address (&en->bcc, "Bcc: ") == -1)
8212+ return (-1);
8213+ }
8214
8215 if (en->subject)
8216 {
8217@@ -242,6 +280,14 @@
8218 return 0;
8219 }
8220
8221+#ifdef USE_NNTP
8222+char *nntp_get_header (const char *s)
8223+{
8224+ SKIPWS (s);
8225+ return safe_strdup (s);
8226+}
8227+#endif
8228+
8229 static void process_user_recips (ENVELOPE *env)
8230 {
8231 LIST *uh = UserHeader;
8232@@ -254,6 +300,14 @@
8233 env->cc = rfc822_parse_adrlist (env->cc, uh->data + 3);
8234 else if (ascii_strncasecmp ("bcc:", uh->data, 4) == 0)
8235 env->bcc = rfc822_parse_adrlist (env->bcc, uh->data + 4);
8236+#ifdef USE_NNTP
8237+ else if (ascii_strncasecmp ("newsgroups:", uh->data, 11) == 0)
8238+ env->newsgroups = nntp_get_header (uh->data + 11);
8239+ else if (ascii_strncasecmp ("followup-to:", uh->data, 12) == 0)
8240+ env->followup_to = nntp_get_header (uh->data + 12);
8241+ else if (ascii_strncasecmp ("x-comment-to:", uh->data, 13) == 0)
8242+ env->x_comment_to = nntp_get_header (uh->data + 13);
8243+#endif
8244 }
8245 }
8246
8247@@ -284,6 +338,12 @@
8248 else if (ascii_strncasecmp ("to:", uh->data, 3) != 0 &&
8249 ascii_strncasecmp ("cc:", uh->data, 3) != 0 &&
8250 ascii_strncasecmp ("bcc:", uh->data, 4) != 0 &&
8251+#ifdef USE_NNTP
8252+ ascii_strncasecmp ("newsgroups:", uh->data, 11) != 0 &&
8253+ ascii_strncasecmp ("followup-to:", uh->data, 12) != 0 &&
8254+ ascii_strncasecmp ("x-comment-to:", uh->data, 13) != 0 &&
8255+#endif
8256+ ascii_strncasecmp ("supersedes:", uh->data, 11) != 0 &&
8257 ascii_strncasecmp ("subject:", uh->data, 8) != 0)
8258 {
8259 if (last)
8260@@ -597,6 +657,10 @@
8261 else
8262 env->subject = safe_strdup ("Re: your mail");
8263
8264+#ifdef USE_NNTP
8265+ if (option (OPTNEWSSEND) && option (OPTXCOMMENTTO) && curenv->from)
8266+ env->x_comment_to = safe_strdup (mutt_get_name (curenv->from));
8267+#endif
8268 }
8269
8270 void mutt_add_to_reference_headers (ENVELOPE *env, ENVELOPE *curenv, LIST ***pp, LIST ***qq)
8271@@ -679,27 +743,39 @@
8272
8273 if (flags & SENDREPLY)
8274 {
8275- if (tag)
8276+#ifdef USE_NNTP
8277+ if ((flags & SENDNEWS))
8278 {
8279- HEADER *h;
8280-
8281- for (i = 0; i < ctx->vcount; i++)
8282+ /* in case followup set Newsgroups: with Followup-To: if it present */
8283+ if (!env->newsgroups && curenv &&
8284+ mutt_strcasecmp (curenv->followup_to, "poster"))
8285+ env->newsgroups = safe_strdup (curenv->followup_to);
8286+ }
8287+ else
8288+#endif
8289+ {
8290+ if (tag)
8291 {
8292- h = ctx->hdrs[ctx->v2r[i]];
8293- if (h->tagged && mutt_fetch_recips (env, h->env, flags) == -1)
8294+ HEADER *h;
8295+
8296+ for (i = 0; i < ctx->vcount; i++)
8297+ {
8298+ h = ctx->hdrs[ctx->v2r[i]];
8299+ if (h->tagged && mutt_fetch_recips (env, h->env, flags) == -1)
8300+ return -1;
8301+ }
8302+ }
8303+ else if (mutt_fetch_recips (env, curenv, flags) == -1)
8304 return -1;
8305+
8306+ if ((flags & SENDLISTREPLY) && !env->to)
8307+ {
8308+ mutt_error _("No mailing lists found!");
8309+ return (-1);
8310 }
8311- }
8312- else if (mutt_fetch_recips (env, curenv, flags) == -1)
8313- return -1;
8314
8315- if ((flags & SENDLISTREPLY) && !env->to)
8316- {
8317- mutt_error _("No mailing lists found!");
8318- return (-1);
8319+ mutt_fix_reply_recipients (env);
8320 }
8321-
8322- mutt_fix_reply_recipients (env);
8323 mutt_make_misc_reply_headers (env, ctx, cur, curenv);
8324 mutt_make_reference_headers (tag ? NULL : curenv, env, ctx);
8325 }
8326@@ -828,7 +904,18 @@
8327 * it hasn't already been set
8328 */
8329
8330- if (option (OPTFOLLOWUPTO) && !e->mail_followup_to)
8331+ if (!option (OPTFOLLOWUPTO))
8332+ return;
8333+#ifdef USE_NNTP
8334+ if (option (OPTNEWSSEND))
8335+ {
8336+ if (!e->followup_to && e->newsgroups && (strrchr (e->newsgroups, ',')))
8337+ e->followup_to = safe_strdup (e->newsgroups);
8338+ return;
8339+ }
8340+#endif
8341+
8342+ if (!e->mail_followup_to)
8343 {
8344 if (mutt_is_list_cc (0, e->to, e->cc))
8345 {
8346@@ -1084,6 +1171,13 @@
8347
8348 int rv = -1;
8349
8350+#ifdef USE_NNTP
8351+ if (flags & SENDNEWS)
8352+ set_option (OPTNEWSSEND);
8353+ else
8354+ unset_option (OPTNEWSSEND);
8355+#endif
8356+
8357 if (!flags && !msg && quadoption (OPT_RECALL) != M_NO &&
8358 mutt_num_postponed (1))
8359 {
8360@@ -1115,6 +1209,22 @@
8361 {
8362 if ((flags = mutt_get_postponed (ctx, msg, &cur, fcc, sizeof (fcc))) < 0)
8363 goto cleanup;
8364+#ifdef USE_NNTP
8365+ /*
8366+ * If postponed message is a news article, it have
8367+ * a "Newsgroups:" header line, then set appropriate flag.
8368+ */
8369+ if (msg->env->newsgroups)
8370+ {
8371+ flags |= SENDNEWS;
8372+ set_option (OPTNEWSSEND);
8373+ }
8374+ else
8375+ {
8376+ flags &= ~SENDNEWS;
8377+ unset_option (OPTNEWSSEND);
8378+ }
8379+#endif
8380 }
8381
8382 if (flags & (SENDPOSTPONED|SENDRESEND))
8383@@ -1195,11 +1305,16 @@
8384 if (option (OPTHDRS))
8385 process_user_recips (msg->env);
8386
8387+#ifdef USE_NNTP
8388+ if ((flags & SENDNEWS) && ctx && ctx->magic == M_NNTP && !msg->env->newsgroups)
8389+ msg->env->newsgroups = safe_strdup (((NNTP_DATA *)ctx->data)->group);
8390+#endif
8391+
8392 if (! (flags & SENDMAILX) &&
8393 ! (option (OPTAUTOEDIT) && option (OPTEDITHDRS)) &&
8394 ! ((flags & SENDREPLY) && option (OPTFASTREPLY)))
8395 {
8396- if (edit_envelope (msg->env) == -1)
8397+ if (edit_envelope (msg->env, flags) == -1)
8398 goto cleanup;
8399 }
8400
8401@@ -1349,6 +1464,11 @@
8402 if (i == -1)
8403 {
8404 /* abort */
8405+#ifdef USE_NNTP
8406+ if (flags & SENDNEWS)
8407+ mutt_message _("Article not posted.");
8408+ else
8409+#endif
8410 mutt_message _("Mail not sent.");
8411 goto cleanup;
8412 }
8413@@ -1380,6 +1500,9 @@
8414 }
8415 }
8416
8417+#ifdef USE_NNTP
8418+ if (!(flags & SENDNEWS))
8419+#endif
8420 if (!msg->env->to && !msg->env->cc && !msg->env->bcc)
8421 {
8422 if (! (flags & SENDBATCH))
8423@@ -1402,6 +1525,19 @@
8424 mutt_error _("No subject specified.");
8425 goto main_loop;
8426 }
8427+#ifdef USE_NNTP
8428+ if ((flags & SENDNEWS) && !msg->env->subject)
8429+ {
8430+ mutt_error _("No subject specified.");
8431+ goto main_loop;
8432+ }
8433+
8434+ if ((flags & SENDNEWS) && !msg->env->newsgroups)
8435+ {
8436+ mutt_error _("No newsgroup specified.");
8437+ goto main_loop;
8438+ }
8439+#endif
8440
8441 if (msg->content->next)
8442 msg->content = mutt_make_multipart (msg->content);
8443@@ -1588,7 +1724,12 @@
8444 }
8445 }
8446 else if (!option (OPTNOCURSES) && ! (flags & SENDMAILX))
8447- mutt_message (i == 0 ? _("Mail sent.") : _("Sending in background."));
8448+ mutt_message (i != 0 ? _("Sending in background.") :
8449+#ifdef USE_NNTP
8450+ (flags & SENDNEWS) ? _("Article posted.") : _("Mail sent."));
8451+#else
8452+ _("Mail sent."));
8453+#endif
8454
8455 #ifdef HAVE_PGP
8456 if (msg->pgp & PGPENCRYPT)
8457diff -uNr mutt-1.4.orig/sendlib.c mutt-1.4/sendlib.c
8458--- mutt-1.4.orig/sendlib.c Sat Apr 20 09:25:49 2002
8459+++ mutt-1.4/sendlib.c Sun Nov 3 21:57:20 2002
8460@@ -40,6 +40,10 @@
8461 #include <sys/wait.h>
8462 #include <fcntl.h>
8463
8464+#ifdef USE_NNTP
8465+#include <nntp.h>
8466+#endif
8467+
8468 #ifdef HAVE_SYSEXITS_H
8469 #include <sysexits.h>
8470 #else /* Make sure EX_OK is defined <philiph@pobox.com> */
8471@@ -1537,7 +1541,7 @@
8472 /* need to write the list in reverse because they are stored in reverse order
8473 * when parsed to speed up threading
8474 */
8475-static void write_references (LIST *r, FILE *f)
8476+void mutt_write_references (LIST *r, FILE *f)
8477 {
8478 LIST **ref = NULL;
8479 int refcnt = 0, refmax = 0;
8480@@ -1579,6 +1583,9 @@
8481 char *p;
8482 LIST *tmp = env->userhdrs;
8483
8484+#ifdef USE_NNTP
8485+ if (!option (OPTNEWSSEND))
8486+#endif
8487 if (mode == 0 && !privacy)
8488 fputs (mutt_make_date (buffer, sizeof(buffer)), fp);
8489
8490@@ -1598,6 +1605,9 @@
8491 mutt_write_address_list (env->to, fp, 4);
8492 }
8493 else if (mode > 0)
8494+#ifdef USE_NNTP
8495+ if (!option (OPTNEWSSEND))
8496+#endif
8497 fputs ("To: \n", fp);
8498
8499 if (env->cc)
8500@@ -1606,6 +1616,9 @@
8501 mutt_write_address_list (env->cc, fp, 4);
8502 }
8503 else if (mode > 0)
8504+#ifdef USE_NNTP
8505+ if (!option (OPTNEWSSEND))
8506+#endif
8507 fputs ("Cc: \n", fp);
8508
8509 if (env->bcc)
8510@@ -1617,8 +1630,28 @@
8511 }
8512 }
8513 else if (mode > 0)
8514+#ifdef USE_NNTP
8515+ if (!option (OPTNEWSSEND))
8516+#endif
8517 fputs ("Bcc: \n", fp);
8518
8519+#ifdef USE_NNTP
8520+ if (env->newsgroups)
8521+ fprintf (fp, "Newsgroups: %s\n", env->newsgroups);
8522+ else if (mode == 1 && option (OPTNEWSSEND))
8523+ fputs ("Newsgroups: \n", fp);
8524+
8525+ if (env->followup_to)
8526+ fprintf (fp, "Followup-To: %s\n", env->followup_to);
8527+ else if (mode == 1 && option (OPTNEWSSEND))
8528+ fputs ("Followup-To: \n", fp);
8529+
8530+ if (env->x_comment_to)
8531+ fprintf (fp, "X-Comment-To: %s\n", env->x_comment_to);
8532+ else if (mode == 1 && option (OPTNEWSSEND) && option (OPTXCOMMENTTO))
8533+ fputs ("X-Comment-To: \n", fp);
8534+#endif
8535+
8536 if (env->subject)
8537 fprintf (fp, "Subject: %s\n", env->subject);
8538 else if (mode == 1)
8539@@ -1637,6 +1670,9 @@
8540 fputs ("Reply-To: \n", fp);
8541
8542 if (env->mail_followup_to)
8543+#ifdef USE_NNTP
8544+ if (!option (OPTNEWSSEND))
8545+#endif
8546 {
8547 fputs ("Mail-Followup-To: ", fp);
8548 mutt_write_address_list (env->mail_followup_to, fp, 18);
8549@@ -1647,7 +1683,7 @@
8550 if (env->references)
8551 {
8552 fputs ("References:", fp);
8553- write_references (env->references, fp);
8554+ mutt_write_references (env->references, fp);
8555 fputc('\n', fp);
8556 }
8557
8558@@ -1659,7 +1695,7 @@
8559 if (env->in_reply_to)
8560 {
8561 fputs ("In-Reply-To:", fp);
8562- write_references (env->in_reply_to, fp);
8563+ mutt_write_references (env->in_reply_to, fp);
8564 fputc ('\n', fp);
8565 }
8566
8567@@ -1967,11 +2003,30 @@
8568 const char *msg, /* file containing message */
8569 int eightbit) /* message contains 8bit chars */
8570 {
8571- char *ps = NULL, *path = NULL, *s = safe_strdup (Sendmail), *childout = NULL;
8572+ char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL;
8573 char **args = NULL;
8574 size_t argslen = 0, argsmax = 0;
8575 int i;
8576
8577+#ifdef USE_NNTP
8578+ if (option (OPTNEWSSEND))
8579+ {
8580+ char cmd[LONG_STRING];
8581+
8582+ mutt_FormatString (cmd, sizeof (cmd), NONULL (Inews), nntp_format_str, 0, 0);
8583+ if (!*cmd)
8584+ {
8585+ i = nntp_post (msg);
8586+ unlink (msg);
8587+ return i;
8588+ }
8589+
8590+ s = safe_strdup (cmd);
8591+ }
8592+ else
8593+#endif
8594+ s = safe_strdup (Sendmail);
8595+
8596 ps = s;
8597 i = 0;
8598 while ((ps = strtok (ps, " ")))
8599@@ -1995,6 +2050,10 @@
8600 i++;
8601 }
8602
8603+#ifdef USE_NNTP
8604+ if (!option (OPTNEWSSEND))
8605+ {
8606+#endif
8607 if (eightbit && option (OPTUSE8BITMIME))
8608 args = add_option (args, &argslen, &argsmax, "-B8BITMIME");
8609
8610@@ -2017,6 +2076,9 @@
8611 args = add_args (args, &argslen, &argsmax, to);
8612 args = add_args (args, &argslen, &argsmax, cc);
8613 args = add_args (args, &argslen, &argsmax, bcc);
8614+#ifdef USE_NNTP
8615+ }
8616+#endif
8617
8618 if (argslen == argsmax)
8619 safe_realloc ((void **) &args, sizeof (char *) * (++argsmax));
8620@@ -2148,6 +2210,9 @@
8621 rfc2047_encode_adrlist (env->reply_to, "Reply-To");
8622
8623 if (env->subject)
8624+#ifdef USE_NNTP
8625+ if (!option (OPTNEWSSEND) || option (OPTMIMESUBJECT))
8626+#endif
8627 {
8628 rfc2047_encode_string (&env->subject);
8629 }
8630@@ -2234,6 +2299,10 @@
8631
8632 rfc822_write_address (resent_from, sizeof (resent_from), from);
8633
8634+#ifdef USE_NNTP
8635+ unset_option (OPTNEWSSEND);
8636+#endif
8637+
8638 _mutt_bounce_message (fp, h, to, resent_from, from);
8639
8640 rfc822_free_address (&from);
8641diff -uNr mutt-1.4.orig/sort.c mutt-1.4/sort.c
8642--- mutt-1.4.orig/sort.c Thu Dec 13 13:10:59 2001
8643+++ mutt-1.4/sort.c Sun Nov 3 21:57:20 2002
8644@@ -144,6 +144,15 @@
8645 HEADER **ha = (HEADER **) a;
8646 HEADER **hb = (HEADER **) b;
8647
8648+#ifdef USE_NNTP
8649+ if ((*ha)->article_num && (*hb)->article_num)
8650+ {
8651+ int result = (*ha)->article_num - (*hb)->article_num;
8652+ AUXSORT(result,a,b);
8653+ return (SORTCODE (result));
8654+ }
8655+ else
8656+#endif
8657 /* no need to auxsort because you will never have equality here */
8658 return (SORTCODE ((*ha)->index - (*hb)->index));
8659 }
8660diff -uNr mutt-1.4.orig/url.c mutt-1.4/url.c
8661--- mutt-1.4.orig/url.c Mon Oct 29 12:53:45 2001
8662+++ mutt-1.4/url.c Sun Nov 3 21:57:20 2002
8663@@ -35,6 +35,8 @@
8664 { "imaps", U_IMAPS },
8665 { "pop", U_POP },
8666 { "pops", U_POPS },
8667+ { "nntp", U_NNTP },
8668+ { "nntps", U_NNTPS },
8669 { "mailto", U_MAILTO },
8670 { NULL, U_UNKNOWN}
8671 };
8672diff -uNr mutt-1.4.orig/url.h mutt-1.4/url.h
8673--- mutt-1.4.orig/url.h Tue Sep 4 11:30:04 2001
8674+++ mutt-1.4/url.h Sun Nov 3 21:57:20 2002
8675@@ -8,6 +8,8 @@
8676 U_POPS,
8677 U_IMAP,
8678 U_IMAPS,
8679+ U_NNTP,
8680+ U_NNTPS,
8681 U_MAILTO,
8682 U_UNKNOWN
8683 }
This page took 1.306268 seconds and 4 git commands to generate.