From: yamaoka Date: Mon, 6 Jan 2003 08:28:00 +0000 (+0000) Subject: Synch with Oort Gnus. X-Git-Tag: t-gnus-6_15_12-00-quimby~46 X-Git-Url: http://git.chise.org/gitweb/?a=commitdiff_plain;h=73bd575d44dbaca134800a63f478cb671bc5df8f;p=elisp%2Fgnus.git- Synch with Oort Gnus. --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 3891842..66f3d53 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,59 @@ +2002-01-06 Kevin Greiner + + * gnus-agent.el (gnus-agent-fetch-group): Modified to permit execution + in either the group or summary buffer. + New command "JS", in summary buffer, will fetch articles per the + group's category, predicate, and processable flags. + (gnus-agent-summary-fetch-series): Rewritten to call + gnus-agent-session-fetch-group once with all articles in the + series. + (gnus-agent-summary-fetch-group): Fixed bug and modified code to + return list of fetched articles. + (gnus-agent-fetch-articles): Split fetch list into sublists such + that the article buffer is only slightly larger than + gnus-agent-max-fetch-size. Added unwind-protect to ensure that + the group's article alist is saved. + (gnus-agent-fetch-headers): The 'killed' and 'cached' marks no + longer result in the agent trying to fetch an article. + (gnus-agent-fetch-group-1): Can now be called in either the group + or summary buffer. Removed the max-fetch-size code that I added + on 2002-12-13 as that capability is now part of + gnus-agent-fetch-articles. Added code to update summary buffer. + When called in the group buffer, articles that can not be fetched + are AUTOMATICALLY MARKED AS READ. + + * gnus-sum.el (): Modified eval-when-compile to minimize + misleading compilation warnings. + (gnus-update-summary-mark-positions): Changed code to use + gnus-undownloaded-mark rather than gnus-downloaded-mark. + + * nnheader.el (nnheader-insert-nov-file): Do not try to insert an + empty file as the parser assumes that the file isn't empty. + + * nntp.el (nntp-send-string): The process-send-string call can, + because it performs I/O on the process, change the process' state + from open to closed. If this happens, call nntp-report + immediately to report the broken connection. + (nntp-report): Rewritten to avoid needing a global variable to + determine the appropriate course of action. Instead, two function + implementations are provided and the nntp-report function value is + bound to the appropriate implementation. + (nntp-retrieve-data): Moved nntp-report call to end of implementation. + (nntp-with-open-group): Now binds nntp-report's function cell + rather than binding gnus-with-open-group-first-pass. Added a + condition-case to detect a quit during a nntp command. When the + quit occurs, the current connection is closed as a fetch articles + request could have several megabytes queued up for reading. + (nntp-retrieve-headers): Bind articles to itself. If + nntp-with-open-group repeats this command, I must have access to + the original list of articles. + (nntp-retrieve-groups): Ditto for groups. + (nntp-retrieve-articles): Ditto for articles. + (*): Replaced nntp-possibly-change-group calls to + nntp-with-open-group forms in all, but one, occurrance. + (nntp-accept-process-output): Bug fix. Detect when called with + null process. + 2003-01-06 Jesper Harder * mm-util.el (mm-find-mime-charset-region): Don't do Latin-9 hack diff --git a/lisp/gnus-agent.el b/lisp/gnus-agent.el index 308cf39..404c14a 100644 --- a/lisp/gnus-agent.el +++ b/lisp/gnus-agent.el @@ -345,6 +345,7 @@ node `(gnus)Server Buffer'.") (gnus-define-keys gnus-agent-summary-mode-map "Jj" gnus-agent-toggle-plugged "Ju" gnus-agent-summary-fetch-group + "JS" gnus-agent-fetch-group "Js" gnus-agent-summary-fetch-series "J#" gnus-agent-mark-article "J\M-#" gnus-agent-unmark-article @@ -545,12 +546,13 @@ be a select method." (error "Groups can't be fetched when Gnus is unplugged")) (gnus-group-iterate n 'gnus-agent-fetch-group)) -(defun gnus-agent-fetch-group (group) +(defun gnus-agent-fetch-group (&optional group) "Put all new articles in GROUP into the Agent." (interactive (list (gnus-group-group-name))) (let ((state gnus-plugged)) (unwind-protect (progn + (setq group (or group gnus-newsgroup-name)) (unless group (error "No group on the current line")) (unless state @@ -793,17 +795,14 @@ article's mark is toggled." (defun gnus-agent-summary-fetch-series () (interactive) - (let ((dl gnus-newsgroup-downloadable)) - (while gnus-newsgroup-processable - (let* ((art (car (last gnus-newsgroup-processable))) - (gnus-newsgroup-downloadable (list art))) - (gnus-summary-goto-subject art) - (sit-for 0) - (gnus-agent-summary-fetch-group) - (setq dl (delq art dl)) - (gnus-summary-remove-process-mark art) - (sit-for 0))) - (setq gnus-newsgroup-downloadable dl))) + (when gnus-newsgroup-processable + (setq gnus-newsgroup-downloadable + (let* ((dl gnus-newsgroup-downloadable) + (gnus-newsgroup-downloadable (sort gnus-newsgroup-processable '<)) + (fetched-articles (gnus-agent-summary-fetch-group))) + (dolist (article fetched-articles) + (gnus-summary-remove-process-mark article)) + (gnus-sorted-ndifference dl fetched-articles))))) (defun gnus-agent-summary-fetch-group (&optional all) "Fetch the downloadable articles in the group. @@ -813,7 +812,8 @@ Optional arg ALL, if non-nil, means to fetch all articles." (if all gnus-newsgroup-articles gnus-newsgroup-downloadable)) (gnus-command-method (gnus-find-method-for-group gnus-newsgroup-name)) - (state gnus-plugged)) + (state gnus-plugged) + fetched-articles) (unwind-protect (progn (unless state @@ -821,19 +821,22 @@ Optional arg ALL, if non-nil, means to fetch all articles." (unless articles (error "No articles to download")) (gnus-agent-with-fetch - (setq gnus-newsgroup-undownloaded - (gnus-sorted-ndifference gnus-newsgroup-undownloaded - (gnus-agent-fetch-articles gnus-newsgroup-name articles)))) + (setq gnus-newsgroup-undownloaded + (gnus-sorted-ndifference gnus-newsgroup-undownloaded + (setq fetched-articles (gnus-agent-fetch-articles gnus-newsgroup-name articles))))) (save-excursion - (dolist (article articles) + +(dolist (article articles) (setq gnus-newsgroup-downloadable (delq article gnus-newsgroup-downloadable)) - (if gnus-agent-mark-unread-after-downloaded - (gnus-summary-mark-article article gnus-unread-mark)) - (gnus-summary-update-download-mark article)))) + (if gnus-agent-mark-unread-after-downloaded + (gnus-summary-mark-article article gnus-unread-mark)) + (when (gnus-summary-goto-subject article nil t) + (gnus-summary-update-download-mark article))))) (when (and (not state) gnus-plugged) - (gnus-agent-toggle-plugged nil))))) + (gnus-agent-toggle-plugged nil))) + fetched-articles)) (defun gnus-agent-fetch-selected-article () "Fetch the current article as it is selected. @@ -975,82 +978,118 @@ This can be added to `gnus-select-article-hook' or (defun gnus-agent-fetch-articles (group articles) "Fetch ARTICLES from GROUP and put them into the Agent." - (gnus-agent-load-alist group) (when articles - ;; Prune off articles that we have already fetched. - (while (and articles - (cdr (assq (car articles) gnus-agent-article-alist))) - (pop articles)) - (let ((arts articles)) - (while (cdr arts) - (if (cdr (assq (cadr arts) gnus-agent-article-alist)) - (setcdr arts (cddr arts)) - (setq arts (cdr arts))))) - (when articles - (let* ((fetched-articles (list nil)) - (tail-fetched-articles fetched-articles) - (dir (concat - (gnus-agent-directory) - (gnus-agent-group-path group) "/")) - (date (time-to-days (current-time))) - (case-fold-search t) - pos crosses id) - (gnus-make-directory dir) - (gnus-message 7 "Fetching articles for %s..." group) - ;; Fetch the articles from the backend. - (if (gnus-check-backend-function 'retrieve-articles group) - (setq pos (gnus-retrieve-articles articles group)) - (with-temp-buffer - (let (article) - (while (setq article (pop articles)) - (gnus-message 10 "Fetching article %s for %s..." - article group) - (when (or - (gnus-backlog-request-article group article - nntp-server-buffer) - (gnus-request-article article group)) - (goto-char (point-max)) - (push (cons article (point)) pos) - (insert-buffer-substring nntp-server-buffer))) - (copy-to-buffer nntp-server-buffer (point-min) (point-max)) - (setq pos (nreverse pos))))) - ;; Then save these articles into the Agent. - (save-excursion - (set-buffer nntp-server-buffer) - (while pos - (narrow-to-region (cdar pos) (or (cdadr pos) (point-max))) - (goto-char (point-min)) - (unless (eobp) ;; Don't save empty articles. - (when (search-forward "\n\n" nil t) - (when (search-backward "\nXrefs: " nil t) - ;; Handle cross posting. - (goto-char (match-end 0)) ; move to end of header name - (skip-chars-forward "^ ") ; skip server name - (skip-chars-forward " ") - (setq crosses nil) - (while (looking-at "\\([^: \n]+\\):\\([0-9]+\\) *") - (push (cons (buffer-substring (match-beginning 1) - (match-end 1)) - (string-to-int (buffer-substring (match-beginning 2) - (match-end 2)))) - crosses) - (goto-char (match-end 0))) - (gnus-agent-crosspost crosses (caar pos) date))) - (goto-char (point-min)) - (if (not (re-search-forward - "^Message-ID: *<\\([^>\n]+\\)>" nil t)) - (setq id "No-Message-ID-in-article") - (setq id (buffer-substring (match-beginning 1) (match-end 1)))) - (write-region-as-coding-system - gnus-agent-file-coding-system (point-min) (point-max) - (concat dir (number-to-string (caar pos))) nil 'silent) - - (gnus-agent-append-to-list tail-fetched-articles (caar pos))) - (widen) - (pop pos))) - - (gnus-agent-save-alist group (cdr fetched-articles) date) - (cdr fetched-articles))))) + (gnus-agent-load-alist group) + (let* ((alist gnus-agent-article-alist) + (headers (if (< (length articles) 2) nil gnus-newsgroup-headers)) + (selected-sets (list nil)) + (current-set-size 0) + article + header-number) + ;; Check each article + (while (setq article (pop articles)) + ;; Skip alist entries preceeding this article + (while (> article (or (caar alist) (1+ article))) + (setq alist (cdr alist))) + + ;; Prune off articles that we have already fetched. + (unless (and (eq article (caar alist)) + (cdar alist)) + ;; Skip headers preceeding this article + (while (> article + (setq header-number + (let* ((header (car headers))) + (if header + (mail-header-number header) + (1+ article))))) + (setq headers (cdr headers))) + + ;; Add this article to the current set + (setcar selected-sets (cons article (car selected-sets))) + + ;; Update the set size, when the set is too large start a + ;; new one. I do this after adding the article as I want at + ;; least one article in each set. + (when (< gnus-agent-max-fetch-size + (setq current-set-size (+ current-set-size (if (= header-number article) + (mail-header-chars (car headers)) + 0)))) + (setcar selected-sets (nreverse (car selected-sets))) + (setq selected-sets (cons nil selected-sets) + current-set-size 0)))) + + (when (or (cdr selected-sets) (car selected-sets)) + (let* ((fetched-articles (list nil)) + (tail-fetched-articles fetched-articles) + (dir (concat + (gnus-agent-directory) + (gnus-agent-group-path group) "/")) + (date (time-to-days (current-time))) + (case-fold-search t) + pos crosses id) + + (setcar selected-sets (nreverse (car selected-sets))) + (setq selected-sets (nreverse selected-sets)) + + (gnus-make-directory dir) + (gnus-message 7 "Fetching articles for %s..." group) + + (unwind-protect + (while (setq articles (pop selected-sets)) + ;; Fetch the articles from the backend. + (if (gnus-check-backend-function 'retrieve-articles group) + (setq pos (gnus-retrieve-articles articles group)) + (with-temp-buffer + (let (article) + (while (setq article (pop articles)) + (gnus-message 10 "Fetching article %s for %s..." + article group) + (when (or + (gnus-backlog-request-article group article + nntp-server-buffer) + (gnus-request-article article group)) + (goto-char (point-max)) + (push (cons article (point)) pos) + (insert-buffer-substring nntp-server-buffer))) + (copy-to-buffer nntp-server-buffer (point-min) (point-max)) + (setq pos (nreverse pos))))) + ;; Then save these articles into the Agent. + (save-excursion + (set-buffer nntp-server-buffer) + (while pos + (narrow-to-region (cdar pos) (or (cdadr pos) (point-max))) + (goto-char (point-min)) + (unless (eobp) ;; Don't save empty articles. + (when (search-forward "\n\n" nil t) + (when (search-backward "\nXrefs: " nil t) + ;; Handle cross posting. + (goto-char (match-end 0)) ; move to end of header name + (skip-chars-forward "^ ") ; skip server name + (skip-chars-forward " ") + (setq crosses nil) + (while (looking-at "\\([^: \n]+\\):\\([0-9]+\\) *") + (push (cons (buffer-substring (match-beginning 1) + (match-end 1)) + (string-to-int (buffer-substring (match-beginning 2) + (match-end 2)))) + crosses) + (goto-char (match-end 0))) + (gnus-agent-crosspost crosses (caar pos) date))) + (goto-char (point-min)) + (if (not (re-search-forward + "^Message-ID: *<\\([^>\n]+\\)>" nil t)) + (setq id "No-Message-ID-in-article") + (setq id (buffer-substring (match-beginning 1) (match-end 1)))) + (write-region-as-coding-system + gnus-agent-file-coding-system (point-min) (point-max) + (concat dir (number-to-string (caar pos))) nil 'silent) + + (gnus-agent-append-to-list tail-fetched-articles (caar pos))) + (widen) + (pop pos)))) + + (gnus-agent-save-alist group (cdr fetched-articles) date)) + (cdr fetched-articles)))))) (defun gnus-agent-crosspost (crosses article &optional date) (setq date (or date t)) @@ -1172,7 +1211,7 @@ article numbers will be returned." ;; interesting marks. (We have to fetch articles with boring marks ;; because otherwise the agent will remove their marks.) (dolist (arts (gnus-info-marks (gnus-get-info group))) - (unless (memq (car arts) '(seen recent)) + (unless (memq (car arts) '(seen recent killed cache)) (setq articles (gnus-range-add articles (cdr arts))))) (setq articles (sort (gnus-uncompress-sequence articles) '<))) @@ -1471,31 +1510,42 @@ of FILE placing the combined headers in nntp-server-buffer." "Fetch GROUP." (let ((gnus-command-method method) (gnus-newsgroup-name group) - gnus-newsgroup-dependencies gnus-newsgroup-headers - gnus-newsgroup-scored gnus-headers gnus-score - gnus-use-cache articles arts - category predicate info marks score-param + (gnus-newsgroup-dependencies gnus-newsgroup-dependencies) + (gnus-newsgroup-headers gnus-newsgroup-headers) + (gnus-newsgroup-scored gnus-newsgroup-scored) + (gnus-use-cache gnus-use-cache) (gnus-summary-expunge-below gnus-summary-expunge-below) (gnus-summary-mark-below gnus-summary-mark-below) (gnus-orphan-score gnus-orphan-score) ;; Maybe some other gnus-summary local variables should also ;; be put here. + + gnus-headers + gnus-score + articles arts + category predicate info marks score-param ) (unless (gnus-check-group group) (error "Can't open server for %s" group)) ;; Fetch headers. - (when (or (gnus-active group) + (when (or gnus-newsgroup-active + (gnus-active group) (gnus-activate-group group)) - (let ((marked-articles nil)) + (let ((marked-articles gnus-newsgroup-downloadable)) ;; Identify the articles marked for download - (dolist (mark gnus-agent-download-marks) - (let ((arts (cdr (assq mark (gnus-info-marks - (setq info (gnus-get-info group))))))) - (when arts - (setq marked-articles (nconc (gnus-uncompress-range arts) - marked-articles)) - ))) + (unless gnus-newsgroup-active ;; This needs to be a + ;; gnus-summary local variable + ;; that is NOT bound to any + ;; value above (It's global + ;; value should default to nil). + (dolist (mark gnus-agent-download-marks) + (let ((arts (cdr (assq mark (gnus-info-marks + (setq info (gnus-get-info group))))))) + (when arts + (setq marked-articles (nconc (gnus-uncompress-range arts) + marked-articles)) + )))) (setq marked-articles (sort marked-articles '<)) ;; Fetch any new articles from the server @@ -1507,11 +1557,13 @@ of FILE placing the combined headers in nntp-server-buffer." (when articles ;; Parse them and see which articles we want to fetch. (setq gnus-newsgroup-dependencies - (make-vector (length articles) 0)) + (or gnus-newsgroup-dependencies + (make-vector (length articles) 0))) (setq gnus-newsgroup-headers - (gnus-get-newsgroup-headers-xover articles nil nil - group)) + (or gnus-newsgroup-headers + (gnus-get-newsgroup-headers-xover articles nil nil + group))) ;; `gnus-agent-overview-buffer' may be killed for ;; timeout reason. If so, recreate it. (gnus-agent-create-buffer) @@ -1544,64 +1596,75 @@ of FILE placing the combined headers in nntp-server-buffer." (not marked-articles)) (let* ((arts (list nil)) (arts-tail arts) + (alist (gnus-agent-load-alist group)) (chunk-size 0) (marked-articles marked-articles) - is-marked) + fetched-articles) (while (setq gnus-headers (pop gnus-newsgroup-headers)) (let ((num (mail-header-number gnus-headers))) - ;; Determine if this article was marked for download. - (while (and marked-articles - (cond ((< num (car marked-articles)) - nil) - ((= num (car marked-articles)) - (setq is-marked t) - nil) - (t - (setq marked-articles - (cdr marked-articles)))))) - - ;; When this article is marked, or selected by the - ;; predicate, add it to the download list - (when (or is-marked - (let ((gnus-score - (or (cdr (assq num gnus-newsgroup-scored)) - gnus-summary-default-score))) - (funcall predicate))) - (gnus-agent-append-to-list arts-tail num) - - ;; When the expected size of the fetched articles - ;; exceeds gnus-agent-max-fetch-size, perform the - ;; fetch. - (when (< gnus-agent-max-fetch-size - (setq chunk-size - (+ chunk-size - (mail-header-chars gnus-headers)))) - (gnus-agent-fetch-articles group (cdr arts)) - (setcdr arts nil) - (setq arts-tail arts) - (setq chunk-size 0))))) - - ;; Fetch all remaining articles + ;; Determine if this article is already in the cache + (while (and alist + (> num (caar alist))) + (setq alist (cdr alist))) + + (unless (and (eq num (caar alist)) + (cdar alist)) + + ;; Determine if this article was marked for download. + (while (and marked-articles + (> num (car marked-articles))) + (setq marked-articles + (cdr marked-articles))) + + ;; When this article is marked, or selected by the + ;; predicate, add it to the download list + (when (or (eq num (car marked-articles)) + (let ((gnus-score + (or (cdr (assq num gnus-newsgroup-scored)) + gnus-summary-default-score))) + (funcall predicate))) + (gnus-agent-append-to-list arts-tail num))))) + + ;; Fetch all selected articles (when (cdr arts) - (gnus-agent-fetch-articles group (cdr arts))))) - - ;; When some, or all, of the marked articles came - ;; from the download mark. Remove that mark. I - ;; didn't do this earlier as I only want to remove - ;; the marks after the fetch is completed. - - (when marked-articles - (dolist (mark gnus-agent-download-marks) - (when (eq mark 'download) - (setq arts (assq mark (gnus-info-marks - (setq info (gnus-get-info group))))) - (when (cdr arts) - (setq marks (delq arts (gnus-info-marks info))) - (gnus-info-set-marks info marks) - (gnus-dribble-enter - (concat "(gnus-group-set-info '" - (gnus-prin1-to-string info) - ")"))))))))))) + (setq gnus-newsgroup-undownloaded + (gnus-sorted-ndifference gnus-newsgroup-undownloaded + (setq fetched-articles (gnus-agent-fetch-articles group (cdr arts))))) + (if gnus-newsgroup-active + (progn + (dolist (article (cdr arts)) + (setq gnus-newsgroup-downloadable + (delq article gnus-newsgroup-downloadable)) + (when (gnus-summary-goto-subject article nil t) + (gnus-summary-update-download-mark article))) + (dolist (article fetched-articles) + (if gnus-agent-mark-unread-after-downloaded + (gnus-summary-mark-article article gnus-unread-mark)))) + ;; When some, or all, of the marked articles came + ;; from the download mark. Remove that mark. I + ;; didn't do this earlier as I only want to remove + ;; the marks after the fetch is completed. + + (when (cdr arts) + (dolist (mark gnus-agent-download-marks) + (when (eq mark 'download) + (let ((marked-arts (assq mark (gnus-info-marks + (setq info (gnus-get-info group)))))) + (when (cdr marked-arts) + (setq marks (delq marked-arts (gnus-info-marks info))) + (gnus-info-set-marks info marks) + )))) + (let ((unfetched-articles (gnus-sorted-ndifference (cdr arts) fetched-articles)) + (read (gnus-info-read (or info (setq info (gnus-get-info group)))))) + (gnus-info-set-read info (gnus-add-to-range read unfetched-articles))) + + (gnus-group-update-group group t) + (sit-for 0) + + (gnus-dribble-enter + (concat "(gnus-group-set-info '" + (gnus-prin1-to-string info) + ")")))))))))))) ;;; ;;; Agent Category Mode diff --git a/lisp/gnus-sum.el b/lisp/gnus-sum.el index 335ff60..ce48376 100644 --- a/lisp/gnus-sum.el +++ b/lisp/gnus-sum.el @@ -1380,7 +1380,12 @@ buffers. For example: ") ;; Byte-compiler warning. -(eval-when-compile (defvar gnus-article-mode-map)) +;(eval-when-compile (defvar gnus-article-mode-map)) +(eval-when-compile + (let ((features (cons 'gnus-sum features))) + (require 'gnus) + (require 'gnus-agent) + (require 'gnus-art))) ;; Subject simplification. @@ -3094,7 +3099,7 @@ buffer that was in action when the last article was fetched." (let ((gnus-replied-mark 129) (gnus-score-below-mark 130) (gnus-score-over-mark 130) - (gnus-downloaded-mark 131) + (gnus-undownloaded-mark 131) (spec gnus-summary-line-format-spec) gnus-visual pos) (save-excursion @@ -3105,7 +3110,7 @@ buffer that was in action when the last article was fetched." (make-full-mail-header 0 "" "nobody" "05 Apr 2001 23:33:09 +0400" "" "" 0 0 "" nil) - 0 nil nil 128 t nil "" nil 1) + 0 nil t 128 t nil "" nil 1) (goto-char (point-min)) (setq pos (list (cons 'unread (and (search-forward "\200" nil t) (- (point) (point-min) 1))))) diff --git a/lisp/nnheader.el b/lisp/nnheader.el index f36059b..a4456af 100644 --- a/lisp/nnheader.el +++ b/lisp/nnheader.el @@ -1504,21 +1504,22 @@ find-file-hooks, etc. (defun nnheader-insert-nov-file (file first) (let ((size (nth 7 (file-attributes file))) (cutoff (* 32 1024))) - (if (< size cutoff) - ;; If the file is small, we just load it. - (nnheader-insert-file-contents file) - ;; We start on the assumption that FIRST is pretty recent. If - ;; not, we just insert the rest of the file as well. - (let (current) - (nnheader-insert-file-contents file nil (- size cutoff) size) - (goto-char (point-min)) - (delete-region (point) (or (search-forward "\n" nil 'move) (point))) - (setq current (ignore-errors (read (current-buffer)))) - (if (and (numberp current) - (< current first)) - t - (delete-region (point-min) (point-max)) - (nnheader-insert-file-contents file)))))) + (when size + (if (< size cutoff) + ;; If the file is small, we just load it. + (nnheader-insert-file-contents file) + ;; We start on the assumption that FIRST is pretty recent. If + ;; not, we just insert the rest of the file as well. + (let (current) + (nnheader-insert-file-contents file nil (- size cutoff) size) + (goto-char (point-min)) + (delete-region (point) (or (search-forward "\n" nil 'move) (point))) + (setq current (ignore-errors (read (current-buffer)))) + (if (and (numberp current) + (< current first)) + t + (delete-region (point-min) (point-max)) + (nnheader-insert-file-contents file))))))) (defun nnheader-find-file-noselect (&rest args) (let ((format-alist nil) diff --git a/lisp/nntp.el b/lisp/nntp.el index 912a82b..5a46da1 100644 --- a/lisp/nntp.el +++ b/lisp/nntp.el @@ -294,7 +294,9 @@ noticing asynchronous data.") nntp-last-command string) (when nntp-record-commands (nntp-record-command string)) - (process-send-string process (concat string nntp-end-of-line))) + (process-send-string process (concat string nntp-end-of-line)) + (or (memq (process-status process) '(open run)) + (nntp-report "Server closed connection"))) (defun nntp-record-command (string) "Record the command STRING." @@ -306,6 +308,25 @@ noticing asynchronous data.") "." (format "%03d" (/ (nth 2 time) 1000)) " " nntp-address " " string "\n")))) +(defun nntp-report (&rest args) + "Report an error from the nntp backend. The first string in ARGS +can be a format string. For some commands, the failed command may be +retried once before actually displaying the error report." + + (when nntp-record-commands + (nntp-record-command "*** CALLED nntp-report ***")) + + (nnheader-report 'nntp args)) + +(defun nntp-report-1 (&rest args) + "Throws out to nntp-with-open-group-error so that the connection may +be restored and the command retried." + + (when nntp-record-commands + (nntp-record-command "*** CONNECTION LOST ***")) + + (throw 'nntp-with-open-group-error t)) + (defsubst nntp-wait-for (process wait-for buffer &optional decode discard) "Wait for WAIT-FOR to arrive from PROCESS." (save-excursion @@ -391,32 +412,33 @@ noticing asynchronous data.") "Use COMMAND to retrieve data into BUFFER from PORT on ADDRESS." (let ((process (or (nntp-find-connection buffer) (nntp-open-connection buffer)))) - (if (not process) - (nnheader-report 'nntp "Couldn't open connection to %s" address) - (unless (or nntp-inhibit-erase nnheader-callback-function) - (save-excursion - (set-buffer (process-buffer process)) - (erase-buffer))) - (condition-case err - (progn - (when command - (nntp-send-string process command)) - (cond - ((eq callback 'ignore) - t) - ((and callback wait-for) - (nntp-async-wait process wait-for buffer decode callback) - t) - (wait-for - (nntp-wait-for process wait-for buffer decode)) - (t t))) - (error - (nnheader-report 'nntp "Couldn't open connection to %s: %s" - address err)) - (quit - (message "Quit retrieving data from nntp") - (signal 'quit nil) - nil))))) + (if process + (progn + (unless (or nntp-inhibit-erase nnheader-callback-function) + (save-excursion + (set-buffer (process-buffer process)) + (erase-buffer))) + (condition-case err + (progn + (when command + (nntp-send-string process command)) + (cond + ((eq callback 'ignore) + t) + ((and callback wait-for) + (nntp-async-wait process wait-for buffer decode callback) + t) + (wait-for + (nntp-wait-for process wait-for buffer decode)) + (t t))) + (error + (nnheader-report 'nntp "Couldn't open connection to %s: %s" + address err)) + (quit + (message "Quit retrieving data from nntp") + (signal 'quit nil) + nil))) + (nnheader-report 'nntp "Couldn't open connection to %s" address)))) (defsubst nntp-send-command (wait-for &rest strings) "Send STRINGS to server and wait until WAIT-FOR returns." @@ -552,7 +574,9 @@ noticing asynchronous data.") (t nil))) -(defvar nntp-with-open-group-first-pass nil) +(eval-when-compile + (defvar nntp-with-open-group-internal nil) + (defvar nntp-report-n nil)) (defmacro nntp-with-open-group (group server &optional connectionless &rest forms) "Protect against servers that don't like clients that keep idle connections opens. @@ -565,209 +589,210 @@ nntp-connection-timeout has expired. When these occur nntp-with-open-group, opens a new connection then re-issues the NNTP command whose response triggered the error." (when (and (listp connectionless) - (not (eq connectionless nil))) + (not (eq connectionless nil))) (setq forms (cons connectionless forms) - connectionless nil)) - `(let ((nntp-with-open-group-first-pass t) - nntp-with-open-group-internal) - (while - (catch 'nntp-with-open-group-error - ;; Open the connection to the server - ;; NOTE: Existing connections are NOT tested. - (nntp-possibly-change-group ,group ,server ,connectionless) - - (let ((timer - (and - nntp-connection-timeout - (nnheader-run-at-time - nntp-connection-timeout nil - '(lambda () - (let ((process (nntp-find-connection - nntp-server-buffer)) - (buffer (and process (process-buffer process)))) - ;; when I an able to identify the connection - ;; to the server AND I've received NO reponse - ;; for nntp-connection-timeout seconds. - (when (and buffer (eq 0 (buffer-size buffer))) - ;; Close the connection. Take no other - ;; action as the accept input code will - ;; handle the closed connection. - (nntp-kill-buffer buffer)))))))) - (unwind-protect - (setq nntp-with-open-group-internal (progn ,@forms)) - (when timer - (nnheader-cancel-timer timer))) - nil)) - (setq nntp-with-open-group-first-pass nil)) + connectionless nil)) + `(letf ((nntp-report-n (symbol-function 'nntp-report)) + ((symbol-function 'nntp-report) (symbol-function 'nntp-report-1)) + (nntp-with-open-group-internal nil)) + (while (catch 'nntp-with-open-group-error + ;; Open the connection to the server + ;; NOTE: Existing connections are NOT tested. + (nntp-possibly-change-group ,group ,server ,connectionless) + + (let ((timer + (and nntp-connection-timeout + (nnheader-run-at-time + nntp-connection-timeout nil + '(lambda () + (let ((process (nntp-find-connection + nntp-server-buffer)) + (buffer (and process + (process-buffer process)))) + ; when I an able to identify + ; the connection to the server + ; AND I've received NO reponse + ; for nntp-connection-timeout + ; seconds. + (when (and buffer (eq 0 (buffer-size buffer))) + ; Close the connection. Take + ; no other action as the + ; accept input code will + ; handle the closed + ; connection. + (nntp-kill-buffer buffer)))))))) + (unwind-protect + (setq nntp-with-open-group-internal + (condition-case nil + (progn ,@forms) + (quit + (nntp-close-server)))) + (when timer + (nnheader-cancel-timer timer))) + nil)) + (setf (symbol-function 'nntp-report) nntp-report-n)) nntp-with-open-group-internal)) -(defsubst nntp-report (&rest args) - "Report an error from the nntp backend. -The first string in ARGS can be a format string. -For some commands, the failed command may be retried once before actually displaying the error report." - - (if nntp-with-open-group-first-pass - (throw 'nntp-with-open-group-error t)) - - (nnheader-report 'nntp args) - ) - (deffoo nntp-retrieve-headers (articles &optional group server fetch-old) "Retrieve the headers of ARTICLES." (nntp-with-open-group - group server - (save-excursion - (set-buffer (nntp-find-connection-buffer nntp-server-buffer)) - (erase-buffer) - (if (and (not gnus-nov-is-evil) - (not nntp-nov-is-evil) - (nntp-retrieve-headers-with-xover articles fetch-old)) - ;; We successfully retrieved the headers via XOVER. - 'nov - ;; XOVER didn't work, so we do it the hard, slow and inefficient - ;; way. - (let ((number (length articles)) - (count 0) - (received 0) - (last-point (point-min)) - (buf (nntp-find-connection-buffer nntp-server-buffer)) - (nntp-inhibit-erase t) - article) - ;; Send HEAD commands. - (while (setq article (pop articles)) - (nntp-send-command - nil - "HEAD" (if (numberp article) - (int-to-string article) - ;; `articles' is either a list of article numbers - ;; or a list of article IDs. - article)) - (incf count) - ;; Every 400 requests we have to read the stream in - ;; order to avoid deadlocks. - (when (or (null articles) ;All requests have been sent. - (zerop (% count nntp-maximum-request))) - (nntp-accept-response) - (while (progn - (set-buffer buf) - (goto-char last-point) - ;; Count replies. - (while (nntp-next-result-arrived-p) - (setq last-point (point)) - (incf received)) - (< received count)) - ;; If number of headers is greater than 100, give - ;; informative messages. - (and (numberp nntp-large-newsgroup) - (> number nntp-large-newsgroup) - (zerop (% received 20)) - (nnheader-message 6 "NNTP: Receiving headers... %d%%" - (/ (* received 100) number))) - (nntp-accept-response)))) - (and (numberp nntp-large-newsgroup) - (> number nntp-large-newsgroup) - (nnheader-message 6 "NNTP: Receiving headers...done")) - - ;; Now all of replies are received. Fold continuation lines. - (nnheader-fold-continuation-lines) - ;; Remove all "\r"'s. - (nnheader-strip-cr) - (copy-to-buffer nntp-server-buffer (point-min) (point-max)) - 'headers))))) + group server + (save-excursion + (set-buffer (nntp-find-connection-buffer nntp-server-buffer)) + (erase-buffer) + (if (and (not gnus-nov-is-evil) + (not nntp-nov-is-evil) + (nntp-retrieve-headers-with-xover articles fetch-old)) + ;; We successfully retrieved the headers via XOVER. + 'nov + ;; XOVER didn't work, so we do it the hard, slow and inefficient + ;; way. + (let ((number (length articles)) + (articles articles) + (count 0) + (received 0) + (last-point (point-min)) + (buf (nntp-find-connection-buffer nntp-server-buffer)) + (nntp-inhibit-erase t) + article) + ;; Send HEAD commands. + (while (setq article (pop articles)) + (nntp-send-command + nil + "HEAD" (if (numberp article) + (int-to-string article) + ;; `articles' is either a list of article numbers + ;; or a list of article IDs. + article)) + (incf count) + ;; Every 400 requests we have to read the stream in + ;; order to avoid deadlocks. + (when (or (null articles) ;All requests have been sent. + (zerop (% count nntp-maximum-request))) + (nntp-accept-response) + (while (progn + (set-buffer buf) + (goto-char last-point) + ;; Count replies. + (while (nntp-next-result-arrived-p) + (setq last-point (point)) + (incf received)) + (< received count)) + ;; If number of headers is greater than 100, give + ;; informative messages. + (and (numberp nntp-large-newsgroup) + (> number nntp-large-newsgroup) + (zerop (% received 20)) + (nnheader-message 6 "NNTP: Receiving headers... %d%%" + (/ (* received 100) number))) + (nntp-accept-response)))) + (and (numberp nntp-large-newsgroup) + (> number nntp-large-newsgroup) + (nnheader-message 6 "NNTP: Receiving headers...done")) + + ;; Now all of replies are received. Fold continuation lines. + (nnheader-fold-continuation-lines) + ;; Remove all "\r"'s. + (nnheader-strip-cr) + (copy-to-buffer nntp-server-buffer (point-min) (point-max)) + 'headers))))) (deffoo nntp-retrieve-groups (groups &optional server) "Retrieve group info on GROUPS." - (nntp-possibly-change-group nil server) - (when (nntp-find-connection-buffer nntp-server-buffer) - (catch 'done - (save-excursion - ;; Erase nntp-server-buffer before nntp-inhibit-erase. - (set-buffer nntp-server-buffer) - (erase-buffer) - (set-buffer (nntp-find-connection-buffer nntp-server-buffer)) - ;; The first time this is run, this variable is `try'. So we - ;; try. - (when (eq nntp-server-list-active-group 'try) - (nntp-try-list-active (car groups))) - (erase-buffer) - (let ((count 0) - (received 0) - (last-point (point-min)) - (nntp-inhibit-erase t) - (buf (nntp-find-connection-buffer nntp-server-buffer)) - (command (if nntp-server-list-active-group - "LIST ACTIVE" "GROUP"))) - (while groups - ;; Timeout may have killed the buffer. - (unless (gnus-buffer-live-p buf) - (nnheader-report 'nntp "Connection to %s is closed." server) - (throw 'done nil)) - ;; Send the command to the server. - (nntp-send-command nil command (pop groups)) - (incf count) - ;; Every 400 requests we have to read the stream in - ;; order to avoid deadlocks. - (when (or (null groups) ;All requests have been sent. - (zerop (% count nntp-maximum-request))) - (nntp-accept-response) - (while (and (gnus-buffer-live-p buf) - (progn - ;; Search `blue moon' in this file for the - ;; reason why set-buffer here. - (set-buffer buf) - (goto-char last-point) - ;; Count replies. - (while (re-search-forward "^[0-9]" nil t) - (incf received)) - (setq last-point (point)) - (< received count))) - (nntp-accept-response)))) - - ;; Wait for the reply from the final command. - (unless (gnus-buffer-live-p buf) - (nnheader-report 'nntp "Connection to %s is closed." server) - (throw 'done nil)) - (set-buffer buf) - (goto-char (point-max)) - (re-search-backward "^[0-9]" nil t) - (when (looking-at "^[23]") - (while (and (gnus-buffer-live-p buf) - (progn - (set-buffer buf) - (goto-char (point-max)) - (if (not nntp-server-list-active-group) - (not (re-search-backward "\r?\n" (- (point) 3) t)) - (not (re-search-backward "^\\.\r?\n" - (- (point) 4) t))))) - (nntp-accept-response))) - - ;; Now all replies are received. We remove CRs. - (unless (gnus-buffer-live-p buf) - (nnheader-report 'nntp "Connection to %s is closed." server) - (throw 'done nil)) - (set-buffer buf) - (goto-char (point-min)) - (while (search-forward "\r" nil t) - (replace-match "" t t)) - - (if (not nntp-server-list-active-group) - (progn - (copy-to-buffer nntp-server-buffer (point-min) (point-max)) - 'group) - ;; We have read active entries, so we just delete the - ;; superfluous gunk. - (goto-char (point-min)) - (while (re-search-forward "^[.2-5]" nil t) - (delete-region (match-beginning 0) - (progn (forward-line 1) (point)))) - (copy-to-buffer nntp-server-buffer (point-min) (point-max)) - 'active)))))) + (nntp-with-open-group + nil server + (when (nntp-find-connection-buffer nntp-server-buffer) + (catch 'done + (save-excursion + ;; Erase nntp-server-buffer before nntp-inhibit-erase. + (set-buffer nntp-server-buffer) + (erase-buffer) + (set-buffer (nntp-find-connection-buffer nntp-server-buffer)) + ;; The first time this is run, this variable is `try'. So we + ;; try. + (when (eq nntp-server-list-active-group 'try) + (nntp-try-list-active (car groups))) + (erase-buffer) + (let ((count 0) + (groups groups) + (received 0) + (last-point (point-min)) + (nntp-inhibit-erase t) + (buf (nntp-find-connection-buffer nntp-server-buffer)) + (command (if nntp-server-list-active-group + "LIST ACTIVE" "GROUP"))) + (while groups + ;; Timeout may have killed the buffer. + (unless (gnus-buffer-live-p buf) + (nnheader-report 'nntp "Connection to %s is closed." server) + (throw 'done nil)) + ;; Send the command to the server. + (nntp-send-command nil command (pop groups)) + (incf count) + ;; Every 400 requests we have to read the stream in + ;; order to avoid deadlocks. + (when (or (null groups) ;All requests have been sent. + (zerop (% count nntp-maximum-request))) + (nntp-accept-response) + (while (and (gnus-buffer-live-p buf) + (progn + ;; Search `blue moon' in this file for the + ;; reason why set-buffer here. + (set-buffer buf) + (goto-char last-point) + ;; Count replies. + (while (re-search-forward "^[0-9]" nil t) + (incf received)) + (setq last-point (point)) + (< received count))) + (nntp-accept-response)))) + + ;; Wait for the reply from the final command. + (unless (gnus-buffer-live-p buf) + (nnheader-report 'nntp "Connection to %s is closed." server) + (throw 'done nil)) + (set-buffer buf) + (goto-char (point-max)) + (re-search-backward "^[0-9]" nil t) + (when (looking-at "^[23]") + (while (and (gnus-buffer-live-p buf) + (progn + (set-buffer buf) + (goto-char (point-max)) + (if (not nntp-server-list-active-group) + (not (re-search-backward "\r?\n" (- (point) 3) t)) + (not (re-search-backward "^\\.\r?\n" + (- (point) 4) t))))) + (nntp-accept-response))) + + ;; Now all replies are received. We remove CRs. + (unless (gnus-buffer-live-p buf) + (nnheader-report 'nntp "Connection to %s is closed." server) + (throw 'done nil)) + (set-buffer buf) + (goto-char (point-min)) + (while (search-forward "\r" nil t) + (replace-match "" t t)) + + (if (not nntp-server-list-active-group) + (progn + (copy-to-buffer nntp-server-buffer (point-min) (point-max)) + 'group) + ;; We have read active entries, so we just delete the + ;; superfluous gunk. + (goto-char (point-min)) + (while (re-search-forward "^[.2-5]" nil t) + (delete-region (match-beginning 0) + (progn (forward-line 1) (point)))) + (copy-to-buffer nntp-server-buffer (point-min) (point-max)) + 'active))))))) (deffoo nntp-retrieve-articles (articles &optional group server) - (nntp-with-open-group + (nntp-with-open-group group server (save-excursion (let ((number (length articles)) + (articles articles) (count 0) (received 0) (last-point (point-min)) @@ -845,16 +870,18 @@ For some commands, the failed command may be retried once before actually displa (deffoo nntp-list-active-group (group &optional server) "Return the active info on GROUP (which can be a regexp)." - (nntp-possibly-change-group nil server) - (nntp-send-command "^\\.*\r?\n" "LIST ACTIVE" group)) + (nntp-with-open-group + nil server + (nntp-send-command "^\\.*\r?\n" "LIST ACTIVE" group))) (deffoo nntp-request-group-articles (group &optional server) "Return the list of existing articles in GROUP." - (nntp-possibly-change-group nil server) - (nntp-send-command "^\\.*\r?\n" "LISTGROUP" group)) + (nntp-with-open-group + nil server + (nntp-send-command "^\\.*\r?\n" "LISTGROUP" group))) (deffoo nntp-request-article (article &optional group server buffer command) - (nntp-with-open-group + (nntp-with-open-group group server (when (nntp-send-command-and-decode "\r?\n\\.\r?\n" "ARTICLE" @@ -868,19 +895,21 @@ For some commands, the failed command may be retried once before actually displa (nntp-find-group-and-number group))))) (deffoo nntp-request-head (article &optional group server) - (nntp-possibly-change-group group server) - (when (nntp-send-command - "\r?\n\\.\r?\n" "HEAD" - (if (numberp article) (int-to-string article) article)) - (prog1 - (nntp-find-group-and-number group) - (nntp-decode-text)))) + (nntp-with-open-group + group server + (when (nntp-send-command + "\r?\n\\.\r?\n" "HEAD" + (if (numberp article) (int-to-string article) article)) + (prog1 + (nntp-find-group-and-number group) + (nntp-decode-text))))) (deffoo nntp-request-body (article &optional group server) - (nntp-possibly-change-group group server) - (nntp-send-command-and-decode - "\r?\n\\.\r?\n" "BODY" - (if (numberp article) (int-to-string article) article))) + (nntp-with-open-group + group server + (nntp-send-command-and-decode + "\r?\n\\.\r?\n" "BODY" + (if (numberp article) (int-to-string article) article)))) (deffoo nntp-request-group (group &optional server dont-check) (nntp-with-open-group @@ -950,81 +979,85 @@ output from the server will be restricted to the specified newsgroups. If `nntp-options-subscribe' is non-nil, remove newsgroups that do not match the regexp. If `nntp-options-not-subscribe' is non-nil, remove newsgroups that match the regexp." - (nntp-possibly-change-group nil server) - (with-current-buffer nntp-server-buffer - (prog1 - (if (not nntp-list-options) - (nntp-send-command-and-decode "\r?\n\\.\r?\n" "LIST") - (let ((options (if (consp nntp-list-options) - nntp-list-options - (list nntp-list-options))) - (ret t)) - (erase-buffer) - (while options - (goto-char (point-max)) - (narrow-to-region (point) (point)) - (setq ret (and ret - (nntp-send-command-nodelete - "\r?\n\\.\r?\n" - (format "LIST ACTIVE %s" (car options)))) - options (cdr options)) - (nntp-decode-text)) - (widen) - ret)) - (when (and (stringp nntp-options-subscribe) - (not (string-equal "" nntp-options-subscribe))) - (goto-char (point-min)) - (keep-lines nntp-options-subscribe)) - (when (and (stringp nntp-options-not-subscribe) - (not (string-equal "" nntp-options-not-subscribe))) - (goto-char (point-min)) - (flush-lines nntp-options-subscribe))))) + (nntp-with-open-group + nil server + (with-current-buffer nntp-server-buffer + (prog1 + (if (not nntp-list-options) + (nntp-send-command-and-decode "\r?\n\\.\r?\n" "LIST") + (let ((options (if (consp nntp-list-options) + nntp-list-options + (list nntp-list-options))) + (ret t)) + (erase-buffer) + (while options + (goto-char (point-max)) + (narrow-to-region (point) (point)) + (setq ret (and ret + (nntp-send-command-nodelete + "\r?\n\\.\r?\n" + (format "LIST ACTIVE %s" (car options)))) + options (cdr options)) + (nntp-decode-text)) + (widen) + ret)) + (when (and (stringp nntp-options-subscribe) + (not (string-equal "" nntp-options-subscribe))) + (goto-char (point-min)) + (keep-lines nntp-options-subscribe)) + (when (and (stringp nntp-options-not-subscribe) + (not (string-equal "" nntp-options-not-subscribe))) + (goto-char (point-min)) + (flush-lines nntp-options-subscribe)))))) (deffoo nntp-request-list-newsgroups (&optional server) - (nntp-possibly-change-group nil server) - (nntp-send-command "\r?\n\\.\r?\n" "LIST NEWSGROUPS")) + (nntp-with-open-group + nil server + (nntp-send-command "\r?\n\\.\r?\n" "LIST NEWSGROUPS"))) (deffoo nntp-request-newgroups (date &optional server) - (nntp-possibly-change-group nil server) - (save-excursion - (set-buffer nntp-server-buffer) - (let* ((time (date-to-time date)) - (ls (- (cadr time) (nth 8 (decode-time time))))) - (cond ((< ls 0) - (setcar time (1- (car time))) - (setcar (cdr time) (+ ls 65536))) - ((>= ls 65536) - (setcar time (1+ (car time))) - (setcar (cdr time) (- ls 65536))) - (t - (setcar (cdr time) ls))) - (prog1 - (nntp-send-command - "^\\.\r?\n" "NEWGROUPS" - (format-time-string "%y%m%d %H%M%S" time) - "GMT") - (nntp-decode-text))))) + (nntp-with-open-group + nil server + (save-excursion + (set-buffer nntp-server-buffer) + (let* ((time (date-to-time date)) + (ls (- (cadr time) (nth 8 (decode-time time))))) + (cond ((< ls 0) + (setcar time (1- (car time))) + (setcar (cdr time) (+ ls 65536))) + ((>= ls 65536) + (setcar time (1+ (car time))) + (setcar (cdr time) (- ls 65536))) + (t + (setcar (cdr time) ls))) + (prog1 + (nntp-send-command + "^\\.\r?\n" "NEWGROUPS" + (format-time-string "%y%m%d %H%M%S" time) + "GMT") + (nntp-decode-text)))))) (deffoo nntp-request-post (&optional server) - (nntp-possibly-change-group nil server) - (when (nntp-send-command "^[23].*\r?\n" "POST") - (let ((response (with-current-buffer nntp-server-buffer - nntp-process-response)) - server-id) - (when (and response - (string-match "^[23].*\\(<[^\t\n @<>]+@[^\t\n @<>]+>\\)" - response)) - (setq server-id (match-string 1 response)) - (narrow-to-region (goto-char (point-min)) - (if (search-forward "\n\n" nil t) - (1- (point)) - (point-max))) - (unless (mail-fetch-field "Message-ID") - (goto-char (point-min)) - (insert "Message-ID: " server-id "\n")) - (widen)) - (run-hooks 'nntp-prepare-post-hook) - (nntp-send-buffer "^[23].*\n")))) + (nntp-with-open-group + nil server + (when (nntp-send-command "^[23].*\r?\n" "POST") + (let ((response (with-current-buffer nntp-server-buffer + nntp-process-response)) + server-id) + (when (and response + (string-match "^[23].*\\(<[^\t\n @<>]+@[^\t\n @<>]+>\\)" + response)) + (setq server-id (match-string 1 response)) + (narrow-to-region (goto-char (point-min)) + (if (search-forward "\n\n" nil t) + (1- (point)) + (point-max))) + (unless (mail-fetch-field "Message-ID") + (goto-char (point-min)) + (insert "Message-ID: " server-id "\n")) + (widen)) + (run-hooks 'nntp-prepare-post-hook) + (nntp-send-buffer "^[23].*\n"))))) (deffoo nntp-request-type (group article) 'news) @@ -1315,7 +1348,8 @@ password contained in '~/.nntp-authinfo'." ;; that the server has closed the connection. This MUST be ;; handled here as the buffer restored by the save-excursion may ;; be the process's former output buffer (i.e. now killed) - (or (memq (process-status process) '(open run)) + (or (not process) + (memq (process-status process) '(open run)) (nntp-report "Server closed connection")))) (defun nntp-accept-response () @@ -1474,18 +1508,22 @@ password contained in '~/.nntp-authinfo'." (nntp-accept-response) (set-buffer process-buffer)))) - ;; Some nntp servers seem to have an extension to the XOVER extension. On these - ;; servers, requesting an article range preceeding the active range does not return an - ;; error as specified in the RFC. What we instead get is the NOV entry for the first - ;; available article. Obviously, a client can use that entry to avoid making unnecessary - ;; requests. The only problem is for a client that assumes that the response will always be - ;; within the requested ranage. For such a client, we can get N copies of the same entry - ;; (one for each XOVER command sent to the server). + ;; Some nntp servers seem to have an extension to the XOVER + ;; extension. On these servers, requesting an article range + ;; preceeding the active range does not return an error as + ;; specified in the RFC. What we instead get is the NOV entry + ;; for the first available article. Obviously, a client can + ;; use that entry to avoid making unnecessary requests. The + ;; only problem is for a client that assumes that the response + ;; will always be within the requested ranage. For such a + ;; client, we can get N copies of the same entry (one for each + ;; XOVER command sent to the server). (when (<= count 1) (goto-char (point-min)) (when (re-search-forward "^[0-9][0-9][0-9] .*\n\\([0-9]+\\)" nil t) - (let ((low-limit (string-to-int (buffer-substring (match-beginning 1) (match-end 1))))) + (let ((low-limit (string-to-int (buffer-substring (match-beginning 1) + (match-end 1))))) (while (and articles (<= (car articles) low-limit)) (setq articles (cdr articles)))))) (set-buffer buf)) diff --git a/texi/gnus-ja.texi b/texi/gnus-ja.texi index cc9de25..6851313 100644 --- a/texi/gnus-ja.texi +++ b/texi/gnus-ja.texi @@ -691,7 +691,7 @@ Article Treatment * Article Washing:: $B?M@8$r$b$C$H$h$/$9$k$?$/$5$s$N5$$NMx$$$?(B $B4X?t(B * Article Header:: $B%X%C%@!<$r$$$m$$$mJQ7A$5$;$k(B -* Article Buttons:: URL $B$d(B Message-ID $B$d(B $B%"%I%l%9$J$I$r%/%j%C(B +* Article Buttons:: URL $B$d(B Message-ID $B$d%"%I%l%9$J$I$r%/%j%C(B $B%/$9$k(B * Article Date:: $B$0$:$0$:8@$&$J!"@$3&;~$@(B! * Article Display:: X-Face, Picons, Smileys $B$rI=<($9$k(B @@ -1373,8 +1373,8 @@ Gnus $B$O!"IaDL$O%0%k!<%W$,?7$7$$$+$I$&$+$r!"9XFI$7$F$$$k%0%k!<%W$H:o=|$5(B @table @code @item gnus-subscribe-zombies @vindex gnus-subscribe-zombies -$B$9$Y$F$N?7$7$$%0%k!<%W$r%>%s%S(B (zombie) $B$K$7$^$9!#$3$l$,=i4|@_Dj(B $B$K$J$C(B -$B$F$$$^$9!#8e$G%>%s%S$r(B (@kbd{A z} $B$K$h$C$F(B) $B354Q$7$?$j!"(B(@kbd{S z} $B$K$h$C(B +$B$9$Y$F$N?7$7$$%0%k!<%W$r%>%s%S(B (zombie) $B$K$7$^$9!#$3$l$,=i4|@_Dj$K$J$C$F(B +$B$$$^$9!#8e$G%>%s%S$r(B (@kbd{A z} $B$K$h$C$F(B) $B354Q$7$?$j!"(B(@kbd{S z} $B$K$h$C(B $B$F(B) $BE,@Z$KA4$F$r:o=|$7$?$j!"(B(@kbd{u} $B$K$h$C$F(B) $B9XFI$7$?$j$G$-$^$9!#(B @item gnus-subscribe-randomly @@ -3533,7 +3533,7 @@ Note: $B$b$7$"$J$?$,$?!<$/$5$s$N%0%k!<%W$rFI$s$G$$$k$N$G$"$l$P!"%0%k!<%W$r%H%T%C(B $B%/Kh$K3,AXJ,$1$G$-$k$HJXMx$G$7$g$&!#(BEmacs $B$N%0%k!<%W$r$3$C$A$X!"%;%C%/%9(B -$B$N%0%k!<%W$r$"$C$A$X!"$G!";D$j$r(B ($B$((B? $B%0%k!<%W$,Fs(B $B$D$/$i$$$7$+$J$$(B +$B$N%0%k!<%W$r$"$C$A$X!"$G!";D$j$r(B ($B$((B? $B%0%k!<%W$,Fs$D$/$i$$$7$+$J$$(B $B$N(B?) $B$N%;%/%7%g%s$KF~$l$^$7$g$&!#$"$k$$(B $B$O(B Emacs $B%;%C%/%9$N%0%k!<%W$r(B Emacs $B%0%k!<%W!"%;%C%/%9%0%k!<%W$N$I$A$i$+(B $B$NI{%H%T%C%/$H$9$k$3$H$5$($b$G$-$^$9!=!=$"$k$$$ON>J}$K(B! $B$9$s$4$$$G$7$g$&(B! @@ -4205,7 +4205,7 @@ gnus $B$O(B @code{gnus-group-charter-alist} $B$r;H$C$F7{>O$N=j:_$rC5$7$^$9!#= @code{gnus-group-fetch-control-use-browse-url} $B$,Hs(B-@code{nil} $B$@$C$?$i!"(B gnus $B$O(B @code{browse-url} $B$r;H$C$F%3%s%H%m!<%k%a%C%;!<%8$r3+$-$^$9!#$=$&(B -$B$G$J$$>l9g$O(B @code{ange-ftp} $B$r;H$C$Fl9g$O(B @code{ange-ftp} $B$r;H$C$Fl=j$K%-%c%C%7%e$9$k$N$O0UL#(B $B$NL5$$;v$G$9!#$"$J$?$,FsG\$NMFNL$r;H$&;v$,NI$$$H46$8$J$$8B$j$O!#(B -$B%-%c%C%7%e$r@)8B$9$k$?$a$K!"(B@code{gnus-cacheable-groups} $B$r(B $B$r%-%c%C%7%e(B -$B$9$k%0%k!<%W$NO"A[%j%9%H!"Nc$($P(B @samp{^nntp} $B$H$9$k$+!"@55,I=(B +$B%-%c%C%7%e$r@)8B$9$k$?$a$K!"(B@code{gnus-cacheable-groups} $B$r%-%c%C%7%e$9(B +$B$k%0%k!<%W$NO"A[%j%9%H!"Nc$($P(B @samp{^nntp} $B$H$9$k$+!"@55,I=(B $B8=(B @code{gnus-uncacheable-groups} $B$rNc$($P!"(B@samp{^nnml} $B$K@_Dj$7$F2<$5(B $B$$!#N>J}$NJQ?t$N=i4|CM$O(B @code{nil} $B$G$9!#$b$7%0%k!<%W$,N>J}$N@55,I=8=$K(B $B9gCW$9$k$H!"$=$N%0%k!<%W$O%-%c%C%7%e$5$l$^$;$s!#(B @@ -7594,7 +7594,7 @@ Gnus $B$O%U%!%$%k$r1\Mw$9$k$N$r7hDj$9$k$N$K(B@dfn{$B5,B'JQ?t(B}$B$rMQ$$$^$9 @vindex gnus-uu-save-in-digest @code{nil} $B$G$J$$$N$O!"(B@code{gnus-uu} $B$,I|9f2=$r$7$J$$$GJ]B8$r$9$k$h$&$K(B $B8@$o$l$?$H$-$K!"MWLs$rJ]B8$9$k$H$$$&;v$G$9!#$3$NJQ?t$,(B @code{nil} $B$G$"$k(B -$B$H!"(B@code{gnus-uu} $B$O(B $B2?$b>~$j$r$7$J$$$GA4$F$r%U%!%$%k$KJ]B8$7$^$9!#MWLs(B +$B$H!"(B@code{gnus-uu} $B$O2?$b>~$j$r$7$J$$$GA4$F$r%U%!%$%k$KJ]B8$7$^$9!#MWLs(B $B$O(B RFC1153 $B=`$8$F$$$^$9!=!=0UL#$N$"$kNL$r;XDj$7$F!"HV9f$rH/9T$9$k4JC1$J(B $BJ}K!$,8+$D$+$i$J$+$C$?$N$G!"C1=c$K$=$l$i$O@Z$jMn$H$7$F$$$^$9!#(B @end table @@ -7692,7 +7692,7 @@ Gnus $B$O%U%!%$%k$r1\Mw$9$k$N$r7hDj$9$k$N$K(B@dfn{$B5,B'JQ?t(B}$B$rMQ$$$^$9 * Article Washing:: $B?M@8$r$b$C$H$h$/$9$k$?$/$5$s$N5$$NMx$$$?(B $B4X?t(B * Article Header:: $B%X%C%@!<$r$$$m$$$mJQ7A$5$;$k(B -* Article Buttons:: URL $B$d(B Message-ID $B$d(B $B%"%I%l%9$J$I$r%/%j%C(B +* Article Buttons:: URL $B$d(B Message-ID $B$d%"%I%l%9$J$I$r%/%j%C(B $B%/$9$k(B * Article Date:: $B$0$:$0$:8@$&$J!"@$3&;~$@(B! * Article Display:: X-Face, Picons, Smileys $B$rI=<($9$k(B @@ -7801,7 +7801,7 @@ Fonts})$B!#F1$8%a%C%;!<%8$NCf$KJ#?t$N5-;v$+$i$N0zMQ$,$"$k$H!"(Bgnus $B$O$=$l$ @cindex gnus-article-emphasize @kindex W e ($B35N,(B) $B?M!9$O$h$/%K%e!<%9$N5-;v$G(B @samp{_$B$3$l(B_} $B$d(B @samp{*$B$3$l(B*} $B$^$?(B -$B$O(B @samp{/$B$3$l(B/} $B$N$h$&$J$b$N$r;H$C$FC18l$r6/D4$7$^$9!#(BGnus $B$O(B $B5-;v$rL?(B +$B$O(B @samp{/$B$3$l(B/} $B$N$h$&$J$b$N$r;H$C$FC18l$r6/D4$7$^$9!#(BGnus $B$O5-;v$rL?(B $BNa(B @kbd{W e} (@code{gnus-article-emphasize}) $B$K$+$1$k;v$K$h$C$FAGE($K8+(B $B$($k$h$&$K$G$-$^$9!#(B @@ -8126,7 +8126,7 @@ gnus $B$,5-;v$rI=<($9$k4{Dj$N$d$jJ}$rJQ$($?$$$H$-(B @cindex M****s*** sm*rtq**t*s @cindex Latin 1 @code{gnus-article-dumbquotes-map} $B$K1~$8$F!"%^"#"#"#%="#(B -$B"#(B sm*rtq**t*s $B$r=hM}$7$^$9(B $B$3$N4X?t$OJ8;z$,(B sm*rtq**t* $B$+$I$&$+$r?dB,$7(B +$B"#(B sm*rtq**t*s $B$r=hM}$7$^$9!#$3$N4X?t$OJ8;z$,(B sm*rtq**t* $B$+$I$&$+$r?dB,$7(B $B$^$9$N$G!"BPOCE*$K$N$_;HMQ$5$l$k$Y$-$G$"$k$3$H$KCm0U$7$F$/$@$5$$!#(B Sm*rtq**t*s $B$O$b$C$HB?$/$N0zMQJ8;z$rDs6!$9$k$?$a$K!"%^"#"#"#%="#"#$,>!e$N$b$N$KHs>o$K;w$F$$$^$9$,!"$$$/$D$+$NJ8=q$r0l$D$NBg!<$-$$%0(B $B%k!<%W$K=8$a$^$9(B (@code{gnus-summary-read-read-document})$B!#$=$l$O$$$/$D(B -$B$+$N(B @code{nndoc} $B%0%k!<%W$r$=$l$>$l$NJ8=q$N$?$a$K(B $B3+$-!"$=$l$+$i$3$l$i(B +$B$+$N(B @code{nndoc} $B%0%k!<%W$r$=$l$>$l$NJ8=q$N$?$a$K3+$-!"$=$l$+$i$3$l$i(B $B$N(B @code{nndoc} $B%0%k!<%W$N>e$K(B @code{nnvirtual} $B%0%k!<%W$r3+$/;v$K$h$C$F(B $B$3$N;v$r2DG=$K$7$F$$$^$9!#$3$NL?Na$O%W%m%;%9(B/$B@\F,0z?t$N=,47$rM}2r$7$^(B $B$9(B (@pxref{Process/Prefix})$B!#(B @@ -9593,9 +9593,9 @@ Parameters}) $B$rJT=8$7$^$9(B (@code{gnus-summary-edit-parameters})$B!#(B $B$O$=$l$OB.EY$r$H$F$bB.$/$9$k$+$i$G$9(B) $B$N;HMQ2DG=$J(B @sc{nntp} $B%5!<%P!<$r(B $B;H$C$F$$$k$3$H$G$9!#$3$l$O320-$J$N$G$9$,!"$"$!!"Ha$7$$$+$J!"Hs>o$KNI$/$"(B $B$k;v$G$9!#(BGnus $B$O$"$J$?$,FI$s$@A4$F$N5-;v$K(B @code{Xref} $B9T$rEPO?$9$k;v$G!"(B -$B@5$7$$;v$r$7$h$&(B $B$H$7$^$9$,!"5-;v$r:o=|$9$k$+!"FI$^$J$$$G4{FI$N0u$rIU$1(B -$B$k$H!"(Bgnus $B$O$3$l$i$N5-;v$K(B @code{Xref} $B$N9T$r$N$>$-$^$o$k5!2q$rF@$k;v$,(B -$BL5$/!"Aj8_;2>H5!9=$rMQ$$$k;v$,$G$-$^$;$s!#(B +$B@5$7$$;v$r$7$h$&$H$7$^$9$,!"5-;v$r:o=|$9$k$+!"FI$^$J$$$G4{FI$N0u$rIU$1$k(B +$B$H!"(Bgnus $B$O$3$l$i$N5-;v$K(B @code{Xref} $B$N9T$r$N$>$-$^$o$k5!2q$rF@$k;v$,L5(B +$B$/!"Aj8_;2>H5!9=$rMQ$$$k;v$,$G$-$^$;$s!#(B @cindex LIST overview.fmt @cindex overview.fmt @@ -9656,7 +9656,7 @@ Gnus $B$K$$$D$G$b@5$7$$(B @code{Xref} $B$ro$KC1=c$JJ}K!$GF0:n$7$F$$$^$9!=!=$b$75-;v$K4{FI$N0u$r(B -$BIU$1$l$P!"$=$l$O$3$N(B Message-ID $B$r(B $B%-%c%C%7%e$K2C$($^$9!#Z$rMW5a$7$F$$$k>l9g$KM-MQ$G$9!#4X(B $B$b$7$"$J$?$N%K%e!<%9%5!<%P!<$,K\Ev$K%a!<%j%s%0%j%9%H$+$i(B @sc{nntp} $B%5!<(B $B%P!<$X$N%2!<%H%&%'%$$rDs6!$7$F$$$k$N$G$"$l$P!"$=$l$i$N%0%k!<%W$OLdBj$J$/(B $BFI$a$k$G$7$g$&!#$7$+$74JC1$K$O$=$l$i$KEj9F(B/$B%U%)%m!<%"%C%W$9$k$3$H$O$G$-(B -$B$^$;$s!#0l$D$N2r7hK!$O(B $B%0%k!<%W%Q%i%a!<(B +$B$^$;$s!#0l$D$N2r7hK!$O%0%k!<%W%Q%i%a!<(B $B%?(B (@pxref{Group Parameters}) $B$K(B @code{to-address} $B$r2C$($k;v$G$9!#4JC1(B $B$K$G$-$k$N$O!"(B@code{gnus-mailing-list-groups} $B$r!"K\Ev$K%a!<%j%s%0%j%9%H(B $B$G$"$k$h$&$J%0%k!<%W$K9gCW$9$k@55,I=8=$K@_Dj$9$k$3$H$G$9!#$=$N8e$O!"$9$/(B @@ -10771,7 +10771,7 @@ from date id references chars lines xref extra $B$N3F%X%C%@!<$+$i@.$k%Y%/(B @cindex nndraft @vindex nndraft-directory -$B2<=q$-%0%k!<%W$O(B @samp{nndraft:drafts} $B$H8F$P$l$kFCJL$J%0%k!<%W(B $B$G$9(B ($B$b(B +$B2<=q$-%0%k!<%W$O(B @samp{nndraft:drafts} $B$H8F$P$l$kFCJL$J%0%k!<%W$G$9(B ($B$b(B $B$7$"$J$?$,A4$F$rCN$i$J$1$l$P$J$i$J$$$N$G$"$l$P!"$=$l$O(B @code{nndraft} $B%0(B $B%k!<%W$H$7$F$C$F40A4$K9gCW$7$J$1$l$P$J$j$^$;$s!#@55,I=8=$G%U%#!<%k%IL>$+(B @findex nnmail-split-fancy-with-parent $B4X?t(B @code{nnmail-split-fancy-with-parent} $B$O!"%U%)%m!<%"%C%W5-;v$r?F5-(B $B;v$HF1$8%0%k!<%W$K?6$jJ,$1$k$?$a$K;H$$$^$9!#%a!<%k$N?6$jJ,$1$r0l@87|L?@_(B -$BDj$7$F$_$F$b40`z$K$O$G$-$J$$$3$H$,$"$j$^$9$M!#(B $BNc$($P!">e;J$+$i8D?M08$F(B -$B$N%a!<%k$,FO$$$?$H$7$^$9!#<+J,$,7H$C$F$$$k%W%m%8%'%/%H$H$OJL$NOC$G$9!#$1(B -$B$l$I!VB>$N%a!<%k$H6hJL$G$-$k$h$&$K$3$l$3$l$3$&$$$&8@MU$rI=Bj$K=q$$$F$/$@(B -$B$5$$!W$H>e;J$K8~$+$C$F;X?^$9$k$o$1$K$O$$$-$^$;$s$+$i!"7k6I<+J,$Ne;J$+$i8D?M08$F$N(B +$B%a!<%k$,FO$$$?$H$7$^$9!#<+J,$,7H$C$F$$$k%W%m%8%'%/%H$H$OJL$NOC$G$9!#$1$l(B +$B$I!VB>$N%a!<%k$H6hJL$G$-$k$h$&$K$3$l$3$l$3$&$$$&8@MU$rI=Bj$K=q$$$F$/$@$5(B +$B$$!W$H>e;J$K8~$+$C$F;X?^$9$k$o$1$K$O$$$-$^$;$s$+$i!"7k6I<+J,$N$C$F40A4$K9gCW$7$J$1$l$P$J$j$^$;$s!#@55,I=8=$G%U%#!<%k%IL>$+(B $B$3$N5!G=$Ol9g!"(BGnus $B$O8+$D$1$?A45-(B -$B;v$N%a%C%;!<%8(B ID $B$r(B $BJQ?t(B @code{nnmail-message-id-cache-file} $B$,;XDj$9$k(B +$B;v$N%a%C%;!<%8(B ID $B$rJQ?t(B @code{nnmail-message-id-cache-file} $B$,;XDj$9$k(B $B%U%!%$%k$K5-O?$7$^$9!#$3$N$H$-!"$=$l$>$l$N5-;v$,B8:_$9$k%0%k!<%W$NL>A0$r(B $BJ;5-$7$^$9(B ($B$?$@$7%a!<%k$N>l9g$@$1!"$5$b$J$1$l$P%0%k!<%WL>$OD4$Y$^$;$s(B)$B!#(B $B$5$F!"$$$h$$$h%a!<%k$N?6$jJ,$1$,;O$^$k$H!"4X?t(B @@ -15916,11 +15916,11 @@ nnvirtual $B%0%k!<%W(B (@dfn{nnvirtual group}) $B$O$N%0%k!<%W$N=89g0J>e @code{nnvirtual} $B$O2>A[%0%k!<%W$KF~$C$?$H$->o$K!"L$FI5-;v$rAv::$7$^$9!#(B $B$3$NJQ?t$,(B @code{nil} ($B$3$l$,=i4|@_Dj(B)$B$G$"$C$F!"2>A[%0%k!<%W$r:n@.$7$?8e(B $B$K9=@.%0%k!<%WFb$N5-;v$rFI$s$@>l9g$O!"$=$N9=@.%0%k!<%W$GFI$^$l$?5-;v$O!"(B -$B2>A[%0%k!<%W$KF~$C$?$H$-$KI=<($5$l(B $B$k$G$7$g$&!#$b$76&DL$N9=@.%0%k!<%W$r(B -$B;}$DFs$D$N2>A[%0%k!<%W$,$"$k>l9g$K$b$3$N1F6A$,$"$j$^$9!#$=$N>l9g$O$3$NJQ(B -$B?t$r(B @code{t} $B$K$7$?J}$,NI$$$G$9!#$"$k$$$O2>A[%0%k!<%W$KF~$k;~$K!"Kh2s$=(B -$B$N%0%k!<%W$N>e$G(B @code{M-g} $B$rC!$$$F$bNI$$$G$9(B --- $B$3$l$O$[$\F1MM$N8z2L(B -$B$,$"$j$^$9!#(B +$B2>A[%0%k!<%W$KF~$C$?$H$-$KI=<($5$l$k$G$7$g$&!#$b$76&DL$N9=@.%0%k!<%W$r;}(B +$B$DFs$D$N2>A[%0%k!<%W$,$"$k>l9g$K$b$3$N1F6A$,$"$j$^$9!#$=$N>l9g$O$3$NJQ?t(B +$B$r(B @code{t} $B$K$7$?J}$,NI$$$G$9!#$"$k$$$O2>A[%0%k!<%W$KF~$k;~$K!"Kh2s$=$N(B +$B%0%k!<%W$N>e$G(B @code{M-g} $B$rC!$$$F$bNI$$$G$9(B --- $B$3$l$O$[$\F1MM$N8z2L$,(B +$B$"$j$^$9!#(B @code{nnvirtual} $B$O%a!<%k$H%K%e!<%9$NN>J}$N%0%k!<%W$r9=@.%0%k!<%W$H$9$k(B $B;v$,$G$-$^$9!#(B@code{nnvirtual} $B%0%k!<%W$N5-;v$KJVEz$9$k$H$-$O!"(B @@ -19333,7 +19333,7 @@ gnus $B$ODL>o$[$H$s$I$N%P%C%U%!$G!"%]%$%s%H$r3F9T$N$"$i$+$8$a7h$a$i$l$?>l(B $B$*$)$C$H!#Fs$D$N%P%C%U%!$KIT;W5D$J(B 100% $B%?%0$,IU$$$F$$$^$9!#$=$7$F!"$"(B $B$N(B @code{horizontal} $B$C$F$$$&$b$N$O2?$G$7$g$&(B? -$B$b$7J,3d$N0l$D$N:G=i$NMWAG$,(B @code{horizontal} $B$G$"$C$?$J$i!"(Bgnus $B$O(B $B%&%#(B +$B$b$7J,3d$N0l$D$N:G=i$NMWAG$,(B @code{horizontal} $B$G$"$C$?$J$i!"(Bgnus $B$O%&%#(B $B%s%I%&$r?eJ?$KJ,3d$7!"Fs$D$N%&%#%s%I%&$r2#$KJB$Y$^$9!#$3$l$i$N$=$l$>$l$N(B $B>.JR$NCf$G$O!"A4$F$rIaDL$NN.57$G9T$&;v$,$G$-$^$9!#(B@code{horizontal} $B$N8e(B $B$N?t;z$O!"$3$N>.JR$K2hLL$N$I$l$/$i$$$N3d9g$,M?$($i$l$k$+$r;XDj$7$^$9!#(B @@ -20899,8 +20899,9 @@ Spam $B$H@o$&$?$a$N?7$7$$5;K!$O!"%a%C%;!<%8$rAw?.$9$k:]$K$$$/$P$/$+$NIiC4(B @code{spam.el} $B$N??$NL\E*$O(B spam $B8!=P$H_I2a$N$?$a$N41@)%;%s%?!<(B $B$r(B gnus $B$NCf$K;}$D$3$H$G$9!#$=$N$?$a$K(B @code{spam.el} $B$OFs$D$N$3$H$r9T$J(B -$B$$$^$9(B: $BF~$C$F$/$k%a!<%k$r_I2a$7!"(Bspam $B$H$7$FCN$i$l$k%a!<%k$rJ,@O$9$k$3(B -$B$H$G$9!#(B +$B$$$^$9(B: $BF~$C$F$/$k%a!<%k$r_I2a$7!"(Bspam $B$^$?$O(B ham $B$H$7$FCN$i$l$k%a!<%k$r(B +$BJ,@O$9$k$3$H$G$9!#(B@emph{Ham} $B$O(B @code{spam.el} $B$N$$$?$k=j$G(B spam $B$G$O$J(B +$B$$%a%C%;!<%8$r<($9$?$a$K;H$&L>A0$G$9!#(B $B$G$O(B @code{spam.el} $B$r(B load $B$9$k$H2?$,5/$-$k$G$7$g$&$+(B? $BBh0l$K!"0J2<$N(B $B%-!<%\!<%IL?Na$,;H$($k$h$&$K$J$j$^$9(B: @@ -20917,7 +20918,8 @@ Spam $B$H@o$&$?$a$N?7$7$$5;K!$O!"%a%C%;!<%8$rAw?.$9$k:]$K$$$/$P$/$+$NIiC4(B $B8=:_$N5-;v$K(B spam $B$H$7$F0u$rIU$1!"$=$l$r(B @samp{H} $B0u$GI=<($7$^$9!#(B Spam $B5-;v$r8+$?$H$-$O$$$D$G$b!"%0%k!<%W$rH4$1$kA0$KI,$:(B @kbd{M-d} $B$G$=$N(B -$B35N,9T$K0u$rIU$1$k$h$&$K$7$F2<$5$$!#(B +$B35N,9T$K0u$rIU$1$k$h$&$K$7$F2<$5$$!#$3$l$O(B @emph{spam} $B%0%k!<%W$NL$FI5-(B +$B;v$KBP$7$F$O<+F0E*$K9T$J$o$l$^$9!#(B @item M s t @itemx S t @@ -20929,49 +20931,89 @@ Spam $B5-;v$r8+$?$H$-$O$$$D$G$b!"%0%k!<%W$rH4$1$kA0$KI,$:(B @kbd{M-d} $B$G$=$ $B$3$N%3%^%s%I$,$A$c$s$HF/$/$?$a$K$O(B bogofilter $B$N=hM}$rM-8z$K$7$J$1$l$P$J(B $B$j$^$;$s!#(B -@xref{Bogofilter}. +@xref{Bogofilter}$B!#(B + @end table -gnus $B$O$"$J$?$,e$N(B spam $B%0%k!<%W$K(B spam $B5-;v$r=8$a$F!"JQ(B -$B?t(B @code{spam-junk-mailgroups} $B$rE,@Z$K@_Dj$9$k$3$H$G$9!#$3$l$i$N%0%k!<(B -$B%W$G$O!"%G%#%U%)%k%H$G$9$Y$F$N%a%C%;!<%8$,(B spam $B$G$"$k$H2rC$5$J$1$l$P$J$j$^$;(B -$B$s!#(BSpam $B%0%k!<%W$+$iH4$1$k$H$-$K!"(B@samp{H} $B0u$,IU$$$?$^$^$N$9$Y$F$N%a%C(B -$B%;!<%8$O(B spam $B8!=P%(%s%8%s(B (bogofilter$B!"(Bifile$B!"$=$NB>(B) $B$KEO$5$l$^$9!#(B -@samp{H} $B0u$r>C$9$K$O(B @kbd{M-u} $B$G5-;v$r(B "$BL$FI(B" $B$K$9$k$+!"(B@kbd{d} $B$G$=$l(B -$B$r(B spam $B$G$O$J$$$b$N$H$7$FFI$s$@$3$H$r@k8@$7$F2<$5$$!#%0%k!<%W$rH4$1$?$H(B -$B$-!"$9$Y$F$N(B @samp{H} $B0u$,IU$$$?5-;v$O%;!<%V$5$l$?$+$I$&$+$K4X78L5$/!"(B -Bogofilter $B$+(B ifile (@code{spam-use-bogofilter} $B$H(B @code{spam-use-ifile} $B$K(B -$B$h$k(B) $B$KAw$i$l!"$=$l$i$r(B spam $B$NI8K\$H$7$F3X=,$7$^$9!#(B +$B$^$?!"(B@code{spam.el} $B$r(B load $B$9$k$H!"$=$NJQ?t72$r%+%9%?%^%$%:$9$k$3$H$,(B +$B$G$-$k$h$&$K$J$j$^$9!#(B@samp{spam} $BJQ?t%0%k!<%W$K$D$$(B +$B$F(B @code{customize-group} $B$r;n$7$F$_$F2<$5$$!#(B + +Ham $B%W%m%;%C%5!<$H(B spam $B%W%m%;%C%5!<$N35G0$OHs>o$K=EMW$G$9!#$"$k%0%k!<%W(B +$B$N(B ham $B%W%m%;%C%5!<$H(B spam $B%W%m%;%C%5!<$O!"(B@code{spam-process} $B%0%k!<%W(B +$B%Q%i%a!<%?$+(B @code{gnus-spam-process-newsgroups} $BJQ?t$G@_Dj$9$k$3$H$,$G(B +$B$-$^$9!#8e$GF1MM$N%a!<%k$r(B spam $B$G$O$J$$$H2re$N(B spam $B%0(B +$B%k!<%W$K(B spam $B5-;v$r=8$a$F!"JQ?t(B @code{spam-junk-mailgroups} $B$rE,@Z$K@_(B +$BDj$b$7$/$O%+%9%?%^%$%:$7$J$1$l$P$J$j$^$;$s!#$^$?!"(Bspam $B$r4^$a$k%0%k!<%W(B +$B$r!"$=$N%0%k!<%W%Q%i%a!<(B +$B%?(B @code{spam-contents} $B$r(B @code{gnus-group-spam-classification-spam} $B$K(B +$B@_Dj$9$k$+!"$^$?$O$=$l$KBP1~$9$kJQ(B +$B?t(B @code{gnus-spam-newsgroup-contents} $B$r%+%9%?%^%$%:$9$k$3$H$K$h$C$F@k(B +$B8@$9$k$3$H$,$G$-$^$9!#(B@code{spam-contents} $B%0%k!<%W%Q%i%a!<%?(B +$B$H(B @code{gnus-spam-newsgroup-contents} $BJQ?t$O!"$=$l$i$NC$5$J$1$l$P$J$j$^$;$s!#(B@samp{H} $B0u$r>C$9$K$O(B @kbd{M-u} $B$G(B +$B$=$N5-;v$r!VL$FI!W$K$9$k$+!"$"$k$$$O(B @kbd{d} $B$G(B spam $B$G$O$J$$$b$N$H$7$F(B +$BFI$s$@$3$H$r@k8@$9$l$PNI$$$G$7$g$&!#%0%k!<%W$rH4$1$k$H$-!"$9$Y$F$N(B spam +$B0u(B (@samp{H}) $B$,IU$$$?5-;v$O(B spam $B%W%m%;%C%5!<$KAw$i$l!"$=$l$i$r(B spam $B$N(B +$BI8K\$H$7$F3X=,$7$^$9!#(B $B%a%C%;!<%8$OB>$N$$$m$$$m$JJ}K!$K$h$C$F$b>C5n$5$l$k$+$b$7$l$^$;$s$7!"(B -@code{spam-ham-marks-form} $B$,8e=R$N$h$&$K>e=q$-$5$l$J$1$l$P!"Dc$$%9%3%"(B -$B$N$?$a$N(B @samp{Y} $B0u$HF1MM!"%G%#%U%)%k%H$N4{FI$+L@<(E*$J>C5n$N$?$a(B +@code{spam-ham-marks} $B$,8e=R$N$h$&$K>e=q$-$5$l$J$1$l$P!"Dc$$%9%3%"$N$?$a(B +$B$N(B @samp{Y} $B0u$HF1MM!"%G%#%U%)%k%H$N4{FI$+L@<(E*$J>C5n$N$?$a(B $B$N(B @samp{R} $B$H(B @samp{r} $B0u!"<+F0$^$?$OL@<(E*$J:o=|$N$?$a(B $B$N(B @samp{X} $B$H(B @samp{K} $B0u!"$=$l$i$9$Y$F$,(B spam $B$H$OL54X78$G$"$k$H2rDj$O!"FC$KK\J*$N(B spam $B$r8!=P$9$k$?$a$K>C5n(B (kill) $B%U%!%$%k(B -$B$+%9%3%"%U%!%$%k$r;H$C$F$$$k>l9g$O4V0c$C$F$$$k$+$b$7$l$^$;$s!#$=$&$G$"$l(B -$B$P(B @code{spam-ham-marks-form} $B$rD4@0$9$k$Y$-$G$9!#%0%k!<%W$rH4$1$k$H$-$K!"(B -$B>e5-$N0u$,IU$$$?$9$Y$F$N%;!<%V$5$l$F$$$J$$5-;v$O(B Bogofilter $B$+(B ifile $B$K(B -$BAw$i$l!"$=$l$i$r(B spam $B$G$O$J$$I8K\$H$7$F3X=,$7$^$9!#0U?^E*$K$?$/$5$s$N>C(B -$B5n$r9T$J$&$H!"$?$^$K$=$l$O8+$F$$$J$$(B @samp{K} $B0u$,IU$$$?5-;v$G=*$o$k$+$b(B -$B$7$l$^$;$s!#$=$7$F$=$l$i$O6vA3$K(B spam $B$r4^$s$G$$$k$+$b$7$l$^$;$s!#:G$bNI(B -$B$$$N$O!"K\Ev$N(B spam $B$K(B @samp{H} $B$,IU$$$F$$$F!"B>$K2?$bL5$$$3$H$r3N$+$a$k(B -$B$3$H$G$9!#(B - -$BB>$N$9$Y$F$N%^!<%/$,(B Bogofilter $B$"$k$$$O(B ifile $B$NF0:n$NA0Ds$H$J$k>r7oIU(B -$B$1$K4sM?$9$k$o$1$G$O$"$j$^$;$s!#$H$j$o$12D;k(B (ticked)$B!"J]N1(B (dormant) $B$^(B -$B$?$O(B soup $B$5$l$F$$$k5-;v$O!"K\Ev$K>C5n$5$l$?8e$G4sM?$9$k$N$,E,Ev$J$N$G!"(B -$B$=$l$i$rAa$^$C$F;H$&I,MW$O$"$j$^$;$s!#L@<(E*$K4|8B@Z$l>C5n$5$l$?5-;v$O4s(B -$BM?$7$^$;$s!#%3%^%s%I(B @kbd{E} $B$O(B Bogofilter $B$^$?$O(B ifile $B$,>o$K8+$k$3$HL5(B -$B$7$K5-;v$rDj$O!"K\J*$N(B spam $B$r8!=P$9$k$?$a$K>C5n(B (kill) $B%U%!%$%k$+%9(B +$B%3%"%U%!%$%k$rFCJL$K;H$C$F$$$k>l9g$O4V0c$C$F$$$k$+$b$7$l$^$;$s!#$=$&$G$"(B +$B$l$P(B @code{spam-ham-marks} $BJQ?t$rD4@0$9$k$Y$-$G$9!#(B + +@defvar spam-ham-marks +$B$3$NJQ?t$r(B ham $B$G$"$k$H2rC5n(B (deleted)$B!"4{FI(B (read)$B!":o=|(B (killed)$B!"(Bkill $B%U%!%$%k(B +$B$K$"$k$b$N(B (kill-filed) $B$*$h$SDc$$%9%3%"(B (low-score) $B0u$N%j%9%H$G$9!#(B +@end defvar + +@defvar spam-spam-marks +$B$3$NJQ?t$r(B spam $B$G$"$k$H2rC5n$r9T$J$&$H!"$?$^$K$=$l$O8+$F$$$J$$(B @samp{K} $B0u$,IU(B +$B$$$?5-;v$G=*$o$k$+$b$7$l$^$;$s!#$=$7$F$=$l$i$O6vA3$K(B spam $B$r4^$s$G$$$k$+(B +$B$b$7$l$^$;$s!#:G$bNI$$$N$O!"K\Ev$N(B spam $B$K(B @samp{H} $B$,IU$$$F$$$F!"B>$K2?(B +$B$bL5$$$3$H$r3N$+$a$k$3$H$G$9!#(B + +@emph{Spam} $B%0%k!<%W$rH4$1$k$H$-$K!"(Bspam $B0u$,IU$$$F$$$k$9$Y$F$N5-;v(B +$B$K$O(B spam $B%W%m%;%C%5!<$G=hM}$7$?8e$G4|8B@Z$l>C5n$N0u$,IU$1$i$l$^$9!#$3$l(B +$B$O(B @emph{$BL$J,N`(B} $B$^$?$O(B @emph{ham} $B%0%k!<%W$KBP$7$F$O9T$J$o$l$^$;$s!#(B + +@emph{Ham} $B%0%k!<%W$rH4$1$k$H$-$K!"(Bham $B0u$,IU$$$F$$$k$9$Y$F$N5-;v(B +$B$O(B ham $B%W%m%;%C%5!<$KAw$i$l!"$=$l$i$r(B spam $B$G$O$J$$I8K\$H$7$F3X=,$7$^$9!#(B + +@strong{TODO: @code{spam-use-ifile} $B$O8=>u$G$OF0:n$7$^$;$s!#;d(B ($BLuCm(B: +Teodor Zlatanov) $B$O$=$N5!G=$,(B @code{spam.el} $B$G$O$J$/(B $B$F(B @code{ifile-gnus.el} $B$G9T$J$o$l$k$Y$-$@$H;W$&$N$G!"(B -@code{ifile-gnus.el} $B$N:nA0$N%0%k!<%W$KAw$j$^$9!#DL(B -$B>o$=$N%0%k!<%WL>$O(B @samp{spam} $B$G$9!#(B +$B$rJQ?t(B @code{spam-split-group} $B$GM?$($i$l$kL>A0$N%0%k!<%W$KAw$j$^$9!#%G%#(B +$B%U%)%k%H$G$O$=$N%0%k!<%WL>$O(B @samp{spam} $B$G$9$,!"%+%9%?%^%$%:$9$k$3$H$O(B +$B2DG=$G$9!#(B $B0J2<$O(B @code{spam-split} $B$NF0:n$r@)8f$9$k$?$a$K;H$&$3$H$,$G$-$k3Fl9g$O!"$3$NJQ?t(B +$B$r(B t $B$K@_Dj$7$F2<$5$$!#Aw?.l9g$O!"$3$NJQ?t$r(B t $B$K@_Dj$7$F2<$5$$!#(B +$BF~$C$F$/$k%a!<%k$rJ,3d$9$k$H$-$K%[%o%$%H%j%9%H$r;H$$$?$$>l9g$O!"$3$NJQ?t(B +$B$r(B t $B$K@_Dj$7$F2<$5$$!#Aw?.$NJ}K!(B +$B$GEA$($i$l$J$+$C$?$J$i$P!"$9$Y$F$N?M$r(B spammer $B$G$"$k$H8+$J$7$^$9!#Cm0U(B +$B$7$F;H$C$F2<$5$$!#(B +@end defvar + +@defvar gnus-group-spam-exit-processor-blacklist +$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W(B +$B$N(B @code{spam-process} $B%Q%i%a!<%?$K2C$($k$+!"$^$?(B +$B$O(B @code{gnus-spam-process-newsgroups} $BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k(B +$B$,%0%k!<%W$N(B @code{spam-process} $B%Q%i%a!<%?$K2C$($i$l$k$H!"(Bspam $B0u$,IU$$(B +$B$?5-;v$NAw?.o$K9-$$HO0O$rM-8z$HG'$a$k$h$&$K$J$C$F$$$J$$$H!"$?$V$s$3$N%*%W%7%g(B +$B%9%H$,Hs>o$K9-$$HO0O$rM-8z$HG'$a$k$+$^$?$O42MF$G$J$$$H!"$?$V$s$3$N%*%W%7%g(B $B%s$O$[$H$s$I$N(B gnus $B$N%f!<%6!<$K$H$C$FM-1W$G$O$"$j$^$;$s!#(B @ref{BBDB Whitelists} $B$b8+$F2<$5$$!#%[%o%$%H%j%9%H$N3F9`L\$O(B Emacs $B$N@5(B $B5,I=8=%7%s%?%C%/%9$r;H$$$^$9!#(B -$B%V%i%C%/%j%9%H$H%[%o%$%H%j%9%H$N=j:_$O(B @code{spam-directory} $BJQ?t(B ($B%G%#(B -$B%U%)%k%H$O(B @file{~/News/spam}) $B$G%+%9%?%^%$%:$G$-$^$9!#%V%i%C%/%j%9%H$H(B -$B%[%o%$%H%j%9%H$N%U%!%$%k$O$=$N%G%#%l%/%H%j$K$"$j!"$=$l$>(B +$B%V%i%C%/%j%9%H$H%[%o%$%H%j%9%H$N%U%!%$%k$N=j:_$O!"(B +@code{spam-directory} $BJQ?t(B ($B%G%#%U%)%k%H$O(B @file{~/News/spam}) $B$^$?(B +$B$OD>@\(B @code{spam-whitelist} $B$H(B @code{spam-blacklist} $BJQ?t$G%+%9%?%^%$%:(B +$B$9$k$3$H$,$G$-$^$9!#%[%o%$%H%j%9%H$H%V%i%C%/%j%9%H$N%U%!%$%k$O!"%G%#%U%)(B +$B%k%H$G$O(B @code{spam-directory} $B$N%G%#%l%/%H%j$K$"$j!"$=$l$>(B $B$l(B @file{whitelist} $B$H(B @file{blacklist} $B$H$$$&L>A0$,IU$1$i$l$^$9!#(B @node BBDB Whitelists @@ -21043,16 +21111,26 @@ Bogofilter $B$+(B ifile (@code{spam-use-bogofilter} $B$H(B @code{spam-use-if @cindex BBDB, spam filtering @cindex spam.el -@defvar spam-use-bbdb +@defvar spam-use-BBDB @code{spam-use-whitelist} (@pxref{Blacklists and Whitelists}) $B$K;w$F$$$^(B $B$9$,!"%[%o%$%H%j%9%H$N%"%I%l%9$N8;$H$7$F!"@55,I=8=$G$O$J$$(B BBDB $B$r;H$$$^(B -$B$9!#(B@code{spam-use-bbdb} $B$r$A$c$s$HF0:n$5$;$k$K$O(B BBDB $B$r(B load $B$7$J$1$l(B +$B$9!#(B@code{spam-use-BBDB} $B$r$A$c$s$HF0:n$5$;$k$K$O(B BBDB $B$r(B load $B$7$J$1$l(B $B$P$J$j$^$;$s!#(BBBDB $B$K$"$k%"%I%l%9$@$1$,5v$5$l!"B>$O$9$Y$F(B spam $B$H$7$FJ,(B $BN`$5$l$^$9!#(B @end defvar +@defvar gnus-group-ham-exit-processor-BBDB +$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W(B +$B$N(B @code{spam-process} $B%Q%i%a!<%?$K2C$($k$+!"$^$?(B +$B$O(B @code{gnus-spam-process-newsgroups} $BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k(B +$B$,%0%k!<%W$N(B @code{spam-process} $B%Q%i%a!<%?$K2C$($i$l$k$H!"(Bham $B0u$,IU$$(B +$B$?(B @emph{ham} $B%0%k!<%W$N5-;v$NAw?.)$5$l$^$9!#(B + +@end defvar + +$B%V%i%C%/%[!<%k!&%A%'%C%/$OF~$C$FMh$k%a!<%k$KBP$7$F$@$19T$J$o$l$^$9!#%V%i%C(B +$B%/%[!<%k$K(B spam $B$^$?$O(B ham $B%W%m%;%C%5!<$O$"$j$^$;$s!#(B + @node Bogofilter @subsubsection Bogofilter @cindex spam filtering @@ -21085,10 +21179,10 @@ Bogofilter $B$+(B ifile (@code{spam-use-bogofilter} $B$H(B @code{spam-use-if @defvar spam-use-bogofilter -Eric Raymond $B$N?WB.$J(B Bogofilter $B$r;HMQ$7$?$$>l9g$O!"$3$NJQ?t$r%;%C%H$7(B -$B$F$/$@$5$$!#$3$l$O!"%P!<%8%g%s(B 0.4 $B$N%m!<%+%k$K%Q%C%A$,Ev$?$C$?%3%T!<$G(B -$B%F%9%H$5$l$^$7$?!#(B@code{spam.el} $B$K$"$k%$%s%9%H!<%k$K4X$9$k%3%a%s%H$rFI(B -$B$s$G3N$+$a$F2<$5$$!#(B +Eric Raymond $B$N?WB.$J(B Bogofilter $B$r(B @code{spam-split} $B$K;HMQ$7$?$$>l9g$O!"(B +$B$3$NJQ?t$r%;%C%H$7$F$/$@$5$$!#$3$l$O!"%P!<%8%g%s(B 0.4 $B$N%m!<%+%k$K%Q%C%A(B +$B$,Ev$?$C$?%3%T!<$G%F%9%H$5$l$^$7$?!#(B@code{spam.el} $B$K$"$k%$%s%9%H!<%k$K(B +$B4X$9$k%3%a%s%H$rFI$s$G3N$+$a$F2<$5$$!#(B Spam $B5-;v$@$1$N(B @samp{H} $B0u$r4XO"IU$1$k:G>.$N@$OC$K$h$C$F!"(BBogofilter $B%H(B $B%l!<%K%s%0$O$9$Y$F$+$J$j<+F0E*$K$J$j$^$9!#3F%+%F%4%j!<$N(B spam $B$+$=$&$G$J(B @@ -21099,6 +21193,20 @@ Spam $B5-;v$@$1$N(B @samp{H} $B0u$r4XO"IU$1$k:G>.$N@$OC$K$h$C$F!"(BBogofilte spam $BEY(B?) $B%9%3%"(B (0.0$B!A(B1.0) $B$r!"%9%3%"$K:G$bCx$7$/4sM?$9$k5-;v$N8l$H$$$C(B $B$7$g$K!"B>$N%P%C%U%!$KI=<($9$k$3$H$rB%$7$^$9!#(B +Path $B$K(B @code{bogofilter} $B$Nl9g!"(BBogofilter $B$N=hM}$O(B +$BC$5$l$^$9!#(B + +@end defvar + +@defvar gnus-group-spam-exit-processor-bogofilter +$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W(B +$B$N(B @code{spam-process} $B%Q%i%a!<%?$K2C$($k$+!"$^$?(B +$B$O(B @code{gnus-spam-process-newsgroups} $BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k(B +$B$,%0%k!<%W$N(B @code{spam-process} $B%Q%i%a!<%?$K2C$($i$l$k$H!"(Bspam $B0u$,IU$$(B +$B$?5-;v$,(B bogofilter $B$N(B spam $B%G!<%?%Y!<%9$K2C$($i$l!"(Bham $B0u$,IU$$$?5-;v(B +$B$,(B bogofilter $B$N(B ham $B%G!<%?%Y!<%9$K2C$($i$l$^$9!#(B +@strong{Bogofilter $B$N(B spam $B%W%m%;%C%5!<$O!"$5$i$K(B ham $B=hM}$b9T$J$&$?$@0l(B +$B$D$N(B spam $B%W%m%;%C%5!<$G$"$k$3$H$KCm0U$7$F2<$5$$!#(B} @end defvar @node Ifile spam filtering @@ -21109,24 +21217,28 @@ spam $BEY(B?) $B%9%3%"(B (0.0$B!A(B1.0) $B$r!"%9%3%"$K:G$bCx$7$/4sM?$9$k5 @defvar spam-use-ifile -Bogofilter $B$K;w$?E}7WJ,@O4o$G$"$k(B Ifile $B$r;H$$$?$$>l9g$O!"$3$NJQ?t$rM-8z(B -$B$K$7$F2<$5$$!#:#$N$H$3$m(B @code{ifile-gnus.el} $B$r(B load $B$7$J$1$l$P$J$j$^$;(B -$B$s!#(BIfile $B$N(B @code{spam.el} $B$X$NE}9g$O$^$@:Q$s$G$$$^$;$s$,!"$=$l$r9%$`$J(B -$B$i$P(B @code{ifile-gnus.el} $B$rC1FH$K;H$&$3$H$,$G$-$^$9!#(B +Bogofilter $B$K;w$?E}7WJ,@O4o$G$"$k(B Ifile $B$r(B @code{spam-split} $B$K;H$$$?$$(B +$B>l9g$O!"$3$NJQ?t$rM-8z$K$7$F2<$5$$!#:#$N$H$3(B +$B$m(B @code{ifile-gnus.el} $B$r(B load $B$7$J$1$l$P$J$j$^$;$s!#(B +Ifile $B$N(B @code{spam.el} $B$X$NE}9g$O$^$@:Q$s$G$$$^$;$s$,!"$=$l$r9%$`$J$i(B +$B$P(B @code{ifile-gnus.el} $B$rC1FH$K;H$&$3$H$,$G$-$^$9!#(B @end defvar +Ifile $B$O!"(B@code{spam-split} $B$rDL$7$FF~$C$FMh$?%a!<%k$r(B spam $B$H(B ham $B$K_I(B +$B2a$9$k$@$1$N$?$a$K;H$&$3$H$,$G$-$^$9!#$=$l$O(B @code{ifile-gnus.el} $B$Nl9g$O!"$3$NJQ?t$rM-8 "Blackbox $B$r;H$&$H$-$O(B t $B$K$9$k!#(B") @end example -@code{spam-list-of-checks} $B$K(B +@code{spam-list-of-checks} $B$K(B @example (spam-use-blackbox . spam-check-blackbox) @end example @@ -21150,6 +21262,62 @@ Bogofilter $B$K;w$?E}7WJ,@O4o$G$"$k(B Ifile $B$r;H$$$?$$>l9g$O!"$3$NJQ?t$rM-8 $B$?$K$G$-$k$3$H$NNc$O!"4{B8$N(B @code{spam-check-*} $B4X?t$r;2>H$7$F$/$@$5$$!#(B @end enumerate +Spam $B$H(B ham $B%a%C%;!<%8$r=hM}$9$k$K$O!"0J2<$rMQ0U$7$F2<$5$$(B: + +@enumerate + +@item +$B%3!<%I(B + +Spam $B$^$?$O(B ham $B$N%W%m%;%C%5!<$rMQ0U$9$kI,MW$O$"$j$^$;$s!#(B +Blackbox $B$,(B spam $B$^$?$O(B ham $B$N=hM}$r%5%]!<%H$9$k>l9g$@$1!"$=$l$i$rMQ0U$7(B +$B$F2<$5$$!#(B + +@example +(defvar gnus-group-spam-exit-processor-blackbox "blackbox" + "$B35N,$r=P$k$H$-$K8F$P$l$k(B blackbox $B$N(B spam $B%W%m%;%C%5!$=$&$H7h?4$7$^$7(B $B$?!#(B @@ -21919,8 +22087,8 @@ Gnus $B$OFs$D$NCJ3,$N=[4D$G3+H/$5$l$F$$$^$9!#:G=i$NCJ3,(B @cindex Incoming* @vindex mail-source-delete-incoming -$B%"%k%U%!(B Gnusae $B$H(B $B%j%j!<%9$5$l$?(B Gnusae $B$G$OJQ?t$N=i4|CM$,0c$&$b$N$,$"(B -$B$j$^$9!#FC$K!"(B@code{mail-source-delete-incoming} $B$O%"%k%U%!(B gnusae $B$G(B +$B%"%k%U%!(B Gnusae $B$H%j%j!<%9$5$l$?(B Gnusae $B$G$OJQ?t$N=i4|CM$,0c$&$b$N$,$"$j(B +$B$^$9!#FC$K!"(B@code{mail-source-delete-incoming} $B$O%"%k%U%!(B gnusae $B$G(B $B$O(B @code{nil} $B$G!"%j%j!<%9$5$l$?(B gnusae $B$G$O(B @code{t} $B$G$9!#$3$l$O%a!<%k(B $B$r07$C$F$$$k:]$K!"%"%k%U%!%j%j!<%9$Nsrsw$K$h$j%a!<%k$r<:$J$&$3$H$rHr$1$k(B $B$?$a$G$9!#(B @@ -21954,7 +22122,7 @@ Micro$oft---$B$"$!!#%"%^%A%e%"!#;d$O(B @emph{$B$b$C$H(B} $B0-$$!#(B($B$b$ @itemize @bullet @item -$BG_ED(B $B@/?.(B---$B85$N(B @sc{gnus} $B$r=q$$$??M$G$9!#(B +$BG_ED@/?.(B---$B85$N(B @sc{gnus} $B$r=q$$$??M$G$9!#(B @item Shenghuo Zhu---uudecode.el, mm-uu.el, rfc1843.el, webmail.el, @@ -23116,7 +23284,7 @@ gnus $B$O4pK\E*$J%a%G%#%"$r07$$$^$;$s!#$9$Y$F$O%P%C%/%(%s%I$K$h$C$F9T$J$o(B @item $B4pK\(B (native) @cindex native Gnus $B$O$$$D$b0l$D$NJ}K!(B ($B$H%P%C%/%(%s%I(B) $B$r%K%e!<%9$rF@$k$?$a$N(B @dfn{$B4p(B -$BK\(B} $B$b$7$/$O=i4|@_Dj(B $B$H$7$F;H$$$^$9!#(B +$BK\(B} $B$b$7$/$O=i4|@_Dj$H$7$F;H$$$^$9!#(B @item $B30It(B (foreign) @cindex foreign