]>
Commit | Line | Data |
---|---|---|
f45a286b AD |
1 | <?php |
2 | ||
3 | class HTMLPurifier_DefinitionCache_Serializer extends | |
4 | HTMLPurifier_DefinitionCache | |
5 | { | |
6 | ||
7 | public function add($def, $config) { | |
8 | if (!$this->checkDefType($def)) return; | |
9 | $file = $this->generateFilePath($config); | |
10 | if (file_exists($file)) return false; | |
11 | if (!$this->_prepareDir($config)) return false; | |
f4f0f80d | 12 | return $this->_write($file, serialize($def), $config); |
f45a286b AD |
13 | } |
14 | ||
15 | public function set($def, $config) { | |
16 | if (!$this->checkDefType($def)) return; | |
17 | $file = $this->generateFilePath($config); | |
18 | if (!$this->_prepareDir($config)) return false; | |
f4f0f80d | 19 | return $this->_write($file, serialize($def), $config); |
f45a286b AD |
20 | } |
21 | ||
22 | public function replace($def, $config) { | |
23 | if (!$this->checkDefType($def)) return; | |
24 | $file = $this->generateFilePath($config); | |
25 | if (!file_exists($file)) return false; | |
26 | if (!$this->_prepareDir($config)) return false; | |
f4f0f80d | 27 | return $this->_write($file, serialize($def), $config); |
f45a286b AD |
28 | } |
29 | ||
30 | public function get($config) { | |
31 | $file = $this->generateFilePath($config); | |
32 | if (!file_exists($file)) return false; | |
33 | return unserialize(file_get_contents($file)); | |
34 | } | |
35 | ||
36 | public function remove($config) { | |
37 | $file = $this->generateFilePath($config); | |
38 | if (!file_exists($file)) return false; | |
39 | return unlink($file); | |
40 | } | |
41 | ||
42 | public function flush($config) { | |
43 | if (!$this->_prepareDir($config)) return false; | |
44 | $dir = $this->generateDirectoryPath($config); | |
45 | $dh = opendir($dir); | |
46 | while (false !== ($filename = readdir($dh))) { | |
47 | if (empty($filename)) continue; | |
48 | if ($filename[0] === '.') continue; | |
49 | unlink($dir . '/' . $filename); | |
50 | } | |
51 | } | |
52 | ||
53 | public function cleanup($config) { | |
54 | if (!$this->_prepareDir($config)) return false; | |
55 | $dir = $this->generateDirectoryPath($config); | |
56 | $dh = opendir($dir); | |
57 | while (false !== ($filename = readdir($dh))) { | |
58 | if (empty($filename)) continue; | |
59 | if ($filename[0] === '.') continue; | |
60 | $key = substr($filename, 0, strlen($filename) - 4); | |
61 | if ($this->isOld($key, $config)) unlink($dir . '/' . $filename); | |
62 | } | |
63 | } | |
64 | ||
65 | /** | |
66 | * Generates the file path to the serial file corresponding to | |
67 | * the configuration and definition name | |
68 | * @todo Make protected | |
69 | */ | |
70 | public function generateFilePath($config) { | |
71 | $key = $this->generateKey($config); | |
72 | return $this->generateDirectoryPath($config) . '/' . $key . '.ser'; | |
73 | } | |
74 | ||
75 | /** | |
76 | * Generates the path to the directory contain this cache's serial files | |
77 | * @note No trailing slash | |
78 | * @todo Make protected | |
79 | */ | |
80 | public function generateDirectoryPath($config) { | |
81 | $base = $this->generateBaseDirectoryPath($config); | |
82 | return $base . '/' . $this->type; | |
83 | } | |
84 | ||
85 | /** | |
86 | * Generates path to base directory that contains all definition type | |
87 | * serials | |
88 | * @todo Make protected | |
89 | */ | |
90 | public function generateBaseDirectoryPath($config) { | |
f4f0f80d | 91 | $base = $config->get('Cache.SerializerPath'); |
f45a286b AD |
92 | $base = is_null($base) ? HTMLPURIFIER_PREFIX . '/HTMLPurifier/DefinitionCache/Serializer' : $base; |
93 | return $base; | |
94 | } | |
95 | ||
96 | /** | |
97 | * Convenience wrapper function for file_put_contents | |
98 | * @param $file File name to write to | |
99 | * @param $data Data to write into file | |
f4f0f80d | 100 | * @param $config Config object |
f45a286b AD |
101 | * @return Number of bytes written if success, or false if failure. |
102 | */ | |
f4f0f80d AD |
103 | private function _write($file, $data, $config) { |
104 | $result = file_put_contents($file, $data); | |
105 | if ($result !== false) { | |
106 | // set permissions of the new file (no execute) | |
107 | $chmod = $config->get('Cache.SerializerPermissions'); | |
108 | if (!$chmod) { | |
109 | $chmod = 0644; // invalid config or simpletest | |
110 | } | |
111 | $chmod = $chmod & 0666; | |
112 | chmod($file, $chmod); | |
113 | } | |
114 | return $result; | |
f45a286b AD |
115 | } |
116 | ||
117 | /** | |
118 | * Prepares the directory that this type stores the serials in | |
f4f0f80d | 119 | * @param $config Config object |
f45a286b AD |
120 | * @return True if successful |
121 | */ | |
122 | private function _prepareDir($config) { | |
123 | $directory = $this->generateDirectoryPath($config); | |
f4f0f80d AD |
124 | $chmod = $config->get('Cache.SerializerPermissions'); |
125 | if (!$chmod) { | |
126 | $chmod = 0755; // invalid config or simpletest | |
127 | } | |
f45a286b AD |
128 | if (!is_dir($directory)) { |
129 | $base = $this->generateBaseDirectoryPath($config); | |
130 | if (!is_dir($base)) { | |
131 | trigger_error('Base directory '.$base.' does not exist, | |
132 | please create or change using %Cache.SerializerPath', | |
133 | E_USER_WARNING); | |
134 | return false; | |
f4f0f80d | 135 | } elseif (!$this->_testPermissions($base, $chmod)) { |
f45a286b AD |
136 | return false; |
137 | } | |
f4f0f80d AD |
138 | $old = umask(0000); |
139 | mkdir($directory, $chmod); | |
f45a286b | 140 | umask($old); |
f4f0f80d | 141 | } elseif (!$this->_testPermissions($directory, $chmod)) { |
f45a286b AD |
142 | return false; |
143 | } | |
144 | return true; | |
145 | } | |
146 | ||
147 | /** | |
148 | * Tests permissions on a directory and throws out friendly | |
149 | * error messages and attempts to chmod it itself if possible | |
f4f0f80d AD |
150 | * @param $dir Directory path |
151 | * @param $chmod Permissions | |
152 | * @return True if directory writable | |
f45a286b | 153 | */ |
f4f0f80d | 154 | private function _testPermissions($dir, $chmod) { |
f45a286b AD |
155 | // early abort, if it is writable, everything is hunky-dory |
156 | if (is_writable($dir)) return true; | |
157 | if (!is_dir($dir)) { | |
158 | // generally, you'll want to handle this beforehand | |
159 | // so a more specific error message can be given | |
160 | trigger_error('Directory '.$dir.' does not exist', | |
161 | E_USER_WARNING); | |
162 | return false; | |
163 | } | |
164 | if (function_exists('posix_getuid')) { | |
165 | // POSIX system, we can give more specific advice | |
166 | if (fileowner($dir) === posix_getuid()) { | |
167 | // we can chmod it ourselves | |
f4f0f80d AD |
168 | $chmod = $chmod | 0700; |
169 | if (chmod($dir, $chmod)) return true; | |
f45a286b | 170 | } elseif (filegroup($dir) === posix_getgid()) { |
f4f0f80d | 171 | $chmod = $chmod | 0070; |
f45a286b AD |
172 | } else { |
173 | // PHP's probably running as nobody, so we'll | |
174 | // need to give global permissions | |
f4f0f80d | 175 | $chmod = $chmod | 0777; |
f45a286b AD |
176 | } |
177 | trigger_error('Directory '.$dir.' not writable, '. | |
f4f0f80d | 178 | 'please chmod to ' . decoct($chmod), |
f45a286b AD |
179 | E_USER_WARNING); |
180 | } else { | |
181 | // generic error message | |
182 | trigger_error('Directory '.$dir.' not writable, '. | |
183 | 'please alter file permissions', | |
184 | E_USER_WARNING); | |
185 | } | |
186 | return false; | |
187 | } | |
188 | ||
189 | } | |
190 | ||
191 | // vim: et sw=4 sts=4 |