diff options
| author | Miles Bader | 2004-10-14 08:50:09 +0000 |
|---|---|---|
| committer | Miles Bader | 2004-10-14 08:50:09 +0000 |
| commit | 91900dd736dc0ab57a38da1fa9daa5ddde487bfb (patch) | |
| tree | f592b350cad8a3a6bd196722bb553469c5781c1a /lisp/url | |
| parent | 2beba76dd5f6e3f1fcf9cba8b66e465ae9e20519 (diff) | |
| parent | ebbeed623cb9902e520fc67d6d271e222e16867f (diff) | |
| download | emacs-91900dd736dc0ab57a38da1fa9daa5ddde487bfb.tar.gz emacs-91900dd736dc0ab57a38da1fa9daa5ddde487bfb.zip | |
Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-57
Merge from emacs--cvs-trunk--0
Patches applied:
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-594
- miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-598
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-599
Merge from gnus--rel--5.10
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-600
- miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-602
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-603
Merge from gnus--rel--5.10
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-604
- miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-609
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-610
Merge from gnus--rel--5.10
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-611
- miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-614
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-615
Merge from gnus--rel--5.10
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-42
Update from CVS
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-43
Merge from emacs--cvs-trunk--0
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-44
- miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-46
Update from CVS
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-47
Merge from emacs--cvs-trunk--0
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-48
Update from CVS
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-49
Add {arch}/=commit-merge-make-log
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-50
{arch}/=commit-merge-make-log: Don't die if there are no ChangeLog changes
Diffstat (limited to 'lisp/url')
| -rw-r--r-- | lisp/url/ChangeLog | 61 | ||||
| -rw-r--r-- | lisp/url/url-auth.el | 316 | ||||
| -rw-r--r-- | lisp/url/url-cache.el | 202 | ||||
| -rw-r--r-- | lisp/url/url-cookie.el | 466 | ||||
| -rw-r--r-- | lisp/url/url-dired.el | 100 | ||||
| -rw-r--r-- | lisp/url/url-file.el | 1 | ||||
| -rw-r--r-- | lisp/url/url-ftp.el | 42 | ||||
| -rw-r--r-- | lisp/url/url-gw.el | 268 | ||||
| -rw-r--r-- | lisp/url/url-handlers.el | 3 | ||||
| -rw-r--r-- | lisp/url/url-history.el | 199 | ||||
| -rw-r--r-- | lisp/url/url-https.el | 14 | ||||
| -rw-r--r-- | lisp/url/url-irc.el | 76 | ||||
| -rw-r--r-- | lisp/url/url-ldap.el | 240 | ||||
| -rw-r--r-- | lisp/url/url-mailto.el | 131 | ||||
| -rw-r--r-- | lisp/url/url-methods.el | 150 | ||||
| -rw-r--r-- | lisp/url/url-misc.el | 117 | ||||
| -rw-r--r-- | lisp/url/url-news.el | 135 | ||||
| -rw-r--r-- | lisp/url/url-nfs.el | 3 | ||||
| -rw-r--r-- | lisp/url/url-parse.el | 210 | ||||
| -rw-r--r-- | lisp/url/url-privacy.el | 81 | ||||
| -rw-r--r-- | lisp/url/url-util.el | 3 | ||||
| -rw-r--r-- | lisp/url/url-vars.el | 431 | ||||
| -rw-r--r-- | lisp/url/url.el | 269 |
23 files changed, 3504 insertions, 14 deletions
diff --git a/lisp/url/ChangeLog b/lisp/url/ChangeLog index 69851ac5046..91a6c869a21 100644 --- a/lisp/url/ChangeLog +++ b/lisp/url/ChangeLog | |||
| @@ -1,3 +1,64 @@ | |||
| 1 | 2004-10-12 Simon Josefsson <jas@extundo.com> | ||
| 2 | |||
| 3 | * url-vars.el (url-gateway-method): Add new method `tls'. | ||
| 4 | |||
| 5 | * url-news.el (url-snews): Use nntp-open-tls-stream if | ||
| 6 | url-gateway-method is tls. | ||
| 7 | |||
| 8 | * url-ldap.el (url-ldap-certificate-formatter): Use | ||
| 9 | tls-certificate-information if ssl.el is not available. | ||
| 10 | |||
| 11 | * url-https.el (url-https-create-secure-wrapper): Use tls if ssl | ||
| 12 | is not available. | ||
| 13 | |||
| 14 | * url-gw.el (url-open-stream): Support tls url-gateway-method. | ||
| 15 | (url-open-stream): Likewise. | ||
| 16 | |||
| 17 | 2004-10-10 Lars Hansen <larsh@math.ku.dk> | ||
| 18 | |||
| 19 | * url-auth.el: Fix copyright notice. | ||
| 20 | |||
| 21 | * url-cache.el: Fix copyright notice. | ||
| 22 | |||
| 23 | * url-cookie.el: Fix copyright notice. | ||
| 24 | |||
| 25 | * url-dired.el: Fix copyright notice. | ||
| 26 | |||
| 27 | * url-file.el: Fix copyright notice. | ||
| 28 | |||
| 29 | * url-ftp.el: Fix copyright notice. | ||
| 30 | |||
| 31 | * url-handlers.el: Fix copyright notice. | ||
| 32 | |||
| 33 | * url-history.el: Fix copyright notice. | ||
| 34 | |||
| 35 | * url-irc.el: Fix copyright notice. | ||
| 36 | |||
| 37 | * url-mailto.el: Fix copyright notice. | ||
| 38 | |||
| 39 | * url-methods.el: Fix copyright notice. | ||
| 40 | |||
| 41 | * url-misc.el: Fix copyright notice. | ||
| 42 | |||
| 43 | * url-news.el: Fix copyright notice. | ||
| 44 | |||
| 45 | * url-nfs.el: Fix copyright notice. | ||
| 46 | |||
| 47 | * url-parse.el: Fix copyright notice. | ||
| 48 | |||
| 49 | * url-privacy.el: Fix copyright notice. | ||
| 50 | |||
| 51 | * url-vars.el: Fix copyright notice. | ||
| 52 | |||
| 53 | * url.el: Fix copyright notice. | ||
| 54 | |||
| 55 | * url-util.el: Fix copyright notice. | ||
| 56 | |||
| 57 | 2004-10-06 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 58 | |||
| 59 | * url-handlers.el (url-insert-file-contents): Use the URL to decide the | ||
| 60 | encoding, not the buffer-file-name (which might not even exist). | ||
| 61 | |||
| 1 | 2004-09-20 Stefan Monnier <monnier@iro.umontreal.ca> | 62 | 2004-09-20 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 63 | ||
| 3 | * url-handlers.el (url-insert-file-contents): Decode contents. | 64 | * url-handlers.el (url-insert-file-contents): Decode contents. |
diff --git a/lisp/url/url-auth.el b/lisp/url/url-auth.el new file mode 100644 index 00000000000..39bb730bebc --- /dev/null +++ b/lisp/url/url-auth.el | |||
| @@ -0,0 +1,316 @@ | |||
| 1 | ;;; url-auth.el --- Uniform Resource Locator authorization modules | ||
| 2 | ;; Keywords: comm, data, processes, hypermedia | ||
| 3 | |||
| 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5 | ;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc. | ||
| 6 | ;;; | ||
| 7 | ;;; This file is part of GNU Emacs. | ||
| 8 | ;;; | ||
| 9 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;;; any later version. | ||
| 13 | ;;; | ||
| 14 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;;; GNU General Public License for more details. | ||
| 18 | ;;; | ||
| 19 | ;;; You should have received a copy of the GNU General Public License | ||
| 20 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;;; Boston, MA 02111-1307, USA. | ||
| 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 24 | |||
| 25 | (require 'url-vars) | ||
| 26 | (require 'url-parse) | ||
| 27 | (autoload 'url-warn "url") | ||
| 28 | |||
| 29 | (defsubst url-auth-user-prompt (url realm) | ||
| 30 | "String to usefully prompt for a username." | ||
| 31 | (concat "Username [for " | ||
| 32 | (or realm (url-truncate-url-for-viewing | ||
| 33 | (url-recreate-url url) | ||
| 34 | (- (window-width) 10 20))) | ||
| 35 | "]: ")) | ||
| 36 | |||
| 37 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 38 | ;;; Basic authorization code | ||
| 39 | ;;; ------------------------ | ||
| 40 | ;;; This implements the BASIC authorization type. See the online | ||
| 41 | ;;; documentation at | ||
| 42 | ;;; http://www.w3.org/hypertext/WWW/AccessAuthorization/Basic.html | ||
| 43 | ;;; for the complete documentation on this type. | ||
| 44 | ;;; | ||
| 45 | ;;; This is very insecure, but it works as a proof-of-concept | ||
| 46 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 47 | (defvar url-basic-auth-storage 'url-http-real-basic-auth-storage | ||
| 48 | "Where usernames and passwords are stored. | ||
| 49 | |||
| 50 | Must be a symbol pointing to another variable that will actually store | ||
| 51 | the information. The value of this variable is an assoc list of assoc | ||
| 52 | lists. The first assoc list is keyed by the server name. The cdr of | ||
| 53 | this is an assoc list based on the 'directory' specified by the url we | ||
| 54 | are looking up.") | ||
| 55 | |||
| 56 | (defun url-basic-auth (url &optional prompt overwrite realm args) | ||
| 57 | "Get the username/password for the specified URL. | ||
| 58 | If optional argument PROMPT is non-nil, ask for the username/password | ||
| 59 | to use for the url and its descendants. If optional third argument | ||
| 60 | OVERWRITE is non-nil, overwrite the old username/password pair if it | ||
| 61 | is found in the assoc list. If REALM is specified, use that as the realm | ||
| 62 | instead of the pathname inheritance method." | ||
| 63 | (let* ((href (if (stringp url) | ||
| 64 | (url-generic-parse-url url) | ||
| 65 | url)) | ||
| 66 | (server (url-host href)) | ||
| 67 | (port (url-port href)) | ||
| 68 | (path (url-filename href)) | ||
| 69 | user pass byserv retval data) | ||
| 70 | (setq server (format "%s:%d" server port) | ||
| 71 | path (cond | ||
| 72 | (realm realm) | ||
| 73 | ((string-match "/$" path) path) | ||
| 74 | (t (url-basepath path))) | ||
| 75 | byserv (cdr-safe (assoc server | ||
| 76 | (symbol-value url-basic-auth-storage)))) | ||
| 77 | (cond | ||
| 78 | ((and prompt (not byserv)) | ||
| 79 | (setq user (read-string (url-auth-user-prompt url realm) | ||
| 80 | (user-real-login-name)) | ||
| 81 | pass (funcall url-passwd-entry-func "Password: ")) | ||
| 82 | (set url-basic-auth-storage | ||
| 83 | (cons (list server | ||
| 84 | (cons path | ||
| 85 | (setq retval | ||
| 86 | (base64-encode-string | ||
| 87 | (format "%s:%s" user pass))))) | ||
| 88 | (symbol-value url-basic-auth-storage)))) | ||
| 89 | (byserv | ||
| 90 | (setq retval (cdr-safe (assoc path byserv))) | ||
| 91 | (if (and (not retval) | ||
| 92 | (string-match "/" path)) | ||
| 93 | (while (and byserv (not retval)) | ||
| 94 | (setq data (car (car byserv))) | ||
| 95 | (if (or (not (string-match "/" data)) ; Its a realm - take it! | ||
| 96 | (and | ||
| 97 | (>= (length path) (length data)) | ||
| 98 | (string= data (substring path 0 (length data))))) | ||
| 99 | (setq retval (cdr (car byserv)))) | ||
| 100 | (setq byserv (cdr byserv)))) | ||
| 101 | (if (or (and (not retval) prompt) overwrite) | ||
| 102 | (progn | ||
| 103 | (setq user (read-string (url-auth-user-prompt url realm) | ||
| 104 | (user-real-login-name)) | ||
| 105 | pass (funcall url-passwd-entry-func "Password: ") | ||
| 106 | retval (base64-encode-string (format "%s:%s" user pass)) | ||
| 107 | byserv (assoc server (symbol-value url-basic-auth-storage))) | ||
| 108 | (setcdr byserv | ||
| 109 | (cons (cons path retval) (cdr byserv)))))) | ||
| 110 | (t (setq retval nil))) | ||
| 111 | (if retval (setq retval (concat "Basic " retval))) | ||
| 112 | retval)) | ||
| 113 | |||
| 114 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 115 | ;;; Digest authorization code | ||
| 116 | ;;; ------------------------ | ||
| 117 | ;;; This implements the DIGEST authorization type. See the internet draft | ||
| 118 | ;;; ftp://ds.internic.net/internet-drafts/draft-ietf-http-digest-aa-01.txt | ||
| 119 | ;;; for the complete documentation on this type. | ||
| 120 | ;;; | ||
| 121 | ;;; This is very secure | ||
| 122 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 123 | (defvar url-digest-auth-storage nil | ||
| 124 | "Where usernames and passwords are stored. Its value is an assoc list of | ||
| 125 | assoc lists. The first assoc list is keyed by the server name. The cdr of | ||
| 126 | this is an assoc list based on the 'directory' specified by the url we are | ||
| 127 | looking up.") | ||
| 128 | |||
| 129 | (defun url-digest-auth-create-key (username password realm method uri) | ||
| 130 | "Create a key for digest authentication method" | ||
| 131 | (let* ((info (if (stringp uri) | ||
| 132 | (url-generic-parse-url uri) | ||
| 133 | uri)) | ||
| 134 | (a1 (md5 (concat username ":" realm ":" password))) | ||
| 135 | (a2 (md5 (concat method ":" (url-filename info))))) | ||
| 136 | (list a1 a2))) | ||
| 137 | |||
| 138 | (defun url-digest-auth (url &optional prompt overwrite realm args) | ||
| 139 | "Get the username/password for the specified URL. | ||
| 140 | If optional argument PROMPT is non-nil, ask for the username/password | ||
| 141 | to use for the url and its descendants. If optional third argument | ||
| 142 | OVERWRITE is non-nil, overwrite the old username/password pair if it | ||
| 143 | is found in the assoc list. If REALM is specified, use that as the realm | ||
| 144 | instead of hostname:portnum." | ||
| 145 | (if args | ||
| 146 | (let* ((href (if (stringp url) | ||
| 147 | (url-generic-parse-url url) | ||
| 148 | url)) | ||
| 149 | (server (url-host href)) | ||
| 150 | (port (url-port href)) | ||
| 151 | (path (url-filename href)) | ||
| 152 | user pass byserv retval data) | ||
| 153 | (setq path (cond | ||
| 154 | (realm realm) | ||
| 155 | ((string-match "/$" path) path) | ||
| 156 | (t (url-basepath path))) | ||
| 157 | server (format "%s:%d" server port) | ||
| 158 | byserv (cdr-safe (assoc server url-digest-auth-storage))) | ||
| 159 | (cond | ||
| 160 | ((and prompt (not byserv)) | ||
| 161 | (setq user (read-string (url-auth-user-prompt url realm) | ||
| 162 | (user-real-login-name)) | ||
| 163 | pass (funcall url-passwd-entry-func "Password: ") | ||
| 164 | url-digest-auth-storage | ||
| 165 | (cons (list server | ||
| 166 | (cons path | ||
| 167 | (setq retval | ||
| 168 | (cons user | ||
| 169 | (url-digest-auth-create-key | ||
| 170 | user pass realm | ||
| 171 | (or url-request-method "GET") | ||
| 172 | url))))) | ||
| 173 | url-digest-auth-storage))) | ||
| 174 | (byserv | ||
| 175 | (setq retval (cdr-safe (assoc path byserv))) | ||
| 176 | (if (and (not retval) ; no exact match, check directories | ||
| 177 | (string-match "/" path)) ; not looking for a realm | ||
| 178 | (while (and byserv (not retval)) | ||
| 179 | (setq data (car (car byserv))) | ||
| 180 | (if (or (not (string-match "/" data)) | ||
| 181 | (and | ||
| 182 | (>= (length path) (length data)) | ||
| 183 | (string= data (substring path 0 (length data))))) | ||
| 184 | (setq retval (cdr (car byserv)))) | ||
| 185 | (setq byserv (cdr byserv)))) | ||
| 186 | (if (or (and (not retval) prompt) overwrite) | ||
| 187 | (progn | ||
| 188 | (setq user (read-string (url-auth-user-prompt url realm) | ||
| 189 | (user-real-login-name)) | ||
| 190 | pass (funcall url-passwd-entry-func "Password: ") | ||
| 191 | retval (setq retval | ||
| 192 | (cons user | ||
| 193 | (url-digest-auth-create-key | ||
| 194 | user pass realm | ||
| 195 | (or url-request-method "GET") | ||
| 196 | url))) | ||
| 197 | byserv (assoc server url-digest-auth-storage)) | ||
| 198 | (setcdr byserv | ||
| 199 | (cons (cons path retval) (cdr byserv)))))) | ||
| 200 | (t (setq retval nil))) | ||
| 201 | (if retval | ||
| 202 | (let ((nonce (or (cdr-safe (assoc "nonce" args)) "nonegiven")) | ||
| 203 | (opaque (or (cdr-safe (assoc "opaque" args)) "nonegiven"))) | ||
| 204 | (format | ||
| 205 | (concat "Digest username=\"%s\", realm=\"%s\"," | ||
| 206 | "nonce=\"%s\", uri=\"%s\"," | ||
| 207 | "response=\"%s\", opaque=\"%s\"") | ||
| 208 | (nth 0 retval) realm nonce (url-filename href) | ||
| 209 | (md5 (concat (nth 1 retval) ":" nonce ":" | ||
| 210 | (nth 2 retval))) opaque)))))) | ||
| 211 | |||
| 212 | (defvar url-registered-auth-schemes nil | ||
| 213 | "A list of the registered authorization schemes and various and sundry | ||
| 214 | information associated with them.") | ||
| 215 | |||
| 216 | ;;;###autoload | ||
| 217 | (defun url-get-authentication (url realm type prompt &optional args) | ||
| 218 | "Return an authorization string suitable for use in the WWW-Authenticate | ||
| 219 | header in an HTTP/1.0 request. | ||
| 220 | |||
| 221 | URL is the url you are requesting authorization to. This can be either a | ||
| 222 | string representing the URL, or the parsed representation returned by | ||
| 223 | `url-generic-parse-url' | ||
| 224 | REALM is the realm at a specific site we are looking for. This should be a | ||
| 225 | string specifying the exact realm, or nil or the symbol 'any' to | ||
| 226 | specify that the filename portion of the URL should be used as the | ||
| 227 | realm | ||
| 228 | TYPE is the type of authentication to be returned. This is either a string | ||
| 229 | representing the type (basic, digest, etc), or nil or the symbol 'any' | ||
| 230 | to specify that any authentication is acceptable. If requesting 'any' | ||
| 231 | the strongest matching authentication will be returned. If this is | ||
| 232 | wrong, its no big deal, the error from the server will specify exactly | ||
| 233 | what type of auth to use | ||
| 234 | PROMPT is boolean - specifies whether to ask the user for a username/password | ||
| 235 | if one cannot be found in the cache" | ||
| 236 | (if (not realm) | ||
| 237 | (setq realm (cdr-safe (assoc "realm" args)))) | ||
| 238 | (if (stringp url) | ||
| 239 | (setq url (url-generic-parse-url url))) | ||
| 240 | (if (or (null type) (eq type 'any)) | ||
| 241 | ;; Whooo doogies! | ||
| 242 | ;; Go through and get _all_ the authorization strings that could apply | ||
| 243 | ;; to this URL, store them along with the 'rating' we have in the list | ||
| 244 | ;; of schemes, then sort them so that the 'best' is at the front of the | ||
| 245 | ;; list, then get the car, then get the cdr. | ||
| 246 | ;; Zooom zooom zoooooom | ||
| 247 | (cdr-safe | ||
| 248 | (car-safe | ||
| 249 | (sort | ||
| 250 | (mapcar | ||
| 251 | (function | ||
| 252 | (lambda (scheme) | ||
| 253 | (if (fboundp (car (cdr scheme))) | ||
| 254 | (cons (cdr (cdr scheme)) | ||
| 255 | (funcall (car (cdr scheme)) url nil nil realm)) | ||
| 256 | (cons 0 nil)))) | ||
| 257 | url-registered-auth-schemes) | ||
| 258 | (function | ||
| 259 | (lambda (x y) | ||
| 260 | (cond | ||
| 261 | ((null (cdr x)) nil) | ||
| 262 | ((and (cdr x) (null (cdr y))) t) | ||
| 263 | ((and (cdr x) (cdr y)) | ||
| 264 | (>= (car x) (car y))) | ||
| 265 | (t nil))))))) | ||
| 266 | (if (symbolp type) (setq type (symbol-name type))) | ||
| 267 | (let* ((scheme (car-safe | ||
| 268 | (cdr-safe (assoc (downcase type) | ||
| 269 | url-registered-auth-schemes))))) | ||
| 270 | (if (and scheme (fboundp scheme)) | ||
| 271 | (funcall scheme url prompt | ||
| 272 | (and prompt | ||
| 273 | (funcall scheme url nil nil realm args)) | ||
| 274 | realm args))))) | ||
| 275 | |||
| 276 | ;;;###autoload | ||
| 277 | (defun url-register-auth-scheme (type &optional function rating) | ||
| 278 | "Register an HTTP authentication method. | ||
| 279 | |||
| 280 | TYPE is a string or symbol specifying the name of the method. This | ||
| 281 | should be the same thing you expect to get returned in an Authenticate | ||
| 282 | header in HTTP/1.0 - it will be downcased. | ||
| 283 | FUNCTION is the function to call to get the authorization information. This | ||
| 284 | defaults to `url-?-auth', where ? is TYPE | ||
| 285 | RATING a rating between 1 and 10 of the strength of the authentication. | ||
| 286 | This is used when asking for the best authentication for a specific | ||
| 287 | URL. The item with the highest rating is returned." | ||
| 288 | (let* ((type (cond | ||
| 289 | ((stringp type) (downcase type)) | ||
| 290 | ((symbolp type) (downcase (symbol-name type))) | ||
| 291 | (t (error "Bad call to `url-register-auth-scheme'")))) | ||
| 292 | (function (or function (intern (concat "url-" type "-auth")))) | ||
| 293 | (rating (cond | ||
| 294 | ((null rating) 2) | ||
| 295 | ((stringp rating) (string-to-int rating)) | ||
| 296 | (t rating))) | ||
| 297 | (node (assoc type url-registered-auth-schemes))) | ||
| 298 | (if (not (fboundp function)) | ||
| 299 | (url-warn 'security | ||
| 300 | (format (concat | ||
| 301 | "Tried to register `%s' as an auth scheme" | ||
| 302 | ", but it is not a function!") function))) | ||
| 303 | |||
| 304 | (if node | ||
| 305 | (setcdr node (cons function rating)) | ||
| 306 | (setq url-registered-auth-schemes | ||
| 307 | (cons (cons type (cons function rating)) | ||
| 308 | url-registered-auth-schemes))))) | ||
| 309 | |||
| 310 | (defun url-auth-registered (scheme) | ||
| 311 | ;; Return non-nil iff SCHEME is registered as an auth type | ||
| 312 | (assoc scheme url-registered-auth-schemes)) | ||
| 313 | |||
| 314 | (provide 'url-auth) | ||
| 315 | |||
| 316 | ;;; arch-tag: 04058625-616d-44e4-9dbf-4b46b00b2a91 | ||
diff --git a/lisp/url/url-cache.el b/lisp/url/url-cache.el new file mode 100644 index 00000000000..1e3374639e1 --- /dev/null +++ b/lisp/url/url-cache.el | |||
| @@ -0,0 +1,202 @@ | |||
| 1 | ;;; url-cache.el --- Uniform Resource Locator retrieval tool | ||
| 2 | ;; Keywords: comm, data, processes, hypermedia | ||
| 3 | |||
| 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5 | ;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc. | ||
| 6 | ;;; | ||
| 7 | ;;; This file is part of GNU Emacs. | ||
| 8 | ;;; | ||
| 9 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;;; any later version. | ||
| 13 | ;;; | ||
| 14 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;;; GNU General Public License for more details. | ||
| 18 | ;;; | ||
| 19 | ;;; You should have received a copy of the GNU General Public License | ||
| 20 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;;; Boston, MA 02111-1307, USA. | ||
| 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 24 | (require 'url-parse) | ||
| 25 | (require 'url-util) | ||
| 26 | |||
| 27 | (defcustom url-cache-directory | ||
| 28 | (expand-file-name "cache" url-configuration-directory) | ||
| 29 | "*The directory where cache files should be stored." | ||
| 30 | :type 'directory | ||
| 31 | :group 'url-file) | ||
| 32 | |||
| 33 | ;; Cache manager | ||
| 34 | (defun url-cache-file-writable-p (file) | ||
| 35 | "Follows the documentation of `file-writable-p', unlike `file-writable-p'." | ||
| 36 | (and (file-writable-p file) | ||
| 37 | (if (file-exists-p file) | ||
| 38 | (not (file-directory-p file)) | ||
| 39 | (file-directory-p (file-name-directory file))))) | ||
| 40 | |||
| 41 | (defun url-cache-prepare (file) | ||
| 42 | "Makes it possible to cache data in FILE. | ||
| 43 | Creates any necessary parent directories, deleting any non-directory files | ||
| 44 | that would stop this. Returns nil if parent directories can not be | ||
| 45 | created. If FILE already exists as a non-directory, it changes | ||
| 46 | permissions of FILE or deletes FILE to make it possible to write a new | ||
| 47 | version of FILE. Returns nil if this can not be done. Returns nil if | ||
| 48 | FILE already exists as a directory. Otherwise, returns t, indicating that | ||
| 49 | FILE can be created or overwritten." | ||
| 50 | (cond | ||
| 51 | ((url-cache-file-writable-p file) | ||
| 52 | t) | ||
| 53 | ((file-directory-p file) | ||
| 54 | nil) | ||
| 55 | (t | ||
| 56 | (condition-case () | ||
| 57 | (or (make-directory (file-name-directory file) t) t) | ||
| 58 | (error nil))))) | ||
| 59 | |||
| 60 | ;;;###autoload | ||
| 61 | (defun url-store-in-cache (&optional buff) | ||
| 62 | "Store buffer BUFF in the cache." | ||
| 63 | (if (not (and buff (get-buffer buff))) | ||
| 64 | nil | ||
| 65 | (save-excursion | ||
| 66 | (and buff (set-buffer buff)) | ||
| 67 | (let* ((fname (url-cache-create-filename (url-view-url t)))) | ||
| 68 | (if (url-cache-prepare fname) | ||
| 69 | (let ((coding-system-for-write 'binary)) | ||
| 70 | (write-region (point-min) (point-max) fname nil 5))))))) | ||
| 71 | |||
| 72 | ;;;###autoload | ||
| 73 | (defun url-is-cached (url) | ||
| 74 | "Return non-nil if the URL is cached." | ||
| 75 | (let* ((fname (url-cache-create-filename url)) | ||
| 76 | (attribs (file-attributes fname))) | ||
| 77 | (and fname ; got a filename | ||
| 78 | (file-exists-p fname) ; file exists | ||
| 79 | (not (eq (nth 0 attribs) t)) ; Its not a directory | ||
| 80 | (nth 5 attribs)))) ; Can get last mod-time | ||
| 81 | |||
| 82 | (defun url-cache-create-filename-human-readable (url) | ||
| 83 | "Return a filename in the local cache for URL" | ||
| 84 | (if url | ||
| 85 | (let* ((url (if (vectorp url) (url-recreate-url url) url)) | ||
| 86 | (urlobj (url-generic-parse-url url)) | ||
| 87 | (protocol (url-type urlobj)) | ||
| 88 | (hostname (url-host urlobj)) | ||
| 89 | (host-components | ||
| 90 | (cons | ||
| 91 | (user-real-login-name) | ||
| 92 | (cons (or protocol "file") | ||
| 93 | (reverse (split-string (or hostname "localhost") | ||
| 94 | (eval-when-compile | ||
| 95 | (regexp-quote "."))))))) | ||
| 96 | (fname (url-filename urlobj))) | ||
| 97 | (if (and fname (/= (length fname) 0) (= (aref fname 0) ?/)) | ||
| 98 | (setq fname (substring fname 1 nil))) | ||
| 99 | (if fname | ||
| 100 | (let ((slash nil)) | ||
| 101 | (setq fname | ||
| 102 | (mapconcat | ||
| 103 | (function | ||
| 104 | (lambda (x) | ||
| 105 | (cond | ||
| 106 | ((and (= ?/ x) slash) | ||
| 107 | (setq slash nil) | ||
| 108 | "%2F") | ||
| 109 | ((= ?/ x) | ||
| 110 | (setq slash t) | ||
| 111 | "/") | ||
| 112 | (t | ||
| 113 | (setq slash nil) | ||
| 114 | (char-to-string x))))) fname "")))) | ||
| 115 | |||
| 116 | (setq fname (and fname | ||
| 117 | (mapconcat | ||
| 118 | (function (lambda (x) | ||
| 119 | (if (= x ?~) "" (char-to-string x)))) | ||
| 120 | fname "")) | ||
| 121 | fname (cond | ||
| 122 | ((null fname) nil) | ||
| 123 | ((or (string= "" fname) (string= "/" fname)) | ||
| 124 | url-directory-index-file) | ||
| 125 | ((= (string-to-char fname) ?/) | ||
| 126 | (if (string= (substring fname -1 nil) "/") | ||
| 127 | (concat fname url-directory-index-file) | ||
| 128 | (substring fname 1 nil))) | ||
| 129 | (t | ||
| 130 | (if (string= (substring fname -1 nil) "/") | ||
| 131 | (concat fname url-directory-index-file) | ||
| 132 | fname)))) | ||
| 133 | (and fname | ||
| 134 | (expand-file-name fname | ||
| 135 | (expand-file-name | ||
| 136 | (mapconcat 'identity host-components "/") | ||
| 137 | url-cache-directory)))))) | ||
| 138 | |||
| 139 | (defun url-cache-create-filename-using-md5 (url) | ||
| 140 | "Create a cached filename using MD5. | ||
| 141 | Very fast if you have an `md5' primitive function, suitably fast otherwise." | ||
| 142 | (require 'md5) | ||
| 143 | (if url | ||
| 144 | (let* ((url (if (vectorp url) (url-recreate-url url) url)) | ||
| 145 | (checksum (md5 url)) | ||
| 146 | (urlobj (url-generic-parse-url url)) | ||
| 147 | (protocol (url-type urlobj)) | ||
| 148 | (hostname (url-host urlobj)) | ||
| 149 | (host-components | ||
| 150 | (cons | ||
| 151 | (user-real-login-name) | ||
| 152 | (cons (or protocol "file") | ||
| 153 | (nreverse | ||
| 154 | (delq nil | ||
| 155 | (split-string (or hostname "localhost") | ||
| 156 | (eval-when-compile | ||
| 157 | (regexp-quote ".")))))))) | ||
| 158 | (fname (url-filename urlobj))) | ||
| 159 | (and fname | ||
| 160 | (expand-file-name checksum | ||
| 161 | (expand-file-name | ||
| 162 | (mapconcat 'identity host-components "/") | ||
| 163 | url-cache-directory)))))) | ||
| 164 | |||
| 165 | (defcustom url-cache-creation-function 'url-cache-create-filename-using-md5 | ||
| 166 | "*What function to use to create a cached filename." | ||
| 167 | :type '(choice (const :tag "MD5 of filename (low collision rate)" | ||
| 168 | :value url-cache-create-filename-using-md5) | ||
| 169 | (const :tag "Human readable filenames (higher collision rate)" | ||
| 170 | :value url-cache-create-filename-human-readable) | ||
| 171 | (function :tag "Other")) | ||
| 172 | :group 'url-cache) | ||
| 173 | |||
| 174 | (defun url-cache-create-filename (url) | ||
| 175 | (funcall url-cache-creation-function url)) | ||
| 176 | |||
| 177 | ;;;###autoload | ||
| 178 | (defun url-cache-extract (fnam) | ||
| 179 | "Extract FNAM from the local disk cache" | ||
| 180 | (erase-buffer) | ||
| 181 | (insert-file-contents-literally fnam)) | ||
| 182 | |||
| 183 | ;;;###autoload | ||
| 184 | (defun url-cache-expired (url mod) | ||
| 185 | "Return t iff a cached file has expired." | ||
| 186 | (let* ((urlobj (if (vectorp url) url (url-generic-parse-url url))) | ||
| 187 | (type (url-type urlobj))) | ||
| 188 | (cond | ||
| 189 | (url-standalone-mode | ||
| 190 | (not (file-exists-p (url-cache-create-filename url)))) | ||
| 191 | ((string= type "http") | ||
| 192 | t) | ||
| 193 | ((member type '("file" "ftp")) | ||
| 194 | (if (or (equal mod '(0 0)) (not mod)) | ||
| 195 | t | ||
| 196 | (or (> (nth 0 mod) (nth 0 (current-time))) | ||
| 197 | (> (nth 1 mod) (nth 1 (current-time)))))) | ||
| 198 | (t nil)))) | ||
| 199 | |||
| 200 | (provide 'url-cache) | ||
| 201 | |||
| 202 | ;;; arch-tag: 95b050a6-8e81-4f23-8e63-191b9d1d657c | ||
diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el new file mode 100644 index 00000000000..9f7db867597 --- /dev/null +++ b/lisp/url/url-cookie.el | |||
| @@ -0,0 +1,466 @@ | |||
| 1 | ;;; url-cookie.el --- Netscape Cookie support | ||
| 2 | |||
| 3 | ;; Copyright (c) 1996 - 1999,2004 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Keywords: comm, data, processes, hypermedia | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | ;; | ||
| 9 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;; any later version. | ||
| 13 | ;; | ||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | ;; | ||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;; Boston, MA 02111-1307, USA. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | |||
| 26 | ;;; Code: | ||
| 27 | |||
| 28 | (require 'timezone) | ||
| 29 | (require 'url-util) | ||
| 30 | (require 'url-parse) | ||
| 31 | (eval-when-compile (require 'cl)) | ||
| 32 | |||
| 33 | ;; See http://home.netscape.com/newsref/std/cookie_spec.html for the | ||
| 34 | ;; 'open standard' defining this crap. | ||
| 35 | ;; | ||
| 36 | ;; A cookie is stored internally as a vector of 7 slots | ||
| 37 | ;; [ 'cookie name value expires path domain secure ] | ||
| 38 | |||
| 39 | (defsubst url-cookie-name (cookie) (aref cookie 1)) | ||
| 40 | (defsubst url-cookie-value (cookie) (aref cookie 2)) | ||
| 41 | (defsubst url-cookie-expires (cookie) (aref cookie 3)) | ||
| 42 | (defsubst url-cookie-path (cookie) (aref cookie 4)) | ||
| 43 | (defsubst url-cookie-domain (cookie) (aref cookie 5)) | ||
| 44 | (defsubst url-cookie-secure (cookie) (aref cookie 6)) | ||
| 45 | |||
| 46 | (defsubst url-cookie-set-name (cookie val) (aset cookie 1 val)) | ||
| 47 | (defsubst url-cookie-set-value (cookie val) (aset cookie 2 val)) | ||
| 48 | (defsubst url-cookie-set-expires (cookie val) (aset cookie 3 val)) | ||
| 49 | (defsubst url-cookie-set-path (cookie val) (aset cookie 4 val)) | ||
| 50 | (defsubst url-cookie-set-domain (cookie val) (aset cookie 5 val)) | ||
| 51 | (defsubst url-cookie-set-secure (cookie val) (aset cookie 6 val)) | ||
| 52 | (defsubst url-cookie-retrieve-arg (key args) (nth 1 (memq key args))) | ||
| 53 | |||
| 54 | (defsubst url-cookie-create (&rest args) | ||
| 55 | (let ((retval (make-vector 7 nil))) | ||
| 56 | (aset retval 0 'cookie) | ||
| 57 | (url-cookie-set-name retval (url-cookie-retrieve-arg :name args)) | ||
| 58 | (url-cookie-set-value retval (url-cookie-retrieve-arg :value args)) | ||
| 59 | (url-cookie-set-expires retval (url-cookie-retrieve-arg :expires args)) | ||
| 60 | (url-cookie-set-path retval (url-cookie-retrieve-arg :path args)) | ||
| 61 | (url-cookie-set-domain retval (url-cookie-retrieve-arg :domain args)) | ||
| 62 | (url-cookie-set-secure retval (url-cookie-retrieve-arg :secure args)) | ||
| 63 | retval)) | ||
| 64 | |||
| 65 | (defun url-cookie-p (obj) | ||
| 66 | (and (vectorp obj) (= (length obj) 7) (eq (aref obj 0) 'cookie))) | ||
| 67 | |||
| 68 | (defgroup url-cookie nil | ||
| 69 | "URL cookies" | ||
| 70 | :prefix "url-" | ||
| 71 | :prefix "url-cookie-" | ||
| 72 | :group 'url) | ||
| 73 | |||
| 74 | (defvar url-cookie-storage nil "Where cookies are stored.") | ||
| 75 | (defvar url-cookie-secure-storage nil "Where secure cookies are stored.") | ||
| 76 | (defcustom url-cookie-file nil "*Where cookies are stored on disk." | ||
| 77 | :type '(choice (const :tag "Default" :value nil) file) | ||
| 78 | :group 'url-file | ||
| 79 | :group 'url-cookie) | ||
| 80 | |||
| 81 | (defcustom url-cookie-confirmation nil | ||
| 82 | "*If non-nil, confirmation by the user is required to accept HTTP cookies." | ||
| 83 | :type 'boolean | ||
| 84 | :group 'url-cookie) | ||
| 85 | |||
| 86 | (defcustom url-cookie-multiple-line nil | ||
| 87 | "*If nil, HTTP requests put all cookies for the server on one line. | ||
| 88 | Some web servers, such as http://www.hotmail.com/, only accept cookies | ||
| 89 | when they are on one line. This is broken behaviour, but just try | ||
| 90 | telling Microsoft that.") | ||
| 91 | |||
| 92 | (defvar url-cookies-changed-since-last-save nil | ||
| 93 | "Whether the cookies list has changed since the last save operation.") | ||
| 94 | |||
| 95 | ;;;###autoload | ||
| 96 | (defun url-cookie-parse-file (&optional fname) | ||
| 97 | (setq fname (or fname url-cookie-file)) | ||
| 98 | (condition-case () | ||
| 99 | (load fname nil t) | ||
| 100 | (error (message "Could not load cookie file %s" fname)))) | ||
| 101 | |||
| 102 | (defun url-cookie-clean-up (&optional secure) | ||
| 103 | (let* ( | ||
| 104 | (var (if secure 'url-cookie-secure-storage 'url-cookie-storage)) | ||
| 105 | (val (symbol-value var)) | ||
| 106 | (cur nil) | ||
| 107 | (new nil) | ||
| 108 | (cookies nil) | ||
| 109 | (cur-cookie nil) | ||
| 110 | (new-cookies nil) | ||
| 111 | ) | ||
| 112 | (while val | ||
| 113 | (setq cur (car val) | ||
| 114 | val (cdr val) | ||
| 115 | new-cookies nil | ||
| 116 | cookies (cdr cur)) | ||
| 117 | (while cookies | ||
| 118 | (setq cur-cookie (car cookies) | ||
| 119 | cookies (cdr cookies)) | ||
| 120 | (if (or (not (url-cookie-p cur-cookie)) | ||
| 121 | (url-cookie-expired-p cur-cookie) | ||
| 122 | (null (url-cookie-expires cur-cookie))) | ||
| 123 | nil | ||
| 124 | (setq new-cookies (cons cur-cookie new-cookies)))) | ||
| 125 | (if (not new-cookies) | ||
| 126 | nil | ||
| 127 | (setcdr cur new-cookies) | ||
| 128 | (setq new (cons cur new)))) | ||
| 129 | (set var new))) | ||
| 130 | |||
| 131 | ;;;###autoload | ||
| 132 | (defun url-cookie-write-file (&optional fname) | ||
| 133 | (setq fname (or fname url-cookie-file)) | ||
| 134 | (cond | ||
| 135 | ((not url-cookies-changed-since-last-save) nil) | ||
| 136 | ((not (file-writable-p fname)) | ||
| 137 | (message "Cookies file %s (see variable `url-cookie-file') is unwritable." fname)) | ||
| 138 | (t | ||
| 139 | (url-cookie-clean-up) | ||
| 140 | (url-cookie-clean-up t) | ||
| 141 | (save-excursion | ||
| 142 | (set-buffer (get-buffer-create " *cookies*")) | ||
| 143 | (erase-buffer) | ||
| 144 | (fundamental-mode) | ||
| 145 | (insert ";; Emacs-W3 HTTP cookies file\n" | ||
| 146 | ";; Automatically generated file!!! DO NOT EDIT!!!\n\n" | ||
| 147 | "(setq url-cookie-storage\n '") | ||
| 148 | (pp url-cookie-storage (current-buffer)) | ||
| 149 | (insert ")\n(setq url-cookie-secure-storage\n '") | ||
| 150 | (pp url-cookie-secure-storage (current-buffer)) | ||
| 151 | (insert ")\n") | ||
| 152 | (write-file fname) | ||
| 153 | (kill-buffer (current-buffer)))))) | ||
| 154 | |||
| 155 | (defun url-cookie-store (name value &optional expires domain path secure) | ||
| 156 | "Store a netscape-style cookie." | ||
| 157 | (let* ((storage (if secure url-cookie-secure-storage url-cookie-storage)) | ||
| 158 | (tmp storage) | ||
| 159 | (cur nil) | ||
| 160 | (found-domain nil)) | ||
| 161 | |||
| 162 | ;; First, look for a matching domain | ||
| 163 | (setq found-domain (assoc domain storage)) | ||
| 164 | |||
| 165 | (if found-domain | ||
| 166 | ;; Need to either stick the new cookie in existing domain storage | ||
| 167 | ;; or possibly replace an existing cookie if the names match. | ||
| 168 | (progn | ||
| 169 | (setq storage (cdr found-domain) | ||
| 170 | tmp nil) | ||
| 171 | (while storage | ||
| 172 | (setq cur (car storage) | ||
| 173 | storage (cdr storage)) | ||
| 174 | (if (and (equal path (url-cookie-path cur)) | ||
| 175 | (equal name (url-cookie-name cur))) | ||
| 176 | (progn | ||
| 177 | (url-cookie-set-expires cur expires) | ||
| 178 | (url-cookie-set-value cur value) | ||
| 179 | (setq tmp t)))) | ||
| 180 | (if (not tmp) | ||
| 181 | ;; New cookie | ||
| 182 | (setcdr found-domain (cons | ||
| 183 | (url-cookie-create :name name | ||
| 184 | :value value | ||
| 185 | :expires expires | ||
| 186 | :domain domain | ||
| 187 | :path path | ||
| 188 | :secure secure) | ||
| 189 | (cdr found-domain))))) | ||
| 190 | ;; Need to add a new top-level domain | ||
| 191 | (setq tmp (url-cookie-create :name name | ||
| 192 | :value value | ||
| 193 | :expires expires | ||
| 194 | :domain domain | ||
| 195 | :path path | ||
| 196 | :secure secure)) | ||
| 197 | (cond | ||
| 198 | (storage | ||
| 199 | (setcdr storage (cons (list domain tmp) (cdr storage)))) | ||
| 200 | (secure | ||
| 201 | (setq url-cookie-secure-storage (list (list domain tmp)))) | ||
| 202 | (t | ||
| 203 | (setq url-cookie-storage (list (list domain tmp)))))))) | ||
| 204 | |||
| 205 | (defun url-cookie-expired-p (cookie) | ||
| 206 | (let* ( | ||
| 207 | (exp (url-cookie-expires cookie)) | ||
| 208 | (cur-date (and exp (timezone-parse-date (current-time-string)))) | ||
| 209 | (exp-date (and exp (timezone-parse-date exp))) | ||
| 210 | (cur-greg (and cur-date (timezone-absolute-from-gregorian | ||
| 211 | (string-to-int (aref cur-date 1)) | ||
| 212 | (string-to-int (aref cur-date 2)) | ||
| 213 | (string-to-int (aref cur-date 0))))) | ||
| 214 | (exp-greg (and exp (timezone-absolute-from-gregorian | ||
| 215 | (string-to-int (aref exp-date 1)) | ||
| 216 | (string-to-int (aref exp-date 2)) | ||
| 217 | (string-to-int (aref exp-date 0))))) | ||
| 218 | (diff-in-days (and exp (- cur-greg exp-greg))) | ||
| 219 | ) | ||
| 220 | (cond | ||
| 221 | ((not exp) nil) ; No expiry == expires at browser quit | ||
| 222 | ((< diff-in-days 0) nil) ; Expires sometime after today | ||
| 223 | ((> diff-in-days 0) t) ; Expired before today | ||
| 224 | (t ; Expires sometime today, check times | ||
| 225 | (let* ((cur-time (timezone-parse-time (aref cur-date 3))) | ||
| 226 | (exp-time (timezone-parse-time (aref exp-date 3))) | ||
| 227 | (cur-norm (+ (* 360 (string-to-int (aref cur-time 2))) | ||
| 228 | (* 60 (string-to-int (aref cur-time 1))) | ||
| 229 | (* 1 (string-to-int (aref cur-time 0))))) | ||
| 230 | (exp-norm (+ (* 360 (string-to-int (aref exp-time 2))) | ||
| 231 | (* 60 (string-to-int (aref exp-time 1))) | ||
| 232 | (* 1 (string-to-int (aref exp-time 0)))))) | ||
| 233 | (> (- cur-norm exp-norm) 1)))))) | ||
| 234 | |||
| 235 | ;;;###autoload | ||
| 236 | (defun url-cookie-retrieve (host path &optional secure) | ||
| 237 | "Retrieve all the netscape-style cookies for a specified HOST and PATH." | ||
| 238 | (let ((storage (if secure | ||
| 239 | (append url-cookie-secure-storage url-cookie-storage) | ||
| 240 | url-cookie-storage)) | ||
| 241 | (case-fold-search t) | ||
| 242 | (cookies nil) | ||
| 243 | (cur nil) | ||
| 244 | (retval nil) | ||
| 245 | (path-regexp nil)) | ||
| 246 | (while storage | ||
| 247 | (setq cur (car storage) | ||
| 248 | storage (cdr storage) | ||
| 249 | cookies (cdr cur)) | ||
| 250 | (if (and (car cur) | ||
| 251 | (string-match (concat "^.*" (regexp-quote (car cur)) "$") host)) | ||
| 252 | ;; The domains match - a possible hit! | ||
| 253 | (while cookies | ||
| 254 | (setq cur (car cookies) | ||
| 255 | cookies (cdr cookies) | ||
| 256 | path-regexp (concat "^" (regexp-quote | ||
| 257 | (url-cookie-path cur)))) | ||
| 258 | (if (and (string-match path-regexp path) | ||
| 259 | (not (url-cookie-expired-p cur))) | ||
| 260 | (setq retval (cons cur retval)))))) | ||
| 261 | retval)) | ||
| 262 | |||
| 263 | ;;;###autolaod | ||
| 264 | (defun url-cookie-generate-header-lines (host path secure) | ||
| 265 | (let* ((cookies (url-cookie-retrieve host path secure)) | ||
| 266 | (retval nil) | ||
| 267 | (cur nil) | ||
| 268 | (chunk nil)) | ||
| 269 | ;; Have to sort this for sending most specific cookies first | ||
| 270 | (setq cookies (and cookies | ||
| 271 | (sort cookies | ||
| 272 | (function | ||
| 273 | (lambda (x y) | ||
| 274 | (> (length (url-cookie-path x)) | ||
| 275 | (length (url-cookie-path y)))))))) | ||
| 276 | (while cookies | ||
| 277 | (setq cur (car cookies) | ||
| 278 | cookies (cdr cookies) | ||
| 279 | chunk (format "%s=%s" (url-cookie-name cur) (url-cookie-value cur)) | ||
| 280 | retval (if (and url-cookie-multiple-line | ||
| 281 | (< 80 (+ (length retval) (length chunk) 4))) | ||
| 282 | (concat retval "\r\nCookie: " chunk) | ||
| 283 | (if retval | ||
| 284 | (concat retval "; " chunk) | ||
| 285 | (concat "Cookie: " chunk))))) | ||
| 286 | (if retval | ||
| 287 | (concat retval "\r\n") | ||
| 288 | ""))) | ||
| 289 | |||
| 290 | (defvar url-cookie-two-dot-domains | ||
| 291 | (concat "\\.\\(" | ||
| 292 | (mapconcat 'identity (list "com" "edu" "net" "org" "gov" "mil" "int") | ||
| 293 | "\\|") | ||
| 294 | "\\)$") | ||
| 295 | "A regexp of top level domains that only require two matching | ||
| 296 | '.'s in the domain name in order to set a cookie.") | ||
| 297 | |||
| 298 | (defcustom url-cookie-trusted-urls nil | ||
| 299 | "*A list of regular expressions matching URLs to always accept cookies from." | ||
| 300 | :type '(repeat regexp) | ||
| 301 | :group 'url-cookie) | ||
| 302 | |||
| 303 | (defcustom url-cookie-untrusted-urls nil | ||
| 304 | "*A list of regular expressions matching URLs to never accept cookies from." | ||
| 305 | :type '(repeat regexp) | ||
| 306 | :group 'url-cookie) | ||
| 307 | |||
| 308 | (defun url-cookie-host-can-set-p (host domain) | ||
| 309 | (let ((numdots 0) | ||
| 310 | (tmp domain) | ||
| 311 | (last nil) | ||
| 312 | (case-fold-search t) | ||
| 313 | (mindots 3)) | ||
| 314 | (while (setq last (string-match "\\." domain last)) | ||
| 315 | (setq numdots (1+ numdots) | ||
| 316 | last (1+ last))) | ||
| 317 | (if (string-match url-cookie-two-dot-domains domain) | ||
| 318 | (setq mindots 2)) | ||
| 319 | (cond | ||
| 320 | ((string= host domain) ; Apparently netscape lets you do this | ||
| 321 | t) | ||
| 322 | ((>= numdots mindots) ; We have enough dots in domain name | ||
| 323 | ;; Need to check and make sure the host is actually _in_ the | ||
| 324 | ;; domain it wants to set a cookie for though. | ||
| 325 | (string-match (concat (regexp-quote domain) "$") host)) | ||
| 326 | (t | ||
| 327 | nil)))) | ||
| 328 | |||
| 329 | ;;;###autoload | ||
| 330 | (defun url-cookie-handle-set-cookie (str) | ||
| 331 | (setq url-cookies-changed-since-last-save t) | ||
| 332 | (let* ((args (url-parse-args str t)) | ||
| 333 | (case-fold-search t) | ||
| 334 | (secure (and (assoc-string "secure" args t) t)) | ||
| 335 | (domain (or (cdr-safe (assoc-string "domain" args t)) | ||
| 336 | (url-host url-current-object))) | ||
| 337 | (current-url (url-view-url t)) | ||
| 338 | (trusted url-cookie-trusted-urls) | ||
| 339 | (untrusted url-cookie-untrusted-urls) | ||
| 340 | (expires (cdr-safe (assoc-string "expires" args t))) | ||
| 341 | (path (or (cdr-safe (assoc-string "path" args t)) | ||
| 342 | (file-name-directory | ||
| 343 | (url-filename url-current-object)))) | ||
| 344 | (rest nil)) | ||
| 345 | (while args | ||
| 346 | (if (not (member (downcase (car (car args))) | ||
| 347 | '("secure" "domain" "expires" "path"))) | ||
| 348 | (setq rest (cons (car args) rest))) | ||
| 349 | (setq args (cdr args))) | ||
| 350 | |||
| 351 | ;; Sometimes we get dates that the timezone package cannot handle very | ||
| 352 | ;; gracefully - take care of this here, instead of in url-cookie-expired-p | ||
| 353 | ;; to speed things up. | ||
| 354 | (if (and expires | ||
| 355 | (string-match | ||
| 356 | (concat "^[^,]+, +\\(..\\)-\\(...\\)-\\(..\\) +" | ||
| 357 | "\\(..:..:..\\) +\\[*\\([^\]]+\\)\\]*$") | ||
| 358 | expires)) | ||
| 359 | (setq expires (concat (match-string 1 expires) " " | ||
| 360 | (match-string 2 expires) " " | ||
| 361 | (match-string 3 expires) " " | ||
| 362 | (match-string 4 expires) " [" | ||
| 363 | (match-string 5 expires) "]"))) | ||
| 364 | |||
| 365 | ;; This one is for older Emacs/XEmacs variants that don't | ||
| 366 | ;; understand this format without tenths of a second in it. | ||
| 367 | ;; Wednesday, 30-Dec-2037 16:00:00 GMT | ||
| 368 | ;; - vs - | ||
| 369 | ;; Wednesday, 30-Dec-2037 16:00:00.00 GMT | ||
| 370 | (if (and expires | ||
| 371 | (string-match | ||
| 372 | "\\([0-9]+\\)-\\([A-Za-z]+\\)-\\([0-9]+\\)[ \t]+\\([0-9]+:[0-9]+:[0-9]+\\)\\(\\.[0-9]+\\)*[ \t]+\\([-+a-zA-Z0-9]+\\)" | ||
| 373 | expires)) | ||
| 374 | (setq expires (concat (match-string 1 expires) "-" ; day | ||
| 375 | (match-string 2 expires) "-" ; month | ||
| 376 | (match-string 3 expires) " " ; year | ||
| 377 | (match-string 4 expires) ".00 " ; hour:minutes:seconds | ||
| 378 | (match-string 6 expires)))) ":" ; timezone | ||
| 379 | |||
| 380 | (while (consp trusted) | ||
| 381 | (if (string-match (car trusted) current-url) | ||
| 382 | (setq trusted (- (match-end 0) (match-beginning 0))) | ||
| 383 | (pop trusted))) | ||
| 384 | (while (consp untrusted) | ||
| 385 | (if (string-match (car untrusted) current-url) | ||
| 386 | (setq untrusted (- (match-end 0) (match-beginning 0))) | ||
| 387 | (pop untrusted))) | ||
| 388 | (if (and trusted untrusted) | ||
| 389 | ;; Choose the more specific match | ||
| 390 | (if (> trusted untrusted) | ||
| 391 | (setq untrusted nil) | ||
| 392 | (setq trusted nil))) | ||
| 393 | (cond | ||
| 394 | (untrusted | ||
| 395 | ;; The site was explicity marked as untrusted by the user | ||
| 396 | nil) | ||
| 397 | ((or (eq url-privacy-level 'paranoid) | ||
| 398 | (and (listp url-privacy-level) (memq 'cookies url-privacy-level))) | ||
| 399 | ;; user never wants cookies | ||
| 400 | nil) | ||
| 401 | ((and url-cookie-confirmation | ||
| 402 | (not trusted) | ||
| 403 | (save-window-excursion | ||
| 404 | (with-output-to-temp-buffer "*Cookie Warning*" | ||
| 405 | (mapcar | ||
| 406 | (function | ||
| 407 | (lambda (x) | ||
| 408 | (princ (format "%s - %s" (car x) (cdr x))))) rest)) | ||
| 409 | (prog1 | ||
| 410 | (not (funcall url-confirmation-func | ||
| 411 | (format "Allow %s to set these cookies? " | ||
| 412 | (url-host url-current-object)))) | ||
| 413 | (if (get-buffer "*Cookie Warning*") | ||
| 414 | (kill-buffer "*Cookie Warning*"))))) | ||
| 415 | ;; user wants to be asked, and declined. | ||
| 416 | nil) | ||
| 417 | ((url-cookie-host-can-set-p (url-host url-current-object) domain) | ||
| 418 | ;; Cookie is accepted by the user, and passes our security checks | ||
| 419 | (let ((cur nil)) | ||
| 420 | (while rest | ||
| 421 | (setq cur (pop rest)) | ||
| 422 | (url-cookie-store (car cur) (cdr cur) | ||
| 423 | expires domain path secure)))) | ||
| 424 | (t | ||
| 425 | (message "%s tried to set a cookie for domain %s - rejected." | ||
| 426 | (url-host url-current-object) domain))))) | ||
| 427 | |||
| 428 | (defvar url-cookie-timer nil) | ||
| 429 | |||
| 430 | (defcustom url-cookie-save-interval 3600 | ||
| 431 | "*The number of seconds between automatic saves of cookies. | ||
| 432 | Default is 1 hour. Note that if you change this variable outside of | ||
| 433 | the `customize' interface after `url-do-setup' has been run, you need | ||
| 434 | to run the `url-cookie-setup-save-timer' function manually." | ||
| 435 | :set (function (lambda (var val) | ||
| 436 | (set-default var val) | ||
| 437 | (and (featurep 'url) | ||
| 438 | (fboundp 'url-cookie-setup-save-timer) | ||
| 439 | (url-cookie-setup-save-timer)))) | ||
| 440 | :type 'integer | ||
| 441 | :group 'url) | ||
| 442 | |||
| 443 | ;;;###autoload | ||
| 444 | (defun url-cookie-setup-save-timer () | ||
| 445 | "Reset the cookie saver timer." | ||
| 446 | (interactive) | ||
| 447 | (ignore-errors | ||
| 448 | (cond ((fboundp 'cancel-timer) (cancel-timer url-cookie-timer)) | ||
| 449 | ((fboundp 'delete-itimer) (delete-itimer url-cookie-timer)))) | ||
| 450 | (setq url-cookie-timer nil) | ||
| 451 | (if url-cookie-save-interval | ||
| 452 | (setq url-cookie-timer | ||
| 453 | (cond | ||
| 454 | ((fboundp 'run-at-time) | ||
| 455 | (run-at-time url-cookie-save-interval | ||
| 456 | url-cookie-save-interval | ||
| 457 | 'url-cookie-write-file)) | ||
| 458 | ((fboundp 'start-itimer) | ||
| 459 | (start-itimer "url-cookie-saver" 'url-cookie-write-file | ||
| 460 | url-cookie-save-interval | ||
| 461 | url-cookie-save-interval)))))) | ||
| 462 | |||
| 463 | (provide 'url-cookie) | ||
| 464 | |||
| 465 | ;; arch-tag: 2568751b-6452-4398-aa2d-303edadb54d7 | ||
| 466 | ;;; url-cookie.el ends here | ||
diff --git a/lisp/url/url-dired.el b/lisp/url/url-dired.el new file mode 100644 index 00000000000..73307412e1e --- /dev/null +++ b/lisp/url/url-dired.el | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | ;;; url-dired.el --- URL Dired minor mode | ||
| 2 | ;; Keywords: comm, files | ||
| 3 | |||
| 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5 | ;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc. | ||
| 6 | ;;; | ||
| 7 | ;;; This file is part of GNU Emacs. | ||
| 8 | ;;; | ||
| 9 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;;; any later version. | ||
| 13 | ;;; | ||
| 14 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;;; GNU General Public License for more details. | ||
| 18 | ;;; | ||
| 19 | ;;; You should have received a copy of the GNU General Public License | ||
| 20 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;;; Boston, MA 02111-1307, USA. | ||
| 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 24 | |||
| 25 | (autoload 'w3-fetch "w3") | ||
| 26 | (autoload 'w3-open-local "w3") | ||
| 27 | (autoload 'dired-get-filename "dired") | ||
| 28 | |||
| 29 | (defvar url-dired-minor-mode-map | ||
| 30 | (let ((map (make-sparse-keymap))) | ||
| 31 | (define-key map "\C-m" 'url-dired-find-file) | ||
| 32 | (if (featurep 'xemacs) | ||
| 33 | (define-key map [button2] 'url-dired-find-file-mouse) | ||
| 34 | (define-key map [mouse-2] 'url-dired-find-file-mouse)) | ||
| 35 | map) | ||
| 36 | "Keymap used when browsing directories.") | ||
| 37 | |||
| 38 | (defvar url-dired-minor-mode nil | ||
| 39 | "Whether we are in url-dired-minor-mode") | ||
| 40 | |||
| 41 | (make-variable-buffer-local 'url-dired-minor-mode) | ||
| 42 | |||
| 43 | (defun url-dired-find-file () | ||
| 44 | "In dired, visit the file or directory named on this line, using Emacs-W3." | ||
| 45 | (interactive) | ||
| 46 | (let ((filename (dired-get-filename))) | ||
| 47 | (cond ((string-match "/\\(.*@.*\\):\\(/.*\\)" filename) | ||
| 48 | (w3-fetch (concat "file://" (match-string 1 filename) (match-string 2 filename)))) | ||
| 49 | (t | ||
| 50 | (w3-open-local filename))))) | ||
| 51 | |||
| 52 | (defun url-dired-find-file-mouse (event) | ||
| 53 | "In dired, visit the file or directory name you click on, using Emacs-W3." | ||
| 54 | (interactive "@e") | ||
| 55 | (mouse-set-point event) | ||
| 56 | (url-dired-find-file)) | ||
| 57 | |||
| 58 | (defun url-dired-minor-mode (&optional arg) | ||
| 59 | "Minor mode for directory browsing with Emacs-W3." | ||
| 60 | (interactive "P") | ||
| 61 | (cond | ||
| 62 | ((null arg) | ||
| 63 | (setq url-dired-minor-mode (not url-dired-minor-mode))) | ||
| 64 | ((equal 0 arg) | ||
| 65 | (setq url-dired-minor-mode nil)) | ||
| 66 | (t | ||
| 67 | (setq url-dired-minor-mode t)))) | ||
| 68 | |||
| 69 | (if (not (fboundp 'add-minor-mode)) | ||
| 70 | (defun add-minor-mode (toggle name &optional keymap after toggle-fun) | ||
| 71 | "Add a minor mode to `minor-mode-alist' and `minor-mode-map-alist'. | ||
| 72 | TOGGLE is a symbol which is used as the variable which toggle the minor mode, | ||
| 73 | NAME is the name that should appear in the modeline (it should be a string | ||
| 74 | beginning with a space), KEYMAP is a keymap to make active when the minor | ||
| 75 | mode is active, and AFTER is the toggling symbol used for another minor | ||
| 76 | mode. If AFTER is non-nil, then it is used to position the new mode in the | ||
| 77 | minor-mode alists. TOGGLE-FUN specifies an interactive function that | ||
| 78 | is called to toggle the mode on and off; this affects what appens when | ||
| 79 | button2 is pressed on the mode, and when button3 is pressed somewhere | ||
| 80 | in the list of modes. If TOGGLE-FUN is nil and TOGGLE names an | ||
| 81 | interactive function, TOGGLE is used as the toggle function. | ||
| 82 | |||
| 83 | Example: (add-minor-mode 'view-minor-mode \" View\" view-mode-map)" | ||
| 84 | (if (not (assq toggle minor-mode-alist)) | ||
| 85 | (setq minor-mode-alist (cons (list toggle name) minor-mode-alist))) | ||
| 86 | (if (and keymap (not (assq toggle minor-mode-map-alist))) | ||
| 87 | (setq minor-mode-map-alist (cons (cons toggle keymap) | ||
| 88 | minor-mode-map-alist))))) | ||
| 89 | |||
| 90 | (add-minor-mode 'url-dired-minor-mode " URL" url-dired-minor-mode-map) | ||
| 91 | |||
| 92 | (defun url-find-file-dired (dir) | ||
| 93 | "\"Edit\" directory DIR, but with additional URL-friendly bindings." | ||
| 94 | (interactive "DURL Dired (directory): ") | ||
| 95 | (find-file dir) | ||
| 96 | (url-dired-minor-mode t)) | ||
| 97 | |||
| 98 | (provide 'url-dired) | ||
| 99 | |||
| 100 | ;;; arch-tag: 2694f21a-43e1-4391-b3cb-cf6e5349f15f | ||
diff --git a/lisp/url/url-file.el b/lisp/url/url-file.el index 77c2e74555f..0aa23acc0ec 100644 --- a/lisp/url/url-file.el +++ b/lisp/url/url-file.el | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | ;;; url-file.el --- File retrieval code | 1 | ;;; url-file.el --- File retrieval code |
| 2 | 2 | ||
| 3 | ;; Copyright (c) 1996 - 1999,2004 Free Software Foundation, Inc. | 3 | ;; Copyright (c) 1996 - 1999,2004 Free Software Foundation, Inc. |
| 4 | ;; Copyright (c) 1993 - 1996 by William M. Perry <wmperry@cs.indiana.edu> | ||
| 5 | 4 | ||
| 6 | ;; Keywords: comm, data, processes | 5 | ;; Keywords: comm, data, processes |
| 7 | 6 | ||
diff --git a/lisp/url/url-ftp.el b/lisp/url/url-ftp.el new file mode 100644 index 00000000000..4346f3910b1 --- /dev/null +++ b/lisp/url/url-ftp.el | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | ;;; url-ftp.el --- FTP wrapper | ||
| 2 | ;; Keywords: comm, data, processes | ||
| 3 | |||
| 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5 | ;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc. | ||
| 6 | ;;; | ||
| 7 | ;;; This file is part of GNU Emacs. | ||
| 8 | ;;; | ||
| 9 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;;; any later version. | ||
| 13 | ;;; | ||
| 14 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;;; GNU General Public License for more details. | ||
| 18 | ;;; | ||
| 19 | ;;; You should have received a copy of the GNU General Public License | ||
| 20 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;;; Boston, MA 02111-1307, USA. | ||
| 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 24 | |||
| 25 | ;; We knew not what we did when we overloaded 'file' to mean 'file' | ||
| 26 | ;; and 'ftp' back in the dark ages of the web. | ||
| 27 | ;; | ||
| 28 | ;; This stub file is just here to please the auto-scheme-loading code | ||
| 29 | ;; in url-methods.el and just maps everything onto the code in | ||
| 30 | ;; url-file. | ||
| 31 | |||
| 32 | (require 'url-parse) | ||
| 33 | (require 'url-file) | ||
| 34 | |||
| 35 | (defconst url-ftp-default-port 21 "Default FTP port.") | ||
| 36 | (defconst url-ftp-asynchronous-p t "FTP transfers are asynchronous.") | ||
| 37 | (defalias 'url-ftp-expand-file-name 'url-default-expander) | ||
| 38 | (defalias 'url-ftp 'url-file) | ||
| 39 | |||
| 40 | (provide 'url-ftp) | ||
| 41 | |||
| 42 | ;;; arch-tag: 9c3e70c4-350f-4d4a-bb51-a1e9b459e7dc | ||
diff --git a/lisp/url/url-gw.el b/lisp/url/url-gw.el new file mode 100644 index 00000000000..608827d7cee --- /dev/null +++ b/lisp/url/url-gw.el | |||
| @@ -0,0 +1,268 @@ | |||
| 1 | ;;; url-gw.el --- Gateway munging for URL loading | ||
| 2 | ;; Author: Bill Perry <wmperry@gnu.org> | ||
| 3 | ;; Keywords: comm, data, processes | ||
| 4 | |||
| 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 6 | ;;; Copyright (c) 1997, 1998, 2004 Free Software Foundation, Inc. | ||
| 7 | ;;; | ||
| 8 | ;;; This file is part of GNU Emacs. | ||
| 9 | ;;; | ||
| 10 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 11 | ;;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 13 | ;;; any later version. | ||
| 14 | ;;; | ||
| 15 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;;; GNU General Public License for more details. | ||
| 19 | ;;; | ||
| 20 | ;;; You should have received a copy of the GNU General Public License | ||
| 21 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 22 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 23 | ;;; Boston, MA 02111-1307, USA. | ||
| 24 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 25 | (eval-when-compile (require 'cl)) | ||
| 26 | (require 'url-vars) | ||
| 27 | |||
| 28 | ;; Fixme: support SSH explicitly or via a url-gateway-rlogin-program? | ||
| 29 | |||
| 30 | (autoload 'socks-open-network-stream "socks") | ||
| 31 | (autoload 'open-ssl-stream "ssl") | ||
| 32 | (autoload 'open-tls-stream "tls") | ||
| 33 | |||
| 34 | (defgroup url-gateway nil | ||
| 35 | "URL gateway variables" | ||
| 36 | :group 'url) | ||
| 37 | |||
| 38 | (defcustom url-gateway-local-host-regexp nil | ||
| 39 | "*A regular expression specifying local hostnames/machines." | ||
| 40 | :type '(choice (const nil) regexp) | ||
| 41 | :group 'url-gateway) | ||
| 42 | |||
| 43 | (defcustom url-gateway-prompt-pattern | ||
| 44 | "^[^#$%>;]*[#$%>;] *" ;; "bash\\|\$ *\r?$\\|> *\r?" | ||
| 45 | "*A regular expression matching a shell prompt." | ||
| 46 | :type 'regexp | ||
| 47 | :group 'url-gateway) | ||
| 48 | |||
| 49 | (defcustom url-gateway-rlogin-host nil | ||
| 50 | "*What hostname to actually rlog into before doing a telnet." | ||
| 51 | :type '(choice (const nil) string) | ||
| 52 | :group 'url-gateway) | ||
| 53 | |||
| 54 | (defcustom url-gateway-rlogin-user-name nil | ||
| 55 | "*Username to log into the remote machine with when using rlogin." | ||
| 56 | :type '(choice (const nil) string) | ||
| 57 | :group 'url-gateway) | ||
| 58 | |||
| 59 | (defcustom url-gateway-rlogin-parameters '("telnet" "-8") | ||
| 60 | "*Parameters to `url-open-rlogin'. | ||
| 61 | This list will be used as the parameter list given to rsh." | ||
| 62 | :type '(repeat string) | ||
| 63 | :group 'url-gateway) | ||
| 64 | |||
| 65 | (defcustom url-gateway-telnet-host nil | ||
| 66 | "*What hostname to actually login to before doing a telnet." | ||
| 67 | :type '(choice (const nil) string) | ||
| 68 | :group 'url-gateway) | ||
| 69 | |||
| 70 | (defcustom url-gateway-telnet-parameters '("exec" "telnet" "-8") | ||
| 71 | "*Parameters to `url-open-telnet'. | ||
| 72 | This list will be executed as a command after logging in via telnet." | ||
| 73 | :type '(repeat string) | ||
| 74 | :group 'url-gateway) | ||
| 75 | |||
| 76 | (defcustom url-gateway-telnet-login-prompt "^\r*.?login:" | ||
| 77 | "*Prompt that tells us we should send our username when loggin in w/telnet." | ||
| 78 | :type 'regexp | ||
| 79 | :group 'url-gateway) | ||
| 80 | |||
| 81 | (defcustom url-gateway-telnet-password-prompt "^\r*.?password:" | ||
| 82 | "*Prompt that tells us we should send our password when loggin in w/telnet." | ||
| 83 | :type 'regexp | ||
| 84 | :group 'url-gateway) | ||
| 85 | |||
| 86 | (defcustom url-gateway-telnet-user-name nil | ||
| 87 | "User name to log in via telnet with." | ||
| 88 | :type '(choice (const nil) string) | ||
| 89 | :group 'url-gateway) | ||
| 90 | |||
| 91 | (defcustom url-gateway-telnet-password nil | ||
| 92 | "Password to use to log in via telnet with." | ||
| 93 | :type '(choice (const nil) string) | ||
| 94 | :group 'url-gateway) | ||
| 95 | |||
| 96 | (defcustom url-gateway-broken-resolution nil | ||
| 97 | "*Whether to use nslookup to resolve hostnames. | ||
| 98 | This should be used when your version of Emacs cannot correctly use DNS, | ||
| 99 | but your machine can. This usually happens if you are running a statically | ||
| 100 | linked Emacs under SunOS 4.x" | ||
| 101 | :type 'boolean | ||
| 102 | :group 'url-gateway) | ||
| 103 | |||
| 104 | (defcustom url-gateway-nslookup-program "nslookup" | ||
| 105 | "*If non-NIL then a string naming nslookup program." | ||
| 106 | :type '(choice (const :tag "None" :value nil) string) | ||
| 107 | :group 'url-gateway) | ||
| 108 | |||
| 109 | ;; Stolen from ange-ftp | ||
| 110 | ;;;###autoload | ||
| 111 | (defun url-gateway-nslookup-host (host) | ||
| 112 | "Attempt to resolve the given HOST using nslookup if possible." | ||
| 113 | (interactive "sHost: ") | ||
| 114 | (if url-gateway-nslookup-program | ||
| 115 | (let ((proc (start-process " *nslookup*" " *nslookup*" | ||
| 116 | url-gateway-nslookup-program host)) | ||
| 117 | (res host)) | ||
| 118 | (process-kill-without-query proc) | ||
| 119 | (save-excursion | ||
| 120 | (set-buffer (process-buffer proc)) | ||
| 121 | (while (memq (process-status proc) '(run open)) | ||
| 122 | (accept-process-output proc)) | ||
| 123 | (goto-char (point-min)) | ||
| 124 | (if (re-search-forward "Name:.*\nAddress: *\\(.*\\)$" nil t) | ||
| 125 | (setq res (buffer-substring (match-beginning 1) | ||
| 126 | (match-end 1)))) | ||
| 127 | (kill-buffer (current-buffer))) | ||
| 128 | res) | ||
| 129 | host)) | ||
| 130 | |||
| 131 | ;; Stolen from red gnus nntp.el | ||
| 132 | (defun url-wait-for-string (regexp proc) | ||
| 133 | "Wait until string matching REGEXP arrives in process PROC's buffer." | ||
| 134 | (let ((buf (current-buffer))) | ||
| 135 | (goto-char (point-min)) | ||
| 136 | (while (not (re-search-forward regexp nil t)) | ||
| 137 | (accept-process-output proc) | ||
| 138 | (set-buffer buf) | ||
| 139 | (goto-char (point-min))))) | ||
| 140 | |||
| 141 | ;; Stolen from red gnus nntp.el | ||
| 142 | (defun url-open-rlogin (name buffer host service) | ||
| 143 | "Open a connection using rsh." | ||
| 144 | (if (not (stringp service)) | ||
| 145 | (setq service (int-to-string service))) | ||
| 146 | (let ((proc (if url-gateway-rlogin-user-name | ||
| 147 | (start-process | ||
| 148 | name buffer "rsh" | ||
| 149 | url-gateway-rlogin-host "-l" url-gateway-rlogin-user-name | ||
| 150 | (mapconcat 'identity | ||
| 151 | (append url-gateway-rlogin-parameters | ||
| 152 | (list host service)) " ")) | ||
| 153 | (start-process | ||
| 154 | name buffer "rsh" url-gateway-rlogin-host | ||
| 155 | (mapconcat 'identity | ||
| 156 | (append url-gateway-rlogin-parameters | ||
| 157 | (list host service)) | ||
| 158 | " "))))) | ||
| 159 | (set-buffer buffer) | ||
| 160 | (url-wait-for-string "^\r*200" proc) | ||
| 161 | (beginning-of-line) | ||
| 162 | (delete-region (point-min) (point)) | ||
| 163 | proc)) | ||
| 164 | |||
| 165 | ;; Stolen from red gnus nntp.el | ||
| 166 | (defun url-open-telnet (name buffer host service) | ||
| 167 | (if (not (stringp service)) | ||
| 168 | (setq service (int-to-string service))) | ||
| 169 | (save-excursion | ||
| 170 | (set-buffer (get-buffer-create buffer)) | ||
| 171 | (erase-buffer) | ||
| 172 | (let ((proc (start-process name buffer "telnet" "-8")) | ||
| 173 | (case-fold-search t)) | ||
| 174 | (when (memq (process-status proc) '(open run)) | ||
| 175 | (process-send-string proc "set escape \^X\n") | ||
| 176 | (process-send-string proc (concat | ||
| 177 | "open " url-gateway-telnet-host "\n")) | ||
| 178 | (url-wait-for-string url-gateway-telnet-login-prompt proc) | ||
| 179 | (process-send-string | ||
| 180 | proc (concat | ||
| 181 | (or url-gateway-telnet-user-name | ||
| 182 | (setq url-gateway-telnet-user-name (read-string "login: "))) | ||
| 183 | "\n")) | ||
| 184 | (url-wait-for-string url-gateway-telnet-password-prompt proc) | ||
| 185 | (process-send-string | ||
| 186 | proc (concat | ||
| 187 | (or url-gateway-telnet-password | ||
| 188 | (setq url-gateway-telnet-password | ||
| 189 | (funcall url-passwd-entry-func "Password: "))) | ||
| 190 | "\n")) | ||
| 191 | (erase-buffer) | ||
| 192 | (url-wait-for-string url-gateway-prompt-pattern proc) | ||
| 193 | (process-send-string | ||
| 194 | proc (concat (mapconcat 'identity | ||
| 195 | (append url-gateway-telnet-parameters | ||
| 196 | (list host service)) " ") "\n")) | ||
| 197 | (url-wait-for-string "^\r*Escape character.*\r*\n+" proc) | ||
| 198 | (delete-region (point-min) (match-end 0)) | ||
| 199 | (process-send-string proc "\^]\n") | ||
| 200 | (url-wait-for-string "^telnet" proc) | ||
| 201 | (process-send-string proc "mode character\n") | ||
| 202 | (accept-process-output proc 1) | ||
| 203 | (sit-for 1) | ||
| 204 | (goto-char (point-min)) | ||
| 205 | (forward-line 1) | ||
| 206 | (delete-region (point) (point-max))) | ||
| 207 | proc))) | ||
| 208 | |||
| 209 | ;;;###autoload | ||
| 210 | (defun url-open-stream (name buffer host service) | ||
| 211 | "Open a stream to HOST, possibly via a gateway. | ||
| 212 | Args per `open-network-stream'. | ||
| 213 | Will not make a connexion if `url-gateway-unplugged' is non-nil." | ||
| 214 | (unless url-gateway-unplugged | ||
| 215 | (let ((gw-method (if (and url-gateway-local-host-regexp | ||
| 216 | (not (eq 'tls url-gateway-method)) | ||
| 217 | (not (eq 'ssl url-gateway-method)) | ||
| 218 | (string-match | ||
| 219 | url-gateway-local-host-regexp | ||
| 220 | host)) | ||
| 221 | 'native | ||
| 222 | url-gateway-method)) | ||
| 223 | ;;; ;; This hack is for OS/2 Emacs so that it will not do bogus CRLF | ||
| 224 | ;;; ;; conversions while trying to be 'helpful' | ||
| 225 | ;;; (tcp-binary-process-output-services (if (stringp service) | ||
| 226 | ;;; (list service) | ||
| 227 | ;;; (list service | ||
| 228 | ;;; (int-to-string service)))) | ||
| 229 | |||
| 230 | ;; An attempt to deal with denied connections, and attempt | ||
| 231 | ;; to reconnect | ||
| 232 | (cur-retries 0) | ||
| 233 | (retry t) | ||
| 234 | (errobj nil) | ||
| 235 | (conn nil)) | ||
| 236 | |||
| 237 | ;; If the user told us to do DNS for them, do it. | ||
| 238 | (if url-gateway-broken-resolution | ||
| 239 | (setq host (url-gateway-nslookup-host host))) | ||
| 240 | |||
| 241 | (condition-case errobj | ||
| 242 | ;; This is a clean way to ensure the new process inherits the | ||
| 243 | ;; right coding systems in both Emacs and XEmacs. | ||
| 244 | (let ((coding-system-for-read 'binary) | ||
| 245 | (coding-system-for-write 'binary)) | ||
| 246 | (setq conn (case gw-method | ||
| 247 | (tls | ||
| 248 | (open-tls-stream name buffer host service)) | ||
| 249 | (ssl | ||
| 250 | (open-ssl-stream name buffer host service)) | ||
| 251 | ((native) | ||
| 252 | (open-network-stream name buffer host service)) | ||
| 253 | (socks | ||
| 254 | (socks-open-network-stream name buffer host service)) | ||
| 255 | (telnet | ||
| 256 | (url-open-telnet name buffer host service)) | ||
| 257 | (rlogin | ||
| 258 | (url-open-rlogin name buffer host service)) | ||
| 259 | (otherwise | ||
| 260 | (error "Bad setting of url-gateway-method: %s" | ||
| 261 | url-gateway-method))))) | ||
| 262 | (error | ||
| 263 | (setq conn nil))) | ||
| 264 | conn))) | ||
| 265 | |||
| 266 | (provide 'url-gw) | ||
| 267 | |||
| 268 | ;;; arch-tag: 1c4c0317-6d03-45b8-b3f3-838bd8f9d838 | ||
diff --git a/lisp/url/url-handlers.el b/lisp/url/url-handlers.el index 56497b00119..db961b9c27e 100644 --- a/lisp/url/url-handlers.el +++ b/lisp/url/url-handlers.el | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | ;;; url-handlers.el --- file-name-handler stuff for URL loading | 1 | ;;; url-handlers.el --- file-name-handler stuff for URL loading |
| 2 | 2 | ||
| 3 | ;; Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. | 3 | ;; Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. |
| 4 | ;; Copyright (c) 1993 - 1996 by William M. Perry <wmperry@cs.indiana.edu> | ||
| 5 | 4 | ||
| 6 | ;; Keywords: comm, data, processes, hypermedia | 5 | ;; Keywords: comm, data, processes, hypermedia |
| 7 | 6 | ||
| @@ -208,7 +207,7 @@ accessible." | |||
| 208 | ;; annotation which we could use as a hint of the locale in use | 207 | ;; annotation which we could use as a hint of the locale in use |
| 209 | ;; at the remote site. Not sure how/if that should be done. --Stef | 208 | ;; at the remote site. Not sure how/if that should be done. --Stef |
| 210 | (decode-coding-inserted-region | 209 | (decode-coding-inserted-region |
| 211 | start (point) buffer-file-name visit beg end replace))) | 210 | start (point) url visit beg end replace))) |
| 212 | (list url (length data)))) | 211 | (list url (length data)))) |
| 213 | 212 | ||
| 214 | (defun url-file-name-completion (url directory) | 213 | (defun url-file-name-completion (url directory) |
diff --git a/lisp/url/url-history.el b/lisp/url/url-history.el new file mode 100644 index 00000000000..6a2d87cfbc1 --- /dev/null +++ b/lisp/url/url-history.el | |||
| @@ -0,0 +1,199 @@ | |||
| 1 | ;;; url-history.el --- Global history tracking for URL package | ||
| 2 | |||
| 3 | ;; Copyright (c) 1996 - 1999,2004 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Keywords: comm, data, processes, hypermedia | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | ;; | ||
| 9 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;; any later version. | ||
| 13 | ;; | ||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | ;; | ||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;; Boston, MA 02111-1307, USA. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | |||
| 26 | ;;; Code: | ||
| 27 | |||
| 28 | ;; This can get a recursive require. | ||
| 29 | ;;(require 'url) | ||
| 30 | (eval-when-compile (require 'cl)) | ||
| 31 | (require 'url-parse) | ||
| 32 | (autoload 'url-do-setup "url") | ||
| 33 | |||
| 34 | (defgroup url-history nil | ||
| 35 | "History variables in the URL package" | ||
| 36 | :prefix "url-history" | ||
| 37 | :group 'url) | ||
| 38 | |||
| 39 | (defcustom url-history-track nil | ||
| 40 | "*Controls whether to keep a list of all the URLS being visited. | ||
| 41 | If non-nil, url will keep track of all the URLS visited. | ||
| 42 | If eq to `t', then the list is saved to disk at the end of each emacs | ||
| 43 | session." | ||
| 44 | :type 'boolean | ||
| 45 | :group 'url-history) | ||
| 46 | |||
| 47 | (defcustom url-history-file nil | ||
| 48 | "*The global history file for the URL package. | ||
| 49 | This file contains a list of all the URLs you have visited. This file | ||
| 50 | is parsed at startup and used to provide URL completion." | ||
| 51 | :type '(choice (const :tag "Default" :value nil) file) | ||
| 52 | :group 'url-history) | ||
| 53 | |||
| 54 | (defcustom url-history-save-interval 3600 | ||
| 55 | "*The number of seconds between automatic saves of the history list. | ||
| 56 | Default is 1 hour. Note that if you change this variable outside of | ||
| 57 | the `customize' interface after `url-do-setup' has been run, you need | ||
| 58 | to run the `url-history-setup-save-timer' function manually." | ||
| 59 | :set (function (lambda (var val) | ||
| 60 | (set-default var val) | ||
| 61 | (and (featurep 'url) | ||
| 62 | (fboundp 'url-history-setup-save-timer) | ||
| 63 | (let ((def (symbol-function | ||
| 64 | 'url-history-setup-save-timer))) | ||
| 65 | (not (and (listp def) (eq 'autoload (car def))))) | ||
| 66 | (url-history-setup-save-timer)))) | ||
| 67 | :type 'integer | ||
| 68 | :group 'url-history) | ||
| 69 | |||
| 70 | (defvar url-history-timer nil) | ||
| 71 | |||
| 72 | (defvar url-history-list nil | ||
| 73 | "List of urls visited this session.") | ||
| 74 | |||
| 75 | (defvar url-history-changed-since-last-save nil | ||
| 76 | "Whether the history list has changed since the last save operation.") | ||
| 77 | |||
| 78 | (defvar url-history-hash-table nil | ||
| 79 | "Hash table for global history completion.") | ||
| 80 | |||
| 81 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 82 | |||
| 83 | ;;;###autoload | ||
| 84 | (defun url-history-setup-save-timer () | ||
| 85 | "Reset the history list timer." | ||
| 86 | (interactive) | ||
| 87 | (ignore-errors | ||
| 88 | (cond ((fboundp 'cancel-timer) (cancel-timer url-history-timer)) | ||
| 89 | ((fboundp 'delete-itimer) (delete-itimer url-history-timer)))) | ||
| 90 | (setq url-history-timer nil) | ||
| 91 | (if url-history-save-interval | ||
| 92 | (setq url-history-timer | ||
| 93 | (cond | ||
| 94 | ((fboundp 'run-at-time) | ||
| 95 | (run-at-time url-history-save-interval | ||
| 96 | url-history-save-interval | ||
| 97 | 'url-history-save-history)) | ||
| 98 | ((fboundp 'start-itimer) | ||
| 99 | (start-itimer "url-history-saver" 'url-history-save-history | ||
| 100 | url-history-save-interval | ||
| 101 | url-history-save-interval)))))) | ||
| 102 | |||
| 103 | ;;;###autoload | ||
| 104 | (defun url-history-parse-history (&optional fname) | ||
| 105 | "Parse a history file stored in FNAME." | ||
| 106 | ;; Parse out the mosaic global history file for completions, etc. | ||
| 107 | (or fname (setq fname (expand-file-name url-history-file))) | ||
| 108 | (cond | ||
| 109 | ((not (file-exists-p fname)) | ||
| 110 | (message "%s does not exist." fname)) | ||
| 111 | ((not (file-readable-p fname)) | ||
| 112 | (message "%s is unreadable." fname)) | ||
| 113 | (t | ||
| 114 | (condition-case nil | ||
| 115 | (load fname nil t) | ||
| 116 | (error (message "Could not load %s" fname))))) | ||
| 117 | (if (not url-history-hash-table) | ||
| 118 | (setq url-history-hash-table (make-hash-table :size 31 :test 'equal)))) | ||
| 119 | |||
| 120 | (defun url-history-update-url (url time) | ||
| 121 | (setq url-history-changed-since-last-save t) | ||
| 122 | (puthash (if (vectorp url) (url-recreate-url url) url) time url-history-hash-table)) | ||
| 123 | |||
| 124 | ;;;###autoload | ||
| 125 | (defun url-history-save-history (&optional fname) | ||
| 126 | "Write the global history file into `url-history-file'. | ||
| 127 | The type of data written is determined by what is in the file to begin | ||
| 128 | with. If the type of storage cannot be determined, then prompt the | ||
| 129 | user for what type to save as." | ||
| 130 | (interactive) | ||
| 131 | (or fname (setq fname (expand-file-name url-history-file))) | ||
| 132 | (cond | ||
| 133 | ((not url-history-changed-since-last-save) nil) | ||
| 134 | ((not (file-writable-p fname)) | ||
| 135 | (message "%s is unwritable." fname)) | ||
| 136 | (t | ||
| 137 | (let ((make-backup-files nil) | ||
| 138 | (version-control nil) | ||
| 139 | (require-final-newline t)) | ||
| 140 | (save-excursion | ||
| 141 | (set-buffer (get-buffer-create " *url-tmp*")) | ||
| 142 | (erase-buffer) | ||
| 143 | (let ((count 0)) | ||
| 144 | (maphash (function | ||
| 145 | (lambda (key value) | ||
| 146 | (while (string-match "[\r\n]+" key) | ||
| 147 | (setq key (concat (substring key 0 (match-beginning 0)) | ||
| 148 | (substring key (match-end 0) nil)))) | ||
| 149 | (setq count (1+ count)) | ||
| 150 | (insert "(puthash \"" key "\"" | ||
| 151 | (if (not (stringp value)) " '" "") | ||
| 152 | (prin1-to-string value) | ||
| 153 | " url-history-hash-table)\n"))) | ||
| 154 | url-history-hash-table) | ||
| 155 | (goto-char (point-min)) | ||
| 156 | (insert (format | ||
| 157 | "(setq url-history-hash-table (make-hash-table :size %d :test 'equal))\n" | ||
| 158 | (/ count 4))) | ||
| 159 | (goto-char (point-max)) | ||
| 160 | (insert "\n") | ||
| 161 | (write-file fname)) | ||
| 162 | (kill-buffer (current-buffer)))))) | ||
| 163 | (setq url-history-changed-since-last-save nil)) | ||
| 164 | |||
| 165 | (defun url-have-visited-url (url) | ||
| 166 | (url-do-setup) | ||
| 167 | (gethash url url-history-hash-table nil)) | ||
| 168 | |||
| 169 | (defun url-completion-function (string predicate function) | ||
| 170 | (url-do-setup) | ||
| 171 | (cond | ||
| 172 | ((eq function nil) | ||
| 173 | (let ((list nil)) | ||
| 174 | (maphash (function (lambda (key val) | ||
| 175 | (setq list (cons (cons key val) | ||
| 176 | list)))) | ||
| 177 | url-history-hash-table) | ||
| 178 | (try-completion string (nreverse list) predicate))) | ||
| 179 | ((eq function t) | ||
| 180 | (let ((stub (concat "^" (regexp-quote string))) | ||
| 181 | (retval nil)) | ||
| 182 | (maphash | ||
| 183 | (function | ||
| 184 | (lambda (url time) | ||
| 185 | (if (string-match stub url) | ||
| 186 | (setq retval (cons url retval))))) | ||
| 187 | url-history-hash-table) | ||
| 188 | retval)) | ||
| 189 | ((eq function 'lambda) | ||
| 190 | (and url-history-hash-table | ||
| 191 | (gethash string url-history-hash-table) | ||
| 192 | t)) | ||
| 193 | (t | ||
| 194 | (error "url-completion-function very confused.")))) | ||
| 195 | |||
| 196 | (provide 'url-history) | ||
| 197 | |||
| 198 | ;; arch-tag: fbbbaf63-db36-4e88-bc9f-2939aa93afb2 | ||
| 199 | ;;; url-history.el ends here | ||
diff --git a/lisp/url/url-https.el b/lisp/url/url-https.el index 11b2593ea80..9631aeb18e4 100644 --- a/lisp/url/url-https.el +++ b/lisp/url/url-https.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; url-https.el --- HTTP over SSL routines | 1 | ;;; url-https.el --- HTTP over SSL/TLS routines |
| 2 | 2 | ||
| 3 | ;; Copyright (c) 1999, 2004 Free Software Foundation, Inc. | 3 | ;; Copyright (c) 1999, 2004 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -30,6 +30,7 @@ | |||
| 30 | (require 'url-parse) | 30 | (require 'url-parse) |
| 31 | (require 'url-cookie) | 31 | (require 'url-cookie) |
| 32 | (require 'url-http) | 32 | (require 'url-http) |
| 33 | (require 'tls) | ||
| 33 | 34 | ||
| 34 | (defconst url-https-default-port 443 "Default HTTPS port.") | 35 | (defconst url-https-default-port 443 "Default HTTPS port.") |
| 35 | (defconst url-https-asynchronous-p t "HTTPS retrievals are asynchronous.") | 36 | (defconst url-https-asynchronous-p t "HTTPS retrievals are asynchronous.") |
| @@ -38,12 +39,11 @@ | |||
| 38 | (defmacro url-https-create-secure-wrapper (method args) | 39 | (defmacro url-https-create-secure-wrapper (method args) |
| 39 | `(defun ,(intern (format (if method "url-https-%s" "url-https") method)) ,args | 40 | `(defun ,(intern (format (if method "url-https-%s" "url-https") method)) ,args |
| 40 | ,(format "HTTPS wrapper around `%s' call." (or method "url-http")) | 41 | ,(format "HTTPS wrapper around `%s' call." (or method "url-http")) |
| 41 | (condition-case () | 42 | (let ((url-gateway-method (condition-case () |
| 42 | (require 'ssl) | 43 | (require 'ssl) |
| 43 | (error | 44 | (error 'tls)))) |
| 44 | (error "HTTPS support could not find `ssl' library"))) | 45 | (,(intern (format (if method "url-http-%s" "url-http") method)) |
| 45 | (let ((url-gateway-method 'ssl)) | 46 | ,@(remove '&rest (remove '&optional args)))))) |
| 46 | ( ,(intern (format (if method "url-http-%s" "url-http") method)) ,@(remove '&rest (remove '&optional args)))))) | ||
| 47 | 47 | ||
| 48 | (url-https-create-secure-wrapper nil (url callback cbargs)) | 48 | (url-https-create-secure-wrapper nil (url callback cbargs)) |
| 49 | (url-https-create-secure-wrapper file-exists-p (url)) | 49 | (url-https-create-secure-wrapper file-exists-p (url)) |
diff --git a/lisp/url/url-irc.el b/lisp/url/url-irc.el new file mode 100644 index 00000000000..a4b195f253f --- /dev/null +++ b/lisp/url/url-irc.el | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | ;;; url-irc.el --- IRC URL interface | ||
| 2 | ;; Keywords: comm, data, processes | ||
| 3 | |||
| 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5 | ;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc. | ||
| 6 | ;;; | ||
| 7 | ;;; This file is part of GNU Emacs. | ||
| 8 | ;;; | ||
| 9 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;;; any later version. | ||
| 13 | ;;; | ||
| 14 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;;; GNU General Public License for more details. | ||
| 18 | ;;; | ||
| 19 | ;;; You should have received a copy of the GNU General Public License | ||
| 20 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;;; Boston, MA 02111-1307, USA. | ||
| 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 24 | |||
| 25 | ;;; IRC URLs are defined in http://www.w3.org/Addressing/draft-mirashi-url-irc-01.txt | ||
| 26 | |||
| 27 | (require 'url-vars) | ||
| 28 | (require 'url-parse) | ||
| 29 | |||
| 30 | (defconst url-irc-default-port 6667 "Default port for IRC connections") | ||
| 31 | |||
| 32 | (defcustom url-irc-function 'url-irc-zenirc | ||
| 33 | "*Function to actually open an IRC connection. | ||
| 34 | Should be a function that takes several argument: | ||
| 35 | HOST - the hostname of the IRC server to contact | ||
| 36 | PORT - the port number of the IRC server to contact | ||
| 37 | CHANNEL - What channel on the server to visit right away (can be nil) | ||
| 38 | USER - What username to use | ||
| 39 | PASSWORD - What password to use" | ||
| 40 | :type '(choice (const :tag "ZEN IRC" :value 'url-irc-zenirc) | ||
| 41 | (function :tag "Other")) | ||
| 42 | :group 'url) | ||
| 43 | |||
| 44 | (defun url-irc-zenirc (host port channel user password) | ||
| 45 | (let ((zenirc-buffer-name (if (and user host port) | ||
| 46 | (format "%s@%s:%d" user host port) | ||
| 47 | (format "%s:%d" host port))) | ||
| 48 | (zenirc-server-alist | ||
| 49 | (list | ||
| 50 | (list host port password nil user)))) | ||
| 51 | (zenirc) | ||
| 52 | (goto-char (point-max)) | ||
| 53 | (if (not channel) | ||
| 54 | nil | ||
| 55 | (insert "/join " channel) | ||
| 56 | (zenirc-send-line)))) | ||
| 57 | |||
| 58 | ;;;###autoload | ||
| 59 | (defun url-irc (url) | ||
| 60 | (let* ((host (url-host url)) | ||
| 61 | (port (string-to-int (url-port url))) | ||
| 62 | (pass (url-password url)) | ||
| 63 | (user (url-user url)) | ||
| 64 | (chan (url-filename url))) | ||
| 65 | (if (url-target url) | ||
| 66 | (setq chan (concat chan "#" (url-target url)))) | ||
| 67 | (if (string-match "^/" chan) | ||
| 68 | (setq chan (substring chan 1 nil))) | ||
| 69 | (if (= (length chan) 0) | ||
| 70 | (setq chan nil)) | ||
| 71 | (funcall url-irc-function host port chan user pass) | ||
| 72 | nil)) | ||
| 73 | |||
| 74 | (provide 'url-irc) | ||
| 75 | |||
| 76 | ;;; arch-tag: 2e5eecf8-9eb3-436b-9fbd-c26f2fb2bf3e | ||
diff --git a/lisp/url/url-ldap.el b/lisp/url/url-ldap.el new file mode 100644 index 00000000000..24a3ade4922 --- /dev/null +++ b/lisp/url/url-ldap.el | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | ;;; url-ldap.el --- LDAP Uniform Resource Locator retrieval code | ||
| 2 | ;; Copyright (c) 1998 - 1999, 2004 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | ;; Keywords: comm, data, processes | ||
| 5 | |||
| 6 | ;; This file is part of GNU Emacs. | ||
| 7 | ;; | ||
| 8 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 9 | ;; it under the terms of the GNU General Public License as published by | ||
| 10 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 11 | ;; any later version. | ||
| 12 | ;; | ||
| 13 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | ;; GNU General Public License for more details. | ||
| 17 | ;; | ||
| 18 | ;; You should have received a copy of the GNU General Public License | ||
| 19 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 20 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 21 | ;; Boston, MA 02111-1307, USA. | ||
| 22 | |||
| 23 | ;;; Commentary: | ||
| 24 | |||
| 25 | ;;; Code: | ||
| 26 | |||
| 27 | (require 'url-vars) | ||
| 28 | (require 'url-parse) | ||
| 29 | (require 'url-util) | ||
| 30 | (require 'ldap) | ||
| 31 | (autoload 'tls-certificate-information "tls") | ||
| 32 | |||
| 33 | ;; This has been implemented from RFC2255 'The LDAP URL Format' (Dec 1997) | ||
| 34 | ;; | ||
| 35 | ;; basic format is: ldap://host:port/dn?attributes?scope?filter?extensions | ||
| 36 | ;; | ||
| 37 | ;; Test URLs: | ||
| 38 | ;; ldap://ldap.itd.umich.edu/cn%3Dumbflabmanager%2C%20ou%3DUser%20Groups%2C%20ou%3DGroups%2C%20o%3DUniversity%20of%20Michigan%2C%20c%3DUS | ||
| 39 | ;; ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US | ||
| 40 | ;; | ||
| 41 | ;; For simple queries, I have verified compatibility with Netscape | ||
| 42 | ;; Communicator v4.5 under GNU/Linux. | ||
| 43 | ;; | ||
| 44 | ;; For anything _useful_ though, like specifying the attributes, | ||
| 45 | ;; scope, filter, or extensions, netscape claims the URL format is | ||
| 46 | ;; unrecognized. So I don't think it supports anything other than the | ||
| 47 | ;; defaults (scope=base,attributes=*,filter=(objectClass=*) | ||
| 48 | |||
| 49 | (defconst url-ldap-default-port 389 "Default LDAP port.") | ||
| 50 | (defalias 'url-ldap-expand-file-name 'url-default-expander) | ||
| 51 | |||
| 52 | (defvar url-ldap-pretty-names | ||
| 53 | '(("l" . "City") | ||
| 54 | ("objectclass" . "Object Class") | ||
| 55 | ("o" . "Organization") | ||
| 56 | ("ou" . "Organizational Unit") | ||
| 57 | ("cn" . "Name") | ||
| 58 | ("sn" . "Last Name") | ||
| 59 | ("givenname" . "First Name") | ||
| 60 | ("mail" . "Email") | ||
| 61 | ("title" . "Title") | ||
| 62 | ("c" . "Country") | ||
| 63 | ("postalcode" . "ZIP Code") | ||
| 64 | ("telephonenumber" . "Phone Number") | ||
| 65 | ("facsimiletelephonenumber" . "Fax") | ||
| 66 | ("postaladdress" . "Mailing Address") | ||
| 67 | ("description" . "Notes")) | ||
| 68 | "*An assoc list mapping LDAP attribute names to pretty descriptions of them.") | ||
| 69 | |||
| 70 | (defvar url-ldap-attribute-formatters | ||
| 71 | '(("mail" . (lambda (x) (format "<a href='mailto:%s'>%s</a>" x x))) | ||
| 72 | ("owner" . url-ldap-dn-formatter) | ||
| 73 | ("creatorsname" . url-ldap-dn-formatter) | ||
| 74 | ("jpegphoto" . url-ldap-image-formatter) | ||
| 75 | ("usercertificate" . url-ldap-certificate-formatter) | ||
| 76 | ("modifiersname" . url-ldap-dn-formatter) | ||
| 77 | ("namingcontexts" . url-ldap-dn-formatter) | ||
| 78 | ("defaultnamingcontext" . url-ldap-dn-formatter) | ||
| 79 | ("member" . url-ldap-dn-formatter)) | ||
| 80 | "*An assoc list mapping LDAP attribute names to pretty formatters for them.") | ||
| 81 | |||
| 82 | (defsubst url-ldap-attribute-pretty-name (n) | ||
| 83 | (or (cdr-safe (assoc (downcase n) url-ldap-pretty-names)) n)) | ||
| 84 | |||
| 85 | (defsubst url-ldap-attribute-pretty-desc (n v) | ||
| 86 | (if (string-match "^\\([^;]+\\);" n) | ||
| 87 | (setq n (match-string 1 n))) | ||
| 88 | (funcall (or (cdr-safe (assoc (downcase n) url-ldap-attribute-formatters)) 'identity) v)) | ||
| 89 | |||
| 90 | (defun url-ldap-dn-formatter (dn) | ||
| 91 | (concat "<a href='/" | ||
| 92 | (url-hexify-string dn) | ||
| 93 | "'>" dn "</a>")) | ||
| 94 | |||
| 95 | (defun url-ldap-certificate-formatter (data) | ||
| 96 | (condition-case () | ||
| 97 | (require 'ssl) | ||
| 98 | (error nil)) | ||
| 99 | (let ((vals (if (fboundp 'ssl-certificate-information) | ||
| 100 | (ssl-certificate-information data) | ||
| 101 | (tls-certificate-information data)))) | ||
| 102 | (if (not vals) | ||
| 103 | "<b>Unable to parse certificate</b>" | ||
| 104 | (concat "<table border=0>\n" | ||
| 105 | (mapconcat | ||
| 106 | (lambda (ava) | ||
| 107 | (format "<tr><td>%s</td><td>%s</td></tr>\n" (car ava) (cdr ava))) | ||
| 108 | vals "\n") | ||
| 109 | "</table>\n")))) | ||
| 110 | |||
| 111 | (defun url-ldap-image-formatter (data) | ||
| 112 | (format "<img alt='JPEG Photo' src='data:image/jpeg;base64,%s'>" | ||
| 113 | (url-hexify-string (base64-encode-string data)))) | ||
| 114 | |||
| 115 | ;; FIXME: This needs sorting out for the Emacs LDAP functions, specifically | ||
| 116 | ;; calls of ldap-open, ldap-close, ldap-search-internal | ||
| 117 | ;;;###autoload | ||
| 118 | (defun url-ldap (url) | ||
| 119 | (save-excursion | ||
| 120 | (set-buffer (generate-new-buffer " *url-ldap*")) | ||
| 121 | (setq url-current-object url) | ||
| 122 | (insert "Content-type: text/html\r\n\r\n") | ||
| 123 | (if (not (fboundp 'ldap-search-internal)) | ||
| 124 | (insert "<html>\n" | ||
| 125 | " <head>\n" | ||
| 126 | " <title>LDAP Not Supported</title>\n" | ||
| 127 | " <base href='" (url-recreate-url url) "'>\n" | ||
| 128 | " </head>\n" | ||
| 129 | " <body>\n" | ||
| 130 | " <h1>LDAP Not Supported</h1>\n" | ||
| 131 | " <p>\n" | ||
| 132 | " This version of Emacs does not support LDAP.\n" | ||
| 133 | " </p>\n" | ||
| 134 | " </body>\n" | ||
| 135 | "</html>\n") | ||
| 136 | (let* ((binddn nil) | ||
| 137 | (data (url-filename url)) | ||
| 138 | (host (url-host url)) | ||
| 139 | (port (url-port url)) | ||
| 140 | (base-object nil) | ||
| 141 | (attributes nil) | ||
| 142 | (scope nil) | ||
| 143 | (filter nil) | ||
| 144 | (extensions nil) | ||
| 145 | (connection nil) | ||
| 146 | (results nil) | ||
| 147 | (extract-dn (and (fboundp 'function-max-args) | ||
| 148 | (= (function-max-args 'ldap-search-internal) 7)))) | ||
| 149 | |||
| 150 | ;; Get rid of leading / | ||
| 151 | (if (string-match "^/" data) | ||
| 152 | (setq data (substring data 1))) | ||
| 153 | |||
| 154 | (setq data (mapcar (lambda (x) (if (/= (length x) 0) x nil)) (split-string data "\\?")) | ||
| 155 | base-object (nth 0 data) | ||
| 156 | attributes (nth 1 data) | ||
| 157 | scope (nth 2 data) | ||
| 158 | filter (nth 3 data) | ||
| 159 | extensions (nth 4 data)) | ||
| 160 | |||
| 161 | ;; fill in the defaults | ||
| 162 | (setq base-object (url-unhex-string (or base-object "")) | ||
| 163 | scope (intern (url-unhex-string (or scope "base"))) | ||
| 164 | filter (url-unhex-string (or filter "(objectClass=*)"))) | ||
| 165 | |||
| 166 | (if (not (memq scope '(base one tree))) | ||
| 167 | (error "Malformed LDAP URL: Unknown scope: %S" scope)) | ||
| 168 | |||
| 169 | ;; Convert to the internal LDAP support scoping names. | ||
| 170 | (setq scope (cdr (assq scope '((base . base) (one . onelevel) (sub . subtree))))) | ||
| 171 | |||
| 172 | (if attributes | ||
| 173 | (setq attributes (mapcar 'url-unhex-string (split-string attributes ",")))) | ||
| 174 | |||
| 175 | ;; Parse out the exentions | ||
| 176 | (if extensions | ||
| 177 | (setq extensions (mapcar (lambda (ext) | ||
| 178 | (if (string-match "\\([^=]*\\)=\\(.*\\)" ext) | ||
| 179 | (cons (match-string 1 ext) (match-string 2 ext)) | ||
| 180 | (cons ext ext))) | ||
| 181 | (split-string extensions ",")) | ||
| 182 | extensions (mapcar (lambda (ext) | ||
| 183 | (cons (url-unhex-string (car ext)) | ||
| 184 | (url-unhex-string (cdr ext)))) | ||
| 185 | extensions))) | ||
| 186 | |||
| 187 | (setq binddn (cdr-safe (or (assoc "bindname" extensions) | ||
| 188 | (assoc "!bindname" extensions)))) | ||
| 189 | |||
| 190 | ;; Now, let's actually do something with it. | ||
| 191 | (setq connection (ldap-open host (if binddn (list 'binddn binddn))) | ||
| 192 | results (if extract-dn | ||
| 193 | (ldap-search-internal connection filter base-object scope attributes nil t) | ||
| 194 | (ldap-search-internal connection filter base-object scope attributes nil))) | ||
| 195 | |||
| 196 | (ldap-close connection) | ||
| 197 | (insert "<html>\n" | ||
| 198 | " <head>\n" | ||
| 199 | " <title>LDAP Search Results</title>\n" | ||
| 200 | " <base href='" (url-recreate-url url) "'>\n" | ||
| 201 | " </head>\n" | ||
| 202 | " <body>\n" | ||
| 203 | " <h1>" (int-to-string (length results)) " matches</h1>\n") | ||
| 204 | |||
| 205 | (mapc (lambda (obj) | ||
| 206 | (insert " <hr>\n" | ||
| 207 | " <table border=1>\n") | ||
| 208 | (if extract-dn | ||
| 209 | (insert " <tr><th colspan=2>" (car obj) "</th></tr>\n")) | ||
| 210 | (mapc (lambda (attr) | ||
| 211 | (if (= (length (cdr attr)) 1) | ||
| 212 | ;; single match, easy | ||
| 213 | (insert " <tr><td>" | ||
| 214 | (url-ldap-attribute-pretty-name (car attr)) | ||
| 215 | "</td><td>" | ||
| 216 | (url-ldap-attribute-pretty-desc (car attr) (car (cdr attr))) | ||
| 217 | "</td></tr>\n") | ||
| 218 | ;; Multiple matches, slightly uglier | ||
| 219 | (insert " <tr>\n" | ||
| 220 | (format " <td valign=top>") | ||
| 221 | (url-ldap-attribute-pretty-name (car attr)) "</td><td>" | ||
| 222 | (mapconcat (lambda (x) | ||
| 223 | (url-ldap-attribute-pretty-desc (car attr) x)) | ||
| 224 | (cdr attr) | ||
| 225 | "<br>\n") | ||
| 226 | "</td>" | ||
| 227 | " </tr>\n"))) | ||
| 228 | (if extract-dn (cdr obj) obj)) | ||
| 229 | (insert " </table>\n")) | ||
| 230 | results) | ||
| 231 | |||
| 232 | (insert " <hr>\n" | ||
| 233 | " </body>\n" | ||
| 234 | "</html>\n"))) | ||
| 235 | (current-buffer))) | ||
| 236 | |||
| 237 | (provide 'url-ldap) | ||
| 238 | |||
| 239 | ;; arch-tag: 6230e21c-41ae-4174-bd83-82c835676fc8 | ||
| 240 | ;;; url-ldap.el ends here | ||
diff --git a/lisp/url/url-mailto.el b/lisp/url/url-mailto.el new file mode 100644 index 00000000000..bcb6bad4179 --- /dev/null +++ b/lisp/url/url-mailto.el | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | ;;; url-mail.el --- Mail Uniform Resource Locator retrieval code | ||
| 2 | |||
| 3 | ;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Keywords: comm, data, processes | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | ;; | ||
| 9 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;; any later version. | ||
| 13 | ;; | ||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | ;; | ||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;; Boston, MA 02111-1307, USA. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | |||
| 26 | ;;; Code: | ||
| 27 | |||
| 28 | (eval-when-compile (require 'cl)) | ||
| 29 | (require 'url-vars) | ||
| 30 | (require 'url-parse) | ||
| 31 | (require 'url-util) | ||
| 32 | |||
| 33 | ;;;###autoload | ||
| 34 | (defun url-mail (&rest args) | ||
| 35 | (interactive "P") | ||
| 36 | (if (fboundp 'message-mail) | ||
| 37 | (apply 'message-mail args) | ||
| 38 | (or (apply 'mail args) | ||
| 39 | (error "Mail aborted")))) | ||
| 40 | |||
| 41 | (defun url-mail-goto-field (field) | ||
| 42 | (if (not field) | ||
| 43 | (goto-char (point-max)) | ||
| 44 | (let ((dest nil) | ||
| 45 | (lim nil) | ||
| 46 | (case-fold-search t)) | ||
| 47 | (save-excursion | ||
| 48 | (goto-char (point-min)) | ||
| 49 | (if (re-search-forward (regexp-quote mail-header-separator) nil t) | ||
| 50 | (setq lim (match-beginning 0))) | ||
| 51 | (goto-char (point-min)) | ||
| 52 | (if (re-search-forward (concat "^" (regexp-quote field) ":") lim t) | ||
| 53 | (setq dest (match-beginning 0)))) | ||
| 54 | (if dest | ||
| 55 | (progn | ||
| 56 | (goto-char dest) | ||
| 57 | (end-of-line)) | ||
| 58 | (goto-char lim) | ||
| 59 | (insert (capitalize field) ": ") | ||
| 60 | (save-excursion | ||
| 61 | (insert "\n")))))) | ||
| 62 | |||
| 63 | ;;;###autoload | ||
| 64 | (defun url-mailto (url) | ||
| 65 | "Handle the mailto: URL syntax." | ||
| 66 | (if (url-user url) | ||
| 67 | ;; malformed mailto URL (mailto://wmperry@gnu.org instead of | ||
| 68 | ;; mailto:wmperry@gnu.org | ||
| 69 | (url-set-filename url (concat (url-user url) "@" (url-filename url)))) | ||
| 70 | (setq url (url-filename url)) | ||
| 71 | (let (to args source-url subject func headers-start) | ||
| 72 | (if (string-match (regexp-quote "?") url) | ||
| 73 | (setq headers-start (match-end 0) | ||
| 74 | to (url-unhex-string (substring url 0 (match-beginning 0))) | ||
| 75 | args (url-parse-query-string | ||
| 76 | (substring url headers-start nil) t)) | ||
| 77 | (setq to (url-unhex-string url))) | ||
| 78 | (setq source-url (url-view-url t)) | ||
| 79 | (if (and url-request-data (not (assoc "subject" args))) | ||
| 80 | (setq args (cons (list "subject" | ||
| 81 | (concat "Automatic submission from " | ||
| 82 | url-package-name "/" | ||
| 83 | url-package-version)) args))) | ||
| 84 | (if (and source-url (not (assoc "x-url-from" args))) | ||
| 85 | (setq args (cons (list "x-url-from" source-url) args))) | ||
| 86 | |||
| 87 | (if (assoc "to" args) | ||
| 88 | (push to (cdr (assoc "to" args))) | ||
| 89 | (setq args (cons (list "to" to) args))) | ||
| 90 | (setq subject (cdr-safe (assoc "subject" args))) | ||
| 91 | (if (fboundp url-mail-command) (funcall url-mail-command) (mail)) | ||
| 92 | (while args | ||
| 93 | (if (string= (caar args) "body") | ||
| 94 | (progn | ||
| 95 | (goto-char (point-max)) | ||
| 96 | (insert (mapconcat 'identity (cdar args) "\n"))) | ||
| 97 | (url-mail-goto-field (caar args)) | ||
| 98 | (setq func (intern-soft (concat "mail-" (caar args)))) | ||
| 99 | (insert (mapconcat 'identity (cdar args) ", "))) | ||
| 100 | (setq args (cdr args))) | ||
| 101 | ;; (url-mail-goto-field "User-Agent") | ||
| 102 | ;; (insert url-package-name "/" url-package-version " URL/" url-version) | ||
| 103 | (if (not url-request-data) | ||
| 104 | (progn | ||
| 105 | (set-buffer-modified-p nil) | ||
| 106 | (if subject | ||
| 107 | (url-mail-goto-field nil) | ||
| 108 | (url-mail-goto-field "subject"))) | ||
| 109 | (if url-request-extra-headers | ||
| 110 | (mapconcat | ||
| 111 | (lambda (x) | ||
| 112 | (url-mail-goto-field (car x)) | ||
| 113 | (insert (cdr x))) | ||
| 114 | url-request-extra-headers "")) | ||
| 115 | (goto-char (point-max)) | ||
| 116 | (insert url-request-data) | ||
| 117 | ;; It seems Microsoft-ish to send without warning. | ||
| 118 | ;; Fixme: presumably this should depend on a privacy setting. | ||
| 119 | (if (y-or-n-p "Send this auto-generated mail? ") | ||
| 120 | (cond ((eq url-mail-command 'compose-mail) | ||
| 121 | (funcall (get mail-user-agent 'sendfunc) nil)) | ||
| 122 | ;; otherwise, we can't be sure | ||
| 123 | ((fboundp 'message-send-and-exit) | ||
| 124 | (message-send-and-exit)) | ||
| 125 | (t (mail-send-and-exit nil))))) | ||
| 126 | nil)) | ||
| 127 | |||
| 128 | (provide 'url-mailto) | ||
| 129 | |||
| 130 | ;; arch-tag: 7b7ad52e-8760-497b-9444-75fae14e34c5 | ||
| 131 | ;;; url-mailto.el ends here | ||
diff --git a/lisp/url/url-methods.el b/lisp/url/url-methods.el new file mode 100644 index 00000000000..75d746f3e3f --- /dev/null +++ b/lisp/url/url-methods.el | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | ;;; url-methods.el --- Load URL schemes as needed | ||
| 2 | |||
| 3 | ;; Copyright (c) 1996,1997,1998,1999,2004 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Keywords: comm, data, processes, hypermedia | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | |||
| 9 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;; any later version. | ||
| 13 | ;; | ||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | ;; | ||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;; Boston, MA 02111-1307, USA. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | |||
| 26 | ;;; Code: | ||
| 27 | |||
| 28 | (eval-when-compile | ||
| 29 | (require 'cl)) | ||
| 30 | |||
| 31 | ;; This loads up some of the small, silly URLs that I really don't | ||
| 32 | ;; want to bother putting in their own separate files. | ||
| 33 | (require 'url-parse) | ||
| 34 | |||
| 35 | (defvar url-scheme-registry (make-hash-table :size 7 :test 'equal)) | ||
| 36 | |||
| 37 | (defconst url-scheme-methods | ||
| 38 | '((default-port . variable) | ||
| 39 | (asynchronous-p . variable) | ||
| 40 | (expand-file-name . function) | ||
| 41 | (file-exists-p . function) | ||
| 42 | (file-attributes . function) | ||
| 43 | (parse-url . function) | ||
| 44 | (file-symlink-p . function) | ||
| 45 | (file-writable-p . function) | ||
| 46 | (file-directory-p . function) | ||
| 47 | (file-executable-p . function) | ||
| 48 | (directory-files . function) | ||
| 49 | (file-truename . function)) | ||
| 50 | "Assoc-list of methods that each URL loader can provide.") | ||
| 51 | |||
| 52 | (defconst url-scheme-default-properties | ||
| 53 | (list 'name "unknown" | ||
| 54 | 'loader 'url-scheme-default-loader | ||
| 55 | 'default-port 0 | ||
| 56 | 'expand-file-name 'url-identity-expander | ||
| 57 | 'parse-url 'url-generic-parse-url | ||
| 58 | 'asynchronous-p nil | ||
| 59 | 'file-directory-p 'ignore | ||
| 60 | 'file-truename (lambda (&rest args) | ||
| 61 | (url-recreate-url (car args))) | ||
| 62 | 'file-exists-p 'ignore | ||
| 63 | 'file-attributes 'ignore)) | ||
| 64 | |||
| 65 | (defun url-scheme-default-loader (url &optional callback cbargs) | ||
| 66 | "Signal an error for an unknown URL scheme." | ||
| 67 | (error "Unkown URL scheme: %s" (url-type url))) | ||
| 68 | |||
| 69 | (defun url-scheme-register-proxy (scheme) | ||
| 70 | "Automatically find a proxy for SCHEME and put it in `url-proxy-services'." | ||
| 71 | (let* ((env-var (concat scheme "_proxy")) | ||
| 72 | (env-proxy (or (getenv (upcase env-var)) | ||
| 73 | (getenv (downcase env-var)))) | ||
| 74 | (cur-proxy (assoc scheme url-proxy-services)) | ||
| 75 | (urlobj nil)) | ||
| 76 | |||
| 77 | ;; Store any proxying information - this will not overwrite an old | ||
| 78 | ;; entry, so that people can still set this information in their | ||
| 79 | ;; .emacs file | ||
| 80 | (cond | ||
| 81 | (cur-proxy nil) ; Keep their old settings | ||
| 82 | ((null env-proxy) nil) ; No proxy setup | ||
| 83 | ;; First check if its something like hostname:port | ||
| 84 | ((string-match "^\\([^:]+\\):\\([0-9]+\\)$" env-proxy) | ||
| 85 | (setq urlobj (url-generic-parse-url nil)) ; Get a blank object | ||
| 86 | (url-set-type urlobj "http") | ||
| 87 | (url-set-host urlobj (match-string 1 env-proxy)) | ||
| 88 | (url-set-port urlobj (string-to-number (match-string 2 env-proxy)))) | ||
| 89 | ;; Then check if its a fully specified URL | ||
| 90 | ((string-match url-nonrelative-link env-proxy) | ||
| 91 | (setq urlobj (url-generic-parse-url env-proxy)) | ||
| 92 | (url-set-type urlobj "http") | ||
| 93 | (url-set-target urlobj nil)) | ||
| 94 | ;; Finally, fall back on the assumption that its just a hostname | ||
| 95 | (t | ||
| 96 | (setq urlobj (url-generic-parse-url nil)) ; Get a blank object | ||
| 97 | (url-set-type urlobj "http") | ||
| 98 | (url-set-host urlobj env-proxy))) | ||
| 99 | |||
| 100 | (if (and (not cur-proxy) urlobj) | ||
| 101 | (progn | ||
| 102 | (setq url-proxy-services | ||
| 103 | (cons (cons scheme (format "%s:%d" (url-host urlobj) | ||
| 104 | (url-port urlobj))) | ||
| 105 | url-proxy-services)) | ||
| 106 | (message "Using a proxy for %s..." scheme))))) | ||
| 107 | |||
| 108 | (defun url-scheme-get-property (scheme property) | ||
| 109 | "Get property of a URL SCHEME. | ||
| 110 | Will automatically try to load a backend from url-SCHEME.el if | ||
| 111 | it has not already been loaded." | ||
| 112 | (setq scheme (downcase scheme)) | ||
| 113 | (let ((desc (gethash scheme url-scheme-registry))) | ||
| 114 | (if (not desc) | ||
| 115 | (let* ((stub (concat "url-" scheme)) | ||
| 116 | (loader (intern stub))) | ||
| 117 | (condition-case () | ||
| 118 | (require loader) | ||
| 119 | (error nil)) | ||
| 120 | (if (fboundp loader) | ||
| 121 | (progn | ||
| 122 | ;; Found the module to handle <scheme> URLs | ||
| 123 | (url-scheme-register-proxy scheme) | ||
| 124 | (setq desc (list 'name scheme | ||
| 125 | 'loader loader)) | ||
| 126 | (dolist (cell url-scheme-methods) | ||
| 127 | (let ((symbol (intern-soft (format "%s-%s" stub (car cell)))) | ||
| 128 | (type (cdr cell))) | ||
| 129 | (if symbol | ||
| 130 | (case type | ||
| 131 | (function | ||
| 132 | ;; Store the symbol name of a function | ||
| 133 | (if (fboundp symbol) | ||
| 134 | (setq desc (plist-put desc (car cell) symbol)))) | ||
| 135 | (variable | ||
| 136 | ;; Store the VALUE of a variable | ||
| 137 | (if (boundp symbol) | ||
| 138 | (setq desc (plist-put desc (car cell) | ||
| 139 | (symbol-value symbol))))) | ||
| 140 | (otherwise | ||
| 141 | (error "Malformed url-scheme-methods entry: %S" | ||
| 142 | cell)))))) | ||
| 143 | (puthash scheme desc url-scheme-registry))))) | ||
| 144 | (or (plist-get desc property) | ||
| 145 | (plist-get url-scheme-default-properties property)))) | ||
| 146 | |||
| 147 | (provide 'url-methods) | ||
| 148 | |||
| 149 | ;; arch-tag: 336863f8-5a07-4906-9be5-b3c6bcebbe67 | ||
| 150 | ;;; url-methods.el ends here | ||
diff --git a/lisp/url/url-misc.el b/lisp/url/url-misc.el new file mode 100644 index 00000000000..ff2f1282137 --- /dev/null +++ b/lisp/url/url-misc.el | |||
| @@ -0,0 +1,117 @@ | |||
| 1 | ;;; url-misc.el --- Misc Uniform Resource Locator retrieval code | ||
| 2 | ;; Keywords: comm, data, processes | ||
| 3 | |||
| 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5 | ;;; Copyright (c) 1996,1997,1998,1999,2002 Free Software Foundation, Inc. | ||
| 6 | ;;; | ||
| 7 | ;;; This file is part of GNU Emacs. | ||
| 8 | ;;; | ||
| 9 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;;; any later version. | ||
| 13 | ;;; | ||
| 14 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;;; GNU General Public License for more details. | ||
| 18 | ;;; | ||
| 19 | ;;; You should have received a copy of the GNU General Public License | ||
| 20 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;;; Boston, MA 02111-1307, USA. | ||
| 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 24 | |||
| 25 | (require 'url-vars) | ||
| 26 | (require 'url-parse) | ||
| 27 | (autoload 'Info-goto-node "info" "" t) | ||
| 28 | (autoload 'man "man" nil t) | ||
| 29 | |||
| 30 | ;;;###autoload | ||
| 31 | (defun url-man (url) | ||
| 32 | "Fetch a Unix manual page URL." | ||
| 33 | (man (url-filename url)) | ||
| 34 | nil) | ||
| 35 | |||
| 36 | ;;;###autoload | ||
| 37 | (defun url-info (url) | ||
| 38 | "Fetch a GNU Info URL." | ||
| 39 | ;; Fetch an info node | ||
| 40 | (let* ((fname (url-filename url)) | ||
| 41 | (node (url-unhex-string (or (url-target url) "Top")))) | ||
| 42 | (if (and fname node) | ||
| 43 | (Info-goto-node (concat "(" fname ")" node)) | ||
| 44 | (error "Malformed url: %s" (url-recreate-url url))) | ||
| 45 | nil)) | ||
| 46 | |||
| 47 | (defun url-do-terminal-emulator (type server port user) | ||
| 48 | (terminal-emulator | ||
| 49 | (generate-new-buffer (format "%s%s" (if user (concat user "@") "") server)) | ||
| 50 | (case type | ||
| 51 | (rlogin "rlogin") | ||
| 52 | (telnet "telnet") | ||
| 53 | (tn3270 "tn3270") | ||
| 54 | (otherwise | ||
| 55 | (error "Unknown terminal emulator required: %s" type))) | ||
| 56 | (case type | ||
| 57 | (rlogin | ||
| 58 | (if user | ||
| 59 | (list server "-l" user) | ||
| 60 | (list server))) | ||
| 61 | (telnet | ||
| 62 | (if user (message "Please log in as user: %s" user)) | ||
| 63 | (if port | ||
| 64 | (list server port) | ||
| 65 | (list server))) | ||
| 66 | (tn3270 | ||
| 67 | (if user (message "Please log in as user: %s" user)) | ||
| 68 | (list server))))) | ||
| 69 | |||
| 70 | ;;;###autoload | ||
| 71 | (defun url-generic-emulator-loader (url) | ||
| 72 | (let* ((type (intern (downcase (url-type url)))) | ||
| 73 | (server (url-host url)) | ||
| 74 | (name (url-user url)) | ||
| 75 | (port (url-port url))) | ||
| 76 | (url-do-terminal-emulator type server port name)) | ||
| 77 | nil) | ||
| 78 | |||
| 79 | ;;;###autoload | ||
| 80 | (defalias 'url-rlogin 'url-generic-emulator-loader) | ||
| 81 | ;;;###autoload | ||
| 82 | (defalias 'url-telnet 'url-generic-emulator-loader) | ||
| 83 | ;;;###autoload | ||
| 84 | (defalias 'url-tn3270 'url-generic-emulator-loader) | ||
| 85 | |||
| 86 | ;; RFC 2397 | ||
| 87 | ;;;###autoload | ||
| 88 | (defun url-data (url) | ||
| 89 | "Fetch a data URL (RFC 2397)." | ||
| 90 | (let ((mediatype nil) | ||
| 91 | ;; The mediatype may need to be hex-encoded too -- see the RFC. | ||
| 92 | (desc (url-unhex-string (url-filename url))) | ||
| 93 | (encoding "8bit") | ||
| 94 | (data nil)) | ||
| 95 | (save-excursion | ||
| 96 | (if (not (string-match "\\([^,]*\\)?," desc)) | ||
| 97 | (error "Malformed data URL: %s" desc) | ||
| 98 | (setq mediatype (match-string 1 desc)) | ||
| 99 | (if (and mediatype (string-match ";base64\\'" mediatype)) | ||
| 100 | (setq mediatype (substring mediatype 0 (match-beginning 0)) | ||
| 101 | encoding "base64")) | ||
| 102 | (if (or (null mediatype) | ||
| 103 | (eq ?\; (aref mediatype 0))) | ||
| 104 | (setq mediatype (concat "text/plain" mediatype))) | ||
| 105 | (setq data (url-unhex-string (substring desc (match-end 0))))) | ||
| 106 | (set-buffer (generate-new-buffer " *url-data*")) | ||
| 107 | (mm-disable-multibyte) | ||
| 108 | (insert (format "Content-Length: %d\n" (length data)) | ||
| 109 | "Content-Type: " mediatype "\n" | ||
| 110 | "Content-Encoding: " encoding "\n" | ||
| 111 | "\n") | ||
| 112 | (if data (insert data)) | ||
| 113 | (current-buffer)))) | ||
| 114 | |||
| 115 | (provide 'url-misc) | ||
| 116 | |||
| 117 | ;;; arch-tag: 8c544e1b-d8bc-40a6-b319-f1f37fef65a0 | ||
diff --git a/lisp/url/url-news.el b/lisp/url/url-news.el new file mode 100644 index 00000000000..59364c9ccd0 --- /dev/null +++ b/lisp/url/url-news.el | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | ;;; url-news.el --- News Uniform Resource Locator retrieval code | ||
| 2 | ;; Keywords: comm, data, processes | ||
| 3 | |||
| 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5 | ;;; Copyright (c) 1996 - 1999, 2004 Free Software Foundation, Inc. | ||
| 6 | ;;; | ||
| 7 | ;;; This file is part of GNU Emacs. | ||
| 8 | ;;; | ||
| 9 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;;; any later version. | ||
| 13 | ;;; | ||
| 14 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;;; GNU General Public License for more details. | ||
| 18 | ;;; | ||
| 19 | ;;; You should have received a copy of the GNU General Public License | ||
| 20 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;;; Boston, MA 02111-1307, USA. | ||
| 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 24 | (require 'url-vars) | ||
| 25 | (require 'url-util) | ||
| 26 | (require 'url-parse) | ||
| 27 | (require 'nntp) | ||
| 28 | (autoload 'url-warn "url") | ||
| 29 | (autoload 'gnus-group-read-ephemeral-group "gnus-group") | ||
| 30 | (eval-when-compile (require 'cl)) | ||
| 31 | |||
| 32 | (defgroup url-news nil | ||
| 33 | "News related options" | ||
| 34 | :group 'url) | ||
| 35 | |||
| 36 | (defun url-news-open-host (host port user pass) | ||
| 37 | (if (fboundp 'nnheader-init-server-buffer) | ||
| 38 | (nnheader-init-server-buffer)) | ||
| 39 | (nntp-open-server host (list (string-to-int port))) | ||
| 40 | (if (and user pass) | ||
| 41 | (progn | ||
| 42 | (nntp-send-command "^.*\r?\n" "AUTHINFO USER" user) | ||
| 43 | (nntp-send-command "^.*\r?\n" "AUTHINFO PASS" pass) | ||
| 44 | (if (not (nntp-server-opened host)) | ||
| 45 | (url-warn 'url (format "NNTP authentication to `%s' as `%s' failed" | ||
| 46 | host user)))))) | ||
| 47 | |||
| 48 | (defun url-news-fetch-message-id (host message-id) | ||
| 49 | (let ((buf (generate-new-buffer " *url-news*"))) | ||
| 50 | (if (eq ?> (aref message-id (1- (length message-id)))) | ||
| 51 | nil | ||
| 52 | (setq message-id (concat "<" message-id ">"))) | ||
| 53 | (if (cdr-safe (nntp-request-article message-id nil host buf)) | ||
| 54 | ;; Successfully retrieved the article | ||
| 55 | nil | ||
| 56 | (save-excursion | ||
| 57 | (set-buffer buf) | ||
| 58 | (insert "Content-type: text/html\n\n" | ||
| 59 | "<html>\n" | ||
| 60 | " <head>\n" | ||
| 61 | " <title>Error</title>\n" | ||
| 62 | " </head>\n" | ||
| 63 | " <body>\n" | ||
| 64 | " <div>\n" | ||
| 65 | " <h1>Error requesting article...</h1>\n" | ||
| 66 | " <p>\n" | ||
| 67 | " The status message returned by the NNTP server was:" | ||
| 68 | "<br><hr>\n" | ||
| 69 | " <xmp>\n" | ||
| 70 | (nntp-status-message) | ||
| 71 | " </xmp>\n" | ||
| 72 | " </p>\n" | ||
| 73 | " <p>\n" | ||
| 74 | " If you If you feel this is an error, <a href=\"" | ||
| 75 | "mailto:" url-bug-address "\">send mail</a>\n" | ||
| 76 | " </p>\n" | ||
| 77 | " </div>\n" | ||
| 78 | " </body>\n" | ||
| 79 | "</html>\n" | ||
| 80 | "<!-- Automatically generated by URL v" url-version " -->\n" | ||
| 81 | ))) | ||
| 82 | buf)) | ||
| 83 | |||
| 84 | (defun url-news-fetch-newsgroup (newsgroup host) | ||
| 85 | (declare (special gnus-group-buffer)) | ||
| 86 | (if (string-match "^/+" newsgroup) | ||
| 87 | (setq newsgroup (substring newsgroup (match-end 0)))) | ||
| 88 | (if (string-match "/+$" newsgroup) | ||
| 89 | (setq newsgroup (substring newsgroup 0 (match-beginning 0)))) | ||
| 90 | |||
| 91 | ;; This saves us from checking new news if Gnus is already running | ||
| 92 | ;; FIXME - is it relatively safe to use gnus-alive-p here? FIXME | ||
| 93 | (if (or (not (get-buffer gnus-group-buffer)) | ||
| 94 | (save-excursion | ||
| 95 | (set-buffer gnus-group-buffer) | ||
| 96 | (not (eq major-mode 'gnus-group-mode)))) | ||
| 97 | (gnus)) | ||
| 98 | (set-buffer gnus-group-buffer) | ||
| 99 | (goto-char (point-min)) | ||
| 100 | (gnus-group-read-ephemeral-group newsgroup | ||
| 101 | (list 'nntp host | ||
| 102 | 'nntp-open-connection-function | ||
| 103 | nntp-open-connection-function) | ||
| 104 | nil | ||
| 105 | (cons (current-buffer) 'browse))) | ||
| 106 | |||
| 107 | ;;;###autoload | ||
| 108 | (defun url-news (url) | ||
| 109 | ;; Find a news reference | ||
| 110 | (let* ((host (or (url-host url) url-news-server)) | ||
| 111 | (port (url-port url)) | ||
| 112 | (article-brackets nil) | ||
| 113 | (buf nil) | ||
| 114 | (article (url-filename url))) | ||
| 115 | (url-news-open-host host port (url-user url) (url-password url)) | ||
| 116 | (setq article (url-unhex-string article)) | ||
| 117 | (cond | ||
| 118 | ((string-match "@" article) ; Its a specific article | ||
| 119 | (setq buf (url-news-fetch-message-id host article))) | ||
| 120 | ((string= article "") ; List all newsgroups | ||
| 121 | (gnus)) | ||
| 122 | (t ; Whole newsgroup | ||
| 123 | (url-news-fetch-newsgroup article host))) | ||
| 124 | buf)) | ||
| 125 | |||
| 126 | ;;;###autoload | ||
| 127 | (defun url-snews (url) | ||
| 128 | (let ((nntp-open-connection-function (if (eq 'tls url-gateway-method) | ||
| 129 | nntp-open-tls-stream | ||
| 130 | nntp-open-ssl-stream))) | ||
| 131 | (url-news url))) | ||
| 132 | |||
| 133 | (provide 'url-news) | ||
| 134 | |||
| 135 | ;;; arch-tag: 8975be13-04e8-4d38-bfff-47918e3ad311 | ||
diff --git a/lisp/url/url-nfs.el b/lisp/url/url-nfs.el index d068341b1c2..3b834bba75f 100644 --- a/lisp/url/url-nfs.el +++ b/lisp/url/url-nfs.el | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | ;;; url-nfs.el --- NFS URL interface | 1 | ;;; url-nfs.el --- NFS URL interface |
| 2 | 2 | ||
| 3 | ;; Copyright (c) 1996,97,98,1999,2004 Free Software Foundation, Inc. | 3 | ;; Copyright (c) 1996,1997,1998,1999,2004 Free Software Foundation, Inc. |
| 4 | ;; Copyright (c) 1996 by William M. Perry <wmperry@cs.indiana.edu> | ||
| 5 | 4 | ||
| 6 | ;; Keywords: comm, data, processes | 5 | ;; Keywords: comm, data, processes |
| 7 | 6 | ||
diff --git a/lisp/url/url-parse.el b/lisp/url/url-parse.el new file mode 100644 index 00000000000..97348ab5db2 --- /dev/null +++ b/lisp/url/url-parse.el | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | ;;; url-parse.el --- Uniform Resource Locator parser | ||
| 2 | |||
| 3 | ;; Copyright (c) 1996,1997,1998,1999,2004 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Keywords: comm, data, processes | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | ;; | ||
| 9 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;; any later version. | ||
| 13 | ;; | ||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | ;; | ||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;; Boston, MA 02111-1307, USA. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | |||
| 26 | ;;; Code: | ||
| 27 | |||
| 28 | (require 'url-vars) | ||
| 29 | |||
| 30 | (autoload 'url-scheme-get-property "url-methods") | ||
| 31 | |||
| 32 | (defmacro url-type (urlobj) | ||
| 33 | `(aref ,urlobj 0)) | ||
| 34 | |||
| 35 | (defmacro url-user (urlobj) | ||
| 36 | `(aref ,urlobj 1)) | ||
| 37 | |||
| 38 | (defmacro url-password (urlobj) | ||
| 39 | `(aref ,urlobj 2)) | ||
| 40 | |||
| 41 | (defmacro url-host (urlobj) | ||
| 42 | `(aref ,urlobj 3)) | ||
| 43 | |||
| 44 | (defmacro url-port (urlobj) | ||
| 45 | `(or (aref ,urlobj 4) | ||
| 46 | (if (url-fullness ,urlobj) | ||
| 47 | (url-scheme-get-property (url-type ,urlobj) 'default-port)))) | ||
| 48 | |||
| 49 | (defmacro url-filename (urlobj) | ||
| 50 | `(aref ,urlobj 5)) | ||
| 51 | |||
| 52 | (defmacro url-target (urlobj) | ||
| 53 | `(aref ,urlobj 6)) | ||
| 54 | |||
| 55 | (defmacro url-attributes (urlobj) | ||
| 56 | `(aref ,urlobj 7)) | ||
| 57 | |||
| 58 | (defmacro url-fullness (urlobj) | ||
| 59 | `(aref ,urlobj 8)) | ||
| 60 | |||
| 61 | (defmacro url-set-type (urlobj type) | ||
| 62 | `(aset ,urlobj 0 ,type)) | ||
| 63 | |||
| 64 | (defmacro url-set-user (urlobj user) | ||
| 65 | `(aset ,urlobj 1 ,user)) | ||
| 66 | |||
| 67 | (defmacro url-set-password (urlobj pass) | ||
| 68 | `(aset ,urlobj 2 ,pass)) | ||
| 69 | |||
| 70 | (defmacro url-set-host (urlobj host) | ||
| 71 | `(aset ,urlobj 3 ,host)) | ||
| 72 | |||
| 73 | (defmacro url-set-port (urlobj port) | ||
| 74 | `(aset ,urlobj 4 ,port)) | ||
| 75 | |||
| 76 | (defmacro url-set-filename (urlobj file) | ||
| 77 | `(aset ,urlobj 5 ,file)) | ||
| 78 | |||
| 79 | (defmacro url-set-target (urlobj targ) | ||
| 80 | `(aset ,urlobj 6 ,targ)) | ||
| 81 | |||
| 82 | (defmacro url-set-attributes (urlobj targ) | ||
| 83 | `(aset ,urlobj 7 ,targ)) | ||
| 84 | |||
| 85 | (defmacro url-set-full (urlobj val) | ||
| 86 | `(aset ,urlobj 8 ,val)) | ||
| 87 | |||
| 88 | ;;;###autoload | ||
| 89 | (defun url-recreate-url (urlobj) | ||
| 90 | "Recreate a URL string from the parsed URLOBJ." | ||
| 91 | (concat (url-type urlobj) ":" (if (url-host urlobj) "//" "") | ||
| 92 | (if (url-user urlobj) | ||
| 93 | (concat (url-user urlobj) | ||
| 94 | (if (url-password urlobj) | ||
| 95 | (concat ":" (url-password urlobj))) | ||
| 96 | "@")) | ||
| 97 | (url-host urlobj) | ||
| 98 | (if (and (url-port urlobj) | ||
| 99 | (not (equal (url-port urlobj) | ||
| 100 | (url-scheme-get-property (url-type urlobj) 'default-port)))) | ||
| 101 | (format ":%d" (url-port urlobj))) | ||
| 102 | (or (url-filename urlobj) "/") | ||
| 103 | (if (url-target urlobj) | ||
| 104 | (concat "#" (url-target urlobj))) | ||
| 105 | (if (url-attributes urlobj) | ||
| 106 | (concat ";" | ||
| 107 | (mapconcat | ||
| 108 | (function | ||
| 109 | (lambda (x) | ||
| 110 | (if (cdr x) | ||
| 111 | (concat (car x) "=" (cdr x)) | ||
| 112 | (car x)))) (url-attributes urlobj) ";"))))) | ||
| 113 | |||
| 114 | ;;;###autoload | ||
| 115 | (defun url-generic-parse-url (url) | ||
| 116 | "Return a vector of the parts of URL. | ||
| 117 | Format is: | ||
| 118 | \[TYPE USER PASSWORD HOST PORT FILE TARGET ATTRIBUTES FULL\]" | ||
| 119 | (cond | ||
| 120 | ((null url) | ||
| 121 | (make-vector 9 nil)) | ||
| 122 | ((or (not (string-match url-nonrelative-link url)) | ||
| 123 | (= ?/ (string-to-char url))) | ||
| 124 | (let ((retval (make-vector 9 nil))) | ||
| 125 | (url-set-filename retval url) | ||
| 126 | (url-set-full retval nil) | ||
| 127 | retval)) | ||
| 128 | (t | ||
| 129 | (save-excursion | ||
| 130 | (set-buffer (get-buffer-create " *urlparse*")) | ||
| 131 | (set-syntax-table url-parse-syntax-table) | ||
| 132 | (let ((save-pos nil) | ||
| 133 | (prot nil) | ||
| 134 | (user nil) | ||
| 135 | (pass nil) | ||
| 136 | (host nil) | ||
| 137 | (port nil) | ||
| 138 | (file nil) | ||
| 139 | (refs nil) | ||
| 140 | (attr nil) | ||
| 141 | (full nil) | ||
| 142 | (inhibit-read-only t)) | ||
| 143 | (erase-buffer) | ||
| 144 | (insert url) | ||
| 145 | (goto-char (point-min)) | ||
| 146 | (setq save-pos (point)) | ||
| 147 | (if (not (looking-at "//")) | ||
| 148 | (progn | ||
| 149 | (skip-chars-forward "a-zA-Z+.\\-") | ||
| 150 | (downcase-region save-pos (point)) | ||
| 151 | (setq prot (buffer-substring save-pos (point))) | ||
| 152 | (skip-chars-forward ":") | ||
| 153 | (setq save-pos (point)))) | ||
| 154 | |||
| 155 | ;; We are doing a fully specified URL, with hostname and all | ||
| 156 | (if (looking-at "//") | ||
| 157 | (progn | ||
| 158 | (setq full t) | ||
| 159 | (forward-char 2) | ||
| 160 | (setq save-pos (point)) | ||
| 161 | (skip-chars-forward "^/") | ||
| 162 | (setq host (buffer-substring save-pos (point))) | ||
| 163 | (if (string-match "^\\([^@]+\\)@" host) | ||
| 164 | (setq user (match-string 1 host) | ||
| 165 | host (substring host (match-end 0) nil))) | ||
| 166 | (if (and user (string-match "\\([^:]+\\):\\(.*\\)" user)) | ||
| 167 | (setq pass (match-string 2 user) | ||
| 168 | user (match-string 1 user))) | ||
| 169 | (if (string-match ":\\([0-9+]+\\)" host) | ||
| 170 | (setq port (string-to-int (match-string 1 host)) | ||
| 171 | host (substring host 0 (match-beginning 0)))) | ||
| 172 | (if (string-match ":$" host) | ||
| 173 | (setq host (substring host 0 (match-beginning 0)))) | ||
| 174 | (setq host (downcase host) | ||
| 175 | save-pos (point)))) | ||
| 176 | |||
| 177 | (if (not port) | ||
| 178 | (setq port (url-scheme-get-property prot 'default-port))) | ||
| 179 | |||
| 180 | ;; Gross hack to preserve ';' in data URLs | ||
| 181 | |||
| 182 | (setq save-pos (point)) | ||
| 183 | |||
| 184 | (if (string= "data" prot) | ||
| 185 | (goto-char (point-max)) | ||
| 186 | ;; Now check for references | ||
| 187 | (skip-chars-forward "^#") | ||
| 188 | (if (eobp) | ||
| 189 | nil | ||
| 190 | (delete-region | ||
| 191 | (point) | ||
| 192 | (progn | ||
| 193 | (skip-chars-forward "#") | ||
| 194 | (setq refs (buffer-substring (point) (point-max))) | ||
| 195 | (point-max)))) | ||
| 196 | (goto-char save-pos) | ||
| 197 | (skip-chars-forward "^;") | ||
| 198 | (if (not (eobp)) | ||
| 199 | (setq attr (url-parse-args (buffer-substring (point) (point-max)) t) | ||
| 200 | attr (nreverse attr)))) | ||
| 201 | |||
| 202 | (setq file (buffer-substring save-pos (point))) | ||
| 203 | (if (and host (string-match "%[0-9][0-9]" host)) | ||
| 204 | (setq host (url-unhex-string host))) | ||
| 205 | (vector prot user pass host port file refs attr full)))))) | ||
| 206 | |||
| 207 | (provide 'url-parse) | ||
| 208 | |||
| 209 | ;; arch-tag: f338325f-71ab-4bee-93cc-78fb9a03d403 | ||
| 210 | ;;; url-parse.el ends here | ||
diff --git a/lisp/url/url-privacy.el b/lisp/url/url-privacy.el new file mode 100644 index 00000000000..cb64cfbd4fc --- /dev/null +++ b/lisp/url/url-privacy.el | |||
| @@ -0,0 +1,81 @@ | |||
| 1 | ;;; url-privacy.el --- Global history tracking for URL package | ||
| 2 | ;; Keywords: comm, data, processes, hypermedia | ||
| 3 | |||
| 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5 | ;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc. | ||
| 6 | ;;; | ||
| 7 | ;;; This file is part of GNU Emacs. | ||
| 8 | ;;; | ||
| 9 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;;; any later version. | ||
| 13 | ;;; | ||
| 14 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;;; GNU General Public License for more details. | ||
| 18 | ;;; | ||
| 19 | ;;; You should have received a copy of the GNU General Public License | ||
| 20 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;;; Boston, MA 02111-1307, USA. | ||
| 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 24 | |||
| 25 | (eval-when-compile (require 'cl)) | ||
| 26 | (require 'url-vars) | ||
| 27 | |||
| 28 | (if (fboundp 'device-type) | ||
| 29 | (defalias 'url-device-type 'device-type) | ||
| 30 | (defun url-device-type (&optional device) (or window-system 'tty))) | ||
| 31 | |||
| 32 | ;;;###autoload | ||
| 33 | (defun url-setup-privacy-info () | ||
| 34 | (interactive) | ||
| 35 | (setq url-system-type | ||
| 36 | (cond | ||
| 37 | ((or (eq url-privacy-level 'paranoid) | ||
| 38 | (and (listp url-privacy-level) | ||
| 39 | (memq 'os url-privacy-level))) | ||
| 40 | nil) | ||
| 41 | ;; First, we handle the inseparable OS/Windowing system | ||
| 42 | ;; combinations | ||
| 43 | ((eq system-type 'Apple-Macintosh) "Macintosh") | ||
| 44 | ((eq system-type 'next-mach) "NeXT") | ||
| 45 | ((eq system-type 'windows-nt) "Windows-NT; 32bit") | ||
| 46 | ((eq system-type 'ms-windows) "Windows; 16bit") | ||
| 47 | ((eq system-type 'ms-dos) "MS-DOS; 32bit") | ||
| 48 | ((memq (url-device-type) '(win32 w32)) "Windows; 32bit") | ||
| 49 | ((eq (url-device-type) 'pm) "OS/2; 32bit") | ||
| 50 | (t | ||
| 51 | (case (url-device-type) | ||
| 52 | (x "X11") | ||
| 53 | (ns "OpenStep") | ||
| 54 | (tty "TTY") | ||
| 55 | (otherwise nil))))) | ||
| 56 | |||
| 57 | (setq url-personal-mail-address (or url-personal-mail-address | ||
| 58 | user-mail-address | ||
| 59 | (format "%s@%s" (user-real-login-name) | ||
| 60 | (system-name)))) | ||
| 61 | |||
| 62 | (if (or (memq url-privacy-level '(paranoid high)) | ||
| 63 | (and (listp url-privacy-level) | ||
| 64 | (memq 'email url-privacy-level))) | ||
| 65 | (setq url-personal-mail-address nil)) | ||
| 66 | |||
| 67 | (setq url-os-type | ||
| 68 | (cond | ||
| 69 | ((or (eq url-privacy-level 'paranoid) | ||
| 70 | (and (listp url-privacy-level) | ||
| 71 | (memq 'os url-privacy-level))) | ||
| 72 | nil) | ||
| 73 | ((boundp 'system-configuration) | ||
| 74 | system-configuration) | ||
| 75 | ((boundp 'system-type) | ||
| 76 | (symbol-name system-type)) | ||
| 77 | (t nil)))) | ||
| 78 | |||
| 79 | (provide 'url-privacy) | ||
| 80 | |||
| 81 | ;;; arch-tag: fdaf95e4-98f0-4680-94c3-f3eadafabe1d | ||
diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el index d4a3733eab5..5d1f73e0d5d 100644 --- a/lisp/url/url-util.el +++ b/lisp/url/url-util.el | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | ;;; url-util.el --- Miscellaneous helper routines for URL library | 1 | ;;; url-util.el --- Miscellaneous helper routines for URL library |
| 2 | 2 | ||
| 3 | ;; Copyright (c) 1996,97,98,99,2001,2004 Free Software Foundation, Inc. | 3 | ;; Copyright (c) 1996,1997,1998,1999,2001,2004 Free Software Foundation, Inc. |
| 4 | ;; Copyright (c) 1993 - 1996 by William M. Perry <wmperry@cs.indiana.edu> | ||
| 5 | 4 | ||
| 6 | ;; Author: Bill Perry <wmperry@gnu.org> | 5 | ;; Author: Bill Perry <wmperry@gnu.org> |
| 7 | ;; Keywords: comm, data, processes | 6 | ;; Keywords: comm, data, processes |
diff --git a/lisp/url/url-vars.el b/lisp/url/url-vars.el new file mode 100644 index 00000000000..a33d8ba43e3 --- /dev/null +++ b/lisp/url/url-vars.el | |||
| @@ -0,0 +1,431 @@ | |||
| 1 | ;;; url-vars.el --- Variables for Uniform Resource Locator tool | ||
| 2 | ;; Keywords: comm, data, processes, hypermedia | ||
| 3 | |||
| 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5 | ;;; Copyright (c) 1996,1997,1998,1999,2001,2004 Free Software Foundation, Inc. | ||
| 6 | ;;; | ||
| 7 | ;;; This file is part of GNU Emacs. | ||
| 8 | ;;; | ||
| 9 | ;;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;;; any later version. | ||
| 13 | ;;; | ||
| 14 | ;;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;;; GNU General Public License for more details. | ||
| 18 | ;;; | ||
| 19 | ;;; You should have received a copy of the GNU General Public License | ||
| 20 | ;;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;;; Boston, MA 02111-1307, USA. | ||
| 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 24 | |||
| 25 | (require 'mm-util) | ||
| 26 | |||
| 27 | (defconst url-version "Emacs" | ||
| 28 | "Version number of URL package.") | ||
| 29 | |||
| 30 | (defgroup url nil | ||
| 31 | "Uniform Resource Locator tool" | ||
| 32 | :version "21.4" | ||
| 33 | :group 'hypermedia) | ||
| 34 | |||
| 35 | (defgroup url-file nil | ||
| 36 | "URL storage" | ||
| 37 | :prefix "url-" | ||
| 38 | :group 'url) | ||
| 39 | |||
| 40 | (defgroup url-cache nil | ||
| 41 | "URL cache" | ||
| 42 | :prefix "url-" | ||
| 43 | :prefix "url-cache-" | ||
| 44 | :group 'url) | ||
| 45 | |||
| 46 | (defgroup url-mime nil | ||
| 47 | "MIME options of URL" | ||
| 48 | :prefix "url-" | ||
| 49 | :group 'url) | ||
| 50 | |||
| 51 | (defgroup url-hairy nil | ||
| 52 | "Hairy options of URL" | ||
| 53 | :prefix "url-" | ||
| 54 | :group 'url) | ||
| 55 | |||
| 56 | |||
| 57 | (defvar url-current-object nil | ||
| 58 | "A parsed representation of the current url.") | ||
| 59 | |||
| 60 | (defvar url-current-mime-headers nil | ||
| 61 | "A parsed representation of the MIME headers for the current url.") | ||
| 62 | |||
| 63 | (mapcar 'make-variable-buffer-local | ||
| 64 | '( | ||
| 65 | url-current-object | ||
| 66 | url-current-referer | ||
| 67 | url-current-mime-headers | ||
| 68 | )) | ||
| 69 | |||
| 70 | (defcustom url-honor-refresh-requests t | ||
| 71 | "*Whether to do automatic page reloads. | ||
| 72 | These are done at the request of the document author or the server via | ||
| 73 | the `Refresh' header in an HTTP response. If nil, no refresh | ||
| 74 | requests will be honored. If t, all refresh requests will be honored. | ||
| 75 | If non-nil and not t, the user will be asked for each refresh | ||
| 76 | request." | ||
| 77 | :type '(choice (const :tag "off" nil) | ||
| 78 | (const :tag "on" t) | ||
| 79 | (const :tag "ask" 'ask)) | ||
| 80 | :group 'url-hairy) | ||
| 81 | |||
| 82 | (defcustom url-automatic-caching nil | ||
| 83 | "*If non-nil, all documents will be automatically cached to the local disk." | ||
| 84 | :type 'boolean | ||
| 85 | :group 'url-cache) | ||
| 86 | |||
| 87 | ;; Fixme: sanitize this. | ||
| 88 | (defcustom url-cache-expired | ||
| 89 | (lambda (t1 t2) (>= (- (car t2) (car t1)) 5)) | ||
| 90 | "*A function determining if a cached item has expired. | ||
| 91 | It takes two times (numbers) as its arguments, and returns non-nil if | ||
| 92 | the second time is 'too old' when compared to the first time." | ||
| 93 | :type 'function | ||
| 94 | :group 'url-cache) | ||
| 95 | |||
| 96 | (defconst url-bug-address "bug-gnu-emacs@gnu.org" | ||
| 97 | "Where to send bug reports.") | ||
| 98 | |||
| 99 | (defcustom url-personal-mail-address nil | ||
| 100 | "*Your full email address. | ||
| 101 | This is what is sent to HTTP servers as the FROM field in an HTTP | ||
| 102 | request." | ||
| 103 | :type '(choice (const :tag "Unspecified" nil) string) | ||
| 104 | :group 'url) | ||
| 105 | |||
| 106 | (defcustom url-directory-index-file "index.html" | ||
| 107 | "*The filename to look for when indexing a directory. | ||
| 108 | If this file exists, and is readable, then it will be viewed instead of | ||
| 109 | using `dired' to view the directory." | ||
| 110 | :type 'string | ||
| 111 | :group 'url-file) | ||
| 112 | |||
| 113 | ;; Fixme: this should have a setter which calls url-setup-privacy-info. | ||
| 114 | (defcustom url-privacy-level '(email) | ||
| 115 | "*How private you want your requests to be. | ||
| 116 | HTTP has header fields for various information about the user, including | ||
| 117 | operating system information, email addresses, the last page you visited, etc. | ||
| 118 | This variable controls how much of this information is sent. | ||
| 119 | |||
| 120 | This should a symbol or a list. | ||
| 121 | Valid values if a symbol are: | ||
| 122 | none -- Send all information | ||
| 123 | low -- Don't send the last location | ||
| 124 | high -- Don't send the email address or last location | ||
| 125 | paranoid -- Don't send anything | ||
| 126 | |||
| 127 | If a list, this should be a list of symbols of what NOT to send. | ||
| 128 | Valid symbols are: | ||
| 129 | email -- the email address | ||
| 130 | os -- the operating system info | ||
| 131 | lastloc -- the last location | ||
| 132 | agent -- Do not send the User-Agent string | ||
| 133 | cookie -- never accept HTTP cookies | ||
| 134 | |||
| 135 | Samples: | ||
| 136 | |||
| 137 | (setq url-privacy-level 'high) | ||
| 138 | (setq url-privacy-level '(email lastloc)) ;; equivalent to 'high | ||
| 139 | (setq url-privacy-level '(os)) | ||
| 140 | |||
| 141 | ::NOTE:: | ||
| 142 | This variable controls several other variables and is _NOT_ automatically | ||
| 143 | updated. Call the function `url-setup-privacy-info' after modifying this | ||
| 144 | variable." | ||
| 145 | :type '(radio (const :tag "None (you believe in the basic goodness of humanity)" | ||
| 146 | :value none) | ||
| 147 | (const :tag "Low (do not reveal last location)" | ||
| 148 | :value low) | ||
| 149 | (const :tag "High (no email address or last location)" | ||
| 150 | :value high) | ||
| 151 | (const :tag "Paranoid (reveal nothing!)" | ||
| 152 | :value paranoid) | ||
| 153 | (checklist :tag "Custom" | ||
| 154 | (const :tag "Email address" :value email) | ||
| 155 | (const :tag "Operating system" :value os) | ||
| 156 | (const :tag "Last location" :value lastloc) | ||
| 157 | (const :tag "Browser identification" :value agent) | ||
| 158 | (const :tag "No cookies" :value cookie))) | ||
| 159 | :group 'url) | ||
| 160 | |||
| 161 | (defvar url-inhibit-uncompression nil "Do not do decompression if non-nil.") | ||
| 162 | |||
| 163 | (defcustom url-uncompressor-alist '((".z" . "x-gzip") | ||
| 164 | (".gz" . "x-gzip") | ||
| 165 | (".uue" . "x-uuencoded") | ||
| 166 | (".hqx" . "x-hqx") | ||
| 167 | (".Z" . "x-compress") | ||
| 168 | (".bz2" . "x-bzip2")) | ||
| 169 | "*An alist of file extensions and appropriate content-transfer-encodings." | ||
| 170 | :type '(repeat (cons :format "%v" | ||
| 171 | (string :tag "Extension") | ||
| 172 | (string :tag "Encoding"))) | ||
| 173 | :group 'url-mime) | ||
| 174 | |||
| 175 | (defcustom url-mail-command (if (fboundp 'compose-mail) | ||
| 176 | 'compose-mail | ||
| 177 | 'url-mail) | ||
| 178 | "*This function will be called whenever url needs to send mail. | ||
| 179 | It should enter a mail-mode-like buffer in the current window. | ||
| 180 | The commands `mail-to' and `mail-subject' should still work in this | ||
| 181 | buffer, and it should use `mail-header-separator' if possible." | ||
| 182 | :type 'function | ||
| 183 | :group 'url) | ||
| 184 | |||
| 185 | (defcustom url-proxy-services nil | ||
| 186 | "*An alist of schemes and proxy servers that gateway them. | ||
| 187 | Looks like ((\"http\" . \"hostname:portnumber\") ...). This is set up | ||
| 188 | from the ACCESS_proxy environment variables." | ||
| 189 | :type '(repeat (cons :format "%v" | ||
| 190 | (string :tag "Protocol") | ||
| 191 | (string :tag "Proxy"))) | ||
| 192 | :group 'url) | ||
| 193 | |||
| 194 | (defcustom url-passwd-entry-func nil | ||
| 195 | "*Symbol indicating which function to call to read in a password. | ||
| 196 | It will be set up depending on whether you are running EFS or ange-ftp | ||
| 197 | at startup if it is nil. This function should accept the prompt | ||
| 198 | string as its first argument, and the default value as its second | ||
| 199 | argument." | ||
| 200 | :type '(choice (const :tag "Guess" :value nil) | ||
| 201 | (const :tag "Use Ange-FTP" :value ange-ftp-read-passwd) | ||
| 202 | (const :tag "Use EFS" :value efs-read-passwd) | ||
| 203 | (const :tag "Use Password Package" :value read-passwd) | ||
| 204 | (function :tag "Other")) | ||
| 205 | :group 'url-hairy) | ||
| 206 | |||
| 207 | (defcustom url-standalone-mode nil | ||
| 208 | "*Rely solely on the cache?" | ||
| 209 | :type 'boolean | ||
| 210 | :group 'url-cache) | ||
| 211 | |||
| 212 | (defvar url-mime-separator-chars (mapcar 'identity | ||
| 213 | (concat "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
| 214 | "abcdefghijklmnopqrstuvwxyz" | ||
| 215 | "0123456789'()+_,-./=?")) | ||
| 216 | "Characters allowable in a MIME multipart separator.") | ||
| 217 | |||
| 218 | (defcustom url-bad-port-list | ||
| 219 | '("25" "119" "19") | ||
| 220 | "*List of ports to warn the user about connecting to. | ||
| 221 | Defaults to just the mail, chargen, and NNTP ports so you cannot be | ||
| 222 | tricked into sending fake mail or forging messages by a malicious HTML | ||
| 223 | document." | ||
| 224 | :type '(repeat (string :tag "Port")) | ||
| 225 | :group 'url-hairy) | ||
| 226 | |||
| 227 | (defvar url-mime-content-type-charset-regexp | ||
| 228 | ";[ \t]*charset=\"?\\([^\"]+\\)\"?" | ||
| 229 | "Regexp used in parsing `Content-Type' for a charset indication.") | ||
| 230 | |||
| 231 | (defvar url-request-data nil "Any data to send with the next request.") | ||
| 232 | |||
| 233 | (defvar url-request-extra-headers nil | ||
| 234 | "A list of extra headers to send with the next request. | ||
| 235 | Should be an assoc list of headers/contents.") | ||
| 236 | |||
| 237 | (defvar url-request-method nil "The method to use for the next request.") | ||
| 238 | |||
| 239 | ;; FIXME!! (RFC 2616 gives examples like `compress, gzip'.) | ||
| 240 | (defvar url-mime-encoding-string nil | ||
| 241 | "*String to send in the Accept-encoding: field in HTTP requests.") | ||
| 242 | |||
| 243 | ;; `mm-mime-mule-charset-alist' in Gnus 5.8/9 contains elements whose | ||
| 244 | ;; cars aren't valid MIME charsets/coding systems, at least in Emacs. | ||
| 245 | ;; This gets it correct by construction in Emacs. Fixme: DTRT for | ||
| 246 | ;; XEmacs -- its `coding-system-list' doesn't have the BASE-ONLY arg. | ||
| 247 | (when (and (not (featurep 'xemacs)) | ||
| 248 | (fboundp 'coding-system-list)) | ||
| 249 | (setq mm-mime-mule-charset-alist | ||
| 250 | (apply | ||
| 251 | 'nconc | ||
| 252 | (mapcar | ||
| 253 | (lambda (cs) | ||
| 254 | (when (and (coding-system-get cs 'mime-charset) | ||
| 255 | (not (eq t (coding-system-get cs 'safe-charsets)))) | ||
| 256 | (list (cons (coding-system-get cs 'mime-charset) | ||
| 257 | (delq 'ascii | ||
| 258 | (coding-system-get cs 'safe-charsets)))))) | ||
| 259 | (coding-system-list 'base-only))))) | ||
| 260 | |||
| 261 | ;; Perhaps the first few should actually be given decreasing `q's and | ||
| 262 | ;; the list should be trimmed significantly. | ||
| 263 | ;; Fixme: do something sane if we don't have `sort-coding-systems' | ||
| 264 | ;; (Emacs 20, XEmacs). | ||
| 265 | (defun url-mime-charset-string () | ||
| 266 | "Generate a list of preferred MIME charsets for HTTP requests. | ||
| 267 | Generated according to current coding system priorities." | ||
| 268 | (if (fboundp 'sort-coding-systems) | ||
| 269 | (let ((ordered (sort-coding-systems | ||
| 270 | (let (accum) | ||
| 271 | (dolist (elt mm-mime-mule-charset-alist) | ||
| 272 | (if (mm-coding-system-p (car elt)) | ||
| 273 | (push (car elt) accum))) | ||
| 274 | (nreverse accum))))) | ||
| 275 | (concat (format "%s;q=1, " (pop ordered)) | ||
| 276 | (mapconcat 'symbol-name ordered ";q=0.5, ") | ||
| 277 | ";q=0.5")))) | ||
| 278 | |||
| 279 | (defvar url-mime-charset-string (url-mime-charset-string) | ||
| 280 | "*String to send in the Accept-charset: field in HTTP requests. | ||
| 281 | The MIME charset corresponding to the most preferred coding system is | ||
| 282 | given priority 1 and the rest are given priority 0.5.") | ||
| 283 | |||
| 284 | (defun url-set-mime-charset-string () | ||
| 285 | (setq url-mime-charset-string (url-mime-charset-string))) | ||
| 286 | ;; Regenerate if the language environment changes. | ||
| 287 | (add-hook 'set-language-environment-hook 'url-set-mime-charset-string) | ||
| 288 | |||
| 289 | ;; Fixme: set from the locale. | ||
| 290 | (defcustom url-mime-language-string nil | ||
| 291 | "*String to send in the Accept-language: field in HTTP requests. | ||
| 292 | |||
| 293 | Specifies the preferred language when servers can serve documents in | ||
| 294 | several languages. Use RFC 1766 abbreviations, e.g.@: `en' for | ||
| 295 | English, `de' for German. A comma-separated specifies descending | ||
| 296 | order of preference. The ordering can be made explicit using `q' | ||
| 297 | factors defined by HTTP, e.g. `de,en-gb;q=0.8,en;q=0.7'. `*' means | ||
| 298 | get the first available language (as opposed to the default)." | ||
| 299 | :type '(radio | ||
| 300 | (const :tag "None (get default language version)" :value nil) | ||
| 301 | (const :tag "Any (get first available language version)" :value "*") | ||
| 302 | (string :tag "Other")) | ||
| 303 | :group 'url-mime | ||
| 304 | :group 'i18n) | ||
| 305 | |||
| 306 | (defvar url-mime-accept-string nil | ||
| 307 | "String to send to the server in the Accept: field in HTTP requests.") | ||
| 308 | |||
| 309 | (defvar url-package-version nil | ||
| 310 | "Version number of package using URL.") | ||
| 311 | |||
| 312 | (defvar url-package-name nil "Version number of package using URL.") | ||
| 313 | |||
| 314 | (defvar url-system-type nil | ||
| 315 | "What type of system we are on.") | ||
| 316 | (defvar url-os-type nil | ||
| 317 | "What OS we are on.") | ||
| 318 | |||
| 319 | (defcustom url-max-password-attempts 5 | ||
| 320 | "*Maximum number of times a password will be prompted for. | ||
| 321 | Applies when a protected document is denied by the server." | ||
| 322 | :type 'integer | ||
| 323 | :group 'url) | ||
| 324 | |||
| 325 | (defcustom url-temporary-directory (or (getenv "TMPDIR") "/tmp") | ||
| 326 | "*Where temporary files go." | ||
| 327 | :type 'directory | ||
| 328 | :group 'url-file) | ||
| 329 | |||
| 330 | (defcustom url-show-status t | ||
| 331 | "*Whether to show a running total of bytes transferred. | ||
| 332 | Can cause a large hit if using a remote X display over a slow link, or | ||
| 333 | a terminal with a slow modem." | ||
| 334 | :type 'boolean | ||
| 335 | :group 'url) | ||
| 336 | |||
| 337 | (defvar url-using-proxy nil | ||
| 338 | "Either nil or the fully qualified proxy URL in use, e.g. | ||
| 339 | http://www.domain.com/") | ||
| 340 | |||
| 341 | (defcustom url-news-server nil | ||
| 342 | "*The default news server from which to get newsgroups/articles. | ||
| 343 | Applies if no server is specified in the URL. Defaults to the | ||
| 344 | environment variable NNTPSERVER or \"news\" if NNTPSERVER is | ||
| 345 | undefined." | ||
| 346 | :type '(choice (const :tag "None" :value nil) string) | ||
| 347 | :group 'url) | ||
| 348 | |||
| 349 | (defvar url-nonrelative-link | ||
| 350 | "\\`\\([-a-zA-Z0-9+.]+:\\)" | ||
| 351 | "A regular expression that will match an absolute URL.") | ||
| 352 | |||
| 353 | (defcustom url-confirmation-func 'y-or-n-p | ||
| 354 | "*What function to use for asking yes or no functions. | ||
| 355 | Possible values are `yes-or-no-p' or `y-or-n-p', or any function that | ||
| 356 | takes a single argument (the prompt), and returns t only if a positive | ||
| 357 | answer is given." | ||
| 358 | :type '(choice (const :tag "Short (y or n)" :value y-or-n-p) | ||
| 359 | (const :tag "Long (yes or no)" :value yes-or-no-p) | ||
| 360 | (function :tag "Other")) | ||
| 361 | :group 'url-hairy) | ||
| 362 | |||
| 363 | (defcustom url-gateway-method 'native | ||
| 364 | "*The type of gateway support to use. | ||
| 365 | Should be a symbol specifying how to get a connection from the local machine. | ||
| 366 | |||
| 367 | Currently supported methods: | ||
| 368 | `telnet': Run telnet in a subprocess to connect; | ||
| 369 | `rlogin': Rlogin to another machine to connect; | ||
| 370 | `socks': Connect through a socks server; | ||
| 371 | `tls': Connect with TLS; | ||
| 372 | `ssl': Connect with SSL (deprecated, use `tls' instead); | ||
| 373 | `native': Connect directy." | ||
| 374 | :type '(radio (const :tag "Telnet to gateway host" :value telnet) | ||
| 375 | (const :tag "Rlogin to gateway host" :value rlogin) | ||
| 376 | (const :tag "Use SOCKS proxy" :value socks) | ||
| 377 | (const :tag "Use SSL/TLS for all connections" :value tls) | ||
| 378 | (const :tag "Use SSL for all connections (obsolete)" :value ssl) | ||
| 379 | (const :tag "Direct connection" :value native)) | ||
| 380 | :group 'url-hairy) | ||
| 381 | |||
| 382 | (defvar url-setup-done nil "Has setup configuration been done?") | ||
| 383 | |||
| 384 | (defconst weekday-alist | ||
| 385 | '(("Sunday" . 0) ("Monday" . 1) ("Tuesday" . 2) ("Wednesday" . 3) | ||
| 386 | ("Thursday" . 4) ("Friday" . 5) ("Saturday" . 6) | ||
| 387 | ("Tues" . 2) ("Thurs" . 4) | ||
| 388 | ("Sun" . 0) ("Mon" . 1) ("Tue" . 2) ("Wed" . 3) | ||
| 389 | ("Thu" . 4) ("Fri" . 5) ("Sat" . 6))) | ||
| 390 | |||
| 391 | (defconst monthabbrev-alist | ||
| 392 | '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3) ("Apr" . 4) ("May" . 5) ("Jun" . 6) | ||
| 393 | ("Jul" . 7) ("Aug" . 8) ("Sep" . 9) ("Oct" . 10) ("Nov" . 11) | ||
| 394 | ("Dec" . 12))) | ||
| 395 | |||
| 396 | (defvar url-lazy-message-time 0) | ||
| 397 | |||
| 398 | ;; Fixme: We may not be able to run SSL. | ||
| 399 | (defvar url-extensions-header "Security/Digest Security/SSL") | ||
| 400 | |||
| 401 | (defvar url-parse-syntax-table | ||
| 402 | (copy-syntax-table emacs-lisp-mode-syntax-table) | ||
| 403 | "*A syntax table for parsing URLs.") | ||
| 404 | |||
| 405 | (modify-syntax-entry ?' "\"" url-parse-syntax-table) | ||
| 406 | (modify-syntax-entry ?` "\"" url-parse-syntax-table) | ||
| 407 | (modify-syntax-entry ?< "(>" url-parse-syntax-table) | ||
| 408 | (modify-syntax-entry ?> ")<" url-parse-syntax-table) | ||
| 409 | (modify-syntax-entry ?/ " " url-parse-syntax-table) | ||
| 410 | |||
| 411 | (defvar url-load-hook nil | ||
| 412 | "*Hooks to be run after initalizing the URL library.") | ||
| 413 | |||
| 414 | ;;; Make OS/2 happy - yeeks | ||
| 415 | ;; (defvar tcp-binary-process-input-services nil | ||
| 416 | ;; "*Make OS/2 happy with our CRLF pairs...") | ||
| 417 | |||
| 418 | (defconst url-working-buffer " *url-work") | ||
| 419 | |||
| 420 | (defvar url-gateway-unplugged nil | ||
| 421 | "Non-nil means don't open new network connexions. | ||
| 422 | This should be set, e.g. by mail user agents rendering HTML to avoid | ||
| 423 | `bugs' which call home.") | ||
| 424 | |||
| 425 | (defun url-vars-unload-hook () | ||
| 426 | (remove-hook 'set-language-environment-hook 'url-set-mime-charset-string)) | ||
| 427 | |||
| 428 | (provide 'url-vars) | ||
| 429 | |||
| 430 | ;;; arch-tag: 29205e5f-c5ce-433c-8d5d-38cbaed64b49 | ||
| 431 | ;;; url-vars.el ends here | ||
diff --git a/lisp/url/url.el b/lisp/url/url.el new file mode 100644 index 00000000000..f7b1b717681 --- /dev/null +++ b/lisp/url/url.el | |||
| @@ -0,0 +1,269 @@ | |||
| 1 | ;;; url.el --- Uniform Resource Locator retrieval tool | ||
| 2 | |||
| 3 | ;; Copyright (c) 1996,1997,1998,1999,2001,2004 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Bill Perry <wmperry@gnu.org> | ||
| 6 | ;; Keywords: comm, data, processes, hypermedia | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | ;; | ||
| 10 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 13 | ;; any later version. | ||
| 14 | ;; | ||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | ;; | ||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 22 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 23 | ;; Boston, MA 02111-1307, USA. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | |||
| 27 | ;; Registered URI schemes: http://www.iana.org/assignments/uri-schemes | ||
| 28 | |||
| 29 | ;;; Code: | ||
| 30 | |||
| 31 | (eval-when-compile (require 'cl)) | ||
| 32 | ;; Don't require CL at runtime if we can avoid it (Emacs 21). | ||
| 33 | ;; Otherwise we need it for hashing functions. `puthash' was never | ||
| 34 | ;; defined in the Emacs 20 cl.el for some reason. | ||
| 35 | (if (fboundp 'puthash) | ||
| 36 | nil ; internal or CL is loaded | ||
| 37 | (defalias 'puthash 'cl-puthash) | ||
| 38 | (autoload 'cl-puthash "cl") | ||
| 39 | (autoload 'gethash "cl") | ||
| 40 | (autoload 'maphash "cl") | ||
| 41 | (autoload 'make-hash-table "cl")) | ||
| 42 | |||
| 43 | (eval-when-compile | ||
| 44 | (require 'mm-decode) | ||
| 45 | (require 'mm-view)) | ||
| 46 | |||
| 47 | (require 'mailcap) | ||
| 48 | (require 'url-vars) | ||
| 49 | (require 'url-cookie) | ||
| 50 | (require 'url-history) | ||
| 51 | (require 'url-expand) | ||
| 52 | (require 'url-privacy) | ||
| 53 | (require 'url-methods) | ||
| 54 | (require 'url-proxy) | ||
| 55 | (require 'url-parse) | ||
| 56 | (require 'url-util) | ||
| 57 | |||
| 58 | ;; Fixme: customize? convert-standard-filename? | ||
| 59 | ;;;###autoload | ||
| 60 | (defvar url-configuration-directory "~/.url") | ||
| 61 | |||
| 62 | (defun url-do-setup () | ||
| 63 | "Setup the url package. | ||
| 64 | This is to avoid conflict with user settings if URL is dumped with | ||
| 65 | Emacs." | ||
| 66 | (unless url-setup-done | ||
| 67 | |||
| 68 | ;; Make OS/2 happy | ||
| 69 | ;;(push '("http" "80") tcp-binary-process-input-services) | ||
| 70 | |||
| 71 | (mailcap-parse-mailcaps) | ||
| 72 | (mailcap-parse-mimetypes) | ||
| 73 | |||
| 74 | ;; Register all the authentication schemes we can handle | ||
| 75 | (url-register-auth-scheme "basic" nil 4) | ||
| 76 | (url-register-auth-scheme "digest" nil 7) | ||
| 77 | |||
| 78 | (setq url-cookie-file | ||
| 79 | (or url-cookie-file | ||
| 80 | (expand-file-name "cookies" url-configuration-directory))) | ||
| 81 | |||
| 82 | (setq url-history-file | ||
| 83 | (or url-history-file | ||
| 84 | (expand-file-name "history" url-configuration-directory))) | ||
| 85 | |||
| 86 | ;; Parse the global history file if it exists, so that it can be used | ||
| 87 | ;; for URL completion, etc. | ||
| 88 | (url-history-parse-history) | ||
| 89 | (url-history-setup-save-timer) | ||
| 90 | |||
| 91 | ;; Ditto for cookies | ||
| 92 | (url-cookie-setup-save-timer) | ||
| 93 | (url-cookie-parse-file url-cookie-file) | ||
| 94 | |||
| 95 | ;; Read in proxy gateways | ||
| 96 | (let ((noproxy (and (not (assoc "no_proxy" url-proxy-services)) | ||
| 97 | (or (getenv "NO_PROXY") | ||
| 98 | (getenv "no_PROXY") | ||
| 99 | (getenv "no_proxy"))))) | ||
| 100 | (if noproxy | ||
| 101 | (setq url-proxy-services | ||
| 102 | (cons (cons "no_proxy" | ||
| 103 | (concat "\\(" | ||
| 104 | (mapconcat | ||
| 105 | (lambda (x) | ||
| 106 | (cond | ||
| 107 | ((= x ?,) "\\|") | ||
| 108 | ((= x ? ) "") | ||
| 109 | ((= x ?.) (regexp-quote ".")) | ||
| 110 | ((= x ?*) ".*") | ||
| 111 | ((= x ??) ".") | ||
| 112 | (t (char-to-string x)))) | ||
| 113 | noproxy "") "\\)")) | ||
| 114 | url-proxy-services)))) | ||
| 115 | |||
| 116 | ;; Set the password entry funtion based on user defaults or guess | ||
| 117 | ;; based on which remote-file-access package they are using. | ||
| 118 | (cond | ||
| 119 | (url-passwd-entry-func nil) ; Already been set | ||
| 120 | ((fboundp 'read-passwd) ; Use secure password if available | ||
| 121 | (setq url-passwd-entry-func 'read-passwd)) | ||
| 122 | ((or (featurep 'efs) ; Using EFS | ||
| 123 | (featurep 'efs-auto)) ; or autoloading efs | ||
| 124 | (if (not (fboundp 'read-passwd)) | ||
| 125 | (autoload 'read-passwd "passwd" "Read in a password" nil)) | ||
| 126 | (setq url-passwd-entry-func 'read-passwd)) | ||
| 127 | ((or (featurep 'ange-ftp) ; Using ange-ftp | ||
| 128 | (and (boundp 'file-name-handler-alist) | ||
| 129 | (not (featurep 'xemacs)))) ; ?? | ||
| 130 | (setq url-passwd-entry-func 'ange-ftp-read-passwd)) | ||
| 131 | (t | ||
| 132 | (url-warn | ||
| 133 | 'security | ||
| 134 | "(url-setup): Can't determine how to read passwords, winging it."))) | ||
| 135 | |||
| 136 | (url-setup-privacy-info) | ||
| 137 | (run-hooks 'url-load-hook) | ||
| 138 | (setq url-setup-done t))) | ||
| 139 | |||
| 140 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 141 | ;;; Retrieval functions | ||
| 142 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 143 | (defun url-retrieve (url callback &optional cbargs) | ||
| 144 | "Retrieve URL asynchronously and call CALLBACK with CBARGS when finished. | ||
| 145 | The callback is called when the object has been completely retrieved, with | ||
| 146 | the current buffer containing the object, and any MIME headers associated | ||
| 147 | with it. URL is either a string or a parsed URL. | ||
| 148 | |||
| 149 | Return the buffer URL will load into, or nil if the process has | ||
| 150 | already completed." | ||
| 151 | (url-do-setup) | ||
| 152 | (url-gc-dead-buffers) | ||
| 153 | (if (stringp url) | ||
| 154 | (set-text-properties 0 (length url) nil url)) | ||
| 155 | (if (not (vectorp url)) | ||
| 156 | (setq url (url-generic-parse-url url))) | ||
| 157 | (if (not (functionp callback)) | ||
| 158 | (error "Must provide a callback function to url-retrieve")) | ||
| 159 | (unless (url-type url) | ||
| 160 | (error "Bad url: %s" (url-recreate-url url))) | ||
| 161 | (let ((loader (url-scheme-get-property (url-type url) 'loader)) | ||
| 162 | (url-using-proxy (if (url-host url) | ||
| 163 | (url-find-proxy-for-url url (url-host url)))) | ||
| 164 | (buffer nil) | ||
| 165 | (asynch (url-scheme-get-property (url-type url) 'asynchronous-p))) | ||
| 166 | (if url-using-proxy | ||
| 167 | (setq asynch t | ||
| 168 | loader 'url-proxy)) | ||
| 169 | (if asynch | ||
| 170 | (setq buffer (funcall loader url callback cbargs)) | ||
| 171 | (setq buffer (funcall loader url)) | ||
| 172 | (if buffer | ||
| 173 | (with-current-buffer buffer | ||
| 174 | (apply callback cbargs)))) | ||
| 175 | (url-history-update-url url (current-time)) | ||
| 176 | buffer)) | ||
| 177 | |||
| 178 | (defun url-retrieve-synchronously (url) | ||
| 179 | "Retrieve URL synchronously. | ||
| 180 | Return the buffer containing the data, or nil if there are no data | ||
| 181 | associated with it (the case for dired, info, or mailto URLs that need | ||
| 182 | no further processing). URL is either a string or a parsed URL." | ||
| 183 | (url-do-setup) | ||
| 184 | |||
| 185 | (lexical-let ((retrieval-done nil) | ||
| 186 | (asynch-buffer nil)) | ||
| 187 | (setq asynch-buffer | ||
| 188 | (url-retrieve url (lambda (&rest ignored) | ||
| 189 | (url-debug 'retrieval "Synchronous fetching done (%S)" (current-buffer)) | ||
| 190 | (setq retrieval-done t | ||
| 191 | asynch-buffer (current-buffer))))) | ||
| 192 | (if (not asynch-buffer) | ||
| 193 | ;; We do not need to do anything, it was a mailto or something | ||
| 194 | ;; similar that takes processing completely outside of the URL | ||
| 195 | ;; package. | ||
| 196 | nil | ||
| 197 | (while (not retrieval-done) | ||
| 198 | (url-debug 'retrieval "Spinning in url-retrieve-synchronously: %S (%S)" | ||
| 199 | retrieval-done asynch-buffer) | ||
| 200 | ;; Quoth Stef: | ||
| 201 | ;; It turns out that the problem seems to be that the (sit-for | ||
| 202 | ;; 0.1) below doesn't actually process the data: instead it | ||
| 203 | ;; returns immediately because there is keyboard input | ||
| 204 | ;; waiting, so we end up spinning endlessly waiting for the | ||
| 205 | ;; process to finish while not letting it finish. | ||
| 206 | |||
| 207 | ;; However, raman claims that it blocks Emacs with Emacspeak | ||
| 208 | ;; for unexplained reasons. Put back for his benefit until | ||
| 209 | ;; someone can understand it. | ||
| 210 | ;; (sleep-for 0.1) | ||
| 211 | (sit-for 0.1)) | ||
| 212 | asynch-buffer))) | ||
| 213 | |||
| 214 | (defun url-mm-callback (&rest ignored) | ||
| 215 | (let ((handle (mm-dissect-buffer t))) | ||
| 216 | (save-excursion | ||
| 217 | (url-mark-buffer-as-dead (current-buffer)) | ||
| 218 | (set-buffer (generate-new-buffer (url-recreate-url url-current-object))) | ||
| 219 | (if (eq (mm-display-part handle) 'external) | ||
| 220 | (progn | ||
| 221 | (set-process-sentinel | ||
| 222 | ;; Fixme: this shouldn't have to know the form of the | ||
| 223 | ;; undisplayer produced by `mm-display-part'. | ||
| 224 | (get-buffer-process (cdr (mm-handle-undisplayer handle))) | ||
| 225 | `(lambda (proc event) | ||
| 226 | (mm-destroy-parts (quote ,handle)))) | ||
| 227 | (message "Viewing externally") | ||
| 228 | (kill-buffer (current-buffer))) | ||
| 229 | (display-buffer (current-buffer)) | ||
| 230 | (mm-destroy-parts handle))))) | ||
| 231 | |||
| 232 | (defun url-mm-url (url) | ||
| 233 | "Retrieve URL and pass to the appropriate viewing application." | ||
| 234 | (require 'mm-decode) | ||
| 235 | (require 'mm-view) | ||
| 236 | (url-retrieve url 'url-mm-callback nil)) | ||
| 237 | |||
| 238 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 239 | ;;; Miscellaneous | ||
| 240 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 241 | (defvar url-dead-buffer-list nil) | ||
| 242 | |||
| 243 | (defun url-mark-buffer-as-dead (buff) | ||
| 244 | (push buff url-dead-buffer-list)) | ||
| 245 | |||
| 246 | (defun url-gc-dead-buffers () | ||
| 247 | (let ((buff)) | ||
| 248 | (while (setq buff (pop url-dead-buffer-list)) | ||
| 249 | (if (buffer-live-p buff) | ||
| 250 | (kill-buffer buff))))) | ||
| 251 | |||
| 252 | (cond | ||
| 253 | ((fboundp 'display-warning) | ||
| 254 | (defalias 'url-warn 'display-warning)) | ||
| 255 | ((fboundp 'warn) | ||
| 256 | (defun url-warn (class message &optional level) | ||
| 257 | (warn "(%s/%s) %s" class (or level 'warning) message))) | ||
| 258 | (t | ||
| 259 | (defun url-warn (class message &optional level) | ||
| 260 | (with-current-buffer (get-buffer-create "*URL-WARNINGS*") | ||
| 261 | (goto-char (point-max)) | ||
| 262 | (save-excursion | ||
| 263 | (insert (format "(%s/%s) %s\n" class (or level 'warning) message))) | ||
| 264 | (display-buffer (current-buffer)))))) | ||
| 265 | |||
| 266 | (provide 'url) | ||
| 267 | |||
| 268 | ;; arch-tag: bc182f1f-d187-4f10-b961-47af2066579a | ||
| 269 | ;;; url.el ends here | ||