changeset 7 | cf61fcea0001 |
parent 5 | 5e2f62d02dcd |
child 9 | 177826044cd9 |
6:490d5cc509ed | 7:cf61fcea0001 |
---|---|
18 * |
18 * |
19 * ’cause today’s effort makes it worth tomorrow’s “holiday” … |
19 * ’cause today’s effort makes it worth tomorrow’s “holiday” … |
20 * |
20 * |
21 * Code within certain html blocks are skipped. |
21 * Code within certain html blocks are skipped. |
22 * |
22 * |
23 * Do not use this function before the {@see 'init'} action hook; everything will break. |
|
24 * |
|
23 * @since 0.71 |
25 * @since 0.71 |
24 * @uses $wp_cockneyreplace Array of formatted entities for certain common phrases |
26 * |
27 * @global array $wp_cockneyreplace Array of formatted entities for certain common phrases |
|
28 * @global array $shortcode_tags |
|
29 * @staticvar array $static_characters |
|
30 * @staticvar array $static_replacements |
|
31 * @staticvar array $dynamic_characters |
|
32 * @staticvar array $dynamic_replacements |
|
33 * @staticvar array $default_no_texturize_tags |
|
34 * @staticvar array $default_no_texturize_shortcodes |
|
35 * @staticvar bool $run_texturize |
|
36 * @staticvar string $apos |
|
37 * @staticvar string $prime |
|
38 * @staticvar string $double_prime |
|
39 * @staticvar string $opening_quote |
|
40 * @staticvar string $closing_quote |
|
41 * @staticvar string $opening_single_quote |
|
42 * @staticvar string $closing_single_quote |
|
43 * @staticvar string $open_q_flag |
|
44 * @staticvar string $open_sq_flag |
|
45 * @staticvar string $apos_flag |
|
25 * |
46 * |
26 * @param string $text The text to be formatted |
47 * @param string $text The text to be formatted |
27 * @param bool $reset Set to true for unit testing. Translated patterns will reset. |
48 * @param bool $reset Set to true for unit testing. Translated patterns will reset. |
28 * @return string The string replaced with html entities |
49 * @return string The string replaced with html entities |
29 */ |
50 */ |
30 function wptexturize($text, $reset = false) { |
51 function wptexturize( $text, $reset = false ) { |
31 global $wp_cockneyreplace, $shortcode_tags; |
52 global $wp_cockneyreplace, $shortcode_tags; |
32 static $static_characters, $static_replacements, $dynamic_characters, $dynamic_replacements, |
53 static $static_characters = null, |
33 $default_no_texturize_tags, $default_no_texturize_shortcodes, $run_texturize = true; |
54 $static_replacements = null, |
55 $dynamic_characters = null, |
|
56 $dynamic_replacements = null, |
|
57 $default_no_texturize_tags = null, |
|
58 $default_no_texturize_shortcodes = null, |
|
59 $run_texturize = true, |
|
60 $apos = null, |
|
61 $prime = null, |
|
62 $double_prime = null, |
|
63 $opening_quote = null, |
|
64 $closing_quote = null, |
|
65 $opening_single_quote = null, |
|
66 $closing_single_quote = null, |
|
67 $open_q_flag = '<!--oq-->', |
|
68 $open_sq_flag = '<!--osq-->', |
|
69 $apos_flag = '<!--apos-->'; |
|
34 |
70 |
35 // If there's nothing to do, just stop. |
71 // If there's nothing to do, just stop. |
36 if ( empty( $text ) || false === $run_texturize ) { |
72 if ( empty( $text ) || false === $run_texturize ) { |
37 return $text; |
73 return $text; |
38 } |
74 } |
39 |
75 |
40 // Set up static variables. Run once only. |
76 // Set up static variables. Run once only. |
41 if ( $reset || ! isset( $static_characters ) ) { |
77 if ( $reset || ! isset( $static_characters ) ) { |
42 /** |
78 /** |
43 * Filter whether to skip running wptexturize(). |
79 * Filters whether to skip running wptexturize(). |
44 * |
80 * |
45 * Passing false to the filter will effectively short-circuit wptexturize(). |
81 * Passing false to the filter will effectively short-circuit wptexturize(). |
46 * returning the original text passed to the function instead. |
82 * returning the original text passed to the function instead. |
47 * |
83 * |
48 * The filter runs only once, the first time wptexturize() is called. |
84 * The filter runs only once, the first time wptexturize() is called. |
86 |
122 |
87 // if a plugin has provided an autocorrect array, use it |
123 // if a plugin has provided an autocorrect array, use it |
88 if ( isset($wp_cockneyreplace) ) { |
124 if ( isset($wp_cockneyreplace) ) { |
89 $cockney = array_keys( $wp_cockneyreplace ); |
125 $cockney = array_keys( $wp_cockneyreplace ); |
90 $cockneyreplace = array_values( $wp_cockneyreplace ); |
126 $cockneyreplace = array_values( $wp_cockneyreplace ); |
91 } elseif ( "'" != $apos ) { // Only bother if we're doing a replacement. |
|
92 $cockney = array( "'tain't", "'twere", "'twas", "'tis", "'twill", "'til", "'bout", "'nuff", "'round", "'cause", "'em" ); |
|
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" ); |
|
94 } else { |
127 } else { |
95 $cockney = $cockneyreplace = array(); |
128 /* translators: This is a comma-separated list of words that defy the syntax of quotations in normal use, |
129 * for example... 'We do not have enough words yet' ... is a typical quoted phrase. But when we write |
|
130 * lines of code 'til we have enough of 'em, then we need to insert apostrophes instead of quotes. |
|
131 */ |
|
132 $cockney = explode( ',', _x( "'tain't,'twere,'twas,'tis,'twill,'til,'bout,'nuff,'round,'cause,'em", |
|
133 'Comma-separated list of words to texturize in your language' ) ); |
|
134 |
|
135 $cockneyreplace = explode( ',', _x( '’tain’t,’twere,’twas,’tis,’twill,’til,’bout,’nuff,’round,’cause,’em', |
|
136 'Comma-separated list of replacement words in your language' ) ); |
|
96 } |
137 } |
97 |
138 |
98 $static_characters = array_merge( array( '...', '``', '\'\'', ' (tm)' ), $cockney ); |
139 $static_characters = array_merge( array( '...', '``', '\'\'', ' (tm)' ), $cockney ); |
99 $static_replacements = array_merge( array( '…', $opening_quote, $closing_quote, ' ™' ), $cockneyreplace ); |
140 $static_replacements = array_merge( array( '…', $opening_quote, $closing_quote, ' ™' ), $cockneyreplace ); |
100 |
141 |
106 $dynamic = array(); |
147 $dynamic = array(); |
107 $spaces = wp_spaces_regexp(); |
148 $spaces = wp_spaces_regexp(); |
108 |
149 |
109 // '99' and '99" are ambiguous among other patterns; assume it's an abbreviated year at the end of a quotation. |
150 // '99' and '99" are ambiguous among other patterns; assume it's an abbreviated year at the end of a quotation. |
110 if ( "'" !== $apos || "'" !== $closing_single_quote ) { |
151 if ( "'" !== $apos || "'" !== $closing_single_quote ) { |
111 $dynamic[ '/\'(\d\d)\'(?=\Z|[.,)}\-\]]|>|' . $spaces . ')/' ] = $apos . '$1' . $closing_single_quote; |
152 $dynamic[ '/\'(\d\d)\'(?=\Z|[.,:;!?)}\-\]]|>|' . $spaces . ')/' ] = $apos_flag . '$1' . $closing_single_quote; |
112 } |
153 } |
113 if ( "'" !== $apos || '"' !== $closing_quote ) { |
154 if ( "'" !== $apos || '"' !== $closing_quote ) { |
114 $dynamic[ '/\'(\d\d)"(?=\Z|[.,)}\-\]]|>|' . $spaces . ')/' ] = $apos . '$1' . $closing_quote; |
155 $dynamic[ '/\'(\d\d)"(?=\Z|[.,:;!?)}\-\]]|>|' . $spaces . ')/' ] = $apos_flag . '$1' . $closing_quote; |
115 } |
156 } |
116 |
157 |
117 // '99 '99s '99's (apostrophe) But never '9 or '99% or '999 or '99.0. |
158 // '99 '99s '99's (apostrophe) But never '9 or '99% or '999 or '99.0. |
118 if ( "'" !== $apos ) { |
159 if ( "'" !== $apos ) { |
119 $dynamic[ '/\'(?=\d\d(?:\Z|(?![%\d]|[.,]\d)))/' ] = $apos; |
160 $dynamic[ '/\'(?=\d\d(?:\Z|(?![%\d]|[.,]\d)))/' ] = $apos_flag; |
120 } |
161 } |
121 |
162 |
122 // Quoted Numbers like '0.42' |
163 // Quoted Numbers like '0.42' |
123 if ( "'" !== $opening_single_quote && "'" !== $closing_single_quote ) { |
164 if ( "'" !== $opening_single_quote && "'" !== $closing_single_quote ) { |
124 $dynamic[ '/(?<=\A|' . $spaces . ')\'(\d[.,\d]*)\'/' ] = $opening_single_quote . '$1' . $closing_single_quote; |
165 $dynamic[ '/(?<=\A|' . $spaces . ')\'(\d[.,\d]*)\'/' ] = $open_sq_flag . '$1' . $closing_single_quote; |
125 } |
166 } |
126 |
167 |
127 // Single quote at start, or preceded by (, {, <, [, ", -, or spaces. |
168 // Single quote at start, or preceded by (, {, <, [, ", -, or spaces. |
128 if ( "'" !== $opening_single_quote ) { |
169 if ( "'" !== $opening_single_quote ) { |
129 $dynamic[ '/(?<=\A|[([{"\-]|<|' . $spaces . ')\'/' ] = $opening_single_quote; |
170 $dynamic[ '/(?<=\A|[([{"\-]|<|' . $spaces . ')\'/' ] = $open_sq_flag; |
130 } |
171 } |
131 |
172 |
132 // Apostrophe in a word. No spaces, double apostrophes, or other punctuation. |
173 // Apostrophe in a word. No spaces, double apostrophes, or other punctuation. |
133 if ( "'" !== $apos ) { |
174 if ( "'" !== $apos ) { |
134 $dynamic[ '/(?<!' . $spaces . ')\'(?!\Z|[.,:;"\'(){}[\]\-]|&[lg]t;|' . $spaces . ')/' ] = $apos; |
175 $dynamic[ '/(?<!' . $spaces . ')\'(?!\Z|[.,:;!?"\'(){}[\]\-]|&[lg]t;|' . $spaces . ')/' ] = $apos_flag; |
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 } |
176 } |
146 |
177 |
147 $dynamic_characters['apos'] = array_keys( $dynamic ); |
178 $dynamic_characters['apos'] = array_keys( $dynamic ); |
148 $dynamic_replacements['apos'] = array_values( $dynamic ); |
179 $dynamic_replacements['apos'] = array_values( $dynamic ); |
149 $dynamic = array(); |
180 $dynamic = array(); |
150 |
181 |
151 // Quoted Numbers like "42" |
182 // Quoted Numbers like "42" |
152 if ( '"' !== $opening_quote && '"' !== $closing_quote ) { |
183 if ( '"' !== $opening_quote && '"' !== $closing_quote ) { |
153 $dynamic[ '/(?<=\A|' . $spaces . ')"(\d[.,\d]*)"/' ] = $opening_quote . '$1' . $closing_quote; |
184 $dynamic[ '/(?<=\A|' . $spaces . ')"(\d[.,\d]*)"/' ] = $open_q_flag . '$1' . $closing_quote; |
154 } |
|
155 |
|
156 // 9" (double prime) |
|
157 if ( '"' !== $double_prime ) { |
|
158 $dynamic[ '/(?<=\d)"/' ] = $double_prime; |
|
159 } |
185 } |
160 |
186 |
161 // Double quote at start, or preceded by (, {, <, [, -, or spaces, and not followed by spaces. |
187 // Double quote at start, or preceded by (, {, <, [, -, or spaces, and not followed by spaces. |
162 if ( '"' !== $opening_quote ) { |
188 if ( '"' !== $opening_quote ) { |
163 $dynamic[ '/(?<=\A|[([{\-]|<|' . $spaces . ')"(?!' . $spaces . ')/' ] = $opening_quote; |
189 $dynamic[ '/(?<=\A|[([{\-]|<|' . $spaces . ')"(?!' . $spaces . ')/' ] = $open_q_flag; |
164 } |
|
165 |
|
166 // Any remaining double quotes. |
|
167 if ( '"' !== $closing_quote ) { |
|
168 $dynamic[ '/"/' ] = $closing_quote; |
|
169 } |
190 } |
170 |
191 |
171 $dynamic_characters['quote'] = array_keys( $dynamic ); |
192 $dynamic_characters['quote'] = array_keys( $dynamic ); |
172 $dynamic_replacements['quote'] = array_values( $dynamic ); |
193 $dynamic_replacements['quote'] = array_values( $dynamic ); |
173 $dynamic = array(); |
194 $dynamic = array(); |
182 $dynamic_replacements['dash'] = array_values( $dynamic ); |
203 $dynamic_replacements['dash'] = array_values( $dynamic ); |
183 } |
204 } |
184 |
205 |
185 // Must do this every time in case plugins use these filters in a context sensitive manner |
206 // Must do this every time in case plugins use these filters in a context sensitive manner |
186 /** |
207 /** |
187 * Filter the list of HTML elements not to texturize. |
208 * Filters the list of HTML elements not to texturize. |
188 * |
209 * |
189 * @since 2.8.0 |
210 * @since 2.8.0 |
190 * |
211 * |
191 * @param array $default_no_texturize_tags An array of HTML element names. |
212 * @param array $default_no_texturize_tags An array of HTML element names. |
192 */ |
213 */ |
193 $no_texturize_tags = apply_filters( 'no_texturize_tags', $default_no_texturize_tags ); |
214 $no_texturize_tags = apply_filters( 'no_texturize_tags', $default_no_texturize_tags ); |
194 /** |
215 /** |
195 * Filter the list of shortcodes not to texturize. |
216 * Filters the list of shortcodes not to texturize. |
196 * |
217 * |
197 * @since 2.8.0 |
218 * @since 2.8.0 |
198 * |
219 * |
199 * @param array $default_no_texturize_shortcodes An array of shortcode names. |
220 * @param array $default_no_texturize_shortcodes An array of shortcode names. |
200 */ |
221 */ |
203 $no_texturize_tags_stack = array(); |
224 $no_texturize_tags_stack = array(); |
204 $no_texturize_shortcodes_stack = array(); |
225 $no_texturize_shortcodes_stack = array(); |
205 |
226 |
206 // Look for shortcodes and HTML elements. |
227 // Look for shortcodes and HTML elements. |
207 |
228 |
208 $tagnames = array_keys( $shortcode_tags ); |
229 preg_match_all( '@\[/?([^<>&/\[\]\x00-\x20=]++)@', $text, $matches ); |
230 $tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] ); |
|
231 $found_shortcodes = ! empty( $tagnames ); |
|
232 $shortcode_regex = $found_shortcodes ? _get_wptexturize_shortcode_regex( $tagnames ) : ''; |
|
233 $regex = _get_wptexturize_split_regex( $shortcode_regex ); |
|
234 |
|
235 $textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); |
|
236 |
|
237 foreach ( $textarr as &$curl ) { |
|
238 // Only call _wptexturize_pushpop_element if $curl is a delimiter. |
|
239 $first = $curl[0]; |
|
240 if ( '<' === $first ) { |
|
241 if ( '<!--' === substr( $curl, 0, 4 ) ) { |
|
242 // This is an HTML comment delimiter. |
|
243 continue; |
|
244 } else { |
|
245 // This is an HTML element delimiter. |
|
246 |
|
247 // Replace each & with & unless it already looks like an entity. |
|
248 $curl = preg_replace( '/&(?!#(?:\d+|x[a-f0-9]+);|[a-z1-4]{1,8};)/i', '&', $curl ); |
|
249 |
|
250 _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags ); |
|
251 } |
|
252 |
|
253 } elseif ( '' === trim( $curl ) ) { |
|
254 // This is a newline between delimiters. Performance improves when we check this. |
|
255 continue; |
|
256 |
|
257 } elseif ( '[' === $first && $found_shortcodes && 1 === preg_match( '/^' . $shortcode_regex . '$/', $curl ) ) { |
|
258 // This is a shortcode delimiter. |
|
259 |
|
260 if ( '[[' !== substr( $curl, 0, 2 ) && ']]' !== substr( $curl, -2 ) ) { |
|
261 // Looks like a normal shortcode. |
|
262 _wptexturize_pushpop_element( $curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes ); |
|
263 } else { |
|
264 // Looks like an escaped shortcode. |
|
265 continue; |
|
266 } |
|
267 |
|
268 } elseif ( empty( $no_texturize_shortcodes_stack ) && empty( $no_texturize_tags_stack ) ) { |
|
269 // This is neither a delimiter, nor is this content inside of no_texturize pairs. Do texturize. |
|
270 |
|
271 $curl = str_replace( $static_characters, $static_replacements, $curl ); |
|
272 |
|
273 if ( false !== strpos( $curl, "'" ) ) { |
|
274 $curl = preg_replace( $dynamic_characters['apos'], $dynamic_replacements['apos'], $curl ); |
|
275 $curl = wptexturize_primes( $curl, "'", $prime, $open_sq_flag, $closing_single_quote ); |
|
276 $curl = str_replace( $apos_flag, $apos, $curl ); |
|
277 $curl = str_replace( $open_sq_flag, $opening_single_quote, $curl ); |
|
278 } |
|
279 if ( false !== strpos( $curl, '"' ) ) { |
|
280 $curl = preg_replace( $dynamic_characters['quote'], $dynamic_replacements['quote'], $curl ); |
|
281 $curl = wptexturize_primes( $curl, '"', $double_prime, $open_q_flag, $closing_quote ); |
|
282 $curl = str_replace( $open_q_flag, $opening_quote, $curl ); |
|
283 } |
|
284 if ( false !== strpos( $curl, '-' ) ) { |
|
285 $curl = preg_replace( $dynamic_characters['dash'], $dynamic_replacements['dash'], $curl ); |
|
286 } |
|
287 |
|
288 // 9x9 (times), but never 0x9999 |
|
289 if ( 1 === preg_match( '/(?<=\d)x\d/', $curl ) ) { |
|
290 // Searching for a digit is 10 times more expensive than for the x, so we avoid doing this one! |
|
291 $curl = preg_replace( '/\b(\d(?(?<=0)[\d\.,]+|[\d\.,]*))x(\d[\d\.,]*)\b/', '$1×$2', $curl ); |
|
292 } |
|
293 |
|
294 // Replace each & with & unless it already looks like an entity. |
|
295 $curl = preg_replace( '/&(?!#(?:\d+|x[a-f0-9]+);|[a-z1-4]{1,8};)/i', '&', $curl ); |
|
296 } |
|
297 } |
|
298 |
|
299 return implode( '', $textarr ); |
|
300 } |
|
301 |
|
302 /** |
|
303 * Implements a logic tree to determine whether or not "7'." represents seven feet, |
|
304 * then converts the special char into either a prime char or a closing quote char. |
|
305 * |
|
306 * @since 4.3.0 |
|
307 * |
|
308 * @param string $haystack The plain text to be searched. |
|
309 * @param string $needle The character to search for such as ' or ". |
|
310 * @param string $prime The prime char to use for replacement. |
|
311 * @param string $open_quote The opening quote char. Opening quote replacement must be |
|
312 * accomplished already. |
|
313 * @param string $close_quote The closing quote char to use for replacement. |
|
314 * @return string The $haystack value after primes and quotes replacements. |
|
315 */ |
|
316 function wptexturize_primes( $haystack, $needle, $prime, $open_quote, $close_quote ) { |
|
317 $spaces = wp_spaces_regexp(); |
|
318 $flag = '<!--wp-prime-or-quote-->'; |
|
319 $quote_pattern = "/$needle(?=\\Z|[.,:;!?)}\\-\\]]|>|" . $spaces . ")/"; |
|
320 $prime_pattern = "/(?<=\\d)$needle/"; |
|
321 $flag_after_digit = "/(?<=\\d)$flag/"; |
|
322 $flag_no_digit = "/(?<!\\d)$flag/"; |
|
323 |
|
324 $sentences = explode( $open_quote, $haystack ); |
|
325 |
|
326 foreach ( $sentences as $key => &$sentence ) { |
|
327 if ( false === strpos( $sentence, $needle ) ) { |
|
328 continue; |
|
329 } elseif ( 0 !== $key && 0 === substr_count( $sentence, $close_quote ) ) { |
|
330 $sentence = preg_replace( $quote_pattern, $flag, $sentence, -1, $count ); |
|
331 if ( $count > 1 ) { |
|
332 // This sentence appears to have multiple closing quotes. Attempt Vulcan logic. |
|
333 $sentence = preg_replace( $flag_no_digit, $close_quote, $sentence, -1, $count2 ); |
|
334 if ( 0 === $count2 ) { |
|
335 // Try looking for a quote followed by a period. |
|
336 $count2 = substr_count( $sentence, "$flag." ); |
|
337 if ( $count2 > 0 ) { |
|
338 // Assume the rightmost quote-period match is the end of quotation. |
|
339 $pos = strrpos( $sentence, "$flag." ); |
|
340 } else { |
|
341 // When all else fails, make the rightmost candidate a closing quote. |
|
342 // This is most likely to be problematic in the context of bug #18549. |
|
343 $pos = strrpos( $sentence, $flag ); |
|
344 } |
|
345 $sentence = substr_replace( $sentence, $close_quote, $pos, strlen( $flag ) ); |
|
346 } |
|
347 // Use conventional replacement on any remaining primes and quotes. |
|
348 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
|
349 $sentence = preg_replace( $flag_after_digit, $prime, $sentence ); |
|
350 $sentence = str_replace( $flag, $close_quote, $sentence ); |
|
351 } elseif ( 1 == $count ) { |
|
352 // Found only one closing quote candidate, so give it priority over primes. |
|
353 $sentence = str_replace( $flag, $close_quote, $sentence ); |
|
354 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
|
355 } else { |
|
356 // No closing quotes found. Just run primes pattern. |
|
357 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
|
358 } |
|
359 } else { |
|
360 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
|
361 $sentence = preg_replace( $quote_pattern, $close_quote, $sentence ); |
|
362 } |
|
363 if ( '"' == $needle && false !== strpos( $sentence, '"' ) ) { |
|
364 $sentence = str_replace( '"', $close_quote, $sentence ); |
|
365 } |
|
366 } |
|
367 |
|
368 return implode( $open_quote, $sentences ); |
|
369 } |
|
370 |
|
371 /** |
|
372 * Search for disabled element tags. Push element to stack on tag open and pop |
|
373 * on tag close. |
|
374 * |
|
375 * Assumes first char of $text is tag opening and last char is tag closing. |
|
376 * Assumes second char of $text is optionally '/' to indicate closing as in </html>. |
|
377 * |
|
378 * @since 2.9.0 |
|
379 * @access private |
|
380 * |
|
381 * @param string $text Text to check. Must be a tag like `<html>` or `[shortcode]`. |
|
382 * @param array $stack List of open tag elements. |
|
383 * @param array $disabled_elements The tag names to match against. Spaces are not allowed in tag names. |
|
384 */ |
|
385 function _wptexturize_pushpop_element( $text, &$stack, $disabled_elements ) { |
|
386 // Is it an opening tag or closing tag? |
|
387 if ( isset( $text[1] ) && '/' !== $text[1] ) { |
|
388 $opening_tag = true; |
|
389 $name_offset = 1; |
|
390 } elseif ( 0 == count( $stack ) ) { |
|
391 // Stack is empty. Just stop. |
|
392 return; |
|
393 } else { |
|
394 $opening_tag = false; |
|
395 $name_offset = 2; |
|
396 } |
|
397 |
|
398 // Parse out the tag name. |
|
399 $space = strpos( $text, ' ' ); |
|
400 if ( false === $space ) { |
|
401 $space = -1; |
|
402 } else { |
|
403 $space -= $name_offset; |
|
404 } |
|
405 $tag = substr( $text, $name_offset, $space ); |
|
406 |
|
407 // Handle disabled tags. |
|
408 if ( in_array( $tag, $disabled_elements ) ) { |
|
409 if ( $opening_tag ) { |
|
410 /* |
|
411 * This disables texturize until we find a closing tag of our type |
|
412 * (e.g. <pre>) even if there was invalid nesting before that |
|
413 * |
|
414 * Example: in the case <pre>sadsadasd</code>"baba"</pre> |
|
415 * "baba" won't be texturize |
|
416 */ |
|
417 |
|
418 array_push( $stack, $tag ); |
|
419 } elseif ( end( $stack ) == $tag ) { |
|
420 array_pop( $stack ); |
|
421 } |
|
422 } |
|
423 } |
|
424 |
|
425 /** |
|
426 * Replaces double line-breaks with paragraph elements. |
|
427 * |
|
428 * A group of regex replaces used to identify text formatted with newlines and |
|
429 * replace double line-breaks with HTML paragraph tags. The remaining line-breaks |
|
430 * after conversion become <<br />> tags, unless $br is set to '0' or 'false'. |
|
431 * |
|
432 * @since 0.71 |
|
433 * |
|
434 * @param string $pee The text which has to be formatted. |
|
435 * @param bool $br Optional. If set, this will convert all remaining line-breaks |
|
436 * after paragraphing. Default true. |
|
437 * @return string Text which has been converted into correct paragraph tags. |
|
438 */ |
|
439 function wpautop( $pee, $br = true ) { |
|
440 $pre_tags = array(); |
|
441 |
|
442 if ( trim($pee) === '' ) |
|
443 return ''; |
|
444 |
|
445 // Just to make things a little easier, pad the end. |
|
446 $pee = $pee . "\n"; |
|
447 |
|
448 /* |
|
449 * Pre tags shouldn't be touched by autop. |
|
450 * Replace pre tags with placeholders and bring them back after autop. |
|
451 */ |
|
452 if ( strpos($pee, '<pre') !== false ) { |
|
453 $pee_parts = explode( '</pre>', $pee ); |
|
454 $last_pee = array_pop($pee_parts); |
|
455 $pee = ''; |
|
456 $i = 0; |
|
457 |
|
458 foreach ( $pee_parts as $pee_part ) { |
|
459 $start = strpos($pee_part, '<pre'); |
|
460 |
|
461 // Malformed html? |
|
462 if ( $start === false ) { |
|
463 $pee .= $pee_part; |
|
464 continue; |
|
465 } |
|
466 |
|
467 $name = "<pre wp-pre-tag-$i></pre>"; |
|
468 $pre_tags[$name] = substr( $pee_part, $start ) . '</pre>'; |
|
469 |
|
470 $pee .= substr( $pee_part, 0, $start ) . $name; |
|
471 $i++; |
|
472 } |
|
473 |
|
474 $pee .= $last_pee; |
|
475 } |
|
476 // Change multiple <br>s into two line breaks, which will turn into paragraphs. |
|
477 $pee = preg_replace('|<br\s*/?>\s*<br\s*/?>|', "\n\n", $pee); |
|
478 |
|
479 $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)'; |
|
480 |
|
481 // Add a double line break above block-level opening tags. |
|
482 $pee = preg_replace('!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee); |
|
483 |
|
484 // Add a double line break below block-level closing tags. |
|
485 $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee); |
|
486 |
|
487 // Standardize newline characters to "\n". |
|
488 $pee = str_replace(array("\r\n", "\r"), "\n", $pee); |
|
489 |
|
490 // Find newlines in all elements and add placeholders. |
|
491 $pee = wp_replace_in_html_tags( $pee, array( "\n" => " <!-- wpnl --> " ) ); |
|
492 |
|
493 // Collapse line breaks before and after <option> elements so they don't get autop'd. |
|
494 if ( strpos( $pee, '<option' ) !== false ) { |
|
495 $pee = preg_replace( '|\s*<option|', '<option', $pee ); |
|
496 $pee = preg_replace( '|</option>\s*|', '</option>', $pee ); |
|
497 } |
|
498 |
|
499 /* |
|
500 * Collapse line breaks inside <object> elements, before <param> and <embed> elements |
|
501 * so they don't get autop'd. |
|
502 */ |
|
503 if ( strpos( $pee, '</object>' ) !== false ) { |
|
504 $pee = preg_replace( '|(<object[^>]*>)\s*|', '$1', $pee ); |
|
505 $pee = preg_replace( '|\s*</object>|', '</object>', $pee ); |
|
506 $pee = preg_replace( '%\s*(</?(?:param|embed)[^>]*>)\s*%', '$1', $pee ); |
|
507 } |
|
508 |
|
509 /* |
|
510 * Collapse line breaks inside <audio> and <video> elements, |
|
511 * before and after <source> and <track> elements. |
|
512 */ |
|
513 if ( strpos( $pee, '<source' ) !== false || strpos( $pee, '<track' ) !== false ) { |
|
514 $pee = preg_replace( '%([<\[](?:audio|video)[^>\]]*[>\]])\s*%', '$1', $pee ); |
|
515 $pee = preg_replace( '%\s*([<\[]/(?:audio|video)[>\]])%', '$1', $pee ); |
|
516 $pee = preg_replace( '%\s*(<(?:source|track)[^>]*>)\s*%', '$1', $pee ); |
|
517 } |
|
518 |
|
519 // Collapse line breaks before and after <figcaption> elements. |
|
520 if ( strpos( $pee, '<figcaption' ) !== false ) { |
|
521 $pee = preg_replace( '|\s*(<figcaption[^>]*>)|', '$1', $pee ); |
|
522 $pee = preg_replace( '|</figcaption>\s*|', '</figcaption>', $pee ); |
|
523 } |
|
524 |
|
525 // Remove more than two contiguous line breaks. |
|
526 $pee = preg_replace("/\n\n+/", "\n\n", $pee); |
|
527 |
|
528 // Split up the contents into an array of strings, separated by double line breaks. |
|
529 $pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY); |
|
530 |
|
531 // Reset $pee prior to rebuilding. |
|
532 $pee = ''; |
|
533 |
|
534 // Rebuild the content as a string, wrapping every bit with a <p>. |
|
535 foreach ( $pees as $tinkle ) { |
|
536 $pee .= '<p>' . trim($tinkle, "\n") . "</p>\n"; |
|
537 } |
|
538 |
|
539 // Under certain strange conditions it could create a P of entirely whitespace. |
|
540 $pee = preg_replace('|<p>\s*</p>|', '', $pee); |
|
541 |
|
542 // Add a closing <p> inside <div>, <address>, or <form> tag if missing. |
|
543 $pee = preg_replace('!<p>([^<]+)</(div|address|form)>!', "<p>$1</p></$2>", $pee); |
|
544 |
|
545 // If an opening or closing block element tag is wrapped in a <p>, unwrap it. |
|
546 $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); |
|
547 |
|
548 // In some cases <li> may get wrapped in <p>, fix them. |
|
549 $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); |
|
550 |
|
551 // If a <blockquote> is wrapped with a <p>, move it inside the <blockquote>. |
|
552 $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee); |
|
553 $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee); |
|
554 |
|
555 // If an opening or closing block element tag is preceded by an opening <p> tag, remove it. |
|
556 $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee); |
|
557 |
|
558 // If an opening or closing block element tag is followed by a closing <p> tag, remove it. |
|
559 $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); |
|
560 |
|
561 // Optionally insert line breaks. |
|
562 if ( $br ) { |
|
563 // Replace newlines that shouldn't be touched with a placeholder. |
|
564 $pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee); |
|
565 |
|
566 // Normalize <br> |
|
567 $pee = str_replace( array( '<br>', '<br/>' ), '<br />', $pee ); |
|
568 |
|
569 // Replace any new line characters that aren't preceded by a <br /> with a <br />. |
|
570 $pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); |
|
571 |
|
572 // Replace newline placeholders with newlines. |
|
573 $pee = str_replace('<WPPreserveNewline />', "\n", $pee); |
|
574 } |
|
575 |
|
576 // If a <br /> tag is after an opening or closing block tag, remove it. |
|
577 $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee); |
|
578 |
|
579 // If a <br /> tag is before a subset of opening or closing block tags, remove it. |
|
580 $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee); |
|
581 $pee = preg_replace( "|\n</p>$|", '</p>', $pee ); |
|
582 |
|
583 // Replace placeholder <pre> tags with their original content. |
|
584 if ( !empty($pre_tags) ) |
|
585 $pee = str_replace(array_keys($pre_tags), array_values($pre_tags), $pee); |
|
586 |
|
587 // Restore newlines in all elements. |
|
588 if ( false !== strpos( $pee, '<!-- wpnl -->' ) ) { |
|
589 $pee = str_replace( array( ' <!-- wpnl --> ', '<!-- wpnl -->' ), "\n", $pee ); |
|
590 } |
|
591 |
|
592 return $pee; |
|
593 } |
|
594 |
|
595 /** |
|
596 * Separate HTML elements and comments from the text. |
|
597 * |
|
598 * @since 4.2.4 |
|
599 * |
|
600 * @param string $input The text which has to be formatted. |
|
601 * @return array The formatted text. |
|
602 */ |
|
603 function wp_html_split( $input ) { |
|
604 return preg_split( get_html_split_regex(), $input, -1, PREG_SPLIT_DELIM_CAPTURE ); |
|
605 } |
|
606 |
|
607 /** |
|
608 * Retrieve the regular expression for an HTML element. |
|
609 * |
|
610 * @since 4.4.0 |
|
611 * |
|
612 * @staticvar string $regex |
|
613 * |
|
614 * @return string The regular expression |
|
615 */ |
|
616 function get_html_split_regex() { |
|
617 static $regex; |
|
618 |
|
619 if ( ! isset( $regex ) ) { |
|
620 $comments = |
|
621 '!' // Start of comment, after the <. |
|
622 . '(?:' // Unroll the loop: Consume everything until --> is found. |
|
623 . '-(?!->)' // Dash not followed by end of comment. |
|
624 . '[^\-]*+' // Consume non-dashes. |
|
625 . ')*+' // Loop possessively. |
|
626 . '(?:-->)?'; // End of comment. If not found, match all input. |
|
627 |
|
628 $cdata = |
|
629 '!\[CDATA\[' // Start of comment, after the <. |
|
630 . '[^\]]*+' // Consume non-]. |
|
631 . '(?:' // Unroll the loop: Consume everything until ]]> is found. |
|
632 . '](?!]>)' // One ] not followed by end of comment. |
|
633 . '[^\]]*+' // Consume non-]. |
|
634 . ')*+' // Loop possessively. |
|
635 . '(?:]]>)?'; // End of comment. If not found, match all input. |
|
636 |
|
637 $escaped = |
|
638 '(?=' // Is the element escaped? |
|
639 . '!--' |
|
640 . '|' |
|
641 . '!\[CDATA\[' |
|
642 . ')' |
|
643 . '(?(?=!-)' // If yes, which type? |
|
644 . $comments |
|
645 . '|' |
|
646 . $cdata |
|
647 . ')'; |
|
648 |
|
649 $regex = |
|
650 '/(' // Capture the entire match. |
|
651 . '<' // Find start of element. |
|
652 . '(?' // Conditional expression follows. |
|
653 . $escaped // Find end of escaped element. |
|
654 . '|' // ... else ... |
|
655 . '[^>]*>?' // Find end of normal element. |
|
656 . ')' |
|
657 . ')/'; |
|
658 } |
|
659 |
|
660 return $regex; |
|
661 } |
|
662 |
|
663 /** |
|
664 * Retrieve the combined regular expression for HTML and shortcodes. |
|
665 * |
|
666 * @access private |
|
667 * @ignore |
|
668 * @internal This function will be removed in 4.5.0 per Shortcode API Roadmap. |
|
669 * @since 4.4.0 |
|
670 * |
|
671 * @staticvar string $html_regex |
|
672 * |
|
673 * @param string $shortcode_regex The result from _get_wptexturize_shortcode_regex(). Optional. |
|
674 * @return string The regular expression |
|
675 */ |
|
676 function _get_wptexturize_split_regex( $shortcode_regex = '' ) { |
|
677 static $html_regex; |
|
678 |
|
679 if ( ! isset( $html_regex ) ) { |
|
680 $comment_regex = |
|
681 '!' // Start of comment, after the <. |
|
682 . '(?:' // Unroll the loop: Consume everything until --> is found. |
|
683 . '-(?!->)' // Dash not followed by end of comment. |
|
684 . '[^\-]*+' // Consume non-dashes. |
|
685 . ')*+' // Loop possessively. |
|
686 . '(?:-->)?'; // End of comment. If not found, match all input. |
|
687 |
|
688 $html_regex = // Needs replaced with wp_html_split() per Shortcode API Roadmap. |
|
689 '<' // Find start of element. |
|
690 . '(?(?=!--)' // Is this a comment? |
|
691 . $comment_regex // Find end of comment. |
|
692 . '|' |
|
693 . '[^>]*>?' // Find end of element. If not found, match all input. |
|
694 . ')'; |
|
695 } |
|
696 |
|
697 if ( empty( $shortcode_regex ) ) { |
|
698 $regex = '/(' . $html_regex . ')/'; |
|
699 } else { |
|
700 $regex = '/(' . $html_regex . '|' . $shortcode_regex . ')/'; |
|
701 } |
|
702 |
|
703 return $regex; |
|
704 } |
|
705 |
|
706 /** |
|
707 * Retrieve the regular expression for shortcodes. |
|
708 * |
|
709 * @access private |
|
710 * @ignore |
|
711 * @internal This function will be removed in 4.5.0 per Shortcode API Roadmap. |
|
712 * @since 4.4.0 |
|
713 * |
|
714 * @param array $tagnames List of shortcodes to find. |
|
715 * @return string The regular expression |
|
716 */ |
|
717 function _get_wptexturize_shortcode_regex( $tagnames ) { |
|
209 $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) ); |
718 $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) ); |
210 $tagregexp = "(?:$tagregexp)(?![\\w-])"; // Excerpt of get_shortcode_regex(). |
719 $tagregexp = "(?:$tagregexp)(?=[\\s\\]\\/])"; // Excerpt of get_shortcode_regex(). |
211 |
720 $regex = |
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. |
721 '\[' // Find start of shortcode. |
222 . '[\/\[]?' // Shortcodes may begin with [/ or [[ |
722 . '[\/\[]?' // Shortcodes may begin with [/ or [[ |
223 . $tagregexp // Only match registered shortcodes, because performance. |
723 . $tagregexp // Only match registered shortcodes, because performance. |
224 . '(?:' |
724 . '(?:' |
225 . '[^\[\]<>]+' // Shortcodes do not contain other shortcodes. Quantifier critical. |
725 . '[^\[\]<>]+' // Shortcodes do not contain other shortcodes. Quantifier critical. |
227 . '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >. |
727 . '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >. |
228 . ')*+' // Possessive critical. |
728 . ')*+' // Possessive critical. |
229 . '\]' // Find end of shortcode. |
729 . '\]' // Find end of shortcode. |
230 . '\]?'; // Shortcodes may end with ]] |
730 . '\]?'; // Shortcodes may end with ]] |
231 |
731 |
232 $regex = |
732 return $regex; |
233 '/(' // Capture the entire match. |
733 } |
234 . '<' // Find start of element. |
734 |
235 . '(?(?=!--)' // Is this a comment? |
735 /** |
236 . $comment_regex // Find end of comment. |
736 * Replace characters or phrases within HTML elements only. |
237 . '|' |
737 * |
238 . '[^>]*>' // Find end of element. |
738 * @since 4.2.3 |
239 . ')' |
739 * |
240 . '|' |
740 * @param string $haystack The text which has to be formatted. |
241 . $shortcode_regex // Find shortcodes. |
741 * @param array $replace_pairs In the form array('from' => 'to', ...). |
242 . ')/s'; |
742 * @return string The formatted text. |
243 |
743 */ |
244 $textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); |
744 function wp_replace_in_html_tags( $haystack, $replace_pairs ) { |
245 |
745 // Find all elements. |
246 foreach ( $textarr as &$curl ) { |
746 $textarr = wp_html_split( $haystack ); |
247 // Only call _wptexturize_pushpop_element if $curl is a delimiter. |
747 $changed = false; |
248 $first = $curl[0]; |
748 |
249 if ( '<' === $first && '<!--' === substr( $curl, 0, 4 ) ) { |
749 // Optimize when searching for one item. |
250 // This is an HTML comment delimeter. |
750 if ( 1 === count( $replace_pairs ) ) { |
251 |
751 // Extract $needle and $replace. |
252 continue; |
752 foreach ( $replace_pairs as $needle => $replace ); |
253 |
753 |
254 } elseif ( '<' === $first && '>' === substr( $curl, -1 ) ) { |
754 // Loop through delimiters (elements) only. |
255 // This is an HTML element delimiter. |
755 for ( $i = 1, $c = count( $textarr ); $i < $c; $i += 2 ) { |
256 |
756 if ( false !== strpos( $textarr[$i], $needle ) ) { |
257 _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags ); |
757 $textarr[$i] = str_replace( $needle, $replace, $textarr[$i] ); |
258 |
758 $changed = true; |
259 } elseif ( '' === trim( $curl ) ) { |
|
260 // This is a newline between delimiters. Performance improves when we check this. |
|
261 |
|
262 continue; |
|
263 |
|
264 } elseif ( '[' === $first && 1 === preg_match( '/^' . $shortcode_regex . '$/', $curl ) ) { |
|
265 // This is a shortcode delimiter. |
|
266 |
|
267 if ( '[[' !== substr( $curl, 0, 2 ) && ']]' !== substr( $curl, -2 ) ) { |
|
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 } |
759 } |
274 |
760 } |
275 } elseif ( empty( $no_texturize_shortcodes_stack ) && empty( $no_texturize_tags_stack ) ) { |
761 } else { |
276 // This is neither a delimiter, nor is this content inside of no_texturize pairs. Do texturize. |
762 // Extract all $needles. |
277 |
763 $needles = array_keys( $replace_pairs ); |
278 $curl = str_replace( $static_characters, $static_replacements, $curl ); |
764 |
279 |
765 // Loop through delimiters (elements) only. |
280 if ( false !== strpos( $curl, "'" ) ) { |
766 for ( $i = 1, $c = count( $textarr ); $i < $c; $i += 2 ) { |
281 $curl = preg_replace( $dynamic_characters['apos'], $dynamic_replacements['apos'], $curl ); |
767 foreach ( $needles as $needle ) { |
768 if ( false !== strpos( $textarr[$i], $needle ) ) { |
|
769 $textarr[$i] = strtr( $textarr[$i], $replace_pairs ); |
|
770 $changed = true; |
|
771 // After one strtr() break out of the foreach loop and look at next element. |
|
772 break; |
|
773 } |
|
282 } |
774 } |
283 if ( false !== strpos( $curl, '"' ) ) { |
775 } |
284 $curl = preg_replace( $dynamic_characters['quote'], $dynamic_replacements['quote'], $curl ); |
776 } |
285 } |
777 |
286 if ( false !== strpos( $curl, '-' ) ) { |
778 if ( $changed ) { |
287 $curl = preg_replace( $dynamic_characters['dash'], $dynamic_replacements['dash'], $curl ); |
779 $haystack = implode( $textarr ); |
288 } |
780 } |
289 |
781 |
290 // 9x9 (times), but never 0x9999 |
782 return $haystack; |
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; |
|
303 } |
|
304 |
|
305 /** |
|
306 * Search for disabled element tags. Push element to stack on tag open and pop |
|
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>. |
|
311 * |
|
312 * @since 2.9.0 |
|
313 * @access private |
|
314 * |
|
315 * @param string $text Text to check. Must be a tag like `<html>` or `[shortcode]`. |
|
316 * @param array $stack List of open tag elements. |
|
317 * @param array $disabled_elements The tag names to match against. Spaces are not allowed in tag names. |
|
318 */ |
|
319 function _wptexturize_pushpop_element($text, &$stack, $disabled_elements) { |
|
320 // Is it an opening tag or closing tag? |
|
321 if ( '/' !== $text[1] ) { |
|
322 $opening_tag = true; |
|
323 $name_offset = 1; |
|
324 } elseif ( 0 == count( $stack ) ) { |
|
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 ) { |
|
344 /* |
|
345 * This disables texturize until we find a closing tag of our type |
|
346 * (e.g. <pre>) even if there was invalid nesting before that |
|
347 * |
|
348 * Example: in the case <pre>sadsadasd</code>"baba"</pre> |
|
349 * "baba" won't be texturize |
|
350 */ |
|
351 |
|
352 array_push( $stack, $tag ); |
|
353 } elseif ( end( $stack ) == $tag ) { |
|
354 array_pop( $stack ); |
|
355 } |
|
356 } |
|
357 } |
|
358 |
|
359 /** |
|
360 * Replaces double line-breaks with paragraph elements. |
|
361 * |
|
362 * A group of regex replaces used to identify text formatted with newlines and |
|
363 * replace double line-breaks with HTML paragraph tags. The remaining line-breaks |
|
364 * after conversion become <<br />> tags, unless $br is set to '0' or 'false'. |
|
365 * |
|
366 * @since 0.71 |
|
367 * |
|
368 * @param string $pee The text which has to be formatted. |
|
369 * @param bool $br Optional. If set, this will convert all remaining line-breaks |
|
370 * after paragraphing. Default true. |
|
371 * @return string Text which has been converted into correct paragraph tags. |
|
372 */ |
|
373 function wpautop($pee, $br = true) { |
|
374 $pre_tags = array(); |
|
375 |
|
376 if ( trim($pee) === '' ) |
|
377 return ''; |
|
378 |
|
379 // Just to make things a little easier, pad the end. |
|
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 */ |
|
386 if ( strpos($pee, '<pre') !== false ) { |
|
387 $pee_parts = explode( '</pre>', $pee ); |
|
388 $last_pee = array_pop($pee_parts); |
|
389 $pee = ''; |
|
390 $i = 0; |
|
391 |
|
392 foreach ( $pee_parts as $pee_part ) { |
|
393 $start = strpos($pee_part, '<pre'); |
|
394 |
|
395 // Malformed html? |
|
396 if ( $start === false ) { |
|
397 $pee .= $pee_part; |
|
398 continue; |
|
399 } |
|
400 |
|
401 $name = "<pre wp-pre-tag-$i></pre>"; |
|
402 $pre_tags[$name] = substr( $pee_part, $start ) . '</pre>'; |
|
403 |
|
404 $pee .= substr( $pee_part, 0, $start ) . $name; |
|
405 $i++; |
|
406 } |
|
407 |
|
408 $pee .= $last_pee; |
|
409 } |
|
410 // Change multiple <br>s into two line breaks, which will turn into paragraphs. |
|
411 $pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee); |
|
412 |
|
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. |
|
416 $pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee); |
|
417 |
|
418 // Add a double line break below block-level closing tags. |
|
419 $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee); |
|
420 |
|
421 // Standardize newline characters to "\n". |
|
422 $pee = str_replace(array("\r\n", "\r"), "\n", $pee); |
|
423 |
|
424 // Collapse line breaks before and after <option> elements so they don't get autop'd. |
|
425 if ( strpos( $pee, '<option' ) !== false ) { |
|
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. |
|
454 $pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY); |
|
455 |
|
456 // Reset $pee prior to rebuilding. |
|
457 $pee = ''; |
|
458 |
|
459 // Rebuild the content as a string, wrapping every bit with a <p>. |
|
460 foreach ( $pees as $tinkle ) { |
|
461 $pee .= '<p>' . trim($tinkle, "\n") . "</p>\n"; |
|
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. |
|
468 $pee = preg_replace('!<p>([^<]+)</(div|address|form)>!', "<p>$1</p></$2>", $pee); |
|
469 |
|
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>. |
|
477 $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $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. |
|
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. |
|
484 $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); |
|
485 |
|
486 // Optionally insert line breaks. |
|
487 if ( $br ) { |
|
488 // Replace newlines that shouldn't be touched with a placeholder. |
|
489 $pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee); |
|
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. |
|
495 $pee = str_replace('<WPPreserveNewline />', "\n", $pee); |
|
496 } |
|
497 |
|
498 // If a <br /> tag is after an opening or closing block tag, remove it. |
|
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. |
|
502 $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee); |
|
503 $pee = preg_replace( "|\n</p>$|", '</p>', $pee ); |
|
504 |
|
505 // Replace placeholder <pre> tags with their original content. |
|
506 if ( !empty($pre_tags) ) |
|
507 $pee = str_replace(array_keys($pre_tags), array_values($pre_tags), $pee); |
|
508 |
|
509 return $pee; |
|
510 } |
783 } |
511 |
784 |
512 /** |
785 /** |
513 * Newline preservation help function for wpautop |
786 * Newline preservation help function for wpautop |
514 * |
787 * |
517 * |
790 * |
518 * @param array $matches preg_replace_callback matches array |
791 * @param array $matches preg_replace_callback matches array |
519 * @return string |
792 * @return string |
520 */ |
793 */ |
521 function _autop_newline_preservation_helper( $matches ) { |
794 function _autop_newline_preservation_helper( $matches ) { |
522 return str_replace("\n", "<WPPreserveNewline />", $matches[0]); |
795 return str_replace( "\n", "<WPPreserveNewline />", $matches[0] ); |
523 } |
796 } |
524 |
797 |
525 /** |
798 /** |
526 * Don't auto-p wrap shortcodes that stand alone |
799 * Don't auto-p wrap shortcodes that stand alone |
527 * |
800 * |
528 * Ensures that shortcodes are not wrapped in `<p>...</p>`. |
801 * Ensures that shortcodes are not wrapped in `<p>...</p>`. |
529 * |
802 * |
530 * @since 2.9.0 |
803 * @since 2.9.0 |
804 * |
|
805 * @global array $shortcode_tags |
|
531 * |
806 * |
532 * @param string $pee The content. |
807 * @param string $pee The content. |
533 * @return string The filtered content. |
808 * @return string The filtered content. |
534 */ |
809 */ |
535 function shortcode_unautop( $pee ) { |
810 function shortcode_unautop( $pee ) { |
570 . ')?' |
845 . ')?' |
571 . ')' |
846 . ')' |
572 . ')' |
847 . ')' |
573 . '(?:' . $spaces . ')*+' // optional trailing whitespace |
848 . '(?:' . $spaces . ')*+' // optional trailing whitespace |
574 . '<\\/p>' // closing paragraph |
849 . '<\\/p>' // closing paragraph |
575 . '/s'; |
850 . '/'; |
576 |
851 |
577 return preg_replace( $pattern, '$1', $pee ); |
852 return preg_replace( $pattern, '$1', $pee ); |
578 } |
853 } |
579 |
854 |
580 /** |
855 /** |
587 * @since 1.2.1 |
862 * @since 1.2.1 |
588 * |
863 * |
589 * @param string $str The string to be checked |
864 * @param string $str The string to be checked |
590 * @return bool True if $str fits a UTF-8 model, false otherwise. |
865 * @return bool True if $str fits a UTF-8 model, false otherwise. |
591 */ |
866 */ |
592 function seems_utf8($str) { |
867 function seems_utf8( $str ) { |
593 mbstring_binary_safe_encoding(); |
868 mbstring_binary_safe_encoding(); |
594 $length = strlen($str); |
869 $length = strlen($str); |
595 reset_mbstring_encoding(); |
870 reset_mbstring_encoding(); |
596 for ($i=0; $i < $length; $i++) { |
871 for ($i=0; $i < $length; $i++) { |
597 $c = ord($str[$i]); |
872 $c = ord($str[$i]); |
619 * ", or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded. |
894 * ", or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded. |
620 * |
895 * |
621 * @since 1.2.2 |
896 * @since 1.2.2 |
622 * @access private |
897 * @access private |
623 * |
898 * |
624 * @param string $string The text which is to be encoded. |
899 * @staticvar string $_charset |
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. |
900 * |
626 * @param string $charset Optional. The character encoding of the string. Default is false. |
901 * @param string $string The text which is to be encoded. |
627 * @param boolean $double_encode Optional. Whether to encode existing html entities. Default is false. |
902 * @param int|string $quote_style Optional. Converts double quotes if set to ENT_COMPAT, |
903 * both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. |
|
904 * Also compatible with old values; converting single quotes if set to 'single', |
|
905 * double if set to 'double' or both if otherwise set. |
|
906 * Default is ENT_NOQUOTES. |
|
907 * @param string $charset Optional. The character encoding of the string. Default is false. |
|
908 * @param bool $double_encode Optional. Whether to encode existing html entities. Default is false. |
|
628 * @return string The encoded text with HTML entities. |
909 * @return string The encoded text with HTML entities. |
629 */ |
910 */ |
630 function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { |
911 function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { |
631 $string = (string) $string; |
912 $string = (string) $string; |
632 |
913 |
643 elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) |
924 elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) |
644 $quote_style = ENT_QUOTES; |
925 $quote_style = ENT_QUOTES; |
645 |
926 |
646 // Store the site charset as a static to avoid multiple calls to wp_load_alloptions() |
927 // Store the site charset as a static to avoid multiple calls to wp_load_alloptions() |
647 if ( ! $charset ) { |
928 if ( ! $charset ) { |
648 static $_charset; |
929 static $_charset = null; |
649 if ( ! isset( $_charset ) ) { |
930 if ( ! isset( $_charset ) ) { |
650 $alloptions = wp_load_alloptions(); |
931 $alloptions = wp_load_alloptions(); |
651 $_charset = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : ''; |
932 $_charset = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : ''; |
652 } |
933 } |
653 $charset = $_charset; |
934 $charset = $_charset; |
663 $_quote_style = ENT_COMPAT; |
944 $_quote_style = ENT_COMPAT; |
664 } elseif ( $quote_style === 'single' ) { |
945 } elseif ( $quote_style === 'single' ) { |
665 $quote_style = ENT_NOQUOTES; |
946 $quote_style = ENT_NOQUOTES; |
666 } |
947 } |
667 |
948 |
668 // Handle double encoding ourselves |
949 if ( ! $double_encode ) { |
669 if ( $double_encode ) { |
950 // Guarantee every &entity; is valid, convert &garbage; into &garbage; |
670 $string = @htmlspecialchars( $string, $quote_style, $charset ); |
951 // This is required for PHP < 5.4.0 because ENT_HTML401 flag is unavailable. |
671 } else { |
|
672 // Decode & into & |
|
673 $string = wp_specialchars_decode( $string, $_quote_style ); |
|
674 |
|
675 // Guarantee every &entity; is valid or re-encode the & |
|
676 $string = wp_kses_normalize_entities( $string ); |
952 $string = wp_kses_normalize_entities( $string ); |
677 |
953 } |
678 // Now re-encode everything except &entity; |
954 |
679 $string = preg_split( '/(&#?x?[0-9a-z]+;)/i', $string, -1, PREG_SPLIT_DELIM_CAPTURE ); |
955 $string = @htmlspecialchars( $string, $quote_style, $charset, $double_encode ); |
680 |
956 |
681 for ( $i = 0, $c = count( $string ); $i < $c; $i += 2 ) { |
957 // Back-compat. |
682 $string[$i] = @htmlspecialchars( $string[$i], $quote_style, $charset ); |
|
683 } |
|
684 $string = implode( '', $string ); |
|
685 } |
|
686 |
|
687 // Backwards compatibility |
|
688 if ( 'single' === $_quote_style ) |
958 if ( 'single' === $_quote_style ) |
689 $string = str_replace( "'", ''', $string ); |
959 $string = str_replace( "'", ''', $string ); |
690 |
960 |
691 return $string; |
961 return $string; |
692 } |
962 } |
699 * $quote_style can be set to ENT_COMPAT to decode " entities, |
969 * $quote_style can be set to ENT_COMPAT to decode " entities, |
700 * or ENT_QUOTES to do both " and '. Default is ENT_NOQUOTES where no quotes are decoded. |
970 * or ENT_QUOTES to do both " and '. Default is ENT_NOQUOTES where no quotes are decoded. |
701 * |
971 * |
702 * @since 2.8.0 |
972 * @since 2.8.0 |
703 * |
973 * |
704 * @param string $string The text which is to be decoded. |
974 * @param string $string The text which is to be decoded. |
705 * @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 _wp_specialchars() values; converting single quotes if set to 'single', double if set to 'double' or both if otherwise set. Default is ENT_NOQUOTES. |
975 * @param string|int $quote_style Optional. Converts double quotes if set to ENT_COMPAT, |
976 * both single and double if set to ENT_QUOTES or |
|
977 * none if set to ENT_NOQUOTES. |
|
978 * Also compatible with old _wp_specialchars() values; |
|
979 * converting single quotes if set to 'single', |
|
980 * double if set to 'double' or both if otherwise set. |
|
981 * Default is ENT_NOQUOTES. |
|
706 * @return string The decoded text without HTML entities. |
982 * @return string The decoded text without HTML entities. |
707 */ |
983 */ |
708 function wp_specialchars_decode( $string, $quote_style = ENT_NOQUOTES ) { |
984 function wp_specialchars_decode( $string, $quote_style = ENT_NOQUOTES ) { |
709 $string = (string) $string; |
985 $string = (string) $string; |
710 |
986 |
756 /** |
1032 /** |
757 * Checks for invalid UTF8 in a string. |
1033 * Checks for invalid UTF8 in a string. |
758 * |
1034 * |
759 * @since 2.8.0 |
1035 * @since 2.8.0 |
760 * |
1036 * |
761 * @param string $string The text which is to be checked. |
1037 * @staticvar bool $is_utf8 |
762 * @param boolean $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false. |
1038 * @staticvar bool $utf8_pcre |
1039 * |
|
1040 * @param string $string The text which is to be checked. |
|
1041 * @param bool $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false. |
|
763 * @return string The checked text. |
1042 * @return string The checked text. |
764 */ |
1043 */ |
765 function wp_check_invalid_utf8( $string, $strip = false ) { |
1044 function wp_check_invalid_utf8( $string, $strip = false ) { |
766 $string = (string) $string; |
1045 $string = (string) $string; |
767 |
1046 |
768 if ( 0 === strlen( $string ) ) { |
1047 if ( 0 === strlen( $string ) ) { |
769 return ''; |
1048 return ''; |
770 } |
1049 } |
771 |
1050 |
772 // Store the site charset as a static to avoid multiple calls to get_option() |
1051 // Store the site charset as a static to avoid multiple calls to get_option() |
773 static $is_utf8; |
1052 static $is_utf8 = null; |
774 if ( !isset( $is_utf8 ) ) { |
1053 if ( ! isset( $is_utf8 ) ) { |
775 $is_utf8 = in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ); |
1054 $is_utf8 = in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ); |
776 } |
1055 } |
777 if ( !$is_utf8 ) { |
1056 if ( ! $is_utf8 ) { |
778 return $string; |
1057 return $string; |
779 } |
1058 } |
780 |
1059 |
781 // Check for support for utf8 in the installed PCRE library once and store the result in a static |
1060 // Check for support for utf8 in the installed PCRE library once and store the result in a static |
782 static $utf8_pcre; |
1061 static $utf8_pcre = null; |
783 if ( !isset( $utf8_pcre ) ) { |
1062 if ( ! isset( $utf8_pcre ) ) { |
784 $utf8_pcre = @preg_match( '/^./u', 'a' ); |
1063 $utf8_pcre = @preg_match( '/^./u', 'a' ); |
785 } |
1064 } |
786 // We can't demand utf8 in the PCRE installation, so just return the string in those cases |
1065 // We can't demand utf8 in the PCRE installation, so just return the string in those cases |
787 if ( !$utf8_pcre ) { |
1066 if ( !$utf8_pcre ) { |
788 return $string; |
1067 return $string; |
805 * Encode the Unicode values to be used in the URI. |
1084 * Encode the Unicode values to be used in the URI. |
806 * |
1085 * |
807 * @since 1.5.0 |
1086 * @since 1.5.0 |
808 * |
1087 * |
809 * @param string $utf8_string |
1088 * @param string $utf8_string |
810 * @param int $length Max length of the string |
1089 * @param int $length Max length of the string |
811 * @return string String with Unicode encoded for URI. |
1090 * @return string String with Unicode encoded for URI. |
812 */ |
1091 */ |
813 function utf8_uri_encode( $utf8_string, $length = 0 ) { |
1092 function utf8_uri_encode( $utf8_string, $length = 0 ) { |
814 $unicode = ''; |
1093 $unicode = ''; |
815 $values = array(); |
1094 $values = array(); |
863 /** |
1142 /** |
864 * Converts all accent characters to ASCII characters. |
1143 * Converts all accent characters to ASCII characters. |
865 * |
1144 * |
866 * If there are no accent characters, then the string given is just returned. |
1145 * If there are no accent characters, then the string given is just returned. |
867 * |
1146 * |
1147 * **Accent characters converted:** |
|
1148 * |
|
1149 * Currency signs: |
|
1150 * |
|
1151 * | Code | Glyph | Replacement | Description | |
|
1152 * | -------- | ----- | ----------- | ------------------- | |
|
1153 * | U+00A3 | £ | (empty) | British Pound sign | |
|
1154 * | U+20AC | € | E | Euro sign | |
|
1155 * |
|
1156 * Decompositions for Latin-1 Supplement: |
|
1157 * |
|
1158 * | Code | Glyph | Replacement | Description | |
|
1159 * | ------- | ----- | ----------- | -------------------------------------- | |
|
1160 * | U+00AA | ª | a | Feminine ordinal indicator | |
|
1161 * | U+00BA | º | o | Masculine ordinal indicator | |
|
1162 * | U+00C0 | À | A | Latin capital letter A with grave | |
|
1163 * | U+00C1 | Á | A | Latin capital letter A with acute | |
|
1164 * | U+00C2 | Â | A | Latin capital letter A with circumflex | |
|
1165 * | U+00C3 | Ã | A | Latin capital letter A with tilde | |
|
1166 * | U+00C4 | Ä | A | Latin capital letter A with diaeresis | |
|
1167 * | U+00C5 | Å | A | Latin capital letter A with ring above | |
|
1168 * | U+00C6 | Æ | AE | Latin capital letter AE | |
|
1169 * | U+00C7 | Ç | C | Latin capital letter C with cedilla | |
|
1170 * | U+00C8 | È | E | Latin capital letter E with grave | |
|
1171 * | U+00C9 | É | E | Latin capital letter E with acute | |
|
1172 * | U+00CA | Ê | E | Latin capital letter E with circumflex | |
|
1173 * | U+00CB | Ë | E | Latin capital letter E with diaeresis | |
|
1174 * | U+00CC | Ì | I | Latin capital letter I with grave | |
|
1175 * | U+00CD | Í | I | Latin capital letter I with acute | |
|
1176 * | U+00CE | Î | I | Latin capital letter I with circumflex | |
|
1177 * | U+00CF | Ï | I | Latin capital letter I with diaeresis | |
|
1178 * | U+00D0 | Ð | D | Latin capital letter Eth | |
|
1179 * | U+00D1 | Ñ | N | Latin capital letter N with tilde | |
|
1180 * | U+00D2 | Ò | O | Latin capital letter O with grave | |
|
1181 * | U+00D3 | Ó | O | Latin capital letter O with acute | |
|
1182 * | U+00D4 | Ô | O | Latin capital letter O with circumflex | |
|
1183 * | U+00D5 | Õ | O | Latin capital letter O with tilde | |
|
1184 * | U+00D6 | Ö | O | Latin capital letter O with diaeresis | |
|
1185 * | U+00D8 | Ø | O | Latin capital letter O with stroke | |
|
1186 * | U+00D9 | Ù | U | Latin capital letter U with grave | |
|
1187 * | U+00DA | Ú | U | Latin capital letter U with acute | |
|
1188 * | U+00DB | Û | U | Latin capital letter U with circumflex | |
|
1189 * | U+00DC | Ü | U | Latin capital letter U with diaeresis | |
|
1190 * | U+00DD | Ý | Y | Latin capital letter Y with acute | |
|
1191 * | U+00DE | Þ | TH | Latin capital letter Thorn | |
|
1192 * | U+00DF | ß | s | Latin small letter sharp s | |
|
1193 * | U+00E0 | à | a | Latin small letter a with grave | |
|
1194 * | U+00E1 | á | a | Latin small letter a with acute | |
|
1195 * | U+00E2 | â | a | Latin small letter a with circumflex | |
|
1196 * | U+00E3 | ã | a | Latin small letter a with tilde | |
|
1197 * | U+00E4 | ä | a | Latin small letter a with diaeresis | |
|
1198 * | U+00E5 | å | a | Latin small letter a with ring above | |
|
1199 * | U+00E6 | æ | ae | Latin small letter ae | |
|
1200 * | U+00E7 | ç | c | Latin small letter c with cedilla | |
|
1201 * | U+00E8 | è | e | Latin small letter e with grave | |
|
1202 * | U+00E9 | é | e | Latin small letter e with acute | |
|
1203 * | U+00EA | ê | e | Latin small letter e with circumflex | |
|
1204 * | U+00EB | ë | e | Latin small letter e with diaeresis | |
|
1205 * | U+00EC | ì | i | Latin small letter i with grave | |
|
1206 * | U+00ED | í | i | Latin small letter i with acute | |
|
1207 * | U+00EE | î | i | Latin small letter i with circumflex | |
|
1208 * | U+00EF | ï | i | Latin small letter i with diaeresis | |
|
1209 * | U+00F0 | ð | d | Latin small letter Eth | |
|
1210 * | U+00F1 | ñ | n | Latin small letter n with tilde | |
|
1211 * | U+00F2 | ò | o | Latin small letter o with grave | |
|
1212 * | U+00F3 | ó | o | Latin small letter o with acute | |
|
1213 * | U+00F4 | ô | o | Latin small letter o with circumflex | |
|
1214 * | U+00F5 | õ | o | Latin small letter o with tilde | |
|
1215 * | U+00F6 | ö | o | Latin small letter o with diaeresis | |
|
1216 * | U+00F8 | ø | o | Latin small letter o with stroke | |
|
1217 * | U+00F9 | ù | u | Latin small letter u with grave | |
|
1218 * | U+00FA | ú | u | Latin small letter u with acute | |
|
1219 * | U+00FB | û | u | Latin small letter u with circumflex | |
|
1220 * | U+00FC | ü | u | Latin small letter u with diaeresis | |
|
1221 * | U+00FD | ý | y | Latin small letter y with acute | |
|
1222 * | U+00FE | þ | th | Latin small letter Thorn | |
|
1223 * | U+00FF | ÿ | y | Latin small letter y with diaeresis | |
|
1224 * |
|
1225 * Decompositions for Latin Extended-A: |
|
1226 * |
|
1227 * | Code | Glyph | Replacement | Description | |
|
1228 * | ------- | ----- | ----------- | ------------------------------------------------- | |
|
1229 * | U+0100 | Ā | A | Latin capital letter A with macron | |
|
1230 * | U+0101 | ā | a | Latin small letter a with macron | |
|
1231 * | U+0102 | Ă | A | Latin capital letter A with breve | |
|
1232 * | U+0103 | ă | a | Latin small letter a with breve | |
|
1233 * | U+0104 | Ą | A | Latin capital letter A with ogonek | |
|
1234 * | U+0105 | ą | a | Latin small letter a with ogonek | |
|
1235 * | U+01006 | Ć | C | Latin capital letter C with acute | |
|
1236 * | U+0107 | ć | c | Latin small letter c with acute | |
|
1237 * | U+0108 | Ĉ | C | Latin capital letter C with circumflex | |
|
1238 * | U+0109 | ĉ | c | Latin small letter c with circumflex | |
|
1239 * | U+010A | Ċ | C | Latin capital letter C with dot above | |
|
1240 * | U+010B | ċ | c | Latin small letter c with dot above | |
|
1241 * | U+010C | Č | C | Latin capital letter C with caron | |
|
1242 * | U+010D | č | c | Latin small letter c with caron | |
|
1243 * | U+010E | Ď | D | Latin capital letter D with caron | |
|
1244 * | U+010F | ď | d | Latin small letter d with caron | |
|
1245 * | U+0110 | Đ | D | Latin capital letter D with stroke | |
|
1246 * | U+0111 | đ | d | Latin small letter d with stroke | |
|
1247 * | U+0112 | Ē | E | Latin capital letter E with macron | |
|
1248 * | U+0113 | ē | e | Latin small letter e with macron | |
|
1249 * | U+0114 | Ĕ | E | Latin capital letter E with breve | |
|
1250 * | U+0115 | ĕ | e | Latin small letter e with breve | |
|
1251 * | U+0116 | Ė | E | Latin capital letter E with dot above | |
|
1252 * | U+0117 | ė | e | Latin small letter e with dot above | |
|
1253 * | U+0118 | Ę | E | Latin capital letter E with ogonek | |
|
1254 * | U+0119 | ę | e | Latin small letter e with ogonek | |
|
1255 * | U+011A | Ě | E | Latin capital letter E with caron | |
|
1256 * | U+011B | ě | e | Latin small letter e with caron | |
|
1257 * | U+011C | Ĝ | G | Latin capital letter G with circumflex | |
|
1258 * | U+011D | ĝ | g | Latin small letter g with circumflex | |
|
1259 * | U+011E | Ğ | G | Latin capital letter G with breve | |
|
1260 * | U+011F | ğ | g | Latin small letter g with breve | |
|
1261 * | U+0120 | Ġ | G | Latin capital letter G with dot above | |
|
1262 * | U+0121 | ġ | g | Latin small letter g with dot above | |
|
1263 * | U+0122 | Ģ | G | Latin capital letter G with cedilla | |
|
1264 * | U+0123 | ģ | g | Latin small letter g with cedilla | |
|
1265 * | U+0124 | Ĥ | H | Latin capital letter H with circumflex | |
|
1266 * | U+0125 | ĥ | h | Latin small letter h with circumflex | |
|
1267 * | U+0126 | Ħ | H | Latin capital letter H with stroke | |
|
1268 * | U+0127 | ħ | h | Latin small letter h with stroke | |
|
1269 * | U+0128 | Ĩ | I | Latin capital letter I with tilde | |
|
1270 * | U+0129 | ĩ | i | Latin small letter i with tilde | |
|
1271 * | U+012A | Ī | I | Latin capital letter I with macron | |
|
1272 * | U+012B | ī | i | Latin small letter i with macron | |
|
1273 * | U+012C | Ĭ | I | Latin capital letter I with breve | |
|
1274 * | U+012D | ĭ | i | Latin small letter i with breve | |
|
1275 * | U+012E | Į | I | Latin capital letter I with ogonek | |
|
1276 * | U+012F | į | i | Latin small letter i with ogonek | |
|
1277 * | U+0130 | İ | I | Latin capital letter I with dot above | |
|
1278 * | U+0131 | ı | i | Latin small letter dotless i | |
|
1279 * | U+0132 | IJ | IJ | Latin capital ligature IJ | |
|
1280 * | U+0133 | ij | ij | Latin small ligature ij | |
|
1281 * | U+0134 | Ĵ | J | Latin capital letter J with circumflex | |
|
1282 * | U+0135 | ĵ | j | Latin small letter j with circumflex | |
|
1283 * | U+0136 | Ķ | K | Latin capital letter K with cedilla | |
|
1284 * | U+0137 | ķ | k | Latin small letter k with cedilla | |
|
1285 * | U+0138 | ĸ | k | Latin small letter Kra | |
|
1286 * | U+0139 | Ĺ | L | Latin capital letter L with acute | |
|
1287 * | U+013A | ĺ | l | Latin small letter l with acute | |
|
1288 * | U+013B | Ļ | L | Latin capital letter L with cedilla | |
|
1289 * | U+013C | ļ | l | Latin small letter l with cedilla | |
|
1290 * | U+013D | Ľ | L | Latin capital letter L with caron | |
|
1291 * | U+013E | ľ | l | Latin small letter l with caron | |
|
1292 * | U+013F | Ŀ | L | Latin capital letter L with middle dot | |
|
1293 * | U+0140 | ŀ | l | Latin small letter l with middle dot | |
|
1294 * | U+0141 | Ł | L | Latin capital letter L with stroke | |
|
1295 * | U+0142 | ł | l | Latin small letter l with stroke | |
|
1296 * | U+0143 | Ń | N | Latin capital letter N with acute | |
|
1297 * | U+0144 | ń | n | Latin small letter N with acute | |
|
1298 * | U+0145 | Ņ | N | Latin capital letter N with cedilla | |
|
1299 * | U+0146 | ņ | n | Latin small letter n with cedilla | |
|
1300 * | U+0147 | Ň | N | Latin capital letter N with caron | |
|
1301 * | U+0148 | ň | n | Latin small letter n with caron | |
|
1302 * | U+0149 | ʼn | n | Latin small letter n preceded by apostrophe | |
|
1303 * | U+014A | Ŋ | N | Latin capital letter Eng | |
|
1304 * | U+014B | ŋ | n | Latin small letter Eng | |
|
1305 * | U+014C | Ō | O | Latin capital letter O with macron | |
|
1306 * | U+014D | ō | o | Latin small letter o with macron | |
|
1307 * | U+014E | Ŏ | O | Latin capital letter O with breve | |
|
1308 * | U+014F | ŏ | o | Latin small letter o with breve | |
|
1309 * | U+0150 | Ő | O | Latin capital letter O with double acute | |
|
1310 * | U+0151 | ő | o | Latin small letter o with double acute | |
|
1311 * | U+0152 | Œ | OE | Latin capital ligature OE | |
|
1312 * | U+0153 | œ | oe | Latin small ligature oe | |
|
1313 * | U+0154 | Ŕ | R | Latin capital letter R with acute | |
|
1314 * | U+0155 | ŕ | r | Latin small letter r with acute | |
|
1315 * | U+0156 | Ŗ | R | Latin capital letter R with cedilla | |
|
1316 * | U+0157 | ŗ | r | Latin small letter r with cedilla | |
|
1317 * | U+0158 | Ř | R | Latin capital letter R with caron | |
|
1318 * | U+0159 | ř | r | Latin small letter r with caron | |
|
1319 * | U+015A | Ś | S | Latin capital letter S with acute | |
|
1320 * | U+015B | ś | s | Latin small letter s with acute | |
|
1321 * | U+015C | Ŝ | S | Latin capital letter S with circumflex | |
|
1322 * | U+015D | ŝ | s | Latin small letter s with circumflex | |
|
1323 * | U+015E | Ş | S | Latin capital letter S with cedilla | |
|
1324 * | U+015F | ş | s | Latin small letter s with cedilla | |
|
1325 * | U+0160 | Š | S | Latin capital letter S with caron | |
|
1326 * | U+0161 | š | s | Latin small letter s with caron | |
|
1327 * | U+0162 | Ţ | T | Latin capital letter T with cedilla | |
|
1328 * | U+0163 | ţ | t | Latin small letter t with cedilla | |
|
1329 * | U+0164 | Ť | T | Latin capital letter T with caron | |
|
1330 * | U+0165 | ť | t | Latin small letter t with caron | |
|
1331 * | U+0166 | Ŧ | T | Latin capital letter T with stroke | |
|
1332 * | U+0167 | ŧ | t | Latin small letter t with stroke | |
|
1333 * | U+0168 | Ũ | U | Latin capital letter U with tilde | |
|
1334 * | U+0169 | ũ | u | Latin small letter u with tilde | |
|
1335 * | U+016A | Ū | U | Latin capital letter U with macron | |
|
1336 * | U+016B | ū | u | Latin small letter u with macron | |
|
1337 * | U+016C | Ŭ | U | Latin capital letter U with breve | |
|
1338 * | U+016D | ŭ | u | Latin small letter u with breve | |
|
1339 * | U+016E | Ů | U | Latin capital letter U with ring above | |
|
1340 * | U+016F | ů | u | Latin small letter u with ring above | |
|
1341 * | U+0170 | Ű | U | Latin capital letter U with double acute | |
|
1342 * | U+0171 | ű | u | Latin small letter u with double acute | |
|
1343 * | U+0172 | Ų | U | Latin capital letter U with ogonek | |
|
1344 * | U+0173 | ų | u | Latin small letter u with ogonek | |
|
1345 * | U+0174 | Ŵ | W | Latin capital letter W with circumflex | |
|
1346 * | U+0175 | ŵ | w | Latin small letter w with circumflex | |
|
1347 * | U+0176 | Ŷ | Y | Latin capital letter Y with circumflex | |
|
1348 * | U+0177 | ŷ | y | Latin small letter y with circumflex | |
|
1349 * | U+0178 | Ÿ | Y | Latin capital letter Y with diaeresis | |
|
1350 * | U+0179 | Ź | Z | Latin capital letter Z with acute | |
|
1351 * | U+017A | ź | z | Latin small letter z with acute | |
|
1352 * | U+017B | Ż | Z | Latin capital letter Z with dot above | |
|
1353 * | U+017C | ż | z | Latin small letter z with dot above | |
|
1354 * | U+017D | Ž | Z | Latin capital letter Z with caron | |
|
1355 * | U+017E | ž | z | Latin small letter z with caron | |
|
1356 * | U+017F | ſ | s | Latin small letter long s | |
|
1357 * | U+01A0 | Ơ | O | Latin capital letter O with horn | |
|
1358 * | U+01A1 | ơ | o | Latin small letter o with horn | |
|
1359 * | U+01AF | Ư | U | Latin capital letter U with horn | |
|
1360 * | U+01B0 | ư | u | Latin small letter u with horn | |
|
1361 * | U+01CD | Ǎ | A | Latin capital letter A with caron | |
|
1362 * | U+01CE | ǎ | a | Latin small letter a with caron | |
|
1363 * | U+01CF | Ǐ | I | Latin capital letter I with caron | |
|
1364 * | U+01D0 | ǐ | i | Latin small letter i with caron | |
|
1365 * | U+01D1 | Ǒ | O | Latin capital letter O with caron | |
|
1366 * | U+01D2 | ǒ | o | Latin small letter o with caron | |
|
1367 * | U+01D3 | Ǔ | U | Latin capital letter U with caron | |
|
1368 * | U+01D4 | ǔ | u | Latin small letter u with caron | |
|
1369 * | U+01D5 | Ǖ | U | Latin capital letter U with diaeresis and macron | |
|
1370 * | U+01D6 | ǖ | u | Latin small letter u with diaeresis and macron | |
|
1371 * | U+01D7 | Ǘ | U | Latin capital letter U with diaeresis and acute | |
|
1372 * | U+01D8 | ǘ | u | Latin small letter u with diaeresis and acute | |
|
1373 * | U+01D9 | Ǚ | U | Latin capital letter U with diaeresis and caron | |
|
1374 * | U+01DA | ǚ | u | Latin small letter u with diaeresis and caron | |
|
1375 * | U+01DB | Ǜ | U | Latin capital letter U with diaeresis and grave | |
|
1376 * | U+01DC | ǜ | u | Latin small letter u with diaeresis and grave | |
|
1377 * |
|
1378 * Decompositions for Latin Extended-B: |
|
1379 * |
|
1380 * | Code | Glyph | Replacement | Description | |
|
1381 * | -------- | ----- | ----------- | ----------------------------------------- | |
|
1382 * | U+0218 | Ș | S | Latin capital letter S with comma below | |
|
1383 * | U+0219 | ș | s | Latin small letter s with comma below | |
|
1384 * | U+021A | Ț | T | Latin capital letter T with comma below | |
|
1385 * | U+021B | ț | t | Latin small letter t with comma below | |
|
1386 * |
|
1387 * Vowels with diacritic (Chinese, Hanyu Pinyin): |
|
1388 * |
|
1389 * | Code | Glyph | Replacement | Description | |
|
1390 * | -------- | ----- | ----------- | ----------------------------------------------------- | |
|
1391 * | U+0251 | ɑ | a | Latin small letter alpha | |
|
1392 * | U+1EA0 | Ạ | A | Latin capital letter A with dot below | |
|
1393 * | U+1EA1 | ạ | a | Latin small letter a with dot below | |
|
1394 * | U+1EA2 | Ả | A | Latin capital letter A with hook above | |
|
1395 * | U+1EA3 | ả | a | Latin small letter a with hook above | |
|
1396 * | U+1EA4 | Ấ | A | Latin capital letter A with circumflex and acute | |
|
1397 * | U+1EA5 | ấ | a | Latin small letter a with circumflex and acute | |
|
1398 * | U+1EA6 | Ầ | A | Latin capital letter A with circumflex and grave | |
|
1399 * | U+1EA7 | ầ | a | Latin small letter a with circumflex and grave | |
|
1400 * | U+1EA8 | Ẩ | A | Latin capital letter A with circumflex and hook above | |
|
1401 * | U+1EA9 | ẩ | a | Latin small letter a with circumflex and hook above | |
|
1402 * | U+1EAA | Ẫ | A | Latin capital letter A with circumflex and tilde | |
|
1403 * | U+1EAB | ẫ | a | Latin small letter a with circumflex and tilde | |
|
1404 * | U+1EA6 | Ậ | A | Latin capital letter A with circumflex and dot below | |
|
1405 * | U+1EAD | ậ | a | Latin small letter a with circumflex and dot below | |
|
1406 * | U+1EAE | Ắ | A | Latin capital letter A with breve and acute | |
|
1407 * | U+1EAF | ắ | a | Latin small letter a with breve and acute | |
|
1408 * | U+1EB0 | Ằ | A | Latin capital letter A with breve and grave | |
|
1409 * | U+1EB1 | ằ | a | Latin small letter a with breve and grave | |
|
1410 * | U+1EB2 | Ẳ | A | Latin capital letter A with breve and hook above | |
|
1411 * | U+1EB3 | ẳ | a | Latin small letter a with breve and hook above | |
|
1412 * | U+1EB4 | Ẵ | A | Latin capital letter A with breve and tilde | |
|
1413 * | U+1EB5 | ẵ | a | Latin small letter a with breve and tilde | |
|
1414 * | U+1EB6 | Ặ | A | Latin capital letter A with breve and dot below | |
|
1415 * | U+1EB7 | ặ | a | Latin small letter a with breve and dot below | |
|
1416 * | U+1EB8 | Ẹ | E | Latin capital letter E with dot below | |
|
1417 * | U+1EB9 | ẹ | e | Latin small letter e with dot below | |
|
1418 * | U+1EBA | Ẻ | E | Latin capital letter E with hook above | |
|
1419 * | U+1EBB | ẻ | e | Latin small letter e with hook above | |
|
1420 * | U+1EBC | Ẽ | E | Latin capital letter E with tilde | |
|
1421 * | U+1EBD | ẽ | e | Latin small letter e with tilde | |
|
1422 * | U+1EBE | Ế | E | Latin capital letter E with circumflex and acute | |
|
1423 * | U+1EBF | ế | e | Latin small letter e with circumflex and acute | |
|
1424 * | U+1EC0 | Ề | E | Latin capital letter E with circumflex and grave | |
|
1425 * | U+1EC1 | ề | e | Latin small letter e with circumflex and grave | |
|
1426 * | U+1EC2 | Ể | E | Latin capital letter E with circumflex and hook above | |
|
1427 * | U+1EC3 | ể | e | Latin small letter e with circumflex and hook above | |
|
1428 * | U+1EC4 | Ễ | E | Latin capital letter E with circumflex and tilde | |
|
1429 * | U+1EC5 | ễ | e | Latin small letter e with circumflex and tilde | |
|
1430 * | U+1EC6 | Ệ | E | Latin capital letter E with circumflex and dot below | |
|
1431 * | U+1EC7 | ệ | e | Latin small letter e with circumflex and dot below | |
|
1432 * | U+1EC8 | Ỉ | I | Latin capital letter I with hook above | |
|
1433 * | U+1EC9 | ỉ | i | Latin small letter i with hook above | |
|
1434 * | U+1ECA | Ị | I | Latin capital letter I with dot below | |
|
1435 * | U+1ECB | ị | i | Latin small letter i with dot below | |
|
1436 * | U+1ECC | Ọ | O | Latin capital letter O with dot below | |
|
1437 * | U+1ECD | ọ | o | Latin small letter o with dot below | |
|
1438 * | U+1ECE | Ỏ | O | Latin capital letter O with hook above | |
|
1439 * | U+1ECF | ỏ | o | Latin small letter o with hook above | |
|
1440 * | U+1ED0 | Ố | O | Latin capital letter O with circumflex and acute | |
|
1441 * | U+1ED1 | ố | o | Latin small letter o with circumflex and acute | |
|
1442 * | U+1ED2 | Ồ | O | Latin capital letter O with circumflex and grave | |
|
1443 * | U+1ED3 | ồ | o | Latin small letter o with circumflex and grave | |
|
1444 * | U+1ED4 | Ổ | O | Latin capital letter O with circumflex and hook above | |
|
1445 * | U+1ED5 | ổ | o | Latin small letter o with circumflex and hook above | |
|
1446 * | U+1ED6 | Ỗ | O | Latin capital letter O with circumflex and tilde | |
|
1447 * | U+1ED7 | ỗ | o | Latin small letter o with circumflex and tilde | |
|
1448 * | U+1ED8 | Ộ | O | Latin capital letter O with circumflex and dot below | |
|
1449 * | U+1ED9 | ộ | o | Latin small letter o with circumflex and dot below | |
|
1450 * | U+1EDA | Ớ | O | Latin capital letter O with horn and acute | |
|
1451 * | U+1EDB | ớ | o | Latin small letter o with horn and acute | |
|
1452 * | U+1EDC | Ờ | O | Latin capital letter O with horn and grave | |
|
1453 * | U+1EDD | ờ | o | Latin small letter o with horn and grave | |
|
1454 * | U+1EDE | Ở | O | Latin capital letter O with horn and hook above | |
|
1455 * | U+1EDF | ở | o | Latin small letter o with horn and hook above | |
|
1456 * | U+1EE0 | Ỡ | O | Latin capital letter O with horn and tilde | |
|
1457 * | U+1EE1 | ỡ | o | Latin small letter o with horn and tilde | |
|
1458 * | U+1EE2 | Ợ | O | Latin capital letter O with horn and dot below | |
|
1459 * | U+1EE3 | ợ | o | Latin small letter o with horn and dot below | |
|
1460 * | U+1EE4 | Ụ | U | Latin capital letter U with dot below | |
|
1461 * | U+1EE5 | ụ | u | Latin small letter u with dot below | |
|
1462 * | U+1EE6 | Ủ | U | Latin capital letter U with hook above | |
|
1463 * | U+1EE7 | ủ | u | Latin small letter u with hook above | |
|
1464 * | U+1EE8 | Ứ | U | Latin capital letter U with horn and acute | |
|
1465 * | U+1EE9 | ứ | u | Latin small letter u with horn and acute | |
|
1466 * | U+1EEA | Ừ | U | Latin capital letter U with horn and grave | |
|
1467 * | U+1EEB | ừ | u | Latin small letter u with horn and grave | |
|
1468 * | U+1EEC | Ử | U | Latin capital letter U with horn and hook above | |
|
1469 * | U+1EED | ử | u | Latin small letter u with horn and hook above | |
|
1470 * | U+1EEE | Ữ | U | Latin capital letter U with horn and tilde | |
|
1471 * | U+1EEF | ữ | u | Latin small letter u with horn and tilde | |
|
1472 * | U+1EF0 | Ự | U | Latin capital letter U with horn and dot below | |
|
1473 * | U+1EF1 | ự | u | Latin small letter u with horn and dot below | |
|
1474 * | U+1EF2 | Ỳ | Y | Latin capital letter Y with grave | |
|
1475 * | U+1EF3 | ỳ | y | Latin small letter y with grave | |
|
1476 * | U+1EF4 | Ỵ | Y | Latin capital letter Y with dot below | |
|
1477 * | U+1EF5 | ỵ | y | Latin small letter y with dot below | |
|
1478 * | U+1EF6 | Ỷ | Y | Latin capital letter Y with hook above | |
|
1479 * | U+1EF7 | ỷ | y | Latin small letter y with hook above | |
|
1480 * | U+1EF8 | Ỹ | Y | Latin capital letter Y with tilde | |
|
1481 * | U+1EF9 | ỹ | y | Latin small letter y with tilde | |
|
1482 * |
|
1483 * German (`de_DE`), German formal (`de_DE_formal`), German (Switzerland) formal (`de_CH`), |
|
1484 * and German (Switzerland) informal (`de_CH_informal`) locales: |
|
1485 * |
|
1486 * | Code | Glyph | Replacement | Description | |
|
1487 * | -------- | ----- | ----------- | --------------------------------------- | |
|
1488 * | U+00C4 | Ä | Ae | Latin capital letter A with diaeresis | |
|
1489 * | U+00E4 | ä | ae | Latin small letter a with diaeresis | |
|
1490 * | U+00D6 | Ö | Oe | Latin capital letter O with diaeresis | |
|
1491 * | U+00F6 | ö | oe | Latin small letter o with diaeresis | |
|
1492 * | U+00DC | Ü | Ue | Latin capital letter U with diaeresis | |
|
1493 * | U+00FC | ü | ue | Latin small letter u with diaeresis | |
|
1494 * | U+00DF | ß | ss | Latin small letter sharp s | |
|
1495 * |
|
1496 * Danish (`da_DK`) locale: |
|
1497 * |
|
1498 * | Code | Glyph | Replacement | Description | |
|
1499 * | -------- | ----- | ----------- | --------------------------------------- | |
|
1500 * | U+00C6 | Æ | Ae | Latin capital letter AE | |
|
1501 * | U+00E6 | æ | ae | Latin small letter ae | |
|
1502 * | U+00D8 | Ø | Oe | Latin capital letter O with stroke | |
|
1503 * | U+00F8 | ø | oe | Latin small letter o with stroke | |
|
1504 * | U+00C5 | Å | Aa | Latin capital letter A with ring above | |
|
1505 * | U+00E5 | å | aa | Latin small letter a with ring above | |
|
1506 * |
|
1507 * Catalan (`ca`) locale: |
|
1508 * |
|
1509 * | Code | Glyph | Replacement | Description | |
|
1510 * | -------- | ----- | ----------- | --------------------------------------- | |
|
1511 * | U+00B7 | l·l | ll | Flown dot (between two Ls) | |
|
1512 * |
|
1513 * Serbian (`sr_RS`) and Bosnian (`bs_BA`) locales: |
|
1514 * |
|
1515 * | Code | Glyph | Replacement | Description | |
|
1516 * | -------- | ----- | ----------- | --------------------------------------- | |
|
1517 * | U+0110 | Đ | DJ | Latin capital letter D with stroke | |
|
1518 * | U+0111 | đ | dj | Latin small letter d with stroke | |
|
1519 * |
|
868 * @since 1.2.1 |
1520 * @since 1.2.1 |
1521 * @since 4.6.0 Added locale support for `de_CH`, `de_CH_informal`, and `ca`. |
|
1522 * @since 4.7.0 Added locale support for `sr_RS`. |
|
1523 * @since 4.8.0 Added locale support for `bs_BA`. |
|
869 * |
1524 * |
870 * @param string $string Text that might have accent characters |
1525 * @param string $string Text that might have accent characters |
871 * @return string Filtered string with replaced "nice" characters. |
1526 * @return string Filtered string with replaced "nice" characters. |
872 */ |
1527 */ |
873 function remove_accents($string) { |
1528 function remove_accents( $string ) { |
874 if ( !preg_match('/[\x80-\xff]/', $string) ) |
1529 if ( !preg_match('/[\x80-\xff]/', $string) ) |
875 return $string; |
1530 return $string; |
876 |
1531 |
877 if (seems_utf8($string)) { |
1532 if (seems_utf8($string)) { |
878 $chars = array( |
1533 $chars = array( |
879 // Decompositions for Latin-1 Supplement |
1534 // Decompositions for Latin-1 Supplement |
880 chr(194).chr(170) => 'a', chr(194).chr(186) => 'o', |
1535 'ª' => 'a', 'º' => 'o', |
881 chr(195).chr(128) => 'A', chr(195).chr(129) => 'A', |
1536 'À' => 'A', 'Á' => 'A', |
882 chr(195).chr(130) => 'A', chr(195).chr(131) => 'A', |
1537 'Â' => 'A', 'Ã' => 'A', |
883 chr(195).chr(132) => 'A', chr(195).chr(133) => 'A', |
1538 'Ä' => 'A', 'Å' => 'A', |
884 chr(195).chr(134) => 'AE',chr(195).chr(135) => 'C', |
1539 'Æ' => 'AE','Ç' => 'C', |
885 chr(195).chr(136) => 'E', chr(195).chr(137) => 'E', |
1540 'È' => 'E', 'É' => 'E', |
886 chr(195).chr(138) => 'E', chr(195).chr(139) => 'E', |
1541 'Ê' => 'E', 'Ë' => 'E', |
887 chr(195).chr(140) => 'I', chr(195).chr(141) => 'I', |
1542 'Ì' => 'I', 'Í' => 'I', |
888 chr(195).chr(142) => 'I', chr(195).chr(143) => 'I', |
1543 'Î' => 'I', 'Ï' => 'I', |
889 chr(195).chr(144) => 'D', chr(195).chr(145) => 'N', |
1544 'Ð' => 'D', 'Ñ' => 'N', |
890 chr(195).chr(146) => 'O', chr(195).chr(147) => 'O', |
1545 'Ò' => 'O', 'Ó' => 'O', |
891 chr(195).chr(148) => 'O', chr(195).chr(149) => 'O', |
1546 'Ô' => 'O', 'Õ' => 'O', |
892 chr(195).chr(150) => 'O', chr(195).chr(153) => 'U', |
1547 'Ö' => 'O', 'Ù' => 'U', |
893 chr(195).chr(154) => 'U', chr(195).chr(155) => 'U', |
1548 'Ú' => 'U', 'Û' => 'U', |
894 chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y', |
1549 'Ü' => 'U', 'Ý' => 'Y', |
895 chr(195).chr(158) => 'TH',chr(195).chr(159) => 's', |
1550 'Þ' => 'TH','ß' => 's', |
896 chr(195).chr(160) => 'a', chr(195).chr(161) => 'a', |
1551 'à' => 'a', 'á' => 'a', |
897 chr(195).chr(162) => 'a', chr(195).chr(163) => 'a', |
1552 'â' => 'a', 'ã' => 'a', |
898 chr(195).chr(164) => 'a', chr(195).chr(165) => 'a', |
1553 'ä' => 'a', 'å' => 'a', |
899 chr(195).chr(166) => 'ae',chr(195).chr(167) => 'c', |
1554 'æ' => 'ae','ç' => 'c', |
900 chr(195).chr(168) => 'e', chr(195).chr(169) => 'e', |
1555 'è' => 'e', 'é' => 'e', |
901 chr(195).chr(170) => 'e', chr(195).chr(171) => 'e', |
1556 'ê' => 'e', 'ë' => 'e', |
902 chr(195).chr(172) => 'i', chr(195).chr(173) => 'i', |
1557 'ì' => 'i', 'í' => 'i', |
903 chr(195).chr(174) => 'i', chr(195).chr(175) => 'i', |
1558 'î' => 'i', 'ï' => 'i', |
904 chr(195).chr(176) => 'd', chr(195).chr(177) => 'n', |
1559 'ð' => 'd', 'ñ' => 'n', |
905 chr(195).chr(178) => 'o', chr(195).chr(179) => 'o', |
1560 'ò' => 'o', 'ó' => 'o', |
906 chr(195).chr(180) => 'o', chr(195).chr(181) => 'o', |
1561 'ô' => 'o', 'õ' => 'o', |
907 chr(195).chr(182) => 'o', chr(195).chr(184) => 'o', |
1562 'ö' => 'o', 'ø' => 'o', |
908 chr(195).chr(185) => 'u', chr(195).chr(186) => 'u', |
1563 'ù' => 'u', 'ú' => 'u', |
909 chr(195).chr(187) => 'u', chr(195).chr(188) => 'u', |
1564 'û' => 'u', 'ü' => 'u', |
910 chr(195).chr(189) => 'y', chr(195).chr(190) => 'th', |
1565 'ý' => 'y', 'þ' => 'th', |
911 chr(195).chr(191) => 'y', chr(195).chr(152) => 'O', |
1566 'ÿ' => 'y', 'Ø' => 'O', |
912 // Decompositions for Latin Extended-A |
1567 // Decompositions for Latin Extended-A |
913 chr(196).chr(128) => 'A', chr(196).chr(129) => 'a', |
1568 'Ā' => 'A', 'ā' => 'a', |
914 chr(196).chr(130) => 'A', chr(196).chr(131) => 'a', |
1569 'Ă' => 'A', 'ă' => 'a', |
915 chr(196).chr(132) => 'A', chr(196).chr(133) => 'a', |
1570 'Ą' => 'A', 'ą' => 'a', |
916 chr(196).chr(134) => 'C', chr(196).chr(135) => 'c', |
1571 'Ć' => 'C', 'ć' => 'c', |
917 chr(196).chr(136) => 'C', chr(196).chr(137) => 'c', |
1572 'Ĉ' => 'C', 'ĉ' => 'c', |
918 chr(196).chr(138) => 'C', chr(196).chr(139) => 'c', |
1573 'Ċ' => 'C', 'ċ' => 'c', |
919 chr(196).chr(140) => 'C', chr(196).chr(141) => 'c', |
1574 'Č' => 'C', 'č' => 'c', |
920 chr(196).chr(142) => 'D', chr(196).chr(143) => 'd', |
1575 'Ď' => 'D', 'ď' => 'd', |
921 chr(196).chr(144) => 'D', chr(196).chr(145) => 'd', |
1576 'Đ' => 'D', 'đ' => 'd', |
922 chr(196).chr(146) => 'E', chr(196).chr(147) => 'e', |
1577 'Ē' => 'E', 'ē' => 'e', |
923 chr(196).chr(148) => 'E', chr(196).chr(149) => 'e', |
1578 'Ĕ' => 'E', 'ĕ' => 'e', |
924 chr(196).chr(150) => 'E', chr(196).chr(151) => 'e', |
1579 'Ė' => 'E', 'ė' => 'e', |
925 chr(196).chr(152) => 'E', chr(196).chr(153) => 'e', |
1580 'Ę' => 'E', 'ę' => 'e', |
926 chr(196).chr(154) => 'E', chr(196).chr(155) => 'e', |
1581 'Ě' => 'E', 'ě' => 'e', |
927 chr(196).chr(156) => 'G', chr(196).chr(157) => 'g', |
1582 'Ĝ' => 'G', 'ĝ' => 'g', |
928 chr(196).chr(158) => 'G', chr(196).chr(159) => 'g', |
1583 'Ğ' => 'G', 'ğ' => 'g', |
929 chr(196).chr(160) => 'G', chr(196).chr(161) => 'g', |
1584 'Ġ' => 'G', 'ġ' => 'g', |
930 chr(196).chr(162) => 'G', chr(196).chr(163) => 'g', |
1585 'Ģ' => 'G', 'ģ' => 'g', |
931 chr(196).chr(164) => 'H', chr(196).chr(165) => 'h', |
1586 'Ĥ' => 'H', 'ĥ' => 'h', |
932 chr(196).chr(166) => 'H', chr(196).chr(167) => 'h', |
1587 'Ħ' => 'H', 'ħ' => 'h', |
933 chr(196).chr(168) => 'I', chr(196).chr(169) => 'i', |
1588 'Ĩ' => 'I', 'ĩ' => 'i', |
934 chr(196).chr(170) => 'I', chr(196).chr(171) => 'i', |
1589 'Ī' => 'I', 'ī' => 'i', |
935 chr(196).chr(172) => 'I', chr(196).chr(173) => 'i', |
1590 'Ĭ' => 'I', 'ĭ' => 'i', |
936 chr(196).chr(174) => 'I', chr(196).chr(175) => 'i', |
1591 'Į' => 'I', 'į' => 'i', |
937 chr(196).chr(176) => 'I', chr(196).chr(177) => 'i', |
1592 'İ' => 'I', 'ı' => 'i', |
938 chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij', |
1593 'IJ' => 'IJ','ij' => 'ij', |
939 chr(196).chr(180) => 'J', chr(196).chr(181) => 'j', |
1594 'Ĵ' => 'J', 'ĵ' => 'j', |
940 chr(196).chr(182) => 'K', chr(196).chr(183) => 'k', |
1595 'Ķ' => 'K', 'ķ' => 'k', |
941 chr(196).chr(184) => 'k', chr(196).chr(185) => 'L', |
1596 'ĸ' => 'k', 'Ĺ' => 'L', |
942 chr(196).chr(186) => 'l', chr(196).chr(187) => 'L', |
1597 'ĺ' => 'l', 'Ļ' => 'L', |
943 chr(196).chr(188) => 'l', chr(196).chr(189) => 'L', |
1598 'ļ' => 'l', 'Ľ' => 'L', |
944 chr(196).chr(190) => 'l', chr(196).chr(191) => 'L', |
1599 'ľ' => 'l', 'Ŀ' => 'L', |
945 chr(197).chr(128) => 'l', chr(197).chr(129) => 'L', |
1600 'ŀ' => 'l', 'Ł' => 'L', |
946 chr(197).chr(130) => 'l', chr(197).chr(131) => 'N', |
1601 'ł' => 'l', 'Ń' => 'N', |
947 chr(197).chr(132) => 'n', chr(197).chr(133) => 'N', |
1602 'ń' => 'n', 'Ņ' => 'N', |
948 chr(197).chr(134) => 'n', chr(197).chr(135) => 'N', |
1603 'ņ' => 'n', 'Ň' => 'N', |
949 chr(197).chr(136) => 'n', chr(197).chr(137) => 'N', |
1604 'ň' => 'n', 'ʼn' => 'n', |
950 chr(197).chr(138) => 'n', chr(197).chr(139) => 'N', |
1605 'Ŋ' => 'N', 'ŋ' => 'n', |
951 chr(197).chr(140) => 'O', chr(197).chr(141) => 'o', |
1606 'Ō' => 'O', 'ō' => 'o', |
952 chr(197).chr(142) => 'O', chr(197).chr(143) => 'o', |
1607 'Ŏ' => 'O', 'ŏ' => 'o', |
953 chr(197).chr(144) => 'O', chr(197).chr(145) => 'o', |
1608 'Ő' => 'O', 'ő' => 'o', |
954 chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe', |
1609 'Œ' => 'OE','œ' => 'oe', |
955 chr(197).chr(148) => 'R',chr(197).chr(149) => 'r', |
1610 'Ŕ' => 'R','ŕ' => 'r', |
956 chr(197).chr(150) => 'R',chr(197).chr(151) => 'r', |
1611 'Ŗ' => 'R','ŗ' => 'r', |
957 chr(197).chr(152) => 'R',chr(197).chr(153) => 'r', |
1612 'Ř' => 'R','ř' => 'r', |
958 chr(197).chr(154) => 'S',chr(197).chr(155) => 's', |
1613 'Ś' => 'S','ś' => 's', |
959 chr(197).chr(156) => 'S',chr(197).chr(157) => 's', |
1614 'Ŝ' => 'S','ŝ' => 's', |
960 chr(197).chr(158) => 'S',chr(197).chr(159) => 's', |
1615 'Ş' => 'S','ş' => 's', |
961 chr(197).chr(160) => 'S', chr(197).chr(161) => 's', |
1616 'Š' => 'S', 'š' => 's', |
962 chr(197).chr(162) => 'T', chr(197).chr(163) => 't', |
1617 'Ţ' => 'T', 'ţ' => 't', |
963 chr(197).chr(164) => 'T', chr(197).chr(165) => 't', |
1618 'Ť' => 'T', 'ť' => 't', |
964 chr(197).chr(166) => 'T', chr(197).chr(167) => 't', |
1619 'Ŧ' => 'T', 'ŧ' => 't', |
965 chr(197).chr(168) => 'U', chr(197).chr(169) => 'u', |
1620 'Ũ' => 'U', 'ũ' => 'u', |
966 chr(197).chr(170) => 'U', chr(197).chr(171) => 'u', |
1621 'Ū' => 'U', 'ū' => 'u', |
967 chr(197).chr(172) => 'U', chr(197).chr(173) => 'u', |
1622 'Ŭ' => 'U', 'ŭ' => 'u', |
968 chr(197).chr(174) => 'U', chr(197).chr(175) => 'u', |
1623 'Ů' => 'U', 'ů' => 'u', |
969 chr(197).chr(176) => 'U', chr(197).chr(177) => 'u', |
1624 'Ű' => 'U', 'ű' => 'u', |
970 chr(197).chr(178) => 'U', chr(197).chr(179) => 'u', |
1625 'Ų' => 'U', 'ų' => 'u', |
971 chr(197).chr(180) => 'W', chr(197).chr(181) => 'w', |
1626 'Ŵ' => 'W', 'ŵ' => 'w', |
972 chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y', |
1627 'Ŷ' => 'Y', 'ŷ' => 'y', |
973 chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z', |
1628 'Ÿ' => 'Y', 'Ź' => 'Z', |
974 chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z', |
1629 'ź' => 'z', 'Ż' => 'Z', |
975 chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z', |
1630 'ż' => 'z', 'Ž' => 'Z', |
976 chr(197).chr(190) => 'z', chr(197).chr(191) => 's', |
1631 'ž' => 'z', 'ſ' => 's', |
977 // Decompositions for Latin Extended-B |
1632 // Decompositions for Latin Extended-B |
978 chr(200).chr(152) => 'S', chr(200).chr(153) => 's', |
1633 'Ș' => 'S', 'ș' => 's', |
979 chr(200).chr(154) => 'T', chr(200).chr(155) => 't', |
1634 'Ț' => 'T', 'ț' => 't', |
980 // Euro Sign |
1635 // Euro Sign |
981 chr(226).chr(130).chr(172) => 'E', |
1636 '€' => 'E', |
982 // GBP (Pound) Sign |
1637 // GBP (Pound) Sign |
983 chr(194).chr(163) => '', |
1638 '£' => '', |
984 // Vowels with diacritic (Vietnamese) |
1639 // Vowels with diacritic (Vietnamese) |
985 // unmarked |
1640 // unmarked |
986 chr(198).chr(160) => 'O', chr(198).chr(161) => 'o', |
1641 'Ơ' => 'O', 'ơ' => 'o', |
987 chr(198).chr(175) => 'U', chr(198).chr(176) => 'u', |
1642 'Ư' => 'U', 'ư' => 'u', |
988 // grave accent |
1643 // grave accent |
989 chr(225).chr(186).chr(166) => 'A', chr(225).chr(186).chr(167) => 'a', |
1644 'Ầ' => 'A', 'ầ' => 'a', |
990 chr(225).chr(186).chr(176) => 'A', chr(225).chr(186).chr(177) => 'a', |
1645 'Ằ' => 'A', 'ằ' => 'a', |
991 chr(225).chr(187).chr(128) => 'E', chr(225).chr(187).chr(129) => 'e', |
1646 'Ề' => 'E', 'ề' => 'e', |
992 chr(225).chr(187).chr(146) => 'O', chr(225).chr(187).chr(147) => 'o', |
1647 'Ồ' => 'O', 'ồ' => 'o', |
993 chr(225).chr(187).chr(156) => 'O', chr(225).chr(187).chr(157) => 'o', |
1648 'Ờ' => 'O', 'ờ' => 'o', |
994 chr(225).chr(187).chr(170) => 'U', chr(225).chr(187).chr(171) => 'u', |
1649 'Ừ' => 'U', 'ừ' => 'u', |
995 chr(225).chr(187).chr(178) => 'Y', chr(225).chr(187).chr(179) => 'y', |
1650 'Ỳ' => 'Y', 'ỳ' => 'y', |
996 // hook |
1651 // hook |
997 chr(225).chr(186).chr(162) => 'A', chr(225).chr(186).chr(163) => 'a', |
1652 'Ả' => 'A', 'ả' => 'a', |
998 chr(225).chr(186).chr(168) => 'A', chr(225).chr(186).chr(169) => 'a', |
1653 'Ẩ' => 'A', 'ẩ' => 'a', |
999 chr(225).chr(186).chr(178) => 'A', chr(225).chr(186).chr(179) => 'a', |
1654 'Ẳ' => 'A', 'ẳ' => 'a', |
1000 chr(225).chr(186).chr(186) => 'E', chr(225).chr(186).chr(187) => 'e', |
1655 'Ẻ' => 'E', 'ẻ' => 'e', |
1001 chr(225).chr(187).chr(130) => 'E', chr(225).chr(187).chr(131) => 'e', |
1656 'Ể' => 'E', 'ể' => 'e', |
1002 chr(225).chr(187).chr(136) => 'I', chr(225).chr(187).chr(137) => 'i', |
1657 'Ỉ' => 'I', 'ỉ' => 'i', |
1003 chr(225).chr(187).chr(142) => 'O', chr(225).chr(187).chr(143) => 'o', |
1658 'Ỏ' => 'O', 'ỏ' => 'o', |
1004 chr(225).chr(187).chr(148) => 'O', chr(225).chr(187).chr(149) => 'o', |
1659 'Ổ' => 'O', 'ổ' => 'o', |
1005 chr(225).chr(187).chr(158) => 'O', chr(225).chr(187).chr(159) => 'o', |
1660 'Ở' => 'O', 'ở' => 'o', |
1006 chr(225).chr(187).chr(166) => 'U', chr(225).chr(187).chr(167) => 'u', |
1661 'Ủ' => 'U', 'ủ' => 'u', |
1007 chr(225).chr(187).chr(172) => 'U', chr(225).chr(187).chr(173) => 'u', |
1662 'Ử' => 'U', 'ử' => 'u', |
1008 chr(225).chr(187).chr(182) => 'Y', chr(225).chr(187).chr(183) => 'y', |
1663 'Ỷ' => 'Y', 'ỷ' => 'y', |
1009 // tilde |
1664 // tilde |
1010 chr(225).chr(186).chr(170) => 'A', chr(225).chr(186).chr(171) => 'a', |
1665 'Ẫ' => 'A', 'ẫ' => 'a', |
1011 chr(225).chr(186).chr(180) => 'A', chr(225).chr(186).chr(181) => 'a', |
1666 'Ẵ' => 'A', 'ẵ' => 'a', |
1012 chr(225).chr(186).chr(188) => 'E', chr(225).chr(186).chr(189) => 'e', |
1667 'Ẽ' => 'E', 'ẽ' => 'e', |
1013 chr(225).chr(187).chr(132) => 'E', chr(225).chr(187).chr(133) => 'e', |
1668 'Ễ' => 'E', 'ễ' => 'e', |
1014 chr(225).chr(187).chr(150) => 'O', chr(225).chr(187).chr(151) => 'o', |
1669 'Ỗ' => 'O', 'ỗ' => 'o', |
1015 chr(225).chr(187).chr(160) => 'O', chr(225).chr(187).chr(161) => 'o', |
1670 'Ỡ' => 'O', 'ỡ' => 'o', |
1016 chr(225).chr(187).chr(174) => 'U', chr(225).chr(187).chr(175) => 'u', |
1671 'Ữ' => 'U', 'ữ' => 'u', |
1017 chr(225).chr(187).chr(184) => 'Y', chr(225).chr(187).chr(185) => 'y', |
1672 'Ỹ' => 'Y', 'ỹ' => 'y', |
1018 // acute accent |
1673 // acute accent |
1019 chr(225).chr(186).chr(164) => 'A', chr(225).chr(186).chr(165) => 'a', |
1674 'Ấ' => 'A', 'ấ' => 'a', |
1020 chr(225).chr(186).chr(174) => 'A', chr(225).chr(186).chr(175) => 'a', |
1675 'Ắ' => 'A', 'ắ' => 'a', |
1021 chr(225).chr(186).chr(190) => 'E', chr(225).chr(186).chr(191) => 'e', |
1676 'Ế' => 'E', 'ế' => 'e', |
1022 chr(225).chr(187).chr(144) => 'O', chr(225).chr(187).chr(145) => 'o', |
1677 'Ố' => 'O', 'ố' => 'o', |
1023 chr(225).chr(187).chr(154) => 'O', chr(225).chr(187).chr(155) => 'o', |
1678 'Ớ' => 'O', 'ớ' => 'o', |
1024 chr(225).chr(187).chr(168) => 'U', chr(225).chr(187).chr(169) => 'u', |
1679 'Ứ' => 'U', 'ứ' => 'u', |
1025 // dot below |
1680 // dot below |
1026 chr(225).chr(186).chr(160) => 'A', chr(225).chr(186).chr(161) => 'a', |
1681 'Ạ' => 'A', 'ạ' => 'a', |
1027 chr(225).chr(186).chr(172) => 'A', chr(225).chr(186).chr(173) => 'a', |
1682 'Ậ' => 'A', 'ậ' => 'a', |
1028 chr(225).chr(186).chr(182) => 'A', chr(225).chr(186).chr(183) => 'a', |
1683 'Ặ' => 'A', 'ặ' => 'a', |
1029 chr(225).chr(186).chr(184) => 'E', chr(225).chr(186).chr(185) => 'e', |
1684 'Ẹ' => 'E', 'ẹ' => 'e', |
1030 chr(225).chr(187).chr(134) => 'E', chr(225).chr(187).chr(135) => 'e', |
1685 'Ệ' => 'E', 'ệ' => 'e', |
1031 chr(225).chr(187).chr(138) => 'I', chr(225).chr(187).chr(139) => 'i', |
1686 'Ị' => 'I', 'ị' => 'i', |
1032 chr(225).chr(187).chr(140) => 'O', chr(225).chr(187).chr(141) => 'o', |
1687 'Ọ' => 'O', 'ọ' => 'o', |
1033 chr(225).chr(187).chr(152) => 'O', chr(225).chr(187).chr(153) => 'o', |
1688 'Ộ' => 'O', 'ộ' => 'o', |
1034 chr(225).chr(187).chr(162) => 'O', chr(225).chr(187).chr(163) => 'o', |
1689 'Ợ' => 'O', 'ợ' => 'o', |
1035 chr(225).chr(187).chr(164) => 'U', chr(225).chr(187).chr(165) => 'u', |
1690 'Ụ' => 'U', 'ụ' => 'u', |
1036 chr(225).chr(187).chr(176) => 'U', chr(225).chr(187).chr(177) => 'u', |
1691 'Ự' => 'U', 'ự' => 'u', |
1037 chr(225).chr(187).chr(180) => 'Y', chr(225).chr(187).chr(181) => 'y', |
1692 'Ỵ' => 'Y', 'ỵ' => 'y', |
1038 // Vowels with diacritic (Chinese, Hanyu Pinyin) |
1693 // Vowels with diacritic (Chinese, Hanyu Pinyin) |
1039 chr(201).chr(145) => 'a', |
1694 'ɑ' => 'a', |
1040 // macron |
1695 // macron |
1041 chr(199).chr(149) => 'U', chr(199).chr(150) => 'u', |
1696 'Ǖ' => 'U', 'ǖ' => 'u', |
1042 // acute accent |
1697 // acute accent |
1043 chr(199).chr(151) => 'U', chr(199).chr(152) => 'u', |
1698 'Ǘ' => 'U', 'ǘ' => 'u', |
1044 // caron |
1699 // caron |
1045 chr(199).chr(141) => 'A', chr(199).chr(142) => 'a', |
1700 'Ǎ' => 'A', 'ǎ' => 'a', |
1046 chr(199).chr(143) => 'I', chr(199).chr(144) => 'i', |
1701 'Ǐ' => 'I', 'ǐ' => 'i', |
1047 chr(199).chr(145) => 'O', chr(199).chr(146) => 'o', |
1702 'Ǒ' => 'O', 'ǒ' => 'o', |
1048 chr(199).chr(147) => 'U', chr(199).chr(148) => 'u', |
1703 'Ǔ' => 'U', 'ǔ' => 'u', |
1049 chr(199).chr(153) => 'U', chr(199).chr(154) => 'u', |
1704 'Ǚ' => 'U', 'ǚ' => 'u', |
1050 // grave accent |
1705 // grave accent |
1051 chr(199).chr(155) => 'U', chr(199).chr(156) => 'u', |
1706 'Ǜ' => 'U', 'ǜ' => 'u', |
1052 ); |
1707 ); |
1053 |
1708 |
1054 // Used for locale-specific rules |
1709 // Used for locale-specific rules |
1055 $locale = get_locale(); |
1710 $locale = get_locale(); |
1056 |
1711 |
1057 if ( 'de_DE' == $locale ) { |
1712 if ( 'de_DE' == $locale || 'de_DE_formal' == $locale || 'de_CH' == $locale || 'de_CH_informal' == $locale ) { |
1058 $chars[ chr(195).chr(132) ] = 'Ae'; |
1713 $chars[ 'Ä' ] = 'Ae'; |
1059 $chars[ chr(195).chr(164) ] = 'ae'; |
1714 $chars[ 'ä' ] = 'ae'; |
1060 $chars[ chr(195).chr(150) ] = 'Oe'; |
1715 $chars[ 'Ö' ] = 'Oe'; |
1061 $chars[ chr(195).chr(182) ] = 'oe'; |
1716 $chars[ 'ö' ] = 'oe'; |
1062 $chars[ chr(195).chr(156) ] = 'Ue'; |
1717 $chars[ 'Ü' ] = 'Ue'; |
1063 $chars[ chr(195).chr(188) ] = 'ue'; |
1718 $chars[ 'ü' ] = 'ue'; |
1064 $chars[ chr(195).chr(159) ] = 'ss'; |
1719 $chars[ 'ß' ] = 'ss'; |
1065 } elseif ( 'da_DK' === $locale ) { |
1720 } elseif ( 'da_DK' === $locale ) { |
1066 $chars[ chr(195).chr(134) ] = 'Ae'; |
1721 $chars[ 'Æ' ] = 'Ae'; |
1067 $chars[ chr(195).chr(166) ] = 'ae'; |
1722 $chars[ 'æ' ] = 'ae'; |
1068 $chars[ chr(195).chr(152) ] = 'Oe'; |
1723 $chars[ 'Ø' ] = 'Oe'; |
1069 $chars[ chr(195).chr(184) ] = 'oe'; |
1724 $chars[ 'ø' ] = 'oe'; |
1070 $chars[ chr(195).chr(133) ] = 'Aa'; |
1725 $chars[ 'Å' ] = 'Aa'; |
1071 $chars[ chr(195).chr(165) ] = 'aa'; |
1726 $chars[ 'å' ] = 'aa'; |
1727 } elseif ( 'ca' === $locale ) { |
|
1728 $chars[ 'l·l' ] = 'll'; |
|
1729 } elseif ( 'sr_RS' === $locale || 'bs_BA' === $locale ) { |
|
1730 $chars[ 'Đ' ] = 'DJ'; |
|
1731 $chars[ 'đ' ] = 'dj'; |
|
1072 } |
1732 } |
1073 |
1733 |
1074 $string = strtr($string, $chars); |
1734 $string = strtr($string, $chars); |
1075 } else { |
1735 } else { |
1076 $chars = array(); |
1736 $chars = array(); |
1077 // Assume ISO-8859-1 if not UTF-8 |
1737 // Assume ISO-8859-1 if not UTF-8 |
1078 $chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158) |
1738 $chars['in'] = "\x80\x83\x8a\x8e\x9a\x9e" |
1079 .chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194) |
1739 ."\x9f\xa2\xa5\xb5\xc0\xc1\xc2" |
1080 .chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202) |
1740 ."\xc3\xc4\xc5\xc7\xc8\xc9\xca" |
1081 .chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210) |
1741 ."\xcb\xcc\xcd\xce\xcf\xd1\xd2" |
1082 .chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218) |
1742 ."\xd3\xd4\xd5\xd6\xd8\xd9\xda" |
1083 .chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227) |
1743 ."\xdb\xdc\xdd\xe0\xe1\xe2\xe3" |
1084 .chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235) |
1744 ."\xe4\xe5\xe7\xe8\xe9\xea\xeb" |
1085 .chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243) |
1745 ."\xec\xed\xee\xef\xf1\xf2\xf3" |
1086 .chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251) |
1746 ."\xf4\xf5\xf6\xf8\xf9\xfa\xfb" |
1087 .chr(252).chr(253).chr(255); |
1747 ."\xfc\xfd\xff"; |
1088 |
1748 |
1089 $chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy"; |
1749 $chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy"; |
1090 |
1750 |
1091 $string = strtr($string, $chars['in'], $chars['out']); |
1751 $string = strtr($string, $chars['in'], $chars['out']); |
1092 $double_chars = array(); |
1752 $double_chars = array(); |
1093 $double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254)); |
1753 $double_chars['in'] = array("\x8c", "\x9c", "\xc6", "\xd0", "\xde", "\xdf", "\xe6", "\xf0", "\xfe"); |
1094 $double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'); |
1754 $double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'); |
1095 $string = str_replace($double_chars['in'], $double_chars['out'], $string); |
1755 $string = str_replace($double_chars['in'], $double_chars['out'], $string); |
1096 } |
1756 } |
1097 |
1757 |
1098 return $string; |
1758 return $string; |
1103 * |
1763 * |
1104 * Removes special characters that are illegal in filenames on certain |
1764 * Removes special characters that are illegal in filenames on certain |
1105 * operating systems and special characters requiring special escaping |
1765 * operating systems and special characters requiring special escaping |
1106 * to manipulate at the command line. Replaces spaces and consecutive |
1766 * to manipulate at the command line. Replaces spaces and consecutive |
1107 * dashes with a single dash. Trims period, dash and underscore from beginning |
1767 * dashes with a single dash. Trims period, dash and underscore from beginning |
1108 * and end of filename. |
1768 * and end of filename. It is not guaranteed that this function will return a |
1769 * filename that is allowed to be uploaded. |
|
1109 * |
1770 * |
1110 * @since 2.1.0 |
1771 * @since 2.1.0 |
1111 * |
1772 * |
1112 * @param string $filename The filename to be sanitized |
1773 * @param string $filename The filename to be sanitized |
1113 * @return string The sanitized filename |
1774 * @return string The sanitized filename |
1114 */ |
1775 */ |
1115 function sanitize_file_name( $filename ) { |
1776 function sanitize_file_name( $filename ) { |
1116 $filename_raw = $filename; |
1777 $filename_raw = $filename; |
1117 $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", chr(0)); |
1778 $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0)); |
1118 /** |
1779 /** |
1119 * Filter the list of characters to remove from a filename. |
1780 * Filters the list of characters to remove from a filename. |
1120 * |
1781 * |
1121 * @since 2.8.0 |
1782 * @since 2.8.0 |
1122 * |
1783 * |
1123 * @param array $special_chars Characters to remove. |
1784 * @param array $special_chars Characters to remove. |
1124 * @param string $filename_raw Filename as it was passed into sanitize_file_name(). |
1785 * @param string $filename_raw Filename as it was passed into sanitize_file_name(). |
1128 $filename = str_replace( $special_chars, '', $filename ); |
1789 $filename = str_replace( $special_chars, '', $filename ); |
1129 $filename = str_replace( array( '%20', '+' ), '-', $filename ); |
1790 $filename = str_replace( array( '%20', '+' ), '-', $filename ); |
1130 $filename = preg_replace( '/[\r\n\t -]+/', '-', $filename ); |
1791 $filename = preg_replace( '/[\r\n\t -]+/', '-', $filename ); |
1131 $filename = trim( $filename, '.-_' ); |
1792 $filename = trim( $filename, '.-_' ); |
1132 |
1793 |
1794 if ( false === strpos( $filename, '.' ) ) { |
|
1795 $mime_types = wp_get_mime_types(); |
|
1796 $filetype = wp_check_filetype( 'test.' . $filename, $mime_types ); |
|
1797 if ( $filetype['ext'] === $filename ) { |
|
1798 $filename = 'unnamed-file.' . $filetype['ext']; |
|
1799 } |
|
1800 } |
|
1801 |
|
1133 // Split the filename into a base and extension[s] |
1802 // Split the filename into a base and extension[s] |
1134 $parts = explode('.', $filename); |
1803 $parts = explode('.', $filename); |
1135 |
1804 |
1136 // Return if only one extension |
1805 // Return if only one extension |
1137 if ( count( $parts ) <= 2 ) { |
1806 if ( count( $parts ) <= 2 ) { |
1138 /** |
1807 /** |
1139 * Filter a sanitized filename string. |
1808 * Filters a sanitized filename string. |
1140 * |
1809 * |
1141 * @since 2.8.0 |
1810 * @since 2.8.0 |
1142 * |
1811 * |
1143 * @param string $filename Sanitized filename. |
1812 * @param string $filename Sanitized filename. |
1144 * @param string $filename_raw The filename prior to sanitization. |
1813 * @param string $filename_raw The filename prior to sanitization. |
1180 * Sanitizes a username, stripping out unsafe characters. |
1849 * Sanitizes a username, stripping out unsafe characters. |
1181 * |
1850 * |
1182 * Removes tags, octets, entities, and if strict is enabled, will only keep |
1851 * Removes tags, octets, entities, and if strict is enabled, will only keep |
1183 * alphanumeric, _, space, ., -, @. After sanitizing, it passes the username, |
1852 * alphanumeric, _, space, ., -, @. After sanitizing, it passes the username, |
1184 * raw username (the username in the parameter), and the value of $strict as |
1853 * raw username (the username in the parameter), and the value of $strict as |
1185 * parameters for the 'sanitize_user' filter. |
1854 * parameters for the {@see 'sanitize_user'} filter. |
1186 * |
1855 * |
1187 * @since 2.0.0 |
1856 * @since 2.0.0 |
1188 * |
1857 * |
1189 * @param string $username The username to be sanitized. |
1858 * @param string $username The username to be sanitized. |
1190 * @param bool $strict If set limits $username to specific characters. Default false. |
1859 * @param bool $strict If set limits $username to specific characters. Default false. |
1191 * @return string The sanitized username, after passing through filters. |
1860 * @return string The sanitized username, after passing through filters. |
1192 */ |
1861 */ |
1193 function sanitize_user( $username, $strict = false ) { |
1862 function sanitize_user( $username, $strict = false ) { |
1194 $raw_username = $username; |
1863 $raw_username = $username; |
1195 $username = wp_strip_all_tags( $username ); |
1864 $username = wp_strip_all_tags( $username ); |
1205 $username = trim( $username ); |
1874 $username = trim( $username ); |
1206 // Consolidate contiguous whitespace |
1875 // Consolidate contiguous whitespace |
1207 $username = preg_replace( '|\s+|', ' ', $username ); |
1876 $username = preg_replace( '|\s+|', ' ', $username ); |
1208 |
1877 |
1209 /** |
1878 /** |
1210 * Filter a sanitized username string. |
1879 * Filters a sanitized username string. |
1211 * |
1880 * |
1212 * @since 2.0.1 |
1881 * @since 2.0.1 |
1213 * |
1882 * |
1214 * @param string $username Sanitized username. |
1883 * @param string $username Sanitized username. |
1215 * @param string $raw_username The username prior to sanitization. |
1884 * @param string $raw_username The username prior to sanitization. |
1232 $raw_key = $key; |
1901 $raw_key = $key; |
1233 $key = strtolower( $key ); |
1902 $key = strtolower( $key ); |
1234 $key = preg_replace( '/[^a-z0-9_\-]/', '', $key ); |
1903 $key = preg_replace( '/[^a-z0-9_\-]/', '', $key ); |
1235 |
1904 |
1236 /** |
1905 /** |
1237 * Filter a sanitized key string. |
1906 * Filters a sanitized key string. |
1238 * |
1907 * |
1239 * @since 3.0.0 |
1908 * @since 3.0.0 |
1240 * |
1909 * |
1241 * @param string $key Sanitized key. |
1910 * @param string $key Sanitized key. |
1242 * @param string $raw_key The key prior to sanitization. |
1911 * @param string $raw_key The key prior to sanitization. |
1251 * via the plugin API. If $title is empty and $fallback_title is set, the latter |
1920 * via the plugin API. If $title is empty and $fallback_title is set, the latter |
1252 * will be used. |
1921 * will be used. |
1253 * |
1922 * |
1254 * @since 1.0.0 |
1923 * @since 1.0.0 |
1255 * |
1924 * |
1256 * @param string $title The string to be sanitized. |
1925 * @param string $title The string to be sanitized. |
1257 * @param string $fallback_title Optional. A title to use if $title is empty. |
1926 * @param string $fallback_title Optional. A title to use if $title is empty. |
1258 * @param string $context Optional. The operation for which the string is sanitized |
1927 * @param string $context Optional. The operation for which the string is sanitized |
1259 * @return string The sanitized string. |
1928 * @return string The sanitized string. |
1260 */ |
1929 */ |
1261 function sanitize_title( $title, $fallback_title = '', $context = 'save' ) { |
1930 function sanitize_title( $title, $fallback_title = '', $context = 'save' ) { |
1262 $raw_title = $title; |
1931 $raw_title = $title; |
1263 |
1932 |
1264 if ( 'save' == $context ) |
1933 if ( 'save' == $context ) |
1265 $title = remove_accents($title); |
1934 $title = remove_accents($title); |
1266 |
1935 |
1267 /** |
1936 /** |
1268 * Filter a sanitized title string. |
1937 * Filters a sanitized title string. |
1269 * |
1938 * |
1270 * @since 1.2.0 |
1939 * @since 1.2.0 |
1271 * |
1940 * |
1272 * @param string $title Sanitized title. |
1941 * @param string $title Sanitized title. |
1273 * @param string $raw_title The title prior to sanitization. |
1942 * @param string $raw_title The title prior to sanitization. |
1301 * Limits the output to alphanumeric characters, underscore (_) and dash (-). |
1970 * Limits the output to alphanumeric characters, underscore (_) and dash (-). |
1302 * Whitespace becomes a dash. |
1971 * Whitespace becomes a dash. |
1303 * |
1972 * |
1304 * @since 1.2.0 |
1973 * @since 1.2.0 |
1305 * |
1974 * |
1306 * @param string $title The title to be sanitized. |
1975 * @param string $title The title to be sanitized. |
1307 * @param string $raw_title Optional. Not used. |
1976 * @param string $raw_title Optional. Not used. |
1308 * @param string $context Optional. The operation for which the string is sanitized. |
1977 * @param string $context Optional. The operation for which the string is sanitized. |
1309 * @return string The sanitized title. |
1978 * @return string The sanitized title. |
1310 */ |
1979 */ |
1311 function sanitize_title_with_dashes( $title, $raw_title = '', $context = 'display' ) { |
1980 function sanitize_title_with_dashes( $title, $raw_title = '', $context = 'display' ) { |
1312 $title = strip_tags($title); |
1981 $title = strip_tags($title); |
1313 // Preserve escaped octets. |
1982 // Preserve escaped octets. |
1323 } |
1992 } |
1324 $title = utf8_uri_encode($title, 200); |
1993 $title = utf8_uri_encode($title, 200); |
1325 } |
1994 } |
1326 |
1995 |
1327 $title = strtolower($title); |
1996 $title = strtolower($title); |
1328 $title = preg_replace('/&.+?;/', '', $title); // kill entities |
|
1329 $title = str_replace('.', '-', $title); |
|
1330 |
1997 |
1331 if ( 'save' == $context ) { |
1998 if ( 'save' == $context ) { |
1332 // Convert nbsp, ndash and mdash to hyphens |
1999 // Convert nbsp, ndash and mdash to hyphens |
1333 $title = str_replace( array( '%c2%a0', '%e2%80%93', '%e2%80%94' ), '-', $title ); |
2000 $title = str_replace( array( '%c2%a0', '%e2%80%93', '%e2%80%94' ), '-', $title ); |
2001 // Convert nbsp, ndash and mdash HTML entities to hyphens |
|
2002 $title = str_replace( array( ' ', ' ', '–', '–', '—', '—' ), '-', $title ); |
|
2003 // Convert forward slash to hyphen |
|
2004 $title = str_replace( '/', '-', $title ); |
|
1334 |
2005 |
1335 // Strip these characters entirely |
2006 // Strip these characters entirely |
1336 $title = str_replace( array( |
2007 $title = str_replace( array( |
1337 // iexcl and iquest |
2008 // iexcl and iquest |
1338 '%c2%a1', '%c2%bf', |
2009 '%c2%a1', '%c2%bf', |
1351 |
2022 |
1352 // Convert times to x |
2023 // Convert times to x |
1353 $title = str_replace( '%c3%97', 'x', $title ); |
2024 $title = str_replace( '%c3%97', 'x', $title ); |
1354 } |
2025 } |
1355 |
2026 |
2027 $title = preg_replace('/&.+?;/', '', $title); // kill entities |
|
2028 $title = str_replace('.', '-', $title); |
|
2029 |
|
1356 $title = preg_replace('/[^%a-z0-9 _-]/', '', $title); |
2030 $title = preg_replace('/[^%a-z0-9 _-]/', '', $title); |
1357 $title = preg_replace('/\s+/', '-', $title); |
2031 $title = preg_replace('/\s+/', '-', $title); |
1358 $title = preg_replace('|-+|', '-', $title); |
2032 $title = preg_replace('|-+|', '-', $title); |
1359 $title = trim($title, '-'); |
2033 $title = trim($title, '-'); |
1360 |
2034 |
1370 * Also accepts 'RAND()'. |
2044 * Also accepts 'RAND()'. |
1371 * |
2045 * |
1372 * @since 2.5.1 |
2046 * @since 2.5.1 |
1373 * |
2047 * |
1374 * @param string $orderby Order by clause to be validated. |
2048 * @param string $orderby Order by clause to be validated. |
1375 * @return string|bool Returns $orderby if valid, false otherwise. |
2049 * @return string|false Returns $orderby if valid, false otherwise. |
1376 */ |
2050 */ |
1377 function sanitize_sql_orderby( $orderby ) { |
2051 function sanitize_sql_orderby( $orderby ) { |
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 ) ) { |
2052 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 ) ) { |
1379 return $orderby; |
2053 return $orderby; |
1380 } |
2054 } |
1389 * |
2063 * |
1390 * @todo Expand to support the full range of CDATA that a class attribute can contain. |
2064 * @todo Expand to support the full range of CDATA that a class attribute can contain. |
1391 * |
2065 * |
1392 * @since 2.8.0 |
2066 * @since 2.8.0 |
1393 * |
2067 * |
1394 * @param string $class The classname to be sanitized |
2068 * @param string $class The classname to be sanitized |
1395 * @param string $fallback Optional. The value to return if the sanitization ends up as an empty string. |
2069 * @param string $fallback Optional. The value to return if the sanitization ends up as an empty string. |
1396 * Defaults to an empty string. |
2070 * Defaults to an empty string. |
1397 * @return string The sanitized value |
2071 * @return string The sanitized value |
1398 */ |
2072 */ |
1399 function sanitize_html_class( $class, $fallback = '' ) { |
2073 function sanitize_html_class( $class, $fallback = '' ) { |
1401 $sanitized = preg_replace( '|%[a-fA-F0-9][a-fA-F0-9]|', '', $class ); |
2075 $sanitized = preg_replace( '|%[a-fA-F0-9][a-fA-F0-9]|', '', $class ); |
1402 |
2076 |
1403 //Limit to A-Z,a-z,0-9,_,- |
2077 //Limit to A-Z,a-z,0-9,_,- |
1404 $sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $sanitized ); |
2078 $sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $sanitized ); |
1405 |
2079 |
1406 if ( '' == $sanitized ) |
2080 if ( '' == $sanitized && $fallback ) { |
1407 $sanitized = $fallback; |
2081 return sanitize_html_class( $fallback ); |
1408 |
2082 } |
1409 /** |
2083 /** |
1410 * Filter a sanitized HTML class string. |
2084 * Filters a sanitized HTML class string. |
1411 * |
2085 * |
1412 * @since 2.8.0 |
2086 * @since 2.8.0 |
1413 * |
2087 * |
1414 * @param string $sanitized The sanitized HTML class. |
2088 * @param string $sanitized The sanitized HTML class. |
1415 * @param string $class HTML class before sanitization. |
2089 * @param string $class HTML class before sanitization. |
1417 */ |
2091 */ |
1418 return apply_filters( 'sanitize_html_class', $sanitized, $class, $fallback ); |
2092 return apply_filters( 'sanitize_html_class', $sanitized, $class, $fallback ); |
1419 } |
2093 } |
1420 |
2094 |
1421 /** |
2095 /** |
1422 * Converts a number of characters from a string. |
2096 * Converts lone & characters into `&` (a.k.a. `&`) |
1423 * |
|
1424 * Metadata tags `<title>` and `<category>` are removed, `<br>` and `<hr>` are |
|
1425 * converted into correct XHTML and Unicode characters are converted to the |
|
1426 * valid range. |
|
1427 * |
2097 * |
1428 * @since 0.71 |
2098 * @since 0.71 |
1429 * |
2099 * |
1430 * @param string $content String of characters to be converted. |
2100 * @param string $content String of characters to be converted. |
1431 * @param string $deprecated Not used. |
2101 * @param string $deprecated Not used. |
1432 * @return string Converted string. |
2102 * @return string Converted string. |
1433 */ |
2103 */ |
1434 function convert_chars($content, $deprecated = '') { |
2104 function convert_chars( $content, $deprecated = '' ) { |
1435 if ( !empty( $deprecated ) ) |
2105 if ( ! empty( $deprecated ) ) { |
1436 _deprecated_argument( __FUNCTION__, '0.71' ); |
2106 _deprecated_argument( __FUNCTION__, '0.71' ); |
1437 |
2107 } |
1438 // Translation of invalid Unicode references range to valid range |
2108 |
2109 if ( strpos( $content, '&' ) !== false ) { |
|
2110 $content = preg_replace( '/&([^#])(?![a-z1-4]{1,8};)/i', '&$1', $content ); |
|
2111 } |
|
2112 |
|
2113 return $content; |
|
2114 } |
|
2115 |
|
2116 /** |
|
2117 * Converts invalid Unicode references range to valid range. |
|
2118 * |
|
2119 * @since 4.3.0 |
|
2120 * |
|
2121 * @param string $content String with entities that need converting. |
|
2122 * @return string Converted string. |
|
2123 */ |
|
2124 function convert_invalid_entities( $content ) { |
|
1439 $wp_htmltranswinuni = array( |
2125 $wp_htmltranswinuni = array( |
1440 '€' => '€', // the Euro sign |
2126 '€' => '€', // the Euro sign |
1441 '' => '', |
2127 '' => '', |
1442 '‚' => '‚', // these are Windows CP1252 specific characters |
2128 '‚' => '‚', // these are Windows CP1252 specific characters |
1443 'ƒ' => 'ƒ', // they would look weird on non-Windows browsers |
2129 'ƒ' => 'ƒ', // they would look weird on non-Windows browsers |
1444 '„' => '„', |
2130 '„' => '„', |
1445 '…' => '…', |
2131 '…' => '…', |
1446 '†' => '†', |
2132 '†' => '†', |
1447 '‡' => '‡', |
2133 '‡' => '‡', |
1448 'ˆ' => 'ˆ', |
2134 'ˆ' => 'ˆ', |
1449 '‰' => '‰', |
2135 '‰' => '‰', |
1450 'Š' => 'Š', |
2136 'Š' => 'Š', |
1451 '‹' => '‹', |
2137 '‹' => '‹', |
1452 'Œ' => 'Œ', |
2138 'Œ' => 'Œ', |
1453 '' => '', |
2139 '' => '', |
1454 'Ž' => 'Ž', |
2140 'Ž' => 'Ž', |
1455 '' => '', |
2141 '' => '', |
1456 '' => '', |
2142 '' => '', |
1457 '‘' => '‘', |
2143 '‘' => '‘', |
1458 '’' => '’', |
2144 '’' => '’', |
1459 '“' => '“', |
2145 '“' => '“', |
1460 '”' => '”', |
2146 '”' => '”', |
1461 '•' => '•', |
2147 '•' => '•', |
1462 '–' => '–', |
2148 '–' => '–', |
1463 '—' => '—', |
2149 '—' => '—', |
1464 '˜' => '˜', |
2150 '˜' => '˜', |
1465 '™' => '™', |
2151 '™' => '™', |
1466 'š' => 'š', |
2152 'š' => 'š', |
1467 '›' => '›', |
2153 '›' => '›', |
1468 'œ' => 'œ', |
2154 'œ' => 'œ', |
1469 '' => '', |
2155 '' => '', |
1470 'ž' => 'ž', |
2156 'ž' => 'ž', |
1471 'Ÿ' => 'Ÿ' |
2157 'Ÿ' => 'Ÿ' |
1472 ); |
2158 ); |
1473 |
2159 |
1474 // Remove metadata tags |
2160 if ( strpos( $content, '' ) !== false ) { |
1475 $content = preg_replace('/<title>(.+?)<\/title>/','',$content); |
2161 $content = strtr( $content, $wp_htmltranswinuni ); |
1476 $content = preg_replace('/<category>(.+?)<\/category>/','',$content); |
2162 } |
1477 |
|
1478 // Converts lone & characters into & (a.k.a. &) |
|
1479 $content = preg_replace('/&([^#])(?![a-z1-4]{1,8};)/i', '&$1', $content); |
|
1480 |
|
1481 // Fix Word pasting |
|
1482 $content = strtr($content, $wp_htmltranswinuni); |
|
1483 |
|
1484 // Just a little XHTML help |
|
1485 $content = str_replace('<br>', '<br />', $content); |
|
1486 $content = str_replace('<hr>', '<hr />', $content); |
|
1487 |
2163 |
1488 return $content; |
2164 return $content; |
1489 } |
2165 } |
1490 |
2166 |
1491 /** |
2167 /** |
1492 * Balances tags if forced to, or if the 'use_balanceTags' option is set to true. |
2168 * Balances tags if forced to, or if the 'use_balanceTags' option is set to true. |
1493 * |
2169 * |
1494 * @since 0.71 |
2170 * @since 0.71 |
1495 * |
2171 * |
1496 * @param string $text Text to be balanced |
2172 * @param string $text Text to be balanced |
1497 * @param bool $force If true, forces balancing, ignoring the value of the option. Default false. |
2173 * @param bool $force If true, forces balancing, ignoring the value of the option. Default false. |
1498 * @return string Balanced text |
2174 * @return string Balanced text |
1499 */ |
2175 */ |
1500 function balanceTags( $text, $force = false ) { |
2176 function balanceTags( $text, $force = false ) { |
1501 if ( $force || get_option('use_balanceTags') == 1 ) { |
2177 if ( $force || get_option('use_balanceTags') == 1 ) { |
1502 return force_balance_tags( $text ); |
2178 return force_balance_tags( $text ); |
1548 $tagqueue = ''; |
2224 $tagqueue = ''; |
1549 // Pop or Push |
2225 // Pop or Push |
1550 if ( isset($regex[1][0]) && '/' == $regex[1][0] ) { // End Tag |
2226 if ( isset($regex[1][0]) && '/' == $regex[1][0] ) { // End Tag |
1551 $tag = strtolower(substr($regex[1],1)); |
2227 $tag = strtolower(substr($regex[1],1)); |
1552 // if too many closing tags |
2228 // if too many closing tags |
1553 if( $stacksize <= 0 ) { |
2229 if ( $stacksize <= 0 ) { |
1554 $tag = ''; |
2230 $tag = ''; |
1555 // or close to be safe $tag = '/' . $tag; |
2231 // or close to be safe $tag = '/' . $tag; |
1556 } |
2232 } |
1557 // if stacktop value = tag close value then pop |
2233 // if stacktop value = tag close value then pop |
1558 elseif ( $tagstack[$stacksize - 1] == $tag ) { // found closing tag |
2234 elseif ( $tagstack[$stacksize - 1] == $tag ) { // found closing tag |
1603 $stacksize = array_push( $tagstack, $tag ); |
2279 $stacksize = array_push( $tagstack, $tag ); |
1604 } |
2280 } |
1605 |
2281 |
1606 // Attributes |
2282 // Attributes |
1607 $attributes = $regex[2]; |
2283 $attributes = $regex[2]; |
1608 if( ! empty( $attributes ) && $attributes[0] != '>' ) |
2284 if ( ! empty( $attributes ) && $attributes[0] != '>' ) |
1609 $attributes = ' ' . $attributes; |
2285 $attributes = ' ' . $attributes; |
1610 |
2286 |
1611 $tag = '<' . $tag . $attributes . '>'; |
2287 $tag = '<' . $tag . $attributes . '>'; |
1612 //If already queuing a close tag, then put this tag on, too |
2288 //If already queuing a close tag, then put this tag on, too |
1613 if ( !empty($tagqueue) ) { |
2289 if ( !empty($tagqueue) ) { |
1638 |
2314 |
1639 /** |
2315 /** |
1640 * Acts on text which is about to be edited. |
2316 * Acts on text which is about to be edited. |
1641 * |
2317 * |
1642 * The $content is run through esc_textarea(), which uses htmlspecialchars() |
2318 * The $content is run through esc_textarea(), which uses htmlspecialchars() |
1643 * to convert special characters to HTML entities. If $richedit is set to true, |
2319 * to convert special characters to HTML entities. If `$richedit` is set to true, |
1644 * it is simply a holder for the 'format_to_edit' filter. |
2320 * it is simply a holder for the {@see 'format_to_edit'} filter. |
1645 * |
2321 * |
1646 * @since 0.71 |
2322 * @since 0.71 |
1647 * |
2323 * @since 4.4.0 The `$richedit` parameter was renamed to `$rich_text` for clarity. |
1648 * @param string $content The text about to be edited. |
2324 * |
1649 * @param bool $richedit Whether the $content should not pass through htmlspecialchars(). Default false (meaning it will be passed). |
2325 * @param string $content The text about to be edited. |
2326 * @param bool $rich_text Optional. Whether `$content` should be considered rich text, |
|
2327 * in which case it would not be passed through esc_textarea(). |
|
2328 * Default false. |
|
1650 * @return string The text after the filter (and possibly htmlspecialchars()) has been run. |
2329 * @return string The text after the filter (and possibly htmlspecialchars()) has been run. |
1651 */ |
2330 */ |
1652 function format_to_edit( $content, $richedit = false ) { |
2331 function format_to_edit( $content, $rich_text = false ) { |
1653 /** |
2332 /** |
1654 * Filter the text to be formatted for editing. |
2333 * Filters the text to be formatted for editing. |
1655 * |
2334 * |
1656 * @since 1.2.0 |
2335 * @since 1.2.0 |
1657 * |
2336 * |
1658 * @param string $content The text, prior to formatting for editing. |
2337 * @param string $content The text, prior to formatting for editing. |
1659 */ |
2338 */ |
1660 $content = apply_filters( 'format_to_edit', $content ); |
2339 $content = apply_filters( 'format_to_edit', $content ); |
1661 if ( ! $richedit ) |
2340 if ( ! $rich_text ) |
1662 $content = esc_textarea( $content ); |
2341 $content = esc_textarea( $content ); |
1663 return $content; |
2342 return $content; |
1664 } |
2343 } |
1665 |
2344 |
1666 /** |
2345 /** |
1674 * and the size of the number. If the number is large enough, then no zeros will |
2353 * and the size of the number. If the number is large enough, then no zeros will |
1675 * be appended. |
2354 * be appended. |
1676 * |
2355 * |
1677 * @since 0.71 |
2356 * @since 0.71 |
1678 * |
2357 * |
1679 * @param mixed $number Number to append zeros to if not greater than threshold. |
2358 * @param int $number Number to append zeros to if not greater than threshold. |
1680 * @param int $threshold Digit places number needs to be to not have zeros added. |
2359 * @param int $threshold Digit places number needs to be to not have zeros added. |
1681 * @return string Adds leading zeros to number if needed. |
2360 * @return string Adds leading zeros to number if needed. |
1682 */ |
2361 */ |
1683 function zeroise($number, $threshold) { |
2362 function zeroise( $number, $threshold ) { |
1684 return sprintf('%0'.$threshold.'s', $number); |
2363 return sprintf( '%0' . $threshold . 's', $number ); |
1685 } |
2364 } |
1686 |
2365 |
1687 /** |
2366 /** |
1688 * Adds backslashes before letters and before a number at the start of a string. |
2367 * Adds backslashes before letters and before a number at the start of a string. |
1689 * |
2368 * |
1690 * @since 0.71 |
2369 * @since 0.71 |
1691 * |
2370 * |
1692 * @param string $string Value to which backslashes will be added. |
2371 * @param string $string Value to which backslashes will be added. |
1693 * @return string String with backslashes inserted. |
2372 * @return string String with backslashes inserted. |
1694 */ |
2373 */ |
1695 function backslashit($string) { |
2374 function backslashit( $string ) { |
1696 if ( isset( $string[0] ) && $string[0] >= '0' && $string[0] <= '9' ) |
2375 if ( isset( $string[0] ) && $string[0] >= '0' && $string[0] <= '9' ) |
1697 $string = '\\\\' . $string; |
2376 $string = '\\\\' . $string; |
1698 return addcslashes( $string, 'A..Za..z' ); |
2377 return addcslashes( $string, 'A..Za..z' ); |
1699 } |
2378 } |
1700 |
2379 |
1733 |
2412 |
1734 /** |
2413 /** |
1735 * Adds slashes to escape strings. |
2414 * Adds slashes to escape strings. |
1736 * |
2415 * |
1737 * Slashes will first be removed if magic_quotes_gpc is set, see {@link |
2416 * Slashes will first be removed if magic_quotes_gpc is set, see {@link |
1738 * http://www.php.net/magic_quotes} for more details. |
2417 * https://secure.php.net/magic_quotes} for more details. |
1739 * |
2418 * |
1740 * @since 0.71 |
2419 * @since 0.71 |
1741 * |
2420 * |
1742 * @param string $gpc The string returned from HTTP request data. |
2421 * @param string $gpc The string returned from HTTP request data. |
1743 * @return string Returns a string escaped with slashes. |
2422 * @return string Returns a string escaped with slashes. |
1748 |
2427 |
1749 return wp_slash($gpc); |
2428 return wp_slash($gpc); |
1750 } |
2429 } |
1751 |
2430 |
1752 /** |
2431 /** |
1753 * Navigates through an array and removes slashes from the values. |
2432 * Navigates through an array, object, or scalar, and removes slashes from the values. |
1754 * |
|
1755 * If an array is passed, the array_map() function causes a callback to pass the |
|
1756 * value back to the function. The slashes from this value will removed. |
|
1757 * |
2433 * |
1758 * @since 2.0.0 |
2434 * @since 2.0.0 |
1759 * |
2435 * |
1760 * @param mixed $value The value to be stripped. |
2436 * @param mixed $value The value to be stripped. |
1761 * @return mixed Stripped value. |
2437 * @return mixed Stripped value. |
1762 */ |
2438 */ |
1763 function stripslashes_deep($value) { |
2439 function stripslashes_deep( $value ) { |
1764 if ( is_array($value) ) { |
2440 return map_deep( $value, 'stripslashes_from_strings_only' ); |
1765 $value = array_map('stripslashes_deep', $value); |
2441 } |
1766 } elseif ( is_object($value) ) { |
2442 |
1767 $vars = get_object_vars( $value ); |
2443 /** |
1768 foreach ($vars as $key=>$data) { |
2444 * Callback function for `stripslashes_deep()` which strips slashes from strings. |
1769 $value->{$key} = stripslashes_deep( $data ); |
2445 * |
1770 } |
2446 * @since 4.4.0 |
1771 } elseif ( is_string( $value ) ) { |
2447 * |
1772 $value = stripslashes($value); |
2448 * @param mixed $value The array or string to be stripped. |
1773 } |
2449 * @return mixed $value The stripped value. |
1774 |
2450 */ |
1775 return $value; |
2451 function stripslashes_from_strings_only( $value ) { |
1776 } |
2452 return is_string( $value ) ? stripslashes( $value ) : $value; |
1777 |
2453 } |
1778 /** |
2454 |
1779 * Navigates through an array and encodes the values to be used in a URL. |
2455 /** |
1780 * |
2456 * Navigates through an array, object, or scalar, and encodes the values to be used in a URL. |
1781 * |
2457 * |
1782 * @since 2.2.0 |
2458 * @since 2.2.0 |
1783 * |
2459 * |
1784 * @param array|string $value The array or string to be encoded. |
2460 * @param mixed $value The array or string to be encoded. |
1785 * @return array|string $value The encoded array (or string from the callback). |
2461 * @return mixed $value The encoded value. |
1786 */ |
2462 */ |
1787 function urlencode_deep($value) { |
2463 function urlencode_deep( $value ) { |
1788 $value = is_array($value) ? array_map('urlencode_deep', $value) : urlencode($value); |
2464 return map_deep( $value, 'urlencode' ); |
1789 return $value; |
2465 } |
1790 } |
2466 |
1791 |
2467 /** |
1792 /** |
2468 * Navigates through an array, object, or scalar, and raw-encodes the values to be used in a URL. |
1793 * Navigates through an array and raw encodes the values to be used in a URL. |
|
1794 * |
2469 * |
1795 * @since 3.4.0 |
2470 * @since 3.4.0 |
1796 * |
2471 * |
1797 * @param array|string $value The array or string to be encoded. |
2472 * @param mixed $value The array or string to be encoded. |
1798 * @return array|string $value The encoded array (or string from the callback). |
2473 * @return mixed $value The encoded value. |
1799 */ |
2474 */ |
1800 function rawurlencode_deep( $value ) { |
2475 function rawurlencode_deep( $value ) { |
1801 return is_array( $value ) ? array_map( 'rawurlencode_deep', $value ) : rawurlencode( $value ); |
2476 return map_deep( $value, 'rawurlencode' ); |
2477 } |
|
2478 |
|
2479 /** |
|
2480 * Navigates through an array, object, or scalar, and decodes URL-encoded values |
|
2481 * |
|
2482 * @since 4.4.0 |
|
2483 * |
|
2484 * @param mixed $value The array or string to be decoded. |
|
2485 * @return mixed $value The decoded value. |
|
2486 */ |
|
2487 function urldecode_deep( $value ) { |
|
2488 return map_deep( $value, 'urldecode' ); |
|
1802 } |
2489 } |
1803 |
2490 |
1804 /** |
2491 /** |
1805 * Converts email addresses characters to HTML entities to block spam bots. |
2492 * Converts email addresses characters to HTML entities to block spam bots. |
1806 * |
2493 * |
1807 * @since 0.71 |
2494 * @since 0.71 |
1808 * |
2495 * |
1809 * @param string $email_address Email address. |
2496 * @param string $email_address Email address. |
1810 * @param int $hex_encoding Optional. Set to 1 to enable hex encoding. |
2497 * @param int $hex_encoding Optional. Set to 1 to enable hex encoding. |
1811 * @return string Converted email address. |
2498 * @return string Converted email address. |
1812 */ |
2499 */ |
1813 function antispambot( $email_address, $hex_encoding = 0 ) { |
2500 function antispambot( $email_address, $hex_encoding = 0 ) { |
1814 $email_no_spam_address = ''; |
2501 $email_no_spam_address = ''; |
1815 for ( $i = 0, $len = strlen( $email_address ); $i < $len; $i++ ) { |
2502 for ( $i = 0, $len = strlen( $email_address ); $i < $len; $i++ ) { |
1821 } elseif ( $j == 2 ) { |
2508 } elseif ( $j == 2 ) { |
1822 $email_no_spam_address .= '%' . zeroise( dechex( ord( $email_address[$i] ) ), 2 ); |
2509 $email_no_spam_address .= '%' . zeroise( dechex( ord( $email_address[$i] ) ), 2 ); |
1823 } |
2510 } |
1824 } |
2511 } |
1825 |
2512 |
1826 $email_no_spam_address = str_replace( '@', '@', $email_no_spam_address ); |
2513 return str_replace( '@', '@', $email_no_spam_address ); |
1827 |
|
1828 return $email_no_spam_address; |
|
1829 } |
2514 } |
1830 |
2515 |
1831 /** |
2516 /** |
1832 * Callback to convert URI match to HTML A element. |
2517 * Callback to convert URI match to HTML A element. |
1833 * |
2518 * |
1834 * This function was backported from 2.5.0 to 2.3.2. Regex callback for {@link |
2519 * This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable(). |
1835 * make_clickable()}. |
|
1836 * |
2520 * |
1837 * @since 2.3.2 |
2521 * @since 2.3.2 |
1838 * @access private |
2522 * @access private |
1839 * |
2523 * |
1840 * @param array $matches Single Regex Match. |
2524 * @param array $matches Single Regex Match. |
1841 * @return string HTML A element with URI address. |
2525 * @return string HTML A element with URI address. |
1842 */ |
2526 */ |
1843 function _make_url_clickable_cb($matches) { |
2527 function _make_url_clickable_cb( $matches ) { |
1844 $url = $matches[2]; |
2528 $url = $matches[2]; |
1845 |
2529 |
1846 if ( ')' == $matches[3] && strpos( $url, '(' ) ) { |
2530 if ( ')' == $matches[3] && strpos( $url, '(' ) ) { |
1847 // If the trailing character is a closing parethesis, and the URL has an opening parenthesis in it, add the closing parenthesis to the URL. |
2531 // If the trailing character is a closing parethesis, and the URL has an opening parenthesis in it, add the closing parenthesis to the URL. |
1848 // Then we can let the parenthesis balancer do its thing below. |
2532 // Then we can let the parenthesis balancer do its thing below. |
1866 } |
2550 } |
1867 |
2551 |
1868 /** |
2552 /** |
1869 * Callback to convert URL match to HTML A element. |
2553 * Callback to convert URL match to HTML A element. |
1870 * |
2554 * |
1871 * This function was backported from 2.5.0 to 2.3.2. Regex callback for {@link |
2555 * This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable(). |
1872 * make_clickable()}. |
|
1873 * |
2556 * |
1874 * @since 2.3.2 |
2557 * @since 2.3.2 |
1875 * @access private |
2558 * @access private |
1876 * |
2559 * |
1877 * @param array $matches Single Regex Match. |
2560 * @param array $matches Single Regex Match. |
1878 * @return string HTML A element with URL address. |
2561 * @return string HTML A element with URL address. |
1879 */ |
2562 */ |
1880 function _make_web_ftp_clickable_cb($matches) { |
2563 function _make_web_ftp_clickable_cb( $matches ) { |
1881 $ret = ''; |
2564 $ret = ''; |
1882 $dest = $matches[2]; |
2565 $dest = $matches[2]; |
1883 $dest = 'http://' . $dest; |
2566 $dest = 'http://' . $dest; |
1884 $dest = esc_url($dest); |
|
1885 if ( empty($dest) ) |
|
1886 return $matches[0]; |
|
1887 |
2567 |
1888 // removed trailing [.,;:)] from URL |
2568 // removed trailing [.,;:)] from URL |
1889 if ( in_array( substr($dest, -1), array('.', ',', ';', ':', ')') ) === true ) { |
2569 if ( in_array( substr($dest, -1), array('.', ',', ';', ':', ')') ) === true ) { |
1890 $ret = substr($dest, -1); |
2570 $ret = substr($dest, -1); |
1891 $dest = substr($dest, 0, strlen($dest)-1); |
2571 $dest = substr($dest, 0, strlen($dest)-1); |
1892 } |
2572 } |
2573 |
|
2574 $dest = esc_url($dest); |
|
2575 if ( empty($dest) ) |
|
2576 return $matches[0]; |
|
2577 |
|
1893 return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>$ret"; |
2578 return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>$ret"; |
1894 } |
2579 } |
1895 |
2580 |
1896 /** |
2581 /** |
1897 * Callback to convert email address match to HTML A element. |
2582 * Callback to convert email address match to HTML A element. |
1898 * |
2583 * |
1899 * This function was backported from 2.5.0 to 2.3.2. Regex callback for {@link |
2584 * This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable(). |
1900 * make_clickable()}. |
|
1901 * |
2585 * |
1902 * @since 2.3.2 |
2586 * @since 2.3.2 |
1903 * @access private |
2587 * @access private |
1904 * |
2588 * |
1905 * @param array $matches Single Regex Match. |
2589 * @param array $matches Single Regex Match. |
1906 * @return string HTML A element with email address. |
2590 * @return string HTML A element with email address. |
1907 */ |
2591 */ |
1908 function _make_email_clickable_cb($matches) { |
2592 function _make_email_clickable_cb( $matches ) { |
1909 $email = $matches[2] . '@' . $matches[3]; |
2593 $email = $matches[2] . '@' . $matches[3]; |
1910 return $matches[1] . "<a href=\"mailto:$email\">$email</a>"; |
2594 return $matches[1] . "<a href=\"mailto:$email\">$email</a>"; |
1911 } |
2595 } |
1912 |
2596 |
1913 /** |
2597 /** |
1925 $r = ''; |
2609 $r = ''; |
1926 $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // split out HTML tags |
2610 $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> |
2611 $nested_code_pre = 0; // Keep track of how many levels link is nested inside <pre> or <code> |
1928 foreach ( $textarr as $piece ) { |
2612 foreach ( $textarr as $piece ) { |
1929 |
2613 |
1930 if ( preg_match( '|^<code[\s>]|i', $piece ) || preg_match( '|^<pre[\s>]|i', $piece ) ) |
2614 if ( preg_match( '|^<code[\s>]|i', $piece ) || preg_match( '|^<pre[\s>]|i', $piece ) || preg_match( '|^<script[\s>]|i', $piece ) || preg_match( '|^<style[\s>]|i', $piece ) ) |
1931 $nested_code_pre++; |
2615 $nested_code_pre++; |
1932 elseif ( ( '</code>' === strtolower( $piece ) || '</pre>' === strtolower( $piece ) ) && $nested_code_pre ) |
2616 elseif ( $nested_code_pre && ( '</code>' === strtolower( $piece ) || '</pre>' === strtolower( $piece ) || '</script>' === strtolower( $piece ) || '</style>' === strtolower( $piece ) ) ) |
1933 $nested_code_pre--; |
2617 $nested_code_pre--; |
1934 |
2618 |
1935 if ( $nested_code_pre || empty( $piece ) || ( $piece[0] === '<' && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) ) ) { |
2619 if ( $nested_code_pre || empty( $piece ) || ( $piece[0] === '<' && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) ) ) { |
1936 $r .= $piece; |
2620 $r .= $piece; |
1937 continue; |
2621 continue; |
1974 $r .= $ret; |
2658 $r .= $ret; |
1975 } |
2659 } |
1976 } |
2660 } |
1977 |
2661 |
1978 // Cleanup of accidental links within links |
2662 // Cleanup of accidental links within links |
1979 $r = preg_replace( '#(<a([ \r\n\t]+[^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i', "$1$3</a>", $r ); |
2663 return preg_replace( '#(<a([ \r\n\t]+[^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i', "$1$3</a>", $r ); |
1980 return $r; |
|
1981 } |
2664 } |
1982 |
2665 |
1983 /** |
2666 /** |
1984 * Breaks a string into chunks by splitting at whitespace characters. |
2667 * Breaks a string into chunks by splitting at whitespace characters. |
1985 * The length of each returned chunk is as close to the specified length goal as possible, |
2668 * The length of each returned chunk is as close to the specified length goal as possible, |
2004 * |
2687 * |
2005 * @since 3.4.0 |
2688 * @since 3.4.0 |
2006 * @access private |
2689 * @access private |
2007 * |
2690 * |
2008 * @param string $string The string to split. |
2691 * @param string $string The string to split. |
2009 * @param int $goal The desired chunk length. |
2692 * @param int $goal The desired chunk length. |
2010 * @return array Numeric array of chunks. |
2693 * @return array Numeric array of chunks. |
2011 */ |
2694 */ |
2012 function _split_str_by_whitespace( $string, $goal ) { |
2695 function _split_str_by_whitespace( $string, $goal ) { |
2013 $chunks = array(); |
2696 $chunks = array(); |
2014 |
2697 |
2046 */ |
2729 */ |
2047 function wp_rel_nofollow( $text ) { |
2730 function wp_rel_nofollow( $text ) { |
2048 // This is a pre save filter, so text is already escaped. |
2731 // This is a pre save filter, so text is already escaped. |
2049 $text = stripslashes($text); |
2732 $text = stripslashes($text); |
2050 $text = preg_replace_callback('|<a (.+?)>|i', 'wp_rel_nofollow_callback', $text); |
2733 $text = preg_replace_callback('|<a (.+?)>|i', 'wp_rel_nofollow_callback', $text); |
2051 $text = wp_slash($text); |
2734 return wp_slash( $text ); |
2052 return $text; |
|
2053 } |
2735 } |
2054 |
2736 |
2055 /** |
2737 /** |
2056 * Callback to add rel=nofollow string to HTML A element. |
2738 * Callback to add rel=nofollow string to HTML A element. |
2057 * |
2739 * |
2063 * @param array $matches Single Match |
2745 * @param array $matches Single Match |
2064 * @return string HTML A Element with rel nofollow. |
2746 * @return string HTML A Element with rel nofollow. |
2065 */ |
2747 */ |
2066 function wp_rel_nofollow_callback( $matches ) { |
2748 function wp_rel_nofollow_callback( $matches ) { |
2067 $text = $matches[1]; |
2749 $text = $matches[1]; |
2068 $text = str_replace(array(' rel="nofollow"', " rel='nofollow'"), '', $text); |
2750 $atts = shortcode_parse_atts( $matches[1] ); |
2069 return "<a $text rel=\"nofollow\">"; |
2751 $rel = 'nofollow'; |
2752 |
|
2753 if ( preg_match( '%href=["\'](' . preg_quote( set_url_scheme( home_url(), 'http' ) ) . ')%i', $text ) || |
|
2754 preg_match( '%href=["\'](' . preg_quote( set_url_scheme( home_url(), 'https' ) ) . ')%i', $text ) |
|
2755 ) { |
|
2756 return "<a $text>"; |
|
2757 } |
|
2758 |
|
2759 if ( ! empty( $atts['rel'] ) ) { |
|
2760 $parts = array_map( 'trim', explode( ' ', $atts['rel'] ) ); |
|
2761 if ( false === array_search( 'nofollow', $parts ) ) { |
|
2762 $parts[] = 'nofollow'; |
|
2763 } |
|
2764 $rel = implode( ' ', $parts ); |
|
2765 unset( $atts['rel'] ); |
|
2766 |
|
2767 $html = ''; |
|
2768 foreach ( $atts as $name => $value ) { |
|
2769 $html .= "{$name}=\"$value\" "; |
|
2770 } |
|
2771 $text = trim( $html ); |
|
2772 } |
|
2773 return "<a $text rel=\"$rel\">"; |
|
2070 } |
2774 } |
2071 |
2775 |
2072 /** |
2776 /** |
2073 * Convert one smiley code to the icon graphic file equivalent. |
2777 * Convert one smiley code to the icon graphic file equivalent. |
2074 * |
2778 * |
2075 * Callback handler for {@link convert_smilies()}. |
2779 * Callback handler for convert_smilies(). |
2780 * |
|
2076 * Looks up one smiley code in the $wpsmiliestrans global array and returns an |
2781 * Looks up one smiley code in the $wpsmiliestrans global array and returns an |
2077 * `<img>` string for that smiley. |
2782 * `<img>` string for that smiley. |
2078 * |
2783 * |
2784 * @since 2.8.0 |
|
2785 * |
|
2079 * @global array $wpsmiliestrans |
2786 * @global array $wpsmiliestrans |
2080 * @since 2.8.0 |
|
2081 * |
2787 * |
2082 * @param array $matches Single match. Smiley code to convert to image. |
2788 * @param array $matches Single match. Smiley code to convert to image. |
2083 * @return string Image string for smiley. |
2789 * @return string Image string for smiley. |
2084 */ |
2790 */ |
2085 function translate_smiley( $matches ) { |
2791 function translate_smiley( $matches ) { |
2099 if ( ! in_array( $ext, $image_exts ) ) { |
2805 if ( ! in_array( $ext, $image_exts ) ) { |
2100 return $img; |
2806 return $img; |
2101 } |
2807 } |
2102 |
2808 |
2103 /** |
2809 /** |
2104 * Filter the Smiley image URL before it's used in the image element. |
2810 * Filters the Smiley image URL before it's used in the image element. |
2105 * |
2811 * |
2106 * @since 2.9.0 |
2812 * @since 2.9.0 |
2107 * |
2813 * |
2108 * @param string $smiley_url URL for the smiley image. |
2814 * @param string $smiley_url URL for the smiley image. |
2109 * @param string $img Filename for the smiley image. |
2815 * @param string $img Filename for the smiley image. |
2119 * |
2825 * |
2120 * Will only convert smilies if the option 'use_smilies' is true and the global |
2826 * Will only convert smilies if the option 'use_smilies' is true and the global |
2121 * used in the function isn't empty. |
2827 * used in the function isn't empty. |
2122 * |
2828 * |
2123 * @since 0.71 |
2829 * @since 0.71 |
2124 * @uses $wp_smiliessearch |
2830 * |
2831 * @global string|array $wp_smiliessearch |
|
2125 * |
2832 * |
2126 * @param string $text Content to convert smilies from text. |
2833 * @param string $text Content to convert smilies from text. |
2127 * @return string Converted content with text smilies replaced with images. |
2834 * @return string Converted content with text smilies replaced with images. |
2128 */ |
2835 */ |
2129 function convert_smilies( $text ) { |
2836 function convert_smilies( $text ) { |
2170 * |
2877 * |
2171 * Does not grok i18n domains. Not RFC compliant. |
2878 * Does not grok i18n domains. Not RFC compliant. |
2172 * |
2879 * |
2173 * @since 0.71 |
2880 * @since 0.71 |
2174 * |
2881 * |
2175 * @param string $email Email address to verify. |
2882 * @param string $email Email address to verify. |
2176 * @param boolean $deprecated Deprecated. |
2883 * @param bool $deprecated Deprecated. |
2177 * @return string|bool Either false or the valid email address. |
2884 * @return string|bool Either false or the valid email address. |
2178 */ |
2885 */ |
2179 function is_email( $email, $deprecated = false ) { |
2886 function is_email( $email, $deprecated = false ) { |
2180 if ( ! empty( $deprecated ) ) |
2887 if ( ! empty( $deprecated ) ) |
2181 _deprecated_argument( __FUNCTION__, '3.0' ); |
2888 _deprecated_argument( __FUNCTION__, '3.0.0' ); |
2182 |
2889 |
2183 // Test for the minimum length the email can be |
2890 // Test for the minimum length the email can be |
2184 if ( strlen( $email ) < 3 ) { |
2891 if ( strlen( $email ) < 6 ) { |
2185 /** |
2892 /** |
2186 * Filter whether an email address is valid. |
2893 * Filters whether an email address is valid. |
2187 * |
2894 * |
2188 * This filter is evaluated under several different contexts, such as 'email_too_short', |
2895 * 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', |
2896 * '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. |
2897 * 'domain_no_periods', 'sub_hyphen_limits', 'sub_invalid_chars', or no specific context. |
2191 * |
2898 * |
2192 * @since 2.8.0 |
2899 * @since 2.8.0 |
2193 * |
2900 * |
2194 * @param bool $is_email Whether the email address has passed the is_email() checks. Default false. |
2901 * @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. |
2902 * @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. |
2903 * @param string $context Context under which the email was tested. |
2198 */ |
2904 */ |
2199 return apply_filters( 'is_email', false, $email, 'email_too_short' ); |
2905 return apply_filters( 'is_email', false, $email, 'email_too_short' ); |
2200 } |
2906 } |
2201 |
2907 |
2263 * @since 1.2.0 |
2969 * @since 1.2.0 |
2264 * |
2970 * |
2265 * @param string $string Subject line |
2971 * @param string $string Subject line |
2266 * @return string Converted string to ASCII |
2972 * @return string Converted string to ASCII |
2267 */ |
2973 */ |
2268 function wp_iso_descrambler($string) { |
2974 function wp_iso_descrambler( $string ) { |
2269 /* this may only work with iso-8859-1, I'm afraid */ |
2975 /* this may only work with iso-8859-1, I'm afraid */ |
2270 if (!preg_match('#\=\?(.+)\?Q\?(.+)\?\=#i', $string, $matches)) { |
2976 if (!preg_match('#\=\?(.+)\?Q\?(.+)\?\=#i', $string, $matches)) { |
2271 return $string; |
2977 return $string; |
2272 } else { |
2978 } else { |
2273 $subject = str_replace('_', ' ', $matches[2]); |
2979 $subject = str_replace('_', ' ', $matches[2]); |
2274 $subject = preg_replace_callback('#\=([0-9a-f]{2})#i', '_wp_iso_convert', $subject); |
2980 return preg_replace_callback( '#\=([0-9a-f]{2})#i', '_wp_iso_convert', $subject ); |
2275 return $subject; |
|
2276 } |
2981 } |
2277 } |
2982 } |
2278 |
2983 |
2279 /** |
2984 /** |
2280 * Helper function to convert hex encoded chars to ASCII |
2985 * Helper function to convert hex encoded chars to ASCII |
2305 */ |
3010 */ |
2306 function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) { |
3011 function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) { |
2307 $tz = get_option( 'timezone_string' ); |
3012 $tz = get_option( 'timezone_string' ); |
2308 if ( $tz ) { |
3013 if ( $tz ) { |
2309 $datetime = date_create( $string, new DateTimeZone( $tz ) ); |
3014 $datetime = date_create( $string, new DateTimeZone( $tz ) ); |
2310 if ( ! $datetime ) |
3015 if ( ! $datetime ) { |
2311 return gmdate( $format, 0 ); |
3016 return gmdate( $format, 0 ); |
3017 } |
|
2312 $datetime->setTimezone( new DateTimeZone( 'UTC' ) ); |
3018 $datetime->setTimezone( new DateTimeZone( 'UTC' ) ); |
2313 $string_gmt = $datetime->format( $format ); |
3019 $string_gmt = $datetime->format( $format ); |
2314 } else { |
3020 } else { |
2315 if ( ! preg_match( '#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches ) ) |
3021 if ( ! preg_match( '#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches ) ) { |
2316 return gmdate( $format, 0 ); |
3022 $datetime = strtotime( $string ); |
3023 if ( false === $datetime ) { |
|
3024 return gmdate( $format, 0 ); |
|
3025 } |
|
3026 return gmdate( $format, $datetime ); |
|
3027 } |
|
2317 $string_time = gmmktime( $matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1] ); |
3028 $string_time = gmmktime( $matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1] ); |
2318 $string_gmt = gmdate( $format, $string_time - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); |
3029 $string_gmt = gmdate( $format, $string_time - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); |
2319 } |
3030 } |
2320 return $string_gmt; |
3031 return $string_gmt; |
2321 } |
3032 } |
2357 * @since 1.5.0 |
3068 * @since 1.5.0 |
2358 * |
3069 * |
2359 * @param string $timezone Either 'Z' for 0 offset or '±hhmm'. |
3070 * @param string $timezone Either 'Z' for 0 offset or '±hhmm'. |
2360 * @return int|float The offset in seconds. |
3071 * @return int|float The offset in seconds. |
2361 */ |
3072 */ |
2362 function iso8601_timezone_to_offset($timezone) { |
3073 function iso8601_timezone_to_offset( $timezone ) { |
2363 // $timezone is either 'Z' or '[+|-]hhmm' |
3074 // $timezone is either 'Z' or '[+|-]hhmm' |
2364 if ($timezone == 'Z') { |
3075 if ($timezone == 'Z') { |
2365 $offset = 0; |
3076 $offset = 0; |
2366 } else { |
3077 } else { |
2367 $sign = (substr($timezone, 0, 1) == '+') ? 1 : -1; |
3078 $sign = (substr($timezone, 0, 1) == '+') ? 1 : -1; |
2375 /** |
3086 /** |
2376 * Converts an iso8601 date to MySQL DateTime format used by post_date[_gmt]. |
3087 * Converts an iso8601 date to MySQL DateTime format used by post_date[_gmt]. |
2377 * |
3088 * |
2378 * @since 1.5.0 |
3089 * @since 1.5.0 |
2379 * |
3090 * |
2380 * @param string $date_string Date and time in ISO 8601 format {@link http://en.wikipedia.org/wiki/ISO_8601}. |
3091 * @param string $date_string Date and time in ISO 8601 format {@link https://en.wikipedia.org/wiki/ISO_8601}. |
2381 * @param string $timezone Optional. If set to GMT returns the time minus gmt_offset. Default is 'user'. |
3092 * @param string $timezone Optional. If set to GMT returns the time minus gmt_offset. Default is 'user'. |
2382 * @return string The date and time in MySQL DateTime format - Y-m-d H:i:s. |
3093 * @return string The date and time in MySQL DateTime format - Y-m-d H:i:s. |
2383 */ |
3094 */ |
2384 function iso8601_to_datetime($date_string, $timezone = 'user') { |
3095 function iso8601_to_datetime( $date_string, $timezone = 'user' ) { |
2385 $timezone = strtolower($timezone); |
3096 $timezone = strtolower($timezone); |
2386 |
3097 |
2387 if ($timezone == 'gmt') { |
3098 if ($timezone == 'gmt') { |
2388 |
3099 |
2389 preg_match('#([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}#', $date_string, $date_bits); |
3100 preg_match('#([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}#', $date_string, $date_bits); |
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); |
3114 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); |
2404 } |
3115 } |
2405 } |
3116 } |
2406 |
3117 |
2407 /** |
3118 /** |
2408 * Adds a element attributes to open links in new windows. |
|
2409 * |
|
2410 * Comment text in popup windows should be filtered through this. Right now it's |
|
2411 * a moderately dumb function, ideally it would detect whether a target or rel |
|
2412 * attribute was already there and adjust its actions accordingly. |
|
2413 * |
|
2414 * @since 0.71 |
|
2415 * |
|
2416 * @param string $text Content to replace links to open in a new window. |
|
2417 * @return string Content that has filtered links. |
|
2418 */ |
|
2419 function popuplinks($text) { |
|
2420 $text = preg_replace('/<a (.+?)>/i', "<a $1 target='_blank' rel='external'>", $text); |
|
2421 return $text; |
|
2422 } |
|
2423 |
|
2424 /** |
|
2425 * Strips out all characters that are not allowable in an email. |
3119 * Strips out all characters that are not allowable in an email. |
2426 * |
3120 * |
2427 * @since 1.5.0 |
3121 * @since 1.5.0 |
2428 * |
3122 * |
2429 * @param string $email Email address to filter. |
3123 * @param string $email Email address to filter. |
2430 * @return string Filtered email address. |
3124 * @return string Filtered email address. |
2431 */ |
3125 */ |
2432 function sanitize_email( $email ) { |
3126 function sanitize_email( $email ) { |
2433 // Test for the minimum length the email can be |
3127 // Test for the minimum length the email can be |
2434 if ( strlen( $email ) < 3 ) { |
3128 if ( strlen( $email ) < 6 ) { |
2435 /** |
3129 /** |
2436 * Filter a sanitized email address. |
3130 * Filters a sanitized email address. |
2437 * |
3131 * |
2438 * This filter is evaluated under several contexts, including 'email_too_short', |
3132 * This filter is evaluated under several contexts, including 'email_too_short', |
2439 * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits', |
3133 * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits', |
2440 * 'domain_no_periods', 'domain_no_valid_subs', or no context. |
3134 * 'domain_no_periods', 'domain_no_valid_subs', or no context. |
2441 * |
3135 * |
2530 * "5 mins", "2 days". |
3224 * "5 mins", "2 days". |
2531 * |
3225 * |
2532 * @since 1.5.0 |
3226 * @since 1.5.0 |
2533 * |
3227 * |
2534 * @param int $from Unix timestamp from which the difference begins. |
3228 * @param int $from Unix timestamp from which the difference begins. |
2535 * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. |
3229 * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. |
2536 * @return string Human readable time difference. |
3230 * @return string Human readable time difference. |
2537 */ |
3231 */ |
2538 function human_time_diff( $from, $to = '' ) { |
3232 function human_time_diff( $from, $to = '' ) { |
2539 if ( empty( $to ) ) { |
3233 if ( empty( $to ) ) { |
2540 $to = time(); |
3234 $to = time(); |
2544 |
3238 |
2545 if ( $diff < HOUR_IN_SECONDS ) { |
3239 if ( $diff < HOUR_IN_SECONDS ) { |
2546 $mins = round( $diff / MINUTE_IN_SECONDS ); |
3240 $mins = round( $diff / MINUTE_IN_SECONDS ); |
2547 if ( $mins <= 1 ) |
3241 if ( $mins <= 1 ) |
2548 $mins = 1; |
3242 $mins = 1; |
2549 /* translators: min=minute */ |
3243 /* translators: Time difference between two dates, in minutes (min=minute). 1: Number of minutes */ |
2550 $since = sprintf( _n( '%s min', '%s mins', $mins ), $mins ); |
3244 $since = sprintf( _n( '%s min', '%s mins', $mins ), $mins ); |
2551 } elseif ( $diff < DAY_IN_SECONDS && $diff >= HOUR_IN_SECONDS ) { |
3245 } elseif ( $diff < DAY_IN_SECONDS && $diff >= HOUR_IN_SECONDS ) { |
2552 $hours = round( $diff / HOUR_IN_SECONDS ); |
3246 $hours = round( $diff / HOUR_IN_SECONDS ); |
2553 if ( $hours <= 1 ) |
3247 if ( $hours <= 1 ) |
2554 $hours = 1; |
3248 $hours = 1; |
3249 /* translators: Time difference between two dates, in hours. 1: Number of hours */ |
|
2555 $since = sprintf( _n( '%s hour', '%s hours', $hours ), $hours ); |
3250 $since = sprintf( _n( '%s hour', '%s hours', $hours ), $hours ); |
2556 } elseif ( $diff < WEEK_IN_SECONDS && $diff >= DAY_IN_SECONDS ) { |
3251 } elseif ( $diff < WEEK_IN_SECONDS && $diff >= DAY_IN_SECONDS ) { |
2557 $days = round( $diff / DAY_IN_SECONDS ); |
3252 $days = round( $diff / DAY_IN_SECONDS ); |
2558 if ( $days <= 1 ) |
3253 if ( $days <= 1 ) |
2559 $days = 1; |
3254 $days = 1; |
3255 /* translators: Time difference between two dates, in days. 1: Number of days */ |
|
2560 $since = sprintf( _n( '%s day', '%s days', $days ), $days ); |
3256 $since = sprintf( _n( '%s day', '%s days', $days ), $days ); |
2561 } elseif ( $diff < 30 * DAY_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) { |
3257 } elseif ( $diff < MONTH_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) { |
2562 $weeks = round( $diff / WEEK_IN_SECONDS ); |
3258 $weeks = round( $diff / WEEK_IN_SECONDS ); |
2563 if ( $weeks <= 1 ) |
3259 if ( $weeks <= 1 ) |
2564 $weeks = 1; |
3260 $weeks = 1; |
3261 /* translators: Time difference between two dates, in weeks. 1: Number of weeks */ |
|
2565 $since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks ); |
3262 $since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks ); |
2566 } elseif ( $diff < YEAR_IN_SECONDS && $diff >= 30 * DAY_IN_SECONDS ) { |
3263 } elseif ( $diff < YEAR_IN_SECONDS && $diff >= MONTH_IN_SECONDS ) { |
2567 $months = round( $diff / ( 30 * DAY_IN_SECONDS ) ); |
3264 $months = round( $diff / MONTH_IN_SECONDS ); |
2568 if ( $months <= 1 ) |
3265 if ( $months <= 1 ) |
2569 $months = 1; |
3266 $months = 1; |
3267 /* translators: Time difference between two dates, in months. 1: Number of months */ |
|
2570 $since = sprintf( _n( '%s month', '%s months', $months ), $months ); |
3268 $since = sprintf( _n( '%s month', '%s months', $months ), $months ); |
2571 } elseif ( $diff >= YEAR_IN_SECONDS ) { |
3269 } elseif ( $diff >= YEAR_IN_SECONDS ) { |
2572 $years = round( $diff / YEAR_IN_SECONDS ); |
3270 $years = round( $diff / YEAR_IN_SECONDS ); |
2573 if ( $years <= 1 ) |
3271 if ( $years <= 1 ) |
2574 $years = 1; |
3272 $years = 1; |
3273 /* translators: Time difference between two dates, in years. 1: Number of years */ |
|
2575 $since = sprintf( _n( '%s year', '%s years', $years ), $years ); |
3274 $since = sprintf( _n( '%s year', '%s years', $years ), $years ); |
2576 } |
3275 } |
2577 |
3276 |
2578 /** |
3277 /** |
2579 * Filter the human readable difference between two timestamps. |
3278 * Filters the human readable difference between two timestamps. |
2580 * |
3279 * |
2581 * @since 4.0.0 |
3280 * @since 4.0.0 |
2582 * |
3281 * |
2583 * @param string $since The difference in human readable text. |
3282 * @param string $since The difference in human readable text. |
2584 * @param int $diff The difference in seconds. |
3283 * @param int $diff The difference in seconds. |
2593 * |
3292 * |
2594 * The excerpt word amount will be 55 words and if the amount is greater than |
3293 * The excerpt word amount will be 55 words and if the amount is greater than |
2595 * that, then the string ' […]' will be appended to the excerpt. If the string |
3294 * that, then the string ' […]' will be appended to the excerpt. If the string |
2596 * is less than 55 words, then the content will be returned as is. |
3295 * is less than 55 words, then the content will be returned as is. |
2597 * |
3296 * |
2598 * The 55 word limit can be modified by plugins/themes using the excerpt_length filter |
3297 * The 55 word limit can be modified by plugins/themes using the {@see 'excerpt_length'} filter |
2599 * The ' […]' string can be modified by plugins/themes using the excerpt_more filter |
3298 * The ' […]' string can be modified by plugins/themes using the {@see 'excerpt_more'} filter |
2600 * |
3299 * |
2601 * @since 1.5.0 |
3300 * @since 1.5.0 |
2602 * |
3301 * |
2603 * @param string $text Optional. The excerpt. If set to empty, an excerpt is generated. |
3302 * @param string $text Optional. The excerpt. If set to empty, an excerpt is generated. |
2604 * @return string The excerpt. |
3303 * @return string The excerpt. |
2605 */ |
3304 */ |
2606 function wp_trim_excerpt($text = '') { |
3305 function wp_trim_excerpt( $text = '' ) { |
2607 $raw_excerpt = $text; |
3306 $raw_excerpt = $text; |
2608 if ( '' == $text ) { |
3307 if ( '' == $text ) { |
2609 $text = get_the_content(''); |
3308 $text = get_the_content(''); |
2610 |
3309 |
2611 $text = strip_shortcodes( $text ); |
3310 $text = strip_shortcodes( $text ); |
2613 /** This filter is documented in wp-includes/post-template.php */ |
3312 /** This filter is documented in wp-includes/post-template.php */ |
2614 $text = apply_filters( 'the_content', $text ); |
3313 $text = apply_filters( 'the_content', $text ); |
2615 $text = str_replace(']]>', ']]>', $text); |
3314 $text = str_replace(']]>', ']]>', $text); |
2616 |
3315 |
2617 /** |
3316 /** |
2618 * Filter the number of words in an excerpt. |
3317 * Filters the number of words in an excerpt. |
2619 * |
3318 * |
2620 * @since 2.7.0 |
3319 * @since 2.7.0 |
2621 * |
3320 * |
2622 * @param int $number The number of words. Default 55. |
3321 * @param int $number The number of words. Default 55. |
2623 */ |
3322 */ |
2624 $excerpt_length = apply_filters( 'excerpt_length', 55 ); |
3323 $excerpt_length = apply_filters( 'excerpt_length', 55 ); |
2625 /** |
3324 /** |
2626 * Filter the string in the "more" link displayed after a trimmed excerpt. |
3325 * Filters the string in the "more" link displayed after a trimmed excerpt. |
2627 * |
3326 * |
2628 * @since 2.9.0 |
3327 * @since 2.9.0 |
2629 * |
3328 * |
2630 * @param string $more_string The string shown within the more link. |
3329 * @param string $more_string The string shown within the more link. |
2631 */ |
3330 */ |
2632 $excerpt_more = apply_filters( 'excerpt_more', ' ' . '[…]' ); |
3331 $excerpt_more = apply_filters( 'excerpt_more', ' ' . '[…]' ); |
2633 $text = wp_trim_words( $text, $excerpt_length, $excerpt_more ); |
3332 $text = wp_trim_words( $text, $excerpt_length, $excerpt_more ); |
2634 } |
3333 } |
2635 /** |
3334 /** |
2636 * Filter the trimmed excerpt string. |
3335 * Filters the trimmed excerpt string. |
2637 * |
3336 * |
2638 * @since 2.8.0 |
3337 * @since 2.8.0 |
2639 * |
3338 * |
2640 * @param string $text The trimmed text. |
3339 * @param string $text The trimmed text. |
2641 * @param string $raw_excerpt The text prior to trimming. |
3340 * @param string $raw_excerpt The text prior to trimming. |
2650 * character (such as East Asian languages), the $num_words argument will apply |
3349 * character (such as East Asian languages), the $num_words argument will apply |
2651 * to the number of individual characters. |
3350 * to the number of individual characters. |
2652 * |
3351 * |
2653 * @since 3.3.0 |
3352 * @since 3.3.0 |
2654 * |
3353 * |
2655 * @param string $text Text to trim. |
3354 * @param string $text Text to trim. |
2656 * @param int $num_words Number of words. Default 55. |
3355 * @param int $num_words Number of words. Default 55. |
2657 * @param string $more Optional. What to append if $text needs to be trimmed. Default '…'. |
3356 * @param string $more Optional. What to append if $text needs to be trimmed. Default '…'. |
2658 * @return string Trimmed text. |
3357 * @return string Trimmed text. |
2659 */ |
3358 */ |
2660 function wp_trim_words( $text, $num_words = 55, $more = null ) { |
3359 function wp_trim_words( $text, $num_words = 55, $more = null ) { |
2661 if ( null === $more ) |
3360 if ( null === $more ) { |
2662 $more = __( '…' ); |
3361 $more = __( '…' ); |
3362 } |
|
3363 |
|
2663 $original_text = $text; |
3364 $original_text = $text; |
2664 $text = wp_strip_all_tags( $text ); |
3365 $text = wp_strip_all_tags( $text ); |
2665 /* translators: If your word count is based on single characters (East Asian characters), |
3366 |
2666 enter 'characters'. Otherwise, enter 'words'. Do not translate into your own language. */ |
3367 /* |
2667 if ( 'characters' == _x( 'words', 'word count: words or characters?' ) && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) { |
3368 * translators: If your word count is based on single characters (e.g. East Asian characters), |
3369 * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. |
|
3370 * Do not translate into your own language. |
|
3371 */ |
|
3372 if ( strpos( _x( 'words', 'Word count type. Do not translate!' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) { |
|
2668 $text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' ); |
3373 $text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' ); |
2669 preg_match_all( '/./u', $text, $words_array ); |
3374 preg_match_all( '/./u', $text, $words_array ); |
2670 $words_array = array_slice( $words_array[0], 0, $num_words + 1 ); |
3375 $words_array = array_slice( $words_array[0], 0, $num_words + 1 ); |
2671 $sep = ''; |
3376 $sep = ''; |
2672 } else { |
3377 } else { |
2673 $words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY ); |
3378 $words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY ); |
2674 $sep = ' '; |
3379 $sep = ' '; |
2675 } |
3380 } |
3381 |
|
2676 if ( count( $words_array ) > $num_words ) { |
3382 if ( count( $words_array ) > $num_words ) { |
2677 array_pop( $words_array ); |
3383 array_pop( $words_array ); |
2678 $text = implode( $sep, $words_array ); |
3384 $text = implode( $sep, $words_array ); |
2679 $text = $text . $more; |
3385 $text = $text . $more; |
2680 } else { |
3386 } else { |
2681 $text = implode( $sep, $words_array ); |
3387 $text = implode( $sep, $words_array ); |
2682 } |
3388 } |
3389 |
|
2683 /** |
3390 /** |
2684 * Filter the text content after words have been trimmed. |
3391 * Filters the text content after words have been trimmed. |
2685 * |
3392 * |
2686 * @since 3.3.0 |
3393 * @since 3.3.0 |
2687 * |
3394 * |
2688 * @param string $text The trimmed text. |
3395 * @param string $text The trimmed text. |
2689 * @param int $num_words The number of words to trim the text to. Default 5. |
3396 * @param int $num_words The number of words to trim the text to. Default 55. |
2690 * @param string $more An optional string to append to the end of the trimmed text, e.g. …. |
3397 * @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. |
3398 * @param string $original_text The text before it was trimmed. |
2692 */ |
3399 */ |
2693 return apply_filters( 'wp_trim_words', $text, $num_words, $more, $original_text ); |
3400 return apply_filters( 'wp_trim_words', $text, $num_words, $more, $original_text ); |
2694 } |
3401 } |
2699 * @since 1.5.1 |
3406 * @since 1.5.1 |
2700 * |
3407 * |
2701 * @param string $text The text within which entities will be converted. |
3408 * @param string $text The text within which entities will be converted. |
2702 * @return string Text with converted entities. |
3409 * @return string Text with converted entities. |
2703 */ |
3410 */ |
2704 function ent2ncr($text) { |
3411 function ent2ncr( $text ) { |
2705 |
3412 |
2706 /** |
3413 /** |
2707 * Filter text before named entities are converted into numbered entities. |
3414 * Filters text before named entities are converted into numbered entities. |
2708 * |
3415 * |
2709 * A non-null string must be returned for the filter to be evaluated. |
3416 * A non-null string must be returned for the filter to be evaluated. |
2710 * |
3417 * |
2711 * @since 3.3.0 |
3418 * @since 3.3.0 |
2712 * |
3419 * |
2713 * @param null $converted_text The text to be converted. Default null. |
3420 * @param null $converted_text The text to be converted. Default null. |
2714 * @param string $text The text prior to entity conversion. |
3421 * @param string $text The text prior to entity conversion. |
2715 */ |
3422 */ |
2716 $filtered = apply_filters( 'pre_ent2ncr', null, $text ); |
3423 $filtered = apply_filters( 'pre_ent2ncr', null, $text ); |
2717 if( null !== $filtered ) |
3424 if ( null !== $filtered ) |
2718 return $filtered; |
3425 return $filtered; |
2719 |
3426 |
2720 $to_ncr = array( |
3427 $to_ncr = array( |
2721 '"' => '"', |
3428 '"' => '"', |
2722 '&' => '&', |
3429 '&' => '&', |
2978 |
3685 |
2979 return str_replace( array_keys($to_ncr), array_values($to_ncr), $text ); |
3686 return str_replace( array_keys($to_ncr), array_values($to_ncr), $text ); |
2980 } |
3687 } |
2981 |
3688 |
2982 /** |
3689 /** |
2983 * Formats text for the rich text editor. |
3690 * Formats text for the editor. |
2984 * |
3691 * |
2985 * The filter 'richedit_pre' is applied here. If $text is empty the filter will |
3692 * Generally the browsers treat everything inside a textarea as text, but |
2986 * be applied to an empty string. |
3693 * it is still a good idea to HTML entity encode `<`, `>` and `&` in the content. |
2987 * |
3694 * |
2988 * @since 2.0.0 |
3695 * The filter {@see 'format_for_editor'} is applied here. If `$text` is empty the |
2989 * |
3696 * filter will be applied to an empty string. |
2990 * @param string $text The text to be formatted. |
3697 * |
3698 * @since 4.3.0 |
|
3699 * |
|
3700 * @see _WP_Editors::editor() |
|
3701 * |
|
3702 * @param string $text The text to be formatted. |
|
3703 * @param string $default_editor The default editor for the current user. |
|
3704 * It is usually either 'html' or 'tinymce'. |
|
2991 * @return string The formatted text after filter is applied. |
3705 * @return string The formatted text after filter is applied. |
2992 */ |
3706 */ |
2993 function wp_richedit_pre($text) { |
3707 function format_for_editor( $text, $default_editor = null ) { |
2994 if ( empty( $text ) ) { |
3708 if ( $text ) { |
2995 /** |
3709 $text = htmlspecialchars( $text, ENT_NOQUOTES, get_option( 'blog_charset' ) ); |
2996 * Filter text returned for the rich text editor. |
3710 } |
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 } |
|
3011 |
|
3012 $output = convert_chars($text); |
|
3013 $output = wpautop($output); |
|
3014 $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); |
|
3015 |
|
3016 /** This filter is documented in wp-includes/formatting.php */ |
|
3017 return apply_filters( 'richedit_pre', $output ); |
|
3018 } |
|
3019 |
|
3020 /** |
|
3021 * Formats text for the HTML editor. |
|
3022 * |
|
3023 * Unless $output is empty it will pass through htmlspecialchars before the |
|
3024 * 'htmledit_pre' filter is applied. |
|
3025 * |
|
3026 * @since 2.5.0 |
|
3027 * |
|
3028 * @param string $output The text to be formatted. |
|
3029 * @return string Formatted text after filter applied. |
|
3030 */ |
|
3031 function wp_htmledit_pre($output) { |
|
3032 if ( !empty($output) ) |
|
3033 $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); // convert only < > & |
|
3034 |
3711 |
3035 /** |
3712 /** |
3036 * Filter the text before it is formatted for the HTML editor. |
3713 * Filters the text after it is formatted for the editor. |
3037 * |
3714 * |
3038 * @since 2.5.0 |
3715 * @since 4.3.0 |
3039 * |
3716 * |
3040 * @param string $output The HTML-formatted text. |
3717 * @param string $text The formatted text. |
3718 * @param string $default_editor The default editor for the current user. |
|
3719 * It is usually either 'html' or 'tinymce'. |
|
3041 */ |
3720 */ |
3042 return apply_filters( 'htmledit_pre', $output ); |
3721 return apply_filters( 'format_for_editor', $text, $default_editor ); |
3043 } |
3722 } |
3044 |
3723 |
3045 /** |
3724 /** |
3046 * Perform a deep string replace operation to ensure the values in $search are no longer present |
3725 * Perform a deep string replace operation to ensure the values in $search are no longer present |
3047 * |
3726 * |
3050 * str_replace would return |
3729 * str_replace would return |
3051 * |
3730 * |
3052 * @since 2.8.1 |
3731 * @since 2.8.1 |
3053 * @access private |
3732 * @access private |
3054 * |
3733 * |
3055 * @param string|array $search The value being searched for, otherwise known as the needle. An array may be used to designate multiple needles. |
3734 * @param string|array $search The value being searched for, otherwise known as the needle. |
3056 * @param string $subject The string being searched and replaced on, otherwise known as the haystack. |
3735 * An array may be used to designate multiple needles. |
3736 * @param string $subject The string being searched and replaced on, otherwise known as the haystack. |
|
3057 * @return string The string with the replaced svalues. |
3737 * @return string The string with the replaced svalues. |
3058 */ |
3738 */ |
3059 function _deep_replace( $search, $subject ) { |
3739 function _deep_replace( $search, $subject ) { |
3060 $subject = (string) $subject; |
3740 $subject = (string) $subject; |
3061 |
3741 |
3072 * |
3752 * |
3073 * Usually you should prepare queries using wpdb::prepare(). |
3753 * Usually you should prepare queries using wpdb::prepare(). |
3074 * Sometimes, spot-escaping is required or useful. One example |
3754 * Sometimes, spot-escaping is required or useful. One example |
3075 * is preparing an array for use in an IN clause. |
3755 * is preparing an array for use in an IN clause. |
3076 * |
3756 * |
3757 * NOTE: Since 4.8.3, '%' characters will be replaced with a placeholder string, |
|
3758 * this prevents certain SQLi attacks from taking place. This change in behaviour |
|
3759 * may cause issues for code that expects the return value of esc_sql() to be useable |
|
3760 * for other purposes. |
|
3761 * |
|
3077 * @since 2.8.0 |
3762 * @since 2.8.0 |
3763 * |
|
3764 * @global wpdb $wpdb WordPress database abstraction object. |
|
3765 * |
|
3078 * @param string|array $data Unescaped data |
3766 * @param string|array $data Unescaped data |
3079 * @return string|array Escaped data |
3767 * @return string|array Escaped data |
3080 */ |
3768 */ |
3081 function esc_sql( $data ) { |
3769 function esc_sql( $data ) { |
3082 global $wpdb; |
3770 global $wpdb; |
3085 |
3773 |
3086 /** |
3774 /** |
3087 * Checks and cleans a URL. |
3775 * Checks and cleans a URL. |
3088 * |
3776 * |
3089 * A number of characters are removed from the URL. If the URL is for displaying |
3777 * A number of characters are removed from the URL. If the URL is for displaying |
3090 * (the default behaviour) ampersands are also replaced. The 'clean_url' filter |
3778 * (the default behaviour) ampersands are also replaced. The {@see 'clean_url'} filter |
3091 * is applied to the returned cleaned URL. |
3779 * is applied to the returned cleaned URL. |
3092 * |
3780 * |
3093 * @since 2.8.0 |
3781 * @since 2.8.0 |
3094 * |
3782 * |
3095 * @param string $url The URL to be cleaned. |
3783 * @param string $url The URL to be cleaned. |
3096 * @param array $protocols Optional. An array of acceptable protocols. |
3784 * @param array $protocols Optional. An array of acceptable protocols. |
3097 * Defaults to 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn' if not set. |
3785 * Defaults to return value of wp_allowed_protocols() |
3098 * @param string $_context Private. Use esc_url_raw() for database usage. |
3786 * @param string $_context Private. Use esc_url_raw() for database usage. |
3099 * @return string The cleaned $url after the 'clean_url' filter is applied. |
3787 * @return string The cleaned $url after the {@see 'clean_url'} filter is applied. |
3100 */ |
3788 */ |
3101 function esc_url( $url, $protocols = null, $_context = 'display' ) { |
3789 function esc_url( $url, $protocols = null, $_context = 'display' ) { |
3102 $original_url = $url; |
3790 $original_url = $url; |
3103 |
3791 |
3104 if ( '' == $url ) |
3792 if ( '' == $url ) |
3105 return $url; |
3793 return $url; |
3106 $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url); |
3794 |
3107 $strip = array('%0d', '%0a', '%0D', '%0A'); |
3795 $url = str_replace( ' ', '%20', $url ); |
3108 $url = _deep_replace($strip, $url); |
3796 $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url); |
3797 |
|
3798 if ( '' === $url ) { |
|
3799 return $url; |
|
3800 } |
|
3801 |
|
3802 if ( 0 !== stripos( $url, 'mailto:' ) ) { |
|
3803 $strip = array('%0d', '%0a', '%0D', '%0A'); |
|
3804 $url = _deep_replace($strip, $url); |
|
3805 } |
|
3806 |
|
3109 $url = str_replace(';//', '://', $url); |
3807 $url = str_replace(';//', '://', $url); |
3110 /* If the URL doesn't appear to contain a scheme, we |
3808 /* If the URL doesn't appear to contain a scheme, we |
3111 * presume it needs http:// appended (unless a relative |
3809 * presume it needs http:// prepended (unless a relative |
3112 * link starting with /, # or ? or a php file). |
3810 * link starting with /, # or ? or a php file). |
3113 */ |
3811 */ |
3114 if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) && |
3812 if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) && |
3115 ! preg_match('/^[a-z0-9-]+?\.php/i', $url) ) |
3813 ! preg_match('/^[a-z0-9-]+?\.php/i', $url) ) |
3116 $url = 'http://' . $url; |
3814 $url = 'http://' . $url; |
3118 // Replace ampersands and single quotes only when displaying. |
3816 // Replace ampersands and single quotes only when displaying. |
3119 if ( 'display' == $_context ) { |
3817 if ( 'display' == $_context ) { |
3120 $url = wp_kses_normalize_entities( $url ); |
3818 $url = wp_kses_normalize_entities( $url ); |
3121 $url = str_replace( '&', '&', $url ); |
3819 $url = str_replace( '&', '&', $url ); |
3122 $url = str_replace( "'", ''', $url ); |
3820 $url = str_replace( "'", ''', $url ); |
3821 } |
|
3822 |
|
3823 if ( ( false !== strpos( $url, '[' ) ) || ( false !== strpos( $url, ']' ) ) ) { |
|
3824 |
|
3825 $parsed = wp_parse_url( $url ); |
|
3826 $front = ''; |
|
3827 |
|
3828 if ( isset( $parsed['scheme'] ) ) { |
|
3829 $front .= $parsed['scheme'] . '://'; |
|
3830 } elseif ( '/' === $url[0] ) { |
|
3831 $front .= '//'; |
|
3832 } |
|
3833 |
|
3834 if ( isset( $parsed['user'] ) ) { |
|
3835 $front .= $parsed['user']; |
|
3836 } |
|
3837 |
|
3838 if ( isset( $parsed['pass'] ) ) { |
|
3839 $front .= ':' . $parsed['pass']; |
|
3840 } |
|
3841 |
|
3842 if ( isset( $parsed['user'] ) || isset( $parsed['pass'] ) ) { |
|
3843 $front .= '@'; |
|
3844 } |
|
3845 |
|
3846 if ( isset( $parsed['host'] ) ) { |
|
3847 $front .= $parsed['host']; |
|
3848 } |
|
3849 |
|
3850 if ( isset( $parsed['port'] ) ) { |
|
3851 $front .= ':' . $parsed['port']; |
|
3852 } |
|
3853 |
|
3854 $end_dirty = str_replace( $front, '', $url ); |
|
3855 $end_clean = str_replace( array( '[', ']' ), array( '%5B', '%5D' ), $end_dirty ); |
|
3856 $url = str_replace( $end_dirty, $end_clean, $url ); |
|
3857 |
|
3123 } |
3858 } |
3124 |
3859 |
3125 if ( '/' === $url[0] ) { |
3860 if ( '/' === $url[0] ) { |
3126 $good_protocol_url = $url; |
3861 $good_protocol_url = $url; |
3127 } else { |
3862 } else { |
3131 if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) |
3866 if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) |
3132 return ''; |
3867 return ''; |
3133 } |
3868 } |
3134 |
3869 |
3135 /** |
3870 /** |
3136 * Filter a string cleaned and escaped for output as a URL. |
3871 * Filters a string cleaned and escaped for output as a URL. |
3137 * |
3872 * |
3138 * @since 2.3.0 |
3873 * @since 2.3.0 |
3139 * |
3874 * |
3140 * @param string $good_protocol_url The cleaned URL to be returned. |
3875 * @param string $good_protocol_url The cleaned URL to be returned. |
3141 * @param string $original_url The URL prior to cleaning. |
3876 * @param string $original_url The URL prior to cleaning. |
3147 /** |
3882 /** |
3148 * Performs esc_url() for database usage. |
3883 * Performs esc_url() for database usage. |
3149 * |
3884 * |
3150 * @since 2.8.0 |
3885 * @since 2.8.0 |
3151 * |
3886 * |
3152 * @param string $url The URL to be cleaned. |
3887 * @param string $url The URL to be cleaned. |
3153 * @param array $protocols An array of acceptable protocols. |
3888 * @param array $protocols An array of acceptable protocols. |
3154 * @return string The cleaned URL. |
3889 * @return string The cleaned URL. |
3155 */ |
3890 */ |
3156 function esc_url_raw( $url, $protocols = null ) { |
3891 function esc_url_raw( $url, $protocols = null ) { |
3157 return esc_url( $url, $protocols, 'db' ); |
3892 return esc_url( $url, $protocols, 'db' ); |
3158 } |
3893 } |
3159 |
3894 |
3160 /** |
3895 /** |
3161 * Convert entities, while preserving already-encoded entities. |
3896 * Convert entities, while preserving already-encoded entities. |
3162 * |
3897 * |
3163 * @link http://www.php.net/htmlentities Borrowed from the PHP Manual user notes. |
3898 * @link https://secure.php.net/htmlentities Borrowed from the PHP Manual user notes. |
3164 * |
3899 * |
3165 * @since 1.2.2 |
3900 * @since 1.2.2 |
3166 * |
3901 * |
3167 * @param string $myHTML The text to be converted. |
3902 * @param string $myHTML The text to be converted. |
3168 * @return string Converted text. |
3903 * @return string Converted text. |
3169 */ |
3904 */ |
3170 function htmlentities2($myHTML) { |
3905 function htmlentities2( $myHTML ) { |
3171 $translation_table = get_html_translation_table( HTML_ENTITIES, ENT_QUOTES ); |
3906 $translation_table = get_html_translation_table( HTML_ENTITIES, ENT_QUOTES ); |
3172 $translation_table[chr(38)] = '&'; |
3907 $translation_table[chr(38)] = '&'; |
3173 return preg_replace( "/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/", "&", strtr($myHTML, $translation_table) ); |
3908 return preg_replace( "/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/", "&", strtr($myHTML, $translation_table) ); |
3174 } |
3909 } |
3175 |
3910 |
3176 /** |
3911 /** |
3177 * Escape single quotes, htmlspecialchar " < > &, and fix line endings. |
3912 * Escape single quotes, htmlspecialchar " < > &, and fix line endings. |
3178 * |
3913 * |
3179 * Escapes text strings for echoing in JS. It is intended to be used for inline JS |
3914 * Escapes text strings for echoing in JS. It is intended to be used for inline JS |
3180 * (in a tag attribute, for example onclick="..."). Note that the strings have to |
3915 * (in a tag attribute, for example onclick="..."). Note that the strings have to |
3181 * be in single quotes. The filter 'js_escape' is also applied here. |
3916 * be in single quotes. The {@see 'js_escape'} filter is also applied here. |
3182 * |
3917 * |
3183 * @since 2.8.0 |
3918 * @since 2.8.0 |
3184 * |
3919 * |
3185 * @param string $text The text to be escaped. |
3920 * @param string $text The text to be escaped. |
3186 * @return string Escaped text. |
3921 * @return string Escaped text. |
3190 $safe_text = _wp_specialchars( $safe_text, ENT_COMPAT ); |
3925 $safe_text = _wp_specialchars( $safe_text, ENT_COMPAT ); |
3191 $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) ); |
3926 $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) ); |
3192 $safe_text = str_replace( "\r", '', $safe_text ); |
3927 $safe_text = str_replace( "\r", '', $safe_text ); |
3193 $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) ); |
3928 $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) ); |
3194 /** |
3929 /** |
3195 * Filter a string cleaned and escaped for output in JavaScript. |
3930 * Filters a string cleaned and escaped for output in JavaScript. |
3196 * |
3931 * |
3197 * Text passed to esc_js() is stripped of invalid or special characters, |
3932 * Text passed to esc_js() is stripped of invalid or special characters, |
3198 * and properly slashed for output. |
3933 * and properly slashed for output. |
3199 * |
3934 * |
3200 * @since 2.0.6 |
3935 * @since 2.0.6 |
3215 */ |
3950 */ |
3216 function esc_html( $text ) { |
3951 function esc_html( $text ) { |
3217 $safe_text = wp_check_invalid_utf8( $text ); |
3952 $safe_text = wp_check_invalid_utf8( $text ); |
3218 $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); |
3953 $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); |
3219 /** |
3954 /** |
3220 * Filter a string cleaned and escaped for output in HTML. |
3955 * Filters a string cleaned and escaped for output in HTML. |
3221 * |
3956 * |
3222 * Text passed to esc_html() is stripped of invalid or special characters |
3957 * Text passed to esc_html() is stripped of invalid or special characters |
3223 * before output. |
3958 * before output. |
3224 * |
3959 * |
3225 * @since 2.8.0 |
3960 * @since 2.8.0 |
3240 */ |
3975 */ |
3241 function esc_attr( $text ) { |
3976 function esc_attr( $text ) { |
3242 $safe_text = wp_check_invalid_utf8( $text ); |
3977 $safe_text = wp_check_invalid_utf8( $text ); |
3243 $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); |
3978 $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); |
3244 /** |
3979 /** |
3245 * Filter a string cleaned and escaped for output in an HTML attribute. |
3980 * Filters a string cleaned and escaped for output in an HTML attribute. |
3246 * |
3981 * |
3247 * Text passed to esc_attr() is stripped of invalid or special characters |
3982 * Text passed to esc_attr() is stripped of invalid or special characters |
3248 * before output. |
3983 * before output. |
3249 * |
3984 * |
3250 * @since 2.0.6 |
3985 * @since 2.0.6 |
3264 * @return string |
3999 * @return string |
3265 */ |
4000 */ |
3266 function esc_textarea( $text ) { |
4001 function esc_textarea( $text ) { |
3267 $safe_text = htmlspecialchars( $text, ENT_QUOTES, get_option( 'blog_charset' ) ); |
4002 $safe_text = htmlspecialchars( $text, ENT_QUOTES, get_option( 'blog_charset' ) ); |
3268 /** |
4003 /** |
3269 * Filter a string cleaned and escaped for output in a textarea element. |
4004 * Filters a string cleaned and escaped for output in a textarea element. |
3270 * |
4005 * |
3271 * @since 3.1.0 |
4006 * @since 3.1.0 |
3272 * |
4007 * |
3273 * @param string $safe_text The text after it has been escaped. |
4008 * @param string $safe_text The text after it has been escaped. |
3274 * @param string $text The text prior to being escaped. |
4009 * @param string $text The text prior to being escaped. |
3282 * @since 2.5.0 |
4017 * @since 2.5.0 |
3283 * |
4018 * |
3284 * @param string $tag_name |
4019 * @param string $tag_name |
3285 * @return string |
4020 * @return string |
3286 */ |
4021 */ |
3287 function tag_escape($tag_name) { |
4022 function tag_escape( $tag_name ) { |
3288 $safe_tag = strtolower( preg_replace('/[^a-zA-Z0-9_:]/', '', $tag_name) ); |
4023 $safe_tag = strtolower( preg_replace('/[^a-zA-Z0-9_:]/', '', $tag_name) ); |
3289 /** |
4024 /** |
3290 * Filter a string cleaned and escaped for output as an HTML tag. |
4025 * Filters a string cleaned and escaped for output as an HTML tag. |
3291 * |
4026 * |
3292 * @since 2.8.0 |
4027 * @since 2.8.0 |
3293 * |
4028 * |
3294 * @param string $safe_tag The tag name after it has been escaped. |
4029 * @param string $safe_tag The tag name after it has been escaped. |
3295 * @param string $tag_name The text before it was escaped. |
4030 * @param string $tag_name The text before it was escaped. |
3308 * |
4043 * |
3309 * @param string $link Full URL path. |
4044 * @param string $link Full URL path. |
3310 * @return string Absolute path. |
4045 * @return string Absolute path. |
3311 */ |
4046 */ |
3312 function wp_make_link_relative( $link ) { |
4047 function wp_make_link_relative( $link ) { |
3313 return preg_replace( '|^(https?:)?//[^/]+(/.*)|i', '$2', $link ); |
4048 return preg_replace( '|^(https?:)?//[^/]+(/?.*)|i', '$2', $link ); |
3314 } |
4049 } |
3315 |
4050 |
3316 /** |
4051 /** |
3317 * Sanitises various option values based on the nature of the option. |
4052 * Sanitises various option values based on the nature of the option. |
3318 * |
4053 * |
3319 * This is basically a switch statement which will pass $value through a number |
4054 * This is basically a switch statement which will pass $value through a number |
3320 * of functions depending on the $option. |
4055 * of functions depending on the $option. |
3321 * |
4056 * |
3322 * @since 2.0.5 |
4057 * @since 2.0.5 |
3323 * |
4058 * |
4059 * @global wpdb $wpdb WordPress database abstraction object. |
|
4060 * |
|
3324 * @param string $option The name of the option. |
4061 * @param string $option The name of the option. |
3325 * @param string $value The unsanitised value. |
4062 * @param string $value The unsanitised value. |
3326 * @return string Sanitized value. |
4063 * @return string Sanitized value. |
3327 */ |
4064 */ |
3328 function sanitize_option($option, $value) { |
4065 function sanitize_option( $option, $value ) { |
3329 global $wpdb; |
4066 global $wpdb; |
4067 |
|
4068 $original_value = $value; |
|
4069 $error = ''; |
|
3330 |
4070 |
3331 switch ( $option ) { |
4071 switch ( $option ) { |
3332 case 'admin_email' : |
4072 case 'admin_email' : |
3333 case 'new_admin_email' : |
4073 case 'new_admin_email' : |
3334 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4074 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
3335 $value = sanitize_email( $value ); |
4075 if ( is_wp_error( $value ) ) { |
3336 if ( ! is_email( $value ) ) { |
4076 $error = $value->get_error_message(); |
3337 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
4077 } else { |
3338 if ( function_exists( 'add_settings_error' ) ) |
4078 $value = sanitize_email( $value ); |
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.' ) ); |
4079 if ( ! is_email( $value ) ) { |
4080 $error = __( 'The email address entered did not appear to be a valid email address. Please enter a valid email address.' ); |
|
4081 } |
|
3340 } |
4082 } |
3341 break; |
4083 break; |
3342 |
4084 |
3343 case 'thumbnail_size_w': |
4085 case 'thumbnail_size_w': |
3344 case 'thumbnail_size_h': |
4086 case 'thumbnail_size_h': |
3345 case 'medium_size_w': |
4087 case 'medium_size_w': |
3346 case 'medium_size_h': |
4088 case 'medium_size_h': |
4089 case 'medium_large_size_w': |
|
4090 case 'medium_large_size_h': |
|
3347 case 'large_size_w': |
4091 case 'large_size_w': |
3348 case 'large_size_h': |
4092 case 'large_size_h': |
3349 case 'mailserver_port': |
4093 case 'mailserver_port': |
3350 case 'comment_max_links': |
4094 case 'comment_max_links': |
3351 case 'page_on_front': |
4095 case 'page_on_front': |
3357 case 'close_comments_days_old': |
4101 case 'close_comments_days_old': |
3358 case 'comments_per_page': |
4102 case 'comments_per_page': |
3359 case 'thread_comments_depth': |
4103 case 'thread_comments_depth': |
3360 case 'users_can_register': |
4104 case 'users_can_register': |
3361 case 'start_of_week': |
4105 case 'start_of_week': |
4106 case 'site_icon': |
|
3362 $value = absint( $value ); |
4107 $value = absint( $value ); |
3363 break; |
4108 break; |
3364 |
4109 |
3365 case 'posts_per_page': |
4110 case 'posts_per_page': |
3366 case 'posts_per_rss': |
4111 case 'posts_per_rss': |
3379 break; |
4124 break; |
3380 |
4125 |
3381 case 'blogdescription': |
4126 case 'blogdescription': |
3382 case 'blogname': |
4127 case 'blogname': |
3383 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4128 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
3384 $value = wp_kses_post( $value ); |
4129 if ( $value !== $original_value ) { |
3385 $value = esc_html( $value ); |
4130 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', wp_encode_emoji( $original_value ) ); |
4131 } |
|
4132 |
|
4133 if ( is_wp_error( $value ) ) { |
|
4134 $error = $value->get_error_message(); |
|
4135 } else { |
|
4136 $value = esc_html( $value ); |
|
4137 } |
|
3386 break; |
4138 break; |
3387 |
4139 |
3388 case 'blog_charset': |
4140 case 'blog_charset': |
3389 $value = preg_replace('/[^a-zA-Z0-9_-]/', '', $value); // strips slashes |
4141 $value = preg_replace('/[^a-zA-Z0-9_-]/', '', $value); // strips slashes |
3390 break; |
4142 break; |
3402 case 'mailserver_url': |
4154 case 'mailserver_url': |
3403 case 'mailserver_login': |
4155 case 'mailserver_login': |
3404 case 'mailserver_pass': |
4156 case 'mailserver_pass': |
3405 case 'upload_path': |
4157 case 'upload_path': |
3406 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4158 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
3407 $value = strip_tags( $value ); |
4159 if ( is_wp_error( $value ) ) { |
3408 $value = wp_kses_data( $value ); |
4160 $error = $value->get_error_message(); |
4161 } else { |
|
4162 $value = strip_tags( $value ); |
|
4163 $value = wp_kses_data( $value ); |
|
4164 } |
|
3409 break; |
4165 break; |
3410 |
4166 |
3411 case 'ping_sites': |
4167 case 'ping_sites': |
3412 $value = explode( "\n", $value ); |
4168 $value = explode( "\n", $value ); |
3413 $value = array_filter( array_map( 'trim', $value ) ); |
4169 $value = array_filter( array_map( 'trim', $value ) ); |
3419 $value = preg_replace('/[^0-9:.-]/', '', $value); // strips slashes |
4175 $value = preg_replace('/[^0-9:.-]/', '', $value); // strips slashes |
3420 break; |
4176 break; |
3421 |
4177 |
3422 case 'siteurl': |
4178 case 'siteurl': |
3423 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4179 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
3424 if ( (bool)preg_match( '#http(s?)://(.+)#i', $value) ) { |
4180 if ( is_wp_error( $value ) ) { |
3425 $value = esc_url_raw($value); |
4181 $error = $value->get_error_message(); |
3426 } else { |
4182 } else { |
3427 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
4183 if ( preg_match( '#http(s?)://(.+)#i', $value ) ) { |
3428 if ( function_exists('add_settings_error') ) |
4184 $value = esc_url_raw( $value ); |
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.')); |
4185 } else { |
4186 $error = __( 'The WordPress address you entered did not appear to be a valid URL. Please enter a valid URL.' ); |
|
4187 } |
|
3430 } |
4188 } |
3431 break; |
4189 break; |
3432 |
4190 |
3433 case 'home': |
4191 case 'home': |
3434 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4192 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
3435 if ( (bool)preg_match( '#http(s?)://(.+)#i', $value) ) { |
4193 if ( is_wp_error( $value ) ) { |
3436 $value = esc_url_raw($value); |
4194 $error = $value->get_error_message(); |
3437 } else { |
4195 } else { |
3438 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
4196 if ( preg_match( '#http(s?)://(.+)#i', $value ) ) { |
3439 if ( function_exists('add_settings_error') ) |
4197 $value = esc_url_raw( $value ); |
3440 add_settings_error('home', 'invalid_home', __('The Site address you entered did not appear to be a valid URL. Please enter a valid URL.')); |
4198 } else { |
4199 $error = __( 'The Site address you entered did not appear to be a valid URL. Please enter a valid URL.' ); |
|
4200 } |
|
3441 } |
4201 } |
3442 break; |
4202 break; |
3443 |
4203 |
3444 case 'WPLANG': |
4204 case 'WPLANG': |
3445 $allowed = get_available_languages(); |
4205 $allowed = get_available_languages(); |
3451 } |
4211 } |
3452 break; |
4212 break; |
3453 |
4213 |
3454 case 'illegal_names': |
4214 case 'illegal_names': |
3455 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4215 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
3456 if ( ! is_array( $value ) ) |
4216 if ( is_wp_error( $value ) ) { |
3457 $value = explode( ' ', $value ); |
4217 $error = $value->get_error_message(); |
3458 |
4218 } else { |
3459 $value = array_values( array_filter( array_map( 'trim', $value ) ) ); |
4219 if ( ! is_array( $value ) ) |
3460 |
4220 $value = explode( ' ', $value ); |
3461 if ( ! $value ) |
4221 |
3462 $value = ''; |
4222 $value = array_values( array_filter( array_map( 'trim', $value ) ) ); |
4223 |
|
4224 if ( ! $value ) |
|
4225 $value = ''; |
|
4226 } |
|
3463 break; |
4227 break; |
3464 |
4228 |
3465 case 'limited_email_domains': |
4229 case 'limited_email_domains': |
3466 case 'banned_email_domains': |
4230 case 'banned_email_domains': |
3467 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4231 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
3468 if ( ! is_array( $value ) ) |
4232 if ( is_wp_error( $value ) ) { |
3469 $value = explode( "\n", $value ); |
4233 $error = $value->get_error_message(); |
3470 |
4234 } else { |
3471 $domains = array_values( array_filter( array_map( 'trim', $value ) ) ); |
4235 if ( ! is_array( $value ) ) |
3472 $value = array(); |
4236 $value = explode( "\n", $value ); |
3473 |
4237 |
3474 foreach ( $domains as $domain ) { |
4238 $domains = array_values( array_filter( array_map( 'trim', $value ) ) ); |
3475 if ( ! preg_match( '/(--|\.\.)/', $domain ) && preg_match( '|^([a-zA-Z0-9-\.])+$|', $domain ) ) |
4239 $value = array(); |
3476 $value[] = $domain; |
4240 |
4241 foreach ( $domains as $domain ) { |
|
4242 if ( ! preg_match( '/(--|\.\.)/', $domain ) && preg_match( '|^([a-zA-Z0-9-\.])+$|', $domain ) ) { |
|
4243 $value[] = $domain; |
|
4244 } |
|
4245 } |
|
4246 if ( ! $value ) |
|
4247 $value = ''; |
|
3477 } |
4248 } |
3478 if ( ! $value ) |
|
3479 $value = ''; |
|
3480 break; |
4249 break; |
3481 |
4250 |
3482 case 'timezone_string': |
4251 case 'timezone_string': |
3483 $allowed_zones = timezone_identifiers_list(); |
4252 $allowed_zones = timezone_identifiers_list(); |
3484 if ( ! in_array( $value, $allowed_zones ) && ! empty( $value ) ) { |
4253 if ( ! in_array( $value, $allowed_zones ) && ! empty( $value ) ) { |
3485 $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization |
4254 $error = __( 'The timezone you have entered is not valid. Please select a valid timezone.' ); |
3486 if ( function_exists('add_settings_error') ) |
|
3487 add_settings_error('timezone_string', 'invalid_timezone_string', __('The timezone you have entered is not valid. Please select a valid timezone.') ); |
|
3488 } |
4255 } |
3489 break; |
4256 break; |
3490 |
4257 |
3491 case 'permalink_structure': |
4258 case 'permalink_structure': |
3492 case 'category_base': |
4259 case 'category_base': |
3493 case 'tag_base': |
4260 case 'tag_base': |
3494 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4261 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
3495 $value = esc_url_raw( $value ); |
4262 if ( is_wp_error( $value ) ) { |
3496 $value = str_replace( 'http://', '', $value ); |
4263 $error = $value->get_error_message(); |
4264 } else { |
|
4265 $value = esc_url_raw( $value ); |
|
4266 $value = str_replace( 'http://', '', $value ); |
|
4267 } |
|
4268 |
|
4269 if ( 'permalink_structure' === $option && '' !== $value && ! preg_match( '/%[^\/%]+%/', $value ) ) { |
|
4270 $error = sprintf( |
|
4271 /* translators: %s: Codex URL */ |
|
4272 __( 'A structure tag is required when using custom permalinks. <a href="%s">Learn more</a>' ), |
|
4273 __( 'https://codex.wordpress.org/Using_Permalinks#Choosing_your_permalink_structure' ) |
|
4274 ); |
|
4275 } |
|
3497 break; |
4276 break; |
3498 |
4277 |
3499 case 'default_role' : |
4278 case 'default_role' : |
3500 if ( ! get_role( $value ) && get_role( 'subscriber' ) ) |
4279 if ( ! get_role( $value ) && get_role( 'subscriber' ) ) |
3501 $value = 'subscriber'; |
4280 $value = 'subscriber'; |
3502 break; |
4281 break; |
3503 |
4282 |
3504 case 'moderation_keys': |
4283 case 'moderation_keys': |
3505 case 'blacklist_keys': |
4284 case 'blacklist_keys': |
3506 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4285 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
3507 $value = explode( "\n", $value ); |
4286 if ( is_wp_error( $value ) ) { |
3508 $value = array_filter( array_map( 'trim', $value ) ); |
4287 $error = $value->get_error_message(); |
3509 $value = array_unique( $value ); |
4288 } else { |
3510 $value = implode( "\n", $value ); |
4289 $value = explode( "\n", $value ); |
4290 $value = array_filter( array_map( 'trim', $value ) ); |
|
4291 $value = array_unique( $value ); |
|
4292 $value = implode( "\n", $value ); |
|
4293 } |
|
3511 break; |
4294 break; |
3512 } |
4295 } |
3513 |
4296 |
4297 if ( ! empty( $error ) ) { |
|
4298 $value = get_option( $option ); |
|
4299 if ( function_exists( 'add_settings_error' ) ) { |
|
4300 add_settings_error( $option, "invalid_{$option}", $error ); |
|
4301 } |
|
4302 } |
|
4303 |
|
3514 /** |
4304 /** |
3515 * Filter an option value following sanitization. |
4305 * Filters an option value following sanitization. |
3516 * |
4306 * |
3517 * @since 2.3.0 |
4307 * @since 2.3.0 |
3518 * |
4308 * @since 4.3.0 Added the `$original_value` parameter. |
3519 * @param string $value The sanitized option value. |
4309 * |
3520 * @param string $option The option name. |
4310 * @param string $value The sanitized option value. |
4311 * @param string $option The option name. |
|
4312 * @param string $original_value The original value passed to the function. |
|
3521 */ |
4313 */ |
3522 $value = apply_filters( "sanitize_option_{$option}", $value, $option ); |
4314 return apply_filters( "sanitize_option_{$option}", $value, $option, $original_value ); |
4315 } |
|
4316 |
|
4317 /** |
|
4318 * Maps a function to all non-iterable elements of an array or an object. |
|
4319 * |
|
4320 * This is similar to `array_walk_recursive()` but acts upon objects too. |
|
4321 * |
|
4322 * @since 4.4.0 |
|
4323 * |
|
4324 * @param mixed $value The array, object, or scalar. |
|
4325 * @param callable $callback The function to map onto $value. |
|
4326 * @return mixed The value with the callback applied to all non-arrays and non-objects inside it. |
|
4327 */ |
|
4328 function map_deep( $value, $callback ) { |
|
4329 if ( is_array( $value ) ) { |
|
4330 foreach ( $value as $index => $item ) { |
|
4331 $value[ $index ] = map_deep( $item, $callback ); |
|
4332 } |
|
4333 } elseif ( is_object( $value ) ) { |
|
4334 $object_vars = get_object_vars( $value ); |
|
4335 foreach ( $object_vars as $property_name => $property_value ) { |
|
4336 $value->$property_name = map_deep( $property_value, $callback ); |
|
4337 } |
|
4338 } else { |
|
4339 $value = call_user_func( $callback, $value ); |
|
4340 } |
|
3523 |
4341 |
3524 return $value; |
4342 return $value; |
3525 } |
4343 } |
3526 |
4344 |
3527 /** |
4345 /** |
3528 * Parses a string into variables to be stored in an array. |
4346 * Parses a string into variables to be stored in an array. |
3529 * |
4347 * |
3530 * Uses {@link http://www.php.net/parse_str parse_str()} and stripslashes if |
4348 * Uses {@link https://secure.php.net/parse_str parse_str()} and stripslashes if |
3531 * {@link http://www.php.net/magic_quotes magic_quotes_gpc} is on. |
4349 * {@link https://secure.php.net/magic_quotes magic_quotes_gpc} is on. |
3532 * |
4350 * |
3533 * @since 2.2.1 |
4351 * @since 2.2.1 |
3534 * |
4352 * |
3535 * @param string $string The string to be parsed. |
4353 * @param string $string The string to be parsed. |
3536 * @param array $array Variables will be stored in this array. |
4354 * @param array $array Variables will be stored in this array. |
3537 */ |
4355 */ |
3538 function wp_parse_str( $string, &$array ) { |
4356 function wp_parse_str( $string, &$array ) { |
3539 parse_str( $string, $array ); |
4357 parse_str( $string, $array ); |
3540 if ( get_magic_quotes_gpc() ) |
4358 if ( get_magic_quotes_gpc() ) |
3541 $array = stripslashes_deep( $array ); |
4359 $array = stripslashes_deep( $array ); |
3542 /** |
4360 /** |
3543 * Filter the array of variables derived from a parsed string. |
4361 * Filters the array of variables derived from a parsed string. |
3544 * |
4362 * |
3545 * @since 2.3.0 |
4363 * @since 2.3.0 |
3546 * |
4364 * |
3547 * @param array $array The array populated with variables. |
4365 * @param array $array The array populated with variables. |
3548 */ |
4366 */ |
3579 |
4397 |
3580 /** |
4398 /** |
3581 * WordPress implementation of PHP sprintf() with filters. |
4399 * WordPress implementation of PHP sprintf() with filters. |
3582 * |
4400 * |
3583 * @since 2.5.0 |
4401 * @since 2.5.0 |
3584 * @link http://www.php.net/sprintf |
4402 * @link https://secure.php.net/sprintf |
3585 * |
4403 * |
3586 * @param string $pattern The string which formatted args are inserted. |
4404 * @param string $pattern The string which formatted args are inserted. |
3587 * @param mixed $args ,... Arguments to be formatted into the $pattern string. |
4405 * @param mixed $args ,... Arguments to be formatted into the $pattern string. |
3588 * @return string The formatted string. |
4406 * @return string The formatted string. |
3589 */ |
4407 */ |
3590 function wp_sprintf( $pattern ) { |
4408 function wp_sprintf( $pattern ) { |
3591 $args = func_get_args(); |
4409 $args = func_get_args(); |
3623 ++$arg_index; |
4441 ++$arg_index; |
3624 $arg = isset($args[$arg_index]) ? $args[$arg_index] : ''; |
4442 $arg = isset($args[$arg_index]) ? $args[$arg_index] : ''; |
3625 } |
4443 } |
3626 |
4444 |
3627 /** |
4445 /** |
3628 * Filter a fragment from the pattern passed to wp_sprintf(). |
4446 * Filters a fragment from the pattern passed to wp_sprintf(). |
3629 * |
4447 * |
3630 * If the fragment is unchanged, then sprintf() will be run on the fragment. |
4448 * If the fragment is unchanged, then sprintf() will be run on the fragment. |
3631 * |
4449 * |
3632 * @since 2.5.0 |
4450 * @since 2.5.0 |
3633 * |
4451 * |
3656 * on the amount of list items in the $args parameter. |
4474 * on the amount of list items in the $args parameter. |
3657 * |
4475 * |
3658 * @since 2.5.0 |
4476 * @since 2.5.0 |
3659 * |
4477 * |
3660 * @param string $pattern Content containing '%l' at the beginning. |
4478 * @param string $pattern Content containing '%l' at the beginning. |
3661 * @param array $args List items to prepend to the content and replace '%l'. |
4479 * @param array $args List items to prepend to the content and replace '%l'. |
3662 * @return string Localized list items and rest of the content. |
4480 * @return string Localized list items and rest of the content. |
3663 */ |
4481 */ |
3664 function wp_sprintf_l($pattern, $args) { |
4482 function wp_sprintf_l( $pattern, $args ) { |
3665 // Not a match |
4483 // Not a match |
3666 if ( substr($pattern, 0, 2) != '%l' ) |
4484 if ( substr($pattern, 0, 2) != '%l' ) |
3667 return $pattern; |
4485 return $pattern; |
3668 |
4486 |
3669 // Nothing to work with |
4487 // Nothing to work with |
3670 if ( empty($args) ) |
4488 if ( empty($args) ) |
3671 return ''; |
4489 return ''; |
3672 |
4490 |
3673 /** |
4491 /** |
3674 * Filter the translated delimiters used by wp_sprintf_l(). |
4492 * Filters the translated delimiters used by wp_sprintf_l(). |
3675 * Placeholders (%s) are included to assist translators and then |
4493 * Placeholders (%s) are included to assist translators and then |
3676 * removed before the array of strings reaches the filter. |
4494 * removed before the array of strings reaches the filter. |
3677 * |
4495 * |
3678 * Please note: Ampersands and entities should be avoided here. |
4496 * Please note: Ampersands and entities should be avoided here. |
3679 * |
4497 * |
3714 * be counted as one character. For example & will be counted as 4, < as |
4532 * be counted as one character. For example & will be counted as 4, < as |
3715 * 3, etc. |
4533 * 3, etc. |
3716 * |
4534 * |
3717 * @since 2.5.0 |
4535 * @since 2.5.0 |
3718 * |
4536 * |
3719 * @param string $str String to get the excerpt from. |
4537 * @param string $str String to get the excerpt from. |
3720 * @param integer $count Maximum number of characters to take. |
4538 * @param int $count Maximum number of characters to take. |
3721 * @param string $more Optional. What to append if $str needs to be trimmed. Defaults to empty string. |
4539 * @param string $more Optional. What to append if $str needs to be trimmed. Defaults to empty string. |
3722 * @return string The excerpt. |
4540 * @return string The excerpt. |
3723 */ |
4541 */ |
3724 function wp_html_excerpt( $str, $count, $more = null ) { |
4542 function wp_html_excerpt( $str, $count, $more = null ) { |
3725 if ( null === $more ) |
4543 if ( null === $more ) |
3726 $more = ''; |
4544 $more = ''; |
3739 * By default it supports the 'src' and 'href' attributes. However this can be |
4557 * By default it supports the 'src' and 'href' attributes. However this can be |
3740 * changed via the 3rd param. |
4558 * changed via the 3rd param. |
3741 * |
4559 * |
3742 * @since 2.7.0 |
4560 * @since 2.7.0 |
3743 * |
4561 * |
4562 * @global string $_links_add_base |
|
4563 * |
|
3744 * @param string $content String to search for links in. |
4564 * @param string $content String to search for links in. |
3745 * @param string $base The base URL to prefix to links. |
4565 * @param string $base The base URL to prefix to links. |
3746 * @param array $attrs The attributes which should be processed. |
4566 * @param array $attrs The attributes which should be processed. |
3747 * @return string The processed content. |
4567 * @return string The processed content. |
3748 */ |
4568 */ |
3749 function links_add_base_url( $content, $base, $attrs = array('src', 'href') ) { |
4569 function links_add_base_url( $content, $base, $attrs = array('src', 'href') ) { |
3750 global $_links_add_base; |
4570 global $_links_add_base; |
3751 $_links_add_base = $base; |
4571 $_links_add_base = $base; |
3757 * Callback to add a base url to relative links in passed content. |
4577 * Callback to add a base url to relative links in passed content. |
3758 * |
4578 * |
3759 * @since 2.7.0 |
4579 * @since 2.7.0 |
3760 * @access private |
4580 * @access private |
3761 * |
4581 * |
4582 * @global string $_links_add_base |
|
4583 * |
|
3762 * @param string $m The matched link. |
4584 * @param string $m The matched link. |
3763 * @return string The processed link. |
4585 * @return string The processed link. |
3764 */ |
4586 */ |
3765 function _links_add_base($m) { |
4587 function _links_add_base( $m ) { |
3766 global $_links_add_base; |
4588 global $_links_add_base; |
3767 //1 = attribute name 2 = quotation mark 3 = URL |
4589 //1 = attribute name 2 = quotation mark 3 = URL |
3768 return $m[1] . '=' . $m[2] . |
4590 return $m[1] . '=' . $m[2] . |
3769 ( preg_match( '#^(\w{1,20}):#', $m[3], $protocol ) && in_array( $protocol[1], wp_allowed_protocols() ) ? |
4591 ( preg_match( '#^(\w{1,20}):#', $m[3], $protocol ) && in_array( $protocol[1], wp_allowed_protocols() ) ? |
3770 $m[3] : |
4592 $m[3] : |
3771 WP_HTTP::make_absolute_url( $m[3], $_links_add_base ) |
4593 WP_Http::make_absolute_url( $m[3], $_links_add_base ) |
3772 ) |
4594 ) |
3773 . $m[2]; |
4595 . $m[2]; |
3774 } |
4596 } |
3775 |
4597 |
3776 /** |
4598 /** |
3781 * |
4603 * |
3782 * *NOTE:* Any current target attributed will be stripped and replaced. |
4604 * *NOTE:* Any current target attributed will be stripped and replaced. |
3783 * |
4605 * |
3784 * @since 2.7.0 |
4606 * @since 2.7.0 |
3785 * |
4607 * |
4608 * @global string $_links_add_target |
|
4609 * |
|
3786 * @param string $content String to search for links in. |
4610 * @param string $content String to search for links in. |
3787 * @param string $target The Target to add to the links. |
4611 * @param string $target The Target to add to the links. |
3788 * @param array $tags An array of tags to apply to. |
4612 * @param array $tags An array of tags to apply to. |
3789 * @return string The processed content. |
4613 * @return string The processed content. |
3790 */ |
4614 */ |
3791 function links_add_target( $content, $target = '_blank', $tags = array('a') ) { |
4615 function links_add_target( $content, $target = '_blank', $tags = array('a') ) { |
3792 global $_links_add_target; |
4616 global $_links_add_target; |
3793 $_links_add_target = $target; |
4617 $_links_add_target = $target; |
3799 * Callback to add a target attribute to all links in passed content. |
4623 * Callback to add a target attribute to all links in passed content. |
3800 * |
4624 * |
3801 * @since 2.7.0 |
4625 * @since 2.7.0 |
3802 * @access private |
4626 * @access private |
3803 * |
4627 * |
4628 * @global string $_links_add_target |
|
4629 * |
|
3804 * @param string $m The matched link. |
4630 * @param string $m The matched link. |
3805 * @return string The processed link. |
4631 * @return string The processed link. |
3806 */ |
4632 */ |
3807 function _links_add_target( $m ) { |
4633 function _links_add_target( $m ) { |
3808 global $_links_add_target; |
4634 global $_links_add_target; |
3833 * the `<script>` and `<style>` tags. E.g. `strip_tags( '<script>something</script>' )` |
4659 * the `<script>` and `<style>` tags. E.g. `strip_tags( '<script>something</script>' )` |
3834 * will return 'something'. wp_strip_all_tags will return '' |
4660 * will return 'something'. wp_strip_all_tags will return '' |
3835 * |
4661 * |
3836 * @since 2.9.0 |
4662 * @since 2.9.0 |
3837 * |
4663 * |
3838 * @param string $string String containing HTML tags |
4664 * @param string $string String containing HTML tags |
3839 * @param bool $remove_breaks optional Whether to remove left over line breaks and white space chars |
4665 * @param bool $remove_breaks Optional. Whether to remove left over line breaks and white space chars |
3840 * @return string The processed string. |
4666 * @return string The processed string. |
3841 */ |
4667 */ |
3842 function wp_strip_all_tags($string, $remove_breaks = false) { |
4668 function wp_strip_all_tags($string, $remove_breaks = false) { |
3843 $string = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $string ); |
4669 $string = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $string ); |
3844 $string = strip_tags($string); |
4670 $string = strip_tags($string); |
3848 |
4674 |
3849 return trim( $string ); |
4675 return trim( $string ); |
3850 } |
4676 } |
3851 |
4677 |
3852 /** |
4678 /** |
3853 * Sanitize a string from user input or from the db |
4679 * Sanitizes a string from user input or from the database. |
3854 * |
4680 * |
3855 * check for invalid UTF-8, |
4681 * - Checks for invalid UTF-8, |
3856 * Convert single < characters to entity, |
4682 * - Converts single `<` characters to entities |
3857 * strip all tags, |
4683 * - Strips all tags |
3858 * remove line breaks, tabs and extra white space, |
4684 * - Removes line breaks, tabs, and extra whitespace |
3859 * strip octets. |
4685 * - Strips octets |
3860 * |
4686 * |
3861 * @since 2.9.0 |
4687 * @since 2.9.0 |
3862 * |
4688 * |
3863 * @param string $str |
4689 * @see sanitize_textarea_field() |
3864 * @return string |
4690 * @see wp_check_invalid_utf8() |
3865 */ |
4691 * @see wp_strip_all_tags() |
3866 function sanitize_text_field($str) { |
4692 * |
4693 * @param string $str String to sanitize. |
|
4694 * @return string Sanitized string. |
|
4695 */ |
|
4696 function sanitize_text_field( $str ) { |
|
4697 $filtered = _sanitize_text_fields( $str, false ); |
|
4698 |
|
4699 /** |
|
4700 * Filters a sanitized text field string. |
|
4701 * |
|
4702 * @since 2.9.0 |
|
4703 * |
|
4704 * @param string $filtered The sanitized string. |
|
4705 * @param string $str The string prior to being sanitized. |
|
4706 */ |
|
4707 return apply_filters( 'sanitize_text_field', $filtered, $str ); |
|
4708 } |
|
4709 |
|
4710 /** |
|
4711 * Sanitizes a multiline string from user input or from the database. |
|
4712 * |
|
4713 * The function is like sanitize_text_field(), but preserves |
|
4714 * new lines (\n) and other whitespace, which are legitimate |
|
4715 * input in textarea elements. |
|
4716 * |
|
4717 * @see sanitize_text_field() |
|
4718 * |
|
4719 * @since 4.7.0 |
|
4720 * |
|
4721 * @param string $str String to sanitize. |
|
4722 * @return string Sanitized string. |
|
4723 */ |
|
4724 function sanitize_textarea_field( $str ) { |
|
4725 $filtered = _sanitize_text_fields( $str, true ); |
|
4726 |
|
4727 /** |
|
4728 * Filters a sanitized textarea field string. |
|
4729 * |
|
4730 * @since 4.7.0 |
|
4731 * |
|
4732 * @param string $filtered The sanitized string. |
|
4733 * @param string $str The string prior to being sanitized. |
|
4734 */ |
|
4735 return apply_filters( 'sanitize_textarea_field', $filtered, $str ); |
|
4736 } |
|
4737 |
|
4738 /** |
|
4739 * Internal helper function to sanitize a string from user input or from the db |
|
4740 * |
|
4741 * @since 4.7.0 |
|
4742 * @access private |
|
4743 * |
|
4744 * @param string $str String to sanitize. |
|
4745 * @param bool $keep_newlines optional Whether to keep newlines. Default: false. |
|
4746 * @return string Sanitized string. |
|
4747 */ |
|
4748 function _sanitize_text_fields( $str, $keep_newlines = false ) { |
|
3867 $filtered = wp_check_invalid_utf8( $str ); |
4749 $filtered = wp_check_invalid_utf8( $str ); |
3868 |
4750 |
3869 if ( strpos($filtered, '<') !== false ) { |
4751 if ( strpos($filtered, '<') !== false ) { |
3870 $filtered = wp_pre_kses_less_than( $filtered ); |
4752 $filtered = wp_pre_kses_less_than( $filtered ); |
3871 // This will strip extra whitespace for us. |
4753 // This will strip extra whitespace for us. |
3872 $filtered = wp_strip_all_tags( $filtered, true ); |
4754 $filtered = wp_strip_all_tags( $filtered, false ); |
3873 } else { |
4755 |
3874 $filtered = trim( preg_replace('/[\r\n\t ]+/', ' ', $filtered) ); |
4756 // Use html entities in a special case to make sure no later |
3875 } |
4757 // newline stripping stage could lead to a functional tag |
4758 $filtered = str_replace("<\n", "<\n", $filtered); |
|
4759 } |
|
4760 |
|
4761 if ( ! $keep_newlines ) { |
|
4762 $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered ); |
|
4763 } |
|
4764 $filtered = trim( $filtered ); |
|
3876 |
4765 |
3877 $found = false; |
4766 $found = false; |
3878 while ( preg_match('/%[a-f0-9]{2}/i', $filtered, $match) ) { |
4767 while ( preg_match('/%[a-f0-9]{2}/i', $filtered, $match) ) { |
3879 $filtered = str_replace($match[0], '', $filtered); |
4768 $filtered = str_replace($match[0], '', $filtered); |
3880 $found = true; |
4769 $found = true; |
3883 if ( $found ) { |
4772 if ( $found ) { |
3884 // Strip out the whitespace that may now exist after removing the octets. |
4773 // Strip out the whitespace that may now exist after removing the octets. |
3885 $filtered = trim( preg_replace('/ +/', ' ', $filtered) ); |
4774 $filtered = trim( preg_replace('/ +/', ' ', $filtered) ); |
3886 } |
4775 } |
3887 |
4776 |
3888 /** |
4777 return $filtered; |
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 ); |
|
3897 } |
4778 } |
3898 |
4779 |
3899 /** |
4780 /** |
3900 * i18n friendly version of basename() |
4781 * i18n friendly version of basename() |
3901 * |
4782 * |
3902 * @since 3.1.0 |
4783 * @since 3.1.0 |
3903 * |
4784 * |
3904 * @param string $path A path. |
4785 * @param string $path A path. |
3905 * @param string $suffix If the filename ends in suffix this will also be cut off. |
4786 * @param string $suffix If the filename ends in suffix this will also be cut off. |
3906 * @return string |
4787 * @return string |
3907 */ |
4788 */ |
3908 function wp_basename( $path, $suffix = '' ) { |
4789 function wp_basename( $path, $suffix = '' ) { |
3909 return urldecode( basename( str_replace( array( '%2F', '%5C' ), '/', urlencode( $path ) ), $suffix ) ); |
4790 return urldecode( basename( str_replace( array( '%2F', '%5C' ), '/', urlencode( $path ) ), $suffix ) ); |
3913 * Forever eliminate "Wordpress" from the planet (or at least the little bit we can influence). |
4794 * Forever eliminate "Wordpress" from the planet (or at least the little bit we can influence). |
3914 * |
4795 * |
3915 * Violating our coding standards for a good function name. |
4796 * Violating our coding standards for a good function name. |
3916 * |
4797 * |
3917 * @since 3.0.0 |
4798 * @since 3.0.0 |
4799 * |
|
4800 * @staticvar string|false $dblq |
|
4801 * |
|
4802 * @param string $text The text to be modified. |
|
4803 * @return string The modified text. |
|
3918 */ |
4804 */ |
3919 function capital_P_dangit( $text ) { |
4805 function capital_P_dangit( $text ) { |
3920 // Simple replacement for titles |
4806 // Simple replacement for titles |
3921 $current_filter = current_filter(); |
4807 $current_filter = current_filter(); |
3922 if ( 'the_title' === $current_filter || 'wp_title' === $current_filter ) |
4808 if ( 'the_title' === $current_filter || 'wp_title' === $current_filter ) |
3923 return str_replace( 'Wordpress', 'WordPress', $text ); |
4809 return str_replace( 'Wordpress', 'WordPress', $text ); |
3924 // Still here? Use the more judicious replacement |
4810 // Still here? Use the more judicious replacement |
3925 static $dblq = false; |
4811 static $dblq = false; |
3926 if ( false === $dblq ) |
4812 if ( false === $dblq ) { |
3927 $dblq = _x( '“', 'opening curly double quote' ); |
4813 $dblq = _x( '“', 'opening curly double quote' ); |
4814 } |
|
3928 return str_replace( |
4815 return str_replace( |
3929 array( ' Wordpress', '‘Wordpress', $dblq . 'Wordpress', '>Wordpress', '(Wordpress' ), |
4816 array( ' Wordpress', '‘Wordpress', $dblq . 'Wordpress', '>Wordpress', '(Wordpress' ), |
3930 array( ' WordPress', '‘WordPress', $dblq . 'WordPress', '>WordPress', '(WordPress' ), |
4817 array( ' WordPress', '‘WordPress', $dblq . 'WordPress', '>WordPress', '(WordPress' ), |
3931 $text ); |
4818 $text ); |
3932 |
|
3933 } |
4819 } |
3934 |
4820 |
3935 /** |
4821 /** |
3936 * Sanitize a mime type |
4822 * Sanitize a mime type |
3937 * |
4823 * |
3941 * @return string Sanitized mime type |
4827 * @return string Sanitized mime type |
3942 */ |
4828 */ |
3943 function sanitize_mime_type( $mime_type ) { |
4829 function sanitize_mime_type( $mime_type ) { |
3944 $sani_mime_type = preg_replace( '/[^-+*.a-zA-Z0-9\/]/', '', $mime_type ); |
4830 $sani_mime_type = preg_replace( '/[^-+*.a-zA-Z0-9\/]/', '', $mime_type ); |
3945 /** |
4831 /** |
3946 * Filter a mime type following sanitization. |
4832 * Filters a mime type following sanitization. |
3947 * |
4833 * |
3948 * @since 3.1.3 |
4834 * @since 3.1.3 |
3949 * |
4835 * |
3950 * @param string $sani_mime_type The sanitized mime type. |
4836 * @param string $sani_mime_type The sanitized mime type. |
3951 * @param string $mime_type The mime type prior to sanitization. |
4837 * @param string $mime_type The mime type prior to sanitization. |
3968 unset( $urls_to_ping[$k] ); |
4854 unset( $urls_to_ping[$k] ); |
3969 } |
4855 } |
3970 $urls_to_ping = array_map( 'esc_url_raw', $urls_to_ping ); |
4856 $urls_to_ping = array_map( 'esc_url_raw', $urls_to_ping ); |
3971 $urls_to_ping = implode( "\n", $urls_to_ping ); |
4857 $urls_to_ping = implode( "\n", $urls_to_ping ); |
3972 /** |
4858 /** |
3973 * Filter a list of trackback URLs following sanitization. |
4859 * Filters a list of trackback URLs following sanitization. |
3974 * |
4860 * |
3975 * The string returned here consists of a space or carriage return-delimited list |
4861 * The string returned here consists of a space or carriage return-delimited list |
3976 * of trackback URLs. |
4862 * of trackback URLs. |
3977 * |
4863 * |
3978 * @since 3.4.0 |
4864 * @since 3.4.0 |
4029 * Extract and return the first URL from passed content. |
4915 * Extract and return the first URL from passed content. |
4030 * |
4916 * |
4031 * @since 3.6.0 |
4917 * @since 3.6.0 |
4032 * |
4918 * |
4033 * @param string $content A string which might contain a URL. |
4919 * @param string $content A string which might contain a URL. |
4034 * @return string The found URL. |
4920 * @return string|false The found URL. |
4035 */ |
4921 */ |
4036 function get_url_in_content( $content ) { |
4922 function get_url_in_content( $content ) { |
4037 if ( empty( $content ) ) { |
4923 if ( empty( $content ) ) { |
4038 return false; |
4924 return false; |
4039 } |
4925 } |
4052 * This is designed to replace the PCRE \s sequence. In ticket #22692, that |
4938 * 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. |
4939 * sequence was found to be unreliable due to random inclusion of the A0 byte. |
4054 * |
4940 * |
4055 * @since 4.0.0 |
4941 * @since 4.0.0 |
4056 * |
4942 * |
4943 * @staticvar string $spaces |
|
4944 * |
|
4057 * @return string The spaces regexp. |
4945 * @return string The spaces regexp. |
4058 */ |
4946 */ |
4059 function wp_spaces_regexp() { |
4947 function wp_spaces_regexp() { |
4060 static $spaces; |
4948 static $spaces = ''; |
4061 |
4949 |
4062 if ( empty( $spaces ) ) { |
4950 if ( empty( $spaces ) ) { |
4063 /** |
4951 /** |
4064 * Filter the regexp for common whitespace characters. |
4952 * Filters the regexp for common whitespace characters. |
4065 * |
4953 * |
4066 * This string is substituted for the \s sequence as needed in regular |
4954 * This string is substituted for the \s sequence as needed in regular |
4067 * expressions. For websites not written in English, different characters |
4955 * expressions. For websites not written in English, different characters |
4068 * may represent whitespace. For websites not encoded in UTF-8, the 0xC2 0xA0 |
4956 * may represent whitespace. For websites not encoded in UTF-8, the 0xC2 0xA0 |
4069 * sequence may not be in use. |
4957 * sequence may not be in use. |
4080 |
4968 |
4081 /** |
4969 /** |
4082 * Print the important emoji-related styles. |
4970 * Print the important emoji-related styles. |
4083 * |
4971 * |
4084 * @since 4.2.0 |
4972 * @since 4.2.0 |
4973 * |
|
4974 * @staticvar bool $printed |
|
4085 */ |
4975 */ |
4086 function print_emoji_styles() { |
4976 function print_emoji_styles() { |
4087 static $printed = false; |
4977 static $printed = false; |
4088 |
4978 |
4089 if ( $printed ) { |
4979 if ( $printed ) { |
4107 } |
4997 } |
4108 </style> |
4998 </style> |
4109 <?php |
4999 <?php |
4110 } |
5000 } |
4111 |
5001 |
5002 /** |
|
5003 * Print the inline Emoji detection script if it is not already printed. |
|
5004 * |
|
5005 * @since 4.2.0 |
|
5006 * @staticvar bool $printed |
|
5007 */ |
|
4112 function print_emoji_detection_script() { |
5008 function print_emoji_detection_script() { |
4113 global $wp_version; |
|
4114 static $printed = false; |
5009 static $printed = false; |
4115 |
5010 |
4116 if ( $printed ) { |
5011 if ( $printed ) { |
4117 return; |
5012 return; |
4118 } |
5013 } |
4119 |
5014 |
4120 $printed = true; |
5015 $printed = true; |
4121 |
5016 |
5017 _print_emoji_detection_script(); |
|
5018 } |
|
5019 |
|
5020 /** |
|
5021 * Prints inline Emoji dection script |
|
5022 * |
|
5023 * @ignore |
|
5024 * @since 4.6.0 |
|
5025 * @access private |
|
5026 */ |
|
5027 function _print_emoji_detection_script() { |
|
4122 $settings = array( |
5028 $settings = array( |
4123 /** |
5029 /** |
4124 * Filter the URL where emoji images are hosted. |
5030 * Filters the URL where emoji png images are hosted. |
4125 * |
5031 * |
4126 * @since 4.2.0 |
5032 * @since 4.2.0 |
4127 * |
5033 * |
4128 * @param string The emoji base URL. |
5034 * @param string The emoji base URL for png images. |
4129 */ |
5035 */ |
4130 'baseUrl' => apply_filters( 'emoji_url', set_url_scheme( '//s.w.org/images/core/emoji/72x72/' ) ), |
5036 'baseUrl' => apply_filters( 'emoji_url', 'https://s.w.org/images/core/emoji/11/72x72/' ), |
4131 |
5037 |
4132 /** |
5038 /** |
4133 * Filter the extension of the emoji files. |
5039 * Filters the extension of the emoji png files. |
4134 * |
5040 * |
4135 * @since 4.2.0 |
5041 * @since 4.2.0 |
4136 * |
5042 * |
4137 * @param string The emoji extension. Default .png. |
5043 * @param string The emoji extension for png files. Default .png. |
4138 */ |
5044 */ |
4139 'ext' => apply_filters( 'emoji_ext', '.png' ), |
5045 'ext' => apply_filters( 'emoji_ext', '.png' ), |
5046 |
|
5047 /** |
|
5048 * Filters the URL where emoji SVG images are hosted. |
|
5049 * |
|
5050 * @since 4.6.0 |
|
5051 * |
|
5052 * @param string The emoji base URL for svg images. |
|
5053 */ |
|
5054 'svgUrl' => apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/11/svg/' ), |
|
5055 |
|
5056 /** |
|
5057 * Filters the extension of the emoji SVG files. |
|
5058 * |
|
5059 * @since 4.6.0 |
|
5060 * |
|
5061 * @param string The emoji extension for svg files. Default .svg. |
|
5062 */ |
|
5063 'svgExt' => apply_filters( 'emoji_svg_ext', '.svg' ), |
|
4140 ); |
5064 ); |
4141 |
5065 |
4142 $version = 'ver=' . $wp_version; |
5066 $version = 'ver=' . get_bloginfo( 'version' ); |
4143 |
5067 |
4144 if ( SCRIPT_DEBUG ) { |
5068 if ( SCRIPT_DEBUG ) { |
4145 $settings['source'] = array( |
5069 $settings['source'] = array( |
4146 /** This filter is documented in wp-includes/class.wp-scripts.php */ |
5070 /** 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' ), |
5071 'wpemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji.js?$version" ), 'wpemoji' ), |
4172 * and edit wp-emoji-loader.js directly. |
5096 * and edit wp-emoji-loader.js directly. |
4173 */ |
5097 */ |
4174 ?> |
5098 ?> |
4175 <script type="text/javascript"> |
5099 <script type="text/javascript"> |
4176 window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>; |
5100 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); |
5101 !function(a,b,c){function d(a,b){var c=String.fromCharCode;l.clearRect(0,0,k.width,k.height),l.fillText(c.apply(this,a),0,0);var d=k.toDataURL();l.clearRect(0,0,k.width,k.height),l.fillText(c.apply(this,b),0,0);var e=k.toDataURL();return d===e}function e(a){var b;if(!l||!l.fillText)return!1;switch(l.textBaseline="top",l.font="600 32px Arial",a){case"flag":return!(b=d([55356,56826,55356,56819],[55356,56826,8203,55356,56819]))&&(b=d([55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447],[55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447]),!b);case"emoji":return b=d([55358,56760,9792,65039],[55358,56760,8203,9792,65039]),!b}return!1}function f(a){var c=b.createElement("script");c.src=a,c.defer=c.type="text/javascript",b.getElementsByTagName("head")[0].appendChild(c)}var g,h,i,j,k=b.createElement("canvas"),l=k.getContext&&k.getContext("2d");for(j=Array("flag","emoji"),c.supports={everything:!0,everythingExceptFlag:!0},i=0;i<j.length;i++)c.supports[j[i]]=e(j[i]),c.supports.everything=c.supports.everything&&c.supports[j[i]],"flag"!==j[i]&&(c.supports.everythingExceptFlag=c.supports.everythingExceptFlag&&c.supports[j[i]]);c.supports.everythingExceptFlag=c.supports.everythingExceptFlag&&!c.supports.flag,c.DOMReady=!1,c.readyCallback=function(){c.DOMReady=!0},c.supports.everything||(h=function(){c.readyCallback()},b.addEventListener?(b.addEventListener("DOMContentLoaded",h,!1),a.addEventListener("load",h,!1)):(a.attachEvent("onload",h),b.attachEvent("onreadystatechange",function(){"complete"===b.readyState&&c.readyCallback()})),g=c.source||{},g.concatemoji?f(g.concatemoji):g.wpemoji&&g.twemoji&&(f(g.twemoji),f(g.wpemoji)))}(window,document,window._wpemojiSettings); |
4178 </script> |
5102 </script> |
4179 <?php |
5103 <?php |
4180 } |
5104 } |
4181 } |
5105 } |
4182 |
5106 |
4183 /** |
5107 /** |
4184 * Convert any 4 byte emoji in a string to their equivalent HTML entity. |
5108 * Convert emoji characters 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 * |
5109 * |
4189 * This allows us to store emoji in a DB using the utf8 character set. |
5110 * This allows us to store emoji in a DB using the utf8 character set. |
4190 * |
5111 * |
4191 * @since 4.2.0 |
5112 * @since 4.2.0 |
4192 * |
5113 * |
4193 * @param string $content The content to encode. |
5114 * @param string $content The content to encode. |
4194 * @return string The encoded content. |
5115 * @return string The encoded content. |
4195 */ |
5116 */ |
4196 function wp_encode_emoji( $content ) { |
5117 function wp_encode_emoji( $content ) { |
4197 if ( function_exists( 'mb_convert_encoding' ) ) { |
5118 $emoji = _wp_emoji_list( 'partials' ); |
4198 $regex = '/( |
5119 |
4199 \x23\xE2\x83\xA3 # Digits |
5120 foreach ( $emoji as $emojum ) { |
4200 [\x30-\x39]\xE2\x83\xA3 |
5121 if ( version_compare( phpversion(), '5.4', '<' ) ) { |
4201 | \xF0\x9F[\x85-\x88][\xA6-\xBF] # Enclosed characters |
5122 $emoji_char = html_entity_decode( $emojum, ENT_COMPAT, 'UTF-8' ); |
4202 | \xF0\x9F[\x8C-\x97][\x80-\xBF] # Misc |
5123 } else { |
4203 | \xF0\x9F\x98[\x80-\xBF] # Smilies |
5124 $emoji_char = html_entity_decode( $emojum ); |
4204 | \xF0\x9F\x99[\x80-\x8F] |
5125 } |
4205 | \xF0\x9F\x9A[\x80-\xBF] # Transport and map symbols |
5126 if ( false !== strpos( $content, $emoji_char ) ) { |
4206 )/x'; |
5127 $content = preg_replace( "/$emoji_char/", $emojum, $content ); |
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 } |
5128 } |
4225 } |
5129 } |
4226 |
5130 |
4227 return $content; |
5131 return $content; |
4228 } |
5132 } |
4234 * |
5138 * |
4235 * @param string $text The content to encode. |
5139 * @param string $text The content to encode. |
4236 * @return string The encoded content. |
5140 * @return string The encoded content. |
4237 */ |
5141 */ |
4238 function wp_staticize_emoji( $text ) { |
5142 function wp_staticize_emoji( $text ) { |
4239 $text = wp_encode_emoji( $text ); |
5143 if ( false === strpos( $text, '&#x' ) ) { |
5144 if ( ( function_exists( 'mb_check_encoding' ) && mb_check_encoding( $text, 'ASCII' ) ) || ! preg_match( '/[^\x00-\x7F]/', $text ) ) { |
|
5145 // The text doesn't contain anything that might be emoji, so we can return early. |
|
5146 return $text; |
|
5147 } else { |
|
5148 $encoded_text = wp_encode_emoji( $text ); |
|
5149 if ( $encoded_text === $text ) { |
|
5150 return $encoded_text; |
|
5151 } |
|
5152 |
|
5153 $text = $encoded_text; |
|
5154 } |
|
5155 } |
|
5156 |
|
5157 $emoji = _wp_emoji_list( 'entities' ); |
|
5158 |
|
5159 // Quickly narrow down the list of emoji that might be in the text and need replacing. |
|
5160 $possible_emoji = array(); |
|
5161 foreach( $emoji as $emojum ) { |
|
5162 if ( false !== strpos( $text, $emojum ) ) { |
|
5163 if ( version_compare( phpversion(), '5.4', '<' ) ) { |
|
5164 $possible_emoji[ $emojum ] = html_entity_decode( $emojum, ENT_COMPAT, 'UTF-8' ); |
|
5165 } else { |
|
5166 $possible_emoji[ $emojum ] = html_entity_decode( $emojum ); |
|
5167 } |
|
5168 } |
|
5169 } |
|
5170 |
|
5171 if ( ! $possible_emoji ) { |
|
5172 return $text; |
|
5173 } |
|
4240 |
5174 |
4241 /** This filter is documented in wp-includes/formatting.php */ |
5175 /** 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/' ) ); |
5176 $cdn_url = apply_filters( 'emoji_url', 'https://s.w.org/images/core/emoji/11/72x72/' ); |
4243 |
5177 |
4244 /** This filter is documented in wp-includes/formatting.php */ |
5178 /** This filter is documented in wp-includes/formatting.php */ |
4245 $ext = apply_filters( 'emoji_ext', '.png' ); |
5179 $ext = apply_filters( 'emoji_ext', '.png' ); |
4246 |
5180 |
4247 $output = ''; |
5181 $output = ''; |
4265 if ( '' == $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')>/', $content, $matches ) ) { |
5199 if ( '' == $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')>/', $content, $matches ) ) { |
4266 $ignore_block_element = $matches[1]; |
5200 $ignore_block_element = $matches[1]; |
4267 } |
5201 } |
4268 |
5202 |
4269 // If it's not a tag and not in ignore block. |
5203 // If it's not a tag and not in ignore block. |
4270 if ( '' == $ignore_block_element && strlen( $content ) > 0 && '<' != $content[0] ) { |
5204 if ( '' == $ignore_block_element && strlen( $content ) > 0 && '<' != $content[0] && false !== strpos( $content, '&#x' ) ) { |
4271 $matches = array(); |
5205 foreach ( $possible_emoji as $emojum => $emoji_char ) { |
4272 if ( preg_match_all( '/(DZ(e[6-9a-f]|f[0-9a-f]);){2}/', $content, $matches ) ) { |
5206 if ( false === strpos( $content, $emojum ) ) { |
4273 if ( ! empty( $matches[0] ) ) { |
5207 continue; |
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 } |
5208 } |
4283 } |
5209 |
4284 |
5210 $file = str_replace( ';&#x', '-', $emojum ); |
4285 // Loosely match the Emoji Unicode range. |
5211 $file = str_replace( array( '&#x', ';'), '', $file ); |
4286 $regex = '/(&#x[2-3][0-9a-f]{3};|[1-6][0-9a-f]{2};)/'; |
5212 |
4287 |
5213 $entity = sprintf( '<img src="%s" alt="%s" class="wp-smiley" style="height: 1em; max-height: 1em;" />', $cdn_url . $file . $ext, $emoji_char ); |
4288 $matches = array(); |
5214 |
4289 if ( preg_match_all( $regex, $content, $matches ) ) { |
5215 $content = str_replace( $emojum, $entity, $content ); |
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 } |
5216 } |
4299 } |
5217 } |
4300 |
5218 |
4301 // Did we exit ignore block. |
5219 // Did we exit ignore block. |
4302 if ( '' != $ignore_block_element && '</' . $ignore_block_element . '>' == $content ) { |
5220 if ( '' != $ignore_block_element && '</' . $ignore_block_element . '>' == $content ) { |
4303 $ignore_block_element = ''; |
5221 $ignore_block_element = ''; |
4304 } |
5222 } |
4305 |
5223 |
4306 $output .= $content; |
5224 $output .= $content; |
4307 } |
5225 } |
5226 |
|
5227 // Finally, remove any stray U+FE0F characters |
|
5228 $output = str_replace( '️', '', $output ); |
|
4308 |
5229 |
4309 return $output; |
5230 return $output; |
4310 } |
5231 } |
4311 |
5232 |
4312 /** |
5233 /** |
4373 $mail['message'] = wp_staticize_emoji( $mail['message'] ); |
5294 $mail['message'] = wp_staticize_emoji( $mail['message'] ); |
4374 } |
5295 } |
4375 |
5296 |
4376 return $mail; |
5297 return $mail; |
4377 } |
5298 } |
5299 |
|
5300 /** |
|
5301 * Returns a arrays of emoji data. |
|
5302 * |
|
5303 * These arrays automatically built from the regex in twemoji.js - if they need to be updated, |
|
5304 * you should update the regex there, then run the `grunt precommit:emoji` job. |
|
5305 * |
|
5306 * @since 4.9.0 |
|
5307 * @access private |
|
5308 * |
|
5309 * @param string $type Optional. Which array type to return. Accepts 'partials' or 'entities', default 'entities'. |
|
5310 * @return array An array to match all emoji that WordPress recognises. |
|
5311 */ |
|
5312 function _wp_emoji_list( $type = 'entities' ) { |
|
5313 // Do not remove the START/END comments - they're used to find where to insert the arrays. |
|
5314 |
|
5315 // START: emoji arrays |
|
5316 $entities = array('👩‍❤️‍💋‍👩','👩‍❤️‍💋‍👨','👨‍❤️‍💋‍👨','🏴󠁧󠁢󠁳󠁣󠁴󠁿','🏴󠁧󠁢󠁷󠁬󠁳󠁿','🏴󠁧󠁢󠁥󠁮󠁧󠁿','👩‍👩‍👧‍👦','👨‍👨‍👦‍👦','👩‍👩‍👦‍👦','👨‍👨‍👧‍👦','👨‍👨‍👧‍👧','👨‍👩‍👧‍👧','👨‍👩‍👦‍👦','👩‍👩‍👧‍👧','👨‍👩‍👧‍👦','👨‍❤️‍👨','👩‍❤️‍👨','👩‍❤️‍👩','👩‍👩‍👦','👩‍👦‍👦','👩‍👧‍👦','👩‍👧‍👧','👨‍👨‍👦','👨‍👩‍👧','👨‍👧‍👧','👨‍👧‍👦','👩‍👩‍👧','👨‍👩‍👦','👨‍👨‍👧','👨‍👦‍👦','🤵🏿‍♀️','🏋🏻‍♂️','🏋🏼‍♀️','🏋🏼‍♂️','🏋🏽‍♀️','🏋🏽‍♂️','🏋🏾‍♀️','🏋🏾‍♂️','🏋🏿‍♀️','🏋🏿‍♂️','🏌🏻‍♀️','🏌🏻‍♂️','🏌🏼‍♀️','🏌🏼‍♂️','🏌🏽‍♀️','🏌🏽‍♂️','🏌🏾‍♀️','🏌🏾‍♂️','🏌🏿‍♀️','🏌🏿‍♂️','💂🏻‍♀️','🏃🏼‍♀️','🏃🏼‍♂️','🧝🏿‍♂️','🧝🏿‍♀️','🧝🏾‍♂️','🧝🏾‍♀️','🧝🏽‍♂️','🧝🏽‍♀️','🧝🏼‍♂️','🧝🏼‍♀️','🧝🏻‍♂️','🧝🏻‍♀️','🧜🏿‍♂️','🧜🏿‍♀️','🧜🏾‍♂️','🧜🏾‍♀️','🧜🏽‍♂️','🧜🏽‍♀️','🧜🏼‍♂️','🧜🏼‍♀️','👨🏻‍⚕️','👨🏻‍⚖️','👨🏻‍✈️','🧜🏻‍♂️','🧜🏻‍♀️','🧛🏿‍♂️','🧛🏿‍♀️','🧛🏾‍♂️','🧛🏾‍♀️','🧛🏽‍♂️','🧛🏽‍♀️','🧛🏼‍♂️','🧛🏼‍♀️','🧛🏻‍♂️','🧛🏻‍♀️','🧚🏿‍♂️','🧚🏿‍♀️','🧚🏾‍♂️','🧚🏾‍♀️','🧚🏽‍♂️','👨🏼‍⚕️','👨🏼‍⚖️','👨🏼‍✈️','🧚🏽‍♀️','🧚🏼‍♂️','🧚🏼‍♀️','🧚🏻‍♂️','🧚🏻‍♀️','🧙🏿‍♂️','🧙🏿‍♀️','🧙🏾‍♂️','🧙🏾‍♀️','🧙🏽‍♂️','🧙🏽‍♀️','🧙🏼‍♂️','🧙🏼‍♀️','🧙🏻‍♂️','🧙🏻‍♀️','🧘🏿‍♂️','🧘🏿‍♀️','👨🏽‍⚕️','👨🏽‍⚖️','👨🏽‍✈️','🧘🏾‍♂️','🧘🏾‍♀️','🧘🏽‍♂️','🧘🏽‍♀️','🧘🏼‍♂️','🧘🏼‍♀️','🧘🏻‍♂️','🧘🏻‍♀️','🧗🏿‍♂️','🧗🏿‍♀️','🧗🏾‍♂️','🧗🏾‍♀️','🧗🏽‍♂️','🧗🏽‍♀️','🧗🏼‍♂️','🧗🏼‍♀️','🧗🏻‍♂️','👨🏾‍⚕️','👨🏾‍⚖️','👨🏾‍✈️','🧗🏻‍♀️','🧖🏿‍♂️','🧖🏿‍♀️','🧖🏾‍♂️','🧖🏾‍♀️','🧖🏽‍♂️','🧖🏽‍♀️','🧖🏼‍♂️','🧖🏼‍♀️','🧖🏻‍♂️','🧖🏻‍♀️','🦹🏿‍♂️','🦹🏿‍♀️','🦹🏾‍♂️','🦹🏾‍♀️','🦹🏽‍♂️','🦹🏽‍♀️','👨🏿‍⚕️','👨🏿‍⚖️','👨🏿‍✈️','🦹🏼‍♂️','🦹🏼‍♀️','🦹🏻‍♂️','🦹🏻‍♀️','🦸🏿‍♂️','🦸🏿‍♀️','🦸🏾‍♂️','🏃🏽‍♀️','🦸🏾‍♀️','🏃🏽‍♂️','🏃🏾‍♀️','🦸🏽‍♂️','🏃🏾‍♂️','🏃🏿‍♀️','🏃🏿‍♂️','🏄🏻‍♀️','🏄🏻‍♂️','🏄🏼‍♀️','🏄🏼‍♂️','🏄🏽‍♀️','🏄🏽‍♂️','🏄🏾‍♀️','🦸🏽‍♀️','🦸🏼‍♂️','🦸🏼‍♀️','🦸🏻‍♂️','🦸🏻‍♀️','🤾🏿‍♂️','🤾🏿‍♀️','🤾🏾‍♂️','🤾🏾‍♀️','🤾🏽‍♂️','🤾🏽‍♀️','🤾🏼‍♂️','🤾🏼‍♀️','🏄🏾‍♂️','🏄🏿‍♀️','🤾🏻‍♂️','🤾🏻‍♀️','🤽🏿‍♂️','🤽🏿‍♀️','🤽🏾‍♂️','🤽🏾‍♀️','🤽🏽‍♂️','🤽🏽‍♀️','🤽🏼‍♂️','🤽🏼‍♀️','🤽🏻‍♂️','🤽🏻‍♀️','🤹🏿‍♂️','🤹🏿‍♀️','🤹🏾‍♂️','🤹🏾‍♀️','🤹🏽‍♂️','👩🏻‍⚕️','👩🏻‍⚖️','👩🏻‍✈️','🤹🏽‍♀️','🤹🏼‍♂️','🤹🏼‍♀️','🤹🏻‍♂️','🤹🏻‍♀️','🤸🏿‍♂️','🤸🏿‍♀️','🤸🏾‍♂️','🤸🏾‍♀️','🤸🏽‍♂️','🤸🏽‍♀️','🤸🏼‍♂️','🤸🏼‍♀️','🤸🏻‍♂️','🤸🏻‍♀️','🤷🏿‍♂️','🤷🏿‍♀️','👩🏼‍⚕️','👩🏼‍⚖️','👩🏼‍✈️','🤷🏾‍♂️','🤷🏾‍♀️','🤷🏽‍♂️','🤷🏽‍♀️','🤷🏼‍♂️','🤷🏼‍♀️','🤷🏻‍♂️','🤷🏻‍♀️','🤵🏿‍♂️','🏃🏻‍♂️','🤵🏾‍♂️','🤵🏾‍♀️','🤵🏽‍♂️','🤵🏽‍♀️','🤵🏼‍♂️','🤵🏼‍♀️','🤵🏻‍♂️','👩🏽‍⚕️','👩🏽‍⚖️','👩🏽‍✈️','🤵🏻‍♀️','🤦🏿‍♂️','🤦🏿‍♀️','🤦🏾‍♂️','🤦🏾‍♀️','🤦🏽‍♂️','🤦🏽‍♀️','🤦🏼‍♂️','🤦🏼‍♀️','🤦🏻‍♂️','🤦🏻‍♀️','🚶🏿‍♂️','🚶🏿‍♀️','🚶🏾‍♂️','🚶🏾‍♀️','🚶🏽‍♂️','🚶🏽‍♀️','👩🏾‍⚕️','👩🏾‍⚖️','👩🏾‍✈️','🚶🏼‍♂️','🚶🏼‍♀️','🚶🏻‍♂️','🚶🏻‍♀️','🚵🏿‍♂️','🚵🏿‍♀️','🚵🏾‍♂️','🚵🏾‍♀️','🚵🏽‍♂️','🚵🏽‍♀️','🚵🏼‍♂️','🚵🏼‍♀️','🚵🏻‍♂️','🚵🏻‍♀️','🚴🏿‍♂️','🚴🏿‍♀️','🚴🏾‍♂️','👩🏿‍⚕️','👩🏿‍⚖️','👩🏿‍✈️','🚴🏾‍♀️','🚴🏽‍♂️','🚴🏽‍♀️','🚴🏼‍♂️','🚴🏼‍♀️','🚴🏻‍♂️','🚴🏻‍♀️','🏄🏿‍♂️','🚣🏿‍♂️','🏊🏻‍♀️','🏊🏻‍♂️','🚣🏿‍♀️','🏊🏼‍♀️','🏊🏼‍♂️','🏊🏽‍♀️','🏊🏽‍♂️','🏊🏾‍♀️','🚣🏾‍♂️','🚣🏾‍♀️','🚣🏽‍♂️','🚣🏽‍♀️','🚣🏼‍♂️','🚣🏼‍♀️','🚣🏻‍♂️','🚣🏻‍♀️','🙎🏿‍♂️','🙎🏿‍♀️','🙎🏾‍♂️','🙎🏾‍♀️','🙎🏽‍♂️','🏊🏾‍♂️','🏊🏿‍♀️','🏊🏿‍♂️','🏋🏻‍♀️','👮🏻‍♀️','👮🏻‍♂️','👮🏼‍♀️','👮🏼‍♂️','👮🏽‍♀️','👮🏽‍♂️','👮🏾‍♀️','👮🏾‍♂️','👮🏿‍♀️','👮🏿‍♂️','🙎🏽‍♀️','🙎🏼‍♂️','🙎🏼‍♀️','🙎🏻‍♂️','👱🏻‍♀️','👱🏻‍♂️','👱🏼‍♀️','👱🏼‍♂️','👱🏽‍♀️','👱🏽‍♂️','👱🏾‍♀️','👱🏾‍♂️','👱🏿‍♀️','👱🏿‍♂️','🙎🏻‍♀️','🙍🏿‍♂️','👳🏻‍♀️','👳🏻‍♂️','👳🏼‍♀️','👳🏼‍♂️','👳🏽‍♀️','👳🏽‍♂️','👳🏾‍♀️','👳🏾‍♂️','👳🏿‍♀️','👳🏿‍♂️','🙍🏿‍♀️','🙍🏾‍♂️','👷🏻‍♀️','👷🏻‍♂️','👷🏼‍♀️','👷🏼‍♂️','👷🏽‍♀️','👷🏽‍♂️','👷🏾‍♀️','👷🏾‍♂️','👷🏿‍♀️','👷🏿‍♂️','🙍🏾‍♀️','🙍🏽‍♂️','💁🏻‍♀️','💁🏻‍♂️','💁🏼‍♀️','💁🏼‍♂️','💁🏽‍♀️','💁🏽‍♂️','💁🏾‍♀️','💁🏾‍♂️','💁🏿‍♀️','💁🏿‍♂️','🙍🏽‍♀️','🙍🏼‍♂️','🏃🏻‍♀️','💂🏻‍♂️','💂🏼‍♀️','💂🏼‍♂️','💂🏽‍♀️','💂🏽‍♂️','💂🏾‍♀️','💂🏾‍♂️','💂🏿‍♀️','💂🏿‍♂️','🙍🏼‍♀️','🙍🏻‍♂️','💆🏻‍♀️','💆🏻‍♂️','💆🏼‍♀️','💆🏼‍♂️','💆🏽‍♀️','💆🏽‍♂️','💆🏾‍♀️','💆🏾‍♂️','💆🏿‍♀️','💆🏿‍♂️','🙍🏻‍♀️','🙋🏿‍♂️','💇🏻‍♀️','💇🏻‍♂️','💇🏼‍♀️','💇🏼‍♂️','💇🏽‍♀️','💇🏽‍♂️','💇🏾‍♀️','💇🏾‍♂️','💇🏿‍♀️','💇🏿‍♂️','🙋🏿‍♀️','🙋🏾‍♂️','🕴🏻‍♀️','🕴🏻‍♂️','🕴🏼‍♀️','🕴🏼‍♂️','🕴🏽‍♀️','🕴🏽‍♂️','🕴🏾‍♀️','🕴🏾‍♂️','🕴🏿‍♀️','🕴🏿‍♂️','🕵🏻‍♀️','🕵🏻‍♂️','🕵🏼‍♀️','🕵🏼‍♂️','🕵🏽‍♀️','🕵🏽‍♂️','🕵🏾‍♀️','🕵🏾‍♂️','🕵🏿‍♀️','🕵🏿‍♂️','🙅🏻‍♀️','🙅🏻‍♂️','🙅🏼‍♀️','🙅🏼‍♂️','🙅🏽‍♀️','🙅🏽‍♂️','🙅🏾‍♀️','🙅🏾‍♂️','🙅🏿‍♀️','🙅🏿‍♂️','🙋🏾‍♀️','🙋🏽‍♂️','🙆🏻‍♀️','🙆🏻‍♂️','🙆🏼‍♀️','🙆🏼‍♂️','🙆🏽‍♀️','🙆🏽‍♂️','🙆🏾‍♀️','🙆🏾‍♂️','🙆🏿‍♀️','🙆🏿‍♂️','🙋🏽‍♀️','🙋🏼‍♂️','🙇🏻‍♀️','🙇🏻‍♂️','🙇🏼‍♀️','🙇🏼‍♂️','🙇🏽‍♀️','🙇🏽‍♂️','🙇🏾‍♀️','🙇🏾‍♂️','🙇🏿‍♀️','🙇🏿‍♂️','🙋🏼‍♀️','🙋🏻‍♂️','🙋🏻‍♀️','🕴️‍♀️','🕴️‍♂️','🏋️‍♀️','🏋️‍♂️','⛹🏾‍♀️','🏌️‍♀️','🏌️‍♂️','⛹🏻‍♂️','⛹🏻‍♀️','⛹🏾‍♂️','⛹🏿‍♀️','⛹🏿‍♂️','🕵️‍♀️','🕵️‍♂️','⛹🏽‍♀️','⛹🏽‍♂️','⛹🏼‍♀️','⛹🏼‍♂️','⛹️‍♀️','⛹️‍♂️','👩🏻‍🎨','👨🏻‍🌾','👨🏻‍🍳','👨🏻‍🎓','👨🏻‍🎤','👨🏻‍🎨','👨🏻‍🏫','👨🏻‍🏭','👨🏻‍💻','👨🏻‍💼','👨🏻‍🔧','👨🏻‍🔬','👨🏻‍🚀','👨🏻‍🚒','👨🏻‍🦰','👨🏻‍🦱','👨🏻‍🦲','👨🏻‍🦳','👨🏼‍🌾','👨🏼‍🍳','👨🏼‍🎓','👨🏼‍🎤','👨🏼‍🎨','👨🏼‍🏫','👨🏼‍🏭','👨🏼‍💻','👨🏼‍💼','👨🏼‍🔧','👨🏼‍🔬','👨🏼‍🚀','👨🏼‍🚒','👨🏼‍🦰','👨🏼‍🦱','👨🏼‍🦲','👨🏼‍🦳','👨🏽‍🌾','👨🏽‍🍳','👨🏽‍🎓','👨🏽‍🎤','👨🏽‍🎨','👨🏽‍🏫','👨🏽‍🏭','👨🏽‍💻','👨🏽‍💼','👨🏽‍🔧','👨🏽‍🔬','👨🏽‍🚀','👨🏽‍🚒','👨🏽‍🦰','👨🏽‍🦱','👨🏽‍🦲','👩🏿‍🦳','👩🏿‍🦲','👩🏿‍🦱','👨🏽‍🦳','👨🏾‍🌾','👩🏿‍🦰','👩🏿‍🚒','👩🏿‍🚀','👩🏿‍🔬','👩🏿‍🔧','👩🏿‍💼','👩🏿‍💻','👩🏿‍🏭','👩🏿‍🏫','👩🏿‍🎨','👨🏾‍🍳','👨🏾‍🎓','👩🏿‍🎤','👩🏿‍🎓','👩🏿‍🍳','👩🏿‍🌾','👩🏾‍🦳','👩🏾‍🦲','👩🏾‍🦱','👩🏾‍🦰','👩🏾‍🚒','👩🏾‍🚀','👨🏾‍🎤','👨🏾‍🎨','👩🏾‍🔬','👩🏾‍🔧','👩🏾‍💼','👩🏾‍💻','👩🏾‍🏭','👩🏾‍🏫','👩🏾‍🎨','👩🏾‍🎤','👩🏾‍🎓','👩🏾‍🍳','👨🏾‍🏫','👨🏾‍🏭','👩🏾‍🌾','👩🏽‍🦳','👩🏽‍🦲','👩🏽‍🦱','👩🏽‍🦰','👩🏽‍🚒','👩🏽‍🚀','👩🏽‍🔬','👩🏽‍🔧','👩🏽‍💼','👨🏾‍💻','👨🏾‍💼','👩🏽‍💻','👩🏽‍🏭','👩🏽‍🏫','👩🏽‍🎨','👩🏽‍🎤','👩🏽‍🎓','👩🏽‍🍳','👩🏽‍🌾','👩🏼‍🦳','👩🏼‍🦲','👨🏾‍🔧','👨🏾‍🔬','👩🏼‍🦱','👩🏼‍🦰','👩🏼‍🚒','👩🏼‍🚀','👩🏼‍🔬','👩🏼‍🔧','👩🏼‍💼','👩🏼‍💻','👩🏼‍🏭','👩🏼‍🏫','👨🏾‍🚀','👨🏾‍🚒','👩🏼‍🎨','👩🏼‍🎤','👩🏼‍🎓','👩🏼‍🍳','👩🏼‍🌾','👩🏻‍🦳','👩🏻‍🦲','👩🏻‍🦱','👩🏻‍🦰','👩🏻‍🚒','👨🏾‍🦰','👨🏾‍🦱','👨🏾‍🦲','👨🏾‍🦳','👩🏻‍🚀','👩🏻‍🔬','👩🏻‍🔧','👩🏻‍💼','👩🏻‍💻','👩🏻‍🏭','👩🏻‍🏫','👨🏿‍🌾','👩🏻‍🎤','👩🏻‍🎓','👨🏿‍🍳','👨🏿‍🎓','👩🏻‍🍳','👩🏻‍🌾','👨🏿‍🎤','👨🏿‍🎨','👨🏿‍🏫','👨🏿‍🏭','👨🏿‍💻','👨🏿‍💼','👨🏿‍🔧','👨🏿‍🔬','👨🏿‍🚀','👨🏿‍🚒','👨🏿‍🦰','👨🏿‍🦱','👨🏿‍🦲','👨🏿‍🦳','🏳️‍🌈','👩‍⚖️','🦸‍♂️','🤾‍♂️','🤾‍♀️','🦹‍♀️','🦹‍♂️','👨‍⚕️','👨‍⚖️','👨‍✈️','🤽‍♂️','🤽‍♀️','🧖‍♀️','🧖‍♂️','🙇‍♀️','🤼‍♂️','🤼‍♀️','🤹‍♂️','🤹‍♀️','🤸‍♂️','🤸‍♀️','🤷‍♂️','🤷‍♀️','🤵‍♂️','🧗‍♀️','🧗‍♂️','🤵‍♀️','🤦‍♂️','🤦‍♀️','🚶‍♂️','🚶‍♀️','🚵‍♂️','🚵‍♀️','🚴‍♂️','🚴‍♀️','🧘‍♀️','🧘‍♂️','🚣‍♂️','🚣‍♀️','🧙‍♀️','🧙‍♂️','🙎‍♂️','🙎‍♀️','🧚‍♀️','🧚‍♂️','👩‍⚕️','🦸‍♀️','👩‍✈️','👮‍♀️','👮‍♂️','👯‍♀️','👯‍♂️','👱‍♀️','🧛‍♀️','🧛‍♂️','🙍‍♂️','🙍‍♀️','👱‍♂️','👳‍♀️','👳‍♂️','👷‍♀️','👷‍♂️','💁‍♀️','💁‍♂️','💂‍♀️','🧜‍♀️','🧜‍♂️','💂‍♂️','💆‍♀️','🙋‍♂️','🙋‍♀️','💆‍♂️','💇‍♀️','💇‍♂️','🙅‍♀️','🙅‍♂️','🧝‍♀️','🧝‍♂️','🧞‍♀️','🧞‍♂️','🧟‍♀️','🧟‍♂️','🏴‍☠️','🙇‍♂️','🙆‍♀️','🙆‍♂️','🏊‍♂️','🏊‍♀️','🏄‍♂️','🏄‍♀️','🏃‍♂️','🏃‍♀️','👨‍🎨','👩‍🍳','👩‍🎓','👩‍🎤','👩‍🎨','👩‍🏫','👩‍🏭','👨‍💻','👨‍🚒','👩‍👦','👨‍👧','👨‍🦰','👨‍🦱','👩‍💻','👩‍💼','👩‍🔧','👩‍🔬','👩‍🚀','👩‍🚒','👩‍🦰','👩‍🦱','👁‍🗨','👨‍🦲','👨‍🦳','👨‍👦','👨‍🎤','👩‍🦲','👩‍🦳','👨‍🎓','👨‍🍳','👨‍🌾','👨‍💼','👨‍🔧','👨‍🔬','👨‍🚀','👨‍🏭','👩‍🌾','👨‍🏫','👩‍👧','👆🏿','👇🏻','👷🏼','👇🏼','👇🏽','👷🏽','👇🏾','👇🏿','👷🏾','👈🏻','👈🏼','👷🏿','👈🏽','👈🏾','👸🏻','👸🏼','👸🏽','👸🏾','👸🏿','👼🏻','👼🏼','👼🏽','👼🏾','👼🏿','👈🏿','👉🏻','💁🏻','👉🏼','👉🏽','💁🏼','👉🏾','👉🏿','💁🏽','👊🏻','👊🏼','💁🏾','👊🏽','👊🏾','💁🏿','👊🏿','👋🏻','👋🏼','👋🏽','💂🏻','👋🏾','👋🏿','💂🏼','👌🏻','👌🏼','💂🏽','👌🏽','👌🏾','💂🏾','👌🏿','👍🏻','💂🏿','👍🏼','👍🏽','💃🏻','💃🏼','💃🏽','💃🏾','💃🏿','💅🏻','💅🏼','💅🏽','💅🏾','💅🏿','👍🏾','👍🏿','💆🏻','👎🏻','👎🏼','💆🏼','👎🏽','👎🏾','💆🏽','👎🏿','👏🏻','💆🏾','👏🏼','👏🏽','💆🏿','👏🏾','👏🏿','👐🏻','👐🏼','💇🏻','👐🏽','👐🏾','💇🏼','👐🏿','👦🏻','💇🏽','👦🏼','👦🏽','💇🏾','👦🏾','👦🏿','💇🏿','👧🏻','👧🏼','💪🏻','💪🏼','💪🏽','💪🏾','💪🏿','👧🏽','👧🏾','🕴🏻','👧🏿','🇪🇪','🕴🏼','🇪🇬','🇪🇭','🕴🏽','🇪🇷','🇪🇸','🕴🏾','🇪🇹','🇪🇺','🕴🏿','🇫🇮','🇫🇯','🇫🇰','🇫🇲','🕵🏻','🇫🇴','🇫🇷','🕵🏼','🇬🇦','🇬🇧','🕵🏽','🇬🇩','🇬🇪','🕵🏾','🇬🇫','🇬🇬','🕵🏿','🇬🇭','👨🏻','🕺🏻','🕺🏼','🕺🏽','🕺🏾','🕺🏿','🖐🏻','🖐🏼','🖐🏽','🖐🏾','🖐🏿','🖕🏻','🖕🏼','🖕🏽','🖕🏾','🖕🏿','🖖🏻','🖖🏼','🖖🏽','🖖🏾','🖖🏿','🇬🇮','🇬🇱','🙅🏻','🇬🇲','🇬🇳','🙅🏼','🇬🇵','🇬🇶','🙅🏽','🇬🇷','🇬🇸','🙅🏾','🇬🇹','🇬🇺','🙅🏿','🇬🇼','🇬🇾','🇭🇰','🇭🇲','🙆🏻','🇭🇳','🇭🇷','🙆🏼','🇭🇹','🇭🇺','🙆🏽','🇮🇨','🇮🇩','🙆🏾','👨🏼','🇮🇪','🙆🏿','🇮🇱','🇮🇲','🇮🇳','🇮🇴','🙇🏻','🇮🇶','🇮🇷','🙇🏼','🇮🇸','🇮🇹','🙇🏽','🇯🇪','🇯🇲','🙇🏾','🇯🇴','🇯🇵','🙇🏿','🇰🇪','🇰🇬','🇰🇭','🇰🇮','🙋🏻','🇰🇲','🇰🇳','🙋🏼','🇰🇵','👨🏽','🙋🏽','🇰🇷','🇰🇼','🙋🏾','🇰🇾','🇰🇿','🙋🏿','🇱🇦','🇱🇧','🙌🏻','🙌🏼','🙌🏽','🙌🏾','🙌🏿','🇱🇨','🇱🇮','🙍🏻','🇱🇰','🇱🇷','🙍🏼','🇱🇸','🇱🇹','🙍🏽','🇱🇺','🇱🇻','🙍🏾','🇱🇾','🇲🇦','🙍🏿','🇲🇨','🇲🇩','🇲🇪','🇲🇫','🙎🏻','👨🏾','🇲🇬','🙎🏼','🇲🇭','🇲🇰','🙎🏽','🇲🇱','🇲🇲','🙎🏾','🇲🇳','🇲🇴','🙎🏿','🇲🇵','🇲🇶','🙏🏻','🙏🏼','🙏🏽','🙏🏾','🙏🏿','🇲🇷','🇲🇸','🚣🏻','🇲🇹','🇲🇺','🚣🏼','🇲🇻','🇲🇼','🚣🏽','🇲🇽','🇲🇾','🚣🏾','🇲🇿','🇳🇦','🚣🏿','🇳🇨','👨🏿','🇳🇪','🇳🇫','🚴🏻','🇳🇬','🇳🇮','🚴🏼','🇳🇱','🇳🇴','🚴🏽','🇳🇵','🇳🇷','🚴🏾','🇳🇺','🇳🇿','🚴🏿','🇴🇲','🇵🇦','🇵🇪','🇵🇫','🚵🏻','🇵🇬','🇵🇭','🚵🏼','🇵🇰','🇵🇱','🚵🏽','🇵🇲','🇵🇳','🚵🏾','🇵🇷','🇵🇸','🚵🏿','🇵🇹','🇵🇼','🇵🇾','🇶🇦','🚶🏻','🇷🇪','🇷🇴','🚶🏼','🇷🇸','🇷🇺','🚶🏽','🇷🇼','🇸🇦','🚶🏾','🇸🇧','🇸🇨','🚶🏿','🇸🇩','🇸🇪','🛀🏻','🛀🏼','🛀🏽','🛀🏾','🛀🏿','🛌🏻','🛌🏼','🛌🏽','🛌🏾','🛌🏿','🤘🏻','🤘🏼','🤘🏽','🤘🏾','🤘🏿','🤙🏻','🤙🏼','🤙🏽','🤙🏾','🤙🏿','🤚🏻','🤚🏼','🤚🏽','🤚🏾','🤚🏿','🤛🏻','🤛🏼','🤛🏽','🤛🏾','🤛🏿','🤜🏻','🤜🏼','🤜🏽','🤜🏾','🤜🏿','🤞🏻','🤞🏼','🤞🏽','🤞🏾','🤞🏿','🤟🏻','🤟🏼','🤟🏽','🤟🏾','🤟🏿','🇸🇬','🇸🇭','🤦🏻','🇸🇮','🇸🇯','🤦🏼','🇸🇰','🇦🇩','🤦🏽','🇸🇲','🇸🇳','🤦🏾','🇸🇴','🇸🇷','🤦🏿','🇸🇸','🇸🇹','🤰🏻','🤰🏼','🤰🏽','🤰🏾','🤰🏿','🤱🏻','🤱🏼','🤱🏽','🤱🏾','🤱🏿','🤲🏻','🤲🏼','🤲🏽','🤲🏾','🤲🏿','🤳🏻','🤳🏼','🤳🏽','🤳🏾','🤳🏿','🤴🏻','🤴🏼','🤴🏽','🤴🏾','🤴🏿','🇸🇻','🇸🇽','🤵🏻','🇸🇾','🇸🇿','🤵🏼','🇹🇦','🇹🇨','🤵🏽','🇹🇩','🇹🇫','🤵🏾','🇹🇬','👩🏻','🤵🏿','🇹🇭','🇹🇯','🤶🏻','🤶🏼','🤶🏽','🤶🏾','🤶🏿','🇹🇰','🇹🇱','🤷🏻','🇹🇲','🇹🇳','🤷🏼','🇹🇴','🇹🇷','🤷🏽','🇹🇹','🇹🇻','🤷🏾','🇹🇼','🇹🇿','🤷🏿','🇺🇦','🇺🇬','🇺🇲','🇺🇳','🤸🏻','🇺🇸','🇺🇾','🤸🏼','🇺🇿','🇻🇦','🤸🏽','👩🏼','🇻🇨','🤸🏾','🇻🇪','🇻🇬','🤸🏿','🇻🇮','🇻🇳','🇻🇺','🇼🇫','🤹🏻','🇼🇸','🇽🇰','🤹🏼','🇾🇪','🇾🇹','🤹🏽','🇿🇦','🇿🇲','🤹🏾','🇿🇼','🎅🏻','🤹🏿','🎅🏼','🎅🏽','🎅🏾','🎅🏿','🏂🏻','👩🏽','🤽🏻','🏂🏼','🏂🏽','🤽🏼','🏂🏾','🏂🏿','🤽🏽','🇦🇨','🇦🇪','🤽🏾','🏃🏻','🇦🇫','🤽🏿','🇦🇬','🏃🏼','🇦🇮','🇦🇱','🤾🏻','🏃🏽','🇦🇲','🤾🏼','🇦🇴','🏃🏾','🤾🏽','🇦🇶','🇦🇷','🤾🏾','🏃🏿','🇦🇸','🤾🏿','👩🏾','🇦🇹','🦵🏻','🦵🏼','🦵🏽','🦵🏾','🦵🏿','🦶🏻','🦶🏼','🦶🏽','🦶🏾','🦶🏿','🇦🇺','🇦🇼','🦸🏻','🏄🏻','🇦🇽','🦸🏼','🇦🇿','🏄🏼','🦸🏽','🇧🇦','🇧🇧','🦸🏾','🏄🏽','🇧🇩','🦸🏿','🇧🇪','🏄🏾','🇧🇫','🇧🇬','🦹🏻','🏄🏿','🇧🇭','🦹🏼','🇧🇮','🏇🏻','🦹🏽','🏇🏼','👩🏿','🦹🏾','🏇🏽','🏇🏾','🦹🏿','🏇🏿','🇧🇯','🧑🏻','🧑🏼','🧑🏽','🧑🏾','🧑🏿','🧒🏻','🧒🏼','🧒🏽','🧒🏾','🧒🏿','🧓🏻','🧓🏼','🧓🏽','🧓🏾','🧓🏿','🧔🏻','🧔🏼','🧔🏽','🧔🏾','🧔🏿','🧕🏻','🧕🏼','🧕🏽','🧕🏾','🧕🏿','🇧🇱','🏊🏻','🧖🏻','🇧🇲','🇧🇳','🧖🏼','🏊🏼','🇧🇴','🧖🏽','🇧🇶','🏊🏽','🧖🏾','🇧🇷','🇧🇸','🧖🏿','🏊🏾','🇧🇹','🇧🇻','🏊🏿','🧗🏻','🇧🇼','🇧🇾','🧗🏼','🇧🇿','🇨🇦','🧗🏽','🏋🏻','🇨🇨','🧗🏾','🇨🇩','🏋🏼','🧗🏿','🇨🇫','🇨🇬','🏋🏽','🇨🇭','🧘🏻','🇨🇮','🏋🏾','🧘🏼','🇨🇰','🇨🇱','🧘🏽','🏋🏿','🇨🇲','🧘🏾','👮🏻','🇨🇳','🧘🏿','🇨🇴','👮🏼','🇨🇵','🏌🏻','🧙🏻','👮🏽','🇨🇷','🧙🏼','🇨🇺','👮🏾','🧙🏽','🏌🏼','🇨🇻','🧙🏾','👮🏿','🇨🇼','🧙🏿','🏌🏽','🇨🇽','🇨🇾','👰🏻','🧚🏻','👰🏼','👰🏽','🧚🏼','👰🏾','👰🏿','🧚🏽','🏌🏾','🇨🇿','🧚🏾','👱🏻','🇩🇪','🧚🏿','🏌🏿','👱🏼','🇩🇬','🇩🇯','🧛🏻','👱🏽','🇩🇰','🧛🏼','🇩🇲','👱🏾','🧛🏽','🇩🇴','🇩🇿','🧛🏾','👱🏿','🇪🇦','🧛🏿','🇪🇨','👲🏻','👲🏼','👲🏽','🧜🏻','👲🏾','👲🏿','🧜🏼','👂🏻','👂🏼','🧜🏽','👳🏻','👂🏽','🧜🏾','👂🏾','👳🏼','🧜🏿','👂🏿','👃🏻','👳🏽','👃🏼','🧝🏻','👃🏽','👳🏾','🧝🏼','👃🏾','👃🏿','🧝🏽','👳🏿','👆🏻','🧝🏾','👆🏼','👴🏻','🧝🏿','👴🏼','👴🏽','👴🏾','👴🏿','👵🏻','👵🏼','👵🏽','👵🏾','👵🏿','👶🏻','👶🏼','👶🏽','👶🏾','👶🏿','👆🏽','👆🏾','👷🏻','🇸🇱','✍🏿','⛹🏻','✍🏾','✍🏽','✍🏼','✍🏻','✌🏿','✌🏾','✌🏽','✌🏼','✌🏻','✋🏿','✋🏾','✋🏽','✋🏼','✋🏻','✊🏿','✊🏾','✊🏽','✊🏼','✊🏻','⛷🏽','⛷🏾','⛹🏿','☝🏿','☝🏾','⛹🏾','☝🏽','☝🏼','⛹🏽','☝🏻','⛷🏿','⛹🏼','⛷🏻','⛷🏼','4⃣','#⃣','0⃣','1⃣','2⃣','3⃣','*⃣','5⃣','6⃣','7⃣','8⃣','9⃣','🃏','🕺','🖇','🖊','🖋','🖌','🖍','🀄','🇾','🇦','🅰','🅱','🖐','🇿','🈁','🈂','🏄','🏅','🖕','🏆','🈚','🈯','🈲','🈳','🖖','🖤','🖥','🖨','🖱','🖲','🖼','🗂','🗃','🗄','🗑','🗒','🗓','🗜','🗝','🗞','🗡','🗣','🗨','🗯','🗳','🗺','🗻','🗼','🗽','🗾','🗿','😀','😁','😂','😃','😄','😅','😆','😇','😈','😉','😊','😋','😌','😍','😎','😏','😐','😑','😒','😓','😔','😕','😖','😗','😘','😙','😚','😛','😜','😝','😞','😟','😠','😡','😢','😣','😤','😥','😦','😧','😨','😩','😪','😫','😬','😭','😮','😯','😰','😱','😲','😳','😴','😵','😶','😷','😸','😹','😺','😻','😼','😽','😾','😿','🙀','🙁','🙂','🙃','🙄','🈴','🏇','🏈','🏉','🈵','🈶','🈷','🈸','🈹','🈺','🉐','🉑','🌀','🌁','🌂','🌃','🌄','🙅','🌅','🌆','🌇','🌈','🏊','🌉','🌊','🌋','🌌','👨','🌍','🌎','🌏','🌐','🌑','🌒','🌓','🙆','🌔','🌕','🌖','🌗','🌘','🌙','🏋','🌚','🌛','🌜','🌝','🌞','🌟','🌠','🌡','🌤','🌥','🙇','🙈','🙉','🙊','🌦','🌧','🌨','🌩','🌪','🌫','🌬','🏌','🏍','🏎','🏏','🏐','🏑','🏒','🏓','🏔','🏕','🙋','🏖','🏗','🏘','🏙','🏚','🙌','🏛','🏜','🏝','🏞','🏟','🏠','🏡','🏢','🏣','🏤','🏥','🏦','🏧','🏨','🏩','🏪','🏫','🙍','🏬','🏭','🏮','🏯','🏰','🌭','🏳','🌮','🌯','🌰','🌱','🏴','🏵','🏷','🏸','🏹','🏺','🙎','🏻','🏼','🏽','🏾','🏿','🙏','🚀','🚁','🚂','🚃','🚄','🚅','🚆','🚇','🚈','🚉','🚊','🚋','🚌','🚍','🚎','🚏','🚐','🚑','🚒','🚓','🚔','🚕','🚖','🚗','🚘','🚙','🚚','🚛','🚜','🚝','🚞','🚟','🚠','🚡','🚢','🐀','🐁','🐂','🐃','🐄','🐅','🐆','🐇','🐈','🐉','🐊','🐋','🐌','🐍','🐎','🐏','🐐','🚣','🚤','🚥','🚦','🚧','🚨','🚩','🚪','🚫','🚬','🚭','🚮','🚯','🚰','🚱','🚲','🚳','🐑','🐒','🐓','🐔','🐕','🐖','🐗','🐘','🐙','🐚','🐛','🐜','🐝','🐞','🐟','🐠','🐡','🚴','🐢','🐣','🐤','🐥','🐦','🐧','🐨','🐩','🐪','🐫','🐬','🐭','🐮','🐯','🐰','🐱','🐲','🚵','🐳','🐴','🐵','👩','👪','👫','👬','👭','🐶','🐷','🐸','🐹','🐺','🐻','🐼','🐽','🐾','🚶','🚷','🚸','🚹','🚺','🚻','🚼','🚽','🚾','🚿','🐿','👀','🌲','👁','🌳','🛀','🛁','🛂','🛃','🛄','🛅','🛋','🌴','🌵','🌶','👮','🌷','🛌','🛍','🛎','🛏','🛐','🛑','🛒','🛠','🛡','🛢','🛣','🛤','🛥','🛩','🛫','🛬','🛰','🛳','🛴','🛵','🛶','🛷','🛸','🛹','🤐','🤑','🤒','🤓','🤔','🤕','🤖','🤗','👂','👯','🌸','🌹','🌺','🤘','🌻','🌼','👰','👃','👄','🤙','👅','🌽','🌾','🌿','🍀','🤚','🍁','👆','🍂','🍃','🍄','🤛','🍅','🍆','👇','🍇','🍈','🤜','🤝','👱','🍉','🍊','🍋','👈','🤞','🍌','👲','🍍','🍎','🍏','🤟','🤠','🤡','🤢','🤣','🤤','🤥','🍐','👉','🍑','🍒','🍓','🍔','🍕','👊','🍖','🍗','🍘','🍙','🍚','👋','👳','🍛','🍜','🤦','🤧','🤨','🤩','🤪','🤫','🤬','🤭','🤮','🤯','🍝','🍞','🍟','👴','👌','🤰','🍠','🍡','🍢','🍣','👵','🤱','🍤','👍','🍥','🍦','🍧','🤲','👶','🍨','🍩','👎','🍪','🤳','🍫','🍬','🍭','🍮','👏','🤴','🍯','🍰','🍱','🍲','🍳','👐','👑','👒','👷','👓','👔','👕','👖','👗','👸','👹','👺','🤵','👻','👘','👙','👚','👛','🤶','👜','👼','👽','👾','👿','💀','👝','👞','👟','👠','👡','👢','👣','👤','👥','🍴','🍵','🤷','🍶','🍷','🍸','👦','🍹','🍺','💁','🍻','🍼','🍽','👧','🍾','🍿','🎀','🎁','🎂','🎃','🤸','🎄','🇵','🅾','🇶','🇲','🅿','🎅','💂','🎆','🎇','🎈','🎉','🎊','💃','💄','🎋','🎌','🤹','🤺','🎍','🎎','🤼','🎏','💅','🎐','🎑','🎒','🎓','🎖','🎗','🎙','🎚','🎛','🎞','🎟','🎠','🎡','🎢','🎣','🤽','🎤','🎥','💆','🎦','🎧','🎨','🎩','🎪','🎫','🎬','🎭','🎮','🎯','🎰','🎱','🎲','🎳','🤾','🥀','🥁','🥂','🥃','🥄','🥅','🥇','🥈','🥉','🥊','🥋','🥌','🥍','🥎','🥏','🥐','🥑','🥒','🥓','🥔','🥕','🥖','🥗','🥘','🥙','🥚','🥛','🥜','🥝','🥞','🥟','🥠','🥡','🥢','🥣','🥤','🥥','🥦','🥧','🥨','🥩','🥪','🥫','🥬','🥭','🥮','🥯','🥰','🥳','🥴','🥵','🥶','🥺','🥼','🥽','🥾','🥿','🦀','🦁','🦂','🦃','🦄','🦅','🦆','🦇','🦈','🦉','🦊','🦋','🦌','🦍','🦎','🦏','🦐','🦑','🦒','🦓','🦔','🦕','🦖','🦗','🦘','🦙','🦚','🦛','🦜','🦝','🦞','🦟','🦠','🦡','🦢','🦴','🎴','🎵','🎶','💇','💈','🦵','💉','💊','💋','💌','💍','🦶','🦷','💎','💏','💐','💑','💒','💓','💔','💕','💖','💗','💘','💙','💚','💛','💜','💝','💞','🦸','💟','💠','💡','💢','💣','💤','💥','💦','💧','💨','💩','🎷','🎸','🎹','🎺','🎻','💪','🦹','🧀','🧁','🧂','🧐','💫','💬','💭','💮','💯','🧑','💰','💱','💲','💳','💴','🧒','💵','💶','💷','💸','💹','🧓','💺','💻','💼','💽','💾','🧔','💿','📀','📁','📂','📃','🧕','📄','📅','📆','📇','📈','📉','📊','📋','📌','📍','📎','📏','📐','📑','📒','📓','📔','🧖','📕','📖','📗','📘','📙','📚','📛','📜','📝','📞','📟','📠','📡','📢','📣','📤','📥','🧗','📦','📧','📨','📩','📪','📫','📬','📭','📮','📯','📰','📱','📲','📳','📴','📵','📶','🧘','📷','📸','📹','📺','📻','📼','📽','📿','🔀','🔁','🔂','🔃','🔄','🔅','🔆','🔇','🔈','🧙','🔉','🔊','🔋','🔌','🔍','🔎','🔏','🔐','🔑','🔒','🔓','🔔','🔕','🔖','🔗','🔘','🔙','🧚','🔚','🔛','🔜','🔝','🔞','🔟','🔠','🔡','🔢','🔣','🔤','🔥','🔦','🔧','🔨','🔩','🔪','🧛','🔫','🔬','🔭','🔮','🔯','🔰','🔱','🔲','🔳','🔴','🔵','🔶','🔷','🔸','🔹','🔺','🔻','🧜','🔼','🔽','🕉','🕊','🕋','🕌','🕍','🕎','🕐','🕑','🕒','🕓','🕔','🕕','🕖','🕗','🕘','🧝','🕙','🕚','🧞','🕛','🕜','🧟','🧠','🧡','🧢','🧣','🧤','🧥','🧦','🧧','🧨','🧩','🧪','🧫','🧬','🧭','🧮','🧯','🧰','🧱','🧲','🧳','🧴','🧵','🧶','🧷','🧸','🧹','🧺','🧻','🧼','🧽','🧾','🧿','🕝','🕞','🕟','🕠','🕡','🕢','🕣','🕤','🕥','🕦','🕧','🕯','🕰','🕳','🎼','🎽','🎾','🎿','🏀','🏁','🇧','🇮','🇪','🇷','🇱','🏂','🆎','🆑','🇨','🇹','🇯','🕴','🆒','🇬','🆓','🇳','🆔','🇴','🇺','🇫','🆕','🆖','🆗','🇭','🏃','🆘','🇩','🇻','🇰','🕵','🕶','🕷','🕸','🕹','🆙','🇼','🆚','🇽','🇸','▫','☦','☮','☯','☸','☹','☺','♀','♂','♈','♉','♊','♋','♌','♍','♎','♏','♐','♑','♒','♓','♟','♠','♣','♥','♦','♨','♻','♾','♿','⚒','⚓','⚔','⚕','⚖','⚗','⚙','⚛','⚜','⚠','⚡','⚪','⚫','⚰','⚱','⚽','⚾','⛄','⛅','⛈','⛎','⛏','⛑','⛓','⛔','⛩','⛪','⛰','⛱','⛲','⛳','⛴','⛵','☣','☢','☠','☝','☘','⛷','⛸','☕','☔','☑','☎','☄','☃','☂','☁','☀','◾','◽','◼','◻','◀','▶','☪','▪','⛹','⛺','⛽','✂','✅','✈','✉','Ⓜ','⏺','⏹','⏸','⏳','✊','⏲','⏱','⏰','⏯','⏮','✋','⏭','⏬','⏫','⏪','⏩','✌','⏏','⌨','⌛','⌚','↪','✍','✏','✒','✔','✖','✝','✡','✨','✳','✴','❄','❇','❌','❎','❓','❔','❕','❗','❣','❤','➕','➖','➗','➡','➰','➿','⤴','⤵','↩','⬅','⬆','⬇','⬛','⬜','⭐','⭕','↙','〰','〽','↘','↗','㊗','㊙','↖','↕','↔','ℹ','™','⁉','‼',''); |
|
5317 $partials = array('🀄','🃏','🅰','🅱','🅾','🅿','🆎','🆑','🆒','🆓','🆔','🆕','🆖','🆗','🆘','🆙','🆚','🇦','🇨','🇩','🇪','🇫','🇬','🇮','🇱','🇲','🇴','🇶','🇷','🇸','🇹','🇺','🇼','🇽','🇿','🇧','🇭','🇯','🇳','🇻','🇾','🇰','🇵','🈁','🈂','🈚','🈯','🈲','🈳','🈴','🈵','🈶','🈷','🈸','🈹','🈺','🉐','🉑','🌀','🌁','🌂','🌃','🌄','🌅','🌆','🌇','🌈','🌉','🌊','🌋','🌌','🌍','🌎','🌏','🌐','🌑','🌒','🌓','🌔','🌕','🌖','🌗','🌘','🌙','🌚','🌛','🌜','🌝','🌞','🌟','🌠','🌡','🌤','🌥','🌦','🌧','🌨','🌩','🌪','🌫','🌬','🌭','🌮','🌯','🌰','🌱','🌲','🌳','🌴','🌵','🌶','🌷','🌸','🌹','🌺','🌻','🌼','🌽','🌾','🌿','🍀','🍁','🍂','🍃','🍄','🍅','🍆','🍇','🍈','🍉','🍊','🍋','🍌','🍍','🍎','🍏','🍐','🍑','🍒','🍓','🍔','🍕','🍖','🍗','🍘','🍙','🍚','🍛','🍜','🍝','🍞','🍟','🍠','🍡','🍢','🍣','🍤','🍥','🍦','🍧','🍨','🍩','🍪','🍫','🍬','🍭','🍮','🍯','🍰','🍱','🍲','🍳','🍴','🍵','🍶','🍷','🍸','🍹','🍺','🍻','🍼','🍽','🍾','🍿','🎀','🎁','🎂','🎃','🎄','🎅','🏻','🏼','🏽','🏾','🏿','🎆','🎇','🎈','🎉','🎊','🎋','🎌','🎍','🎎','🎏','🎐','🎑','🎒','🎓','🎖','🎗','🎙','🎚','🎛','🎞','🎟','🎠','🎡','🎢','🎣','🎤','🎥','🎦','🎧','🎨','🎩','🎪','🎫','🎬','🎭','🎮','🎯','🎰','🎱','🎲','🎳','🎴','🎵','🎶','🎷','🎸','🎹','🎺','🎻','🎼','🎽','🎾','🎿','🏀','🏁','🏂','🏃','‍','♀','️','♂','🏄','🏅','🏆','🏇','🏈','🏉','🏊','🏋','🏌','🏍','🏎','🏏','🏐','🏑','🏒','🏓','🏔','🏕','🏖','🏗','🏘','🏙','🏚','🏛','🏜','🏝','🏞','🏟','🏠','🏡','🏢','🏣','🏤','🏥','🏦','🏧','🏨','🏩','🏪','🏫','🏬','🏭','🏮','🏯','🏰','🏳','🏴','☠','󠁧','󠁢','󠁥','󠁮','󠁿','󠁳','󠁣','󠁴','󠁷','󠁬','🏵','🏷','🏸','🏹','🏺','🐀','🐁','🐂','🐃','🐄','🐅','🐆','🐇','🐈','🐉','🐊','🐋','🐌','🐍','🐎','🐏','🐐','🐑','🐒','🐓','🐔','🐕','🐖','🐗','🐘','🐙','🐚','🐛','🐜','🐝','🐞','🐟','🐠','🐡','🐢','🐣','🐤','🐥','🐦','🐧','🐨','🐩','🐪','🐫','🐬','🐭','🐮','🐯','🐰','🐱','🐲','🐳','🐴','🐵','🐶','🐷','🐸','🐹','🐺','🐻','🐼','🐽','🐾','🐿','👀','👁','🗨','👂','👃','👄','👅','👆','👇','👈','👉','👊','👋','👌','👍','👎','👏','👐','👑','👒','👓','👔','👕','👖','👗','👘','👙','👚','👛','👜','👝','👞','👟','👠','👡','👢','👣','👤','👥','👦','👧','👨','💻','💼','🔧','🔬','🚀','🚒','🦰','🦱','🦲','🦳','⚕','⚖','✈','👩','❤','💋','👪','👫','👬','👭','👮','👯','👰','👱','👲','👳','👴','👵','👶','👷','👸','👹','👺','👻','👼','👽','👾','👿','💀','💁','💂','💃','💄','💅','💆','💇','💈','💉','💊','💌','💍','💎','💏','💐','💑','💒','💓','💔','💕','💖','💗','💘','💙','💚','💛','💜','💝','💞','💟','💠','💡','💢','💣','💤','💥','💦','💧','💨','💩','💪','💫','💬','💭','💮','💯','💰','💱','💲','💳','💴','💵','💶','💷','💸','💹','💺','💽','💾','💿','📀','📁','📂','📃','📄','📅','📆','📇','📈','📉','📊','📋','📌','📍','📎','📏','📐','📑','📒','📓','📔','📕','📖','📗','📘','📙','📚','📛','📜','📝','📞','📟','📠','📡','📢','📣','📤','📥','📦','📧','📨','📩','📪','📫','📬','📭','📮','📯','📰','📱','📲','📳','📴','📵','📶','📷','📸','📹','📺','📻','📼','📽','📿','🔀','🔁','🔂','🔃','🔄','🔅','🔆','🔇','🔈','🔉','🔊','🔋','🔌','🔍','🔎','🔏','🔐','🔑','🔒','🔓','🔔','🔕','🔖','🔗','🔘','🔙','🔚','🔛','🔜','🔝','🔞','🔟','🔠','🔡','🔢','🔣','🔤','🔥','🔦','🔨','🔩','🔪','🔫','🔭','🔮','🔯','🔰','🔱','🔲','🔳','🔴','🔵','🔶','🔷','🔸','🔹','🔺','🔻','🔼','🔽','🕉','🕊','🕋','🕌','🕍','🕎','🕐','🕑','🕒','🕓','🕔','🕕','🕖','🕗','🕘','🕙','🕚','🕛','🕜','🕝','🕞','🕟','🕠','🕡','🕢','🕣','🕤','🕥','🕦','🕧','🕯','🕰','🕳','🕴','🕵','🕶','🕷','🕸','🕹','🕺','🖇','🖊','🖋','🖌','🖍','🖐','🖕','🖖','🖤','🖥','🖨','🖱','🖲','🖼','🗂','🗃','🗄','🗑','🗒','🗓','🗜','🗝','🗞','🗡','🗣','🗯','🗳','🗺','🗻','🗼','🗽','🗾','🗿','😀','😁','😂','😃','😄','😅','😆','😇','😈','😉','😊','😋','😌','😍','😎','😏','😐','😑','😒','😓','😔','😕','😖','😗','😘','😙','😚','😛','😜','😝','😞','😟','😠','😡','😢','😣','😤','😥','😦','😧','😨','😩','😪','😫','😬','😭','😮','😯','😰','😱','😲','😳','😴','😵','😶','😷','😸','😹','😺','😻','😼','😽','😾','😿','🙀','🙁','🙂','🙃','🙄','🙅','🙆','🙇','🙈','🙉','🙊','🙋','🙌','🙍','🙎','🙏','🚁','🚂','🚃','🚄','🚅','🚆','🚇','🚈','🚉','🚊','🚋','🚌','🚍','🚎','🚏','🚐','🚑','🚓','🚔','🚕','🚖','🚗','🚘','🚙','🚚','🚛','🚜','🚝','🚞','🚟','🚠','🚡','🚢','🚣','🚤','🚥','🚦','🚧','🚨','🚩','🚪','🚫','🚬','🚭','🚮','🚯','🚰','🚱','🚲','🚳','🚴','🚵','🚶','🚷','🚸','🚹','🚺','🚻','🚼','🚽','🚾','🚿','🛀','🛁','🛂','🛃','🛄','🛅','🛋','🛌','🛍','🛎','🛏','🛐','🛑','🛒','🛠','🛡','🛢','🛣','🛤','🛥','🛩','🛫','🛬','🛰','🛳','🛴','🛵','🛶','🛷','🛸','🛹','🤐','🤑','🤒','🤓','🤔','🤕','🤖','🤗','🤘','🤙','🤚','🤛','🤜','🤝','🤞','🤟','🤠','🤡','🤢','🤣','🤤','🤥','🤦','🤧','🤨','🤩','🤪','🤫','🤬','🤭','🤮','🤯','🤰','🤱','🤲','🤳','🤴','🤵','🤶','🤷','🤸','🤹','🤺','🤼','🤽','🤾','🥀','🥁','🥂','🥃','🥄','🥅','🥇','🥈','🥉','🥊','🥋','🥌','🥍','🥎','🥏','🥐','🥑','🥒','🥓','🥔','🥕','🥖','🥗','🥘','🥙','🥚','🥛','🥜','🥝','🥞','🥟','🥠','🥡','🥢','🥣','🥤','🥥','🥦','🥧','🥨','🥩','🥪','🥫','🥬','🥭','🥮','🥯','🥰','🥳','🥴','🥵','🥶','🥺','🥼','🥽','🥾','🥿','🦀','🦁','🦂','🦃','🦄','🦅','🦆','🦇','🦈','🦉','🦊','🦋','🦌','🦍','🦎','🦏','🦐','🦑','🦒','🦓','🦔','🦕','🦖','🦗','🦘','🦙','🦚','🦛','🦜','🦝','🦞','🦟','🦠','🦡','🦢','🦴','🦵','🦶','🦷','🦸','🦹','🧀','🧁','🧂','🧐','🧑','🧒','🧓','🧔','🧕','🧖','🧗','🧘','🧙','🧚','🧛','🧜','🧝','🧞','🧟','🧠','🧡','🧢','🧣','🧤','🧥','🧦','🧧','🧨','🧩','🧪','🧫','🧬','🧭','🧮','🧯','🧰','🧱','🧲','🧳','🧴','🧵','🧶','🧷','🧸','🧹','🧺','🧻','🧼','🧽','🧾','🧿','‼','⁉','™','ℹ','↔','↕','↖','↗','↘','↙','↩','↪','⃣','⌚','⌛','⌨','⏏','⏩','⏪','⏫','⏬','⏭','⏮','⏯','⏰','⏱','⏲','⏳','⏸','⏹','⏺','Ⓜ','▪','▫','▶','◀','◻','◼','◽','◾','☀','☁','☂','☃','☄','☎','☑','☔','☕','☘','☝','☢','☣','☦','☪','☮','☯','☸','☹','☺','♈','♉','♊','♋','♌','♍','♎','♏','♐','♑','♒','♓','♟','♠','♣','♥','♦','♨','♻','♾','♿','⚒','⚓','⚔','⚗','⚙','⚛','⚜','⚠','⚡','⚪','⚫','⚰','⚱','⚽','⚾','⛄','⛅','⛈','⛎','⛏','⛑','⛓','⛔','⛩','⛪','⛰','⛱','⛲','⛳','⛴','⛵','⛷','⛸','⛹','⛺','⛽','✂','✅','✉','✊','✋','✌','✍','✏','✒','✔','✖','✝','✡','✨','✳','✴','❄','❇','❌','❎','❓','❔','❕','❗','❣','➕','➖','➗','➡','➰','➿','⤴','⤵','⬅','⬆','⬇','⬛','⬜','⭐','⭕','〰','〽','㊗','㊙',''); |
|
5318 // END: emoji arrays |
|
5319 |
|
5320 if ( 'entities' === $type ) { |
|
5321 return $entities; |
|
5322 } |
|
5323 |
|
5324 return $partials; |
|
5325 } |
|
5326 |
|
5327 /** |
|
5328 * Shorten a URL, to be used as link text. |
|
5329 * |
|
5330 * @since 1.2.0 |
|
5331 * @since 4.4.0 Moved to wp-includes/formatting.php from wp-admin/includes/misc.php and added $length param. |
|
5332 * |
|
5333 * @param string $url URL to shorten. |
|
5334 * @param int $length Optional. Maximum length of the shortened URL. Default 35 characters. |
|
5335 * @return string Shortened URL. |
|
5336 */ |
|
5337 function url_shorten( $url, $length = 35 ) { |
|
5338 $stripped = str_replace( array( 'https://', 'http://', 'www.' ), '', $url ); |
|
5339 $short_url = untrailingslashit( $stripped ); |
|
5340 |
|
5341 if ( strlen( $short_url ) > $length ) { |
|
5342 $short_url = substr( $short_url, 0, $length - 3 ) . '…'; |
|
5343 } |
|
5344 return $short_url; |
|
5345 } |
|
5346 |
|
5347 /** |
|
5348 * Sanitizes a hex color. |
|
5349 * |
|
5350 * Returns either '', a 3 or 6 digit hex color (with #), or nothing. |
|
5351 * For sanitizing values without a #, see sanitize_hex_color_no_hash(). |
|
5352 * |
|
5353 * @since 3.4.0 |
|
5354 * |
|
5355 * @param string $color |
|
5356 * @return string|void |
|
5357 */ |
|
5358 function sanitize_hex_color( $color ) { |
|
5359 if ( '' === $color ) { |
|
5360 return ''; |
|
5361 } |
|
5362 |
|
5363 // 3 or 6 hex digits, or the empty string. |
|
5364 if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) { |
|
5365 return $color; |
|
5366 } |
|
5367 } |
|
5368 |
|
5369 /** |
|
5370 * Sanitizes a hex color without a hash. Use sanitize_hex_color() when possible. |
|
5371 * |
|
5372 * Saving hex colors without a hash puts the burden of adding the hash on the |
|
5373 * UI, which makes it difficult to use or upgrade to other color types such as |
|
5374 * rgba, hsl, rgb, and html color names. |
|
5375 * |
|
5376 * Returns either '', a 3 or 6 digit hex color (without a #), or null. |
|
5377 * |
|
5378 * @since 3.4.0 |
|
5379 * |
|
5380 * @param string $color |
|
5381 * @return string|null |
|
5382 */ |
|
5383 function sanitize_hex_color_no_hash( $color ) { |
|
5384 $color = ltrim( $color, '#' ); |
|
5385 |
|
5386 if ( '' === $color ) { |
|
5387 return ''; |
|
5388 } |
|
5389 |
|
5390 return sanitize_hex_color( '#' . $color ) ? $color : null; |
|
5391 } |
|
5392 |
|
5393 /** |
|
5394 * Ensures that any hex color is properly hashed. |
|
5395 * Otherwise, returns value untouched. |
|
5396 * |
|
5397 * This method should only be necessary if using sanitize_hex_color_no_hash(). |
|
5398 * |
|
5399 * @since 3.4.0 |
|
5400 * |
|
5401 * @param string $color |
|
5402 * @return string |
|
5403 */ |
|
5404 function maybe_hash_hex_color( $color ) { |
|
5405 if ( $unhashed = sanitize_hex_color_no_hash( $color ) ) { |
|
5406 return '#' . $unhashed; |
|
5407 } |
|
5408 |
|
5409 return $color; |
|
5410 } |