PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.9.5
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.9.5
4.10.0 4.9.5 4.9.4 4.9.3 4.9.2 4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Backup / Utils / BackupPathResolver.php
wp-staging / Backup / Utils Last commit date
BackupPathResolver.php 1 week ago
BackupPathResolver.php
85 lines
1 <?php
2
3 namespace WPStaging\Backup\Utils;
4
5 use WPStaging\Backup\Service\BackupsFinder;
6 use WPStaging\Backup\WithBackupIdentifier;
7 use WPStaging\Framework\Filesystem\PathIdentifier;
8
9 /**
10 * Utility for resolving backup file paths securely within the backups directory.
11 */
12 class BackupPathResolver
13 {
14 use WithBackupIdentifier;
15
16 /**
17 * @var BackupsFinder
18 */
19 private $backupsFinder;
20
21 /**
22 * @var PathIdentifier
23 */
24 private $pathIdentifier;
25
26 /**
27 * @param BackupsFinder $backupsFinder
28 * @param PathIdentifier $pathIdentifier
29 */
30 public function __construct(BackupsFinder $backupsFinder, PathIdentifier $pathIdentifier)
31 {
32 $this->backupsFinder = $backupsFinder;
33 $this->pathIdentifier = $pathIdentifier;
34 }
35
36 /**
37 * Resolve a backup file path securely within the backups directory.
38 *
39 * @param string $filePath
40 * @return string Empty string if invalid, or the resolved path
41 */
42 public function resolveBackupPath(string $filePath): string
43 {
44 $backupDir = wp_normalize_path($this->backupsFinder->getBackupsDirectory());
45 $filePath = wp_normalize_path(untrailingslashit($filePath));
46
47 $relativePath = ltrim(str_replace($backupDir, '', $filePath), '/');
48 $resolvedPath = wp_normalize_path(trailingslashit($backupDir) . $relativePath);
49
50 if (!$this->pathIdentifier->isPathWithinRoot($resolvedPath, $backupDir)) {
51 return '';
52 }
53
54 $basename = wp_basename($resolvedPath);
55 $extension = strtolower(pathinfo($basename, PATHINFO_EXTENSION));
56 if (!in_array($extension, ['wpstg', 'sql'], true) && !$this->isBackupPart($basename)) {
57 return '';
58 }
59
60 return $resolvedPath;
61 }
62
63 /**
64 * @param string $partName Part name as listed in the multipart metadata.
65 * @param string $backupFilename Filename of the backup the part must belong to.
66 * @return string Empty string if invalid, or the resolved path
67 */
68 public function resolveBackupPartPath(string $partName, string $backupFilename): string
69 {
70 if ($partName === '' || $partName !== wp_basename($partName)) {
71 return '';
72 }
73
74 if (!$this->isBackupPart($partName)) {
75 return '';
76 }
77
78 if ($this->extractBackupIdFromFilename($partName) !== $this->extractBackupIdFromFilename($backupFilename)) {
79 return '';
80 }
81
82 return $this->resolveBackupPath($partName);
83 }
84 }
85