Add 2010 to copyright years.
[gnus] / lisp / nnwarchive.el
index 4057db5..9b4e804 100644 (file)
@@ -1,32 +1,32 @@
 ;;; nnwarchive.el --- interfacing with web archives
-;; Copyright (C) 1999 Free Software Foundation, Inc.
+
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
+;;   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: news egroups mail-archive
 
 ;; This file is 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 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 3 of the License, 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.
+;; 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.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 ;; Note: You need to have `url' (w3 0.46) or greater version
-;; installed for this backend to work.
+;; installed for some functions of this backend to work.
 
-;; Todo: 
+;; Todo:
 ;; 1. To support more web archives.
 ;; 2. Generalize webmail to other MHonArc archive.
 
 (require 'gnus-bcklg)
 (require 'nnmail)
 (require 'mm-util)
-(require 'mail-source)
-(eval-when-compile
-  (ignore-errors
-    (require 'w3)
-    (require 'url)
-    (require 'w3-forms)
-    (require 'nnweb)))
-;; Report failure to find w3 at load time if appropriate.
-(eval '(progn
-        (require 'w3)
-        (require 'url)
-        (require 'w3-forms)
-        (require 'nnweb)))
+(require 'mm-url)
 
 (nnoo-declare nnwarchive)
 
 (defvar nnwarchive-type-definition
   '((egroups
      (address . "www.egroups.com")
-     (open-url 
-      "http://www.egroups.com/register?method=loginAction&email=%s&password=%s" 
+     (open-url
+      "http://www.egroups.com/login.cgi?&login_email=%s&login_password=%s"
       nnwarchive-login nnwarchive-passwd)
-     (list-url 
-      "http://www.egroups.com/UserGroupsPage?")
+     (list-url
+      "http://www.egroups.com/mygroups")
      (list-dissect . nnwarchive-egroups-list)
      (list-groups . nnwarchive-egroups-list-groups)
-     (xover-url 
-      "http://www.egroups.com/group/%s/?fetchForward=1&start=%d" group aux)
-     (xover-last-url 
-      "http://www.egroups.com/group/%s/?fetchForward=1" group)
+     (xover-url
+      "http://www.egroups.com/messages/%s/%d" group aux)
+     (xover-last-url
+      "http://www.egroups.com/messages/%s/" group)
      (xover-page-size . 13)
      (xover-dissect . nnwarchive-egroups-xover)
-     (article-url 
-      "http://www.egroups.com/group/%s/%d.html?raw=1" group article)
+     (article-url
+      "http://www.egroups.com/message/%s/%d?source=1" group article)
      (article-dissect . nnwarchive-egroups-article)
      (authentication . t)
      (article-offset . 0)
     (mail-archive
      (address . "www.mail-archive.com")
      (open-url)
-     (list-url 
+     (list-url
       "http://www.mail-archive.com/lists.html")
      (list-dissect . nnwarchive-mail-archive-list)
      (list-groups . nnwarchive-mail-archive-list-groups)
-     (xover-url 
+     (xover-url
       "http://www.mail-archive.com/%s/mail%d.html" group aux)
-     (xover-last-url 
+     (xover-last-url
       "http://www.mail-archive.com/%s/maillist.html" group)
      (xover-page-size)
      (xover-dissect . nnwarchive-mail-archive-xover)
-     (article-url 
+     (article-url
       "http://www.mail-archive.com/%s/msg%05d.html" group article1)
      (article-dissect . nnwarchive-mail-archive-article)
      (xover-files . nnwarchive-mail-archive-xover-files)
   (let ((defs (cdr (assq type nnwarchive-type-definition)))
        def)
     (dolist (def defs)
-      (set (intern (concat "nnwarchive-" (symbol-name (car def)))) 
+      (set (intern (concat "nnwarchive-" (symbol-name (car def))))
           (cdr def)))))
 
 (defmacro nnwarchive-backlog (&rest form)
   `(let ((gnus-keep-backlog nnwarchive-keep-backlog)
-        (gnus-backlog-buffer 
+        (gnus-backlog-buffer
          (format " *nnwarchive backlog %s*" nnwarchive-address))
         (gnus-backlog-articles nnwarchive-backlog-articles)
         (gnus-backlog-hashtb nnwarchive-backlog-hashtb))
   (nnwarchive-backlog
     (gnus-backlog-enter-article group number buffer)))
 
-(defun nnwarchive-get-article (article &optional group server buffer) 
+(defun nnwarchive-get-article (article &optional group server buffer)
   (if (numberp article)
       (if (nnwarchive-backlog
-           (gnus-backlog-request-article group article 
+           (gnus-backlog-request-article group article
                                          (or buffer nntp-server-buffer)))
          (cons group article)
        (let (contents)
   t)
 
 (deffoo nnwarchive-open-server (server &optional defs connectionless)
+  (nnoo-change-server 'nnwarchive server defs)
   (nnwarchive-init server)
-  (if (nnwarchive-server-opened server)
-      t
-    (nnoo-change-server 'nnwarchive server defs)
-    (when nnwarchive-authentication
-      (setq nnwarchive-login
-           (or nnwarchive-login
-               (read-string
+  (when nnwarchive-authentication
+    (setq nnwarchive-login
+         (or nnwarchive-login
+             (read-string
                 (format "Login at %s: " server)
                 user-mail-address)))
-      (setq nnwarchive-passwd
-           (or nnwarchive-passwd
-               (mail-source-read-passwd
-                (format "Password for %s at %s: " 
-                        nnwarchive-login server)))))
-    (unless nnwarchive-groups
-      (nnwarchive-read-groups))
-    (save-excursion
-      (set-buffer nnwarchive-buffer)
-      (erase-buffer)
-      (if nnwarchive-open-url
-         (nnwarchive-url nnwarchive-open-url))
-      (if nnwarchive-open-dissect
-         (funcall nnwarchive-open-dissect)))
-    t))
+    (setq nnwarchive-passwd
+         (or nnwarchive-passwd
+             (read-passwd
+              (format "Password for %s at %s: "
+                      nnwarchive-login server)))))
+  (unless nnwarchive-groups
+    (nnwarchive-read-groups))
+  (save-excursion
+    (set-buffer nnwarchive-buffer)
+    (erase-buffer)
+    (if nnwarchive-open-url
+       (nnwarchive-url nnwarchive-open-url))
+    (if nnwarchive-open-dissect
+       (funcall nnwarchive-open-dissect)))
+  t)
 
 (nnoo-define-skeleton nnwarchive)
 
     (nnwarchive-open-server server)))
 
 (defun nnwarchive-read-groups ()
-  (let ((file (expand-file-name (concat "groups-" nnwarchive-address) 
+  (let ((file (expand-file-name (concat "groups-" nnwarchive-address)
                                nnwarchive-directory)))
     (when (file-exists-p file)
       (with-temp-buffer
        (setq nnwarchive-groups (read (current-buffer)))))))
 
 (defun nnwarchive-write-groups ()
-  (with-temp-file (expand-file-name (concat "groups-" nnwarchive-address) 
+  (with-temp-file (expand-file-name (concat "groups-" nnwarchive-address)
                                    nnwarchive-directory)
     (prin1 nnwarchive-groups (current-buffer))))
 
 (defun nnwarchive-init (server)
   "Initialize buffers and such."
   (let ((type (intern server)) (defs nnwarchive-type-definition) def)
-    (cond 
+    (cond
      ((equal server "")
       (setq type nnwarchive-default-type))
      ((assq type nnwarchive-type-definition) t)
             (format " *nnwarchive %s %s*" nnwarchive-type server)))))
   (nnwarchive-set-default nnwarchive-type))
 
-(defun nnwarchive-encode-www-form-urlencoded (pairs)
-  "Return PAIRS encoded for forms."
-  (mapconcat
-   (function
-    (lambda (data)
-      (concat (w3-form-encode-xwfu (car data)) "="
-             (w3-form-encode-xwfu (cdr data)))))
-   pairs "&"))
-
-(defun nnwarchive-fetch-form (url pairs)
-  (let ((url-request-data (nnwarchive-encode-www-form-urlencoded pairs))
-       (url-request-method "POST")
-       (url-request-extra-headers
-        '(("Content-type" . "application/x-www-form-urlencoded"))))
-    (nnweb-insert url))
-  t)
-
 (defun nnwarchive-eval (expr)
   (cond
    ((consp expr)
     expr)))
 
 (defun nnwarchive-url (xurl)
-  (let ((url-confirmation-func 'identity))
-    (cond 
-     ((eq (car xurl) 'post)
-      (pop xurl)
-      (nnwarchive-fetch-form (car xurl) (nnwarchive-eval (cdr xurl))))
-     (t
-      (nnweb-insert (apply 'format (nnwarchive-eval xurl)))))))
+  (mm-with-unibyte-current-buffer
+    (let ((url-confirmation-func 'identity) ;; Some hacks.
+         (url-cookie-multiple-line nil))
+      (cond
+       ((eq (car xurl) 'post)
+       (pop xurl)
+       (mm-url-fetch-form (car xurl) (nnwarchive-eval (cdr xurl))))
+       (t
+       (mm-url-insert (apply 'format (nnwarchive-eval xurl))))))))
 
 (defun nnwarchive-generate-active ()
   (save-excursion
   (save-excursion
     (let (articles)
       (set-buffer nnwarchive-buffer)
-      (dolist (group groups) 
+      (dolist (group groups)
        (erase-buffer)
        (nnwarchive-url nnwarchive-xover-last-url)
        (goto-char (point-min))
-       (when (re-search-forward "of \\([0-9]+\\)</title>" nil t)
-         (setq articles (string-to-number (match-string 1)))) 
+       (when (re-search-forward "of \\([0-9]+\\)[ \t\n\r]*</title>" nil t)
+         (setq articles (string-to-number (match-string 1))))
        (let ((elem (assoc group nnwarchive-groups)))
          (if elem
              (setcar (cdr elem) articles)
   (let ((case-fold-search t)
        group description elem articles)
     (goto-char (point-min))
-    (while 
-       (re-search-forward
-        "/group/\\([^/]+\\)/info\\.html[^>]+>[^>]+>[\040\t]*-[\040\t]*\\([^<]+\\)<"
-        nil t)
+    (while
+       (re-search-forward "href=\"/group/\\([^/\"\> ]+\\)" nil t)
       (setq group (match-string 1)
            description (match-string 2))
-      (forward-line 1)
-      (when (re-search-forward ">\\([0-9]+\\)<" nil t)
-       (setq articles (string-to-number (match-string 1)))) 
       (if (setq elem (assoc group nnwarchive-groups))
-         (setcar (cdr elem) articles)
+         (setcar (cdr elem) 0)
        (push (list group articles description) nnwarchive-groups))))
   t)
 
   (let (article subject from date)
     (goto-char (point-min))
     (while (re-search-forward
-           "<a href=\"/group/\\([^/]+\\)/\\([0-9]+\\)\\.html[^>]+>\\([^<]+\\)<"
+           "<a href=\"/group/\\([^/]+\\)/\\([0-9]+\\)[^>]+>\\([^<]+\\)<"
            nil t)
       (setq group  (match-string 1)
            article (string-to-number (match-string 2))
        (push (cons
               article
               (make-full-mail-header
-               article 
-               (nnweb-decode-entities-string subject)
-               (nnweb-decode-entities-string from)
+               article
+               (mm-url-decode-entities-string subject)
+               (mm-url-decode-entities-string from)
                date
                (concat "<" group "%"
-                       (number-to-string article) 
+                       (number-to-string article)
                        "@egroup.com>")
                ""
                0 0 "")) nnwarchive-headers))))
       (delete-region (point) (point-max)))
   (goto-char (point-min))
   (while (re-search-forward "<a[^>]+>\\([^<]+\\)</a>" nil t)
-    (replace-match "<\\1>"))
-  (nnweb-decode-entities)
+    (replace-match "\\1"))
+  (mm-url-decode-entities)
   (buffer-string))
 
 (defun nnwarchive-egroups-xover-files (group articles)
        (let ((elem (assoc group nnwarchive-headers-cache)))
          (if elem
              (setcdr elem nnwarchive-headers)
-           (push (cons group nnwarchive-headers) 
+           (push (cons group nnwarchive-headers)
                  nnwarchive-headers-cache)))))))
 
 (defun nnwarchive-mail-archive-list ()
            subject (match-string 2))
       (forward-line 1)
       (unless (assq article nnwarchive-headers)
-       (if (looking-at "<UL><LI><EM>From</EM>:\\([^&]+\\)<\\([^&]+\\)>")
+       (if (looking-at "<UL><LI><EM>From</EM>: *\\([^<]*[^< ]\\) *&lt;\\([^&]+\\)&gt;")
            (progn
              (setq from (match-string 1)
                    date (identity (match-string 2))))
        (push (cons
               article
               (make-full-mail-header
-               article 
-               (nnweb-decode-entities-string subject)
-               (nnweb-decode-entities-string from)
+               article
+               (mm-url-decode-entities-string subject)
+               (mm-url-decode-entities-string from)
                date
                (format "<%05d%%%s>\n" (1- article) group)
                ""
       (insert from-r13)
       (let ((message-caesar-translation-table
             (or nnwarchive-caesar-translation-table
-                (setq nnwarchive-caesar-translation-table 
+                (setq nnwarchive-caesar-translation-table
                       (nnwarchive-make-caesar-translation-table)))))
        (message-caesar-region (point-min) (point-max))
        (buffer-string)))))
 
 (defun nnwarchive-mail-archive-article (group article)
-  (let (p refs url mime e 
-         from subject date id 
+  (let (p refs url mime e
+         from subject date id
          done
-         (case-fold-serch t))
+         (case-fold-search t))
     (save-restriction
       (goto-char (point-min))
       (when (search-forward "X-Head-End" nil t)
        (beginning-of-line)
        (narrow-to-region (point-min) (point))
-       (nnweb-decode-entities)
+       (mm-url-decode-entities)
        (goto-char (point-min))
        (while (search-forward "<!--X-" nil t)
          (replace-match ""))
        (goto-char (point-min))
        (while (search-forward " -->" nil t)
          (replace-match ""))
-       (setq from 
+       (setq from
              (or (mail-fetch-field "from")
-                 (nnwarchive-from-r13 
+                 (nnwarchive-from-r13
                   (mail-fetch-field "from-r13"))))
        (setq date (mail-fetch-field "date"))
        (setq id (mail-fetch-field "message-id"))
        (search-forward "</ul>" nil t)
        (end-of-line)
        (narrow-to-region (point-min) (point))
-       (nnweb-remove-markup)
-       (nnweb-decode-entities)
+       (mm-url-remove-markup)
+       (mm-url-decode-entities)
        (goto-char (point-min))
        (delete-blank-lines)
        (when from
        (goto-char (point-max))
        (widen)
        (insert "\n"))
-      (setq p (point)) 
+      (setq p (point))
       (when (search-forward "X-Body-of-Message" nil t)
        (forward-line)
        (delete-region p (point))
          (if (> (skip-chars-forward "\040\n\r\t") 0)
              (delete-region (point-min) (point)))
          (while (not (eobp))
-           (cond 
-            ((looking-at "<PRE>\r?\n?") 
+           (cond
+            ((looking-at "<PRE>\r?\n?")
              (delete-region (match-beginning 0) (match-end 0))
              (setq p (point))
              (when (search-forward "</PRE>" nil t)
                (delete-region (match-beginning 0) (match-end 0))
                (save-restriction
                  (narrow-to-region p (point))
-                 (nnweb-remove-markup)
-                 (nnweb-decode-entities)
+                 (mm-url-remove-markup)
+                 (mm-url-decode-entities)
                  (goto-char (point-max)))))
             ((looking-at "<P><A HREF=\"\\([^\"]+\\)")
              (setq url (match-string 1))
-             (delete-region (match-beginning 0) 
+             (delete-region (match-beginning 0)
                             (progn (forward-line) (point)))
-             ;; I hate to download the url encode it, then immediately 
+             ;; I hate to download the url encode it, then immediately
              ;; decode it.
-             ;; FixMe: Find a better solution to attach the URL.
-             ;; Maybe do some hack in external part of mml-generate-mim-1.
-             (insert "<#part>"
-                     "\n--\nExternal: \n"
-                     (format "<URL:http://www.mail-archive.com/%s/%s>" 
+             (insert "<#external"
+                     " type="
+                     (or (and url
+                              (string-match "\\.[^\\.]+$" url)
+                              (mailcap-extension-to-mime
+                               (match-string 0 url)))
+                         "application/octet-stream")
+                     (format " url=\"http://www.mail-archive.com/%s/%s\""
                              group url)
-                     "\n--\n"
-                     "<#/part>")
+                     ">\n"
+                     "<#/external>")
              (setq mime t))
             (t
              (setq p (point))
              (insert "<#part type=\"text/html\" disposition=inline>")
              (goto-char
-              (if (re-search-forward 
-                   "[\040\n\r\t]*<PRE>\\|[\040\n\r\t]*<P><A HREF=\"" 
+              (if (re-search-forward
+                   "[\040\n\r\t]*<PRE>\\|[\040\n\r\t]*<P><A HREF=\""
                    nil t)
                   (match-beginning 0)
                 (point-max)))
          (insert " " (pop refs)))
        (insert "\n"))
       (when mime
-       (unless (looking-at "$") 
+       (unless (looking-at "$")
          (search-forward "\n\n" nil t)
          (forward-line -1))
        (narrow-to-region (point) (point-max))
 
 (provide 'nnwarchive)
 
+;; arch-tag: 1ab7a15c-777a-40e0-95c0-0c41b3963578
 ;;; nnwarchive.el ends here