PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.9.2
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.9.2
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 4 months ago Database 2 weeks ago AbstractBackupsFinder.php 1 year ago AbstractExtractor.php 1 day ago AbstractServiceProvider.php 2 years ago Archiver.php 2 weeks ago BackupAssets.php 1 month ago BackupContent.php 1 year ago BackupMetadataEditor.php 1 year ago BackupMetadataReader.php 5 months ago BackupSigner.php 7 months ago BackupsDirectoryResolver.php 2 weeks ago BackupsFinder.php 2 weeks ago Extractor.php 2 weeks ago FileBackupService.php 1 day ago FileBackupServiceProvider.php 2 years ago ServiceInterface.php 2 years ago TmpBackupCleaner.php 2 weeks ago ZlibCompressor.php 11 months 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