;;; clamav.el --- clamav anti-virus scanner. ;; Copyright (C) 2004 Yuuichi Teranishi ;; Author: Yuuichi Teranishi ;; Keywords: mail, net news ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;; ;;; Commentary: ;; ;;; Code (require 'pces) (defgroup clamav nil "Clamav anti virus scanner client." :group 'mail) (defcustom clamav-port 3310 "Server port number of clamav." :type 'integer :group 'clamav) (defvar clamav-target-buffer nil) (make-variable-buffer-local 'clamav-target-buffer) (defvar clamav-state nil) (make-variable-buffer-local 'clamav-state) (defvar clamav-result nil) (make-variable-buffer-local 'clamav-result) (defun clamav-process-sentinel (process string) "A sentinel for clamav process. PROCESS, STRING are arguments for sentinel." (delete-process process)) (defun clamav-process-filter (process string) "Process filter of clamav. PROCESS and STRING are given." (when (buffer-live-p (process-buffer process)) (with-current-buffer (process-buffer process) (goto-char (point-max)) (insert string) (goto-char (point-min)) (case clamav-state (stream (when (re-search-forward "^PORT \\([0-9]+\\)" nil t) (setq clamav-state 'result) (clamav-send-buffer clamav-target-buffer (string-to-int (match-string 1))))) (result (when (re-search-forward "^stream: \\(.*\\)$" nil t) (let ((result (match-string 1))) (if (string-match " FOUND" result) (setq clamav-result (substring result 0 (match-beginning 0))) (setq clamav-result 'ok))))))))) (defun clamav-send-buffer (buffer port) "Send BUFFER to the PORT." (let ((process (open-network-stream-as-binary " *clamav data*" nil "127.0.0.1" port))) (with-current-buffer buffer (process-send-region process (point-min) (point-max)) (process-send-eof process)))) (defun clamav-scan-file (file) "Scan FILE. If the file has Virus, return virus name." (interactive "fFile: ") (with-temp-buffer (set-buffer-multibyte nil) (insert-file-contents-literally file) (let ((result (clamav-scan-buffer (current-buffer)))) (if (interactive-p) (if (stringp result) (message "Virus `%s' was detected." result) (message "Clean."))) result))) (defun clamav-scan-buffer (buffer) "Scan BUFFER. If the buffer has Virus, return virus name." (interactive "bBuffer: ") (with-temp-buffer (set-buffer-multibyte nil) (let ((process (open-network-stream-as-binary " *clamav*" (current-buffer) "127.0.0.1" clamav-port))) (setq clamav-target-buffer buffer clamav-state 'stream clamav-result nil) (set-process-filter process 'clamav-process-filter) (set-process-sentinel process 'clamav-process-sentinel) (process-send-string process "STREAM") (while (null clamav-result) (accept-process-output process)) (if (interactive-p) (if (stringp clamav-result) (message "Virus `%s' was detected." clamav-result) (message "Clean."))) (unless (eq clamav-result 'ok) clamav-result)))) (provide 'clamav) ;;; clamav.el ends here