changeset 5 | 5e2f62d02dcd |
parent 0 | d970ebf37754 |
child 7 | cf61fcea0001 |
4:346c88efed21 | 5:5e2f62d02dcd |
---|---|
9 |
9 |
10 /** |
10 /** |
11 * Replaces common plain text characters into formatted entities |
11 * Replaces common plain text characters into formatted entities |
12 * |
12 * |
13 * As an example, |
13 * As an example, |
14 * <code> |
14 * |
15 * 'cause today's effort makes it worth tomorrow's "holiday"... |
15 * 'cause today's effort makes it worth tomorrow's "holiday" ... |
16 * </code> |
16 * |
17 * Becomes: |
17 * Becomes: |
18 * <code> |
18 * |
19 * ’cause today’s effort makes it worth tomorrow’s “holiday”… |
19 * ’cause today’s effort makes it worth tomorrow’s “holiday” … |
20 * </code> |
20 * |
21 * Code within certain html blocks are skipped. |
21 * Code within certain html blocks are skipped. |
22 * |
22 * |
23 * @since 0.71 |
23 * @since 0.71 |
24 * @uses $wp_cockneyreplace Array of formatted entities for certain common phrases |
24 * @uses $wp_cockneyreplace Array of formatted entities for certain common phrases |
25 * |
25 * |
26 * @param string $text The text to be formatted |
26 * @param string $text The text to be formatted |
27 * @param bool $reset Set to true for unit testing. Translated patterns will reset. |
|
27 * @return string The string replaced with html entities |
28 * @return string The string replaced with html entities |
28 */ |
29 */ |
29 function wptexturize($text) { |
30 function wptexturize($text, $reset = false) { |
30 global $wp_cockneyreplace; |
31 global $wp_cockneyreplace, $shortcode_tags; |
31 static $static_characters, $static_replacements, $dynamic_characters, $dynamic_replacements, |
32 static $static_characters, $static_replacements, $dynamic_characters, $dynamic_replacements, |
32 $default_no_texturize_tags, $default_no_texturize_shortcodes; |
33 $default_no_texturize_tags, $default_no_texturize_shortcodes, $run_texturize = true; |
33 |
34 |
34 // No need to set up these static variables more than once |
35 // If there's nothing to do, just stop. |
35 if ( ! isset( $static_characters ) ) { |
36 if ( empty( $text ) || false === $run_texturize ) { |
37 return $text; |
|
38 } |
|
39 |
|
40 // Set up static variables. Run once only. |
|
41 if ( $reset || ! isset( $static_characters ) ) { |
|
42 /** |
|
43 * Filter whether to skip running wptexturize(). |
|
44 * |
|
45 * Passing false to the filter will effectively short-circuit wptexturize(). |
|
46 * returning the original text passed to the function instead. |
|
47 * |
|
48 * The filter runs only once, the first time wptexturize() is called. |
|
49 * |
|
50 * @since 4.0.0 |
|
51 * |
|
52 * @see wptexturize() |
|
53 * |
|
54 * @param bool $run_texturize Whether to short-circuit wptexturize(). |
|
55 */ |
|
56 $run_texturize = apply_filters( 'run_wptexturize', $run_texturize ); |
|
57 if ( false === $run_texturize ) { |
|
58 return $text; |
|
59 } |
|
60 |
|
36 /* translators: opening curly double quote */ |
61 /* translators: opening curly double quote */ |
37 $opening_quote = _x( '“', 'opening curly double quote' ); |
62 $opening_quote = _x( '“', 'opening curly double quote' ); |
38 /* translators: closing curly double quote */ |
63 /* translators: closing curly double quote */ |
39 $closing_quote = _x( '”', 'closing curly double quote' ); |
64 $closing_quote = _x( '”', 'closing curly double quote' ); |
40 |
65 |
59 $default_no_texturize_tags = array('pre', 'code', 'kbd', 'style', 'script', 'tt'); |
84 $default_no_texturize_tags = array('pre', 'code', 'kbd', 'style', 'script', 'tt'); |
60 $default_no_texturize_shortcodes = array('code'); |
85 $default_no_texturize_shortcodes = array('code'); |
61 |
86 |
62 // if a plugin has provided an autocorrect array, use it |
87 // if a plugin has provided an autocorrect array, use it |
63 if ( isset($wp_cockneyreplace) ) { |
88 if ( isset($wp_cockneyreplace) ) { |
64 $cockney = array_keys($wp_cockneyreplace); |
89 $cockney = array_keys( $wp_cockneyreplace ); |
65 $cockneyreplace = array_values($wp_cockneyreplace); |
90 $cockneyreplace = array_values( $wp_cockneyreplace ); |
66 } elseif ( "'" != $apos ) { // Only bother if we're doing a replacement. |
91 } elseif ( "'" != $apos ) { // Only bother if we're doing a replacement. |
67 $cockney = array( "'tain't", "'twere", "'twas", "'tis", "'twill", "'til", "'bout", "'nuff", "'round", "'cause" ); |
92 $cockney = array( "'tain't", "'twere", "'twas", "'tis", "'twill", "'til", "'bout", "'nuff", "'round", "'cause", "'em" ); |
68 $cockneyreplace = array( $apos . "tain" . $apos . "t", $apos . "twere", $apos . "twas", $apos . "tis", $apos . "twill", $apos . "til", $apos . "bout", $apos . "nuff", $apos . "round", $apos . "cause" ); |
93 $cockneyreplace = array( $apos . "tain" . $apos . "t", $apos . "twere", $apos . "twas", $apos . "tis", $apos . "twill", $apos . "til", $apos . "bout", $apos . "nuff", $apos . "round", $apos . "cause", $apos . "em" ); |
69 } else { |
94 } else { |
70 $cockney = $cockneyreplace = array(); |
95 $cockney = $cockneyreplace = array(); |
71 } |
96 } |
72 |
97 |
73 $static_characters = array_merge( array( '---', ' -- ', '--', ' - ', 'xn–', '...', '``', '\'\'', ' (tm)' ), $cockney ); |
98 $static_characters = array_merge( array( '...', '``', '\'\'', ' (tm)' ), $cockney ); |
74 $static_replacements = array_merge( array( $em_dash, ' ' . $em_dash . ' ', $en_dash, ' ' . $en_dash . ' ', 'xn--', '…', $opening_quote, $closing_quote, ' ™' ), $cockneyreplace ); |
99 $static_replacements = array_merge( array( '…', $opening_quote, $closing_quote, ' ™' ), $cockneyreplace ); |
75 |
100 |
101 |
|
102 // Pattern-based replacements of characters. |
|
103 // Sort the remaining patterns into several arrays for performance tuning. |
|
104 $dynamic_characters = array( 'apos' => array(), 'quote' => array(), 'dash' => array() ); |
|
105 $dynamic_replacements = array( 'apos' => array(), 'quote' => array(), 'dash' => array() ); |
|
76 $dynamic = array(); |
106 $dynamic = array(); |
77 if ( "'" != $apos ) { |
107 $spaces = wp_spaces_regexp(); |
78 $dynamic[ '/\'(\d\d(?:’|\')?s)/' ] = $apos . '$1'; // '99's |
108 |
79 $dynamic[ '/\'(\d)/' ] = $apos . '$1'; // '99 |
109 // '99' and '99" are ambiguous among other patterns; assume it's an abbreviated year at the end of a quotation. |
80 } |
110 if ( "'" !== $apos || "'" !== $closing_single_quote ) { |
81 if ( "'" != $opening_single_quote ) |
111 $dynamic[ '/\'(\d\d)\'(?=\Z|[.,)}\-\]]|>|' . $spaces . ')/' ] = $apos . '$1' . $closing_single_quote; |
82 $dynamic[ '/(\s|\A|[([{<]|")\'/' ] = '$1' . $opening_single_quote; // opening single quote, even after (, {, <, [ |
112 } |
83 if ( '"' != $double_prime ) |
113 if ( "'" !== $apos || '"' !== $closing_quote ) { |
84 $dynamic[ '/(\d)"/' ] = '$1' . $double_prime; // 9" (double prime) |
114 $dynamic[ '/\'(\d\d)"(?=\Z|[.,)}\-\]]|>|' . $spaces . ')/' ] = $apos . '$1' . $closing_quote; |
85 if ( "'" != $prime ) |
115 } |
86 $dynamic[ '/(\d)\'/' ] = '$1' . $prime; // 9' (prime) |
116 |
87 if ( "'" != $apos ) |
117 // '99 '99s '99's (apostrophe) But never '9 or '99% or '999 or '99.0. |
88 $dynamic[ '/(\S)\'([^\'\s])/' ] = '$1' . $apos . '$2'; // apostrophe in a word |
118 if ( "'" !== $apos ) { |
89 if ( '"' != $opening_quote ) |
119 $dynamic[ '/\'(?=\d\d(?:\Z|(?![%\d]|[.,]\d)))/' ] = $apos; |
90 $dynamic[ '/(\s|\A|[([{<])"(?!\s)/' ] = '$1' . $opening_quote . '$2'; // opening double quote, even after (, {, <, [ |
120 } |
91 if ( '"' != $closing_quote ) |
121 |
92 $dynamic[ '/"(\s|\S|\Z)/' ] = $closing_quote . '$1'; // closing double quote |
122 // Quoted Numbers like '0.42' |
93 if ( "'" != $closing_single_quote ) |
123 if ( "'" !== $opening_single_quote && "'" !== $closing_single_quote ) { |
94 $dynamic[ '/\'([\s.]|\Z)/' ] = $closing_single_quote . '$1'; // closing single quote |
124 $dynamic[ '/(?<=\A|' . $spaces . ')\'(\d[.,\d]*)\'/' ] = $opening_single_quote . '$1' . $closing_single_quote; |
95 |
125 } |
96 $dynamic[ '/\b(\d+)x(\d+)\b/' ] = '$1×$2'; // 9x9 (times) |
126 |
97 |
127 // Single quote at start, or preceded by (, {, <, [, ", -, or spaces. |
98 $dynamic_characters = array_keys( $dynamic ); |
128 if ( "'" !== $opening_single_quote ) { |
99 $dynamic_replacements = array_values( $dynamic ); |
129 $dynamic[ '/(?<=\A|[([{"\-]|<|' . $spaces . ')\'/' ] = $opening_single_quote; |
100 } |
130 } |
101 |
131 |
102 // Transform into regexp sub-expression used in _wptexturize_pushpop_element |
132 // Apostrophe in a word. No spaces, double apostrophes, or other punctuation. |
133 if ( "'" !== $apos ) { |
|
134 $dynamic[ '/(?<!' . $spaces . ')\'(?!\Z|[.,:;"\'(){}[\]\-]|&[lg]t;|' . $spaces . ')/' ] = $apos; |
|
135 } |
|
136 |
|
137 // 9' (prime) |
|
138 if ( "'" !== $prime ) { |
|
139 $dynamic[ '/(?<=\d)\'/' ] = $prime; |
|
140 } |
|
141 |
|
142 // Single quotes followed by spaces or ending punctuation. |
|
143 if ( "'" !== $closing_single_quote ) { |
|
144 $dynamic[ '/\'(?=\Z|[.,)}\-\]]|>|' . $spaces . ')/' ] = $closing_single_quote; |
|
145 } |
|
146 |
|
147 $dynamic_characters['apos'] = array_keys( $dynamic ); |
|
148 $dynamic_replacements['apos'] = array_values( $dynamic ); |
|
149 $dynamic = array(); |
|
150 |
|
151 // Quoted Numbers like "42" |
|
152 if ( '"' !== $opening_quote && '"' !== $closing_quote ) { |
|
153 $dynamic[ '/(?<=\A|' . $spaces . ')"(\d[.,\d]*)"/' ] = $opening_quote . '$1' . $closing_quote; |
|
154 } |
|
155 |
|
156 // 9" (double prime) |
|
157 if ( '"' !== $double_prime ) { |
|
158 $dynamic[ '/(?<=\d)"/' ] = $double_prime; |
|
159 } |
|
160 |
|
161 // Double quote at start, or preceded by (, {, <, [, -, or spaces, and not followed by spaces. |
|
162 if ( '"' !== $opening_quote ) { |
|
163 $dynamic[ '/(?<=\A|[([{\-]|<|' . $spaces . ')"(?!' . $spaces . ')/' ] = $opening_quote; |
|
164 } |
|
165 |
|
166 // Any remaining double quotes. |
|
167 if ( '"' !== $closing_quote ) { |
|
168 $dynamic[ '/"/' ] = $closing_quote; |
|
169 } |
|
170 |
|
171 $dynamic_characters['quote'] = array_keys( $dynamic ); |
|
172 $dynamic_replacements['quote'] = array_values( $dynamic ); |
|
173 $dynamic = array(); |
|
174 |
|
175 // Dashes and spaces |
|
176 $dynamic[ '/---/' ] = $em_dash; |
|
177 $dynamic[ '/(?<=^|' . $spaces . ')--(?=$|' . $spaces . ')/' ] = $em_dash; |
|
178 $dynamic[ '/(?<!xn)--/' ] = $en_dash; |
|
179 $dynamic[ '/(?<=^|' . $spaces . ')-(?=$|' . $spaces . ')/' ] = $en_dash; |
|
180 |
|
181 $dynamic_characters['dash'] = array_keys( $dynamic ); |
|
182 $dynamic_replacements['dash'] = array_values( $dynamic ); |
|
183 } |
|
184 |
|
103 // Must do this every time in case plugins use these filters in a context sensitive manner |
185 // Must do this every time in case plugins use these filters in a context sensitive manner |
104 $no_texturize_tags = '(' . implode('|', apply_filters('no_texturize_tags', $default_no_texturize_tags) ) . ')'; |
186 /** |
105 $no_texturize_shortcodes = '(' . implode('|', apply_filters('no_texturize_shortcodes', $default_no_texturize_shortcodes) ) . ')'; |
187 * Filter the list of HTML elements not to texturize. |
188 * |
|
189 * @since 2.8.0 |
|
190 * |
|
191 * @param array $default_no_texturize_tags An array of HTML element names. |
|
192 */ |
|
193 $no_texturize_tags = apply_filters( 'no_texturize_tags', $default_no_texturize_tags ); |
|
194 /** |
|
195 * Filter the list of shortcodes not to texturize. |
|
196 * |
|
197 * @since 2.8.0 |
|
198 * |
|
199 * @param array $default_no_texturize_shortcodes An array of shortcode names. |
|
200 */ |
|
201 $no_texturize_shortcodes = apply_filters( 'no_texturize_shortcodes', $default_no_texturize_shortcodes ); |
|
106 |
202 |
107 $no_texturize_tags_stack = array(); |
203 $no_texturize_tags_stack = array(); |
108 $no_texturize_shortcodes_stack = array(); |
204 $no_texturize_shortcodes_stack = array(); |
109 |
205 |
110 $textarr = preg_split('/(<.*>|\[.*\])/Us', $text, -1, PREG_SPLIT_DELIM_CAPTURE); |
206 // Look for shortcodes and HTML elements. |
207 |
|
208 $tagnames = array_keys( $shortcode_tags ); |
|
209 $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) ); |
|
210 $tagregexp = "(?:$tagregexp)(?![\\w-])"; // Excerpt of get_shortcode_regex(). |
|
211 |
|
212 $comment_regex = |
|
213 '!' // Start of comment, after the <. |
|
214 . '(?:' // Unroll the loop: Consume everything until --> is found. |
|
215 . '-(?!->)' // Dash not followed by end of comment. |
|
216 . '[^\-]*+' // Consume non-dashes. |
|
217 . ')*+' // Loop possessively. |
|
218 . '(?:-->)?'; // End of comment. If not found, match all input. |
|
219 |
|
220 $shortcode_regex = |
|
221 '\[' // Find start of shortcode. |
|
222 . '[\/\[]?' // Shortcodes may begin with [/ or [[ |
|
223 . $tagregexp // Only match registered shortcodes, because performance. |
|
224 . '(?:' |
|
225 . '[^\[\]<>]+' // Shortcodes do not contain other shortcodes. Quantifier critical. |
|
226 . '|' |
|
227 . '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >. |
|
228 . ')*+' // Possessive critical. |
|
229 . '\]' // Find end of shortcode. |
|
230 . '\]?'; // Shortcodes may end with ]] |
|
231 |
|
232 $regex = |
|
233 '/(' // Capture the entire match. |
|
234 . '<' // Find start of element. |
|
235 . '(?(?=!--)' // Is this a comment? |
|
236 . $comment_regex // Find end of comment. |
|
237 . '|' |
|
238 . '[^>]*>' // Find end of element. |
|
239 . ')' |
|
240 . '|' |
|
241 . $shortcode_regex // Find shortcodes. |
|
242 . ')/s'; |
|
243 |
|
244 $textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); |
|
111 |
245 |
112 foreach ( $textarr as &$curl ) { |
246 foreach ( $textarr as &$curl ) { |
113 if ( empty( $curl ) ) |
247 // Only call _wptexturize_pushpop_element if $curl is a delimiter. |
248 $first = $curl[0]; |
|
249 if ( '<' === $first && '<!--' === substr( $curl, 0, 4 ) ) { |
|
250 // This is an HTML comment delimeter. |
|
251 |
|
114 continue; |
252 continue; |
115 |
253 |
116 // Only call _wptexturize_pushpop_element if first char is correct tag opening |
254 } elseif ( '<' === $first && '>' === substr( $curl, -1 ) ) { |
117 $first = $curl[0]; |
255 // This is an HTML element delimiter. |
118 if ( '<' === $first ) { |
256 |
119 _wptexturize_pushpop_element($curl, $no_texturize_tags_stack, $no_texturize_tags, '<', '>'); |
257 _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags ); |
120 } elseif ( '[' === $first ) { |
258 |
121 _wptexturize_pushpop_element($curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes, '[', ']'); |
259 } elseif ( '' === trim( $curl ) ) { |
122 } elseif ( empty($no_texturize_shortcodes_stack) && empty($no_texturize_tags_stack) ) { |
260 // This is a newline between delimiters. Performance improves when we check this. |
123 // This is not a tag, nor is the texturization disabled static strings |
261 |
124 $curl = str_replace($static_characters, $static_replacements, $curl); |
262 continue; |
125 // regular expressions |
263 |
126 $curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl); |
264 } elseif ( '[' === $first && 1 === preg_match( '/^' . $shortcode_regex . '$/', $curl ) ) { |
127 } |
265 // This is a shortcode delimiter. |
128 $curl = preg_replace('/&([^#])(?![a-zA-Z1-4]{1,8};)/', '&$1', $curl); |
266 |
129 } |
267 if ( '[[' !== substr( $curl, 0, 2 ) && ']]' !== substr( $curl, -2 ) ) { |
130 return implode( '', $textarr ); |
268 // Looks like a normal shortcode. |
269 _wptexturize_pushpop_element( $curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes ); |
|
270 } else { |
|
271 // Looks like an escaped shortcode. |
|
272 continue; |
|
273 } |
|
274 |
|
275 } elseif ( empty( $no_texturize_shortcodes_stack ) && empty( $no_texturize_tags_stack ) ) { |
|
276 // This is neither a delimiter, nor is this content inside of no_texturize pairs. Do texturize. |
|
277 |
|
278 $curl = str_replace( $static_characters, $static_replacements, $curl ); |
|
279 |
|
280 if ( false !== strpos( $curl, "'" ) ) { |
|
281 $curl = preg_replace( $dynamic_characters['apos'], $dynamic_replacements['apos'], $curl ); |
|
282 } |
|
283 if ( false !== strpos( $curl, '"' ) ) { |
|
284 $curl = preg_replace( $dynamic_characters['quote'], $dynamic_replacements['quote'], $curl ); |
|
285 } |
|
286 if ( false !== strpos( $curl, '-' ) ) { |
|
287 $curl = preg_replace( $dynamic_characters['dash'], $dynamic_replacements['dash'], $curl ); |
|
288 } |
|
289 |
|
290 // 9x9 (times), but never 0x9999 |
|
291 if ( 1 === preg_match( '/(?<=\d)x\d/', $curl ) ) { |
|
292 // Searching for a digit is 10 times more expensive than for the x, so we avoid doing this one! |
|
293 $curl = preg_replace( '/\b(\d(?(?<=0)[\d\.,]+|[\d\.,]*))x(\d[\d\.,]*)\b/', '$1×$2', $curl ); |
|
294 } |
|
295 } |
|
296 } |
|
297 $text = implode( '', $textarr ); |
|
298 |
|
299 // Replace each & with & unless it already looks like an entity. |
|
300 $text = preg_replace('/&(?!#(?:\d+|x[a-f0-9]+);|[a-z1-4]{1,8};)/i', '&', $text); |
|
301 |
|
302 return $text; |
|
131 } |
303 } |
132 |
304 |
133 /** |
305 /** |
134 * Search for disabled element tags. Push element to stack on tag open and pop |
306 * Search for disabled element tags. Push element to stack on tag open and pop |
135 * on tag close. Assumes first character of $text is tag opening. |
307 * on tag close. |
308 * |
|
309 * Assumes first char of $text is tag opening and last char is tag closing. |
|
310 * Assumes second char of $text is optionally '/' to indicate closing as in </html>. |
|
136 * |
311 * |
137 * @since 2.9.0 |
312 * @since 2.9.0 |
138 * @access private |
313 * @access private |
139 * |
314 * |
140 * @param string $text Text to check. First character is assumed to be $opening |
315 * @param string $text Text to check. Must be a tag like `<html>` or `[shortcode]`. |
141 * @param array $stack Array used as stack of opened tag elements |
316 * @param array $stack List of open tag elements. |
142 * @param string $disabled_elements Tags to match against formatted as regexp sub-expression |
317 * @param array $disabled_elements The tag names to match against. Spaces are not allowed in tag names. |
143 * @param string $opening Tag opening character, assumed to be 1 character long |
318 */ |
144 * @param string $closing Tag closing character |
319 function _wptexturize_pushpop_element($text, &$stack, $disabled_elements) { |
145 */ |
320 // Is it an opening tag or closing tag? |
146 function _wptexturize_pushpop_element($text, &$stack, $disabled_elements, $opening = '<', $closing = '>') { |
321 if ( '/' !== $text[1] ) { |
147 // Check if it is a closing tag -- otherwise assume opening tag |
322 $opening_tag = true; |
148 if (strncmp($opening . '/', $text, 2)) { |
323 $name_offset = 1; |
149 // Opening? Check $text+1 against disabled elements |
324 } elseif ( 0 == count( $stack ) ) { |
150 if (preg_match('/^' . $disabled_elements . '\b/', substr($text, 1), $matches)) { |
325 // Stack is empty. Just stop. |
326 return; |
|
327 } else { |
|
328 $opening_tag = false; |
|
329 $name_offset = 2; |
|
330 } |
|
331 |
|
332 // Parse out the tag name. |
|
333 $space = strpos( $text, ' ' ); |
|
334 if ( false === $space ) { |
|
335 $space = -1; |
|
336 } else { |
|
337 $space -= $name_offset; |
|
338 } |
|
339 $tag = substr( $text, $name_offset, $space ); |
|
340 |
|
341 // Handle disabled tags. |
|
342 if ( in_array( $tag, $disabled_elements ) ) { |
|
343 if ( $opening_tag ) { |
|
151 /* |
344 /* |
152 * This disables texturize until we find a closing tag of our type |
345 * This disables texturize until we find a closing tag of our type |
153 * (e.g. <pre>) even if there was invalid nesting before that |
346 * (e.g. <pre>) even if there was invalid nesting before that |
154 * |
347 * |
155 * Example: in the case <pre>sadsadasd</code>"baba"</pre> |
348 * Example: in the case <pre>sadsadasd</code>"baba"</pre> |
156 * "baba" won't be texturize |
349 * "baba" won't be texturize |
157 */ |
350 */ |
158 |
351 |
159 array_push($stack, $matches[1]); |
352 array_push( $stack, $tag ); |
160 } |
353 } elseif ( end( $stack ) == $tag ) { |
161 } else { |
354 array_pop( $stack ); |
162 // Closing? Check $text+2 against disabled elements |
|
163 $c = preg_quote($closing, '/'); |
|
164 if (preg_match('/^' . $disabled_elements . $c . '/', substr($text, 2), $matches)) { |
|
165 $last = array_pop($stack); |
|
166 |
|
167 // Make sure it matches the opening tag |
|
168 if ($last != $matches[1]) |
|
169 array_push($stack, $last); |
|
170 } |
355 } |
171 } |
356 } |
172 } |
357 } |
173 |
358 |
174 /** |
359 /** |
175 * Replaces double line-breaks with paragraph elements. |
360 * Replaces double line-breaks with paragraph elements. |
176 * |
361 * |
177 * A group of regex replaces used to identify text formatted with newlines and |
362 * A group of regex replaces used to identify text formatted with newlines and |
178 * replace double line-breaks with HTML paragraph tags. The remaining |
363 * replace double line-breaks with HTML paragraph tags. The remaining line-breaks |
179 * line-breaks after conversion become <<br />> tags, unless $br is set to '0' |
364 * after conversion become <<br />> tags, unless $br is set to '0' or 'false'. |
180 * or 'false'. |
|
181 * |
365 * |
182 * @since 0.71 |
366 * @since 0.71 |
183 * |
367 * |
184 * @param string $pee The text which has to be formatted. |
368 * @param string $pee The text which has to be formatted. |
185 * @param bool $br Optional. If set, this will convert all remaining line-breaks after paragraphing. Default true. |
369 * @param bool $br Optional. If set, this will convert all remaining line-breaks |
370 * after paragraphing. Default true. |
|
186 * @return string Text which has been converted into correct paragraph tags. |
371 * @return string Text which has been converted into correct paragraph tags. |
187 */ |
372 */ |
188 function wpautop($pee, $br = true) { |
373 function wpautop($pee, $br = true) { |
189 $pre_tags = array(); |
374 $pre_tags = array(); |
190 |
375 |
191 if ( trim($pee) === '' ) |
376 if ( trim($pee) === '' ) |
192 return ''; |
377 return ''; |
193 |
378 |
194 $pee = $pee . "\n"; // just to make things a little easier, pad the end |
379 // Just to make things a little easier, pad the end. |
195 |
380 $pee = $pee . "\n"; |
381 |
|
382 /* |
|
383 * Pre tags shouldn't be touched by autop. |
|
384 * Replace pre tags with placeholders and bring them back after autop. |
|
385 */ |
|
196 if ( strpos($pee, '<pre') !== false ) { |
386 if ( strpos($pee, '<pre') !== false ) { |
197 $pee_parts = explode( '</pre>', $pee ); |
387 $pee_parts = explode( '</pre>', $pee ); |
198 $last_pee = array_pop($pee_parts); |
388 $last_pee = array_pop($pee_parts); |
199 $pee = ''; |
389 $pee = ''; |
200 $i = 0; |
390 $i = 0; |
215 $i++; |
405 $i++; |
216 } |
406 } |
217 |
407 |
218 $pee .= $last_pee; |
408 $pee .= $last_pee; |
219 } |
409 } |
220 |
410 // Change multiple <br>s into two line breaks, which will turn into paragraphs. |
221 $pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee); |
411 $pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee); |
222 // Space things out a little |
412 |
223 $allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|option|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|noscript|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)'; |
413 $allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)'; |
414 |
|
415 // Add a single line break above block-level opening tags. |
|
224 $pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee); |
416 $pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee); |
417 |
|
418 // Add a double line break below block-level closing tags. |
|
225 $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee); |
419 $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee); |
226 $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines |
420 |
227 if ( strpos($pee, '<object') !== false ) { |
421 // Standardize newline characters to "\n". |
228 $pee = preg_replace('|\s*<param([^>]*)>\s*|', "<param$1>", $pee); // no pee inside object/embed |
422 $pee = str_replace(array("\r\n", "\r"), "\n", $pee); |
229 $pee = preg_replace('|\s*</embed>\s*|', '</embed>', $pee); |
423 |
230 } |
424 // Collapse line breaks before and after <option> elements so they don't get autop'd. |
231 $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates |
425 if ( strpos( $pee, '<option' ) !== false ) { |
232 // make paragraphs, including one at the end |
426 $pee = preg_replace( '|\s*<option|', '<option', $pee ); |
427 $pee = preg_replace( '|</option>\s*|', '</option>', $pee ); |
|
428 } |
|
429 |
|
430 /* |
|
431 * Collapse line breaks inside <object> elements, before <param> and <embed> elements |
|
432 * so they don't get autop'd. |
|
433 */ |
|
434 if ( strpos( $pee, '</object>' ) !== false ) { |
|
435 $pee = preg_replace( '|(<object[^>]*>)\s*|', '$1', $pee ); |
|
436 $pee = preg_replace( '|\s*</object>|', '</object>', $pee ); |
|
437 $pee = preg_replace( '%\s*(</?(?:param|embed)[^>]*>)\s*%', '$1', $pee ); |
|
438 } |
|
439 |
|
440 /* |
|
441 * Collapse line breaks inside <audio> and <video> elements, |
|
442 * before and after <source> and <track> elements. |
|
443 */ |
|
444 if ( strpos( $pee, '<source' ) !== false || strpos( $pee, '<track' ) !== false ) { |
|
445 $pee = preg_replace( '%([<\[](?:audio|video)[^>\]]*[>\]])\s*%', '$1', $pee ); |
|
446 $pee = preg_replace( '%\s*([<\[]/(?:audio|video)[>\]])%', '$1', $pee ); |
|
447 $pee = preg_replace( '%\s*(<(?:source|track)[^>]*>)\s*%', '$1', $pee ); |
|
448 } |
|
449 |
|
450 // Remove more than two contiguous line breaks. |
|
451 $pee = preg_replace("/\n\n+/", "\n\n", $pee); |
|
452 |
|
453 // Split up the contents into an array of strings, separated by double line breaks. |
|
233 $pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY); |
454 $pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY); |
455 |
|
456 // Reset $pee prior to rebuilding. |
|
234 $pee = ''; |
457 $pee = ''; |
235 foreach ( $pees as $tinkle ) |
458 |
459 // Rebuild the content as a string, wrapping every bit with a <p>. |
|
460 foreach ( $pees as $tinkle ) { |
|
236 $pee .= '<p>' . trim($tinkle, "\n") . "</p>\n"; |
461 $pee .= '<p>' . trim($tinkle, "\n") . "</p>\n"; |
237 $pee = preg_replace('|<p>\s*</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace |
462 } |
463 |
|
464 // Under certain strange conditions it could create a P of entirely whitespace. |
|
465 $pee = preg_replace('|<p>\s*</p>|', '', $pee); |
|
466 |
|
467 // Add a closing <p> inside <div>, <address>, or <form> tag if missing. |
|
238 $pee = preg_replace('!<p>([^<]+)</(div|address|form)>!', "<p>$1</p></$2>", $pee); |
468 $pee = preg_replace('!<p>([^<]+)</(div|address|form)>!', "<p>$1</p></$2>", $pee); |
239 $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); // don't pee all over a tag |
469 |
240 $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists |
470 // If an opening or closing block element tag is wrapped in a <p>, unwrap it. |
471 $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); |
|
472 |
|
473 // In some cases <li> may get wrapped in <p>, fix them. |
|
474 $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); |
|
475 |
|
476 // If a <blockquote> is wrapped with a <p>, move it inside the <blockquote>. |
|
241 $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee); |
477 $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee); |
242 $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee); |
478 $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee); |
479 |
|
480 // If an opening or closing block element tag is preceded by an opening <p> tag, remove it. |
|
243 $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee); |
481 $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee); |
482 |
|
483 // If an opening or closing block element tag is followed by a closing <p> tag, remove it. |
|
244 $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); |
484 $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); |
485 |
|
486 // Optionally insert line breaks. |
|
245 if ( $br ) { |
487 if ( $br ) { |
488 // Replace newlines that shouldn't be touched with a placeholder. |
|
246 $pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee); |
489 $pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee); |
247 $pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); // optionally make line breaks |
490 |
491 // Replace any new line characters that aren't preceded by a <br /> with a <br />. |
|
492 $pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); |
|
493 |
|
494 // Replace newline placeholders with newlines. |
|
248 $pee = str_replace('<WPPreserveNewline />', "\n", $pee); |
495 $pee = str_replace('<WPPreserveNewline />', "\n", $pee); |
249 } |
496 } |
497 |
|
498 // If a <br /> tag is after an opening or closing block tag, remove it. |
|
250 $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee); |
499 $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee); |
500 |
|
501 // If a <br /> tag is before a subset of opening or closing block tags, remove it. |
|
251 $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee); |
502 $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee); |
252 $pee = preg_replace( "|\n</p>$|", '</p>', $pee ); |
503 $pee = preg_replace( "|\n</p>$|", '</p>', $pee ); |
253 |
504 |
505 // Replace placeholder <pre> tags with their original content. |
|
254 if ( !empty($pre_tags) ) |
506 if ( !empty($pre_tags) ) |
255 $pee = str_replace(array_keys($pre_tags), array_values($pre_tags), $pee); |
507 $pee = str_replace(array_keys($pre_tags), array_values($pre_tags), $pee); |
256 |
508 |
257 return $pee; |
509 return $pee; |
258 } |
510 } |
271 } |
523 } |
272 |
524 |
273 /** |
525 /** |
274 * Don't auto-p wrap shortcodes that stand alone |
526 * Don't auto-p wrap shortcodes that stand alone |
275 * |
527 * |
276 * Ensures that shortcodes are not wrapped in <<p>>...<</p>>. |
528 * Ensures that shortcodes are not wrapped in `<p>...</p>`. |
277 * |
529 * |
278 * @since 2.9.0 |
530 * @since 2.9.0 |
279 * |
531 * |
280 * @param string $pee The content. |
532 * @param string $pee The content. |
281 * @return string The filtered content. |
533 * @return string The filtered content. |
286 if ( empty( $shortcode_tags ) || !is_array( $shortcode_tags ) ) { |
538 if ( empty( $shortcode_tags ) || !is_array( $shortcode_tags ) ) { |
287 return $pee; |
539 return $pee; |
288 } |
540 } |
289 |
541 |
290 $tagregexp = join( '|', array_map( 'preg_quote', array_keys( $shortcode_tags ) ) ); |
542 $tagregexp = join( '|', array_map( 'preg_quote', array_keys( $shortcode_tags ) ) ); |
543 $spaces = wp_spaces_regexp(); |
|
291 |
544 |
292 $pattern = |
545 $pattern = |
293 '/' |
546 '/' |
294 . '<p>' // Opening paragraph |
547 . '<p>' // Opening paragraph |
295 . '\\s*+' // Optional leading whitespace |
548 . '(?:' . $spaces . ')*+' // Optional leading whitespace |
296 . '(' // 1: The shortcode |
549 . '(' // 1: The shortcode |
297 . '\\[' // Opening bracket |
550 . '\\[' // Opening bracket |
298 . "($tagregexp)" // 2: Shortcode name |
551 . "($tagregexp)" // 2: Shortcode name |
299 . '(?![\\w-])' // Not followed by word character or hyphen |
552 . '(?![\\w-])' // Not followed by word character or hyphen |
300 // Unroll the loop: Inside the opening shortcode tag |
553 // Unroll the loop: Inside the opening shortcode tag |
315 . ')*+' |
568 . ')*+' |
316 . '\\[\\/\\2\\]' // Closing shortcode tag |
569 . '\\[\\/\\2\\]' // Closing shortcode tag |
317 . ')?' |
570 . ')?' |
318 . ')' |
571 . ')' |
319 . ')' |
572 . ')' |
320 . '\\s*+' // optional trailing whitespace |
573 . '(?:' . $spaces . ')*+' // optional trailing whitespace |
321 . '<\\/p>' // closing paragraph |
574 . '<\\/p>' // closing paragraph |
322 . '/s'; |
575 . '/s'; |
323 |
576 |
324 return preg_replace( $pattern, '$1', $pee ); |
577 return preg_replace( $pattern, '$1', $pee ); |
325 } |
578 } |
335 * |
588 * |
336 * @param string $str The string to be checked |
589 * @param string $str The string to be checked |
337 * @return bool True if $str fits a UTF-8 model, false otherwise. |
590 * @return bool True if $str fits a UTF-8 model, false otherwise. |
338 */ |
591 */ |
339 function seems_utf8($str) { |
592 function seems_utf8($str) { |
593 mbstring_binary_safe_encoding(); |
|
340 $length = strlen($str); |
594 $length = strlen($str); |
595 reset_mbstring_encoding(); |
|
341 for ($i=0; $i < $length; $i++) { |
596 for ($i=0; $i < $length; $i++) { |
342 $c = ord($str[$i]); |
597 $c = ord($str[$i]); |
343 if ($c < 0x80) $n = 0; # 0bbbbbbb |
598 if ($c < 0x80) $n = 0; // 0bbbbbbb |
344 elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb |
599 elseif (($c & 0xE0) == 0xC0) $n=1; // 110bbbbb |
345 elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb |
600 elseif (($c & 0xF0) == 0xE0) $n=2; // 1110bbbb |
346 elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb |
601 elseif (($c & 0xF8) == 0xF0) $n=3; // 11110bbb |
347 elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb |
602 elseif (($c & 0xFC) == 0xF8) $n=4; // 111110bb |
348 elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b |
603 elseif (($c & 0xFE) == 0xFC) $n=5; // 1111110b |
349 else return false; # Does not match any model |
604 else return false; // Does not match any model |
350 for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ? |
605 for ($j=0; $j<$n; $j++) { // n bytes matching 10bbbbbb follow ? |
351 if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80)) |
606 if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80)) |
352 return false; |
607 return false; |
353 } |
608 } |
354 } |
609 } |
355 return true; |
610 return true; |
365 * |
620 * |
366 * @since 1.2.2 |
621 * @since 1.2.2 |
367 * @access private |
622 * @access private |
368 * |
623 * |
369 * @param string $string The text which is to be encoded. |
624 * @param string $string The text which is to be encoded. |
370 * @param mixed $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. |
625 * @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. |
371 * @param string $charset Optional. The character encoding of the string. Default is false. |
626 * @param string $charset Optional. The character encoding of the string. Default is false. |
372 * @param boolean $double_encode Optional. Whether to encode existing html entities. Default is false. |
627 * @param boolean $double_encode Optional. Whether to encode existing html entities. Default is false. |
373 * @return string The encoded text with HTML entities. |
628 * @return string The encoded text with HTML entities. |
374 */ |
629 */ |
375 function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { |
630 function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { |
421 $string = wp_kses_normalize_entities( $string ); |
676 $string = wp_kses_normalize_entities( $string ); |
422 |
677 |
423 // Now re-encode everything except &entity; |
678 // Now re-encode everything except &entity; |
424 $string = preg_split( '/(&#?x?[0-9a-z]+;)/i', $string, -1, PREG_SPLIT_DELIM_CAPTURE ); |
679 $string = preg_split( '/(&#?x?[0-9a-z]+;)/i', $string, -1, PREG_SPLIT_DELIM_CAPTURE ); |
425 |
680 |
426 for ( $i = 0; $i < count( $string ); $i += 2 ) |
681 for ( $i = 0, $c = count( $string ); $i < $c; $i += 2 ) { |
427 $string[$i] = @htmlspecialchars( $string[$i], $quote_style, $charset ); |
682 $string[$i] = @htmlspecialchars( $string[$i], $quote_style, $charset ); |
428 |
683 } |
429 $string = implode( '', $string ); |
684 $string = implode( '', $string ); |
430 } |
685 } |
431 |
686 |
432 // Backwards compatibility |
687 // Backwards compatibility |
433 if ( 'single' === $_quote_style ) |
688 if ( 'single' === $_quote_style ) |
559 $unicode = ''; |
814 $unicode = ''; |
560 $values = array(); |
815 $values = array(); |
561 $num_octets = 1; |
816 $num_octets = 1; |
562 $unicode_length = 0; |
817 $unicode_length = 0; |
563 |
818 |
819 mbstring_binary_safe_encoding(); |
|
564 $string_length = strlen( $utf8_string ); |
820 $string_length = strlen( $utf8_string ); |
821 reset_mbstring_encoding(); |
|
822 |
|
565 for ($i = 0; $i < $string_length; $i++ ) { |
823 for ($i = 0; $i < $string_length; $i++ ) { |
566 |
824 |
567 $value = ord( $utf8_string[ $i ] ); |
825 $value = ord( $utf8_string[ $i ] ); |
568 |
826 |
569 if ( $value < 128 ) { |
827 if ( $value < 128 ) { |
570 if ( $length && ( $unicode_length >= $length ) ) |
828 if ( $length && ( $unicode_length >= $length ) ) |
571 break; |
829 break; |
572 $unicode .= chr($value); |
830 $unicode .= chr($value); |
573 $unicode_length++; |
831 $unicode_length++; |
574 } else { |
832 } else { |
575 if ( count( $values ) == 0 ) $num_octets = ( $value < 224 ) ? 2 : 3; |
833 if ( count( $values ) == 0 ) { |
834 if ( $value < 224 ) { |
|
835 $num_octets = 2; |
|
836 } elseif ( $value < 240 ) { |
|
837 $num_octets = 3; |
|
838 } else { |
|
839 $num_octets = 4; |
|
840 } |
|
841 } |
|
576 |
842 |
577 $values[] = $value; |
843 $values[] = $value; |
578 |
844 |
579 if ( $length && ( $unicode_length + ($num_octets * 3) ) > $length ) |
845 if ( $length && ( $unicode_length + ($num_octets * 3) ) > $length ) |
580 break; |
846 break; |
581 if ( count( $values ) == $num_octets ) { |
847 if ( count( $values ) == $num_octets ) { |
582 if ($num_octets == 3) { |
848 for ( $j = 0; $j < $num_octets; $j++ ) { |
583 $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]) . '%' . dechex($values[2]); |
849 $unicode .= '%' . dechex( $values[ $j ] ); |
584 $unicode_length += 9; |
|
585 } else { |
|
586 $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]); |
|
587 $unicode_length += 6; |
|
588 } |
850 } |
851 |
|
852 $unicode_length += $num_octets * 3; |
|
589 |
853 |
590 $values = array(); |
854 $values = array(); |
591 $num_octets = 1; |
855 $num_octets = 1; |
592 } |
856 } |
593 } |
857 } |
796 $chars[ chr(195).chr(150) ] = 'Oe'; |
1060 $chars[ chr(195).chr(150) ] = 'Oe'; |
797 $chars[ chr(195).chr(182) ] = 'oe'; |
1061 $chars[ chr(195).chr(182) ] = 'oe'; |
798 $chars[ chr(195).chr(156) ] = 'Ue'; |
1062 $chars[ chr(195).chr(156) ] = 'Ue'; |
799 $chars[ chr(195).chr(188) ] = 'ue'; |
1063 $chars[ chr(195).chr(188) ] = 'ue'; |
800 $chars[ chr(195).chr(159) ] = 'ss'; |
1064 $chars[ chr(195).chr(159) ] = 'ss'; |
1065 } elseif ( 'da_DK' === $locale ) { |
|
1066 $chars[ chr(195).chr(134) ] = 'Ae'; |
|
1067 $chars[ chr(195).chr(166) ] = 'ae'; |
|
1068 $chars[ chr(195).chr(152) ] = 'Oe'; |
|
1069 $chars[ chr(195).chr(184) ] = 'oe'; |
|
1070 $chars[ chr(195).chr(133) ] = 'Aa'; |
|
1071 $chars[ chr(195).chr(165) ] = 'aa'; |
|
801 } |
1072 } |
802 |
1073 |
803 $string = strtr($string, $chars); |
1074 $string = strtr($string, $chars); |
804 } else { |
1075 } else { |
1076 $chars = array(); |
|
805 // Assume ISO-8859-1 if not UTF-8 |
1077 // Assume ISO-8859-1 if not UTF-8 |
806 $chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158) |
1078 $chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158) |
807 .chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194) |
1079 .chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194) |
808 .chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202) |
1080 .chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202) |
809 .chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210) |
1081 .chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210) |
815 .chr(252).chr(253).chr(255); |
1087 .chr(252).chr(253).chr(255); |
816 |
1088 |
817 $chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy"; |
1089 $chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy"; |
818 |
1090 |
819 $string = strtr($string, $chars['in'], $chars['out']); |
1091 $string = strtr($string, $chars['in'], $chars['out']); |
1092 $double_chars = array(); |
|
820 $double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254)); |
1093 $double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254)); |
821 $double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'); |
1094 $double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'); |
822 $string = str_replace($double_chars['in'], $double_chars['out'], $string); |
1095 $string = str_replace($double_chars['in'], $double_chars['out'], $string); |
823 } |
1096 } |
824 |
1097 |
840 * @return string The sanitized filename |
1113 * @return string The sanitized filename |
841 */ |
1114 */ |
842 function sanitize_file_name( $filename ) { |
1115 function sanitize_file_name( $filename ) { |
843 $filename_raw = $filename; |
1116 $filename_raw = $filename; |
844 $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", chr(0)); |
1117 $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", chr(0)); |
845 $special_chars = apply_filters('sanitize_file_name_chars', $special_chars, $filename_raw); |
1118 /** |
846 $filename = str_replace($special_chars, '', $filename); |
1119 * Filter the list of characters to remove from a filename. |
847 $filename = preg_replace('/[\s-]+/', '-', $filename); |
1120 * |
848 $filename = trim($filename, '.-_'); |
1121 * @since 2.8.0 |
1122 * |
|
1123 * @param array $special_chars Characters to remove. |
|
1124 * @param string $filename_raw Filename as it was passed into sanitize_file_name(). |
|
1125 */ |
|
1126 $special_chars = apply_filters( 'sanitize_file_name_chars', $special_chars, $filename_raw ); |
|
1127 $filename = preg_replace( "#\x{00a0}#siu", ' ', $filename ); |
|
1128 $filename = str_replace( $special_chars, '', $filename ); |
|
1129 $filename = str_replace( array( '%20', '+' ), '-', $filename ); |
|
1130 $filename = preg_replace( '/[\r\n\t -]+/', '-', $filename ); |
|
1131 $filename = trim( $filename, '.-_' ); |
|
849 |
1132 |
850 // Split the filename into a base and extension[s] |
1133 // Split the filename into a base and extension[s] |
851 $parts = explode('.', $filename); |
1134 $parts = explode('.', $filename); |
852 |
1135 |
853 // Return if only one extension |
1136 // Return if only one extension |
854 if ( count($parts) <= 2 ) |
1137 if ( count( $parts ) <= 2 ) { |
855 return apply_filters('sanitize_file_name', $filename, $filename_raw); |
1138 /** |
1139 * Filter a sanitized filename string. |
|
1140 * |
|
1141 * @since 2.8.0 |
|
1142 * |
|
1143 * @param string $filename Sanitized filename. |
|
1144 * @param string $filename_raw The filename prior to sanitization. |
|
1145 */ |
|
1146 return apply_filters( 'sanitize_file_name', $filename, $filename_raw ); |
|
1147 } |
|
856 |
1148 |
857 // Process multiple extensions |
1149 // Process multiple extensions |
858 $filename = array_shift($parts); |
1150 $filename = array_shift($parts); |
859 $extension = array_pop($parts); |
1151 $extension = array_pop($parts); |
860 $mimes = get_allowed_mime_types(); |
1152 $mimes = get_allowed_mime_types(); |
861 |
1153 |
862 // Loop over any intermediate extensions. Munge them with a trailing underscore if they are a 2 - 5 character |
1154 /* |
863 // long alpha string not in the extension whitelist. |
1155 * Loop over any intermediate extensions. Postfix them with a trailing underscore |
1156 * if they are a 2 - 5 character long alpha string not in the extension whitelist. |
|
1157 */ |
|
864 foreach ( (array) $parts as $part) { |
1158 foreach ( (array) $parts as $part) { |
865 $filename .= '.' . $part; |
1159 $filename .= '.' . $part; |
866 |
1160 |
867 if ( preg_match("/^[a-zA-Z]{2,5}\d?$/", $part) ) { |
1161 if ( preg_match("/^[a-zA-Z]{2,5}\d?$/", $part) ) { |
868 $allowed = false; |
1162 $allowed = false; |
876 if ( !$allowed ) |
1170 if ( !$allowed ) |
877 $filename .= '_'; |
1171 $filename .= '_'; |
878 } |
1172 } |
879 } |
1173 } |
880 $filename .= '.' . $extension; |
1174 $filename .= '.' . $extension; |
881 |
1175 /** This filter is documented in wp-includes/formatting.php */ |
882 return apply_filters('sanitize_file_name', $filename, $filename_raw); |
1176 return apply_filters('sanitize_file_name', $filename, $filename_raw); |
883 } |
1177 } |
884 |
1178 |
885 /** |
1179 /** |
886 * Sanitizes a username, stripping out unsafe characters. |
1180 * Sanitizes a username, stripping out unsafe characters. |
889 * alphanumeric, _, space, ., -, @. After sanitizing, it passes the username, |
1183 * alphanumeric, _, space, ., -, @. After sanitizing, it passes the username, |
890 * raw username (the username in the parameter), and the value of $strict as |
1184 * raw username (the username in the parameter), and the value of $strict as |
891 * parameters for the 'sanitize_user' filter. |
1185 * parameters for the 'sanitize_user' filter. |
892 * |
1186 * |
893 * @since 2.0.0 |
1187 * @since 2.0.0 |
894 * @uses apply_filters() Calls 'sanitize_user' hook on username, raw username, |
|
895 * and $strict parameter. |
|
896 * |
1188 * |
897 * @param string $username The username to be sanitized. |
1189 * @param string $username The username to be sanitized. |
898 * @param bool $strict If set limits $username to specific characters. Default false. |
1190 * @param bool $strict If set limits $username to specific characters. Default false. |
899 * @return string The sanitized username, after passing through filters. |
1191 * @return string The sanitized username, after passing through filters. |
900 */ |
1192 */ |
912 |
1204 |
913 $username = trim( $username ); |
1205 $username = trim( $username ); |
914 // Consolidate contiguous whitespace |
1206 // Consolidate contiguous whitespace |
915 $username = preg_replace( '|\s+|', ' ', $username ); |
1207 $username = preg_replace( '|\s+|', ' ', $username ); |
916 |
1208 |
1209 /** |
|
1210 * Filter a sanitized username string. |
|
1211 * |
|
1212 * @since 2.0.1 |
|
1213 * |
|
1214 * @param string $username Sanitized username. |
|
1215 * @param string $raw_username The username prior to sanitization. |
|
1216 * @param bool $strict Whether to limit the sanitization to specific characters. Default false. |
|
1217 */ |
|
917 return apply_filters( 'sanitize_user', $username, $raw_username, $strict ); |
1218 return apply_filters( 'sanitize_user', $username, $raw_username, $strict ); |
918 } |
1219 } |
919 |
1220 |
920 /** |
1221 /** |
921 * Sanitizes a string key. |
1222 * Sanitizes a string key. |
929 */ |
1230 */ |
930 function sanitize_key( $key ) { |
1231 function sanitize_key( $key ) { |
931 $raw_key = $key; |
1232 $raw_key = $key; |
932 $key = strtolower( $key ); |
1233 $key = strtolower( $key ); |
933 $key = preg_replace( '/[^a-z0-9_\-]/', '', $key ); |
1234 $key = preg_replace( '/[^a-z0-9_\-]/', '', $key ); |
1235 |
|
1236 /** |
|
1237 * Filter a sanitized key string. |
|
1238 * |
|
1239 * @since 3.0.0 |
|
1240 * |
|
1241 * @param string $key Sanitized key. |
|
1242 * @param string $raw_key The key prior to sanitization. |
|
1243 */ |
|
934 return apply_filters( 'sanitize_key', $key, $raw_key ); |
1244 return apply_filters( 'sanitize_key', $key, $raw_key ); |
935 } |
1245 } |
936 |
1246 |
937 /** |
1247 /** |
938 * Sanitizes a title, or returns a fallback title. |
1248 * Sanitizes a title, or returns a fallback title. |
952 $raw_title = $title; |
1262 $raw_title = $title; |
953 |
1263 |
954 if ( 'save' == $context ) |
1264 if ( 'save' == $context ) |
955 $title = remove_accents($title); |
1265 $title = remove_accents($title); |
956 |
1266 |
957 $title = apply_filters('sanitize_title', $title, $raw_title, $context); |
1267 /** |
1268 * Filter a sanitized title string. |
|
1269 * |
|
1270 * @since 1.2.0 |
|
1271 * |
|
1272 * @param string $title Sanitized title. |
|
1273 * @param string $raw_title The title prior to sanitization. |
|
1274 * @param string $context The context for which the title is being sanitized. |
|
1275 */ |
|
1276 $title = apply_filters( 'sanitize_title', $title, $raw_title, $context ); |
|
958 |
1277 |
959 if ( '' === $title || false === $title ) |
1278 if ( '' === $title || false === $title ) |
960 $title = $fallback_title; |
1279 $title = $fallback_title; |
961 |
1280 |
962 return $title; |
1281 return $title; |
966 * Sanitizes a title with the 'query' context. |
1285 * Sanitizes a title with the 'query' context. |
967 * |
1286 * |
968 * Used for querying the database for a value from URL. |
1287 * Used for querying the database for a value from URL. |
969 * |
1288 * |
970 * @since 3.1.0 |
1289 * @since 3.1.0 |
971 * @uses sanitize_title() |
|
972 * |
1290 * |
973 * @param string $title The string to be sanitized. |
1291 * @param string $title The string to be sanitized. |
974 * @return string The sanitized string. |
1292 * @return string The sanitized string. |
975 */ |
1293 */ |
976 function sanitize_title_for_query( $title ) { |
1294 function sanitize_title_for_query( $title ) { |
1042 |
1360 |
1043 return $title; |
1361 return $title; |
1044 } |
1362 } |
1045 |
1363 |
1046 /** |
1364 /** |
1047 * Ensures a string is a valid SQL order by clause. |
1365 * Ensures a string is a valid SQL 'order by' clause. |
1048 * |
1366 * |
1049 * Accepts one or more columns, with or without ASC/DESC, and also accepts |
1367 * Accepts one or more columns, with or without a sort order (ASC / DESC). |
1050 * RAND(). |
1368 * e.g. 'column_1', 'column_1, column_2', 'column_1 ASC, column_2 DESC' etc. |
1369 * |
|
1370 * Also accepts 'RAND()'. |
|
1051 * |
1371 * |
1052 * @since 2.5.1 |
1372 * @since 2.5.1 |
1053 * |
1373 * |
1054 * @param string $orderby Order by string to be checked. |
1374 * @param string $orderby Order by clause to be validated. |
1055 * @return string|bool Returns the order by clause if it is a match, false otherwise. |
1375 * @return string|bool Returns $orderby if valid, false otherwise. |
1056 */ |
1376 */ |
1057 function sanitize_sql_orderby( $orderby ){ |
1377 function sanitize_sql_orderby( $orderby ) { |
1058 preg_match('/^\s*([a-z0-9_]+(\s+(ASC|DESC))?(\s*,\s*|\s*$))+|^\s*RAND\(\s*\)\s*$/i', $orderby, $obmatches); |
1378 if ( preg_match( '/^\s*(([a-z0-9_]+|`[a-z0-9_]+`)(\s+(ASC|DESC))?\s*(,\s*(?=[a-z0-9_`])|$))+$/i', $orderby ) || preg_match( '/^\s*RAND\(\s*\)\s*$/i', $orderby ) ) { |
1059 if ( !$obmatches ) |
1379 return $orderby; |
1060 return false; |
1380 } |
1061 return $orderby; |
1381 return false; |
1062 } |
1382 } |
1063 |
1383 |
1064 /** |
1384 /** |
1065 * Sanitizes an HTML classname to ensure it only contains valid characters. |
1385 * Sanitizes an HTML classname to ensure it only contains valid characters. |
1066 * |
1386 * |
1070 * @todo Expand to support the full range of CDATA that a class attribute can contain. |
1390 * @todo Expand to support the full range of CDATA that a class attribute can contain. |
1071 * |
1391 * |
1072 * @since 2.8.0 |
1392 * @since 2.8.0 |
1073 * |
1393 * |
1074 * @param string $class The classname to be sanitized |
1394 * @param string $class The classname to be sanitized |
1075 * @param string $fallback Optional. The value to return if the sanitization end's up as an empty string. |
1395 * @param string $fallback Optional. The value to return if the sanitization ends up as an empty string. |
1076 * Defaults to an empty string. |
1396 * Defaults to an empty string. |
1077 * @return string The sanitized value |
1397 * @return string The sanitized value |
1078 */ |
1398 */ |
1079 function sanitize_html_class( $class, $fallback = '' ) { |
1399 function sanitize_html_class( $class, $fallback = '' ) { |
1080 //Strip out any % encoded octets |
1400 //Strip out any % encoded octets |
1084 $sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $sanitized ); |
1404 $sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $sanitized ); |
1085 |
1405 |
1086 if ( '' == $sanitized ) |
1406 if ( '' == $sanitized ) |
1087 $sanitized = $fallback; |
1407 $sanitized = $fallback; |
1088 |
1408 |
1409 /** |
|
1410 * Filter a sanitized HTML class string. |
|
1411 * |
|
1412 * @since 2.8.0 |
|
1413 * |
|
1414 * @param string $sanitized The sanitized HTML class. |
|
1415 * @param string $class HTML class before sanitization. |
|
1416 * @param string $fallback The fallback string. |
|
1417 */ |
|
1089 return apply_filters( 'sanitize_html_class', $sanitized, $class, $fallback ); |
1418 return apply_filters( 'sanitize_html_class', $sanitized, $class, $fallback ); |
1090 } |
1419 } |
1091 |
1420 |
1092 /** |
1421 /** |
1093 * Converts a number of characters from a string. |
1422 * Converts a number of characters from a string. |
1094 * |
1423 * |
1095 * Metadata tags <<title>> and <<category>> are removed, <<br>> and <<hr>> are |
1424 * Metadata tags `<title>` and `<category>` are removed, `<br>` and `<hr>` are |
1096 * converted into correct XHTML and Unicode characters are converted to the |
1425 * converted into correct XHTML and Unicode characters are converted to the |
1097 * valid range. |
1426 * valid range. |
1098 * |
1427 * |
1099 * @since 0.71 |
1428 * @since 0.71 |
1100 * |
1429 * |
1167 * @param string $text Text to be balanced |
1496 * @param string $text Text to be balanced |
1168 * @param bool $force If true, forces balancing, ignoring the value of the option. Default false. |
1497 * @param bool $force If true, forces balancing, ignoring the value of the option. Default false. |
1169 * @return string Balanced text |
1498 * @return string Balanced text |
1170 */ |
1499 */ |
1171 function balanceTags( $text, $force = false ) { |
1500 function balanceTags( $text, $force = false ) { |
1172 if ( $force || get_option('use_balanceTags') == 1 ) |
1501 if ( $force || get_option('use_balanceTags') == 1 ) { |
1173 return force_balance_tags( $text ); |
1502 return force_balance_tags( $text ); |
1174 else |
1503 } else { |
1175 return $text; |
1504 return $text; |
1505 } |
|
1176 } |
1506 } |
1177 |
1507 |
1178 /** |
1508 /** |
1179 * Balances tags of string using a modified stack. |
1509 * Balances tags of string using a modified stack. |
1180 * |
1510 * |
1223 if( $stacksize <= 0 ) { |
1553 if( $stacksize <= 0 ) { |
1224 $tag = ''; |
1554 $tag = ''; |
1225 // or close to be safe $tag = '/' . $tag; |
1555 // or close to be safe $tag = '/' . $tag; |
1226 } |
1556 } |
1227 // if stacktop value = tag close value then pop |
1557 // if stacktop value = tag close value then pop |
1228 else if ( $tagstack[$stacksize - 1] == $tag ) { // found closing tag |
1558 elseif ( $tagstack[$stacksize - 1] == $tag ) { // found closing tag |
1229 $tag = '</' . $tag . '>'; // Close Tag |
1559 $tag = '</' . $tag . '>'; // Close Tag |
1230 // Pop |
1560 // Pop |
1231 array_pop( $tagstack ); |
1561 array_pop( $tagstack ); |
1232 $stacksize--; |
1562 $stacksize--; |
1233 } else { // closing tag not at top, search for it |
1563 } else { // closing tag not at top, search for it |
1318 * @param string $content The text about to be edited. |
1648 * @param string $content The text about to be edited. |
1319 * @param bool $richedit Whether the $content should not pass through htmlspecialchars(). Default false (meaning it will be passed). |
1649 * @param bool $richedit Whether the $content should not pass through htmlspecialchars(). Default false (meaning it will be passed). |
1320 * @return string The text after the filter (and possibly htmlspecialchars()) has been run. |
1650 * @return string The text after the filter (and possibly htmlspecialchars()) has been run. |
1321 */ |
1651 */ |
1322 function format_to_edit( $content, $richedit = false ) { |
1652 function format_to_edit( $content, $richedit = false ) { |
1653 /** |
|
1654 * Filter the text to be formatted for editing. |
|
1655 * |
|
1656 * @since 1.2.0 |
|
1657 * |
|
1658 * @param string $content The text, prior to formatting for editing. |
|
1659 */ |
|
1323 $content = apply_filters( 'format_to_edit', $content ); |
1660 $content = apply_filters( 'format_to_edit', $content ); |
1324 if ( ! $richedit ) |
1661 if ( ! $richedit ) |
1325 $content = esc_textarea( $content ); |
1662 $content = esc_textarea( $content ); |
1326 return $content; |
1663 return $content; |
1327 } |
1664 } |
1328 |
1665 |
1329 /** |
1666 /** |
1330 * Holder for the 'format_to_post' filter. |
|
1331 * |
|
1332 * @since 0.71 |
|
1333 * |
|
1334 * @param string $content The text to pass through the filter. |
|
1335 * @return string Text returned from the 'format_to_post' filter. |
|
1336 */ |
|
1337 function format_to_post($content) { |
|
1338 $content = apply_filters('format_to_post', $content); |
|
1339 return $content; |
|
1340 } |
|
1341 |
|
1342 /** |
|
1343 * Add leading zeros when necessary. |
1667 * Add leading zeros when necessary. |
1344 * |
1668 * |
1345 * If you set the threshold to '4' and the number is '10', then you will get |
1669 * If you set the threshold to '4' and the number is '10', then you will get |
1346 * back '0010'. If you set the threshold to '4' and the number is '5000', then you |
1670 * back '0010'. If you set the threshold to '4' and the number is '5000', then you |
1347 * will get back '5000'. |
1671 * will get back '5000'. |
1375 } |
1699 } |
1376 |
1700 |
1377 /** |
1701 /** |
1378 * Appends a trailing slash. |
1702 * Appends a trailing slash. |
1379 * |
1703 * |
1380 * Will remove trailing slash if it exists already before adding a trailing |
1704 * Will remove trailing forward and backslashes if it exists already before adding |
1381 * slash. This prevents double slashing a string or path. |
1705 * a trailing forward slash. This prevents double slashing a string or path. |
1382 * |
1706 * |
1383 * The primary use of this is for paths and thus should be used for paths. It is |
1707 * The primary use of this is for paths and thus should be used for paths. It is |
1384 * not restricted to paths and offers no specific path support. |
1708 * not restricted to paths and offers no specific path support. |
1385 * |
1709 * |
1386 * @since 1.2.0 |
1710 * @since 1.2.0 |
1387 * @uses untrailingslashit() Unslashes string if it was slashed already. |
|
1388 * |
1711 * |
1389 * @param string $string What to add the trailing slash to. |
1712 * @param string $string What to add the trailing slash to. |
1390 * @return string String with trailing slash added. |
1713 * @return string String with trailing slash added. |
1391 */ |
1714 */ |
1392 function trailingslashit($string) { |
1715 function trailingslashit( $string ) { |
1393 return untrailingslashit($string) . '/'; |
1716 return untrailingslashit( $string ) . '/'; |
1394 } |
1717 } |
1395 |
1718 |
1396 /** |
1719 /** |
1397 * Removes trailing slash if it exists. |
1720 * Removes trailing forward slashes and backslashes if they exist. |
1398 * |
1721 * |
1399 * The primary use of this is for paths and thus should be used for paths. It is |
1722 * The primary use of this is for paths and thus should be used for paths. It is |
1400 * not restricted to paths and offers no specific path support. |
1723 * not restricted to paths and offers no specific path support. |
1401 * |
1724 * |
1402 * @since 2.2.0 |
1725 * @since 2.2.0 |
1403 * |
1726 * |
1404 * @param string $string What to remove the trailing slash from. |
1727 * @param string $string What to remove the trailing slashes from. |
1405 * @return string String without the trailing slash. |
1728 * @return string String without the trailing slashes. |
1406 */ |
1729 */ |
1407 function untrailingslashit($string) { |
1730 function untrailingslashit( $string ) { |
1408 return rtrim($string, '/'); |
1731 return rtrim( $string, '/\\' ); |
1409 } |
1732 } |
1410 |
1733 |
1411 /** |
1734 /** |
1412 * Adds slashes to escape strings. |
1735 * Adds slashes to escape strings. |
1413 * |
1736 * |
1487 * @param int $hex_encoding Optional. Set to 1 to enable hex encoding. |
1810 * @param int $hex_encoding Optional. Set to 1 to enable hex encoding. |
1488 * @return string Converted email address. |
1811 * @return string Converted email address. |
1489 */ |
1812 */ |
1490 function antispambot( $email_address, $hex_encoding = 0 ) { |
1813 function antispambot( $email_address, $hex_encoding = 0 ) { |
1491 $email_no_spam_address = ''; |
1814 $email_no_spam_address = ''; |
1492 for ( $i = 0; $i < strlen( $email_address ); $i++ ) { |
1815 for ( $i = 0, $len = strlen( $email_address ); $i < $len; $i++ ) { |
1493 $j = rand( 0, 1 + $hex_encoding ); |
1816 $j = rand( 0, 1 + $hex_encoding ); |
1494 if ( $j == 0 ) { |
1817 if ( $j == 0 ) { |
1495 $email_no_spam_address .= '&#' . ord( $email_address[$i] ) . ';'; |
1818 $email_no_spam_address .= '&#' . ord( $email_address[$i] ) . ';'; |
1496 } elseif ( $j == 1 ) { |
1819 } elseif ( $j == 1 ) { |
1497 $email_no_spam_address .= $email_address[$i]; |
1820 $email_no_spam_address .= $email_address[$i]; |
1599 * @return string Content with converted URIs. |
1922 * @return string Content with converted URIs. |
1600 */ |
1923 */ |
1601 function make_clickable( $text ) { |
1924 function make_clickable( $text ) { |
1602 $r = ''; |
1925 $r = ''; |
1603 $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // split out HTML tags |
1926 $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // split out HTML tags |
1927 $nested_code_pre = 0; // Keep track of how many levels link is nested inside <pre> or <code> |
|
1604 foreach ( $textarr as $piece ) { |
1928 foreach ( $textarr as $piece ) { |
1605 if ( empty( $piece ) || ( $piece[0] == '<' && ! preg_match('|^<\s*[\w]{1,20}+://|', $piece) ) ) { |
1929 |
1930 if ( preg_match( '|^<code[\s>]|i', $piece ) || preg_match( '|^<pre[\s>]|i', $piece ) ) |
|
1931 $nested_code_pre++; |
|
1932 elseif ( ( '</code>' === strtolower( $piece ) || '</pre>' === strtolower( $piece ) ) && $nested_code_pre ) |
|
1933 $nested_code_pre--; |
|
1934 |
|
1935 if ( $nested_code_pre || empty( $piece ) || ( $piece[0] === '<' && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) ) ) { |
|
1606 $r .= $piece; |
1936 $r .= $piece; |
1607 continue; |
1937 continue; |
1608 } |
1938 } |
1609 |
1939 |
1610 // Long strings might contain expensive edge cases ... |
1940 // Long strings might contain expensive edge cases ... |
1644 $r .= $ret; |
1974 $r .= $ret; |
1645 } |
1975 } |
1646 } |
1976 } |
1647 |
1977 |
1648 // Cleanup of accidental links within links |
1978 // Cleanup of accidental links within links |
1649 $r = preg_replace( '#(<a( [^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i', "$1$3</a>", $r ); |
1979 $r = preg_replace( '#(<a([ \r\n\t]+[^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i', "$1$3</a>", $r ); |
1650 return $r; |
1980 return $r; |
1651 } |
1981 } |
1652 |
1982 |
1653 /** |
1983 /** |
1654 * Breaks a string into chunks by splitting at whitespace characters. |
1984 * Breaks a string into chunks by splitting at whitespace characters. |
1658 * |
1988 * |
1659 * Joining the returned chunks with empty delimiters reconstructs the input string losslessly. |
1989 * Joining the returned chunks with empty delimiters reconstructs the input string losslessly. |
1660 * |
1990 * |
1661 * Input string must have no null characters (or eventual transformations on output chunks must not care about null characters) |
1991 * Input string must have no null characters (or eventual transformations on output chunks must not care about null characters) |
1662 * |
1992 * |
1663 * <code> |
1993 * _split_str_by_whitespace( "1234 67890 1234 67890a cd 1234 890 123456789 1234567890a 45678 1 3 5 7 90 ", 10 ) == |
1664 * _split_str_by_whitespace( "1234 67890 1234 67890a cd 1234 890 123456789 1234567890a 45678 1 3 5 7 90 ", 10 ) == |
1994 * array ( |
1665 * array ( |
1995 * 0 => '1234 67890 ', // 11 characters: Perfect split |
1666 * 0 => '1234 67890 ', // 11 characters: Perfect split |
1996 * 1 => '1234 ', // 5 characters: '1234 67890a' was too long |
1667 * 1 => '1234 ', // 5 characters: '1234 67890a' was too long |
1997 * 2 => '67890a cd ', // 10 characters: '67890a cd 1234' was too long |
1668 * 2 => '67890a cd ', // 10 characters: '67890a cd 1234' was too long |
1998 * 3 => '1234 890 ', // 11 characters: Perfect split |
1669 * 3 => '1234 890 ', // 11 characters: Perfect split |
1999 * 4 => '123456789 ', // 10 characters: '123456789 1234567890a' was too long |
1670 * 4 => '123456789 ', // 10 characters: '123456789 1234567890a' was too long |
2000 * 5 => '1234567890a ', // 12 characters: Too long, but no inner whitespace on which to split |
1671 * 5 => '1234567890a ', // 12 characters: Too long, but no inner whitespace on which to split |
2001 * 6 => ' 45678 ', // 11 characters: Perfect split |
1672 * 6 => ' 45678 ', // 11 characters: Perfect split |
2002 * 7 => '1 3 5 7 90 ', // 11 characters: End of $string |
1673 * 7 => '1 3 5 7 9', // 9 characters: End of $string |
2003 * ); |
1674 * ); |
|
1675 * </code> |
|
1676 * |
2004 * |
1677 * @since 3.4.0 |
2005 * @since 3.4.0 |
1678 * @access private |
2006 * @access private |
1679 * |
2007 * |
1680 * @param string $string The string to split. |
2008 * @param string $string The string to split. |
1744 /** |
2072 /** |
1745 * Convert one smiley code to the icon graphic file equivalent. |
2073 * Convert one smiley code to the icon graphic file equivalent. |
1746 * |
2074 * |
1747 * Callback handler for {@link convert_smilies()}. |
2075 * Callback handler for {@link convert_smilies()}. |
1748 * Looks up one smiley code in the $wpsmiliestrans global array and returns an |
2076 * Looks up one smiley code in the $wpsmiliestrans global array and returns an |
1749 * <img> string for that smiley. |
2077 * `<img>` string for that smiley. |
1750 * |
2078 * |
1751 * @global array $wpsmiliestrans |
2079 * @global array $wpsmiliestrans |
1752 * @since 2.8.0 |
2080 * @since 2.8.0 |
1753 * |
2081 * |
1754 * @param array $matches Single match. Smiley code to convert to image. |
2082 * @param array $matches Single match. Smiley code to convert to image. |
1760 if ( count( $matches ) == 0 ) |
2088 if ( count( $matches ) == 0 ) |
1761 return ''; |
2089 return ''; |
1762 |
2090 |
1763 $smiley = trim( reset( $matches ) ); |
2091 $smiley = trim( reset( $matches ) ); |
1764 $img = $wpsmiliestrans[ $smiley ]; |
2092 $img = $wpsmiliestrans[ $smiley ]; |
1765 $smiley_masked = esc_attr( $smiley ); |
2093 |
1766 |
2094 $matches = array(); |
2095 $ext = preg_match( '/\.([^.]+)$/', $img, $matches ) ? strtolower( $matches[1] ) : false; |
|
2096 $image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' ); |
|
2097 |
|
2098 // Don't convert smilies that aren't images - they're probably emoji. |
|
2099 if ( ! in_array( $ext, $image_exts ) ) { |
|
2100 return $img; |
|
2101 } |
|
2102 |
|
2103 /** |
|
2104 * Filter the Smiley image URL before it's used in the image element. |
|
2105 * |
|
2106 * @since 2.9.0 |
|
2107 * |
|
2108 * @param string $smiley_url URL for the smiley image. |
|
2109 * @param string $img Filename for the smiley image. |
|
2110 * @param string $site_url Site URL, as returned by site_url(). |
|
2111 */ |
|
1767 $src_url = apply_filters( 'smilies_src', includes_url( "images/smilies/$img" ), $img, site_url() ); |
2112 $src_url = apply_filters( 'smilies_src', includes_url( "images/smilies/$img" ), $img, site_url() ); |
1768 |
2113 |
1769 return " <img src='$src_url' alt='$smiley_masked' class='wp-smiley' /> "; |
2114 return sprintf( '<img src="%s" alt="%s" class="wp-smiley" style="height: 1em; max-height: 1em;" />', esc_url( $src_url ), esc_attr( $smiley ) ); |
1770 } |
2115 } |
1771 |
2116 |
1772 /** |
2117 /** |
1773 * Convert text equivalent of smilies to images. |
2118 * Convert text equivalent of smilies to images. |
1774 * |
2119 * |
1779 * @uses $wp_smiliessearch |
2124 * @uses $wp_smiliessearch |
1780 * |
2125 * |
1781 * @param string $text Content to convert smilies from text. |
2126 * @param string $text Content to convert smilies from text. |
1782 * @return string Converted content with text smilies replaced with images. |
2127 * @return string Converted content with text smilies replaced with images. |
1783 */ |
2128 */ |
1784 function convert_smilies($text) { |
2129 function convert_smilies( $text ) { |
1785 global $wp_smiliessearch; |
2130 global $wp_smiliessearch; |
1786 $output = ''; |
2131 $output = ''; |
1787 if ( get_option('use_smilies') && !empty($wp_smiliessearch) ) { |
2132 if ( get_option( 'use_smilies' ) && ! empty( $wp_smiliessearch ) ) { |
1788 // HTML loop taken from texturize function, could possible be consolidated |
2133 // HTML loop taken from texturize function, could possible be consolidated |
1789 $textarr = preg_split("/(<.*>)/U", $text, -1, PREG_SPLIT_DELIM_CAPTURE); // capture the tags as well as in between |
2134 $textarr = preg_split( '/(<.*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // capture the tags as well as in between |
1790 $stop = count($textarr);// loop stuff |
2135 $stop = count( $textarr );// loop stuff |
1791 for ($i = 0; $i < $stop; $i++) { |
2136 |
2137 // Ignore proessing of specific tags |
|
2138 $tags_to_ignore = 'code|pre|style|script|textarea'; |
|
2139 $ignore_block_element = ''; |
|
2140 |
|
2141 for ( $i = 0; $i < $stop; $i++ ) { |
|
1792 $content = $textarr[$i]; |
2142 $content = $textarr[$i]; |
1793 if ((strlen($content) > 0) && ('<' != $content[0])) { // If it's not a tag |
2143 |
1794 $content = preg_replace_callback($wp_smiliessearch, 'translate_smiley', $content); |
2144 // If we're in an ignore block, wait until we find its closing tag |
2145 if ( '' == $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')>/', $content, $matches ) ) { |
|
2146 $ignore_block_element = $matches[1]; |
|
1795 } |
2147 } |
2148 |
|
2149 // If it's not a tag and not in ignore block |
|
2150 if ( '' == $ignore_block_element && strlen( $content ) > 0 && '<' != $content[0] ) { |
|
2151 $content = preg_replace_callback( $wp_smiliessearch, 'translate_smiley', $content ); |
|
2152 } |
|
2153 |
|
2154 // did we exit ignore block |
|
2155 if ( '' != $ignore_block_element && '</' . $ignore_block_element . '>' == $content ) { |
|
2156 $ignore_block_element = ''; |
|
2157 } |
|
2158 |
|
1796 $output .= $content; |
2159 $output .= $content; |
1797 } |
2160 } |
1798 } else { |
2161 } else { |
1799 // return default text. |
2162 // return default text. |
1800 $output = $text; |
2163 $output = $text; |
1817 if ( ! empty( $deprecated ) ) |
2180 if ( ! empty( $deprecated ) ) |
1818 _deprecated_argument( __FUNCTION__, '3.0' ); |
2181 _deprecated_argument( __FUNCTION__, '3.0' ); |
1819 |
2182 |
1820 // Test for the minimum length the email can be |
2183 // Test for the minimum length the email can be |
1821 if ( strlen( $email ) < 3 ) { |
2184 if ( strlen( $email ) < 3 ) { |
2185 /** |
|
2186 * Filter whether an email address is valid. |
|
2187 * |
|
2188 * This filter is evaluated under several different contexts, such as 'email_too_short', |
|
2189 * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits', |
|
2190 * 'domain_no_periods', 'sub_hyphen_limits', 'sub_invalid_chars', or no specific context. |
|
2191 * |
|
2192 * @since 2.8.0 |
|
2193 * |
|
2194 * @param bool $is_email Whether the email address has passed the is_email() checks. Default false. |
|
2195 * @param string $email The email address being checked. |
|
2196 * @param string $message An explanatory message to the user. |
|
2197 * @param string $context Context under which the email was tested. |
|
2198 */ |
|
1822 return apply_filters( 'is_email', false, $email, 'email_too_short' ); |
2199 return apply_filters( 'is_email', false, $email, 'email_too_short' ); |
1823 } |
2200 } |
1824 |
2201 |
1825 // Test for an @ character after the first position |
2202 // Test for an @ character after the first position |
1826 if ( strpos( $email, '@', 1 ) === false ) { |
2203 if ( strpos( $email, '@', 1 ) === false ) { |
2204 /** This filter is documented in wp-includes/formatting.php */ |
|
1827 return apply_filters( 'is_email', false, $email, 'email_no_at' ); |
2205 return apply_filters( 'is_email', false, $email, 'email_no_at' ); |
1828 } |
2206 } |
1829 |
2207 |
1830 // Split out the local and domain parts |
2208 // Split out the local and domain parts |
1831 list( $local, $domain ) = explode( '@', $email, 2 ); |
2209 list( $local, $domain ) = explode( '@', $email, 2 ); |
1832 |
2210 |
1833 // LOCAL PART |
2211 // LOCAL PART |
1834 // Test for invalid characters |
2212 // Test for invalid characters |
1835 if ( !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) { |
2213 if ( !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) { |
2214 /** This filter is documented in wp-includes/formatting.php */ |
|
1836 return apply_filters( 'is_email', false, $email, 'local_invalid_chars' ); |
2215 return apply_filters( 'is_email', false, $email, 'local_invalid_chars' ); |
1837 } |
2216 } |
1838 |
2217 |
1839 // DOMAIN PART |
2218 // DOMAIN PART |
1840 // Test for sequences of periods |
2219 // Test for sequences of periods |
1841 if ( preg_match( '/\.{2,}/', $domain ) ) { |
2220 if ( preg_match( '/\.{2,}/', $domain ) ) { |
2221 /** This filter is documented in wp-includes/formatting.php */ |
|
1842 return apply_filters( 'is_email', false, $email, 'domain_period_sequence' ); |
2222 return apply_filters( 'is_email', false, $email, 'domain_period_sequence' ); |
1843 } |
2223 } |
1844 |
2224 |
1845 // Test for leading and trailing periods and whitespace |
2225 // Test for leading and trailing periods and whitespace |
1846 if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) { |
2226 if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) { |
2227 /** This filter is documented in wp-includes/formatting.php */ |
|
1847 return apply_filters( 'is_email', false, $email, 'domain_period_limits' ); |
2228 return apply_filters( 'is_email', false, $email, 'domain_period_limits' ); |
1848 } |
2229 } |
1849 |
2230 |
1850 // Split the domain into subs |
2231 // Split the domain into subs |
1851 $subs = explode( '.', $domain ); |
2232 $subs = explode( '.', $domain ); |
1852 |
2233 |
1853 // Assume the domain will have at least two subs |
2234 // Assume the domain will have at least two subs |
1854 if ( 2 > count( $subs ) ) { |
2235 if ( 2 > count( $subs ) ) { |
2236 /** This filter is documented in wp-includes/formatting.php */ |
|
1855 return apply_filters( 'is_email', false, $email, 'domain_no_periods' ); |
2237 return apply_filters( 'is_email', false, $email, 'domain_no_periods' ); |
1856 } |
2238 } |
1857 |
2239 |
1858 // Loop through each sub |
2240 // Loop through each sub |
1859 foreach ( $subs as $sub ) { |
2241 foreach ( $subs as $sub ) { |
1860 // Test for leading and trailing hyphens and whitespace |
2242 // Test for leading and trailing hyphens and whitespace |
1861 if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) { |
2243 if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) { |
2244 /** This filter is documented in wp-includes/formatting.php */ |
|
1862 return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' ); |
2245 return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' ); |
1863 } |
2246 } |
1864 |
2247 |
1865 // Test for invalid characters |
2248 // Test for invalid characters |
1866 if ( !preg_match('/^[a-z0-9-]+$/i', $sub ) ) { |
2249 if ( !preg_match('/^[a-z0-9-]+$/i', $sub ) ) { |
2250 /** This filter is documented in wp-includes/formatting.php */ |
|
1867 return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' ); |
2251 return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' ); |
1868 } |
2252 } |
1869 } |
2253 } |
1870 |
2254 |
1871 // Congratulations your email made it! |
2255 // Congratulations your email made it! |
2256 /** This filter is documented in wp-includes/formatting.php */ |
|
1872 return apply_filters( 'is_email', $email, $email, null ); |
2257 return apply_filters( 'is_email', $email, $email, null ); |
1873 } |
2258 } |
1874 |
2259 |
1875 /** |
2260 /** |
1876 * Convert to ASCII from email subjects. |
2261 * Convert to ASCII from email subjects. |
1896 * |
2281 * |
1897 * @since 3.1.0 |
2282 * @since 3.1.0 |
1898 * @access private |
2283 * @access private |
1899 * |
2284 * |
1900 * @param array $match The preg_replace_callback matches array |
2285 * @param array $match The preg_replace_callback matches array |
1901 * @return array Converted chars |
2286 * @return string Converted chars |
1902 */ |
2287 */ |
1903 function _wp_iso_convert( $match ) { |
2288 function _wp_iso_convert( $match ) { |
1904 return chr( hexdec( strtolower( $match[1] ) ) ); |
2289 return chr( hexdec( strtolower( $match[1] ) ) ); |
1905 } |
2290 } |
1906 |
2291 |
1912 * otherwise it simply subtracts the value of the 'gmt_offset' option. Return |
2297 * otherwise it simply subtracts the value of the 'gmt_offset' option. Return |
1913 * format can be overridden using the $format parameter. |
2298 * format can be overridden using the $format parameter. |
1914 * |
2299 * |
1915 * @since 1.2.0 |
2300 * @since 1.2.0 |
1916 * |
2301 * |
1917 * @uses get_option() to retrieve the value of 'gmt_offset'. |
|
1918 * @param string $string The date to be converted. |
2302 * @param string $string The date to be converted. |
1919 * @param string $format The format string for the returned date (default is Y-m-d H:i:s) |
2303 * @param string $format The format string for the returned date (default is Y-m-d H:i:s) |
1920 * @return string GMT version of the date provided. |
2304 * @return string GMT version of the date provided. |
1921 */ |
2305 */ |
1922 function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) { |
2306 function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) { |
2013 $timestamp = gmmktime($date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1]); |
2397 $timestamp = gmmktime($date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1]); |
2014 $timestamp -= $offset; |
2398 $timestamp -= $offset; |
2015 |
2399 |
2016 return gmdate('Y-m-d H:i:s', $timestamp); |
2400 return gmdate('Y-m-d H:i:s', $timestamp); |
2017 |
2401 |
2018 } else if ($timezone == 'user') { |
2402 } elseif ($timezone == 'user') { |
2019 return preg_replace('#([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(Z|[\+|\-][0-9]{2,4}){0,1}#', '$1-$2-$3 $4:$5:$6', $date_string); |
2403 return preg_replace('#([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(Z|[\+|\-][0-9]{2,4}){0,1}#', '$1-$2-$3 $4:$5:$6', $date_string); |
2020 } |
2404 } |
2021 } |
2405 } |
2022 |
2406 |
2023 /** |
2407 /** |
2046 * @return string Filtered email address. |
2430 * @return string Filtered email address. |
2047 */ |
2431 */ |
2048 function sanitize_email( $email ) { |
2432 function sanitize_email( $email ) { |
2049 // Test for the minimum length the email can be |
2433 // Test for the minimum length the email can be |
2050 if ( strlen( $email ) < 3 ) { |
2434 if ( strlen( $email ) < 3 ) { |
2435 /** |
|
2436 * Filter a sanitized email address. |
|
2437 * |
|
2438 * This filter is evaluated under several contexts, including 'email_too_short', |
|
2439 * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits', |
|
2440 * 'domain_no_periods', 'domain_no_valid_subs', or no context. |
|
2441 * |
|
2442 * @since 2.8.0 |
|
2443 * |
|
2444 * @param string $email The sanitized email address. |
|
2445 * @param string $email The email address, as provided to sanitize_email(). |
|
2446 * @param string $message A message to pass to the user. |
|
2447 */ |
|
2051 return apply_filters( 'sanitize_email', '', $email, 'email_too_short' ); |
2448 return apply_filters( 'sanitize_email', '', $email, 'email_too_short' ); |
2052 } |
2449 } |
2053 |
2450 |
2054 // Test for an @ character after the first position |
2451 // Test for an @ character after the first position |
2055 if ( strpos( $email, '@', 1 ) === false ) { |
2452 if ( strpos( $email, '@', 1 ) === false ) { |
2453 /** This filter is documented in wp-includes/formatting.php */ |
|
2056 return apply_filters( 'sanitize_email', '', $email, 'email_no_at' ); |
2454 return apply_filters( 'sanitize_email', '', $email, 'email_no_at' ); |
2057 } |
2455 } |
2058 |
2456 |
2059 // Split out the local and domain parts |
2457 // Split out the local and domain parts |
2060 list( $local, $domain ) = explode( '@', $email, 2 ); |
2458 list( $local, $domain ) = explode( '@', $email, 2 ); |
2061 |
2459 |
2062 // LOCAL PART |
2460 // LOCAL PART |
2063 // Test for invalid characters |
2461 // Test for invalid characters |
2064 $local = preg_replace( '/[^a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]/', '', $local ); |
2462 $local = preg_replace( '/[^a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]/', '', $local ); |
2065 if ( '' === $local ) { |
2463 if ( '' === $local ) { |
2464 /** This filter is documented in wp-includes/formatting.php */ |
|
2066 return apply_filters( 'sanitize_email', '', $email, 'local_invalid_chars' ); |
2465 return apply_filters( 'sanitize_email', '', $email, 'local_invalid_chars' ); |
2067 } |
2466 } |
2068 |
2467 |
2069 // DOMAIN PART |
2468 // DOMAIN PART |
2070 // Test for sequences of periods |
2469 // Test for sequences of periods |
2071 $domain = preg_replace( '/\.{2,}/', '', $domain ); |
2470 $domain = preg_replace( '/\.{2,}/', '', $domain ); |
2072 if ( '' === $domain ) { |
2471 if ( '' === $domain ) { |
2472 /** This filter is documented in wp-includes/formatting.php */ |
|
2073 return apply_filters( 'sanitize_email', '', $email, 'domain_period_sequence' ); |
2473 return apply_filters( 'sanitize_email', '', $email, 'domain_period_sequence' ); |
2074 } |
2474 } |
2075 |
2475 |
2076 // Test for leading and trailing periods and whitespace |
2476 // Test for leading and trailing periods and whitespace |
2077 $domain = trim( $domain, " \t\n\r\0\x0B." ); |
2477 $domain = trim( $domain, " \t\n\r\0\x0B." ); |
2078 if ( '' === $domain ) { |
2478 if ( '' === $domain ) { |
2479 /** This filter is documented in wp-includes/formatting.php */ |
|
2079 return apply_filters( 'sanitize_email', '', $email, 'domain_period_limits' ); |
2480 return apply_filters( 'sanitize_email', '', $email, 'domain_period_limits' ); |
2080 } |
2481 } |
2081 |
2482 |
2082 // Split the domain into subs |
2483 // Split the domain into subs |
2083 $subs = explode( '.', $domain ); |
2484 $subs = explode( '.', $domain ); |
2084 |
2485 |
2085 // Assume the domain will have at least two subs |
2486 // Assume the domain will have at least two subs |
2086 if ( 2 > count( $subs ) ) { |
2487 if ( 2 > count( $subs ) ) { |
2488 /** This filter is documented in wp-includes/formatting.php */ |
|
2087 return apply_filters( 'sanitize_email', '', $email, 'domain_no_periods' ); |
2489 return apply_filters( 'sanitize_email', '', $email, 'domain_no_periods' ); |
2088 } |
2490 } |
2089 |
2491 |
2090 // Create an array that will contain valid subs |
2492 // Create an array that will contain valid subs |
2091 $new_subs = array(); |
2493 $new_subs = array(); |
2104 } |
2506 } |
2105 } |
2507 } |
2106 |
2508 |
2107 // If there aren't 2 or more valid subs |
2509 // If there aren't 2 or more valid subs |
2108 if ( 2 > count( $new_subs ) ) { |
2510 if ( 2 > count( $new_subs ) ) { |
2511 /** This filter is documented in wp-includes/formatting.php */ |
|
2109 return apply_filters( 'sanitize_email', '', $email, 'domain_no_valid_subs' ); |
2512 return apply_filters( 'sanitize_email', '', $email, 'domain_no_valid_subs' ); |
2110 } |
2513 } |
2111 |
2514 |
2112 // Join valid subs into the new domain |
2515 // Join valid subs into the new domain |
2113 $domain = join( '.', $new_subs ); |
2516 $domain = join( '.', $new_subs ); |
2114 |
2517 |
2115 // Put the email back together |
2518 // Put the email back together |
2116 $email = $local . '@' . $domain; |
2519 $email = $local . '@' . $domain; |
2117 |
2520 |
2118 // Congratulations your email made it! |
2521 // Congratulations your email made it! |
2522 /** This filter is documented in wp-includes/formatting.php */ |
|
2119 return apply_filters( 'sanitize_email', $email, $email, null ); |
2523 return apply_filters( 'sanitize_email', $email, $email, null ); |
2120 } |
2524 } |
2121 |
2525 |
2122 /** |
2526 /** |
2123 * Determines the difference between two timestamps. |
2527 * Determines the difference between two timestamps. |
2130 * @param int $from Unix timestamp from which the difference begins. |
2534 * @param int $from Unix timestamp from which the difference begins. |
2131 * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. |
2535 * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. |
2132 * @return string Human readable time difference. |
2536 * @return string Human readable time difference. |
2133 */ |
2537 */ |
2134 function human_time_diff( $from, $to = '' ) { |
2538 function human_time_diff( $from, $to = '' ) { |
2135 if ( empty( $to ) ) |
2539 if ( empty( $to ) ) { |
2136 $to = time(); |
2540 $to = time(); |
2541 } |
|
2137 |
2542 |
2138 $diff = (int) abs( $to - $from ); |
2543 $diff = (int) abs( $to - $from ); |
2139 |
2544 |
2140 if ( $diff < HOUR_IN_SECONDS ) { |
2545 if ( $diff < HOUR_IN_SECONDS ) { |
2141 $mins = round( $diff / MINUTE_IN_SECONDS ); |
2546 $mins = round( $diff / MINUTE_IN_SECONDS ); |
2168 if ( $years <= 1 ) |
2573 if ( $years <= 1 ) |
2169 $years = 1; |
2574 $years = 1; |
2170 $since = sprintf( _n( '%s year', '%s years', $years ), $years ); |
2575 $since = sprintf( _n( '%s year', '%s years', $years ), $years ); |
2171 } |
2576 } |
2172 |
2577 |
2173 return $since; |
2578 /** |
2579 * Filter the human readable difference between two timestamps. |
|
2580 * |
|
2581 * @since 4.0.0 |
|
2582 * |
|
2583 * @param string $since The difference in human readable text. |
|
2584 * @param int $diff The difference in seconds. |
|
2585 * @param int $from Unix timestamp from which the difference begins. |
|
2586 * @param int $to Unix timestamp to end the time difference. |
|
2587 */ |
|
2588 return apply_filters( 'human_time_diff', $since, $diff, $from, $to ); |
|
2174 } |
2589 } |
2175 |
2590 |
2176 /** |
2591 /** |
2177 * Generates an excerpt from the content, if needed. |
2592 * Generates an excerpt from the content, if needed. |
2178 * |
2593 * |
2193 if ( '' == $text ) { |
2608 if ( '' == $text ) { |
2194 $text = get_the_content(''); |
2609 $text = get_the_content(''); |
2195 |
2610 |
2196 $text = strip_shortcodes( $text ); |
2611 $text = strip_shortcodes( $text ); |
2197 |
2612 |
2198 $text = apply_filters('the_content', $text); |
2613 /** This filter is documented in wp-includes/post-template.php */ |
2614 $text = apply_filters( 'the_content', $text ); |
|
2199 $text = str_replace(']]>', ']]>', $text); |
2615 $text = str_replace(']]>', ']]>', $text); |
2200 $excerpt_length = apply_filters('excerpt_length', 55); |
2616 |
2201 $excerpt_more = apply_filters('excerpt_more', ' ' . '[…]'); |
2617 /** |
2618 * Filter the number of words in an excerpt. |
|
2619 * |
|
2620 * @since 2.7.0 |
|
2621 * |
|
2622 * @param int $number The number of words. Default 55. |
|
2623 */ |
|
2624 $excerpt_length = apply_filters( 'excerpt_length', 55 ); |
|
2625 /** |
|
2626 * Filter the string in the "more" link displayed after a trimmed excerpt. |
|
2627 * |
|
2628 * @since 2.9.0 |
|
2629 * |
|
2630 * @param string $more_string The string shown within the more link. |
|
2631 */ |
|
2632 $excerpt_more = apply_filters( 'excerpt_more', ' ' . '[…]' ); |
|
2202 $text = wp_trim_words( $text, $excerpt_length, $excerpt_more ); |
2633 $text = wp_trim_words( $text, $excerpt_length, $excerpt_more ); |
2203 } |
2634 } |
2204 return apply_filters('wp_trim_excerpt', $text, $raw_excerpt); |
2635 /** |
2636 * Filter the trimmed excerpt string. |
|
2637 * |
|
2638 * @since 2.8.0 |
|
2639 * |
|
2640 * @param string $text The trimmed text. |
|
2641 * @param string $raw_excerpt The text prior to trimming. |
|
2642 */ |
|
2643 return apply_filters( 'wp_trim_excerpt', $text, $raw_excerpt ); |
|
2205 } |
2644 } |
2206 |
2645 |
2207 /** |
2646 /** |
2208 * Trims text to a certain number of words. |
2647 * Trims text to a certain number of words. |
2209 * |
2648 * |
2239 $text = implode( $sep, $words_array ); |
2678 $text = implode( $sep, $words_array ); |
2240 $text = $text . $more; |
2679 $text = $text . $more; |
2241 } else { |
2680 } else { |
2242 $text = implode( $sep, $words_array ); |
2681 $text = implode( $sep, $words_array ); |
2243 } |
2682 } |
2683 /** |
|
2684 * Filter the text content after words have been trimmed. |
|
2685 * |
|
2686 * @since 3.3.0 |
|
2687 * |
|
2688 * @param string $text The trimmed text. |
|
2689 * @param int $num_words The number of words to trim the text to. Default 5. |
|
2690 * @param string $more An optional string to append to the end of the trimmed text, e.g. …. |
|
2691 * @param string $original_text The text before it was trimmed. |
|
2692 */ |
|
2244 return apply_filters( 'wp_trim_words', $text, $num_words, $more, $original_text ); |
2693 return apply_filters( 'wp_trim_words', $text, $num_words, $more, $original_text ); |
2245 } |
2694 } |
2246 |
2695 |
2247 /** |
2696 /** |
2248 * Converts named entities into numbered entities. |
2697 * Converts named entities into numbered entities. |
2252 * @param string $text The text within which entities will be converted. |
2701 * @param string $text The text within which entities will be converted. |
2253 * @return string Text with converted entities. |
2702 * @return string Text with converted entities. |
2254 */ |
2703 */ |
2255 function ent2ncr($text) { |
2704 function ent2ncr($text) { |
2256 |
2705 |
2257 // Allow a plugin to short-circuit and override the mappings. |
2706 /** |
2707 * Filter text before named entities are converted into numbered entities. |
|
2708 * |
|
2709 * A non-null string must be returned for the filter to be evaluated. |
|
2710 * |
|
2711 * @since 3.3.0 |
|
2712 * |
|
2713 * @param null $converted_text The text to be converted. Default null. |
|
2714 * @param string $text The text prior to entity conversion. |
|
2715 */ |
|
2258 $filtered = apply_filters( 'pre_ent2ncr', null, $text ); |
2716 $filtered = apply_filters( 'pre_ent2ncr', null, $text ); |
2259 if( null !== $filtered ) |
2717 if( null !== $filtered ) |
2260 return $filtered; |
2718 return $filtered; |
2261 |
2719 |
2262 $to_ncr = array( |
2720 $to_ncr = array( |
2531 * |
2989 * |
2532 * @param string $text The text to be formatted. |
2990 * @param string $text The text to be formatted. |
2533 * @return string The formatted text after filter is applied. |
2991 * @return string The formatted text after filter is applied. |
2534 */ |
2992 */ |
2535 function wp_richedit_pre($text) { |
2993 function wp_richedit_pre($text) { |
2536 // Filtering a blank results in an annoying <br />\n |
2994 if ( empty( $text ) ) { |
2537 if ( empty($text) ) return apply_filters('richedit_pre', ''); |
2995 /** |
2996 * Filter text returned for the rich text editor. |
|
2997 * |
|
2998 * This filter is first evaluated, and the value returned, if an empty string |
|
2999 * is passed to wp_richedit_pre(). If an empty string is passed, it results |
|
3000 * in a break tag and line feed. |
|
3001 * |
|
3002 * If a non-empty string is passed, the filter is evaluated on the wp_richedit_pre() |
|
3003 * return after being formatted. |
|
3004 * |
|
3005 * @since 2.0.0 |
|
3006 * |
|
3007 * @param string $output Text for the rich text editor. |
|
3008 */ |
|
3009 return apply_filters( 'richedit_pre', '' ); |
|
3010 } |
|
2538 |
3011 |
2539 $output = convert_chars($text); |
3012 $output = convert_chars($text); |
2540 $output = wpautop($output); |
3013 $output = wpautop($output); |
2541 $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); |
3014 $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); |
2542 |
3015 |
2543 return apply_filters('richedit_pre', $output); |
3016 /** This filter is documented in wp-includes/formatting.php */ |
3017 return apply_filters( 'richedit_pre', $output ); |
|
2544 } |
3018 } |
2545 |
3019 |
2546 /** |
3020 /** |
2547 * Formats text for the HTML editor. |
3021 * Formats text for the HTML editor. |
2548 * |
3022 * |
2556 */ |
3030 */ |
2557 function wp_htmledit_pre($output) { |
3031 function wp_htmledit_pre($output) { |
2558 if ( !empty($output) ) |
3032 if ( !empty($output) ) |
2559 $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); // convert only < > & |
3033 $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); // convert only < > & |
2560 |
3034 |
2561 return apply_filters('htmledit_pre', $output); |
3035 /** |
3036 * Filter the text before it is formatted for the HTML editor. |
|
3037 * |
|
3038 * @since 2.5.0 |
|
3039 * |
|
3040 * @param string $output The HTML-formatted text. |
|
3041 */ |
|
3042 return apply_filters( 'htmledit_pre', $output ); |
|
2562 } |
3043 } |
2563 |
3044 |
2564 /** |
3045 /** |
2565 * Perform a deep string replace operation to ensure the values in $search are no longer present |
3046 * Perform a deep string replace operation to ensure the values in $search are no longer present |
2566 * |
3047 * |
2608 * A number of characters are removed from the URL. If the URL is for displaying |
3089 * A number of characters are removed from the URL. If the URL is for displaying |
2609 * (the default behaviour) ampersands are also replaced. The 'clean_url' filter |
3090 * (the default behaviour) ampersands are also replaced. The 'clean_url' filter |
2610 * is applied to the returned cleaned URL. |
3091 * is applied to the returned cleaned URL. |
2611 * |
3092 * |
2612 * @since 2.8.0 |
3093 * @since 2.8.0 |
2613 * @uses wp_kses_bad_protocol() To only permit protocols in the URL set |
|
2614 * via $protocols or the common ones set in the function. |
|
2615 * |
3094 * |
2616 * @param string $url The URL to be cleaned. |
3095 * @param string $url The URL to be cleaned. |
2617 * @param array $protocols Optional. An array of acceptable protocols. |
3096 * @param array $protocols Optional. An array of acceptable protocols. |
2618 * Defaults to 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn' if not set. |
3097 * Defaults to 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn' if not set. |
2619 * @param string $_context Private. Use esc_url_raw() for database usage. |
3098 * @param string $_context Private. Use esc_url_raw() for database usage. |
2651 $good_protocol_url = wp_kses_bad_protocol( $url, $protocols ); |
3130 $good_protocol_url = wp_kses_bad_protocol( $url, $protocols ); |
2652 if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) |
3131 if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) |
2653 return ''; |
3132 return ''; |
2654 } |
3133 } |
2655 |
3134 |
2656 return apply_filters('clean_url', $good_protocol_url, $original_url, $_context); |
3135 /** |
3136 * Filter a string cleaned and escaped for output as a URL. |
|
3137 * |
|
3138 * @since 2.3.0 |
|
3139 * |
|
3140 * @param string $good_protocol_url The cleaned URL to be returned. |
|
3141 * @param string $original_url The URL prior to cleaning. |
|
3142 * @param string $_context If 'display', replace ampersands and single quotes only. |
|
3143 */ |
|
3144 return apply_filters( 'clean_url', $good_protocol_url, $original_url, $_context ); |
|
2657 } |
3145 } |
2658 |
3146 |
2659 /** |
3147 /** |
2660 * Performs esc_url() for database usage. |
3148 * Performs esc_url() for database usage. |
2661 * |
3149 * |
2662 * @since 2.8.0 |
3150 * @since 2.8.0 |
2663 * @uses esc_url() |
|
2664 * |
3151 * |
2665 * @param string $url The URL to be cleaned. |
3152 * @param string $url The URL to be cleaned. |
2666 * @param array $protocols An array of acceptable protocols. |
3153 * @param array $protocols An array of acceptable protocols. |
2667 * @return string The cleaned URL. |
3154 * @return string The cleaned URL. |
2668 */ |
3155 */ |
2702 $safe_text = wp_check_invalid_utf8( $text ); |
3189 $safe_text = wp_check_invalid_utf8( $text ); |
2703 $safe_text = _wp_specialchars( $safe_text, ENT_COMPAT ); |
3190 $safe_text = _wp_specialchars( $safe_text, ENT_COMPAT ); |
2704 $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) ); |
3191 $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) ); |
2705 $safe_text = str_replace( "\r", '', $safe_text ); |
3192 $safe_text = str_replace( "\r", '', $safe_text ); |
2706 $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) ); |
3193 $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) ); |
3194 /** |
|
3195 * Filter a string cleaned and escaped for output in JavaScript. |
|
3196 * |
|
3197 * Text passed to esc_js() is stripped of invalid or special characters, |
|
3198 * and properly slashed for output. |
|
3199 * |
|
3200 * @since 2.0.6 |
|
3201 * |
|
3202 * @param string $safe_text The text after it has been escaped. |
|
3203 * @param string $text The text prior to being escaped. |
|
3204 */ |
|
2707 return apply_filters( 'js_escape', $safe_text, $text ); |
3205 return apply_filters( 'js_escape', $safe_text, $text ); |
2708 } |
3206 } |
2709 |
3207 |
2710 /** |
3208 /** |
2711 * Escaping for HTML blocks. |
3209 * Escaping for HTML blocks. |
2716 * @return string |
3214 * @return string |
2717 */ |
3215 */ |
2718 function esc_html( $text ) { |
3216 function esc_html( $text ) { |
2719 $safe_text = wp_check_invalid_utf8( $text ); |
3217 $safe_text = wp_check_invalid_utf8( $text ); |
2720 $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); |
3218 $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); |
3219 /** |
|
3220 * Filter a string cleaned and escaped for output in HTML. |
|
3221 * |
|
3222 * Text passed to esc_html() is stripped of invalid or special characters |
|
3223 * before output. |
|
3224 * |
|
3225 * @since 2.8.0 |
|
3226 * |
|
3227 * @param string $safe_text The text after it has been escaped. |
|
3228 * @param string $text The text prior to being escaped. |
|
3229 */ |
|
2721 return apply_filters( 'esc_html', $safe_text, $text ); |
3230 return apply_filters( 'esc_html', $safe_text, $text ); |
2722 } |
3231 } |
2723 |
3232 |
2724 /** |
3233 /** |
2725 * Escaping for HTML attributes. |
3234 * Escaping for HTML attributes. |
2730 * @return string |
3239 * @return string |
2731 */ |
3240 */ |
2732 function esc_attr( $text ) { |
3241 function esc_attr( $text ) { |
2733 $safe_text = wp_check_invalid_utf8( $text ); |
3242 $safe_text = wp_check_invalid_utf8( $text ); |
2734 $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); |
3243 $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); |
3244 /** |
|
3245 * Filter a string cleaned and escaped for output in an HTML attribute. |
|
3246 * |
|
3247 * Text passed to esc_attr() is stripped of invalid or special characters |
|
3248 * before output. |
|
3249 * |
|
3250 * @since 2.0.6 |
|
3251 * |
|
3252 * @param string $safe_text The text after it has been escaped. |
|
3253 * @param string $text The text prior to being escaped. |
|
3254 */ |
|
2735 return apply_filters( 'attribute_escape', $safe_text, $text ); |
3255 return apply_filters( 'attribute_escape', $safe_text, $text ); |
2736 } |
3256 } |
2737 |
3257 |
2738 /** |
3258 /** |
2739 * Escaping for textarea values. |
3259 * Escaping for textarea values. |
2743 * @param string $text |
3263 * @param string $text |
2744 * @return string |
3264 * @return string |
2745 */ |
3265 */ |
2746 function esc_textarea( $text ) { |
3266 function esc_textarea( $text ) { |
2747 $safe_text = htmlspecialchars( $text, ENT_QUOTES, get_option( 'blog_charset' ) ); |
3267 $safe_text = htmlspecialchars( $text, ENT_QUOTES, get_option( 'blog_charset' ) ); |
3268 /** |
|
3269 * Filter a string cleaned and escaped for output in a textarea element. |
|
3270 * |
|
3271 * @since 3.1.0 |
|
3272 * |
|
3273 * @param string $safe_text The text after it has been escaped. |
|
3274 * @param string $text The text prior to being escaped. |
|
3275 */ |
|
2748 return apply_filters( 'esc_textarea', $safe_text, $text ); |
3276 return apply_filters( 'esc_textarea', $safe_text, $text ); |
2749 } |
3277 } |
2750 |
3278 |
2751 /** |
3279 /** |
2752 * Escape an HTML tag name. |
3280 * Escape an HTML tag name. |
2756 * @param string $tag_name |
3284 * @param string $tag_name |
2757 * @return string |
3285 * @return string |
2758 */ |
3286 */ |
2759 function tag_escape($tag_name) { |
3287 function tag_escape($tag_name) { |
2760 $safe_tag = strtolower( preg_replace('/[^a-zA-Z0-9_:]/', '', $tag_name) ); |
3288 $safe_tag = strtolower( preg_replace('/[^a-zA-Z0-9_:]/', '', $tag_name) ); |
2761 return apply_filters('tag_escape', $safe_tag, $tag_name); |
3289 /** |
2762 } |
3290 * Filter a string cleaned and escaped for output as an HTML tag. |
2763 |
3291 * |
2764 /** |
3292 * @since 2.8.0 |
2765 * Escapes text for SQL LIKE special characters % and _. |
3293 * |
2766 * |
3294 * @param string $safe_tag The tag name after it has been escaped. |
2767 * @since 2.5.0 |
3295 * @param string $tag_name The text before it was escaped. |
2768 * |
3296 */ |
2769 * @param string $text The text to be escaped. |
3297 return apply_filters( 'tag_escape', $safe_tag, $tag_name ); |
2770 * @return string text, safe for inclusion in LIKE query. |
|
2771 */ |
|
2772 function like_escape($text) { |
|
2773 return str_replace(array("%", "_"), array("\\%", "\\_"), $text); |
|
2774 } |
3298 } |
2775 |
3299 |
2776 /** |
3300 /** |
2777 * Convert full URL paths to absolute paths. |
3301 * Convert full URL paths to absolute paths. |
2778 * |
3302 * |
2779 * Removes the http or https protocols and the domain. Keeps the path '/' at the |
3303 * Removes the http or https protocols and the domain. Keeps the path '/' at the |
2780 * beginning, so it isn't a true relative link, but from the web root base. |
3304 * beginning, so it isn't a true relative link, but from the web root base. |
2781 * |
3305 * |
2782 * @since 2.1.0 |
3306 * @since 2.1.0 |
3307 * @since 4.1.0 Support was added for relative URLs. |
|
2783 * |
3308 * |
2784 * @param string $link Full URL path. |
3309 * @param string $link Full URL path. |
2785 * @return string Absolute path. |
3310 * @return string Absolute path. |
2786 */ |
3311 */ |
2787 function wp_make_link_relative( $link ) { |
3312 function wp_make_link_relative( $link ) { |
2788 return preg_replace( '|https?://[^/]+(/.*)|i', '$1', $link ); |
3313 return preg_replace( '|^(https?:)?//[^/]+(/.*)|i', '$2', $link ); |
2789 } |
3314 } |
2790 |
3315 |
2791 /** |
3316 /** |
2792 * Sanitises various option values based on the nature of the option. |
3317 * Sanitises various option values based on the nature of the option. |
2793 * |
3318 * |
2799 * @param string $option The name of the option. |
3324 * @param string $option The name of the option. |
2800 * @param string $value The unsanitised value. |
3325 * @param string $value The unsanitised value. |
2801 * @return string Sanitized value. |
3326 * @return string Sanitized value. |
2802 */ |
3327 */ |
2803 function sanitize_option($option, $value) { |
3328 function sanitize_option($option, $value) { |
3329 global $wpdb; |
|
2804 |
3330 |
2805 switch ( $option ) { |
3331 switch ( $option ) { |
2806 case 'admin_email' : |
3332 case 'admin_email' : |
2807 case 'new_admin_email' : |
3333 case 'new_admin_email' : |
3334 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
|
2808 $value = sanitize_email( $value ); |
3335 $value = sanitize_email( $value ); |
2809 if ( ! is_email( $value ) ) { |
3336 if ( ! is_email( $value ) ) { |
2810 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
3337 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
2811 if ( function_exists( 'add_settings_error' ) ) |
3338 if ( function_exists( 'add_settings_error' ) ) |
2812 add_settings_error( $option, 'invalid_admin_email', __( 'The email address entered did not appear to be a valid email address. Please enter a valid email address.' ) ); |
3339 add_settings_error( $option, 'invalid_admin_email', __( 'The email address entered did not appear to be a valid email address. Please enter a valid email address.' ) ); |
2851 $value = 'closed'; |
3378 $value = 'closed'; |
2852 break; |
3379 break; |
2853 |
3380 |
2854 case 'blogdescription': |
3381 case 'blogdescription': |
2855 case 'blogname': |
3382 case 'blogname': |
3383 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
|
2856 $value = wp_kses_post( $value ); |
3384 $value = wp_kses_post( $value ); |
2857 $value = esc_html( $value ); |
3385 $value = esc_html( $value ); |
2858 break; |
3386 break; |
2859 |
3387 |
2860 case 'blog_charset': |
3388 case 'blog_charset': |
2873 case 'time_format': |
3401 case 'time_format': |
2874 case 'mailserver_url': |
3402 case 'mailserver_url': |
2875 case 'mailserver_login': |
3403 case 'mailserver_login': |
2876 case 'mailserver_pass': |
3404 case 'mailserver_pass': |
2877 case 'upload_path': |
3405 case 'upload_path': |
3406 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
|
2878 $value = strip_tags( $value ); |
3407 $value = strip_tags( $value ); |
2879 $value = wp_kses_data( $value ); |
3408 $value = wp_kses_data( $value ); |
2880 break; |
3409 break; |
2881 |
3410 |
2882 case 'ping_sites': |
3411 case 'ping_sites': |
2889 case 'gmt_offset': |
3418 case 'gmt_offset': |
2890 $value = preg_replace('/[^0-9:.-]/', '', $value); // strips slashes |
3419 $value = preg_replace('/[^0-9:.-]/', '', $value); // strips slashes |
2891 break; |
3420 break; |
2892 |
3421 |
2893 case 'siteurl': |
3422 case 'siteurl': |
3423 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
|
2894 if ( (bool)preg_match( '#http(s?)://(.+)#i', $value) ) { |
3424 if ( (bool)preg_match( '#http(s?)://(.+)#i', $value) ) { |
2895 $value = esc_url_raw($value); |
3425 $value = esc_url_raw($value); |
2896 } else { |
3426 } else { |
2897 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
3427 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
2898 if ( function_exists('add_settings_error') ) |
3428 if ( function_exists('add_settings_error') ) |
2899 add_settings_error('siteurl', 'invalid_siteurl', __('The WordPress address you entered did not appear to be a valid URL. Please enter a valid URL.')); |
3429 add_settings_error('siteurl', 'invalid_siteurl', __('The WordPress address you entered did not appear to be a valid URL. Please enter a valid URL.')); |
2900 } |
3430 } |
2901 break; |
3431 break; |
2902 |
3432 |
2903 case 'home': |
3433 case 'home': |
3434 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
|
2904 if ( (bool)preg_match( '#http(s?)://(.+)#i', $value) ) { |
3435 if ( (bool)preg_match( '#http(s?)://(.+)#i', $value) ) { |
2905 $value = esc_url_raw($value); |
3436 $value = esc_url_raw($value); |
2906 } else { |
3437 } else { |
2907 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
3438 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
2908 if ( function_exists('add_settings_error') ) |
3439 if ( function_exists('add_settings_error') ) |
2910 } |
3441 } |
2911 break; |
3442 break; |
2912 |
3443 |
2913 case 'WPLANG': |
3444 case 'WPLANG': |
2914 $allowed = get_available_languages(); |
3445 $allowed = get_available_languages(); |
2915 if ( ! in_array( $value, $allowed ) && ! empty( $value ) ) |
3446 if ( ! is_multisite() && defined( 'WPLANG' ) && '' !== WPLANG && 'en_US' !== WPLANG ) { |
3447 $allowed[] = WPLANG; |
|
3448 } |
|
3449 if ( ! in_array( $value, $allowed ) && ! empty( $value ) ) { |
|
2916 $value = get_option( $option ); |
3450 $value = get_option( $option ); |
3451 } |
|
2917 break; |
3452 break; |
2918 |
3453 |
2919 case 'illegal_names': |
3454 case 'illegal_names': |
3455 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
|
2920 if ( ! is_array( $value ) ) |
3456 if ( ! is_array( $value ) ) |
2921 $value = explode( ' ', $value ); |
3457 $value = explode( ' ', $value ); |
2922 |
3458 |
2923 $value = array_values( array_filter( array_map( 'trim', $value ) ) ); |
3459 $value = array_values( array_filter( array_map( 'trim', $value ) ) ); |
2924 |
3460 |
2926 $value = ''; |
3462 $value = ''; |
2927 break; |
3463 break; |
2928 |
3464 |
2929 case 'limited_email_domains': |
3465 case 'limited_email_domains': |
2930 case 'banned_email_domains': |
3466 case 'banned_email_domains': |
3467 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
|
2931 if ( ! is_array( $value ) ) |
3468 if ( ! is_array( $value ) ) |
2932 $value = explode( "\n", $value ); |
3469 $value = explode( "\n", $value ); |
2933 |
3470 |
2934 $domains = array_values( array_filter( array_map( 'trim', $value ) ) ); |
3471 $domains = array_values( array_filter( array_map( 'trim', $value ) ) ); |
2935 $value = array(); |
3472 $value = array(); |
2952 break; |
3489 break; |
2953 |
3490 |
2954 case 'permalink_structure': |
3491 case 'permalink_structure': |
2955 case 'category_base': |
3492 case 'category_base': |
2956 case 'tag_base': |
3493 case 'tag_base': |
3494 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
|
2957 $value = esc_url_raw( $value ); |
3495 $value = esc_url_raw( $value ); |
2958 $value = str_replace( 'http://', '', $value ); |
3496 $value = str_replace( 'http://', '', $value ); |
2959 break; |
3497 break; |
2960 |
3498 |
2961 case 'default_role' : |
3499 case 'default_role' : |
2962 if ( ! get_role( $value ) && get_role( 'subscriber' ) ) |
3500 if ( ! get_role( $value ) && get_role( 'subscriber' ) ) |
2963 $value = 'subscriber'; |
3501 $value = 'subscriber'; |
2964 break; |
3502 break; |
2965 } |
3503 |
2966 |
3504 case 'moderation_keys': |
2967 $value = apply_filters("sanitize_option_{$option}", $value, $option); |
3505 case 'blacklist_keys': |
3506 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
|
3507 $value = explode( "\n", $value ); |
|
3508 $value = array_filter( array_map( 'trim', $value ) ); |
|
3509 $value = array_unique( $value ); |
|
3510 $value = implode( "\n", $value ); |
|
3511 break; |
|
3512 } |
|
3513 |
|
3514 /** |
|
3515 * Filter an option value following sanitization. |
|
3516 * |
|
3517 * @since 2.3.0 |
|
3518 * |
|
3519 * @param string $value The sanitized option value. |
|
3520 * @param string $option The option name. |
|
3521 */ |
|
3522 $value = apply_filters( "sanitize_option_{$option}", $value, $option ); |
|
2968 |
3523 |
2969 return $value; |
3524 return $value; |
2970 } |
3525 } |
2971 |
3526 |
2972 /** |
3527 /** |
2974 * |
3529 * |
2975 * Uses {@link http://www.php.net/parse_str parse_str()} and stripslashes if |
3530 * Uses {@link http://www.php.net/parse_str parse_str()} and stripslashes if |
2976 * {@link http://www.php.net/magic_quotes magic_quotes_gpc} is on. |
3531 * {@link http://www.php.net/magic_quotes magic_quotes_gpc} is on. |
2977 * |
3532 * |
2978 * @since 2.2.1 |
3533 * @since 2.2.1 |
2979 * @uses apply_filters() for the 'wp_parse_str' filter. |
|
2980 * |
3534 * |
2981 * @param string $string The string to be parsed. |
3535 * @param string $string The string to be parsed. |
2982 * @param array $array Variables will be stored in this array. |
3536 * @param array $array Variables will be stored in this array. |
2983 */ |
3537 */ |
2984 function wp_parse_str( $string, &$array ) { |
3538 function wp_parse_str( $string, &$array ) { |
2985 parse_str( $string, $array ); |
3539 parse_str( $string, $array ); |
2986 if ( get_magic_quotes_gpc() ) |
3540 if ( get_magic_quotes_gpc() ) |
2987 $array = stripslashes_deep( $array ); |
3541 $array = stripslashes_deep( $array ); |
3542 /** |
|
3543 * Filter the array of variables derived from a parsed string. |
|
3544 * |
|
3545 * @since 2.3.0 |
|
3546 * |
|
3547 * @param array $array The array populated with variables. |
|
3548 */ |
|
2988 $array = apply_filters( 'wp_parse_str', $array ); |
3549 $array = apply_filters( 'wp_parse_str', $array ); |
2989 } |
3550 } |
2990 |
3551 |
2991 /** |
3552 /** |
2992 * Convert lone less than signs. |
3553 * Convert lone less than signs. |
2993 * |
3554 * |
2994 * KSES already converts lone greater than signs. |
3555 * KSES already converts lone greater than signs. |
2995 * |
3556 * |
2996 * @uses wp_pre_kses_less_than_callback in the callback function. |
|
2997 * @since 2.3.0 |
3557 * @since 2.3.0 |
2998 * |
3558 * |
2999 * @param string $text Text to be converted. |
3559 * @param string $text Text to be converted. |
3000 * @return string Converted text. |
3560 * @return string Converted text. |
3001 */ |
3561 */ |
3004 } |
3564 } |
3005 |
3565 |
3006 /** |
3566 /** |
3007 * Callback function used by preg_replace. |
3567 * Callback function used by preg_replace. |
3008 * |
3568 * |
3009 * @uses esc_html to format the $matches text. |
|
3010 * @since 2.3.0 |
3569 * @since 2.3.0 |
3011 * |
3570 * |
3012 * @param array $matches Populated by matches to preg_replace. |
3571 * @param array $matches Populated by matches to preg_replace. |
3013 * @return string The text returned after esc_html if needed. |
3572 * @return string The text returned after esc_html if needed. |
3014 */ |
3573 */ |
3023 * |
3582 * |
3024 * @since 2.5.0 |
3583 * @since 2.5.0 |
3025 * @link http://www.php.net/sprintf |
3584 * @link http://www.php.net/sprintf |
3026 * |
3585 * |
3027 * @param string $pattern The string which formatted args are inserted. |
3586 * @param string $pattern The string which formatted args are inserted. |
3028 * @param mixed $args,... Arguments to be formatted into the $pattern string. |
3587 * @param mixed $args ,... Arguments to be formatted into the $pattern string. |
3029 * @return string The formatted string. |
3588 * @return string The formatted string. |
3030 */ |
3589 */ |
3031 function wp_sprintf( $pattern ) { |
3590 function wp_sprintf( $pattern ) { |
3032 $args = func_get_args(); |
3591 $args = func_get_args(); |
3033 $len = strlen($pattern); |
3592 $len = strlen($pattern); |
3063 } else { |
3622 } else { |
3064 ++$arg_index; |
3623 ++$arg_index; |
3065 $arg = isset($args[$arg_index]) ? $args[$arg_index] : ''; |
3624 $arg = isset($args[$arg_index]) ? $args[$arg_index] : ''; |
3066 } |
3625 } |
3067 |
3626 |
3068 // Apply filters OR sprintf |
3627 /** |
3628 * Filter a fragment from the pattern passed to wp_sprintf(). |
|
3629 * |
|
3630 * If the fragment is unchanged, then sprintf() will be run on the fragment. |
|
3631 * |
|
3632 * @since 2.5.0 |
|
3633 * |
|
3634 * @param string $fragment A fragment from the pattern. |
|
3635 * @param string $arg The argument. |
|
3636 */ |
|
3069 $_fragment = apply_filters( 'wp_sprintf', $fragment, $arg ); |
3637 $_fragment = apply_filters( 'wp_sprintf', $fragment, $arg ); |
3070 if ( $_fragment != $fragment ) |
3638 if ( $_fragment != $fragment ) |
3071 $fragment = $_fragment; |
3639 $fragment = $_fragment; |
3072 else |
3640 else |
3073 $fragment = sprintf($fragment, strval($arg) ); |
3641 $fragment = sprintf($fragment, strval($arg) ); |
3100 |
3668 |
3101 // Nothing to work with |
3669 // Nothing to work with |
3102 if ( empty($args) ) |
3670 if ( empty($args) ) |
3103 return ''; |
3671 return ''; |
3104 |
3672 |
3105 // Translate and filter the delimiter set (avoid ampersands and entities here) |
3673 /** |
3106 $l = apply_filters('wp_sprintf_l', array( |
3674 * Filter the translated delimiters used by wp_sprintf_l(). |
3107 /* translators: used between list items, there is a space after the comma */ |
3675 * Placeholders (%s) are included to assist translators and then |
3108 'between' => __(', '), |
3676 * removed before the array of strings reaches the filter. |
3109 /* translators: used between list items, there is a space after the and */ |
3677 * |
3110 'between_last_two' => __(', and '), |
3678 * Please note: Ampersands and entities should be avoided here. |
3111 /* translators: used between only two list items, there is a space after the and */ |
3679 * |
3112 'between_only_two' => __(' and '), |
3680 * @since 2.5.0 |
3113 )); |
3681 * |
3682 * @param array $delimiters An array of translated delimiters. |
|
3683 */ |
|
3684 $l = apply_filters( 'wp_sprintf_l', array( |
|
3685 /* translators: used to join items in a list with more than 2 items */ |
|
3686 'between' => sprintf( __('%s, %s'), '', '' ), |
|
3687 /* translators: used to join last two items in a list with more than 2 times */ |
|
3688 'between_last_two' => sprintf( __('%s, and %s'), '', '' ), |
|
3689 /* translators: used to join items in a list with only 2 items */ |
|
3690 'between_only_two' => sprintf( __('%s and %s'), '', '' ), |
|
3691 ) ); |
|
3114 |
3692 |
3115 $args = (array) $args; |
3693 $args = (array) $args; |
3116 $result = array_shift($args); |
3694 $result = array_shift($args); |
3117 if ( count($args) == 1 ) |
3695 if ( count($args) == 1 ) |
3118 $result .= $l['between_only_two'] . array_shift($args); |
3696 $result .= $l['between_only_two'] . array_shift($args); |
3188 global $_links_add_base; |
3766 global $_links_add_base; |
3189 //1 = attribute name 2 = quotation mark 3 = URL |
3767 //1 = attribute name 2 = quotation mark 3 = URL |
3190 return $m[1] . '=' . $m[2] . |
3768 return $m[1] . '=' . $m[2] . |
3191 ( preg_match( '#^(\w{1,20}):#', $m[3], $protocol ) && in_array( $protocol[1], wp_allowed_protocols() ) ? |
3769 ( preg_match( '#^(\w{1,20}):#', $m[3], $protocol ) && in_array( $protocol[1], wp_allowed_protocols() ) ? |
3192 $m[3] : |
3770 $m[3] : |
3193 path_join( $_links_add_base, $m[3] ) ) |
3771 WP_HTTP::make_absolute_url( $m[3], $_links_add_base ) |
3772 ) |
|
3194 . $m[2]; |
3773 . $m[2]; |
3195 } |
3774 } |
3196 |
3775 |
3197 /** |
3776 /** |
3198 * Adds a Target attribute to all links in passed content. |
3777 * Adds a Target attribute to all links in passed content. |
3199 * |
3778 * |
3200 * This function by default only applies to <a> tags, however this can be |
3779 * This function by default only applies to `<a>` tags, however this can be |
3201 * modified by the 3rd param. |
3780 * modified by the 3rd param. |
3202 * |
3781 * |
3203 * <b>NOTE:</b> Any current target attributed will be stripped and replaced. |
3782 * *NOTE:* Any current target attributed will be stripped and replaced. |
3204 * |
3783 * |
3205 * @since 2.7.0 |
3784 * @since 2.7.0 |
3206 * |
3785 * |
3207 * @param string $content String to search for links in. |
3786 * @param string $content String to search for links in. |
3208 * @param string $target The Target to add to the links. |
3787 * @param string $target The Target to add to the links. |
3211 */ |
3790 */ |
3212 function links_add_target( $content, $target = '_blank', $tags = array('a') ) { |
3791 function links_add_target( $content, $target = '_blank', $tags = array('a') ) { |
3213 global $_links_add_target; |
3792 global $_links_add_target; |
3214 $_links_add_target = $target; |
3793 $_links_add_target = $target; |
3215 $tags = implode('|', (array)$tags); |
3794 $tags = implode('|', (array)$tags); |
3216 return preg_replace_callback( "!<($tags)(.+?)>!i", '_links_add_target', $content ); |
3795 return preg_replace_callback( "!<($tags)([^>]*)>!i", '_links_add_target', $content ); |
3217 } |
3796 } |
3218 |
3797 |
3219 /** |
3798 /** |
3220 * Callback to add a target attribute to all links in passed content. |
3799 * Callback to add a target attribute to all links in passed content. |
3221 * |
3800 * |
3226 * @return string The processed link. |
3805 * @return string The processed link. |
3227 */ |
3806 */ |
3228 function _links_add_target( $m ) { |
3807 function _links_add_target( $m ) { |
3229 global $_links_add_target; |
3808 global $_links_add_target; |
3230 $tag = $m[1]; |
3809 $tag = $m[1]; |
3231 $link = preg_replace('|(target=([\'"])(.*?)\2)|i', '', $m[2]); |
3810 $link = preg_replace('|( target=([\'"])(.*?)\2)|i', '', $m[2]); |
3232 return '<' . $tag . $link . ' target="' . esc_attr( $_links_add_target ) . '">'; |
3811 return '<' . $tag . $link . ' target="' . esc_attr( $_links_add_target ) . '">'; |
3233 } |
3812 } |
3234 |
3813 |
3235 /** |
3814 /** |
3236 * Normalize EOL characters and strip duplicate whitespace. |
3815 * Normalize EOL characters and strip duplicate whitespace. |
3247 return $str; |
3826 return $str; |
3248 } |
3827 } |
3249 |
3828 |
3250 /** |
3829 /** |
3251 * Properly strip all HTML tags including script and style |
3830 * Properly strip all HTML tags including script and style |
3831 * |
|
3832 * This differs from strip_tags() because it removes the contents of |
|
3833 * the `<script>` and `<style>` tags. E.g. `strip_tags( '<script>something</script>' )` |
|
3834 * will return 'something'. wp_strip_all_tags will return '' |
|
3252 * |
3835 * |
3253 * @since 2.9.0 |
3836 * @since 2.9.0 |
3254 * |
3837 * |
3255 * @param string $string String containing HTML tags |
3838 * @param string $string String containing HTML tags |
3256 * @param bool $remove_breaks optional Whether to remove left over line breaks and white space chars |
3839 * @param bool $remove_breaks optional Whether to remove left over line breaks and white space chars |
3300 if ( $found ) { |
3883 if ( $found ) { |
3301 // Strip out the whitespace that may now exist after removing the octets. |
3884 // Strip out the whitespace that may now exist after removing the octets. |
3302 $filtered = trim( preg_replace('/ +/', ' ', $filtered) ); |
3885 $filtered = trim( preg_replace('/ +/', ' ', $filtered) ); |
3303 } |
3886 } |
3304 |
3887 |
3305 return apply_filters('sanitize_text_field', $filtered, $str); |
3888 /** |
3889 * Filter a sanitized text field string. |
|
3890 * |
|
3891 * @since 2.9.0 |
|
3892 * |
|
3893 * @param string $filtered The sanitized string. |
|
3894 * @param string $str The string prior to being sanitized. |
|
3895 */ |
|
3896 return apply_filters( 'sanitize_text_field', $filtered, $str ); |
|
3306 } |
3897 } |
3307 |
3898 |
3308 /** |
3899 /** |
3309 * i18n friendly version of basename() |
3900 * i18n friendly version of basename() |
3310 * |
3901 * |
3325 * |
3916 * |
3326 * @since 3.0.0 |
3917 * @since 3.0.0 |
3327 */ |
3918 */ |
3328 function capital_P_dangit( $text ) { |
3919 function capital_P_dangit( $text ) { |
3329 // Simple replacement for titles |
3920 // Simple replacement for titles |
3330 if ( 'the_title' === current_filter() ) |
3921 $current_filter = current_filter(); |
3922 if ( 'the_title' === $current_filter || 'wp_title' === $current_filter ) |
|
3331 return str_replace( 'Wordpress', 'WordPress', $text ); |
3923 return str_replace( 'Wordpress', 'WordPress', $text ); |
3332 // Still here? Use the more judicious replacement |
3924 // Still here? Use the more judicious replacement |
3333 static $dblq = false; |
3925 static $dblq = false; |
3334 if ( false === $dblq ) |
3926 if ( false === $dblq ) |
3335 $dblq = _x( '“', 'opening curly double quote' ); |
3927 $dblq = _x( '“', 'opening curly double quote' ); |
3348 * @param string $mime_type Mime type |
3940 * @param string $mime_type Mime type |
3349 * @return string Sanitized mime type |
3941 * @return string Sanitized mime type |
3350 */ |
3942 */ |
3351 function sanitize_mime_type( $mime_type ) { |
3943 function sanitize_mime_type( $mime_type ) { |
3352 $sani_mime_type = preg_replace( '/[^-+*.a-zA-Z0-9\/]/', '', $mime_type ); |
3944 $sani_mime_type = preg_replace( '/[^-+*.a-zA-Z0-9\/]/', '', $mime_type ); |
3945 /** |
|
3946 * Filter a mime type following sanitization. |
|
3947 * |
|
3948 * @since 3.1.3 |
|
3949 * |
|
3950 * @param string $sani_mime_type The sanitized mime type. |
|
3951 * @param string $mime_type The mime type prior to sanitization. |
|
3952 */ |
|
3353 return apply_filters( 'sanitize_mime_type', $sani_mime_type, $mime_type ); |
3953 return apply_filters( 'sanitize_mime_type', $sani_mime_type, $mime_type ); |
3354 } |
3954 } |
3355 |
3955 |
3356 /** |
3956 /** |
3357 * Sanitize space or carriage return separated URLs that are used to send trackbacks. |
3957 * Sanitize space or carriage return separated URLs that are used to send trackbacks. |
3367 if ( !preg_match( '#^https?://.#i', $url ) ) |
3967 if ( !preg_match( '#^https?://.#i', $url ) ) |
3368 unset( $urls_to_ping[$k] ); |
3968 unset( $urls_to_ping[$k] ); |
3369 } |
3969 } |
3370 $urls_to_ping = array_map( 'esc_url_raw', $urls_to_ping ); |
3970 $urls_to_ping = array_map( 'esc_url_raw', $urls_to_ping ); |
3371 $urls_to_ping = implode( "\n", $urls_to_ping ); |
3971 $urls_to_ping = implode( "\n", $urls_to_ping ); |
3972 /** |
|
3973 * Filter a list of trackback URLs following sanitization. |
|
3974 * |
|
3975 * The string returned here consists of a space or carriage return-delimited list |
|
3976 * of trackback URLs. |
|
3977 * |
|
3978 * @since 3.4.0 |
|
3979 * |
|
3980 * @param string $urls_to_ping Sanitized space or carriage return separated URLs. |
|
3981 * @param string $to_ping Space or carriage return separated URLs before sanitization. |
|
3982 */ |
|
3372 return apply_filters( 'sanitize_trackback_urls', $urls_to_ping, $to_ping ); |
3983 return apply_filters( 'sanitize_trackback_urls', $urls_to_ping, $to_ping ); |
3373 } |
3984 } |
3374 |
3985 |
3375 /** |
3986 /** |
3376 * Add slashes to a string or array of strings. |
3987 * Add slashes to a string or array of strings. |
3421 * |
4032 * |
3422 * @param string $content A string which might contain a URL. |
4033 * @param string $content A string which might contain a URL. |
3423 * @return string The found URL. |
4034 * @return string The found URL. |
3424 */ |
4035 */ |
3425 function get_url_in_content( $content ) { |
4036 function get_url_in_content( $content ) { |
3426 if ( empty( $content ) ) |
4037 if ( empty( $content ) ) { |
3427 return ''; |
4038 return false; |
3428 |
4039 } |
3429 if ( preg_match( '/<a\s[^>]*?href=([\'"])(.+?)\1/is', $content, $matches ) ) |
4040 |
4041 if ( preg_match( '/<a\s[^>]*?href=([\'"])(.+?)\1/is', $content, $matches ) ) { |
|
3430 return esc_url_raw( $matches[2] ); |
4042 return esc_url_raw( $matches[2] ); |
4043 } |
|
3431 |
4044 |
3432 return false; |
4045 return false; |
3433 } |
4046 } |
4047 |
|
4048 /** |
|
4049 * Returns the regexp for common whitespace characters. |
|
4050 * |
|
4051 * By default, spaces include new lines, tabs, nbsp entities, and the UTF-8 nbsp. |
|
4052 * This is designed to replace the PCRE \s sequence. In ticket #22692, that |
|
4053 * sequence was found to be unreliable due to random inclusion of the A0 byte. |
|
4054 * |
|
4055 * @since 4.0.0 |
|
4056 * |
|
4057 * @return string The spaces regexp. |
|
4058 */ |
|
4059 function wp_spaces_regexp() { |
|
4060 static $spaces; |
|
4061 |
|
4062 if ( empty( $spaces ) ) { |
|
4063 /** |
|
4064 * Filter the regexp for common whitespace characters. |
|
4065 * |
|
4066 * This string is substituted for the \s sequence as needed in regular |
|
4067 * expressions. For websites not written in English, different characters |
|
4068 * may represent whitespace. For websites not encoded in UTF-8, the 0xC2 0xA0 |
|
4069 * sequence may not be in use. |
|
4070 * |
|
4071 * @since 4.0.0 |
|
4072 * |
|
4073 * @param string $spaces Regexp pattern for matching common whitespace characters. |
|
4074 */ |
|
4075 $spaces = apply_filters( 'wp_spaces_regexp', '[\r\n\t ]|\xC2\xA0| ' ); |
|
4076 } |
|
4077 |
|
4078 return $spaces; |
|
4079 } |
|
4080 |
|
4081 /** |
|
4082 * Print the important emoji-related styles. |
|
4083 * |
|
4084 * @since 4.2.0 |
|
4085 */ |
|
4086 function print_emoji_styles() { |
|
4087 static $printed = false; |
|
4088 |
|
4089 if ( $printed ) { |
|
4090 return; |
|
4091 } |
|
4092 |
|
4093 $printed = true; |
|
4094 ?> |
|
4095 <style type="text/css"> |
|
4096 img.wp-smiley, |
|
4097 img.emoji { |
|
4098 display: inline !important; |
|
4099 border: none !important; |
|
4100 box-shadow: none !important; |
|
4101 height: 1em !important; |
|
4102 width: 1em !important; |
|
4103 margin: 0 .07em !important; |
|
4104 vertical-align: -0.1em !important; |
|
4105 background: none !important; |
|
4106 padding: 0 !important; |
|
4107 } |
|
4108 </style> |
|
4109 <?php |
|
4110 } |
|
4111 |
|
4112 function print_emoji_detection_script() { |
|
4113 global $wp_version; |
|
4114 static $printed = false; |
|
4115 |
|
4116 if ( $printed ) { |
|
4117 return; |
|
4118 } |
|
4119 |
|
4120 $printed = true; |
|
4121 |
|
4122 $settings = array( |
|
4123 /** |
|
4124 * Filter the URL where emoji images are hosted. |
|
4125 * |
|
4126 * @since 4.2.0 |
|
4127 * |
|
4128 * @param string The emoji base URL. |
|
4129 */ |
|
4130 'baseUrl' => apply_filters( 'emoji_url', set_url_scheme( '//s.w.org/images/core/emoji/72x72/' ) ), |
|
4131 |
|
4132 /** |
|
4133 * Filter the extension of the emoji files. |
|
4134 * |
|
4135 * @since 4.2.0 |
|
4136 * |
|
4137 * @param string The emoji extension. Default .png. |
|
4138 */ |
|
4139 'ext' => apply_filters( 'emoji_ext', '.png' ), |
|
4140 ); |
|
4141 |
|
4142 $version = 'ver=' . $wp_version; |
|
4143 |
|
4144 if ( SCRIPT_DEBUG ) { |
|
4145 $settings['source'] = array( |
|
4146 /** This filter is documented in wp-includes/class.wp-scripts.php */ |
|
4147 'wpemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji.js?$version" ), 'wpemoji' ), |
|
4148 /** This filter is documented in wp-includes/class.wp-scripts.php */ |
|
4149 'twemoji' => apply_filters( 'script_loader_src', includes_url( "js/twemoji.js?$version" ), 'twemoji' ), |
|
4150 ); |
|
4151 |
|
4152 ?> |
|
4153 <script type="text/javascript"> |
|
4154 window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>; |
|
4155 <?php readfile( ABSPATH . WPINC . "/js/wp-emoji-loader.js" ); ?> |
|
4156 </script> |
|
4157 <?php |
|
4158 } else { |
|
4159 $settings['source'] = array( |
|
4160 /** This filter is documented in wp-includes/class.wp-scripts.php */ |
|
4161 'concatemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji-release.min.js?$version" ), 'concatemoji' ), |
|
4162 ); |
|
4163 |
|
4164 /* |
|
4165 * If you're looking at a src version of this file, you'll see an "include" |
|
4166 * statement below. This is used by the `grunt build` process to directly |
|
4167 * include a minified version of wp-emoji-loader.js, instead of using the |
|
4168 * readfile() method from above. |
|
4169 * |
|
4170 * If you're looking at a build version of this file, you'll see a string of |
|
4171 * minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG |
|
4172 * and edit wp-emoji-loader.js directly. |
|
4173 */ |
|
4174 ?> |
|
4175 <script type="text/javascript"> |
|
4176 window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>; |
|
4177 !function(a,b,c){function d(a){var c=b.createElement("canvas"),d=c.getContext&&c.getContext("2d");return d&&d.fillText?(d.textBaseline="top",d.font="600 32px Arial","flag"===a?(d.fillText(String.fromCharCode(55356,56812,55356,56807),0,0),c.toDataURL().length>3e3):(d.fillText(String.fromCharCode(55357,56835),0,0),0!==d.getImageData(16,16,1,1).data[0])):!1}function e(a){var c=b.createElement("script");c.src=a,c.type="text/javascript",b.getElementsByTagName("head")[0].appendChild(c)}var f,g;c.supports={simple:d("simple"),flag:d("flag")},c.DOMReady=!1,c.readyCallback=function(){c.DOMReady=!0},c.supports.simple&&c.supports.flag||(g=function(){c.readyCallback()},b.addEventListener?(b.addEventListener("DOMContentLoaded",g,!1),a.addEventListener("load",g,!1)):(a.attachEvent("onload",g),b.attachEvent("onreadystatechange",function(){"complete"===b.readyState&&c.readyCallback()})),f=c.source||{},f.concatemoji?e(f.concatemoji):f.wpemoji&&f.twemoji&&(e(f.twemoji),e(f.wpemoji)))}(window,document,window._wpemojiSettings); |
|
4178 </script> |
|
4179 <?php |
|
4180 } |
|
4181 } |
|
4182 |
|
4183 /** |
|
4184 * Convert any 4 byte emoji in a string to their equivalent HTML entity. |
|
4185 * |
|
4186 * Currently, only Unicode 7 emoji are supported. Skin tone modifiers are allowed, |
|
4187 * all other Unicode 8 emoji will be added when the spec is finalised. |
|
4188 * |
|
4189 * This allows us to store emoji in a DB using the utf8 character set. |
|
4190 * |
|
4191 * @since 4.2.0 |
|
4192 * |
|
4193 * @param string $content The content to encode. |
|
4194 * @return string The encoded content. |
|
4195 */ |
|
4196 function wp_encode_emoji( $content ) { |
|
4197 if ( function_exists( 'mb_convert_encoding' ) ) { |
|
4198 $regex = '/( |
|
4199 \x23\xE2\x83\xA3 # Digits |
|
4200 [\x30-\x39]\xE2\x83\xA3 |
|
4201 | \xF0\x9F[\x85-\x88][\xA6-\xBF] # Enclosed characters |
|
4202 | \xF0\x9F[\x8C-\x97][\x80-\xBF] # Misc |
|
4203 | \xF0\x9F\x98[\x80-\xBF] # Smilies |
|
4204 | \xF0\x9F\x99[\x80-\x8F] |
|
4205 | \xF0\x9F\x9A[\x80-\xBF] # Transport and map symbols |
|
4206 )/x'; |
|
4207 |
|
4208 $matches = array(); |
|
4209 if ( preg_match_all( $regex, $content, $matches ) ) { |
|
4210 if ( ! empty( $matches[1] ) ) { |
|
4211 foreach( $matches[1] as $emoji ) { |
|
4212 /* |
|
4213 * UTF-32's hex encoding is the same as HTML's hex encoding. |
|
4214 * So, by converting the emoji from UTF-8 to UTF-32, we magically |
|
4215 * get the correct hex encoding. |
|
4216 */ |
|
4217 $unpacked = unpack( 'H*', mb_convert_encoding( $emoji, 'UTF-32', 'UTF-8' ) ); |
|
4218 if ( isset( $unpacked[1] ) ) { |
|
4219 $entity = '&#x' . ltrim( $unpacked[1], '0' ) . ';'; |
|
4220 $content = str_replace( $emoji, $entity, $content ); |
|
4221 } |
|
4222 } |
|
4223 } |
|
4224 } |
|
4225 } |
|
4226 |
|
4227 return $content; |
|
4228 } |
|
4229 |
|
4230 /** |
|
4231 * Convert emoji to a static img element. |
|
4232 * |
|
4233 * @since 4.2.0 |
|
4234 * |
|
4235 * @param string $text The content to encode. |
|
4236 * @return string The encoded content. |
|
4237 */ |
|
4238 function wp_staticize_emoji( $text ) { |
|
4239 $text = wp_encode_emoji( $text ); |
|
4240 |
|
4241 /** This filter is documented in wp-includes/formatting.php */ |
|
4242 $cdn_url = apply_filters( 'emoji_url', set_url_scheme( '//s.w.org/images/core/emoji/72x72/' ) ); |
|
4243 |
|
4244 /** This filter is documented in wp-includes/formatting.php */ |
|
4245 $ext = apply_filters( 'emoji_ext', '.png' ); |
|
4246 |
|
4247 $output = ''; |
|
4248 /* |
|
4249 * HTML loop taken from smiley function, which was taken from texturize function. |
|
4250 * It'll never be consolidated. |
|
4251 * |
|
4252 * First, capture the tags as well as in between. |
|
4253 */ |
|
4254 $textarr = preg_split( '/(<.*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); |
|
4255 $stop = count( $textarr ); |
|
4256 |
|
4257 // Ignore processing of specific tags. |
|
4258 $tags_to_ignore = 'code|pre|style|script|textarea'; |
|
4259 $ignore_block_element = ''; |
|
4260 |
|
4261 for ( $i = 0; $i < $stop; $i++ ) { |
|
4262 $content = $textarr[$i]; |
|
4263 |
|
4264 // If we're in an ignore block, wait until we find its closing tag. |
|
4265 if ( '' == $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')>/', $content, $matches ) ) { |
|
4266 $ignore_block_element = $matches[1]; |
|
4267 } |
|
4268 |
|
4269 // If it's not a tag and not in ignore block. |
|
4270 if ( '' == $ignore_block_element && strlen( $content ) > 0 && '<' != $content[0] ) { |
|
4271 $matches = array(); |
|
4272 if ( preg_match_all( '/(DZ(e[6-9a-f]|f[0-9a-f]);){2}/', $content, $matches ) ) { |
|
4273 if ( ! empty( $matches[0] ) ) { |
|
4274 foreach ( $matches[0] as $flag ) { |
|
4275 $chars = str_replace( array( '&#x', ';'), '', $flag ); |
|
4276 |
|
4277 list( $char1, $char2 ) = str_split( $chars, 5 ); |
|
4278 $entity = sprintf( '<img src="%s" alt="%s" class="wp-smiley" style="height: 1em; max-height: 1em;" />', $cdn_url . $char1 . '-' . $char2 . $ext, html_entity_decode( $flag ) ); |
|
4279 |
|
4280 $content = str_replace( $flag, $entity, $content ); |
|
4281 } |
|
4282 } |
|
4283 } |
|
4284 |
|
4285 // Loosely match the Emoji Unicode range. |
|
4286 $regex = '/(&#x[2-3][0-9a-f]{3};|[1-6][0-9a-f]{2};)/'; |
|
4287 |
|
4288 $matches = array(); |
|
4289 if ( preg_match_all( $regex, $content, $matches ) ) { |
|
4290 if ( ! empty( $matches[1] ) ) { |
|
4291 foreach ( $matches[1] as $emoji ) { |
|
4292 $char = str_replace( array( '&#x', ';'), '', $emoji ); |
|
4293 $entity = sprintf( '<img src="%s" alt="%s" class="wp-smiley" style="height: 1em; max-height: 1em;" />', $cdn_url . $char . $ext, html_entity_decode( $emoji ) ); |
|
4294 |
|
4295 $content = str_replace( $emoji, $entity, $content ); |
|
4296 } |
|
4297 } |
|
4298 } |
|
4299 } |
|
4300 |
|
4301 // Did we exit ignore block. |
|
4302 if ( '' != $ignore_block_element && '</' . $ignore_block_element . '>' == $content ) { |
|
4303 $ignore_block_element = ''; |
|
4304 } |
|
4305 |
|
4306 $output .= $content; |
|
4307 } |
|
4308 |
|
4309 return $output; |
|
4310 } |
|
4311 |
|
4312 /** |
|
4313 * Convert emoji in emails into static images. |
|
4314 * |
|
4315 * @since 4.2.0 |
|
4316 * |
|
4317 * @param array $mail The email data array. |
|
4318 * @return array The email data array, with emoji in the message staticized. |
|
4319 */ |
|
4320 function wp_staticize_emoji_for_email( $mail ) { |
|
4321 if ( ! isset( $mail['message'] ) ) { |
|
4322 return $mail; |
|
4323 } |
|
4324 |
|
4325 /* |
|
4326 * We can only transform the emoji into images if it's a text/html email. |
|
4327 * To do that, here's a cut down version of the same process that happens |
|
4328 * in wp_mail() - get the Content-Type from the headers, if there is one, |
|
4329 * then pass it through the wp_mail_content_type filter, in case a plugin |
|
4330 * is handling changing the Content-Type. |
|
4331 */ |
|
4332 $headers = array(); |
|
4333 if ( isset( $mail['headers'] ) ) { |
|
4334 if ( is_array( $mail['headers'] ) ) { |
|
4335 $headers = $mail['headers']; |
|
4336 } else { |
|
4337 $headers = explode( "\n", str_replace( "\r\n", "\n", $mail['headers'] ) ); |
|
4338 } |
|
4339 } |
|
4340 |
|
4341 foreach ( $headers as $header ) { |
|
4342 if ( strpos($header, ':') === false ) { |
|
4343 continue; |
|
4344 } |
|
4345 |
|
4346 // Explode them out. |
|
4347 list( $name, $content ) = explode( ':', trim( $header ), 2 ); |
|
4348 |
|
4349 // Cleanup crew. |
|
4350 $name = trim( $name ); |
|
4351 $content = trim( $content ); |
|
4352 |
|
4353 if ( 'content-type' === strtolower( $name ) ) { |
|
4354 if ( strpos( $content, ';' ) !== false ) { |
|
4355 list( $type, $charset ) = explode( ';', $content ); |
|
4356 $content_type = trim( $type ); |
|
4357 } else { |
|
4358 $content_type = trim( $content ); |
|
4359 } |
|
4360 break; |
|
4361 } |
|
4362 } |
|
4363 |
|
4364 // Set Content-Type if we don't have a content-type from the input headers. |
|
4365 if ( ! isset( $content_type ) ) { |
|
4366 $content_type = 'text/plain'; |
|
4367 } |
|
4368 |
|
4369 /** This filter is documented in wp-includes/pluggable.php */ |
|
4370 $content_type = apply_filters( 'wp_mail_content_type', $content_type ); |
|
4371 |
|
4372 if ( 'text/html' === $content_type ) { |
|
4373 $mail['message'] = wp_staticize_emoji( $mail['message'] ); |
|
4374 } |
|
4375 |
|
4376 return $mail; |
|
4377 } |