1 : <?php
2 :
3 : class HTMLPurifier_DefinitionCache_Serializer extends
4 1 : HTMLPurifier_DefinitionCache
5 : {
6 :
7 : public function add($def, $config) {
8 0 : if (!$this->checkDefType($def)) return;
9 0 : $file = $this->generateFilePath($config);
10 0 : if (file_exists($file)) return false;
11 0 : if (!$this->_prepareDir($config)) return false;
12 0 : return $this->_write($file, serialize($def));
13 : }
14 :
15 : public function set($def, $config) {
16 0 : if (!$this->checkDefType($def)) return;
17 0 : $file = $this->generateFilePath($config);
18 0 : if (!$this->_prepareDir($config)) return false;
19 0 : return $this->_write($file, serialize($def));
20 : }
21 :
22 : public function replace($def, $config) {
23 0 : if (!$this->checkDefType($def)) return;
24 0 : $file = $this->generateFilePath($config);
25 0 : if (!file_exists($file)) return false;
26 0 : if (!$this->_prepareDir($config)) return false;
27 0 : return $this->_write($file, serialize($def));
28 : }
29 :
30 : public function get($config) {
31 2 : $file = $this->generateFilePath($config);
32 2 : if (!file_exists($file)) return false;
33 2 : return unserialize(file_get_contents($file));
34 : }
35 :
36 : public function remove($config) {
37 0 : $file = $this->generateFilePath($config);
38 0 : if (!file_exists($file)) return false;
39 0 : return unlink($file);
40 : }
41 :
42 : public function flush($config) {
43 0 : if (!$this->_prepareDir($config)) return false;
44 0 : $dir = $this->generateDirectoryPath($config);
45 0 : $dh = opendir($dir);
46 0 : while (false !== ($filename = readdir($dh))) {
47 0 : if (empty($filename)) continue;
48 0 : if ($filename[0] === '.') continue;
49 0 : unlink($dir . '/' . $filename);
50 0 : }
51 0 : }
52 :
53 : public function cleanup($config) {
54 0 : if (!$this->_prepareDir($config)) return false;
55 0 : $dir = $this->generateDirectoryPath($config);
56 0 : $dh = opendir($dir);
57 0 : while (false !== ($filename = readdir($dh))) {
58 0 : if (empty($filename)) continue;
59 0 : if ($filename[0] === '.') continue;
60 0 : $key = substr($filename, 0, strlen($filename) - 4);
61 0 : if ($this->isOld($key, $config)) unlink($dir . '/' . $filename);
62 0 : }
63 0 : }
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 2 : $key = $this->generateKey($config);
72 2 : 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 2 : $base = $this->generateBaseDirectoryPath($config);
82 2 : 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) {
91 2 : $base = $config->get('Cache', 'SerializerPath');
92 2 : $base = is_null($base) ? HTMLPURIFIER_PREFIX . '/HTMLPurifier/DefinitionCache/Serializer' : $base;
93 2 : 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
100 : * @return Number of bytes written if success, or false if failure.
101 : */
102 : private function _write($file, $data) {
103 0 : return file_put_contents($file, $data);
104 : }
105 :
106 : /**
107 : * Prepares the directory that this type stores the serials in
108 : * @return True if successful
109 : */
110 : private function _prepareDir($config) {
111 0 : $directory = $this->generateDirectoryPath($config);
112 0 : if (!is_dir($directory)) {
113 0 : $base = $this->generateBaseDirectoryPath($config);
114 0 : if (!is_dir($base)) {
115 0 : trigger_error('Base directory '.$base.' does not exist,
116 0 : please create or change using %Cache.SerializerPath',
117 0 : E_USER_ERROR);
118 0 : return false;
119 0 : } elseif (!$this->_testPermissions($base)) {
120 0 : return false;
121 : }
122 0 : $old = umask(0022); // disable group and world writes
123 0 : mkdir($directory);
124 0 : umask($old);
125 0 : } elseif (!$this->_testPermissions($directory)) {
126 0 : return false;
127 : }
128 0 : return true;
129 : }
130 :
131 : /**
132 : * Tests permissions on a directory and throws out friendly
133 : * error messages and attempts to chmod it itself if possible
134 : */
135 : private function _testPermissions($dir) {
136 : // early abort, if it is writable, everything is hunky-dory
137 0 : if (is_writable($dir)) return true;
138 0 : if (!is_dir($dir)) {
139 : // generally, you'll want to handle this beforehand
140 : // so a more specific error message can be given
141 0 : trigger_error('Directory '.$dir.' does not exist',
142 0 : E_USER_ERROR);
143 0 : return false;
144 : }
145 0 : if (function_exists('posix_getuid')) {
146 : // POSIX system, we can give more specific advice
147 0 : if (fileowner($dir) === posix_getuid()) {
148 : // we can chmod it ourselves
149 0 : chmod($dir, 0755);
150 0 : return true;
151 0 : } elseif (filegroup($dir) === posix_getgid()) {
152 0 : $chmod = '775';
153 0 : } else {
154 : // PHP's probably running as nobody, so we'll
155 : // need to give global permissions
156 0 : $chmod = '777';
157 : }
158 0 : trigger_error('Directory '.$dir.' not writable, '.
159 0 : 'please chmod to ' . $chmod,
160 0 : E_USER_ERROR);
161 0 : } else {
162 : // generic error message
163 0 : trigger_error('Directory '.$dir.' not writable, '.
164 0 : 'please alter file permissions',
165 0 : E_USER_ERROR);
166 : }
167 0 : return false;
168 : }
169 :
170 : }
171 :
|