1 | <?php |
||
2 | /** |
||
3 | * File engine For XOOPS |
||
4 | * |
||
5 | * You may not change or alter any portion of this comment or credits |
||
6 | * of supporting developers from this source code or any supporting source code |
||
7 | * which is considered copyrighted (c) material of the original comment or credit authors. |
||
8 | * This program is distributed in the hope that it will be useful, |
||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
11 | * |
||
12 | * @copyright (c) 2005-2016 XOOPS Project (www.xoops.org) |
||
13 | * @license GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html) |
||
14 | * @package class |
||
15 | * @subpackage file |
||
16 | * @since 2.3.0 |
||
17 | * @author Taiwen Jiang <[email protected]> |
||
18 | */ |
||
19 | defined('XOOPS_ROOT_PATH') || exit('Restricted access'); |
||
20 | |||
21 | /** |
||
22 | * Convenience class for reading, writing and appending to files. |
||
23 | * |
||
24 | * PHP versions 4 and 5 |
||
25 | * |
||
26 | * CakePHP(tm) : Rapid Development Framework <https://www.cakephp.org/> |
||
27 | * Copyright 2005-2008, Cake Software Foundation, Inc. |
||
28 | * 1785 E. Sahara Avenue, Suite 490-204 |
||
29 | * Las Vegas, Nevada 89104 |
||
30 | * |
||
31 | * Licensed under The MIT License |
||
32 | * Redistributions of files must retain the above copyright notice. |
||
33 | * |
||
34 | * @filesource |
||
35 | * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. |
||
36 | * @link https://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project |
||
37 | * @package cake |
||
38 | * @subpackage cake.cake.libs |
||
39 | * @since CakePHP(tm) v 0.2.9 |
||
40 | * @modifiedby $LastChangedBy: beckmi $ |
||
41 | * @lastmodified $Date: 2015-06-06 17:59:41 -0400 (Sat, 06 Jun 2015) $ |
||
42 | * @license https://www.opensource.org/licenses/mit-license.php The MIT License |
||
43 | */ |
||
44 | |||
45 | /** |
||
46 | * Convenience class for reading, writing and appending to files. |
||
47 | * |
||
48 | * @package cake |
||
49 | * @subpackage cake.cake.libs |
||
50 | */ |
||
51 | class XoopsFileHandler |
||
52 | { |
||
53 | /** |
||
54 | * folder object of the File |
||
55 | * |
||
56 | * @var object |
||
57 | * @access public |
||
58 | */ |
||
59 | public $folder; |
||
60 | |||
61 | /** |
||
62 | * Filename |
||
63 | * |
||
64 | * @var string |
||
65 | * @access public |
||
66 | */ |
||
67 | public $name; |
||
68 | |||
69 | /** |
||
70 | * file info |
||
71 | * |
||
72 | * @var string |
||
73 | * @access public |
||
74 | */ |
||
75 | public $info = array(); |
||
76 | |||
77 | /** |
||
78 | * Holds the file handler resource if the file is opened |
||
79 | * |
||
80 | * @var resource |
||
81 | * @access public |
||
82 | */ |
||
83 | public $handle; |
||
84 | |||
85 | /** |
||
86 | * enable locking for file reading and writing |
||
87 | * |
||
88 | * @var boolean |
||
89 | * @access public |
||
90 | */ |
||
91 | public $lock; |
||
92 | |||
93 | /** |
||
94 | * Constructor |
||
95 | * |
||
96 | * @param string $path Path to file |
||
97 | * @param boolean $create Create file if it does not exist (if true) |
||
98 | * @param integer $mode Mode to apply to the folder holding the file |
||
99 | * @access private |
||
100 | */ |
||
101 | public function __construct($path, $create = false, $mode = 0755) |
||
102 | { |
||
103 | XoopsLoad::load('XoopsFile'); |
||
104 | $this->folder = XoopsFile::getHandler('folder', dirname($path), $create, $mode); |
||
105 | if (!is_dir($path)) { |
||
106 | $this->name = basename($path); |
||
107 | } |
||
108 | if (!$this->exists()) { |
||
109 | if ($create === true) { |
||
110 | if ($this->safe($path) && $this->create() === false) { |
||
111 | return false; |
||
112 | } |
||
113 | } else { |
||
114 | return false; |
||
115 | } |
||
116 | } |
||
117 | return null; |
||
118 | } |
||
119 | |||
120 | /** |
||
121 | * Closes the current file if it is opened |
||
122 | * |
||
123 | * @access private |
||
124 | */ |
||
125 | public function __destruct() |
||
126 | { |
||
127 | $this->close(); |
||
128 | } |
||
129 | |||
130 | /** |
||
131 | * Creates the File. |
||
132 | * |
||
133 | * @return boolean Success |
||
134 | * @access public |
||
135 | */ |
||
136 | public function create() |
||
137 | { |
||
138 | $dir = $this->folder->pwd(); |
||
139 | if (is_dir($dir) && is_writable($dir) && !$this->exists()) { |
||
140 | if (touch($this->pwd())) { |
||
141 | return true; |
||
142 | } |
||
143 | } |
||
144 | |||
145 | return false; |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Opens the current file with a given $mode |
||
150 | * |
||
151 | * @param string $mode A valid 'fopen' mode string (r|w|a ...) |
||
152 | * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't |
||
153 | * @return boolean True on success, false on failure |
||
154 | * @access public |
||
155 | */ |
||
156 | public function open($mode = 'r', $force = false) |
||
157 | { |
||
158 | if (!$force && is_resource($this->handle)) { |
||
159 | return true; |
||
160 | } |
||
161 | if ($this->exists() === false) { |
||
162 | if ($this->create() === false) { |
||
163 | return false; |
||
164 | } |
||
165 | } |
||
166 | $this->handle = fopen($this->pwd(), $mode); |
||
167 | if (is_resource($this->handle)) { |
||
168 | return true; |
||
169 | } |
||
170 | |||
171 | return false; |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Return the contents of this File as a string. |
||
176 | * |
||
177 | * @param bool|string|int $bytes where to start |
||
178 | * @param string $mode |
||
179 | * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't |
||
180 | * |
||
181 | * @return mixed string on success, false on failure |
||
182 | * @access public |
||
183 | */ |
||
184 | public function read($bytes = false, $mode = 'rb', $force = false) |
||
185 | { |
||
186 | $success = false; |
||
187 | if ($this->lock !== null) { |
||
188 | if (flock($this->handle, LOCK_SH) === false) { |
||
189 | return false; |
||
190 | } |
||
191 | } |
||
192 | if ($bytes === false) { |
||
193 | $success = file_get_contents($this->pwd()); |
||
194 | } elseif ($this->open($mode, $force) === true) { |
||
195 | if (is_int($bytes)) { |
||
196 | $success = fread($this->handle, $bytes); |
||
197 | } else { |
||
198 | $data = ''; |
||
199 | while (!feof($this->handle)) { |
||
200 | $data .= fgets($this->handle, 4096); |
||
201 | } |
||
202 | $success = trim($data); |
||
203 | } |
||
204 | } |
||
205 | if ($this->lock !== null) { |
||
206 | flock($this->handle, LOCK_UN); |
||
207 | } |
||
208 | |||
209 | return $success; |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Sets or gets the offset for the currently opened file. |
||
214 | * |
||
215 | * @param mixed $offset The $offset in bytes to seek. If set to false then the current offset is returned. |
||
216 | * @param integer $seek PHP Constant SEEK_SET | SEEK_CUR | SEEK_END determining what the $offset is relative to |
||
217 | * @return mixed True on success, false on failure (set mode), false on failure or integer offset on success (get mode) |
||
218 | * @access public |
||
219 | */ |
||
220 | public function offset($offset = false, $seek = SEEK_SET) |
||
221 | { |
||
222 | if ($offset === false) { |
||
223 | if (is_resource($this->handle)) { |
||
224 | return ftell($this->handle); |
||
225 | } |
||
226 | } elseif ($this->open() === true) { |
||
227 | return fseek($this->handle, $offset, $seek) === 0; |
||
228 | } |
||
229 | |||
230 | return false; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Prepares a ascii string for writing |
||
235 | * fixes line endings |
||
236 | * |
||
237 | * @param string $data Data to prepare for writing. |
||
238 | * @return string |
||
239 | * @access public |
||
240 | */ |
||
241 | public function prepare($data) |
||
242 | { |
||
243 | $lineBreak = "\n"; |
||
244 | if (substr(PHP_OS, 0, 3) === 'WIN') { |
||
245 | $lineBreak = "\r\n"; |
||
246 | } |
||
247 | |||
248 | return strtr($data, array( |
||
249 | "\r\n" => $lineBreak, |
||
250 | "\n" => $lineBreak, |
||
251 | "\r" => $lineBreak)); |
||
252 | } |
||
253 | |||
254 | /** |
||
255 | * Write given data to this File. |
||
256 | * |
||
257 | * @param string $data Data to write to this File. |
||
258 | * @param string $mode Mode of writing. {@link https://php.net/fwrite See fwrite()}. |
||
259 | * @param bool|string $force force the file to open |
||
260 | * @return boolean Success |
||
261 | * @access public |
||
262 | */ |
||
263 | public function write($data, $mode = 'w', $force = false) |
||
264 | { |
||
265 | $success = false; |
||
266 | if ($this->open($mode, $force) === true) { |
||
267 | if ($this->lock !== null) { |
||
268 | if (flock($this->handle, LOCK_EX) === false) { |
||
269 | return false; |
||
270 | } |
||
271 | } |
||
272 | if (fwrite($this->handle, $data) !== false) { |
||
273 | $success = true; |
||
274 | } |
||
275 | if ($this->lock !== null) { |
||
276 | flock($this->handle, LOCK_UN); |
||
277 | } |
||
278 | } |
||
279 | |||
280 | return $success; |
||
281 | } |
||
282 | |||
283 | /** |
||
284 | * Append given data string to this File. |
||
285 | * |
||
286 | * @param string $data Data to write |
||
287 | * @param bool|string $force force the file to open |
||
288 | * @return boolean Success |
||
289 | * @access public |
||
290 | */ |
||
291 | public function append($data, $force = false) |
||
292 | { |
||
293 | return $this->write($data, 'a', $force); |
||
294 | } |
||
295 | |||
296 | /** |
||
297 | * Closes the current file if it is opened. |
||
298 | * |
||
299 | * @return boolean True if closing was successful or file was already closed, otherwise false |
||
300 | * @access public |
||
301 | */ |
||
302 | public function close() |
||
303 | { |
||
304 | if (!is_resource($this->handle)) { |
||
305 | return true; |
||
306 | } |
||
307 | |||
308 | return fclose($this->handle); |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Deletes the File. |
||
313 | * |
||
314 | * @return boolean Success |
||
315 | * @access public |
||
316 | */ |
||
317 | public function delete() |
||
318 | { |
||
319 | if ($this->exists()) { |
||
320 | return unlink($this->pwd()); |
||
321 | } |
||
322 | |||
323 | return false; |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Returns the File extension. |
||
328 | * |
||
329 | * @return string The File extension |
||
330 | * @access public |
||
331 | */ |
||
332 | public function info() |
||
333 | { |
||
334 | if ($this->info == null) { |
||
335 | $this->info = pathinfo($this->pwd()); |
||
0 ignored issues
–
show
|
|||
336 | } |
||
337 | if (!isset($this->info['filename'])) { |
||
338 | $this->info['filename'] = $this->name(); |
||
339 | } |
||
340 | |||
341 | return $this->info; |
||
342 | } |
||
343 | |||
344 | /** |
||
345 | * Returns the File extension. |
||
346 | * |
||
347 | * @return string|false The File extension |
||
348 | * @access public |
||
349 | */ |
||
350 | public function ext() |
||
351 | { |
||
352 | if ($this->info == null) { |
||
353 | $this->info(); |
||
354 | } |
||
355 | if (isset($this->info['extension'])) { |
||
356 | return $this->info['extension']; |
||
357 | } |
||
358 | |||
359 | return false; |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * Returns the File name without extension. |
||
364 | * |
||
365 | * @return string|false The File name without extension. |
||
366 | * @access public |
||
367 | */ |
||
368 | public function name() |
||
369 | { |
||
370 | if ($this->info == null) { |
||
371 | $this->info(); |
||
372 | } |
||
373 | if (isset($this->info['extension'])) { |
||
374 | return basename($this->name, '.' . $this->info['extension']); |
||
375 | } elseif ($this->name) { |
||
376 | return $this->name; |
||
377 | } |
||
378 | |||
379 | return false; |
||
380 | } |
||
381 | |||
382 | /** |
||
383 | * makes filename safe for saving |
||
384 | * |
||
385 | * @param string $name the name of the file to make safe if different from $this->name |
||
386 | * @param null|string $ext |
||
387 | * @return string $ext the extension of the file |
||
388 | * @access public |
||
389 | */ |
||
390 | public function safe($name = null, $ext = null) |
||
391 | { |
||
392 | if (!$name) { |
||
393 | $name = $this->name; |
||
394 | } |
||
395 | if (!$ext) { |
||
396 | $ext = $this->ext(); |
||
397 | } |
||
398 | |||
399 | return preg_replace('/[^\w\.-]+/', '_', basename($name, $ext)); |
||
400 | } |
||
401 | |||
402 | /** |
||
403 | * Get md5 Checksum of file with previous check of Filesize |
||
404 | * |
||
405 | * @param mixed $maxsize in MB or true to force |
||
406 | * @return string|false md5 Checksum {@link https://php.net/md5_file See md5_file()} |
||
407 | * @access public |
||
408 | */ |
||
409 | public function md5($maxsize = 5) |
||
410 | { |
||
411 | if ($maxsize === true) { |
||
412 | return md5_file($this->pwd()); |
||
413 | } else { |
||
414 | $size = $this->size(); |
||
415 | if ($size && $size < ($maxsize * 1024) * 1024) { |
||
416 | return md5_file($this->pwd()); |
||
417 | } |
||
418 | } |
||
419 | |||
420 | return false; |
||
421 | } |
||
422 | |||
423 | /** |
||
424 | * Returns the full path of the File. |
||
425 | * |
||
426 | * @return string Full path to file |
||
427 | * @access public |
||
428 | */ |
||
429 | public function pwd() |
||
430 | { |
||
431 | return $this->folder->slashTerm($this->folder->pwd()) . $this->name; |
||
432 | } |
||
433 | |||
434 | /** |
||
435 | * Returns true if the File exists. |
||
436 | * |
||
437 | * @return boolean true if it exists, false otherwise |
||
438 | * @access public |
||
439 | */ |
||
440 | public function exists() |
||
441 | { |
||
442 | $exists = (file_exists($this->pwd()) && is_file($this->pwd())); |
||
443 | |||
444 | return $exists; |
||
445 | } |
||
446 | |||
447 | /** |
||
448 | * Returns the "chmod" (permissions) of the File. |
||
449 | * |
||
450 | * @return string|false Permissions for the file |
||
451 | * @access public |
||
452 | */ |
||
453 | public function perms() |
||
454 | { |
||
455 | if ($this->exists()) { |
||
456 | return substr(sprintf('%o', fileperms($this->pwd())), -4); |
||
457 | } |
||
458 | |||
459 | return false; |
||
460 | } |
||
461 | |||
462 | /** |
||
463 | * Returns the Filesize, either in bytes or in human-readable format. |
||
464 | * |
||
465 | * @return string|false |int filesize as int or as a human-readable string |
||
466 | * @access public |
||
467 | */ |
||
468 | public function size() |
||
469 | { |
||
470 | if ($this->exists()) { |
||
471 | return filesize($this->pwd()); |
||
472 | } |
||
473 | |||
474 | return false; |
||
475 | } |
||
476 | |||
477 | /** |
||
478 | * Returns true if the File is writable. |
||
479 | * |
||
480 | * @return boolean true if its writable, false otherwise |
||
481 | * @access public |
||
482 | */ |
||
483 | public function writable() |
||
484 | { |
||
485 | return is_writable($this->pwd()); |
||
486 | } |
||
487 | |||
488 | /** |
||
489 | * Returns true if the File is executable. |
||
490 | * |
||
491 | * @return boolean true if its executable, false otherwise |
||
492 | * @access public |
||
493 | */ |
||
494 | public function executable() |
||
495 | { |
||
496 | return is_executable($this->pwd()); |
||
497 | } |
||
498 | |||
499 | /** |
||
500 | * Returns true if the File is readable. |
||
501 | * |
||
502 | * @return boolean true if file is readable, false otherwise |
||
503 | * @access public |
||
504 | */ |
||
505 | public function readable() |
||
506 | { |
||
507 | return is_readable($this->pwd()); |
||
508 | } |
||
509 | |||
510 | /** |
||
511 | * Returns the File's owner. |
||
512 | * |
||
513 | * @return integer|false the Fileowner |
||
514 | */ |
||
515 | public function owner() |
||
516 | { |
||
517 | if ($this->exists()) { |
||
518 | return fileowner($this->pwd()); |
||
519 | } |
||
520 | |||
521 | return false; |
||
522 | } |
||
523 | |||
524 | /** |
||
525 | * Returns the File group. |
||
526 | * |
||
527 | * @return integer|false the Filegroup |
||
528 | * @access public |
||
529 | */ |
||
530 | public function group() |
||
531 | { |
||
532 | if ($this->exists()) { |
||
533 | return filegroup($this->pwd()); |
||
534 | } |
||
535 | |||
536 | return false; |
||
537 | } |
||
538 | |||
539 | /** |
||
540 | * Returns last access time. |
||
541 | * |
||
542 | * @return integer|false timestamp Timestamp of last access time |
||
543 | * @access public |
||
544 | */ |
||
545 | public function lastAccess() |
||
546 | { |
||
547 | if ($this->exists()) { |
||
548 | return fileatime($this->pwd()); |
||
549 | } |
||
550 | |||
551 | return false; |
||
552 | } |
||
553 | |||
554 | /** |
||
555 | * Returns last modified time. |
||
556 | * |
||
557 | * @return integer|false timestamp Timestamp of last modification |
||
558 | * @access public |
||
559 | */ |
||
560 | public function lastChange() |
||
561 | { |
||
562 | if ($this->exists()) { |
||
563 | return filemtime($this->pwd()); |
||
564 | } |
||
565 | |||
566 | return false; |
||
567 | } |
||
568 | |||
569 | /** |
||
570 | * Returns the current folder. |
||
571 | * |
||
572 | * @return Folder Current folder |
||
573 | * @access public |
||
574 | */ |
||
575 | public function &folder() |
||
576 | { |
||
577 | return $this->folder; |
||
578 | } |
||
579 | } |
||
580 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.