| 1 |
<?php |
| 2 |
|
| 3 |
|
| 4 |
if (!defined('ABSPATH')) { |
| 5 |
exit; |
| 6 |
} |
| 7 |
|
| 8 |
/* Static functions that can be used from anywhere. */ |
| 9 |
class ABJ_404_Solution_FunctionsMBString extends ABJ_404_Solution_Functions { |
| 10 |
|
| 11 |
function ord(string $char): int { |
| 12 |
return mb_ord($char); |
| 13 |
} |
| 14 |
|
| 15 |
function strtolower(?string $string): string { |
| 16 |
if ($string === null) { |
| 17 |
return ''; |
| 18 |
} |
| 19 |
return mb_strtolower($string); |
| 20 |
} |
| 21 |
|
| 22 |
function strlen(string $string): int { |
| 23 |
return mb_strlen($string); |
| 24 |
} |
| 25 |
|
| 26 |
/** @return int|false */ |
| 27 |
function strpos(string $haystack, string $needle, int $offset = 0) { |
| 28 |
return mb_strpos($haystack, $needle, $offset); |
| 29 |
} |
| 30 |
|
| 31 |
function substr(?string $str, int $start, ?int $length = null): string { |
| 32 |
if ($str === null) { |
| 33 |
return ''; |
| 34 |
} |
| 35 |
return mb_substr($str, $start, $length); |
| 36 |
} |
| 37 |
|
| 38 |
/** |
| 39 |
* @param array<int, string>|null $regs |
| 40 |
* @return bool|int |
| 41 |
*/ |
| 42 |
function regexMatch(string $pattern, string $string, ?array &$regs = null) { |
| 43 |
return mb_ereg($pattern, $string, $regs); |
| 44 |
} |
| 45 |
|
| 46 |
/** |
| 47 |
* @param array<int, string>|null $regs |
| 48 |
* @return bool|int |
| 49 |
*/ |
| 50 |
function regexMatchi(string $pattern, string $string, ?array &$regs = null) { |
| 51 |
return mb_eregi($pattern, $string, $regs); |
| 52 |
} |
| 53 |
|
| 54 |
/** Replace regular expression with multibyte support. |
| 55 |
* Scans string for matches to pattern, then replaces the matched text with replacement. |
| 56 |
* @param string $pattern The regular expression pattern. |
| 57 |
* @param string $replacement The replacement text. |
| 58 |
* @param string $string The string being checked. |
| 59 |
* @return string The resultant string on success, or FALSE on error. |
| 60 |
*/ |
| 61 |
function regexReplace($pattern, $replacement, $string) { |
| 62 |
$result = mb_ereg_replace($pattern, $replacement, $string); |
| 63 |
return is_string($result) ? $result : $string; |
| 64 |
} |
| 65 |
|
| 66 |
/** |
| 67 |
* Sanitize invalid UTF-8 byte sequences from a string. |
| 68 |
* |
| 69 |
* This method removes or replaces invalid UTF-8 byte sequences that would cause |
| 70 |
* database errors like "Could not perform query because it contains invalid data". |
| 71 |
* |
| 72 |
* Uses mb_convert_encoding() to strip invalid UTF-8 bytes by converting from UTF-8 to UTF-8, |
| 73 |
* which automatically removes any invalid sequences. |
| 74 |
* |
| 75 |
* @param string|null $string The string to sanitize |
| 76 |
* @return string The sanitized string with only valid UTF-8 characters |
| 77 |
*/ |
| 78 |
function sanitizeInvalidUTF8(?string $string): string { |
| 79 |
// Handle null and empty cases |
| 80 |
if ($string === null || $string === '') { |
| 81 |
return ''; |
| 82 |
} |
| 83 |
|
| 84 |
// Convert to string if not already |
| 85 |
if (!is_string($string)) { |
| 86 |
$string = strval($string); |
| 87 |
} |
| 88 |
|
| 89 |
// Use mb_convert_encoding to strip invalid UTF-8 bytes |
| 90 |
// Converting from UTF-8 to UTF-8 removes invalid sequences |
| 91 |
$sanitized = mb_convert_encoding($string, 'UTF-8', 'UTF-8'); |
| 92 |
|
| 93 |
// Additional safety: remove null bytes and control characters that might cause issues |
| 94 |
// Keep only valid UTF-8 characters, removing C0 control characters except whitespace |
| 95 |
$sanitized = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/u', '', $sanitized) ?? $sanitized; |
| 96 |
|
| 97 |
return $sanitized; |
| 98 |
} |
| 99 |
|
| 100 |
} |
| 101 |
|