;;; 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
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
+the car is what the data specify as the encoding. Or, the car is used
for decoding when the cdr that the data specify is not available.")
+(defvar nnrss-wash-html-in-text-plain-parts nil
+ "*Non-nil means render text in text/plain parts as HTML.
+The function specified by the `mm-text-html-renderer' variable will be
+used to render text. If it is nil, text will simply be folded.")
+
(nnoo-define-basics nnrss)
;;; Interface functions
(deffoo nnrss-close-group (group &optional server)
t)
+(eval-when-compile
+ (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))
(when (stringp article)
(if (nth 5 e)
(insert "Date: " (nnrss-format-string (nth 5 e)) "\n"))
(let ((header (buffer-string))
- (text (if (nth 6 e)
- (mapconcat 'identity
- (delete "" (split-string (nth 6 e) "\n+"))
- " ")))
+ (text (nth 6 e))
(link (nth 2 e))
(enclosure (nth 7 e))
(comments (nth 8 e))
(cons '("Newsgroups" . utf-8)
rfc2047-header-encoding-alist)
rfc2047-header-encoding-alist))
- rfc2047-encode-encoded-words body)
+ rfc2047-encode-encoded-words body fn)
(when (or text link enclosure comments)
(insert "\n")
(insert "<#multipart type=alternative>\n"
(when text
(insert text)
(goto-char body)
- ;; See `nnrss-check-group', which inserts "<br /><br />".
- (when (search-forward "<br /><br />" nil t)
- (if (eobp)
- (replace-match "\n")
- (replace-match "\n\n")))
- (unless (eobp)
- (let ((fill-column default-fill-column)
- (window (get-buffer-window nntp-server-buffer)))
- (when window
- (setq fill-column
- (max 1 (/ (* (window-width window) 7) 8))))
- (fill-region (point) (point-max))
- (goto-char (point-max))
- ;; XEmacs version of `fill-region' inserts newline.
- (unless (bolp)
- (insert "\n"))))
+ (if (and nnrss-wash-html-in-text-plain-parts
+ (progn
+ (require 'mm-view)
+ (setq fn (or (cdr (assq mm-text-html-renderer
+ mm-text-html-washer-alist))
+ mm-text-html-renderer))))
+ (progn
+ (narrow-to-region body (point-max))
+ (if (functionp fn)
+ (funcall fn)
+ (apply (car fn) (cdr fn)))
+ (widen)
+ (goto-char body)
+ (re-search-forward "[^\t\n ]" nil t)
+ (beginning-of-line)
+ (delete-region body (point))
+ (goto-char (point-max))
+ (skip-chars-backward "\t\n ")
+ (end-of-line)
+ (delete-region (point) (point-max))
+ (insert "\n"))
+ (while (re-search-forward "\n+" nil t)
+ (replace-match " "))
+ (goto-char body)
+ ;; See `nnrss-check-group', which inserts "<br /><br />".
+ (when (search-forward "<br /><br />" nil t)
+ (if (eobp)
+ (replace-match "\n")
+ (replace-match "\n\n")))
+ (unless (eobp)
+ (let ((fill-column default-fill-column)
+ (window (get-buffer-window nntp-server-buffer)))
+ (when window
+ (setq fill-column
+ (max 1 (/ (* (window-width window) 7) 8))))
+ (fill-region (point) (point-max))
+ (goto-char (point-max))
+ ;; XEmacs version of `fill-region' inserts newline.
+ (unless (bolp)
+ (insert "\n")))))
(when (or link enclosure)
(insert "\n")))
(when link
(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)
(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
(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)))))))
(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)))
(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
(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 (md5 (gnus-prin1-to-string item)
+ nil nil
+ nnrss-file-coding-system))
+ (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)))
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
"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.