PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.11.0
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.11.0
4.11.0 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 / Framework / Traits / SerializeTrait.php
wp-staging / Framework / Traits Last commit date
ApplyFiltersTrait.php 1 day ago ArrayableTrait.php 1 day ago BatchSizeCalculateTrait.php 1 day ago BearerTokenTrait.php 1 day ago BenchmarkTrait.php 1 day ago BooleanTransientTrait.php 1 day ago DatabaseSearchReplaceTrait.php 1 day ago DbRowsGeneratorTrait.php 1 day ago DebugLogTrait.php 1 day ago DeveloperTimerTrait.php 1 day ago EndOfLinePlaceholderTrait.php 1 day ago EventLoggerTrait.php 1 day ago FileScanToCacheTrait.php 1 day ago FormatTrait.php 1 day ago HttpRequestTrait.php 1 day ago HydrateTrait.php 1 day ago I18nTrait.php 1 day ago IpResolverTrait.php 1 day ago JobResponseTrait.php 1 day ago MaintenanceTrait.php 7 months ago MemoryExhaustTrait.php 1 day ago MySQLRowsGeneratorTrait.php 1 day ago NoticesTrait.php 1 day ago PagesTrait.php 1 day ago PropertyConstructor.php 1 day ago RenameTmpDirectoryTrait.php 1 day ago ResourceTrait.php 1 day ago RestRequestTrait.php 1 day ago RestoreFileExclusionTrait.php 1 day ago SafeFileInfoTrait.php 1 day ago SerializeTrait.php 1 day ago SetTimeLimitTrait.php 1 day ago SlashTrait.php 1 day ago SqlCommentTrait.php 1 day ago TablePrefixValidator.php 5 months ago UrlTrait.php 1 day ago ValueGetterTrait.php 1 day ago WindowsOsTrait.php 1 day ago
SerializeTrait.php
163 lines
1 <?php
2
3 namespace WPStaging\Framework\Traits;
4
5 use __PHP_Incomplete_Class;
6
7 trait SerializeTrait
8 {
9
10
11
12
13
14
15 protected function safeMaybeUnserialize($data, array $allowedClasses = [], &$rejected = false)
16 {
17 $rejected = false;
18
19 if (!is_string($data) || !$this->isSerialized($data)) {
20 return $data;
21 }
22
23 $data = trim($data);
24 $failedToParse = false;
25 $value = $this->unserializeQuietly($data, $allowedClasses, $failedToParse);
26
27 if ($value === false && $failedToParse) {
28 $rejected = true;
29 return false;
30 }
31
32 if ($this->containsForbiddenClass($value)) {
33 $rejected = true;
34 return false;
35 }
36
37 return $value;
38 }
39
40
41
42
43
44
45
46 private function unserializeQuietly(string $data, array $allowedClasses, &$failed = false)
47 {
48 $failed = false;
49
50 set_error_handler(function () use (&$failed) {
51 $failed = true;
52 return true;
53 });
54
55 try {
56 return unserialize($data, ['allowed_classes' => $allowedClasses]);
57 } finally {
58 restore_error_handler();
59 }
60 }
61
62
63
64
65
66
67 protected function containsForbiddenClass($value, int $remainingDepth = 20): bool
68 {
69 if ($value instanceof __PHP_Incomplete_Class) {
70 return true;
71 }
72
73 if (is_object($value)) {
74 $value = (array)$value;
75 }
76
77 if (!is_array($value)) {
78 return false;
79 }
80
81 if ($remainingDepth < 1) {
82 return true;
83 }
84
85 foreach ($value as $item) {
86 if ($this->containsForbiddenClass($item, $remainingDepth - 1)) {
87 return true;
88 }
89 }
90
91 return false;
92 }
93
94
95
96
97
98 protected function isSerialized(string $data, bool $strict = true): bool
99 {
100 if (!is_string($data)) {
101 return false;
102 }
103
104 $data = trim($data);
105 if ($data === 'N;') {
106 return true;
107 }
108
109 if (strlen($data) < 4) {
110 return false;
111 }
112
113 if ($data[1] !== ':') {
114 return false;
115 }
116
117 if ($strict) {
118 $lastc = substr($data, -1);
119 if ($lastc !== ';' && $lastc !== '}') {
120 return false;
121 }
122 } else {
123 $semicolon = strpos($data, ';');
124 $brace = strpos($data, '}');
125 if ($semicolon === false && $brace === false) {
126 return false;
127 }
128
129 if ($semicolon !== false && $semicolon < 3) {
130 return false;
131 }
132
133 if ($brace !== false && $brace < 4) {
134 return false;
135 }
136 }
137
138 $token = $data[0];
139 switch ($token) {
140 case 's':
141 if ($strict) {
142 if ('"' !== substr($data, -2, 1)) {
143 return false;
144 }
145 } elseif (function_exists('str_contains') && !str_contains($data, '"') || strpos($data, '"') === false) {
146 return false;
147 }
148
149 case 'a':
150 case 'O':
151 case 'E':
152 return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
153 case 'b':
154 case 'i':
155 case 'd':
156 $end = $strict ? '$' : '';
157 return (bool) preg_match("/^{$token}:[0-9.E+-]+;$end/", $data);
158 }
159
160 return false;
161 }
162 }
163