diff lisp/gnus/nnweb.el @ 82951:0fde48feb604

Import Gnus 5.10 from the v5_10 branch of the Gnus repository.
author Andreas Schwab <schwab@suse.de>
date Thu, 22 Jul 2004 16:45:51 +0000
parents 695cf19ef79e
children 3f394ef46f57 cce1c0ee76ee
line wrap: on
line diff
--- a/lisp/gnus/nnweb.el	Thu Jul 22 14:26:26 2004 +0000
+++ b/lisp/gnus/nnweb.el	Thu Jul 22 16:45:51 2004 +0000
@@ -1,5 +1,5 @@
 ;;; nnweb.el --- retrieving articles via web search engines
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
 ;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -24,8 +24,7 @@
 
 ;;; Commentary:
 
-;; Note: You need to have `url' and `w3' installed for this
-;; backend to work.
+;; Note: You need to have `w3' installed for some functions to work.
 
 ;;; Code:
 
@@ -37,18 +36,11 @@
 (require 'gnus)
 (require 'nnmail)
 (require 'mm-util)
-(eval-when-compile
+(require 'mm-url)
+(eval-and-compile
   (ignore-errors
-    (require 'w3)
-    (require 'url)
-    (require 'w3-forms)))
-
-;; Report failure to find w3 at load time if appropriate.
-(unless noninteractive
-  (eval '(progn
-	   (require 'w3)
-	   (require 'url)
-	   (require 'w3-forms))))
+    (require 'url)))
+(autoload 'w3-parse-buffer "w3-parse")
 
 (nnoo-declare nnweb)
 
@@ -57,63 +49,37 @@
 
 (defvoo nnweb-type 'google
   "What search engine type is being used.
-Valid types include `google', `dejanews', `dejanewsold', `reference',
-and `altavista'.")
+Valid types include `google', `dejanews', and `gmane'.")
 
 (defvar nnweb-type-definition
-  '(
-    (google
-     ;;(article . nnweb-google-wash-article)
-     ;;(id . "http://groups.google.com/groups?as_umsgid=%s")
+  '((google
      (article . ignore)
      (id . "http://groups.google.com/groups?selm=%s&output=gplain")
-     ;;(reference . nnweb-google-reference)
      (reference . identity)
      (map . nnweb-google-create-mapping)
      (search . nnweb-google-search)
      (address . "http://groups.google.com/groups")
      (identifier . nnweb-google-identity))
     (dejanews ;; alias of google
-     ;;(article . nnweb-google-wash-article)
-     ;;(id . "http://groups.google.com/groups?as_umsgid=%s")
      (article . ignore)
      (id . "http://groups.google.com/groups?selm=%s&output=gplain")
-     ;;(reference . nnweb-google-reference)
      (reference . identity)
      (map . nnweb-google-create-mapping)
      (search . nnweb-google-search)
      (address . "http://groups.google.com/groups")
      (identifier . nnweb-google-identity))
-;;;     (dejanews
-;;;      (article . ignore)
-;;;      (id . "http://search.dejanews.com/msgid.xp?MID=%s&fmt=text")
-;;;      (map . nnweb-dejanews-create-mapping)
-;;;      (search . nnweb-dejanews-search)
-;;;      (address . "http://www.deja.com/=dnc/qs.xp")
-;;;      (identifier . nnweb-dejanews-identity))
-;;;     (dejanewsold
-;;;      (article . ignore)
-;;;      (map . nnweb-dejanews-create-mapping)
-;;;      (search . nnweb-dejanewsold-search)
-;;;      (address . "http://www.deja.com/dnquery.xp")
-;;;      (identifier . nnweb-dejanews-identity))
-    (reference
-     (article . nnweb-reference-wash-article)
-     (map . nnweb-reference-create-mapping)
-     (search . nnweb-reference-search)
-     (address . "http://www.reference.com/cgi-bin/pn/go")
-     (identifier . identity))
-    (altavista
-     (article . nnweb-altavista-wash-article)
-     (map . nnweb-altavista-create-mapping)
-     (search . nnweb-altavista-search)
-     (address . "http://www.altavista.digital.com/cgi-bin/query")
-     (id . "/cgi-bin/news?id@%s")
-     (identifier . identity)))
+    (gmane
+     (article . nnweb-gmane-wash-article)
+     (id . "http://gmane.org/view.php?group=%s")
+     (reference . identity)
+     (map . nnweb-gmane-create-mapping)
+     (search . nnweb-gmane-search)
+     (address . "http://gmane.org/")
+     (identifier . nnweb-gmane-identity)))
   "Type-definition alist.")
 
 (defvoo nnweb-search nil
-  "Search string to feed to DejaNews.")
+  "Search string to feed to Google.")
 
 (defvoo nnweb-max-hits 999
   "Maximum number of hits to display.")
@@ -197,7 +163,7 @@
 	   (url (and header (mail-header-xref header))))
       (when (or (and url
 		     (mm-with-unibyte-current-buffer
-		       (nnweb-fetch-url url)))
+		       (mm-url-insert url)))
 		(and (stringp article)
 		     (nnweb-definition 'id t)
 		     (let ((fetch (nnweb-definition 'id))
@@ -207,7 +173,7 @@
 		       (when (and fetch art)
 			 (setq url (format fetch art))
 			 (mm-with-unibyte-current-buffer
-			   (nnweb-fetch-url url))
+			   (mm-url-insert url))
 			 (if (nnweb-definition 'reference t)
 			     (setq article
 				   (funcall (nnweb-definition
@@ -237,7 +203,7 @@
   (nnweb-possibly-change-server group server))
 
 (deffoo nnweb-asynchronous-p ()
-  t)
+  nil)
 
 (deffoo nnweb-request-create-group (group &optional server args)
   (nnweb-possibly-change-server nil server)
@@ -336,383 +302,6 @@
 		       nnweb-type nnweb-search server))
 	      (current-buffer))))))
 
-(defun nnweb-fetch-url (url)
-  (let (buf)
-    (save-excursion
-      (if (not nnheader-callback-function)
-	  (progn
-	    (with-temp-buffer
-	      (mm-enable-multibyte)
-	      (let ((coding-system-for-read 'binary)
-		    (coding-system-for-write 'binary)
-		    (default-process-coding-system 'binary))
-		(nnweb-insert url))
-	      (setq buf (buffer-string)))
-	    (erase-buffer)
-	    (insert buf)
-	    t)
-	(nnweb-url-retrieve-asynch
-	 url 'nnweb-callback (current-buffer) nnheader-callback-function)
-	t))))
-
-(defun nnweb-callback (buffer callback)
-  (when (gnus-buffer-live-p url-working-buffer)
-    (save-excursion
-      (set-buffer url-working-buffer)
-      (funcall (nnweb-definition 'article))
-      (nnweb-decode-entities)
-      (set-buffer buffer)
-      (goto-char (point-max))
-      (insert-buffer-substring url-working-buffer))
-    (funcall callback t)
-    (gnus-kill-buffer url-working-buffer)))
-
-(defun nnweb-url-retrieve-asynch (url callback &rest data)
-  (let ((url-request-method "GET")
-	(old-asynch url-be-asynchronous)
-	(url-request-data nil)
-	(url-request-extra-headers nil)
-	(url-working-buffer (generate-new-buffer-name " *nnweb*")))
-    (setq-default url-be-asynchronous t)
-    (save-excursion
-      (set-buffer (get-buffer-create url-working-buffer))
-      (setq url-current-callback-data data
-	    url-be-asynchronous t
-	    url-current-callback-func callback)
-      (url-retrieve url nil))
-    (setq-default url-be-asynchronous old-asynch)))
-
-(if (fboundp 'url-retrieve-synchronously)
-    (defun nnweb-url-retrieve-asynch (url callback &rest data)
-      (url-retrieve url callback data)))
-
-;;;
-;;; DejaNews functions.
-;;;
-
-(defun nnweb-dejanews-create-mapping ()
-  "Perform the search and create a number-to-url alist."
-  (save-excursion
-    (set-buffer nnweb-buffer)
-    (erase-buffer)
-    (when (funcall (nnweb-definition 'search) nnweb-search)
-      (let ((i 0)
-	    (more t)
-	    (case-fold-search t)
-	    (active (or (cadr (assoc nnweb-group nnweb-group-alist))
-			(cons 1 0)))
-	    subject date from
-	    map url parse a table group text)
-	(while more
-	  ;; Go through all the article hits on this page.
-	  (goto-char (point-min))
-	  (setq parse (w3-parse-buffer (current-buffer))
-		table (nth 1 (nnweb-parse-find-all 'table parse)))
-	  (dolist (row (nth 2 (car (nth 2 table))))
-	    (setq a (nnweb-parse-find 'a row)
-		  url (cdr (assq 'href (nth 1 a)))
-		  text (nreverse (nnweb-text row)))
-	    (when a
-	      (setq subject (nth 4 text)
-		    group (nth 2 text)
-		    date (nth 1 text)
-		    from (nth 0 text))
-	      (if (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" date)
-		  (setq date (format "%s %s 00:00:00 %s"
-				     (car (rassq (string-to-number
-						  (match-string 2 date))
-						 parse-time-months))
-				     (match-string 3 date)
-				     (match-string 1 date)))
-		(setq date "Jan 1 00:00:00 0000"))
-	      (incf i)
-	      (setq url (concat url "&fmt=text"))
-	      (when (string-match "&context=[^&]+" url)
-		(setq url (replace-match "" t t url)))
-	      (unless (nnweb-get-hashtb url)
-		(push
-		 (list
-		  (incf (cdr active))
-		  (make-full-mail-header
-		   (cdr active) (concat subject " (" group ")") from date
-		   (concat "<" (nnweb-identifier url) "@dejanews>")
-		   nil 0 0 url))
-		 map)
-		(nnweb-set-hashtb (cadar map) (car map)))))
-	  ;; See whether there is a "Get next 20 hits" button here.
-	  (goto-char (point-min))
-	  (if (or (not (re-search-forward
-			"HREF=\"\\([^\"]+\\)\"[<>b]+Next result" nil t))
-		  (>= i nnweb-max-hits))
-	      (setq more nil)
-	    ;; Yup -- fetch it.
-	    (setq more (match-string 1))
-	    (erase-buffer)
-	    (url-insert-file-contents more)))
-	;; Return the articles in the right order.
-	(setq nnweb-articles
-	      (sort (nconc nnweb-articles map) 'car-less-than-car))))))
-
-(defun nnweb-dejanews-search (search)
-  (nnweb-insert
-   (concat
-    (nnweb-definition 'address)
-    "?"
-    (nnweb-encode-www-form-urlencoded
-     `(("ST" . "PS")
-       ("svcclass" . "dnyr")
-       ("QRY" . ,search)
-       ("defaultOp" . "AND")
-       ("DBS" . "1")
-       ("OP" . "dnquery.xp")
-       ("LNG" . "ALL")
-       ("maxhits" . "100")
-       ("threaded" . "0")
-       ("format" . "verbose2")
-       ("showsort" . "date")
-       ("agesign" . "1")
-       ("ageweight" . "1")))))
-  t)
-
-(defun nnweb-dejanewsold-search (search)
-  (nnweb-fetch-form
-   (nnweb-definition 'address)
-   `(("query" . ,search)
-     ("defaultOp" . "AND")
-     ("svcclass" . "dnold")
-     ("maxhits" . "100")
-     ("format" . "verbose2")
-     ("threaded" . "0")
-     ("showsort" . "date")
-     ("agesign" . "1")
-     ("ageweight" . "1")))
-  t)
-
-(defun nnweb-dejanews-identity (url)
-  "Return an unique identifier based on URL."
-  (if (string-match "AN=\\([0-9]+\\)" url)
-      (match-string 1 url)
-    url))
-
-;;;
-;;; InReference
-;;;
-
-(defun nnweb-reference-create-mapping ()
-  "Perform the search and create a number-to-url alist."
-  (save-excursion
-    (set-buffer nnweb-buffer)
-    (erase-buffer)
-    (when (funcall (nnweb-definition 'search) nnweb-search)
-      (let ((i 0)
-	    (more t)
-	    (case-fold-search t)
-	    (active (or (cadr (assoc nnweb-group nnweb-group-alist))
-			(cons 1 0)))
-	    Subject Score Date Newsgroups From Message-ID
-	    map url)
-	(while more
-	  ;; Go through all the article hits on this page.
-	  (goto-char (point-min))
-	  (search-forward "</pre><hr>" nil t)
-	  (delete-region (point-min) (point))
-	  (goto-char (point-min))
-	  (while (re-search-forward "^ +[0-9]+\\." nil t)
-	    (narrow-to-region
-	     (point)
-	     (if (re-search-forward "^$" nil t)
-		 (match-beginning 0)
-	       (point-max)))
-	    (goto-char (point-min))
-	    (when (looking-at ".*href=\"\\([^\"]+\\)\"")
-	      (setq url (match-string 1)))
-	    (nnweb-remove-markup)
-	    (goto-char (point-min))
-	    (while (search-forward "\t" nil t)
-	      (replace-match " "))
-	    (goto-char (point-min))
-	    (while (re-search-forward "^\\([^:]+\\): \\(.*\\)$" nil t)
-	      (set (intern (match-string 1)) (match-string 2)))
-	    (widen)
-	    (search-forward "</pre>" nil t)
-	    (incf i)
-	    (unless (nnweb-get-hashtb url)
-	      (push
-	       (list
-		(incf (cdr active))
-		(make-full-mail-header
-		 (cdr active) (concat  "(" Newsgroups ") " Subject) From Date
-		 Message-ID
-		 nil 0 (string-to-int Score) url))
-	       map)
-	      (nnweb-set-hashtb (cadar map) (car map))))
-	  (setq more nil))
-	;; Return the articles in the right order.
-	(setq nnweb-articles
-	      (sort (nconc nnweb-articles map) 'car-less-than-car))))))
-
-(defun nnweb-reference-wash-article ()
-  (let ((case-fold-search t))
-    (goto-char (point-min))
-    (re-search-forward "^</center><hr>" nil t)
-    (delete-region (point-min) (point))
-    (search-forward "<pre>" nil t)
-    (forward-line -1)
-    (let ((body (point-marker)))
-      (search-forward "</pre>" nil t)
-      (delete-region (point) (point-max))
-      (nnweb-remove-markup)
-      (goto-char (point-min))
-      (while (looking-at " *$")
-	(gnus-delete-line))
-      (narrow-to-region (point-min) body)
-      (while (and (re-search-forward "^$" nil t)
-		  (not (eobp)))
-	(gnus-delete-line))
-      (goto-char (point-min))
-      (while (looking-at "\\(^[^ ]+:\\) *")
-	(replace-match "\\1 " t)
-	(forward-line 1))
-      (goto-char (point-min))
-      (when (re-search-forward "^References:" nil t)
-	(narrow-to-region
-	 (point) (if (re-search-forward "^$\\|^[^:]+:" nil t)
-		     (match-beginning 0)
-		   (point-max)))
-	(goto-char (point-min))
-	(while (not (eobp))
-	  (unless (looking-at "References")
-	    (insert "\t")
-	    (forward-line 1)))
-	(goto-char (point-min))
-	(while (search-forward "," nil t)
-	  (replace-match " " t t)))
-      (widen)
-      (nnweb-decode-entities)
-      (set-marker body nil))))
-
-(defun nnweb-reference-search (search)
-  (url-insert-file-contents
-   (concat
-    (nnweb-definition 'address)
-    "?"
-    (nnweb-encode-www-form-urlencoded
-     `(("search" . "advanced")
-       ("querytext" . ,search)
-       ("subj" . "")
-       ("name" . "")
-       ("login" . "")
-       ("host" . "")
-       ("organization" . "")
-       ("groups" . "")
-       ("keywords" . "")
-       ("choice" . "Search")
-       ("startmonth" . "Jul")
-       ("startday" . "25")
-       ("startyear" . "1996")
-       ("endmonth" . "Aug")
-       ("endday" . "24")
-       ("endyear" . "1996")
-       ("mode" . "Quick")
-       ("verbosity" . "Verbose")
-       ("ranking" . "Relevance")
-       ("first" . "1")
-       ("last" . "25")
-       ("score" . "50")))))
-  (setq buffer-file-name nil)
-  t)
-
-;;;
-;;; Alta Vista
-;;;
-
-(defun nnweb-altavista-create-mapping ()
-  "Perform the search and create a number-to-url alist."
-  (save-excursion
-    (set-buffer nnweb-buffer)
-    (erase-buffer)
-    (let ((part 0))
-      (when (funcall (nnweb-definition 'search) nnweb-search part)
-	(let ((i 0)
-	      (more t)
-	      (case-fold-search t)
-	      (active (or (cadr (assoc nnweb-group nnweb-group-alist))
-			  (cons 1 0)))
-	      subject date from id group
-	      map url)
-	  (while more
-	    ;; Go through all the article hits on this page.
-	    (goto-char (point-min))
-	    (search-forward "<dt>" nil t)
-	    (delete-region (point-min) (match-beginning 0))
-	    (goto-char (point-min))
-	    (while (search-forward "<dt>" nil t)
-	      (replace-match "\n<blubb>"))
-	    (nnweb-decode-entities)
-	    (goto-char (point-min))
-	    (while (re-search-forward "<blubb>.*href=\"\\([^\"]+\\)\"><strong>\\([^>]*\\)</strong></a><dd>\\([^-]+\\)- <b>\\([^<]+\\)<.*href=\"news:\\([^\"]+\\)\">.*\">\\(.+\\)</a><P>"
-				      nil t)
-	      (setq url (match-string 1)
-		    subject (match-string 2)
-		    date (match-string 3)
-		    group (match-string 4)
-		    id (concat "<" (match-string 5) ">")
-		    from (match-string 6))
-	      (incf i)
-	      (unless (nnweb-get-hashtb url)
-		(push
-		 (list
-		  (incf (cdr active))
-		  (make-full-mail-header
-		   (cdr active) (concat  "(" group ") " subject) from date
-		   id nil 0 0 url))
-		 map)
-		(nnweb-set-hashtb (cadar map) (car map))))
-	    ;; See if we want more.
-	    (when (or (not nnweb-articles)
-		      (>= i nnweb-max-hits)
-		      (not (funcall (nnweb-definition 'search)
-				    nnweb-search (incf part))))
-	      (setq more nil)))
-	  ;; Return the articles in the right order.
-	  (setq nnweb-articles
-		(sort (nconc nnweb-articles map) 'car-less-than-car)))))))
-
-(defun nnweb-altavista-wash-article ()
-  (goto-char (point-min))
-  (let ((case-fold-search t))
-    (when (re-search-forward "^<strong>" nil t)
-      (delete-region (point-min) (match-beginning 0)))
-    (goto-char (point-min))
-    (while (looking-at "<strong>\\([^ ]+\\) +</strong> +\\(.*\\)$")
-      (replace-match "\\1: \\2" t)
-      (forward-line 1))
-    (when (re-search-backward "^References:" nil t)
-      (narrow-to-region (point) (progn (forward-line 1) (point)))
-      (goto-char (point-min))
-      (while (re-search-forward "<A.*\\?id@\\([^\"]+\\)\">[0-9]+</A>" nil t)
-	(replace-match "&lt;\\1&gt; " t)))
-    (widen)
-    (nnweb-remove-markup)
-    (nnweb-decode-entities)))
-
-(defun nnweb-altavista-search (search &optional part)
-  (url-insert-file-contents
-   (concat
-    (nnweb-definition 'address)
-    "?"
-    (nnweb-encode-www-form-urlencoded
-     `(("pg" . "aq")
-       ("what" . "news")
-       ,@(when part `(("stq" . ,(int-to-string (* part 30)))))
-       ("fmt" . "d")
-       ("q" . ,search)
-       ("r" . "")
-       ("d0" . "")
-       ("d1" . "")))))
-  (setq buffer-file-name nil)
-  t)
-
 ;;;
 ;;; Deja bought by google.com
 ;;;
@@ -731,7 +320,7 @@
     (goto-char (point-min))
     (while (search-forward "<br>" nil t)
       (replace-match "\n"))
-    (nnweb-remove-markup)
+    (mm-url-remove-markup)
     (goto-char (point-min))
     (while (re-search-forward "^[ \t]*\n" nil t)
       (replace-match ""))
@@ -741,7 +330,7 @@
     (narrow-to-region (point) (point-max))
     (search-forward "</pre>" nil t)
     (delete-region (point) (point-max))
-    (nnweb-remove-markup)
+    (mm-url-remove-markup)
     (widen)))
 
 (defun nnweb-google-parse-1 (&optional Message-ID)
@@ -763,28 +352,30 @@
 		 "http://groups.google.com/groups?selm=%s&output=gplain" mid))
       (narrow-to-region (search-forward ">" nil t)
 			(search-forward "</a>" nil t))
-      (nnweb-remove-markup)
-      (nnweb-decode-entities)
+      (mm-url-remove-markup)
+      (mm-url-decode-entities)
       (setq Subject (buffer-string))
       (goto-char (point-max))
       (widen)
-      (forward-line 1)
+      (forward-line 2)
       (when (looking-at "<br><font[^>]+>")
 	(goto-char (match-end 0)))
       (if (not (looking-at "<a[^>]+>"))
 	  (skip-chars-forward " \t")
 	(narrow-to-region (point)
 			  (search-forward "</a>" nil t))
-	(nnweb-remove-markup)
-	(nnweb-decode-entities)
+	(mm-url-remove-markup)
+	(mm-url-decode-entities)
 	(setq Newsgroups (buffer-string))
 	(goto-char (point-max))
 	(widen)
 	(skip-chars-forward "- \t"))
       (when (looking-at
-	     "\\([0-9]+[/ ][A-Za-z]+[/ ][0-9]+\\)[ \t]*by[ \t]*\\([^<]*\\) - <a")
-	(setq From (match-string 2)
-	      Date (match-string 1)))
+	     "\\([0-9]+\\)[/ ]\\([A-Za-z]+\\)[/ ]\\([0-9]+\\)[ \t]*by[ \t]*\\([^<]*\\) - <a")
+	(setq From (match-string 4)
+	      Date (format "%s %s 00:00:00 %s"
+			   (match-string 2) (match-string 1)
+			   (match-string 3))))
       (forward-line 1)
       (incf i)
       (unless (nnweb-get-hashtb url)
@@ -807,7 +398,7 @@
 	  (nconc nnweb-articles map))
     (when (setq header (cadar map))
       (mm-with-unibyte-current-buffer
-	(nnweb-fetch-url (mail-header-xref header)))
+	(mm-url-insert (mail-header-xref header)))
       (caar map))))
 
 (defun nnweb-google-create-mapping ()
@@ -816,22 +407,33 @@
     (set-buffer nnweb-buffer)
     (erase-buffer)
     (when (funcall (nnweb-definition 'search) nnweb-search)
-	(let ((more t))
+	(let ((more t)
+	      (i 0))
 	  (while more
 	    (setq nnweb-articles
 		  (nconc nnweb-articles (nnweb-google-parse-1)))
-	    ;; FIXME: There is more.
-	    (setq more nil))
+	    ;; Check if there are more articles to fetch
+	    (goto-char (point-min))
+	    (incf i 100)
+	    (if (or (not (re-search-forward
+			  "<td nowrap><a href=\\([^>]+\\).*<span class=b>Next</span>" nil t))
+		    (>= i nnweb-max-hits))
+		(setq more nil)
+	      ;; Yup, there are more articles
+	      (setq more (concat "http://groups.google.com" (match-string 1)))
+	    (when more
+	      (erase-buffer)
+	      (mm-url-insert more))))
 	  ;; Return the articles in the right order.
 	  (setq nnweb-articles
 		(sort nnweb-articles 'car-less-than-car))))))
 
 (defun nnweb-google-search (search)
-  (nnweb-insert
+  (mm-url-insert
    (concat
     (nnweb-definition 'address)
     "?"
-    (nnweb-encode-www-form-urlencoded
+    (mm-url-encode-www-form-urlencoded
      `(("q" . ,search)
        ("num". "100")
        ("hq" . "")
@@ -848,6 +450,71 @@
     url))
 
 ;;;
+;;; gmane.org
+;;;
+(defun nnweb-gmane-create-mapping ()
+  "Perform the search and create a number-to-url alist."
+  (save-excursion
+    (set-buffer nnweb-buffer)
+    (erase-buffer)
+    (when (funcall (nnweb-definition 'search) nnweb-search)
+      (let ((more t)
+	    (case-fold-search t)
+	    (active (or (cadr (assoc nnweb-group nnweb-group-alist))
+			(cons 1 0)))
+	    subject group url
+	    map)
+	  ;; Remove stuff from the beginning of results
+	(goto-char (point-min))
+	(search-forward "Search Results</h1><ul>" nil t)
+	(delete-region (point-min) (point))
+	(goto-char (point-min))
+	;; Iterate over the actual hits
+	(while (re-search-forward ".*href=\"\\([^\"]+\\)\">\\(.*\\)" nil t)
+	    (setq url (concat "http://gmane.org/" (match-string 1)))
+	    (setq subject (match-string 2))
+	  (unless (nnweb-get-hashtb url)
+	    (push
+	     (list
+	      (incf (cdr active))
+	      (make-full-mail-header
+	       (cdr active) (concat  "(" group ") " subject) nil nil
+	       nil nil 0 0 url))
+	     map)
+	    (nnweb-set-hashtb (cadar map) (car map))))
+	;; Return the articles in the right order.
+	(setq nnweb-articles
+	      (sort (nconc nnweb-articles map) 'car-less-than-car))))))
+
+(defun nnweb-gmane-wash-article ()
+  (let ((case-fold-search t))
+    (goto-char (point-min))
+    (re-search-forward "<!--X-Head-of-Message-->" nil t)
+    (delete-region (point-min) (point))
+    (goto-char (point-min))
+    (while (looking-at "^<li><em>\\([^ ]+\\)</em>.*</li>")
+      (replace-match "\\1\\2" t)
+      (forward-line 1))
+    (mm-url-remove-markup)))
+
+(defun nnweb-gmane-search (search)
+  (mm-url-insert
+   (concat
+    (nnweb-definition 'address)
+    "?"
+    (mm-url-encode-www-form-urlencoded
+     `(("query" . ,search)))))
+  (setq buffer-file-name nil)
+  t)
+
+
+(defun nnweb-gmane-identity (url)
+  "Return a unique identifier based on URL."
+  (if (string-match "group=\\(.+\\)" url)
+      (match-string 1 url)
+    url))
+
+;;;
 ;;; General web/w3 interface utility functions
 ;;;
 
@@ -869,75 +536,6 @@
     (mapcar 'nnweb-insert-html (nth 2 parse))
     (insert "</" (symbol-name (car parse)) ">\n")))
 
-(defun nnweb-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 nnweb-fetch-form (url pairs)
-  "Fetch a form from URL with PAIRS as the data using the POST method."
-  (let ((url-request-data (nnweb-encode-www-form-urlencoded pairs))
-	(url-request-method "POST")
-	(url-request-extra-headers
-	 '(("Content-type" . "application/x-www-form-urlencoded"))))
-    (url-insert-file-contents url)
-    (setq buffer-file-name nil))
-  t)
-
-(defun nnweb-decode-entities ()
-  "Decode all HTML entities."
-  (goto-char (point-min))
-  (while (re-search-forward "&\\(#[0-9]+\\|[a-z]+\\);" nil t)
-    (let ((elem (if (eq (aref (match-string 1) 0) ?\#)
-			(let ((c
-			       (string-to-number (substring
-						  (match-string 1) 1))))
-			  (if (mm-char-or-char-int-p c) c 32))
-		      (or (cdr (assq (intern (match-string 1))
-				     w3-html-entities))
-			  ?#))))
-      (unless (stringp elem)
-	(setq elem (char-to-string elem)))
-      (replace-match elem t t))))
-
-(defun nnweb-decode-entities-string (string)
-  (with-temp-buffer
-    (insert string)
-    (nnweb-decode-entities)
-    (buffer-substring (point-min) (point-max))))
-
-(defun nnweb-remove-markup ()
-  "Remove all HTML markup, leaving just plain text."
-  (goto-char (point-min))
-  (while (search-forward "<!--" nil t)
-    (delete-region (match-beginning 0)
-		   (or (search-forward "-->" nil t)
-		       (point-max))))
-  (goto-char (point-min))
-  (while (re-search-forward "<[^>]+>" nil t)
-    (replace-match "" t t)))
-
-(defun nnweb-insert (url &optional follow-refresh)
-  "Insert the contents from an URL in the current buffer.
-If FOLLOW-REFRESH is non-nil, redirect refresh url in META."
-  (let ((name buffer-file-name))
-    (if follow-refresh
-	(save-restriction
-	  (narrow-to-region (point) (point))
-	  (url-insert-file-contents url)
-	  (goto-char (point-min))
-	  (when (re-search-forward
-		 "<meta[ \t\r\n]*http-equiv=\"Refresh\"[^>]*URL=\\([^\"]+\\)\"" nil t)
-	    (let ((url (match-string 1)))
-	      (delete-region (point-min) (point-max))
-	      (nnweb-insert url t))))
-      (url-insert-file-contents url))
-    (setq buffer-file-name name)))
-
 (defun nnweb-parse-find (type parse &optional maxdepth)
   "Find the element of TYPE in PARSE."
   (catch 'found
@@ -987,11 +585,6 @@
 		 (listp (cdr element)))
 	(nnweb-text-1 element)))))
 
-(defun nnweb-replace-in-string (string match newtext)
-  (while (string-match match string)
-    (setq string (replace-match newtext t t string)))
-  string)
-
 (provide 'nnweb)
 
 ;;; arch-tag: f59307eb-c90f-479f-b7d2-dbd8bf51b697