Merge from emacs--devo--0, emacs--rel--22
[gnus] / lisp / nnrss.el
index e5e9773..f72166b 100644 (file)
@@ -1,6 +1,7 @@
 ;;; nnrss.el --- interfacing with RSS
 
-;; Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2002, 2003, 2004, 2005,
+;;   2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: RSS
@@ -9,7 +10,7 @@
 
 ;; 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
+;; by the Free Software Foundation; either version 3, or (at your
 ;; option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful, but
 (defvoo nnrss-directory (nnheader-concat gnus-directory "rss/")
   "Where nnrss will save its files.")
 
+(defvoo nnrss-ignore-article-fields '(slash:comments)
+  "*List of fields that should be ignored when comparing RSS articles.
+Some RSS feeds update article fields during their lives, e.g. to
+indicate the number of comments or the number of times the
+articles have been seen.  However, if there is a difference
+between the local article and the distant one, the latter is
+considered to be new.  To avoid this and discard some fields, set
+this variable to the list of fields to be ignored.")
+
 ;; (group max rss-url)
 (defvoo nnrss-server-data nil)
 
@@ -82,9 +92,20 @@ ENTRY is the record of the current headline.  GROUP is the group name.
 ARTICLE is the article number of the current headline.")
 
 (defvar nnrss-file-coding-system mm-universal-coding-system
-  "Coding system used when reading and writing files.")
-
-(defvar nnrss-compatible-encoding-alist '((iso-8859-1 . windows-1252))
+  "*Coding system used when reading and writing files.
+If you run Gnus with various versions of Emacsen, the value of this
+variable should be the coding system that all those Emacsen support.
+Note that you have to regenerate all the nnrss groups if you change
+the value.  Moreover, you should be patient even if you are made to
+read the same articles twice, that arises for the difference of the
+versions of xml.el.")
+
+(defvar nnrss-compatible-encoding-alist
+  (delq nil (mapcar (lambda (elem)
+                     (if (and (mm-coding-system-p (car elem))
+                              (mm-coding-system-p (cdr elem)))
+                         elem))
+                   mm-charset-override-alist))
   "Alist of encodings and those supersets.
 The cdr of each element is used to decode data if it is available when
 the car is what the data specify as the encoding.  Or, the car is used
@@ -174,9 +195,8 @@ used to render text.  If it is nil, text will simply be folded.")
 (deffoo nnrss-close-group (group &optional server)
   t)
 
-(eval-when-compile
-  (defvar mm-text-html-renderer)
-  (defvar mm-text-html-washer-alist))
+(defvar mm-text-html-renderer)
+(defvar mm-text-html-washer-alist)
 
 (deffoo nnrss-request-article (article &optional group server buffer)
   (setq group (nnrss-decode-group-name group))
@@ -359,7 +379,8 @@ used to render text.  If it is nil, text will simply be folded.")
        (delq (assoc group nnrss-server-data) nnrss-server-data))
   (nnrss-save-server-data server)
   (ignore-errors
-   (delete-file (nnrss-make-filename group server)))
+    (let ((file-name-coding-system nnmail-pathname-coding-system))
+      (delete-file (nnrss-make-filename group server))))
   t)
 
 (deffoo nnrss-request-list-newsgroups (&optional server)
@@ -417,8 +438,10 @@ otherwise return nil."
       (nnheader-remove-cr-followed-by-lf)
       ;; Decode text according to the encoding attribute.
       (when (setq cs (nnrss-get-encoding))
-       (mm-decode-coding-region (point-min) (point-max) cs)
-       (mm-enable-multibyte))
+       (insert (prog1
+                   (mm-decode-coding-string (buffer-string) cs)
+                 (erase-buffer)
+                 (mm-enable-multibyte))))
       (goto-char (point-min))
 
       ;; Because xml-parse-region can't deal with anything that isn't
@@ -536,13 +559,13 @@ which RSS 2.0 allows."
 
 (defun nnrss-read-server-data (server)
   (setq nnrss-server-data nil)
-  (let ((file (nnrss-make-filename "nnrss" server)))
+  (let ((file (nnrss-make-filename "nnrss" server))
+       (file-name-coding-system nnmail-pathname-coding-system))
     (when (file-exists-p file)
       ;; In Emacs 21.3 and earlier, `load' doesn't support non-ASCII
       ;; file names.  So, we use `insert-file-contents' instead.
       (mm-with-multibyte-buffer
-       (let ((coding-system-for-read nnrss-file-coding-system)
-             (file-name-coding-system nnmail-pathname-coding-system))
+       (let ((coding-system-for-read nnrss-file-coding-system))
          (insert-file-contents file)
          (eval-region (point-min) (point-max)))))))
 
@@ -565,17 +588,17 @@ which RSS 2.0 allows."
   (let ((pair (assoc group nnrss-server-data)))
     (setq nnrss-group-max (or (cadr pair) 0))
     (setq nnrss-group-min (+ nnrss-group-max 1)))
-  (let ((file (nnrss-make-filename group server)))
+  (let ((file (nnrss-make-filename group server))
+       (file-name-coding-system nnmail-pathname-coding-system))
     (when (file-exists-p file)
       ;; In Emacs 21.3 and earlier, `load' doesn't support non-ASCII
       ;; file names.  So, we use `insert-file-contents' instead.
       (mm-with-multibyte-buffer
-       (let ((coding-system-for-read nnrss-file-coding-system)
-             (file-name-coding-system nnmail-pathname-coding-system))
+       (let ((coding-system-for-read nnrss-file-coding-system))
          (insert-file-contents file)
          (eval-region (point-min) (point-max))))
       (dolist (e nnrss-group-data)
-       (puthash (or (nth 2 e) (nth 6 e)) t nnrss-group-hashtb)
+       (puthash (nth 9 e) t nnrss-group-hashtb)
        (when (and (car e) (> nnrss-group-min (car e)))
          (setq nnrss-group-min (car e)))
        (when (and (car e) (< nnrss-group-max (car e)))
@@ -655,9 +678,20 @@ which RSS 2.0 allows."
 
 ;;; Snarf functions
 
+(defun nnrss-make-hash-index (item)
+  (setq item (gnus-remove-if
+             (lambda (field)
+               (when (listp field)
+                 (memq (car field) nnrss-ignore-article-fields)))
+             item))
+  (md5 (gnus-prin1-to-string item)
+       nil nil
+       nnrss-file-coding-system))
+
 (defun nnrss-check-group (group server)
   (let (file xml subject url extra changed author date feed-subject
-            enclosure comments rss-ns rdf-ns content-ns dc-ns)
+            enclosure comments rss-ns rdf-ns content-ns dc-ns
+            hash-index)
     (if (and nnrss-use-local
             (file-exists-p (setq file (expand-file-name
                                        (nnrss-translate-file-chars
@@ -689,15 +723,12 @@ which RSS 2.0 allows."
     (dolist (item (nreverse (nnrss-find-el (intern (concat rss-ns "item")) xml)))
       (when (and (listp item)
                 (string= (concat rss-ns "item") (car item))
-                (if (setq url (nnrss-decode-entities-string
-                               (nnrss-node-text rss-ns 'link (cddr item))))
-                    (not (gethash url nnrss-group-hashtb))
-                  (setq extra (or (nnrss-node-text content-ns 'encoded item)
-                                  (nnrss-node-text rss-ns 'description item)))
-                  (not (gethash extra nnrss-group-hashtb))))
+                (progn (setq hash-index (nnrss-make-hash-index item))
+                       (not (gethash hash-index nnrss-group-hashtb))))
        (setq subject (nnrss-node-text rss-ns 'title item))
-       (setq extra (or extra
-                       (nnrss-node-text content-ns 'encoded item)
+       (setq url (nnrss-decode-entities-string
+                  (nnrss-node-text rss-ns 'link (cddr item))))
+       (setq extra (or (nnrss-node-text content-ns 'encoded item)
                        (nnrss-node-text rss-ns 'description item)))
        (if (setq feed-subject (nnrss-node-text dc-ns 'subject item))
            (setq extra (concat feed-subject "<br /><br />" extra)))
@@ -739,9 +770,10 @@ which RSS 2.0 allows."
          date
          (and extra (nnrss-decode-entities-string extra))
          enclosure
-         comments)
+         comments
+         hash-index)
         nnrss-group-data)
-       (puthash (or url extra) t nnrss-group-hashtb)
+       (puthash hash-index t nnrss-group-hashtb)
        (setq changed t))
       (setq extra nil))
     (when changed
@@ -756,14 +788,29 @@ which RSS 2.0 allows."
   "OPML subscriptions import.
 Read the file and attempt to subscribe to each Feed in the file."
   (interactive "fImport file: ")
-  (mapcar
-   (lambda (node) (gnus-group-make-rss-group
-                  (cdr (assq 'xmlUrl (cadr node)))))
+  (mapc
+   (lambda (node)
+     (let ((xmlurl (cdr (assq 'xmlUrl (cadr node)))))
+       (when (and xmlurl
+                 (not (string-match "\\`[\t ]*\\'" xmlurl))
+                 (prog1
+                     (y-or-n-p (format "Subscribe to %s " xmlurl))
+                   (message "")))
+        (condition-case err
+            (progn
+              (gnus-group-make-rss-group xmlurl)
+              (forward-line 1))
+          (error
+           (message
+            "Failed to subscribe to %s (%s); type any key to continue: "
+            xmlurl
+            (error-message-string err))
+           (let ((echo-keystrokes 0))
+             (read-char)))))))
    (nnrss-find-el 'outline
-                 (progn
-                   (find-file opml-file)
-                   (xml-parse-region (point-min)
-                                     (point-max))))))
+                 (mm-with-multibyte-buffer
+                   (insert-file-contents opml-file)
+                   (xml-parse-region (point-min) (point-max))))))
 
 (defun nnrss-opml-export ()
   "OPML subscription export.