Synch with Oort Gnus.
authoryamaoka <yamaoka>
Tue, 31 Dec 2002 03:49:16 +0000 (03:49 +0000)
committeryamaoka <yamaoka>
Tue, 31 Dec 2002 03:49:16 +0000 (03:49 +0000)
20 files changed:
ChangeLog
contrib/ChangeLog
contrib/hashcash.el
lisp/ChangeLog
lisp/dig.el
lisp/flow-fill.el
lisp/gnus-agent.el
lisp/gnus-art.el
lisp/gnus-group.el
lisp/gnus-start.el
lisp/gnus-sum.el
lisp/message.el
lisp/mm-uu.el
lisp/mml.el
lisp/spam.el
texi/ChangeLog
texi/gnus-ja.texi
texi/gnus.texi
texi/message-ja.texi
texi/message.texi

index 1916657..afe3596 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,13 @@
+2002-12-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-start.el (gnus-re-read-newsrc-el-file): Commented out.
+       (gnus-load): Allow coding-system as an argument.
+
 2002-12-16  ARISAWA Akihiro  <ari@mbf.sphere.ne.jp>
 
        * lisp/nnimap.el (nnimap-callback): Use `nnimap-demule'.
        (nnimap-request-article-part): Ditto.
-       
+
 2002-12-10  Katsumi Yamaoka  <yamaoka@jpl.org>
 
        * texi/Makefile.in (%.info, .texi): Conceal control procedures.
index 124ce41..f8271d6 100644 (file)
@@ -1,3 +1,8 @@
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * hashcash.el: New version from Paul Foley with new
+       mail-check-payment function.
+
 2002-06-22  Simon Josefsson  <jas@extundo.com>
 
        * hashcash.el: New file.
index b3c32fc..5ec251f 100644 (file)
@@ -27,16 +27,29 @@ If this is zero, no payment header will be generated.
 See `hashcash-payment-alist'."
   :type 'integer)
 
-(defcustom hashcash-payment-alist nil
+(defcustom hashcash-payment-alist '()
   "*An association list mapping email addresses to payment amounts.
 Elements may consist of (ADDR AMOUNT) or (ADDR STRING AMOUNT), where
 ADDR is the email address of the intended recipient and AMOUNT is
 the value of hashcash payment to be made to that user.  STRING, if
 present, is the string to be hashed; if not present ADDR will be used.")
 
+(defcustom hashcash-default-accept-payment 10
+  "*The default minimum number of bits to accept on incoming payments."
+  :type 'integer)
+
+(defcustom hashcash-accept-resources `((,(user-mail-address) nil))
+  "*An association list mapping hashcash resources to payment amounts.
+Resources named here are to be accepted in incoming payments.  If the
+corresponding AMOUNT is NIL, the value of `hashcash-default-accept-payment'
+is used instead.")
+
 (defcustom hashcash "/usr/local/bin/hashcash"
   "*The path to the hashcash binary.")
 
+(defcustom hashcash-double-spend-database "hashcash.db"
+  "*The path to the double-spending database.")
+
 (defcustom hashcash-in-news nil
   "*Specifies whether or not hashcash payments should be made to newsgroups."
   :type 'boolean)
@@ -80,18 +93,41 @@ present, is the string to be hashed; if not present ADDR will be used.")
        (buffer-substring (point-at-bol) (point-at-eol)))
     nil))
 
+(defun hashcash-check-payment (token str val)
+  "Check the validity of a hashcash payment."
+  (zerop (call-process hashcash nil nil nil "-c"
+                      "-d" "-f" hashcash-double-spend-database
+                      "-b" (number-to-string val)
+                      "-r" str
+                      token)))
+
+;;;###autoload
 (defun hashcash-insert-payment (arg)
-  "Insert an X-Hashcash header with a payment for ARG"
+  "Insert X-Payment and X-Hashcash headers with a payment for ARG"
   (interactive "sPay to: ")
   (let ((pay (hashcash-generate-payment (hashcash-payment-to arg)
                                        (hashcash-payment-required arg))))
     (when pay
+      (insert-before-markers "X-Payment: hashcash 1.1 " pay "\n")
       (insert-before-markers "X-Hashcash: " pay "\n"))))
 
 ;;;###autoload
+(defun hashcash-verify-payment (token &optional resource amount)
+  "Verify a hashcash payment"
+  (let ((key (cadr (split-string-by-char token ?:))))
+    (cond ((null resource)
+          (let ((elt (assoc key hashcash-accept-resources)))
+            (and elt (hashcash-check-payment token (car elt)
+                       (or (cadr elt) hashcash-default-accept-payment)))))
+         ((equal token key)
+          (hashcash-check-payment token resource
+                               (or amount hashcash-default-accept-payment)))
+         (t nil))))
+
+;;;###autoload
 (defun mail-add-payment (&optional arg)
-  "Add an X-Hashcash: header with a hashcash payment for each recipient address
-Prefix arg sets default payment temporarily."
+  "Add X-Payment: and X-Hashcash: headers with a hashcash payment
+for each recipient address.  Prefix arg sets default payment temporarily."
   (interactive "P")
   (let ((hashcash-default-payment (if arg (prefix-numeric-value arg)
                                    hashcash-default-payment))
@@ -118,6 +154,31 @@ Prefix arg sets default payment temporarily."
          (hashcash-insert-payment (pop addrlist))))))
   t)
 
+;;;###autoload
+(defun mail-check-payment (&optional arg)
+  "Look for a valid X-Payment: or X-Hashcash: header.
+Prefix arg sets default accept amount temporarily."
+  (interactive "P")
+  (let ((hashcash-default-accept-payment (if arg (prefix-numeric-value arg)
+                                          hashcash-default-accept-payment)))
+    (save-excursion
+      (goto-char (point-min))
+      (search-forward mail-header-separator)
+      (beginning-of-line)
+      (let ((end (point))
+           (ok nil))
+       (goto-char (point-min))
+       (while (and (not ok) (search-forward "X-Payment: hashcash 1.1 " end t))
+         (setq ok (hashcash-verify-payment
+                   (buffer-substring (point) (point-at-eol)))))
+       (goto-char (point-min))
+       (while (and (not ok) (search-forward "X-Hashcash: " end t))
+         (setq ok (hashcash-verify-payment
+                   (buffer-substring (point) (point-at-eol)))))
+       (when ok
+         (message "Payment valid"))
+       ok))))
+
 (provide 'hashcash)
 
 ;;; hashcash.el ends here
index 9c90550..a689811 100644 (file)
@@ -1,5 +1,81 @@
+2002-12-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-start.el (gnus-load): Replace `ding-file' with `file'.
+
 2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
+       * gnus-start.el (gnus-load): New function.
+       (gnus-read-newsrc-el-file): Use it.
+
+2002-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-button-valid-fqdn-regexp): New variable.
+       (gnus-button-handle-apropos-documentation): New function.
+       (gnus-button-handle-ctan): New function.
+       (gnus-button-alist): Use them.  Improve some regexps.
+       (gnus-button-prefer-mid-or-mail): Addition to doc-string.
+
+2002-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-subscribed-p): New function.
+       (message-send-mail): Use it.
+       * mml.el (mml-preview-insert-mft): New function.
+       (mml-preview): Use it.
+
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-thread-latest-date): Protect against errors
+       when sorting by date.
+
+       * gnus-art.el (gnus-article-edit-mode): New variable.
+       (gnus-article-setup-buffer): Warn user about discarding edits. 
+
+       * gnus-sum.el (gnus-summary-pipe-output): Clean up.
+       (gnus-summary-pipe-output): Take a symbolic prefix to save all
+       headers. 
+
+       * mm-uu.el (mm-uu-configure-list): Default to (shar . disabled). 
+
+2002-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-completion-alist): Added "Mail-Followup-To"
+       and "Mail-Copies-To".
+
+2002-07-21  Jesper harder  <harder@ifa.au.dk>
+
+       * gnus-group.el: Add key bindings for
+       gnus-group-sort-groups-by-real-name and
+       gnus-group-sort-selected-groups-by-real-name.
+
+2002-07-21  Jesper harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Sorting Groups): Add key bindings for
+       gnus-group-sort-groups-by-real-name and
+       gnus-group-sort-selected-groups-by-real-name.
+
+2002-12-30  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-use-dig): new variable for blackhole checking
+       through dig.el
+       (spam-check-blackholes): added dig.el checking functionality and
+       more verbose reporting; query-dig is autoloaded from dig.el
+       (spam-use-blackholes): disabled by default
+       (spam-blackhole-servers): removed rbl.maps.vix.com from the
+       blackhole servers list
+
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-required-headers): New variable.
+
+2002-12-30  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * dig.el (query-dig): new function
+
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * flow-fill.el (fill-flowed): Don't infloop on too long fill
+       prefixes. 
+
        * dns.el (query-dns): Protect against errors.
 
        * gnus-msg.el (gnus-article-yanked-articles): New variable.
