1 ;;; elsp-bsfilter.el --- Bsfilter support for elmo-spam.
3 ;; Copyright (C) 2004 Hiroya Murata <lapis-lazuli@pop06.odn.ne.jp>
4 ;; Copyright (C) 2004 Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Author: Hiroya Murata <lapis-lazuli@pop06.odn.ne.jp>
7 ;; Keywords: mail, net news, spam
9 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
35 (defgroup elmo-spam-bsfilter nil
36 "Spam bsfilter configuration."
39 (defcustom elmo-spam-bsfilter-shell-program
"ruby"
42 :group
'elmo-spam-bsfilter
)
44 (defcustom elmo-spam-bsfilter-shell-switch nil
47 :group
'elmo-spam-bsfilter
)
49 (defcustom elmo-spam-bsfilter-program
(exec-installed-p "bsfilter")
50 "*Program name of the Bsfilter."
51 :type
'(string :tag
"Program name of the bsfilter")
52 :group
'elmo-spam-bsfilter
)
54 (defcustom elmo-spam-bsfilter-args nil
55 "*Argument list for bsfilter."
56 :type
'(repeat string
)
57 :group
'elmo-spam-bsfilter
)
59 (defcustom elmo-spam-bsfilter-update-switch
"--auto-update"
60 "*The switch that Bsfilter uses to update database with classify."
62 :group
'elmo-spam-bsfilter
)
64 (defcustom elmo-spam-bsfilter-database-directory nil
65 "*Directory path of the Bsfilter databases."
66 :type
'(choice (directory :tag
"Location of the Bsfilter database directory")
67 (const :tag
"Use the default"))
68 :group
'elmo-spam-bsfilter
)
70 (defcustom elmo-spam-bsfilter-max-files-per-process
100
71 "Number of files processed at once."
73 :group
'elmo-spam-bsfilter
)
75 (defcustom elmo-spam-bsfilter-max-messages-per-process
30
76 "Number of messages processed at once."
78 :group
'elmo-spam-bsfilter
)
80 (defcustom elmo-spam-bsfilter-use-remote
81 (and elmo-spam-bsfilter-shell-program
82 (let ((program (file-name-nondirectory
83 elmo-spam-bsfilter-shell-program
))
84 (remote-shells '("ssh" "rsh")))
86 (dolist (shell remote-shells
)
87 (when (string-match (concat "\\`" shell
) program
)
90 "*Non-nil disables local file feature."
92 :group
'elmo-spam-bsfilter
)
94 (defcustom elmo-spam-bsfilter-debug nil
95 "Non-nil to debug elmo bsfilter spam backend."
97 :group
'elmo-spam-bsfilter
)
100 (luna-define-class elsp-bsfilter
(elsp-generic)))
102 (defsubst elsp-bsfilter-call-bsfilter
(&rest args
)
103 (apply #'call-process-region
104 (point-min) (point-max)
105 elmo-spam-bsfilter-shell-program
106 nil
(if elmo-spam-bsfilter-debug
107 (get-buffer-create "*Debug ELMO Bsfilter*"))
109 (append (if elmo-spam-bsfilter-shell-switch
110 (list elmo-spam-bsfilter-shell-switch
))
111 (if elmo-spam-bsfilter-program
112 (list elmo-spam-bsfilter-program
))
113 elmo-spam-bsfilter-args
114 (if elmo-spam-bsfilter-database-directory
115 (list "--homedir" elmo-spam-bsfilter-database-directory
))
116 (elmo-flatten args
))))
118 (luna-define-method elmo-spam-buffer-spam-p
((processor elsp-bsfilter
)
119 buffer
&optional register
)
120 (with-current-buffer buffer
121 (= 0 (elsp-bsfilter-call-bsfilter
122 (if register elmo-spam-bsfilter-update-switch
)))))
124 (defun elsp-bsfilter-list-spam-filter (process output
)
125 (when (buffer-live-p (process-buffer process
))
126 (with-current-buffer (process-buffer process
)
128 (goto-char (process-mark process
))
130 (set-marker (process-mark process
) (point)))
131 (while (re-search-forward "^combined probability.+\r?\n" nil t
)
132 (delete-region (match-beginning 0) (match-end 0))
133 (elmo-progress-notify 'elmo-spam-check-spam
))
134 (when elmo-spam-bsfilter-debug
135 (with-current-buffer (get-buffer-create "*Debug ELMO Bsfilter*")
136 (goto-char (point-max))
139 (defsubst elsp-bsfilter-start-list-spam
(targets)
141 (apply #'start-process
144 elmo-spam-bsfilter-shell-program
145 (append (if elmo-spam-bsfilter-shell-switch
146 (list elmo-spam-bsfilter-shell-switch
))
147 (if elmo-spam-bsfilter-program
148 (list elmo-spam-bsfilter-program
))
149 elmo-spam-bsfilter-args
151 (if elmo-spam-bsfilter-database-directory
153 elmo-spam-bsfilter-database-directory
))
155 (set-process-filter process
#'elsp-bsfilter-list-spam-filter
)
158 (defsubst elsp-bsfilter-read-list-spam
(results hash
)
159 (goto-char (point-min))
161 (let* ((filename (buffer-substring (point) (save-excursion
164 (number (elmo-get-hash-val filename hash
)))
166 (setq results
(cons number results
)))
170 (luna-define-method elmo-spam-list-spam-messages
:around
171 ((processor elsp-bsfilter
) folder
&optional numbers
)
172 (if (or elmo-spam-bsfilter-use-remote
173 (not (elmo-folder-message-file-p folder
)))
174 (luna-call-next-method)
175 (let* ((nth-of-targets (1- (or elmo-spam-bsfilter-max-files-per-process
177 (numbers (or numbers
(elmo-folder-list-messages folder t t
)))
178 (hash (elmo-make-hash (length numbers
)))
181 (let ((filename (elmo-message-file-name folder number
)))
182 (elmo-set-hash-val filename number hash
)
188 (let* ((last (nthcdr nth-of-targets targets
))
192 (let ((process (elsp-bsfilter-start-list-spam targets
)))
193 (while (memq (process-status process
) '(open run
))
194 (accept-process-output process
1))
195 (setq results
(elsp-bsfilter-read-list-spam results hash
)))
197 (setq targets next
))))
201 (defsubst elsp-bsfilter-register-buffer
(buffer spam restore
&optional mbox
)
202 (with-current-buffer buffer
203 (elsp-bsfilter-call-bsfilter
205 (if restore
(if spam
"--sub-clean" "--sub-spam"))
206 (if spam
"--add-spam" "--add-clean")
207 (if mbox
"--mbox"))))
209 (luna-define-method elmo-spam-register-spam-buffer
((processor elsp-bsfilter
)
210 buffer
&optional restore
)
211 (elsp-bsfilter-register-buffer buffer t restore
))
213 (luna-define-method elmo-spam-register-good-buffer
((processor elsp-bsfilter
)
214 buffer
&optional restore
)
215 (elsp-bsfilter-register-buffer buffer nil restore
))
217 (defsubst elmo-spam-bsfilter-register-messages
(folder numbers spam restore
)
218 (let ((numbers (or numbers
(elmo-folder-list-messages folder t t
))))
219 (if (and (> (length numbers
) 1)
220 elmo-spam-bsfilter-max-messages-per-process
221 (> elmo-spam-bsfilter-max-messages-per-process
0))
222 (elmo-spam-process-messages-as-mbox
224 elmo-spam-bsfilter-max-messages-per-process
225 (lambda (count spam restore
)
226 (elsp-bsfilter-register-buffer (current-buffer) spam restore
'mbox
)
227 (elmo-progress-notify 'elmo-spam-register count
))
229 (luna-call-next-method))))
231 (luna-define-method elmo-spam-register-spam-messages
:around
232 ((processor elsp-bsfilter
) folder
&optional numbers restore
)
233 (elmo-spam-bsfilter-register-messages folder numbers t restore
))
235 (luna-define-method elmo-spam-register-good-messages
:around
236 ((processor elsp-bsfilter
) folder
&optional numbers restore
)
237 (elmo-spam-bsfilter-register-messages folder numbers nil restore
))
240 (product-provide (provide 'elsp-bsfilter
) (require 'elmo-version
))
242 ;;; elsp-bsfilter.el ends here