WordPress 4.2
[autoinstalls/wordpress.git] / wp-admin / includes / class-wp-filesystem-direct.php
1 <?php
2 /**
3  * WordPress Direct Filesystem.
4  *
5  * @package WordPress
6  * @subpackage Filesystem
7  */
8
9 /**
10  * WordPress Filesystem Class for direct PHP file and folder manipulation.
11  *
12  * @since 2.5.0
13  * @package WordPress
14  * @subpackage Filesystem
15  * @uses WP_Filesystem_Base Extends class
16  */
17 class WP_Filesystem_Direct extends WP_Filesystem_Base {
18
19         /**
20          * constructor
21          *
22          * @param mixed $arg ignored argument
23          */
24         public function __construct($arg) {
25                 $this->method = 'direct';
26                 $this->errors = new WP_Error();
27         }
28
29         /**
30          * Reads entire file into a string
31          *
32          * @param string $file Name of the file to read.
33          * @return string|bool The function returns the read data or false on failure.
34          */
35         public function get_contents($file) {
36                 return @file_get_contents($file);
37         }
38
39         /**
40          * Reads entire file into an array
41          *
42          * @param string $file Path to the file.
43          * @return array|bool the file contents in an array or false on failure.
44          */
45         public function get_contents_array($file) {
46                 return @file($file);
47         }
48
49         /**
50          * Write a string to a file
51          *
52          * @param string $file     Remote path to the file where to write the data.
53          * @param string $contents The data to write.
54          * @param int    $mode     Optional. The file permissions as octal number, usually 0644.
55          *                         Default false.
56          * @return bool False upon failure, true otherwise.
57          */
58         public function put_contents( $file, $contents, $mode = false ) {
59                 $fp = @fopen( $file, 'wb' );
60                 if ( ! $fp )
61                         return false;
62
63                 mbstring_binary_safe_encoding();
64
65                 $data_length = strlen( $contents );
66
67                 $bytes_written = fwrite( $fp, $contents );
68
69                 reset_mbstring_encoding();
70
71                 fclose( $fp );
72
73                 if ( $data_length !== $bytes_written )
74                         return false;
75
76                 $this->chmod( $file, $mode );
77
78                 return true;
79         }
80
81         /**
82          * Gets the current working directory
83          *
84          * @return string|bool the current working directory on success, or false on failure.
85          */
86         public function cwd() {
87                 return @getcwd();
88         }
89
90         /**
91          * Change directory
92          *
93          * @param string $dir The new current directory.
94          * @return bool Returns true on success or false on failure.
95          */
96         public function chdir($dir) {
97                 return @chdir($dir);
98         }
99
100         /**
101          * Changes file group
102          *
103          * @param string $file      Path to the file.
104          * @param mixed  $group     A group name or number.
105          * @param bool   $recursive Optional. If set True changes file group recursively. Default false.
106          * @return bool Returns true on success or false on failure.
107          */
108         public function chgrp($file, $group, $recursive = false) {
109                 if ( ! $this->exists($file) )
110                         return false;
111                 if ( ! $recursive )
112                         return @chgrp($file, $group);
113                 if ( ! $this->is_dir($file) )
114                         return @chgrp($file, $group);
115                 // Is a directory, and we want recursive
116                 $file = trailingslashit($file);
117                 $filelist = $this->dirlist($file);
118                 foreach ($filelist as $filename)
119                         $this->chgrp($file . $filename, $group, $recursive);
120
121                 return true;
122         }
123
124         /**
125          * Changes filesystem permissions
126          *
127          * @param string $file      Path to the file.
128          * @param int    $mode      Optional. The permissions as octal number, usually 0644 for files,
129          *                          0755 for dirs. Default false.
130          * @param bool   $recursive Optional. If set True changes file group recursively. Default false.
131          * @return bool Returns true on success or false on failure.
132          */
133         public function chmod($file, $mode = false, $recursive = false) {
134                 if ( ! $mode ) {
135                         if ( $this->is_file($file) )
136                                 $mode = FS_CHMOD_FILE;
137                         elseif ( $this->is_dir($file) )
138                                 $mode = FS_CHMOD_DIR;
139                         else
140                                 return false;
141                 }
142
143                 if ( ! $recursive || ! $this->is_dir($file) )
144                         return @chmod($file, $mode);
145                 // Is a directory, and we want recursive
146                 $file = trailingslashit($file);
147                 $filelist = $this->dirlist($file);
148                 foreach ( (array)$filelist as $filename => $filemeta)
149                         $this->chmod($file . $filename, $mode, $recursive);
150
151                 return true;
152         }
153
154         /**
155          * Changes file owner
156          *
157          * @param string $file      Path to the file.
158          * @param mixed  $owner     A user name or number.
159          * @param bool   $recursive Optional. If set True changes file owner recursively.
160          *                          Default false.
161          * @return bool Returns true on success or false on failure.
162          */
163         public function chown($file, $owner, $recursive = false) {
164                 if ( ! $this->exists($file) )
165                         return false;
166                 if ( ! $recursive )
167                         return @chown($file, $owner);
168                 if ( ! $this->is_dir($file) )
169                         return @chown($file, $owner);
170                 // Is a directory, and we want recursive
171                 $filelist = $this->dirlist($file);
172                 foreach ($filelist as $filename) {
173                         $this->chown($file . '/' . $filename, $owner, $recursive);
174                 }
175                 return true;
176         }
177
178         /**
179          * Gets file owner
180          *
181          * @param string $file Path to the file.
182          * @return string|bool Username of the user or false on error.
183          */
184         public function owner($file) {
185                 $owneruid = @fileowner($file);
186                 if ( ! $owneruid )
187                         return false;
188                 if ( ! function_exists('posix_getpwuid') )
189                         return $owneruid;
190                 $ownerarray = posix_getpwuid($owneruid);
191                 return $ownerarray['name'];
192         }
193
194         /**
195          * Gets file permissions
196          *
197          * FIXME does not handle errors in fileperms()
198          *
199          * @param string $file Path to the file.
200          * @return string Mode of the file (last 3 digits).
201          */
202         public function getchmod($file) {
203                 return substr( decoct( @fileperms( $file ) ), -3 );
204         }
205
206         /**
207          * @param string $file
208          * @return string|false
209          */
210         public function group($file) {
211                 $gid = @filegroup($file);
212                 if ( ! $gid )
213                         return false;
214                 if ( ! function_exists('posix_getgrgid') )
215                         return $gid;
216                 $grouparray = posix_getgrgid($gid);
217                 return $grouparray['name'];
218         }
219
220         /**
221          * @param string $source
222          * @param string $destination
223          * @param bool   $overwrite
224          * @param int    $mode
225          * @return bool
226          */
227         public function copy($source, $destination, $overwrite = false, $mode = false) {
228                 if ( ! $overwrite && $this->exists($destination) )
229                         return false;
230
231                 $rtval = copy($source, $destination);
232                 if ( $mode )
233                         $this->chmod($destination, $mode);
234                 return $rtval;
235         }
236
237         /**
238          * @param string $source
239          * @param string $destination
240          * @param bool $overwrite
241          * @return bool
242          */
243         public function move($source, $destination, $overwrite = false) {
244                 if ( ! $overwrite && $this->exists($destination) )
245                         return false;
246
247                 // Try using rename first. if that fails (for example, source is read only) try copy.
248                 if ( @rename($source, $destination) )
249                         return true;
250
251                 if ( $this->copy($source, $destination, $overwrite) && $this->exists($destination) ) {
252                         $this->delete($source);
253                         return true;
254                 } else {
255                         return false;
256                 }
257         }
258
259         /**
260          * @param string $file
261          * @param bool $recursive
262          * @param string $type
263          * @return bool
264          */
265         public function delete($file, $recursive = false, $type = false) {
266                 if ( empty( $file ) ) // Some filesystems report this as /, which can cause non-expected recursive deletion of all files in the filesystem.
267                         return false;
268                 $file = str_replace( '\\', '/', $file ); // for win32, occasional problems deleting files otherwise
269
270                 if ( 'f' == $type || $this->is_file($file) )
271                         return @unlink($file);
272                 if ( ! $recursive && $this->is_dir($file) )
273                         return @rmdir($file);
274
275                 // At this point it's a folder, and we're in recursive mode
276                 $file = trailingslashit($file);
277                 $filelist = $this->dirlist($file, true);
278
279                 $retval = true;
280                 if ( is_array( $filelist ) ) {
281                         foreach ( $filelist as $filename => $fileinfo ) {
282                                 if ( ! $this->delete($file . $filename, $recursive, $fileinfo['type']) )
283                                         $retval = false;
284                         }
285                 }
286
287                 if ( file_exists($file) && ! @rmdir($file) )
288                         $retval = false;
289
290                 return $retval;
291         }
292         /**
293          * @param string $file
294          * @return bool
295          */
296         public function exists($file) {
297                 return @file_exists($file);
298         }
299         /**
300          * @param string $file
301          * @return bool
302          */
303         public function is_file($file) {
304                 return @is_file($file);
305         }
306         /**
307          * @param string $path
308          * @return bool
309          */
310         public function is_dir($path) {
311                 return @is_dir($path);
312         }
313
314         /**
315          * @param string $file
316          * @return bool
317          */
318         public function is_readable($file) {
319                 return @is_readable($file);
320         }
321
322         /**
323          * @param string $file
324          * @return bool
325          */
326         public function is_writable($file) {
327                 return @is_writable($file);
328         }
329
330         /**
331          * @param string $file
332          * @return int
333          */
334         public function atime($file) {
335                 return @fileatime($file);
336         }
337
338         /**
339          * @param string $file
340          * @return int
341          */
342         public function mtime($file) {
343                 return @filemtime($file);
344         }
345
346         /**
347          * @param string $file
348          * @return int
349          */
350         public function size($file) {
351                 return @filesize($file);
352         }
353
354         /**
355          * @param string $file
356          * @param int $time
357          * @param int $atime
358          * @return bool
359          */
360         public function touch($file, $time = 0, $atime = 0) {
361                 if ($time == 0)
362                         $time = time();
363                 if ($atime == 0)
364                         $atime = time();
365                 return @touch($file, $time, $atime);
366         }
367
368         /**
369          * @param string $path
370          * @param mixed  $chmod
371          * @param mixed  $chown
372          * @param mixed  $chgrp
373          * @return bool
374          */
375         public function mkdir($path, $chmod = false, $chown = false, $chgrp = false) {
376                 // Safe mode fails with a trailing slash under certain PHP versions.
377                 $path = untrailingslashit($path);
378                 if ( empty($path) )
379                         return false;
380
381                 if ( ! $chmod )
382                         $chmod = FS_CHMOD_DIR;
383
384                 if ( ! @mkdir($path) )
385                         return false;
386                 $this->chmod($path, $chmod);
387                 if ( $chown )
388                         $this->chown($path, $chown);
389                 if ( $chgrp )
390                         $this->chgrp($path, $chgrp);
391                 return true;
392         }
393
394         /**
395          * @param string $path
396          * @param bool $recursive
397          * @return bool
398          */
399         public function rmdir($path, $recursive = false) {
400                 return $this->delete($path, $recursive);
401         }
402
403         /**
404          * @param string $path
405          * @param bool $include_hidden
406          * @param bool $recursive
407          * @return bool|array
408          */
409         public function dirlist($path, $include_hidden = true, $recursive = false) {
410                 if ( $this->is_file($path) ) {
411                         $limit_file = basename($path);
412                         $path = dirname($path);
413                 } else {
414                         $limit_file = false;
415                 }
416
417                 if ( ! $this->is_dir($path) )
418                         return false;
419
420                 $dir = @dir($path);
421                 if ( ! $dir )
422                         return false;
423
424                 $ret = array();
425
426                 while (false !== ($entry = $dir->read()) ) {
427                         $struc = array();
428                         $struc['name'] = $entry;
429
430                         if ( '.' == $struc['name'] || '..' == $struc['name'] )
431                                 continue;
432
433                         if ( ! $include_hidden && '.' == $struc['name'][0] )
434                                 continue;
435
436                         if ( $limit_file && $struc['name'] != $limit_file)
437                                 continue;
438
439                         $struc['perms']         = $this->gethchmod($path.'/'.$entry);
440                         $struc['permsn']        = $this->getnumchmodfromh($struc['perms']);
441                         $struc['number']        = false;
442                         $struc['owner']         = $this->owner($path.'/'.$entry);
443                         $struc['group']         = $this->group($path.'/'.$entry);
444                         $struc['size']          = $this->size($path.'/'.$entry);
445                         $struc['lastmodunix']= $this->mtime($path.'/'.$entry);
446                         $struc['lastmod']   = date('M j',$struc['lastmodunix']);
447                         $struc['time']          = date('h:i:s',$struc['lastmodunix']);
448                         $struc['type']          = $this->is_dir($path.'/'.$entry) ? 'd' : 'f';
449
450                         if ( 'd' == $struc['type'] ) {
451                                 if ( $recursive )
452                                         $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive);
453                                 else
454                                         $struc['files'] = array();
455                         }
456
457                         $ret[ $struc['name'] ] = $struc;
458                 }
459                 $dir->close();
460                 unset($dir);
461                 return $ret;
462         }
463 }