strlen($base) ? substr($dir, strlen($base)) : null; } /** * Folder holding job state and staging files. * * @return string */ public static function jobs_dir() { return self::dir() . '/jobs'; } /** * Folder holding in-progress uploads. * * @return string */ public static function uploads_dir() { return self::dir() . '/uploads'; } /** * Creates the folders and blocks direct web access. * * @return bool */ public static function ensure() { foreach (array(self::dir(), self::jobs_dir(), self::uploads_dir()) as $dir) { if (! is_dir($dir) && ! wp_mkdir_p($dir)) { return false; } if (! file_exists($dir . '/index.php')) { @file_put_contents($dir . '/index.php', "\nRequire all denied\n\n\nOrder allow,deny\nDeny from all\n\nOptions -Indexes\n"); } if (! file_exists($dir . '/web.config')) { @file_put_contents($dir . '/web.config', "\n\n"); } } return is_writable(self::dir()); } /** * Backups in the storage folder, newest first. * * @return array[] name, size, time. */ public static function list_backups() { $out = array(); $files = array_merge((array) glob(self::dir() . '/*' . self::EXT), (array) glob(self::dir() . '/*.wpress')); foreach ($files as $file) { if (is_file($file)) { $out[] = array( 'name' => basename($file), 'size' => (float) filesize($file), 'time' => (int) filemtime($file), ); } } usort( $out, static function ($a, $b) { return $b['time'] - $a['time']; } ); return $out; } /** * Safe absolute path to a stored backup, or false. * * @param string $name File name. * @return string|false */ public static function backup_path($name) { $name = basename((string) $name); if (! preg_match('/^[A-Za-z0-9._-]+\.(shiftbox|wpress)$/', $name)) { return false; } $path = self::dir() . '/' . $name; return is_file($path) ? $path : false; } /** * Folder where All-in-One WP Migration keeps its backups on this site. * * @return string */ public static function ai1wm_dir() { return self::content_dir() . '/ai1wm-backups'; } /** * .wpress backups made by All-in-One WP Migration on this site, newest first. * * @return array[] name, size, time. */ public static function list_ai1wm() { $out = array(); foreach ((array) glob(self::ai1wm_dir() . '/*.wpress') as $file) { if (is_file($file)) { $out[] = array( 'name' => basename($file), 'size' => (float) filesize($file), 'time' => (int) filemtime($file), ); } } usort( $out, static function ($a, $b) { return $b['time'] - $a['time']; } ); return $out; } /** * Safe path to an All-in-One WP Migration backup on this site, or false. * * @param string $name File name. * @return string|false */ public static function ai1wm_path($name) { $name = basename((string) $name); if (! preg_match('/^[A-Za-z0-9._-]+\.wpress$/', $name)) { return false; } $path = self::ai1wm_dir() . '/' . $name; return is_file($path) ? $path : false; } /** * New unguessable backup file name. * * @param string $tag Optional tag. * @return string */ public static function new_backup_name($tag = '') { /** * Filters the first part of backup file names (default: the site's host name). * * @param string $host Host name. */ $host = apply_filters('shiftbox_backup_name_prefix', (string) wp_parse_url(home_url(), PHP_URL_HOST)); $host = preg_replace('/[^A-Za-z0-9-]+/', '-', (string) $host); $tag = $tag ? '-' . sanitize_key($tag) : ''; return trim($host, '-') . $tag . '-' . gmdate('Ymd-His') . '-' . strtolower(wp_generate_password(16, false)) . self::EXT; } /** * Removes a folder recursively. * * @param string $dir Folder. * @return void */ public static function rrmdir($dir) { if (! is_dir($dir) || is_link($dir)) { if (is_link($dir) || is_file($dir)) { @unlink($dir); } return; } $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($it as $f) { if ($f->isDir() && ! $f->isLink()) { @rmdir($f->getPathname()); } else { @unlink($f->getPathname()); } } @rmdir($dir); } /** * Free disk space in bytes, or -1 when unknown. * * @return float */ public static function free_space() { if (function_exists('disk_free_space')) { $free = @disk_free_space(self::dir()); if (false !== $free) { return (float) $free; } } return -1; } /** * Moves a file or folder, falling back to copy across devices. * * @param string $from Source. * @param string $to Target. * @return bool */ public static function move($from, $to) { if (@rename($from, $to)) { return true; } if (is_dir($from)) { if (! wp_mkdir_p($to)) { return false; } $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($from, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST ); foreach ($it as $f) { $target = $to . '/' . substr($f->getPathname(), strlen($from) + 1); if ($f->isDir()) { wp_mkdir_p($target); } elseif (! @copy($f->getPathname(), $target)) { return false; } } self::rrmdir($from); return true; } if (@copy($from, $to)) { @unlink($from); return true; } return false; } }