Completed
Push — master ( 7bb5bf...9a4e50 )
by Richard
28:24 queued 22s
created

htdocs/class/file/file.php (9 issues)

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 <http://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       http://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    http://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 http://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());
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 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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
360
    }
361
362
    /**
363
     * Returns the File name without extension.
364
     *
365
     * @return string 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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
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 md5 Checksum {@link http://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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
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 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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
460
    }
461
462
    /**
463
     * Returns the Filesize, either in bytes or in human-readable format.
464
     *
465
     * @return string |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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer|string.
Loading history...
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 the Fileowner
514
     */
515
    public function owner()
516
    {
517
        if ($this->exists()) {
518
            return fileowner($this->pwd());
519
        }
520
521
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
522
    }
523
524
    /**
525
     * Returns the File group.
526
     *
527
     * @return integer 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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
537
    }
538
539
    /**
540
     * Returns last access time.
541
     *
542
     * @return integer 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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
552
    }
553
554
    /**
555
     * Returns last modified time.
556
     *
557
     * @return integer 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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
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