Revision: miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-243

Merge from gnus--rel--5.10

Patches applied:

 * gnus--rel--5.10  (patch 59)

   - Update from CVS

2005-04-06  Katsumi Yamaoka  <yamaoka@jpl.org>

   * lisp/calendar/time-date.el (time-to-seconds): Don't use the #xhhhh
   syntax which Emacs 20 doesn't support.
   (seconds-to-time, days-to-time, time-subtract, time-add): Ditto.

2005-04-06  Katsumi Yamaoka  <yamaoka@jpl.org>

   * lisp/gnus/mm-util.el (mm-coding-system-p): Don't return binary for the nil
   argument in XEmacs.

   * lisp/gnus/nnrss.el (nnrss-compatible-encoding-alist): New variable.
   (nnrss-request-group): Decode group name first.
   (nnrss-request-article): Make a text/plain article if mml-to-mime
   failed.
   (nnrss-get-encoding): Return a compatible encoding according to
   nnrss-compatible-encoding-alist.
   (nnrss-opml-export): Use dolist.
   (nnrss-find-el): Use consp instead of listp.
   (nnrss-order-hrefs): Use dolist.

2005-04-06  Arne J,Ax(Brgensen  <arne@arnested.dk>

   * lisp/gnus/nnrss.el (nnrss-verbose): Remove.
   (nnrss-request-group): Use `nnheader-message' instead.

2005-04-06  Mark Plaksin  <happy@usg.edu>  (tiny change)

   * lisp/gnus/nnrss.el (nnrss-verbose): New variable.
   (nnrss-request-group): Make it say nnrss is requesting a group.

2005-04-06  Katsumi Yamaoka  <yamaoka@jpl.org>

   * lisp/gnus/gnus-agent.el (gnus-agent-group-path): Decode group name.
   (gnus-agent-group-pathname): Ditto.

   * lisp/gnus/gnus-cache.el (gnus-cache-file-name): Decode group name.

   * lisp/gnus/gnus-group.el (gnus-group-line-format-alist): Use decoded group
   name for only %g and %c.
   (gnus-group-insert-group-line): Bind gnus-tmp-decoded-group
   instead of gnus-tmp-group to decoded group name.
   (gnus-group-make-group): Decode group name.
   (gnus-group-delete-group): Ditto.
   (gnus-group-make-rss-group): Exclude `/'s from group names;
   register the group data after opening the nnrss group; unify
   non-ASCII group names; encode group name.
   (gnus-group-catchup-current): Decode group name.
   (gnus-group-expire-articles-1): Ditto.
   (gnus-group-set-current-level): Ditto.
   (gnus-group-kill-group): Ditto.

   * lisp/gnus/gnus-spec.el (gnus-update-format-specifications): Flush the
   group format spec cache if it doesn't support decoded group names.

   * lisp/gnus/mm-url.el (mm-url-predefined-programs): Add --silent arg to curl.

   * lisp/gnus/nnrss.el: Require rfc2047 and mml.
   (nnrss-file-coding-system): New variable.
   (nnrss-format-string): Redefine it as an inline function.
   (nnrss-decode-group-name): New function.
   (nnrss-string-as-multibyte): Remove.
   (nnrss-retrieve-headers): Decode group name; don't use
   nnrss-format-string.
   (nnrss-request-group): Decode group name.
   (nnrss-request-article): Decode group name; allow a Message-ID as
   well as an article number; don't use nnrss-format-string; encode a
   Message-ID string which may contain non-ASCII characters; use
   mml-to-mime to compose a MIME article; use search-forward instead
   of re-search-forward.
   (nnrss-request-expire-articles): Decode group name.
   (nnrss-request-delete-group): Delete entries in nnrss-group-alist
   as well; decode group name.
   (nnrss-get-encoding): Fix regexp.
   (nnrss-fetch): Clarify error message.
   (nnrss-read-server-data): Use insert-file-contents instead of load;
   bind file-name-coding-system; use multibyte buffer.
   (nnrss-save-server-data): Insert newline; bind
   coding-system-for-write to the value of nnrss-file-coding-system;
   bind file-name-coding-system; add coding cookie.
   (nnrss-read-group-data): Use insert-file-contents instead of load;
   bind file-name-coding-system; use multibyte buffer.
   (nnrss-save-group-data): Bind coding-system-for-write to the
   value of nnrss-file-coding-system; bind file-name-coding-system.
   (nnrss-decode-entities-string): Rename from n-d-e-unibyte-string;
   make it work with non-ASCII text.
   (nnrss-opml-export): Use mm-set-buffer-file-coding-system instead
   of set-buffer-file-coding-system.
   (nnrss-find-el): Check carefully whether there's a list of string
   which old xml.el may return rather than a string; make it work
   with old xml.el as well.

2005-04-06  Tsuyoshi AKIHO  <akiho@kawachi.zaq.ne.jp>

   * lisp/gnus/gnus-sum.el (gnus-summary-walk-group-buffer): Decode group name.

   * lisp/gnus/nnrss.el (nnrss-get-encoding): New function.
   (nnrss-fetch): Use unibyte buffer initially; bind
   coding-system-for-read while performing mm-url-insert; remove ^Ms;
   decode contents according to the encoding attribute.
   (nnrss-save-group-data): Add coding cookie.
   (nnrss-mime-encode-string): New function.
   (nnrss-check-group): Use it to encode subject and author.

2005-04-06  Maciek Pasternacki  <maciekp@japhy.fnord.org>  (tiny change)

   * lisp/gnus/nnrss.el (nnrss-fetch): Signal an error if w3-parse-buffer also
   failed.

2005-04-06  Jesper Harder  <harder@ifa.au.dk>

   * lisp/gnus/mm-util.el (mm-subst-char-in-string): Support inplace.

   * lisp/gnus/nnrss.el: Pedantic docstring and whitespace fixes (courtesy of
   checkdoc.el).
   (nnrss-request-article): Cleanup.
   (nnrss-request-delete-group): Use nnrss-make-filename.
   (nnrss-read-server-data): Use nnrss-make-filename; use load.
   (nnrss-save-server-data): Use nnrss-make-filename; use gnus-prin1.
   (nnrss-read-group-data): Fix off-by-one error.  From Joakim Verona
   <joakim@verona.se>; hash on description if link is missing; use
   nnrss-make-filename; use load.
   (nnrss-save-group-data): Use nnrss-make-filename; use gnus-prin1.
   (nnrss-make-filename): New function.
   (nnrss-close): New function.
   (nnrss-check-group): Hash on description if link is missing.
   (nnrss-get-namespace-prefix): Use string= to compare strings!
   Reported by David D. Smith <davidsmith@acm.org>.
   (nnrss-opml-export): Turn on sgml-mode.

2005-04-06  Mark A. Hershberger  <mah@everybody.org>

   * lisp/gnus/nnrss.el (nnrss-opml-import, nnrss-opml-export): New functions.

2005-04-06  Katsumi Yamaoka  <yamaoka@jpl.org>

   * man/gnus.texi (RSS): Addition.
This commit is contained in:
Miles Bader 2005-04-10 04:20:14 +00:00
parent 36178ae8fb
commit 9147257891
13 changed files with 670 additions and 318 deletions

View file

@ -1,3 +1,9 @@
2005-04-06 Katsumi Yamaoka <yamaoka@jpl.org>
* calendar/time-date.el (time-to-seconds): Don't use the #xhhhh
syntax which Emacs 20 doesn't support.
(seconds-to-time, days-to-time, time-subtract, time-add): Ditto.
2005-04-09 Stefan Monnier <monnier@iro.umontreal.ca>
* arc-mode.el (archive-mode-map): Move initialization into

View file

@ -1,5 +1,6 @@
;;; time-date.el --- Date and time handling functions
;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
;; Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Masanobu Umeda <umerin@mse.kyutech.ac.jp>
@ -112,15 +113,15 @@ and type 3 is the list (HIGH LOW MICRO)."
"Convert time value TIME to a floating point number.
You can use `float-time' instead."
(with-decoded-time-value ((high low micro time))
(+ (* 1.0 high #x10000)
(+ (* 1.0 high 65536)
low
(/ micro 1000000.0))))
;;;###autoload
(defun seconds-to-time (seconds)
"Convert SECONDS (a floating point number) to a time value."
(list (floor seconds #x10000)
(floor (mod seconds #x10000))
(list (floor seconds 65536)
(floor (mod seconds 65536))
(floor (* (- seconds (ffloor seconds)) 1000000))))
;;;###autoload
@ -138,10 +139,10 @@ You can use `float-time' instead."
(defun days-to-time (days)
"Convert DAYS into a time value."
(let* ((seconds (* 1.0 days 60 60 24))
(high (condition-case nil (floor (/ seconds #x10000))
(high (condition-case nil (floor (/ seconds 65536))
(range-error most-positive-fixnum))))
(list high (condition-case nil (floor (- seconds (* 1.0 high #x10000)))
(range-error #xffff)))))
(list high (condition-case nil (floor (- seconds (* 1.0 high 65536)))
(range-error 65535)))))
;;;###autoload
(defun time-since (time)
@ -170,7 +171,7 @@ Return the difference in the format of a time value."
micro (+ micro 1000000)))
(when (< low 0)
(setq high (1- high)
low (+ low #x10000)))
low (+ low 65536)))
(encode-time-value high low micro type)))
;;;###autoload
@ -185,9 +186,9 @@ Return the difference in the format of a time value."
(when (>= micro 1000000)
(setq low (1+ low)
micro (- micro 1000000)))
(when (>= low #x10000)
(when (>= low 65536)
(setq high (1+ high)
low (- low #x10000)))
low (- low 65536)))
(encode-time-value high low micro type)))
;;;###autoload

View file

@ -1,3 +1,131 @@
2005-04-06 Katsumi Yamaoka <yamaoka@jpl.org>
* mm-util.el (mm-coding-system-p): Don't return binary for the nil
argument in XEmacs.
* nnrss.el (nnrss-compatible-encoding-alist): New variable.
(nnrss-request-group): Decode group name first.
(nnrss-request-article): Make a text/plain article if mml-to-mime
failed.
(nnrss-get-encoding): Return a compatible encoding according to
nnrss-compatible-encoding-alist.
(nnrss-opml-export): Use dolist.
(nnrss-find-el): Use consp instead of listp.
(nnrss-order-hrefs): Use dolist.
2005-04-06 Arne J,Ax(Brgensen <arne@arnested.dk>
* nnrss.el (nnrss-verbose): Remove.
(nnrss-request-group): Use `nnheader-message' instead.
2005-04-06 Mark Plaksin <happy@usg.edu> (tiny change)
* nnrss.el (nnrss-verbose): New variable.
(nnrss-request-group): Make it say nnrss is requesting a group.
2005-04-06 Katsumi Yamaoka <yamaoka@jpl.org>
* gnus-agent.el (gnus-agent-group-path): Decode group name.
(gnus-agent-group-pathname): Ditto.
* gnus-cache.el (gnus-cache-file-name): Decode group name.
* gnus-group.el (gnus-group-line-format-alist): Use decoded group
name for only %g and %c.
(gnus-group-insert-group-line): Bind gnus-tmp-decoded-group
instead of gnus-tmp-group to decoded group name.
(gnus-group-make-group): Decode group name.
(gnus-group-delete-group): Ditto.
(gnus-group-make-rss-group): Exclude `/'s from group names;
register the group data after opening the nnrss group; unify
non-ASCII group names; encode group name.
(gnus-group-catchup-current): Decode group name.
(gnus-group-expire-articles-1): Ditto.
(gnus-group-set-current-level): Ditto.
(gnus-group-kill-group): Ditto.
* gnus-spec.el (gnus-update-format-specifications): Flush the
group format spec cache if it doesn't support decoded group names.
* mm-url.el (mm-url-predefined-programs): Add --silent arg to curl.
* nnrss.el: Require rfc2047 and mml.
(nnrss-file-coding-system): New variable.
(nnrss-format-string): Redefine it as an inline function.
(nnrss-decode-group-name): New function.
(nnrss-string-as-multibyte): Remove.
(nnrss-retrieve-headers): Decode group name; don't use
nnrss-format-string.
(nnrss-request-group): Decode group name.
(nnrss-request-article): Decode group name; allow a Message-ID as
well as an article number; don't use nnrss-format-string; encode a
Message-ID string which may contain non-ASCII characters; use
mml-to-mime to compose a MIME article; use search-forward instead
of re-search-forward.
(nnrss-request-expire-articles): Decode group name.
(nnrss-request-delete-group): Delete entries in nnrss-group-alist
as well; decode group name.
(nnrss-get-encoding): Fix regexp.
(nnrss-fetch): Clarify error message.
(nnrss-read-server-data): Use insert-file-contents instead of load;
bind file-name-coding-system; use multibyte buffer.
(nnrss-save-server-data): Insert newline; bind
coding-system-for-write to the value of nnrss-file-coding-system;
bind file-name-coding-system; add coding cookie.
(nnrss-read-group-data): Use insert-file-contents instead of load;
bind file-name-coding-system; use multibyte buffer.
(nnrss-save-group-data): Bind coding-system-for-write to the
value of nnrss-file-coding-system; bind file-name-coding-system.
(nnrss-decode-entities-string): Rename from n-d-e-unibyte-string;
make it work with non-ASCII text.
(nnrss-opml-export): Use mm-set-buffer-file-coding-system instead
of set-buffer-file-coding-system.
(nnrss-find-el): Check carefully whether there's a list of string
which old xml.el may return rather than a string; make it work
with old xml.el as well.
2005-04-06 Tsuyoshi AKIHO <akiho@kawachi.zaq.ne.jp>
* gnus-sum.el (gnus-summary-walk-group-buffer): Decode group name.
* nnrss.el (nnrss-get-encoding): New function.
(nnrss-fetch): Use unibyte buffer initially; bind
coding-system-for-read while performing mm-url-insert; remove ^Ms;
decode contents according to the encoding attribute.
(nnrss-save-group-data): Add coding cookie.
(nnrss-mime-encode-string): New function.
(nnrss-check-group): Use it to encode subject and author.
2005-04-06 Maciek Pasternacki <maciekp@japhy.fnord.org> (tiny change)
* nnrss.el (nnrss-fetch): Signal an error if w3-parse-buffer also
failed.
2005-04-06 Jesper Harder <harder@ifa.au.dk>
* mm-util.el (mm-subst-char-in-string): Support inplace.
* nnrss.el: Pedantic docstring and whitespace fixes (courtesy of
checkdoc.el).
(nnrss-request-article): Cleanup.
(nnrss-request-delete-group): Use nnrss-make-filename.
(nnrss-read-server-data): Use nnrss-make-filename; use load.
(nnrss-save-server-data): Use nnrss-make-filename; use gnus-prin1.
(nnrss-read-group-data): Fix off-by-one error. From Joakim Verona
<joakim@verona.se>; hash on description if link is missing; use
nnrss-make-filename; use load.
(nnrss-save-group-data): Use nnrss-make-filename; use gnus-prin1.
(nnrss-make-filename): New function.
(nnrss-close): New function.
(nnrss-check-group): Hash on description if link is missing.
(nnrss-get-namespace-prefix): Use string= to compare strings!
Reported by David D. Smith <davidsmith@acm.org>.
(nnrss-opml-export): Turn on sgml-mode.
2005-04-06 Mark A. Hershberger <mah@everybody.org>
* nnrss.el (nnrss-opml-import, nnrss-opml-export): New functions.
2005-04-04 Reiner Steib <Reiner.Steib@gmx.de>
* message.el (message-make-date): Add defvars in order to silence

View file

@ -1,5 +1,5 @@
;;; gnus-agent.el --- unplugged support for Gnus
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
;; Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
@ -1371,7 +1371,7 @@ downloaded into the agent."
(nnheader-translate-file-chars
(nnheader-replace-duplicate-chars-in-string
(nnheader-replace-chars-in-string
(gnus-group-real-name group)
(gnus-group-real-name (gnus-group-decoded-name group))
?/ ?_)
?. ?_)))
(if (or nnmail-use-long-file-names
@ -1387,8 +1387,10 @@ downloaded into the agent."
;; unplugged. The agent must, therefore, use the same directory
;; while plugged.
(let ((gnus-command-method (or gnus-command-method
(gnus-find-method-for-group group))))
(nnmail-group-pathname (gnus-group-real-name group) (gnus-agent-directory))))
(gnus-find-method-for-group group))))
(nnmail-group-pathname (gnus-group-real-name
(gnus-group-decoded-name group))
(gnus-agent-directory))))
(defun gnus-agent-get-function (method)
(if (gnus-online method)

View file

@ -1,6 +1,6 @@
;;; gnus-cache.el --- cache interface for Gnus
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
;; Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
;; 2004, 2005 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
@ -421,6 +421,7 @@ Returns the list of articles removed."
(and (not unread) (not ticked) (not dormant) (memq 'read class))))
(defun gnus-cache-file-name (group article)
(setq group (gnus-group-decoded-name group))
(expand-file-name
(if (stringp article) article (int-to-string article))
(file-name-as-directory

View file

@ -482,9 +482,15 @@ simple manner.")
(?T (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))) ?d)
(?i (+ (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
(gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) ?d)
(?g gnus-tmp-group ?s)
(?g (if (boundp 'gnus-tmp-decoded-group)
gnus-tmp-decoded-group
gnus-tmp-group)
?s)
(?G gnus-tmp-qualified-group ?s)
(?c (gnus-short-group-name gnus-tmp-group) ?s)
(?c (gnus-short-group-name (if (boundp 'gnus-tmp-decoded-group)
gnus-tmp-decoded-group
gnus-tmp-group))
?s)
(?C gnus-tmp-comment ?s)
(?D gnus-tmp-newsgroup-description ?s)
(?o gnus-tmp-moderated ?c)
@ -1441,8 +1447,8 @@ if it is a string, only list groups matching REGEXP."
(point)
(prog1 (1+ (point))
;; Insert the text.
(let ((gnus-tmp-group (gnus-group-name-decode
gnus-tmp-group group-name-charset)))
(let ((gnus-tmp-decoded-group (gnus-group-name-decode
gnus-tmp-group group-name-charset)))
(eval gnus-group-line-format-spec)))
`(gnus-group ,(gnus-intern-safe gnus-tmp-group gnus-active-hashtb)
gnus-unread ,(if (numberp number)
@ -2244,7 +2250,7 @@ ADDRESS."
(nname (if method (gnus-group-prefixed-name name meth) name))
backend info)
(when (gnus-gethash nname gnus-newsrc-hashtb)
(error "Group %s already exists" nname))
(error "Group %s already exists" (gnus-group-decoded-name nname)))
;; Subscribe to the new group.
(gnus-group-change-level
(setq info (list t nname gnus-level-default-subscribed nil nil meth))
@ -2305,20 +2311,21 @@ be removed from the server, even when it's empty."
(unless (gnus-check-backend-function 'request-delete-group group)
(error "This back end does not support group deletion"))
(prog1
(if (and (not no-prompt)
(not (gnus-yes-or-no-p
(format
"Do you really want to delete %s%s? "
group (if force " and all its contents" "")))))
() ; Whew!
(gnus-message 6 "Deleting group %s..." group)
(if (not (gnus-request-delete-group group force))
(gnus-error 3 "Couldn't delete group %s" group)
(gnus-message 6 "Deleting group %s...done" group)
(gnus-group-goto-group group)
(gnus-group-kill-group 1 t)
(gnus-sethash group nil gnus-active-hashtb)
t))
(let ((group-decoded (gnus-group-decoded-name group)))
(if (and (not no-prompt)
(not (gnus-yes-or-no-p
(format
"Do you really want to delete %s%s? "
group-decoded (if force " and all its contents" "")))))
() ; Whew!
(gnus-message 6 "Deleting group %s..." group-decoded)
(if (not (gnus-request-delete-group group force))
(gnus-error 3 "Couldn't delete group %s" group-decoded)
(gnus-message 6 "Deleting group %s...done" group-decoded)
(gnus-group-goto-group group)
(gnus-group-kill-group 1 t)
(gnus-sethash group nil gnus-active-hashtb)
t)))
(gnus-group-position-point)))
(defun gnus-group-rename-group (group new-name)
@ -2588,16 +2595,26 @@ If there is, use Gnus to create an nnrss group"
(setq url (read-from-minibuffer "URL to Search for RSS: ")))
(let ((feedinfo (nnrss-discover-feed url)))
(if feedinfo
(let ((title (read-from-minibuffer "Title: "
(cdr (assoc 'title
feedinfo))))
(let ((title (gnus-newsgroup-savable-name
(read-from-minibuffer "Title: "
(gnus-newsgroup-savable-name
(or (cdr (assoc 'title
feedinfo))
"")))))
(desc (read-from-minibuffer "Description: "
(cdr (assoc 'description
feedinfo))))
(href (cdr (assoc 'href feedinfo))))
(push (list title href desc)
nnrss-group-alist)
(gnus-group-make-group title '(nnrss ""))
(href (cdr (assoc 'href feedinfo)))
(encodable (mm-coding-system-p 'utf-8)))
(when encodable
;; Unify non-ASCII text.
(setq title (mm-decode-coding-string
(mm-encode-coding-string title 'utf-8) 'utf-8)))
(gnus-group-make-group (if encodable
(mm-encode-coding-string title 'utf-8)
title)
'(nnrss ""))
(push (list title href desc) nnrss-group-alist)
(nnrss-save-server-data nil))
(error "No feeds found for %s" url))))
@ -3101,7 +3118,7 @@ up is returned."
"Do you really want to mark all articles in %s as read? "
"Mark all unread articles in %s as read? ")
(if (= (length groups) 1)
(car groups)
(gnus-group-decoded-name (car groups))
(format "these %d groups" (length groups)))))))
n
(while (setq group (pop groups))
@ -3179,7 +3196,8 @@ Uses the process/prefix convention."
(defun gnus-group-expire-articles-1 (group)
(when (gnus-check-backend-function 'request-expire-articles group)
(gnus-message 6 "Expiring articles in %s..." group)
(gnus-message 6 "Expiring articles in %s..."
(gnus-group-decoded-name group))
(let* ((info (gnus-get-info group))
(expirable (if (gnus-group-total-expirable-p group)
(cons nil (gnus-list-of-read-articles group))
@ -3204,7 +3222,8 @@ Uses the process/prefix convention."
(gnus-request-expire-articles
(gnus-uncompress-sequence (cdr expirable)) group))))
(gnus-close-group group))
(gnus-message 6 "Expiring articles in %s...done" group)
(gnus-message 6 "Expiring articles in %s...done"
(gnus-group-decoded-name group))
;; Return the list of un-expired articles.
(cdr expirable))))
@ -3243,7 +3262,8 @@ Uses the process/prefix convention."
(while (setq group (pop groups))
(gnus-group-remove-mark group)
(gnus-message 6 "Changed level of %s from %d to %d"
group (or (gnus-group-group-level) gnus-level-killed)
(gnus-group-decoded-name group)
(or (gnus-group-group-level) gnus-level-killed)
level)
(gnus-group-change-level
group level (or (gnus-group-group-level) gnus-level-killed))
@ -3392,7 +3412,7 @@ of groups killed."
gnus-list-of-killed-groups))
(gnus-group-change-level
(if entry entry group) gnus-level-killed (if entry nil level))
(message "Killed group %s" group))
(message "Killed group %s" (gnus-group-decoded-name group)))
;; If there are lots and lots of groups to be killed, we use
;; this thing instead.
(dolist (group (nreverse groups))

View file

@ -1,5 +1,5 @@
;;; gnus-spec.el --- format spec functions for Gnus
;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
;; Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
@ -196,6 +196,13 @@ Return a list of updated types."
(not (equal emacs-version
(cdr (assq 'version gnus-format-specs)))))
(setq gnus-format-specs nil))
;; Flush the group format spec cache if it doesn't support decoded
;; group names.
(when (memq 'group types)
(let ((spec (assq 'group gnus-format-specs)))
(unless (string-match " gnus-tmp-decoded-group[ )]"
(gnus-prin1-to-string (nth 2 spec)))
(setq gnus-format-specs (delq spec gnus-format-specs)))))
;; Go through all the formats and see whether they need updating.
(let (new-format entry type val updated)

View file

@ -7254,11 +7254,12 @@ If BACKWARD, the previous article is selected instead of the next."
(if (and group
(not (gnus-ephemeral-group-p gnus-newsgroup-name)))
(format " (Type %s for %s [%s])"
(single-key-description cmd) group
(single-key-description cmd)
(gnus-group-decoded-name group)
(car (gnus-gethash group gnus-newsrc-hashtb)))
(format " (Type %s to exit %s)"
(single-key-description cmd)
gnus-newsgroup-name))))
(gnus-group-decoded-name gnus-newsgroup-name)))))
;; Confirm auto selection.
(setq key (car (setq keve (gnus-read-event-char prompt)))
ended t)

View file

@ -59,7 +59,7 @@
'((wget "wget" "--user-agent=mm-url" "-q" "-O" "-")
(w3m "w3m" "-dump_source")
(lynx "lynx" "-source")
(curl "curl")))
(curl "curl" "--silent")))
(defcustom mm-url-program
(cond

View file

@ -57,9 +57,11 @@
mm-mime-mule-charset-alist)
nil t))))
(subst-char-in-string
. (lambda (from to string) ;; stolen (and renamed) from nnheader.el
"Replace characters in STRING from FROM to TO."
(let ((string (substring string 0)) ;Copy string.
. (lambda (from to string &optional inplace)
;; stolen (and renamed) from nnheader.el
"Replace characters in STRING from FROM to TO.
Unless optional argument INPLACE is non-nil, return a new string."
(let ((string (if inplace string (copy-sequence string)))
(len (length string))
(idx 0))
;; Replace all occurrences of FROM with TO.
@ -153,7 +155,7 @@ In XEmacs, also return non-nil if CS is a coding system object.
If CS is available, return CS itself in Emacs, and return a coding
system object in XEmacs."
(if (fboundp 'find-coding-system)
(find-coding-system cs)
(and cs (find-coding-system cs))
(if (fboundp 'coding-system-p)
(when (coding-system-p cs)
cs)

View file

@ -1,5 +1,5 @@
;;; nnrss.el --- interfacing with RSS
;; Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
;; Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: RSS
@ -36,9 +36,11 @@
(require 'time-date)
(require 'rfc2231)
(require 'mm-url)
(require 'rfc2047)
(require 'mml)
(eval-when-compile
(ignore-errors
(require 'xml)))
(require 'xml)))
(eval '(require 'xml))
(nnoo-declare nnrss)
@ -75,20 +77,32 @@ To use the description in headers, put this name into `nnmail-extra-headers'.")
(defvar nnrss-content-function nil
"A function which is called in `nnrss-request-article'.
The arguments are (ENTRY GROUP ARTICLE).
ENTRY is the record of the current headline. GROUP is the group name.
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))
"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
for decoding when the cdr that the data specify is not available.")
(nnoo-define-basics nnrss)
;;; Interface functions
(eval-when-compile
(defmacro nnrss-string-as-multibyte (string)
(if (featurep 'xemacs)
string
`(string-as-multibyte ,string))))
(defsubst nnrss-format-string (string)
(gnus-replace-in-string string " *\n *" " "))
(defun nnrss-decode-group-name (group)
(if (and group (mm-coding-system-p 'utf-8))
(setq group (mm-decode-coding-string group 'utf-8))
group))
(deffoo nnrss-retrieve-headers (articles &optional group server fetch-old)
(setq group (nnrss-decode-group-name group))
(nnrss-possibly-change-group group server)
(let (e)
(save-excursion
@ -97,21 +111,26 @@ ARTICLE is the article number of the current headline.")
(dolist (article articles)
(if (setq e (assq article nnrss-group-data))
(insert (number-to-string (car e)) "\t" ;; number
(if (nth 3 e)
(nnrss-format-string (nth 3 e)) "")
"\t" ;; subject
(if (nth 4 e)
(nnrss-format-string (nth 4 e))
"(nobody)")
"\t" ;;from
;; subject
(or (nth 3 e) "")
"\t"
;; from
(or (nth 4 e) "(nobody)")
"\t"
;; date
(or (nth 5 e) "")
"\t" ;; date
"\t"
;; id
(format "<%d@%s.nnrss>" (car e) group)
"\t" ;; id
"\t" ;; refs
"-1" "\t" ;; chars
"-1" "\t" ;; lines
"" "\t" ;; Xref
"\t"
;; refs
"\t"
;; chars
"-1" "\t"
;; lines
"-1" "\t"
;; Xref
"" "\t"
(if (and (nth 6 e)
(memq nnrss-description-field
nnmail-extra-headers))
@ -132,69 +151,102 @@ ARTICLE is the article number of the current headline.")
'nov)
(deffoo nnrss-request-group (group &optional server dont-check)
(setq group (nnrss-decode-group-name group))
(nnheader-message 6 "nnrss: Requesting %s..." group)
(nnrss-possibly-change-group group server)
(if dont-check
t
(nnrss-check-group group server)
(nnheader-report 'nnrss "Opened group %s" group)
(nnheader-insert
"211 %d %d %d %s\n" nnrss-group-max nnrss-group-min nnrss-group-max
(prin1-to-string group)
t)))
(prog1
(if dont-check
t
(nnrss-check-group group server)
(nnheader-report 'nnrss "Opened group %s" group)
(nnheader-insert
"211 %d %d %d %s\n" nnrss-group-max nnrss-group-min nnrss-group-max
(prin1-to-string group)
t))
(nnheader-message 6 "nnrss: Requesting %s...done" group)))
(deffoo nnrss-close-group (group &optional server)
t)
(deffoo nnrss-request-article (article &optional group server buffer)
(setq group (nnrss-decode-group-name group))
(when (stringp article)
(setq article (if (string-match "\\`<\\([0-9]+\\)@" article)
(string-to-number (match-string 1 article))
0)))
(nnrss-possibly-change-group group server)
(let ((e (assq article nnrss-group-data))
(boundary "=-=-=-=-=-=-=-=-=-")
(nntp-server-buffer (or buffer nntp-server-buffer))
post err)
(when e
(catch 'error
(with-current-buffer nntp-server-buffer
(erase-buffer)
(goto-char (point-min))
(insert "Mime-Version: 1.0\nContent-Type: multipart/alternative; boundary=\"" boundary "\"\n")
(if group
(insert "Newsgroups: " group "\n"))
(if (nth 3 e)
(insert "Subject: " (nnrss-format-string (nth 3 e)) "\n"))
(if (nth 4 e)
(insert "From: " (nnrss-format-string (nth 4 e)) "\n"))
(if (nth 5 e)
(insert "Date: " (nnrss-format-string (nth 5 e)) "\n"))
(insert "Message-ID: " (format "<%d@%s.nnrss>" (car e) group) "\n")
(insert "\n")
(let ((text (if (nth 6 e)
(nnrss-string-as-multibyte (nth 6 e))))
(link (if (nth 2 e)
(nth 2 e))))
(insert "\n\n--" boundary "\nContent-Type: text/plain\n\n")
(let ((point (point)))
(if text
(progn (insert text)
(goto-char point)
(while (re-search-forward "\n" nil t)
(replace-match " "))
(goto-char (point-max))
(insert "\n\n")))
(if link
(insert link)))
(insert "\n\n--" boundary "\nContent-Type: text/html\n\n")
(let ((point (point)))
(if text
(progn (insert "<html><head></head><body>\n" text "\n</body></html>")
(goto-char point)
(while (re-search-forward "\n" nil t)
(replace-match " "))
(goto-char (point-max))
(insert "\n\n")))
(if link
(insert "<p><a href=\"" link "\">link</a></p>\n"))))
(if nnrss-content-function
(funcall nnrss-content-function e group article)))))
(with-current-buffer nntp-server-buffer
(erase-buffer)
(if group
(insert "Newsgroups: " group "\n"))
(if (nth 3 e)
(insert "Subject: " (nth 3 e) "\n"))
(if (nth 4 e)
(insert "From: " (nth 4 e) "\n"))
(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+"))
" ")))
(link (nth 2 e))
;; Enable encoding of Newsgroups header in XEmacs.
(default-enable-multibyte-characters t)
(rfc2047-header-encoding-alist
(if (mm-coding-system-p 'utf-8)
(cons '("Newsgroups" . utf-8)
rfc2047-header-encoding-alist)
rfc2047-header-encoding-alist))
rfc2047-encode-encoded-words body)
(when (or text link)
(insert "\n")
(insert "<#multipart type=alternative>\n"
"<#part type=\"text/plain\">\n")
(setq body (point))
(if text
(progn
(insert text "\n")
(when link
(insert "\n" link "\n")))
(when link
(insert link "\n")))
(setq body (buffer-substring body (point)))
(insert "<#/part>\n"
"<#part type=\"text/html\">\n"
"<html><head></head><body>\n")
(when text
(insert text "\n"))
(when link
(insert "<p><a href=\"" link "\">link</a></p>\n"))
(insert "</body></html>\n"
"<#/part>\n"
"<#/multipart>\n"))
(condition-case nil
(mml-to-mime)
(error
(erase-buffer)
(insert header
"Content-Type: text/plain; charset=gnus-decoded\n"
"Content-Transfer-Encoding: 8bit\n\n"
body)
(nnheader-message
3 "Warning - there might be invalid characters"))))
(goto-char (point-min))
(search-forward "\n\n")
(forward-line -1)
(insert (format "Message-ID: <%d@%s.nnrss>\n"
(car e)
(let ((rfc2047-encoding-type 'mime)
rfc2047-encode-max-chars)
(rfc2047-encode-string
(gnus-replace-in-string group "[\t\n ]+" "_")))))
(when nnrss-content-function
(funcall nnrss-content-function e group article))))
(cond
(err
(nnheader-report 'nnrss err))
@ -217,6 +269,7 @@ ARTICLE is the article number of the current headline.")
(deffoo nnrss-request-expire-articles
(articles group &optional server force)
(setq group (nnrss-decode-group-name group))
(nnrss-possibly-change-group group server)
(let (e days not-expirable changed)
(dolist (art articles)
@ -234,18 +287,18 @@ ARTICLE is the article number of the current headline.")
not-expirable))
(deffoo nnrss-request-delete-group (group &optional force server)
(setq group (nnrss-decode-group-name group))
(nnrss-possibly-change-group group server)
(let (elem)
;; There may be two or more entries in `nnrss-group-alist' since
;; this function didn't delete them formerly.
(while (setq elem (assoc group nnrss-group-alist))
(setq nnrss-group-alist (delq elem nnrss-group-alist))))
(setq nnrss-server-data
(delq (assoc group nnrss-server-data) nnrss-server-data))
(nnrss-save-server-data server)
(let ((file (expand-file-name
(nnrss-translate-file-chars
(concat group (and server
(not (equal server ""))
"-")
server ".el")) nnrss-directory)))
(ignore-errors
(delete-file file)))
(ignore-errors
(delete-file (nnrss-make-filename group server)))
t)
(deffoo nnrss-request-list-newsgroups (&optional server)
@ -262,34 +315,67 @@ ARTICLE is the article number of the current headline.")
;;; Internal functions
(eval-when-compile (defun xml-rpc-method-call (&rest args)))
(defun nnrss-get-encoding ()
"Return an encoding attribute specified in the current xml contents.
If `nnrss-compatible-encoding-alist' specifies the compatible encoding,
it is used instead. If the xml contents doesn't specify the encoding,
return `utf-8' which is the default encoding for xml if it is available,
otherwise return nil."
(goto-char (point-min))
(if (re-search-forward
"<\\?[^>]*encoding=\\(\"\\([^\">]+\\)\"\\|'\\([^'>]+\\)'\\)"
nil t)
(let ((encoding (intern (downcase (or (match-string 2)
(match-string 3))))))
(or
(mm-coding-system-p (cdr (assq encoding
nnrss-compatible-encoding-alist)))
(mm-coding-system-p encoding)
(mm-coding-system-p (car (rassq encoding
nnrss-compatible-encoding-alist)))))
(mm-coding-system-p 'utf-8)))
(defun nnrss-fetch (url &optional local)
"Fetch the url and put it in a the expected lisp structure."
(with-temp-buffer
;some CVS versions of url.el need this to close the connection quickly
(let* (xmlform htmlform)
"Fetch URL and put it in a the expected Lisp structure."
(mm-with-unibyte-buffer
;;some CVS versions of url.el need this to close the connection quickly
(let (cs xmlform htmlform)
;; bit o' work necessary for w3 pre-cvs and post-cvs
(if local
(let ((coding-system-for-read 'binary))
(insert-file-contents url))
(mm-url-insert url))
;; FIXME: shouldn't binding `coding-system-for-read' be moved
;; to `mm-url-insert'?
(let ((coding-system-for-read 'binary))
(mm-url-insert url)))
(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))
(goto-char (point-min))
;; Because xml-parse-region can't deal with anything that isn't
;; xml and w3-parse-buffer can't deal with some xml, we have to
;; parse with xml-parse-region first and, if that fails, parse
;; with w3-parse-buffer. Yuck. Eventually, someone should find out
;; why w3-parse-buffer fails to parse some well-formed xml and
;; fix it.
;; Because xml-parse-region can't deal with anything that isn't
;; xml and w3-parse-buffer can't deal with some xml, we have to
;; parse with xml-parse-region first and, if that fails, parse
;; with w3-parse-buffer. Yuck. Eventually, someone should find out
;; why w3-parse-buffer fails to parse some well-formed xml and
;; fix it.
(condition-case err
(setq xmlform (xml-parse-region (point-min) (point-max)))
(error (if (fboundp 'w3-parse-buffer)
(setq htmlform (caddar (w3-parse-buffer
(current-buffer))))
(message "nnrss: Not valid XML and w3 parse not available (%s)"
url))))
(if htmlform
htmlform
xmlform))))
(condition-case err1
(setq xmlform (xml-parse-region (point-min) (point-max)))
(error
(condition-case err2
(setq htmlform (caddar (w3-parse-buffer
(current-buffer))))
(error
(message "\
nnrss: %s: Not valid XML %s and w3-parse doesn't work %s"
url err1 err2)))))
(if htmlform
htmlform
xmlform))))
(defun nnrss-possibly-change-group (&optional group server)
(when (and server
@ -302,9 +388,9 @@ ARTICLE is the article number of the current headline.")
(defvar nnrss-extra-categories '(nnrss-snarf-moreover-categories))
(defun nnrss-generate-active ()
(if (y-or-n-p "fetch extra categories? ")
(dolist (func nnrss-extra-categories)
(funcall func)))
(when (y-or-n-p "Fetch extra categories? ")
(dolist (func nnrss-extra-categories)
(funcall func)))
(save-excursion
(set-buffer nntp-server-buffer)
(erase-buffer)
@ -318,41 +404,26 @@ ARTICLE is the article number of the current headline.")
(defun nnrss-read-server-data (server)
(setq nnrss-server-data nil)
(let ((file (expand-file-name
(nnrss-translate-file-chars
(concat "nnrss" (and server
(not (equal server ""))
"-")
server
".el"))
nnrss-directory)))
(let ((file (nnrss-make-filename "nnrss" server)))
(when (file-exists-p file)
(with-temp-buffer
(let ((coding-system-for-read 'binary)
emacs-lisp-mode-hook)
;; 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))
(insert-file-contents file)
(emacs-lisp-mode)
(goto-char (point-min))
(eval-buffer))))))
(eval-region (point-min) (point-max)))))))
(defun nnrss-save-server-data (server)
(gnus-make-directory nnrss-directory)
(let ((file (expand-file-name
(nnrss-translate-file-chars
(concat "nnrss" (and server
(not (equal server ""))
"-")
server ".el"))
nnrss-directory)))
(let ((coding-system-for-write 'binary)
print-level print-length)
(with-temp-file file
(insert "(setq nnrss-group-alist '"
(prin1-to-string nnrss-group-alist)
")\n")
(insert "(setq nnrss-server-data '"
(prin1-to-string nnrss-server-data)
")\n")))))
(let ((coding-system-for-write nnrss-file-coding-system)
(file-name-coding-system nnmail-pathname-coding-system))
(with-temp-file (nnrss-make-filename "nnrss" server)
(insert (format ";; -*- coding: %s; -*-\n"
nnrss-file-coding-system))
(gnus-prin1 `(setq nnrss-group-alist ',nnrss-group-alist))
(insert "\n")
(gnus-prin1 `(setq nnrss-server-data ',nnrss-server-data)))))
(defun nnrss-read-group-data (group server)
(setq nnrss-group-data nil)
@ -360,43 +431,50 @@ ARTICLE is the article number of the current headline.")
(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 (expand-file-name
(nnrss-translate-file-chars
(concat group (and server
(not (equal server ""))
"-")
server ".el"))
nnrss-directory)))
(let ((file (nnrss-make-filename group server)))
(when (file-exists-p file)
(with-temp-buffer
(let ((coding-system-for-read 'binary)
emacs-lisp-mode-hook)
;; 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))
(insert-file-contents file)
(emacs-lisp-mode)
(goto-char (point-min))
(eval-buffer)))
(eval-region (point-min) (point-max))))
(dolist (e nnrss-group-data)
(gnus-sethash (nth 2 e) e nnrss-group-hashtb)
(if (and (car e) (> nnrss-group-min (car e)))
(setq nnrss-group-min (car e)))
(if (and (car e) (< nnrss-group-max (car e)))
(setq nnrss-group-max (car e)))))))
(gnus-sethash (or (nth 2 e) (nth 6 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)))
(setq nnrss-group-max (car e)))))))
(defun nnrss-save-group-data (group server)
(gnus-make-directory nnrss-directory)
(let ((file (expand-file-name
(nnrss-translate-file-chars
(concat group (and server
(not (equal server ""))
"-")
server ".el"))
nnrss-directory)))
(let ((coding-system-for-write 'binary)
print-level print-length)
(with-temp-file file
(insert "(setq nnrss-group-data '"
(prin1-to-string nnrss-group-data)
")\n")))))
(let ((coding-system-for-write nnrss-file-coding-system)
(file-name-coding-system nnmail-pathname-coding-system))
(with-temp-file (nnrss-make-filename group server)
(insert (format ";; -*- coding: %s; -*-\n"
nnrss-file-coding-system))
(gnus-prin1 `(setq nnrss-group-data ',nnrss-group-data)))))
(defun nnrss-make-filename (name server)
(expand-file-name
(nnrss-translate-file-chars
(concat name
(and server
(not (equal server ""))
"-")
server
".el"))
nnrss-directory))
(gnus-add-shutdown 'nnrss-close 'gnus)
(defun nnrss-close ()
"Clear internal nnrss variables."
(setq nnrss-group-data nil
nnrss-server-data nil
nnrss-group-hashtb nil
nnrss-group-alist nil))
;;; URL interface
@ -407,15 +485,36 @@ ARTICLE is the article number of the current headline.")
(mm-with-unibyte-current-buffer
(mm-url-insert url)))
(defun nnrss-decode-entities-unibyte-string (string)
(defun nnrss-decode-entities-string (string)
(if string
(mm-with-unibyte-buffer
(mm-with-multibyte-buffer
(insert string)
(mm-url-decode-entities-nbsp)
(buffer-string))))
(defalias 'nnrss-insert 'nnrss-insert-w3)
(defun nnrss-mime-encode-string (string)
(mm-with-multibyte-buffer
(insert string)
(mm-url-decode-entities-nbsp)
(goto-char (point-min))
(while (re-search-forward "[\t\n ]+" nil t)
(replace-match " "))
(goto-char (point-min))
(skip-chars-forward " ")
(delete-region (point-min) (point))
(goto-char (point-max))
(skip-chars-forward " ")
(delete-region (point) (point-max))
(let ((rfc2047-encoding-type 'mime)
rfc2047-encode-max-chars)
(rfc2047-encode-region (point-min) (point-max)))
(goto-char (point-min))
(while (search-forward "\n" nil t)
(delete-backward-char 1))
(buffer-string)))
;;; Snarf functions
(defun nnrss-check-group (group server)
@ -431,11 +530,11 @@ ARTICLE is the article number of the current headline.")
(second (assoc group nnrss-group-alist))))
(unless url
(setq url
(cdr
(assoc 'href
(nnrss-discover-feed
(read-string
(format "URL to search for %s: " group) "http://")))))
(cdr
(assoc 'href
(nnrss-discover-feed
(read-string
(format "URL to search for %s: " group) "http://")))))
(let ((pair (assoc group nnrss-server-data)))
(if pair
(setcdr (cdr pair) (list url))
@ -451,12 +550,16 @@ ARTICLE is the article number of the current headline.")
content-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/modules/content/"))
(dolist (item (nreverse (nnrss-find-el (intern (concat rss-ns "item")) xml)))
(when (and (listp item)
(eq (intern (concat rss-ns "item")) (car item))
(setq url (nnrss-decode-entities-unibyte-string
(nnrss-node-text rss-ns 'link (cddr item))))
(not (gnus-gethash url nnrss-group-hashtb)))
(string= (concat rss-ns "item") (car item))
(if (setq url (nnrss-decode-entities-string
(nnrss-node-text rss-ns 'link (cddr item))))
(not (gnus-gethash url nnrss-group-hashtb))
(setq extra (or (nnrss-node-text content-ns 'encoded item)
(nnrss-node-text rss-ns 'description item)))
(not (gnus-gethash extra nnrss-group-hashtb))))
(setq subject (nnrss-node-text rss-ns 'title item))
(setq extra (or (nnrss-node-text content-ns 'encoded item)
(setq extra (or extra
(nnrss-node-text content-ns 'encoded item)
(nnrss-node-text rss-ns 'description item)))
(setq author (or (nnrss-node-text rss-ns 'author item)
(nnrss-node-text dc-ns 'creator item)
@ -469,13 +572,14 @@ ARTICLE is the article number of the current headline.")
(incf nnrss-group-max)
(current-time)
url
(and subject (nnrss-decode-entities-unibyte-string subject))
(and author (nnrss-decode-entities-unibyte-string author))
(and subject (nnrss-mime-encode-string subject))
(and author (nnrss-mime-encode-string author))
date
(and extra (nnrss-decode-entities-unibyte-string extra)))
(and extra (nnrss-decode-entities-string extra)))
nnrss-group-data)
(gnus-sethash url (car nnrss-group-data) nnrss-group-hashtb)
(setq changed t)))
(gnus-sethash (or url extra) t nnrss-group-hashtb)
(setq changed t))
(setq extra nil))
(when changed
(nnrss-save-group-data group server)
(let ((pair (assoc group nnrss-server-data)))
@ -484,6 +588,45 @@ ARTICLE is the article number of the current headline.")
(push (list group nnrss-group-max) nnrss-server-data)))
(nnrss-save-server-data server))))
(defun nnrss-opml-import (opml-file)
"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)))))
(nnrss-find-el 'outline
(progn
(find-file opml-file)
(xml-parse-region (point-min)
(point-max))))))
(defun nnrss-opml-export ()
"OPML subscription export.
Export subscriptions to a buffer in OPML Format."
(interactive)
(with-current-buffer (get-buffer-create "*OPML Export*")
(mm-set-buffer-file-coding-system 'utf-8)
(insert "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<!-- OPML generated by Emacs Gnus' nnrss.el -->\n"
"<opml version=\"1.1\">\n"
" <head>\n"
" <title>mySubscriptions</title>\n"
" <dateCreated>" (format-time-string "%a, %d %b %Y %T %z")
"</dateCreated>\n"
" <ownerEmail>" user-mail-address "</ownerEmail>\n"
" <ownerName>" (user-full-name) "</ownerName>\n"
" </head>\n"
" <body>\n")
(dolist (sub nnrss-group-alist)
(insert " <outline text=\"" (car sub)
"\" xmlUrl=\"" (cadr sub) "\"/>\n"))
(insert " </body>\n"
"</opml>\n"))
(pop-to-buffer "*OPML Export*")
(when (fboundp 'sgml-mode)
(sgml-mode)))
(defun nnrss-generate-download-script ()
"Generate a download script in the current buffer.
It is useful when `(setq nnrss-use-local t)'."
@ -530,9 +673,6 @@ It is useful when `(setq nnrss-use-local t)'."
(if changed
(nnrss-save-server-data ""))))
(defun nnrss-format-string (string)
(gnus-replace-in-string (nnrss-string-as-multibyte string) " *\n *" " "))
(defun nnrss-node-text (namespace local-name element)
(let* ((node (assq (intern (concat namespace (symbol-name local-name)))
element))
@ -551,56 +691,59 @@ It is useful when `(setq nnrss-use-local t)'."
node))
(defun nnrss-find-el (tag data &optional found-list)
"Find the all matching elements in the data. Careful with this on
large documents!"
(if (listp data)
(mapcar (lambda (bit)
(if (car-safe bit)
(progn (if (equal tag (car bit))
(setq found-list
(append found-list
(list bit))))
(if (and (listp (car-safe (caddr bit)))
(not (stringp (caddr bit))))
(setq found-list
(append found-list
(nnrss-find-el
tag (caddr bit))))
(setq found-list
(append found-list
(nnrss-find-el
tag (cddr bit))))))))
data))
"Find the all matching elements in the data.
Careful with this on large documents!"
(when (consp data)
(dolist (bit data)
(when (car-safe bit)
(when (equal tag (car bit))
;; Old xml.el may return a list of string.
(when (and (consp (caddr bit))
(stringp (caaddr bit)))
(setcar (cddr bit) (caaddr bit)))
(setq found-list
(append found-list
(list bit))))
(if (and (consp (car-safe (caddr bit)))
(not (stringp (caddr bit))))
(setq found-list
(append found-list
(nnrss-find-el
tag (caddr bit))))
(setq found-list
(append found-list
(nnrss-find-el
tag (cddr bit))))))))
found-list)
(defun nnrss-rsslink-p (el)
"Test if the element we are handed is an RSS autodiscovery link."
(and (eq (car-safe el) 'link)
(string-equal (cdr (assoc 'rel (cadr el))) "alternate")
(or (string-equal (cdr (assoc 'type (cadr el)))
(or (string-equal (cdr (assoc 'type (cadr el)))
"application/rss+xml")
(string-equal (cdr (assoc 'type (cadr el))) "text/xml"))))
(defun nnrss-get-rsslinks (data)
"Extract the <link> elements that are links to RSS from the parsed data."
(delq nil (mapcar
(delq nil (mapcar
(lambda (el)
(if (nnrss-rsslink-p el) el))
(nnrss-find-el 'link data))))
(defun nnrss-extract-hrefs (data)
"Recursively extract hrefs from a page's source. DATA should be
the output of xml-parse-region or w3-parse-buffer."
"Recursively extract hrefs from a page's source.
DATA should be the output of `xml-parse-region' or
`w3-parse-buffer'."
(mapcar (lambda (ahref)
(cdr (assoc 'href (cadr ahref))))
(nnrss-find-el 'a data)))
(defmacro nnrss-match-macro (base-uri item
onsite-list offsite-list)
(defmacro nnrss-match-macro (base-uri item onsite-list offsite-list)
`(cond ((or (string-match (concat "^" ,base-uri) ,item)
(not (string-match "://" ,item)))
(setq ,onsite-list (append ,onsite-list (list ,item))))
(t (setq ,offsite-list (append ,offsite-list (list ,item))))))
(not (string-match "://" ,item)))
(setq ,onsite-list (append ,onsite-list (list ,item))))
(t (setq ,offsite-list (append ,offsite-list (list ,item))))))
(defun nnrss-order-hrefs (base-uri hrefs)
"Given a list of hrefs, sort them using the following priorities:
@ -615,29 +758,28 @@ whether they are `offsite' or `onsite'."
(let (rss-onsite-end rdf-onsite-end xml-onsite-end
rss-onsite-in rdf-onsite-in xml-onsite-in
rss-offsite-end rdf-offsite-end xml-offsite-end
rss-offsite-in rdf-offsite-in xml-offsite-in)
(mapcar (lambda (href)
(if (not (null href))
(cond ((string-match "\\.rss$" href)
(nnrss-match-macro
base-uri href rss-onsite-end rss-offsite-end))
((string-match "\\.rdf$" href)
(nnrss-match-macro
base-uri href rdf-onsite-end rdf-offsite-end))
((string-match "\\.xml$" href)
(nnrss-match-macro
base-uri href xml-onsite-end xml-offsite-end))
((string-match "rss" href)
(nnrss-match-macro
base-uri href rss-onsite-in rss-offsite-in))
((string-match "rdf" href)
(nnrss-match-macro
base-uri href rdf-onsite-in rdf-offsite-in))
((string-match "xml" href)
(nnrss-match-macro
base-uri href xml-onsite-in xml-offsite-in)))))
hrefs)
(append
rss-offsite-in rdf-offsite-in xml-offsite-in)
(dolist (href hrefs)
(cond ((null href))
((string-match "\\.rss$" href)
(nnrss-match-macro
base-uri href rss-onsite-end rss-offsite-end))
((string-match "\\.rdf$" href)
(nnrss-match-macro
base-uri href rdf-onsite-end rdf-offsite-end))
((string-match "\\.xml$" href)
(nnrss-match-macro
base-uri href xml-onsite-end xml-offsite-end))
((string-match "rss" href)
(nnrss-match-macro
base-uri href rss-onsite-in rss-offsite-in))
((string-match "rdf" href)
(nnrss-match-macro
base-uri href rdf-onsite-in rdf-offsite-in))
((string-match "xml" href)
(nnrss-match-macro
base-uri href xml-onsite-in xml-offsite-in))))
(append
rss-onsite-end rdf-onsite-end xml-onsite-end
rss-onsite-in rdf-onsite-in xml-onsite-in
rss-offsite-end rdf-offsite-end xml-offsite-end
@ -670,23 +812,23 @@ whether they are `offsite' or `onsite'."
;; - offsite links containing any of the above
(let* ((base-uri (progn (string-match ".*://[^/]+/?" url)
(match-string 0 url)))
(hrefs (nnrss-order-hrefs
(hrefs (nnrss-order-hrefs
base-uri (nnrss-extract-hrefs parsed-page)))
(rss-link nil))
(while (and (eq rss-link nil) (not (eq hrefs nil)))
(let ((href-data (nnrss-fetch (car hrefs))))
(if (nnrss-rss-p href-data)
(let* ((rss-ns (nnrss-get-namespace-prefix href-data "http://purl.org/rss/1.0/")))
(setq rss-link (nnrss-rss-title-description
rss-ns href-data (car hrefs))))
(setq hrefs (cdr hrefs)))))
(if rss-link rss-link
(while (and (eq rss-link nil) (not (eq hrefs nil)))
(let ((href-data (nnrss-fetch (car hrefs))))
(if (nnrss-rss-p href-data)
(let* ((rss-ns (nnrss-get-namespace-prefix href-data "http://purl.org/rss/1.0/")))
(setq rss-link (nnrss-rss-title-description
rss-ns href-data (car hrefs))))
(setq hrefs (cdr hrefs)))))
(if rss-link rss-link
;; 4. check syndic8
(nnrss-find-rss-via-syndic8 url))))))))
(nnrss-find-rss-via-syndic8 url))))))))
(defun nnrss-find-rss-via-syndic8 (url)
"query syndic8 for the rss feeds it has for the url."
"Query syndic8 for the rss feeds it has for URL."
(if (not (locate-library "xml-rpc"))
(progn
(message "XML-RPC is not available... not checking Syndic8.")
@ -697,22 +839,22 @@ whether they are `offsite' or `onsite'."
'syndic8.FindSites
url)))
(when feedid
(let* ((feedinfo (xml-rpc-method-call
(let* ((feedinfo (xml-rpc-method-call
"http://www.syndic8.com/xmlrpc.php"
'syndic8.GetFeedInfo
feedid))
(urllist
(delq nil
(delq nil
(mapcar
(lambda (listinfo)
(if (string-equal
(if (string-equal
(cdr (assoc "status" listinfo))
"Syndicated")
(cons
(cdr (assoc "sitename" listinfo))
(list
(cons 'title
(cdr (assoc
(cdr (assoc
"sitename" listinfo)))
(cons 'href
(cdr (assoc
@ -721,20 +863,20 @@ whether they are `offsite' or `onsite'."
(if (not (> (length urllist) 1))
(cdar urllist)
(let ((completion-ignore-case t)
(selection
(selection
(mapcar (lambda (listinfo)
(cons (cdr (assoc "sitename" listinfo))
(string-to-int
(cons (cdr (assoc "sitename" listinfo))
(string-to-int
(cdr (assoc "feedid" listinfo)))))
feedinfo)))
(cdr (assoc
(cdr (assoc
(completing-read
"Multiple feeds found. Select one: "
selection nil t) urllist)))))))))
(defun nnrss-rss-p (data)
"Test if data is an RSS feed. Simply ensures that the first
element is rss or rdf."
"Test if DATA is an RSS feed.
Simply ensures that the first element is rss or rdf."
(or (eq (caar data) 'rss)
(eq (caar data) 'rdf:RDF)))
@ -755,13 +897,13 @@ element is rss or rdf."
that gives the URI for which you want to retrieve the namespace
prefix), return the prefix."
(let* ((prefix (car (rassoc uri (cadar el))))
(nslist (if prefix
(nslist (if prefix
(split-string (symbol-name prefix) ":")))
(ns (cond ((eq (length nslist) 1) ; no prefix given
"")
((eq (length nslist) 2) ; extract prefix
(cadr nslist)))))
(if (and ns (not (eq ns "")))
(if (and ns (not (string= ns "")))
(concat ns ":")
ns)))

View file

@ -1,3 +1,7 @@
2005-04-06 Katsumi Yamaoka <yamaoka@jpl.org>
* gnus.texi (RSS): Addition.
2005-04-09 Luc Teirlinck <teirllm@auburn.edu>
* display.texi (Useless Whitespace): `indicate-unused-lines' is

View file

@ -15873,14 +15873,45 @@ changes to a wiki (e.g. @url{http://cliki.net/recent-changes.rdf}).
@acronym{RSS} has a quite regular and nice interface, and it's
possible to get the information Gnus needs to keep groups updated.
Note: you had better use Emacs which supports the @code{utf-8} coding
system because @acronym{RSS} uses UTF-8 for encoding non-@acronym{ASCII}
text by default. It is also used by default for non-@acronym{ASCII}
group names.
@kindex G R (Summary)
Use @kbd{G R} from the summary buffer to subscribe to a feed---you
will be prompted for the location of the feed.
Use @kbd{G R} from the summary buffer to subscribe to a feed---you will
be prompted for the location, the title and the description of the feed.
The title, which allows any characters, will be used for the group name
and the name of the group data file. The description can be omitted.
An easy way to get started with @code{nnrss} is to say something like
the following in the group buffer: @kbd{B nnrss RET RET y}, then
subscribe to groups.
The @code{nnrss} back end saves the group data file in
@code{nnrss-directory} (see below) for each @code{nnrss} group. File
names containing non-@acronym{ASCII} characters will be encoded by the
coding system specified with the @code{nnmail-pathname-coding-system}
variable. If it is @code{nil}, in Emacs the coding system defaults to
the value of @code{default-file-name-coding-system}. If you are using
XEmacs and want to use non-@acronym{ASCII} group names, you should set
the value for the @code{nnmail-pathname-coding-system} variable properly.
@cindex OPML
You can also use the following commands to import and export your
subscriptions from a file in @acronym{OPML} format (Outline Processor
Markup Language).
@defun nnrss-opml-import file
Prompt for an @acronym{OPML} file, and subscribe to each feed in the
file.
@end defun
@defun nnrss-opml-export
Write your current @acronym{RSS} subscriptions to a buffer in
@acronym{OPML} format.
@end defun
The following @code{nnrss} variables can be altered:
@table @code
@ -15889,6 +15920,13 @@ The following @code{nnrss} variables can be altered:
The directory where @code{nnrss} stores its files. The default is
@file{~/News/rss/}.
@item nnrss-file-coding-system
@vindex nnrss-file-coding-system
The coding system used when reading and writing the @code{nnrss} groups
data files. The default is the value of
@code{mm-universal-coding-system} (which defaults to @code{emacs-mule}
in Emacs or @code{escape-quoted} in XEmacs).
@item nnrss-use-local
@vindex nnrss-use-local
@findex nnrss-generate-download-script