Switch to recommended form of GPLv3 permissions notice.
[bpt/emacs.git] / lisp / gnus / nnultimate.el
CommitLineData
23f87bed
MB
1;;; nnultimate.el --- interfacing with the Ultimate Bulletin Board system
2
e84b4b86 3;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
e3fe4da0 4;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
c113de23
GM
5
6;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
7;; Keywords: news
8
9;; This file is part of GNU Emacs.
10
5e809f55 11;; GNU Emacs is free software: you can redistribute it and/or modify
c113de23 12;; it under the terms of the GNU General Public License as published by
5e809f55
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
c113de23
GM
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
5e809f55 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
c113de23
GM
23
24;;; Commentary:
25
26;; Note: You need to have `url' and `w3' installed for this
27;; backend to work.
28
29;;; Code:
30
31(eval-when-compile (require 'cl))
32
33(require 'nnoo)
34(require 'message)
35(require 'gnus-util)
36(require 'gnus)
37(require 'nnmail)
38(require 'mm-util)
23f87bed
MB
39(require 'mm-url)
40(require 'nnweb)
498063ec 41(require 'parse-time)
23f87bed 42(autoload 'w3-parse-buffer "w3-parse")
c113de23
GM
43
44(nnoo-declare nnultimate)
45
46(defvoo nnultimate-directory (nnheader-concat gnus-directory "ultimate/")
47 "Where nnultimate will save its files.")
48
49(defvoo nnultimate-address ""
50 "The address of the Ultimate bulletin board.")
51
52;;; Internal variables
53
54(defvar nnultimate-groups-alist nil)
55(defvoo nnultimate-groups nil)
56(defvoo nnultimate-headers nil)
57(defvoo nnultimate-articles nil)
95fa1ff7
SZ
58(defvar nnultimate-table-regexp
59 "postings.*editpost\\|forumdisplay\\|Forum[0-9]+/HTML\\|getbio")
c113de23
GM
60
61;;; Interface functions
62
63(nnoo-define-basics nnultimate)
64
65(deffoo nnultimate-retrieve-headers (articles &optional group server fetch-old)
66 (nnultimate-possibly-change-server group server)
67 (unless gnus-nov-is-evil
68 (let* ((last (car (last articles)))
69 (did nil)
70 (start 1)
71 (entry (assoc group nnultimate-groups))
72 (sid (nth 2 entry))
73 (topics (nth 4 entry))
74 (mapping (nth 5 entry))
75 (old-total (or (nth 6 entry) 1))
76 (furl "forumdisplay.cgi?action=topics&number=%d&DaysPrune=1000")
77 (furls (list (concat nnultimate-address (format furl sid))))
95fa1ff7
SZ
78 (nnultimate-table-regexp
79 "postings.*editpost\\|forumdisplay\\|getbio")
c113de23
GM
80 headers article subject score from date lines parent point
81 contents tinfo fetchers map elem a href garticles topic old-max
95fa1ff7 82 inc datel table current-page total-contents pages
c113de23
GM
83 farticles forum-contents parse furl-fetched mmap farticle)
84 (setq map mapping)
85 (while (and (setq article (car articles))
86 map)
95fa1ff7
SZ
87 ;; Skip past the articles in the map until we reach the
88 ;; article we're looking for.
c113de23
GM
89 (while (and map
90 (or (> article (caar map))
91 (< (cadar map) (caar map))))
92 (pop map))
93 (when (setq mmap (car map))
94 (setq farticle -1)
95 (while (and article
96 (<= article (nth 1 mmap)))
97 ;; Do we already have a fetcher for this topic?
98 (if (setq elem (assq (nth 2 mmap) fetchers))
99 ;; Yes, so we just add the spec to the end.
100 (nconc elem (list (cons article
101 (+ (nth 3 mmap) (incf farticle)))))
102 ;; No, so we add a new one.
103 (push (list (nth 2 mmap)
104 (cons article
105 (+ (nth 3 mmap) (incf farticle))))
106 fetchers))
107 (pop articles)
108 (setq article (car articles)))))
23f87bed 109 ;; Now we have the mapping from/to Gnus/nnultimate article numbers,
c113de23
GM
110 ;; so we start fetching the topics that we need to satisfy the
111 ;; request.
112 (if (not fetchers)
113 (save-excursion
114 (set-buffer nntp-server-buffer)
115 (erase-buffer))
116 (setq nnultimate-articles nil)
117 (mm-with-unibyte-buffer
118 (dolist (elem fetchers)
119 (setq pages 1
120 current-page 1
121 total-contents nil)
122 (while (<= current-page pages)
123 (erase-buffer)
124 (setq subject (nth 2 (assq (car elem) topics)))
125 (setq href (nth 3 (assq (car elem) topics)))
126 (if (= current-page 1)
23f87bed 127 (mm-url-insert href)
c113de23 128 (string-match "\\.html$" href)
23f87bed 129 (mm-url-insert (concat (substring href 0 (match-beginning 0))
c113de23
GM
130 "-" (number-to-string current-page)
131 (match-string 0 href))))
132 (goto-char (point-min))
133 (setq contents
134 (ignore-errors (w3-parse-buffer (current-buffer))))
135 (setq table (nnultimate-find-forum-table contents))
95fa1ff7
SZ
136 (goto-char (point-min))
137 (when (re-search-forward "topic is \\([0-9]+\\) pages" nil t)
138 (setq pages (string-to-number (match-string 1))))
c113de23
GM
139 (setq contents (cdr (nth 2 (car (nth 2 table)))))
140 (setq total-contents (nconc total-contents contents))
141 (incf current-page))
95fa1ff7
SZ
142 (when t
143 (let ((i 0))
144 (dolist (co total-contents)
145 (push (list (or (nnultimate-topic-article-to-article
146 group (car elem) (incf i))
147 1)
148 co subject)
149 nnultimate-articles))))
150 (when nil
151 (dolist (art (cdr elem))
152 (when (nth (1- (cdr art)) total-contents)
153 (push (list (car art)
154 (nth (1- (cdr art)) total-contents)
155 subject)
156 nnultimate-articles))))))
c113de23
GM
157 (setq nnultimate-articles
158 (sort nnultimate-articles 'car-less-than-car))
159 ;; Now we have all the articles, conveniently in an alist
160 ;; where the key is the Gnus article number.
161 (dolist (articlef nnultimate-articles)
162 (setq article (nth 0 articlef)
163 contents (nth 1 articlef)
164 subject (nth 2 articlef))
165 (setq from (mapconcat 'identity
166 (nnweb-text (car (nth 2 contents)))
167 " ")
168 datel (nnweb-text (nth 2 (car (cdr (nth 2 contents))))))
169 (while datel
170 (when (string-match "Posted" (car datel))
171 (setq date (substring (car datel) (match-end 0))
172 datel nil))
173 (pop datel))
95fa1ff7 174 (when date
23f87bed
MB
175