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 / Framework / Utils / Sanitize.php
wp-staging / Framework / Utils Last commit date
Cache 7 months ago DBPermissions.php 9 months ago DataEncoder.php 10 months ago DatabaseOptions.php 2 weeks ago Escape.php 9 months ago Glob.php 2 years ago Hooks.php 2 months ago Math.php 9 months ago PluginInfo.php 5 months ago Sanitize.php 2 months ago ServerVars.php 2 years ago SlashMode.php 5 years ago Strings.php 7 months ago Times.php 5 months ago Urls.php 2 weeks ago Version.php 1 year ago WpDefaultDirectories.php 2 years ago
Sanitize.php
410 lines
1 <?php
2
3 namespace WPStaging\Framework\Utils;
4
5 use WPStaging\Core\WPStaging;
6
7 /**
8 * Sanitizes user input for safe use across the application
9 *
10 * Provides various sanitization methods for strings, integers, booleans,
11 * emails, paths, arrays, and CLI-specific inputs like domains, table prefixes,
12 * and license keys.
13 */
14 class Sanitize
15 {
16 protected $config = [];
17
18 /**
19 * Sanitize a string value.
20 *
21 * Applies HTML special characters encoding and trimming.
22 * For arrays or objects, returns empty string to prevent security issues.
23 *
24 * Examples:
25 * sanitizeString('<script>') // Returns: '&lt;script&gt;'
26 * sanitizeString(123) // Returns: '123'
27 * sanitizeString(['text']) // Returns: '' (empty string)
28 * sanitizeString($obj) // Returns: '' (empty string)
29 *
30 * @param mixed $value The value to sanitize (should be string or scalar)
31 * @return string The sanitized string, or empty string for non-scalar values
32 */
33 public function sanitizeString($value)
34 {
35 if (is_array($value) || is_object($value)) {
36 return '';
37 }
38
39 return trim(htmlspecialchars($value));
40 }
41
42 /**
43 * @param string $password
44 * @return string
45 */
46 public function sanitizePassword($password)
47 {
48 if (!is_string($password)) {
49 return '';
50 }
51
52 return trim(stripslashes($password));
53 }
54
55 /**
56 * Sanitize PEM-encoded credential content (SSH keys, certificates).
57 * Strips NUL bytes, control characters (except newlines/carriage returns),
58 * and normalises line endings while preserving the PEM structure.
59 *
60 * @param mixed $value
61 * @return string
62 */
63 public function sanitizeCredentialContent($value)
64 {
65 if (!is_string($value) || $value === '') {
66 return '';
67 }
68
69 // Strip NUL bytes
70 $value = str_replace("\0", '', $value);
71
72 // Strip control characters except \n, \r, \t
73 $value = preg_replace('/[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $value);
74
75 // Normalise line endings to LF
76 $value = str_replace(["\r\n", "\r"], "\n", $value);
77
78 return trim($value);
79 }
80
81 /**
82 * Sanitize a remote file path to prevent directory traversal.
83 * Collapses ".." and "." segments to prevent escaping the intended base directory.
84 *
85 * @param string $path
86 * @return string
87 */
88 public function sanitizeRemotePath($path)
89 {
90 if (!is_string($path)) {
91 return '';
92 }
93
94 // Normalise separators
95 $path = str_replace('\\', '/', $path);
96
97 $isAbsolute = strpos($path, '/') === 0;
98
99 $parts = explode('/', $path);
100 $resolved = [];
101
102 foreach ($parts as $part) {
103 if ($part === '' || $part === '.') {
104 continue;
105 }
106
107 if ($part === '..') {
108 if (!empty($resolved)) {
109 array_pop($resolved);
110 }
111
112 continue;
113 }
114
115 $resolved[] = $part;
116 }
117
118 $sanitized = implode('/', $resolved);
119 return $isAbsolute ? '/' . $sanitized : $sanitized;
120 }
121
122 /**
123 * Sanitize integer. Optionally use abs flag.
124 *
125 * @param int|string $value
126 * @param bool $useAbsValue
127 * @return int
128 */
129 public function sanitizeInt($value, $useAbsValue = false)
130 {
131 $integer = filter_var($value, FILTER_VALIDATE_INT);
132 if ($useAbsValue) {
133 return absint($integer);
134 }
135
136 return $integer;
137 }
138
139 /**
140 * @param int|bool|string $value
141 * @return bool
142 */
143 public function sanitizeBool($value)
144 {
145 // FILTER_VALIDATE_BOOL is alias of FILTER_VALIDATE_BOOLEAN and was introduced in PHP 8.0 but php.net say that we use the BOOL variant,
146 // See if we should use like this or just use the BOOLEAN variant?
147 return filter_var($value, defined('FILTER_VALIDATE_BOOL') ? FILTER_VALIDATE_BOOL : FILTER_VALIDATE_BOOLEAN);
148 }
149
150 /**
151 * @param string $value
152 * @return string
153 */
154 public function sanitizeEmail($value): string
155 {
156 return filter_var($value, FILTER_VALIDATE_EMAIL) ? $value : '';
157 }
158
159 /**
160 * Sanitize the path, remove spaces and trailing slashes.
161 *
162 * @param string $value
163 * @return string|false returns false if $value is an array or object
164 */
165 public function sanitizePath($value)
166 {
167 if (is_array($value) || is_object($value)) {
168 return false;
169 }
170
171 $value = $this->sanitizeString($value);
172
173 // Remove trailing slashes.
174 $path = rtrim($value, '/\\');
175
176 // To support network path on windows.
177 if (WPStaging::isWindowsOs()) {
178 return $path;
179 }
180
181 // Remove whitespace and spaces but not for macos
182 if (!WPStaging::isMacOs()) {
183 $path = preg_replace('/\s+/', '', $path);
184 }
185
186 // Convert all invalid slashes to one single forward slash
187 $replacements = [
188 '//' => '/',
189 ];
190
191 return strtr($path, $replacements);
192 }
193
194 /**
195 * Html decode and then sanitize.
196 *
197 * @param string $text
198 * @return string
199 */
200 public function htmlDecodeAndSanitize($text)
201 {
202 return sanitize_text_field(html_entity_decode($text));
203 }
204
205 /**
206 * @param array $file
207 * @param array
208 */
209 public function sanitizeFileUpload($file)
210 {
211 if (!is_array($file)) {
212 return;
213 }
214
215 if (!isset($file['tmp_name'])) {
216 return;
217 }
218
219 return $file;
220 }
221
222 /**
223 * @param array|string $htmlPost
224 * @return array
225 */
226 public function sanitizeExcludeRules($htmlPost)
227 {
228 if (is_object($htmlPost)) {
229 return [];
230 }
231
232 $decoded = wpstg_urldecode($htmlPost);
233
234 if (!is_array($decoded)) {
235 $items = explode(',', $decoded);
236 } else {
237 $items = $decoded;
238 }
239
240 $sanitized = [];
241 foreach ($items as $item) {
242 $sanitized[] = $this->sanitizeString($item);
243 }
244
245 return $sanitized;
246 }
247
248 /**
249 * @param array $items
250 * @return array
251 */
252 public function sanitizeArrayInt($items)
253 {
254 // Early bail if not array
255 if (!is_array($items) || empty($items)) {
256 return [];
257 }
258
259 $sanitized = [];
260 foreach ($items as $item) {
261 $sanitized[] = $this->sanitizeInt($item);
262 }
263
264 return $sanitized;
265 }
266
267 /**
268 * Sanitize an array of strings, with support for multidimensional arrays.
269 *
270 * Applies sanitizeString to each element of the array. For nested arrays,
271 * recursively sanitizes while preserving the array structure.
272 *
273 * Examples:
274 * sanitizeArrayString(['text', '<script>']) // Returns: ['text', '&lt;script&gt;']
275 * sanitizeArrayString([['a', 'b'], ['c']]) // Returns: [['a', 'b'], ['c']]
276 *
277 * @param array<mixed> $items
278 * @return array<int|string, mixed>
279 */
280 public function sanitizeArrayString($items)
281 {
282 if (!is_array($items) || empty($items)) {
283 return [];
284 }
285
286 $sanitized = [];
287 foreach ($items as $key => $item) {
288 if (is_array($item)) {
289 $sanitized[$key] = $this->sanitizeArrayString($item);
290 } else {
291 $sanitized[$key] = $this->sanitizeString($item);
292 }
293 }
294
295 return $sanitized;
296 }
297
298 /**
299 * @param array $items
300 * @param array $config An array that defines the expected type of a key,e.g. ['thisIsAbooleanValue' => true, 'thisShouldBeAnInteger' => int]
301 * @return array
302 */
303 public function sanitizeArray($items, $config = [])
304 {
305 // Early bail if not array
306 if (!is_array($items) || empty($items)) {
307 return [];
308 }
309
310 $sanitized = [];
311 if (!is_array($config) || empty($config)) {
312 $config = $this->config;
313 } else {
314 $this->config = $config;
315 }
316
317 foreach ($items as $key => $value) {
318 $sanitized[$key] = isset($config[$key]) ?
319 $this->sanitizeCall($value, $config[$key]) :
320 (is_array($value) ? $this->sanitizeArrayString($value) : $this->sanitizeString($value));
321 }
322
323 return $sanitized;
324 }
325
326 /**
327 * @param string $text
328 * @return string
329 */
330 public function decodeBase64AndSanitize($text)
331 {
332 return $this->sanitizeString(base64_decode($text));
333 }
334
335 /**
336 * @param int|bool|string|array $value
337 * @param string $method
338 * @return int|bool|string|array
339 */
340 protected function sanitizeCall($value, $method)
341 {
342 $methodName = 'sanitize' . ucfirst($method);
343 if (!method_exists($this, $methodName)) {
344 return $this->sanitizeString($value);
345 }
346
347 return $this->{$methodName}($value);
348 }
349
350 /**
351 * Wrapper for sanitize_url and esc_url_raw.
352 *
353 * @param string $url
354 * @param string[] $protocols Optional. An array of acceptable protocols.
355 * @return string
356 */
357 public function sanitizeUrl($url, $protocols = null)
358 {
359 return esc_url($url, $protocols, 'db');
360 }
361
362 /**
363 * Sanitize a domain name for safe use in CLI commands.
364 * Only allows alphanumeric characters, dots, and hyphens.
365 *
366 * @param string $domain
367 * @return string
368 */
369 public function sanitizeDomainForCli($domain)
370 {
371 if (!is_string($domain)) {
372 return '';
373 }
374
375 return preg_replace('/[^a-zA-Z0-9.\-]/', '', $domain);
376 }
377
378 /**
379 * Sanitize a database table prefix for safe use in CLI commands.
380 * Only allows alphanumeric characters and underscores.
381 *
382 * @param string $prefix
383 * @return string
384 */
385 public function sanitizeTablePrefixForCli($prefix)
386 {
387 if (!is_string($prefix)) {
388 return '';
389 }
390
391 return preg_replace('/[^a-zA-Z0-9_]/', '', $prefix);
392 }
393
394 /**
395 * Sanitize a license key for safe use in CLI commands.
396 * Only allows alphanumeric characters and hyphens.
397 *
398 * @param string $licenseKey
399 * @return string
400 */
401 public function sanitizeLicenseKeyForCli($licenseKey)
402 {
403 if (!is_string($licenseKey)) {
404 return '';
405 }
406
407 return preg_replace('/[^a-zA-Z0-9\-]/', '', $licenseKey);
408 }
409 }
410