X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/dc1231b7312fbdca99e9e887cc2bb35a28f85cdc..refs/tags/wordpress-4.4:/wp-includes/formatting.php
diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php
index 640e136f..ff4167d2 100644
--- a/wp-includes/formatting.php
+++ b/wp-includes/formatting.php
@@ -216,63 +216,31 @@ function wptexturize( $text, $reset = false ) {
// Look for shortcodes and HTML elements.
- $tagnames = array_keys( $shortcode_tags );
- $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) );
- $tagregexp = "(?:$tagregexp)(?![\\w-])"; // Excerpt of get_shortcode_regex().
-
- $comment_regex =
- '!' // Start of comment, after the <.
- . '(?:' // Unroll the loop: Consume everything until --> is found.
- . '-(?!->)' // Dash not followed by end of comment.
- . '[^\-]*+' // Consume non-dashes.
- . ')*+' // Loop possessively.
- . '(?:-->)?'; // End of comment. If not found, match all input.
-
- $shortcode_regex =
- '\[' // Find start of shortcode.
- . '[\/\[]?' // Shortcodes may begin with [/ or [[
- . $tagregexp // Only match registered shortcodes, because performance.
- . '(?:'
- . '[^\[\]<>]+' // Shortcodes do not contain other shortcodes. Quantifier critical.
- . '|'
- . '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >.
- . ')*+' // Possessive critical.
- . '\]' // Find end of shortcode.
- . '\]?'; // Shortcodes may end with ]]
-
- $regex =
- '/(' // Capture the entire match.
- . '<' // Find start of element.
- . '(?(?=!--)' // Is this a comment?
- . $comment_regex // Find end of comment.
- . '|'
- . '[^>]*>' // Find end of element.
- . ')'
- . '|'
- . $shortcode_regex // Find shortcodes.
- . ')/s';
+ preg_match_all( '@\[/?([^<>&/\[\]\x00-\x20]++)@', $text, $matches );
+ $tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
+ $found_shortcodes = ! empty( $tagnames );
+ $shortcode_regex = $found_shortcodes ? _get_wptexturize_shortcode_regex( $tagnames ) : '';
+ $regex = _get_wptexturize_split_regex( $shortcode_regex );
$textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
foreach ( $textarr as &$curl ) {
// Only call _wptexturize_pushpop_element if $curl is a delimiter.
$first = $curl[0];
- if ( '<' === $first && ' is found.
+ . '-(?!->)' // Dash not followed by end of comment.
+ . '[^\-]*+' // Consume non-dashes.
+ . ')*+' // Loop possessively.
+ . '(?:-->)?'; // End of comment. If not found, match all input.
+
+ $html_regex = // Needs replaced with wp_html_split() per Shortcode API Roadmap.
+ '<' // Find start of element.
+ . '(?(?=!--)' // Is this a comment?
+ . $comment_regex // Find end of comment.
+ . '|'
+ . '[^>]*>?' // Find end of element. If not found, match all input.
+ . ')';
+ }
+
+ if ( empty( $shortcode_regex ) ) {
+ $regex = '/(' . $html_regex . ')/';
+ } else {
+ $regex = '/(' . $html_regex . '|' . $shortcode_regex . ')/';
+ }
+
+ return $regex;
+}
+
+/**
+ * Retrieve the regular expression for shortcodes.
+ *
+ * @access private
+ * @ignore
+ * @internal This function will be removed in 4.5.0 per Shortcode API Roadmap.
+ * @since 4.4.0
+ *
+ * @param array $tagnames List of shortcodes to find.
+ * @return string The regular expression
+ */
+function _get_wptexturize_shortcode_regex( $tagnames ) {
+ $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) );
+ $tagregexp = "(?:$tagregexp)(?=[\\s\\]\\/])"; // Excerpt of get_shortcode_regex().
+ $regex =
+ '\[' // Find start of shortcode.
+ . '[\/\[]?' // Shortcodes may begin with [/ or [[
+ . $tagregexp // Only match registered shortcodes, because performance.
+ . '(?:'
+ . '[^\[\]<>]+' // Shortcodes do not contain other shortcodes. Quantifier critical.
+ . '|'
+ . '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >.
+ . ')*+' // Possessive critical.
+ . '\]' // Find end of shortcode.
+ . '\]?'; // Shortcodes may end with ]]
+
+ return $regex;
}
/**
@@ -669,7 +727,7 @@ function wp_replace_in_html_tags( $haystack, $replace_pairs ) {
// Extract $needle and $replace.
foreach ( $replace_pairs as $needle => $replace );
- // Loop through delimeters (elements) only.
+ // Loop through delimiters (elements) only.
for ( $i = 1, $c = count( $textarr ); $i < $c; $i += 2 ) {
if ( false !== strpos( $textarr[$i], $needle ) ) {
$textarr[$i] = str_replace( $needle, $replace, $textarr[$i] );
@@ -680,7 +738,7 @@ function wp_replace_in_html_tags( $haystack, $replace_pairs ) {
// Extract all $needles.
$needles = array_keys( $replace_pairs );
- // Loop through delimeters (elements) only.
+ // Loop through delimiters (elements) only.
for ( $i = 1, $c = count( $textarr ); $i < $c; $i += 2 ) {
foreach ( $needles as $needle ) {
if ( false !== strpos( $textarr[$i], $needle ) ) {
@@ -765,7 +823,7 @@ function shortcode_unautop( $pee ) {
. ')'
. '(?:' . $spaces . ')*+' // optional trailing whitespace
. '<\\/p>' // closing paragraph
- . '/s';
+ . '/';
return preg_replace( $pattern, '$1', $pee );
}
@@ -816,10 +874,14 @@ function seems_utf8( $str ) {
*
* @staticvar string $_charset
*
- * @param string $string The text which is to be encoded.
- * @param int $quote_style Optional. Converts double quotes if set to ENT_COMPAT, both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. Also compatible with old values; converting single quotes if set to 'single', double if set to 'double' or both if otherwise set. Default is ENT_NOQUOTES.
- * @param string $charset Optional. The character encoding of the string. Default is false.
- * @param bool $double_encode Optional. Whether to encode existing html entities. Default is false.
+ * @param string $string The text which is to be encoded.
+ * @param int|string $quote_style Optional. Converts double quotes if set to ENT_COMPAT,
+ * both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES.
+ * Also compatible with old values; converting single quotes if set to 'single',
+ * double if set to 'double' or both if otherwise set.
+ * Default is ENT_NOQUOTES.
+ * @param string $charset Optional. The character encoding of the string. Default is false.
+ * @param bool $double_encode Optional. Whether to encode existing html entities. Default is false.
* @return string The encoded text with HTML entities.
*/
function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) {
@@ -1307,7 +1369,7 @@ function remove_accents( $string ) {
*/
function sanitize_file_name( $filename ) {
$filename_raw = $filename;
- $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", chr(0));
+ $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0));
/**
* Filter the list of characters to remove from a filename.
*
@@ -1596,9 +1658,9 @@ function sanitize_html_class( $class, $fallback = '' ) {
//Limit to A-Z,a-z,0-9,_,-
$sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $sanitized );
- if ( '' == $sanitized )
- $sanitized = $fallback;
-
+ if ( '' == $sanitized && $fallback ) {
+ return sanitize_html_class( $fallback );
+ }
/**
* Filter a sanitized HTML class string.
*
@@ -1839,12 +1901,15 @@ function force_balance_tags( $text ) {
* it is simply a holder for the 'format_to_edit' filter.
*
* @since 0.71
+ * @since 4.4.0 The `$richedit` parameter was renamed to `$rich_text` for clarity.
*
- * @param string $content The text about to be edited.
- * @param bool $richedit Whether the $content should not pass through htmlspecialchars(). Default false (meaning it will be passed).
+ * @param string $content The text about to be edited.
+ * @param bool $rich_text Optional. Whether `$content` should be considered rich text,
+ * in which case it would not be passed through esc_textarea().
+ * Default false.
* @return string The text after the filter (and possibly htmlspecialchars()) has been run.
*/
-function format_to_edit( $content, $richedit = false ) {
+function format_to_edit( $content, $rich_text = false ) {
/**
* Filter the text to be formatted for editing.
*
@@ -1853,7 +1918,7 @@ function format_to_edit( $content, $richedit = false ) {
* @param string $content The text, prior to formatting for editing.
*/
$content = apply_filters( 'format_to_edit', $content );
- if ( ! $richedit )
+ if ( ! $rich_text )
$content = esc_textarea( $content );
return $content;
}
@@ -1945,10 +2010,7 @@ function addslashes_gpc($gpc) {
}
/**
- * Navigates through an array and removes slashes from the values.
- *
- * If an array is passed, the array_map() function causes a callback to pass the
- * value back to the function. The slashes from this value will removed.
+ * Navigates through an array, object, or scalar, and removes slashes from the values.
*
* @since 2.0.0
*
@@ -1956,43 +2018,55 @@ function addslashes_gpc($gpc) {
* @return mixed Stripped value.
*/
function stripslashes_deep( $value ) {
- if ( is_array($value) ) {
- $value = array_map('stripslashes_deep', $value);
- } elseif ( is_object($value) ) {
- $vars = get_object_vars( $value );
- foreach ($vars as $key=>$data) {
- $value->{$key} = stripslashes_deep( $data );
- }
- } elseif ( is_string( $value ) ) {
- $value = stripslashes($value);
- }
-
- return $value;
+ return map_deep( $value, 'stripslashes_from_strings_only' );
}
/**
- * Navigates through an array and encodes the values to be used in a URL.
+ * Callback function for `stripslashes_deep()` which strips slashes from strings.
*
+ * @since 4.4.0
+ *
+ * @param mixed $value The array or string to be stripped.
+ * @return mixed $value The stripped value.
+ */
+function stripslashes_from_strings_only( $value ) {
+ return is_string( $value ) ? stripslashes( $value ) : $value;
+}
+
+/**
+ * Navigates through an array, object, or scalar, and encodes the values to be used in a URL.
*
* @since 2.2.0
*
- * @param array|string $value The array or string to be encoded.
- * @return array|string $value The encoded array (or string from the callback).
+ * @param mixed $value The array or string to be encoded.
+ * @return mixed $value The encoded value.
*/
function urlencode_deep( $value ) {
- return is_array( $value ) ? array_map( 'urlencode_deep', $value ) : urlencode( $value );
+ return map_deep( $value, 'urlencode' );
}
/**
- * Navigates through an array and raw encodes the values to be used in a URL.
+ * Navigates through an array, object, or scalar, and raw-encodes the values to be used in a URL.
*
* @since 3.4.0
*
- * @param array|string $value The array or string to be encoded.
- * @return array|string $value The encoded array (or string from the callback).
+ * @param mixed $value The array or string to be encoded.
+ * @return mixed $value The encoded value.
*/
function rawurlencode_deep( $value ) {
- return is_array( $value ) ? array_map( 'rawurlencode_deep', $value ) : rawurlencode( $value );
+ return map_deep( $value, 'rawurlencode' );
+}
+
+/**
+ * Navigates through an array, object, or scalar, and decodes URL-encoded values
+ *
+ * @since 4.4.0
+ *
+ * @param mixed $value The array or string to be decoded.
+ * @return mixed $value The decoded value.
+ */
+function urldecode_deep( $value ) {
+ return map_deep( $value, 'urldecode' );
}
/**
@@ -2073,15 +2147,17 @@ function _make_web_ftp_clickable_cb( $matches ) {
$ret = '';
$dest = $matches[2];
$dest = 'http://' . $dest;
- $dest = esc_url($dest);
- if ( empty($dest) )
- return $matches[0];
// removed trailing [.,;:)] from URL
if ( in_array( substr($dest, -1), array('.', ',', ';', ':', ')') ) === true ) {
$ret = substr($dest, -1);
$dest = substr($dest, 0, strlen($dest)-1);
}
+
+ $dest = esc_url($dest);
+ if ( empty($dest) )
+ return $matches[0];
+
return $matches[1] . "$dest$ret";
}
@@ -2255,8 +2331,23 @@ function wp_rel_nofollow( $text ) {
*/
function wp_rel_nofollow_callback( $matches ) {
$text = $matches[1];
- $text = str_replace(array(' rel="nofollow"', " rel='nofollow'"), '', $text);
- return "";
+ $atts = shortcode_parse_atts( $matches[1] );
+ $rel = 'nofollow';
+ if ( ! empty( $atts['rel'] ) ) {
+ $parts = array_map( 'trim', explode( ' ', $atts['rel'] ) );
+ if ( false === array_search( 'nofollow', $parts ) ) {
+ $parts[] = 'nofollow';
+ }
+ $rel = implode( ' ', $parts );
+ unset( $atts['rel'] );
+
+ $html = '';
+ foreach ( $atts as $name => $value ) {
+ $html .= "{$name}=\"$value\" ";
+ }
+ $text = trim( $html );
+ }
+ return "";
}
/**
@@ -2385,7 +2476,6 @@ function is_email( $email, $deprecated = false ) {
*
* @param bool $is_email Whether the email address has passed the is_email() checks. Default false.
* @param string $email The email address being checked.
- * @param string $message An explanatory message to the user.
* @param string $context Context under which the email was tested.
*/
return apply_filters( 'is_email', false, $email, 'email_too_short' );
@@ -2498,13 +2588,19 @@ function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) {
$tz = get_option( 'timezone_string' );
if ( $tz ) {
$datetime = date_create( $string, new DateTimeZone( $tz ) );
- if ( ! $datetime )
+ if ( ! $datetime ) {
return gmdate( $format, 0 );
+ }
$datetime->setTimezone( new DateTimeZone( 'UTC' ) );
$string_gmt = $datetime->format( $format );
} else {
- if ( ! preg_match( '#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches ) )
- return gmdate( $format, 0 );
+ if ( ! preg_match( '#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches ) ) {
+ $datetime = strtotime( $string );
+ if ( false === $datetime ) {
+ return gmdate( $format, 0 );
+ }
+ return gmdate( $format, $datetime );
+ }
$string_time = gmmktime( $matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1] );
$string_gmt = gmdate( $format, $string_time - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
}
@@ -2749,13 +2845,13 @@ function human_time_diff( $from, $to = '' ) {
if ( $days <= 1 )
$days = 1;
$since = sprintf( _n( '%s day', '%s days', $days ), $days );
- } elseif ( $diff < 30 * DAY_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) {
+ } elseif ( $diff < MONTH_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) {
$weeks = round( $diff / WEEK_IN_SECONDS );
if ( $weeks <= 1 )
$weeks = 1;
$since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks );
- } elseif ( $diff < YEAR_IN_SECONDS && $diff >= 30 * DAY_IN_SECONDS ) {
- $months = round( $diff / ( 30 * DAY_IN_SECONDS ) );
+ } elseif ( $diff < YEAR_IN_SECONDS && $diff >= MONTH_IN_SECONDS ) {
+ $months = round( $diff / MONTH_IN_SECONDS );
if ( $months <= 1 )
$months = 1;
$since = sprintf( _n( '%s month', '%s months', $months ), $months );
@@ -3242,7 +3338,7 @@ function _deep_replace( $search, $subject ) {
*
* @since 2.8.0
*
- * @global wpdb $wpdb
+ * @global wpdb $wpdb WordPress database abstraction object.
*
* @param string|array $data Unescaped data
* @return string|array Escaped data
@@ -3272,14 +3368,22 @@ function esc_url( $url, $protocols = null, $_context = 'display' ) {
if ( '' == $url )
return $url;
- $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
+
+ $url = str_replace( ' ', '%20', $url );
+ $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url);
+
+ if ( '' === $url ) {
+ return $url;
+ }
+
if ( 0 !== stripos( $url, 'mailto:' ) ) {
$strip = array('%0d', '%0a', '%0D', '%0A');
$url = _deep_replace($strip, $url);
}
+
$url = str_replace(';//', '://', $url);
/* If the URL doesn't appear to contain a scheme, we
- * presume it needs http:// appended (unless a relative
+ * presume it needs http:// prepended (unless a relative
* link starting with /, # or ? or a php file).
*/
if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) &&
@@ -3293,6 +3397,43 @@ function esc_url( $url, $protocols = null, $_context = 'display' ) {
$url = str_replace( "'", ''', $url );
}
+ if ( ( false !== strpos( $url, '[' ) ) || ( false !== strpos( $url, ']' ) ) ) {
+
+ $parsed = wp_parse_url( $url );
+ $front = '';
+
+ if ( isset( $parsed['scheme'] ) ) {
+ $front .= $parsed['scheme'] . '://';
+ } elseif ( '/' === $url[0] ) {
+ $front .= '//';
+ }
+
+ if ( isset( $parsed['user'] ) ) {
+ $front .= $parsed['user'];
+ }
+
+ if ( isset( $parsed['pass'] ) ) {
+ $front .= ':' . $parsed['pass'];
+ }
+
+ if ( isset( $parsed['user'] ) || isset( $parsed['pass'] ) ) {
+ $front .= '@';
+ }
+
+ if ( isset( $parsed['host'] ) ) {
+ $front .= $parsed['host'];
+ }
+
+ if ( isset( $parsed['port'] ) ) {
+ $front .= ':' . $parsed['port'];
+ }
+
+ $end_dirty = str_replace( $front, '', $url );
+ $end_clean = str_replace( array( '[', ']' ), array( '%5B', '%5D' ), $end_dirty );
+ $url = str_replace( $end_dirty, $end_clean, $url );
+
+ }
+
if ( '/' === $url[0] ) {
$good_protocol_url = $url;
} else {
@@ -3481,7 +3622,7 @@ function tag_escape( $tag_name ) {
* @return string Absolute path.
*/
function wp_make_link_relative( $link ) {
- return preg_replace( '|^(https?:)?//[^/]+(/.*)|i', '$2', $link );
+ return preg_replace( '|^(https?:)?//[^/]+(/?.*)|i', '$2', $link );
}
/**
@@ -3492,7 +3633,7 @@ function wp_make_link_relative( $link ) {
*
* @since 2.0.5
*
- * @global wpdb $wpdb
+ * @global wpdb $wpdb WordPress database abstraction object.
*
* @param string $option The name of the option.
* @param string $value The unsanitised value.
@@ -3522,6 +3663,8 @@ function sanitize_option( $option, $value ) {
case 'thumbnail_size_h':
case 'medium_size_w':
case 'medium_size_h':
+ case 'medium_large_size_w':
+ case 'medium_large_size_h':
case 'large_size_w':
case 'large_size_h':
case 'mailserver_port':
@@ -3737,6 +3880,28 @@ function sanitize_option( $option, $value ) {
return apply_filters( "sanitize_option_{$option}", $value, $option, $original_value );
}
+/**
+ * Maps a function to all non-iterable elements of an array or an object.
+ *
+ * This is similar to `array_walk_recursive()` but acts upon objects too.
+ *
+ * @since 4.4.0
+ *
+ * @param mixed $value The array, object, or scalar.
+ * @param callable $callback The function to map onto $value.
+ * @return The value with the callback applied to all non-arrays and non-objects inside it.
+ */
+function map_deep( $value, $callback ) {
+ if ( is_array( $value ) || is_object( $value ) ) {
+ foreach ( $value as &$item ) {
+ $item = map_deep( $item, $callback );
+ }
+ return $value;
+ } else {
+ return call_user_func( $callback, $value );
+ }
+}
+
/**
* Parses a string into variables to be stored in an array.
*
@@ -3985,7 +4150,7 @@ function _links_add_base( $m ) {
return $m[1] . '=' . $m[2] .
( preg_match( '#^(\w{1,20}):#', $m[3], $protocol ) && in_array( $protocol[1], wp_allowed_protocols() ) ?
$m[3] :
- WP_HTTP::make_absolute_url( $m[3], $_links_add_base )
+ WP_Http::make_absolute_url( $m[3], $_links_add_base )
)
. $m[2];
}
@@ -4406,7 +4571,7 @@ function print_emoji_detection_script() {
?>
$length ) {
+ $short_url = substr( $short_url, 0, $length - 3 ) . '…';
+ }
+ return $short_url;
+}
\ No newline at end of file