From 82e13245db666826b6b9679d3c516cb9a1292f16 Mon Sep 17 00:00:00 2001 From: Jakub Bogusz Date: Sun, 3 Jun 2007 13:56:47 +0000 Subject: [PATCH] - outdated Changed files: mutt-cd.edit_threads.patch -> 1.2 mutt-devl.narrow_tree.patch -> 1.2 mutt-kill_warnings.patch -> 1.2 mutt-nntp.patch -> 1.5 --- mutt-cd.edit_threads.patch | 417 -- mutt-devl.narrow_tree.patch | 107 - mutt-kill_warnings.patch | 199 - mutt-nntp.patch | 8680 ----------------------------------- 4 files changed, 9403 deletions(-) delete mode 100644 mutt-cd.edit_threads.patch delete mode 100644 mutt-devl.narrow_tree.patch delete mode 100644 mutt-kill_warnings.patch delete mode 100644 mutt-nntp.patch diff --git a/mutt-cd.edit_threads.patch b/mutt-cd.edit_threads.patch deleted file mode 100644 index 5cc130a..0000000 --- a/mutt-cd.edit_threads.patch +++ /dev/null @@ -1,417 +0,0 @@ -diff -pruN2 mutt-1.3.27.orig/thread.c mutt-1.3.27/thread.c ---- mutt-1.3.27.orig/thread.c Wed Jan 16 21:43:59 2002 -+++ mutt-1.3.27/thread.c Wed Jan 23 22:26:56 2002 -@@ -1285,2 +1285,78 @@ HASH *mutt_make_subj_hash (CONTEXT *ctx) - return hash; - } -+ -+static void clean_references (THREAD *brk, THREAD *cur) -+{ -+ THREAD *p; -+ LIST *ref = NULL; -+ int done = 0; -+ -+ for (; cur; cur = cur->next, done = 0) -+ { -+ /* parse subthread recursively */ -+ clean_references (brk, cur->child); -+ -+ if (!cur->message) -+ break; /* skip pseudo-message */ -+ -+ /* Looking for the first bad reference according to the new threading. -+ * Optimal since Mutt stores the references in reverse order, and the -+ * first loop should match immediatly for mails respecting RFC2822. */ -+ for (p = brk; !done && p; p = p->parent) -+ for (ref = cur->message->env->references; p->message && ref; ref = ref->next) -+ if (!mutt_strcasecmp (ref->data, p->message->env->message_id)) -+ { -+ done = 1; -+ break; -+ } -+ -+ if (done) -+ { -+ /* clearing the References: header from obsolete Message-Id(s) */ -+ mutt_free_list (&ref->next); -+ -+ cur->message->refs_changed = cur->message->changed = 1; -+ } -+ } -+} -+ -+void mutt_break_thread (HEADER *hdr) -+{ -+ mutt_free_list (&hdr->env->in_reply_to); -+ mutt_free_list (&hdr->env->references); -+ hdr->irt_changed = hdr->refs_changed = hdr->changed = 1; -+ -+ clean_references (hdr->thread, hdr->thread->child); -+} -+ -+static int link_threads (HEADER *parent, HEADER *child, CONTEXT *ctx) -+{ -+ if (child == parent) -+ return 0; -+ -+ mutt_break_thread (child); -+ -+ child->env->in_reply_to = mutt_new_list (); -+ child->env->in_reply_to->data = safe_strdup (parent->env->message_id); -+ -+ mutt_set_flag (ctx, child, M_TAG, 0); -+ -+ child->irt_changed = child->changed = 1; -+ return 1; -+} -+ -+int mutt_link_threads (HEADER *cur, HEADER *last, CONTEXT *ctx) -+{ -+ int i, changed = 0; -+ -+ if (!last) -+ { -+ for (i = 0; i < ctx->vcount; i++) -+ if (ctx->hdrs[Context->v2r[i]]->tagged) -+ changed |= link_threads (cur, ctx->hdrs[Context->v2r[i]], ctx); -+ } -+ else -+ changed = link_threads (cur, last, ctx); -+ -+ return changed; -+} -diff -pruN2 mutt-1.3.27.orig/OPS mutt-1.3.27/OPS ---- mutt-1.3.27.orig/OPS Tue Sep 11 12:50:50 2001 -+++ mutt-1.3.27/OPS Wed Jan 23 22:26:56 2002 -@@ -95,4 +95,5 @@ OP_LIST_REPLY "reply to specified mailin - OP_MACRO "execute a macro" - OP_MAIL "compose a new mail message" -+OP_MAIN_BREAK_THREAD "break the thread in two" - OP_MAIN_CHANGE_FOLDER "open a different folder" - OP_MAIN_CHANGE_FOLDER_READONLY "open a different folder in read only mode" -@@ -104,4 +105,5 @@ OP_MAIN_FIRST_MESSAGE "move to the first - OP_MAIN_LAST_MESSAGE "move to the last message" - OP_MAIN_LIMIT "show only messages matching a pattern" -+OP_MAIN_LINK_THREADS "link tagged message to the current one" - OP_MAIN_NEXT_NEW "jump to the next new message" - OP_MAIN_NEXT_SUBTHREAD "jump to the next subthread" -diff -pruN2 mutt-1.3.27.orig/copy.c mutt-1.3.27/copy.c ---- mutt-1.3.27.orig/copy.c Mon Dec 3 11:17:57 2001 -+++ mutt-1.3.27/copy.c Wed Jan 23 22:26:56 2002 -@@ -92,4 +92,10 @@ mutt_copy_hdr (FILE *in, FILE *out, long - ascii_strncasecmp ("Lines:", buf, 6) == 0)) - continue; -+ if ((flags & CH_UPDATE_REFS) && -+ ascii_strncasecmp ("References:", buf, 11) == 0) -+ continue; -+ if ((flags & CH_UPDATE_IRT) && -+ ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0) -+ continue; - ignore = 0; - } -@@ -168,4 +174,10 @@ mutt_copy_hdr (FILE *in, FILE *out, long - ascii_strncasecmp ("mime-version:", buf, 13) == 0)) - continue; -+ if ((flags & CH_UPDATE_REFS) && -+ ascii_strncasecmp ("References:", buf, 11) == 0) -+ continue; -+ if ((flags & CH_UPDATE_IRT) && -+ ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0) -+ continue; - - /* Find x -- the array entry where this header is to be saved */ -@@ -277,4 +289,6 @@ mutt_copy_hdr (FILE *in, FILE *out, long - CH_XMIT ignore Lines: and Content-Length: - CH_WEED do header weeding -+ CH_UPDATE_IRT update the In-Reply-To: header -+ CH_UPDATE_REFS update the References: header - - prefix -@@ -286,4 +300,7 @@ mutt_copy_header (FILE *in, HEADER *h, F - { - char buffer[SHORT_STRING]; -+ -+ flags |= (h->irt_changed ? CH_UPDATE_IRT : 0) -+ | (h->refs_changed ? CH_UPDATE_REFS : 0); - - if (mutt_copy_hdr (in, out, h->offset, h->content->offset, flags, prefix) == -1) -@@ -310,4 +327,47 @@ mutt_copy_header (FILE *in, HEADER *h, F - if ((flags & CH_NOSTATUS) == 0) - { -+ if (h->irt_changed && h->env->in_reply_to) -+ { -+ LIST *listp = h->env->in_reply_to; -+ -+ if (fputs ("In-Reply-To: ", out) == EOF) -+ return (-1); -+ -+ for (; listp; listp = listp->next) -+ if ((fputs (listp->data, out) == EOF) || (fputc (' ', out) == EOF)) -+ return (-1); -+ -+ if (fputc ('\n', out) == EOF) -+ return (-1); -+ } -+ -+ if (h->refs_changed && h->env->references) -+ { -+ LIST *listp = h->env->references, *refs = NULL, *t; -+ -+ if (fputs ("References: ", out) == EOF) -+ return (-1); -+ -+ /* Mutt stores references in reverse order, thus we create -+ * a reordered refs list that we can put in the headers */ -+ for (; listp; listp = listp->next, refs = t) -+ { -+ t = (LIST *)safe_malloc (sizeof (LIST)); -+ t->data = listp->data; -+ t->next = refs; -+ } -+ -+ for (; refs; refs = refs->next) -+ if ((fputs (refs->data, out) == EOF) || (fputc (' ', out) == EOF)) -+ return (-1); -+ -+ /* clearing refs from memory */ -+ for (t = refs; refs; refs = t->next, t = refs) -+ safe_free ((void **)&refs); -+ -+ if (fputc ('\n', out) == EOF) -+ return (-1); -+ } -+ - if (h->old || h->read) - { -diff -pruN2 mutt-1.3.27.orig/curs_main.c mutt-1.3.27/curs_main.c ---- mutt-1.3.27.orig/curs_main.c Wed Jan 16 21:43:58 2002 -+++ mutt-1.3.27/curs_main.c Wed Jan 23 22:26:56 2002 -@@ -878,4 +878,9 @@ int mutt_index_menu (void) - { - mutt_set_flag (Context, CURHDR, M_TAG, !CURHDR->tagged); -+ -+ Context->last_tag = CURHDR->tagged ? CURHDR : -+ ((Context->last_tag == CURHDR && !CURHDR->tagged) -+ ? NULL : Context->last_tag); -+ - menu->redraw = REDRAW_STATUS; - if (option (OPTRESOLVE) && menu->current < Context->vcount - 1) -@@ -1098,4 +1103,83 @@ int mutt_index_menu (void) - done = 1; - } -+ break; -+ -+ case OP_MAIN_BREAK_THREAD: -+ -+ CHECK_MSGCOUNT; -+ CHECK_VISIBLE; -+ CHECK_READONLY; -+ -+ if ((Sort & SORT_MASK) != SORT_THREADS) -+ { -+ mutt_error _("Threading is not enabled."); -+ break; -+ } -+ if (Context->magic != M_MBOX && Context->magic != M_MMDF) -+ { -+ mutt_error _("break-thread: only for mbox and mmdf mailbox formats"); -+ break; -+ } -+ -+ { -+ HEADER *oldcur = CURHDR; -+ -+ mutt_break_thread (CURHDR); -+ mutt_sort_headers (Context, 1); -+ menu->current = oldcur->virtual; -+ } -+ -+ Context->changed = 1; -+ mutt_message _("Thread broken"); -+ -+ if (menu->menu == MENU_PAGER) -+ { -+ op = OP_DISPLAY_MESSAGE; -+ continue; -+ } -+ else -+ menu->redraw |= REDRAW_INDEX; -+ -+ break; -+ -+ case OP_MAIN_LINK_THREADS: -+ -+ CHECK_MSGCOUNT; -+ CHECK_VISIBLE; -+ CHECK_READONLY; -+ -+ if ((Sort & SORT_MASK) != SORT_THREADS) -+ mutt_error _("Threading is not enabled."); -+ else if (Context->magic != M_MBOX && Context->magic != M_MMDF) -+ mutt_error _("link-threads: only for mbox and mmdf mailbox formats"); -+ else if (!CURHDR->env->message_id) -+ mutt_error _("No Message-ID: header available to link thread"); -+ else if (!tag && (!Context->last_tag || !Context->last_tag->tagged)) -+ mutt_error _("First, please tag a message to be linked here"); -+ else -+ { -+ HEADER *oldcur = CURHDR; -+ -+ if (mutt_link_threads (CURHDR, tag ? NULL : Context->last_tag, -+ Context)) -+ { -+ mutt_sort_headers (Context, 1); -+ menu->current = oldcur->virtual; -+ -+ Context->changed = 1; -+ mutt_message _("Threads linked"); -+ } -+ else -+ mutt_error _("No thread linked"); -+ } -+ -+ if (menu->menu == MENU_PAGER) -+ { -+ op = OP_DISPLAY_MESSAGE; -+ continue; -+ } -+ else -+ menu->redraw |= REDRAW_STATUS | REDRAW_INDEX; -+ - break; - -diff -pruN2 mutt-1.3.27.orig/doc/manual.sgml.head mutt-1.3.27/doc/manual.sgml.head ---- mutt-1.3.27.orig/doc/manual.sgml.head Sat Jan 12 12:35:43 2002 -+++ mutt-1.3.27/doc/manual.sgml.head Wed Jan 23 22:26:56 2002 -@@ -2116,6 +2116,38 @@ with large volume mailing lists easier b - uninteresting threads and quickly find topics of value. - -+Editing threads -+

-+Mutt has the ability to dynamically restructure threads that are broken -+either by misconfigured software or bad behaviour from some -+correspondents. This allows to clean your mailboxes (Linking threads -+

-+ -+Some mailers tend to "forget" to correctly set the "In-Reply-To:" and -+"References:" headers when replying to a message. This results in broken -+discussions because Mutt has not enough information to guess the correct -+threading. -+You can fix this by tagging the reply to a mail, then go onto this mail -+and use the ``link-threads'' function (bound to & by default). The -+reply will then be connected to its "parent" message. -+ -+You can also connect multiple childs at once, tagging them and using the -+tag-prefix command (';') or the auto_tag option. -+ -+Breaking threads -+

-+ -+On mailing lists, some people are in the bad habit of starting a new -+discussion by hitting "reply" to any message from the list and changing -+the subject to a totally unrelated one. -+You can fix such threads by using the ``break-thread'' function (bound -+by default to #), which will turn the subthread starting from the -+current message into a whole different thread. -+ - Delivery Status Notification (DSN) Support -

-+ - RFC1894 defines a set of MIME content types for relaying information - about the status of electronic mail messages. These can be thought of as -diff -pruN2 mutt-1.3.27.orig/functions.h mutt-1.3.27/functions.h ---- mutt-1.3.27.orig/functions.h Tue Sep 11 12:51:39 2001 -+++ mutt-1.3.27/functions.h Wed Jan 23 22:26:56 2002 -@@ -67,4 +67,5 @@ struct binding_t OpMain[] = { - { "create-alias", OP_CREATE_ALIAS, "a" }, - { "bounce-message", OP_BOUNCE_MESSAGE, "b" }, -+ { "break-thread", OP_MAIN_BREAK_THREAD, "#" }, - { "change-folder", OP_MAIN_CHANGE_FOLDER, "c" }, - { "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" }, -@@ -93,4 +94,5 @@ struct binding_t OpMain[] = { - { "previous-undeleted", OP_MAIN_PREV_UNDELETED, "k" }, - { "limit", OP_MAIN_LIMIT, "l" }, -+ { "link-threads", OP_MAIN_LINK_THREADS, "&" }, - { "list-reply", OP_LIST_REPLY, "L" }, - { "mail", OP_MAIL, "m" }, -@@ -151,4 +153,5 @@ struct binding_t OpMain[] = { - - struct binding_t OpPager[] = { -+ { "break-thread", OP_MAIN_BREAK_THREAD, "#" }, - { "create-alias", OP_CREATE_ALIAS, "a" }, - { "bounce-message", OP_BOUNCE_MESSAGE, "b" }, -@@ -173,4 +176,5 @@ struct binding_t OpPager[] = { - { "previous-undeleted",OP_MAIN_PREV_UNDELETED, "k" }, - { "previous-entry", OP_PREV_ENTRY, "K" }, -+ { "link-threads", OP_MAIN_LINK_THREADS, "&" }, - { "list-reply", OP_LIST_REPLY, "L" }, - { "redraw-screen", OP_REDRAW, "\014" }, -diff -pruN2 mutt-1.3.27.orig/mutt.h mutt-1.3.27/mutt.h ---- mutt-1.3.27.orig/mutt.h Tue Jan 15 22:00:32 2002 -+++ mutt-1.3.27/mutt.h Wed Jan 23 22:26:56 2002 -@@ -82,4 +82,6 @@ - #define CH_WEED_DELIVERED (1<<13) /* weed eventual Delivered-To headers */ - #define CH_FORCE_FROM (1<<14) /* give CH_FROM precedence over CH_WEED? */ -+#define CH_UPDATE_IRT (1<<15) /* update In-Reply-To: */ -+#define CH_UPDATE_REFS (1<<16) /* update References: */ - - /* flags for mutt_enter_string() */ -@@ -629,4 +631,6 @@ typedef struct header - unsigned int threaded : 1; /* used for threading */ - unsigned int display_subject : 1; /* used for threading */ -+ unsigned int irt_changed : 1; /* In-Reply-To changed to link/break threads */ -+ unsigned int refs_changed : 1; /* References changed to break thread */ - unsigned int recip_valid : 1; /* is_recipient is valid */ - unsigned int active : 1; /* message is not to be removed */ -@@ -728,4 +732,5 @@ typedef struct - pattern_t *limit_pattern; /* compiled limit pattern */ - HEADER **hdrs; -+ HEADER *last_tag; /* last tagged msg. used to link threads */ - THREAD *tree; /* top of thread tree */ - HASH *id_hash; /* hash table by msg id */ -diff -pruN2 mutt-1.3.27.orig/mx.c mutt-1.3.27/mx.c ---- mutt-1.3.27.orig/mx.c Tue Jan 15 22:09:53 2002 -+++ mutt-1.3.27/mx.c Wed Jan 23 22:26:56 2002 -@@ -1163,4 +1163,6 @@ int mx_sync_mailbox (CONTEXT *ctx, int * - } - } -+ else if (ctx->last_tag && ctx->last_tag->deleted) -+ ctx->last_tag = NULL; /* reset last tagged msg now useless */ - } - -diff -pruN2 mutt-1.3.27.orig/pager.c mutt-1.3.27/pager.c ---- mutt-1.3.27.orig/pager.c Sun Jan 13 09:49:39 2002 -+++ mutt-1.3.27/pager.c Wed Jan 23 22:26:56 2002 -@@ -2436,4 +2436,9 @@ mutt_pager (const char *banner, const ch - CHECK_MODE(IsHeader (extra)); - mutt_set_flag (Context, extra->hdr, M_TAG, !extra->hdr->tagged); -+ -+ Context->last_tag = extra->hdr->tagged ? extra->hdr : -+ ((Context->last_tag == extra->hdr && !extra->hdr->tagged) -+ ? NULL : Context->last_tag); -+ - redraw = REDRAW_STATUS | REDRAW_INDEX; - if (option (OPTRESOLVE)) -diff -pruN2 mutt-1.3.27.orig/protos.h mutt-1.3.27/protos.h ---- mutt-1.3.27.orig/protos.h Wed Jan 16 21:43:58 2002 -+++ mutt-1.3.27/protos.h Wed Jan 23 22:26:56 2002 -@@ -154,4 +154,5 @@ void mutt_block_signals_system (void); - void mutt_body_handler (BODY *, STATE *); - void mutt_bounce_message (FILE *fp, HEADER *, ADDRESS *); -+void mutt_break_thread (HEADER *); - void mutt_buffy (char *, size_t); - void mutt_canonical_charset (char *, size_t, const char *); -@@ -289,4 +290,5 @@ int mutt_is_subscribed_list (ADDRESS *); - int mutt_is_text_type (int, char *); - int mutt_is_valid_mailbox (const char *); -+int mutt_link_threads (HEADER *, HEADER *, CONTEXT *); - int mutt_messages_in_thread (CONTEXT *, HEADER *, int); - int mutt_multi_choice (char *prompt, char *letters); -diff -pruN mutt-1.3.27.orig/PATCHES mutt-1.3.27/PATCHES ---- mutt-1.3.27.orig/PATCHES Mon Nov 26 20:16:52 2001 -+++ mutt-1.3.27/PATCHES Thu Dec 6 16:27:55 2001 -@@ -1,0 +1 @@ -+patch-1.3.27.cd.edit_threads.9.1 diff --git a/mutt-devl.narrow_tree.patch b/mutt-devl.narrow_tree.patch deleted file mode 100644 index bf9af85..0000000 --- a/mutt-devl.narrow_tree.patch +++ /dev/null @@ -1,107 +0,0 @@ -diff -u mutt-1.3.26.old/PATCHES mutt-1.3.26/PATCHES ---- mutt-1.3.26.old/PATCHES Tue Jan 15 10:03:20 2002 -+++ mutt-1.3.26/PATCHES Fri Jan 18 15:54:52 2002 -@@ -0,0 +1 @@ -+patch-1.3.26.devl.narrow_tree.1 -diff -u mutt-1.3.26.old/hdrline.c mutt-1.3.26/hdrline.c ---- mutt-1.3.26.old/hdrline.c Mon Dec 17 11:04:48 2001 -+++ mutt-1.3.26/hdrline.c Fri Jan 18 15:54:28 2002 -@@ -200,6 +200,50 @@ - return h->recipient; - } - -+/* do_subject returns the pointer it is given for tree or subject if -+ * the respective one of them is all the subject that needs to be -+ * printed. otherwise, it copies the appropriate string into buf -+ * and returns that. -+ */ -+char *do_subject (char *dest, size_t destlen, char *subject, char *tree, int flags, char *buf, size_t bufsize) -+{ -+ char *dst; -+ -+ if (option (OPTNARROWTREE)) -+ { -+ dst = buf; -+ -+ while (bufsize > 1) -+ { -+ *dst = *tree; -+ bufsize--; -+ dst++; -+ if (!(*(tree + 1))) -+ break; -+ tree += 2; -+ } -+ if (*(tree - 1) == '\010') -+ *(dst - 2) = '\010'; -+ -+ if (flags & M_FORMAT_FORCESUBJ) -+ { -+ mutt_format_s (dest, destlen, "", NONULL (subject)); -+ snprintf (dst, bufsize, "%s", dest); -+ } -+ else -+ *dst = 0; -+ return (buf); -+ } -+ else if (flags & M_FORMAT_FORCESUBJ) -+ { -+ mutt_format_s (dest, destlen, "", NONULL (subject)); -+ snprintf (buf, bufsize, "%s%s", tree, dest); -+ return (buf); -+ } -+ else -+ return (tree); -+} -+ - /* %a = address of author - * %b = filename of the originating folder - * %B = the list to which the letter was sent -@@ -528,16 +572,8 @@ - case 's': - - if (flags & M_FORMAT_TREE && !hdr->collapsed) -- { -- if (flags & M_FORMAT_FORCESUBJ) -- { -- mutt_format_s (dest, destlen, "", NONULL (hdr->env->subject)); -- snprintf (buf2, sizeof (buf2), "%s%s", hdr->tree, dest); -- mutt_format_s_tree (dest, destlen, prefix, buf2); -- } -- else -- mutt_format_s_tree (dest, destlen, prefix, hdr->tree); -- } -+ mutt_format_s_tree (dest, destlen, prefix, -+ do_subject (dest, destlen, hdr->env->subject, hdr->tree, flags, buf2, sizeof (buf2))); - else - mutt_format_s (dest, destlen, prefix, NONULL (hdr->env->subject)); - break; -diff -u mutt-1.3.26.old/init.h mutt-1.3.26/init.h ---- mutt-1.3.26.old/init.h Mon Dec 10 11:09:03 2001 -+++ mutt-1.3.26/init.h Fri Jan 18 15:54:28 2002 -@@ -1093,6 +1093,14 @@ - { "msg_format", DT_SYN, R_NONE, UL "message_format", 0 }, - /* - */ -+ { "narrow_tree", DT_BOOL, R_BOTH, OPTNARROWTREE, 0 }, -+ /* -+ ** .pp -+ ** This variable controls the width of the thread tree when sorting by -+ ** threads. When set, it makes the tree approximately twice as narrow, -+ ** to allow more room the tree and message subjects. This is useful on -+ ** narrow screens. -+ */ - { "pager", DT_PATH, R_NONE, UL &Pager, UL "builtin" }, - /* - ** .pp -diff -u mutt-1.3.26.old/mutt.h mutt-1.3.26/mutt.h ---- mutt-1.3.26.old/mutt.h Tue Jan 15 22:00:32 2002 -+++ mutt-1.3.26/mutt.h Fri Jan 18 15:54:28 2002 -@@ -364,6 +364,7 @@ - OPTMETOO, - OPTMHPURGE, - OPTMIMEFORWDECODE, -+ OPTNARROWTREE, - OPTPAGERSTOP, - OPTPIPEDECODE, - OPTPIPESPLIT, diff --git a/mutt-kill_warnings.patch b/mutt-kill_warnings.patch deleted file mode 100644 index b12edad..0000000 --- a/mutt-kill_warnings.patch +++ /dev/null @@ -1,199 +0,0 @@ -diff -dur mutt-1.4.1.orig/curs_lib.c mutt-1.4.1/curs_lib.c ---- mutt-1.4.1.orig/curs_lib.c 2001-10-10 14:49:37.000000000 +0200 -+++ mutt-1.4.1/curs_lib.c 2004-02-05 08:53:53.097928184 +0100 -@@ -16,6 +16,8 @@ - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ - -+#define _GNU_SOURCE 1 -+ - #include "mutt.h" - #include "mutt_menu.h" - #include "mutt_curses.h" -@@ -30,6 +32,7 @@ - #include - #include - #include -+#include - - #ifdef HAVE_LANGINFO_YESEXPR - #include -diff -dur mutt-1.4.1.orig/enter.c mutt-1.4.1/enter.c ---- mutt-1.4.1.orig/enter.c 2001-10-03 00:20:03.000000000 +0200 -+++ mutt-1.4.1/enter.c 2004-02-05 08:54:06.695860984 +0100 -@@ -17,6 +17,8 @@ - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ - -+#define _GNU_SOURCE 1 -+ - #include "mutt.h" - #include "mutt_menu.h" - #include "mutt_curses.h" -@@ -24,6 +26,7 @@ - #include "history.h" - - #include -+#include - - /* redraw flags for mutt_enter_string() */ - enum -diff -dur mutt-1.4.1.orig/extlib.c mutt-1.4.1/extlib.c ---- mutt-1.4.1.orig/extlib.c 2000-04-22 10:47:31.000000000 +0200 -+++ mutt-1.4.1/extlib.c 2004-02-05 08:53:31.728176880 +0100 -@@ -28,6 +28,7 @@ - #define _EXTLIB_C - - #include "lib.h" -+#include - - void (*mutt_error) (const char *, ...) = mutt_nocurses_error; - -diff -dur mutt-1.4.1.orig/help.c mutt-1.4.1/help.c ---- mutt-1.4.1.orig/help.c 2000-10-07 20:06:24.000000000 +0200 -+++ mutt-1.4.1/help.c 2004-02-05 08:54:24.125211320 +0100 -@@ -16,6 +16,7 @@ - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ - -+#define _GNU_SOURCE 1 - #define HELP_C - - #include "mutt.h" -@@ -26,6 +27,7 @@ - - #include - #include -+#include - - static struct binding_t *help_lookupFunction (int op, int menu) - { -diff -dur mutt-1.4.1.orig/imap/message.c mutt-1.4.1/imap/message.c ---- mutt-1.4.1.orig/imap/message.c 2002-04-07 23:19:57.000000000 +0200 -+++ mutt-1.4.1/imap/message.c 2004-02-05 08:53:31.729176728 +0100 -@@ -435,7 +435,7 @@ - rewind (fp); - - imap_munge_mbox_name (mbox, sizeof (mbox), mailbox); -- snprintf (buf, sizeof (buf), "APPEND %s (\\Seen) {%d}", mbox, len); -+ snprintf (buf, sizeof (buf), "APPEND %s (\\Seen) {%ld}", mbox, (long)len); - - imap_cmd_start (idata, buf); - -diff -dur mutt-1.4.1.orig/init.c mutt-1.4.1/init.c ---- mutt-1.4.1.orig/init.c 2004-02-05 08:38:03.000000000 +0100 -+++ mutt-1.4.1/init.c 2004-02-05 08:53:31.730176576 +0100 -@@ -16,6 +16,8 @@ - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ - -+#define _GNU_SOURCE 1 -+ - #include "mutt.h" - #include "mapping.h" - #include "mutt_curses.h" -diff -dur mutt-1.4.1.orig/main.c mutt-1.4.1/main.c ---- mutt-1.4.1.orig/main.c 2004-02-05 08:38:03.000000000 +0100 -+++ mutt-1.4.1/main.c 2004-02-05 08:53:31.731176424 +0100 -@@ -74,6 +74,9 @@ - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\n\ - "); - -+void mutt_start_slrnface(void); -+void mutt_stop_slrnface(void); -+ - void mutt_exit (int code) - { - mutt_endwin (NULL); -diff -dur mutt-1.4.1.orig/mutt_sasl.c mutt-1.4.1/mutt_sasl.c ---- mutt-1.4.1.orig/mutt_sasl.c 2004-02-05 08:38:03.000000000 +0100 -+++ mutt-1.4.1/mutt_sasl.c 2004-02-05 09:01:49.346527392 +0100 -@@ -26,6 +26,9 @@ - #include - #include - #include -+#include -+#include -+#include - - /* arbitrary. SASL will probably use a smaller buffer anyway. OTOH it's - * been a while since I've had access to an SASL server which negotiated -@@ -212,6 +215,7 @@ - { - char prompt[SHORT_STRING]; - char resp[SHORT_STRING]; -+ char * result; - - while (interaction->id != SASL_CB_LIST_END) - { -@@ -223,8 +227,9 @@ - return SASL_FAIL; - - interaction->len = mutt_strlen (resp)+1; -- interaction->result = safe_malloc (interaction->len); -- memcpy (interaction->result, resp, interaction->len); -+ result = safe_malloc (interaction->len); -+ memcpy (result, resp, interaction->len); -+ interaction->result=result; - - interaction++; - } -@@ -258,7 +263,7 @@ - dprint (3, (debugfile, "SASL protection strength: %u\n", *sasldata->ssf)); - /* Add SASL SSF to transport SSF */ - conn->ssf += *sasldata->ssf; -- sasl_getprop (saslconn, SASL_MAXOUTBUF, (void**) &sasldata->pbufsize); -+ sasl_getprop (saslconn, SASL_MAXOUTBUF, (const void**) &sasldata->pbufsize); - dprint (3, (debugfile, "SASL protection buffer size: %u\n", *sasldata->pbufsize)); - - /* clear input buffer */ -@@ -424,7 +429,7 @@ - if (rc <= 0) - goto out; - -- rc = sasl_decode (sasldata->saslconn, buf, rc, &sasldata->buf, -+ rc = sasl_decode (sasldata->saslconn, buf, rc, (const char **)&sasldata->buf, - &sasldata->blen); - if (rc != SASL_OK) - { -@@ -472,7 +477,7 @@ - { - olen = (len > *sasldata->pbufsize) ? *sasldata->pbufsize : len; - -- rc = sasl_encode (sasldata->saslconn, buf, olen, &pbuf, &plen); -+ rc = sasl_encode (sasldata->saslconn, buf, olen, (const char **)&pbuf, &plen); - if (rc != SASL_OK) - { - dprint (1, (debugfile, "SASL encoding failed: %s\n", -diff -dur mutt-1.4.1.orig/pager.c mutt-1.4.1/pager.c ---- mutt-1.4.1.orig/pager.c 2004-02-05 08:38:03.000000000 +0100 -+++ mutt-1.4.1/pager.c 2004-02-05 08:54:45.326988160 +0100 -@@ -16,6 +16,8 @@ - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ - -+#define _GNU_SOURCE 1 -+ - #include "mutt.h" - #include "mutt_curses.h" - #include "mutt_regex.h" -@@ -52,6 +54,7 @@ - #include - #include - #include -+#include - - #define ISHEADER(x) ((x) == MT_COLOR_HEADER || (x) == MT_COLOR_HDEFAULT) - -diff -dur mutt-1.4.1.orig/regex.c mutt-1.4.1/regex.c ---- mutt-1.4.1.orig/regex.c 2001-01-09 00:09:30.000000000 +0100 -+++ mutt-1.4.1/regex.c 2004-02-05 08:55:22.777294848 +0100 -@@ -3113,8 +3113,6 @@ - #ifndef REGEX_MALLOC - char *destination; - #endif -- /* We don't push any register information onto the failure stack. */ -- unsigned num_regs = 0; - - register char *fastmap = bufp->fastmap; - unsigned char *pattern = bufp->buffer; diff --git a/mutt-nntp.patch b/mutt-nntp.patch deleted file mode 100644 index 137efb6..0000000 --- a/mutt-nntp.patch +++ /dev/null @@ -1,8680 +0,0 @@ -diff -uNr mutt-1.4.orig/ChangeLog.nntp mutt-1.4/ChangeLog.nntp ---- mutt-1.4.orig/ChangeLog.nntp Thu Jan 1 01:00:00 1970 -+++ mutt-1.4/ChangeLog.nntp Sun Nov 3 21:57:20 2002 -@@ -0,0 +1,422 @@ -+* Wed May 29 2002 Vsevolod Volkov -+- update to 1.4 -+ -+* Thu May 2 2002 Vsevolod Volkov -+- update to 1.3.99 -+ -+* Wed Mar 13 2002 Vsevolod Volkov -+- update to 1.3.28 -+- fixed SIGSEGV in , , , -+ functions -+- fixed message about nntp reconnect -+- fixed function using browser -+- added support of Followup-To: poster -+- added %n (new articles) in group_index_format -+- posting articles without inews by default -+ -+* Wed Jan 23 2002 Vsevolod Volkov -+- update to 1.3.27 -+ -+* Fri Jan 18 2002 Vsevolod Volkov -+- update to 1.3.26 -+ -+* Thu Jan 3 2002 Vsevolod Volkov -+- update to 1.3.25 -+- accelerated speed of access to news->newsgroups hash (by ) -+- added default content disposition -+ -+* Mon Dec 3 2001 Vsevolod Volkov -+- update to 1.3.24 -+ -+* Fri Nov 9 2001 Vsevolod Volkov -+- update to 1.3.23.2 -+- fixed segfault if mutt_conn_find() returns null -+ -+* Wed Oct 31 2001 Vsevolod Volkov -+- update to 1.3.23.1 -+- added support of LISTGROUP command -+- added support for servers with broken overview -+- disabled function on news server -+- fixed error storing bad authentication information -+ -+* Wed Oct 10 2001 Vsevolod Volkov -+- update to 1.3.23 -+- fixed typo in buffy.c -+- added substitution of %s parameter in $inews variable -+ -+* Fri Aug 31 2001 Vsevolod Volkov -+- update to 1.3.22.1 -+- update to 1.3.22 -+ -+* Thu Aug 23 2001 Vsevolod Volkov -+- update to 1.3.21 -+ -+* Wed Jul 25 2001 Vsevolod Volkov -+- update to 1.3.20 -+- removed 'server-hook', use 'account-hook' instead -+- fixed error opening NNTP server without newsgroup using -f option -+ -+* Fri Jun 8 2001 Vsevolod Volkov -+- update to 1.3.19 -+ -+* Sat May 5 2001 Vsevolod Volkov -+- update to 1.3.18 -+- fixed typo in nntp_attempt_features() -+- changed algorithm of XGTITLE command testing -+- disabled writing of NNTP password in debug file -+- fixed reading and writing of long newsrc lines -+- changed checking of last line while reading lines from server -+- fixed possible buffer overrun in nntp_parse_newsrc_line() -+- removed checking of XHDR command -+- compare NNTP return codes without trailing space -+ -+* Thu Mar 29 2001 Vsevolod Volkov -+- update to 1.3.17 -+- support for 'LIST NEWSGROUPS' command to read descriptions -+ -+* Fri Mar 2 2001 Vsevolod Volkov -+- update to 1.3.16 -+ -+* Wed Feb 14 2001 Vsevolod Volkov -+- update to 1.3.15 -+ -+* Sun Jan 28 2001 Vsevolod Volkov -+- update to 1.3.14 -+- show number of tagged messages patch from Felix von Leitner -+ -+* Sun Dec 31 2000 Vsevolod Volkov -+- update to 1.3.13 -+ -+* Sat Dec 30 2000 Vsevolod Volkov -+- Fixed problem if last article in group is deleted -+ -+* Fri Dec 22 2000 Vsevolod Volkov -+- Fixed checking of XGTITLE command on some servers -+ -+* Mon Dec 18 2000 Vsevolod Volkov -+- Added \r in AUTHINFO commands -+ -+* Mon Nov 27 2000 Vsevolod Volkov -+- update to 1.3.12 -+ -+* Wed Nov 1 2000 Vsevolod Volkov -+- update to 1.3.11 -+- fixed error opening newsgroup from mutt started with -g or -G -+ -+* Thu Oct 12 2000 Vsevolod Volkov -+- update to 1.3.10 -+- hotkey 'G' (get-message) replaced with '^G' -+ -+* Thu Sep 21 2000 Vsevolod Volkov -+- update to 1.3.9 -+- changed delay displaying error messages from 1 to 2 seconds -+- fixed error compiling with nntp and without imap -+ -+* Wed Sep 6 2000 Vsevolod Volkov -+- fixed catchup in index -+- fixed nntp_open_mailbox() -+ -+* Sat Sep 2 2000 Vsevolod Volkov -+- functions and disabled -+- format of news mailbox names changed to url form -+- option nntp_attempts removed -+- option reconnect_news renamed to nntp_reconnect -+- default value of nntp_poll changed from 30 to 60 -+- error handling improved -+ -+* Wed Aug 30 2000 Vsevolod Volkov -+- update to 1.3.8 -+- new option show_only_unread -+- add newsgroup completion -+ -+* Fri Aug 4 2000 Vsevolod Volkov -+- update to 1.3.7 -+ -+* Sat Jul 29 2000 Vsevolod Volkov -+- update to 1.3.6 -+ -+* Sun Jul 9 2000 Vsevolod Volkov -+- update to 1.3.5 -+- authentication code update -+- fix for changing to newsgroup from mailbox with read messages -+- socket code optimization -+ -+* Wed Jun 21 2000 Vsevolod Volkov -+- update to 1.3.4 -+ -+* Wed Jun 14 2000 Vsevolod Volkov -+- don't substitute current newsgroup with deleted new messages -+ -+* Mon Jun 12 2000 Vsevolod Volkov -+- update to 1.3.3 -+- fix for substitution of newsgroup after reconnection -+- fix for loading newsgroups with very long names -+- fix for loading more than 32768 newsgroups -+ -+* Wed May 24 2000 Vsevolod Volkov -+- update to 1.3.2 -+ -+* Sat May 20 2000 Vsevolod Volkov -+- update to 1.3.1 -+ -+* Fri May 12 2000 Vsevolod Volkov -+- update to 1.3 -+ -+* Thu May 11 2000 Vsevolod Volkov -+- update to 1.2 -+ -+* Thu May 4 2000 Vsevolod Volkov -+- update to 1.1.14 -+ -+* Sun Apr 23 2000 Vsevolod Volkov -+- update to 1.1.12 -+ -+* Fri Apr 7 2000 Vsevolod Volkov -+- add substitution of newsgroup with new messages by default -+ -+* Wed Apr 5 2000 Vsevolod Volkov -+- add attach message from newsgroup -+- add one-line help in newsreader mode -+- disable 'change-dir' command in newsgroups browser -+- add -G option -+ -+* Tue Apr 4 2000 Vsevolod Volkov -+- get default newsserver name from file /etc/nntpserver -+- use case insensitive server names -+- add print-style sequence %s to $newsrc -+- add -g option -+ -+* Sat Apr 1 2000 Vsevolod Volkov -+- remove 'X-FTN-Origin' header processing -+ -+* Thu Mar 30 2000 Vsevolod Volkov -+- update to 1.1.11 -+- update to 1.1.10 -+ -+* Thu Mar 23 2000 Vsevolod Volkov -+- fix mutt_select_newsserver() -+- remove 'toggle-mode' function -+- add 'change-newsgroup' function -+ -+* Wed Mar 22 2000 Vsevolod Volkov -+- fix server-hook -+ -+* Tue Mar 21 2000 Vsevolod Volkov -+- fix error 'bounce' function after 'post' -+- add 'forward to newsgroup' function -+ -+* Mon Mar 20 2000 Vsevolod Volkov -+- 'forward' function works in newsreader mode -+- add 'post' and 'followup' functions to pager and attachment menu -+- fix active descriptions and allowed flag reload -+ -+* Tue Mar 14 2000 Vsevolod Volkov -+- update to 1.1.9 -+- remove deleted newsgroups from list -+ -+* Mon Mar 13 2000 Vsevolod Volkov -+- update .newsrc in browser -+ -+* Sun Mar 12 2000 Vsevolod Volkov -+- reload .newsrc if externally modified -+- fix active cache update -+ -+* Sun Mar 5 2000 Vsevolod Volkov -+- update to 1.1.8 -+ -+* Sat Mar 4 2000 Vsevolod Volkov -+- patch *.update_list_file is not required -+- count lines when loading descriptions -+- remove cache of unsubscribed newsgroups -+ -+* Thu Mar 2 2000 Vsevolod Volkov -+- load list of newsgroups from cache faster -+ -+* Wed Mar 1 2000 Vsevolod Volkov -+- update to 1.1.7 -+ -+* Tue Feb 29 2000 Vsevolod Volkov -+- fix unread messages in browser -+- fix newsrc_gen_entries() -+ -+* Mon Feb 28 2000 Vsevolod Volkov -+- fix mutt_newsgroup_stat() -+- fix nntp_delete_cache() -+- fix nntp_get_status() -+- fix check_children() -+- fix nntp_fetch_headers() -+ -+* Fri Feb 25 2000 Vsevolod Volkov -+- update to 1.1.5 -+ -+* Thu Feb 24 2000 Vsevolod Volkov -+- fix updating new messages in cache -+ -+* Mon Feb 21 2000 Vsevolod Volkov -+- change default cache filenames -+- fix updating new messages in cache -+ -+* Fri Feb 18 2000 Vsevolod Volkov -+- fix segmentation fault in news groups browser -+ -+* Tue Feb 15 2000 Vsevolod Volkov -+- update to 1.1.4 -+ -+* Thu Feb 10 2000 Vsevolod Volkov -+- update to 1.1.3 -+ -+* Sun Jan 30 2000 Vsevolod Volkov -+- add X-Comment-To editing -+- add my_hdr support for Newsgroups:, Followup-To: and X-Comment-To: headers -+- add variables $ask_followup_to and $ask_x_comment_to -+ -+* Fri Jan 28 2000 Vsevolod Volkov -+- update to 1.1.2 -+ -+* Wed Aug 23 2000 Andrej Gritsenko -+- nntp.c: inserted server hook when opened a newsgroup - for -+ difference between mail and news reader environment -+- parse.c: `X-FTN-Origin:' processed for bad Fido gates -+ -+* Tue Aug 22 2000 Vsevolod Volkov -+- browser.c, complete.c: newsgroup completion patch -+ -+* Wed Dec 22 1999 Andrej Gritsenko -+- send.c: fixed bug with `Subject:' on followup -+ -+* Sat Dec 18 1999 Andrej Gritsenko -+- updated to 1.1.1 -+ -+* Tue Oct 26 1999 Andrej Gritsenko -+- updated to 1.1 -+ -+* Mon Jun 14 1999 Andrej Gritsenko -+- sendlib.c: use $mime_subject for news articles only -+ -+* Fri Jun 11 1999 Edouard G. Parmelan -+- nntp.c: bugfix with number of new articles -+ -+* Thu Jun 10 1999 Andrej Gritsenko -+- nntp.c: fixed incomplete creating of index file -+ -+* Wed Jun 9 1999 Andrej Gritsenko -+- updated to 0.96.3 -+- doc/manual*: documentation updated -+ -+* Sun Feb 21 1999 Andrej Gritsenko -+- browser.c, newsrc.c, nntp.c: couple of fixes -+ -+* Wed Dec 16 1998 Andrej Gritsenko -+- curs_main.c, newsrc.c, nntp.c: fixes on number of read -+ articles -+ -+* Tue Dec 15 1998 Vikas Agnihotri -+- nntp.c: fix with gone cache files -+ -+* Tue Dec 15 1998 Andrej Gritsenko -+- newsrc.c, nntp.c: fixes on number of read articles -+ -+* Mon Dec 14 1998 Andrej Gritsenko -+- browser.c, newsrc.c, nntp.c, nntp.h: changed then simplified -+ nntp_parse_xover() -+ -+* Mon Dec 14 1998 Vikas Agnihotri -+- browser.c: cosmetic patch -+- nntp.c: say "Fetching %s from server..." -+ -+* Sun Dec 13 1998 Andrej Gritsenko -+- commands.c, newsrc.c, nntp.c, nntp.h: don't save newsrc file -+ so often (noted by Vikas Agnihotri) -+ -+* Sat Dec 12 1998 Andrej Gritsenko -+- browser.c, functions.h, nntp.c, nntp.h: fixed incorrect first -+ active loading -+ -+* Wed Dec 9 1998 Vikas Agnihotri -+- nntp.c: fixed bug in `reconstruct-thread' function -+- curs_main.c, nntp.c: fixed the bug in non-XOVER case of get -+ headers -+ -+* Tue Dec 8 1998 Andrej Gritsenko -+- nntp.c: fixed error in getting status of article -+ -+* Tue Dec 8 1998 Vikas Agnihotri -+- mutt.h, pattern.c: added `~w' search pattern -+ -+* Tue Dec 8 1998 Andrej Gritsenko -+- nntp.c: bugfix when get children -+ -+* Tue Dec 8 1998 Vikas Agnihotri -+- newsrc.c: bugfix in mutt_newsgroup_catchup() -+ -+* Tue Dec 8 1998 Andrej Gritsenko -+- browser.c: bugfix in _mutt_select_file() -+ -+* Sat Dec 5 1998 Andrej Gritsenko -+- browser.c, newsrc.c, nntp.c, nntp.h: fix the sorting of -+ newsgroups in browser (from Vikas Agnihotri) -+ -+* Fri Dec 4 1998 Vikas Agnihotri -+- OPS, curs_main.c, functions.h, nntp.c, nntp.h: new functions: -+ `get-children' and `reconstruct-thread' -+ -+* Thu Dec 3 1998 Vikas Agnihotri -+- OPS, curs_main.c, functions.h, nntp.c, nntp.h: new functions: -+ `get-message' and `get-parent' -+ -+* Wed Dec 2 1998 Vikas Agnihotri -+- OPS, compose.c, curs_main.c, functions.h, parse.c, send.c, -+ sendlib.c: added `Followup-To:' field editing -+ -+* Wed Dec 2 1998 Vikas Agnihotri -+- OPS, browser.c, functions.h: new `load-active' function -+ -+* Tue Dec 1 1998 Andrej Gritsenko -+- browser.c: added option for blank %s in $group_index_format -+- hdrline.c, lib.c, mutt.h, parse.c: added %g and %W parameters -+ to $pager_format -+- hook.c, newsrc.c, nntp.c, sendlib.c: some small bugfixes -+ -+* Mon Nov 30 1998 Andrej Gritsenko -+- send.c: bugfix in `Followup-To:' field -+ -+* Sun Nov 29 1998 Vikas Agnihotri -+- compose.c, lib.c, parse.c, protos.h: remove white spaces from -+ `Newsgroup:' field to prevent a unnecessary rejection of article -+ -+* Sat Nov 28 1998 Vikas Agnihotri -+- newsrc.c: fixed bug in catchup -+ -+* Sat Nov 28 1998 Vikas Agnihotri -+- browser.c: make indicator advance when (un)subscribe -+ -+* Sat Nov 28 1998 Andrej Gritsenko -+- newsrc.c: fixed segmentation fault in newsrc_update_line() -+ -+* Sat Nov 28 1998 Andrej Gritsenko -+- OPS, browser.c, functions.h, init.h, mutt.h, mx.c, newsrc.c, -+ nntp.c, nntp.h: corrected reading of newsrc file and added new -+ `catchup' function -+ -+* Thu Nov 26 1998 Andrej Gritsenko -+- browser.c, newsrc.c: implementation of `(un)subscribe-pattern' -+ functions from Vikas Agnihotri -+- globals.h, init.h, nntp.h, nntp.c: added variable $nntp_poll -+ to avoid of polling newsserver on each keypressing -+ -+* Thu Nov 26 1998 Andrej Gritsenko -+- nntp.c, socket.c: fixed parsing of long XOVER lines -+- send.c: removed silly ask for newsgroup name (noted by Vikas -+ Agnihotri) -+ -+* Wed Nov 25 1998 -+- commands.c: bugfix in mutt_update_list_file() -+ -+* Wed Nov 25 1998 Andrej Gritsenko -+- updated to mutt-0.94.17 -+- init.c, nntp.c, nntp.h, parse.c, send.c: couple of bugfixes -+ from Vikas Agnihotri -+ -+* Sat Nov 21 1998 Andrej Gritsenko -+- [mutt-0.94.13] couple of files: pre-alpha version of patch, -+ partially based on code that written by Brandon Long -diff -uNr mutt-1.4.orig/Makefile.am mutt-1.4/Makefile.am ---- mutt-1.4.orig/Makefile.am Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/Makefile.am Sun Nov 3 21:57:20 2002 -@@ -68,7 +68,8 @@ - EXTRA_mutt_SOURCES = account.c md5c.c mutt_sasl.c mutt_socket.c mutt_ssl.c \ - mutt_tunnel.c pop.c pop_auth.c pop_lib.c pgp.c pgpinvoke.c pgpkey.c \ - pgplib.c sha1.c pgpmicalg.c gnupgparse.c resize.c dotlock.c remailer.c \ -- browser.h mbyte.h remailer.h url.h mutt_ssl_nss.c pgppacket.c -+ browser.h mbyte.h remailer.h url.h mutt_ssl_nss.c pgppacket.c \ -+ nntp.c newsrc.c - - EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP TODO configure acconfig.h account.h \ - attach.h buffy.h charset.h compress.h copy.h dotlock.h functions.h \ -@@ -77,6 +78,7 @@ - mutt_regex.h mutt_sasl.h mutt_socket.h mutt_ssl.h mutt_tunnel.h \ - mx.h pager.h pgp.h pop.h protos.h reldate.h rfc1524.h rfc2047.h \ - rfc2231.h rfc822.h sha1.h sort.h mime.types VERSION prepare \ -+ nntp.h ChangeLog.nntp \ - _regex.h OPS.MIX README.SECURITY remailer.c remailer.h browser.h \ - mbyte.h lib.h extlib.c pgpewrap.c pgplib.h Muttrc.head Muttrc \ - makedoc.c stamp-doc-rc README.SSL \ -diff -uNr mutt-1.4.orig/Muttrc mutt-1.4/Muttrc ---- mutt-1.4.orig/Muttrc Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/Muttrc Sun Nov 3 21:57:20 2002 -@@ -185,6 +185,28 @@ - # editing the body of an outgoing message. - # - # -+# set ask_follow_up=no -+# -+# Name: ask_follow_up -+# Type: boolean -+# Default: no -+# -+# -+# If set, Mutt will prompt you for follow-up groups before editing -+# the body of an outgoing message. -+# -+# -+# set ask_x_comment_to=no -+# -+# Name: ask_x_comment_to -+# Type: boolean -+# Default: no -+# -+# -+# If set, Mutt will prompt you for x-comment-to field before editing -+# the body of an outgoing message. -+# -+# - # set attach_format="%u%D%I %t%4n %T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] " - # - # Name: attach_format -@@ -308,6 +330,17 @@ - # bouncing messages. Postfix users may wish to unset this variable. - # - # -+# set catchup_newsgroup=ask-yes -+# -+# Name: catchup_newsgroup -+# Type: quadoption -+# Default: ask-yes -+# -+# -+# If this variable is set, Mutt will mark all articles in newsgroup -+# as read when you quit the newsgroup (catchup newsgroup). -+# -+# - # set charset="" - # - # Name: charset -@@ -734,6 +767,19 @@ - # resulting in two copies of the same email for you. - # - # -+# set followup_to_poster=ask-yes -+# -+# Name: followup_to_poster -+# Type: quadoption -+# Default: ask-yes -+# -+# -+# If this variable is set and the keyword "poster" is present in -+# Followup-To header, follow-up to newsgroup function is not -+# permitted. The message will be mailed to the submitter of the -+# message via mail. -+# -+# - # set force_name=no - # - # Name: force_name -@@ -818,6 +864,28 @@ - # "Franklin" to "Franklin, Steve". - # - # -+# set group_index_format="%4C %M%N %5s %-45.45f %d" -+# -+# Name: group_index_format -+# Type: string -+# Default: "%4C %M%N %5s %-45.45f %d" -+# -+# -+# This variable allows you to customize the newsgroup browser display to -+# your personal taste. This string is similar to ``index_format'', but -+# has its own set of printf()-like sequences: -+# -+# %C current newsgroup number -+# %d description of newsgroup (becomes from server) -+# %f newsgroup name -+# %M - if newsgroup not allowed for direct post (moderated for example) -+# %N N if newsgroup is new, u if unsubscribed, blank otherwise -+# %n number of new articles in newsgroup -+# %s number of unread articles in newsgroup -+# %>X right justify the rest of the string and pad with character "X" -+# %|X pad to the end of the line with character "X" -+# -+# - # set hdrs=yes - # - # Name: hdrs -@@ -1187,6 +1255,7 @@ - # %E number of messages in current thread - # %f entire From: line (address + real name) - # %F author name, or recipient name if the message is from you -+# %g newsgroup name (if compiled with nntp support) - # %i message-id of the current message - # %l number of lines in the message - # %L If an address in the To or CC header field matches an address -@@ -1204,6 +1273,7 @@ - # %T the appropriate character from the $to_chars string - # %u user (login) name of the author - # %v first name of the author, or the recipient if the message is from you -+# %W name of organization of author (`organization:' field) - # %y `x-label:' field, if present - # %Y `x-label' field, if present, and (1) not at part of a thread tree, - # (2) at the top of a thread, or (3) `x-label' is different from -@@ -1227,6 +1297,22 @@ - # See also: ``$to_chars''. - # - # -+# set inews="" -+# -+# Name: inews -+# Type: path -+# Default: "" -+# -+# -+# If set, specifies the program and arguments used to deliver news posted -+# by Mutt. Otherwise, mutt posts article using current connection to -+# news server. The following printf-style sequence is understood: -+# -+# %s newsserver name -+# -+# Example: set inews="/usr/local/bin/inews -hS" -+# -+# - # set ispell="/usr/bin/ispell" - # - # Name: ispell -@@ -1496,6 +1582,18 @@ - # be attached to the newly composed message if this option is set. - # - # -+# set mime_subject=yes -+# -+# Name: mime_subject -+# Type: boolean -+# Default: yes -+# -+# -+# If unset, 8-bit ``subject:'' line in article header will not be -+# encoded according to RFC2047 to base64. This is useful when message -+# is Usenet article, because MIME for news is nonstandard feature. -+# -+# - # set mix_entry_format="%4n %c %-16s %a" - # - # Name: mix_entry_format -@@ -1550,6 +1648,118 @@ - # escape sequences see the section on ``$index_format''. - # - # -+# set news_cache_dir="~/.mutt" -+# -+# Name: news_cache_dir -+# Type: path -+# Default: "~/.mutt" -+# -+# -+# This variable pointing to directory where Mutt will save cached news -+# articles headers in. If unset, headers will not be saved at all -+# and will be reloaded each time when you enter to newsgroup. -+# -+# -+# set news_server="" -+# -+# Name: news_server -+# Type: string -+# Default: "" -+# -+# -+# This variable specifies domain name or address of NNTP server. It -+# defaults to the newsserver specified in the environment variable -+# $NNTPSERVER or contained in the file /etc/nntpserver. You can also -+# specify username and an alternative port for each newsserver, ie: -+# -+# [nntp[s]://][username[:password]@]newsserver[:port] -+# -+# -+# set newsrc="~/.newsrc" -+# -+# Name: newsrc -+# Type: path -+# Default: "~/.newsrc" -+# -+# -+# The file, containing info about subscribed newsgroups - names and -+# indexes of read articles. The following printf-style sequence -+# is understood: -+# -+# %s newsserver name -+# -+# -+# set nntp_context=1000 -+# -+# Name: nntp_context -+# Type: number -+# Default: 1000 -+# -+# -+# This variable defines number of articles which will be in index when -+# newsgroup entered. If active newsgroup have more articles than this -+# number, oldest articles will be ignored. Also controls how many -+# articles headers will be saved in cache when you quit newsgroup. -+# -+# -+# set nntp_load_description=yes -+# -+# Name: nntp_load_description -+# Type: boolean -+# Default: yes -+# -+# -+# This variable controls whether or not descriptions for each newsgroup -+# must be loaded when newsgroup is added to list (first time list -+# loading or new newsgroup adding). -+# -+# -+# set nntp_user="" -+# -+# Name: nntp_user -+# Type: string -+# Default: "" -+# -+# -+# Your login name on the NNTP server. If unset and NNTP server requires -+# authentification, Mutt will prompt you for your account name when you -+# connect to newsserver. -+# -+# -+# set nntp_pass="" -+# -+# Name: nntp_pass -+# Type: string -+# Default: "" -+# -+# -+# Your password for NNTP account. -+# -+# -+# set nntp_poll=60 -+# -+# Name: nntp_poll -+# Type: number -+# Default: 60 -+# -+# -+# The time in seconds until any operations on newsgroup except post new -+# article will cause recheck for new news. If set to 0, Mutt will -+# recheck newsgroup on each operation in index (stepping, read article, -+# etc.). -+# -+# -+# set nntp_reconnect=ask-yes -+# -+# Name: nntp_reconnect -+# Type: quadoption -+# Default: ask-yes -+# -+# -+# Controls whether or not Mutt will try to reconnect to newsserver when -+# connection lost. -+# -+# - # set pager="builtin" - # - # Name: pager -@@ -2293,6 +2503,19 @@ - # string after the inclusion of a message which is being replied to. - # - # -+# set post_moderated=ask-yes -+# -+# Name: post_moderated -+# Type: quadoption -+# Default: ask-yes -+# -+# -+# If set to yes, Mutt will post article to newsgroup that have -+# not permissions to posting (e.g. moderated). Note: if newsserver -+# does not support posting to that newsgroup or totally read-only, that -+# posting will not have an effect. -+# -+# - # set postpone=ask-yes - # - # Name: postpone -@@ -2802,6 +3025,41 @@ - # shell from /etc/passwd is used. - # - # -+# set save_unsubscribed=no -+# -+# Name: save_unsubscribed -+# Type: boolean -+# Default: no -+# -+# -+# When set, info about unsubscribed newsgroups will be saved into -+# ``newsrc'' file and into cache. -+# -+# -+# set show_new_news=yes -+# -+# Name: show_new_news -+# Type: boolean -+# Default: yes -+# -+# -+# If set, newsserver will be asked for new newsgroups on entering -+# the browser. Otherwise, it will be done only once for a newsserver. -+# Also controls whether or not number of new articles of subscribed -+# newsgroups will be then checked. -+# -+# -+# set show_only_unread=no -+# -+# Name: show_only_unread -+# Type: boolean -+# Default: no -+# -+# -+# If set, only subscribed newsgroups that contain unread articles -+# will be displayed in browser. -+# -+# - # set sig_dashes=yes - # - # Name: sig_dashes -@@ -3285,6 +3543,18 @@ - # command. - # - # -+# set use_ipv6=yes -+# -+# Name: use_ipv6 -+# Type: boolean -+# Default: yes -+# -+# -+# When set, Mutt will look for IPv6 addresses of hosts it tries to -+# contact. If this option is unset, Mutt will restrict itself to IPv4 addresses. -+# Normally, the default should work. -+# -+# - # set user_agent=yes - # - # Name: user_agent -@@ -3387,3 +3657,14 @@ - # messages to be sent. Exim users may wish to use this. - # - # -+# set x_comment_to=no -+# -+# Name: x_comment_to -+# Type: boolean -+# Default: no -+# -+# -+# If set, Mutt will add ``X-Comment-To:'' field (that contains full -+# name of original article author) to article that followuped to newsgroup. -+# -+# -diff -uNr mutt-1.4.orig/Muttrc.head mutt-1.4/Muttrc.head ---- mutt-1.4.orig/Muttrc.head Sun Nov 3 21:42:51 2002 -+++ mutt-1.4/Muttrc.head Thu Jan 1 01:00:00 1970 -@@ -1,43 +0,0 @@ --# --# System configuration file for Mutt --# -- --# default list of header fields to weed when displaying --# --ignore "from " received content- mime-version status x-status message-id --ignore sender references return-path lines -- --# imitate the old search-body function --macro index \eb '/~b ' 'search in message bodies' -- --# simulate the old url menu --macro index \cb |urlview\n 'call urlview to extract URLs out of a message' --macro pager \cb |urlview\n 'call urlview to extract URLs out of a message' -- --# Show documentation when pressing F1 --macro generic "!less /usr/local/doc/mutt/manual.txt\n" "Show Mutt documentation" --macro index "!less /usr/local/doc/mutt/manual.txt\n" "Show Mutt documentation" --macro pager "!less /usr/local/doc/mutt/manual.txt\n" "Show Mutt documentation" -- --# Use folders which match on \\.gz$ as gzipped folders: --# open-hook \\.gz$ "gzip -cd %f > %t" --# close-hook \\.gz$ "gzip -c %t > %f" --# append-hook \\.gz$ "gzip -c %t >> %f" -- --# open-hook \\.bz2$ "bzip2 -cd %f > %t" --# close-hook \\.bz2$ "bzip2 -c %t > %f" --# append-hook \\.bz2$ "bzip2 -c %t >> %f" -- --# If Mutt is unable to determine your site's domain name correctly, you can --# set the default here. --# --# set hostname=cs.hmc.edu -- --# If your sendmail supports the -B8BITMIME flag, enable the following --# --# set use_8bitmime -- --## --## More settings --## -- -diff -uNr mutt-1.4.orig/OPS mutt-1.4/OPS ---- mutt-1.4.orig/OPS Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/OPS Sun Nov 3 21:57:20 2002 -@@ -7,13 +7,15 @@ - OP_BROWSER_NEW_FILE "select a new file in this directory" - OP_BROWSER_VIEW_FILE "view file" - OP_BROWSER_TELL "display the currently selected file's name" --OP_BROWSER_SUBSCRIBE "subscribe to current mailbox (IMAP only)" --OP_BROWSER_UNSUBSCRIBE "unsubscribe to current mailbox (IMAP only)" -+OP_CATCHUP "mark all articles in newsgroup as read" -+OP_BROWSER_SUBSCRIBE "subscribe to current (IMAP/NNTP only)" -+OP_BROWSER_UNSUBSCRIBE "unsubscribe to current (IMAP/NNTP only)" - OP_BROWSER_TOGGLE_LSUB "toggle view all/subscribed mailboxes (IMAP only)" - OP_CHANGE_DIRECTORY "change directories" - OP_CHECK_NEW "check mailboxes for new mail" - OP_COMPOSE_ATTACH_FILE "attach a file(s) to this message" - OP_COMPOSE_ATTACH_MESSAGE "attach message(s) to this message" -+OP_COMPOSE_ATTACH_NEWS_MESSAGE "attach newsmessage(s) to this message" - OP_COMPOSE_EDIT_BCC "edit the BCC list" - OP_COMPOSE_EDIT_CC "edit the CC list" - OP_COMPOSE_EDIT_DESCRIPTION "edit attachment description" -@@ -24,7 +26,10 @@ - OP_COMPOSE_EDIT_HEADERS "edit the message with headers" - OP_COMPOSE_EDIT_MESSAGE "edit the message" - OP_COMPOSE_EDIT_MIME "edit attachment using mailcap entry" -+OP_COMPOSE_EDIT_NEWSGROUPS "edit the newsgroups list" - OP_COMPOSE_EDIT_REPLY_TO "edit the Reply-To field" -+OP_COMPOSE_EDIT_FOLLOWUP_TO "edit the Followup-To field" -+OP_COMPOSE_EDIT_X_COMMENT_TO "edit the X-Comment-To field" - OP_COMPOSE_EDIT_SUBJECT "edit the subject of this message" - OP_COMPOSE_EDIT_TO "edit the TO list" - OP_CREATE_MAILBOX "create a new mailbox (IMAP only)" -@@ -84,8 +89,13 @@ - OP_FILTER "filter attachment through a shell command" - OP_FIRST_ENTRY "move to the first entry" - OP_FLAG_MESSAGE "toggle a message's 'important' flag" -+OP_FOLLOWUP "followup to newsgroup" -+OP_FORWARD_TO_GROUP "forward to newsgroup" - OP_FORWARD_MESSAGE "forward a message with comments" - OP_GENERIC_SELECT_ENTRY "select the current entry" -+OP_GET_CHILDREN "get all children of the current message" -+OP_GET_MESSAGE "get message with Message-Id" -+OP_GET_PARENT "get parent of the current message" - OP_GROUP_REPLY "reply to all recipients" - OP_HALF_DOWN "scroll down 1/2 page" - OP_HALF_UP "scroll up 1/2 page" -@@ -93,13 +103,17 @@ - OP_JUMP "jump to an index number" - OP_LAST_ENTRY "move to the last entry" - OP_LIST_REPLY "reply to specified mailing list" -+OP_LOAD_ACTIVE "load active file from NNTP server" - OP_MACRO "execute a macro" - OP_MAIL "compose a new mail message" - OP_MAIN_BREAK_THREAD "break the thread in two" - OP_MAIN_CHANGE_FOLDER "open a different folder" - OP_MAIN_CHANGE_FOLDER_READONLY "open a different folder in read only mode" -+OP_MAIN_CHANGE_GROUP "open a different newsgroup" -+OP_MAIN_CHANGE_GROUP_READONLY "open a different newsgroup in read only mode" - OP_MAIN_CLEAR_FLAG "clear a status flag from a message" - OP_MAIN_DELETE_PATTERN "delete messages matching a pattern" -+OP_RECONSTRUCT_THREAD "reconstruct thread containing current message" - OP_MAIN_IMAP_FETCH "force retrieval of mail from IMAP server" - OP_MAIN_FETCH_MAIL "retrieve mail from POP server" - OP_MAIN_FIRST_MESSAGE "move to the first message" -@@ -134,6 +148,7 @@ - OP_PAGER_SKIP_QUOTED "skip beyond quoted text" - OP_PAGER_TOP "jump to the top of the message" - OP_PIPE "pipe message/attachment to a shell command" -+OP_POST "post message to newsgroup" - OP_PREV_ENTRY "move to the previous entry" - OP_PREV_LINE "scroll up one line" - OP_PREV_PAGE "move to the previous page" -@@ -159,17 +174,21 @@ - OP_SIG_SEARCH "search signatures matching a pattern" - OP_SORT "sort messages" - OP_SORT_REVERSE "sort messages in reverse order" -+OP_SUBSCRIBE_PATTERN "subscribe to newsgroups matching a pattern" - OP_TAG "tag the current entry" - OP_TAG_PREFIX "apply next function to tagged messages" - OP_TAG_SUBTHREAD "tag the current subthread" - OP_TAG_THREAD "tag the current thread" - OP_TOGGLE_NEW "toggle a message's 'new' flag" -+OP_TOGGLE_READ "toggle view of read messages" - OP_TOGGLE_WRITE "toggle whether the mailbox will be rewritten" - OP_TOGGLE_MAILBOXES "toggle whether to browse mailboxes or all files" - OP_TOP_PAGE "move to the top of the page" -+OP_UNCATCHUP "mark all articles in newsgroup as unread" - OP_UNDELETE "undelete the current entry" - OP_UNDELETE_THREAD "undelete all messages in thread" - OP_UNDELETE_SUBTHREAD "undelete all messages in subthread" -+OP_UNSUBSCRIBE_PATTERN "unsubscribe from newsgroups matching a pattern" - OP_VERSION "show the Mutt version number and date" - OP_VIEW_ATTACH "view attachment using mailcap entry if necessary" - OP_VIEW_ATTACHMENTS "show MIME attachments" -diff -uNr mutt-1.4.orig/PATCHES mutt-1.4/PATCHES ---- mutt-1.4.orig/PATCHES Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/PATCHES Sun Nov 3 21:57:20 2002 -@@ -1,0 +1,1 @@ -+vvv.nntp -diff -uNr mutt-1.4.orig/acconfig.h mutt-1.4/acconfig.h ---- mutt-1.4.orig/acconfig.h Tue Jan 15 23:08:12 2002 -+++ mutt-1.4/acconfig.h Sun Nov 3 21:57:20 2002 -@@ -14,6 +14,9 @@ - */ - #undef HOMESPOOL - -+/* Compiling with newsreading support with NNTP */ -+#undef USE_NNTP -+ - /* program to use for shell commands */ - #define EXECSHELL "/bin/sh" - -diff -uNr mutt-1.4.orig/account.c mutt-1.4/account.c ---- mutt-1.4.orig/account.c Thu Apr 26 15:36:33 2001 -+++ mutt-1.4/account.c Sun Nov 3 21:57:20 2002 -@@ -44,6 +44,11 @@ - user = PopUser; - #endif - -+#ifdef USE_NNTP -+ if (a1->type == M_ACCT_TYPE_NNTP && NntpUser) -+ user = NntpUser; -+#endif -+ - if (a1->flags & a2->flags & M_ACCT_USER) - return (!strcmp (a1->user, a2->user)); - if (a1->flags & M_ACCT_USER) -@@ -113,6 +118,16 @@ - } - #endif - -+#ifdef USE_NNTP -+ if (account->type == M_ACCT_TYPE_NNTP) -+ { -+ if (account->flags & M_ACCT_SSL) -+ url->scheme = U_NNTPS; -+ else -+ url->scheme = U_NNTP; -+ } -+#endif -+ - url->host = account->host; - if (account->flags & M_ACCT_PORT) - url->port = account->port; -@@ -138,6 +153,10 @@ - else if ((account->type == M_ACCT_TYPE_POP) && PopUser) - strfcpy (account->user, PopUser, sizeof (account->user)); - #endif -+#ifdef USE_NNTP -+ else if ((account->type == M_ACCT_TYPE_NNTP) && NntpUser) -+ strfcpy (account->user, NntpUser, sizeof (account->user)); -+#endif - /* prompt (defaults to unix username), copy into account->user */ - else - { -@@ -167,6 +186,10 @@ - else if ((account->type == M_ACCT_TYPE_POP) && PopPass) - strfcpy (account->pass, PopPass, sizeof (account->pass)); - #endif -+#ifdef USE_NNTP -+ else if ((account->type == M_ACCT_TYPE_NNTP) && NntpPass) -+ strfcpy (account->pass, NntpPass, sizeof (account->pass)); -+#endif - else - { - snprintf (prompt, sizeof (prompt), _("Password for %s@%s: "), -diff -uNr mutt-1.4.orig/account.h mutt-1.4/account.h ---- mutt-1.4.orig/account.h Tue Jan 2 10:34:30 2001 -+++ mutt-1.4/account.h Sun Nov 3 21:57:20 2002 -@@ -28,6 +28,7 @@ - { - M_ACCT_TYPE_NONE = 0, - M_ACCT_TYPE_IMAP, -+ M_ACCT_TYPE_NNTP, - M_ACCT_TYPE_POP - }; - -diff -uNr mutt-1.4.orig/attach.h mutt-1.4/attach.h ---- mutt-1.4.orig/attach.h Tue Sep 11 13:20:34 2001 -+++ mutt-1.4/attach.h Sun Nov 3 21:57:20 2002 -@@ -30,5 +30,5 @@ - - void mutt_attach_bounce (FILE *, HEADER *, ATTACHPTR **, short, BODY *); - void mutt_attach_resend (FILE *, HEADER *, ATTACHPTR **, short, BODY *); --void mutt_attach_forward (FILE *, HEADER *, ATTACHPTR **, short, BODY *); -+void mutt_attach_forward (FILE *, HEADER *, ATTACHPTR **, short, BODY *, int); - void mutt_attach_reply (FILE *, HEADER *, ATTACHPTR **, short, BODY *, int); -diff -uNr mutt-1.4.orig/browser.c mutt-1.4/browser.c ---- mutt-1.4.orig/browser.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/browser.c Sun Nov 3 22:00:14 2002 -@@ -27,6 +27,9 @@ - #ifdef USE_IMAP - #include "imap.h" - #endif -+#ifdef USE_NNTP -+#include "nntp.h" -+#endif - - #include - #include -@@ -44,6 +47,19 @@ - { NULL } - }; - -+#ifdef USE_NNTP -+static struct mapping_t FolderNewsHelp[] = { -+ { N_("Exit"), OP_EXIT }, -+ { N_("List"), OP_TOGGLE_MAILBOXES }, -+ { N_("Subscribe"), OP_BROWSER_SUBSCRIBE }, -+ { N_("Unsubscribe"), OP_BROWSER_UNSUBSCRIBE }, -+ { N_("Catchup"), OP_CATCHUP }, -+ { N_("Mask"), OP_ENTER_MASK }, -+ { N_("Help"), OP_HELP }, -+ { NULL } -+}; -+#endif -+ - typedef struct folder_t - { - struct folder_file *ff; -@@ -109,9 +125,17 @@ - case SORT_ORDER: - return; - case SORT_DATE: -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ return; -+#endif - f = browser_compare_date; - break; - case SORT_SIZE: -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ return; -+#endif - f = browser_compare_size; - break; - case SORT_SUBJECT: -@@ -299,8 +323,106 @@ - return (src); - } - -+#ifdef USE_NNTP -+static const char * -+newsgroup_format_str (char *dest, size_t destlen, char op, const char *src, -+ const char *fmt, const char *ifstring, const char *elsestring, -+ unsigned long data, format_flag flags) -+{ -+ char fn[SHORT_STRING], tmp[SHORT_STRING]; -+ FOLDER *folder = (FOLDER *) data; -+ -+ switch (op) -+ { -+ case 'C': -+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt); -+ snprintf (dest, destlen, tmp, folder->num + 1); -+ break; -+ -+ case 'f': -+ strncpy (fn, folder->ff->name, sizeof(fn) - 1); -+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt); -+ snprintf (dest, destlen, tmp, fn); -+ break; -+ -+ case 'N': -+ snprintf (tmp, sizeof (tmp), "%%%sc", fmt); -+ if (folder->ff->nd->subscribed) -+ snprintf (dest, destlen, tmp, ' '); -+ else -+ snprintf (dest, destlen, tmp, folder->ff->new ? 'N' : 'u'); -+ break; -+ -+ case 'M': -+ snprintf (tmp, sizeof (tmp), "%%%sc", fmt); -+ if (folder->ff->nd->deleted) -+ snprintf (dest, destlen, tmp, 'D'); -+ else -+ snprintf (dest, destlen, tmp, folder->ff->nd->allowed ? ' ' : '-'); -+ break; -+ -+ case 's': -+ if (flags & M_FORMAT_OPTIONAL) -+ { -+ if (folder->ff->nd->unread != 0) -+ mutt_FormatString (dest, destlen, ifstring, newsgroup_format_str, -+ data, flags); -+ else -+ mutt_FormatString (dest, destlen, elsestring, newsgroup_format_str, -+ data, flags); -+ } -+ else if (Context && Context->data == folder->ff->nd) -+ { -+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt); -+ snprintf (dest, destlen, tmp, Context->unread); -+ } -+ else -+ { -+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt); -+ snprintf (dest, destlen, tmp, folder->ff->nd->unread); -+ } -+ break; -+ -+ case 'n': -+ if (Context && Context->data == folder->ff->nd) -+ { -+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt); -+ snprintf (dest, destlen, tmp, Context->new); -+ } -+ else if (option (OPTMARKOLD) && -+ folder->ff->nd->lastCached >= folder->ff->nd->firstMessage && -+ folder->ff->nd->lastCached <= folder->ff->nd->lastMessage) -+ { -+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt); -+ snprintf (dest, destlen, tmp, folder->ff->nd->lastMessage - folder->ff->nd->lastCached); -+ } -+ else -+ { -+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt); -+ snprintf (dest, destlen, tmp, folder->ff->nd->unread); -+ } -+ break; -+ -+ case 'd': -+ if (folder->ff->nd->desc != NULL) -+ { -+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt); -+ snprintf (dest, destlen, tmp, folder->ff->nd->desc); -+ } -+ else -+ { -+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt); -+ snprintf (dest, destlen, tmp, ""); -+ } -+ break; -+ } -+ return (src); -+} -+#endif /* USE_NNTP */ -+ - static void add_folder (MUTTMENU *m, struct browser_state *state, -- const char *name, const struct stat *s, int new) -+ const char *name, const struct stat *s, -+ void *data, int new) - { - if (state->entrylen == state->entrymax) - { -@@ -329,6 +451,10 @@ - #ifdef USE_IMAP - (state->entry)[state->entrylen].imap = 0; - #endif -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ (state->entry)[state->entrylen].nd = (NNTP_DATA *) data; -+#endif - (state->entrylen)++; - } - -@@ -344,9 +470,35 @@ - menu->data = state->entry; - } - -+/* get list of all files/newsgroups with mask */ - static int examine_directory (MUTTMENU *menu, struct browser_state *state, - char *d, const char *prefix) - { -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ { -+ LIST *tmp; -+ NNTP_DATA *data; -+ NNTP_SERVER *news = CurrentNewsSrv; -+ -+/* mutt_buffy_check (0); */ -+ init_state (state, menu); -+ -+ for (tmp = news->list; tmp; tmp = tmp->next) -+ { -+ if (!(data = (NNTP_DATA *)tmp->data)) -+ continue; -+ if (prefix && *prefix && strncmp (prefix, data->group, -+ strlen (prefix)) != 0) -+ continue; -+ if (!((regexec (Mask.rx, data->group, 0, NULL, 0) == 0) ^ Mask.not)) -+ continue; -+ add_folder (menu, state, data->group, NULL, data, data->new); -+ } -+ } -+ else -+#endif /* USE_NNTP */ -+ { - struct stat s; - DIR *dp; - struct dirent *de; -@@ -411,60 +563,95 @@ - tmp = Incoming; - while (tmp && mutt_strcmp (buffer, tmp->path)) - tmp = tmp->next; -- add_folder (menu, state, de->d_name, &s, (tmp) ? tmp->new : 0); -+ add_folder (menu, state, de->d_name, &s, NULL, (tmp) ? tmp->new : 0); -+ } -+ closedir (dp); - } -- closedir (dp); - browser_sort (state); - return 0; - } - -+/* get list of mailboxes/subscribed newsgroups */ - static int examine_mailboxes (MUTTMENU *menu, struct browser_state *state) - { - struct stat s; - char buffer[LONG_STRING]; -- BUFFY *tmp = Incoming; - -- if (!Incoming) -- return (-1); -- mutt_buffy_check (0); -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ { -+ LIST *tmp; -+ NNTP_DATA *data; -+ NNTP_SERVER *news = CurrentNewsSrv; - -- init_state (state, menu); -+/* mutt_buffy_check (0); */ -+ init_state (state, menu); - -- do -- { --#ifdef USE_IMAP -- if (mx_is_imap (tmp->path)) -+ for (tmp = news->list; tmp; tmp = tmp->next) - { -- add_folder (menu, state, tmp->path, NULL, tmp->new); -- continue; -+ if ((data = (NNTP_DATA *) tmp->data) != NULL && (data->new || -+ (data->subscribed && (!option (OPTSHOWONLYUNREAD) || data->unread)))) -+ add_folder (menu, state, data->group, NULL, data, data->new); - } -+ } -+ else - #endif --#ifdef USE_POP -- if (mx_is_pop (tmp->path)) -+ { -+ BUFFY *tmp = Incoming; -+ -+ if (!Incoming) -+ return (-1); -+ mutt_buffy_check (0); -+ -+ init_state (state, menu); -+ -+ do - { -- add_folder (menu, state, tmp->path, NULL, tmp->new); -- continue; -- } -+#ifdef USE_IMAP -+ if (mx_is_imap (tmp->path)) -+ { -+ add_folder (menu, state, tmp->path, NULL, NULL, tmp->new); -+ continue; -+ } - #endif -- if (lstat (tmp->path, &s) == -1) -- continue; -+#ifdef USE_POP -+ if (mx_is_pop (tmp->path)) -+ { -+ add_folder (menu, state, tmp->path, NULL, NULL, tmp->new); -+ continue; -+ } -+#endif -+#ifdef USE_NNTP -+ if (mx_is_nntp (tmp->path)) -+ { -+ add_folder (menu, state, tmp->path, NULL, NULL, tmp->new); -+ continue; -+ } -+#endif -+ if (lstat (tmp->path, &s) == -1) -+ continue; - -- if ((! S_ISREG (s.st_mode)) && (! S_ISDIR (s.st_mode)) && -- (! S_ISLNK (s.st_mode))) -- continue; -+ if ((! S_ISREG (s.st_mode)) && (! S_ISDIR (s.st_mode)) && -+ (! S_ISLNK (s.st_mode))) -+ continue; - -- strfcpy (buffer, NONULL(tmp->path), sizeof (buffer)); -- mutt_pretty_mailbox (buffer); -+ strfcpy (buffer, NONULL(tmp->path), sizeof (buffer)); -+ mutt_pretty_mailbox (buffer); - -- add_folder (menu, state, buffer, &s, tmp->new); -+ add_folder (menu, state, buffer, &s, NULL, tmp->new); -+ } -+ while ((tmp = tmp->next)); - } -- while ((tmp = tmp->next)); - browser_sort (state); - return 0; - } - - int select_file_search (MUTTMENU *menu, regex_t *re, int n) - { -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ return (regexec (re, ((struct folder_file *) menu->data)[n].desc, 0, NULL, 0)); -+#endif - return (regexec (re, ((struct folder_file *) menu->data)[n].name, 0, NULL, 0)); - } - -@@ -475,7 +662,13 @@ - folder.ff = &((struct folder_file *) menu->data)[num]; - folder.num = num; - -- mutt_FormatString (s, slen, NONULL(FolderFormat), folder_format_str, -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ mutt_FormatString (s, slen, NONULL(GroupFormat), newsgroup_format_str, -+ (unsigned long) &folder, M_FORMAT_ARROWCURSOR); -+ else -+#endif -+ mutt_FormatString (s, slen, NONULL(FolderFormat), folder_format_str, - (unsigned long) &folder, M_FORMAT_ARROWCURSOR); - } - -@@ -495,7 +688,18 @@ - menu->top = 0; - - menu->tagged = 0; -- -+ -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ { -+ if (buffy) -+ snprintf (title, titlelen, _("Subscribed newsgroups")); -+ else -+ snprintf (title, titlelen, _("Newsgroups on server [%s]"), -+ CurrentNewsSrv->conn->account.host); -+ } -+ else -+#endif - if (buffy) - snprintf (title, titlelen, _("Mailboxes [%d]"), mutt_buffy_check (0)); - else -@@ -551,6 +755,31 @@ - if (!folder) - strfcpy (LastDirBackup, LastDir, sizeof (LastDirBackup)); - -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ { -+ if (*f) -+ strfcpy (prefix, f, sizeof (prefix)); -+ else -+ { -+ LIST *list; -+ -+ /* default state for news reader mode is browse subscribed newsgroups */ -+ buffy = 0; -+ for (list = CurrentNewsSrv->list; list; list = list->next) -+ { -+ NNTP_DATA *data = (NNTP_DATA *) list->data; -+ -+ if (data && data->subscribed) -+ { -+ buffy = 1; -+ break; -+ } -+ } -+ } -+ } -+ else -+#endif - if (*f) - { - mutt_expand_path (f, flen); -@@ -639,6 +868,9 @@ - menu->tag = file_tag; - - menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_FOLDER, -+#ifdef USE_NNTP -+ (option (OPTNEWS)) ? FolderNewsHelp : -+#endif - FolderHelp); - - init_menu (&state, menu, title, sizeof (title), buffy, FolderColumns); -@@ -777,7 +1009,11 @@ - } - } - -+#ifdef USE_NNTP -+ if (buffy || option (OPTNEWS)) /* news have not path */ -+#else - if (buffy) -+#endif - { - strfcpy (f, state.entry[menu->current].name, flen); - mutt_expand_path (f, flen); -@@ -835,14 +1071,6 @@ - break; - - #ifdef USE_IMAP -- case OP_BROWSER_SUBSCRIBE: -- imap_subscribe (state.entry[menu->current].name, 1); -- break; -- -- case OP_BROWSER_UNSUBSCRIBE: -- imap_subscribe (state.entry[menu->current].name, 0); -- break; -- - case OP_BROWSER_TOGGLE_LSUB: - if (option (OPTIMAPLSUB)) - { -@@ -913,6 +1141,11 @@ - - case OP_CHANGE_DIRECTORY: - -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ break; -+#endif -+ - strfcpy (buf, LastDir, sizeof (buf)); - #ifdef USE_IMAP - if (!state.imap_browse) -@@ -1163,6 +1396,190 @@ - else - mutt_error _("Error trying to view file"); - } -+ break; -+ -+#ifdef USE_NNTP -+ case OP_CATCHUP: -+ case OP_UNCATCHUP: -+ if (option (OPTNEWS)) -+ { -+ struct folder_file *f = &state.entry[menu->current]; -+ NNTP_DATA *nd; -+ -+ if (i == OP_CATCHUP) -+ nd = mutt_newsgroup_catchup (CurrentNewsSrv, f->name); -+ else -+ nd = mutt_newsgroup_uncatchup (CurrentNewsSrv, f->name); -+ -+ if (nd) -+ { -+/* FOLDER folder; -+ struct folder_file ff; -+ char buffer[_POSIX_PATH_MAX + SHORT_STRING]; -+ -+ folder.ff = &ff; -+ folder.ff->name = f->name; -+ folder.ff->st = NULL; -+ folder.ff->is_new = nd->new; -+ folder.ff->nd = nd; -+ safe_free ((void **) &f->desc); -+ mutt_FormatString (buffer, sizeof (buffer), NONULL(GroupFormat), -+ newsgroup_format_str, (unsigned long) &folder, -+ M_FORMAT_ARROWCURSOR); -+ f->desc = safe_strdup (buffer); */ -+ if (menu->current + 1 < menu->max) -+ menu->current++; -+ menu->redraw = REDRAW_MOTION_RESYNCH; -+ } -+ } -+ break; -+ -+ case OP_LOAD_ACTIVE: -+ if (!option (OPTNEWS)) -+ break; -+ -+ { -+ LIST *tmp; -+ NNTP_DATA *data; -+ -+ for (tmp = CurrentNewsSrv->list; tmp; tmp = tmp->next) -+ { -+ if ((data = (NNTP_DATA *)tmp->data)) -+ data->deleted = 1; -+ } -+ } -+ nntp_get_active (CurrentNewsSrv); -+ -+ destroy_state (&state); -+ if (buffy) -+ examine_mailboxes (menu, &state); -+ else -+ examine_directory (menu, &state, NULL, NULL); -+ init_menu (&state, menu, title, sizeof (title), buffy, 1); -+ break; -+#endif /* USE_NNTP */ -+ -+#if defined USE_IMAP || defined USE_NNTP -+ case OP_BROWSER_SUBSCRIBE: -+ case OP_BROWSER_UNSUBSCRIBE: -+#endif -+#ifdef USE_NNTP -+ case OP_SUBSCRIBE_PATTERN: -+ case OP_UNSUBSCRIBE_PATTERN: -+ if (option (OPTNEWS)) -+ { -+ regex_t *rx = (regex_t *) safe_malloc (sizeof (regex_t)); -+ char *s = buf; -+ int j = menu->current; -+ NNTP_DATA *nd; -+ NNTP_SERVER *news = CurrentNewsSrv; -+ -+ if (i == OP_SUBSCRIBE_PATTERN || i == OP_UNSUBSCRIBE_PATTERN) -+ { -+ char tmp[STRING]; -+ int err; -+ -+ buf[0] = 0; -+ if (i == OP_SUBSCRIBE_PATTERN) -+ snprintf (tmp, sizeof (tmp), _("Subscribe pattern: ")); -+ else -+ snprintf (tmp, sizeof (tmp), _("Unsubscribe pattern: ")); -+ if (mutt_get_field (tmp, buf, sizeof (buf), 0) != 0 || !buf[0]) -+ { -+ FREE (&rx); -+ break; -+ } -+ -+ if ((err = REGCOMP (rx, s, REG_NOSUB)) != 0) -+ { -+ regerror (err, rx, buf, sizeof (buf)); -+ regfree (rx); -+ safe_free ((void **) &rx); -+ mutt_error ("%s", buf); -+ break; -+ } -+ menu->redraw = REDRAW_FULL; -+ j = 0; -+ } -+ else if (!state.entrylen) -+ { -+ mutt_error _("No newsgroups match the mask"); -+ break; -+ } -+ -+ for ( ; j < state.entrylen; j++) -+ { -+ struct folder_file *f = &state.entry[j]; -+ -+ if (i == OP_BROWSER_SUBSCRIBE || i == OP_BROWSER_UNSUBSCRIBE || -+ regexec (rx, f->name, 0, NULL, 0) == 0) -+ { -+ if (i == OP_BROWSER_SUBSCRIBE || i == OP_SUBSCRIBE_PATTERN) -+ nd = mutt_newsgroup_subscribe (news, f->name); -+ else -+ nd = mutt_newsgroup_unsubscribe (news, f->name); -+/* if (nd) -+ { -+ FOLDER folder; -+ char buffer[_POSIX_PATH_MAX + SHORT_STRING]; -+ -+ folder.name = f->name; -+ folder.f = NULL; -+ folder.new = nd->new; -+ folder.nd = nd; -+ safe_free ((void **) &f->desc); -+ mutt_FormatString (buffer, sizeof (buffer), NONULL(GroupFormat), -+ newsgroup_format_str, (unsigned long) &folder, -+ M_FORMAT_ARROWCURSOR); -+ f->desc = safe_strdup (buffer); -+ } */ -+ } -+ if (i == OP_BROWSER_SUBSCRIBE || i == OP_BROWSER_UNSUBSCRIBE) -+ { -+ if (menu->current + 1 < menu->max) -+ menu->current++; -+ menu->redraw = REDRAW_MOTION_RESYNCH; -+ break; -+ } -+ } -+ if (i == OP_SUBSCRIBE_PATTERN) -+ { -+ LIST *grouplist = NULL; -+ -+ if (news) -+ grouplist = news->list; -+ for (; grouplist; grouplist = grouplist->next) -+ { -+ nd = (NNTP_DATA *) grouplist->data; -+ if (nd && nd->group && !nd->subscribed) -+ { -+ if (regexec (rx, nd->group, 0, NULL, 0) == 0) -+ { -+ mutt_newsgroup_subscribe (news, nd->group); -+ add_folder (menu, &state, nd->group, NULL, nd, nd->new); -+ } -+ } -+ } -+ init_menu (&state, menu, title, sizeof (title), buffy, 1); -+ } -+ mutt_newsrc_update (news); -+ nntp_clear_cacheindex (news); -+ if (i != OP_BROWSER_SUBSCRIBE && i != OP_BROWSER_UNSUBSCRIBE) -+ regfree (rx); -+ safe_free ((void **) &rx); -+ } -+#ifdef USE_IMAP -+ else -+#endif /* USE_IMAP && USE_NNTP */ -+#endif /* USE_NNTP */ -+#ifdef USE_IMAP -+ { -+ if (i == OP_BROWSER_SUBSCRIBE) -+ imap_subscribe (state.entry[menu->current].name, 1); -+ else -+ imap_subscribe (state.entry[menu->current].name, 0); -+ } -+#endif /* USE_IMAP */ - } - } - -diff -uNr mutt-1.4.orig/browser.h mutt-1.4/browser.h ---- mutt-1.4.orig/browser.h Mon Aug 21 17:42:20 2000 -+++ mutt-1.4/browser.h Sun Nov 3 21:57:20 2002 -@@ -20,6 +20,10 @@ - #ifndef _BROWSER_H - #define _BROWSER_H 1 - -+#ifdef USE_NNTP -+#include "nntp.h" -+#endif -+ - struct folder_file - { - mode_t mode; -@@ -38,14 +42,17 @@ - unsigned selectable : 1; - unsigned inferiors : 1; - #endif -+#ifdef USE_NNTP -+ NNTP_DATA *nd; -+#endif - unsigned tagged : 1; - }; - - struct browser_state - { - struct folder_file *entry; -- short entrylen; /* number of real entries */ -- short entrymax; /* max entry */ -+ unsigned int entrylen; /* number of real entries */ -+ unsigned int entrymax; /* max entry */ - #ifdef USE_IMAP - short imap_browse; - char *folder; -diff -uNr mutt-1.4.orig/buffy.c mutt-1.4/buffy.c ---- mutt-1.4.orig/buffy.c Mon Mar 25 12:30:08 2002 -+++ mutt-1.4/buffy.c Sun Nov 3 21:57:20 2002 -@@ -257,6 +257,9 @@ - #ifdef USE_POP - if (!Context || Context->magic != M_POP) - #endif -+#ifdef USE_NNTP -+ if (!Context || Context->magic != M_NNTP) -+#endif - /* check device ID and serial number instead of comparing paths */ - if (!Context || !Context->path || stat (Context->path, &contex_sb) != 0) - { -@@ -278,6 +281,11 @@ - tmp->magic = M_POP; - else - #endif -+#ifdef USE_NNTP -+ if ((tmp->magic == M_NNTP) || mx_is_nntp (tmp->path)) -+ tmp->magic = M_NNTP; -+ else -+#endif - if (stat (tmp->path, &sb) != 0 || sb.st_size == 0 || - (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0)) - { -@@ -294,25 +302,21 @@ - /* check to see if the folder is the currently selected folder - * before polling */ - if (!Context || !Context->path || --#if defined USE_IMAP || defined USE_POP -- (( -+ ( -+ (0 - #ifdef USE_IMAP -- tmp->magic == M_IMAP -+ || tmp->magic == M_IMAP - #endif - #ifdef USE_POP --#ifdef USE_IMAP -- || --#endif -- tmp->magic == M_POP -+ || tmp->magic == M_POP - #endif -- ) ? mutt_strcmp (tmp->path, Context->path) : -+#ifdef USE_NNTP -+ || tmp->magic == M_NNTP - #endif -- (sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino) --#if defined USE_IMAP || defined USE_POP -- ) --#endif -- ) -- -+ ) ? mutt_strcmp (tmp->path, Context->path) : -+ (sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino) -+ ) -+ ) - { - switch (tmp->magic) - { -@@ -380,6 +384,11 @@ - case M_POP: - break; - #endif -+ -+#ifdef USE_NNTP -+ case M_NNTP: -+ break; -+#endif - } - } - #ifdef BUFFY_SIZE -diff -uNr mutt-1.4.orig/commands.c mutt-1.4/commands.c ---- mutt-1.4.orig/commands.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/commands.c Sun Nov 3 21:57:20 2002 -@@ -26,6 +26,7 @@ - #include "copy.h" - #include "mx.h" - #include "pager.h" -+#include "rfc1524.h" - #include - #include - #include -@@ -791,6 +792,131 @@ - return -1; - } - -+int mutt_update_list_file (char *filename, char *section, char *key, char *line) -+{ -+ FILE *ifp; -+ FILE *ofp; -+ char buf[HUGE_STRING]; -+ char oldfile[_POSIX_PATH_MAX]; -+ char *c; -+ int ext = 0, done = 0, r = 0; -+ -+ snprintf (oldfile, sizeof(oldfile), "%s.bak", filename); -+ dprint (1, (debugfile, "Renaming %s to %s\n", filename, oldfile)); -+ -+ /* if file not exist, create it */ -+ if ((ifp = safe_fopen (filename, "a"))) -+ fclose (ifp); -+ if (_mutt_rename_file (filename, oldfile, 1)) -+ { -+ mutt_perror _("Unable to create backup file"); -+ return (-1); -+ } -+ dprint (1, (debugfile, "Opening %s\n", oldfile)); -+ if (!(ifp = safe_fopen (oldfile, "r"))) -+ { -+ mutt_perror _("Unable to open backup file for reading"); -+ return (-1); -+ } -+ dprint (1, (debugfile, "Opening %s\n", filename)); -+ if (!(ofp = fopen (filename, "w"))) -+ { -+ fclose (ifp); -+ mutt_perror _("Unable to open new file for writing"); -+ return (-1); -+ } -+ if (mx_lock_file (filename, fileno (ofp), 1, 0, 1)) -+ { -+ fclose (ofp); -+ fclose (ifp); -+ mutt_error (_("Unable to lock %s, old file saved as %s"), filename, oldfile); -+ return (-1); -+ } -+ -+ if (section) -+ { -+ while (r != EOF && !done && fgets (buf, sizeof (buf), ifp)) -+ { -+ r = fputs (buf, ofp); -+ c = buf; -+ while (*c && *c != '\n') c++; -+ c[0] = 0; /* strip EOL */ -+ if (!strncmp (buf, "#: ", 3) && !mutt_strcasecmp (buf+3, section)) -+ done++; -+ } -+ if (r != EOF && !done) -+ { -+ snprintf (buf, sizeof(buf), "#: %s\n", section); -+ r = fputs (buf, ofp); -+ } -+ done = 0; -+ } -+ -+ while (r != EOF && fgets (buf, sizeof (buf), ifp)) -+ { -+ if (ext) -+ { -+ c = buf; -+ while (*c && (*c != '\r') && (*c != '\n')) c++; -+ c--; -+ if (*c != '\\') ext = 0; -+ } -+ else if ((section && !strncmp (buf, "#: ", 3))) -+ { -+ if (!done && line) -+ { -+ fputs (line, ofp); -+ fputc ('\n', ofp); -+ } -+ r = fputs (buf, ofp); -+ done++; -+ break; -+ } -+ else if (key && !strncmp (buf, key, strlen(key)) && -+ (!*key || buf[strlen(key)] == ' ')) -+ { -+ c = buf; -+ ext = 0; -+ while (*c && (*c != '\r') && (*c != '\n')) c++; -+ c--; -+ if (*c == '\\') ext = 1; -+ if (!done && line) -+ { -+ r = fputs (line, ofp); -+ if (*key) -+ r = fputc ('\n', ofp); -+ done++; -+ } -+ } -+ else -+ { -+ r = fputs (buf, ofp); -+ } -+ } -+ -+ while (r != EOF && fgets (buf, sizeof (buf), ifp)) -+ r = fputs (buf, ofp); -+ -+ /* If there wasn't a line to replace, put it on the end of the file */ -+ if (r != EOF && !done && line) -+ { -+ fputs (line, ofp); -+ r = fputc ('\n', ofp); -+ } -+ mx_unlock_file (filename, fileno (ofp), 0); -+ fclose (ofp); -+ fclose (ifp); -+ if (r != EOF) -+ { -+ unlink (oldfile); -+ return 0; -+ } -+ unlink (filename); -+ mutt_error (_("Cannot write new %s, old file saved as %s"), filename, -+ oldfile); -+ return (-1); -+} -+ - - void mutt_version (void) - { -diff -uNr mutt-1.4.orig/complete.c mutt-1.4/complete.c ---- mutt-1.4.orig/complete.c Wed Nov 7 11:22:08 2001 -+++ mutt-1.4/complete.c Sun Nov 3 21:57:20 2002 -@@ -21,6 +21,9 @@ - #include "mailbox.h" - #include "imap.h" - #endif -+#ifdef USE_NNTP -+#include "nntp.h" -+#endif - - #include - #include -@@ -44,9 +47,71 @@ - char filepart[_POSIX_PATH_MAX]; - #ifdef USE_IMAP - char imap_path[LONG_STRING]; -+#endif - - dprint (2, (debugfile, "mutt_complete: completing %s\n", s)); - -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ { -+ LIST *l = CurrentNewsSrv->list; -+ -+ strfcpy (filepart, s, sizeof (filepart)); -+ -+ /* -+ * special case to handle when there is no filepart yet. -+ * find the first subscribed newsgroup -+ */ -+ if ((len = mutt_strlen (filepart)) == 0) -+ { -+ for (; l; l = l->next) -+ { -+ NNTP_DATA *data = (NNTP_DATA *)l->data; -+ -+ if (data && data->subscribed) -+ { -+ strfcpy (filepart, data->group, sizeof (filepart)); -+ init++; -+ l = l->next; -+ break; -+ } -+ } -+ } -+ -+ for (; l; l = l->next) -+ { -+ NNTP_DATA *data = (NNTP_DATA *)l->data; -+ -+ if (data && data->subscribed && -+ mutt_strncmp (data->group, filepart, len) == 0) -+ { -+ if (init) -+ { -+ for (i = 0; filepart[i] && data->group[i]; i++) -+ { -+ if (filepart[i] != data->group[i]) -+ { -+ filepart[i] = 0; -+ break; -+ } -+ } -+ filepart[i] = 0; -+ } -+ else -+ { -+ strfcpy (filepart, data->group, sizeof (filepart)); -+ init = 1; -+ } -+ } -+ } -+ -+ strcpy (s, filepart); -+ -+ return (init ? 0 : -1); -+ } -+#endif -+ -+#ifdef USE_IMAP - /* we can use '/' as a delimiter, imap_complete rewrites it */ - if (*s == '=' || *s == '+' || *s == '!') - { -diff -uNr mutt-1.4.orig/compose.c mutt-1.4/compose.c ---- mutt-1.4.orig/compose.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/compose.c Sun Nov 3 21:57:20 2002 -@@ -26,10 +26,15 @@ - #include "mailbox.h" - #include "sort.h" - #include "charset.h" -+#include "mx.h" - - #ifdef MIXMASTER - #include "remailer.h" - #endif -+ -+#ifdef USE_NNTP -+#include "nntp.h" -+#endif - - #include - #include -@@ -63,12 +68,18 @@ - HDR_PGPSIGINFO, - #endif - -+#ifdef USE_NNTP -+ HDR_NEWSGROUPS, -+ HDR_FOLLOWUPTO, -+ HDR_XCOMMENTTO, -+#endif -+ - - HDR_ATTACH = (HDR_FCC + 5) /* where to start printing the attachments */ - }; - --#define HDR_XOFFSET 10 --#define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */ -+#define HDR_XOFFSET 14 -+#define TITLE_FMT "%14s" /* Used for Prompts, which are ASCII */ - #define W (COLS - HDR_XOFFSET) - - static char *Prompts[] = -@@ -80,6 +91,15 @@ - "Subject: ", - "Reply-To: ", - "Fcc: " -+#ifdef HAVE_PGP -+ ,"" -+ ,"" -+#endif -+#ifdef USE_NNTP -+ ,"Newsgroups: " -+ ,"Followup-To: " -+ ,"X-Comment-To: " -+#endif - }; - - static struct mapping_t ComposeHelp[] = { -@@ -94,6 +114,19 @@ - { NULL } - }; - -+#ifdef USE_NNTP -+static struct mapping_t ComposeNewsHelp[] = { -+ { N_("Send"), OP_COMPOSE_SEND_MESSAGE }, -+ { N_("Abort"), OP_EXIT }, -+ { "Newsgroups", OP_COMPOSE_EDIT_NEWSGROUPS }, -+ { "Subj", OP_COMPOSE_EDIT_SUBJECT }, -+ { N_("Attach file"), OP_COMPOSE_ATTACH_FILE }, -+ { N_("Descrip"), OP_COMPOSE_EDIT_DESCRIPTION }, -+ { N_("Help"), OP_HELP }, -+ { NULL } -+}; -+#endif -+ - static void snd_entry (char *b, size_t blen, MUTTMENU *menu, int num) - { - mutt_FormatString (b, blen, NONULL (AttachFormat), mutt_attach_fmt, -@@ -108,7 +141,7 @@ - - static void redraw_pgp_lines (int pgp) - { -- mvaddstr (HDR_PGP, 0, " PGP: "); -+ mvaddstr (HDR_PGP, 0, " PGP: "); - if ((pgp & (PGPENCRYPT | PGPSIGN)) == (PGPENCRYPT | PGPSIGN)) - addstr (_("Sign, Encrypt")); - else if (pgp & PGPENCRYPT) -@@ -122,7 +155,7 @@ - move (HDR_PGPSIGINFO, 0); - clrtoeol (); - if (pgp & PGPSIGN) -- printw ("%s%s", _(" sign as: "), PgpSignAs ? PgpSignAs : _("")); -+ printw (" %s%s", _(" sign as: "), PgpSignAs ? PgpSignAs : _("")); - } - - static int pgp_send_menu (int bits, int *redraw) -@@ -258,9 +291,28 @@ - static void draw_envelope (HEADER *msg, char *fcc) - { - draw_envelope_addr (HDR_FROM, msg->env->from); -+#ifdef USE_NNTP -+ if (!option (OPTNEWSSEND)) -+ { -+#endif - draw_envelope_addr (HDR_TO, msg->env->to); - draw_envelope_addr (HDR_CC, msg->env->cc); - draw_envelope_addr (HDR_BCC, msg->env->bcc); -+#ifdef USE_NNTP -+ } -+ else -+ { -+ mvprintw (HDR_TO, 0, TITLE_FMT , Prompts[HDR_NEWSGROUPS - 1]); -+ mutt_paddstr (W, NONULL (msg->env->newsgroups)); -+ mvprintw (HDR_CC, 0, TITLE_FMT , Prompts[HDR_FOLLOWUPTO - 1]); -+ mutt_paddstr (W, NONULL (msg->env->followup_to)); -+ if (option (OPTXCOMMENTTO)) -+ { -+ mvprintw (HDR_BCC, 0, TITLE_FMT , Prompts[HDR_XCOMMENTTO - 1]); -+ mutt_paddstr (W, NONULL (msg->env->x_comment_to)); -+ } -+ } -+#endif - mvprintw (HDR_SUBJECT, 0, TITLE_FMT, Prompts[HDR_SUBJECT - 1]); - mutt_paddstr (W, NONULL (msg->env->subject)); - draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to); -@@ -506,6 +558,12 @@ - /* Sort, SortAux could be changed in mutt_index_menu() */ - int oldSort, oldSortAux; - struct stat st; -+#ifdef USE_NNTP -+ int news = 0; /* is it a news article ? */ -+ -+ if (option (OPTNEWSSEND)) -+ news++; -+#endif - - mutt_attach_init (msg->content); - idx = mutt_gen_attach_list (msg->content, -1, idx, &idxlen, &idxmax, 0, 1); -@@ -517,10 +575,18 @@ - menu->make_entry = snd_entry; - menu->tag = mutt_tag_attach; - menu->data = idx; -+#ifdef USE_NNTP -+ if (news) -+ menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeNewsHelp); -+ else -+#endif - menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeHelp); - - while (loop) - { -+#ifdef USE_NNTP -+ unset_option (OPTNEWS); /* for any case */ -+#endif - switch (op = mutt_menuLoop (menu)) - { - case OP_REDRAW: -@@ -532,14 +598,81 @@ - menu->redraw = edit_address_list (HDR_FROM, &msg->env->from); - break; - case OP_COMPOSE_EDIT_TO: -- menu->redraw = edit_address_list (HDR_TO, &msg->env->to); -+#ifdef USE_NNTP -+ if (!news) -+#endif -+ menu->redraw = edit_address_list (HDR_TO, &msg->env->to); - break; - case OP_COMPOSE_EDIT_BCC: -- menu->redraw = edit_address_list (HDR_BCC, &msg->env->bcc); -+#ifdef USE_NNTP -+ if (!news) -+#endif -+ menu->redraw = edit_address_list (HDR_BCC, &msg->env->bcc); - break; - case OP_COMPOSE_EDIT_CC: -- menu->redraw = edit_address_list (HDR_CC, &msg->env->cc); -+#ifdef USE_NNTP -+ if (!news) -+#endif -+ menu->redraw = edit_address_list (HDR_CC, &msg->env->cc); -+ break; -+#ifdef USE_NNTP -+ case OP_COMPOSE_EDIT_NEWSGROUPS: -+ if (news) -+ { -+ if (msg->env->newsgroups) -+ strfcpy (buf, msg->env->newsgroups, sizeof (buf)); -+ else -+ buf[0] = 0; -+ if (mutt_get_field ("Newsgroups: ", buf, sizeof (buf), 0) == 0 && buf[0]) -+ { -+ safe_free ((void **) &msg->env->newsgroups); -+ mutt_remove_trailing_ws (buf); -+ msg->env->newsgroups = safe_strdup (mutt_skip_whitespace (buf)); -+ move (HDR_TO, HDR_XOFFSET); -+ clrtoeol (); -+ if (msg->env->newsgroups) -+ printw ("%-*.*s", W, W, msg->env->newsgroups); -+ } -+ } -+ break; -+ -+ case OP_COMPOSE_EDIT_FOLLOWUP_TO: -+ if (news) -+ { -+ buf[0] = 0; -+ if (msg->env->followup_to) -+ strfcpy (buf, msg->env->followup_to, sizeof (buf)); -+ if (mutt_get_field ("Followup-To: ", buf, sizeof (buf), 0) == 0 && buf[0]) -+ { -+ safe_free ((void **) &msg->env->followup_to); -+ mutt_remove_trailing_ws (buf); -+ msg->env->followup_to = safe_strdup (mutt_skip_whitespace (buf)); -+ move (HDR_CC, HDR_XOFFSET); -+ clrtoeol(); -+ if (msg->env->followup_to) -+ printw ("%-*.*s", W, W, msg->env->followup_to); -+ } -+ } - break; -+ -+ case OP_COMPOSE_EDIT_X_COMMENT_TO: -+ if (news && option (OPTXCOMMENTTO)) -+ { -+ buf[0] = 0; -+ if (msg->env->x_comment_to) -+ strfcpy (buf, msg->env->x_comment_to, sizeof (buf)); -+ if (mutt_get_field ("X-Comment-To: ", buf, sizeof (buf), 0) == 0 && buf[0]) -+ { -+ safe_free ((void **) &msg->env->x_comment_to); -+ msg->env->x_comment_to = safe_strdup (buf); -+ move (HDR_BCC, HDR_XOFFSET); -+ clrtoeol(); -+ if (msg->env->x_comment_to) -+ printw ("%-*.*s", W, W, msg->env->x_comment_to); -+ } -+ } -+ break; -+#endif - case OP_COMPOSE_EDIT_SUBJECT: - if (msg->env->subject) - strfcpy (buf, msg->env->subject, sizeof (buf)); -@@ -695,6 +828,9 @@ - break; - - case OP_COMPOSE_ATTACH_MESSAGE: -+#ifdef USE_NNTP -+ case OP_COMPOSE_ATTACH_NEWS_MESSAGE: -+#endif - { - char *prompt; - HEADER *h; -@@ -702,7 +838,22 @@ - fname[0] = 0; - prompt = _("Open mailbox to attach message from"); - -+#ifdef USE_NNTP -+ unset_option (OPTNEWS); -+ if (op == OP_COMPOSE_ATTACH_NEWS_MESSAGE) -+ { -+ if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer))) -+ break; -+ -+ prompt = _("Open newsgroup to attach message from"); -+ set_option (OPTNEWS); -+ } -+#endif -+ - if (Context) -+#ifdef USE_NNTP -+ if ((op == OP_COMPOSE_ATTACH_MESSAGE) ^ (Context->magic == M_NNTP)) -+#endif - { - strfcpy (fname, NONULL (Context->path), sizeof (fname)); - mutt_pretty_mailbox (fname); -@@ -711,6 +862,11 @@ - if (mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, 1) == -1 || !fname[0]) - break; - -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ nntp_expand_path (fname, sizeof (fname), &CurrentNewsSrv->conn->account); -+ else -+#endif - mutt_expand_path (fname, sizeof (fname)); - #ifdef USE_IMAP - if (!mx_is_imap (fname)) -@@ -718,6 +874,9 @@ - #ifdef USE_POP - if (!mx_is_pop (fname)) - #endif -+#ifdef USE_NNTP -+ if (!mx_is_nntp (fname) && !option (OPTNEWS)) -+#endif - /* check to make sure the file exists and is readable */ - if (access (fname, R_OK) == -1) - { -diff -uNr mutt-1.4.orig/configure.in mutt-1.4/configure.in ---- mutt-1.4.orig/configure.in Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/configure.in Sun Nov 3 21:57:20 2002 -@@ -457,6 +457,14 @@ - ]) - AM_CONDITIONAL(BUILD_IMAP, test x$need_imap = xyes) - -+AC_ARG_ENABLE(nntp, [ --enable-nntp Enable NNTP support], -+[ if test x$enableval = xyes ; then -+ AC_DEFINE(USE_NNTP) -+ MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS nntp.o newsrc.o" -+ need_socket="yes" -+ fi -+]) -+ - dnl -- end socket dependencies -- - - if test "$need_socket" = "yes" -diff -uNr mutt-1.4.orig/curs_main.c mutt-1.4/curs_main.c ---- mutt-1.4.orig/curs_main.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/curs_main.c Sun Nov 3 21:57:20 2002 -@@ -18,6 +18,7 @@ - - #include "mutt.h" - #include "mutt_curses.h" -+#include "mx.h" - #include "mutt_menu.h" - #include "mailbox.h" - #include "mapping.h" -@@ -33,6 +34,10 @@ - #include "imap.h" - #endif - -+#ifdef USE_NNTP -+#include "nntp.h" -+#endif -+ - - - #ifdef HAVE_PGP -@@ -405,12 +410,27 @@ - { NULL } - }; - -+#ifdef USE_NNTP -+struct mapping_t IndexNewsHelp[] = { -+ { N_("Quit"), OP_QUIT }, -+ { N_("Del"), OP_DELETE }, -+ { N_("Undel"), OP_UNDELETE }, -+ { N_("Save"), OP_SAVE }, -+ { N_("Post"), OP_POST }, -+ { N_("Followup"), OP_FOLLOWUP }, -+ { N_("Catchup"), OP_CATCHUP }, -+ { N_("Help"), OP_HELP }, -+ { NULL } -+}; -+#endif -+ - /* This function handles the message index window as well as commands returned - * from the pager (MENU_PAGER). - */ - int mutt_index_menu (void) - { - char buf[LONG_STRING], helpstr[SHORT_STRING]; -+ int flags; - int op = OP_NULL; - int done = 0; /* controls when to exit the "event" loop */ - int i = 0, j; -@@ -432,7 +452,11 @@ - menu->make_entry = index_make_entry; - menu->color = index_color; - menu->current = ci_first_message (); -- menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN, IndexHelp); -+ menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN, -+#ifdef USE_NNTP -+ (Context && (Context->magic == M_NNTP)) ? IndexNewsHelp : -+#endif -+ IndexHelp); - - if (!attach_msg) - mutt_buffy_check(1); /* force the buffy check after we enter the folder */ -@@ -633,6 +657,9 @@ - mutt_curs_set (1); /* fallback from the pager */ - } - -+#ifdef USE_NNTP -+ unset_option (OPTNEWS); /* for any case */ -+#endif - switch (op) - { - -@@ -683,6 +710,120 @@ - menu_current_bottom (menu); - break; - -+#ifdef USE_NNTP -+ case OP_GET_MESSAGE: -+ case OP_GET_PARENT: -+ CHECK_MSGCOUNT; -+ if (Context->magic == M_NNTP) -+ { -+ HEADER *h; -+ -+ if (op == OP_GET_MESSAGE) -+ { -+ buf[0] = 0; -+ if (mutt_get_field (_("Enter Message-Id: "), buf, sizeof (buf), 0) != 0 -+ || !buf[0]) -+ break; -+ } -+ else -+ { -+ LIST *ref = CURHDR->env->references; -+ if (!ref) -+ { -+ mutt_error _("Article has no parent reference!"); -+ break; -+ } -+ strfcpy (buf, ref->data, sizeof (buf)); -+ } -+ if (!Context->id_hash) -+ Context->id_hash = mutt_make_id_hash (Context); -+ if ((h = hash_find (Context->id_hash, buf))) -+ { -+ if (h->virtual != -1) -+ { -+ menu->current = h->virtual; -+ menu->redraw = REDRAW_MOTION_RESYNCH; -+ } -+ else if (h->collapsed) -+ { -+ mutt_uncollapse_thread (Context, h); -+ mutt_set_virtual (Context); -+ menu->current = h->virtual; -+ menu->redraw = REDRAW_MOTION_RESYNCH; -+ } -+ else -+ mutt_error _("Message not visible in limited view."); -+ } -+ else -+ { -+ if (nntp_check_msgid (Context, buf) == 0) -+ { -+ h = Context->hdrs[Context->msgcount-1]; -+ mutt_sort_headers (Context, 0); -+ menu->current = h->virtual; -+ menu->redraw = REDRAW_FULL; -+ } -+ else -+ mutt_error (_("Article %s not found on server"), buf); -+ } -+ } -+ break; -+ -+ case OP_GET_CHILDREN: -+ case OP_RECONSTRUCT_THREAD: -+ CHECK_MSGCOUNT; -+ if (Context->magic == M_NNTP) -+ { -+ HEADER *h; -+ int old = CURHDR->index, i; -+ -+ if (!CURHDR->env->message_id) -+ { -+ mutt_error _("No Message-Id. Unable to perform operation"); -+ break; -+ } -+ -+ if (!Context->id_hash) -+ Context->id_hash = mutt_make_id_hash (Context); -+ strfcpy (buf, CURHDR->env->message_id, sizeof (buf)); -+ -+ if (op == OP_RECONSTRUCT_THREAD) -+ { -+ LIST *ref = CURHDR->env->references; -+ while (ref) -+ { -+ nntp_check_msgid (Context, ref->data); -+ /* the last msgid in References is the root message */ -+ if (!ref->next) -+ strfcpy (buf, ref->data, sizeof (buf)); -+ ref = ref->next; -+ } -+ } -+ mutt_message _("Check for children of message..."); -+ if (nntp_check_children (Context, buf) == 0) -+ { -+ mutt_sort_headers (Context, (op == OP_RECONSTRUCT_THREAD)); -+ h = hash_find (Context->id_hash, buf); -+ /* if the root message was retrieved, move to it */ -+ if (h) -+ menu->current = h->virtual; -+ else /* try to restore old position */ -+ for (i = 0; i < Context->msgcount; i++) -+ if (Context->hdrs[i]->index == old) -+ { -+ menu->current = Context->hdrs[i]->virtual; -+ /* As an added courtesy, recenter the menu -+ * with the current entry at the middle of the screen */ -+ menu_check_recenter (menu); -+ menu_current_middle (menu); -+ } -+ } -+ menu->redraw = REDRAW_FULL; -+ mutt_clear_error (); -+ } -+ break; -+#endif -+ - case OP_JUMP: - - CHECK_MSGCOUNT; -@@ -778,11 +919,33 @@ - break; - - case OP_MAIN_LIMIT: -+ case OP_TOGGLE_READ: - - CHECK_MSGCOUNT; - menu->oldcurrent = (Context->vcount && menu->current >= 0 && menu->current < Context->vcount) ? - CURHDR->index : -1; -- if (mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0) -+ if (op == OP_TOGGLE_READ) -+ { -+ char buf[LONG_STRING]; -+ -+ if (!Context->pattern || strncmp (Context->pattern, "!~R!~D~s", 8) != 0) -+ { -+ snprintf (buf, sizeof (buf), "!~R!~D~s%s", -+ Context->pattern ? Context->pattern : ".*"); -+ set_option (OPTHIDEREAD); -+ } -+ else -+ { -+ strfcpy (buf, Context->pattern + 8, sizeof(buf)); -+ if (!*buf || strncmp (buf, ".*", 2) == 0) -+ snprintf (buf, sizeof(buf), "~A"); -+ unset_option (OPTHIDEREAD); -+ } -+ FREE (&Context->pattern); -+ Context->pattern = safe_strdup (buf); -+ } -+ if ((op == OP_TOGGLE_READ && mutt_pattern_func (M_LIMIT, NULL) == 0) || -+ mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0) - { - if (menu->oldcurrent >= 0) - { -@@ -980,20 +1143,43 @@ - break; - - case OP_MAIN_CHANGE_FOLDER: -- -- if (attach_msg) -- op = OP_MAIN_CHANGE_FOLDER_READONLY; -- -- /* fallback to the readonly case */ -- - case OP_MAIN_CHANGE_FOLDER_READONLY: -+#ifdef USE_NNTP -+ case OP_MAIN_CHANGE_GROUP: -+ case OP_MAIN_CHANGE_GROUP_READONLY: -+#endif -+ -+ if (attach_msg || option (OPTREADONLY) || -+#ifdef USE_NNTP -+ op == OP_MAIN_CHANGE_GROUP_READONLY || -+#endif -+ op == OP_MAIN_CHANGE_FOLDER_READONLY) -+ flags = M_READONLY; -+ else -+ flags = 0; - -- if ((op == OP_MAIN_CHANGE_FOLDER_READONLY) || option (OPTREADONLY)) -+ if (flags) - cp = _("Open mailbox in read-only mode"); - else - cp = _("Open mailbox"); - - buf[0] = '\0'; -+#ifdef USE_NNTP -+ unset_option (OPTNEWS); -+ if (op == OP_MAIN_CHANGE_GROUP || -+ op == OP_MAIN_CHANGE_GROUP_READONLY) -+ { -+ set_option (OPTNEWS); -+ if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer))) -+ break; -+ if (flags) -+ cp = _("Open newsgroup in read-only mode"); -+ else -+ cp = _("Open newsgroup"); -+ nntp_buffy (buf); -+ } -+ else -+#endif - mutt_buffy (buf, sizeof (buf)); - - if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1) -@@ -1004,6 +1190,14 @@ - break; - } - -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ { -+ unset_option (OPTNEWS); -+ nntp_expand_path (buf, sizeof (buf), &CurrentNewsSrv->conn->account); -+ } -+ else -+#endif - mutt_expand_path (buf, sizeof (buf)); - if (mx_get_magic (buf) <= 0) - { -@@ -1039,15 +1233,18 @@ - - mutt_folder_hook (buf); - -- if ((Context = mx_open_mailbox (buf, -- (option (OPTREADONLY) || op == OP_MAIN_CHANGE_FOLDER_READONLY) ? -- M_READONLY : 0, NULL)) != NULL) -+ if ((Context = mx_open_mailbox (buf, flags, NULL)) != NULL) - { - menu->current = ci_first_message (); - } - else - menu->current = 0; - -+#ifdef USE_NNTP -+ /* mutt_buffy_check() must be done with mail-reader mode! */ -+ menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN, -+ (Context && (Context->magic == M_NNTP)) ? IndexNewsHelp : IndexHelp); -+#endif - mutt_clear_error (); - mutt_buffy_check(1); /* force the buffy check after we have changed - the folder */ -@@ -1422,6 +1619,15 @@ - } - #endif - -+#ifdef USE_NNTP -+ if (Context->magic == M_NNTP) -+ { -+ mutt_flushinp (); -+ mutt_error _("Can't change 'important' flag on NNTP server."); -+ break; -+ } -+#endif -+ - if (tag) - { - for (j = 0; j < Context->vcount; j++) -@@ -1767,6 +1973,17 @@ - } - break; - -+#ifdef USE_NNTP -+ case OP_CATCHUP: -+ if (Context && Context->magic == M_NNTP) -+ { -+ if (mutt_newsgroup_catchup (CurrentNewsSrv, -+ ((NNTP_DATA *)Context->data)->group)) -+ menu->redraw = REDRAW_INDEX | REDRAW_STATUS; -+ } -+ break; -+#endif -+ - case OP_DISPLAY_ADDRESS: - - CHECK_MSGCOUNT; -@@ -1801,6 +2018,15 @@ - } - #endif - -+#ifdef USE_NNTP -+ if (Context->magic == M_NNTP) -+ { -+ mutt_flushinp (); -+ mutt_error _("Can't edit message on newsserver."); -+ break; -+ } -+#endif -+ - mutt_edit_message (Context, tag ? NULL : CURHDR); - menu->redraw = REDRAW_FULL; - -@@ -1955,6 +2181,37 @@ - - menu->redraw = REDRAW_FULL; - break; -+ -+#ifdef USE_NNTP -+ case OP_POST: -+ case OP_FOLLOWUP: -+ case OP_FORWARD_TO_GROUP: -+ -+ CHECK_ATTACH; -+ if (op != OP_FOLLOWUP || !CURHDR->env->followup_to || -+ mutt_strcasecmp (CURHDR->env->followup_to, "poster") || -+ query_quadoption (OPT_FOLLOWUPTOPOSTER,_("Reply by mail as poster prefers?")) != M_YES) -+ { -+ if (Context && Context->magic == M_NNTP && -+ !((NNTP_DATA *)Context->data)->allowed && -+ query_quadoption (OPT_TOMODERATED, _("Posting to this group not allowed, may be moderated. Continue?")) != M_YES) -+ break; -+ if (op == OP_POST) -+ ci_send_message (SENDNEWS, NULL, NULL, Context, NULL); -+ else -+ { -+ CHECK_MSGCOUNT; -+ if (op == OP_FOLLOWUP) -+ ci_send_message (SENDNEWS|SENDREPLY, NULL, NULL, Context, -+ tag ? NULL : CURHDR); -+ else -+ ci_send_message (SENDNEWS|SENDFORWARD, NULL, NULL, Context, -+ tag ? NULL : CURHDR); -+ } -+ menu->redraw = REDRAW_FULL; -+ break; -+ } -+#endif - - case OP_REPLY: - -@@ -2081,6 +2338,12 @@ - if (!attach_msg) - imap_logout_all (); - #endif -+#ifdef USE_NNTP -+ /* Close all open NNTP connections */ -+ if (!attach_msg) -+ nntp_logout_all (); -+#endif -+ - - mutt_menuDestroy (&menu); - return (close); -diff -uNr mutt-1.4.orig/doc/manual.sgml mutt-1.4/doc/manual.sgml ---- mutt-1.4.orig/doc/manual.sgml Sun Nov 3 21:42:51 2002 -+++ mutt-1.4/doc/manual.sgml Sun Nov 3 21:57:20 2002 -@@ -723,6 +723,17 @@ - - See also the quad-option. - -+Reading news via NNTP

-+ -+If compiled with ``--enable-nntp'' option, Mutt can read news from newsserver -+via NNTP. You can open a newsgroup with function ``change-newsgroup'' -+(default: i). Default newsserver can be obtained from -+variable. Article headers are cached and can be loaded from file when -+newsgroup entered instead loading from newsserver. -+ - Configuration -

- -@@ -3262,6 +3273,26 @@ - editing the body of an outgoing message. - - -+ask_follow_up

-+Type: boolean -+Default: no -+ -+

-+If set, Mutt will prompt you for follow-up groups before editing -+the body of an outgoing message. -+ -+ -+ask_x_comment_to

-+Type: boolean -+Default: no -+ -+

-+If set, Mutt will prompt you for x-comment-to field before editing -+the body of an outgoing message. -+ -+ - attach_format

- Type: string -@@ -3379,6 +3410,16 @@ - bouncing messages. Postfix users may wish to unset this variable. - - -+catchup_newsgroup

-+Type: quadoption -+Default: ask-yes -+ -+

-+If this variable is set, Mutt will mark all articles in newsgroup -+as read when you quit the newsgroup (catchup newsgroup). -+ -+ - charset

- Type: string -@@ -3781,6 +3822,18 @@ - resulting in two copies of the same email for you. - - -+followup_to_poster

-+Type: quadoption -+Default: ask-yes -+ -+

-+If this variable is set and the keyword &dquot;poster&dquot; is present in -+Followup-To header, follow-up to newsgroup function is not -+permitted. The message will be mailed to the submitter of the -+message via mail. -+ -+ - force_name

- Type: boolean -@@ -3859,6 +3912,30 @@ - &dquot;Franklin&dquot; to &dquot;Franklin, Steve&dquot;. - - -+group_index_format

-+Type: string -+Default: &dquot;%4C %M%N %5s %-45.45f %d&dquot; -+ -+

-+This variable allows you to customize the newsgroup browser display to -+your personal taste. This string is similar to ``'', but -+has its own set of printf()-like sequences: -+

-+ -+ -+%C current newsgroup number -+%d description of newsgroup (becomes from server) -+%f newsgroup name -+%M - if newsgroup not allowed for direct post (moderated for example) -+%N N if newsgroup is new, u if unsubscribed, blank otherwise -+%n number of new articles in newsgroup -+%s number of unread articles in newsgroup -+%>X right justify the rest of the string and pad with character "X" -+%|X pad to the end of the line with character "X" -+ -+ -+ - hdrs

- Type: boolean -@@ -4203,6 +4280,7 @@ - %E number of messages in current thread - %f entire From: line (address + real name) - %F author name, or recipient name if the message is from you -+%g newsgroup name (if compiled with nntp support) - %i message-id of the current message - %l number of lines in the message - %L If an address in the To or CC header field matches an address -@@ -4220,6 +4298,7 @@ - %T the appropriate character from the string - %u user (login) name of the author - %v first name of the author, or the recipient if the message is from you -+%W name of organization of author (`organization:' field) - %y `x-label:' field, if present - %Y `x-label' field, if present, and (1) not at part of a thread tree, - (2) at the top of a thread, or (3) `x-label' is different from -@@ -4244,6 +4323,24 @@ - See also: ``''. - - -+inews

-+Type: path -+Default: &dquot;&dquot; -+ -+

-+If set, specifies the program and arguments used to deliver news posted -+by Mutt. Otherwise, mutt posts article using current connection to -+news server. The following printf-style sequence is understood: -+

-+ -+ -+%s newsserver name -+ -+

-+Example: set inews=&dquot;/usr/local/bin/inews -hS&dquot; -+ -+ - ispell

- Type: path -@@ -4491,6 +4588,17 @@ - be attached to the newly composed message if this option is set. - - -+mime_subject

-+Type: boolean -+Default: yes -+ -+

-+If unset, 8-bit ``subject:'' line in article header will not be -+encoded according to RFC2047 to base64. This is useful when message -+is Usenet article, because MIME for news is nonstandard feature. -+ -+ - mix_entry_format

- Type: string -@@ -4544,6 +4652,112 @@ - escape sequences see the section on ``''. - - -+news_cache_dir

-+Type: path -+Default: &dquot;˜/.mutt&dquot; -+ -+

-+This variable pointing to directory where Mutt will save cached news -+articles headers in. If unset, headers will not be saved at all -+and will be reloaded each time when you enter to newsgroup. -+ -+ -+news_server

-+Type: string -+Default: &dquot;&dquot; -+ -+

-+This variable specifies domain name or address of NNTP server. It -+defaults to the newsserver specified in the environment variable -+$NNTPSERVER or contained in the file /etc/nntpserver. You can also -+specify username and an alternative port for each newsserver, ie: -+

-+[nntp[s]://][username[:password]@]newsserver[:port] -+ -+ -+newsrc

-+Type: path -+Default: &dquot;˜/.newsrc&dquot; -+ -+

-+The file, containing info about subscribed newsgroups - names and -+indexes of read articles. The following printf-style sequence -+is understood: -+

-+ -+ -+%s newsserver name -+ -+ -+ -+nntp_context

-+Type: number -+Default: 1000 -+ -+

-+This variable defines number of articles which will be in index when -+newsgroup entered. If active newsgroup have more articles than this -+number, oldest articles will be ignored. Also controls how many -+articles headers will be saved in cache when you quit newsgroup. -+ -+ -+nntp_load_description

-+Type: boolean -+Default: yes -+ -+

-+This variable controls whether or not descriptions for each newsgroup -+must be loaded when newsgroup is added to list (first time list -+loading or new newsgroup adding). -+ -+ -+nntp_user

-+Type: string -+Default: &dquot;&dquot; -+ -+

-+Your login name on the NNTP server. If unset and NNTP server requires -+authentification, Mutt will prompt you for your account name when you -+connect to newsserver. -+ -+ -+nntp_pass

-+Type: string -+Default: &dquot;&dquot; -+ -+

-+Your password for NNTP account. -+ -+ -+nntp_poll

-+Type: number -+Default: 60 -+ -+

-+The time in seconds until any operations on newsgroup except post new -+article will cause recheck for new news. If set to 0, Mutt will -+recheck newsgroup on each operation in index (stepping, read article, -+etc.). -+ -+ -+nntp_reconnect

-+Type: quadoption -+Default: ask-yes -+ -+

-+Controls whether or not Mutt will try to reconnect to newsserver when -+connection lost. -+ -+ - pager

- Type: path -@@ -5240,6 +5454,18 @@ - string after the inclusion of a message which is being replied to. - - -+post_moderated

-+Type: quadoption -+Default: ask-yes -+ -+

-+If set to yes, Mutt will post article to newsgroup that have -+not permissions to posting (e.g. moderated). Note: if newsserver -+does not support posting to that newsgroup or totally read-only, that -+posting will not have an effect. -+ -+ - postpone

- Type: quadoption -@@ -5723,6 +5949,38 @@ - shell from /etc/passwd is used. - - -+save_unsubscribed

-+Type: boolean -+Default: no -+ -+

-+When set, info about unsubscribed newsgroups will be saved into -+``newsrc'' file and into cache. -+ -+ -+show_new_news

-+Type: boolean -+Default: yes -+ -+

-+If set, newsserver will be asked for new newsgroups on entering -+the browser. Otherwise, it will be done only once for a newsserver. -+Also controls whether or not number of new articles of subscribed -+newsgroups will be then checked. -+ -+ -+show_only_unread

-+Type: boolean -+Default: no -+ -+

-+If set, only subscribed newsgroups that contain unread articles -+will be displayed in browser. -+ -+ - sig_dashes

- Type: boolean -@@ -6189,6 +6447,17 @@ - command. - - -+use_ipv6

-+Type: boolean -+Default: yes -+ -+

-+When set, Mutt will look for IPv6 addresses of hosts it tries to -+contact. If this option is unset, Mutt will restrict itself to IPv4 addresses. -+Normally, the default should work. -+ -+ - user_agent

- Type: boolean -@@ -6283,6 +6552,16 @@ - messages to be sent. Exim users may wish to use this. - - -+x_comment_to

-+Type: boolean -+Default: no -+ -+

-+If set, Mutt will add ``X-Comment-To:'' field (that contains full -+name of original article author) to article that followuped to newsgroup. -+ -+ - Functions

- The following is the list of available functions listed by the mapping -diff -uNr mutt-1.4.orig/doc/manual.sgml.head mutt-1.4/doc/manual.sgml.head ---- mutt-1.4.orig/doc/manual.sgml.head Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/doc/manual.sgml.head Sun Nov 3 21:57:20 2002 -@@ -724,6 +724,17 @@ - - See also the quad-option. - -+Reading news via NNTP

-+ -+If compiled with ``--enable-nntp'' option, Mutt can read news from newsserver -+via NNTP. You can open a newsgroup with function ``change-newsgroup'' -+(default: i). Default newsserver can be obtained from -+variable. Article headers are cached and can be loaded from file when -+newsgroup entered instead loading from newsserver. -+ - Configuration -

- -diff -uNr mutt-1.4.orig/doc/mutt.man mutt-1.4/doc/mutt.man ---- mutt-1.4.orig/doc/mutt.man Thu Aug 30 14:55:37 2001 -+++ mutt-1.4/doc/mutt.man Sun Nov 3 21:57:20 2002 -@@ -24,8 +24,8 @@ - .SH SYNOPSIS - .PP - .B mutt --[-nRyzZ] --[-e \fIcmd\fP] [-F \fIfile\fP] [-m \fItype\fP] [-f \fIfile\fP] -+[-GnRyzZ] -+[-e \fIcmd\fP] [-F \fIfile\fP] [-g \fIserver\fP] [-m \fItype\fP] [-f \fIfile\fP] - .PP - .B mutt - [-nx] -@@ -63,6 +63,10 @@ - Specify which mailbox to load. - .IP "-F \fImuttrc\fP" - Specify an initialization file to read instead of ~/.muttrc -+.IP "-g \fIserver\fP" -+Start Mutt with a listing of subscribed newsgroups at specified newsserver. -+.IP "-G" -+Start Mutt with a listing of subscribed newsgroups. - .IP "-h" - Display help. - .IP "-H \fIdraft\fP" -diff -uNr mutt-1.4.orig/doc/muttrc.man mutt-1.4/doc/muttrc.man ---- mutt-1.4.orig/doc/muttrc.man Sun Nov 3 21:42:51 2002 -+++ mutt-1.4/doc/muttrc.man Sun Nov 3 21:57:47 2002 -@@ -257,7 +257,9 @@ - \fBpgp-hook\fP \fIpattern\fP \fIkey-id\fP - The pgp-hook command provides a method by which you can - specify the ID of the public key to be used when encrypting messages --to a certain recipient. -+to a certain recipient. You may use multiple \fBpgp-hook\fPs with the -+same \fIpattern\fP; multiple matching \fBpgp-hook\fPs result in the use -+of multiple \fIkey-id\fPs for recipient. - .PP - .nf - \fBopen-hook\fP \fIregexp\fP "\fIcommand\fP" -@@ -622,6 +624,28 @@ - - - .TP -+.B ask_follow_up -+.nf -+Type: boolean -+Default: no -+.fi -+.IP -+If set, Mutt will prompt you for follow-up groups before editing -+the body of an outgoing message. -+ -+ -+.TP -+.B ask_x_comment_to -+.nf -+Type: boolean -+Default: no -+.fi -+.IP -+If set, Mutt will prompt you for x-comment-to field before editing -+the body of an outgoing message. -+ -+ -+.TP - .B attach_format - .nf - Type: string -@@ -773,6 +797,17 @@ - - - .TP -+.B catchup_newsgroup -+.nf -+Type: quadoption -+Default: ask-yes -+.fi -+.IP -+If this variable is \fIset\fP, Mutt will mark all articles in newsgroup -+as read when you quit the newsgroup (catchup newsgroup). -+ -+ -+.TP - .B charset - .nf - Type: string -@@ -990,7 +1025,7 @@ - .B dotlock_program - .nf - Type: path --Default: \(lq/usr/local/bin/mutt_dotlock\(rq -+Default: \(lq/usr/bin/mutt_dotlock\(rq - .fi - .IP - Contains the path of the mutt_dotlock (8) binary to be used by -@@ -1161,6 +1196,16 @@ - - - .TP -+.B folder_columns -+.nf -+Type: number -+Default: 1 -+.fi -+.IP -+Specifies the number of folder columns in folder browser. -+ -+ -+.TP - .B folder_format - .nf - Type: string -@@ -1235,6 +1280,19 @@ - - - .TP -+.B followup_to_poster -+.nf -+Type: quadoption -+Default: ask-yes -+.fi -+.IP -+If this variable is \fIset\fP and the keyword \(rqposter\(rq is present in -+\fIFollowup-To\fP header, follow-up to newsgroup function is not -+permitted. The message will be mailed to the submitter of the -+message via mail. -+ -+ -+.TP - .B force_name - .nf - Type: boolean -@@ -1319,6 +1377,39 @@ - - - .TP -+.B group_index_format -+.nf -+Type: string -+Default: \(lq%4C %M%N %5s %-45.45f %d\(rq -+.fi -+.IP -+This variable allows you to customize the newsgroup browser display to -+your personal taste. This string is similar to \(lqindex_format\(rq, but -+has its own set of printf()-like sequences: -+.IP -+ -+.IP -+.DS -+.sp -+.ft CR -+.nf -+%C current newsgroup number -+%d description of newsgroup (becomes from server) -+%f newsgroup name -+%M - if newsgroup not allowed for direct post (moderated for example) -+%N N if newsgroup is new, u if unsubscribed, blank otherwise -+%n number of new articles in newsgroup -+%s number of unread articles in newsgroup -+%>X right justify the rest of the string and pad with character \(rqX\(rq -+%|X pad to the end of the line with character \(rqX\(rq -+ -+.fi -+.ec -+.ft P -+.sp -+ -+ -+.TP - .B hdrs - .nf - Type: boolean -@@ -1711,6 +1802,9 @@ - .IP %F - author name, or recipient name if the message is from you - -+.IP %g -+newsgroup name (if compiled with nntp support) -+ - .IP %i - message-id of the current message - -@@ -1756,6 +1850,9 @@ - .IP %v - first name of the author, or the recipient if the message is from you - -+.IP %W -+name of organization of author (`organization:' field) -+ - .IP %y - `x-label:' field, if present - -@@ -1798,10 +1895,37 @@ - - - .TP -+.B inews -+.nf -+Type: path -+Default: \(lq\(rq -+.fi -+.IP -+If set, specifies the program and arguments used to deliver news posted -+by Mutt. Otherwise, mutt posts article using current connection to -+news server. The following printf-style sequence is understood: -+.IP -+ -+.IP -+.DS -+.sp -+.ft CR -+.nf -+%s newsserver name -+ -+.fi -+.ec -+.ft P -+.sp -+.IP -+Example: set inews=\(rq/usr/local/bin/inews -hS\(rq -+ -+ -+.TP - .B ispell - .nf - Type: path --Default: \(lq/usr/bin/ispell\(rq -+Default: \(lqispell\(rq - .fi - .IP - How to invoke ispell (GNU's spell-checking software). -@@ -2067,6 +2191,18 @@ - - - .TP -+.B mime_subject -+.nf -+Type: boolean -+Default: yes -+.fi -+.IP -+If \fIunset\fP, 8-bit \(lqsubject:\(rq line in article header will not be -+encoded according to RFC2047 to base64. This is useful when message -+is Usenet article, because MIME for news is nonstandard feature. -+ -+ -+.TP - .B mix_entry_format - .nf - Type: string -@@ -2131,6 +2267,142 @@ - - - .TP -+.B narrow_tree -+.nf -+Type: boolean -+Default: no -+.fi -+.IP -+This variable controls the width of the thread tree when sorting by -+threads. When set, it makes the tree approximately twice as narrow, -+to allow more room the tree and message subjects. This is useful on -+narrow screens. -+ -+ -+.TP -+.B news_cache_dir -+.nf -+Type: path -+Default: \(lq~/.mutt\(rq -+.fi -+.IP -+This variable pointing to directory where Mutt will save cached news -+articles headers in. If \fIunset\fP, headers will not be saved at all -+and will be reloaded each time when you enter to newsgroup. -+ -+ -+.TP -+.B news_server -+.nf -+Type: string -+Default: \(lq\(rq -+.fi -+.IP -+This variable specifies domain name or address of NNTP server. It -+defaults to the newsserver specified in the environment variable -+$NNTPSERVER or contained in the file /etc/nntpserver. You can also -+specify username and an alternative port for each newsserver, ie: -+.IP -+[nntp[s]://][username[:password]@]newsserver[:port] -+ -+ -+.TP -+.B newsrc -+.nf -+Type: path -+Default: \(lq~/.newsrc\(rq -+.fi -+.IP -+The file, containing info about subscribed newsgroups - names and -+indexes of read articles. The following printf-style sequence -+is understood: -+.IP -+ -+.IP -+.DS -+.sp -+.ft CR -+.nf -+%s newsserver name -+ -+.fi -+.ec -+.ft P -+.sp -+ -+ -+.TP -+.B nntp_context -+.nf -+Type: number -+Default: 1000 -+.fi -+.IP -+This variable defines number of articles which will be in index when -+newsgroup entered. If active newsgroup have more articles than this -+number, oldest articles will be ignored. Also controls how many -+articles headers will be saved in cache when you quit newsgroup. -+ -+ -+.TP -+.B nntp_load_description -+.nf -+Type: boolean -+Default: yes -+.fi -+.IP -+This variable controls whether or not descriptions for each newsgroup -+must be loaded when newsgroup is added to list (first time list -+loading or new newsgroup adding). -+ -+ -+.TP -+.B nntp_user -+.nf -+Type: string -+Default: \(lq\(rq -+.fi -+.IP -+Your login name on the NNTP server. If \fIunset\fP and NNTP server requires -+authentification, Mutt will prompt you for your account name when you -+connect to newsserver. -+ -+ -+.TP -+.B nntp_pass -+.nf -+Type: string -+Default: \(lq\(rq -+.fi -+.IP -+Your password for NNTP account. -+ -+ -+.TP -+.B nntp_poll -+.nf -+Type: number -+Default: 60 -+.fi -+.IP -+The time in seconds until any operations on newsgroup except post new -+article will cause recheck for new news. If set to 0, Mutt will -+recheck newsgroup on each operation in index (stepping, read article, -+etc.). -+ -+ -+.TP -+.B nntp_reconnect -+.nf -+Type: quadoption -+Default: ask-yes -+.fi -+.IP -+Controls whether or not Mutt will try to reconnect to newsserver when -+connection lost. -+ -+ -+.TP - .B pager - .nf - Type: path -@@ -2207,6 +2479,19 @@ - - - .TP -+.B pgp_autoselectkey -+.nf -+Type: boolean -+Default: no -+.fi -+.IP -+If set, then a list of keys is not presented for selection when only -+one matching key is available. This may be useful in conjunction with -+the \fIpgp-hook\fP command (with \(lq$pgp_confirmhook\(rq set) and the -+\(lq$pgp_ignore_subkeys\(rq variable. -+ -+ -+.TP - .B pgp_autosign - .nf - Type: boolean -@@ -2234,6 +2519,19 @@ - - - .TP -+.B pgp_confirmhook -+.nf -+Type: boolean -+Default: yes -+.fi -+.IP -+If set, then you will be prompted for confirmation of keys when using -+the \fIpgp-hook\fP command. If unset, no such confirmation prompt will -+be presented. This is generally considered unsafe, especially where -+typos are concerned. -+ -+ -+.TP - .B pgp_ignore_subkeys - .nf - Type: boolean -@@ -2916,6 +3214,19 @@ - - - .TP -+.B post_moderated -+.nf -+Type: quadoption -+Default: ask-yes -+.fi -+.IP -+If set to \fIyes\fP, Mutt will post article to newsgroup that have -+not permissions to posting (e.g. moderated). \fBNote:\fP if newsserver -+does not support posting to that newsgroup or totally read-only, that -+posting will not have an effect. -+ -+ -+.TP - .B postpone - .nf - Type: quadoption -@@ -3056,6 +3367,29 @@ - - - .TP -+.B quote_empty -+.nf -+Type: boolean -+Default: yes -+.fi -+.IP -+Controls whether or not empty lines will be quoted using -+\(lqindent_string\(rq. -+ -+ -+.TP -+.B quote_quoted -+.nf -+Type: boolean -+Default: no -+.fi -+.IP -+Controls how quoted lines will be quoted. If set, one quote -+character will be added to the end of existing prefix. Otherwise, -+quoted lines will be prepended by \(lqindent_string\(rq. -+ -+ -+.TP - .B quote_regexp - .nf - Type: regular expression -@@ -3455,6 +3789,41 @@ - - - .TP -+.B save_unsubscribed -+.nf -+Type: boolean -+Default: no -+.fi -+.IP -+When \fIset\fP, info about unsubscribed newsgroups will be saved into -+\(lqnewsrc\(rq file and into cache. -+ -+ -+.TP -+.B show_new_news -+.nf -+Type: boolean -+Default: yes -+.fi -+.IP -+If \fIset\fP, newsserver will be asked for new newsgroups on entering -+the browser. Otherwise, it will be done only once for a newsserver. -+Also controls whether or not number of new articles of subscribed -+newsgroups will be then checked. -+ -+ -+.TP -+.B show_only_unread -+.nf -+Type: boolean -+Default: no -+.fi -+.IP -+If \fIset\fP, only subscribed newsgroups that contain unread articles -+will be displayed in browser. -+ -+ -+.TP - .B sig_dashes - .nf - Type: boolean -@@ -3496,6 +3865,19 @@ - - - .TP -+.B signatures_directory -+.nf -+Type: path -+Default: \(lq\(rq -+.fi -+.IP -+Specifies the path where your signatures are located. In the files of -+this directory, the signatures are separated by blank lines and/or -+sig_dashes (\(lq-- \(rq). -+You can choose between these signatures from the compose menu. -+ -+ -+.TP - .B simple_search - .nf - Type: string -@@ -3788,6 +4170,11 @@ - .IP %V - currently active limit pattern, if any * - -+.IP %[fmt] -+the current date and time. \(lqfmt\(rq is -+expanded by the system call \(lqstrftime\(rq; -+a leading bang disables locales -+ - .IP %>X - right justify the rest of the string and pad with \(rqX\(rq - -@@ -3840,6 +4227,21 @@ - - - .TP -+.B status_update -+.nf -+Type: number -+Default: -1 -+.fi -+.IP -+This variable controls, if positive, the maximum interval in seconds -+before the time in the status line is updated. It is checked at -+every key press and after a keyboard $timeout. -+If the value is zero, the status line will be updated at every check. -+If it is negative, the status time will only be updated -+if it necessary to update to the status line for some other reason. -+ -+ -+.TP - .B strict_threads - .nf - Type: boolean -@@ -3960,6 +4362,18 @@ - - - .TP -+.B trash -+.nf -+Type: path -+Default: \(lq\(rq -+.fi -+.IP -+If set, this variable specifies the path of the trash folder where the -+mails marked for deletion will be moved, instead of being irremediably -+purged. -+ -+ -+.TP - .B tunnel - .nf - Type: string -@@ -4017,6 +4431,18 @@ - - - .TP -+.B use_ipv6 -+.nf -+Type: boolean -+Default: yes -+.fi -+.IP -+When \fIset\fP, Mutt will look for IPv6 addresses of hosts it tries to -+contact. If this option is unset, Mutt will restrict itself to IPv4 addresses. -+Normally, the default should work. -+ -+ -+.TP - .B user_agent - .nf - Type: boolean -@@ -4118,6 +4544,17 @@ - messages to be sent. Exim users may wish to use this. - - -+.TP -+.B x_comment_to -+.nf -+Type: boolean -+Default: no -+.fi -+.IP -+If \fIset\fP, Mutt will add \(lqX-Comment-To:\(rq field (that contains full -+name of original article author) to article that followuped to newsgroup. -+ -+ - .\" -*-nroff-*- - .SH SEE ALSO - .PP -diff -uNr mutt-1.4.orig/functions.h mutt-1.4/functions.h ---- mutt-1.4.orig/functions.h Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/functions.h Sun Nov 3 21:57:20 2002 -@@ -69,6 +69,10 @@ - { "break-thread", OP_MAIN_BREAK_THREAD, "#" }, - { "change-folder", OP_MAIN_CHANGE_FOLDER, "c" }, - { "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" }, -+#ifdef USE_NNTP -+ { "change-newsgroup", OP_MAIN_CHANGE_GROUP, NULL }, -+ { "change-newsgroup-readonly",OP_MAIN_CHANGE_GROUP_READONLY, NULL }, -+#endif - { "collapse-thread", OP_MAIN_COLLAPSE_THREAD, "\033v" }, - { "collapse-all", OP_MAIN_COLLAPSE_ALL, "\033V" }, - { "copy-message", OP_COPY_MESSAGE, "C" }, -@@ -81,7 +85,15 @@ - { "edit", OP_EDIT_MESSAGE, "e" }, - { "edit-type", OP_EDIT_TYPE, "\005" }, - { "forward-message", OP_FORWARD_MESSAGE, "f" }, -- { "flag-message", OP_FLAG_MESSAGE, "F" }, -+#ifdef USE_NNTP -+ { "forward-to-group", OP_FORWARD_TO_GROUP, NULL }, -+ { "followup-message", OP_FOLLOWUP, NULL }, -+ { "get-children", OP_GET_CHILDREN, NULL }, -+ { "get-message", OP_GET_MESSAGE, NULL }, -+ { "get-parent", OP_GET_PARENT, NULL }, -+ { "reconstruct-thread", OP_RECONSTRUCT_THREAD, NULL }, -+#endif -+ { "flag-message", OP_FLAG_MESSAGE, "F" }, - { "group-reply", OP_GROUP_REPLY, "g" }, - #ifdef USE_POP - { "fetch-mail", OP_MAIN_FETCH_MAIL, "G" }, -@@ -108,6 +120,9 @@ - { "sort-mailbox", OP_SORT, "o" }, - { "sort-reverse", OP_SORT_REVERSE, "O" }, - { "print-message", OP_PRINT, "p" }, -+#ifdef USE_NNTP -+ { "post-message", OP_POST, NULL }, -+#endif - { "previous-thread", OP_MAIN_PREV_THREAD, "\020" }, - { "previous-subthread", OP_MAIN_PREV_SUBTHREAD, "\033p" }, - { "recall-message", OP_RECALL_MESSAGE, "R" }, -@@ -127,6 +142,10 @@ - { "show-version", OP_VERSION, "V" }, - { "set-flag", OP_MAIN_SET_FLAG, "w" }, - { "clear-flag", OP_MAIN_CLEAR_FLAG, "W" }, -+ { "toggle-read", OP_TOGGLE_READ, NULL }, -+#ifdef USE_NNTP -+ { "catchup", OP_CATCHUP, NULL }, -+#endif - { "display-message", OP_DISPLAY_MESSAGE, M_ENTER_S }, - { "sync-mailbox", OP_MAIN_SYNC_FOLDER, "$" }, - { "display-address", OP_DISPLAY_ADDRESS, "@" }, -@@ -158,6 +177,10 @@ - { "bounce-message", OP_BOUNCE_MESSAGE, "b" }, - { "change-folder", OP_MAIN_CHANGE_FOLDER, "c" }, - { "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" }, -+#ifdef USE_NNTP -+ { "change-newsgroup", OP_MAIN_CHANGE_GROUP, NULL }, -+ { "change-newsgroup-readonly",OP_MAIN_CHANGE_GROUP_READONLY, NULL }, -+#endif - { "copy-message", OP_COPY_MESSAGE, "C" }, - { "decode-copy", OP_DECODE_COPY, "\033C" }, - { "delete-message", OP_DELETE, "d" }, -@@ -165,8 +188,12 @@ - { "delete-subthread", OP_DELETE_SUBTHREAD, "\033d" }, - { "edit", OP_EDIT_MESSAGE, "e" }, - { "edit-type", OP_EDIT_TYPE, "\005" }, -+#ifdef USE_NNTP -+ { "followup-message", OP_FOLLOWUP, NULL }, -+ { "forward-to-group", OP_FORWARD_TO_GROUP, NULL }, -+#endif - { "forward-message", OP_FORWARD_MESSAGE, "f" }, -- { "flag-message", OP_FLAG_MESSAGE, "F" }, -+ { "flag-message", OP_FLAG_MESSAGE, "F" }, - { "group-reply", OP_GROUP_REPLY, "g" }, - #ifdef USE_IMAP - { "imap-fetch-mail", OP_MAIN_IMAP_FETCH, NULL }, -@@ -185,6 +212,9 @@ - { "next-thread", OP_MAIN_NEXT_THREAD, "\016" }, - { "next-subthread", OP_MAIN_NEXT_SUBTHREAD, "\033n" }, - { "print-message", OP_PRINT, "p" }, -+#ifdef USE_NNTP -+ { "post-message", OP_POST, NULL }, -+#endif - { "previous-thread", OP_MAIN_PREV_THREAD, "\020" }, - { "previous-subthread",OP_MAIN_PREV_SUBTHREAD, "\033p" }, - { "purge-message", OP_PURGE_MESSAGE, NULL }, -@@ -252,6 +282,10 @@ - { "bounce-message", OP_BOUNCE_MESSAGE, "b" }, - { "display-toggle-weed", OP_DISPLAY_HEADERS, "h" }, - { "edit-type", OP_EDIT_TYPE, "\005" }, -+#ifdef USE_NNTP -+ { "followup-message", OP_FOLLOWUP, NULL }, -+ { "forward-to-group", OP_FORWARD_TO_GROUP, NULL }, -+#endif - { "print-entry", OP_PRINT, "p" }, - { "save-entry", OP_SAVE, "s" }, - { "pipe-entry", OP_PIPE, "|" }, -@@ -282,6 +316,7 @@ - struct binding_t OpCompose[] = { - { "attach-file", OP_COMPOSE_ATTACH_FILE, "a" }, - { "attach-message", OP_COMPOSE_ATTACH_MESSAGE, "A" }, -+ { "attach-news-message",OP_COMPOSE_ATTACH_NEWS_MESSAGE,NULL }, - { "edit-bcc", OP_COMPOSE_EDIT_BCC, "b" }, - { "edit-cc", OP_COMPOSE_EDIT_CC, "c" }, - { "copy-file", OP_SAVE, "C" }, -@@ -301,6 +336,11 @@ - { "print-entry", OP_PRINT, "l" }, - { "edit-mime", OP_COMPOSE_EDIT_MIME, "m" }, - { "new-mime", OP_COMPOSE_NEW_MIME, "n" }, -+#ifdef USE_NNTP -+ { "edit-newsgroups", OP_COMPOSE_EDIT_NEWSGROUPS, NULL }, -+ { "edit-followup-to", OP_COMPOSE_EDIT_FOLLOWUP_TO, NULL }, -+ { "edit-x-comment-to",OP_COMPOSE_EDIT_X_COMMENT_TO, NULL }, -+#endif - { "postpone-message", OP_COMPOSE_POSTPONE_MESSAGE, "P" }, - { "edit-reply-to", OP_COMPOSE_EDIT_REPLY_TO, "r" }, - { "rename-file", OP_COMPOSE_RENAME_FILE, "R" }, -@@ -352,12 +392,23 @@ - { "select-new", OP_BROWSER_NEW_FILE, "N" }, - { "check-new", OP_CHECK_NEW, NULL }, - { "toggle-mailboxes", OP_TOGGLE_MAILBOXES, "\t" }, -+#ifdef USE_NNTP -+ { "reload-active", OP_LOAD_ACTIVE, NULL}, -+ { "subscribe-pattern", OP_SUBSCRIBE_PATTERN, NULL }, -+ { "unsubscribe-pattern", OP_UNSUBSCRIBE_PATTERN, NULL }, -+ { "catchup", OP_CATCHUP, NULL }, -+ { "uncatchup", OP_UNCATCHUP, NULL }, -+#endif - { "view-file", OP_BROWSER_VIEW_FILE, " " }, - #ifdef USE_IMAP - { "create-mailbox", OP_CREATE_MAILBOX, "C" }, - { "delete-mailbox", OP_DELETE_MAILBOX, "d" }, -+#endif -+#if defined USE_IMAP || defined USE_NNTP - { "subscribe", OP_BROWSER_SUBSCRIBE, "s" }, - { "unsubscribe", OP_BROWSER_UNSUBSCRIBE, "u" }, -+#endif -+#ifdef USE_IMAP - { "toggle-subscribed", OP_BROWSER_TOGGLE_LSUB, "T" }, - #endif - { NULL, 0, NULL } -diff -uNr mutt-1.4.orig/globals.h mutt-1.4/globals.h ---- mutt-1.4.orig/globals.h Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/globals.h Sun Nov 3 21:57:20 2002 -@@ -80,6 +80,15 @@ - #endif - - WHERE char *Muttrc INITVAL (NULL); -+#ifdef USE_NNTP -+WHERE char *NewsCacheDir; -+WHERE char *GroupFormat; -+WHERE char *Inews; -+WHERE char *NewsServer; -+WHERE char *NntpUser; -+WHERE char *NntpPass; -+WHERE char *NewsRc; -+#endif - WHERE char *Outbox; - WHERE char *Pager; - WHERE char *PagerFmt; -@@ -146,6 +155,11 @@ - - WHERE unsigned short Counter INITVAL (0); - -+#ifdef USE_NNTP -+WHERE short NewsPollTimeout; -+WHERE short NntpContext; -+#endif -+ - WHERE short ConnectTimeout; - WHERE short FolderColumns; - WHERE short HistSize; -diff -uNr mutt-1.4.orig/hash.c mutt-1.4/hash.c ---- mutt-1.4.orig/hash.c Mon Nov 19 11:41:32 2001 -+++ mutt-1.4/hash.c Sun Nov 3 21:57:20 2002 -@@ -47,10 +47,35 @@ - if (nelem == 0) - nelem = 2; - table->nelem = nelem; -+ table->curnelem = 0; - table->table = safe_calloc (nelem, sizeof (struct hash_elem *)); - return table; - } - -+HASH *hash_resize (HASH *ptr, int nelem) -+{ -+ HASH *table; -+ struct hash_elem *elem, *tmp; -+ int i; -+ -+ table = hash_create (nelem); -+ -+ for (i = 0; i < ptr->nelem; i++) -+ { -+ for (elem = ptr->table[i]; elem; ) -+ { -+ tmp = elem; -+ elem = elem->next; -+ hash_insert (table, tmp->key, tmp->data, 1); -+ safe_free ((void **) &tmp); -+ } -+ } -+ safe_free ((void **) &ptr->table); -+ safe_free ((void **) &ptr); -+ -+ return table; -+} -+ - /* table hash table to update - * key key to hash on - * data data to associate with `key' -@@ -70,6 +95,7 @@ - { - ptr->next = table->table[h]; - table->table[h] = ptr; -+ table->curnelem++; - } - else - { -@@ -92,6 +118,7 @@ - else - table->table[h] = ptr; - ptr->next = tmp; -+ table->curnelem++; - } - return h; - } -@@ -124,6 +151,7 @@ - *last = ptr->next; - if (destroy) destroy (ptr->data); - FREE (&ptr); -+ table->curnelem--; - return; - } - } -diff -uNr mutt-1.4.orig/hash.h mutt-1.4/hash.h ---- mutt-1.4.orig/hash.h Fri Mar 3 11:10:08 2000 -+++ mutt-1.4/hash.h Sun Nov 3 21:57:20 2002 -@@ -28,7 +28,7 @@ - - typedef struct - { -- int nelem; -+ int nelem, curnelem; - struct hash_elem **table; - } - HASH; -@@ -40,6 +40,7 @@ - HASH *hash_create (int nelem); - int hash_string (const unsigned char *s, int n); - int hash_insert (HASH * table, const char *key, void *data, int allow_dup); -+HASH *hash_resize (HASH * table, int nelem); - void *hash_find_hash (const HASH * table, int hash, const char *key); - void hash_delete_hash (HASH * table, int hash, const char *key, const void *data, - void (*destroy) (void *)); -diff -uNr mutt-1.4.orig/hdrline.c mutt-1.4/hdrline.c ---- mutt-1.4.orig/hdrline.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/hdrline.c Sun Nov 3 21:57:20 2002 -@@ -255,6 +255,7 @@ - * %E = number of messages in current thread - * %f = entire from line - * %F = like %n, unless from self -+ * %g = newsgroup name (if compiled with nntp support) - * %i = message-id - * %l = number of lines in the message - * %L = like %F, except `lists' are displayed first -@@ -268,6 +269,7 @@ - * %T = $to_chars - * %u = user (login) name of author - * %v = first name of author, unless from self -+ * %W = where user is (organization) - * %y = `x-label:' field (if present) - * %Y = `x-label:' field (if present, tree unfolded, and != parent's x-label) - * %Z = status flags */ -@@ -484,6 +486,12 @@ - optional = 0; - break; - -+#ifdef USE_NNTP -+ case 'g': -+ mutt_format_s (dest, destlen, prefix, hdr->env->newsgroups ? hdr->env->newsgroups : ""); -+ break; -+#endif -+ - case 'i': - mutt_format_s (dest, destlen, prefix, hdr->env->message_id ? hdr->env->message_id : ""); - break; -@@ -655,6 +663,13 @@ - mutt_format_s (dest, destlen, prefix, buf2); - break; - -+ case 'W': -+ if (!optional) -+ mutt_format_s (dest, destlen, prefix, hdr->env->organization ? hdr->env->organization : ""); -+ else if (!hdr->env->organization) -+ optional = 0; -+ break; -+ - case 'Z': - - ch = ' '; -diff -uNr mutt-1.4.orig/headers.c mutt-1.4/headers.c ---- mutt-1.4.orig/headers.c Mon Nov 5 22:19:33 2001 -+++ mutt-1.4/headers.c Sun Nov 3 21:57:20 2002 -@@ -115,6 +115,9 @@ - msg->env = n; n = NULL; - - if (!msg->env->in_reply_to) -+#ifdef USE_NNTP -+ if (!option (OPTNEWSSEND)) -+#endif - mutt_free_list (&msg->env->references); - - mutt_expand_aliases_env (msg->env); -diff -uNr mutt-1.4.orig/init.c mutt-1.4/init.c ---- mutt-1.4.orig/init.c Sun Nov 3 21:42:51 2002 -+++ mutt-1.4/init.c Sun Nov 3 21:57:20 2002 -@@ -1789,6 +1789,28 @@ - else - Fqdn = safe_strdup(NONULL(Hostname)); - -+#ifdef USE_NNTP -+ { -+ FILE *f; -+ char *i; -+ -+ if ((f = safe_fopen (SYSCONFDIR "/nntpserver", "r"))) -+ { -+ buffer[0] = '\0'; -+ fgets (buffer, sizeof (buffer), f); -+ p = &buffer; -+ SKIPWS (p); -+ i = p; -+ while (*i && (*i != ' ') && (*i != '\t') && (*i != '\r') && (*i != '\n')) i++; -+ *i = '\0'; -+ NewsServer = safe_strdup (p); -+ fclose (f); -+ } -+ } -+ if ((p = getenv ("NNTPSERVER"))) -+ NewsServer = safe_strdup (p); -+#endif -+ - if ((p = getenv ("MAIL"))) - Spoolfile = safe_strdup (p); - else if ((p = getenv ("MAILDIR"))) -diff -uNr mutt-1.4.orig/init.h mutt-1.4/init.h ---- mutt-1.4.orig/init.h Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/init.h Sun Nov 3 21:57:20 2002 -@@ -193,6 +193,20 @@ - ** If set, Mutt will prompt you for carbon-copy (Cc) recipients before - ** editing the body of an outgoing message. - */ -+#ifdef USE_NNTP -+ { "ask_follow_up", DT_BOOL, R_NONE, OPTASKFOLLOWUP, 0 }, -+ /* -+ ** .pp -+ ** If set, Mutt will prompt you for follow-up groups before editing -+ ** the body of an outgoing message. -+ */ -+ { "ask_x_comment_to", DT_BOOL, R_NONE, OPTASKXCOMMENTTO, 0 }, -+ /* -+ ** .pp -+ ** If set, Mutt will prompt you for x-comment-to field before editing -+ ** the body of an outgoing message. -+ */ -+#endif - { "attach_format", DT_STR, R_NONE, UL &AttachFormat, UL "%u%D%I %t%4n %T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] " }, - /* - ** .pp -@@ -273,6 +287,14 @@ - ** When this variable is set, mutt will include Delivered-To headers when - ** bouncing messages. Postfix users may wish to unset this variable. - */ -+#ifdef USE_NNTP -+ { "catchup_newsgroup", DT_QUAD, R_NONE, OPT_CATCHUP, M_ASKYES }, -+ /* -+ ** .pp -+ ** If this variable is \fIset\fP, Mutt will mark all articles in newsgroup -+ ** as read when you quit the newsgroup (catchup newsgroup). -+ */ -+#endif - { "charset", DT_STR, R_NONE, UL &Charset, UL 0 }, - /* - ** .pp -@@ -565,6 +587,16 @@ - ** subscribed list will be sent to both the list and your address, - ** resulting in two copies of the same email for you. - */ -+#ifdef USE_NNTP -+ { "followup_to_poster", DT_QUAD, R_NONE, OPT_FOLLOWUPTOPOSTER, M_ASKYES }, -+ /* -+ ** .pp -+ ** If this variable is \fIset\fP and the keyword "poster" is present in -+ ** \fIFollowup-To\fP header, follow-up to newsgroup function is not -+ ** permitted. The message will be mailed to the submitter of the -+ ** message via mail. -+ */ -+#endif - { "force_name", DT_BOOL, R_NONE, OPTFORCENAME, 0 }, - /* - ** .pp -@@ -628,6 +660,27 @@ - ** a regular expression that will match the whole name so mutt will expand - ** "Franklin" to "Franklin, Steve". - */ -+#ifdef USE_NNTP -+ { "group_index_format", DT_STR, R_BOTH, UL &GroupFormat, UL "%4C %M%N %5s %-45.45f %d" }, -+ /* -+ ** .pp -+ ** This variable allows you to customize the newsgroup browser display to -+ ** your personal taste. This string is similar to ``$index_format'', but -+ ** has its own set of printf()-like sequences: -+ ** .pp -+ ** .ts -+ ** %C current newsgroup number -+ ** %d description of newsgroup (becomes from server) -+ ** %f newsgroup name -+ ** %M - if newsgroup not allowed for direct post (moderated for example) -+ ** %N N if newsgroup is new, u if unsubscribed, blank otherwise -+ ** %n number of new articles in newsgroup -+ ** %s number of unread articles in newsgroup -+ ** %>X right justify the rest of the string and pad with character "X" -+ ** %|X pad to the end of the line with character "X" -+ ** .te -+ */ -+#endif - { "hdr_format", DT_SYN, R_NONE, UL "index_format", 0 }, - /* - */ -@@ -874,6 +927,7 @@ - ** .dt %E .dd number of messages in current thread - ** .dt %f .dd entire From: line (address + real name) - ** .dt %F .dd author name, or recipient name if the message is from you -+ ** .dt %g .dd newsgroup name (if compiled with nntp support) - ** .dt %i .dd message-id of the current message - ** .dt %l .dd number of lines in the message - ** .dt %L .dd If an address in the To or CC header field matches an address -@@ -891,6 +945,7 @@ - ** .dt %T .dd the appropriate character from the $$to_chars string - ** .dt %u .dd user (login) name of the author - ** .dt %v .dd first name of the author, or the recipient if the message is from you -+ ** .dt %W .dd name of organization of author (`organization:' field) - ** .dt %y .dd `x-label:' field, if present - ** .dt %Y .dd `x-label' field, if present, and (1) not at part of a thread tree, - ** (2) at the top of a thread, or (3) `x-label' is different from -@@ -913,6 +968,21 @@ - ** .pp - ** See also: ``$$to_chars''. - */ -+#ifdef USE_NNTP -+ { "inews", DT_PATH, R_NONE, UL &Inews, UL "" }, -+ /* -+ ** .pp -+ ** If set, specifies the program and arguments used to deliver news posted -+ ** by Mutt. Otherwise, mutt posts article using current connection to -+ ** news server. The following printf-style sequence is understood: -+ ** .pp -+ ** .ts -+ ** %s newsserver name -+ ** .te -+ ** .pp -+ ** Example: set inews="/usr/local/bin/inews -hS" -+ */ -+#endif - { "ispell", DT_PATH, R_NONE, UL &Ispell, UL ISPELL }, - /* - ** .pp -@@ -1077,6 +1147,16 @@ - ** be attached to the newly composed message if this option is set. - */ - -+#ifdef USE_NNTP -+ { "mime_subject", DT_BOOL, R_NONE, OPTMIMESUBJECT, 1 }, -+ /* -+ ** .pp -+ ** If \fIunset\fP, 8-bit ``subject:'' line in article header will not be -+ ** encoded according to RFC2047 to base64. This is useful when message -+ ** is Usenet article, because MIME for news is nonstandard feature. -+ */ -+#endif -+ - #ifdef MIXMASTER - { "mix_entry_format", DT_STR, R_NONE, UL &MixEntryFormat, UL "%4n %c %-16s %a" }, - /* -@@ -1128,6 +1208,77 @@ - ** to allow more room the tree and message subjects. This is useful on - ** narrow screens. - */ -+#ifdef USE_NNTP -+ { "news_cache_dir", DT_PATH, R_NONE, UL &NewsCacheDir, UL "~/.mutt" }, -+ /* -+ ** .pp -+ ** This variable pointing to directory where Mutt will save cached news -+ ** articles headers in. If \fIunset\fP, headers will not be saved at all -+ ** and will be reloaded each time when you enter to newsgroup. -+ */ -+ { "news_server", DT_STR, R_NONE, UL &NewsServer, 0 }, -+ /* -+ ** .pp -+ ** This variable specifies domain name or address of NNTP server. It -+ ** defaults to the newsserver specified in the environment variable -+ ** $$$NNTPSERVER or contained in the file /etc/nntpserver. You can also -+ ** specify username and an alternative port for each newsserver, ie: -+ ** .pp -+ ** [nntp[s]://][username[:password]@]newsserver[:port] -+ */ -+ { "newsrc", DT_PATH, R_NONE, UL &NewsRc, UL "~/.newsrc" }, -+ /* -+ ** .pp -+ ** The file, containing info about subscribed newsgroups - names and -+ ** indexes of read articles. The following printf-style sequence -+ ** is understood: -+ ** .pp -+ ** .ts -+ ** %s newsserver name -+ ** .te -+ */ -+ { "nntp_context", DT_NUM, R_NONE, UL &NntpContext, 1000 }, -+ /* -+ ** .pp -+ ** This variable defines number of articles which will be in index when -+ ** newsgroup entered. If active newsgroup have more articles than this -+ ** number, oldest articles will be ignored. Also controls how many -+ ** articles headers will be saved in cache when you quit newsgroup. -+ */ -+ { "nntp_load_description", DT_BOOL, R_NONE, OPTLOADDESC, 1 }, -+ /* -+ ** .pp -+ ** This variable controls whether or not descriptions for each newsgroup -+ ** must be loaded when newsgroup is added to list (first time list -+ ** loading or new newsgroup adding). -+ */ -+ { "nntp_user", DT_STR, R_NONE, UL &NntpUser, UL "" }, -+ /* -+ ** .pp -+ ** Your login name on the NNTP server. If \fIunset\fP and NNTP server requires -+ ** authentification, Mutt will prompt you for your account name when you -+ ** connect to newsserver. -+ */ -+ { "nntp_pass", DT_STR, R_NONE, UL &NntpPass, UL "" }, -+ /* -+ ** .pp -+ ** Your password for NNTP account. -+ */ -+ { "nntp_poll", DT_NUM, R_NONE, UL &NewsPollTimeout, 60 }, -+ /* -+ ** .pp -+ ** The time in seconds until any operations on newsgroup except post new -+ ** article will cause recheck for new news. If set to 0, Mutt will -+ ** recheck newsgroup on each operation in index (stepping, read article, -+ ** etc.). -+ */ -+ { "nntp_reconnect", DT_QUAD, R_NONE, OPT_NNTPRECONNECT, M_ASKYES }, -+ /* -+ ** .pp -+ ** Controls whether or not Mutt will try to reconnect to newsserver when -+ ** connection lost. -+ */ -+#endif - { "pager", DT_PATH, R_NONE, UL &Pager, UL "builtin" }, - /* - ** .pp -@@ -1633,6 +1784,16 @@ - { "post_indent_str", DT_SYN, R_NONE, UL "post_indent_string", 0 }, - /* - */ -+#ifdef USE_NNTP -+ { "post_moderated", DT_QUAD, R_NONE, OPT_TOMODERATED, M_ASKYES }, -+ /* -+ ** .pp -+ ** If set to \fIyes\fP, Mutt will post article to newsgroup that have -+ ** not permissions to posting (e.g. moderated). \fBNote:\fP if newsserver -+ ** does not support posting to that newsgroup or totally read-only, that -+ ** posting will not have an effect. -+ */ -+#endif - { "postpone", DT_QUAD, R_NONE, OPT_POSTPONE, M_ASKYES }, - /* - ** .pp -@@ -1991,6 +2152,28 @@ - ** Command to use when spawning a subshell. By default, the user's login - ** shell from /etc/passwd is used. - */ -+#ifdef USE_NNTP -+ { "save_unsubscribed",DT_BOOL, R_NONE, OPTSAVEUNSUB, 0 }, -+ /* -+ ** .pp -+ ** When \fIset\fP, info about unsubscribed newsgroups will be saved into -+ ** ``newsrc'' file and into cache. -+ */ -+ { "show_new_news", DT_BOOL, R_NONE, OPTSHOWNEWNEWS, 1 }, -+ /* -+ ** .pp -+ ** If \fIset\fP, newsserver will be asked for new newsgroups on entering -+ ** the browser. Otherwise, it will be done only once for a newsserver. -+ ** Also controls whether or not number of new articles of subscribed -+ ** newsgroups will be then checked. -+ */ -+ { "show_only_unread", DT_BOOL, R_NONE, OPTSHOWONLYUNREAD, 0 }, -+ /* -+ ** .pp -+ ** If \fIset\fP, only subscribed newsgroups that contain unread articles -+ ** will be displayed in browser. -+ */ -+#endif - { "sig_dashes", DT_BOOL, R_NONE, OPTSIGDASHES, 1 }, - /* - ** .pp -@@ -2437,6 +2620,14 @@ - ** Controls whether mutt writes out the Bcc header when preparing - ** messages to be sent. Exim users may wish to use this. - */ -+#ifdef USE_NNTP -+ { "x_comment_to", DT_BOOL, R_NONE, OPTXCOMMENTTO, 0 }, -+ /* -+ ** .pp -+ ** If \fIset\fP, Mutt will add ``X-Comment-To:'' field (that contains full -+ ** name of original article author) to article that followuped to newsgroup. -+ */ -+#endif - /*--*/ - { NULL } - }; -diff -uNr mutt-1.4.orig/keymap.c mutt-1.4/keymap.c ---- mutt-1.4.orig/keymap.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/keymap.c Sun Nov 3 21:57:20 2002 -@@ -593,7 +593,6 @@ - km_bindkey ("", MENU_MAIN, OP_DISPLAY_MESSAGE); - - km_bindkey ("x", MENU_PAGER, OP_EXIT); -- km_bindkey ("i", MENU_PAGER, OP_EXIT); - km_bindkey ("", MENU_PAGER, OP_PREV_LINE); - km_bindkey ("", MENU_PAGER, OP_NEXT_PAGE); - km_bindkey ("", MENU_PAGER, OP_PREV_PAGE); -diff -uNr mutt-1.4.orig/mailbox.h mutt-1.4/mailbox.h ---- mutt-1.4.orig/mailbox.h Wed Mar 20 10:53:34 2002 -+++ mutt-1.4/mailbox.h Sun Nov 3 21:57:20 2002 -@@ -73,6 +73,9 @@ - #ifdef USE_POP - int mx_is_pop (const char *); - #endif -+#ifdef USE_NNTP -+int mx_is_nntp (const char *); -+#endif - - int mx_access (const char*, int); - -diff -uNr mutt-1.4.orig/main.c mutt-1.4/main.c ---- mutt-1.4.orig/main.c Sun Nov 3 21:42:51 2002 -+++ mutt-1.4/main.c Sun Nov 3 21:57:20 2002 -@@ -37,6 +37,10 @@ - #include - #endif - -+#ifdef USE_NNTP -+#include -+#endif -+ - static const char *ReachingUs = N_("\ - To contact the developers, please mail to .\n\ - To report a bug, please use the flea(1) utility.\n"); -@@ -97,6 +101,8 @@ - -e \tspecify a command to be executed after initialization\n\ - -f \tspecify which mailbox to read\n\ - -F \tspecify an alternate muttrc file\n\ -+ -g \tspecify a newsserver (if compiled with NNTP)\n\ -+ -G\t\tselect a newsgroup (if compiled with NNTP)\n\ - -H \tspecify a draft file to read header from\n\ - -i \tspecify a file which Mutt should include in the reply\n\ - -m \tspecify a default mailbox type\n\ -@@ -202,6 +208,12 @@ - "-USE_POP " - #endif - -+#ifdef USE_NNTP -+ "+USE_NNTP " -+#else -+ "-USE_NNTP " -+#endif -+ - #ifdef USE_IMAP - "+USE_IMAP " - #else -@@ -444,6 +456,9 @@ - #define M_NOSYSRC (1<<2) /* -n */ - #define M_RO (1<<3) /* -R */ - #define M_SELECT (1<<4) /* -y */ -+#ifdef USE_NNTP -+#define M_NEWS (1<<5) /* -g and -G */ -+#endif - - int main (int argc, char **argv) - { -@@ -489,7 +504,11 @@ - memset (Options, 0, sizeof (Options)); - memset (QuadOptions, 0, sizeof (QuadOptions)); - -+#ifdef USE_NNTP -+ while ((i = getopt (argc, argv, "a:b:F:f:c:d:e:H:s:i:hm:npRvxyg:GzZ")) != EOF) -+#else - while ((i = getopt (argc, argv, "a:b:F:f:c:d:e:H:s:i:hm:npRvxyzZ")) != EOF) -+#endif - switch (i) - { - case 'a': -@@ -571,6 +590,20 @@ - flags |= M_SELECT; - break; - -+#ifdef USE_NNTP -+ case 'g': /* Specify a newsserver */ -+ { -+ char buf[LONG_STRING]; -+ -+ snprintf (buf, sizeof (buf), "set news_server=%s", optarg); -+ commands = mutt_add_list (commands, buf); -+ } -+ -+ case 'G': /* List of newsgroups */ -+ flags |= M_SELECT | M_NEWS; -+ break; -+#endif -+ - case 'z': - flags |= M_IGNORE; - break; -@@ -802,6 +835,18 @@ - } - else if (flags & M_SELECT) - { -+#ifdef USE_NNTP -+ if (flags & M_NEWS) -+ { -+ set_option (OPTNEWS); -+ if(!(CurrentNewsSrv = mutt_select_newsserver (NewsServer))) -+ { -+ mutt_endwin (Errorbuf); -+ exit (1); -+ } -+ } -+ else -+#endif - if (!Incoming) { - mutt_endwin _("No incoming mailboxes defined."); - exit (1); -@@ -817,6 +862,15 @@ - - if (!folder[0]) - strfcpy (folder, NONULL(Spoolfile), sizeof (folder)); -+ -+#ifdef USE_NNTP -+ if (option (OPTNEWS)) -+ { -+ unset_option (OPTNEWS); -+ nntp_expand_path (folder, sizeof (folder), &CurrentNewsSrv->conn->account); -+ } -+ else -+#endif - mutt_expand_path (folder, sizeof (folder)); - - mutt_str_replace (&LastFolder, folder); -diff -uNr mutt-1.4.orig/mutt.h mutt-1.4/mutt.h ---- mutt-1.4.orig/mutt.h Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/mutt.h Sun Nov 3 21:57:20 2002 -@@ -231,6 +231,9 @@ - M_PGP_KEY, - #endif - M_XLABEL, -+#ifdef USE_NNTP -+ M_NEWSGROUPS, -+#endif - - /* Options for Mailcap lookup */ - M_EDIT, -@@ -266,6 +269,12 @@ - OPT_VERIFYSIG, /* verify PGP signatures */ - OPT_PGPTRADITIONAL, /* create old-style PGP messages */ - #endif -+#ifdef USE_NNTP -+ OPT_TOMODERATED, -+ OPT_NNTPRECONNECT, -+ OPT_CATCHUP, -+ OPT_FOLLOWUPTOPOSTER, -+#endif /* USE_NNTP */ - - #ifdef USE_SSL - OPT_SSLSTARTTLS, -@@ -302,6 +311,7 @@ - #define SENDMAILX (1<<6) - #define SENDKEY (1<<7) - #define SENDRESEND (1<<8) -+#define SENDNEWS (1<<9) - - /* flags to _mutt_select_file() */ - #define M_SEL_BUFFY (1<<0) -@@ -318,6 +328,8 @@ - OPTASCIICHARS, - OPTASKBCC, - OPTASKCC, -+ OPTASKFOLLOWUP, -+ OPTASKXCOMMENTTO, - OPTATTACHSPLIT, - OPTAUTOEDIT, - OPTAUTOTAG, -@@ -376,6 +388,9 @@ - OPTMETOO, - OPTMHPURGE, - OPTMIMEFORWDECODE, -+#ifdef USE_NNTP -+ OPTMIMESUBJECT, /* encode subject line with RFC2047 */ -+#endif - OPTNARROWTREE, - OPTPAGERSTOP, - OPTPIPEDECODE, -@@ -445,6 +460,16 @@ - OPTPGPSHOWUNUSABLE, - #endif - -+ /* news options */ -+ -+#ifdef USE_NNTP -+ OPTSHOWNEWNEWS, -+ OPTSHOWONLYUNREAD, -+ OPTSAVEUNSUB, -+ OPTLOADDESC, -+ OPTXCOMMENTTO, -+#endif /* USE_NNTP */ -+ - /* pseudo options */ - - OPTAUXSORT, /* (pseudo) using auxillary sort function */ -@@ -465,6 +490,7 @@ - OPTSORTSUBTHREADS, /* (pseudo) used when $sort_aux changes */ - OPTNEEDRESCORE, /* (pseudo) set when the `score' command is used */ - OPTATTACHMSG, /* (pseudo) used by attach-message */ -+ OPTHIDEREAD, /* (pseudo) whether or not hide read messages */ - OPTKEEPQUIET, /* (pseudo) shut up the message and refresh - * functions while we are executing an - * external program. -@@ -475,6 +501,12 @@ - OPTDONTHANDLEPGPKEYS, /* (pseudo) used to extract PGP keys */ - #endif - -+#ifdef USE_NNTP -+ OPTNEWS, /* (pseudo) used to change reader mode */ -+ OPTNEWSSEND, /* (pseudo) used to change behavior when posting */ -+ OPTNEWSCACHE, /* (pseudo) used to indicate if news cache exist */ -+#endif -+ - - - -@@ -538,6 +570,13 @@ - char *supersedes; - char *date; - char *x_label; -+ char *organization; -+#ifdef USE_NNTP -+ char *newsgroups; -+ char *xref; -+ char *followup_to; -+ char *x_comment_to; -+#endif - LIST *references; /* message references (in reverse order) */ - LIST *in_reply_to; /* in-reply-to header content */ - LIST *userhdrs; /* user defined headers */ -@@ -685,6 +724,9 @@ - ENVELOPE *env; /* envelope information */ - BODY *content; /* list of MIME parts */ - char *path; -+#ifdef USE_NNTP -+ int article_num; -+#endif - - char *tree; /* character string to print thread tree */ - struct thread *thread; -@@ -697,7 +739,7 @@ - int refno; /* message number on server */ - #endif - --#if defined USE_POP || defined USE_IMAP -+#if defined USE_POP || defined USE_IMAP || defined USE_NNTP - void *data; /* driver-specific data */ - #endif - } HEADER; -@@ -768,7 +810,7 @@ - int appended; /* how many saved messages? */ - int flagged; /* how many flagged messages */ - int msgnotreadyet; /* which msg "new" in pager, -1 if none */ --#if defined USE_POP || defined USE_IMAP -+#if defined USE_POP || defined USE_IMAP || defined USE_NNTP - void *data; /* driver specific data */ - #endif /* USE_IMAP */ - -diff -uNr mutt-1.4.orig/muttlib.c mutt-1.4/muttlib.c ---- mutt-1.4.orig/muttlib.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/muttlib.c Sun Nov 3 21:57:20 2002 -@@ -270,7 +270,7 @@ - #ifdef MIXMASTER - mutt_free_list (&(*h)->chain); - #endif --#if defined USE_POP || defined USE_IMAP -+#if defined USE_POP || defined USE_IMAP || defined USE_NNTP - safe_free ((void**) &(*h)->data); - #endif - safe_free ((void **) h); -@@ -648,6 +648,13 @@ - safe_free ((void **) &(*p)->message_id); - safe_free ((void **) &(*p)->supersedes); - safe_free ((void **) &(*p)->date); -+ safe_free ((void **) &(*p)->organization); -+#ifdef USE_NNTP -+ safe_free ((void **) &(*p)->newsgroups); -+ safe_free ((void **) &(*p)->xref); -+ safe_free ((void **) &(*p)->followup_to); -+ safe_free ((void **) &(*p)->x_comment_to); -+#endif - mutt_free_list (&(*p)->references); - mutt_free_list (&(*p)->in_reply_to); - mutt_free_list (&(*p)->userhdrs); -@@ -1143,6 +1150,14 @@ - return 0; - } - #endif -+ -+#ifdef USE_NNTP -+ if (magic == M_NNTP) -+ { -+ mutt_error _("Can't save message to newsserver."); -+ return 0; -+ } -+#endif - - if (stat (s, st) != -1) - { -diff -uNr mutt-1.4.orig/mx.c mutt-1.4/mx.c ---- mutt-1.4.orig/mx.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/mx.c Sun Nov 3 21:57:20 2002 -@@ -42,6 +42,10 @@ - #include "pop.h" - #endif - -+#ifdef USE_NNTP -+#include "nntp.h" -+#endif -+ - #ifdef BUFFY_SIZE - #include "buffy.h" - #endif -@@ -354,6 +358,22 @@ - } - #endif - -+#ifdef USE_NNTP -+int mx_is_nntp (const char *p) -+{ -+ url_scheme_t scheme; -+ -+ if (!p) -+ return 0; -+ -+ scheme = url_check_scheme (p); -+ if (scheme == U_NNTP || scheme == U_NNTPS) -+ return 1; -+ -+ return 0; -+} -+#endif -+ - int mx_get_magic (const char *path) - { - struct stat st; -@@ -371,6 +391,11 @@ - return M_POP; - #endif /* USE_POP */ - -+#ifdef USE_NNTP -+ if (mx_is_nntp (path)) -+ return M_NNTP; -+#endif /* USE_NNTP */ -+ - if (stat (path, &st) == -1) - { - dprint (1, (debugfile, "mx_get_magic(): unable to stat %s: %s (errno %d).\n", -@@ -721,6 +746,12 @@ - break; - #endif /* USE_POP */ - -+#ifdef USE_NNTP -+ case M_NNTP: -+ rc = nntp_open_mailbox (ctx); -+ break; -+#endif /* USE_NNTP */ -+ - default: - rc = -1; - break; -@@ -766,6 +797,10 @@ - if (ctx->magic == M_POP) - pop_close_mailbox (ctx); - #endif /* USE_POP */ -+#ifdef USE_NNTP -+ if (ctx->magic == M_NNTP) -+ nntp_fastclose_mailbox (ctx); -+#endif /* USE_NNTP */ - if (ctx->id_hash) - hash_destroy (&ctx->id_hash, NULL); - mutt_clear_threads (ctx); -@@ -823,6 +858,12 @@ - rc = pop_sync_mailbox (ctx, index_hint); - break; - #endif /* USE_POP */ -+ -+#ifdef USE_NNTP -+ case M_NNTP: -+ rc = nntp_sync_mailbox (ctx); -+ break; -+#endif /* USE_NNTP */ - } - - #if 0 -@@ -899,6 +940,16 @@ - - ctx->closing = 1; - -+#ifdef USE_NNTP -+ if (ctx->magic == M_NNTP) -+ { -+ int ret; -+ -+ ret = nntp_close_mailbox (ctx); -+ mx_fastclose_mailbox (ctx); -+ return ret; -+ } -+#endif - if (ctx->readonly || ctx->dontwrite) - { - /* mailbox is readonly or we don't want to write */ -@@ -1460,6 +1511,11 @@ - case M_POP: - return (pop_check_mailbox (ctx, index_hint)); - #endif /* USE_POP */ -+ -+#ifdef USE_NNTP -+ case M_NNTP: -+ return (nntp_check_mailbox (ctx)); -+#endif /* USE_NNTP */ - } - } - -@@ -1520,6 +1576,15 @@ - } - #endif /* USE_POP */ - -+#ifdef USE_NNTP -+ case M_NNTP: -+ { -+ if (nntp_fetch_message (msg, ctx, msgno) != 0) -+ FREE (&msg); -+ break; -+ } -+#endif /* USE_NNTP */ -+ - default: - dprint (1, (debugfile, "mx_open_message(): function not implemented for mailbox type %d.\n", ctx->magic)); - FREE (&msg); -@@ -1608,6 +1673,9 @@ - #ifdef USE_POP - || (*msg)->magic == M_POP - #endif -+#ifdef USE_NNTP -+ || (*msg)->magic == M_NNTP -+#endif - ) - { - r = safe_fclose (&(*msg)->fp); -diff -uNr mutt-1.4.orig/mx.h mutt-1.4/mx.h ---- mutt-1.4.orig/mx.h Sun Nov 3 21:42:51 2002 -+++ mutt-1.4/mx.h Sun Nov 3 21:57:20 2002 -@@ -44,6 +44,9 @@ - #ifdef USE_COMPRESSED - , M_COMPRESSED - #endif -+#ifdef USE_NNTP -+ , M_NNTP -+#endif - }; - - WHERE short DefaultMagic INITVAL (M_MBOX); -diff -uNr mutt-1.4.orig/newsrc.c mutt-1.4/newsrc.c ---- mutt-1.4.orig/newsrc.c Thu Jan 1 01:00:00 1970 -+++ mutt-1.4/newsrc.c Sun Nov 3 21:57:20 2002 -@@ -0,0 +1,1042 @@ -+/* -+ * Copyright (C) 1998 Brandon Long -+ * Copyright (C) 1999 Andrej Gritsenko -+ * Copyright (C) 2000-2001 Vsevolod Volkov -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include "mutt.h" -+#include "mutt_curses.h" -+#include "sort.h" -+#include "mx.h" -+#include "mime.h" -+#include "mailbox.h" -+#include "nntp.h" -+#include "rfc822.h" -+#include "rfc1524.h" -+#include "rfc2047.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+void nntp_add_to_list (NNTP_SERVER *s, NNTP_DATA *d) -+{ -+ LIST *l; -+ -+ if (!s || !d) -+ return; -+ -+ l = safe_calloc (1, sizeof (LIST)); -+ if (s->list) -+ s->tail->next = l; -+ else -+ s->list = l; -+ s->tail = l; -+ l->data = (void *) d; -+} -+ -+static int nntp_parse_newsrc_line (NNTP_SERVER *news, char *line) -+{ -+ NNTP_DATA *data; -+ char group[LONG_STRING]; -+ int x = 1; -+ char *p = line, *b, *h; -+ size_t len; -+ -+ while (*p) -+ { -+ if (*p++ == ',') -+ x++; -+ } -+ -+ p = line; -+ while (*p && (*p != ':' && *p != '!')) p++; -+ if (!*p) -+ return -1; -+ len = p + 1 - line; -+ if (len > sizeof (group)) -+ len = sizeof (group); -+ strfcpy (group, line, len); -+ if ((data = (NNTP_DATA *)hash_find (news->newsgroups, group)) == NULL) -+ { -+ data = (NNTP_DATA *) safe_calloc (1, sizeof (NNTP_DATA) + strlen (group) + 1); -+ data->group = (char *) data + sizeof (NNTP_DATA); -+ strcpy (data->group, group); -+ data->nserv = news; -+ data->deleted = 1; -+ if (news->newsgroups->nelem < news->newsgroups->curnelem * 2) -+ news->newsgroups = hash_resize (news->newsgroups, news->newsgroups->nelem * 2); -+ hash_insert (news->newsgroups, data->group, data, 0); -+ nntp_add_to_list (news, data); -+ } -+ else -+ FREE ((void **) &data->entries); -+ -+ data->rc = 1; -+ data->entries = safe_calloc (x*2, sizeof (NEWSRC_ENTRY)); -+ data->max = x*2; -+ -+ if (*p == ':') -+ data->subscribed = 1; -+ else -+ data->subscribed = 0; -+ -+ p++; -+ b = p; -+ x = 0; -+ while (*b) -+ { -+ while (*p && *p != ',' && *p != '\n') p++; -+ if (*p) -+ { -+ *p = '\0'; -+ p++; -+ } -+ if ((h = strchr(b, '-'))) -+ { -+ *h = '\0'; -+ h++; -+ data->entries[x].first = atoi(b); -+ data->entries[x].last = atoi(h); -+ } -+ else -+ { -+ data->entries[x].first = atoi(b); -+ data->entries[x].last = data->entries[x].first; -+ } -+ b = p; -+ if (data->entries[x].last != 0) -+ x++; -+ } -+ if (x && !data->lastMessage) -+ data->lastMessage = data->entries[x-1].last; -+ data->num = x; -+ mutt_newsgroup_stat (data); -+ dprint (2, (debugfile, "parse_line: Newsgroup %s\n", data->group)); -+ -+ return 0; -+} -+ -+static int slurp_newsrc (NNTP_SERVER *news) -+{ -+ FILE *fp; -+ char *buf; -+ struct stat sb; -+ -+ news->stat = stat (news->newsrc, &sb); -+ news->size = sb.st_size; -+ news->mtime = sb.st_mtime; -+ -+ if ((fp = safe_fopen (news->newsrc, "r")) == NULL) -+ return -1; -+ /* hmm, should we use dotlock? */ -+ if (mx_lock_file (news->newsrc, fileno (fp), 0, 0, 1)) -+ { -+ fclose (fp); -+ return -1; -+ } -+ -+ buf = safe_malloc (sb.st_size + 1); -+ while (fgets (buf, sb.st_size + 1, fp)) -+ nntp_parse_newsrc_line (news, buf); -+ FREE (&buf); -+ -+ mx_unlock_file (news->newsrc, fileno (fp), 0); -+ fclose (fp); -+ return 0; -+} -+ -+void nntp_cache_expand (char *dst, const char *src) -+{ -+ snprintf (dst, _POSIX_PATH_MAX, "%s/%s", NewsCacheDir, src); -+ mutt_expand_path (dst, _POSIX_PATH_MAX); -+} -+ -+/* Loads $news_cache_dir/.index into memory, loads newsserver data -+ * and newsgroup cache names */ -+static int nntp_parse_cacheindex (NNTP_SERVER *news) -+{ -+ struct stat st; -+ char buf[HUGE_STRING], *cp; -+ char dir[_POSIX_PATH_MAX], file[_POSIX_PATH_MAX]; -+ FILE *index; -+ NNTP_DATA *data; -+ int l, m, t; -+ -+ /* check is server name defined or not */ -+ if (!news || !news->conn || !news->conn->account.host) -+ return -1; -+ unset_option (OPTNEWSCACHE); -+ if (!NewsCacheDir || !*NewsCacheDir) -+ return 0; -+ -+ strfcpy (dir, NewsCacheDir, sizeof (dir)); -+ mutt_expand_path (dir, sizeof(dir)); -+ -+ if (lstat (dir, &st) || (st.st_mode & S_IFDIR) == 0) -+ { -+ snprintf (buf, sizeof(buf), _("Directory %s not exist. Create it?"), dir); -+ if (mutt_yesorno (buf, M_YES) != M_YES || mkdir (dir, (S_IRWXU+S_IRWXG+ -+ S_IRWXO))) -+ { -+ mutt_error _("Cache directory not created!"); -+ return -1; -+ } -+ mutt_clear_error(); -+ } -+ -+ set_option (OPTNEWSCACHE); -+ -+ FREE (&news->cache); -+ snprintf (buf, sizeof(buf), "%s/.index", dir); -+ if (!(index = safe_fopen (buf, "a+"))) -+ return 0; -+ rewind (index); -+ while (fgets (buf, sizeof(buf), index)) -+ { -+ buf[strlen(buf) - 1] = 0; /* strip ending '\n' */ -+ if (!mutt_strncmp (buf, "#: ", 3) && -+ !mutt_strcasecmp (buf+3, news->conn->account.host)) -+ break; -+ } -+ while (fgets (buf, sizeof(buf), index)) -+ { -+ cp = buf; -+ while (*cp && *cp != ' ') cp++; -+ if (!*cp) continue; -+ cp[0] = 0; -+ if (!mutt_strcmp (buf, "#:")) -+ break; -+ sscanf (cp + 1, "%s %d %d", file, &l, &m); -+ if (!mutt_strcmp (buf, "ALL")) -+ { -+ news->cache = safe_strdup (file); -+ news->newgroups_time = m; -+ } -+ else if (news->newsgroups) -+ { -+ if ((data = (NNTP_DATA *)hash_find (news->newsgroups, buf)) == NULL) -+ { -+ data = (NNTP_DATA *) safe_calloc (1, sizeof (NNTP_DATA) + strlen (buf) + 1); -+ data->group = (char *) data + sizeof (NNTP_DATA); -+ strcpy(data->group, buf); -+ data->nserv = news; -+ data->deleted = 1; -+ if (news->newsgroups->nelem < news->newsgroups->curnelem * 2) -+ news->newsgroups = hash_resize (news->newsgroups, news->newsgroups->nelem * 2); -+ hash_insert (news->newsgroups, data->group, data, 0); -+ nntp_add_to_list (news, data); -+ } -+ data->cache = safe_strdup (file); -+ t = 0; -+ if (!data->firstMessage || data->lastMessage < m) -+ t = 1; -+ if (!data->firstMessage) -+ data->firstMessage = l; -+ if (data->lastMessage < m) -+ data->lastMessage = m; -+ data->lastCached = m; -+ if (t || !data->unread) -+ mutt_newsgroup_stat (data); -+ } -+ } -+ fclose (index); -+ return 0; -+} -+ -+const char * -+nntp_format_str (char *dest, size_t destlen, char op, const char *src, -+ const char *fmt, const char *ifstring, const char *elsestring, -+ unsigned long data, format_flag flags) -+{ -+ char fn[SHORT_STRING], tmp[SHORT_STRING]; -+ -+ switch (op) -+ { -+ case 's': -+ strncpy (fn, NewsServer, sizeof(fn) - 1); -+ mutt_strlower (fn); -+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt); -+ snprintf (dest, destlen, tmp, fn); -+ break; -+ } -+ return (src); -+} -+ -+/* nntp_parse_url: given an NNPT URL, return host, port, -+ * username, password and newsgroup will recognise. */ -+int nntp_parse_url (const char *server, ACCOUNT *acct, -+ char *group, size_t group_len) -+{ -+ ciss_url_t url; -+ char *c; -+ int ret = -1; -+ -+ /* Defaults */ -+ acct->flags = 0; -+ acct->port = NNTP_PORT; -+ acct->type = M_ACCT_TYPE_NNTP; -+ -+ c = safe_strdup (server); -+ url_parse_ciss (&url, c); -+ -+ if (url.scheme == U_NNTP || url.scheme == U_NNTPS) -+ { -+ if (url.scheme == U_NNTPS) -+ { -+ acct->flags |= M_ACCT_SSL; -+ acct->port = NNTP_SSL_PORT; -+ } -+ -+ *group = '\0'; -+ if (url.path) -+ strfcpy (group, url.path, group_len); -+ -+ ret = mutt_account_fromurl (acct, &url); -+ } -+ -+ FREE (&c); -+ return ret; -+} -+ -+void nntp_expand_path (char *line, size_t len, ACCOUNT *acct) -+{ -+ ciss_url_t url; -+ -+ url.path = safe_strdup (line); -+ mutt_account_tourl (acct, &url); -+ url_ciss_tostring (&url, line, len, 0); -+ FREE (&url.path); -+} -+ -+/* -+ * Automatically loads a newsrc into memory, if necessary. -+ * Checks the size/mtime of a newsrc file, if it doesn't match, load -+ * again. Hmm, if a system has broken mtimes, this might mean the file -+ * is reloaded every time, which we'd have to fix. -+ * -+ * a newsrc file is a line per newsgroup, with the newsgroup, then a -+ * ':' denoting subscribed or '!' denoting unsubscribed, then a -+ * comma separated list of article numbers and ranges. -+ */ -+NNTP_SERVER *mutt_select_newsserver (char *server) -+{ -+ char file[_POSIX_PATH_MAX]; -+ char *buf, *p; -+ LIST *list; -+ ACCOUNT acct; -+ NNTP_SERVER *serv; -+ CONNECTION *conn; -+ -+ if (!server || !*server) -+ { -+ mutt_error _("No newsserver defined!"); -+ return NULL; -+ } -+ -+ buf = p = safe_calloc (strlen (server) + 10, sizeof (char)); -+ if (url_check_scheme (server) == U_UNKNOWN) -+ { -+ strcpy (buf, "nntp://"); -+ p = strchr (buf, '\0'); -+ } -+ strcpy (p, server); -+ -+ if ((nntp_parse_url (buf, &acct, file, sizeof (file))) < 0 || *file) -+ { -+ FREE (&buf); -+ mutt_error (_("%s is an invalid newsserver specification!"), server); -+ return NULL; -+ } -+ FREE (&buf); -+ -+ conn = mutt_conn_find (NULL, &acct); -+ if (!conn) -+ return NULL; -+ -+ mutt_FormatString (file, sizeof (file), NONULL (NewsRc), nntp_format_str, 0, 0); -+ mutt_expand_path (file, sizeof (file)); -+ -+ serv = (NNTP_SERVER *)conn->data; -+ if (serv) -+ { -+ struct stat sb; -+ -+ /* externally modified? */ -+ if (serv->stat != stat (file, &sb) || (!serv->stat && -+ (serv->size != sb.st_size || serv->mtime != sb.st_mtime))) -+ { -+ for (list = serv->list; list; list = list->next) -+ { -+ NNTP_DATA *data = (NNTP_DATA *) list->data; -+ -+ if (data) -+ { -+ data->subscribed = 0; -+ data->rc = 0; -+ data->num = 0; -+ } -+ } -+ slurp_newsrc (serv); -+ nntp_clear_cacheindex (serv); -+ } -+ -+ if (serv->status == NNTP_BYE) -+ serv->status = NNTP_NONE; -+ nntp_check_newgroups (serv, 0); -+ return serv; -+ } -+ -+ /* New newsserver */ -+ serv = safe_calloc (1, sizeof (NNTP_SERVER)); -+ serv->conn = conn; -+ serv->newsrc = safe_strdup (file); -+ serv->newsgroups = hash_create (1009); -+ slurp_newsrc (serv); /* load .newsrc */ -+ nntp_parse_cacheindex (serv); /* load .index */ -+ if (option (OPTNEWSCACHE) && serv->cache && nntp_get_cache_all (serv) >= 0) -+ nntp_check_newgroups (serv, 1); -+ else if (nntp_get_active (serv) < 0) -+ { -+ hash_destroy (&serv->newsgroups, nntp_delete_data); -+ for (list = serv->list; list; list = list->next) -+ list->data = NULL; -+ mutt_free_list (&serv->list); -+ FREE (&serv->newsrc); -+ FREE (&serv->cache); -+ FREE (&serv); -+ return NULL; -+ } -+ nntp_clear_cacheindex (serv); -+ conn->data = (void *)serv; -+ -+ return serv; -+} -+ -+/* -+ * full status flags are not supported by nntp, but we can fake some -+ * of them. This is how: -+ * Read = a read message number is in the .newsrc -+ * New = a message is new since we last read this newsgroup -+ * Old = anything else -+ * So, Read is marked as such in the newsrc, old is anything that is -+ * "skipped" in the newsrc, and new is anything not in the newsrc nor -+ * in the cache. By skipped, I mean before the last unread message -+ */ -+void nntp_get_status (CONTEXT *ctx, HEADER *h, char *group, int article) -+{ -+ NNTP_DATA *data = (NNTP_DATA *) ctx->data; -+ int x; -+ -+ if (group) -+ data = (NNTP_DATA *) hash_find (data->nserv->newsgroups, group); -+ -+ if (!data) -+ { -+#ifdef DEBUG -+ if (group) -+ dprint (3, (debugfile, "newsgroup %s not found\n", group)); -+#endif -+ return; -+ } -+ -+ for (x = 0; x < data->num; x++) -+ { -+ if ((article >= data->entries[x].first) && -+ (article <= data->entries[x].last)) -+ { -+ /* we cannot use mutt_set_flag() because mx_update_context() -+ didn't called yet */ -+ h->read = 1; -+ return; -+ } -+ } -+ /* If article was not cached yet, it is new! :) */ -+ if (!data->cache || article > data->lastCached) -+ return; -+ /* Old articles are articles which aren't read but an article after them -+ * has been cached */ -+ if (option (OPTMARKOLD)) -+ h->old = 1; -+} -+ -+void mutt_newsgroup_stat (NNTP_DATA *data) -+{ -+ int i; -+ unsigned int first, last; -+ -+ data->unread = 0; -+ if (data->lastMessage == 0 || data->firstMessage > data->lastMessage) -+ return; -+ -+ data->unread = data->lastMessage - data->firstMessage + 1; -+ for (i = 0; i < data->num; i++) -+ { -+ first = data->entries[i].first; -+ if (first < data->firstMessage) -+ first = data->firstMessage; -+ last = data->entries[i].last; -+ if (last > data->lastMessage) -+ last = data->lastMessage; -+ if (first <= last) -+ data->unread -= last - first + 1; -+ } -+} -+ -+static int puti (char *line, int num) -+{ -+ char *p, s[32]; -+ -+ for (p = s; num; ) -+ { -+ *p++ = '0' + num % 10; -+ num /= 10; -+ } -+ while (p > s) -+ *line++ = *--p, num++; -+ *line = '\0'; -+ return num; -+} -+ -+static void nntp_create_newsrc_line (NNTP_DATA *data, char **buf, char **pline, size_t *buflen) -+{ -+ char *line = *pline; -+ size_t len = *buflen - (*pline - *buf); -+ int x, i; -+ -+ if (len < LONG_STRING * 10) -+ { -+ len += *buflen; -+ *buflen *= 2; -+ line = *buf; -+ safe_realloc ((void **) buf, *buflen); -+ line = *buf + (*pline - line); -+ } -+ strcpy (line, data->group); -+ len -= strlen (line) + 1; -+ line += strlen (line); -+ *line++ = data->subscribed ? ':' : '!'; -+ *line = '\0'; -+ -+ for (x = 0; x < data->num; x++) -+ { -+ if (len < LONG_STRING) -+ { -+ len += *buflen; -+ *buflen *= 2; -+ *pline = line; -+ line = *buf; -+ safe_realloc ((void **) buf, *buflen); -+ line = *buf + (*pline - line); -+ } -+ if (x) -+ { -+ *line++ = ','; -+ len--; -+ } -+ -+#if 0 -+ if (data->entries[x].first == data->entries[x].last) -+ snprintf (line, len, "%d%n", data->entries[x].first, &i); -+ else -+ snprintf (line, len, "%d-%d%n", -+ data->entries[x].first, data->entries[x].last, &i); -+ len -= i; -+ line += i; -+#else -+ i = puti (line, data->entries[x].first); -+ line +=i; len -= i; -+ if (data->entries[x].first != data->entries[x].last) -+ { -+ *line++ = '-'; -+ len--; -+ i = puti (line, data->entries[x].last); -+ line +=i; len -= i; -+ } -+#endif -+ } -+ *line++ = '\n'; -+ *line = '\0'; -+ *pline = line; -+} -+ -+void newsrc_gen_entries (CONTEXT *ctx) -+{ -+ NNTP_DATA *data = (NNTP_DATA *)ctx->data; -+ int series, x; -+ unsigned int last = 0, first = 1; -+ int save_sort = SORT_ORDER; -+ -+ if (Sort != SORT_ORDER) -+ { -+ save_sort = Sort; -+ Sort = SORT_ORDER; -+ mutt_sort_headers (ctx, 0); -+ } -+ -+ if (!data->max) -+ { -+ data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY)); -+ data->max = 5; -+ } -+ -+ /* -+ * Set up to fake initial sequence from 1 to the article before the -+ * first article in our list -+ */ -+ data->num = 0; -+ series = 1; -+ -+ for (x = 0; x < ctx->msgcount; x++) -+ { -+ if (series) /* search for first unread */ -+ { -+ /* -+ * We don't actually check sequential order, since we mark -+ * "missing" entries as read/deleted -+ */ -+ last = ctx->hdrs[x]->article_num; -+ if (last >= data->firstMessage && !ctx->hdrs[x]->deleted && -+ !ctx->hdrs[x]->read) -+ { -+ if (data->num >= data->max) -+ { -+ data->max = data->max * 2; -+ safe_realloc ((void **)&data->entries, -+ data->max * sizeof (NEWSRC_ENTRY)); -+ } -+ data->entries[data->num].first = first; -+ data->entries[data->num].last = last - 1; -+ data->num++; -+ series = 0; -+ } -+ } -+ else /* search for first read */ -+ { -+ if (ctx->hdrs[x]->deleted || ctx->hdrs[x]->read) -+ { -+ first = last + 1; -+ series = 1; -+ } -+ last = ctx->hdrs[x]->article_num; -+ } -+ } -+ if (series && first <= data->lastLoaded) -+ { -+ if (data->num >= data->max) -+ { -+ data->max = data->max * 2; -+ safe_realloc ((void **)&data->entries, -+ data->max * sizeof (NEWSRC_ENTRY)); -+ } -+ data->entries[data->num].first = first; -+ data->entries[data->num].last = data->lastLoaded; -+ data->num++; -+ } -+ -+ if (save_sort != Sort) -+ { -+ Sort = save_sort; -+ mutt_sort_headers (ctx, 0); -+ } -+} -+ -+int mutt_newsrc_update (NNTP_SERVER *news) -+{ -+ char *buf, *line; -+ NNTP_DATA *data; -+ LIST *tmp; -+ int r = -1; -+ size_t len, llen; -+ -+ if (!news) -+ return -1; -+ llen = len = 10 * LONG_STRING; -+ line = buf = safe_calloc (1, len); -+ /* we will generate full newsrc here */ -+ for (tmp = news->list; tmp; tmp = tmp->next) -+ { -+ data = (NNTP_DATA *) tmp->data; -+ if (!data || !data->rc) -+ continue; -+ nntp_create_newsrc_line (data, &buf, &line, &llen); -+ dprint (2, (debugfile, "Added to newsrc: %s", line)); -+ line += strlen (line); -+ } -+ /* newrc being fully rewritten */ -+ if (news->newsrc && -+ (r = mutt_update_list_file (news->newsrc, NULL, "", buf)) == 0) -+ { -+ struct stat st; -+ -+ stat (news->newsrc, &st); -+ news->size = st.st_size; -+ news->mtime = st.st_mtime; -+ } -+ FREE (&buf); -+ return r; -+} -+ -+static FILE *mutt_mkname (char *s) -+{ -+ char buf[_POSIX_PATH_MAX], *pc; -+ int fd; -+ FILE *fp; -+ -+ nntp_cache_expand (buf, s); -+ if ((fp = safe_fopen (buf, "w"))) -+ return fp; -+ -+ nntp_cache_expand (buf, "cache-XXXXXX"); -+ pc = buf + strlen (buf) - 12; /* positioning to "cache-XXXXXX" */ -+ if ((fd = mkstemp (buf)) == -1) -+ return NULL; -+ strcpy (s, pc); /* generated name */ -+ return fdopen (fd, "w"); -+} -+ -+/* Updates info into .index file: ALL or about selected newsgroup */ -+static int nntp_update_cacheindex (NNTP_SERVER *serv, NNTP_DATA *data) -+{ -+ char buf[LONG_STRING], *key = "ALL"; -+ char file[_POSIX_PATH_MAX]; -+ -+ if (!serv || !serv->conn || !serv->conn->account.host) -+ return -1; -+ -+ if (data && data->group) -+ { -+ key = data->group; -+ snprintf (buf, sizeof (buf), "%s %s %d %d", key, data->cache, -+ data->firstMessage, data->lastLoaded); -+ } -+ else -+ { -+ strfcpy (file, serv->cache, sizeof (file)); -+ snprintf (buf, sizeof (buf), "ALL %s 0 %d", file, (int)serv->newgroups_time); -+ } -+ nntp_cache_expand (file, ".index"); -+ return mutt_update_list_file (file, serv->conn->account.host, key, buf); -+} -+ -+/* Remove cache files of unsubscribed newsgroups */ -+void nntp_clear_cacheindex (NNTP_SERVER *news) -+{ -+ NNTP_DATA *data; -+ LIST *tmp; -+ -+ if (option (OPTSAVEUNSUB) || !news) -+ return; -+ -+ for (tmp = news->list; tmp; tmp = tmp->next) -+ { -+ data = (NNTP_DATA *) tmp->data; -+ if (!data || data->subscribed || !data->cache) -+ continue; -+ nntp_delete_cache (data); -+ dprint (2, (debugfile, "Removed from .index: %s\n", data->group)); -+ } -+ return; -+} -+ -+int nntp_save_cache_index (NNTP_SERVER *news) -+{ -+ char buf[HUGE_STRING]; -+ char file[_POSIX_PATH_MAX]; -+ NNTP_DATA *d; -+ FILE *f; -+ LIST *l; -+ -+ if (!news || !news->newsgroups) -+ return -1; -+ if (!option (OPTNEWSCACHE)) -+ return 0; -+ -+ if (news->cache) -+ { -+ nntp_cache_expand (file, news->cache); -+ unlink (file); -+ f = safe_fopen (file, "w"); -+ } -+ else -+ { -+ strfcpy (buf, news->conn->account.host, sizeof(buf)); -+ f = mutt_mkname (buf); -+ news->cache = safe_strdup (buf); -+ nntp_cache_expand (file, buf); -+ } -+ if (!f) -+ return -1; -+ -+ for (l = news->list; l; l = l->next) -+ { -+ if ((d = (NNTP_DATA *)l->data) && !d->deleted) -+ { -+ if (d->desc) -+ snprintf (buf, sizeof(buf), "%s %d %d %c %s\n", d->group, -+ d->lastMessage, d->firstMessage, d->allowed ? 'y' : 'n', -+ d->desc); -+ else -+ snprintf (buf, sizeof(buf), "%s %d %d %c\n", d->group, -+ d->lastMessage, d->firstMessage, d->allowed ? 'y' : 'n'); -+ if (fputs (buf, f) == EOF) -+ { -+ fclose (f); -+ unlink (file); -+ return -1; -+ } -+ } -+ } -+ fclose (f); -+ -+ if (nntp_update_cacheindex (news, NULL)) -+ { -+ unlink (file); -+ return -1; -+ } -+ return 0; -+} -+ -+int nntp_save_cache_group (CONTEXT *ctx) -+{ -+ char buf[HUGE_STRING], addr[STRING]; -+ char file[_POSIX_PATH_MAX]; -+ FILE *f; -+ HEADER *h; -+ struct tm *tm; -+ int i = 0, save = SORT_ORDER; -+ int prev = 0; -+ -+ if (!option (OPTNEWSCACHE)) -+ return 0; -+ if (!ctx || !ctx->data || ctx->magic != M_NNTP) -+ return -1; -+ -+ if (((NNTP_DATA *)ctx->data)->cache) -+ { -+ nntp_cache_expand (file, ((NNTP_DATA *)ctx->data)->cache); -+ unlink (file); -+ f = safe_fopen (file, "w"); -+ } -+ else -+ { -+ snprintf (buf, sizeof(buf), "%s-%s", -+ ((NNTP_DATA *)ctx->data)->nserv->conn->account.host, -+ ((NNTP_DATA *)ctx->data)->group); -+ f = mutt_mkname (buf); -+ ((NNTP_DATA *)ctx->data)->cache = safe_strdup (buf); -+ nntp_cache_expand (file, buf); -+ } -+ if (!f) -+ return -1; -+ -+ if (Sort != SORT_ORDER) -+ { -+ save = Sort; -+ Sort = SORT_ORDER; -+ mutt_sort_headers (ctx, 0); -+ } -+ -+ /* Save only $nntp_context messages... */ -+ ((NNTP_DATA *)ctx->data)->lastCached = 0; -+ if (NntpContext && ctx->msgcount > NntpContext) -+ i = ctx->msgcount - NntpContext; -+ for (; i < ctx->msgcount; i++) -+ { -+ if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->article_num != prev) -+ { -+ h = ctx->hdrs[i]; -+ addr[0] = 0; -+ rfc822_write_address (addr, sizeof(addr), h->env->from); -+ tm = gmtime (&h->date_sent); -+ snprintf (buf, sizeof(buf), -+ "%d\t%s\t%s\t%d %s %d %02d:%02d:%02d GMT\t%s\t", -+ h->article_num, h->env->subject, addr, tm->tm_mday, -+ Months[tm->tm_mon], tm->tm_year+1900, tm->tm_hour, tm->tm_min, -+ tm->tm_sec, h->env->message_id); -+ fputs (buf, f); -+ if (h->env->references) -+ mutt_write_references (h->env->references, f); -+ snprintf (buf, sizeof(buf), "\t%ld\t%d\tXref: %s\n", h->content->length, -+ h->lines, NONULL(h->env->xref)); -+ if (fputs (buf, f) == EOF) -+ { -+ fclose (f); -+ unlink (file); -+ return -1; -+ } -+ } -+ prev = ctx->hdrs[i]->article_num; -+ } -+ -+ if (save != Sort) -+ { -+ Sort = save; -+ mutt_sort_headers (ctx, 0); -+ } -+ fclose (f); -+ -+ if (nntp_update_cacheindex (((NNTP_DATA *)ctx->data)->nserv, -+ (NNTP_DATA *)ctx->data)) -+ { -+ unlink (file); -+ return -1; -+ } -+ ((NNTP_DATA *)ctx->data)->lastCached = ((NNTP_DATA *)ctx->data)->lastLoaded; -+ return 0; -+} -+ -+void nntp_delete_cache (NNTP_DATA *data) -+{ -+ char buf[_POSIX_PATH_MAX]; -+ -+ if (!option (OPTNEWSCACHE) || !data || !data->cache || !data->nserv) -+ return; -+ -+ nntp_cache_expand (buf, data->cache); -+ unlink (buf); -+ FREE (&data->cache); -+ data->lastCached = 0; -+ nntp_cache_expand (buf, ".index"); -+ mutt_update_list_file (buf, data->nserv->conn->account.host, data->group, NULL); -+} -+ -+NNTP_DATA *mutt_newsgroup_subscribe (NNTP_SERVER *news, char *group) -+{ -+ NNTP_DATA *data; -+ -+ if (!news || !news->newsgroups || !group || !*group) -+ return NULL; -+ if (!(data = (NNTP_DATA *)hash_find (news->newsgroups, group))) -+ { -+ data = (NNTP_DATA *) safe_calloc (1, sizeof (NNTP_DATA) + strlen (group) + 1); -+ data->group = (char *) data + sizeof (NNTP_DATA); -+ strcpy (data->group, group); -+ data->nserv = news; -+ data->deleted = 1; -+ if (news->newsgroups->nelem < news->newsgroups->curnelem * 2) -+ news->newsgroups = hash_resize (news->newsgroups, news->newsgroups->nelem * 2); -+ hash_insert (news->newsgroups, data->group, data, 0); -+ nntp_add_to_list (news, data); -+ } -+ if (!data->subscribed) -+ { -+ data->subscribed = 1; -+ data->rc = 1; -+ } -+ return data; -+} -+ -+NNTP_DATA *mutt_newsgroup_unsubscribe (NNTP_SERVER *news, char *group) -+{ -+ NNTP_DATA *data; -+ -+ if (!news || !news->newsgroups || !group || !*group || -+ !(data = (NNTP_DATA *)hash_find (news->newsgroups, group))) -+ return NULL; -+ if (data->subscribed) -+ { -+ data->subscribed = 0; -+ if (!option (OPTSAVEUNSUB)) -+ data->rc = 0; -+ } -+ return data; -+} -+ -+NNTP_DATA *mutt_newsgroup_catchup (NNTP_SERVER *news, char *group) -+{ -+ NNTP_DATA *data; -+ -+ if (!news || !news->newsgroups || !group || !*group || -+ !(data = (NNTP_DATA *)hash_find (news->newsgroups, group))) -+ return NULL; -+ if (!data->max) -+ { -+ data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY)); -+ data->max = 5; -+ } -+ data->num = 1; -+ data->entries[0].first = 1; -+ data->unread = 0; -+ data->entries[0].last = data->lastMessage; -+ if (Context && Context->data == data) -+ { -+ int x; -+ -+ for (x = 0; x < Context->msgcount; x++) -+ mutt_set_flag (Context, Context->hdrs[x], M_READ, 1); -+ } -+ return data; -+} -+ -+NNTP_DATA *mutt_newsgroup_uncatchup (NNTP_SERVER *news, char *group) -+{ -+ NNTP_DATA *data; -+ -+ if (!news || !news->newsgroups || !group || !*group || -+ !(data = (NNTP_DATA *)hash_find (news->newsgroups, group))) -+ return NULL; -+ if (!data->max) -+ { -+ data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY)); -+ data->max = 5; -+ } -+ data->num = 1; -+ data->entries[0].first = 1; -+ data->entries[0].last = data->firstMessage - 1; -+ if (Context && Context->data == data) -+ { -+ int x; -+ -+ data->unread = Context->msgcount; -+ for (x = 0; x < Context->msgcount; x++) -+ mutt_set_flag (Context, Context->hdrs[x], M_READ, 0); -+ } -+ else -+ data->unread = data->lastMessage - data->entries[0].last; -+ return data; -+} -+ -+/* this routine gives the first newsgroup with new messages */ -+void nntp_buffy (char *s) -+{ -+ LIST *list; -+ -+ for (list = CurrentNewsSrv->list; list; list = list->next) -+ { -+ NNTP_DATA *data = (NNTP_DATA *) list->data; -+ -+ if (data && data->subscribed && data->unread) -+ { -+ if (Context && Context->magic == M_NNTP && -+ !mutt_strcmp (data->group, ((NNTP_DATA *) Context->data)->group)) -+ { -+ unsigned int i, unread = 0; -+ -+ for (i = 0; i < Context->msgcount; i++) -+ if (!Context->hdrs[i]->read && !Context->hdrs[i]->deleted) -+ unread++; -+ if (!unread) -+ continue; -+ } -+ strcpy (s, data->group); -+ break; -+ } -+ } -+} -diff -uNr mutt-1.4.orig/nntp.c mutt-1.4/nntp.c ---- mutt-1.4.orig/nntp.c Thu Jan 1 01:00:00 1970 -+++ mutt-1.4/nntp.c Sun Nov 3 21:57:20 2002 -@@ -0,0 +1,1526 @@ -+/* -+ * Copyright (C) 1998 Brandon Long -+ * Copyright (C) 1999 Andrej Gritsenko -+ * Copyright (C) 2000-2002 Vsevolod Volkov -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include "mutt.h" -+#include "mutt_curses.h" -+#include "sort.h" -+#include "mx.h" -+#include "mime.h" -+#include "rfc1524.h" -+#include "rfc2047.h" -+#include "mailbox.h" -+#include "nntp.h" -+ -+#ifdef HAVE_PGP -+#include "pgp.h" -+#endif -+ -+#include -+#include -+#include -+#include -+ -+static unsigned int _checked = 0; -+ -+#ifdef DEBUG -+static void nntp_error (const char *where, const char *msg) -+{ -+ dprint (1, (debugfile, "nntp_error(): unexpected response in %s: %s\n", where, msg)); -+} -+#endif /* DEBUG */ -+ -+static int nntp_connect_error (NNTP_SERVER *serv) -+{ -+ serv->status = NNTP_NONE; -+ mutt_socket_close (serv->conn); -+ mutt_error _("Server closed connection!"); -+ sleep (2); -+ return -1; -+} -+ -+static int nntp_connect_and_auth (NNTP_SERVER *serv) -+{ -+ CONNECTION *conn = serv->conn; -+ char buf[STRING]; -+ unsigned char flags = conn->account.flags; -+ -+ serv->status = NNTP_NONE; -+ -+ if (mutt_socket_open (conn) < 0) -+ return -1; -+ -+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) -+ return nntp_connect_error (serv); -+ -+ if (!mutt_strncmp ("200", buf, 3)) -+ mutt_message (_("Connected to %s. Posting ok."), conn->account.host); -+ else if (!mutt_strncmp ("201", buf, 3)) -+ mutt_message (_("Connected to %s. Posting NOT ok."), conn->account.host); -+ else -+ { -+ mutt_socket_close (conn); -+ mutt_remove_trailing_ws (buf); -+ mutt_error ("%s", buf); -+ sleep (2); -+ return -1; -+ } -+ -+ sleep (1); -+ -+ /* Tell INN to switch to mode reader if it isn't so. Ignore all -+ returned codes and messages. */ -+ mutt_socket_write (conn, "MODE READER\r\n"); -+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) -+ return nntp_connect_error (serv); -+ -+ mutt_socket_write (conn, "STAT\r\n"); -+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) -+ return nntp_connect_error (serv); -+ -+ if (!(conn->account.flags & M_ACCT_USER) && mutt_strncmp ("480", buf, 3)) -+ { -+ serv->status = NNTP_OK; -+ return 0; -+ } -+ -+ if (mutt_account_getuser (&conn->account) || !conn->account.user[0] || -+ mutt_account_getpass (&conn->account) || !conn->account.pass[0]) -+ { -+ mutt_socket_close (conn); -+ serv->status = NNTP_BYE; -+ conn->account.flags = flags; -+ return -1; -+ } -+ -+ mutt_message _("Logging in..."); -+ -+ snprintf (buf, sizeof (buf), "AUTHINFO USER %s\r\n", conn->account.user); -+ mutt_socket_write (conn, buf); -+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) -+ { -+ conn->account.flags = flags; -+ return nntp_connect_error (serv); -+ } -+ -+#ifdef DEBUG -+ /* don't print the password unless we're at the ungodly debugging level */ -+ if (debuglevel < M_SOCK_LOG_FULL) -+ dprint (M_SOCK_LOG_CMD, (debugfile, "> AUTHINFO PASS *\n")); -+#endif -+ snprintf (buf, sizeof (buf), "AUTHINFO PASS %s\r\n", conn->account.pass); -+ mutt_socket_write_d (conn, buf, M_SOCK_LOG_FULL); -+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) -+ { -+ conn->account.flags = flags; -+ return nntp_connect_error (serv); -+ } -+ -+ if (!mutt_strncmp ("281", buf, 3)) -+ { -+ serv->status = NNTP_OK; -+ return 0; -+ } -+ -+ mutt_socket_close (conn); -+ conn->account.flags = flags; -+ mutt_error _("Login failed."); -+ sleep (2); -+ return -1; -+} -+ -+static int nntp_attempt_features (NNTP_SERVER *serv) -+{ -+ char buf[LONG_STRING]; -+ CONNECTION *conn = serv->conn; -+ -+ mutt_socket_write (conn, "XOVER\r\n"); -+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) -+ return nntp_connect_error (serv); -+ if (mutt_strncmp ("500", buf, 3)) -+ serv->hasXOVER = 1; -+ -+ mutt_socket_write (conn, "XPAT\r\n"); -+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) -+ return nntp_connect_error (serv); -+ if (mutt_strncmp ("500", buf, 3)) -+ serv->hasXPAT = 1; -+ -+ mutt_socket_write (conn, "XGTITLE +\r\n"); -+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) -+ return nntp_connect_error (serv); -+ if (mutt_strncmp ("500", buf, 3)) -+ serv->hasXGTITLE = 1; -+ -+ if (!mutt_strncmp ("282", buf, 3)) -+ { -+ do -+ { -+ if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) -+ return nntp_connect_error (serv); -+ } while (!(buf[0] == '.' && buf[1] == '\0')); -+ } -+ -+ return 0; -+} -+ -+static int nntp_open_connection (NNTP_SERVER *serv) -+{ -+ if (serv->status == NNTP_OK) -+ return 0; -+ if (serv->status == NNTP_BYE) -+ return -1; -+ if (nntp_connect_and_auth (serv) < 0) -+ return -1; -+ if (nntp_attempt_features (serv) < 0) -+ return -1; -+ return 0; -+} -+ -+static int nntp_reconnect (NNTP_SERVER *serv) -+{ -+ char buf[SHORT_STRING]; -+ -+ mutt_socket_close (serv->conn); -+ -+ FOREVER -+ { -+ if (nntp_connect_and_auth (serv) == 0) -+ return 0; -+ -+ snprintf (buf, sizeof (buf), _("Connection to %s lost. Reconnect?"), -+ serv->conn->account.host); -+ if (query_quadoption (OPT_NNTPRECONNECT, buf) != M_YES) -+ { -+ serv->status = NNTP_BYE; -+ return -1; -+ } -+ } -+} -+ -+/* Send data from line[LONG_STRING] and receive answer to same line */ -+static int mutt_nntp_query (NNTP_DATA *data, char *line, size_t linelen) -+{ -+ char buf[LONG_STRING]; -+ int done = TRUE; -+ -+ if (data->nserv->status == NNTP_BYE) -+ return -1; -+ -+ do -+ { -+ if (!*line && data->group) -+ { -+ snprintf (buf, sizeof (buf), "GROUP %s\r\n", data->group); -+ mutt_socket_write (data->nserv->conn, buf); -+ } -+ else -+ mutt_socket_write (data->nserv->conn, line); -+ -+ done = TRUE; -+ if (mutt_socket_readln (buf, sizeof (buf), data->nserv->conn) < 0) -+ { -+ if (nntp_reconnect (data->nserv) < 0) -+ return -1; -+ -+ if (data->group) -+ { -+ snprintf (buf, sizeof (buf), "GROUP %s\r\n", data->group); -+ mutt_socket_write (data->nserv->conn, buf); -+ if (mutt_socket_readln (buf, sizeof (buf), data->nserv->conn) < 0) -+ return -1; -+ } -+ if (*line) done = FALSE; -+ } -+ } while (!done); -+ -+ strfcpy (line, buf, linelen); -+ return 0; -+} -+ -+/* -+ * This function calls funct(*line, *data) for each received line, -+ * funct(NULL, *data) if rewind(*data) needs, exits when fail or done. -+ * Returned codes: -+ * 0 - successful, -+ * 1 - correct but not performed (may be, have to be continued), -+ * -1 - conection lost, -+ * -2 - invalid command or execution error, -+ * -3 - error in funct(*line, *data). -+ */ -+static int mutt_nntp_fetch (NNTP_DATA *nntp_data, char *query, char *msg, -+ int (*funct) (char *, void *), void *data, int tagged) -+{ -+ char buf[LONG_STRING]; -+ char *inbuf, *p; -+ int done = FALSE; -+ int chunk, line; -+ size_t lenbuf = 0; -+ int ret; -+ -+ do -+ { -+ strfcpy (buf, query, sizeof (buf)); -+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0) -+ return -1; -+ if (buf[0] == '5') -+ return -2; -+ if (buf[0] != '2') -+ return 1; -+ -+ ret = 0; -+ line = 0; -+ inbuf = safe_malloc (sizeof (buf)); -+ -+ FOREVER -+ { -+ chunk = mutt_socket_readln_d (buf, sizeof (buf), nntp_data->nserv->conn, -+ M_SOCK_LOG_HDR); -+ if (chunk < 0) -+ break; -+ -+ p = buf; -+ if (!lenbuf && buf[0] == '.') -+ { -+ if (buf[1] == '\0') -+ { -+ done = TRUE; -+ break; -+ } -+ if (buf[1] == '.') -+ p++; -+ } -+ -+ strfcpy (inbuf + lenbuf, p, sizeof (buf)); -+ -+ if (chunk >= sizeof (buf)) -+ { -+ lenbuf += strlen (p); -+ } -+ else -+ { -+ line++; -+ if (msg && ReadInc && (line % ReadInc == 0)) { -+ if (tagged) -+ mutt_message (_("%s (tagged: %d) %d"), msg, tagged, line); -+ else -+ mutt_message ("%s %d", msg, line); -+ } -+ -+ if (ret == 0 && funct (inbuf, data) < 0) -+ ret = -3; -+ lenbuf = 0; -+ } -+ -+ safe_realloc ((void **) &inbuf, lenbuf + sizeof (buf)); -+ } -+ FREE (&inbuf); -+ funct (NULL, data); -+ } -+ while (!done); -+ return ret; -+} -+ -+static int nntp_read_tempfile (char *line, void *file) -+{ -+ FILE *f = (FILE *)file; -+ -+ if (!line) -+ rewind (f); -+ else -+ { -+ fputs (line, f); -+ if (fputc ('\n', f) == EOF) -+ return -1; -+ } -+ return 0; -+} -+ -+static void nntp_parse_xref (CONTEXT *ctx, char *group, char *xref, HEADER *h) -+{ -+ register char *p, *b; -+ register char *colon = NULL; -+ -+ b = p = xref; -+ while (*p) -+ { -+ /* skip to next word */ -+ b = p; -+ while (*b && ((*b == ' ') || (*b == '\t'))) b++; -+ p = b; -+ colon = NULL; -+ /* skip to end of word */ -+ while (*p && (*p != ' ') && (*p != '\t')) -+ { -+ if (*p == ':') -+ colon = p; -+ p++; -+ } -+ if (*p) -+ { -+ *p = '\0'; -+ p++; -+ } -+ if (colon) -+ { -+ *colon = '\0'; -+ colon++; -+ nntp_get_status (ctx, h, p, atoi(colon)); -+ if (h && h->article_num == 0 && mutt_strcmp (group, b) == 0) -+ h->article_num = atoi(colon); -+ } -+ } -+} -+ -+/* -+ * returns: -+ * 0 on success -+ * 1 if article not found -+ * -1 if read or write error on tempfile or socket -+ */ -+static int nntp_read_header (CONTEXT *ctx, const char *msgid, int article_num) -+{ -+ NNTP_DATA *nntp_data = ((NNTP_DATA *)ctx->data); -+ FILE *f; -+ char buf[LONG_STRING]; -+ char tempfile[_POSIX_PATH_MAX]; -+ int ret; -+ HEADER *h = ctx->hdrs[ctx->msgcount]; -+ -+ mutt_mktemp (tempfile); -+ if (!(f = safe_fopen (tempfile, "w+"))) -+ return -1; -+ -+ if (!msgid) -+ snprintf (buf, sizeof (buf), "HEAD %d\r\n", article_num); -+ else -+ snprintf (buf, sizeof (buf), "HEAD %s\r\n", msgid); -+ -+ ret = mutt_nntp_fetch (nntp_data, buf, NULL, nntp_read_tempfile, f, 0); -+ if (ret) -+ { -+#ifdef DEBUG -+ if (ret != -1) -+ dprint(1, (debugfile, "nntp_read_header: %s\n", buf)); -+#endif -+ fclose (f); -+ unlink (tempfile); -+ return (ret == -1 ? -1 : 1); -+ } -+ -+ h->article_num = article_num; -+ h->env = mutt_read_rfc822_header (f, h, 0, 0); -+ fclose (f); -+ unlink (tempfile); -+ -+ if (h->env->xref != NULL) -+ nntp_parse_xref (ctx, nntp_data->group, h->env->xref, h); -+ else if (h->article_num == 0 && msgid) -+ { -+ snprintf (buf, sizeof (buf), "STAT %s\r\n", msgid); -+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) == 0) -+ h->article_num = atoi (buf + 4); -+ } -+ -+ return 0; -+} -+ -+static int parse_description (char *line, void *n) -+{ -+#define news ((NNTP_SERVER *) n) -+ register char *d = line; -+ NNTP_DATA *data; -+ -+ if (!line) -+ return 0; -+ while (*d && *d != '\t' && *d != ' ') d++; -+ *d = 0; -+ d++; -+ while (*d && (*d == '\t' || *d == ' ')) d++; -+ dprint (2, (debugfile, "group: %s, desc: %s\n", line, d)); -+ if ((data = (NNTP_DATA *) hash_find (news->newsgroups, line)) != NULL && -+ mutt_strcmp (d, data->desc)) -+ { -+ FREE (&data->desc); -+ data->desc = safe_strdup (d); -+ } -+ return 0; -+#undef news -+} -+ -+static void nntp_get_desc (NNTP_DATA *data, char *mask, char *msg) -+{ -+ char buf[STRING]; -+ -+ if (!option (OPTLOADDESC) || !data || !data->nserv) -+ return; -+ -+ /* Get newsgroup description, if we can */ -+ if (data->nserv->hasXGTITLE) -+ snprintf (buf, sizeof (buf), "XGTITLE %s\r\n", mask); -+ else -+ snprintf (buf, sizeof (buf), "LIST NEWSGROUPS %s\r\n", mask); -+ if (mutt_nntp_fetch (data, buf, msg, parse_description, data->nserv, 0) != 0) -+ { -+#ifdef DEBUG -+ nntp_error ("nntp_get_desc()", buf); -+#endif -+ } -+} -+ -+/* -+ * XOVER returns a tab separated list of: -+ * id|subject|from|date|Msgid|references|bytes|lines|xref -+ * -+ * This has to duplicate some of the functionality of -+ * mutt_read_rfc822_header(), since it replaces the call to that (albeit with -+ * a limited number of headers which are "parsed" by placement in the list) -+ */ -+static int nntp_parse_xover (CONTEXT *ctx, char *buf, HEADER *hdr) -+{ -+ NNTP_DATA *nntp_data = (NNTP_DATA *) ctx->data; -+ char *p, *b; -+ int x, done = 0; -+ -+ hdr->env = mutt_new_envelope(); -+ hdr->env->newsgroups = safe_strdup (nntp_data->group); -+ hdr->content = mutt_new_body(); -+ hdr->content->type = TYPETEXT; -+ hdr->content->subtype = safe_strdup ("plain"); -+ hdr->content->encoding = ENC7BIT; -+ hdr->content->disposition = DISPINLINE; -+ hdr->content->length = -1; -+ b = p = buf; -+ -+ for (x = 0; !done && x < 9; x++) -+ { -+ /* if from file, need to skip newline character */ -+ while (*p && *p != '\n' && *p != '\t') p++; -+ if (!*p) done++; -+ *p = '\0'; -+ p++; -+ switch (x) -+ { -+ case 0: -+ -+ hdr->article_num = atoi (b); -+ nntp_get_status (ctx, hdr, NULL, hdr->article_num); -+ break; -+ case 1: -+ hdr->env->subject = safe_strdup (b); -+ /* Now we need to do the things which would normally be done in -+ * mutt_read_rfc822_header() */ -+ if (hdr->env->subject) -+ { -+ regmatch_t pmatch[1]; -+ -+ rfc2047_decode (&hdr->env->subject); -+ -+ if (regexec (ReplyRegexp.rx, hdr->env->subject, 1, pmatch, 0) == 0) -+ hdr->env->real_subj = hdr->env->subject + pmatch[0].rm_eo; -+ else -+ hdr->env->real_subj = hdr->env->subject; -+ } -+ break; -+ case 2: -+ rfc822_free_address (&hdr->env->from); -+ hdr->env->from = rfc822_parse_adrlist (hdr->env->from, b); -+ rfc2047_decode_adrlist (hdr->env->from); -+ break; -+ case 3: -+ hdr->date_sent = mutt_parse_date (b, hdr); -+ hdr->received = hdr->date_sent; -+ break; -+ case 4: -+ FREE (&hdr->env->message_id); -+ hdr->env->message_id = safe_strdup (b); -+ break; -+ case 5: -+ mutt_free_list (&hdr->env->references); -+ hdr->env->references = mutt_parse_references (b, 0); -+ break; -+ case 6: -+ hdr->content->length = atoi (b); -+ break; -+ case 7: -+ hdr->lines = atoi (b); -+ break; -+ case 8: -+ if (!hdr->read) -+ FREE (&hdr->env->xref); -+ b = b + 6; /* skips the "Xref: " */ -+ hdr->env->xref = safe_strdup (b); -+ nntp_parse_xref (ctx, nntp_data->group, b, hdr); -+ } -+ if (!*p) -+ return -1; -+ b = p; -+ } -+ return 0; -+} -+ -+typedef struct -+{ -+ CONTEXT *ctx; -+ unsigned int base; -+ unsigned int first; -+ unsigned int last; -+ unsigned short *messages; -+ char* msg; -+} FETCH_CONTEXT; -+ -+#define fc ((FETCH_CONTEXT *) c) -+static int nntp_fetch_numbers (char *line, void *c) -+{ -+ unsigned int num; -+ -+ if (!line) -+ return 0; -+ num = atoi (line); -+ if (num < fc->base || num > fc->last) -+ return 0; -+ fc->messages[num - fc->base] = 1; -+ return 0; -+} -+ -+static int add_xover_line (char *line, void *c) -+{ -+ unsigned int num, total; -+ CONTEXT *ctx = fc->ctx; -+ NNTP_DATA *data = (NNTP_DATA *)ctx->data; -+ -+ if (!line) -+ return 0; -+ -+ if (ctx->msgcount >= ctx->hdrmax) -+ mx_alloc_memory (ctx); -+ ctx->hdrs[ctx->msgcount] = mutt_new_header (); -+ ctx->hdrs[ctx->msgcount]->index = ctx->msgcount; -+ -+ nntp_parse_xover (ctx, line, ctx->hdrs[ctx->msgcount]); -+ num = ctx->hdrs[ctx->msgcount]->article_num; -+ -+ if (num >= fc->first && num <= fc->last && fc->messages[num - fc->base]) -+ { -+ ctx->msgcount++; -+ if (num > data->lastLoaded) -+ data->lastLoaded = num; -+ num = num - fc->first + 1; -+ total = fc->last - fc->first + 1; -+ if (!ctx->quiet && fc->msg && ReadInc && (num % ReadInc == 0)) -+ mutt_message ("%s %d/%d", fc->msg, num, total); -+ } -+ else -+ mutt_free_header (&ctx->hdrs[ctx->msgcount]); /* skip it */ -+ -+ return 0; -+} -+#undef fc -+ -+static int nntp_fetch_headers (CONTEXT *ctx, unsigned int first, -+ unsigned int last) -+{ -+ char buf[HUGE_STRING]; -+ char *msg = _("Fetching message headers..."); -+ NNTP_DATA *nntp_data = ((NNTP_DATA *)ctx->data); -+ int ret; -+ int num; -+ int oldmsgcount; -+ unsigned int current; -+ FILE *f; -+ FETCH_CONTEXT fc; -+ -+ /* if empty group or nothing to do */ -+ if (!last || first > last) -+ return 0; -+ -+ /* fetch list of articles */ -+ mutt_message _("Fetching list of articles..."); -+ fc.ctx = ctx; -+ fc.base = first; -+ fc.last = last; -+ fc.messages = safe_calloc (last - first + 1, sizeof (unsigned short)); -+ snprintf (buf, sizeof (buf), "LISTGROUP %s\r\n", nntp_data->group); -+ if (mutt_nntp_fetch (nntp_data, buf, NULL, nntp_fetch_numbers, &fc, 0) != 0) -+ { -+ mutt_error (_("LISTGROUP command failed: %s"), buf); -+#ifdef DEBUG -+ nntp_error ("nntp_fetch_headers()", buf); -+#endif -+ FREE (&fc.messages); -+ return -1; -+ } -+ -+ /* CACHE: must be loaded xover cache here */ -+ num = nntp_data->lastCached - first + 1; -+ if (option (OPTNEWSCACHE) && nntp_data->cache && num > 0) -+ { -+ nntp_cache_expand (buf, nntp_data->cache); -+ mutt_message _("Fetching headers from cache..."); -+ if ((f = safe_fopen (buf, "r"))) -+ { -+ int r = 0; -+ -+ /* counting number of lines */ -+ while (fgets (buf, sizeof (buf), f) != NULL) -+ r++; -+ rewind (f); -+ while (r > num && fgets (buf, sizeof (buf), f) != NULL) -+ r--; -+ oldmsgcount = ctx->msgcount; -+ fc.first = first; -+ fc.last = first + num - 1; -+ fc.msg = NULL; -+ while (fgets (buf, sizeof (buf), f) != NULL) -+ add_xover_line (buf, &fc); -+ fclose (f); -+ nntp_data->lastLoaded = fc.last; -+ first = fc.last + 1; -+ if (ctx->msgcount > oldmsgcount) -+ mx_update_context (ctx, ctx->msgcount - oldmsgcount); -+ } -+ else -+ nntp_delete_cache (nntp_data); -+ } -+ num = last - first + 1; -+ if (num <= 0) -+ { -+ FREE (&fc.messages); -+ return 0; -+ } -+ -+ /* -+ * Without XOVER, we have to fetch each article header and parse -+ * it. With XOVER, we ask for all of them -+ */ -+ mutt_message (msg); -+ if (nntp_data->nserv->hasXOVER) -+ { -+ oldmsgcount = ctx->msgcount; -+ fc.first = first; -+ fc.last = last; -+ fc.msg = msg; -+ snprintf (buf, sizeof (buf), "XOVER %d-%d\r\n", first, last); -+ ret = mutt_nntp_fetch (nntp_data, buf, NULL, add_xover_line, &fc, 0); -+ if (ctx->msgcount > oldmsgcount) -+ mx_update_context (ctx, ctx->msgcount - oldmsgcount); -+ if (ret != 0) -+ { -+ mutt_error (_("XOVER command failed: %s"), buf); -+#ifdef DEBUG -+ nntp_error ("nntp_fetch_headers()", buf); -+#endif -+ FREE (&fc.messages); -+ return -1; -+ } -+ /* fetched OK */ -+ } -+ else -+ for (current = first; current <= last; current++) -+ { -+ HEADER *h; -+ -+ ret = current - first + 1; -+ mutt_message ("%s %d/%d", msg, ret, num); -+ -+ if (!fc.messages[current - fc.base]) -+ continue; -+ -+ if (ctx->msgcount >= ctx->hdrmax) -+ mx_alloc_memory (ctx); -+ h = ctx->hdrs[ctx->msgcount] = mutt_new_header (); -+ h->index = ctx->msgcount; -+ -+ ret = nntp_read_header (ctx, NULL, current); -+ if (ret == 0) /* Got article. Fetch next header */ -+ { -+ nntp_get_status (ctx, h, NULL, h->article_num); -+ ctx->msgcount++; -+ mx_update_context (ctx, 1); -+ } -+ else -+ mutt_free_header (&h); /* skip it */ -+ if (ret == -1) -+ { -+ FREE (&fc.messages); -+ return -1; -+ } -+ -+ if (current > nntp_data->lastLoaded) -+ nntp_data->lastLoaded = current; -+ } -+ FREE (&fc.messages); -+ nntp_data->lastLoaded = last; -+ mutt_clear_error (); -+ return 0; -+} -+ -+/* -+ * currently, nntp "mailbox" is "newsgroup" -+ */ -+int nntp_open_mailbox (CONTEXT *ctx) -+{ -+ NNTP_DATA *nntp_data; -+ NNTP_SERVER *serv; -+ char buf[HUGE_STRING]; -+ char server[LONG_STRING]; -+ int count = 0; -+ unsigned int first; -+ ACCOUNT acct; -+ -+ if (nntp_parse_url (ctx->path, &acct, buf, sizeof (buf)) < 0 || !*buf) -+ { -+ mutt_error (_("%s is an invalid newsgroup specification!"), ctx->path); -+ mutt_sleep (2); -+ return -1; -+ } -+ -+ server[0] = '\0'; -+ nntp_expand_path (server, sizeof (server), &acct); -+ if (!(serv = mutt_select_newsserver (server)) || serv->status != NNTP_OK) -+ return -1; -+ -+ CurrentNewsSrv = serv; -+ -+ /* create NNTP-specific state struct if nof found in list */ -+ if ((nntp_data = (NNTP_DATA *) hash_find (serv->newsgroups, buf)) == NULL) -+ { -+ nntp_data = safe_calloc (1, sizeof (NNTP_DATA) + strlen (buf) + 1); -+ nntp_data->group = (char *) nntp_data + sizeof (NNTP_DATA); -+ strcpy (nntp_data->group, buf); -+ hash_insert (serv->newsgroups, nntp_data->group, nntp_data, 0); -+ nntp_add_to_list (serv, nntp_data); -+ } -+ ctx->data = nntp_data; -+ nntp_data->nserv = serv; -+ -+ mutt_message (_("Selecting %s..."), nntp_data->group); -+ -+ if (!nntp_data->desc) -+ { -+ nntp_get_desc (nntp_data, nntp_data->group, NULL); -+ if (nntp_data->desc) -+ nntp_save_cache_index (serv); -+ } -+ -+ buf[0] = 0; -+ if (mutt_nntp_query (nntp_data, buf, sizeof(buf)) < 0) -+ { -+#ifdef DEBUG -+ nntp_error ("nntp_open_mailbox()", buf); -+#endif -+ return -1; -+ } -+ -+ if (mutt_strncmp ("211", buf, 3)) -+ { -+ LIST *l = serv->list; -+ -+ /* GROUP command failed */ -+ if (!mutt_strncmp ("411", buf, 3)) -+ { -+ mutt_error (_("Newsgroup %s not found on server %s"), -+ nntp_data->group, serv->conn->account.host); -+ -+ /* CACHE: delete cache and line from .index */ -+ nntp_delete_cache (nntp_data); -+ hash_delete (serv->newsgroups, nntp_data->group, NULL, nntp_delete_data); -+ while (l && l->data != (void *) nntp_data) l = l->next; -+ if (l) -+ l->data = NULL; -+ -+ sleep (2); -+ } -+ -+ return -1; -+ } -+ -+ sscanf (buf + 4, "%d %u %u %s", &count, &nntp_data->firstMessage, -+ &nntp_data->lastMessage, buf); -+ -+ nntp_data->deleted = 0; -+ -+ time (&serv->check_time); -+ -+ /* -+ * Check for max adding context. If it is greater than $nntp_context, -+ * strip off extra articles -+ */ -+ first = nntp_data->firstMessage; -+ if (NntpContext && nntp_data->lastMessage - first + 1 > NntpContext) -+ first = nntp_data->lastMessage - NntpContext + 1; -+ if (first) -+ nntp_data->lastLoaded = first - 1; -+ return nntp_fetch_headers (ctx, first, nntp_data->lastMessage); -+} -+ -+int nntp_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) -+{ -+ char buf[LONG_STRING]; -+ char path[_POSIX_PATH_MAX]; -+ NNTP_CACHE *cache; -+ char *m = _("Fetching message..."); -+ int ret; -+ -+ /* see if we already have the message in our cache */ -+ cache = &((NNTP_DATA *) ctx->data)->acache[ctx->hdrs[msgno]->index % NNTP_CACHE_LEN]; -+ -+ /* if everything is fine, assign msg->fp and return */ -+ if (cache->path && cache->index == ctx->hdrs[msgno]->index && -+ (msg->fp = fopen (cache->path, "r"))) -+ return 0; -+ -+ /* clear the previous entry */ -+ unlink (cache->path); -+ free (cache->path); -+ -+ mutt_message (m); -+ -+ cache->index = ctx->hdrs[msgno]->index; -+ mutt_mktemp (path); -+ cache->path = safe_strdup (path); -+ if (!(msg->fp = safe_fopen (path, "w+"))) -+ { -+ FREE (&cache->path); -+ return -1; -+ } -+ -+ if (ctx->hdrs[msgno]->article_num == 0) -+ snprintf (buf, sizeof (buf), "ARTICLE %s\r\n", -+ ctx->hdrs[msgno]->env->message_id); -+ else -+ snprintf (buf, sizeof (buf), "ARTICLE %d\r\n", -+ ctx->hdrs[msgno]->article_num); -+ -+ ret = mutt_nntp_fetch ((NNTP_DATA *)ctx->data, buf, m, nntp_read_tempfile, -+ msg->fp, ctx->tagged); -+ if (ret == 1) -+ { -+ mutt_error (_("Article %d not found on server"), -+ ctx->hdrs[msgno]->article_num); -+ dprint (1, (debugfile, "nntp_fetch_message: %s\n", buf)); -+ } -+ -+ if (ret) -+ { -+ fclose (msg->fp); -+ unlink (path); -+ FREE (&cache->path); -+ return -1; -+ } -+ -+ mutt_free_envelope (&ctx->hdrs[msgno]->env); -+ ctx->hdrs[msgno]->env = mutt_read_rfc822_header (msg->fp, ctx->hdrs[msgno], 0, 0); -+ /* fix content length */ -+ fseek(msg->fp, 0, SEEK_END); -+ ctx->hdrs[msgno]->content->length = ftell (msg->fp) - -+ ctx->hdrs[msgno]->content->offset; -+ -+ /* this is called in mutt before the open which fetches the message, -+ * which is probably wrong, but we just call it again here to handle -+ * the problem instead of fixing it. -+ */ -+ mutt_parse_mime_message (ctx, ctx->hdrs[msgno]); -+ -+ /* These would normally be updated in mx_update_context(), but the -+ * full headers aren't parsed with XOVER, so the information wasn't -+ * available then. -+ */ -+#ifdef HAVE_PGP -+ ctx->hdrs[msgno]->pgp = pgp_query (ctx->hdrs[msgno]->content); -+#endif /* HAVE_PGP */ -+ -+ mutt_clear_error(); -+ rewind (msg->fp); -+ -+ return 0; -+} -+ -+/* Post article */ -+int nntp_post (const char *msg) { -+ char buf[LONG_STRING]; -+ size_t len; -+ FILE *f; -+ NNTP_DATA *nntp_data; -+ -+ if (Context && Context->magic == M_NNTP) -+ nntp_data = (NNTP_DATA *)Context->data; -+ else -+ { -+ if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)) || -+ !CurrentNewsSrv->list || !CurrentNewsSrv->list->data) -+ { -+ mutt_error (_("Can't post article. No connection to news server.")); -+ return -1; -+ } -+ nntp_data = (NNTP_DATA *)CurrentNewsSrv->list->data; -+ } -+ -+ if (!(f = safe_fopen (msg, "r"))) -+ { -+ mutt_error (_("Can't post article. Unable to open %s"), msg); -+ return -1; -+ } -+ -+ strfcpy (buf, "POST\r\n", sizeof (buf)); -+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0) -+ { -+ mutt_error (_("Can't post article. Connection to %s lost."), -+ nntp_data->nserv->conn->account.host); -+ return -1; -+ } -+ if (buf[0] != '3') -+ { -+ mutt_error (_("Can't post article: %s"), buf); -+ return -1; -+ } -+ -+ buf[0] = '.'; -+ buf[1] = '\0'; -+ while (fgets (buf + 1, sizeof (buf) - 2, f) != NULL) -+ { -+ len = strlen (buf); -+ if (buf[len - 1] == '\n') -+ { -+ buf[len - 1] = '\r'; -+ buf[len] = '\n'; -+ len++; -+ buf[len] = '\0'; -+ } -+ if (buf[1] == '.') -+ mutt_socket_write_d (nntp_data->nserv->conn, buf, M_SOCK_LOG_HDR); -+ else -+ mutt_socket_write_d (nntp_data->nserv->conn, buf + 1, M_SOCK_LOG_HDR); -+ } -+ fclose (f); -+ -+ if (buf[strlen (buf) - 1] != '\n') -+ mutt_socket_write_d (nntp_data->nserv->conn, "\r\n", M_SOCK_LOG_HDR); -+ mutt_socket_write_d (nntp_data->nserv->conn, ".\r\n", M_SOCK_LOG_HDR); -+ if (mutt_socket_readln (buf, sizeof (buf), nntp_data->nserv->conn) < 0) -+ { -+ mutt_error (_("Can't post article. Connection to %s lost."), -+ nntp_data->nserv->conn->account.host); -+ return -1; -+ } -+ if (buf[0] != '2') -+ { -+ mutt_error (_("Can't post article: %s"), buf); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+/* nntp_logout_all: close all open connections. */ -+void nntp_logout_all (void) -+{ -+ char buf[LONG_STRING]; -+ CONNECTION* conn; -+ CONNECTION* tmp; -+ -+ conn = mutt_socket_head (); -+ -+ while (conn) -+ { -+ tmp = conn; -+ -+ if (conn->account.type == M_ACCT_TYPE_NNTP) -+ { -+ mutt_message (_("Closing connection to %s..."), conn->account.host); -+ mutt_socket_write (conn, "QUIT\r\n"); -+ mutt_socket_readln (buf, sizeof (buf), conn); -+ mutt_clear_error (); -+ mutt_socket_close (conn); -+ -+ mutt_socket_free (tmp); -+ } -+ -+ conn = conn->next; -+ } -+} -+ -+static void nntp_free_acache (NNTP_DATA *data) -+{ -+ int i; -+ -+ for (i = 0; i < NNTP_CACHE_LEN; i++) -+ { -+ if (data->acache[i].path) -+ { -+ unlink (data->acache[i].path); -+ FREE (&data->acache[i].path); -+ } -+ } -+} -+ -+void nntp_delete_data (void *p) -+{ -+ NNTP_DATA *data = (NNTP_DATA *)p; -+ -+ if (!p) -+ return; -+ FREE (&data->entries); -+ FREE (&data->desc); -+ FREE (&data->cache); -+ nntp_free_acache (data); -+ FREE (p); -+} -+ -+int nntp_sync_mailbox (CONTEXT *ctx) -+{ -+ NNTP_DATA *data = ctx->data; -+ -+ /* CACHE: update cache and .index files */ -+ if ((option (OPTSAVEUNSUB) || data->subscribed)) -+ nntp_save_cache_group (ctx); -+ nntp_free_acache (data); -+ -+ data->nserv->check_time = 0; /* next nntp_check_mailbox() will really check */ -+ return 0; -+} -+ -+void nntp_fastclose_mailbox (CONTEXT *ctx) -+{ -+ NNTP_DATA *data = (NNTP_DATA *) ctx->data, *tmp; -+ -+ if (!data) -+ return; -+ nntp_free_acache (data); -+ if (!data->nserv || !data->nserv->newsgroups || !data->group) -+ return; -+ nntp_save_cache_index (data->nserv); -+ if ((tmp = hash_find (data->nserv->newsgroups, data->group)) == NULL -+ || tmp != data) -+ nntp_delete_data (data); -+} -+ -+/* commit changes and terminate connection */ -+int nntp_close_mailbox (CONTEXT *ctx) -+{ -+ if (!ctx) -+ return -1; -+ mutt_message _("Quitting newsgroup..."); -+ if (ctx->data) -+ { -+ NNTP_DATA *data = (NNTP_DATA *) ctx->data; -+ int ret; -+ -+ if (data->nserv && data->nserv->conn && ctx->unread) -+ { -+ ret = query_quadoption (OPT_CATCHUP, _("Mark all articles read?")); -+ if (ret == M_YES) -+ mutt_newsgroup_catchup (data->nserv, data->group); -+ else if (ret < 0) -+ return -1; -+ } -+ } -+ nntp_sync_mailbox (ctx); -+ if (ctx->data && ((NNTP_DATA *)ctx->data)->nserv) -+ { -+ NNTP_SERVER *news; -+ -+ news = ((NNTP_DATA *)ctx->data)->nserv; -+ newsrc_gen_entries (ctx); -+ ((NNTP_DATA *)ctx->data)->unread = ctx->unread; -+ mutt_newsrc_update (news); -+ } -+ mutt_clear_error(); -+ return 0; -+} -+ -+/* use the GROUP command to poll for new mail */ -+static int _nntp_check_mailbox (CONTEXT *ctx, NNTP_DATA *nntp_data) -+{ -+ char buf[LONG_STRING]; -+ int count = 0; -+ -+ if (nntp_data->nserv->check_time + NewsPollTimeout > time (NULL)) -+ return 0; -+ -+ buf[0] = 0; -+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0) -+ { -+#ifdef DEBUG -+ nntp_error ("nntp_check_mailbox()", buf); -+#endif -+ return -1; -+ } -+ if (mutt_strncmp ("211", buf, 3)) -+ { -+ buf[0] = 0; -+ if (mutt_nntp_query (nntp_data, buf, sizeof (buf)) < 0) -+ { -+#ifdef DEBUG -+ nntp_error ("nntp_check_mailbox()", buf); -+#endif -+ return -1; -+ } -+ } -+ if (!mutt_strncmp ("211", buf, 3)) -+ { -+ int first; -+ int last; -+ -+ sscanf (buf + 4, "%d %d %d", &count, &first, &last); -+ nntp_data->firstMessage = first; -+ nntp_data->lastMessage = last; -+ if (ctx && last > nntp_data->lastLoaded) -+ { -+ nntp_fetch_headers (ctx, nntp_data->lastLoaded + 1, last); -+ time (&nntp_data->nserv->check_time); -+ return 1; -+ } -+ if (!last || (!nntp_data->rc && !nntp_data->lastCached)) -+ nntp_data->unread = count; -+ else -+ mutt_newsgroup_stat (nntp_data); -+ /* active was renumbered? */ -+ if (last < nntp_data->lastLoaded) -+ { -+ if (!nntp_data->max) -+ { -+ nntp_data->entries = safe_calloc (5, sizeof (NEWSRC_ENTRY)); -+ nntp_data->max = 5; -+ } -+ nntp_data->lastCached = 0; -+ nntp_data->num = 1; -+ nntp_data->entries[0].first = 1; -+ nntp_data->entries[0].last = 0; -+ } -+ } -+ -+ time (&nntp_data->nserv->check_time); -+ return 0; -+} -+ -+int nntp_check_mailbox (CONTEXT *ctx) -+{ -+ return _nntp_check_mailbox (ctx, (NNTP_DATA *)ctx->data); -+} -+ -+static int add_group (char *buf, void *serv) -+{ -+#define s ((NNTP_SERVER *) serv) -+ char group[LONG_STRING], mod, desc[HUGE_STRING]; -+ int first, last; -+ NNTP_DATA *nntp_data; -+ static int n = 0; -+ -+ _checked = n; /* _checked have N, where N = number of groups */ -+ if (!buf) /* at EOF must be zerouth */ -+ n = 0; -+ -+ if (!s || !buf) -+ return 0; -+ -+ *desc = 0; -+ sscanf (buf, "%s %d %d %c %[^\n]", group, &last, &first, &mod, desc); -+ if (!group) -+ return 0; -+ if ((nntp_data = (NNTP_DATA *) hash_find (s->newsgroups, group)) == NULL) -+ { -+ n++; -+ nntp_data = safe_calloc (1, sizeof (NNTP_DATA) + strlen (group) + 1); -+ nntp_data->group = (char *) nntp_data + sizeof (NNTP_DATA); -+ strcpy (nntp_data->group, group); -+ nntp_data->nserv = s; -+ if (s->newsgroups->nelem < s->newsgroups->curnelem * 2) -+ s->newsgroups = hash_resize (s->newsgroups, s->newsgroups->nelem * 2); -+ hash_insert (s->newsgroups, nntp_data->group, nntp_data, 0); -+ nntp_add_to_list (s, nntp_data); -+ } -+ nntp_data->deleted = 0; -+ nntp_data->firstMessage = first; -+ nntp_data->lastMessage = last; -+ if (mod == 'y') -+ nntp_data->allowed = 1; -+ else -+ nntp_data->allowed = 0; -+ if (nntp_data->desc) -+ FREE (&nntp_data->desc); -+ if (*desc) -+ nntp_data->desc = safe_strdup (desc); -+ if (nntp_data->rc || nntp_data->lastCached) -+ mutt_newsgroup_stat (nntp_data); -+ else if (nntp_data->lastMessage && -+ nntp_data->firstMessage <= nntp_data->lastMessage) -+ nntp_data->unread = nntp_data->lastMessage - nntp_data->firstMessage + 1; -+ else -+ nntp_data->unread = 0; -+ -+ return 0; -+#undef s -+} -+ -+int nntp_check_newgroups (NNTP_SERVER *serv, int force) -+{ -+ char buf[LONG_STRING]; -+ NNTP_DATA nntp_data; -+ LIST *l; -+ LIST emp; -+ time_t now; -+ struct tm *t; -+ -+ if (!serv || !serv->newgroups_time) -+ return -1; -+ -+ if (nntp_open_connection (serv) < 0) -+ return -1; -+ -+ /* check subscribed groups for new news */ -+ if (option (OPTSHOWNEWNEWS)) -+ { -+ mutt_message _("Checking for new messages..."); -+ for (l = serv->list; l; l = l->next) -+ { -+ serv->check_time = 0; /* really check! */ -+ if (l->data && ((NNTP_DATA *) l->data)->subscribed) -+ _nntp_check_mailbox (NULL, (NNTP_DATA *) l->data); -+ } -+ } -+ else if (!force) -+ return 0; -+ -+ mutt_message _("Checking for new newsgroups..."); -+ now = serv->newgroups_time; -+ time (&serv->newgroups_time); -+ t = gmtime (&now); -+ snprintf (buf, sizeof (buf), "NEWGROUPS %02d%02d%02d %02d%02d%02d GMT\r\n", -+ (t->tm_year % 100), t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, -+ t->tm_sec); -+ nntp_data.nserv = serv; -+ if (Context && Context->magic == M_NNTP) -+ nntp_data.group = ((NNTP_DATA *)Context->data)->group; -+ else -+ nntp_data.group = NULL; -+ l = serv->tail; -+ if (mutt_nntp_fetch (&nntp_data, buf, _("Adding new newsgroups..."), -+ add_group, serv, 0) != 0) -+ { -+#ifdef DEBUG -+ nntp_error ("nntp_check_newgroups()", buf); -+#endif -+ return -1; -+ } -+ -+ mutt_message _("Loading descriptions..."); -+ if (l) -+ emp.next = l->next; -+ else -+ emp.next = serv->list; -+ l = &emp; -+ while (l->next) -+ { -+ l = l->next; -+ ((NNTP_DATA *) l->data)->new = 1; -+ nntp_get_desc ((NNTP_DATA *) l->data, ((NNTP_DATA *) l->data)->group, NULL); -+ } -+ if (emp.next) -+ nntp_save_cache_index (serv); -+ mutt_clear_error (); -+ return _checked; -+} -+ -+/* Load list of all newsgroups from cache ALL */ -+int nntp_get_cache_all (NNTP_SERVER *serv) -+{ -+ char buf[HUGE_STRING]; -+ FILE *f; -+ -+ nntp_cache_expand (buf, serv->cache); -+ if ((f = safe_fopen (buf, "r"))) -+ { -+ int i = 0; -+ -+ while (fgets (buf, sizeof(buf), f) != NULL) -+ { -+ if (ReadInc && (i % ReadInc == 0)) -+ mutt_message (_("Loading list from cache... %d"), i); -+ add_group (buf, serv); -+ i++; -+ } -+ add_group (NULL, NULL); -+ fclose (f); -+ mutt_clear_error (); -+ return 0; -+ } -+ else -+ { -+ FREE (&serv->cache); -+ return -1; -+ } -+} -+ -+/* Load list of all newsgroups from active */ -+int nntp_get_active (NNTP_SERVER *serv) -+{ -+ char msg[SHORT_STRING]; -+ NNTP_DATA nntp_data; -+ LIST *tmp; -+ -+ if (nntp_open_connection (serv) < 0) -+ return -1; -+ -+ snprintf (msg, sizeof(msg), _("Loading list of all newsgroups on server %s..."), -+ serv->conn->account.host); -+ mutt_message (msg); -+ time (&serv->newgroups_time); -+ nntp_data.nserv = serv; -+ nntp_data.group = NULL; -+ -+ if (mutt_nntp_fetch (&nntp_data, "LIST\r\n", msg, add_group, serv, 0) < 0) -+ { -+#ifdef DEBUG -+ nntp_error ("nntp_get_active()", "LIST\r\n"); -+#endif -+ return -1; -+ } -+ -+ strfcpy (msg, _("Loading descriptions..."), sizeof (msg)); -+ mutt_message (msg); -+ nntp_get_desc (&nntp_data, "*", msg); -+ -+ for (tmp = serv->list; tmp; tmp = tmp->next) -+ { -+ NNTP_DATA *data = (NNTP_DATA *)tmp->data; -+ -+ if (data && data->deleted && !data->rc) -+ { -+ nntp_delete_cache (data); -+ hash_delete (serv->newsgroups, data->group, NULL, nntp_delete_data); -+ tmp->data = NULL; -+ } -+ } -+ nntp_save_cache_index (serv); -+ -+ mutt_clear_error (); -+ return _checked; -+} -+ -+/* -+ * returns -1 if error ocurred while retrieving header, -+ * number of articles which ones exist in context on success. -+ */ -+int nntp_check_msgid (CONTEXT *ctx, const char *msgid) -+{ -+ int ret; -+ -+ /* if msgid is already in context, don't reload them */ -+ if (hash_find (ctx->id_hash, msgid)) -+ return 1; -+ if (ctx->msgcount == ctx->hdrmax) -+ mx_alloc_memory (ctx); -+ ctx->hdrs[ctx->msgcount] = mutt_new_header (); -+ ctx->hdrs[ctx->msgcount]->index = ctx->msgcount; -+ -+ mutt_message (_("Fetching %s from server..."), msgid); -+ ret = nntp_read_header (ctx, msgid, 0); -+ /* since nntp_read_header() may set read flag, we must reset it */ -+ ctx->hdrs[ctx->msgcount]->read = 0; -+ if (ret != 0) -+ mutt_free_header (&ctx->hdrs[ctx->msgcount]); -+ else -+ { -+ ctx->msgcount++; -+ mx_update_context (ctx, 1); -+ ctx->changed = 1; -+ } -+ return ret; -+} -+ -+typedef struct -+{ -+ CONTEXT *ctx; -+ unsigned int num; -+ unsigned int max; -+ unsigned int *child; -+} CHILD_CONTEXT; -+ -+static int check_children (char *s, void *c) -+{ -+#define cc ((CHILD_CONTEXT *) c) -+ unsigned int i, n; -+ -+ if (!s || (n = atoi (s)) == 0) -+ return 0; -+ for (i = 0; i < cc->ctx->msgcount; i++) -+ if (cc->ctx->hdrs[i]->article_num == n) -+ return 0; -+ if (cc->num >= cc->max) -+ safe_realloc ((void **) &cc->child, sizeof (unsigned int) * (cc->max += 25)); -+ cc->child[cc->num++] = n; -+ -+ return 0; -+#undef cc -+} -+ -+int nntp_check_children (CONTEXT *ctx, const char *msgid) -+{ -+ NNTP_DATA *nntp_data = (NNTP_DATA *)ctx->data; -+ char buf[STRING]; -+ int i, ret = 0, tmp = 0; -+ CHILD_CONTEXT cc; -+ -+ if (!nntp_data || !nntp_data->nserv || !nntp_data->nserv->conn || -+ !nntp_data->nserv->conn->account.host) -+ return -1; -+ if (nntp_data->firstMessage > nntp_data->lastLoaded) -+ return 0; -+ if (!nntp_data->nserv->hasXPAT) -+ { -+ mutt_error (_("Server %s does not support this operation!"), -+ nntp_data->nserv->conn->account.host); -+ return -1; -+ } -+ -+ snprintf (buf, sizeof (buf), "XPAT References %d-%d *%s*\r\n", -+ nntp_data->firstMessage, nntp_data->lastLoaded, msgid); -+ -+ cc.ctx = ctx; -+ cc.num = 0; -+ cc.max = 25; -+ cc.child = safe_malloc (sizeof (unsigned int) * 25); -+ if (mutt_nntp_fetch (nntp_data, buf, NULL, check_children, &cc, 0)) -+ { -+ safe_free ((void **) &cc.child); -+ return -1; -+ } -+ /* dont try to read the xover cache. check_children() already -+ * made sure that we dont have the article, so we need to visit -+ * the server. Reading the cache at this point is also bad -+ * because it would duplicate messages */ -+ if (option (OPTNEWSCACHE)) -+ { -+ tmp++; -+ unset_option (OPTNEWSCACHE); -+ } -+ for (i = 0; i < cc.num; i++) -+ { -+ if ((ret = nntp_fetch_headers (ctx, cc.child[i], cc.child[i]))) -+ break; -+ if (ctx->msgcount && -+ ctx->hdrs[ctx->msgcount - 1]->article_num == cc.child[i]) -+ ctx->hdrs[ctx->msgcount - 1]->read = 0; -+ } -+ if (tmp) -+ set_option (OPTNEWSCACHE); -+ safe_free ((void **) &cc.child); -+ return ret; -+} -diff -uNr mutt-1.4.orig/nntp.h mutt-1.4/nntp.h ---- mutt-1.4.orig/nntp.h Thu Jan 1 01:00:00 1970 -+++ mutt-1.4/nntp.h Sun Nov 3 21:57:20 2002 -@@ -0,0 +1,135 @@ -+/* -+ * Copyright (C) 1998 Brandon Long -+ * Copyright (C) 1999 Andrej Gritsenko -+ * Copyright (C) 2000-2002 Vsevolod Volkov -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef _NNTP_H_ -+#define _NNTP_H_ 1 -+ -+#include "mutt_socket.h" -+#include "mailbox.h" -+ -+#include -+ -+#define NNTP_PORT 119 -+#define NNTP_SSL_PORT 563 -+ -+/* number of entries in the hash table */ -+#define NNTP_CACHE_LEN 10 -+ -+enum -+{ -+ NNTP_NONE = 0, -+ NNTP_OK, -+ NNTP_BYE -+}; -+ -+typedef struct -+{ -+ int first; -+ int last; -+} NEWSRC_ENTRY; -+ -+typedef struct -+{ -+ unsigned int hasXPAT : 1; -+ unsigned int hasXGTITLE : 1; -+ unsigned int hasXOVER : 1; -+ unsigned int status : 3; -+ char *newsrc; -+ char *cache; -+ int stat; -+ off_t size; -+ time_t mtime; -+ time_t newgroups_time; -+ time_t check_time; -+ HASH *newsgroups; -+ LIST *list; /* list of newsgroups */ -+ LIST *tail; /* last entry of list */ -+ CONNECTION *conn; -+} NNTP_SERVER; -+ -+typedef struct -+{ -+ unsigned int index; -+ char *path; -+} NNTP_CACHE; -+ -+typedef struct -+{ -+ NEWSRC_ENTRY *entries; -+ unsigned int num; /* number of used entries */ -+ unsigned int max; /* number of allocated entries */ -+ unsigned int unread; -+ unsigned int firstMessage; -+ unsigned int lastMessage; -+ unsigned int lastLoaded; -+ unsigned int lastCached; -+ unsigned int subscribed : 1; -+ unsigned int rc : 1; -+ unsigned int new : 1; -+ unsigned int allowed : 1; -+ unsigned int deleted : 1; -+ char *group; -+ char *desc; -+ char *cache; -+ NNTP_SERVER *nserv; -+ NNTP_CACHE acache[NNTP_CACHE_LEN]; -+} NNTP_DATA; -+ -+/* internal functions */ -+int nntp_get_active (NNTP_SERVER *); -+int nntp_get_cache_all (NNTP_SERVER *); -+int nntp_save_cache_index (NNTP_SERVER *); -+int nntp_check_newgroups (NNTP_SERVER *, int); -+int nntp_save_cache_group (CONTEXT *); -+int nntp_parse_url (const char *, ACCOUNT *, char *, size_t); -+void newsrc_gen_entries (CONTEXT *); -+void nntp_get_status (CONTEXT *, HEADER *, char *, int); -+void mutt_newsgroup_stat (NNTP_DATA *); -+void nntp_delete_cache (NNTP_DATA *); -+void nntp_add_to_list (NNTP_SERVER *, NNTP_DATA *); -+void nntp_cache_expand (char *, const char *); -+void nntp_delete_data (void *); -+ -+/* exposed interface */ -+NNTP_SERVER *mutt_select_newsserver (char *); -+NNTP_DATA *mutt_newsgroup_subscribe (NNTP_SERVER *, char *); -+NNTP_DATA *mutt_newsgroup_unsubscribe (NNTP_SERVER *, char *); -+NNTP_DATA *mutt_newsgroup_catchup (NNTP_SERVER *, char *); -+NNTP_DATA *mutt_newsgroup_uncatchup (NNTP_SERVER *, char *); -+void nntp_clear_cacheindex (NNTP_SERVER *); -+int mutt_newsrc_update (NNTP_SERVER *); -+int nntp_open_mailbox (CONTEXT *); -+int nntp_sync_mailbox (CONTEXT *); -+int nntp_check_mailbox (CONTEXT *); -+int nntp_close_mailbox (CONTEXT *); -+void nntp_fastclose_mailbox (CONTEXT *); -+int nntp_fetch_message (MESSAGE *, CONTEXT *, int); -+int nntp_post (const char *); -+int nntp_check_msgid (CONTEXT *, const char *); -+int nntp_check_children (CONTEXT *, const char *); -+void nntp_buffy (char *); -+void nntp_expand_path (char *, size_t, ACCOUNT *); -+void nntp_logout_all (); -+const char *nntp_format_str (char *, size_t, char, const char *, const char *, -+ const char *, const char *, unsigned long, format_flag); -+ -+NNTP_SERVER *CurrentNewsSrv INITVAL (NULL); -+ -+#endif /* _NNTP_H_ */ -diff -uNr mutt-1.4.orig/pager.c mutt-1.4/pager.c ---- mutt-1.4.orig/pager.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/pager.c Sun Nov 3 21:57:20 2002 -@@ -33,6 +33,11 @@ - #include "imap.h" - #endif - -+#ifdef USE_NNTP -+#include "mx.h" -+#include "nntp.h" -+#endif -+ - - #ifdef HAVE_PGP - #include "pgp.h" -@@ -1445,6 +1450,16 @@ - { NULL, 0 } - }; - -+#ifdef USE_NNTP -+static struct mapping_t PagerNewsHelpExtra[] = { -+ { N_("Post"), OP_POST }, -+ { N_("Followup"), OP_FOLLOWUP }, -+ { N_("Del"), OP_DELETE }, -+ { N_("Next"), OP_MAIN_NEXT_UNDELETED }, -+ { NULL, 0 } -+}; -+#endif -+ - - - /* This pager is actually not so simple as it once was. It now operates in -@@ -1486,6 +1501,10 @@ - int old_PagerIndexLines; /* some people want to resize it - * while inside the pager... */ - -+#ifdef USE_NNTP -+ char *followup_to; -+#endif -+ - if (!(flags & M_SHOWCOLOR)) - flags |= M_SHOWFLAT; - -@@ -1525,7 +1544,11 @@ - if (IsHeader (extra)) - { - strfcpy (tmphelp, helpstr, sizeof (tmphelp)); -- mutt_compile_help (buffer, sizeof (buffer), MENU_PAGER, PagerHelpExtra); -+ mutt_compile_help (buffer, sizeof (buffer), MENU_PAGER, -+#ifdef USE_NNTP -+ (Context && (Context->magic == M_NNTP)) ? PagerNewsHelpExtra : -+#endif -+ PagerHelpExtra); - snprintf (helpstr, sizeof (helpstr), "%s %s", tmphelp, buffer); - } - if (!InHelp) -@@ -2300,6 +2323,15 @@ - } - #endif - -+#ifdef USE_NNTP -+ if (Context->magic == M_NNTP) -+ { -+ mutt_flushinp (); -+ mutt_error _("Can't change 'important' flag on NNTP server."); -+ break; -+ } -+#endif -+ - mutt_set_flag (Context, extra->hdr, M_FLAG, !extra->hdr->flagged); - redraw = REDRAW_STATUS | REDRAW_INDEX; - if (option (OPTRESOLVE)) -@@ -2333,6 +2365,60 @@ - redraw = REDRAW_FULL; - break; - -+#ifdef USE_NNTP -+ case OP_POST: -+ CHECK_MODE(IsHeader (extra) && !IsAttach (extra)); -+ CHECK_ATTACH; -+ if (extra->ctx && extra->ctx->magic == M_NNTP && -+ !((NNTP_DATA *)extra->ctx->data)->allowed && -+ query_quadoption (OPT_TOMODERATED,_("Posting to this group not allowed, may be moderated. Continue?")) != M_YES) -+ break; -+ ci_send_message (SENDNEWS, NULL, NULL, extra->ctx, NULL); -+ redraw = REDRAW_FULL; -+ break; -+ -+ case OP_FORWARD_TO_GROUP: -+ CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)); -+ CHECK_ATTACH; -+ if (extra->ctx && extra->ctx->magic == M_NNTP && -+ !((NNTP_DATA *)extra->ctx->data)->allowed && -+ query_quadoption (OPT_TOMODERATED,_("Posting to this group not allowed, may be moderated. Continue?")) != M_YES) -+ break; -+ if (IsMsgAttach (extra)) -+ mutt_attach_forward (extra->fp, extra->hdr, extra->idx, -+ extra->idxlen, extra->bdy, SENDNEWS); -+ else -+ ci_send_message (SENDNEWS|SENDFORWARD, NULL, NULL, extra->ctx, extra->hdr); -+ redraw = REDRAW_FULL; -+ break; -+ -+ case OP_FOLLOWUP: -+ CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)); -+ CHECK_ATTACH; -+ -+ if (IsMsgAttach (extra)) -+ followup_to = extra->bdy->hdr->env->followup_to; -+ else -+ followup_to = extra->hdr->env->followup_to; -+ -+ if (!followup_to || mutt_strcasecmp (followup_to, "poster") || -+ query_quadoption (OPT_FOLLOWUPTOPOSTER,_("Reply by mail as poster prefers?")) != M_YES) -+ { -+ if (extra->ctx && extra->ctx->magic == M_NNTP && -+ !((NNTP_DATA *)extra->ctx->data)->allowed && -+ query_quadoption (OPT_TOMODERATED,_("Posting to this group not allowed, may be moderated. Continue?")) != M_YES) -+ break; -+ if (IsMsgAttach (extra)) -+ mutt_attach_reply (extra->fp, extra->hdr, extra->idx, -+ extra->idxlen, extra->bdy, SENDNEWS|SENDREPLY); -+ else -+ ci_send_message (SENDNEWS|SENDREPLY, NULL, NULL, -+ extra->ctx, extra->hdr); -+ redraw = REDRAW_FULL; -+ break; -+ } -+#endif -+ - case OP_REPLY: - CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)); - CHECK_ATTACH; -@@ -2379,7 +2465,7 @@ - CHECK_ATTACH; - if (IsMsgAttach (extra)) - mutt_attach_forward (extra->fp, extra->hdr, extra->idx, -- extra->idxlen, extra->bdy); -+ extra->idxlen, extra->bdy, 0); - else - ci_send_message (SENDFORWARD, NULL, NULL, extra->ctx, extra->hdr); - redraw = REDRAW_FULL; -diff -uNr mutt-1.4.orig/parse.c mutt-1.4/parse.c ---- mutt-1.4.orig/parse.c Tue Jan 29 11:05:20 2002 -+++ mutt-1.4/parse.c Sun Nov 3 21:57:20 2002 -@@ -90,7 +90,7 @@ - /* not reached */ - } - --static LIST *mutt_parse_references (char *s, int in_reply_to) -+LIST *mutt_parse_references (char *s, int in_reply_to) - { - LIST *t, *lst = NULL; - int m, n = 0; -@@ -1047,6 +1047,17 @@ - e->from = rfc822_parse_adrlist (e->from, p); - matched = 1; - } -+#ifdef USE_NNTP -+ else if (!mutt_strcasecmp (line+1, "ollowup-to")) -+ { -+ if (!e->followup_to) -+ { -+ mutt_remove_trailing_ws (p); -+ e->followup_to = safe_strdup (mutt_skip_whitespace (p)); -+ } -+ matched = 1; -+ } -+#endif - break; - - case 'i': -@@ -1098,6 +1109,27 @@ - } - break; - -+#ifdef USE_NNTP -+ case 'n': -+ if (!mutt_strcasecmp (line + 1, "ewsgroups")) -+ { -+ safe_free ((void **)&e->newsgroups); -+ mutt_remove_trailing_ws (p); -+ e->newsgroups = safe_strdup (mutt_skip_whitespace (p)); -+ matched = 1; -+ } -+ break; -+#endif -+ -+ case 'o': -+ /* field `Organization:' saves only for pager! */ -+ if (!mutt_strcasecmp (line + 1, "rganization")) -+ { -+ if (!e->organization && mutt_strcasecmp (p, "unknown")) -+ e->organization = safe_strdup (p); -+ } -+ break; -+ - case 'r': - if (!ascii_strcasecmp (line + 1, "eferences")) - { -@@ -1207,7 +1239,21 @@ - e->x_label = safe_strdup(p); - matched = 1; - } -- -+#ifdef USE_NNTP -+ else if (!mutt_strcasecmp (line + 1, "-comment-to")) -+ { -+ if (!e->x_comment_to) -+ e->x_comment_to = safe_strdup (p); -+ matched = 1; -+ } -+ else if (!mutt_strcasecmp (line + 1, "ref")) -+ { -+ if (!e->xref) -+ e->xref = safe_strdup (p); -+ matched = 1; -+ } -+#endif -+ - default: - break; - } -diff -uNr mutt-1.4.orig/pattern.c mutt-1.4/pattern.c ---- mutt-1.4.orig/pattern.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/pattern.c Sun Nov 3 21:57:20 2002 -@@ -87,6 +87,9 @@ - { 't', M_TO, 0, eat_regexp }, - { 'U', M_UNREAD, 0, NULL }, - { 'v', M_COLLAPSED, 0, NULL }, -+#ifdef USE_NNTP -+ { 'w', M_NEWSGROUPS, 0, eat_regexp }, -+#endif - { 'x', M_REFERENCE, 0, eat_regexp }, - { 'y', M_XLABEL, 0, eat_regexp }, - { 'z', M_SIZE, 0, eat_range }, -@@ -1053,6 +1056,10 @@ - return (pat->not ^ (h->env->x_label && regexec (pat->rx, h->env->x_label, 0, NULL, 0) == 0)); - case M_DUPLICATED: - return (pat->not ^ (h->thread && h->thread->duplicate_thread)); -+#ifdef USE_NNTP -+ case M_NEWSGROUPS: -+ return (pat->not ^ (h->env->newsgroups && regexec (pat->rx, h->env->newsgroups, 0, NULL, 0) == 0)); -+#endif - } - mutt_error (_("error: unknown op %d (report this error)."), pat->op); - return (-1); -@@ -1120,6 +1127,7 @@ - int i; - - strfcpy (buf, NONULL (Context->pattern), sizeof (buf)); -+ if (prompt || op != M_LIMIT) - if (mutt_get_field (prompt, buf, sizeof (buf), M_PATTERN | M_CLEAR) != 0 || !buf[0]) - return (-1); - -diff -uNr mutt-1.4.orig/po/POTFILES.in mutt-1.4/po/POTFILES.in ---- mutt-1.4.orig/po/POTFILES.in Sun Nov 3 21:42:51 2002 -+++ mutt-1.4/po/POTFILES.in Sun Nov 3 21:57:20 2002 -@@ -41,6 +41,8 @@ - mutt_socket.c - mutt_ssl.c - mx.c -+newsrc.c -+nntp.c - pager.c - parse.c - pattern.c -diff -uNr mutt-1.4.orig/postpone.c mutt-1.4/postpone.c ---- mutt-1.4.orig/postpone.c Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/postpone.c Sun Nov 3 21:57:20 2002 -@@ -125,15 +125,26 @@ - - if (LastModify < st.st_mtime) - { -+#ifdef USE_NNTP -+ int optnews = option (OPTNEWS); -+#endif - LastModify = st.st_mtime; - - if (access (Postponed, R_OK | F_OK) != 0) - return (PostCount = 0); -+#ifdef USE_NNTP -+ if (optnews) -+ unset_option (OPTNEWS); -+#endif - if (mx_open_mailbox (Postponed, M_NOSORT | M_QUIET, &ctx) == NULL) - PostCount = 0; - else - PostCount = ctx.msgcount; - mx_fastclose_mailbox (&ctx); -+#ifdef USE_NNTP -+ if (optnews) -+ set_option (OPTNEWS); -+#endif - } - - return (PostCount); -diff -uNr mutt-1.4.orig/protos.h mutt-1.4/protos.h ---- mutt-1.4.orig/protos.h Sun Nov 3 21:42:52 2002 -+++ mutt-1.4/protos.h Sun Nov 3 21:57:20 2002 -@@ -95,6 +95,7 @@ - HASH *mutt_make_subj_hash (CONTEXT *); - - LIST *mutt_make_references(ENVELOPE *e); -+LIST *mutt_parse_references (char *, int); - - ENVELOPE *mutt_read_rfc822_header (FILE *, HEADER *, short, short); - HEADER *mutt_dup_header (HEADER *); -@@ -230,6 +231,7 @@ - void mutt_update_tree (ATTACHPTR **, short); - void mutt_version (void); - void mutt_view_attachments (HEADER *); -+void mutt_write_references (LIST *, FILE *); - void mutt_set_virtual (CONTEXT *); - - int mutt_addr_is_user (ADDRESS *); -@@ -316,6 +318,7 @@ - int mutt_search_command (int, int); - int mutt_compose_menu (HEADER *, char *, size_t, HEADER *); - int mutt_thread_set_flag (HEADER *, int, int, int); -+int mutt_update_list_file (char *, char *, char *, char *); - int mutt_user_is_recipient (HEADER *); - void mutt_update_num_postponed (void); - int mutt_view_attachment (FILE*, BODY *, int, HEADER *, ATTACHPTR **, short); -diff -uNr mutt-1.4.orig/recvattach.c mutt-1.4/recvattach.c ---- mutt-1.4.orig/recvattach.c Wed Sep 26 12:33:09 2001 -+++ mutt-1.4/recvattach.c Sun Nov 3 21:57:20 2002 -@@ -989,6 +989,15 @@ - } - #endif - -+#ifdef USE_NNTP -+ if (Context->magic == M_NNTP) -+ { -+ mutt_flushinp (); -+ mutt_error _("Can't delete attachment from newsserver."); -+ break; -+ } -+#endif -+ - - - #ifdef HAVE_PGP -@@ -1084,10 +1093,33 @@ - case OP_FORWARD_MESSAGE: - CHECK_ATTACH; - mutt_attach_forward (fp, hdr, idx, idxlen, -- menu->tagprefix ? NULL : idx[menu->current]->content); -+ menu->tagprefix ? NULL : idx[menu->current]->content, 0); - menu->redraw = REDRAW_FULL; - break; - -+#ifdef USE_NNTP -+ case OP_FORWARD_TO_GROUP: -+ CHECK_ATTACH; -+ mutt_attach_forward (fp, hdr, idx, idxlen, -+ menu->tagprefix ? NULL : idx[menu->current]->content, SENDNEWS); -+ menu->redraw = REDRAW_FULL; -+ break; -+ -+ case OP_FOLLOWUP: -+ CHECK_ATTACH; -+ -+ if (!idx[menu->current]->content->hdr->env->followup_to || -+ mutt_strcasecmp (idx[menu->current]->content->hdr->env->followup_to, "poster") || -+ query_quadoption (OPT_FOLLOWUPTOPOSTER,_("Reply by mail as poster prefers?")) != M_YES) -+ { -+ mutt_attach_reply (fp, hdr, idx, idxlen, -+ menu->tagprefix ? NULL : idx[menu->current]->content, -+ SENDNEWS|SENDREPLY); -+ menu->redraw = REDRAW_FULL; -+ break; -+ } -+#endif -+ - case OP_REPLY: - case OP_GROUP_REPLY: - case OP_LIST_REPLY: -diff -uNr mutt-1.4.orig/recvcmd.c mutt-1.4/recvcmd.c ---- mutt-1.4.orig/recvcmd.c Wed Jan 2 10:33:38 2002 -+++ mutt-1.4/recvcmd.c Sun Nov 3 21:57:20 2002 -@@ -334,7 +334,7 @@ - static void attach_forward_bodies (FILE * fp, HEADER * hdr, - ATTACHPTR ** idx, short idxlen, - BODY * cur, -- short nattach) -+ short nattach, int flags) - { - short i; - short mime_fwd_all = 0; -@@ -480,7 +480,7 @@ - tmpfp = NULL; - - /* now that we have the template, send it. */ -- ci_send_message (0, tmphdr, tmpbody, NULL, parent); -+ ci_send_message (flags, tmphdr, tmpbody, NULL, parent); - return; - - bail: -@@ -507,7 +507,7 @@ - */ - - static void attach_forward_msgs (FILE * fp, HEADER * hdr, -- ATTACHPTR ** idx, short idxlen, BODY * cur) -+ ATTACHPTR ** idx, short idxlen, BODY * cur, int flags) - { - HEADER *curhdr = NULL; - HEADER *tmphdr; -@@ -612,23 +612,23 @@ - else - mutt_free_header (&tmphdr); - -- ci_send_message (0, tmphdr, *tmpbody ? tmpbody : NULL, -+ ci_send_message (flags, tmphdr, *tmpbody ? tmpbody : NULL, - NULL, curhdr); - - } - - void mutt_attach_forward (FILE * fp, HEADER * hdr, -- ATTACHPTR ** idx, short idxlen, BODY * cur) -+ ATTACHPTR ** idx, short idxlen, BODY * cur, int flags) - { - short nattach; - - - if (check_all_msg (idx, idxlen, cur, 0) == 0) -- attach_forward_msgs (fp, hdr, idx, idxlen, cur); -+ attach_forward_msgs (fp, hdr, idx, idxlen, cur, flags); - else - { - nattach = count_tagged (idx, idxlen); -- attach_forward_bodies (fp, hdr, idx, idxlen, cur, nattach); -+ attach_forward_bodies (fp, hdr, idx, idxlen, cur, nattach, flags); - } - } - -@@ -686,28 +686,40 @@ - return -1; - } - -- if (parent) -+#ifdef USE_NNTP -+ if ((flags & SENDNEWS)) - { -- if (mutt_fetch_recips (env, curenv, flags) == -1) -- return -1; -+ /* in case followup set Newsgroups: with Followup-To: if it present */ -+ if (!env->newsgroups && curenv && -+ mutt_strcasecmp (curenv->followup_to, "poster")) -+ env->newsgroups = safe_strdup (curenv->followup_to); - } - else -+#endif - { -- for (i = 0; i < idxlen; i++) -+ if (parent) - { -- if (idx[i]->content->tagged -- && mutt_fetch_recips (env, idx[i]->content->hdr->env, flags) == -1) -+ if (mutt_fetch_recips (env, curenv, flags) == -1) - return -1; - } -+ else -+ { -+ for (i = 0; i < idxlen; i++) -+ { -+ if (idx[i]->content->tagged -+ && mutt_fetch_recips (env, idx[i]->content->hdr->env, flags) == -1) -+ return -1; -+ } -+ } -+ -+ if ((flags & SENDLISTREPLY) && !env->to) -+ { -+ mutt_error _("No mailing lists found!"); -+ return (-1); -+ } -+ -+ mutt_fix_reply_recipients (env); - } -- -- if ((flags & SENDLISTREPLY) && !env->to) -- { -- mutt_error _("No mailing lists found!"); -- return (-1); -- } -- -- mutt_fix_reply_recipients (env); - mutt_make_misc_reply_headers (env, Context, curhdr, curenv); - - if (parent) -@@ -768,6 +780,13 @@ - char prefix[SHORT_STRING]; - int rc; - -+#ifdef USE_NNTP -+ if (flags & SENDNEWS) -+ set_option (OPTNEWSSEND); -+ else -+ unset_option (OPTNEWSSEND); -+#endif -+ - if (check_all_msg (idx, idxlen, cur, 0) == -1) - { - nattach = count_tagged (idx, idxlen); -diff -uNr mutt-1.4.orig/rfc1524.c mutt-1.4/rfc1524.c ---- mutt-1.4.orig/rfc1524.c Tue May 15 09:23:49 2001 -+++ mutt-1.4/rfc1524.c Sun Nov 3 21:57:20 2002 -@@ -563,13 +563,13 @@ - * safe_fopen(). - */ - --int mutt_rename_file (char *oldfile, char *newfile) -+int _mutt_rename_file (char *oldfile, char *newfile, int overwrite) - { - FILE *ofp, *nfp; - - if (access (oldfile, F_OK) != 0) - return 1; -- if (access (newfile, F_OK) == 0) -+ if (!overwrite && access (newfile, F_OK) == 0) - return 2; - if ((ofp = fopen (oldfile,"r")) == NULL) - return 3; -@@ -584,3 +584,8 @@ - mutt_unlink (oldfile); - return 0; - } -+ -+int mutt_rename_file (char *oldfile, char *newfile) -+{ -+ return _mutt_rename_file (oldfile, newfile, 0); -+} -diff -uNr mutt-1.4.orig/rfc1524.h mutt-1.4/rfc1524.h ---- mutt-1.4.orig/rfc1524.h Fri Mar 3 11:10:13 2000 -+++ mutt-1.4/rfc1524.h Sun Nov 3 21:57:20 2002 -@@ -40,5 +40,6 @@ - int rfc1524_expand_filename (char *, char *, char *, size_t); - int rfc1524_mailcap_lookup (BODY *, char *, rfc1524_entry *, int); - int mutt_rename_file (char *, char *); -+int _mutt_rename_file (char *, char *, int); - - #endif /* _RFC1524_H */ -diff -uNr mutt-1.4.orig/send.c mutt-1.4/send.c ---- mutt-1.4.orig/send.c Wed Jan 30 23:50:40 2002 -+++ mutt-1.4/send.c Sun Nov 3 21:57:20 2002 -@@ -41,6 +41,10 @@ - #include "pgp.h" - #endif - -+#ifdef USE_NNTP -+#include "nntp.h" -+#endif -+ - #ifdef MIXMASTER - #include "remailer.h" - #endif -@@ -196,17 +200,51 @@ - return 0; - } - --static int edit_envelope (ENVELOPE *en) -+static int edit_envelope (ENVELOPE *en, int flags) - { - char buf[HUGE_STRING]; - LIST *uh = UserHeader; - -- if (edit_address (&en->to, "To: ") == -1 || en->to == NULL) -- return (-1); -- if (option (OPTASKCC) && edit_address (&en->cc, "Cc: ") == -1) -- return (-1); -- if (option (OPTASKBCC) && edit_address (&en->bcc, "Bcc: ") == -1) -- return (-1); -+#ifdef USE_NNTP -+ if (option (OPTNEWSSEND)) -+ { -+ if (en->newsgroups) -+ strfcpy (buf, en->newsgroups, sizeof (buf)); -+ else -+ buf[0] = 0; -+ if (mutt_get_field ("Newsgroups: ", buf, sizeof (buf), 0) != 0) -+ return (-1); -+ safe_free ((void **)&en->newsgroups); -+ en->newsgroups = safe_strdup (buf); -+ -+ if (en->followup_to) -+ strfcpy (buf, en->followup_to, sizeof (buf)); -+ else -+ buf[0] = 0; -+ if (option (OPTASKFOLLOWUP) && mutt_get_field ("Followup-To: ", buf, sizeof (buf), 0) != 0) -+ return (-1); -+ safe_free ((void **)&en->followup_to); -+ en->followup_to = safe_strdup (buf); -+ -+ if (en->x_comment_to) -+ strfcpy (buf, en->x_comment_to, sizeof (buf)); -+ else -+ buf[0] = 0; -+ if (option (OPTXCOMMENTTO) && option (OPTASKXCOMMENTTO) && mutt_get_field ("X-Comment-To: ", buf, sizeof (buf), 0) != 0) -+ return (-1); -+ safe_free ((void **)&en->x_comment_to); -+ en->x_comment_to = safe_strdup (buf); -+ } -+ else -+#endif -+ { -+ if (edit_address (&en->to, "To: ") == -1 || en->to == NULL) -+ return (-1); -+ if (option (OPTASKCC) && edit_address (&en->cc, "Cc: ") == -1) -+ return (-1); -+ if (option (OPTASKBCC) && edit_address (&en->bcc, "Bcc: ") == -1) -+ return (-1); -+ } - - if (en->subject) - { -@@ -242,6 +280,14 @@ - return 0; - } - -+#ifdef USE_NNTP -+char *nntp_get_header (const char *s) -+{ -+ SKIPWS (s); -+ return safe_strdup (s); -+} -+#endif -+ - static void process_user_recips (ENVELOPE *env) - { - LIST *uh = UserHeader; -@@ -254,6 +300,14 @@ - env->cc = rfc822_parse_adrlist (env->cc, uh->data + 3); - else if (ascii_strncasecmp ("bcc:", uh->data, 4) == 0) - env->bcc = rfc822_parse_adrlist (env->bcc, uh->data + 4); -+#ifdef USE_NNTP -+ else if (ascii_strncasecmp ("newsgroups:", uh->data, 11) == 0) -+ env->newsgroups = nntp_get_header (uh->data + 11); -+ else if (ascii_strncasecmp ("followup-to:", uh->data, 12) == 0) -+ env->followup_to = nntp_get_header (uh->data + 12); -+ else if (ascii_strncasecmp ("x-comment-to:", uh->data, 13) == 0) -+ env->x_comment_to = nntp_get_header (uh->data + 13); -+#endif - } - } - -@@ -284,6 +338,12 @@ - else if (ascii_strncasecmp ("to:", uh->data, 3) != 0 && - ascii_strncasecmp ("cc:", uh->data, 3) != 0 && - ascii_strncasecmp ("bcc:", uh->data, 4) != 0 && -+#ifdef USE_NNTP -+ ascii_strncasecmp ("newsgroups:", uh->data, 11) != 0 && -+ ascii_strncasecmp ("followup-to:", uh->data, 12) != 0 && -+ ascii_strncasecmp ("x-comment-to:", uh->data, 13) != 0 && -+#endif -+ ascii_strncasecmp ("supersedes:", uh->data, 11) != 0 && - ascii_strncasecmp ("subject:", uh->data, 8) != 0) - { - if (last) -@@ -597,6 +657,10 @@ - else - env->subject = safe_strdup ("Re: your mail"); - -+#ifdef USE_NNTP -+ if (option (OPTNEWSSEND) && option (OPTXCOMMENTTO) && curenv->from) -+ env->x_comment_to = safe_strdup (mutt_get_name (curenv->from)); -+#endif - } - - void mutt_add_to_reference_headers (ENVELOPE *env, ENVELOPE *curenv, LIST ***pp, LIST ***qq) -@@ -679,27 +743,39 @@ - - if (flags & SENDREPLY) - { -- if (tag) -+#ifdef USE_NNTP -+ if ((flags & SENDNEWS)) - { -- HEADER *h; -- -- for (i = 0; i < ctx->vcount; i++) -+ /* in case followup set Newsgroups: with Followup-To: if it present */ -+ if (!env->newsgroups && curenv && -+ mutt_strcasecmp (curenv->followup_to, "poster")) -+ env->newsgroups = safe_strdup (curenv->followup_to); -+ } -+ else -+#endif -+ { -+ if (tag) - { -- h = ctx->hdrs[ctx->v2r[i]]; -- if (h->tagged && mutt_fetch_recips (env, h->env, flags) == -1) -+ HEADER *h; -+ -+ for (i = 0; i < ctx->vcount; i++) -+ { -+ h = ctx->hdrs[ctx->v2r[i]]; -+ if (h->tagged && mutt_fetch_recips (env, h->env, flags) == -1) -+ return -1; -+ } -+ } -+ else if (mutt_fetch_recips (env, curenv, flags) == -1) - return -1; -+ -+ if ((flags & SENDLISTREPLY) && !env->to) -+ { -+ mutt_error _("No mailing lists found!"); -+ return (-1); - } -- } -- else if (mutt_fetch_recips (env, curenv, flags) == -1) -- return -1; - -- if ((flags & SENDLISTREPLY) && !env->to) -- { -- mutt_error _("No mailing lists found!"); -- return (-1); -+ mutt_fix_reply_recipients (env); - } -- -- mutt_fix_reply_recipients (env); - mutt_make_misc_reply_headers (env, ctx, cur, curenv); - mutt_make_reference_headers (tag ? NULL : curenv, env, ctx); - } -@@ -828,7 +904,18 @@ - * it hasn't already been set - */ - -- if (option (OPTFOLLOWUPTO) && !e->mail_followup_to) -+ if (!option (OPTFOLLOWUPTO)) -+ return; -+#ifdef USE_NNTP -+ if (option (OPTNEWSSEND)) -+ { -+ if (!e->followup_to && e->newsgroups && (strrchr (e->newsgroups, ','))) -+ e->followup_to = safe_strdup (e->newsgroups); -+ return; -+ } -+#endif -+ -+ if (!e->mail_followup_to) - { - if (mutt_is_list_cc (0, e->to, e->cc)) - { -@@ -1084,6 +1171,13 @@ - - int rv = -1; - -+#ifdef USE_NNTP -+ if (flags & SENDNEWS) -+ set_option (OPTNEWSSEND); -+ else -+ unset_option (OPTNEWSSEND); -+#endif -+ - if (!flags && !msg && quadoption (OPT_RECALL) != M_NO && - mutt_num_postponed (1)) - { -@@ -1115,6 +1209,22 @@ - { - if ((flags = mutt_get_postponed (ctx, msg, &cur, fcc, sizeof (fcc))) < 0) - goto cleanup; -+#ifdef USE_NNTP -+ /* -+ * If postponed message is a news article, it have -+ * a "Newsgroups:" header line, then set appropriate flag. -+ */ -+ if (msg->env->newsgroups) -+ { -+ flags |= SENDNEWS; -+ set_option (OPTNEWSSEND); -+ } -+ else -+ { -+ flags &= ~SENDNEWS; -+ unset_option (OPTNEWSSEND); -+ } -+#endif - } - - if (flags & (SENDPOSTPONED|SENDRESEND)) -@@ -1195,11 +1305,16 @@ - if (option (OPTHDRS)) - process_user_recips (msg->env); - -+#ifdef USE_NNTP -+ if ((flags & SENDNEWS) && ctx && ctx->magic == M_NNTP && !msg->env->newsgroups) -+ msg->env->newsgroups = safe_strdup (((NNTP_DATA *)ctx->data)->group); -+#endif -+ - if (! (flags & SENDMAILX) && - ! (option (OPTAUTOEDIT) && option (OPTEDITHDRS)) && - ! ((flags & SENDREPLY) && option (OPTFASTREPLY))) - { -- if (edit_envelope (msg->env) == -1) -+ if (edit_envelope (msg->env, flags) == -1) - goto cleanup; - } - -@@ -1349,6 +1464,11 @@ - if (i == -1) - { - /* abort */ -+#ifdef USE_NNTP -+ if (flags & SENDNEWS) -+ mutt_message _("Article not posted."); -+ else -+#endif - mutt_message _("Mail not sent."); - goto cleanup; - } -@@ -1380,6 +1500,9 @@ - } - } - -+#ifdef USE_NNTP -+ if (!(flags & SENDNEWS)) -+#endif - if (!msg->env->to && !msg->env->cc && !msg->env->bcc) - { - if (! (flags & SENDBATCH)) -@@ -1402,6 +1525,19 @@ - mutt_error _("No subject specified."); - goto main_loop; - } -+#ifdef USE_NNTP -+ if ((flags & SENDNEWS) && !msg->env->subject) -+ { -+ mutt_error _("No subject specified."); -+ goto main_loop; -+ } -+ -+ if ((flags & SENDNEWS) && !msg->env->newsgroups) -+ { -+ mutt_error _("No newsgroup specified."); -+ goto main_loop; -+ } -+#endif - - if (msg->content->next) - msg->content = mutt_make_multipart (msg->content); -@@ -1588,7 +1724,12 @@ - } - } - else if (!option (OPTNOCURSES) && ! (flags & SENDMAILX)) -- mutt_message (i == 0 ? _("Mail sent.") : _("Sending in background.")); -+ mutt_message (i != 0 ? _("Sending in background.") : -+#ifdef USE_NNTP -+ (flags & SENDNEWS) ? _("Article posted.") : _("Mail sent.")); -+#else -+ _("Mail sent.")); -+#endif - - #ifdef HAVE_PGP - if (msg->pgp & PGPENCRYPT) -diff -uNr mutt-1.4.orig/sendlib.c mutt-1.4/sendlib.c ---- mutt-1.4.orig/sendlib.c Sat Apr 20 09:25:49 2002 -+++ mutt-1.4/sendlib.c Sun Nov 3 21:57:20 2002 -@@ -40,6 +40,10 @@ - #include - #include - -+#ifdef USE_NNTP -+#include -+#endif -+ - #ifdef HAVE_SYSEXITS_H - #include - #else /* Make sure EX_OK is defined */ -@@ -1537,7 +1541,7 @@ - /* need to write the list in reverse because they are stored in reverse order - * when parsed to speed up threading - */ --static void write_references (LIST *r, FILE *f) -+void mutt_write_references (LIST *r, FILE *f) - { - LIST **ref = NULL; - int refcnt = 0, refmax = 0; -@@ -1579,6 +1583,9 @@ - char *p; - LIST *tmp = env->userhdrs; - -+#ifdef USE_NNTP -+ if (!option (OPTNEWSSEND)) -+#endif - if (mode == 0 && !privacy) - fputs (mutt_make_date (buffer, sizeof(buffer)), fp); - -@@ -1598,6 +1605,9 @@ - mutt_write_address_list (env->to, fp, 4); - } - else if (mode > 0) -+#ifdef USE_NNTP -+ if (!option (OPTNEWSSEND)) -+#endif - fputs ("To: \n", fp); - - if (env->cc) -@@ -1606,6 +1616,9 @@ - mutt_write_address_list (env->cc, fp, 4); - } - else if (mode > 0) -+#ifdef USE_NNTP -+ if (!option (OPTNEWSSEND)) -+#endif - fputs ("Cc: \n", fp); - - if (env->bcc) -@@ -1617,8 +1630,28 @@ - } - } - else if (mode > 0) -+#ifdef USE_NNTP -+ if (!option (OPTNEWSSEND)) -+#endif - fputs ("Bcc: \n", fp); - -+#ifdef USE_NNTP -+ if (env->newsgroups) -+ fprintf (fp, "Newsgroups: %s\n", env->newsgroups); -+ else if (mode == 1 && option (OPTNEWSSEND)) -+ fputs ("Newsgroups: \n", fp); -+ -+ if (env->followup_to) -+ fprintf (fp, "Followup-To: %s\n", env->followup_to); -+ else if (mode == 1 && option (OPTNEWSSEND)) -+ fputs ("Followup-To: \n", fp); -+ -+ if (env->x_comment_to) -+ fprintf (fp, "X-Comment-To: %s\n", env->x_comment_to); -+ else if (mode == 1 && option (OPTNEWSSEND) && option (OPTXCOMMENTTO)) -+ fputs ("X-Comment-To: \n", fp); -+#endif -+ - if (env->subject) - fprintf (fp, "Subject: %s\n", env->subject); - else if (mode == 1) -@@ -1637,6 +1670,9 @@ - fputs ("Reply-To: \n", fp); - - if (env->mail_followup_to) -+#ifdef USE_NNTP -+ if (!option (OPTNEWSSEND)) -+#endif - { - fputs ("Mail-Followup-To: ", fp); - mutt_write_address_list (env->mail_followup_to, fp, 18); -@@ -1647,7 +1683,7 @@ - if (env->references) - { - fputs ("References:", fp); -- write_references (env->references, fp); -+ mutt_write_references (env->references, fp); - fputc('\n', fp); - } - -@@ -1659,7 +1695,7 @@ - if (env->in_reply_to) - { - fputs ("In-Reply-To:", fp); -- write_references (env->in_reply_to, fp); -+ mutt_write_references (env->in_reply_to, fp); - fputc ('\n', fp); - } - -@@ -1967,11 +2003,30 @@ - const char *msg, /* file containing message */ - int eightbit) /* message contains 8bit chars */ - { -- char *ps = NULL, *path = NULL, *s = safe_strdup (Sendmail), *childout = NULL; -+ char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL; - char **args = NULL; - size_t argslen = 0, argsmax = 0; - int i; - -+#ifdef USE_NNTP -+ if (option (OPTNEWSSEND)) -+ { -+ char cmd[LONG_STRING]; -+ -+ mutt_FormatString (cmd, sizeof (cmd), NONULL (Inews), nntp_format_str, 0, 0); -+ if (!*cmd) -+ { -+ i = nntp_post (msg); -+ unlink (msg); -+ return i; -+ } -+ -+ s = safe_strdup (cmd); -+ } -+ else -+#endif -+ s = safe_strdup (Sendmail); -+ - ps = s; - i = 0; - while ((ps = strtok (ps, " "))) -@@ -1995,6 +2050,10 @@ - i++; - } - -+#ifdef USE_NNTP -+ if (!option (OPTNEWSSEND)) -+ { -+#endif - if (eightbit && option (OPTUSE8BITMIME)) - args = add_option (args, &argslen, &argsmax, "-B8BITMIME"); - -@@ -2017,6 +2076,9 @@ - args = add_args (args, &argslen, &argsmax, to); - args = add_args (args, &argslen, &argsmax, cc); - args = add_args (args, &argslen, &argsmax, bcc); -+#ifdef USE_NNTP -+ } -+#endif - - if (argslen == argsmax) - safe_realloc ((void **) &args, sizeof (char *) * (++argsmax)); -@@ -2148,6 +2210,9 @@ - rfc2047_encode_adrlist (env->reply_to, "Reply-To"); - - if (env->subject) -+#ifdef USE_NNTP -+ if (!option (OPTNEWSSEND) || option (OPTMIMESUBJECT)) -+#endif - { - rfc2047_encode_string (&env->subject); - } -@@ -2234,6 +2299,10 @@ - - rfc822_write_address (resent_from, sizeof (resent_from), from); - -+#ifdef USE_NNTP -+ unset_option (OPTNEWSSEND); -+#endif -+ - _mutt_bounce_message (fp, h, to, resent_from, from); - - rfc822_free_address (&from); -diff -uNr mutt-1.4.orig/sort.c mutt-1.4/sort.c ---- mutt-1.4.orig/sort.c Thu Dec 13 13:10:59 2001 -+++ mutt-1.4/sort.c Sun Nov 3 21:57:20 2002 -@@ -144,6 +144,15 @@ - HEADER **ha = (HEADER **) a; - HEADER **hb = (HEADER **) b; - -+#ifdef USE_NNTP -+ if ((*ha)->article_num && (*hb)->article_num) -+ { -+ int result = (*ha)->article_num - (*hb)->article_num; -+ AUXSORT(result,a,b); -+ return (SORTCODE (result)); -+ } -+ else -+#endif - /* no need to auxsort because you will never have equality here */ - return (SORTCODE ((*ha)->index - (*hb)->index)); - } -diff -uNr mutt-1.4.orig/url.c mutt-1.4/url.c ---- mutt-1.4.orig/url.c Mon Oct 29 12:53:45 2001 -+++ mutt-1.4/url.c Sun Nov 3 21:57:20 2002 -@@ -35,6 +35,8 @@ - { "imaps", U_IMAPS }, - { "pop", U_POP }, - { "pops", U_POPS }, -+ { "nntp", U_NNTP }, -+ { "nntps", U_NNTPS }, - { "mailto", U_MAILTO }, - { NULL, U_UNKNOWN} - }; -diff -uNr mutt-1.4.orig/url.h mutt-1.4/url.h ---- mutt-1.4.orig/url.h Tue Sep 4 11:30:04 2001 -+++ mutt-1.4/url.h Sun Nov 3 21:57:20 2002 -@@ -8,6 +8,8 @@ - U_POPS, - U_IMAP, - U_IMAPS, -+ U_NNTP, -+ U_NNTPS, - U_MAILTO, - U_UNKNOWN - } -- 2.43.0