Be more liberal when extracting forwards as MIME
[gnus] / lisp / nntp.el
index 3285da5..621aece 100644 (file)
@@ -1,6 +1,6 @@
 ;;; nntp.el --- nntp access for Gnus
 
-;; Copyright (C) 1987-1990, 1992-1998, 2000-2011
+;; Copyright (C) 1987-1990, 1992-1998, 2000-2012
 ;;   Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -261,6 +261,8 @@ See `nnml-marks-is-evil' for more information.")
                                          (const :format "" "password")
                                          (string :format "Password: %v")))))))
 
+(make-obsolete 'nntp-authinfo-file nil "Emacs 24.1")
+
 \f
 
 (defvoo nntp-connection-timeout nil
@@ -279,6 +281,7 @@ update their active files often, this can help.")
 
 ;;; Internal variables.
 
+(defvoo nntp-retrieval-in-progress nil)
 (defvar nntp-record-commands nil
   "*If non-nil, nntp will record all commands in the \"*nntp-log*\" buffer.")
 
@@ -338,10 +341,8 @@ backend doesn't catch this error.")
   "Record the command STRING."
   (with-current-buffer (get-buffer-create "*nntp-log*")
     (goto-char (point-max))
-    (let ((time (current-time)))
-      (insert (format-time-string "%Y%m%dT%H%M%S" time)
-             "." (format "%03d" (/ (nth 2 time) 1000))
-             " " nntp-address " " string "\n"))))
+    (insert (format-time-string "%Y%m%dT%H%M%S.%3N")
+           " " nntp-address " " string "\n")))
 
 (defun nntp-report (&rest args)
   "Report an error from the nntp backend.  The first string in ARGS
@@ -364,19 +365,6 @@ be restored and the command retried."
 
   (throw 'nntp-with-open-group-error t))
 
-(defmacro nntp-insert-buffer-substring (buffer &optional start end)
-  "Copy string from unibyte buffer to multibyte current buffer."
-  (if (featurep 'xemacs)
-      `(insert-buffer-substring ,buffer ,start ,end)
-    `(if enable-multibyte-characters
-        (insert (with-current-buffer ,buffer
-                  (mm-string-to-multibyte
-                   ,(if (or start end)
-                        `(buffer-substring (or ,start (point-min))
-                                           (or ,end (point-max)))
-                      '(buffer-string)))))
-       (insert-buffer-substring ,buffer ,start ,end))))
-
 (defmacro nntp-copy-to-buffer (buffer start end)
   "Copy string from unibyte current buffer to multibyte buffer."
   (if (featurep 'xemacs)
@@ -434,7 +422,7 @@ be restored and the command retried."
          (unless discard
            (with-current-buffer buffer
              (goto-char (point-max))
-             (nntp-insert-buffer-substring (process-buffer process))
+             (nnheader-insert-buffer-substring (process-buffer process))
              ;; Nix out "nntp reading...." message.
              (when nntp-have-messaged
                (setq nntp-have-messaged nil)
@@ -445,6 +433,9 @@ be restored and the command retried."
 
 (defun nntp-kill-buffer (buffer)
   (when (buffer-name buffer)
+    (let ((process (get-buffer-process buffer)))
+      (when process
+       (delete-process process)))
     (kill-buffer buffer)
     (nnheader-init-server-buffer)))
 
@@ -675,7 +666,7 @@ command whose response triggered the error."
                                                   (process-buffer -process))))
                               ;; When I an able to identify the
                               ;; connection to the server AND I've
-                              ;; received NO reponse for
+                              ;; received NO response for
                               ;; nntp-connection-timeout seconds.
                               (when (and -buffer (eq 0 (buffer-size -buffer)))
                                 ;; Close the connection.  Take no
@@ -780,21 +771,32 @@ command whose response triggered the error."
 (deffoo nntp-retrieve-group-data-early (server infos)
   "Retrieve group info on INFOS."
   (nntp-with-open-group nil server
-    (when (nntp-find-connection-buffer nntp-server-buffer)
-      ;; The first time this is run, this variable is `try'.  So we
-      ;; try.
-      (when (eq nntp-server-list-active-group 'try)
-       (nntp-try-list-active
-        (gnus-group-real-name (gnus-info-group (car infos)))))
-      (with-current-buffer (nntp-find-connection-buffer nntp-server-buffer)
-       (erase-buffer)
-       (let ((nntp-inhibit-erase t)
-             (command (if nntp-server-list-active-group
-                          "LIST ACTIVE" "GROUP")))
-         (dolist (info infos)
-           (nntp-send-command
-            nil command (gnus-group-real-name (gnus-info-group info)))))
-       (length infos)))))
+    (let ((buffer (nntp-find-connection-buffer nntp-server-buffer)))
+      (unless infos
+       (with-current-buffer buffer
+         (setq nntp-retrieval-in-progress nil)))
+      (when (and buffer
+                infos
+                (with-current-buffer buffer
+                  (not nntp-retrieval-in-progress)))
+       ;; The first time this is run, this variable is `try'.  So we
+       ;; try.
+       (when (eq nntp-server-list-active-group 'try)
+         (nntp-try-list-active
+          (gnus-group-real-name (gnus-info-group (car infos)))))
+       (with-current-buffer buffer
+         (erase-buffer)
+         ;; Mark this buffer as "in use" in case we try to issue two
+         ;; retrievals from the same server.  This shouldn't happen,
+         ;; so this is mostly a sanity check.
+         (setq nntp-retrieval-in-progress t)
+         (let ((nntp-inhibit-erase t)
+               (command (if nntp-server-list-active-group
+                            "LIST ACTIVE" "GROUP")))
+           (dolist (info infos)
+             (nntp-send-command
+              nil command (gnus-group-real-name (gnus-info-group info)))))
+         (length infos))))))
 
 (deffoo nntp-finish-retrieve-group-infos (server infos count)
   (nntp-with-open-group nil server
@@ -804,6 +806,8 @@ command whose response triggered the error."
                   (car infos)))
          (received 0)
          (last-point 1))
+      (with-current-buffer buf
+       (setq nntp-retrieval-in-progress nil))
       (when (and buf
                 count)
        (with-current-buffer buf
@@ -847,7 +851,14 @@ command whose response triggered the error."
   "Retrieve group info on GROUPS."
   (nntp-with-open-group
    nil server
-   (when (nntp-find-connection-buffer nntp-server-buffer)
+   (when (and (nntp-find-connection-buffer nntp-server-buffer)
+             (with-current-buffer
+                 (nntp-find-connection-buffer nntp-server-buffer)
+               (if (not nntp-retrieval-in-progress)
+                   t
+                 (message "Warning: Refusing to do retrieval from %s because a retrieval is already happening"
+                          server)
+                 nil)))
      (catch 'done
        (save-excursion
          ;; Erase nntp-server-buffer before nntp-inhibit-erase.
@@ -996,7 +1007,7 @@ command whose response triggered the error."
           (narrow-to-region
            (setq point (goto-char (point-max)))
            (progn
-            (nntp-insert-buffer-substring buf last-point (cdr entry))
+            (nnheader-insert-buffer-substring buf last-point (cdr entry))
              (point-max)))
           (setq last-point (cdr entry))
           (nntp-decode-text)
@@ -1028,16 +1039,15 @@ command whose response triggered the error."
 
 (deffoo nntp-request-article (article &optional group server buffer command)
   (nntp-with-open-group
-    group server
+      group server
     (when (nntp-send-command-and-decode
            "\r?\n\\.\r?\n" "ARTICLE"
            (if (numberp article) (int-to-string article) article))
-      (if (and buffer
-               (not (equal buffer nntp-server-buffer)))
-          (with-current-buffer nntp-server-buffer
-            (copy-to-buffer buffer (point-min) (point-max))
-            (nntp-find-group-and-number group))
-        (nntp-find-group-and-number group)))))
+      (when (and buffer
+                (not (equal buffer nntp-server-buffer)))
+       (with-current-buffer nntp-server-buffer
+         (copy-to-buffer buffer (point-min) (point-max))))
+      (nntp-find-group-and-number group))))
 
 (deffoo nntp-request-head (article &optional group server)
   (nntp-with-open-group
@@ -1241,17 +1251,21 @@ If SEND-IF-FORCE, only send authinfo to the server if the
   (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))
          (auth-info
-          (nth 0 (auth-source-search :max 1
-                                     ;; TODO: allow the virtual server name too
-                                     :host nntp-address
-                                     :port '("119" "nntp"))))
+          (nth 0 (auth-source-search
+                 :max 1
+                 :host (list nntp-address (nnoo-current-server 'nntp))
+                 :port `("119" "nntp" ,(format "%s" nntp-port-number)
+                         "563" "nntps" "snews"))))
          (auth-user (plist-get auth-info :user))
+         (auth-force (plist-get auth-info :force))
          (auth-passwd (plist-get auth-info :secret))
          (auth-passwd (if (functionp auth-passwd)
                           (funcall auth-passwd)
                         auth-passwd))
+        (force (or (netrc-get alist "force")
+                    nntp-authinfo-force
+                    auth-force))
         (user (or
                ;; this is preferred to netrc-*
                auth-user
@@ -1326,6 +1340,7 @@ password contained in '~/.nntp-authinfo'."
     (set (make-local-variable 'nntp-process-to-buffer) nil)
     (set (make-local-variable 'nntp-process-start-point) nil)
     (set (make-local-variable 'nntp-process-decode) nil)
+    (set (make-local-variable 'nntp-retrieval-in-progress) nil)
     (current-buffer)))
 
 (defun nntp-open-connection (buffer)
@@ -1371,11 +1386,21 @@ password contained in '~/.nntp-authinfo'."
       (nnheader-cancel-timer timer))
     (when (and process
               (not (memq (process-status process) '(open run))))
+      (with-current-buffer pbuffer
+       (goto-char (point-min))
+       (nnheader-report 'nntp "Error when connecting: %s"
+                        (buffer-substring (point) (line-end-position))))
       (setq process nil))
     (unless process
       (nntp-kill-buffer pbuffer))
     (when (and (buffer-name pbuffer)
               process)
+      (when (and (fboundp 'set-network-process-option) ;; Unavailable in XEmacs.
+                (fboundp 'process-type) ;; Emacs 22 doesn't provide it.
+                 (eq (process-type process) 'network))
+        ;; Use TCP-keepalive so that connections that pass through a NAT router
+        ;; don't hang when left idle.
+        (set-network-process-option process :keepalive t))
       (gnus-set-process-query-on-exit-flag process nil)
       (if (and (nntp-wait-for process "^2.*\n" buffer nil t)
               (memq (process-status process) '(open run)))
@@ -1473,7 +1498,7 @@ password contained in '~/.nntp-authinfo'."
                (goto-char (point-max))
                (save-restriction
                  (narrow-to-region (point) (point))
-                 (nntp-insert-buffer-substring buf start)
+                 (nnheader-insert-buffer-substring buf start)
                  (when decode
                    (nntp-decode-text))))))
          ;; report it.
@@ -1683,7 +1708,7 @@ password contained in '~/.nntp-authinfo'."
         ;; for the first available article.  Obviously, a client can
         ;; use that entry to avoid making unnecessary requests.  The
         ;; only problem is for a client that assumes that the response
-        ;; will always be within the requested ranage.  For such a
+        ;; will always be within the requested range.  For such a
         ;; client, we can get N copies of the same entry (one for each
         ;; XOVER command sent to the server).
 
@@ -1701,7 +1726,7 @@ password contained in '~/.nntp-authinfo'."
        (when in-process-buffer-p
          (set-buffer buf)
          (goto-char (point-max))
-         (nntp-insert-buffer-substring process-buffer)
+         (nnheader-insert-buffer-substring process-buffer)
          (set-buffer process-buffer)
          (erase-buffer)
          (set-buffer buf))