PluginProbe
ManageWP Worker / trunk
ManageWP Worker vtrunk
4.9.38 4.9.37 4.9.36 4.9.35 4.9.34 3.8.7 3.8.8 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.18 3.9.19 3.9.2 3.9.20 3.9.21 3.9.22 3.9.23 3.9.24 All 73 releases
worker / src / MWP / Action / IncrementalBackup / ListFiles.php

ListFiles.php in ManageWP Worker trunk, at src/MWP/Action/IncrementalBackup/ListFiles.php

282 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * This file is part of the ManageWP Worker plugin.
4 *
5 * (c) ManageWP LLC <[email protected]>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11 class MWP_Action_IncrementalBackup_ListFiles extends MWP_Action_IncrementalBackup_AbstractFiles
12 {
13
14 /** @var Symfony_Filesystem_Filesystem */
15 protected $fileSystem;
16
17 public function __construct()
18 {
19 parent::__construct();
20 $this->fileSystem = new Symfony_Filesystem_Filesystem();
21 }
22
23 /**
24 * Return a list of all files
25 *
26 * @param array $params
27 * @param MWP_Worker_Request $request
28 *
29 * @return array
30 */
31 public function queryFiles(array $params, MWP_Worker_Request $request)
32 {
33 if (isset($params['query']) && is_array($params['query'])) {
34 $files = $this->getFilesInfo($params['query']);
35 } else {
36 try {
37 $files = $this->listFiles(ABSPATH, true);
38 } catch (UnexpectedValueException $e) {
39 $files = $this->listFilesWindowsPermissionsFix(ABSPATH, true);
40 }
41 }
42
43 return $this->createResult(array('files' => $files));
44 }
45
46 /**
47 * @param array $params
48 * @param MWP_Worker_Request $request
49 *
50 * @return array
51 */
52 public function listDirectories(array $params, MWP_Worker_Request $request)
53 {
54 $directories = $params['directories'];
55
56 $result = array();
57
58 foreach ($directories as $directory) {
59 $relativePath = $directory['path'];
60 $decodedPath = $directory['pathEncoded'] ? $this->pathDecode($relativePath) : $relativePath;
61 $recursive = isset($directory['recursive']) ? $directory['recursive'] : false;
62 $offset = isset($directory['offset']) ? $directory['offset'] : 0;
63 $limit = isset($directory['limit']) ? $directory['limit'] : 0;
64
65 $realPath = $this->getRealPath($decodedPath, true);
66 if (!file_exists($realPath)) {
67 $result[$relativePath] = false;
68 continue;
69 }
70
71 try {
72 $filesInDirectory = $this->listFiles($realPath, $recursive, $offset, $limit);
73 } catch (UnexpectedValueException $e) {
74 if ($relativePath !== ".") {
75 throw $e;
76 }
77
78 $filesInDirectory = $this->listFilesWindowsPermissionsFix($realPath, $recursive, $offset, $limit);
79 }
80
81 $result[$relativePath] = $filesInDirectory;
82 }
83
84 return $this->createResult(array('directories' => $result));
85 }
86
87 /**
88 * Return a list of files in the WordPress root directory, recursively
89 *
90 * @param string $rootPath
91 * @param bool $recursive
92 * @param int $offset
93 * @param int $limit
94 *
95 * @return array
96 */
97 private function listFiles($rootPath, $recursive = false, $offset = 0, $limit = 0)
98 {
99 $result = array();
100
101 $iterator = $this->createIterator($recursive, $rootPath);
102
103 $i = 0;
104
105 foreach ($iterator as $file) {
106 if ($i++ < $offset) {
107 continue;
108 }
109
110 if ($limit !== 0 && $i > $offset + $limit) {
111 break;
112 }
113
114 /** @var SplFileInfo $file */
115 $fileResult = $this->createFileResult($file);
116
117 $result[] = $fileResult;
118 }
119
120 return $result;
121 }
122
123 /**
124 * This is a special case of listFiles function, with the purpose of bypassing the
125 * Windows permissions issue when the php user does not have permission to list
126 * the parent directory of "."
127 *
128 * See https://bugs.php.net/bug.php?id=43817 for the details of the issue.
129 *
130 * @param string $rootPath
131 * @param bool $recursive
132 * @param int $offset
133 * @param int $limit
134 *
135 * @return array
136 */
137 private function listFilesWindowsPermissionsFix($rootPath, $recursive = false, $offset = 0, $limit = 0)
138 {
139 $result = array();
140
141 $iterator = $this->createIterator($recursive, $rootPath . DIRECTORY_SEPARATOR . 'wp-admin' . DIRECTORY_SEPARATOR . '..');
142
143 $i = 0;
144
145 foreach ($iterator as $file) {
146 if ($i++ < $offset) {
147 continue;
148 }
149
150 if ($limit !== 0 && $i > $offset + $limit) {
151 break;
152 }
153
154 /** @var SplFileInfo $file */
155 $fileResult = $this->createFileResult($file);
156 $fileResult['path'] = str_replace("wp-admin/../", "", $fileResult['path']);
157
158 $result[] = $fileResult;
159 }
160
161 return $result;
162 }
163
164 /**
165 * Get a list of file stats for given $files
166 *
167 * @param array $files
168 *
169 * @return array
170 */
171 protected function getFilesInfo(array $files)
172 {
173 $result = array();
174
175 foreach ($files as $file) {
176 $relativePath = $file['path'];
177 $decodedPath = $file['pathEncoded'] ? $this->pathDecode($relativePath) : $relativePath;
178 $realPath = $this->getRealPath($decodedPath, true);
179
180 if (!file_exists($realPath)) {
181 $result[] = array(
182 'path' => $relativePath,
183 'exists' => false,
184 );
185 continue;
186 }
187
188 $file = new SplFileInfo($realPath);
189 $result[] = $this->createFileResult($file);
190 }
191
192 return $result;
193 }
194
195 /**
196 * @param string $realPath
197 * @param string $rootPath
198 *
199 * @return string
200 */
201 private function getRelativePath($realPath, $rootPath)
202 {
203 $path = $this->fileSystem->makePathRelative($realPath, $rootPath);
204
205 return rtrim($path, '/\\');
206 }
207
208 /**
209 * @param SplFileInfo $file
210 *
211 * @return array
212 */
213 private function createFileResult(SplFileInfo $file)
214 {
215 $fileResult = array(
216 'path' => $this->replaceWindowsPath($this->getRelativePath($file->getPathname(), $this->cleanPath(ABSPATH))),
217 'pathEncoded' => false,
218 'isLink' => false,
219 'exists' => false,
220 'isDirectory' => false,
221 'owner' => 0,
222 'group' => 0,
223 'permissions' => 0,
224 );
225 if (!seems_utf8($fileResult['path'])) {
226 $fileResult['path'] = $this->pathEncode($fileResult['path']);
227 $fileResult['pathEncoded'] = true;
228 }
229 try {
230 $fileResult['isLink'] = $file->isLink(); // need to be first
231 $fileResult['size'] = $file->getSize();
232 $fileResult['isDirectory'] = $file->isDir();
233 $fileResult['owner'] = $file->getOwner();
234 $fileResult['group'] = $file->getGroup();
235 $fileResult['permissions'] = $file->getPerms();
236 $fileResult['mTime'] = $file->getMTime();
237 $fileResult['exists'] = true;
238 if ($file->isLink()) {
239 $fileResult['linkTarget'] = $file->getLinkTarget();
240 };
241 } catch (RuntimeException $e) {
242 }
243
244 return $fileResult;
245 }
246
247 /**
248 * Create a recursive or non-recursive iterator for $path. Handles php 5.2 incompatibility.
249 *
250 * @param bool $recursive
251 * @param string $path
252 *
253 * @return Iterator
254 */
255 private function createIterator($recursive, $path)
256 {
257 if ($recursive) {
258 // PHP 5.2.x does not have the SKIP_DOTS flag because it skips all dots by default
259 // The behavior was changed in PHP 5.3+ and it does not skip dots without the SKIP_DOTS flag
260 $php52 = version_compare(phpversion(), '5.3', '<');
261
262 if ($php52) {
263 $directory = new RecursiveDirectoryIterator($path);
264 } else {
265 /** @handled constant */
266 $directory = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
267 }
268
269 $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD);
270 } else {
271 $directory = new Symfony_Filesystem_FilesystemIterator($path, Symfony_Filesystem_FilesystemIterator::SKIP_DOTS);
272 $iterator = new IteratorIterator($directory);
273 }
274
275 return $iterator;
276 }
277
278 private function cleanPath($path) {
279 return preg_replace('#/{2,}#', '/', $path);
280 }
281 }
282