PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13
1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 All 211 releases
← All changes | includes/public/charitable-template-helpers.php +71 -7 1.8.12.1 → 1.8.13 View file →
@@ -8,9 +8,9 @@
8 8 * @author David Bisset
9 9 * @copyright Copyright (c) 2023, WP Charitable LLC
10 10 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11 11 * @since 1.0.0
12 - * @version 1.8.9.1
12 + * @version 1.8.13
13 13 */
14 14
15 15 // Exit if accessed directly.
16 16 if ( ! defined( 'ABSPATH' ) ) {
@@ -275,13 +275,54 @@
275 275 return apply_filters( 'charitable_is_main_loop', $is_main_loop );
276 276 }
277 277
278 278 /**
279 + * Re-encodes a raw query string so that every key and value is percent-encoded.
280 + *
281 + * The query string arrives from the request untrusted and unencoded. Rebuilding it
282 + * pair by pair guarantees the result contains no character that could break out of
283 + * the HTML attribute, JavaScript string or URL context it is later printed into --
284 + * including HTML entities such as `'` that survive esc_url() and are decoded
285 + * back into a quote by the browser's HTML parser.
286 + *
287 + * Query strings are application/x-www-form-urlencoded, so urldecode()/urlencode()
288 + * is the correct pair here: it round-trips `+` as a space the way the request did.
289 + *
290 + * @since 1.8.13
291 + *
292 + * @param string $query_string Raw query string, without the leading '?'.
293 + * @return string Re-encoded query string, or an empty string if nothing usable remains.
294 + */
295 +function charitable_sanitize_query_string( $query_string ) {
296 + $pairs = array();
297 +
298 + foreach ( explode( '&', (string) $query_string ) as $pair ) {
299 + if ( '' === $pair ) {
300 + continue;
301 + }
302 +
303 + $parts = explode( '=', $pair, 2 );
304 + $key = urlencode( urldecode( $parts[0] ) );
305 +
306 + if ( '' === $key ) {
307 + continue;
308 + }
309 +
310 + $pairs[] = isset( $parts[1] ) ? $key . '=' . urlencode( urldecode( $parts[1] ) ) : $key;
311 + }
312 +
313 + return implode( '&', $pairs );
314 +}
315 +
316 +/**
279 317 * Returns the current URL.
280 318 *
281 319 * @see https://gist.github.com/leereamsnyder/fac3b9ccb6b99ab14f36
282 320 *
283 321 * @since 1.0.0
322 + * @since 1.8.13 The path and query string are both percent-encoded instead of being
323 + * reflected raw, and the trailing slash is applied to the path rather
324 + * than to the end of the query string.
284 325 *
285 326 * @global WP $wp
286 327 * @return string
287 328 */
@@ -287,15 +328,38 @@
287 328 */
288 329 function charitable_get_current_url() {
289 330 global $wp;
290 331
291 - return trailingslashit(
292 - add_query_arg(
293 - array_key_exists( 'QUERY_STRING', $_SERVER ) ? $_SERVER['QUERY_STRING'] : '', // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
294 - '',
295 - home_url( $wp->request )
296 - )
332 + $path = isset( $wp->request ) ? (string) $wp->request : '';
333 +
334 + /*
335 + * The requested path is reflected here too, and WordPress hands it over exactly as
336 + * it arrived: any %XX escapes are already inert, but characters that arrived
337 + * literally are not. Encoding '&' closes off every HTML entity form at once
338 + * (', ', ', ", ...), which is what a URL escaper cannot do
339 + * because those entities are made of characters it considers legal; the quotes and
340 + * angle brackets cover the literal cases. Only these five are touched, so existing
341 + * %XX escapes and ordinary slugs pass through unchanged and the result is idempotent.
342 + */
343 + $path = str_replace(
344 + array( '&', "'", '"', '<', '>' ),
345 + array( '%26', '%27', '%22', '%3C', '%3E' ),
346 + $path
297 347 );
348 +
349 + $url = trailingslashit( home_url( $path ) );
350 +
351 + if ( empty( $_SERVER['QUERY_STRING'] ) ) {
352 + return $url;
353 + }
354 +
355 + $query_string = charitable_sanitize_query_string( wp_unslash( $_SERVER['QUERY_STRING'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
356 +
357 + if ( '' === $query_string ) {
358 + return $url;
359 + }
360 +
361 + return $url . '?' . $query_string;
298 362 }
299 363
300 364 /**
301 365 * Returns the URL to which the user should be redirected after signing on or registering an account.