getPathname(); if (strpos($path_source, $source) !== 0) { continue; } if ($exclude_regexp && preg_match($exclude_regexp, $path_source)) { continue; } $path_destination = $destination . substr($path_source, strlen($source)); if ($path->isDir()) { $status = self::isDirectory($path_destination) || self::createDirectory($path_destination, $path->getPerms()); if (!$status) { return false; } } else { $status = self::copy($path_source, $path_destination, $path->getPerms()); if (!$status) { return false; } } } return true; } /** * Move a directory. * * @param string $source * @param string $destination * @return bool */ public static function moveDirectory($source, $destination) { return self::move($source, $destination); } /** * Delete a directory recursively. * * @param string $dirname * @param bool $delete_self (optional) * @return bool */ public static function deleteDirectory($dirname, $delete_self = true) { $dirname = rtrim($dirname, '/\\'); if (!self::exists($dirname)) { return false; } if (!self::isDirectory($dirname)) { trigger_error('Delete target is not a directory: ' . $dirname, \E_USER_WARNING); return false; } $rdi_options = \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS; $rii_options = \RecursiveIteratorIterator::CHILD_FIRST; $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dirname, $rdi_options), $rii_options); foreach ($iterator as $path) { if ($path->isDir()) { if (!@rmdir($path->getPathname())) { trigger_error('Cannot delete directory: ' . $path->getPathname(), \E_USER_WARNING); return false; } } else { if (!@unlink($path->getPathname())) { trigger_error('Cannot delete file: ' . $path->getPathname(), \E_USER_WARNING); return false; } } } if ($delete_self) { $result = @rmdir($dirname); if (!$result) { trigger_error('Cannot delete directory: ' . $dirname, \E_USER_WARNING); return false; } else { return true; } } else { return true; } } /** * Delete a directory only if it is empty. * * @param string $dirname * @param bool $delete_empty_parents (optional) * @return bool */ public static function deleteEmptyDirectory($dirname, $delete_empty_parents = false) { $dirname = rtrim($dirname, '/\\'); if (!self::isDirectory($dirname) || !self::isEmptyDirectory($dirname)) { return false; } $result = @rmdir($dirname); if (!$result) { return false; } else { if ($delete_empty_parents) { self::deleteEmptyDirectory(dirname($dirname), true); } return true; } } /** * Get the current umask. * * @return int */ public static function getUmask() { if (self::$_umask === null) { self::$_umask = intval(config('file.umask'), 8) ?: 0; } return self::$_umask; } /** * Set the current umask. * * @param int $umask * @return void */ public static function setUmask($umask) { self::$_umask = intval($umask); } /** * Determine the best umask for this installation of Rhymix. * * @return string */ public static function recommendUmask() { // On Windows, set the umask to 0000. if (\RX_WINDOWS) { return '0000'; } // Get the UID of the owner of the current file. $file_uid = fileowner(__FILE__); // Get the UID of the current PHP process. $php_uid = self::getServerUID(); // If both UIDs are the same, set the umask to 0022. if ($file_uid == $php_uid) { return '0022'; } // Otherwise, set the umask to 0000. else { return '0000'; } } /** * Get the UID of the server process. * * @return int|false */ public static function getServerUID() { if (function_exists('posix_geteuid')) { return posix_geteuid(); } else { $testfile = \RX_BASEDIR . 'files/cache/uidcheck_' . time(); if (self::exists($testfile)) { self::delete($testfile); } if (self::write($testfile, 'TEST')) { $uid = fileowner($testfile); self::delete($testfile); return $uid; } else { return false; } } } /** * Obtain an exclusive lock. * * @return bool */ public static function getLock($name) { $name = str_replace('.', '%2E', rawurlencode($name)); if (isset(self::$_locks[$name])) { return false; } $lockdir = \RX_BASEDIR . 'files/locks'; if (!self::isDirectory($lockdir) && !self::createDirectory($lockdir)) { return false; } self::$_locks[$name] = @fopen($lockdir . '/' . $name . '.lock', 'w'); if (!self::$_locks[$name]) { unset(self::$_locks[$name]); return false; } $result = @flock(self::$_locks[$name], \LOCK_EX | \LOCK_NB); if (!$result) { @fclose(self::$_locks[$name]); unset(self::$_locks[$name]); return false; } register_shutdown_function('\\Rhymix\\Framework\\Storage::clearLocks'); return true; } /** * Clear all locks. * * @return void */ public static function clearLocks() { foreach (self::$_locks as $name => $lock) { @flock($lock, \LOCK_UN); @fclose($lock); @unlink(\RX_BASEDIR . 'files/locks/' . $name . '.lock'); unset(self::$_locks[$name]); } } }