PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.9.4
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.9.4
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 / Service / BackupMetadataReader.php
wp-staging / Backup / Service Last commit date
Compression 5 months ago Database 1 month ago AbstractBackupsFinder.php 1 year ago AbstractExtractor.php 3 weeks ago AbstractServiceProvider.php 2 years ago Archiver.php 1 month ago BackupAssets.php 2 months ago BackupContent.php 1 year ago BackupMetadataEditor.php 1 year ago BackupMetadataReader.php 6 months ago BackupSigner.php 7 months ago BackupsDirectoryResolver.php 1 month ago BackupsFinder.php 1 month ago Extractor.php 1 month ago FileBackupService.php 3 weeks ago FileBackupServiceProvider.php 2 years ago ServiceInterface.php 2 years ago TmpBackupCleaner.php 1 month ago ZlibCompressor.php 1 year ago
BackupMetadataReader.php
115 lines
1 <?php
2
3 namespace WPStaging\Backup\Service;
4
5 use WPStaging\Framework\Filesystem\FileObject;
6
7 class BackupMetadataReader
8 {
9 /** @var string */
10 const FILTER_MAX_BACKUP_METADATA_SIZE = 'wpstg_max_backup_metadata_size';
11
12 /** @var int */
13 private $existingMetadataPosition;
14
15 /** @var FileObject */
16 private $fileObject;
17
18 public function __construct(FileObject $fileObject)
19 {
20 $this->fileObject = $fileObject;
21 }
22
23 /**
24 * @return array The backup metadata array
25 * @throws \RuntimeException
26 */
27 public function readBackupMetadata(): array
28 {
29 // Default max size 128KB for backup metadata
30 $maxBackupMetadataSize = $this->getExpectedMaxBackupMetadataSize();
31 // Make sure the max size is never above 1MB
32 $negativeOffset = min($maxBackupMetadataSize, 1 * MB_IN_BYTES);
33 // Make sure the max size is never below 32KB
34 $negativeOffset = max($negativeOffset, 32 * KB_IN_BYTES);
35
36 // Set the pointer to the end of the file, minus the negative offset for which to start looking for the backup metadata.
37 $this->fileObject->fseek(max($this->fileObject->getSize() - $negativeOffset, 0), SEEK_SET);
38
39 $backupMetadata = null;
40
41 do {
42 $this->existingMetadataPosition = $this->fileObject->ftell();
43 $line = trim($this->fileObject->readAndMoveNext());
44 if ($this->isValidMetadata($line)) {
45 $backupMetadata = $this->extractMetadata($line);
46 }
47 } while ($this->fileObject->valid() && !is_array($backupMetadata));
48
49 if (!is_array($backupMetadata)) {
50 $error = sprintf('Could not find metadata in the backup file %s - This file could be corrupt.', $this->fileObject->getFilename());
51 throw new \RuntimeException($error);
52 }
53
54 return $backupMetadata;
55 }
56
57 public function extractMetadata(string $line): array
58 {
59 $json = [];
60 if (!$this->fileObject->isSqlFile()) {
61 $json = json_decode($line, true);
62 } else {
63 $json = json_decode(substr($line, 3), true);
64 }
65
66 return empty($json) ? [] : $json;
67 }
68
69 /**
70 * @param string $line
71 * @return bool
72 */
73 public function isValidMetadata(string $line): bool
74 {
75 if ($this->fileObject->isSqlFile() && substr($line, 3, 1) !== '{') {
76 return false;
77 } elseif (!$this->fileObject->isSqlFile() && substr($line, 0, 1) !== '{') {
78 return false;
79 }
80
81 $maybeMetadata = $this->extractMetadata($line);
82
83 if (!is_array($maybeMetadata) || !array_key_exists('networks', $maybeMetadata) || !is_array($maybeMetadata['networks'])) {
84 return false;
85 }
86
87 // We only have one network, pop it to check for blogs.
88 $network = array_pop($maybeMetadata['networks']);
89 if (!is_array($network) || !array_key_exists('blogs', $network) || !is_array($network['blogs'])) {
90 return false;
91 }
92
93 return true;
94 }
95
96 public function getExistingMetadataPosition(): int
97 {
98 if ($this->existingMetadataPosition === null) {
99 $this->readBackupMetadata();
100 }
101
102 return $this->existingMetadataPosition;
103 }
104
105 private function getExpectedMaxBackupMetadataSize(): int
106 {
107 $maxBackupMetadataSize = 128 * KB_IN_BYTES;
108 if (!function_exists('apply_filters')) {
109 return $maxBackupMetadataSize;
110 }
111
112 return apply_filters(self::FILTER_MAX_BACKUP_METADATA_SIZE, $maxBackupMetadataSize);
113 }
114 }
115