angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-wp-filesystem-direct.php (16639B)


      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  *
     14  * @see WP_Filesystem_Base
     15  */
     16 class WP_Filesystem_Direct extends WP_Filesystem_Base {
     17 
     18 	/**
     19 	 * Constructor.
     20 	 *
     21 	 * @since 2.5.0
     22 	 *
     23 	 * @param mixed $arg Not used.
     24 	 */
     25 	public function __construct( $arg ) {
     26 		$this->method = 'direct';
     27 		$this->errors = new WP_Error();
     28 	}
     29 
     30 	/**
     31 	 * Reads entire file into a string.
     32 	 *
     33 	 * @since 2.5.0
     34 	 *
     35 	 * @param string $file Name of the file to read.
     36 	 * @return string|false Read data on success, false on failure.
     37 	 */
     38 	public function get_contents( $file ) {
     39 		return @file_get_contents( $file );
     40 	}
     41 
     42 	/**
     43 	 * Reads entire file into an array.
     44 	 *
     45 	 * @since 2.5.0
     46 	 *
     47 	 * @param string $file Path to the file.
     48 	 * @return array|false File contents in an array on success, false on failure.
     49 	 */
     50 	public function get_contents_array( $file ) {
     51 		return @file( $file );
     52 	}
     53 
     54 	/**
     55 	 * Writes a string to a file.
     56 	 *
     57 	 * @since 2.5.0
     58 	 *
     59 	 * @param string    $file     Remote path to the file where to write the data.
     60 	 * @param string    $contents The data to write.
     61 	 * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
     62 	 *                            Default false.
     63 	 * @return bool True on success, false on failure.
     64 	 */
     65 	public function put_contents( $file, $contents, $mode = false ) {
     66 		$fp = @fopen( $file, 'wb' );
     67 
     68 		if ( ! $fp ) {
     69 			return false;
     70 		}
     71 
     72 		mbstring_binary_safe_encoding();
     73 
     74 		$data_length = strlen( $contents );
     75 
     76 		$bytes_written = fwrite( $fp, $contents );
     77 
     78 		reset_mbstring_encoding();
     79 
     80 		fclose( $fp );
     81 
     82 		if ( $data_length !== $bytes_written ) {
     83 			return false;
     84 		}
     85 
     86 		$this->chmod( $file, $mode );
     87 
     88 		return true;
     89 	}
     90 
     91 	/**
     92 	 * Gets the current working directory.
     93 	 *
     94 	 * @since 2.5.0
     95 	 *
     96 	 * @return string|false The current working directory on success, false on failure.
     97 	 */
     98 	public function cwd() {
     99 		return getcwd();
    100 	}
    101 
    102 	/**
    103 	 * Changes current directory.
    104 	 *
    105 	 * @since 2.5.0
    106 	 *
    107 	 * @param string $dir The new current directory.
    108 	 * @return bool True on success, false on failure.
    109 	 */
    110 	public function chdir( $dir ) {
    111 		return @chdir( $dir );
    112 	}
    113 
    114 	/**
    115 	 * Changes the file group.
    116 	 *
    117 	 * @since 2.5.0
    118 	 *
    119 	 * @param string     $file      Path to the file.
    120 	 * @param string|int $group     A group name or number.
    121 	 * @param bool       $recursive Optional. If set to true, changes file group recursively.
    122 	 *                              Default false.
    123 	 * @return bool True on success, false on failure.
    124 	 */
    125 	public function chgrp( $file, $group, $recursive = false ) {
    126 		if ( ! $this->exists( $file ) ) {
    127 			return false;
    128 		}
    129 
    130 		if ( ! $recursive ) {
    131 			return chgrp( $file, $group );
    132 		}
    133 
    134 		if ( ! $this->is_dir( $file ) ) {
    135 			return chgrp( $file, $group );
    136 		}
    137 
    138 		// Is a directory, and we want recursive.
    139 		$file     = trailingslashit( $file );
    140 		$filelist = $this->dirlist( $file );
    141 
    142 		foreach ( $filelist as $filename ) {
    143 			$this->chgrp( $file . $filename, $group, $recursive );
    144 		}
    145 
    146 		return true;
    147 	}
    148 
    149 	/**
    150 	 * Changes filesystem permissions.
    151 	 *
    152 	 * @since 2.5.0
    153 	 *
    154 	 * @param string    $file      Path to the file.
    155 	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
    156 	 *                             0755 for directories. Default false.
    157 	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
    158 	 *                             Default false.
    159 	 * @return bool True on success, false on failure.
    160 	 */
    161 	public function chmod( $file, $mode = false, $recursive = false ) {
    162 		if ( ! $mode ) {
    163 			if ( $this->is_file( $file ) ) {
    164 				$mode = FS_CHMOD_FILE;
    165 			} elseif ( $this->is_dir( $file ) ) {
    166 				$mode = FS_CHMOD_DIR;
    167 			} else {
    168 				return false;
    169 			}
    170 		}
    171 
    172 		if ( ! $recursive || ! $this->is_dir( $file ) ) {
    173 			return chmod( $file, $mode );
    174 		}
    175 
    176 		// Is a directory, and we want recursive.
    177 		$file     = trailingslashit( $file );
    178 		$filelist = $this->dirlist( $file );
    179 
    180 		foreach ( (array) $filelist as $filename => $filemeta ) {
    181 			$this->chmod( $file . $filename, $mode, $recursive );
    182 		}
    183 
    184 		return true;
    185 	}
    186 
    187 	/**
    188 	 * Changes the owner of a file or directory.
    189 	 *
    190 	 * @since 2.5.0
    191 	 *
    192 	 * @param string     $file      Path to the file or directory.
    193 	 * @param string|int $owner     A user name or number.
    194 	 * @param bool       $recursive Optional. If set to true, changes file owner recursively.
    195 	 *                              Default false.
    196 	 * @return bool True on success, false on failure.
    197 	 */
    198 	public function chown( $file, $owner, $recursive = false ) {
    199 		if ( ! $this->exists( $file ) ) {
    200 			return false;
    201 		}
    202 
    203 		if ( ! $recursive ) {
    204 			return chown( $file, $owner );
    205 		}
    206 
    207 		if ( ! $this->is_dir( $file ) ) {
    208 			return chown( $file, $owner );
    209 		}
    210 
    211 		// Is a directory, and we want recursive.
    212 		$filelist = $this->dirlist( $file );
    213 
    214 		foreach ( $filelist as $filename ) {
    215 			$this->chown( $file . '/' . $filename, $owner, $recursive );
    216 		}
    217 
    218 		return true;
    219 	}
    220 
    221 	/**
    222 	 * Gets the file owner.
    223 	 *
    224 	 * @since 2.5.0
    225 	 *
    226 	 * @param string $file Path to the file.
    227 	 * @return string|false Username of the owner on success, false on failure.
    228 	 */
    229 	public function owner( $file ) {
    230 		$owneruid = @fileowner( $file );
    231 
    232 		if ( ! $owneruid ) {
    233 			return false;
    234 		}
    235 
    236 		if ( ! function_exists( 'posix_getpwuid' ) ) {
    237 			return $owneruid;
    238 		}
    239 
    240 		$ownerarray = posix_getpwuid( $owneruid );
    241 
    242 		if ( ! $ownerarray ) {
    243 			return false;
    244 		}
    245 
    246 		return $ownerarray['name'];
    247 	}
    248 
    249 	/**
    250 	 * Gets the permissions of the specified file or filepath in their octal format.
    251 	 *
    252 	 * FIXME does not handle errors in fileperms()
    253 	 *
    254 	 * @since 2.5.0
    255 	 *
    256 	 * @param string $file Path to the file.
    257 	 * @return string Mode of the file (the last 3 digits).
    258 	 */
    259 	public function getchmod( $file ) {
    260 		return substr( decoct( @fileperms( $file ) ), -3 );
    261 	}
    262 
    263 	/**
    264 	 * Gets the file's group.
    265 	 *
    266 	 * @since 2.5.0
    267 	 *
    268 	 * @param string $file Path to the file.
    269 	 * @return string|false The group on success, false on failure.
    270 	 */
    271 	public function group( $file ) {
    272 		$gid = @filegroup( $file );
    273 
    274 		if ( ! $gid ) {
    275 			return false;
    276 		}
    277 
    278 		if ( ! function_exists( 'posix_getgrgid' ) ) {
    279 			return $gid;
    280 		}
    281 
    282 		$grouparray = posix_getgrgid( $gid );
    283 
    284 		if ( ! $grouparray ) {
    285 			return false;
    286 		}
    287 
    288 		return $grouparray['name'];
    289 	}
    290 
    291 	/**
    292 	 * Copies a file.
    293 	 *
    294 	 * @since 2.5.0
    295 	 *
    296 	 * @param string    $source      Path to the source file.
    297 	 * @param string    $destination Path to the destination file.
    298 	 * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
    299 	 *                               Default false.
    300 	 * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
    301 	 *                               0755 for dirs. Default false.
    302 	 * @return bool True on success, false on failure.
    303 	 */
    304 	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
    305 		if ( ! $overwrite && $this->exists( $destination ) ) {
    306 			return false;
    307 		}
    308 
    309 		$rtval = copy( $source, $destination );
    310 
    311 		if ( $mode ) {
    312 			$this->chmod( $destination, $mode );
    313 		}
    314 
    315 		return $rtval;
    316 	}
    317 
    318 	/**
    319 	 * Moves a file.
    320 	 *
    321 	 * @since 2.5.0
    322 	 *
    323 	 * @param string $source      Path to the source file.
    324 	 * @param string $destination Path to the destination file.
    325 	 * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
    326 	 *                            Default false.
    327 	 * @return bool True on success, false on failure.
    328 	 */
    329 	public function move( $source, $destination, $overwrite = false ) {
    330 		if ( ! $overwrite && $this->exists( $destination ) ) {
    331 			return false;
    332 		}
    333 
    334 		// Try using rename first. if that fails (for example, source is read only) try copy.
    335 		if ( @rename( $source, $destination ) ) {
    336 			return true;
    337 		}
    338 
    339 		if ( $this->copy( $source, $destination, $overwrite ) && $this->exists( $destination ) ) {
    340 			$this->delete( $source );
    341 
    342 			return true;
    343 		} else {
    344 			return false;
    345 		}
    346 	}
    347 
    348 	/**
    349 	 * Deletes a file or directory.
    350 	 *
    351 	 * @since 2.5.0
    352 	 *
    353 	 * @param string       $file      Path to the file or directory.
    354 	 * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
    355 	 *                                Default false.
    356 	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
    357 	 *                                Default false.
    358 	 * @return bool True on success, false on failure.
    359 	 */
    360 	public function delete( $file, $recursive = false, $type = false ) {
    361 		if ( empty( $file ) ) {
    362 			// Some filesystems report this as /, which can cause non-expected recursive deletion of all files in the filesystem.
    363 			return false;
    364 		}
    365 
    366 		$file = str_replace( '\\', '/', $file ); // For Win32, occasional problems deleting files otherwise.
    367 
    368 		if ( 'f' === $type || $this->is_file( $file ) ) {
    369 			return @unlink( $file );
    370 		}
    371 
    372 		if ( ! $recursive && $this->is_dir( $file ) ) {
    373 			return @rmdir( $file );
    374 		}
    375 
    376 		// At this point it's a folder, and we're in recursive mode.
    377 		$file     = trailingslashit( $file );
    378 		$filelist = $this->dirlist( $file, true );
    379 
    380 		$retval = true;
    381 
    382 		if ( is_array( $filelist ) ) {
    383 			foreach ( $filelist as $filename => $fileinfo ) {
    384 				if ( ! $this->delete( $file . $filename, $recursive, $fileinfo['type'] ) ) {
    385 					$retval = false;
    386 				}
    387 			}
    388 		}
    389 
    390 		if ( file_exists( $file ) && ! @rmdir( $file ) ) {
    391 			$retval = false;
    392 		}
    393 
    394 		return $retval;
    395 	}
    396 
    397 	/**
    398 	 * Checks if a file or directory exists.
    399 	 *
    400 	 * @since 2.5.0
    401 	 *
    402 	 * @param string $file Path to file or directory.
    403 	 * @return bool Whether $file exists or not.
    404 	 */
    405 	public function exists( $file ) {
    406 		return @file_exists( $file );
    407 	}
    408 
    409 	/**
    410 	 * Checks if resource is a file.
    411 	 *
    412 	 * @since 2.5.0
    413 	 *
    414 	 * @param string $file File path.
    415 	 * @return bool Whether $file is a file.
    416 	 */
    417 	public function is_file( $file ) {
    418 		return @is_file( $file );
    419 	}
    420 
    421 	/**
    422 	 * Checks if resource is a directory.
    423 	 *
    424 	 * @since 2.5.0
    425 	 *
    426 	 * @param string $path Directory path.
    427 	 * @return bool Whether $path is a directory.
    428 	 */
    429 	public function is_dir( $path ) {
    430 		return @is_dir( $path );
    431 	}
    432 
    433 	/**
    434 	 * Checks if a file is readable.
    435 	 *
    436 	 * @since 2.5.0
    437 	 *
    438 	 * @param string $file Path to file.
    439 	 * @return bool Whether $file is readable.
    440 	 */
    441 	public function is_readable( $file ) {
    442 		return @is_readable( $file );
    443 	}
    444 
    445 	/**
    446 	 * Checks if a file or directory is writable.
    447 	 *
    448 	 * @since 2.5.0
    449 	 *
    450 	 * @param string $file Path to file or directory.
    451 	 * @return bool Whether $file is writable.
    452 	 */
    453 	public function is_writable( $file ) {
    454 		return @is_writable( $file );
    455 	}
    456 
    457 	/**
    458 	 * Gets the file's last access time.
    459 	 *
    460 	 * @since 2.5.0
    461 	 *
    462 	 * @param string $file Path to file.
    463 	 * @return int|false Unix timestamp representing last access time, false on failure.
    464 	 */
    465 	public function atime( $file ) {
    466 		return @fileatime( $file );
    467 	}
    468 
    469 	/**
    470 	 * Gets the file modification time.
    471 	 *
    472 	 * @since 2.5.0
    473 	 *
    474 	 * @param string $file Path to file.
    475 	 * @return int|false Unix timestamp representing modification time, false on failure.
    476 	 */
    477 	public function mtime( $file ) {
    478 		return @filemtime( $file );
    479 	}
    480 
    481 	/**
    482 	 * Gets the file size (in bytes).
    483 	 *
    484 	 * @since 2.5.0
    485 	 *
    486 	 * @param string $file Path to file.
    487 	 * @return int|false Size of the file in bytes on success, false on failure.
    488 	 */
    489 	public function size( $file ) {
    490 		return @filesize( $file );
    491 	}
    492 
    493 	/**
    494 	 * Sets the access and modification times of a file.
    495 	 *
    496 	 * Note: If $file doesn't exist, it will be created.
    497 	 *
    498 	 * @since 2.5.0
    499 	 *
    500 	 * @param string $file  Path to file.
    501 	 * @param int    $time  Optional. Modified time to set for file.
    502 	 *                      Default 0.
    503 	 * @param int    $atime Optional. Access time to set for file.
    504 	 *                      Default 0.
    505 	 * @return bool True on success, false on failure.
    506 	 */
    507 	public function touch( $file, $time = 0, $atime = 0 ) {
    508 		if ( 0 === $time ) {
    509 			$time = time();
    510 		}
    511 
    512 		if ( 0 === $atime ) {
    513 			$atime = time();
    514 		}
    515 
    516 		return touch( $file, $time, $atime );
    517 	}
    518 
    519 	/**
    520 	 * Creates a directory.
    521 	 *
    522 	 * @since 2.5.0
    523 	 *
    524 	 * @param string           $path  Path for new directory.
    525 	 * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
    526 	 *                                Default false.
    527 	 * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
    528 	 *                                Default false.
    529 	 * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
    530 	 *                                Default false.
    531 	 * @return bool True on success, false on failure.
    532 	 */
    533 	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
    534 		// Safe mode fails with a trailing slash under certain PHP versions.
    535 		$path = untrailingslashit( $path );
    536 
    537 		if ( empty( $path ) ) {
    538 			return false;
    539 		}
    540 
    541 		if ( ! $chmod ) {
    542 			$chmod = FS_CHMOD_DIR;
    543 		}
    544 
    545 		if ( ! @mkdir( $path ) ) {
    546 			return false;
    547 		}
    548 
    549 		$this->chmod( $path, $chmod );
    550 
    551 		if ( $chown ) {
    552 			$this->chown( $path, $chown );
    553 		}
    554 
    555 		if ( $chgrp ) {
    556 			$this->chgrp( $path, $chgrp );
    557 		}
    558 
    559 		return true;
    560 	}
    561 
    562 	/**
    563 	 * Deletes a directory.
    564 	 *
    565 	 * @since 2.5.0
    566 	 *
    567 	 * @param string $path      Path to directory.
    568 	 * @param bool   $recursive Optional. Whether to recursively remove files/directories.
    569 	 *                          Default false.
    570 	 * @return bool True on success, false on failure.
    571 	 */
    572 	public function rmdir( $path, $recursive = false ) {
    573 		return $this->delete( $path, $recursive );
    574 	}
    575 
    576 	/**
    577 	 * Gets details for files in a directory or a specific file.
    578 	 *
    579 	 * @since 2.5.0
    580 	 *
    581 	 * @param string $path           Path to directory or file.
    582 	 * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
    583 	 *                               Default true.
    584 	 * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
    585 	 *                               Default false.
    586 	 * @return array|false {
    587 	 *     Array of files. False if unable to list directory contents.
    588 	 *
    589 	 *     @type string $name        Name of the file or directory.
    590 	 *     @type string $perms       *nix representation of permissions.
    591 	 *     @type int    $permsn      Octal representation of permissions.
    592 	 *     @type string $owner       Owner name or ID.
    593 	 *     @type int    $size        Size of file in bytes.
    594 	 *     @type int    $lastmodunix Last modified unix timestamp.
    595 	 *     @type mixed  $lastmod     Last modified month (3 letter) and day (without leading 0).
    596 	 *     @type int    $time        Last modified time.
    597 	 *     @type string $type        Type of resource. 'f' for file, 'd' for directory.
    598 	 *     @type mixed  $files       If a directory and $recursive is true, contains another array of files.
    599 	 * }
    600 	 */
    601 	public function dirlist( $path, $include_hidden = true, $recursive = false ) {
    602 		if ( $this->is_file( $path ) ) {
    603 			$limit_file = basename( $path );
    604 			$path       = dirname( $path );
    605 		} else {
    606 			$limit_file = false;
    607 		}
    608 
    609 		if ( ! $this->is_dir( $path ) || ! $this->is_readable( $path ) ) {
    610 			return false;
    611 		}
    612 
    613 		$dir = dir( $path );
    614 
    615 		if ( ! $dir ) {
    616 			return false;
    617 		}
    618 
    619 		$ret = array();
    620 
    621 		while ( false !== ( $entry = $dir->read() ) ) {
    622 			$struc         = array();
    623 			$struc['name'] = $entry;
    624 
    625 			if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
    626 				continue;
    627 			}
    628 
    629 			if ( ! $include_hidden && '.' === $struc['name'][0] ) {
    630 				continue;
    631 			}
    632 
    633 			if ( $limit_file && $struc['name'] !== $limit_file ) {
    634 				continue;
    635 			}
    636 
    637 			$struc['perms']       = $this->gethchmod( $path . '/' . $entry );
    638 			$struc['permsn']      = $this->getnumchmodfromh( $struc['perms'] );
    639 			$struc['number']      = false;
    640 			$struc['owner']       = $this->owner( $path . '/' . $entry );
    641 			$struc['group']       = $this->group( $path . '/' . $entry );
    642 			$struc['size']        = $this->size( $path . '/' . $entry );
    643 			$struc['lastmodunix'] = $this->mtime( $path . '/' . $entry );
    644 			$struc['lastmod']     = gmdate( 'M j', $struc['lastmodunix'] );
    645 			$struc['time']        = gmdate( 'h:i:s', $struc['lastmodunix'] );
    646 			$struc['type']        = $this->is_dir( $path . '/' . $entry ) ? 'd' : 'f';
    647 
    648 			if ( 'd' === $struc['type'] ) {
    649 				if ( $recursive ) {
    650 					$struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive );
    651 				} else {
    652 					$struc['files'] = array();
    653 				}
    654 			}
    655 
    656 			$ret[ $struc['name'] ] = $struc;
    657 		}
    658 
    659 		$dir->close();
    660 		unset( $dir );
    661 
    662 		return $ret;
    663 	}
    664 }