PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.16.6
GiveWP – Donation Plugin and Fundraising Platform v4.16.6
4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / src / Helpers / Utils.php
give / src / Helpers Last commit date
Form 6 months ago Frontend 2 years ago Gateways 4 years ago ArrayDataSet.php 1 year ago Call.php 3 years ago Date.php 4 years ago EnqueueScript.php 4 years ago Hooks.php 4 years ago Html.php 4 years ago IntlTelInput.php 4 weeks ago Language.php 9 months ago Table.php 4 years ago Utils.php 5 days ago
Utils.php
284 lines
1 <?php
2
3 namespace Give\Helpers;
4
5 /**
6 * Class Utils
7 *
8 * @package Give\Helpers
9 */
10 class Utils
11 {
12 /**
13 * Extract query param from URL
14 *
15 * @since 2.7.0
16 *
17 * @param string $url
18 * @param string $queryParamName
19 * @param mixed $default
20 *
21 * @return string
22 */
23 public static function getQueryParamFromURL($url, $queryParamName, $default = '')
24 {
25 $queryArgs = wp_parse_args(parse_url($url, PHP_URL_QUERY));
26
27 return isset($queryArgs[$queryParamName]) ? give_clean($queryArgs[$queryParamName]) : $default;
28 }
29
30 /**
31 * This function will change request url with other url.
32 *
33 * @since 4.2.0 Replace URL anchor with request_anchor argument
34 * @since 2.7.0
35 *
36 * @param string $location Requested URL.
37 * @param string $url URL.
38 * @param array $removeArgs Remove extra query params.
39 * @param array $addArgs add extra query params.
40 *
41 * @return string
42 */
43 public static function switchRequestedURL($location, $url, $addArgs = [], $removeArgs = [])
44 {
45 $urlAnchor = '';
46
47 if (strpos($url, '#') !== false) {
48 [$url, $urlAnchor] = explode('#', $url, 2);
49 }
50
51 $queryString = [];
52
53 if (($index = strpos($location, '?')) !== false) {
54 $queryString = wp_parse_args(substr($location, $index + 1));
55 }
56
57 if (($index = strpos($url, '?')) !== false) {
58 $queryString = array_merge(
59 $queryString,
60 wp_parse_args(substr($url, $index + 1))
61 );
62 $url = substr($url, 0, $index);
63 }
64
65 $url = add_query_arg($queryString, $url);
66
67 foreach ((array) $removeArgs as $name) {
68 $url = add_query_arg([$name => false], $url);
69 }
70
71 foreach ((array) $addArgs as $name => $value) {
72 $url = add_query_arg([$name => $value], $url);
73 }
74
75 if (!empty($urlAnchor)) {
76 $url = add_query_arg('request_anchor', $urlAnchor, $url);
77 }
78
79 return esc_url_raw($url);
80 }
81
82 /**
83 * Remove giveDonationAction from URL.
84 *
85 * @since 2.7.0
86 *
87 * @param $url
88 *
89 * @return string
90 */
91 public static function removeDonationAction($url)
92 {
93 return esc_url_raw( add_query_arg(['giveDonationAction' => false], $url) );
94 }
95
96 /**
97 * Determines whether a plugin is active.
98 *
99 * Only plugins installed in the plugins/ folder can be active.
100 *
101 * Plugins in the mu-plugins/ folder can't be "activated," so this function will
102 * return false for those plugins.
103 *
104 * For more information on this and similar theme functions, check out
105 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
106 * Conditional Tags} article in the Theme Developer Handbook.
107 *
108 * @since 2.7.0
109 *
110 * @param string $plugin Path to the plugin file relative to the plugins directory.
111 *
112 * @return bool True, if in the active plugins list. False, not in the list.
113 */
114 public static function isPluginActive($plugin)
115 {
116 if ( ! function_exists('is_plugin_active')) {
117 include_once ABSPATH . 'wp-admin/includes/plugin.php';
118 }
119
120 return is_plugin_active($plugin);
121 }
122
123 /**
124 * @since 3.17.2
125 */
126 public static function removeBackslashes($data)
127 {
128 /**
129 * The stripslashes_deep() method removes only the first backslash occurrence from
130 * a given string, so we are using the ltrim() method to make sure we are removing
131 * all other occurrences. We need to remove these backslashes from the beginner of
132 * the input because attackers can use them to bypass the is_serialized() check.
133 */
134 $data = stripslashes_deep($data);
135 $data = is_string($data) ? ltrim($data, '\\') : $data;
136
137 return $data;
138 }
139
140 /**
141 * Decode strings recursively to prevent double (or more) encoded strings
142 *
143 * @since 3.19.4
144 */
145 public static function recursiveUrlDecode(string $data): string
146 {
147 $decoded = urldecode($data);
148
149 return $decoded === $data ? $data : self::recursiveUrlDecode($decoded);
150 }
151
152 /**
153 * The regular expression attempts to capture the basic structure of all data types that can be serialized by PHP.
154 *
155 * @since 3.19.4 Decode the string and remove any character not allowed in a serialized string
156 * @since 3.19.3 Support all types of serialized data instead of only objects and arrays
157 * @since 3.17.2
158 */
159 public static function containsSerializedDataRegex($data): bool
160 {
161 if ( ! is_string($data)) {
162 return false;
163 }
164
165 $data = self::recursiveUrlDecode($data);
166
167 /**
168 * This regular expression removes any special character that is not:
169 * a Letter (a-zA-Z), number (0-9), or any of the characters {}, :, ;, ", ', ., [, ], (, ), ,
170 */
171 $data = preg_replace('/[^a-zA-Z0-9:{};"\'.\[\](),]/', '', $data);
172
173 $pattern = '/
174 (a:\d+:\{.*}) | # Matches arrays (e.g: a:2:{i:0;s:5:"hello";i:1;i:42;})
175 (O:\d+:"[^"]+":\{.*}) | # Matches objects (e.g: O:8:"stdClass":1:{s:4:"name";s:5:"James";})
176 (s:\d+:"[^"]*";) | # Matches strings (e.g: s:5:"hello";)
177 (i:\d+;) | # Matches integers (e.g: i:42;)
178 (b:[01];) | # Matches booleans (e.g: b:1; or b:0;)
179 (d:\d+(\.\d+)?;) | # Matches floats (e.g: d:3.14;)
180 (N;) # Matches NULL (e.g: N;)
181 /x';
182
183 return preg_match($pattern, $data) === 1;
184 }
185
186 /**
187 * @since 3.17.2
188 */
189 public static function isSerialized($data): bool
190 {
191 $data = self::removeBackslashes($data);
192
193 if (is_serialized($data) || self::containsSerializedDataRegex($data)) {
194 return true;
195 }
196
197 return false;
198 }
199
200 /**
201 * @since 3.17.2
202 */
203 public static function safeUnserialize($data)
204 {
205 $data = self::removeBackslashes($data);
206
207 /**
208 * We are setting the allowed_classes to false as a default to
209 * prevent the injection of objects that can run unwished code.
210 *
211 * From PHP docs:
212 * allowed_classes - Either an array of class names which should be accepted, false to accept no classes, or
213 * true to accept all classes. If this option is defined and unserialize() encounters an object of a class
214 * that isn't to be accepted, then the object will be instantiated as __PHP_Incomplete_Class instead. Omitting
215 * this option is the same as defining it as true: PHP will attempt to instantiate objects of any class.
216 */
217 $unserializedData = @unserialize(trim($data), ['allowed_classes' => false]);
218
219 /**
220 * Never return objects, not even as __PHP_Incomplete_Class instances. When a
221 * __PHP_Incomplete_Class is serialized again, PHP writes the original class bytes
222 * back, so returning it would re-arm the payload for the next unrestricted
223 * unserialize() call (e.g. the donation session storage). In that case, we return
224 * the data as a plain string instead, keeping it inert.
225 *
226 * @since 4.16.6
227 */
228 if (self::containsPhpIncompleteClass($unserializedData)) {
229 return $data;
230 }
231
232 /*
233 * In case the passed string is not unserializeable, false is returned.
234 *
235 * @see https://www.php.net/manual/en/function.unserialize.php
236 */
237
238 return ! $unserializedData && ! self::containsSerializedDataRegex($data) ? $data : $unserializedData;
239 }
240
241 /**
242 * Recursively checks if the given data contains any __PHP_Incomplete_Class instance,
243 * which is what unserialize() produces for classes not present in allowed_classes.
244 *
245 * @since 4.16.6
246 *
247 * @param mixed $data Data to check, can be any type.
248 *
249 * @return bool True if a __PHP_Incomplete_Class instance is found at any nesting level.
250 */
251 public static function containsPhpIncompleteClass($data): bool
252 {
253 if ($data instanceof \__PHP_Incomplete_Class) {
254 return true;
255 }
256
257 if (is_array($data) || is_object($data)) {
258 foreach ((array)$data as $value) {
259 if (self::containsPhpIncompleteClass($value)) {
260 return true;
261 }
262 }
263 }
264
265 return false;
266 }
267
268 /**
269 * Avoid insecure usage of `unserialize` when the data could be submitted by the user.
270 *
271 * @since 3.16.1
272 *
273 * @param string $data Data that might be unserialized.
274 *
275 * @return mixed Unserialized data can be any type.
276 */
277 public static function maybeSafeUnserialize($data)
278 {
279 return self::isSerialized($data)
280 ? self::safeUnserialize($data)
281 : $data;
282 }
283 }
284