comparison lisp/w3/url.el @ 26:441bb1e64a06 r19-15b96

Import from CVS: tag r19-15b96
author cvs
date Mon, 13 Aug 2007 08:51:32 +0200
parents 859a2309aef8
children ec9a17fef872
comparison
equal deleted inserted replaced
25:383a494979f8 26:441bb1e64a06
1 ;;; url.el --- Uniform Resource Locator retrieval tool 1 ;;; url.el --- Uniform Resource Locator retrieval tool
2 ;; Author: wmperry 2 ;; Author: wmperry
3 ;; Created: 1997/02/07 14:30:25 3 ;; Created: 1997/02/20 15:34:07
4 ;; Version: 1.51 4 ;; Version: 1.57
5 ;; Keywords: comm, data, processes, hypermedia 5 ;; Keywords: comm, data, processes, hypermedia
6 6
7 ;;; LCD Archive Entry: 7 ;;; LCD Archive Entry:
8 ;;; url|William M. Perry|wmperry@cs.indiana.edu| 8 ;;; url|William M. Perry|wmperry@cs.indiana.edu|
9 ;;; Functions for retrieving/manipulating URLs| 9 ;;; Functions for retrieving/manipulating URLs|
10 ;;; 1997/02/07 14:30:25|1.51|Location Undetermined 10 ;;; 1997/02/20 15:34:07|1.57|Location Undetermined
11 ;;; 11 ;;;
12 12
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14 ;;; Copyright (c) 1993-1996 by William M. Perry (wmperry@cs.indiana.edu) 14 ;;; Copyright (c) 1993-1996 by William M. Perry (wmperry@cs.indiana.edu)
15 ;;; Copyright (c) 1996, 1997 Free Software Foundation, Inc. 15 ;;; Copyright (c) 1996, 1997 Free Software Foundation, Inc.
95 (autoload 'url-finger "url-misc") 95 (autoload 'url-finger "url-misc")
96 (autoload 'url-rlogin "url-misc") 96 (autoload 'url-rlogin "url-misc")
97 (autoload 'url-telnet "url-misc") 97 (autoload 'url-telnet "url-misc")
98 (autoload 'url-tn3270 "url-misc") 98 (autoload 'url-tn3270 "url-misc")
99 (autoload 'url-proxy "url-misc") 99 (autoload 'url-proxy "url-misc")
100 (autoload 'url-x-exec "url-misc")
101 (autoload 'url-news "url-news") 100 (autoload 'url-news "url-news")
102 (autoload 'url-nntp "url-news") 101 (autoload 'url-nntp "url-news")
103 (autoload 'url-decode-pgp/pem "url-pgp")
104 (autoload 'url-wais "url-wais")
105 102
106 (autoload 'url-open-stream "url-gw") 103 (autoload 'url-open-stream "url-gw")
107 (autoload 'url-mime-response-p "url-http") 104 (autoload 'url-mime-response-p "url-http")
108 (autoload 'url-parse-mime-headers "url-http") 105 (autoload 'url-parse-mime-headers "url-http")
109 (autoload 'url-handle-refresh-header "url-http") 106 (autoload 'url-handle-refresh-header "url-http")
116 (autoload 'url-register-auth-scheme "url-auth") 113 (autoload 'url-register-auth-scheme "url-auth")
117 (autoload 'url-cookie-write-file "url-cookie") 114 (autoload 'url-cookie-write-file "url-cookie")
118 (autoload 'url-cookie-retrieve "url-cookie") 115 (autoload 'url-cookie-retrieve "url-cookie")
119 (autoload 'url-cookie-generate-header-lines "url-cookie") 116 (autoload 'url-cookie-generate-header-lines "url-cookie")
120 (autoload 'url-cookie-handle-set-cookie "url-cookie") 117 (autoload 'url-cookie-handle-set-cookie "url-cookie")
118
119 (autoload 'url-is-cached "url-cache")
120 (autoload 'url-store-in-cache "url-cache")
121 (autoload 'url-is-cached "url-cache")
122 (autoload 'url-create-cached-filename "url-cache")
123 (autoload 'url-extract-from-cache "url-cache")
124 (autoload 'url-cache-expired "url-cache")
121 125
122 (require 'md5) 126 (require 'md5)
123 (require 'base64) 127 (require 'base64)
124 128
125 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 129 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
130 '(cond 134 '(cond
131 ((not (boundp 'file-name-handler-alist)) 135 ((not (boundp 'file-name-handler-alist))
132 nil) ; Don't load if no alist 136 nil) ; Don't load if no alist
133 ((rassq 'url-file-handler file-name-handler-alist) 137 ((rassq 'url-file-handler file-name-handler-alist)
134 nil) ; Don't load twice 138 nil) ; Don't load twice
135 ((and (string-match "XEmacs\\|Lucid" emacs-version)
136 (< url-emacs-minor-version 11)) ; Don't load in lemacs 19.10
137 nil)
138 (t 139 (t
139 (setq file-name-handler-alist 140 (setq file-name-handler-alist
140 (let ((new-handler (cons 141 (let ((new-handler (cons
141 (concat "^/*" 142 (concat "^/*"
142 (substring url-nonrelative-link1 nil)) 143 (substring url-nonrelative-link1 nil))
564 (and (not data) 565 (and (not data)
565 (setq data (list (url-file-directory-p url) 566 (setq data (list (url-file-directory-p url)
566 1 0 0 (cons 0 0) (cons 0 0) (cons 0 0) 567 1 0 0 (cons 0 0) (cons 0 0) (cons 0 0)
567 -1 (mm-extension-to-mime 568 -1 (mm-extension-to-mime
568 (url-file-extension 569 (url-file-extension
569 url-current-file)) 570 (url-filename
571 url-current-object)))
570 nil 0 0))) 572 nil 0 0)))
571 (kill-buffer " *url-temp*")))))) 573 (kill-buffer " *url-temp*"))))))
572 ((member type '("ftp" "file")) 574 ((member type '("ftp" "file"))
573 (let ((fname (if (url-host urlobj) 575 (let ((fname (if (url-host urlobj)
574 (concat "/" 576 (concat "/"
807 ((eq (device-type) 'pm) "OS/2") 809 ((eq (device-type) 'pm) "OS/2")
808 ((eq (device-type) 'win32) "Windows; 32bit") 810 ((eq (device-type) 'win32) "Windows; 32bit")
809 ((eq (device-type) 'tty) "(Unix?); TTY") 811 ((eq (device-type) 'tty) "(Unix?); TTY")
810 (t "UnkownPlatform"))) 812 (t "UnkownPlatform")))
811 813
812 ;; Set up the entity definition for PGP and PEM authentication
813 (setq url-pgp/pem-entity (or url-pgp/pem-entity
814 user-mail-address
815 (format "%s@%s" (user-real-login-name)
816 (system-name))))
817
818 (setq url-personal-mail-address (or url-personal-mail-address 814 (setq url-personal-mail-address (or url-personal-mail-address
819 url-pgp/pem-entity 815 user-mail-address
820 user-mail-address)) 816 (format "%s@%s" (user-real-login-name)
817 (system-name))))
821 818
822 (if (or (memq url-privacy-level '(paranoid high)) 819 (if (or (memq url-privacy-level '(paranoid high))
823 (and (listp url-privacy-level) 820 (and (listp url-privacy-level)
824 (memq 'email url-privacy-level))) 821 (memq 'email url-privacy-level)))
825 (setq url-personal-mail-address nil)) 822 (setq url-personal-mail-address nil))
905 (url-register-protocol 'news nil 'url-identity-expander "119") 902 (url-register-protocol 'news nil 'url-identity-expander "119")
906 (url-register-protocol 'nntp nil 'url-identity-expander "119") 903 (url-register-protocol 'nntp nil 'url-identity-expander "119")
907 (url-register-protocol 'irc nil 'url-identity-expander "6667") 904 (url-register-protocol 'irc nil 'url-identity-expander "6667")
908 (url-register-protocol 'data nil 'url-identity-expander) 905 (url-register-protocol 'data nil 'url-identity-expander)
909 (url-register-protocol 'rlogin) 906 (url-register-protocol 'rlogin)
910 (url-register-protocol 'shttp nil nil "80")
911 (url-register-protocol 'telnet) 907 (url-register-protocol 'telnet)
912 (url-register-protocol 'tn3270) 908 (url-register-protocol 'tn3270)
913 (url-register-protocol 'wais)
914 (url-register-protocol 'x-exec)
915 (url-register-protocol 'proxy) 909 (url-register-protocol 'proxy)
916 (url-register-protocol 'auto 'url-handle-no-scheme) 910 (url-register-protocol 'auto 'url-handle-no-scheme)
917 911
918 ;; Register all the authentication schemes we can handle 912 ;; Register all the authentication schemes we can handle
919 (url-register-auth-scheme "basic" nil 4) 913 (url-register-auth-scheme "basic" nil 4)
969 ((= x ??) ".") 963 ((= x ??) ".")
970 (t (char-to-string x))))) 964 (t (char-to-string x)))))
971 noproxy "") "\\)")) 965 noproxy "") "\\)"))
972 url-proxy-services)))) 966 url-proxy-services))))
973 967
974 ;; Set the url-use-transparent with decent defaults
975 (if (not (eq (device-type) 'tty))
976 (setq url-use-transparent nil))
977 (and url-use-transparent (require 'transparent))
978
979 ;; Set the password entry funtion based on user defaults or guess 968 ;; Set the password entry funtion based on user defaults or guess
980 ;; based on which remote-file-access package they are using. 969 ;; based on which remote-file-access package they are using.
981 (cond 970 (cond
982 (url-passwd-entry-func nil) ; Already been set 971 (url-passwd-entry-func nil) ; Already been set
983 ((boundp 'read-passwd) ; Use secure password if available 972 ((fboundp 'read-passwd) ; Use secure password if available
984 (setq url-passwd-entry-func 'read-passwd)) 973 (setq url-passwd-entry-func 'read-passwd))
985 ((or (featurep 'efs) ; Using EFS 974 ((or (featurep 'efs) ; Using EFS
986 (featurep 'efs-auto)) ; or autoloading efs 975 (featurep 'efs-auto)) ; or autoloading efs
987 (if (not (fboundp 'read-passwd)) 976 (if (not (fboundp 'read-passwd))
988 (autoload 'read-passwd "passwd" "Read in a password" nil)) 977 (autoload 'read-passwd "passwd" "Read in a password" nil))
990 ((or (featurep 'ange-ftp) ; Using ange-ftp 979 ((or (featurep 'ange-ftp) ; Using ange-ftp
991 (and (boundp 'file-name-handler-alist) 980 (and (boundp 'file-name-handler-alist)
992 (not (string-match "Lucid" (emacs-version))))) 981 (not (string-match "Lucid" (emacs-version)))))
993 (setq url-passwd-entry-func 'ange-ftp-read-passwd)) 982 (setq url-passwd-entry-func 'ange-ftp-read-passwd))
994 (t 983 (t
995 (url-warn 'security 984 (url-warn
996 "Can't determine how to read passwords, winging it."))) 985 'security
986 "(url-setup): Can't determine how to read passwords, winging it.")))
997 987
998 ;; Set up the news service if they haven't done so 988 ;; Set up the news service if they haven't done so
999 (setq url-news-server 989 (setq url-news-server
1000 (cond 990 (cond
1001 (url-news-server url-news-server) 991 (url-news-server url-news-server)
1023 ", "))) 1013 ", ")))
1024 1014
1025 (url-setup-privacy-info) 1015 (url-setup-privacy-info)
1026 (run-hooks 'url-load-hook) 1016 (run-hooks 'url-load-hook)
1027 (setq url-setup-done t))) 1017 (setq url-setup-done t)))
1028
1029 (defun url-cache-file-writable-p (file)
1030 "Follows the documentation of file-writable-p, unlike file-writable-p."
1031 (and (file-writable-p file)
1032 (if (file-exists-p file)
1033 (not (file-directory-p file))
1034 (file-directory-p (file-name-directory file)))))
1035
1036 (defun url-prepare-cache-for-file (file)
1037 "Makes it possible to cache data in FILE.
1038 Creates any necessary parent directories, deleting any non-directory files
1039 that would stop this. Returns nil if parent directories can not be
1040 created. If FILE already exists as a non-directory, it changes
1041 permissions of FILE or deletes FILE to make it possible to write a new
1042 version of FILE. Returns nil if this can not be done. Returns nil if
1043 FILE already exists as a directory. Otherwise, returns t, indicating that
1044 FILE can be created or overwritten."
1045
1046 ;; COMMENT: We don't delete directories because that requires
1047 ;; recursively deleting the directories's contents, which might
1048 ;; eliminate a substantial portion of the cache.
1049
1050 (cond
1051 ((url-cache-file-writable-p file)
1052 t)
1053 ((file-directory-p file)
1054 nil)
1055 (t
1056 (catch 'upcff-tag
1057 (let ((dir (file-name-directory file))
1058 dir-parent dir-last-component)
1059 (if (string-equal dir file)
1060 ;; *** Should I have a warning here?
1061 ;; FILE must match a pattern like /foo/bar/, indicating it is a
1062 ;; name only suitable for a directory. So presume we won't be
1063 ;; able to overwrite FILE and return nil.
1064 (throw 'upcff-tag nil))
1065
1066 ;; Make sure the containing directory exists, or throw a failure
1067 ;; if we can't create it.
1068 (if (file-directory-p dir)
1069 nil
1070 (or (fboundp 'make-directory)
1071 (throw 'upcff-tag nil))
1072 (make-directory dir t)
1073 ;; make-directory silently fails if there is an obstacle, so
1074 ;; we must verify its results.
1075 (if (file-directory-p dir)
1076 nil
1077 ;; Look at prefixes of the path to find the obstacle that is
1078 ;; stopping us from making the directory. Unfortunately, there
1079 ;; is no portable function in Emacs to find the parent directory
1080 ;; of a *directory*. So this code may not work on VMS.
1081 (while (progn
1082 (if (eq ?/ (aref dir (1- (length dir))))
1083 (setq dir (substring dir 0 -1))
1084 ;; Maybe we're on VMS where the syntax is different.
1085 (throw 'upcff-tag nil))
1086 (setq dir-parent (file-name-directory dir))
1087 (not (file-directory-p dir-parent)))
1088 (setq dir dir-parent))
1089 ;; We have found the longest path prefix that exists as a
1090 ;; directory. Deal with any obstacles in this directory.
1091 (if (file-exists-p dir)
1092 (condition-case nil
1093 (delete-file dir)
1094 (error (throw 'upcff-tag nil))))
1095 (if (file-exists-p dir)
1096 (throw 'upcff-tag nil))
1097 ;; Try making the directory again.
1098 (setq dir (file-name-directory file))
1099 (make-directory dir t)
1100 (or (file-directory-p dir)
1101 (throw 'upcff-tag nil))))
1102
1103 ;; The containing directory exists. Let's see if there is
1104 ;; something in the way in this directory.
1105 (if (url-cache-file-writable-p file)
1106 (throw 'upcff-tag t)
1107 (condition-case nil
1108 (delete-file file)
1109 (error (throw 'upcff-tag nil))))
1110
1111 ;; The return value, if we get this far.
1112 (url-cache-file-writable-p file))))))
1113
1114 (defun url-store-in-cache (&optional buff)
1115 "Store buffer BUFF in the cache"
1116 (if (or (not (get-buffer buff))
1117 (member url-current-type '("www" "about" "https" "shttp"
1118 "news" "mailto"))
1119 (and (member url-current-type '("file" "ftp" nil))
1120 (not url-current-server))
1121 )
1122 nil
1123 (save-excursion
1124 (and buff (set-buffer buff))
1125 (let* ((fname (url-create-cached-filename (url-view-url t)))
1126 (fname-hdr (concat (if (memq system-type '(ms-windows ms-dos os2))
1127 (url-file-extension fname t)
1128 fname) ".hdr"))
1129 (info (mapcar (function (lambda (var)
1130 (cons (symbol-name var)
1131 (symbol-value var))))
1132 '( url-current-content-length
1133 url-current-file
1134 url-current-isindex
1135 url-current-mime-encoding
1136 url-current-mime-headers
1137 url-current-mime-type
1138 url-current-port
1139 url-current-server
1140 url-current-type
1141 url-current-user
1142 ))))
1143 (cond ((and (url-prepare-cache-for-file fname)
1144 (url-prepare-cache-for-file fname-hdr))
1145 (write-region (point-min) (point-max) fname nil 5)
1146 (set-buffer (get-buffer-create " *cache-tmp*"))
1147 (erase-buffer)
1148 (insert "(setq ")
1149 (mapcar
1150 (function
1151 (lambda (x)
1152 (insert (car x) " "
1153 (cond ((null (setq x (cdr x))) "nil")
1154 ((stringp x) (prin1-to-string x))
1155 ((listp x) (concat "'" (prin1-to-string x)))
1156 ((numberp x) (int-to-string x))
1157 (t "'???")) "\n")))
1158 info)
1159 (insert ")\n")
1160 (write-region (point-min) (point-max) fname-hdr nil 5)))))))
1161
1162
1163 (defun url-is-cached (url)
1164 "Return non-nil if the URL is cached."
1165 (let* ((fname (url-create-cached-filename url))
1166 (attribs (file-attributes fname)))
1167 (and fname ; got a filename
1168 (file-exists-p fname) ; file exists
1169 (not (eq (nth 0 attribs) t)) ; Its not a directory
1170 (nth 5 attribs)))) ; Can get last mod-time
1171
1172 (defun url-create-cached-filename-using-md5 (url)
1173 (if url
1174 (expand-file-name (md5 url)
1175 (concat url-temporary-directory "/"
1176 (user-real-login-name)))))
1177
1178 (defun url-create-cached-filename (url)
1179 "Return a filename in the local cache for URL"
1180 (if url
1181 (let* ((url url)
1182 (urlobj (if (vectorp url)
1183 url
1184 (url-generic-parse-url url)))
1185 (protocol (url-type urlobj))
1186 (hostname (url-host urlobj))
1187 (host-components
1188 (cons
1189 (user-real-login-name)
1190 (cons (or protocol "file")
1191 (nreverse
1192 (delq nil
1193 (mm-string-to-tokens
1194 (or hostname "localhost") ?.))))))
1195 (fname (url-filename urlobj)))
1196 (if (and fname (/= (length fname) 0) (= (aref fname 0) ?/))
1197 (setq fname (substring fname 1 nil)))
1198 (if fname
1199 (let ((slash nil))
1200 (setq fname
1201 (mapconcat
1202 (function
1203 (lambda (x)
1204 (cond
1205 ((and (= ?/ x) slash)
1206 (setq slash nil)
1207 "%2F")
1208 ((= ?/ x)
1209 (setq slash t)
1210 "/")
1211 (t
1212 (setq slash nil)
1213 (char-to-string x))))) fname ""))))
1214
1215 (if (and fname (memq system-type '(ms-windows ms-dos windows-nt))
1216 (string-match "\\([A-Za-z]\\):[/\\]" fname))
1217 (setq fname (concat (url-match fname 1) "/"
1218 (substring fname (match-end 0)))))
1219
1220 (setq fname (and fname
1221 (mapconcat
1222 (function (lambda (x)
1223 (if (= x ?~) "" (char-to-string x))))
1224 fname ""))
1225 fname (cond
1226 ((null fname) nil)
1227 ((or (string= "" fname) (string= "/" fname))
1228 url-directory-index-file)
1229 ((= (string-to-char fname) ?/)
1230 (if (string= (substring fname -1 nil) "/")
1231 (concat fname url-directory-index-file)
1232 (substring fname 1 nil)))
1233 (t
1234 (if (string= (substring fname -1 nil) "/")
1235 (concat fname url-directory-index-file)
1236 fname))))
1237
1238 ;; Honor hideous 8.3 filename limitations on dos and windows
1239 ;; we don't have to worry about this in Windows NT/95 (or OS/2?)
1240 (if (and fname (memq system-type '(ms-windows ms-dos)))
1241 (let ((base (url-file-extension fname t))
1242 (ext (url-file-extension fname nil)))
1243 (setq fname (concat (substring base 0 (min 8 (length base)))
1244 (substring ext 0 (min 4 (length ext)))))
1245 (setq host-components
1246 (mapcar
1247 (function
1248 (lambda (x)
1249 (if (> (length x) 8)
1250 (concat
1251 (substring x 0 8) "."
1252 (substring x 8 (min (length x) 11)))
1253 x)))
1254 host-components))))
1255
1256 (and fname
1257 (expand-file-name fname
1258 (expand-file-name
1259 (mapconcat 'identity host-components "/")
1260 url-temporary-directory))))))
1261
1262 (defun url-extract-from-cache (fnam)
1263 "Extract FNAM from the local disk cache"
1264 (set-buffer (get-buffer-create url-working-buffer))
1265 (erase-buffer)
1266 (setq url-current-mime-viewer nil)
1267 (insert-file-contents-literally fnam)
1268 (load (concat (if (memq system-type '(ms-windows ms-dos os2))
1269 (url-file-extension fnam t)
1270 fnam) ".hdr") t t))
1271 1018
1272 ;;;###autoload 1019 ;;;###autoload
1273 (defun url-get-url-at-point (&optional pt) 1020 (defun url-get-url-at-point (&optional pt)
1274 "Get the URL closest to point, but don't change your 1021 "Get the URL closest to point, but don't change your
1275 position. Has a preference for looking backward when not 1022 position. Has a preference for looking backward when not
1534 1281
1535 (defun url-uncompress () 1282 (defun url-uncompress ()
1536 "Do any necessary uncompression on `url-working-buffer'" 1283 "Do any necessary uncompression on `url-working-buffer'"
1537 (set-buffer url-working-buffer) 1284 (set-buffer url-working-buffer)
1538 (if (not url-inhibit-uncompression) 1285 (if (not url-inhibit-uncompression)
1539 (let* ((extn (url-file-extension url-current-file)) 1286 (let* ((decoder nil)
1540 (decoder nil)
1541 (code-1 (cdr-safe 1287 (code-1 (cdr-safe
1542 (assoc "content-transfer-encoding" 1288 (assoc "content-transfer-encoding"
1543 url-current-mime-headers))) 1289 url-current-mime-headers)))
1544 (code-2 (cdr-safe 1290 (code-2 (cdr-safe
1545 (assoc "content-encoding" url-current-mime-headers))) 1291 (assoc "content-encoding" url-current-mime-headers)))
1580 (url-sentinel proc string)))) 1326 (url-sentinel proc string))))
1581 string) 1327 string)
1582 1328
1583 (defun url-default-callback (buf) 1329 (defun url-default-callback (buf)
1584 (url-download-minor-mode nil) 1330 (url-download-minor-mode nil)
1331 (url-store-in-cache)
1585 (cond 1332 (cond
1586 ((save-excursion (set-buffer buf) 1333 ((save-excursion (set-buffer buf)
1587 (and url-current-callback-func 1334 (and url-current-callback-func
1588 (fboundp url-current-callback-func))) 1335 (fboundp url-current-callback-func)))
1589 (save-excursion 1336 (save-excursion
1622 ((url-mime-response-p) 1369 ((url-mime-response-p)
1623 (setq status (url-parse-mime-headers)))) 1370 (setq status (url-parse-mime-headers))))
1624 (if (not url-current-mime-type) 1371 (if (not url-current-mime-type)
1625 (setq url-current-mime-type (mm-extension-to-mime 1372 (setq url-current-mime-type (mm-extension-to-mime
1626 (url-file-extension 1373 (url-file-extension
1627 url-current-file))))))) 1374 (url-filename
1628 (if (member status '(401 301 302 303 204)) 1375 url-current-object)))))
1629 nil 1376 (if (member status '(401 301 302 303 204))
1630 (funcall url-default-retrieval-proc (buffer-name url-working-buffer)))))) 1377 nil
1378 (funcall url-default-retrieval-proc (buffer-name url-working-buffer)))))))))
1631 1379
1632 (defun url-remove-relative-links (name) 1380 (defun url-remove-relative-links (name)
1633 ;; Strip . and .. from pathnames 1381 ;; Strip . and .. from pathnames
1634 (let ((new (if (not (string-match "^/" name)) 1382 (let ((new (if (not (string-match "^/" name))
1635 (concat "/" name) 1383 (concat "/" name)
1680 1428
1681 (defun url-view-url (&optional no-show) 1429 (defun url-view-url (&optional no-show)
1682 "View the current document's URL. Optional argument NO-SHOW means 1430 "View the current document's URL. Optional argument NO-SHOW means
1683 just return the URL, don't show it in the minibuffer." 1431 just return the URL, don't show it in the minibuffer."
1684 (interactive) 1432 (interactive)
1685 (let ((url "")) 1433 (if (not url-current-object)
1686 (cond 1434 nil
1687 ((equal url-current-type "gopher") 1435 (if no-show
1688 (setq url (format "%s://%s%s/%s" 1436 (url-recreate-url url-current-object)
1689 url-current-type url-current-server 1437 (message "%s" (url-recreate-url url-current-object)))))
1690 (if (or (null url-current-port)
1691 (string= "70" url-current-port)) ""
1692 (concat ":" url-current-port))
1693 url-current-file)))
1694 ((equal url-current-type "news")
1695 (setq url (concat "news:"
1696 (if (not (equal url-current-server
1697 url-news-server))
1698 (concat "//" url-current-server
1699 (if (or (null url-current-port)
1700 (string= "119" url-current-port))
1701 ""
1702 (concat ":" url-current-port)) "/"))
1703 url-current-file)))
1704 ((equal url-current-type "about")
1705 (setq url (concat "about:" url-current-file)))
1706 ((member url-current-type '("http" "shttp" "https"))
1707 (setq url (format "%s://%s%s/%s" url-current-type url-current-server
1708 (if (or (null url-current-port)
1709 (string= "80" url-current-port))
1710 ""
1711 (concat ":" url-current-port))
1712 (if (and url-current-file
1713 (= ?/ (string-to-char url-current-file)))
1714 (substring url-current-file 1 nil)
1715 url-current-file))))
1716 ((equal url-current-type "ftp")
1717 (setq url (format "%s://%s%s/%s" url-current-type
1718 (if (and url-current-user
1719 (not (string= "anonymous" url-current-user)))
1720 (concat url-current-user "@") "")
1721 url-current-server
1722 (if (and url-current-file
1723 (= ?/ (string-to-char url-current-file)))
1724 (substring url-current-file 1 nil)
1725 url-current-file))))
1726 ((and (member url-current-type '("file" nil)) url-current-file)
1727 (setq url (format "file:%s" url-current-file)))
1728 ((equal url-current-type "www")
1729 (setq url (format "www:/%s/%s" url-current-server url-current-file)))
1730 (t
1731 (setq url nil)))
1732 (if (not no-show) (message "%s" url) url)))
1733 1438
1734 (defun url-parse-Netscape-history (fname) 1439 (defun url-parse-Netscape-history (fname)
1735 ;; Parse a Netscape/X style global history list. 1440 ;; Parse a Netscape/X style global history list.
1736 (let (pos ; Position holder 1441 (let (pos ; Position holder
1737 url ; The URL 1442 url ; The URL
2112 (url-file-directly-accessible-p urlobj)) 1817 (url-file-directly-accessible-p urlobj))
2113 (url-retrieve-internally url) 1818 (url-retrieve-internally url)
2114 (url-lazy-message "Retrieving %s..." url) 1819 (url-lazy-message "Retrieving %s..." url)
2115 (apply 'call-process url-external-retrieval-program 1820 (apply 'call-process url-external-retrieval-program
2116 nil t nil args) 1821 nil t nil args)
2117 (url-lazy-message "Retrieving %s... done" url) 1822 (url-lazy-message "Retrieving %s... done" url)))))
2118 (if (and type urlobj)
2119 (setq url-current-server (url-host urlobj)
2120 url-current-type (url-type urlobj)
2121 url-current-port (url-port urlobj)
2122 url-current-file (url-filename urlobj)))
2123 (if (member url-current-file '("/" ""))
2124 (setq url-current-mime-type "text/html"))))))
2125 1823
2126 (defun url-get-normalized-date (&optional specified-time) 1824 (defun url-get-normalized-date (&optional specified-time)
2127 ;; Return a 'real' date string that most HTTP servers can understand. 1825 ;; Return a 'real' date string that most HTTP servers can understand.
2128 (require 'timezone) 1826 (require 'timezone)
2129 (let* ((raw (if specified-time (current-time-string specified-time) 1827 (let* ((raw (if specified-time (current-time-string specified-time)
2150 (concat day ", " (aref parsed 2) "-" month "-" year " " 1848 (concat day ", " (aref parsed 2) "-" month "-" year " "
2151 (aref parsed 3) " " (or (aref parsed 4) 1849 (aref parsed 3) " " (or (aref parsed 4)
2152 (concat "[" (nth 1 (current-time-zone)) 1850 (concat "[" (nth 1 (current-time-zone))
2153 "]"))))) 1851 "]")))))
2154 1852
2155 ;;;###autoload
2156 (defun url-cache-expired (url mod)
2157 "Return t iff a cached file has expired."
2158 (if (not (string-match url-nonrelative-link url))
2159 t
2160 (let* ((urlobj (url-generic-parse-url url))
2161 (type (url-type urlobj)))
2162 (cond
2163 (url-standalone-mode
2164 (not (file-exists-p (url-create-cached-filename urlobj))))
2165 ((string= type "http")
2166 (if (not url-standalone-mode) t
2167 (not (file-exists-p (url-create-cached-filename urlobj)))))
2168 ((not (fboundp 'current-time))
2169 t)
2170 ((member type '("file" "ftp"))
2171 (if (or (equal mod '(0 0)) (not mod))
2172 (return t)
2173 (or (> (nth 0 mod) (nth 0 (current-time)))
2174 (> (nth 1 mod) (nth 1 (current-time))))))
2175 (t nil)))))
2176
2177 (defun url-get-working-buffer-name () 1853 (defun url-get-working-buffer-name ()
2178 "Get a working buffer name such as ` *URL-<i>*' without a live process and empty" 1854 "Get a working buffer name such as ` *URL-<i>*' without a live process and empty"
2179 (let ((num 1) 1855 (let ((num 1)
2180 name buf) 1856 name buf)
2181 (while (progn (setq name (format " *URL-%d*" num)) 1857 (while (progn (setq name (format " *URL-%d*" num))
2222 (t 1898 (t
2223 (url-warn 'url (format "Unknown proxy directive: %s" proxy) 'critical) 1899 (url-warn 'url (format "Unknown proxy directive: %s" proxy) 'critical)
2224 nil)))) 1900 nil))))
2225 1901
2226 (defun url-retrieve-internally (url &optional no-cache) 1902 (defun url-retrieve-internally (url &optional no-cache)
2227 (let ((url-working-buffer (if (and url-multiple-p 1903 (let* ((url-working-buffer (if (and url-multiple-p
2228 (string-equal 1904 (string-equal
2229 (if (bufferp url-working-buffer) 1905 (if (bufferp url-working-buffer)
2230 (buffer-name url-working-buffer) 1906 (buffer-name url-working-buffer)
2231 url-working-buffer) 1907 url-working-buffer)
2232 url-default-working-buffer)) 1908 url-default-working-buffer))
2233 (url-get-working-buffer-name) 1909 (url-get-working-buffer-name)
2234 url-working-buffer))) 1910 url-working-buffer))
2235 (if (get-buffer url-working-buffer) 1911 (urlobj (url-generic-parse-url url))
2236 (save-excursion 1912 (type (url-type urlobj))
2237 (set-buffer url-working-buffer) 1913 (url-using-proxy (if (url-host urlobj)
2238 (erase-buffer) 1914 (url-find-proxy-for-url urlobj
2239 (setq url-current-can-be-cached (not no-cache)) 1915 (url-host urlobj))
2240 (set-buffer-modified-p nil))) 1916 nil))
2241 (let* ((urlobj (url-generic-parse-url url)) 1917 (handler nil)
2242 (type (url-type urlobj)) 1918 (original-url url)
2243 (url-using-proxy (if (url-host urlobj) 1919 (cached nil))
2244 (url-find-proxy-for-url urlobj 1920 (if url-using-proxy (setq type "proxy"))
2245 (url-host urlobj)) 1921 (setq cached (url-is-cached url)
2246 nil)) 1922 cached (and cached (not (url-cache-expired url cached)))
2247 (handler nil) 1923 handler (if cached
2248 (original-url url) 1924 'url-extract-from-cache
2249 (cached nil) 1925 (car-safe
2250 (tmp url-current-file)) 1926 (cdr-safe (assoc (or type "auto")
2251 (if url-using-proxy (setq type "proxy")) 1927 url-registered-protocols))))
2252 (setq cached (url-is-cached url) 1928 url (if cached (url-create-cached-filename url) url))
2253 cached (and cached (not (url-cache-expired url cached))) 1929 (save-excursion
2254 handler (if cached 'url-extract-from-cache 1930 (set-buffer (get-buffer-create url-working-buffer))
2255 (car-safe 1931 (setq url-current-can-be-cached (not no-cache)
2256 (cdr-safe (assoc (or type "auto") 1932 url-current-object urlobj))
2257 url-registered-protocols)))) 1933 (if (and handler (fboundp handler))
2258 url (if cached (url-create-cached-filename url) url)) 1934 (funcall handler url)
2259 (save-excursion 1935 (set-buffer (get-buffer-create url-working-buffer))
2260 (set-buffer (get-buffer-create url-working-buffer)) 1936 (erase-buffer)
2261 (setq url-current-can-be-cached (not no-cache))) 1937 (setq url-current-mime-type "text/html")
2262 ; (if url-be-asynchronous 1938 (insert "<title> Link Error! </title>\n"
2263 ; (url-download-minor-mode t)) 1939 "<h1> An error has occurred... </h1>\n"
2264 (if (and handler (fboundp handler)) 1940 (format "The link type `<code>%s</code>'" type)
2265 (funcall handler url) 1941 " is unrecognized or unsupported at this time.<p>\n"
2266 (set-buffer (get-buffer-create url-working-buffer)) 1942 "If you feel this is an error in Emacs-W3, please "
2267 (setq url-current-file tmp) 1943 "<a href=\"mailto://" url-bug-address "\">send me mail.</a>"
2268 (erase-buffer) 1944 "<p><address>William Perry</address><br>"
2269 (insert "<title> Link Error! </title>\n" 1945 "<address>" url-bug-address "</address>"))
2270 "<h1> An error has occurred... </h1>\n" 1946 (cond
2271 (format "The link type `<code>%s</code>'" type) 1947 ((and url-be-asynchronous (not cached) (member type '("http" "proxy")))
2272 " is unrecognized or unsupported at this time.<p>\n" 1948 nil)
2273 "If you feel this is an error, please " 1949 (url-be-asynchronous
2274 "<a href=\"mailto://" url-bug-address "\">send me mail.</a>" 1950 (funcall url-default-retrieval-proc (buffer-name)))
2275 "<p><address>William Perry</address><br>" 1951 ((not (get-buffer url-working-buffer)) nil)
2276 "<address>" url-bug-address "</address>") 1952 ((and (not url-inhibit-mime-parsing)
2277 (setq url-current-file "error.html")) 1953 (or cached (url-mime-response-p t)))
2278 (if (and 1954 (or cached (url-parse-mime-headers nil t))))
2279 (not url-be-asynchronous) 1955 (if (and (or (not url-be-asynchronous)
2280 (get-buffer url-working-buffer)) 1956 (not (equal type "http")))
2281 (progn 1957 url-current-object
2282 (set-buffer url-working-buffer) 1958 (not url-current-mime-type))
2283 1959 (if (url-buffer-is-hypertext)
2284 (url-clean-text))) 1960 (setq url-current-mime-type "text/html")
2285 (cond 1961 (setq url-current-mime-type (mm-extension-to-mime
2286 ((equal type "wais") nil) 1962 (url-file-extension
2287 ((and url-be-asynchronous (not cached) (member type '("http" "proxy"))) 1963 (url-filename
2288 nil) 1964 url-current-object))))))
2289 (url-be-asynchronous 1965 (if (not url-be-asynchronous)
2290 (funcall url-default-retrieval-proc (buffer-name))) 1966 (url-store-in-cache url-working-buffer))
2291 ((not (get-buffer url-working-buffer)) nil) 1967 (if (not url-global-history-hash-table)
2292 ((and (not url-inhibit-mime-parsing) 1968 (setq url-global-history-hash-table (make-hash-table :size 131
2293 (or cached (url-mime-response-p t))) 1969 :test 'equal)))
2294 (or cached (url-parse-mime-headers nil t)))) 1970 (if (not (string-match "^\\(about\\|www\\):" original-url))
2295 (if (and (or (not url-be-asynchronous) 1971 (progn
2296 (not (equal type "http"))) 1972 (setq url-history-changed-since-last-save t)
2297 (not url-current-mime-type)) 1973 (cl-puthash original-url (current-time)
2298 (if (url-buffer-is-hypertext) 1974 url-global-history-hash-table)))
2299 (setq url-current-mime-type "text/html") 1975 (cons cached url-working-buffer)))
2300 (setq url-current-mime-type (mm-extension-to-mime
2301 (url-file-extension
2302 url-current-file)))))
2303 (if (and url-automatic-caching url-current-can-be-cached
2304 (not url-be-asynchronous))
2305 (save-excursion
2306 (url-store-in-cache url-working-buffer)))
2307 (if (not url-global-history-hash-table)
2308 (setq url-global-history-hash-table (make-hash-table :size 131
2309 :test 'equal)))
2310 (if (not (string-match "^about:" original-url))
2311 (progn
2312 (setq url-history-changed-since-last-save t)
2313 (cl-puthash original-url (current-time)
2314 url-global-history-hash-table)))
2315 (cons cached url-working-buffer))))
2316 1976
2317 ;;;###autoload 1977 ;;;###autoload
2318 (defun url-retrieve (url &optional no-cache expected-md5) 1978 (defun url-retrieve (url &optional no-cache expected-md5)
2319 "Retrieve a document over the World Wide Web. 1979 "Retrieve a document over the World Wide Web.
2320 The document should be specified by its fully specified 1980 The document should be specified by its fully specified
2329 (subrp (symbol-function 'set-text-properties))) 1989 (subrp (symbol-function 'set-text-properties)))
2330 (set-text-properties 0 (length url) nil url)) 1990 (set-text-properties 0 (length url) nil url))
2331 (if (and url (string-match "^url:" url)) 1991 (if (and url (string-match "^url:" url))
2332 (setq url (substring url (match-end 0) nil))) 1992 (setq url (substring url (match-end 0) nil)))
2333 (let ((status (url-retrieve-internally url no-cache))) 1993 (let ((status (url-retrieve-internally url no-cache)))
2334 (if (and expected-md5 url-check-md5s)
2335 (let ((cur-md5 (md5 (current-buffer))))
2336 (if (not (string= cur-md5 expected-md5))
2337 (and (not (funcall url-confirmation-func
2338 "MD5s do not match, use anyway? "))
2339 (error "MD5 error.")))))
2340 status)) 1994 status))
2341 1995
2342 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1996 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2343 ;;; How to register a protocol 1997 ;;; How to register a protocol
2344 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1998 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;