*** empty log message ***
[gnus] / lisp / gnus-nocem.el
1 ;;; gnus-nocem.el --- NoCeM pseudo-cancellation treatment
2 ;; Copyright (C) 1995,96 Free Software Foundation, Inc.
3
4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
5 ;; Keywords: news
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;; Commentary:
25
26 ;;; Code:
27
28 (require 'gnus)
29 (eval-when-compile (require 'cl))
30
31 (defvar gnus-nocem-groups '("alt.nocem.misc" "news.admin.net-abuse.announce")
32   "*List of groups that will be searched for NoCeM messages.")
33
34 (defvar gnus-nocem-issuers '("Automoose-1" "clewis@ferret.ocunix.on.ca;")
35   "*List of NoCeM issuers to pay attention to.")
36
37 (defvar gnus-nocem-directory 
38   (concat (file-name-as-directory gnus-article-save-directory) "NoCeM/")
39   "*Directory where NoCeM files will be stored.")
40
41 (defvar gnus-nocem-expiry-wait 30
42   "*Number of days to keep NoCeM headers in the cache.")
43
44 ;;; Internal variables
45
46 (defvar gnus-nocem-active nil)
47 (defvar gnus-nocem-alist nil)
48 (defvar gnus-nocem-touched-alist nil)
49
50 ;;; Functions
51
52 (defun gnus-nocem-active-file ()
53   (concat (file-name-as-directory gnus-nocem-directory) "active"))
54
55 (defun gnus-nocem-cache-file ()
56   (concat (file-name-as-directory gnus-nocem-directory) "cache"))
57
58 (defun gnus-nocem-scan-groups ()
59   "Scan all NoCeM groups for new NoCeM messages."
60   (interactive)
61   (let ((groups gnus-nocem-groups)
62         group active gactive articles)
63     (or (file-exists-p gnus-nocem-directory)
64         (make-directory gnus-nocem-directory t))
65     ;; Load any previous NoCeM headers.
66     (gnus-nocem-load-cache)
67     ;; Read the active file if it hasn't been read yet.
68     (and (file-exists-p (gnus-nocem-active-file))
69          (not gnus-nocem-active)
70          (condition-case ()
71              (load (gnus-nocem-active-file) t t t)
72            (error nil)))
73     ;; Go through all groups and see whether new articles have
74     ;; arrived.  
75     (while groups
76       (setq group (pop groups))
77       (if (not (gnus-activate-group group))
78           () ; This group doesn't exist.
79         (setq active (nth 1 (assoc group gnus-nocem-active)))
80         (when (and (not (< (cdr gactive) (car gactive))) ; Empty group.
81                    (or (not active)
82                        (< (cdr active) 
83                           (cdr (setq gactive (gnus-gethash 
84                                               group gnus-newsrc-hashtb))))))
85           ;; Ok, there are new articles in this group, se we fetch the
86           ;; headers.
87           (let ((gnus-newsgroup-dependencies (make-vector 10 nil))
88                 headers)
89             (setq headers
90                   (if (eq 'nov
91                           (gnus-retrieve-headers 
92                            (setq articles
93                                  (gnus-uncompress-range
94                                   (cons (1+ (cdr active)) (cdr gactive))))
95                            group))
96                       (gnus-get-newsgroup-headers-xover articles)
97                     (gnus-get-newsgroup-headers)))
98             (while headers
99               ;; We take a closer look on all articles that have
100               ;; "@@NCM" in the subject.  
101               (and (string-match "@@NCM" (mail-header-subject (car headers)))
102                    (gnus-nocem-check-article
103                     (mail-header-number (car headers)) group))
104               (setq headers (cdr headers)))))))
105     ;; Save the results, if any.
106     (gnus-nocem-save-cache)))
107
108 (defun gnus-nocem-check-article (number group)
109   "Check whether the current article is a NCM article and that we want it."
110   (save-excursion
111     (set-buffer nntp-server-buffer)
112     ;; Get the article.
113     (gnus-request-article-this-buffer number group)
114     (goto-char (point-min))
115     (let (issuer b)
116       ;; The article has to have proper NoCeM headers.
117       (when (and (setq b (search-forward "\n@@BEGIN NCM HEADERS\n" nil t))
118                  (search-forward "\n@@BEGIN NCM BODY\n" nil t))
119         ;; We get the name of the issuer.
120         (narrow-to-region b (match-beginning 0))
121         (setq issuer (mail-fetch-field "issuer"))
122         (and (member issuer gnus-nocem-issuers) ; We like her...
123              (gnus-nocem-verify-issuer issuer) ; She is who she says she is...
124              (gnus-nocem-enter-article)))) ; We gobble the message.
125     (widen)))
126
127 (defun gnus-nocem-verify-issuer (person)
128   "Verify using PGP that the canceler is who she says she is."
129   t)
130
131 (defun gnus-nocem-enter-article ()
132   "Enter the current article into the NoCeM cache."
133   (widen)
134   (goto-char (point-min))
135   (let ((b (search-forward "\n@@BEGIN NCM BODY\n" nil t))
136         (e (search-forward "\n@@END NCM BODY\n" nil t))
137         (buf (current-buffer))
138         ncm id)
139     (when (and b e)
140       (narrow-to-region b (1+ (match-beginning 0)))
141       (goto-char (point-min))
142       (while (search-forward "\t" nil t)
143         (when (boundp (let ((obarray gnus-newsrc-hashtb)) (read buf)))
144           (beginning-of-line)
145           (while (= (following-char) ?\t)
146             (forward-line -1))
147           (setq id (buffer-substring (point) (1- (search-forward "\t"))))
148           (push id ncm)
149           (gnus-sethash id t gnus-nocem-hashtb)
150           (forward-line 1)
151           (while (= (following-char) ?\t)
152             (forward-line 1))))
153       (when ncm
154         (setq gnus-nocem-touched-alist t)
155         (push (push (current-time-string) ncm) gnus-nocem-alist)))))
156
157 (defun gnus-nocem-load-cache ()
158   "Load the NoCeM cache."
159   (if gnus-nocem-alist
160       () ; Do nothing.
161     ;; The buffer doesn't exist, so we create it and load the NoCeM
162     ;; cache.  
163     (when (file-exists-p (gnus-nocem-cache-file))
164       (load (gnus-nocem-cache-file) t t t)
165       (gnus-nocem-alist-to-hashtb))))
166       
167 (defun gnus-nocem-save-cache ()
168   "Save the NoCeM cache."
169   (when (and gnus-nocem-alist
170              gnus-nocem-touched-alist)
171     (save-excursion
172       (nnheader-set-temp-buffer " *NoCeM*")
173       (insert (prin1-to-string
174                (list 'setq 'gnus-nocem-alist gnus-nocem-alist)))
175       (write-region (point-min) (point-max) 
176                     (gnus-nocem-cache-file) nil 'silent)
177       (kill-buffer (current-buffer))
178       (setq gnus-nocem-touched-alist nil))))
179
180 (defun gnus-nocem-alist-to-hashtb ()
181   "Create a hashtable from the Message-IDs we have."
182   (let ((alist gnus-nocem-alist)
183         (date (current-time-string))
184         entry)
185     (setq gnus-nocem-hashtb (* (length alist) 51))
186     (while alist
187       (setq entry (pop alist))
188       (if (> (gnus-days-between date (car entry)) gnus-nocem-expiry-wait)
189           ;; This entry has expired, so we remove it.
190           (setq gnus-nocem-alist (delq entry gnus-nocem-alist))
191         ;; This is ok, so we enter it into the hashtable.
192         (setq entry (cdr entry))
193         (while entry
194           (gnus-sethash (car entry) t gnus-nocem-hashtb)
195           (setq entry (cdr entry)))))))
196
197 (defun gnus-nocem-close ()
198   "Clear internal NoCeM variables."
199   (setq gnus-nocem-alist nil
200         gnus-nocem-hashtb nil
201         gnus-nocem-active nil
202         gnus-nocem-touched-alist nil))
203
204 ;;; gnus-nocem.el ends here