PluginProbe
404 Solution / trunk
404 Solution vtrunk
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / core / RegexHelper.php

RegexHelper.php in 404 Solution trunk, at includes/core/RegexHelper.php

112 lines 4.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3
4 if (!defined('ABSPATH')) {
5 exit;
6 }
7
8 /**
9 * Polymorphic regex service.
10 *
11 * Owns the three regex primitives the plugin needs across hosts with and
12 * without the PHP mbstring extension, plus the urlLooksLikeRegex URL
13 * classifier. Two concrete implementations live alongside this base class:
14 *
15 * - ABJ_404_Solution_RegexHelperMb - uses mb_ereg / mb_eregi / mb_ereg_replace
16 * - ABJ_404_Solution_RegexHelperPreg - uses native preg_match / preg_replace
17 *
18 * Choose Mb when the mbstring extension is loaded; otherwise Preg. The Preg
19 * variant is also used directly by callers that intentionally want PCRE
20 * regex semantics regardless of host mbstring availability (e.g. SQL
21 * placeholder rewrites that use \d / lookarounds, which mb_ereg's POSIX
22 * syntax cannot express).
23 *
24 * Extracted from ABJ_404_Solution_MbStringAdapter per design-audit-2026-06-02
25 * M201 (parent task i802, this task i826). The adapter previously carried
26 * both byte/multibyte string primitives and regex primitives in the same
27 * interface; splitting regex off lets callers depend on the smaller surface
28 * they actually need.
29 */
30 abstract class ABJ_404_Solution_RegexHelper {
31
32 /**
33 * Regex match. Mb implementations use POSIX (mb_ereg) syntax; Preg
34 * implementations use PCRE syntax (without delimiters - the helper
35 * supplies them). Callers that intentionally rely on PCRE shorthand
36 * classes (\d, \w, lookarounds, etc.) MUST use the Preg helper
37 * directly, not the polymorphic one.
38 *
39 * @param string $pattern
40 * @param string $string
41 * @param array<int, string>|null $regs
42 * @return bool|int
43 */
44 abstract public function regexMatch(string $pattern, string $string, ?array &$regs = null);
45
46 /**
47 * Case-insensitive regex match. Same syntax caveat as regexMatch().
48 *
49 * @param string $pattern
50 * @param string $string
51 * @param array<int, string>|null $regs
52 * @return bool|int
53 */
54 abstract public function regexMatchi(string $pattern, string $string, ?array &$regs = null);
55
56 /**
57 * Regex replace. Same syntax caveat as regexMatch().
58 *
59 * @param string $pattern
60 * @param string $replacement
61 * @param string $string
62 * @return string|null
63 */
64 abstract public function regexReplace($pattern, $replacement, $string);
65
66 /**
67 * Check whether a URL appears to contain regex syntax.
68 *
69 * This is a PCRE-pattern URL classifier used to warn users when a
70 * redirect URL looks like it contains regex syntax but is not marked
71 * as a regex redirect. Implementation is PCRE-only by definition (the
72 * patterns it scans for are PCRE constructs like \d, \w, lookarounds,
73 * etc.), so the same concrete method serves both Mb and Preg variants
74 * - it is not polymorphic.
75 *
76 * @param string|null $url
77 * @return bool true if the URL appears to contain regex patterns
78 */
79 public function urlLooksLikeRegex($url) {
80 if ($url === null || $url === '' || !is_string($url)) {
81 return false;
82 }
83
84 $regexIndicators = array(
85 '/\(\.\*\)/', // (.*) - common capture-all pattern
86 '/\(\.\+\)/', // (.+) - one or more of anything
87 '/\(\?\:/', // (?: - non-capturing group
88 '/\(\?=/', // (?= - positive lookahead
89 '/\(\?!/', // (?! - negative lookahead
90 '/\[\^[^\]]+\]/', // [^...] - negated character class
91 '/\[[a-z]-[a-z]\]/i', // [a-z] or [A-Z] - character range
92 '/\[[0-9]-[0-9]\]/', // [0-9] - digit range
93 '/\\\\d/', // \d - digit shorthand
94 '/\\\\w/', // \w - word character shorthand
95 '/\\\\s/', // \s - whitespace shorthand
96 '/\.\*/', // .* - match anything (greedy)
97 '/\.\+/', // .+ - match one or more of anything
98 '/\.\?/', // .? - match zero or one of anything
99 '/\{\d+,?\d*\}/', // {n} or {n,} or {n,m} - quantifiers
100 '/\|/', // | - alternation
101 );
102
103 foreach ($regexIndicators as $pattern) {
104 if (preg_match($pattern, $url)) {
105 return true;
106 }
107 }
108
109 return false;
110 }
111 }
112