ensure_dir($dir);
return $dir;
}
public function work_dir(): string
{
$dir = $this->base_dir() . '/tmp';
$this->ensure_dir($dir);
return $dir;
}
public function job_dir(string $job_id): string
{
$dir = $this->work_dir() . '/' . preg_replace('/[^a-z0-9]/', '', strtolower($job_id));
$this->ensure_dir($dir);
return $dir;
}
public function ensure_dir(string $dir): void
{
if (!is_dir($dir)) {
wp_mkdir_p($dir);
}
$this->protect($dir);
}
public function protect(string $dir): void
{
$files = [
'.htaccess' => "# seljeBackup: deny all web access\n\n Require all denied\n\n\n Order allow,deny\n Deny from all\n\n",
'web.config' => "\n\n \n \n \n \n \n\n",
'index.php' => " '',
];
foreach ($files as $name => $content) {
$path = $dir . '/' . $name;
if (!file_exists($path) && is_dir($dir) && wp_is_writable($dir)) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
@file_put_contents($path, $content);
}
}
}
public function rrmdir(string $dir): void
{
if ($dir === '' || !is_dir($dir) || strpos(self::normalize($dir), $this->base_dir()) !== 0) {
return;
}
$items = @scandir($dir);
if (!is_array($items)) {
return;
}
foreach ($items as $item) {
if ($item === '.' || $item === '..') {
continue;
}
$path = $dir . '/' . $item;
if (is_dir($path) && !is_link($path)) {
$this->rrmdir($path);
} else {
wp_delete_file($path);
}
}
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir
@rmdir($dir);
}
public function free_space(string $dir): ?float
{
if (!function_exists('disk_free_space')) {
return null;
}
$free = @disk_free_space($dir);
return $free === false ? null : (float)$free;
}
/**
* Short, filesystem-safe name of this site used in backup file names, e.g. "example-com".
*/
public static function site_slug(): string
{
$host = (string)wp_parse_url(home_url(), PHP_URL_HOST);
$path = (string)wp_parse_url(home_url(), PHP_URL_PATH);
$slug = sanitize_title($host . $path);
return $slug !== '' ? substr($slug, 0, 60) : 'wordpress';
}
public static function normalize(string $path): string
{
$path = str_replace('\\', '/', $path);
return (string)preg_replace('#/+#', '/', $path);
}
/**
* Resolve a backup file name to its absolute path, refusing anything outside the backup folder.
*/
public function backup_file_path(string $name): ?string
{
if ($name === '' || $name !== basename($name) || strpos($name, '..') !== false) {
return null;
}
$path = $this->base_dir() . '/' . $name;
return is_file($path) ? $path : null;
}
}