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