1 | <?php |
||||
2 | class DiskCache { |
||||
3 | private $dir; |
||||
4 | |||||
5 | public function __construct($dir) { |
||||
6 | $this->dir = CACHE_DIR."/".clean_filename($dir); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
7 | } |
||||
8 | |||||
9 | public function getDir() { |
||||
10 | return $this->dir; |
||||
11 | } |
||||
12 | |||||
13 | public function makeDir() { |
||||
14 | if (!is_dir($this->dir)) { |
||||
15 | return mkdir($this->dir); |
||||
16 | } |
||||
17 | } |
||||
18 | |||||
19 | public function isWritable($filename = "") { |
||||
20 | if ($filename) { |
||||
21 | if (file_exists($this->getFullPath($filename))) { |
||||
22 | return is_writable($this->getFullPath($filename)); |
||||
23 | } else { |
||||
24 | return is_writable($this->dir); |
||||
25 | } |
||||
26 | } else { |
||||
27 | return is_writable($this->dir); |
||||
28 | } |
||||
29 | } |
||||
30 | |||||
31 | public function exists($filename) { |
||||
32 | return file_exists($this->getFullPath($filename)); |
||||
33 | } |
||||
34 | |||||
35 | public function getSize($filename) { |
||||
36 | if ($this->exists($filename)) { |
||||
37 | return filesize($this->getFullPath($filename)); |
||||
38 | } else { |
||||
39 | return -1; |
||||
40 | } |
||||
41 | } |
||||
42 | |||||
43 | public function getFullPath($filename) { |
||||
44 | $filename = clean_filename($filename); |
||||
45 | |||||
46 | return $this->dir."/".$filename; |
||||
47 | } |
||||
48 | |||||
49 | public function put($filename, $data) { |
||||
50 | return file_put_contents($this->getFullPath($filename), $data); |
||||
51 | } |
||||
52 | |||||
53 | public function touch($filename) { |
||||
54 | return touch($this->getFullPath($filename)); |
||||
55 | } |
||||
56 | |||||
57 | public function get($filename) { |
||||
58 | if ($this->exists($filename)) { |
||||
59 | return file_get_contents($this->getFullPath($filename)); |
||||
60 | } else { |
||||
61 | return null; |
||||
62 | } |
||||
63 | } |
||||
64 | |||||
65 | public function getMimeType($filename) { |
||||
66 | if ($this->exists($filename)) { |
||||
67 | return mime_content_type($this->getFullPath($filename)); |
||||
68 | } else { |
||||
69 | return null; |
||||
70 | } |
||||
71 | } |
||||
72 | |||||
73 | public function send($filename) { |
||||
74 | header("Content-Disposition: inline; filename=\"$filename\""); |
||||
75 | |||||
76 | return send_local_file($this->getFullPath($filename)); |
||||
77 | } |
||||
78 | |||||
79 | public function getUrl($filename) { |
||||
80 | return get_self_url_prefix()."/public.php?op=cached_url&file=".basename($this->dir)."/".$filename; |
||||
81 | } |
||||
82 | |||||
83 | // check for locally cached (media) URLs and rewrite to local versions |
||||
84 | // this is called separately after sanitize() and plugin render article hooks to allow |
||||
85 | // plugins work on original source URLs used before caching |
||||
86 | static public function rewriteUrls($str) |
||||
87 | { |
||||
88 | $res = trim($str); |
||||
89 | if (!$res) { |
||||
90 | return ''; |
||||
91 | } |
||||
92 | |||||
93 | $doc = new DOMDocument(); |
||||
94 | if ($doc->loadHTML('<?xml encoding="UTF-8">'.$res)) { |
||||
95 | $xpath = new DOMXPath($doc); |
||||
96 | $cache = new DiskCache("images"); |
||||
97 | |||||
98 | $entries = $xpath->query('(//img[@src]|//picture/source[@src]|//video[@poster]|//video/source[@src]|//audio/source[@src])'); |
||||
99 | |||||
100 | $need_saving = false; |
||||
101 | |||||
102 | foreach ($entries as $entry) { |
||||
103 | |||||
104 | if ($entry->hasAttribute('src') || $entry->hasAttribute('poster')) { |
||||
105 | |||||
106 | // should be already absolutized because this is called after sanitize() |
||||
107 | $src = $entry->hasAttribute('poster') ? $entry->getAttribute('poster') : $entry->getAttribute('src'); |
||||
108 | $cached_filename = sha1($src); |
||||
109 | |||||
110 | if ($cache->exists($cached_filename)) { |
||||
111 | |||||
112 | $src = $cache->getUrl(sha1($src)); |
||||
113 | |||||
114 | if ($entry->hasAttribute('poster')) { |
||||
115 | $entry->setAttribute('poster', $src); |
||||
116 | } else { |
||||
117 | $entry->setAttribute('src', $src); |
||||
118 | $entry->removeAttribute("srcset"); |
||||
119 | } |
||||
120 | |||||
121 | $need_saving = true; |
||||
122 | } |
||||
123 | } |
||||
124 | } |
||||
125 | |||||
126 | if ($need_saving) { |
||||
127 | $doc->removeChild($doc->firstChild); //remove doctype |
||||
128 | $res = $doc->saveHTML(); |
||||
129 | } |
||||
130 | } |
||||
131 | return $res; |
||||
132 | } |
||||
133 | |||||
134 | public static function expire() { |
||||
135 | $dirs = array_filter(glob(CACHE_DIR."/*"), "is_dir"); |
||||
0 ignored issues
–
show
It seems like
glob(CACHE_DIR . '/*') can also be of type false ; however, parameter $input of array_filter() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
136 | |||||
137 | foreach ($dirs as $cache_dir) { |
||||
138 | $num_deleted = 0; |
||||
139 | |||||
140 | if (is_writable($cache_dir) && !file_exists("$cache_dir/.no-auto-expiry")) { |
||||
141 | $files = glob("$cache_dir/*"); |
||||
142 | |||||
143 | if ($files) { |
||||
144 | foreach ($files as $file) { |
||||
145 | if (time() - filemtime($file) > 86400 * CACHE_MAX_DAYS) { |
||||
0 ignored issues
–
show
|
|||||
146 | unlink($file); |
||||
147 | |||||
148 | ++$num_deleted; |
||||
149 | } |
||||
150 | } |
||||
151 | } |
||||
152 | |||||
153 | Debug::log("expired $cache_dir: removed $num_deleted files."); |
||||
154 | } |
||||
155 | } |
||||
156 | } |
||||
157 | } |
||||
158 |