1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
|
;;; nndb.el --- nndb access for Gnus
;; Copyright (C) 1997 Free Software Foundation, Inc.
;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
;; Kai Grossjohann <grossjohann@ls6.informatik.uni-dortmund.de>
;; Joe Hildebrand <joe.hildebrand@ilg.com>
;; David Blacka <davidb@rwhois.net>
;; Keywords: news
;; This file is NOT part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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:
;;; This was based upon Kai Grossjohan's shamessly snarfed code and
;;; further modified by Joe Hildebrand. It has been updated for Red
;;; Gnus.
;; TODO:
;;
;; * Fix bug where server connection can be lost and impossible to regain
;; This hasn't happened to me in a while; think it was fixed in Rgnus
;;
;; * make it handle different nndb servers seemlessly
;;
;; * Optimize expire if FORCE
;;
;; * Optimize move (only expire once)
;;
;; * Deal with add/deletion of groups
;;
;; * make the backend TOUCH an article when marked as expireable (will
;; make article expire 'expiry' days after that moment).
;;-
;; Register nndb with known select methods.
(gnus-declare-backend "nndb" 'mail 'respool 'address 'prompt-address)
;;; Code:
(require 'nnmail)
(require 'nnheader)
(require 'nntp)
(eval-when-compile (require 'cl))
(eval-and-compile
(unless (fboundp 'open-network-stream)
(require 'tcp)))
(eval-when-compile (require 'cl))
(eval-and-compile
(autoload 'news-setup "rnewspost")
(autoload 'news-reply-mode "rnewspost")
(autoload 'cancel-timer "timer")
(autoload 'telnet "telnet" nil t)
(autoload 'telnet-send-input "telnet" nil t)
(autoload 'timezone-parse-date "timezone"))
;; Declare nndb as derived from nntp
(nnoo-declare nndb nntp)
;; Variables specific to nndb
;;- currently not used but just in case...
(defvoo nndb-deliver-program "nndel"
"*The program used to put a message in an NNDB group.")
(defvoo nndb-server-side-expiry nil
"If t, expiry calculation will occur on the server side")
(defvoo nndb-set-expire-date-on-mark nil
"If t, the expiry date for a given article will be set to the time
it was marked as expireable; otherwise the date will be the time the
article was posted to nndb")
;; Variables copied from nntp
(defvoo nndb-server-opened-hook '(nntp-send-authinfo-from-file)
"Like nntp-server-opened-hook."
nntp-server-opened-hook)
(defvoo nndb-address "localhost"
"*The name of the NNDB server."
nntp-address)
(defvoo nndb-port-number 9000
"*Port number to connect to."
nntp-port-number)
;; change to 'news if you are actually using nndb for news
(defvoo nndb-article-type 'mail)
(defvoo nndb-status-string nil "" nntp-status-string)
(defconst nndb-version "nndb 0.7"
"Version numbers of this version of NNDB.")
;;; Interface functions.
(nnoo-define-basics nndb)
;;------------------------------------------------------------------
;; this function turns the lisp list into a string list. There is
;; probably a more efficient way to do this.
(defun nndb-build-article-string (articles)
(let (art-string art)
(while articles
(setq art (pop articles))
(setq art-string (concat art-string art " ")))
art-string))
(defun nndb-build-expire-rest-list (total expire)
(let (art rest)
(while total
(setq art (pop total))
(if (memq art expire)
()
(push art rest)))
rest))
;;
(deffoo nndb-request-type (group &optional article)
nndb-article-type)
;; nndb-request-update-info does not exist and is not needed
;; nndb-request-update-mark does not exist; it should be used to TOUCH
;; articles as they are marked exipirable
(defun nndb-touch-article (group article)
(nntp-send-command nil "X-TOUCH" article))
(deffoo nndb-request-update-mark
(group article mark)
"Sets the expiry date for ARTICLE in GROUP to now, if the mark is 'E'"
(if (and nndb-set-expire-date-on-mark (string-equal mark "E"))
(nndb-touch-article group article))
mark)
;; nndb-request-create-group -- currently this isn't necessary; nndb
;; creates groups on demand.
;; todo -- use some other time than the creation time of the article
;; best is time since article has been marked as expirable
(defun nndb-request-expire-articles-local
(articles &optional group server force)
"Let gnus do the date check and issue the delete commands."
(let (msg art delete-list (num-delete 0) rest)
(nntp-possibly-change-group group server)
(while articles
(setq art (pop articles))
(nntp-send-command "^\\([23]\\|^423\\).*\n" "X-DATE" art)
(setq msg (nndb-status-message))
(if (string-match "^423" msg)
()
(or (string-match "'\\(.+\\)'" msg)
(error "Not a valid response for X-DATE command: %s"
msg))
(if (nnmail-expired-article-p
group
(gnus-encode-date
(substring msg (match-beginning 1) (match-end 1)))
force)
(progn
(setq delete-list (concat delete-list " " (int-to-string art)))
(setq num-delete (1+ num-delete)))
(push art rest))))
(if (> (length delete-list) 0)
(progn
(nnheader-message 5 "Deleting %s article(s) from %s"
(int-to-string num-delete) group)
(nntp-send-command "^[23].*\n" "X-DELETE" delete-list))
)
(message "")
(nconc rest articles)))
(defun nndb-get-remote-expire-response ()
(let (list)
(set-buffer nntp-server-buffer)
(goto-char (point-min))
(if (looking-at "^[34]")
;; x-expire returned error--presume no articles were expirable)
(setq list nil)
;; otherwise, pull all of the following numbers into the list
(re-search-forward "follows\r?\n?" nil t)
(while (re-search-forward "^[0-9]+$" nil t)
(push (string-to-int (match-string 0)) list)))
list))
(defun nndb-request-expire-articles-remote
(articles &optional group server force)
"Let the nndb backend expire articles"
(let (days art-string delete-list (num-delete 0))
(nntp-possibly-change-group group server)
;; first calculate the wait period in days
(setq days (or (and nnmail-expiry-wait-function
(funcall nnmail-expiry-wait-function group))
nnmail-expiry-wait))
;; now handle the special cases
(cond (force
(setq days 0))
((eq days 'never)
;; This isn't an expirable group.
(setq days -1))
((eq days 'immediate)
(setq days 0)))
;; build article string
(setq art-string (concat days " " (nndb-build-article-string articles)))
(nntp-send-command "^\.\r?\n\\|^[345].*\n" "X-EXPIRE" art-string)
(setq delete-list (nndb-get-remote-expire-response))
(setq num-delete (length delete-list))
(if (> num-delete 0)
(nnheader-message 5 "Deleting %s article(s) from %s"
(int-to-string num-delete) group))
(nndb-build-expire-rest-list articles delete-list)))
(deffoo nndb-request-expire-articles
(articles &optional group server force)
"Expires ARTICLES from GROUP on SERVER.
If FORCE, delete regardless of exiration date, otherwise use normal
expiry mechanism."
(if nndb-server-side-expiry
(nndb-request-expire-articles-remote articles group server force)
(nndb-request-expire-articles-local articles group server force)))
(deffoo nndb-request-move-article
(article group server accept-form &optional last)
"Move ARTICLE (a number) from GROUP on SERVER.
Evals ACCEPT-FORM in current buffer, where the article is.
Optional LAST is ignored."
;; we guess that the second arg in accept-form is the new group,
;; which it will be for nndb, which is all that matters anyway
(let ((new-group (nth 1 accept-form)) result)
(nntp-possibly-change-group group server)
;; use the move command for nndb-to-nndb moves
(if (string-match "^nndb" new-group)
(let ((new-group-name (gnus-group-real-name new-group)))
(nntp-send-command "^[23].*\n" "X-MOVE" article new-group-name)
(cons new-group article))
;; else move normally
(let ((artbuf (get-buffer-create " *nndb move*")))
(and
(nndb-request-article article group server artbuf)
(save-excursion
(set-buffer artbuf)
(insert-buffer-substring nntp-server-buffer)
(setq result (eval accept-form))
(kill-buffer (current-buffer))
result)
(nndb-request-expire-articles (list article)
group
server
t))
result)
)))
(deffoo nndb-request-accept-article (group server &optional last)
"The article in the current buffer is put into GROUP."
(nntp-possibly-change-group group server)
(let (art msg)
(when (nntp-send-command "^[23].*\r?\n" "ACCEPT" group)
(nnheader-insert "")
(nntp-send-buffer "^[23].*\n"))
(set-buffer nntp-server-buffer)
(setq msg (buffer-string (point-min) (point-max)))
(or (string-match "^\\([0-9]+\\)" msg)
(error "nndb: %s" msg))
(setq art (substring msg (match-beginning 1) (match-end 1)))
(message "nndb: accepted %s" art)
(list art)))
(deffoo nndb-request-replace-article (article group buffer)
"ARTICLE is the number of the article in GROUP to be replaced
with the contents of the BUFFER."
(set-buffer buffer)
(when (nntp-send-command "^[23].*\r?\n" "X-REPLACE" (int-to-string article))
(nnheader-insert "")
(nntp-send-buffer "^[23.*\n")
(list (int-to-string article))))
; nndb-request-delete-group does not exist
; todo -- maybe later
; nndb-request-rename-group does not exist
; todo -- maybe later
;; -- standard compatability functions
(deffoo nndb-status-message (&optional server)
"Return server status as a string."
(set-buffer nntp-server-buffer)
(buffer-string (point-min) (point-max)))
;; Import stuff from nntp
(nnoo-import nndb
(nntp))
(provide 'nndb)
|