index d719c38..b13b7af 100644 (file)
@@ -168,6 +168,18 @@ Optional arguments are passed to `dig-invoke'."
   (setq buffer-read-only t)
   (set-buffer-modified-p nil))
 
+;; named for consistency with query-dns in dns.el
+(defun query-dig (domain &optional
+                  query-type query-class query-option dig-option server)
+  "Query addresses of a DOMAIN using dig, by calling `dig-invoke' and `dig-extract-rr'.
+Optional arguments are passed to `dig-invoke' and `dig-extract-rr'.  Returns nil for a nonexistent domain."
+(let ((buffer (dig-invoke domain query-type query-class query-option dig-option server)))
+  (when buffer
+    (switch-to-buffer buffer)
+    (let ((digger (dig-extract-rr domain query-type query-class)))
+      (kill-buffer buffer)
+      digger))))
+
 (provide 'dig)
 
 ;;; dig.el ends here
index 654bf40..987113d 100644 (file)
@@ -109,7 +109,8 @@ RFC 2646 suggests 66 characters for readability."
       (when (save-excursion
              (beginning-of-line)
              (looking-at "^\\(>*\\)\\( ?\\)"))
-       (let ((quote (match-string 1)) sig)
+       (let ((quote (match-string 1))
+             sig)
          (if (string= quote "")
              (setq quote nil))
          (when (and quote (string= (match-string 2) ""))
@@ -139,9 +140,12 @@ RFC 2646 suggests 66 characters for readability."
                      (fill-column (eval fill-flowed-display-column))
                      filladapt-mode)
                  (fill-region (fill-flowed-point-at-bol)
-                              (min (1+ (fill-flowed-point-at-eol)) (point-max))
+                              (min (1+ (fill-flowed-point-at-eol))
+                                   (point-max))
                               'left 'nosqueeze))
-             (error nil))))))))
+             (error
+              (forward-line 1)
+              nil))))))))
 
 (provide 'flow-fill)
 
index af1016a..ab6e70e 100644 (file)
@@ -1969,80 +1969,79 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)."
   (interactive)
 
   (if (or (not (eq articles t))
-          (yes-or-no-p (concat "Are you sure that you want to expire all articles in " (if group group "every agentized group") ".")))
+         (yes-or-no-p (concat "Are you sure that you want to expire all articles in " (if group group "every agentized group") ".")))
       (let ((methods (if group
-                         (list (gnus-find-method-for-group group))
-                       gnus-agent-covered-methods))
-            (day (if (numberp gnus-agent-expire-days)
-                     (- (time-to-days (current-time)) gnus-agent-expire-days)
-                   nil))
-            gnus-command-method sym arts pos
-            history overview file histories elem art nov-file low info
-            unreads marked article orig lowest highest found days)
-        (save-excursion
-          (setq overview (gnus-get-buffer-create " *expire overview*"))
+                        (list (gnus-find-method-for-group group))
+                      gnus-agent-covered-methods))
+           (day (if (numberp gnus-agent-expire-days)
+                    (- (time-to-days (current-time)) gnus-agent-expire-days)
+                  nil))
+           gnus-command-method sym arts pos
+           history overview file histories elem art nov-file low info
+           unreads marked article orig lowest highest found days)
+       (save-excursion
+         (setq overview (gnus-get-buffer-create " *expire overview*"))
          (unwind-protect
-          (while (setq gnus-command-method (pop methods))
-            (when (file-exists-p (gnus-agent-lib-file "active"))
-              (with-temp-buffer
-                (nnheader-insert-file-contents (gnus-agent-lib-file "active"))
-                (gnus-active-to-gnus-format
-                 gnus-command-method
-                 (setq orig (gnus-make-hashtable
-                             (count-lines (point-min) (point-max))))))
-              (dolist (expiring-group (gnus-groups-from-server gnus-command-method))
-                (if (or (not group)
-                        (equal group expiring-group))
-                    (let* ((dir (concat
-                                 (gnus-agent-directory)
+             (while (setq gnus-command-method (pop methods))
+               (when (file-exists-p (gnus-agent-lib-file "active"))
+                 (with-temp-buffer
+                   (nnheader-insert-file-contents (gnus-agent-lib-file "active"))
+                   (gnus-active-to-gnus-format
+                    gnus-command-method
+                    (setq orig (gnus-make-hashtable
+                                (count-lines (point-min) (point-max))))))
+                 (dolist (expiring-group (gnus-groups-from-server gnus-command-method))
+                   (if (or (not group)
+                           (equal group expiring-group))
+                       (let* ((dir (concat
+                                    (gnus-agent-directory)
                                     (gnus-agent-group-path expiring-group) "/"))
                               (active
                                (gnus-gethash-safe expiring-group orig)))
                          (when active
-                             (gnus-agent-load-alist expiring-group)
-                             (gnus-message 5 "Expiring articles in %s" expiring-group)
-                             (let* ((info (gnus-get-info expiring-group))
-                                    (alist gnus-agent-article-alist)
-                                    (specials (if alist
-                                                  (list (caar (last alist)))))
+                           (gnus-agent-load-alist expiring-group)
+                           (gnus-message 5 "Expiring articles in %s" expiring-group)
+                           (let* ((info (gnus-get-info expiring-group))
+                                  (alist gnus-agent-article-alist)
+                                  (specials (if alist
+                                                (list (caar (last alist)))))
                                   (unreads ;; Articles that are excluded from the expiration process
-                                     (cond (gnus-agent-expire-all
-                                            ;; All articles are marked read by global decree
-                                            nil)
-                                           ((eq articles t)
-                                            ;; All articles are marked read by function parameter
-                                            nil)
-                                           ((not articles)
-                                            ;; Unread articles are marked protected from expiration
+                                   (cond (gnus-agent-expire-all
+                                          ;; All articles are marked read by global decree
+                                          nil)
+                                         ((eq articles t)
+                                          ;; All articles are marked read by function parameter
+                                          nil)
+                                         ((not articles)
+                                          ;; Unread articles are marked protected from expiration
                                           ;; Don't call gnus-list-of-unread-articles as it returns articles that have not been fetched into the agent.
                                           (ignore-errors (gnus-agent-unread-articles expiring-group)))
-                                           (t
-                                            ;; All articles EXCEPT those named by the caller are protected from expiration
-                                            (gnus-sorted-difference (gnus-uncompress-range (cons (caar alist) (caar (last alist)))) (sort articles '<)))))
+                                         (t
+                                          ;; All articles EXCEPT those named by the caller are protected from expiration
+                                          (gnus-sorted-difference (gnus-uncompress-range (cons (caar alist) (caar (last alist)))) (sort articles '<)))))
                                   (marked ;; More articles that are exluded from the expiration process
-                                     (cond (gnus-agent-expire-all
-                                            ;; All articles are unmarked by global decree
-                                            nil)
-                                           ((eq articles t)
-                                            ;; All articles are unmarked by function parameter
-                                            nil)
-                                           (articles
-                                            ;; All articles may as well be unmarked as the unreads list already names the articles we are going to keep
-                                            nil)
-                                           (t
-                                            ;; Ticked and/or dormant articles are excluded from expiration
-                                            (nconc
-                                             (gnus-uncompress-range
-                                              (cdr (assq 'tick (gnus-info-marks info))))
-                                             (gnus-uncompress-range
-                                              (cdr (assq 'dormant
-                                                         (gnus-info-marks info))))))
-                                           ))
-                                    (nov-file (concat dir ".overview"))
-                                    (cnt 0)
+                                   (cond (gnus-agent-expire-all
+                                          ;; All articles are unmarked by global decree
+                                          nil)
+                                         ((eq articles t)
+                                          ;; All articles are unmarked by function parameter
+                                          nil)
+                                         (articles
+                                          ;; All articles may as well be unmarked as the unreads list already names the articles we are going to keep
+                                          nil)
+                                         (t
+                                          ;; Ticked and/or dormant articles are excluded from expiration
+                                          (nconc
+                                           (gnus-uncompress-range
+                                            (cdr (assq 'tick (gnus-info-marks info))))
+                                           (gnus-uncompress-range
+                                            (cdr (assq 'dormant
+                                                       (gnus-info-marks info))))))))
+                                  (nov-file (concat dir ".overview"))
+                                  (cnt 0)
                                   (completed -1)
                                   dlist
-                                    type)
+                                  type)
 
                              ;; The normal article alist contains elements that look like (article# . fetch_date)
                              ;; I need to combine other information with this list.  For example, a flag indicating that a particular article MUST BE KEPT.
@@ -2061,16 +2060,16 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)."
                              (setq dlist (nconc dlist
                                                 (mapcar (lambda (e) (list e nil 'special nil)) specials)))
 
-                                 (set-buffer overview)
-                                 (erase-buffer)
+                             (set-buffer overview)
+                             (erase-buffer)
                              (when (file-exists-p nov-file)
                                (gnus-message 7 "gnus-agent-expire: Loading overview...")
-                                 (nnheader-insert-file-contents nov-file)
-                                 (goto-char (point-min))
-                         
+                               (nnheader-insert-file-contents nov-file)
+                               (goto-char (point-min))
+
                                (let (p)
                                  (while (< (setq p (point)) (point-max))
-                                          (condition-case nil
+                                   (condition-case nil
                                        ;; If I successfully read an integer (the plus zero ensures a numeric type), prepend a marker entry to the list
                                        (push (list (+ 0 (read (current-buffer))) nil nil (set-marker (make-marker) p)) dlist)
                                      (error
@@ -2082,21 +2081,20 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)."
 
                              ;; At this point, all of the information is in dlist.  The only problem is that much of it is spread across multiple entries.  Sort then MERGE!!
                              (gnus-message 7 "gnus-agent-expire: Sorting entries... ")
-                             (setq dlist
-                                   (let ((special 0) ; If two entries have the same article-number then sort by ascending keep_flag.
-                                         (marked 1)
-                                         (unread 2)
-                                         ;(nil 3)
-                                         )
-                                   (sort dlist (function (lambda (a b)
-                                                           (cond ((< (nth 0 a) (nth 0 b))
-                                                              t)
-                                                                 ((> (nth 0 a) (nth 0 b))
-                                                              nil)
-                                                             (t
-                                                                  (let ((a (or (symbol-value (nth 2 a)) 3))
-                                                                        (b (or (symbol-value (nth 2 b)) 3)))
-                                                                    (<= a b)))))))))
+                             (let ((special 0) ; If two entries have the same article-number then sort by ascending keep_flag.
+                                   (marked 1)
+                                   (unread 2))
+                               (setq dlist
+                                     (sort dlist
+                                           (lambda (a b)
+                                             (cond ((< (nth 0 a) (nth 0 b))
+                                                    t)
+                                                   ((> (nth 0 a) (nth 0 b))
+                                                    nil)
+                                                   (t
+                                                    (let ((a (or (symbol-value (nth 2 a)) 3))
+                                                          (b (or (symbol-value (nth 2 b)) 3)))
+                                                      (<= a b))))))))
                              (gnus-message 7 "gnus-agent-expire: Sorting entries... Done")
                              (gnus-message 7 "gnus-agent-expire: Merging entries... ")
                              (let ((dlist dlist))
@@ -2154,20 +2152,20 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)."
                                             ;; We now have the arrival day, so we see
                                             ;; whether it's old enough to be expired.
                                             ((< fetch-date
-                                                               (if (numberp day)
-                                                                   day
-                                                                 (let (found
-                                                                       (days gnus-agent-expire-days))
-                                                                   (while (and (not found)
-                                                                               days)
-                                                                     (when (eq 0 (string-match (caar days) expiring-group))
-                                                                       (setq found (cadar days)))
-                                                                     (pop days))
-                                                                   found)))
-                                                            'expired)
+                                                (if (numberp day)
+                                                    day
+                                                  (let (found
+                                                        (days gnus-agent-expire-days))
+                                                    (while (and (not found)
+                                                                days)
+                                                      (when (eq 0 (string-match (caar days) expiring-group))
+                                                        (setq found (cadar days)))
+                                                      (pop days))
+                                                    found)))
+                                             'expired)
                                             (force
                                              'forced)))
-                                          
+
                                      ;; I found some reason to expire this entry.
 
                                      (let ((actions nil))
@@ -2176,7 +2174,7 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)."
                                            (delete-file (concat dir (number-to-string article-number)))
                                            (push "expired cached article" actions))
                                          (setf (nth 1 entry) nil)
-                                         )
+                                         )
 
                                        (when marker
                                          (push "NOV entry removed" article)
@@ -2191,7 +2189,7 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)."
                                          (push (format "Removed %s article number from article alist" type) actions))
 
                                        (gnus-message 7 "gnus-agent-expire: Article %d: %s" article-number (mapconcat 'identity actions ", "))))
-                                 )
+                                    )
 
                                    ;; Clean up markers as I want to recycle this buffer over several groups.
                                    (when marker
@@ -2201,10 +2199,10 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)."
 
                                (setq alist (cdr alist))
 
-                               (let ((inhibit-quit t))
+                               (let ((inhibit-quit t))
                                  (unless (equal alist gnus-agent-article-alist)
                                    (setq gnus-agent-article-alist alist)
-                                     (gnus-agent-save-alist expiring-group))
+                                   (gnus-agent-save-alist expiring-group))
 
                                  (when (buffer-modified-p)
                                    (gnus-make-directory dir)
@@ -2213,12 +2211,10 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)."
                                     (point-min) (point-max) nov-file
                                     nil 'silent)
                                    ;; clear the modified flag as that I'm not confused by its status on the next pass through this routine.
-                                   (set-buffer-modified-p nil)
-                                   )
+                                   (set-buffer-modified-p nil))
 
                                  (when (eq articles t)
-                                     (gnus-summary-update-info))
-                                 )))))))))
+                                   (gnus-summary-update-info)))))))))))
            (kill-buffer overview)))))
   (gnus-message 4 "Expiry...done"))
 
index eaa3105..7afe1ed 100644 (file)
@@ -3698,6 +3698,12 @@ commands:
     (if (get-buffer name)
        (save-excursion
          (set-buffer name)
+         (when (and gnus-article-edit-mode
+                    (buffer-modified-p)
+                    (not
+                     (y-or-n-p "Article mode edit in progress; discard? ")))
+           (error "Action aborted"))
+         (set (make-local-variable 'gnus-article-edit-mode) nil)
          (buffer-disable-undo)
          (setq buffer-read-only t)
          (unless (eq major-mode 'gnus-article-mode)
@@ -5528,6 +5534,7 @@ If given a prefix, show the hidden text instead."
 (defvar gnus-article-edit-done-function nil)
 
 (defvar gnus-article-edit-mode-map nil)
+(defvar gnus-article-edit-mode nil)
 
 ;; Should we be using derived.el for this?
 (unless gnus-article-edit-mode-map
@@ -5602,6 +5609,7 @@ This is an extended text-mode.
   (set (make-local-variable 'font-lock-defaults)
        '(message-font-lock-keywords t))
   (set (make-local-variable 'mail-header-separator) "")
+  (set (make-local-variable 'gnus-article-edit-mode) t)
   (easy-menu-add message-mode-field-menu message-mode-map)
   (setq buffer-read-only nil)
   (buffer-enable-undo)
@@ -5833,6 +5841,18 @@ after replacing with the original article."
   :group 'gnus-article-buttons
   :type 'regexp)
 
+(defcustom gnus-button-valid-fqdn-regexp
+  (concat "[a-z0-9][-.a-z0-9]+\\." ;; [hostname.subdomain.]domain.
+         ;; valid TLDs:
+         "\\([a-z][a-z]" ;; two letter country TDLs
+         "\\|biz\\|com\\|edu\\|gov\\|int\\|mil\\|net\\|org"
+         "\\|aero\\|coop\\|info\\|name\\|museum"
+         "\\|arpa\\|pro\\|uucp\\|bitnet\\|bofh" ;; old style?
+         "\\)")
+  "Regular expression that matches a valid FQDN."
+  :group 'gnus-article-buttons
+  :type 'regexp)
+
 (defcustom gnus-button-man-handler 'manual-entry
   "Function to use for displaying man pages.
 The function must take at least one argument with a string naming the
@@ -5842,15 +5862,48 @@ man page."
                 (function :tag "Other"))
   :group 'gnus-article-buttons)
 
+(defcustom gnus-ctan-url "http://tug.ctan.org/tex-archive/"
+  "Top directory of a CTAN \(Comprehensive TeX Archive Network\) archive.
+If the default site is too slow, try to find a CTAN mirror, see
+<URL:http://tug.ctan.org/tex-archive/CTAN.sites?action=/index.html>.  See also
+the variable `gnus-button-handle-ctan'."
+  :group 'gnus-article-buttons
+  :link '(custom-manual "(gnus)Group Parameters")
+  :type '(choice (const "http://www.tex.ac.uk/tex-archive/")
+                (const "http://tug.ctan.org/tex-archive/")
+                (const "http://www.dante.de/CTAN/")
+                (string :tag "Other")))
+
+(defcustom gnus-button-ctan-handler 'browse-url
+  "Function to use for displaying CTAN links.
+The function must take one argument, the string naming the URL."
+  :type '(choice (function-item :tag "Browse Url" browse-url)
+                (function :tag "Other"))
+  :group 'gnus-article-buttons)
+
+(defcustom gnus-button-handle-ctan-bogus-regexp "^/?tex-archive/\\|^/"
+  "Bogus strings removed from CTAN URLs."
+  :group 'gnus-article-buttons
+  :type '(choice (const "^/?tex-archive/\\|/")
+                (regexp :tag "Other")))
+
+(defcustom gnus-button-mid-or-mail-regexp
+  (concat "\\b\\(<?[a-zA-Z0-9][^<>\")!;:,{}\n\t ]*@"
+         gnus-button-valid-fqdn-regexp
+         ">?\\)\\b")
+  "Regular expression that matches a message ID or a mail address."
+  :group 'gnus-article-buttons
+  :type 'regexp)
+
 (defcustom gnus-button-prefer-mid-or-mail 'guess
   "What to do when the button on a string as \"foo123@bar.com\" is pushed.
 Strings like this can be either a message ID or a mail address.  If the
 variable is set to the symbol `ask', query the user what do do.  If it is the
 symbol `guess', Gnus will do a guess and query the user what do do if it is
-ambiguous. If it is one of the sybols `mid' or `mail', Gnus will always assume
-that the string is a message ID or a mail address, respectivly.  See the
-variable `gnus-button-guessed-mid-regexp' for details concerning the
-guessing."
+ambiguous.  See the variable `gnus-button-guessed-mid-regexp' for details
+concerning the guessing.  If it is one of the sybols `mid' or `mail', Gnus
+will always assume that the string is a message ID or a mail address,
+respectivly."
   ;; FIXME: doc-string could/should be improved.
   :group 'gnus-article-buttons
   :type '(choice (const ask)
@@ -5933,10 +5986,35 @@ guessing."
    (if (fboundp 'apropos-variable) 'apropos-variable 'apropos)
    (gnus-replace-in-string url gnus-button-handle-describe-prefix "")))
 
+(defun gnus-button-handle-apropos-documentation (url)
+  "Call apropos when pushing the corresponding URL button."
+  (funcall
+   (if (fboundp 'apropos-documentation) 'apropos-documentation 'apropos)
+   (gnus-replace-in-string url gnus-button-handle-describe-prefix "")))
+
+(defun gnus-button-handle-ctan (url)
+  "Call `browse-url' when pushing a CTAN URL button."
+  (funcall
+   gnus-button-ctan-handler
+   (concat
+    gnus-ctan-url
+    (gnus-replace-in-string url gnus-button-handle-ctan-bogus-regexp ""))))
+
+(defcustom gnus-button-tex-level 5
+  "*Integer that says how many TeX-related buttons Gnus will show.
+The higher the number, the more buttons will appear and the more false
+positives are possible.  Note that you can set this variable local to
+specifific groups.  Setting it higher in TeX groups is probably a good idea.
+See Info node `(gnus)Group Parameters' and the variable `gnus-parameters' on
+how to set variables in specific groups."
+  :group 'gnus-article-buttons
+  :link '(custom-manual "(gnus)Group Parameters")
+  :type 'integer)
+
 (defcustom gnus-button-man-level 5
   "*Integer that says how many man-related buttons Gnus will show.
 The higher the number, the more buttons will appear and the more false
-positves are possible.  Note that you can set this variable local to
+positives are possible.  Note that you can set this variable local to
 specifific groups.  Setting it higher in Unix groups is probably a good idea.
 See Info node `(gnus)Group Parameters' and the variable `gnus-parameters' on
 how to set variables in specific groups."
@@ -5947,9 +6025,9 @@ how to set variables in specific groups."
 (defcustom gnus-button-emacs-level 5
   "*Integer that says how many emacs-related buttons Gnus will show.
 The higher the number, the more buttons will appear and the more false
-positves are possible.  Note that you can set this variable local to
+positives are possible.  Note that you can set this variable local to
 specifific groups.  Setting it higher in Emacs or Gnus related groups is
-probably a good idea.See Info node `(gnus)Group Parameters' and the variable
+probably a good idea.  See Info node `(gnus)Group Parameters' and the variable
 `gnus-parameters' on how to set variables in specific groups."
   :group 'gnus-article-buttons
   :link '(custom-manual "(gnus)Group Parameters")
@@ -5958,7 +6036,7 @@ probably a good idea.See Info node `(gnus)Group Parameters' and the variable
 (defcustom gnus-button-mail-level 5
   "*Integer that says how many buttons for message IDs or mail addresses will appear.
 The higher the number, the more buttons will appear and the more false
-positves are possible."
+positives are possible."
   :group 'gnus-article-buttons
   :type 'integer)
 
@@ -5976,6 +6054,9 @@ positves are possible."
     ("\\(<URL: *\\)mailto: *\\([^> \n\t]+\\)>" 0 t gnus-url-mailto 2)
     ("mailto:\\([-a-zA-Z.@_+0-9%=?]+\\)" 0 t gnus-url-mailto 1)
     ("\\bmailto:\\([^ \n\t]+\\)" 0 t gnus-url-mailto 1)
+    ;; CTAN
+    ("\\bCTAN:[ \t\n]*\\([^>)!;:,\n\t ]*\\)" 0 (>= gnus-button-tex-level 1)
+     gnus-button-handle-ctan 1)
     ;; This is info
     ("\\binfo:\\(//\\)?\\([^'\">\n\t ]+\\)" 0
      (>= gnus-button-emacs-level 1) gnus-button-handle-info 2)
@@ -5992,11 +6073,13 @@ positves are possible."
      0 (>= gnus-button-emacs-level 1) gnus-button-handle-apropos-command 1)
     ("M-x[ \t\n]+apropos-variable[ \t\n]+RET[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
      0 (>= gnus-button-emacs-level 1) gnus-button-handle-apropos-variable 1)
-    ("\\W\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+f[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+    ("M-x[ \t\n]+apropos-documentation[ \t\n]+RET[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-apropos-documentation 1)
+    ("\\b\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+f[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
      0 (>= gnus-button-emacs-level 1) gnus-button-handle-describe-function 2)
-    ("\\W\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+v[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+    ("\\b\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+v[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
      0 (>= gnus-button-emacs-level 1) gnus-button-handle-describe-variable 2)
-    ("\\W\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+k[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+" 0
+    ("\\b\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+k[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+" 0
      ;; this regexp needs to be fixed!
      (>= gnus-button-emacs-level 9) gnus-button-handle-describe-key 2)
     ;; This is how URLs _should_ be embedded in text...
@@ -6004,22 +6087,23 @@ positves are possible."
     ;; Raw URLs.
     (gnus-button-url-regexp 0 t browse-url 0)
     ;; man pages
-    ("\\b\\([a-z][a-z]+\\)([0-9])\\W" 0
+    ("\\b\\([a-z][a-z]+\\)([1-9])\\W" 0
      (and (>= gnus-button-man-level 1) (< gnus-button-man-level 3))
      gnus-button-handle-man 1)
     ;; more man pages: resolv.conf(5), iso_8859-1(7), xterm(1x)
-    ("\\b\\([a-zA-Z][-_.a-zA-Z0-9]+\\)([0-9])\\W" 0
+    ("\\b\\([a-zA-Z][-_.a-zA-Z0-9]+\\)([1-9])\\W" 0
      (and (>= gnus-button-man-level 3) (< gnus-button-man-level 5))
      gnus-button-handle-man 1)
-    ;; even more: Apache::PerlRun(3pm), PDL::IO::FastRaw(3pm), SoWWWAnchor(3iv)
-    ("\\b\\([a-zA-Z][-_.:a-zA-Z0-9]+\\)([0-9][a-z]*)\\W" 0
+    ;; even more: Apache::PerlRun(3pm), PDL::IO::FastRaw(3pm),
+    ;; SoWWWAnchor(3iv), XSelectInput(3X11)
+    ("\\b\\([a-zA-Z][-_.:a-zA-Z0-9]+\\)([1-9][X1a-z]*)\\W" 0
      (>= gnus-button-man-level 5) gnus-button-handle-man 1)
     ;; MID or mail: To avoid too many false positives we don't try to catch
     ;; all kind of allowed MIDs or mail addresses.  Domain part must contain
     ;; at least one dot.  TLD must contain two or three chars or be a know TLD
     ;; (info|name|...).  Put this entry near the _end_ of `gnus-button-alist'
     ;; so that non-ambiguous entries (see above) match first.
-    ("\\b\\(<?[a-zA-Z0-9][^<>\")!;:,{}\n\t ]*@[a-zA-Z0-9][-.a-zA-Z0-9]+\\.\\([a-zA-Z][a-zA-Z]\\([a-zA-Z]\\)?\\|[Ii][Nn][Ff][Oo]\\|[Nn][Aa][Mm][Ee]\\)>?\\)\\b"
+    (gnus-button-mid-or-mail-regexp
      0 (>= gnus-button-mail-level 5) gnus-button-handle-mid-or-mail 1))
   "*Alist of regexps matching buttons in article bodies.
 
index 275f68c..fe44b7d 100644 (file)
@@ -649,7 +649,8 @@ simple manner.")
     "l" gnus-group-sort-groups-by-level
     "v" gnus-group-sort-groups-by-score
     "r" gnus-group-sort-groups-by-rank
-    "m" gnus-group-sort-groups-by-method)
+    "m" gnus-group-sort-groups-by-method
+    "n" gnus-group-sort-groups-by-real-name)
 
   (gnus-define-keys (gnus-group-sort-selected-map "P" gnus-group-group-map)
     "s" gnus-group-sort-selected-groups
@@ -658,7 +659,8 @@ simple manner.")
     "l" gnus-group-sort-selected-groups-by-level
     "v" gnus-group-sort-selected-groups-by-score
     "r" gnus-group-sort-selected-groups-by-rank
-    "m" gnus-group-sort-selected-groups-by-method)
+    "m" gnus-group-sort-selected-groups-by-method
+    "n" gnus-group-sort-selected-groups-by-real-name)
 
   (gnus-define-keys (gnus-group-list-map "A" gnus-group-mode-map)
     "k" gnus-group-list-killed
index 4fb7865..fd5df3f 100644 (file)
@@ -2156,41 +2156,40 @@ If FORCE is non-nil, the .newsrc file is read."
          (kill-buffer (current-buffer))
          (gnus-message 5 "Reading %s...done" newsrc-file))))))
 
+(defun gnus-load (file &optional coding-system)
+  "Load FILE, but in such a way that read errors can be reported."
+  (with-temp-buffer
+    (if coding-system
+       (insert-file-contents-as-coding-system coding-system file)
+      (insert-file-contents file))
+    (while (not (eobp))
+      (condition-case type
+         (let ((form (read (current-buffer))))
+           (eval form))
+       (error
+        (unless (eq (car type) 'end-of-file)
+          (let ((error (format "Error in %s line %d" file
+                               (count-lines (point-min) (point)))))
+            (ding)
+            (unless (gnus-yes-or-no-p (concat error "; continue? "))
+              (error "%s" error)))))))))
+
 (defun gnus-read-newsrc-el-file (file)
   (let ((ding-file (concat file "d")))
     ;; We always, always read the .eld file.
     (gnus-message 5 "Reading %s..." ding-file)
     (let (gnus-newsrc-assoc)
-      (when (file-exists-p ding-file)
-       (with-temp-buffer
-         (if (or debug-on-error debug-on-quit)
-             (progn
-               (insert-file-contents-as-coding-system
-                gnus-ding-file-coding-system ding-file)
-               (eval-region (point-min) (point-max)))
-           (condition-case nil
-               (progn
-                 (insert-file-contents-as-coding-system
-                  gnus-ding-file-coding-system ding-file)
-                 (eval-region (point-min) (point-max)))
-             (error
-              (ding)
-              (or (not (or (zerop (buffer-size))
-                           (eq 'binary gnus-ding-file-coding-system)
-                           (gnus-re-read-newsrc-el-file ding-file)))
-                  (gnus-yes-or-no-p
-                   (format "Error in %s; continue? " ding-file))
-                  (error "Error in %s" ding-file))))))
-;;     ;; Older versions of `gnus-format-specs' are no longer valid
-;;     ;; in Oort Gnus 0.01.
-;;     (let ((version
-;;            (and gnus-newsrc-file-version
-;;                 (gnus-continuum-version gnus-newsrc-file-version))))
-;;       (when (or (not version)
-;;                 (< version 5.090009))
-;;         (setq gnus-format-specs gnus-default-format-specs)))
-       (when gnus-newsrc-assoc
-         (setq gnus-newsrc-alist gnus-newsrc-assoc))))
+      (gnus-load ding-file gnus-ding-file-coding-system)
+;;      ;; Older versions of `gnus-format-specs' are no longer valid
+;;      ;; in Oort Gnus 0.01.
+;;      (let ((version
+;;          (and gnus-newsrc-file-version
+;;               (gnus-continuum-version gnus-newsrc-file-version))))
+;;     (when (or (not version)
+;;               (< version 5.090009))
+;;       (setq gnus-format-specs gnus-default-format-specs)))
+      (when gnus-newsrc-assoc
+       (setq gnus-newsrc-alist gnus-newsrc-assoc)))
     (gnus-make-hashtable-from-newsrc-alist)
     (when (file-newer-than-file-p file ding-file)
       ;; Old format quick file
@@ -2205,35 +2204,35 @@ If FORCE is non-nil, the .newsrc file is read."
        (apply 'gnus-product-read-variable-file-1 (car list))
        (setq list (cdr list))))))
 
-(defun gnus-re-read-newsrc-el-file (file)
-  "Attempt to re-read .newsrc.eld file.  Returns `nil' if successful.
-The backup file \".newsrc.eld_\" will be created before re-reading."
-  (message "Error in %s; retrying..." file)
-  (if (and
-       (condition-case nil
-          (let ((backup (concat file "_")))
-            (copy-file file backup 'ok-if-already-exists 'keep-time)
-            (message " (The backup file %s has been created)" backup)
-            t)
-        (error nil))
-       (progn
-        (insert-file-contents-as-binary file nil nil nil 'replace)
-        (goto-char (point-min))
-        (when (re-search-forward
-               "^[\t ]*([\t\n\r ]*setq[\t\n\r ]+gnus-format-specs" nil t)
-          (delete-region (goto-char (match-beginning 0)) (forward-list 1))
-          (decode-coding-region (point-min) (point-max)
-                                gnus-ding-file-coding-system)
-          (condition-case nil
-              (progn
-                (eval-region (point-min) (point-max))
-                t)
-            (error nil)))))
-      (prog1
-         nil
-       (message "Error in %s; retrying...done" file))
-    (message "Error in %s; retrying...failed" file)
-    t))
+;;(defun gnus-re-read-newsrc-el-file (file)
+;;  "Attempt to re-read .newsrc.eld file.  Returns `nil' if successful.
+;;The backup file \".newsrc.eld_\" will be created before re-reading."
+;;  (message "Error in %s; retrying..." file)
+;;  (if (and
+;;       (condition-case nil
+;;        (let ((backup (concat file "_")))
+;;          (copy-file file backup 'ok-if-already-exists 'keep-time)
+;;          (message " (The backup file %s has been created)" backup)
+;;          t)
+;;      (error nil))
+;;       (progn
+;;      (insert-file-contents-as-binary file nil nil nil 'replace)
+;;      (goto-char (point-min))
+;;      (when (re-search-forward
+;;             "^[\t ]*([\t\n\r ]*setq[\t\n\r ]+gnus-format-specs" nil t)
+;;        (delete-region (goto-char (match-beginning 0)) (forward-list 1))
+;;        (decode-coding-region (point-min) (point-max)
+;;                              gnus-ding-file-coding-system)
+;;        (condition-case nil
+;;            (progn
+;;              (eval-region (point-min) (point-max))
+;;              t)
+;;          (error nil)))))
+;;      (prog1
+;;       nil
+;;     (message "Error in %s; retrying...done" file))
+;;    (message "Error in %s; retrying...failed" file)
+;;    t))
 
 (defun gnus-product-read-variable-file-1 (file checking-methods coding
                                               &rest variables)
index ff86153..238ce6d 100644 (file)
@@ -4429,19 +4429,19 @@ Unscored articles will be counted as having a score of zero."
 (defun gnus-thread-latest-date (thread)
   "Return the highest article date in THREAD."
   (let ((previous-time 0))
-    (apply 'max (mapcar
-                (lambda (header)
-                  (setq previous-time
-                        (time-to-seconds
-                         (mail-header-parse-date
-                          (condition-case ()
-                              (mail-header-date header)
-                            (error previous-time))))))
-                (sort
-                 (message-flatten-list thread)
-                 (lambda (h1 h2)
-                   (< (mail-header-number h1)
-                      (mail-header-number h2))))))))
+    (apply 'max
+          (mapcar
+           (lambda (header)
+             (setq previous-time
+                   (time-to-seconds
+                    (condition-case ()
+                        (mail-header-parse-date (mail-header-date header))
+                      (error previous-time)))))
+           (sort
+            (message-flatten-list thread)
+            (lambda (h1 h2)
+              (< (mail-header-number h1)
+                 (mail-header-number h2))))))))
 
 (defun gnus-thread-total-score-1 (root)
   ;; This function find the total score of the thread below ROOT.
@@ -6988,14 +6988,16 @@ If UNREAD is non-nil, only unread articles are selected."
    (and gnus-auto-select-same
        (gnus-summary-article-subject))))
 
-(defun gnus-summary-next-page (&optional lines circular)
+(defun gnus-summary-next-page (&optional lines circular stop)
   "Show next page of the selected article.
 If at the end of the current article, select the next article.
 LINES says how many lines should be scrolled up.
 
 If CIRCULAR is non-nil, go to the start of the article instead of
 selecting the next article when reaching the end of the current
-article."
+article.
+
+If STOP is non-nil, just stop when reaching the end of the message."
   (interactive "P")
   (setq gnus-summary-buffer (current-buffer))
   (gnus-set-global-variables)
@@ -7021,7 +7023,9 @@ article."
          (gnus-eval-in-buffer-window gnus-article-buffer
            (setq endp (gnus-article-next-page lines)))
          (when endp
-           (cond (circular
+           (cond (stop
+                  (gnus-message 3 "End of message"))
+                 (circular
                   (gnus-summary-beginning-of-article))
                  (lines
                   (gnus-message 3 "End of message"))
@@ -10545,20 +10549,22 @@ The variable `gnus-default-article-saver' specifies the saver function."
     (gnus-set-mode-line 'summary)
     n))
 
-(defun gnus-summary-pipe-output (&optional arg)
+(defun gnus-summary-pipe-output (&optional arg headers)
   "Pipe the current article to a subprocess.
 If N is a positive number, pipe the N next articles.
 If N is a negative number, pipe the N previous articles.
 If N is nil and any articles have been marked with the process mark,
-pipe those articles instead."
-  (interactive "P")
+pipe those articles instead.
+If HEADERS (the symbolic prefix), include the headers, too."
+  (interactive (gnus-interactive "P\ny"))
   (require 'gnus-art)
-  (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe))
+  (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe)
+       (gnus-save-all-headers (or headers gnus-save-all-headers)))
     (gnus-summary-save-article arg t))
   (let ((buffer (get-buffer "*Shell Command Output*")))
-    (if (and buffer
-            (with-current-buffer buffer (> (point-max) (point-min))))
-       (gnus-configure-windows 'pipe))))
+    (when (and buffer
+              (not (zerop (buffer-size buffer))))
+      (gnus-configure-windows 'pipe))))
 
 (defun gnus-summary-save-article-mail (&optional arg)
   "Append the current article to an mail file.
index 411953a..fa11f64 100644 (file)
@@ -345,10 +345,17 @@ Checks include `subject-cmsg', `multiple-headers', `sendsys',
   :group 'message-news
   :type '(repeat sexp))                        ; Fixme: improve this
 
+(defcustom message-required-headers '((optional . References))
+  "*Headers to be generated or promted for when sending a message.
+Also see `message-required-news-headers' and
+1message-required-mail-headers'."
+  :group 'message-news
+  :group 'message-headers
+  :type '(repeat sexp))
+
 (defcustom message-required-news-headers
   '(From Newsgroups Subject Date Message-ID
         (optional . Organization)
-        (optional . References)
         (optional . User-Agent))
   "*Headers to be generated or prompted for when posting an article.
 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
@@ -361,8 +368,7 @@ header, remove it from this list."
 
 (defcustom message-required-mail-headers
   '(From Subject Date (optional . In-Reply-To) Message-ID
-        (optional . User-Agent)
-        (optional . References))
+        (optional . User-Agent))
   "*Headers to be generated or prompted for when mailing a message.
 It is recommended that From, Date, To, Subject and Message-ID be
 included.  Organization and User-Agent are optional."
@@ -2124,6 +2130,13 @@ Point is left at the beginning of the narrowed-to region."
                   (message-fetch-field "cc")
                   (message-fetch-field "bcc")))))))
 
+(defun message-subscribed-p ()
+  "Say whether we need to insert a MFT header."
+  (or message-subscribed-regexps
+      message-subscribed-addresses
+      message-subscribed-address-file
+      message-subscribed-address-functions))
+
 (defun message-next-header ()
   "Go to the beginning of the next header."
   (beginning-of-line)
@@ -3851,10 +3864,7 @@ This sub function is for exclusive use of `message-send-mail'."
     (save-restriction
       (message-narrow-to-headers)
       ;; Generate the Mail-Followup-To header if the header is not there...
-      (if (and (or message-subscribed-regexps
-                  message-subscribed-addresses
-                  message-subscribed-address-file
-                  message-subscribed-address-functions)
+      (if (and (message-subscribed-p)
               (not (mail-fetch-field "mail-followup-to")))
          (setq headers
                (cons
@@ -5116,6 +5126,7 @@ string."
 (defun message-generate-headers (headers)
   "Prepare article HEADERS.
 Headers already prepared in the buffer are not modified."
+  (setq headers (append headers message-required-headers))
   (save-restriction
     (message-narrow-to-headers)
     (let* ((Date (message-make-date))
@@ -6645,7 +6656,9 @@ which specify the range to operate on."
 (defcustom message-completion-alist
   (list (cons message-newgroups-header-regexp 'message-expand-group)
        '("^\\(Resent-\\)?\\(To\\|B?Cc\\):" . message-expand-name)
-       '("^\\(Reply-To\\|From\\|Disposition-Notification-To\\|Return-Receipt-To\\):" 
+       '("^\\(Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\):" 
+         . message-expand-name)
+       '("^\\(Disposition-Notification-To\\|Return-Receipt-To\\):" 
          . message-expand-name))
   "Alist of (RE . FUN).  Use FUN for completion on header lines matching RE."
   :group 'message
index 0ff83a9..ffc4353 100644 (file)
@@ -141,7 +141,7 @@ This can be either \"inline\" or \"attachment\".")
      nil
      mm-uu-emacs-sources-test)))
 
-(defcustom mm-uu-configure-list nil
+(defcustom mm-uu-configure-list '((shar . disabled))
   "A list of mm-uu configuration.
 To disable dissecting shar codes, for instance, add
 `(shar . disabled)' to this list."
index ae5fa83..d19ecaa 100644 (file)
@@ -1007,6 +1007,16 @@ TYPE is the MIME type to use."
   (mml-insert-tag 'part 'type type 'disposition "inline")
   (forward-line -1))
 
+(defun mml-preview-insert-mft ()
+  "Insert a Mail-Followup-To header before previewing an article.
+Should be adopted if code in `message-send-mail' is changed."
+  (when (and (message-mail-p)
+            (message-subscribed-p)
+            (not (mail-fetch-field "mail-followup-to"))
+            (message-make-mft))
+    (message-position-on-field "Mail-Followup-To" "X-Draft-From")
+    (insert (message-make-mft))))
+
 (defun mml-preview (&optional raw)
   "Display current buffer with Gnus, in a new buffer.
 If RAW, don't highlight the article."
@@ -1027,6 +1037,7 @@ If RAW, don't highlight the article."
                                   "*MIME preview of ") (buffer-name))))
       (erase-buffer)
       (insert-buffer buf)
+      (mml-preview-insert-mft)
       (let ((message-deletable-headers (if (message-news-p)
                                           nil
                                         message-deletable-headers)))
index bb399c4..cbbad60 100644 (file)
 (eval-and-compile
   (autoload 'ifile-spam-filter "ifile-gnus"))
 
+;; autoload query-dig
+(eval-and-compile
+  (autoload 'query-dig "dig"))
+
 ;;; Main parameters.
 
+(defvar spam-use-dig t
+  "True if query-dig should be used instead of query-dns.")
+
 (defvar spam-use-blacklist t
   "True if the blacklist should be used.")
 
@@ -63,7 +70,6 @@
   "True if the whitelist should be used.")
 
 (defvar spam-use-blackholes nil
-  ;; FIXME!  Turned off for now.  The DNS routines are said to be flaky.
   "True if blackholes should be used.")
 
 (defvar spam-use-bogofilter nil
@@ -208,12 +214,11 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
 (defvar spam-blackhole-servers '("bl.spamcop.net"
                                 "relays.ordb.org"
                                 "dev.null.dk"
-                                "relays.visi.com"
-                                "rbl.maps.vix.com")
+                                "relays.visi.com")
   "List of blackhole servers.")
 
 (defun spam-check-blackholes ()
-  "Check the Receieved headers for blackholed relays."
+  "Check the Received headers for blackholed relays."
   (let ((headers (message-fetch-field "received"))
        ips matches)
     (when headers
@@ -229,9 +234,17 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
                ips)))
       (dolist (server spam-blackhole-servers)
        (dolist (ip ips)
-         (when (query-dns (concat ip "." server))
-           (push (list ip server (query-dns (concat ip "." server) 'TXT))
-                 matches)))))
+         (let ((query-string (concat ip "." server)))
+           (if spam-use-dig
+               (let ((query-result (query-dig query-string)))
+                 (when query-result
+                   (message "spam detected with blackhole check of relay %s (dig query result '%s')" query-string query-result)
+                   (push (list ip server query-result)
+                         matches)))
+             ;; else, if not using dig.el
+             (when (query-dns query-string)
+               (push (list ip server (query-dns query-string 'TXT))
+                     matches)))))))
     (when matches
       spam-split-group)))
 \f
index 83702b5..5880afa 100644 (file)
@@ -1,3 +1,12 @@
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Saving Articles): Addition.
+
+2002-12-30  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Blackholes): added information on query-dig and
+       dig.el; users are told that using blackhole checks is OK now
+
 2002-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus.texi (Loose Threads): add
index 91bebfa..7f72514 100644 (file)
@@ -3219,7 +3219,7 @@ kill \e$B$5$l$?%0%k!<%W$rA4$FI=<($7$^$9\e(B (@code{gnus-group-list-killed})\e$B!#@\
 
 @item gnus-group-sort-by-real-name
 @findex gnus-group-sort-by-real-name
-\e$B%0%k!<%W$rK\Ev$N\e(B (\e$BA0$K2?$b$D$$$F$$$J$$\e(B) \e$B%0%k!<%WL>$G%"%k%U%!%Y%C%H=g$KJB\e(B
+\e$B%0%k!<%W$rK\Ev$N\e(B (\e$BA0$K2?$bIU$$$F$$$J$$\e(B) \e$B%0%k!<%WL>$G%"%k%U%!%Y%C%H=g$KJB\e(B
 \e$B$YJQ$($^$9!#\e(B
 
 @item gnus-group-sort-by-level
@@ -3290,6 +3290,12 @@ kill \e$B$5$l$?%0%k!<%W$rA4$FI=<($7$^$9\e(B (@code{gnus-group-list-killed})\e$B!#@\
 @findex gnus-group-sort-groups-by-method
 \e$B%0%k!<%W%P%C%U%!$r%P%C%/%(%s%I$NL>A0$G%"%k%U%!%Y%C%H=g$KJB$YBX$($^\e(B
 \e$B$9\e(B (@code{gnus-group-sort-groups-by-method})\e$B!#\e(B
+
+@item G S n
+@kindex G S n (Group)
+@findex gnus-group-sort-groups-by-real-name
+\e$B%0%k!<%W%P%C%U%!$rK\Ev$N\e(B (\e$BA0$K2?$bIU$$$F$$$J$$\e(B) \e$B%0%k!<%WL>$G%"%k%U%!%Y%C\e(B
+\e$B%H=g$KJB$YBX$($^$9\e(B (@code{gnus-group-sort-groups-by-real-name})\e$B!#\e(B
 @end table
 
 \e$B0J2<$NA4$F$NL?Na$O%W%m%;%9\e(B/\e$B@\F,<-$N=,47$K=>$$$^\e(B
@@ -3338,6 +3344,12 @@ kill \e$B$5$l$?%0%k!<%W$rA4$FI=<($7$^$9\e(B (@code{gnus-group-list-killed})\e$B!#@\
 \e$B%0%k!<%W$r%P%C%/%(%s%I$NL>A0$G%"%k%U%!%Y%C%H=g$KJB$YBX$($^\e(B
 \e$B$9\e(B (@code{gnus-group-sort-selected-groups-by-method})\e$B!#\e(B
 
+@item G P n
+@kindex G P n (Group)
+@findex gnus-group-sort-selected-groups-by-real-name
+\e$B%0%k!<%W$rK\Ev$N\e(B (\e$BA0$K2?$bIU$$$F$$$J$$\e(B) \e$B%0%k!<%WL>$G%"%k%U%!%Y%C%H=g$KJB\e(B
+\e$B$YBX$($^$9\e(B (@code{gnus-group-sort-selected-groups-by-real-name})\e$B!#\e(B
+
 @item G P s
 @kindex G P s (\e$B%0%k!<%W\e(B)
 @findex gnus-group-sort-selected-groups
@@ -7059,7 +7071,8 @@ Gnus \e$B$O$?$/$5$s$NJ}K!$G5-;v$rJ]B8$9$k;v$,$G$-$^$9!#0J2<$N$b$N$OHs>o$KN(\e(B
 @findex gnus-summary-pipe-output
 \e$B8=:_$N5-;v$r%Q%$%W$KJ]B8$7$^$9!#$&!<$s$H!"$"$N$)!";d$,8@$*$&$H$7$F$$$k;v\e(B
 \e$B$O!=!=8=:_$N5-;v$r%W%m%;%9$K%Q%$%W$9$k$H$$$&$3$H$G\e(B
-\e$B$9\e(B (@code{gnus-summary-pipe-output})\e$B!#\e(B
+\e$B$9\e(B (@code{gnus-summary-pipe-output})\e$B!#%7%s%\%k@\F,<-\e(B (@pxref{Symbolic
+Prefixes}) \e$B$,M?$($i$l$k$H!"%Q%$%W$X$N=PNO$K40A4$J%X%C%@!<$r4^$a$^$9!#\e(B
 
 @item O P
 @kindex O P (\e$B35N,\e(B)
@@ -21021,13 +21034,19 @@ Bogofilter \e$B$+\e(B ifile (@code{spam-use-bogofilter} \e$B$H\e(B @code{spam-use-if
 
 @defvar spam-use-blackholes
 
-\e$B$3$N%*%W%7%g%s$r%;%C%H$9$k$H!"\e(Bgnus \e$B$K%V%i%C%/%[!<%k7?$NJ,;6\e(B spam \e$B=hM}%7\e(B
-\e$B%9%F%`\e(B (\e$BNc$($P\e(B DCC) \e$B$rD4$Y$5$;$k$3$H$,$G$-$^$9!#JQ\e(B
-\e$B?t\e(B @code{spam-blackhole-servers} \e$B$O!"\e(Bgnus \e$B$,0U8+$r5a$a$k%V%i%C%/%[!<%k!&\e(B
-\e$B%5!<%P!<$N%j%9%H$r;}$A$^$9!#\e(B
-
-\e$B$3$NJQ?t$O%G%#%U%)%k%H$GL58z$K$J$C$F$$$^$9!#\e(B@code{dns.el} \e$B$N%3!<%I$K%P%0\e(B
-\e$B$,$"$k$N$G!"8=;~E@$G$O?d>)$5$l$^$;$s!#\e(B
+\e$B$3$N%*%W%7%g%s$O%G%#%U%)%k%H$GL58z$K$J$C$F$$$^$9!#$3$N%*%W%7%g%s$r%;%C%H\e(B
+\e$B$9$k$H!"\e(Bgnus \e$B$K%V%i%C%/%[!<%k7?$NJ,;6\e(B spam \e$B=hM}%7%9%F%`\e(B (\e$BNc$($P\e(B DCC) \e$B$r\e(B
+\e$BD4$Y$5$;$k$3$H$,$G$-$^$9!#JQ?t\e(B @code{spam-blackhole-servers} \e$B$O!"\e(Bgnus \e$B$,\e(B
+\e$B0U8+$r5a$a$k%V%i%C%/%[!<%k!&%5!<%P!<$N%j%9%H$r;}$A$^$9!#8=:_$N%j%9%H$O$+\e(B
+\e$B$J$j9-HO0O$KEO$C$F$$$^$9$,!"$b$7;~BeCY$l$J%5!<%P!<$r4^$s$G$$$?$i;d$?$A$K\e(B
+\e$BCN$i$;$k$?$a$K!"3NG'$7$F2<$5$$!#\e(B
+
+\e$B%V%i%C%/%[!<%k!&%A%'%C%/$O\e(B @code{dig.el} \e$B%Q%C%1!<%8$r;H$$$^$9!#$7$+\e(B
+\e$B$7\e(B @code{spam-use-dig} \e$B$r\e(B nil \e$B$K@_Dj$9$l$P!"$h$jNI$$@-G=$N$?$a\e(B
+\e$B$K\e(B @code{dns.el} \e$B$rBe$o$j$K;H$&$3$H$r\e(B @code{spam.el} \e$B$K;X<($9$k$3$H$,$G\e(B
+\e$B$-$^$9!#8=>u$G$O\e(B @code{spam-use-dig} \e$B$r\e(B nil \e$B$K@_Dj$9$k$3$H$O!"$$$/?M$+$N\e(B
+\e$B%f!<%6!<$,;H$($J$$$+$b$7$l$J$$$N$G!"$=$l$,2DG=$J@-G=2~A1$G$"$k$K$b$+$+$o\e(B
+\e$B$i$:?d>)$5$l$^$;$s!#$7$+$7!"$=$l$,F0$/$+$I$&$+$r3N$+$a$k$3$H$O$G$-$^$9!#\e(B
 
 @end defvar
 
index 9de02ae..9c59319 100644 (file)
@@ -3208,6 +3208,12 @@ Sort the group buffer by group rank
 Sort the group buffer alphabetically by back end name
 (@code{gnus-group-sort-groups-by-method}).
 
+@item G S n
+@kindex G S n (Group)
+@findex gnus-group-sort-groups-by-real-name
+Sort the group buffer alphabetically by real (unprefixed) group name
+(@code{gnus-group-sort-groups-by-real-name}).
+
 @end table
 
 All the commands below obey the process/prefix convention
@@ -3255,6 +3261,12 @@ Sort the groups by group rank
 Sort the groups alphabetically by back end name
 (@code{gnus-group-sort-selected-groups-by-method}).
 
+@item G P n
+@kindex G P n (Group)
+@findex gnus-group-sort-selected-groups-by-real-name
+Sort the groups alphabetically by real (unprefixed) group name
+(@code{gnus-group-sort-selected-groups-by-real-name}).
+
 @item G P s
 @kindex G P s (Group)
 @findex gnus-group-sort-selected-groups
@@ -7160,6 +7172,8 @@ Save the current article in a VM folder
 @findex gnus-summary-pipe-output
 Save the current article in a pipe.  Uhm, like, what I mean is---Pipe
 the current article to a process (@code{gnus-summary-pipe-output}).
+If given a symbolic prefix (@pxref{Symbolic Prefixes}), include the
+complete headers in the piped output.
 
 @item O P
 @kindex O P (Summary)
@@ -21481,13 +21495,19 @@ will be allowed through; all others will be classified as spam.
 
 @defvar spam-use-blackholes
 
-You can let Gnus consult the blackhole-type distributed spam
-processing systems (DCC, for instance) when you set this option.  The
-variable @code{spam-blackhole-servers} holds the list of blackhole servers
-Gnus will consult.
-
-This variable is disabled by default.  It is not recommended at this
-time because of bugs in the @code{dns.el} code.
+This option is disabled by default.  You can let Gnus consult the
+blackhole-type distributed spam processing systems (DCC, for instance)
+when you set this option.  The variable @code{spam-blackhole-servers}
+holds the list of blackhole servers Gnus will consult.  The current
+list is fairly comprehensive, but make sure to let us know if it
+contains outdated servers.
+
+The blackhole check uses the @code{dig.el} package, but you can tell
+@code{spam.el} to use @code{dns.el} instead for better performance if
+you set @code{spam-use-dig} to nil.  It is not recommended at this
+time to set @code{spam-use-dig} to nil despite the possible
+performance improvements, because some users may be unable to use it,
+but you can try it and see if it works for you.
 
 @end defvar
 
index dc02e2b..48a907b 100644 (file)
@@ -1137,8 +1137,11 @@ Message \e$B$O%a%C%;!<%8:n@.ItJ,$K4X$7$F$OHs>o$K@Q6KE*$G$9!#$=$l$O<!$N$h$&$G\e(B
 @code{nil} \e$B$G$J$1$l$P!"%a%C%;!<%8$N:n@.$r;O$a$kA0$KA4$F$NI,MW$J%X%C%@!<\e(B
 \e$B$r:n@.$7$^$9!#\e(B
 
-\e$BJQ?t\e(B @code{message-required-mail-headers} \e$B$H\e(B @code{message-required-news-headers} \e$B$G!"\e(B
-\e$B$I$N%X%C%@!<$,I,MW$+$r;XDj$7$^$9!#\e(B
+@vindex message-required-headers
+\e$BJQ?t\e(B @code{message-required-headers}\e$B!"\e(B
+@code{message-required-mail-headers} \e$B$*$h\e(B
+\e$B$S\e(B @code{message-required-news-headers} \e$B$G!"$I$N%X%C%@!<$,I,MW$+$r;XDj$7\e(B
+\e$B$^$9!#\e(B
 
 \e$B$$$/$D$+$N%X%C%@!<$O!"Aw?.$9$kA0$K>C$5$l$?$j:n$jD>$5$l$?$j$7$^$9!#$3$l$K\e(B
 \e$B$OJQ?t\e(B @code{message-deletable-headers} (\e$B8e=R\e(B) \e$B$,4X78$7$^$9!#\e(B
index 3905d30..4008078 100644 (file)
@@ -1133,8 +1133,11 @@ look sufficiently similar.
 If non-@code{nil}, generate all required headers before starting to
 compose the message.
 
-The variables @code{message-required-mail-headers} and
-@code{message-required-news-headers} specify which headers are required.
+@vindex message-required-headers
+The variables @code{message-required-headers},
+@code{message-required-mail-headers} and
+@code{message-required-news-headers} specify which headers are
+required.
 
 Note that some headers will be removed and re-generated before posting,
 because of the variable @code{message-deletable-headers} (see below).