;;; nntp.el --- nntp access for Gnus
-;; Copyright (C) 1987, 1988, 1989, 1990, 1992, 1993,
-;; 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002,
-;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1987-1990, 1992-1998, 2000-2011
+;; Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
;;; Code:
+;; For Emacs <22.2 and XEmacs.
+(eval-and-compile
+ (unless (fboundp 'declare-function) (defmacro declare-function (&rest r))))
+
(require 'nnheader)
(require 'nnoo)
(require 'gnus-util)
(require 'gnus)
+(require 'proto-stream)
(require 'gnus-group) ;; gnus-group-name-charset
(nnoo-declare nntp)
(eval-when-compile (require 'cl))
-(eval-and-compile
- (autoload 'auth-source-user-or-password "auth-source"))
+(autoload 'auth-source-user-or-password "auth-source")
(defgroup nntp nil
"NNTP access for Gnus."
Direct connections:
- `nntp-open-network-stream' (the default),
+- `network-only' (the same as the above, but don't do automatic
+ STARTTLS upgrades).
- `nntp-open-ssl-stream',
- `nntp-open-tls-stream',
- `nntp-open-netcat-stream'.
"*Hook run just before posting an article. It is supposed to be used
to insert Cancel-Lock headers.")
+(defvoo nntp-server-list-active-group 'try
+ "If nil, then always use GROUP instead of LIST ACTIVE.
+This is usually slower, but on misconfigured servers that don't
+update their active files often, this can help.")
+
;;; Internal variables.
(defvar nntp-record-commands nil
(defvoo nntp-inhibit-output nil)
(defvoo nntp-server-xover 'try)
-(defvoo nntp-server-list-active-group 'try)
-
-(defvar nntp-async-needs-kluge
- (string-match "^GNU Emacs 20\\.3\\." (emacs-version))
- "*When non-nil, nntp will poll asynchronous connections
-once a second. By default, this is turned on only for Emacs
-20.3, which has a bug that breaks nntp's normal method of
-noticing asynchronous data.")
(defvar nntp-async-timer nil)
(defvar nntp-async-process-list nil)
-(defvar nntp-ssl-program
- "openssl s_client -quiet -ssl3 -connect %s:%p"
-"A string containing commands for SSL connections.
-Within a string, %s is replaced with the server address and %p with
-port number on server. The program should accept IMAP commands on
-stdin and return responses to stdout.")
-
(defvar nntp-authinfo-rejected nil
-"A custom error condition used to report 'Authentication Rejected' errors.
-Condition handlers that match just this condition ensure that the nntp
+"A custom error condition used to report 'Authentication Rejected' errors.
+Condition handlers that match just this condition ensure that the nntp
backend doesn't catch this error.")
(put 'nntp-authinfo-rejected 'error-conditions '(error nntp-authinfo-rejected))
(put 'nntp-authinfo-rejected 'error-message "Authorization Rejected")
(cond ((looking-at "480")
(nntp-handle-authinfo process))
((looking-at "482")
- (nnheader-report 'nntp (get 'nntp-authinfo-rejected 'error-message))
+ (nnheader-report 'nntp "%s"
+ (get 'nntp-authinfo-rejected 'error-message))
(signal 'nntp-authinfo-rejected nil))
((looking-at "^.*\n")
(delete-region (point) (progn (forward-line 1) (point)))))
"\r?\n\\.\r?\n" "BODY"
(if (numberp article) (int-to-string article) article))))
-(deffoo nntp-request-group (group &optional server dont-check)
+(deffoo nntp-request-group (group &optional server dont-check info)
(nntp-with-open-group
nil server
(when (nntp-send-command "^[245].*\n" "GROUP" group)
(unless (assq 'nntp-address defs)
(setq defs (append defs (list (list 'nntp-address server)))))
(nnoo-change-server 'nntp server defs)
- (unless connectionless
+ (if connectionless
+ t
(or (nntp-find-connection nntp-server-buffer)
(nntp-open-connection nntp-server-buffer)))))
t)
(deffoo nntp-request-set-mark (group actions &optional server)
- (unless nntp-marks-is-evil
+ (when (and (not nntp-marks-is-evil)
+ nntp-marks-file-name)
(nntp-possibly-create-directory group server)
(nntp-open-marks group server)
- (dolist (action actions)
- (let ((range (nth 0 action))
- (what (nth 1 action))
- (marks (nth 2 action)))
- (assert (or (eq what 'add) (eq what 'del)) nil
- "Unknown request-set-mark action: %s" what)
- (dolist (mark marks)
- (setq nntp-marks (gnus-update-alist-soft
- mark
- (funcall (if (eq what 'add) 'gnus-range-add
- 'gnus-remove-from-range)
- (cdr (assoc mark nntp-marks)) range)
- nntp-marks)))))
+ (setq nntp-marks (nnheader-update-marks-actions nntp-marks actions))
(nntp-save-marks group server))
nil)
-(deffoo nntp-request-update-info (group info &optional server)
- (unless nntp-marks-is-evil
+(deffoo nntp-request-marks (group info &optional server)
+ (when (and (not nntp-marks-is-evil)
+ nntp-marks-file-name)
(nntp-possibly-create-directory group server)
(when (nntp-marks-changed-p group server)
(nnheader-message 8 "Updating marks for %s..." group)
reading."
(nntp-send-command "^.*\n" "MODE READER"))
+(declare-function netrc-parse "netrc" (&optional file))
+(declare-function netrc-machine "netrc"
+ (list machine &optional port defaultport))
+(declare-function netrc-get "netrc" (alist type))
+
(defun nntp-send-authinfo (&optional send-if-force)
"Send the AUTHINFO to the nntp server.
It will look in the \"~/.authinfo\" file for matching entries. If
If SEND-IF-FORCE, only send authinfo to the server if the
.authinfo file has the FORCE token."
+ (require 'netrc)
(let* ((list (netrc-parse nntp-authinfo-file))
(alist (netrc-machine list nntp-address "nntp"))
(force (or (netrc-get alist "force") nntp-authinfo-force))
- (user (or
+ (auth-info
+ (auth-source-user-or-password '("login" "password") nntp-address "nntp"))
+ (auth-user (nth 0 auth-info))
+ (auth-passwd (nth 1 auth-info))
+ (user (or
;; this is preferred to netrc-*
- (auth-source-user-or-password "login" nntp-address "nntp")
- (netrc-get alist "login")
+ auth-user
+ (netrc-get alist "login")
nntp-authinfo-user))
(passwd (or
;; this is preferred to netrc-*
- (auth-source-user-or-password "password" nntp-address "nntp")
+ auth-passwd
(netrc-get alist "password"))))
(when (or (not send-if-force)
force)
`(lambda ()
(nntp-kill-buffer ,pbuffer)))))
(process
- (condition-case ()
+ (condition-case err
(let ((coding-system-for-read nntp-coding-system-for-read)
- (coding-system-for-write nntp-coding-system-for-write))
- (funcall nntp-open-connection-function pbuffer))
- (error nil)
+ (coding-system-for-write nntp-coding-system-for-write)
+ (map '((nntp-open-network-stream network)
+ (network-only network-only)
+ (nntp-open-ssl-stream tls)
+ (nntp-open-tls-stream tls))))
+ (if (assoc nntp-open-connection-function map)
+ (car (open-protocol-stream
+ "nntpd" pbuffer nntp-address nntp-port-number
+ :type (cadr
+ (assoc nntp-open-connection-function map))
+ :end-of-command "^\\([2345]\\|[.]\\).*\n"
+ :capability-command "CAPABILITIES\r\n"
+ :success "^3"
+ :starttls-function
+ (lambda (capabilities)
+ (if (not (string-match "STARTTLS" capabilities))
+ nil
+ "STARTTLS\r\n"))))
+ (funcall nntp-open-connection-function pbuffer)))
+ (error
+ (nnheader-report 'nntp "%s" err))
(quit
(message "Quit opening connection to %s" nntp-address)
(nntp-kill-buffer pbuffer)
(nntp-kill-buffer (process-buffer process))
nil))))
-(defun nntp-open-network-stream (buffer)
- (open-network-stream "nntpd" buffer nntp-address nntp-port-number))
-
-(eval-and-compile
- (autoload 'format-spec "format-spec")
- (autoload 'format-spec-make "format-spec")
- (autoload 'open-tls-stream "tls"))
-
-(defun nntp-open-ssl-stream (buffer)
- (let* ((process-connection-type nil)
- (proc (start-process "nntpd" buffer
- shell-file-name
- shell-command-switch
- (format-spec nntp-ssl-program
- (format-spec-make
- ?s nntp-address
- ?p nntp-port-number)))))
- (gnus-set-process-query-on-exit-flag proc nil)
- (with-current-buffer buffer
- (let ((nntp-connection-alist (list proc buffer nil)))
- (nntp-wait-for-string "^\r*20[01]"))
- (beginning-of-line)
- (delete-region (point-min) (point))
- proc)))
-
-(defun nntp-open-tls-stream (buffer)
- (let ((proc (open-tls-stream "nntpd" buffer nntp-address nntp-port-number)))
- (gnus-set-process-query-on-exit-flag proc nil)
- (with-current-buffer buffer
- (let ((nntp-connection-alist (list proc buffer nil)))
- (nntp-wait-for-string "^\r*20[01]"))
- (beginning-of-line)
- (delete-region (point-min) (point))
- proc)))
-
(defun nntp-read-server-type ()
"Find out what the name of the server we have connected to is."
;; Wait for the status string to arrive.
nntp-process-decode decode
nntp-process-callback callback
nntp-process-start-point (point-max))
- (setq after-change-functions '(nntp-after-change-function))
- (if nntp-async-needs-kluge
- (nntp-async-kluge process))))
-
-(defun nntp-async-kluge (process)
- ;; emacs 20.3 bug: process output with encoding 'binary
- ;; doesn't trigger after-change-functions.
- (unless nntp-async-timer
- (setq nntp-async-timer
- (run-at-time 1 1 'nntp-async-timer-handler)))
- (add-to-list 'nntp-async-process-list process))
+ (setq after-change-functions '(nntp-after-change-function))))
(defun nntp-async-timer-handler ()
(mapcar
(let ((message (buffer-string)))
(while (string-match "[\r\n]+" message)
(setq message (replace-match " " t t message)))
- (nnheader-report 'nntp message)
+ (nnheader-report 'nntp "%s" message)
message))
(defun nntp-accept-process-output (process)
(while (and (setq proc (get-buffer-process buf))
(memq (process-status proc) '(open run))
(not (re-search-forward regexp nil t)))
- (accept-process-output proc)
+ (accept-process-output proc 0.1)
(set-buffer buf)
(goto-char (point-min)))))
(defun nntp-service-to-port (svc)
(cond
((integerp svc) (number-to-string svc))
- ((string-match "\\`[[:digit:]]\\'" svc) svc)
+ ((string-match "\\`[0-9]+\\'" svc) svc)
(t
(with-temp-buffer
(ignore-errors (insert-file-contents "/etc/services"))
(goto-char (point-min))
(if (re-search-forward (concat "^" (regexp-quote svc)
- "[ \t]+\\([[:digit:]]+\\)/tcp"))
+ "[ \t]+\\([0-9]+\\)/tcp"))
(match-string 1)
svc)))))
(and nntp-pre-command (push nntp-pre-command command))
(let ((process-connection-type nil)) ;See `nntp-open-via-rlogin-and-netcat'.
(apply 'start-process "nntpd" buffer command))))
-
+
(defun nntp-open-via-telnet-and-telnet (buffer)
"Open a connection to an nntp server through an intermediate host.
(make-directory (directory-file-name dir) t)
(nnheader-message 5 "Creating nntp marks directory %s" dir))))
-(eval-and-compile
- (autoload 'time-less-p "time-date"))
+(autoload 'time-less-p "time-date")
(defun nntp-marks-changed-p (group server)
(let ((file (nntp-group-pathname server group nntp-marks-file-name))
(provide 'nntp)
-;; arch-tag: 8655466a-b1b5-4929-9c45-7b1b2e767271
;;; nntp.el ends here