* url-cache.el (url-cache-expired): Don't autoload. Tweak previous change.
[bpt/emacs.git] / lisp / url / url-cache.el
CommitLineData
8c8b8430 1;;; url-cache.el --- Uniform Resource Locator retrieval tool
00eef4de 2
a5cda60e
GM
3;; Copyright (C) 1996, 1997, 1998, 1999, 2004, 2005, 2006, 2007, 2008,
4;; 2009, 2010 Free Software Foundation, Inc.
00eef4de 5
8c8b8430
SM
6;; Keywords: comm, data, processes, hypermedia
7
00eef4de
LH
8;; This file is part of GNU Emacs.
9
4936186e 10;; GNU Emacs is free software: you can redistribute it and/or modify
00eef4de 11;; it under the terms of the GNU General Public License as published by
4936186e
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
00eef4de
LH
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
4936186e 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
00eef4de
LH
22
23;;; Code:
24
8c8b8430 25(require 'url-parse)
55d6ea46 26(require 'url-util)
8abe1fd5 27(require 'url) ;E.g. for url-configuration-directory.
8c8b8430
SM
28
29(defcustom url-cache-directory
30 (expand-file-name "cache" url-configuration-directory)
a5cda60e 31 "The directory where cache files should be stored."
8c8b8430
SM
32 :type 'directory
33 :group 'url-file)
34
18d68e52
JD
35(defcustom url-cache-expire-time 3600
36 "Maximum time in seconds to keep the documents cached."
37 :version "24.1"
38 :type 'integer
39 :group 'url-cache)
40
8c8b8430
SM
41;; Cache manager
42(defun url-cache-file-writable-p (file)
43 "Follows the documentation of `file-writable-p', unlike `file-writable-p'."
44 (and (file-writable-p file)
45 (if (file-exists-p file)
46 (not (file-directory-p file))
47 (file-directory-p (file-name-directory file)))))
71ddfde5 48
8c8b8430
SM
49(defun url-cache-prepare (file)
50 "Makes it possible to cache data in FILE.
51Creates any necessary parent directories, deleting any non-directory files
52that would stop this. Returns nil if parent directories can not be
53created. If FILE already exists as a non-directory, it changes
54permissions of FILE or deletes FILE to make it possible to write a new
d1ce47b0
JB
55version of FILE. Returns nil if this can not be done, or if FILE already
56exists as a directory. Otherwise, returns t, indicating that
8c8b8430
SM
57FILE can be created or overwritten."
58 (cond
59 ((url-cache-file-writable-p file)
60 t)
61 ((file-directory-p file)
62 nil)
63 (t
64 (condition-case ()
65 (or (make-directory (file-name-directory file) t) t)
66 (error nil)))))
67
68;;;###autoload
69(defun url-store-in-cache (&optional buff)
70 "Store buffer BUFF in the cache."
6f6dc4da
JD
71 (with-current-buffer (get-buffer (or buff (current-buffer)))
72 (let ((fname (url-cache-create-filename (url-view-url t))))
73 (if (url-cache-prepare fname)
74 (let ((coding-system-for-write 'binary))
75 (write-region (point-min) (point-max) fname nil 5))))))
71ddfde5 76
50e4f0bf
JD
77(defun url-fetch-from-cache (url)
78 "Fetch URL from cache and return a buffer with the content."
79 (with-current-buffer (generate-new-buffer " *temp*")
80 (url-cache-extract (url-cache-create-filename url))
81 (current-buffer)))
82
8c8b8430
SM
83;;;###autoload
84(defun url-is-cached (url)
85 "Return non-nil if the URL is cached."
86 (let* ((fname (url-cache-create-filename url))
87 (attribs (file-attributes fname)))
88 (and fname ; got a filename
89 (file-exists-p fname) ; file exists
90 (not (eq (nth 0 attribs) t)) ; Its not a directory
91 (nth 5 attribs)))) ; Can get last mod-time
92
93(defun url-cache-create-filename-human-readable (url)
d1ce47b0 94 "Return a filename in the local cache for URL."
8c8b8430
SM
95 (if url
96 (let* ((url (if (vectorp url) (url-recreate-url url) url))
97 (urlobj (url-generic-parse-url url))
98 (protocol (url-type urlobj))
99 (hostname (url-host urlobj))
100 (host-components
101 (cons
102 (user-real-login-name)
103 (cons (or protocol "file")
104 (reverse (split-string (or hostname "localhost")
105 (eval-when-compile
106 (regexp-quote ".")))))))
107 (fname (url-filename urlobj)))
108 (if (and fname (/= (length fname) 0) (= (aref fname 0) ?/))
109 (setq fname (substring fname 1 nil)))
110 (if fname
111 (let ((slash nil))
112 (setq fname
113 (mapconcat
114 (function
115 (lambda (x)
116 (cond
117 ((and (= ?/ x) slash)
118 (setq slash nil)
119 "%2F")
120 ((= ?/ x)
121 (setq slash t)
122 "/")
123 (t
124 (setq slash nil)
125 (char-to-string x))))) fname ""))))
126
127 (setq fname (and fname
128 (mapconcat
129 (function (lambda (x)
130 (if (= x ?~) "" (char-to-string x))))
131 fname ""))
132 fname (cond
133 ((null fname) nil)
134 ((or (string= "" fname) (string= "/" fname))
135 url-directory-index-file)
136 ((= (string-to-char fname) ?/)
137 (if (string= (substring fname -1 nil) "/")
138 (concat fname url-directory-index-file)
139 (substring fname 1 nil)))
140 (t
141 (if (string= (substring fname -1 nil) "/")
142 (concat fname url-directory-index-file)
143 fname))))
144 (and fname
145 (expand-file-name fname
146 (expand-file-name
147 (mapconcat 'identity host-components "/")
148 url-cache-directory))))))
149
150(defun url-cache-create-filename-using-md5 (url)
151 "Create a cached filename using MD5.
55d6ea46 152Very fast if you have an `md5' primitive function, suitably fast otherwise."
8c8b8430
SM
153 (require 'md5)
154 (if url
155 (let* ((url (if (vectorp url) (url-recreate-url url) url))
156 (checksum (md5 url))
157 (urlobj (url-generic-parse-url url))
158 (protocol (url-type urlobj))
159 (hostname (url-host urlobj))
160 (host-components
161 (cons
162 (user-real-login-name)
163 (cons (or protocol "file")
164 (nreverse
165 (delq nil
166 (split-string (or hostname "localhost")
167 (eval-when-compile
168 (regexp-quote "."))))))))
169 (fname (url-filename urlobj)))
170 (and fname
171 (expand-file-name checksum
172 (expand-file-name
173 (mapconcat 'identity host-components "/")
174 url-cache-directory))))))
175
176(defcustom url-cache-creation-function 'url-cache-create-filename-using-md5
a5cda60e 177 "What function to use to create a cached filename."
8c8b8430
SM
178 :type '(choice (const :tag "MD5 of filename (low collision rate)"
179 :value url-cache-create-filename-using-md5)
180 (const :tag "Human readable filenames (higher collision rate)"
181 :value url-cache-create-filename-human-readable)
182 (function :tag "Other"))
183 :group 'url-cache)
184
185(defun url-cache-create-filename (url)
186 (funcall url-cache-creation-function url))
187
188;;;###autoload
189(defun url-cache-extract (fnam)
d1ce47b0 190 "Extract FNAM from the local disk cache."
8c8b8430
SM
191 (erase-buffer)
192 (insert-file-contents-literally fnam))
193
18d68e52 194(defun url-cache-expired (url &optional expire-time)
48ff1664
GM
195 "Return non-nil if a cached URL is older than EXPIRE-TIME seconds.
196The default value of EXPIRE-TIME is `url-cache-expire-time'.
197If `url-standalone-mode' is non-nil, cached items never expire."
198 (if url-standalone-mode
199 (not (file-exists-p (url-cache-create-filename url)))
200 (let ((cache-time (url-is-cached url)))
201 (and cache-time
202 (time-less-p
203 (time-add
204 cache-time
205 (seconds-to-time (or expire-time url-cache-expire-time)))
206 (current-time))))))
8c8b8430
SM
207
208(provide 'url-cache)
e5566bd5 209
32d5ce4d 210;; arch-tag: 95b050a6-8e81-4f23-8e63-191b9d1d657c
00eef4de 211;;; url-cache.el ends here