changeset 16 | a86126ab1dd4 |
parent 9 | 177826044cd9 |
child 18 | be944660c56a |
15:3d4e9c994f10 | 16:a86126ab1dd4 |
---|---|
6 * |
6 * |
7 * @package WordPress |
7 * @package WordPress |
8 */ |
8 */ |
9 |
9 |
10 /** |
10 /** |
11 * Replaces common plain text characters into formatted entities |
11 * Replaces common plain text characters with formatted entities. |
12 * |
|
13 * Returns given text with transformations of quotes into smart quotes, apostrophes, |
|
14 * dashes, ellipses, the trademark symbol, and the multiplication symbol. |
|
12 * |
15 * |
13 * As an example, |
16 * As an example, |
14 * |
17 * |
15 * 'cause today's effort makes it worth tomorrow's "holiday" ... |
18 * 'cause today's effort makes it worth tomorrow's "holiday" ... |
16 * |
19 * |
17 * Becomes: |
20 * Becomes: |
18 * |
21 * |
19 * ’cause today’s effort makes it worth tomorrow’s “holiday” … |
22 * ’cause today’s effort makes it worth tomorrow’s “holiday” … |
20 * |
23 * |
21 * Code within certain html blocks are skipped. |
24 * Code within certain HTML blocks are skipped. |
22 * |
25 * |
23 * Do not use this function before the {@see 'init'} action hook; everything will break. |
26 * Do not use this function before the {@see 'init'} action hook; everything will break. |
24 * |
27 * |
25 * @since 0.71 |
28 * @since 0.71 |
26 * |
29 * |
27 * @global array $wp_cockneyreplace Array of formatted entities for certain common phrases |
30 * @global array $wp_cockneyreplace Array of formatted entities for certain common phrases. |
28 * @global array $shortcode_tags |
31 * @global array $shortcode_tags |
29 * @staticvar array $static_characters |
32 * |
30 * @staticvar array $static_replacements |
33 * @param string $text The text to be formatted. |
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 |
|
46 * |
|
47 * @param string $text The text to be formatted |
|
48 * @param bool $reset Set to true for unit testing. Translated patterns will reset. |
34 * @param bool $reset Set to true for unit testing. Translated patterns will reset. |
49 * @return string The string replaced with html entities |
35 * @return string The string replaced with HTML entities. |
50 */ |
36 */ |
51 function wptexturize( $text, $reset = false ) { |
37 function wptexturize( $text, $reset = false ) { |
52 global $wp_cockneyreplace, $shortcode_tags; |
38 global $wp_cockneyreplace, $shortcode_tags; |
53 static $static_characters = null, |
39 static $static_characters = null, |
54 $static_replacements = null, |
40 $static_replacements = null, |
76 // Set up static variables. Run once only. |
62 // Set up static variables. Run once only. |
77 if ( $reset || ! isset( $static_characters ) ) { |
63 if ( $reset || ! isset( $static_characters ) ) { |
78 /** |
64 /** |
79 * Filters whether to skip running wptexturize(). |
65 * Filters whether to skip running wptexturize(). |
80 * |
66 * |
81 * Passing false to the filter will effectively short-circuit wptexturize(). |
67 * Returning false from the filter will effectively short-circuit wptexturize() |
82 * returning the original text passed to the function instead. |
68 * and return the original text passed to the function instead. |
83 * |
69 * |
84 * The filter runs only once, the first time wptexturize() is called. |
70 * The filter runs only once, the first time wptexturize() is called. |
85 * |
71 * |
86 * @since 4.0.0 |
72 * @since 4.0.0 |
87 * |
73 * |
92 $run_texturize = apply_filters( 'run_wptexturize', $run_texturize ); |
78 $run_texturize = apply_filters( 'run_wptexturize', $run_texturize ); |
93 if ( false === $run_texturize ) { |
79 if ( false === $run_texturize ) { |
94 return $text; |
80 return $text; |
95 } |
81 } |
96 |
82 |
97 /* translators: opening curly double quote */ |
83 /* translators: Opening curly double quote. */ |
98 $opening_quote = _x( '“', 'opening curly double quote' ); |
84 $opening_quote = _x( '“', 'opening curly double quote' ); |
99 /* translators: closing curly double quote */ |
85 /* translators: Closing curly double quote. */ |
100 $closing_quote = _x( '”', 'closing curly double quote' ); |
86 $closing_quote = _x( '”', 'closing curly double quote' ); |
101 |
87 |
102 /* translators: apostrophe, for example in 'cause or can't */ |
88 /* translators: Apostrophe, for example in 'cause or can't. */ |
103 $apos = _x( '’', 'apostrophe' ); |
89 $apos = _x( '’', 'apostrophe' ); |
104 |
90 |
105 /* translators: prime, for example in 9' (nine feet) */ |
91 /* translators: Prime, for example in 9' (nine feet). */ |
106 $prime = _x( '′', 'prime' ); |
92 $prime = _x( '′', 'prime' ); |
107 /* translators: double prime, for example in 9" (nine inches) */ |
93 /* translators: Double prime, for example in 9" (nine inches). */ |
108 $double_prime = _x( '″', 'double prime' ); |
94 $double_prime = _x( '″', 'double prime' ); |
109 |
95 |
110 /* translators: opening curly single quote */ |
96 /* translators: Opening curly single quote. */ |
111 $opening_single_quote = _x( '‘', 'opening curly single quote' ); |
97 $opening_single_quote = _x( '‘', 'opening curly single quote' ); |
112 /* translators: closing curly single quote */ |
98 /* translators: Closing curly single quote. */ |
113 $closing_single_quote = _x( '’', 'closing curly single quote' ); |
99 $closing_single_quote = _x( '’', 'closing curly single quote' ); |
114 |
100 |
115 /* translators: en dash */ |
101 /* translators: En dash. */ |
116 $en_dash = _x( '–', 'en dash' ); |
102 $en_dash = _x( '–', 'en dash' ); |
117 /* translators: em dash */ |
103 /* translators: Em dash. */ |
118 $em_dash = _x( '—', 'em dash' ); |
104 $em_dash = _x( '—', 'em dash' ); |
119 |
105 |
120 $default_no_texturize_tags = array( 'pre', 'code', 'kbd', 'style', 'script', 'tt' ); |
106 $default_no_texturize_tags = array( 'pre', 'code', 'kbd', 'style', 'script', 'tt' ); |
121 $default_no_texturize_shortcodes = array( 'code' ); |
107 $default_no_texturize_shortcodes = array( 'code' ); |
122 |
108 |
123 // if a plugin has provided an autocorrect array, use it |
109 // If a plugin has provided an autocorrect array, use it. |
124 if ( isset( $wp_cockneyreplace ) ) { |
110 if ( isset( $wp_cockneyreplace ) ) { |
125 $cockney = array_keys( $wp_cockneyreplace ); |
111 $cockney = array_keys( $wp_cockneyreplace ); |
126 $cockneyreplace = array_values( $wp_cockneyreplace ); |
112 $cockneyreplace = array_values( $wp_cockneyreplace ); |
127 } else { |
113 } else { |
128 /* translators: This is a comma-separated list of words that defy the syntax of quotations in normal use, |
114 /* |
129 * for example... 'We do not have enough words yet' ... is a typical quoted phrase. But when we write |
115 * translators: This is a comma-separated list of words that defy the syntax of quotations in normal use, |
116 * 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. |
117 * lines of code 'til we have enough of 'em, then we need to insert apostrophes instead of quotes. |
131 */ |
118 */ |
132 $cockney = explode( |
119 $cockney = explode( |
133 ',', |
120 ',', |
134 _x( |
121 _x( |
175 // '99 '99s '99's (apostrophe) But never '9 or '99% or '999 or '99.0. |
162 // '99 '99s '99's (apostrophe) But never '9 or '99% or '999 or '99.0. |
176 if ( "'" !== $apos ) { |
163 if ( "'" !== $apos ) { |
177 $dynamic['/\'(?=\d\d(?:\Z|(?![%\d]|[.,]\d)))/'] = $apos_flag; |
164 $dynamic['/\'(?=\d\d(?:\Z|(?![%\d]|[.,]\d)))/'] = $apos_flag; |
178 } |
165 } |
179 |
166 |
180 // Quoted Numbers like '0.42' |
167 // Quoted numbers like '0.42'. |
181 if ( "'" !== $opening_single_quote && "'" !== $closing_single_quote ) { |
168 if ( "'" !== $opening_single_quote && "'" !== $closing_single_quote ) { |
182 $dynamic[ '/(?<=\A|' . $spaces . ')\'(\d[.,\d]*)\'/' ] = $open_sq_flag . '$1' . $closing_single_quote; |
169 $dynamic[ '/(?<=\A|' . $spaces . ')\'(\d[.,\d]*)\'/' ] = $open_sq_flag . '$1' . $closing_single_quote; |
183 } |
170 } |
184 |
171 |
185 // Single quote at start, or preceded by (, {, <, [, ", -, or spaces. |
172 // Single quote at start, or preceded by (, {, <, [, ", -, or spaces. |
186 if ( "'" !== $opening_single_quote ) { |
173 if ( "'" !== $opening_single_quote ) { |
187 $dynamic[ '/(?<=\A|[([{"\-]|<|' . $spaces . ')\'/' ] = $open_sq_flag; |
174 $dynamic[ '/(?<=\A|[([{"\-]|<|' . $spaces . ')\'/' ] = $open_sq_flag; |
188 } |
175 } |
189 |
176 |
190 // Apostrophe in a word. No spaces, double apostrophes, or other punctuation. |
177 // Apostrophe in a word. No spaces, double apostrophes, or other punctuation. |
191 if ( "'" !== $apos ) { |
178 if ( "'" !== $apos ) { |
192 $dynamic[ '/(?<!' . $spaces . ')\'(?!\Z|[.,:;!?"\'(){}[\]\-]|&[lg]t;|' . $spaces . ')/' ] = $apos_flag; |
179 $dynamic[ '/(?<!' . $spaces . ')\'(?!\Z|[.,:;!?"\'(){}[\]\-]|&[lg]t;|' . $spaces . ')/' ] = $apos_flag; |
193 } |
180 } |
194 |
181 |
195 $dynamic_characters['apos'] = array_keys( $dynamic ); |
182 $dynamic_characters['apos'] = array_keys( $dynamic ); |
196 $dynamic_replacements['apos'] = array_values( $dynamic ); |
183 $dynamic_replacements['apos'] = array_values( $dynamic ); |
197 $dynamic = array(); |
184 $dynamic = array(); |
198 |
185 |
199 // Quoted Numbers like "42" |
186 // Quoted numbers like "42". |
200 if ( '"' !== $opening_quote && '"' !== $closing_quote ) { |
187 if ( '"' !== $opening_quote && '"' !== $closing_quote ) { |
201 $dynamic[ '/(?<=\A|' . $spaces . ')"(\d[.,\d]*)"/' ] = $open_q_flag . '$1' . $closing_quote; |
188 $dynamic[ '/(?<=\A|' . $spaces . ')"(\d[.,\d]*)"/' ] = $open_q_flag . '$1' . $closing_quote; |
202 } |
189 } |
203 |
190 |
204 // Double quote at start, or preceded by (, {, <, [, -, or spaces, and not followed by spaces. |
191 // Double quote at start, or preceded by (, {, <, [, -, or spaces, and not followed by spaces. |
208 |
195 |
209 $dynamic_characters['quote'] = array_keys( $dynamic ); |
196 $dynamic_characters['quote'] = array_keys( $dynamic ); |
210 $dynamic_replacements['quote'] = array_values( $dynamic ); |
197 $dynamic_replacements['quote'] = array_values( $dynamic ); |
211 $dynamic = array(); |
198 $dynamic = array(); |
212 |
199 |
213 // Dashes and spaces |
200 // Dashes and spaces. |
214 $dynamic['/---/'] = $em_dash; |
201 $dynamic['/---/'] = $em_dash; |
215 $dynamic[ '/(?<=^|' . $spaces . ')--(?=$|' . $spaces . ')/' ] = $em_dash; |
202 $dynamic[ '/(?<=^|' . $spaces . ')--(?=$|' . $spaces . ')/' ] = $em_dash; |
216 $dynamic['/(?<!xn)--/'] = $en_dash; |
203 $dynamic['/(?<!xn)--/'] = $en_dash; |
217 $dynamic[ '/(?<=^|' . $spaces . ')-(?=$|' . $spaces . ')/' ] = $en_dash; |
204 $dynamic[ '/(?<=^|' . $spaces . ')-(?=$|' . $spaces . ')/' ] = $en_dash; |
218 |
205 |
219 $dynamic_characters['dash'] = array_keys( $dynamic ); |
206 $dynamic_characters['dash'] = array_keys( $dynamic ); |
220 $dynamic_replacements['dash'] = array_values( $dynamic ); |
207 $dynamic_replacements['dash'] = array_values( $dynamic ); |
221 } |
208 } |
222 |
209 |
223 // Must do this every time in case plugins use these filters in a context sensitive manner |
210 // Must do this every time in case plugins use these filters in a context sensitive manner. |
224 /** |
211 /** |
225 * Filters the list of HTML elements not to texturize. |
212 * Filters the list of HTML elements not to texturize. |
226 * |
213 * |
227 * @since 2.8.0 |
214 * @since 2.8.0 |
228 * |
215 * |
229 * @param array $default_no_texturize_tags An array of HTML element names. |
216 * @param string[] $default_no_texturize_tags An array of HTML element names. |
230 */ |
217 */ |
231 $no_texturize_tags = apply_filters( 'no_texturize_tags', $default_no_texturize_tags ); |
218 $no_texturize_tags = apply_filters( 'no_texturize_tags', $default_no_texturize_tags ); |
232 /** |
219 /** |
233 * Filters the list of shortcodes not to texturize. |
220 * Filters the list of shortcodes not to texturize. |
234 * |
221 * |
235 * @since 2.8.0 |
222 * @since 2.8.0 |
236 * |
223 * |
237 * @param array $default_no_texturize_shortcodes An array of shortcode names. |
224 * @param string[] $default_no_texturize_shortcodes An array of shortcode names. |
238 */ |
225 */ |
239 $no_texturize_shortcodes = apply_filters( 'no_texturize_shortcodes', $default_no_texturize_shortcodes ); |
226 $no_texturize_shortcodes = apply_filters( 'no_texturize_shortcodes', $default_no_texturize_shortcodes ); |
240 |
227 |
241 $no_texturize_tags_stack = array(); |
228 $no_texturize_tags_stack = array(); |
242 $no_texturize_shortcodes_stack = array(); |
229 $no_texturize_shortcodes_stack = array(); |
265 $curl = preg_replace( '/&(?!#(?:\d+|x[a-f0-9]+);|[a-z1-4]{1,8};)/i', '&', $curl ); |
252 $curl = preg_replace( '/&(?!#(?:\d+|x[a-f0-9]+);|[a-z1-4]{1,8};)/i', '&', $curl ); |
266 |
253 |
267 _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags ); |
254 _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags ); |
268 } |
255 } |
269 } elseif ( '' === trim( $curl ) ) { |
256 } elseif ( '' === trim( $curl ) ) { |
270 // This is a newline between delimiters. Performance improves when we check this. |
257 // This is a newline between delimiters. Performance improves when we check this. |
271 continue; |
258 continue; |
272 |
259 |
273 } elseif ( '[' === $first && $found_shortcodes && 1 === preg_match( '/^' . $shortcode_regex . '$/', $curl ) ) { |
260 } elseif ( '[' === $first && $found_shortcodes && 1 === preg_match( '/^' . $shortcode_regex . '$/', $curl ) ) { |
274 // This is a shortcode delimiter. |
261 // This is a shortcode delimiter. |
275 |
262 |
279 } else { |
266 } else { |
280 // Looks like an escaped shortcode. |
267 // Looks like an escaped shortcode. |
281 continue; |
268 continue; |
282 } |
269 } |
283 } elseif ( empty( $no_texturize_shortcodes_stack ) && empty( $no_texturize_tags_stack ) ) { |
270 } elseif ( empty( $no_texturize_shortcodes_stack ) && empty( $no_texturize_tags_stack ) ) { |
284 // This is neither a delimiter, nor is this content inside of no_texturize pairs. Do texturize. |
271 // This is neither a delimiter, nor is this content inside of no_texturize pairs. Do texturize. |
285 |
272 |
286 $curl = str_replace( $static_characters, $static_replacements, $curl ); |
273 $curl = str_replace( $static_characters, $static_replacements, $curl ); |
287 |
274 |
288 if ( false !== strpos( $curl, "'" ) ) { |
275 if ( false !== strpos( $curl, "'" ) ) { |
289 $curl = preg_replace( $dynamic_characters['apos'], $dynamic_replacements['apos'], $curl ); |
276 $curl = preg_replace( $dynamic_characters['apos'], $dynamic_replacements['apos'], $curl ); |
298 } |
285 } |
299 if ( false !== strpos( $curl, '-' ) ) { |
286 if ( false !== strpos( $curl, '-' ) ) { |
300 $curl = preg_replace( $dynamic_characters['dash'], $dynamic_replacements['dash'], $curl ); |
287 $curl = preg_replace( $dynamic_characters['dash'], $dynamic_replacements['dash'], $curl ); |
301 } |
288 } |
302 |
289 |
303 // 9x9 (times), but never 0x9999 |
290 // 9x9 (times), but never 0x9999. |
304 if ( 1 === preg_match( '/(?<=\d)x\d/', $curl ) ) { |
291 if ( 1 === preg_match( '/(?<=\d)x\d/', $curl ) ) { |
305 // Searching for a digit is 10 times more expensive than for the x, so we avoid doing this one! |
292 // Searching for a digit is 10 times more expensive than for the x, so we avoid doing this one! |
306 $curl = preg_replace( '/\b(\d(?(?<=0)[\d\.,]+|[\d\.,]*))x(\d[\d\.,]*)\b/', '$1×$2', $curl ); |
293 $curl = preg_replace( '/\b(\d(?(?<=0)[\d\.,]+|[\d\.,]*))x(\d[\d\.,]*)\b/', '$1×$2', $curl ); |
307 } |
294 } |
308 |
295 |
342 if ( false === strpos( $sentence, $needle ) ) { |
329 if ( false === strpos( $sentence, $needle ) ) { |
343 continue; |
330 continue; |
344 } elseif ( 0 !== $key && 0 === substr_count( $sentence, $close_quote ) ) { |
331 } elseif ( 0 !== $key && 0 === substr_count( $sentence, $close_quote ) ) { |
345 $sentence = preg_replace( $quote_pattern, $flag, $sentence, -1, $count ); |
332 $sentence = preg_replace( $quote_pattern, $flag, $sentence, -1, $count ); |
346 if ( $count > 1 ) { |
333 if ( $count > 1 ) { |
347 // This sentence appears to have multiple closing quotes. Attempt Vulcan logic. |
334 // This sentence appears to have multiple closing quotes. Attempt Vulcan logic. |
348 $sentence = preg_replace( $flag_no_digit, $close_quote, $sentence, -1, $count2 ); |
335 $sentence = preg_replace( $flag_no_digit, $close_quote, $sentence, -1, $count2 ); |
349 if ( 0 === $count2 ) { |
336 if ( 0 === $count2 ) { |
350 // Try looking for a quote followed by a period. |
337 // Try looking for a quote followed by a period. |
351 $count2 = substr_count( $sentence, "$flag." ); |
338 $count2 = substr_count( $sentence, "$flag." ); |
352 if ( $count2 > 0 ) { |
339 if ( $count2 > 0 ) { |
366 } elseif ( 1 == $count ) { |
353 } elseif ( 1 == $count ) { |
367 // Found only one closing quote candidate, so give it priority over primes. |
354 // Found only one closing quote candidate, so give it priority over primes. |
368 $sentence = str_replace( $flag, $close_quote, $sentence ); |
355 $sentence = str_replace( $flag, $close_quote, $sentence ); |
369 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
356 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
370 } else { |
357 } else { |
371 // No closing quotes found. Just run primes pattern. |
358 // No closing quotes found. Just run primes pattern. |
372 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
359 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
373 } |
360 } |
374 } else { |
361 } else { |
375 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
362 $sentence = preg_replace( $prime_pattern, $prime, $sentence ); |
376 $sentence = preg_replace( $quote_pattern, $close_quote, $sentence ); |
363 $sentence = preg_replace( $quote_pattern, $close_quote, $sentence ); |
377 } |
364 } |
378 if ( '"' == $needle && false !== strpos( $sentence, '"' ) ) { |
365 if ( '"' === $needle && false !== strpos( $sentence, '"' ) ) { |
379 $sentence = str_replace( '"', $close_quote, $sentence ); |
366 $sentence = str_replace( '"', $close_quote, $sentence ); |
380 } |
367 } |
381 } |
368 } |
382 |
369 |
383 return implode( $open_quote, $sentences ); |
370 return implode( $open_quote, $sentences ); |
391 * Assumes second char of $text is optionally '/' to indicate closing as in </html>. |
378 * Assumes second char of $text is optionally '/' to indicate closing as in </html>. |
392 * |
379 * |
393 * @since 2.9.0 |
380 * @since 2.9.0 |
394 * @access private |
381 * @access private |
395 * |
382 * |
396 * @param string $text Text to check. Must be a tag like `<html>` or `[shortcode]`. |
383 * @param string $text Text to check. Must be a tag like `<html>` or `[shortcode]`. |
397 * @param array $stack List of open tag elements. |
384 * @param string[] $stack Array of open tag elements. |
398 * @param array $disabled_elements The tag names to match against. Spaces are not allowed in tag names. |
385 * @param string[] $disabled_elements Array of tag names to match against. Spaces are not allowed in tag names. |
399 */ |
386 */ |
400 function _wptexturize_pushpop_element( $text, &$stack, $disabled_elements ) { |
387 function _wptexturize_pushpop_element( $text, &$stack, $disabled_elements ) { |
401 // Is it an opening tag or closing tag? |
388 // Is it an opening tag or closing tag? |
402 if ( isset( $text[1] ) && '/' !== $text[1] ) { |
389 if ( isset( $text[1] ) && '/' !== $text[1] ) { |
403 $opening_tag = true; |
390 $opening_tag = true; |
404 $name_offset = 1; |
391 $name_offset = 1; |
405 } elseif ( 0 == count( $stack ) ) { |
392 } elseif ( 0 === count( $stack ) ) { |
406 // Stack is empty. Just stop. |
393 // Stack is empty. Just stop. |
407 return; |
394 return; |
408 } else { |
395 } else { |
409 $opening_tag = false; |
396 $opening_tag = false; |
410 $name_offset = 2; |
397 $name_offset = 2; |
418 $space -= $name_offset; |
405 $space -= $name_offset; |
419 } |
406 } |
420 $tag = substr( $text, $name_offset, $space ); |
407 $tag = substr( $text, $name_offset, $space ); |
421 |
408 |
422 // Handle disabled tags. |
409 // Handle disabled tags. |
423 if ( in_array( $tag, $disabled_elements ) ) { |
410 if ( in_array( $tag, $disabled_elements, true ) ) { |
424 if ( $opening_tag ) { |
411 if ( $opening_tag ) { |
425 /* |
412 /* |
426 * This disables texturize until we find a closing tag of our type |
413 * This disables texturize until we find a closing tag of our type |
427 * (e.g. <pre>) even if there was invalid nesting before that |
414 * (e.g. <pre>) even if there was invalid nesting before that. |
428 * |
415 * |
429 * Example: in the case <pre>sadsadasd</code>"baba"</pre> |
416 * Example: in the case <pre>sadsadasd</code>"baba"</pre> |
430 * "baba" won't be texturize |
417 * "baba" won't be texturized. |
431 */ |
418 */ |
432 |
419 |
433 array_push( $stack, $tag ); |
420 array_push( $stack, $tag ); |
434 } elseif ( end( $stack ) == $tag ) { |
421 } elseif ( end( $stack ) == $tag ) { |
435 array_pop( $stack ); |
422 array_pop( $stack ); |
436 } |
423 } |
437 } |
424 } |
438 } |
425 } |
439 |
426 |
440 /** |
427 /** |
441 * Replaces double line-breaks with paragraph elements. |
428 * Replaces double line breaks with paragraph elements. |
442 * |
429 * |
443 * A group of regex replaces used to identify text formatted with newlines and |
430 * A group of regex replaces used to identify text formatted with newlines and |
444 * replace double line-breaks with HTML paragraph tags. The remaining line-breaks |
431 * replace double line breaks with HTML paragraph tags. The remaining line breaks |
445 * after conversion become <<br />> tags, unless $br is set to '0' or 'false'. |
432 * after conversion become <<br />> tags, unless $br is set to '0' or 'false'. |
446 * |
433 * |
447 * @since 0.71 |
434 * @since 0.71 |
448 * |
435 * |
449 * @param string $pee The text which has to be formatted. |
436 * @param string $pee The text which has to be formatted. |
450 * @param bool $br Optional. If set, this will convert all remaining line-breaks |
437 * @param bool $br Optional. If set, this will convert all remaining line breaks |
451 * after paragraphing. Default true. |
438 * after paragraphing. Line breaks within `<script>`, `<style>`, |
439 * and `<svg>` tags are not affected. Default true. |
|
452 * @return string Text which has been converted into correct paragraph tags. |
440 * @return string Text which has been converted into correct paragraph tags. |
453 */ |
441 */ |
454 function wpautop( $pee, $br = true ) { |
442 function wpautop( $pee, $br = true ) { |
455 $pre_tags = array(); |
443 $pre_tags = array(); |
456 |
444 |
472 $i = 0; |
460 $i = 0; |
473 |
461 |
474 foreach ( $pee_parts as $pee_part ) { |
462 foreach ( $pee_parts as $pee_part ) { |
475 $start = strpos( $pee_part, '<pre' ); |
463 $start = strpos( $pee_part, '<pre' ); |
476 |
464 |
477 // Malformed html? |
465 // Malformed HTML? |
478 if ( $start === false ) { |
466 if ( false === $start ) { |
479 $pee .= $pee_part; |
467 $pee .= $pee_part; |
480 continue; |
468 continue; |
481 } |
469 } |
482 |
470 |
483 $name = "<pre wp-pre-tag-$i></pre>"; |
471 $name = "<pre wp-pre-tag-$i></pre>"; |
487 $i++; |
475 $i++; |
488 } |
476 } |
489 |
477 |
490 $pee .= $last_pee; |
478 $pee .= $last_pee; |
491 } |
479 } |
492 // Change multiple <br>s into two line breaks, which will turn into paragraphs. |
480 // Change multiple <br>'s into two line breaks, which will turn into paragraphs. |
493 $pee = preg_replace( '|<br\s*/?>\s*<br\s*/?>|', "\n\n", $pee ); |
481 $pee = preg_replace( '|<br\s*/?>\s*<br\s*/?>|', "\n\n", $pee ); |
494 |
482 |
495 $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)'; |
483 $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)'; |
496 |
484 |
497 // Add a double line break above block-level opening tags. |
485 // Add a double line break above block-level opening tags. |
498 $pee = preg_replace( '!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee ); |
486 $pee = preg_replace( '!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee ); |
499 |
487 |
500 // Add a double line break below block-level closing tags. |
488 // Add a double line break below block-level closing tags. |
501 $pee = preg_replace( '!(</' . $allblocks . '>)!', "$1\n\n", $pee ); |
489 $pee = preg_replace( '!(</' . $allblocks . '>)!', "$1\n\n", $pee ); |
490 |
|
491 // Add a double line break after hr tags, which are self closing. |
|
492 $pee = preg_replace( '!(<hr\s*?/?>)!', "$1\n\n", $pee ); |
|
502 |
493 |
503 // Standardize newline characters to "\n". |
494 // Standardize newline characters to "\n". |
504 $pee = str_replace( array( "\r\n", "\r" ), "\n", $pee ); |
495 $pee = str_replace( array( "\r\n", "\r" ), "\n", $pee ); |
505 |
496 |
506 // Find newlines in all elements and add placeholders. |
497 // Find newlines in all elements and add placeholders. |
575 $pee = preg_replace( '!(</?' . $allblocks . '[^>]*>)\s*</p>!', '$1', $pee ); |
566 $pee = preg_replace( '!(</?' . $allblocks . '[^>]*>)\s*</p>!', '$1', $pee ); |
576 |
567 |
577 // Optionally insert line breaks. |
568 // Optionally insert line breaks. |
578 if ( $br ) { |
569 if ( $br ) { |
579 // Replace newlines that shouldn't be touched with a placeholder. |
570 // Replace newlines that shouldn't be touched with a placeholder. |
580 $pee = preg_replace_callback( '/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee ); |
571 $pee = preg_replace_callback( '/<(script|style|svg).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee ); |
581 |
572 |
582 // Normalize <br> |
573 // Normalize <br> |
583 $pee = str_replace( array( '<br>', '<br/>' ), '<br />', $pee ); |
574 $pee = str_replace( array( '<br>', '<br/>' ), '<br />', $pee ); |
584 |
575 |
585 // Replace any new line characters that aren't preceded by a <br /> with a <br />. |
576 // Replace any new line characters that aren't preceded by a <br /> with a <br />. |
613 * Separate HTML elements and comments from the text. |
604 * Separate HTML elements and comments from the text. |
614 * |
605 * |
615 * @since 4.2.4 |
606 * @since 4.2.4 |
616 * |
607 * |
617 * @param string $input The text which has to be formatted. |
608 * @param string $input The text which has to be formatted. |
618 * @return array The formatted text. |
609 * @return string[] Array of the formatted text. |
619 */ |
610 */ |
620 function wp_html_split( $input ) { |
611 function wp_html_split( $input ) { |
621 return preg_split( get_html_split_regex(), $input, -1, PREG_SPLIT_DELIM_CAPTURE ); |
612 return preg_split( get_html_split_regex(), $input, -1, PREG_SPLIT_DELIM_CAPTURE ); |
622 } |
613 } |
623 |
614 |
624 /** |
615 /** |
625 * Retrieve the regular expression for an HTML element. |
616 * Retrieve the regular expression for an HTML element. |
626 * |
617 * |
627 * @since 4.4.0 |
618 * @since 4.4.0 |
628 * |
|
629 * @staticvar string $regex |
|
630 * |
619 * |
631 * @return string The regular expression |
620 * @return string The regular expression |
632 */ |
621 */ |
633 function get_html_split_regex() { |
622 function get_html_split_regex() { |
634 static $regex; |
623 static $regex; |
667 $regex = |
656 $regex = |
668 '/(' // Capture the entire match. |
657 '/(' // Capture the entire match. |
669 . '<' // Find start of element. |
658 . '<' // Find start of element. |
670 . '(?' // Conditional expression follows. |
659 . '(?' // Conditional expression follows. |
671 . $escaped // Find end of escaped element. |
660 . $escaped // Find end of escaped element. |
672 . '|' // ... else ... |
661 . '|' // ...else... |
673 . '[^>]*>?' // Find end of normal element. |
662 . '[^>]*>?' // Find end of normal element. |
674 . ')' |
663 . ')' |
675 . ')/'; |
664 . ')/'; |
676 // phpcs:enable |
665 // phpcs:enable |
677 } |
666 } |
685 * @access private |
674 * @access private |
686 * @ignore |
675 * @ignore |
687 * @internal This function will be removed in 4.5.0 per Shortcode API Roadmap. |
676 * @internal This function will be removed in 4.5.0 per Shortcode API Roadmap. |
688 * @since 4.4.0 |
677 * @since 4.4.0 |
689 * |
678 * |
690 * @staticvar string $html_regex |
679 * @param string $shortcode_regex The result from _get_wptexturize_shortcode_regex(). Optional. |
691 * |
|
692 * @param string $shortcode_regex The result from _get_wptexturize_shortcode_regex(). Optional. |
|
693 * @return string The regular expression |
680 * @return string The regular expression |
694 */ |
681 */ |
695 function _get_wptexturize_split_regex( $shortcode_regex = '' ) { |
682 function _get_wptexturize_split_regex( $shortcode_regex = '' ) { |
696 static $html_regex; |
683 static $html_regex; |
697 |
684 |
727 /** |
714 /** |
728 * Retrieve the regular expression for shortcodes. |
715 * Retrieve the regular expression for shortcodes. |
729 * |
716 * |
730 * @access private |
717 * @access private |
731 * @ignore |
718 * @ignore |
732 * @internal This function will be removed in 4.5.0 per Shortcode API Roadmap. |
|
733 * @since 4.4.0 |
719 * @since 4.4.0 |
734 * |
720 * |
735 * @param array $tagnames List of shortcodes to find. |
721 * @param string[] $tagnames Array of shortcodes to find. |
736 * @return string The regular expression |
722 * @return string The regular expression |
737 */ |
723 */ |
738 function _get_wptexturize_shortcode_regex( $tagnames ) { |
724 function _get_wptexturize_shortcode_regex( $tagnames ) { |
739 $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) ); |
725 $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) ); |
740 $tagregexp = "(?:$tagregexp)(?=[\\s\\]\\/])"; // Excerpt of get_shortcode_regex(). |
726 $tagregexp = "(?:$tagregexp)(?=[\\s\\]\\/])"; // Excerpt of get_shortcode_regex(). |
741 // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- don't remove regex indentation |
727 // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- don't remove regex indentation |
742 $regex = |
728 $regex = |
743 '\[' // Find start of shortcode. |
729 '\[' // Find start of shortcode. |
744 . '[\/\[]?' // Shortcodes may begin with [/ or [[ |
730 . '[\/\[]?' // Shortcodes may begin with [/ or [[. |
745 . $tagregexp // Only match registered shortcodes, because performance. |
731 . $tagregexp // Only match registered shortcodes, because performance. |
746 . '(?:' |
732 . '(?:' |
747 . '[^\[\]<>]+' // Shortcodes do not contain other shortcodes. Quantifier critical. |
733 . '[^\[\]<>]+' // Shortcodes do not contain other shortcodes. Quantifier critical. |
748 . '|' |
734 . '|' |
749 . '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >. |
735 . '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >. |
750 . ')*+' // Possessive critical. |
736 . ')*+' // Possessive critical. |
751 . '\]' // Find end of shortcode. |
737 . '\]' // Find end of shortcode. |
752 . '\]?'; // Shortcodes may end with ]] |
738 . '\]?'; // Shortcodes may end with ]]. |
753 // phpcs:enable |
739 // phpcs:enable |
754 |
740 |
755 return $regex; |
741 return $regex; |
756 } |
742 } |
757 |
743 |
758 /** |
744 /** |
759 * Replace characters or phrases within HTML elements only. |
745 * Replace characters or phrases within HTML elements only. |
760 * |
746 * |
761 * @since 4.2.3 |
747 * @since 4.2.3 |
762 * |
748 * |
763 * @param string $haystack The text which has to be formatted. |
749 * @param string $haystack The text which has to be formatted. |
764 * @param array $replace_pairs In the form array('from' => 'to', ...). |
750 * @param array $replace_pairs In the form array('from' => 'to', ...). |
765 * @return string The formatted text. |
751 * @return string The formatted text. |
766 */ |
752 */ |
767 function wp_replace_in_html_tags( $haystack, $replace_pairs ) { |
753 function wp_replace_in_html_tags( $haystack, $replace_pairs ) { |
768 // Find all elements. |
754 // Find all elements. |
769 $textarr = wp_html_split( $haystack ); |
755 $textarr = wp_html_split( $haystack ); |
839 } |
825 } |
840 |
826 |
841 $tagregexp = join( '|', array_map( 'preg_quote', array_keys( $shortcode_tags ) ) ); |
827 $tagregexp = join( '|', array_map( 'preg_quote', array_keys( $shortcode_tags ) ) ); |
842 $spaces = wp_spaces_regexp(); |
828 $spaces = wp_spaces_regexp(); |
843 |
829 |
844 // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- don't remove regex indentation |
830 // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound,WordPress.WhiteSpace.PrecisionAlignment.Found -- don't remove regex indentation |
845 $pattern = |
831 $pattern = |
846 '/' |
832 '/' |
847 . '<p>' // Opening paragraph |
833 . '<p>' // Opening paragraph. |
848 . '(?:' . $spaces . ')*+' // Optional leading whitespace |
834 . '(?:' . $spaces . ')*+' // Optional leading whitespace. |
849 . '(' // 1: The shortcode |
835 . '(' // 1: The shortcode. |
850 . '\\[' // Opening bracket |
836 . '\\[' // Opening bracket. |
851 . "($tagregexp)" // 2: Shortcode name |
837 . "($tagregexp)" // 2: Shortcode name. |
852 . '(?![\\w-])' // Not followed by word character or hyphen |
838 . '(?![\\w-])' // Not followed by word character or hyphen. |
853 // Unroll the loop: Inside the opening shortcode tag |
839 // Unroll the loop: Inside the opening shortcode tag. |
854 . '[^\\]\\/]*' // Not a closing bracket or forward slash |
840 . '[^\\]\\/]*' // Not a closing bracket or forward slash. |
855 . '(?:' |
841 . '(?:' |
856 . '\\/(?!\\])' // A forward slash not followed by a closing bracket |
842 . '\\/(?!\\])' // A forward slash not followed by a closing bracket. |
857 . '[^\\]\\/]*' // Not a closing bracket or forward slash |
843 . '[^\\]\\/]*' // Not a closing bracket or forward slash. |
858 . ')*?' |
844 . ')*?' |
859 . '(?:' |
845 . '(?:' |
860 . '\\/\\]' // Self closing tag and closing bracket |
846 . '\\/\\]' // Self closing tag and closing bracket. |
861 . '|' |
847 . '|' |
862 . '\\]' // Closing bracket |
848 . '\\]' // Closing bracket. |
863 . '(?:' // Unroll the loop: Optionally, anything between the opening and closing shortcode tags |
849 . '(?:' // Unroll the loop: Optionally, anything between the opening and closing shortcode tags. |
864 . '[^\\[]*+' // Not an opening bracket |
850 . '[^\\[]*+' // Not an opening bracket. |
865 . '(?:' |
851 . '(?:' |
866 . '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag |
852 . '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag. |
867 . '[^\\[]*+' // Not an opening bracket |
853 . '[^\\[]*+' // Not an opening bracket. |
868 . ')*+' |
854 . ')*+' |
869 . '\\[\\/\\2\\]' // Closing shortcode tag |
855 . '\\[\\/\\2\\]' // Closing shortcode tag. |
870 . ')?' |
856 . ')?' |
871 . ')' |
857 . ')' |
872 . ')' |
858 . ')' |
873 . '(?:' . $spaces . ')*+' // optional trailing whitespace |
859 . '(?:' . $spaces . ')*+' // Optional trailing whitespace. |
874 . '<\\/p>' // closing paragraph |
860 . '<\\/p>' // Closing paragraph. |
875 . '/'; |
861 . '/'; |
876 // phpcs:enable |
862 // phpcs:enable |
877 |
863 |
878 return preg_replace( $pattern, '$1', $pee ); |
864 return preg_replace( $pattern, '$1', $pee ); |
879 } |
865 } |
907 } elseif ( ( $c & 0xFC ) == 0xF8 ) { |
893 } elseif ( ( $c & 0xFC ) == 0xF8 ) { |
908 $n = 4; // 111110bb |
894 $n = 4; // 111110bb |
909 } elseif ( ( $c & 0xFE ) == 0xFC ) { |
895 } elseif ( ( $c & 0xFE ) == 0xFC ) { |
910 $n = 5; // 1111110b |
896 $n = 5; // 1111110b |
911 } else { |
897 } else { |
912 return false; // Does not match any model |
898 return false; // Does not match any model. |
913 } |
899 } |
914 for ( $j = 0; $j < $n; $j++ ) { // n bytes matching 10bbbbbb follow ? |
900 for ( $j = 0; $j < $n; $j++ ) { // n bytes matching 10bbbbbb follow ? |
915 if ( ( ++$i == $length ) || ( ( ord( $str[ $i ] ) & 0xC0 ) != 0x80 ) ) { |
901 if ( ( ++$i == $length ) || ( ( ord( $str[ $i ] ) & 0xC0 ) != 0x80 ) ) { |
916 return false; |
902 return false; |
917 } |
903 } |
927 * |
913 * |
928 * $quote_style can be set to ENT_COMPAT to encode " to |
914 * $quote_style can be set to ENT_COMPAT to encode " to |
929 * ", or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded. |
915 * ", or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded. |
930 * |
916 * |
931 * @since 1.2.2 |
917 * @since 1.2.2 |
918 * @since 5.5.0 `$quote_style` also accepts `ENT_XML1`. |
|
932 * @access private |
919 * @access private |
933 * |
920 * |
934 * @staticvar string $_charset |
921 * @param string $string The text which is to be encoded. |
935 * |
922 * @param int|string $quote_style Optional. Converts double quotes if set to ENT_COMPAT, |
936 * @param string $string The text which is to be encoded. |
923 * both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. |
937 * @param int|string $quote_style Optional. Converts double quotes if set to ENT_COMPAT, |
924 * Converts single and double quotes, as well as converting HTML |
938 * both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. |
925 * named entities (that are not also XML named entities) to their |
939 * Also compatible with old values; converting single quotes if set to 'single', |
926 * code points if set to ENT_XML1. Also compatible with old values; |
940 * double if set to 'double' or both if otherwise set. |
927 * converting single quotes if set to 'single', |
941 * Default is ENT_NOQUOTES. |
928 * double if set to 'double' or both if otherwise set. |
942 * @param string $charset Optional. The character encoding of the string. Default is false. |
929 * Default is ENT_NOQUOTES. |
943 * @param bool $double_encode Optional. Whether to encode existing html entities. Default is false. |
930 * @param false|string $charset Optional. The character encoding of the string. Default false. |
931 * @param bool $double_encode Optional. Whether to encode existing HTML entities. Default false. |
|
944 * @return string The encoded text with HTML entities. |
932 * @return string The encoded text with HTML entities. |
945 */ |
933 */ |
946 function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { |
934 function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { |
947 $string = (string) $string; |
935 $string = (string) $string; |
948 |
936 |
949 if ( 0 === strlen( $string ) ) { |
937 if ( 0 === strlen( $string ) ) { |
950 return ''; |
938 return ''; |
951 } |
939 } |
952 |
940 |
953 // Don't bother if there are no specialchars - saves some processing |
941 // Don't bother if there are no specialchars - saves some processing. |
954 if ( ! preg_match( '/[&<>"\']/', $string ) ) { |
942 if ( ! preg_match( '/[&<>"\']/', $string ) ) { |
955 return $string; |
943 return $string; |
956 } |
944 } |
957 |
945 |
958 // Account for the previous behaviour of the function when the $quote_style is not an accepted value |
946 // Account for the previous behaviour of the function when the $quote_style is not an accepted value. |
959 if ( empty( $quote_style ) ) { |
947 if ( empty( $quote_style ) ) { |
960 $quote_style = ENT_NOQUOTES; |
948 $quote_style = ENT_NOQUOTES; |
961 } elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) { |
949 } elseif ( ENT_XML1 === $quote_style ) { |
950 $quote_style = ENT_QUOTES | ENT_XML1; |
|
951 } elseif ( ! in_array( $quote_style, array( ENT_NOQUOTES, ENT_COMPAT, ENT_QUOTES, 'single', 'double' ), true ) ) { |
|
962 $quote_style = ENT_QUOTES; |
952 $quote_style = ENT_QUOTES; |
963 } |
953 } |
964 |
954 |
965 // Store the site charset as a static to avoid multiple calls to wp_load_alloptions() |
955 // Store the site charset as a static to avoid multiple calls to wp_load_alloptions(). |
966 if ( ! $charset ) { |
956 if ( ! $charset ) { |
967 static $_charset = null; |
957 static $_charset = null; |
968 if ( ! isset( $_charset ) ) { |
958 if ( ! isset( $_charset ) ) { |
969 $alloptions = wp_load_alloptions(); |
959 $alloptions = wp_load_alloptions(); |
970 $_charset = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : ''; |
960 $_charset = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : ''; |
971 } |
961 } |
972 $charset = $_charset; |
962 $charset = $_charset; |
973 } |
963 } |
974 |
964 |
975 if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ) ) ) { |
965 if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ), true ) ) { |
976 $charset = 'UTF-8'; |
966 $charset = 'UTF-8'; |
977 } |
967 } |
978 |
968 |
979 $_quote_style = $quote_style; |
969 $_quote_style = $quote_style; |
980 |
970 |
981 if ( $quote_style === 'double' ) { |
971 if ( 'double' === $quote_style ) { |
982 $quote_style = ENT_COMPAT; |
972 $quote_style = ENT_COMPAT; |
983 $_quote_style = ENT_COMPAT; |
973 $_quote_style = ENT_COMPAT; |
984 } elseif ( $quote_style === 'single' ) { |
974 } elseif ( 'single' === $quote_style ) { |
985 $quote_style = ENT_NOQUOTES; |
975 $quote_style = ENT_NOQUOTES; |
986 } |
976 } |
987 |
977 |
988 if ( ! $double_encode ) { |
978 if ( ! $double_encode ) { |
989 // Guarantee every &entity; is valid, convert &garbage; into &garbage; |
979 // Guarantee every &entity; is valid, convert &garbage; into &garbage; |
990 // This is required for PHP < 5.4.0 because ENT_HTML401 flag is unavailable. |
980 // This is required for PHP < 5.4.0 because ENT_HTML401 flag is unavailable. |
991 $string = wp_kses_normalize_entities( $string ); |
981 $string = wp_kses_normalize_entities( $string, ( $quote_style & ENT_XML1 ) ? 'xml' : 'html' ); |
992 } |
982 } |
993 |
983 |
994 $string = @htmlspecialchars( $string, $quote_style, $charset, $double_encode ); |
984 $string = htmlspecialchars( $string, $quote_style, $charset, $double_encode ); |
995 |
985 |
996 // Back-compat. |
986 // Back-compat. |
997 if ( 'single' === $_quote_style ) { |
987 if ( 'single' === $_quote_style ) { |
998 $string = str_replace( "'", ''', $string ); |
988 $string = str_replace( "'", ''', $string ); |
999 } |
989 } |
1026 |
1016 |
1027 if ( 0 === strlen( $string ) ) { |
1017 if ( 0 === strlen( $string ) ) { |
1028 return ''; |
1018 return ''; |
1029 } |
1019 } |
1030 |
1020 |
1031 // Don't bother if there are no entities - saves a lot of processing |
1021 // Don't bother if there are no entities - saves a lot of processing. |
1032 if ( strpos( $string, '&' ) === false ) { |
1022 if ( strpos( $string, '&' ) === false ) { |
1033 return $string; |
1023 return $string; |
1034 } |
1024 } |
1035 |
1025 |
1036 // Match the previous behaviour of _wp_specialchars() when the $quote_style is not an accepted value |
1026 // Match the previous behaviour of _wp_specialchars() when the $quote_style is not an accepted value. |
1037 if ( empty( $quote_style ) ) { |
1027 if ( empty( $quote_style ) ) { |
1038 $quote_style = ENT_NOQUOTES; |
1028 $quote_style = ENT_NOQUOTES; |
1039 } elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) { |
1029 } elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) { |
1040 $quote_style = ENT_QUOTES; |
1030 $quote_style = ENT_QUOTES; |
1041 } |
1031 } |
1042 |
1032 |
1043 // More complete than get_html_translation_table( HTML_SPECIALCHARS ) |
1033 // More complete than get_html_translation_table( HTML_SPECIALCHARS ). |
1044 $single = array( |
1034 $single = array( |
1045 ''' => '\'', |
1035 ''' => '\'', |
1046 ''' => '\'', |
1036 ''' => '\'', |
1047 ); |
1037 ); |
1048 $single_preg = array( |
1038 $single_preg = array( |
1072 '/�*62;/' => '>', |
1062 '/�*62;/' => '>', |
1073 '/�*38;/' => '&', |
1063 '/�*38;/' => '&', |
1074 '/�*26;/i' => '&', |
1064 '/�*26;/i' => '&', |
1075 ); |
1065 ); |
1076 |
1066 |
1077 if ( $quote_style === ENT_QUOTES ) { |
1067 if ( ENT_QUOTES === $quote_style ) { |
1078 $translation = array_merge( $single, $double, $others ); |
1068 $translation = array_merge( $single, $double, $others ); |
1079 $translation_preg = array_merge( $single_preg, $double_preg, $others_preg ); |
1069 $translation_preg = array_merge( $single_preg, $double_preg, $others_preg ); |
1080 } elseif ( $quote_style === ENT_COMPAT || $quote_style === 'double' ) { |
1070 } elseif ( ENT_COMPAT === $quote_style || 'double' === $quote_style ) { |
1081 $translation = array_merge( $double, $others ); |
1071 $translation = array_merge( $double, $others ); |
1082 $translation_preg = array_merge( $double_preg, $others_preg ); |
1072 $translation_preg = array_merge( $double_preg, $others_preg ); |
1083 } elseif ( $quote_style === 'single' ) { |
1073 } elseif ( 'single' === $quote_style ) { |
1084 $translation = array_merge( $single, $others ); |
1074 $translation = array_merge( $single, $others ); |
1085 $translation_preg = array_merge( $single_preg, $others_preg ); |
1075 $translation_preg = array_merge( $single_preg, $others_preg ); |
1086 } elseif ( $quote_style === ENT_NOQUOTES ) { |
1076 } elseif ( ENT_NOQUOTES === $quote_style ) { |
1087 $translation = $others; |
1077 $translation = $others; |
1088 $translation_preg = $others_preg; |
1078 $translation_preg = $others_preg; |
1089 } |
1079 } |
1090 |
1080 |
1091 // Remove zero padding on numeric entities |
1081 // Remove zero padding on numeric entities. |
1092 $string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string ); |
1082 $string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string ); |
1093 |
1083 |
1094 // Replace characters according to translation table |
1084 // Replace characters according to translation table. |
1095 return strtr( $string, $translation ); |
1085 return strtr( $string, $translation ); |
1096 } |
1086 } |
1097 |
1087 |
1098 /** |
1088 /** |
1099 * Checks for invalid UTF8 in a string. |
1089 * Checks for invalid UTF8 in a string. |
1100 * |
1090 * |
1101 * @since 2.8.0 |
1091 * @since 2.8.0 |
1102 * |
1092 * |
1103 * @staticvar bool $is_utf8 |
1093 * @param string $string The text which is to be checked. |
1104 * @staticvar bool $utf8_pcre |
1094 * @param bool $strip Optional. Whether to attempt to strip out invalid UTF8. Default false. |
1105 * |
|
1106 * @param string $string The text which is to be checked. |
|
1107 * @param bool $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false. |
|
1108 * @return string The checked text. |
1095 * @return string The checked text. |
1109 */ |
1096 */ |
1110 function wp_check_invalid_utf8( $string, $strip = false ) { |
1097 function wp_check_invalid_utf8( $string, $strip = false ) { |
1111 $string = (string) $string; |
1098 $string = (string) $string; |
1112 |
1099 |
1113 if ( 0 === strlen( $string ) ) { |
1100 if ( 0 === strlen( $string ) ) { |
1114 return ''; |
1101 return ''; |
1115 } |
1102 } |
1116 |
1103 |
1117 // Store the site charset as a static to avoid multiple calls to get_option() |
1104 // Store the site charset as a static to avoid multiple calls to get_option(). |
1118 static $is_utf8 = null; |
1105 static $is_utf8 = null; |
1119 if ( ! isset( $is_utf8 ) ) { |
1106 if ( ! isset( $is_utf8 ) ) { |
1120 $is_utf8 = in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ); |
1107 $is_utf8 = in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ), true ); |
1121 } |
1108 } |
1122 if ( ! $is_utf8 ) { |
1109 if ( ! $is_utf8 ) { |
1123 return $string; |
1110 return $string; |
1124 } |
1111 } |
1125 |
1112 |
1126 // Check for support for utf8 in the installed PCRE library once and store the result in a static |
1113 // Check for support for utf8 in the installed PCRE library once and store the result in a static. |
1127 static $utf8_pcre = null; |
1114 static $utf8_pcre = null; |
1128 if ( ! isset( $utf8_pcre ) ) { |
1115 if ( ! isset( $utf8_pcre ) ) { |
1116 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged |
|
1129 $utf8_pcre = @preg_match( '/^./u', 'a' ); |
1117 $utf8_pcre = @preg_match( '/^./u', 'a' ); |
1130 } |
1118 } |
1131 // We can't demand utf8 in the PCRE installation, so just return the string in those cases |
1119 // We can't demand utf8 in the PCRE installation, so just return the string in those cases. |
1132 if ( ! $utf8_pcre ) { |
1120 if ( ! $utf8_pcre ) { |
1133 return $string; |
1121 return $string; |
1134 } |
1122 } |
1135 |
1123 |
1136 // preg_match fails when it encounters invalid UTF8 in $string |
1124 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- preg_match fails when it encounters invalid UTF8 in $string. |
1137 if ( 1 === @preg_match( '/^./us', $string ) ) { |
1125 if ( 1 === @preg_match( '/^./us', $string ) ) { |
1138 return $string; |
1126 return $string; |
1139 } |
1127 } |
1140 |
1128 |
1141 // Attempt to strip the bad chars if requested (not recommended) |
1129 // Attempt to strip the bad chars if requested (not recommended). |
1142 if ( $strip && function_exists( 'iconv' ) ) { |
1130 if ( $strip && function_exists( 'iconv' ) ) { |
1143 return iconv( 'utf-8', 'utf-8', $string ); |
1131 return iconv( 'utf-8', 'utf-8', $string ); |
1144 } |
1132 } |
1145 |
1133 |
1146 return ''; |
1134 return ''; |
1598 return $string; |
1586 return $string; |
1599 } |
1587 } |
1600 |
1588 |
1601 if ( seems_utf8( $string ) ) { |
1589 if ( seems_utf8( $string ) ) { |
1602 $chars = array( |
1590 $chars = array( |
1603 // Decompositions for Latin-1 Supplement |
1591 // Decompositions for Latin-1 Supplement. |
1604 'ª' => 'a', |
1592 'ª' => 'a', |
1605 'º' => 'o', |
1593 'º' => 'o', |
1606 'À' => 'A', |
1594 'À' => 'A', |
1607 'Á' => 'A', |
1595 'Á' => 'A', |
1608 'Â' => 'A', |
1596 'Â' => 'A', |
1663 'ü' => 'u', |
1651 'ü' => 'u', |
1664 'ý' => 'y', |
1652 'ý' => 'y', |
1665 'þ' => 'th', |
1653 'þ' => 'th', |
1666 'ÿ' => 'y', |
1654 'ÿ' => 'y', |
1667 'Ø' => 'O', |
1655 'Ø' => 'O', |
1668 // Decompositions for Latin Extended-A |
1656 // Decompositions for Latin Extended-A. |
1669 'Ā' => 'A', |
1657 'Ā' => 'A', |
1670 'ā' => 'a', |
1658 'ā' => 'a', |
1671 'Ă' => 'A', |
1659 'Ă' => 'A', |
1672 'ă' => 'a', |
1660 'ă' => 'a', |
1673 'Ą' => 'A', |
1661 'Ą' => 'A', |
1792 'Ż' => 'Z', |
1780 'Ż' => 'Z', |
1793 'ż' => 'z', |
1781 'ż' => 'z', |
1794 'Ž' => 'Z', |
1782 'Ž' => 'Z', |
1795 'ž' => 'z', |
1783 'ž' => 'z', |
1796 'ſ' => 's', |
1784 'ſ' => 's', |
1797 // Decompositions for Latin Extended-B |
1785 // Decompositions for Latin Extended-B. |
1798 'Ș' => 'S', |
1786 'Ș' => 'S', |
1799 'ș' => 's', |
1787 'ș' => 's', |
1800 'Ț' => 'T', |
1788 'Ț' => 'T', |
1801 'ț' => 't', |
1789 'ț' => 't', |
1802 // Euro Sign |
1790 // Euro sign. |
1803 '€' => 'E', |
1791 '€' => 'E', |
1804 // GBP (Pound) Sign |
1792 // GBP (Pound) sign. |
1805 '£' => '', |
1793 '£' => '', |
1806 // Vowels with diacritic (Vietnamese) |
1794 // Vowels with diacritic (Vietnamese). |
1807 // unmarked |
1795 // Unmarked. |
1808 'Ơ' => 'O', |
1796 'Ơ' => 'O', |
1809 'ơ' => 'o', |
1797 'ơ' => 'o', |
1810 'Ư' => 'U', |
1798 'Ư' => 'U', |
1811 'ư' => 'u', |
1799 'ư' => 'u', |
1812 // grave accent |
1800 // Grave accent. |
1813 'Ầ' => 'A', |
1801 'Ầ' => 'A', |
1814 'ầ' => 'a', |
1802 'ầ' => 'a', |
1815 'Ằ' => 'A', |
1803 'Ằ' => 'A', |
1816 'ằ' => 'a', |
1804 'ằ' => 'a', |
1817 'Ề' => 'E', |
1805 'Ề' => 'E', |
1822 'ờ' => 'o', |
1810 'ờ' => 'o', |
1823 'Ừ' => 'U', |
1811 'Ừ' => 'U', |
1824 'ừ' => 'u', |
1812 'ừ' => 'u', |
1825 'Ỳ' => 'Y', |
1813 'Ỳ' => 'Y', |
1826 'ỳ' => 'y', |
1814 'ỳ' => 'y', |
1827 // hook |
1815 // Hook. |
1828 'Ả' => 'A', |
1816 'Ả' => 'A', |
1829 'ả' => 'a', |
1817 'ả' => 'a', |
1830 'Ẩ' => 'A', |
1818 'Ẩ' => 'A', |
1831 'ẩ' => 'a', |
1819 'ẩ' => 'a', |
1832 'Ẳ' => 'A', |
1820 'Ẳ' => 'A', |
1847 'ủ' => 'u', |
1835 'ủ' => 'u', |
1848 'Ử' => 'U', |
1836 'Ử' => 'U', |
1849 'ử' => 'u', |
1837 'ử' => 'u', |
1850 'Ỷ' => 'Y', |
1838 'Ỷ' => 'Y', |
1851 'ỷ' => 'y', |
1839 'ỷ' => 'y', |
1852 // tilde |
1840 // Tilde. |
1853 'Ẫ' => 'A', |
1841 'Ẫ' => 'A', |
1854 'ẫ' => 'a', |
1842 'ẫ' => 'a', |
1855 'Ẵ' => 'A', |
1843 'Ẵ' => 'A', |
1856 'ẵ' => 'a', |
1844 'ẵ' => 'a', |
1857 'Ẽ' => 'E', |
1845 'Ẽ' => 'E', |
1864 'ỡ' => 'o', |
1852 'ỡ' => 'o', |
1865 'Ữ' => 'U', |
1853 'Ữ' => 'U', |
1866 'ữ' => 'u', |
1854 'ữ' => 'u', |
1867 'Ỹ' => 'Y', |
1855 'Ỹ' => 'Y', |
1868 'ỹ' => 'y', |
1856 'ỹ' => 'y', |
1869 // acute accent |
1857 // Acute accent. |
1870 'Ấ' => 'A', |
1858 'Ấ' => 'A', |
1871 'ấ' => 'a', |
1859 'ấ' => 'a', |
1872 'Ắ' => 'A', |
1860 'Ắ' => 'A', |
1873 'ắ' => 'a', |
1861 'ắ' => 'a', |
1874 'Ế' => 'E', |
1862 'Ế' => 'E', |
1877 'ố' => 'o', |
1865 'ố' => 'o', |
1878 'Ớ' => 'O', |
1866 'Ớ' => 'O', |
1879 'ớ' => 'o', |
1867 'ớ' => 'o', |
1880 'Ứ' => 'U', |
1868 'Ứ' => 'U', |
1881 'ứ' => 'u', |
1869 'ứ' => 'u', |
1882 // dot below |
1870 // Dot below. |
1883 'Ạ' => 'A', |
1871 'Ạ' => 'A', |
1884 'ạ' => 'a', |
1872 'ạ' => 'a', |
1885 'Ậ' => 'A', |
1873 'Ậ' => 'A', |
1886 'ậ' => 'a', |
1874 'ậ' => 'a', |
1887 'Ặ' => 'A', |
1875 'Ặ' => 'A', |
1902 'ụ' => 'u', |
1890 'ụ' => 'u', |
1903 'Ự' => 'U', |
1891 'Ự' => 'U', |
1904 'ự' => 'u', |
1892 'ự' => 'u', |
1905 'Ỵ' => 'Y', |
1893 'Ỵ' => 'Y', |
1906 'ỵ' => 'y', |
1894 'ỵ' => 'y', |
1907 // Vowels with diacritic (Chinese, Hanyu Pinyin) |
1895 // Vowels with diacritic (Chinese, Hanyu Pinyin). |
1908 'ɑ' => 'a', |
1896 'ɑ' => 'a', |
1909 // macron |
1897 // Macron. |
1910 'Ǖ' => 'U', |
1898 'Ǖ' => 'U', |
1911 'ǖ' => 'u', |
1899 'ǖ' => 'u', |
1912 // acute accent |
1900 // Acute accent. |
1913 'Ǘ' => 'U', |
1901 'Ǘ' => 'U', |
1914 'ǘ' => 'u', |
1902 'ǘ' => 'u', |
1915 // caron |
1903 // Caron. |
1916 'Ǎ' => 'A', |
1904 'Ǎ' => 'A', |
1917 'ǎ' => 'a', |
1905 'ǎ' => 'a', |
1918 'Ǐ' => 'I', |
1906 'Ǐ' => 'I', |
1919 'ǐ' => 'i', |
1907 'ǐ' => 'i', |
1920 'Ǒ' => 'O', |
1908 'Ǒ' => 'O', |
1921 'ǒ' => 'o', |
1909 'ǒ' => 'o', |
1922 'Ǔ' => 'U', |
1910 'Ǔ' => 'U', |
1923 'ǔ' => 'u', |
1911 'ǔ' => 'u', |
1924 'Ǚ' => 'U', |
1912 'Ǚ' => 'U', |
1925 'ǚ' => 'u', |
1913 'ǚ' => 'u', |
1926 // grave accent |
1914 // Grave accent. |
1927 'Ǜ' => 'U', |
1915 'Ǜ' => 'U', |
1928 'ǜ' => 'u', |
1916 'ǜ' => 'u', |
1929 ); |
1917 ); |
1930 |
1918 |
1931 // Used for locale-specific rules |
1919 // Used for locale-specific rules. |
1932 $locale = get_locale(); |
1920 $locale = get_locale(); |
1933 |
1921 |
1934 if ( 'de_DE' == $locale || 'de_DE_formal' == $locale || 'de_CH' == $locale || 'de_CH_informal' == $locale ) { |
1922 if ( in_array( $locale, array( 'de_DE', 'de_DE_formal', 'de_CH', 'de_CH_informal' ), true ) ) { |
1935 $chars['Ä'] = 'Ae'; |
1923 $chars['Ä'] = 'Ae'; |
1936 $chars['ä'] = 'ae'; |
1924 $chars['ä'] = 'ae'; |
1937 $chars['Ö'] = 'Oe'; |
1925 $chars['Ö'] = 'Oe'; |
1938 $chars['ö'] = 'oe'; |
1926 $chars['ö'] = 'oe'; |
1939 $chars['Ü'] = 'Ue'; |
1927 $chars['Ü'] = 'Ue'; |
1954 } |
1942 } |
1955 |
1943 |
1956 $string = strtr( $string, $chars ); |
1944 $string = strtr( $string, $chars ); |
1957 } else { |
1945 } else { |
1958 $chars = array(); |
1946 $chars = array(); |
1959 // Assume ISO-8859-1 if not UTF-8 |
1947 // Assume ISO-8859-1 if not UTF-8. |
1960 $chars['in'] = "\x80\x83\x8a\x8e\x9a\x9e" |
1948 $chars['in'] = "\x80\x83\x8a\x8e\x9a\x9e" |
1961 . "\x9f\xa2\xa5\xb5\xc0\xc1\xc2" |
1949 . "\x9f\xa2\xa5\xb5\xc0\xc1\xc2" |
1962 . "\xc3\xc4\xc5\xc7\xc8\xc9\xca" |
1950 . "\xc3\xc4\xc5\xc7\xc8\xc9\xca" |
1963 . "\xcb\xcc\xcd\xce\xcf\xd1\xd2" |
1951 . "\xcb\xcc\xcd\xce\xcf\xd1\xd2" |
1964 . "\xd3\xd4\xd5\xd6\xd8\xd9\xda" |
1952 . "\xd3\xd4\xd5\xd6\xd8\xd9\xda" |
1990 * and end of filename. It is not guaranteed that this function will return a |
1978 * and end of filename. It is not guaranteed that this function will return a |
1991 * filename that is allowed to be uploaded. |
1979 * filename that is allowed to be uploaded. |
1992 * |
1980 * |
1993 * @since 2.1.0 |
1981 * @since 2.1.0 |
1994 * |
1982 * |
1995 * @param string $filename The filename to be sanitized |
1983 * @param string $filename The filename to be sanitized. |
1996 * @return string The sanitized filename |
1984 * @return string The sanitized filename. |
1997 */ |
1985 */ |
1998 function sanitize_file_name( $filename ) { |
1986 function sanitize_file_name( $filename ) { |
1999 $filename_raw = $filename; |
1987 $filename_raw = $filename; |
2000 $special_chars = array( '?', '[', ']', '/', '\\', '=', '<', '>', ':', ';', ',', "'", '"', '&', '$', '#', '*', '(', ')', '|', '~', '`', '!', '{', '}', '%', '+', chr( 0 ) ); |
1988 $filename = remove_accents( $filename ); |
1989 |
|
1990 $special_chars = array( '?', '[', ']', '/', '\\', '=', '<', '>', ':', ';', ',', "'", '"', '&', '$', '#', '*', '(', ')', '|', '~', '`', '!', '{', '}', '%', '+', '’', '«', '»', '”', '“', chr( 0 ) ); |
|
1991 |
|
1992 // Check for support for utf8 in the installed PCRE library once and store the result in a static. |
|
1993 static $utf8_pcre = null; |
|
1994 if ( ! isset( $utf8_pcre ) ) { |
|
1995 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged |
|
1996 $utf8_pcre = @preg_match( '/^./u', 'a' ); |
|
1997 } |
|
1998 |
|
1999 if ( ! seems_utf8( $filename ) ) { |
|
2000 $_ext = pathinfo( $filename, PATHINFO_EXTENSION ); |
|
2001 $_name = pathinfo( $filename, PATHINFO_FILENAME ); |
|
2002 $filename = sanitize_title_with_dashes( $_name ) . '.' . $_ext; |
|
2003 } |
|
2004 |
|
2005 if ( $utf8_pcre ) { |
|
2006 $filename = preg_replace( "#\x{00a0}#siu", ' ', $filename ); |
|
2007 } |
|
2008 |
|
2001 /** |
2009 /** |
2002 * Filters the list of characters to remove from a filename. |
2010 * Filters the list of characters to remove from a filename. |
2003 * |
2011 * |
2004 * @since 2.8.0 |
2012 * @since 2.8.0 |
2005 * |
2013 * |
2006 * @param array $special_chars Characters to remove. |
2014 * @param string[] $special_chars Array of characters to remove. |
2007 * @param string $filename_raw Filename as it was passed into sanitize_file_name(). |
2015 * @param string $filename_raw The original filename to be sanitized. |
2008 */ |
2016 */ |
2009 $special_chars = apply_filters( 'sanitize_file_name_chars', $special_chars, $filename_raw ); |
2017 $special_chars = apply_filters( 'sanitize_file_name_chars', $special_chars, $filename_raw ); |
2010 $filename = preg_replace( "#\x{00a0}#siu", ' ', $filename ); |
2018 |
2011 $filename = str_replace( $special_chars, '', $filename ); |
2019 $filename = str_replace( $special_chars, '', $filename ); |
2012 $filename = str_replace( array( '%20', '+' ), '-', $filename ); |
2020 $filename = str_replace( array( '%20', '+' ), '-', $filename ); |
2013 $filename = preg_replace( '/[\r\n\t -]+/', '-', $filename ); |
2021 $filename = preg_replace( '/[\r\n\t -]+/', '-', $filename ); |
2014 $filename = trim( $filename, '.-_' ); |
2022 $filename = trim( $filename, '.-_' ); |
2015 |
2023 |
2016 if ( false === strpos( $filename, '.' ) ) { |
2024 if ( false === strpos( $filename, '.' ) ) { |
2017 $mime_types = wp_get_mime_types(); |
2025 $mime_types = wp_get_mime_types(); |
2018 $filetype = wp_check_filetype( 'test.' . $filename, $mime_types ); |
2026 $filetype = wp_check_filetype( 'test.' . $filename, $mime_types ); |
2019 if ( $filetype['ext'] === $filename ) { |
2027 if ( $filetype['ext'] === $filename ) { |
2020 $filename = 'unnamed-file.' . $filetype['ext']; |
2028 $filename = 'unnamed-file.' . $filetype['ext']; |
2021 } |
2029 } |
2022 } |
2030 } |
2023 |
2031 |
2024 // Split the filename into a base and extension[s] |
2032 // Split the filename into a base and extension[s]. |
2025 $parts = explode( '.', $filename ); |
2033 $parts = explode( '.', $filename ); |
2026 |
2034 |
2027 // Return if only one extension |
2035 // Return if only one extension. |
2028 if ( count( $parts ) <= 2 ) { |
2036 if ( count( $parts ) <= 2 ) { |
2029 /** |
2037 /** |
2030 * Filters a sanitized filename string. |
2038 * Filters a sanitized filename string. |
2031 * |
2039 * |
2032 * @since 2.8.0 |
2040 * @since 2.8.0 |
2035 * @param string $filename_raw The filename prior to sanitization. |
2043 * @param string $filename_raw The filename prior to sanitization. |
2036 */ |
2044 */ |
2037 return apply_filters( 'sanitize_file_name', $filename, $filename_raw ); |
2045 return apply_filters( 'sanitize_file_name', $filename, $filename_raw ); |
2038 } |
2046 } |
2039 |
2047 |
2040 // Process multiple extensions |
2048 // Process multiple extensions. |
2041 $filename = array_shift( $parts ); |
2049 $filename = array_shift( $parts ); |
2042 $extension = array_pop( $parts ); |
2050 $extension = array_pop( $parts ); |
2043 $mimes = get_allowed_mime_types(); |
2051 $mimes = get_allowed_mime_types(); |
2044 |
2052 |
2045 /* |
2053 /* |
2046 * Loop over any intermediate extensions. Postfix them with a trailing underscore |
2054 * Loop over any intermediate extensions. Postfix them with a trailing underscore |
2047 * if they are a 2 - 5 character long alpha string not in the extension whitelist. |
2055 * if they are a 2 - 5 character long alpha string not in the allowed extension list. |
2048 */ |
2056 */ |
2049 foreach ( (array) $parts as $part ) { |
2057 foreach ( (array) $parts as $part ) { |
2050 $filename .= '.' . $part; |
2058 $filename .= '.' . $part; |
2051 |
2059 |
2052 if ( preg_match( '/^[a-zA-Z]{2,5}\d?$/', $part ) ) { |
2060 if ( preg_match( '/^[a-zA-Z]{2,5}\d?$/', $part ) ) { |
2061 if ( ! $allowed ) { |
2069 if ( ! $allowed ) { |
2062 $filename .= '_'; |
2070 $filename .= '_'; |
2063 } |
2071 } |
2064 } |
2072 } |
2065 } |
2073 } |
2074 |
|
2066 $filename .= '.' . $extension; |
2075 $filename .= '.' . $extension; |
2076 |
|
2067 /** This filter is documented in wp-includes/formatting.php */ |
2077 /** This filter is documented in wp-includes/formatting.php */ |
2068 return apply_filters( 'sanitize_file_name', $filename, $filename_raw ); |
2078 return apply_filters( 'sanitize_file_name', $filename, $filename_raw ); |
2069 } |
2079 } |
2070 |
2080 |
2071 /** |
2081 /** |
2077 * parameters for the {@see 'sanitize_user'} filter. |
2087 * parameters for the {@see 'sanitize_user'} filter. |
2078 * |
2088 * |
2079 * @since 2.0.0 |
2089 * @since 2.0.0 |
2080 * |
2090 * |
2081 * @param string $username The username to be sanitized. |
2091 * @param string $username The username to be sanitized. |
2082 * @param bool $strict If set limits $username to specific characters. Default false. |
2092 * @param bool $strict Optional. If set limits $username to specific characters. |
2093 * Default false. |
|
2083 * @return string The sanitized username, after passing through filters. |
2094 * @return string The sanitized username, after passing through filters. |
2084 */ |
2095 */ |
2085 function sanitize_user( $username, $strict = false ) { |
2096 function sanitize_user( $username, $strict = false ) { |
2086 $raw_username = $username; |
2097 $raw_username = $username; |
2087 $username = wp_strip_all_tags( $username ); |
2098 $username = wp_strip_all_tags( $username ); |
2088 $username = remove_accents( $username ); |
2099 $username = remove_accents( $username ); |
2089 // Kill octets |
2100 // Kill octets. |
2090 $username = preg_replace( '|%([a-fA-F0-9][a-fA-F0-9])|', '', $username ); |
2101 $username = preg_replace( '|%([a-fA-F0-9][a-fA-F0-9])|', '', $username ); |
2091 $username = preg_replace( '/&.+?;/', '', $username ); // Kill entities |
2102 // Kill entities. |
2103 $username = preg_replace( '/&.+?;/', '', $username ); |
|
2092 |
2104 |
2093 // If strict, reduce to ASCII for max portability. |
2105 // If strict, reduce to ASCII for max portability. |
2094 if ( $strict ) { |
2106 if ( $strict ) { |
2095 $username = preg_replace( '|[^a-z0-9 _.\-@]|i', '', $username ); |
2107 $username = preg_replace( '|[^a-z0-9 _.\-@]|i', '', $username ); |
2096 } |
2108 } |
2097 |
2109 |
2098 $username = trim( $username ); |
2110 $username = trim( $username ); |
2099 // Consolidate contiguous whitespace |
2111 // Consolidate contiguous whitespace. |
2100 $username = preg_replace( '|\s+|', ' ', $username ); |
2112 $username = preg_replace( '|\s+|', ' ', $username ); |
2101 |
2113 |
2102 /** |
2114 /** |
2103 * Filters a sanitized username string. |
2115 * Filters a sanitized username string. |
2104 * |
2116 * |
2105 * @since 2.0.1 |
2117 * @since 2.0.1 |
2106 * |
2118 * |
2107 * @param string $username Sanitized username. |
2119 * @param string $username Sanitized username. |
2108 * @param string $raw_username The username prior to sanitization. |
2120 * @param string $raw_username The username prior to sanitization. |
2109 * @param bool $strict Whether to limit the sanitization to specific characters. Default false. |
2121 * @param bool $strict Whether to limit the sanitization to specific characters. |
2110 */ |
2122 */ |
2111 return apply_filters( 'sanitize_user', $username, $raw_username, $strict ); |
2123 return apply_filters( 'sanitize_user', $username, $raw_username, $strict ); |
2112 } |
2124 } |
2113 |
2125 |
2114 /** |
2126 /** |
2115 * Sanitizes a string key. |
2127 * Sanitizes a string key. |
2116 * |
2128 * |
2117 * Keys are used as internal identifiers. Lowercase alphanumeric characters, dashes and underscores are allowed. |
2129 * Keys are used as internal identifiers. Lowercase alphanumeric characters, |
2130 * dashes, and underscores are allowed. |
|
2118 * |
2131 * |
2119 * @since 3.0.0 |
2132 * @since 3.0.0 |
2120 * |
2133 * |
2121 * @param string $key String key |
2134 * @param string $key String key |
2122 * @return string Sanitized key |
2135 * @return string Sanitized key |
2136 */ |
2149 */ |
2137 return apply_filters( 'sanitize_key', $key, $raw_key ); |
2150 return apply_filters( 'sanitize_key', $key, $raw_key ); |
2138 } |
2151 } |
2139 |
2152 |
2140 /** |
2153 /** |
2141 * Sanitizes a title, or returns a fallback title. |
2154 * Sanitizes a string into a slug, which can be used in URLs or HTML attributes. |
2142 * |
2155 * |
2143 * Specifically, HTML and PHP tags are stripped. Further actions can be added |
2156 * By default, converts accent characters to ASCII characters and further |
2144 * via the plugin API. If $title is empty and $fallback_title is set, the latter |
2157 * limits the output to alphanumeric characters, underscore (_) and dash (-) |
2145 * will be used. |
2158 * through the {@see 'sanitize_title'} filter. |
2159 * |
|
2160 * If `$title` is empty and `$fallback_title` is set, the latter will be used. |
|
2146 * |
2161 * |
2147 * @since 1.0.0 |
2162 * @since 1.0.0 |
2148 * |
2163 * |
2149 * @param string $title The string to be sanitized. |
2164 * @param string $title The string to be sanitized. |
2150 * @param string $fallback_title Optional. A title to use if $title is empty. |
2165 * @param string $fallback_title Optional. A title to use if $title is empty. Default empty. |
2151 * @param string $context Optional. The operation for which the string is sanitized |
2166 * @param string $context Optional. The operation for which the string is sanitized. |
2167 * Default 'save'. |
|
2152 * @return string The sanitized string. |
2168 * @return string The sanitized string. |
2153 */ |
2169 */ |
2154 function sanitize_title( $title, $fallback_title = '', $context = 'save' ) { |
2170 function sanitize_title( $title, $fallback_title = '', $context = 'save' ) { |
2155 $raw_title = $title; |
2171 $raw_title = $title; |
2156 |
2172 |
2157 if ( 'save' == $context ) { |
2173 if ( 'save' === $context ) { |
2158 $title = remove_accents( $title ); |
2174 $title = remove_accents( $title ); |
2159 } |
2175 } |
2160 |
2176 |
2161 /** |
2177 /** |
2162 * Filters a sanitized title string. |
2178 * Filters a sanitized title string. |
2197 * Whitespace becomes a dash. |
2213 * Whitespace becomes a dash. |
2198 * |
2214 * |
2199 * @since 1.2.0 |
2215 * @since 1.2.0 |
2200 * |
2216 * |
2201 * @param string $title The title to be sanitized. |
2217 * @param string $title The title to be sanitized. |
2202 * @param string $raw_title Optional. Not used. |
2218 * @param string $raw_title Optional. Not used. Default empty. |
2203 * @param string $context Optional. The operation for which the string is sanitized. |
2219 * @param string $context Optional. The operation for which the string is sanitized. |
2220 * Default 'display'. |
|
2204 * @return string The sanitized title. |
2221 * @return string The sanitized title. |
2205 */ |
2222 */ |
2206 function sanitize_title_with_dashes( $title, $raw_title = '', $context = 'display' ) { |
2223 function sanitize_title_with_dashes( $title, $raw_title = '', $context = 'display' ) { |
2207 $title = strip_tags( $title ); |
2224 $title = strip_tags( $title ); |
2208 // Preserve escaped octets. |
2225 // Preserve escaped octets. |
2219 $title = utf8_uri_encode( $title, 200 ); |
2236 $title = utf8_uri_encode( $title, 200 ); |
2220 } |
2237 } |
2221 |
2238 |
2222 $title = strtolower( $title ); |
2239 $title = strtolower( $title ); |
2223 |
2240 |
2224 if ( 'save' == $context ) { |
2241 if ( 'save' === $context ) { |
2225 // Convert nbsp, ndash and mdash to hyphens |
2242 // Convert  , &ndash, and &mdash to hyphens. |
2226 $title = str_replace( array( '%c2%a0', '%e2%80%93', '%e2%80%94' ), '-', $title ); |
2243 $title = str_replace( array( '%c2%a0', '%e2%80%93', '%e2%80%94' ), '-', $title ); |
2227 // Convert nbsp, ndash and mdash HTML entities to hyphens |
2244 // Convert  , &ndash, and &mdash HTML entities to hyphens. |
2228 $title = str_replace( array( ' ', ' ', '–', '–', '—', '—' ), '-', $title ); |
2245 $title = str_replace( array( ' ', ' ', '–', '–', '—', '—' ), '-', $title ); |
2229 // Convert forward slash to hyphen |
2246 // Convert forward slash to hyphen. |
2230 $title = str_replace( '/', '-', $title ); |
2247 $title = str_replace( '/', '-', $title ); |
2231 |
2248 |
2232 // Strip these characters entirely |
2249 // Strip these characters entirely. |
2233 $title = str_replace( |
2250 $title = str_replace( |
2234 array( |
2251 array( |
2235 // soft hyphens |
2252 // Soft hyphens. |
2236 '%c2%ad', |
2253 '%c2%ad', |
2237 // iexcl and iquest |
2254 // ¡ and ¿. |
2238 '%c2%a1', |
2255 '%c2%a1', |
2239 '%c2%bf', |
2256 '%c2%bf', |
2240 // angle quotes |
2257 // Angle quotes. |
2241 '%c2%ab', |
2258 '%c2%ab', |
2242 '%c2%bb', |
2259 '%c2%bb', |
2243 '%e2%80%b9', |
2260 '%e2%80%b9', |
2244 '%e2%80%ba', |
2261 '%e2%80%ba', |
2245 // curly quotes |
2262 // Curly quotes. |
2246 '%e2%80%98', |
2263 '%e2%80%98', |
2247 '%e2%80%99', |
2264 '%e2%80%99', |
2248 '%e2%80%9c', |
2265 '%e2%80%9c', |
2249 '%e2%80%9d', |
2266 '%e2%80%9d', |
2250 '%e2%80%9a', |
2267 '%e2%80%9a', |
2251 '%e2%80%9b', |
2268 '%e2%80%9b', |
2252 '%e2%80%9e', |
2269 '%e2%80%9e', |
2253 '%e2%80%9f', |
2270 '%e2%80%9f', |
2254 // copy, reg, deg, hellip and trade |
2271 // Bullet. |
2272 '%e2%80%a2', |
|
2273 // ©, ®, °, &hellip, and &trade. |
|
2255 '%c2%a9', |
2274 '%c2%a9', |
2256 '%c2%ae', |
2275 '%c2%ae', |
2257 '%c2%b0', |
2276 '%c2%b0', |
2258 '%e2%80%a6', |
2277 '%e2%80%a6', |
2259 '%e2%84%a2', |
2278 '%e2%84%a2', |
2260 // acute accents |
2279 // Acute accents. |
2261 '%c2%b4', |
2280 '%c2%b4', |
2262 '%cb%8a', |
2281 '%cb%8a', |
2263 '%cc%81', |
2282 '%cc%81', |
2264 '%cd%81', |
2283 '%cd%81', |
2265 // grave accent, macron, caron |
2284 // Grave accent, macron, caron. |
2266 '%cc%80', |
2285 '%cc%80', |
2267 '%cc%84', |
2286 '%cc%84', |
2268 '%cc%8c', |
2287 '%cc%8c', |
2269 ), |
2288 ), |
2270 '', |
2289 '', |
2271 $title |
2290 $title |
2272 ); |
2291 ); |
2273 |
2292 |
2274 // Convert times to x |
2293 // Convert × to 'x'. |
2275 $title = str_replace( '%c3%97', 'x', $title ); |
2294 $title = str_replace( '%c3%97', 'x', $title ); |
2276 } |
2295 } |
2277 |
2296 |
2278 $title = preg_replace( '/&.+?;/', '', $title ); // kill entities |
2297 // Kill entities. |
2298 $title = preg_replace( '/&.+?;/', '', $title ); |
|
2279 $title = str_replace( '.', '-', $title ); |
2299 $title = str_replace( '.', '-', $title ); |
2280 |
2300 |
2281 $title = preg_replace( '/[^%a-z0-9 _-]/', '', $title ); |
2301 $title = preg_replace( '/[^%a-z0-9 _-]/', '', $title ); |
2282 $title = preg_replace( '/\s+/', '-', $title ); |
2302 $title = preg_replace( '/\s+/', '-', $title ); |
2283 $title = preg_replace( '|-+|', '-', $title ); |
2303 $title = preg_replace( '|-+|', '-', $title ); |
2320 * @param string $fallback Optional. The value to return if the sanitization ends up as an empty string. |
2340 * @param string $fallback Optional. The value to return if the sanitization ends up as an empty string. |
2321 * Defaults to an empty string. |
2341 * Defaults to an empty string. |
2322 * @return string The sanitized value |
2342 * @return string The sanitized value |
2323 */ |
2343 */ |
2324 function sanitize_html_class( $class, $fallback = '' ) { |
2344 function sanitize_html_class( $class, $fallback = '' ) { |
2325 //Strip out any % encoded octets |
2345 // Strip out any %-encoded octets. |
2326 $sanitized = preg_replace( '|%[a-fA-F0-9][a-fA-F0-9]|', '', $class ); |
2346 $sanitized = preg_replace( '|%[a-fA-F0-9][a-fA-F0-9]|', '', $class ); |
2327 |
2347 |
2328 //Limit to A-Z,a-z,0-9,_,- |
2348 // Limit to A-Z, a-z, 0-9, '_', '-'. |
2329 $sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $sanitized ); |
2349 $sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $sanitized ); |
2330 |
2350 |
2331 if ( '' == $sanitized && $fallback ) { |
2351 if ( '' === $sanitized && $fallback ) { |
2332 return sanitize_html_class( $fallback ); |
2352 return sanitize_html_class( $fallback ); |
2333 } |
2353 } |
2334 /** |
2354 /** |
2335 * Filters a sanitized HTML class string. |
2355 * Filters a sanitized HTML class string. |
2336 * |
2356 * |
2372 * @param string $content String with entities that need converting. |
2392 * @param string $content String with entities that need converting. |
2373 * @return string Converted string. |
2393 * @return string Converted string. |
2374 */ |
2394 */ |
2375 function convert_invalid_entities( $content ) { |
2395 function convert_invalid_entities( $content ) { |
2376 $wp_htmltranswinuni = array( |
2396 $wp_htmltranswinuni = array( |
2377 '€' => '€', // the Euro sign |
2397 '€' => '€', // The Euro sign. |
2378 '' => '', |
2398 '' => '', |
2379 '‚' => '‚', // these are Windows CP1252 specific characters |
2399 '‚' => '‚', // These are Windows CP1252 specific characters. |
2380 'ƒ' => 'ƒ', // they would look weird on non-Windows browsers |
2400 'ƒ' => 'ƒ', // They would look weird on non-Windows browsers. |
2381 '„' => '„', |
2401 '„' => '„', |
2382 '…' => '…', |
2402 '…' => '…', |
2383 '†' => '†', |
2403 '†' => '†', |
2384 '‡' => '‡', |
2404 '‡' => '‡', |
2385 'ˆ' => 'ˆ', |
2405 'ˆ' => 'ˆ', |
2422 * |
2442 * |
2423 * @param string $text Text to be balanced |
2443 * @param string $text Text to be balanced |
2424 * @param bool $force If true, forces balancing, ignoring the value of the option. Default false. |
2444 * @param bool $force If true, forces balancing, ignoring the value of the option. Default false. |
2425 * @return string Balanced text |
2445 * @return string Balanced text |
2426 */ |
2446 */ |
2427 function balanceTags( $text, $force = false ) { |
2447 function balanceTags( $text, $force = false ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid |
2428 if ( $force || get_option( 'use_balanceTags' ) == 1 ) { |
2448 if ( $force || (int) get_option( 'use_balanceTags' ) === 1 ) { |
2429 return force_balance_tags( $text ); |
2449 return force_balance_tags( $text ); |
2430 } else { |
2450 } else { |
2431 return $text; |
2451 return $text; |
2432 } |
2452 } |
2433 } |
2453 } |
2434 |
2454 |
2435 /** |
2455 /** |
2436 * Balances tags of string using a modified stack. |
2456 * Balances tags of string using a modified stack. |
2437 * |
2457 * |
2438 * @since 2.0.4 |
2458 * @since 2.0.4 |
2459 * @since 5.3.0 Improve accuracy and add support for custom element tags. |
|
2439 * |
2460 * |
2440 * @author Leonard Lin <leonard@acm.org> |
2461 * @author Leonard Lin <leonard@acm.org> |
2441 * @license GPL |
2462 * @license GPL |
2442 * @copyright November 4, 2001 |
2463 * @copyright November 4, 2001 |
2443 * @version 1.1 |
2464 * @version 1.1 |
2453 function force_balance_tags( $text ) { |
2474 function force_balance_tags( $text ) { |
2454 $tagstack = array(); |
2475 $tagstack = array(); |
2455 $stacksize = 0; |
2476 $stacksize = 0; |
2456 $tagqueue = ''; |
2477 $tagqueue = ''; |
2457 $newtext = ''; |
2478 $newtext = ''; |
2458 // Known single-entity/self-closing tags |
2479 // Known single-entity/self-closing tags. |
2459 $single_tags = array( 'area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param', 'source' ); |
2480 $single_tags = array( 'area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param', 'source' ); |
2460 // Tags that can be immediately nested within themselves |
2481 // Tags that can be immediately nested within themselves. |
2461 $nestable_tags = array( 'blockquote', 'div', 'object', 'q', 'span' ); |
2482 $nestable_tags = array( 'blockquote', 'div', 'object', 'q', 'span' ); |
2462 |
2483 |
2463 // WP bug fix for comments - in case you REALLY meant to type '< !--' |
2484 // WP bug fix for comments - in case you REALLY meant to type '< !--'. |
2464 $text = str_replace( '< !--', '< !--', $text ); |
2485 $text = str_replace( '< !--', '< !--', $text ); |
2465 // WP bug fix for LOVE <3 (and other situations with '<' before a number) |
2486 // WP bug fix for LOVE <3 (and other situations with '<' before a number). |
2466 $text = preg_replace( '#<([0-9]{1})#', '<$1', $text ); |
2487 $text = preg_replace( '#<([0-9]{1})#', '<$1', $text ); |
2467 |
2488 |
2468 while ( preg_match( '/<(\/?[\w:]*)\s*([^>]*)>/', $text, $regex ) ) { |
2489 /** |
2490 * Matches supported tags. |
|
2491 * |
|
2492 * To get the pattern as a string without the comments paste into a PHP |
|
2493 * REPL like `php -a`. |
|
2494 * |
|
2495 * @see https://html.spec.whatwg.org/#elements-2 |
|
2496 * @see https://w3c.github.io/webcomponents/spec/custom/#valid-custom-element-name |
|
2497 * |
|
2498 * @example |
|
2499 * ~# php -a |
|
2500 * php > $s = [paste copied contents of expression below including parentheses]; |
|
2501 * php > echo $s; |
|
2502 */ |
|
2503 $tag_pattern = ( |
|
2504 '#<' . // Start with an opening bracket. |
|
2505 '(/?)' . // Group 1 - If it's a closing tag it'll have a leading slash. |
|
2506 '(' . // Group 2 - Tag name. |
|
2507 // Custom element tags have more lenient rules than HTML tag names. |
|
2508 '(?:[a-z](?:[a-z0-9._]*)-(?:[a-z0-9._-]+)+)' . |
|
2509 '|' . |
|
2510 // Traditional tag rules approximate HTML tag names. |
|
2511 '(?:[\w:]+)' . |
|
2512 ')' . |
|
2513 '(?:' . |
|
2514 // We either immediately close the tag with its '>' and have nothing here. |
|
2515 '\s*' . |
|
2516 '(/?)' . // Group 3 - "attributes" for empty tag. |
|
2517 '|' . |
|
2518 // Or we must start with space characters to separate the tag name from the attributes (or whitespace). |
|
2519 '(\s+)' . // Group 4 - Pre-attribute whitespace. |
|
2520 '([^>]*)' . // Group 5 - Attributes. |
|
2521 ')' . |
|
2522 '>#' // End with a closing bracket. |
|
2523 ); |
|
2524 |
|
2525 while ( preg_match( $tag_pattern, $text, $regex ) ) { |
|
2526 $full_match = $regex[0]; |
|
2527 $has_leading_slash = ! empty( $regex[1] ); |
|
2528 $tag_name = $regex[2]; |
|
2529 $tag = strtolower( $tag_name ); |
|
2530 $is_single_tag = in_array( $tag, $single_tags, true ); |
|
2531 $pre_attribute_ws = isset( $regex[4] ) ? $regex[4] : ''; |
|
2532 $attributes = trim( isset( $regex[5] ) ? $regex[5] : $regex[3] ); |
|
2533 $has_self_closer = '/' === substr( $attributes, -1 ); |
|
2534 |
|
2469 $newtext .= $tagqueue; |
2535 $newtext .= $tagqueue; |
2470 |
2536 |
2471 $i = strpos( $text, $regex[0] ); |
2537 $i = strpos( $text, $full_match ); |
2472 $l = strlen( $regex[0] ); |
2538 $l = strlen( $full_match ); |
2473 |
2539 |
2474 // clear the shifter |
2540 // Clear the shifter. |
2475 $tagqueue = ''; |
2541 $tagqueue = ''; |
2476 // Pop or Push |
2542 if ( $has_leading_slash ) { // End tag. |
2477 if ( isset( $regex[1][0] ) && '/' == $regex[1][0] ) { // End Tag |
2543 // If too many closing tags. |
2478 $tag = strtolower( substr( $regex[1], 1 ) ); |
|
2479 // if too many closing tags |
|
2480 if ( $stacksize <= 0 ) { |
2544 if ( $stacksize <= 0 ) { |
2481 $tag = ''; |
2545 $tag = ''; |
2482 // or close to be safe $tag = '/' . $tag; |
2546 // Or close to be safe $tag = '/' . $tag. |
2483 |
2547 |
2484 // if stacktop value = tag close value then pop |
2548 // If stacktop value = tag close value, then pop. |
2485 } elseif ( $tagstack[ $stacksize - 1 ] == $tag ) { // found closing tag |
2549 } elseif ( $tagstack[ $stacksize - 1 ] === $tag ) { // Found closing tag. |
2486 $tag = '</' . $tag . '>'; // Close Tag |
2550 $tag = '</' . $tag . '>'; // Close tag. |
2487 // Pop |
|
2488 array_pop( $tagstack ); |
2551 array_pop( $tagstack ); |
2489 $stacksize--; |
2552 $stacksize--; |
2490 } else { // closing tag not at top, search for it |
2553 } else { // Closing tag not at top, search for it. |
2491 for ( $j = $stacksize - 1; $j >= 0; $j-- ) { |
2554 for ( $j = $stacksize - 1; $j >= 0; $j-- ) { |
2492 if ( $tagstack[ $j ] == $tag ) { |
2555 if ( $tagstack[ $j ] === $tag ) { |
2493 // add tag to tagqueue |
2556 // Add tag to tagqueue. |
2494 for ( $k = $stacksize - 1; $k >= $j; $k-- ) { |
2557 for ( $k = $stacksize - 1; $k >= $j; $k-- ) { |
2495 $tagqueue .= '</' . array_pop( $tagstack ) . '>'; |
2558 $tagqueue .= '</' . array_pop( $tagstack ) . '>'; |
2496 $stacksize--; |
2559 $stacksize--; |
2497 } |
2560 } |
2498 break; |
2561 break; |
2499 } |
2562 } |
2500 } |
2563 } |
2501 $tag = ''; |
2564 $tag = ''; |
2502 } |
2565 } |
2503 } else { // Begin Tag |
2566 } else { // Begin tag. |
2504 $tag = strtolower( $regex[1] ); |
2567 if ( $has_self_closer ) { // If it presents itself as a self-closing tag... |
2505 |
2568 // ...but it isn't a known single-entity self-closing tag, then don't let it be treated as such |
2506 // Tag Cleaning |
2569 // and immediately close it with a closing tag (the tag will encapsulate no text as a result). |
2507 |
2570 if ( ! $is_single_tag ) { |
2508 // If it's an empty tag "< >", do nothing |
2571 $attributes = trim( substr( $attributes, 0, -1 ) ) . "></$tag"; |
2509 if ( '' == $tag ) { |
|
2510 // do nothing |
|
2511 } elseif ( substr( $regex[2], -1 ) == '/' ) { // ElseIf it presents itself as a self-closing tag... |
|
2512 // ...but it isn't a known single-entity self-closing tag, then don't let it be treated as such and |
|
2513 // immediately close it with a closing tag (the tag will encapsulate no text as a result) |
|
2514 if ( ! in_array( $tag, $single_tags ) ) { |
|
2515 $regex[2] = trim( substr( $regex[2], 0, -1 ) ) . "></$tag"; |
|
2516 } |
2572 } |
2517 } elseif ( in_array( $tag, $single_tags ) ) { // ElseIf it's a known single-entity tag but it doesn't close itself, do so |
2573 } elseif ( $is_single_tag ) { // Else if it's a known single-entity tag but it doesn't close itself, do so. |
2518 $regex[2] .= '/'; |
2574 $pre_attribute_ws = ' '; |
2519 } else { // Else it's not a single-entity tag |
2575 $attributes .= '/'; |
2520 // If the top of the stack is the same as the tag we want to push, close previous tag |
2576 } else { // It's not a single-entity tag. |
2521 if ( $stacksize > 0 && ! in_array( $tag, $nestable_tags ) && $tagstack[ $stacksize - 1 ] == $tag ) { |
2577 // If the top of the stack is the same as the tag we want to push, close previous tag. |
2578 if ( $stacksize > 0 && ! in_array( $tag, $nestable_tags, true ) && $tagstack[ $stacksize - 1 ] === $tag ) { |
|
2522 $tagqueue = '</' . array_pop( $tagstack ) . '>'; |
2579 $tagqueue = '</' . array_pop( $tagstack ) . '>'; |
2523 $stacksize--; |
2580 $stacksize--; |
2524 } |
2581 } |
2525 $stacksize = array_push( $tagstack, $tag ); |
2582 $stacksize = array_push( $tagstack, $tag ); |
2526 } |
2583 } |
2527 |
2584 |
2528 // Attributes |
2585 // Attributes. |
2529 $attributes = $regex[2]; |
2586 if ( $has_self_closer && $is_single_tag ) { |
2530 if ( ! empty( $attributes ) && $attributes[0] != '>' ) { |
2587 // We need some space - avoid <br/> and prefer <br />. |
2531 $attributes = ' ' . $attributes; |
2588 $pre_attribute_ws = ' '; |
2532 } |
2589 } |
2533 |
2590 |
2534 $tag = '<' . $tag . $attributes . '>'; |
2591 $tag = '<' . $tag . $pre_attribute_ws . $attributes . '>'; |
2535 //If already queuing a close tag, then put this tag on, too |
2592 // If already queuing a close tag, then put this tag on too. |
2536 if ( ! empty( $tagqueue ) ) { |
2593 if ( ! empty( $tagqueue ) ) { |
2537 $tagqueue .= $tag; |
2594 $tagqueue .= $tag; |
2538 $tag = ''; |
2595 $tag = ''; |
2539 } |
2596 } |
2540 } |
2597 } |
2541 $newtext .= substr( $text, 0, $i ) . $tag; |
2598 $newtext .= substr( $text, 0, $i ) . $tag; |
2542 $text = substr( $text, $i + $l ); |
2599 $text = substr( $text, $i + $l ); |
2543 } |
2600 } |
2544 |
2601 |
2545 // Clear Tag Queue |
2602 // Clear tag queue. |
2546 $newtext .= $tagqueue; |
2603 $newtext .= $tagqueue; |
2547 |
2604 |
2548 // Add Remaining text |
2605 // Add remaining text. |
2549 $newtext .= $text; |
2606 $newtext .= $text; |
2550 |
2607 |
2551 // Empty Stack |
|
2552 while ( $x = array_pop( $tagstack ) ) { |
2608 while ( $x = array_pop( $tagstack ) ) { |
2553 $newtext .= '</' . $x . '>'; // Add remaining tags to close |
2609 $newtext .= '</' . $x . '>'; // Add remaining tags to close. |
2554 } |
2610 } |
2555 |
2611 |
2556 // WP fix for the bug with HTML comments |
2612 // WP fix for the bug with HTML comments. |
2557 $newtext = str_replace( '< !--', '<!--', $newtext ); |
2613 $newtext = str_replace( '< !--', '<!--', $newtext ); |
2558 $newtext = str_replace( '< !--', '< !--', $newtext ); |
2614 $newtext = str_replace( '< !--', '< !--', $newtext ); |
2559 |
2615 |
2560 return $newtext; |
2616 return $newtext; |
2561 } |
2617 } |
2662 |
2718 |
2663 /** |
2719 /** |
2664 * Adds slashes to escape strings. |
2720 * Adds slashes to escape strings. |
2665 * |
2721 * |
2666 * Slashes will first be removed if magic_quotes_gpc is set, see {@link |
2722 * Slashes will first be removed if magic_quotes_gpc is set, see {@link |
2667 * https://secure.php.net/magic_quotes} for more details. |
2723 * https://www.php.net/magic_quotes} for more details. |
2668 * |
2724 * |
2669 * @since 0.71 |
2725 * @since 0.71 |
2670 * |
2726 * |
2671 * @param string $gpc The string returned from HTTP request data. |
2727 * @param string $gpc The string returned from HTTP request data. |
2672 * @return string Returns a string escaped with slashes. |
2728 * @return string Returns a string escaped with slashes. |
2673 */ |
2729 */ |
2674 function addslashes_gpc( $gpc ) { |
2730 function addslashes_gpc( $gpc ) { |
2675 if ( get_magic_quotes_gpc() ) { |
|
2676 $gpc = stripslashes( $gpc ); |
|
2677 } |
|
2678 |
|
2679 return wp_slash( $gpc ); |
2731 return wp_slash( $gpc ); |
2680 } |
2732 } |
2681 |
2733 |
2682 /** |
2734 /** |
2683 * Navigates through an array, object, or scalar, and removes slashes from the values. |
2735 * Navigates through an array, object, or scalar, and removes slashes from the values. |
2695 * Callback function for `stripslashes_deep()` which strips slashes from strings. |
2747 * Callback function for `stripslashes_deep()` which strips slashes from strings. |
2696 * |
2748 * |
2697 * @since 4.4.0 |
2749 * @since 4.4.0 |
2698 * |
2750 * |
2699 * @param mixed $value The array or string to be stripped. |
2751 * @param mixed $value The array or string to be stripped. |
2700 * @return mixed $value The stripped value. |
2752 * @return mixed The stripped value. |
2701 */ |
2753 */ |
2702 function stripslashes_from_strings_only( $value ) { |
2754 function stripslashes_from_strings_only( $value ) { |
2703 return is_string( $value ) ? stripslashes( $value ) : $value; |
2755 return is_string( $value ) ? stripslashes( $value ) : $value; |
2704 } |
2756 } |
2705 |
2757 |
2707 * Navigates through an array, object, or scalar, and encodes the values to be used in a URL. |
2759 * Navigates through an array, object, or scalar, and encodes the values to be used in a URL. |
2708 * |
2760 * |
2709 * @since 2.2.0 |
2761 * @since 2.2.0 |
2710 * |
2762 * |
2711 * @param mixed $value The array or string to be encoded. |
2763 * @param mixed $value The array or string to be encoded. |
2712 * @return mixed $value The encoded value. |
2764 * @return mixed The encoded value. |
2713 */ |
2765 */ |
2714 function urlencode_deep( $value ) { |
2766 function urlencode_deep( $value ) { |
2715 return map_deep( $value, 'urlencode' ); |
2767 return map_deep( $value, 'urlencode' ); |
2716 } |
2768 } |
2717 |
2769 |
2719 * Navigates through an array, object, or scalar, and raw-encodes the values to be used in a URL. |
2771 * Navigates through an array, object, or scalar, and raw-encodes the values to be used in a URL. |
2720 * |
2772 * |
2721 * @since 3.4.0 |
2773 * @since 3.4.0 |
2722 * |
2774 * |
2723 * @param mixed $value The array or string to be encoded. |
2775 * @param mixed $value The array or string to be encoded. |
2724 * @return mixed $value The encoded value. |
2776 * @return mixed The encoded value. |
2725 */ |
2777 */ |
2726 function rawurlencode_deep( $value ) { |
2778 function rawurlencode_deep( $value ) { |
2727 return map_deep( $value, 'rawurlencode' ); |
2779 return map_deep( $value, 'rawurlencode' ); |
2728 } |
2780 } |
2729 |
2781 |
2731 * Navigates through an array, object, or scalar, and decodes URL-encoded values |
2783 * Navigates through an array, object, or scalar, and decodes URL-encoded values |
2732 * |
2784 * |
2733 * @since 4.4.0 |
2785 * @since 4.4.0 |
2734 * |
2786 * |
2735 * @param mixed $value The array or string to be decoded. |
2787 * @param mixed $value The array or string to be decoded. |
2736 * @return mixed $value The decoded value. |
2788 * @return mixed The decoded value. |
2737 */ |
2789 */ |
2738 function urldecode_deep( $value ) { |
2790 function urldecode_deep( $value ) { |
2739 return map_deep( $value, 'urldecode' ); |
2791 return map_deep( $value, 'urldecode' ); |
2740 } |
2792 } |
2741 |
2793 |
2750 */ |
2802 */ |
2751 function antispambot( $email_address, $hex_encoding = 0 ) { |
2803 function antispambot( $email_address, $hex_encoding = 0 ) { |
2752 $email_no_spam_address = ''; |
2804 $email_no_spam_address = ''; |
2753 for ( $i = 0, $len = strlen( $email_address ); $i < $len; $i++ ) { |
2805 for ( $i = 0, $len = strlen( $email_address ); $i < $len; $i++ ) { |
2754 $j = rand( 0, 1 + $hex_encoding ); |
2806 $j = rand( 0, 1 + $hex_encoding ); |
2755 if ( $j == 0 ) { |
2807 if ( 0 == $j ) { |
2756 $email_no_spam_address .= '&#' . ord( $email_address[ $i ] ) . ';'; |
2808 $email_no_spam_address .= '&#' . ord( $email_address[ $i ] ) . ';'; |
2757 } elseif ( $j == 1 ) { |
2809 } elseif ( 1 == $j ) { |
2758 $email_no_spam_address .= $email_address[ $i ]; |
2810 $email_no_spam_address .= $email_address[ $i ]; |
2759 } elseif ( $j == 2 ) { |
2811 } elseif ( 2 == $j ) { |
2760 $email_no_spam_address .= '%' . zeroise( dechex( ord( $email_address[ $i ] ) ), 2 ); |
2812 $email_no_spam_address .= '%' . zeroise( dechex( ord( $email_address[ $i ] ) ), 2 ); |
2761 } |
2813 } |
2762 } |
2814 } |
2763 |
2815 |
2764 return str_replace( '@', '@', $email_no_spam_address ); |
2816 return str_replace( '@', '@', $email_no_spam_address ); |
2776 * @return string HTML A element with URI address. |
2828 * @return string HTML A element with URI address. |
2777 */ |
2829 */ |
2778 function _make_url_clickable_cb( $matches ) { |
2830 function _make_url_clickable_cb( $matches ) { |
2779 $url = $matches[2]; |
2831 $url = $matches[2]; |
2780 |
2832 |
2781 if ( ')' == $matches[3] && strpos( $url, '(' ) ) { |
2833 if ( ')' === $matches[3] && strpos( $url, '(' ) ) { |
2782 // If the trailing character is a closing parethesis, and the URL has an opening parenthesis in it, add the closing parenthesis to the URL. |
2834 // If the trailing character is a closing parethesis, and the URL has an opening parenthesis in it, |
2783 // Then we can let the parenthesis balancer do its thing below. |
2835 // add the closing parenthesis to the URL. Then we can let the parenthesis balancer do its thing below. |
2784 $url .= $matches[3]; |
2836 $url .= $matches[3]; |
2785 $suffix = ''; |
2837 $suffix = ''; |
2786 } else { |
2838 } else { |
2787 $suffix = $matches[3]; |
2839 $suffix = $matches[3]; |
2788 } |
2840 } |
2789 |
2841 |
2790 // Include parentheses in the URL only if paired |
2842 // Include parentheses in the URL only if paired. |
2791 while ( substr_count( $url, '(' ) < substr_count( $url, ')' ) ) { |
2843 while ( substr_count( $url, '(' ) < substr_count( $url, ')' ) ) { |
2792 $suffix = strrchr( $url, ')' ) . $suffix; |
2844 $suffix = strrchr( $url, ')' ) . $suffix; |
2793 $url = substr( $url, 0, strrpos( $url, ')' ) ); |
2845 $url = substr( $url, 0, strrpos( $url, ')' ) ); |
2794 } |
2846 } |
2795 |
2847 |
2796 $url = esc_url( $url ); |
2848 $url = esc_url( $url ); |
2797 if ( empty( $url ) ) { |
2849 if ( empty( $url ) ) { |
2798 return $matches[0]; |
2850 return $matches[0]; |
2799 } |
2851 } |
2800 |
2852 |
2801 return $matches[1] . "<a href=\"$url\" rel=\"nofollow\">$url</a>" . $suffix; |
2853 if ( 'comment_text' === current_filter() ) { |
2854 $rel = 'nofollow ugc'; |
|
2855 } else { |
|
2856 $rel = 'nofollow'; |
|
2857 } |
|
2858 |
|
2859 /** |
|
2860 * Filters the rel value that is added to URL matches converted to links. |
|
2861 * |
|
2862 * @since 5.3.0 |
|
2863 * |
|
2864 * @param string $rel The rel value. |
|
2865 * @param string $url The matched URL being converted to a link tag. |
|
2866 */ |
|
2867 $rel = apply_filters( 'make_clickable_rel', $rel, $url ); |
|
2868 $rel = esc_attr( $rel ); |
|
2869 |
|
2870 return $matches[1] . "<a href=\"$url\" rel=\"$rel\">$url</a>" . $suffix; |
|
2802 } |
2871 } |
2803 |
2872 |
2804 /** |
2873 /** |
2805 * Callback to convert URL match to HTML A element. |
2874 * Callback to convert URL match to HTML A element. |
2806 * |
2875 * |
2815 function _make_web_ftp_clickable_cb( $matches ) { |
2884 function _make_web_ftp_clickable_cb( $matches ) { |
2816 $ret = ''; |
2885 $ret = ''; |
2817 $dest = $matches[2]; |
2886 $dest = $matches[2]; |
2818 $dest = 'http://' . $dest; |
2887 $dest = 'http://' . $dest; |
2819 |
2888 |
2820 // removed trailing [.,;:)] from URL |
2889 // Removed trailing [.,;:)] from URL. |
2821 if ( in_array( substr( $dest, -1 ), array( '.', ',', ';', ':', ')' ) ) === true ) { |
2890 $last_char = substr( $dest, -1 ); |
2822 $ret = substr( $dest, -1 ); |
2891 if ( in_array( $last_char, array( '.', ',', ';', ':', ')' ), true ) === true ) { |
2892 $ret = $last_char; |
|
2823 $dest = substr( $dest, 0, strlen( $dest ) - 1 ); |
2893 $dest = substr( $dest, 0, strlen( $dest ) - 1 ); |
2824 } |
2894 } |
2825 |
2895 |
2826 $dest = esc_url( $dest ); |
2896 $dest = esc_url( $dest ); |
2827 if ( empty( $dest ) ) { |
2897 if ( empty( $dest ) ) { |
2828 return $matches[0]; |
2898 return $matches[0]; |
2829 } |
2899 } |
2830 |
2900 |
2831 return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>$ret"; |
2901 if ( 'comment_text' === current_filter() ) { |
2902 $rel = 'nofollow ugc'; |
|
2903 } else { |
|
2904 $rel = 'nofollow'; |
|
2905 } |
|
2906 |
|
2907 /** This filter is documented in wp-includes/formatting.php */ |
|
2908 $rel = apply_filters( 'make_clickable_rel', $rel, $dest ); |
|
2909 $rel = esc_attr( $rel ); |
|
2910 |
|
2911 return $matches[1] . "<a href=\"$dest\" rel=\"$rel\">$dest</a>$ret"; |
|
2832 } |
2912 } |
2833 |
2913 |
2834 /** |
2914 /** |
2835 * Callback to convert email address match to HTML A element. |
2915 * Callback to convert email address match to HTML A element. |
2836 * |
2916 * |
2858 * @param string $text Content to convert URIs. |
2938 * @param string $text Content to convert URIs. |
2859 * @return string Content with converted URIs. |
2939 * @return string Content with converted URIs. |
2860 */ |
2940 */ |
2861 function make_clickable( $text ) { |
2941 function make_clickable( $text ) { |
2862 $r = ''; |
2942 $r = ''; |
2863 $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // split out HTML tags |
2943 $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // Split out HTML tags. |
2864 $nested_code_pre = 0; // Keep track of how many levels link is nested inside <pre> or <code> |
2944 $nested_code_pre = 0; // Keep track of how many levels link is nested inside <pre> or <code>. |
2865 foreach ( $textarr as $piece ) { |
2945 foreach ( $textarr as $piece ) { |
2866 |
2946 |
2867 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 ) ) { |
2947 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 ) ) { |
2868 $nested_code_pre++; |
2948 $nested_code_pre++; |
2869 } elseif ( $nested_code_pre && ( '</code>' === strtolower( $piece ) || '</pre>' === strtolower( $piece ) || '</script>' === strtolower( $piece ) || '</style>' === strtolower( $piece ) ) ) { |
2949 } elseif ( $nested_code_pre && ( '</code>' === strtolower( $piece ) || '</pre>' === strtolower( $piece ) || '</script>' === strtolower( $piece ) || '</style>' === strtolower( $piece ) ) ) { |
2870 $nested_code_pre--; |
2950 $nested_code_pre--; |
2871 } |
2951 } |
2872 |
2952 |
2873 if ( $nested_code_pre || empty( $piece ) || ( $piece[0] === '<' && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) ) ) { |
2953 if ( $nested_code_pre || empty( $piece ) || ( '<' === $piece[0] && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) ) ) { |
2874 $r .= $piece; |
2954 $r .= $piece; |
2875 continue; |
2955 continue; |
2876 } |
2956 } |
2877 |
2957 |
2878 // Long strings might contain expensive edge cases ... |
2958 // Long strings might contain expensive edge cases... |
2879 if ( 10000 < strlen( $piece ) ) { |
2959 if ( 10000 < strlen( $piece ) ) { |
2880 // ... break it up |
2960 // ...break it up. |
2881 foreach ( _split_str_by_whitespace( $piece, 2100 ) as $chunk ) { // 2100: Extra room for scheme and leading and trailing paretheses |
2961 foreach ( _split_str_by_whitespace( $piece, 2100 ) as $chunk ) { // 2100: Extra room for scheme and leading and trailing paretheses. |
2882 if ( 2101 < strlen( $chunk ) ) { |
2962 if ( 2101 < strlen( $chunk ) ) { |
2883 $r .= $chunk; // Too big, no whitespace: bail. |
2963 $r .= $chunk; // Too big, no whitespace: bail. |
2884 } else { |
2964 } else { |
2885 $r .= make_clickable( $chunk ); |
2965 $r .= make_clickable( $chunk ); |
2886 } |
2966 } |
2887 } |
2967 } |
2888 } else { |
2968 } else { |
2889 $ret = " $piece "; // Pad with whitespace to simplify the regexes |
2969 $ret = " $piece "; // Pad with whitespace to simplify the regexes. |
2890 |
2970 |
2891 $url_clickable = '~ |
2971 $url_clickable = '~ |
2892 ([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation |
2972 ([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation. |
2893 ( # 2: URL |
2973 ( # 2: URL. |
2894 [\\w]{1,20}+:// # Scheme and hier-part prefix |
2974 [\\w]{1,20}+:// # Scheme and hier-part prefix. |
2895 (?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long |
2975 (?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long. |
2896 [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character |
2976 [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character. |
2897 (?: # Unroll the Loop: Only allow puctuation URL character if followed by a non-punctuation URL character |
2977 (?: # Unroll the Loop: Only allow puctuation URL character if followed by a non-punctuation URL character. |
2898 [\'.,;:!?)] # Punctuation URL character |
2978 [\'.,;:!?)] # Punctuation URL character. |
2899 [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character |
2979 [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character. |
2900 )* |
2980 )* |
2901 ) |
2981 ) |
2902 (\)?) # 3: Trailing closing parenthesis (for parethesis balancing post processing) |
2982 (\)?) # 3: Trailing closing parenthesis (for parethesis balancing post processing). |
2903 ~xS'; // The regex is a non-anchored pattern and does not have a single fixed starting character. |
2983 ~xS'; |
2904 // Tell PCRE to spend more time optimizing since, when used on a page load, it will probably be used several times. |
2984 // The regex is a non-anchored pattern and does not have a single fixed starting character. |
2985 // Tell PCRE to spend more time optimizing since, when used on a page load, it will probably be used several times. |
|
2905 |
2986 |
2906 $ret = preg_replace_callback( $url_clickable, '_make_url_clickable_cb', $ret ); |
2987 $ret = preg_replace_callback( $url_clickable, '_make_url_clickable_cb', $ret ); |
2907 |
2988 |
2908 $ret = preg_replace_callback( '#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is', '_make_web_ftp_clickable_cb', $ret ); |
2989 $ret = preg_replace_callback( '#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is', '_make_web_ftp_clickable_cb', $ret ); |
2909 $ret = preg_replace_callback( '#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret ); |
2990 $ret = preg_replace_callback( '#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret ); |
2911 $ret = substr( $ret, 1, -1 ); // Remove our whitespace padding. |
2992 $ret = substr( $ret, 1, -1 ); // Remove our whitespace padding. |
2912 $r .= $ret; |
2993 $r .= $ret; |
2913 } |
2994 } |
2914 } |
2995 } |
2915 |
2996 |
2916 // Cleanup of accidental links within links |
2997 // Cleanup of accidental links within links. |
2917 return preg_replace( '#(<a([ \r\n\t]+[^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i', '$1$3</a>', $r ); |
2998 return preg_replace( '#(<a([ \r\n\t]+[^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i', '$1$3</a>', $r ); |
2918 } |
2999 } |
2919 |
3000 |
2920 /** |
3001 /** |
2921 * Breaks a string into chunks by splitting at whitespace characters. |
3002 * Breaks a string into chunks by splitting at whitespace characters. |
2927 * |
3008 * |
2928 * Input string must have no null characters (or eventual transformations on output chunks must not care about null characters) |
3009 * Input string must have no null characters (or eventual transformations on output chunks must not care about null characters) |
2929 * |
3010 * |
2930 * _split_str_by_whitespace( "1234 67890 1234 67890a cd 1234 890 123456789 1234567890a 45678 1 3 5 7 90 ", 10 ) == |
3011 * _split_str_by_whitespace( "1234 67890 1234 67890a cd 1234 890 123456789 1234567890a 45678 1 3 5 7 90 ", 10 ) == |
2931 * array ( |
3012 * array ( |
2932 * 0 => '1234 67890 ', // 11 characters: Perfect split |
3013 * 0 => '1234 67890 ', // 11 characters: Perfect split. |
2933 * 1 => '1234 ', // 5 characters: '1234 67890a' was too long |
3014 * 1 => '1234 ', // 5 characters: '1234 67890a' was too long. |
2934 * 2 => '67890a cd ', // 10 characters: '67890a cd 1234' was too long |
3015 * 2 => '67890a cd ', // 10 characters: '67890a cd 1234' was too long. |
2935 * 3 => '1234 890 ', // 11 characters: Perfect split |
3016 * 3 => '1234 890 ', // 11 characters: Perfect split. |
2936 * 4 => '123456789 ', // 10 characters: '123456789 1234567890a' was too long |
3017 * 4 => '123456789 ', // 10 characters: '123456789 1234567890a' was too long. |
2937 * 5 => '1234567890a ', // 12 characters: Too long, but no inner whitespace on which to split |
3018 * 5 => '1234567890a ', // 12 characters: Too long, but no inner whitespace on which to split. |
2938 * 6 => ' 45678 ', // 11 characters: Perfect split |
3019 * 6 => ' 45678 ', // 11 characters: Perfect split. |
2939 * 7 => '1 3 5 7 90 ', // 11 characters: End of $string |
3020 * 7 => '1 3 5 7 90 ', // 11 characters: End of $string. |
2940 * ); |
3021 * ); |
2941 * |
3022 * |
2942 * @since 3.4.0 |
3023 * @since 3.4.0 |
2943 * @access private |
3024 * @access private |
2944 * |
3025 * |
2972 |
3053 |
2973 return $chunks; |
3054 return $chunks; |
2974 } |
3055 } |
2975 |
3056 |
2976 /** |
3057 /** |
2977 * Adds rel nofollow string to all HTML A elements in content. |
3058 * Callback to add a rel attribute to HTML A element. |
2978 * |
3059 * |
2979 * @since 1.5.0 |
3060 * Will remove already existing string before adding to prevent invalidating (X)HTML. |
2980 * |
3061 * |
2981 * @param string $text Content that may contain HTML A elements. |
3062 * @since 5.3.0 |
2982 * @return string Converted content. |
3063 * |
2983 */ |
3064 * @param array $matches Single match. |
2984 function wp_rel_nofollow( $text ) { |
3065 * @param string $rel The rel attribute to add. |
2985 // This is a pre save filter, so text is already escaped. |
3066 * @return string HTML A element with the added rel attribute. |
2986 $text = stripslashes( $text ); |
3067 */ |
2987 $text = preg_replace_callback( '|<a (.+?)>|i', 'wp_rel_nofollow_callback', $text ); |
3068 function wp_rel_callback( $matches, $rel ) { |
2988 return wp_slash( $text ); |
|
2989 } |
|
2990 |
|
2991 /** |
|
2992 * Callback to add rel=nofollow string to HTML A element. |
|
2993 * |
|
2994 * Will remove already existing rel="nofollow" and rel='nofollow' from the |
|
2995 * string to prevent from invalidating (X)HTML. |
|
2996 * |
|
2997 * @since 2.3.0 |
|
2998 * |
|
2999 * @param array $matches Single Match |
|
3000 * @return string HTML A Element with rel nofollow. |
|
3001 */ |
|
3002 function wp_rel_nofollow_callback( $matches ) { |
|
3003 $text = $matches[1]; |
3069 $text = $matches[1]; |
3004 $atts = wp_kses_hair( $matches[1], wp_allowed_protocols() ); |
3070 $atts = wp_kses_hair( $matches[1], wp_allowed_protocols() ); |
3005 $rel = 'nofollow'; |
|
3006 |
3071 |
3007 if ( ! empty( $atts['href'] ) ) { |
3072 if ( ! empty( $atts['href'] ) ) { |
3008 if ( in_array( strtolower( wp_parse_url( $atts['href']['value'], PHP_URL_SCHEME ) ), array( 'http', 'https' ), true ) ) { |
3073 if ( in_array( strtolower( wp_parse_url( $atts['href']['value'], PHP_URL_SCHEME ) ), array( 'http', 'https' ), true ) ) { |
3009 if ( strtolower( wp_parse_url( $atts['href']['value'], PHP_URL_HOST ) ) === strtolower( wp_parse_url( home_url(), PHP_URL_HOST ) ) ) { |
3074 if ( strtolower( wp_parse_url( $atts['href']['value'], PHP_URL_HOST ) ) === strtolower( wp_parse_url( home_url(), PHP_URL_HOST ) ) ) { |
3010 return "<a $text>"; |
3075 return "<a $text>"; |
3011 } |
3076 } |
3012 } |
3077 } |
3013 } |
3078 } |
3014 |
3079 |
3015 if ( ! empty( $atts['rel'] ) ) { |
3080 if ( ! empty( $atts['rel'] ) ) { |
3016 $parts = array_map( 'trim', explode( ' ', $atts['rel']['value'] ) ); |
3081 $parts = array_map( 'trim', explode( ' ', $atts['rel']['value'] ) ); |
3017 if ( false === array_search( 'nofollow', $parts ) ) { |
3082 $rel_array = array_map( 'trim', explode( ' ', $rel ) ); |
3018 $parts[] = 'nofollow'; |
3083 $parts = array_unique( array_merge( $parts, $rel_array ) ); |
3019 } |
3084 $rel = implode( ' ', $parts ); |
3020 $rel = implode( ' ', $parts ); |
|
3021 unset( $atts['rel'] ); |
3085 unset( $atts['rel'] ); |
3022 |
3086 |
3023 $html = ''; |
3087 $html = ''; |
3024 foreach ( $atts as $name => $value ) { |
3088 foreach ( $atts as $name => $value ) { |
3025 if ( isset( $value['vless'] ) && 'y' === $value['vless'] ) { |
3089 if ( isset( $value['vless'] ) && 'y' === $value['vless'] ) { |
3032 } |
3096 } |
3033 return "<a $text rel=\"" . esc_attr( $rel ) . '">'; |
3097 return "<a $text rel=\"" . esc_attr( $rel ) . '">'; |
3034 } |
3098 } |
3035 |
3099 |
3036 /** |
3100 /** |
3037 * Adds rel noreferrer and noopener to all HTML A elements that have a target. |
3101 * Adds `rel="nofollow"` string to all HTML A elements in content. |
3038 * |
3102 * |
3039 * @since 5.1.0 |
3103 * @since 1.5.0 |
3040 * |
3104 * |
3041 * @param string $text Content that may contain HTML A elements. |
3105 * @param string $text Content that may contain HTML A elements. |
3042 * @return string Converted content. |
3106 * @return string Converted content. |
3043 */ |
3107 */ |
3108 function wp_rel_nofollow( $text ) { |
|
3109 // This is a pre-save filter, so text is already escaped. |
|
3110 $text = stripslashes( $text ); |
|
3111 $text = preg_replace_callback( |
|
3112 '|<a (.+?)>|i', |
|
3113 function( $matches ) { |
|
3114 return wp_rel_callback( $matches, 'nofollow' ); |
|
3115 }, |
|
3116 $text |
|
3117 ); |
|
3118 return wp_slash( $text ); |
|
3119 } |
|
3120 |
|
3121 /** |
|
3122 * Callback to add `rel="nofollow"` string to HTML A element. |
|
3123 * |
|
3124 * @since 2.3.0 |
|
3125 * @deprecated 5.3.0 Use wp_rel_callback() |
|
3126 * |
|
3127 * @param array $matches Single match. |
|
3128 * @return string HTML A Element with `rel="nofollow"`. |
|
3129 */ |
|
3130 function wp_rel_nofollow_callback( $matches ) { |
|
3131 return wp_rel_callback( $matches, 'nofollow' ); |
|
3132 } |
|
3133 |
|
3134 /** |
|
3135 * Adds `rel="nofollow ugc"` string to all HTML A elements in content. |
|
3136 * |
|
3137 * @since 5.3.0 |
|
3138 * |
|
3139 * @param string $text Content that may contain HTML A elements. |
|
3140 * @return string Converted content. |
|
3141 */ |
|
3142 function wp_rel_ugc( $text ) { |
|
3143 // This is a pre-save filter, so text is already escaped. |
|
3144 $text = stripslashes( $text ); |
|
3145 $text = preg_replace_callback( |
|
3146 '|<a (.+?)>|i', |
|
3147 function( $matches ) { |
|
3148 return wp_rel_callback( $matches, 'nofollow ugc' ); |
|
3149 }, |
|
3150 $text |
|
3151 ); |
|
3152 return wp_slash( $text ); |
|
3153 } |
|
3154 |
|
3155 /** |
|
3156 * Adds rel noreferrer and noopener to all HTML A elements that have a target. |
|
3157 * |
|
3158 * @since 5.1.0 |
|
3159 * |
|
3160 * @param string $text Content that may contain HTML A elements. |
|
3161 * @return string Converted content. |
|
3162 */ |
|
3044 function wp_targeted_link_rel( $text ) { |
3163 function wp_targeted_link_rel( $text ) { |
3045 // Don't run (more expensive) regex if no links with targets. |
3164 // Don't run (more expensive) regex if no links with targets. |
3046 if ( stripos( $text, 'target' ) !== false && stripos( $text, '<a ' ) !== false ) { |
3165 if ( stripos( $text, 'target' ) === false || stripos( $text, '<a ' ) === false || is_serialized( $text ) ) { |
3047 $text = preg_replace_callback( '|<a\s([^>]*target\s*=[^>]*)>|i', 'wp_targeted_link_rel_callback', $text ); |
3166 return $text; |
3167 } |
|
3168 |
|
3169 $script_and_style_regex = '/<(script|style).*?<\/\\1>/si'; |
|
3170 |
|
3171 preg_match_all( $script_and_style_regex, $text, $matches ); |
|
3172 $extra_parts = $matches[0]; |
|
3173 $html_parts = preg_split( $script_and_style_regex, $text ); |
|
3174 |
|
3175 foreach ( $html_parts as &$part ) { |
|
3176 $part = preg_replace_callback( '|<a\s([^>]*target\s*=[^>]*)>|i', 'wp_targeted_link_rel_callback', $part ); |
|
3177 } |
|
3178 |
|
3179 $text = ''; |
|
3180 for ( $i = 0; $i < count( $html_parts ); $i++ ) { |
|
3181 $text .= $html_parts[ $i ]; |
|
3182 if ( isset( $extra_parts[ $i ] ) ) { |
|
3183 $text .= $extra_parts[ $i ]; |
|
3184 } |
|
3048 } |
3185 } |
3049 |
3186 |
3050 return $text; |
3187 return $text; |
3051 } |
3188 } |
3052 |
3189 |
3060 * |
3197 * |
3061 * @param array $matches Single Match |
3198 * @param array $matches Single Match |
3062 * @return string HTML A Element with rel noreferrer noopener in addition to any existing values |
3199 * @return string HTML A Element with rel noreferrer noopener in addition to any existing values |
3063 */ |
3200 */ |
3064 function wp_targeted_link_rel_callback( $matches ) { |
3201 function wp_targeted_link_rel_callback( $matches ) { |
3065 $link_html = $matches[1]; |
3202 $link_html = $matches[1]; |
3066 $rel_match = array(); |
3203 $original_link_html = $link_html; |
3204 |
|
3205 // Consider the HTML escaped if there are no unescaped quotes. |
|
3206 $is_escaped = ! preg_match( '/(^|[^\\\\])[\'"]/', $link_html ); |
|
3207 if ( $is_escaped ) { |
|
3208 // Replace only the quotes so that they are parsable by wp_kses_hair(), leave the rest as is. |
|
3209 $link_html = preg_replace( '/\\\\([\'"])/', '$1', $link_html ); |
|
3210 } |
|
3211 |
|
3212 $atts = wp_kses_hair( $link_html, wp_allowed_protocols() ); |
|
3067 |
3213 |
3068 /** |
3214 /** |
3069 * Filters the rel values that are added to links with `target` attribute. |
3215 * Filters the rel values that are added to links with `target` attribute. |
3070 * |
3216 * |
3071 * @since 5.1.0 |
3217 * @since 5.1.0 |
3072 * |
3218 * |
3073 * @param string The rel values. |
3219 * @param string $rel The rel values. |
3074 * @param string $link_html The matched content of the link tag including all HTML attributes. |
3220 * @param string $link_html The matched content of the link tag including all HTML attributes. |
3075 */ |
3221 */ |
3076 $rel = apply_filters( 'wp_targeted_link_rel', 'noopener noreferrer', $link_html ); |
3222 $rel = apply_filters( 'wp_targeted_link_rel', 'noopener noreferrer', $link_html ); |
3077 |
3223 |
3078 // Avoid additional regex if the filter removes rel values. |
3224 // Return early if no rel values to be added or if no actual target attribute. |
3079 if ( ! $rel ) { |
3225 if ( ! $rel || ! isset( $atts['target'] ) ) { |
3080 return "<a $link_html>"; |
3226 return "<a $original_link_html>"; |
3081 } |
3227 } |
3082 |
3228 |
3083 // Value with delimiters, spaces around are optional. |
3229 if ( isset( $atts['rel'] ) ) { |
3084 $attr_regex = '|rel\s*=\s*?(\\\\{0,1}["\'])(.*?)\\1|i'; |
3230 $all_parts = preg_split( '/\s/', "{$atts['rel']['value']} $rel", -1, PREG_SPLIT_NO_EMPTY ); |
3085 preg_match( $attr_regex, $link_html, $rel_match ); |
3231 $rel = implode( ' ', array_unique( $all_parts ) ); |
3086 |
3232 } |
3087 if ( empty( $rel_match[0] ) ) { |
3233 |
3088 // No delimiters, try with a single value and spaces, because `rel = va"lue` is totally fine... |
3234 $atts['rel']['whole'] = 'rel="' . esc_attr( $rel ) . '"'; |
3089 $attr_regex = '|rel\s*=(\s*)([^\s]*)|i'; |
3235 $link_html = join( ' ', array_column( $atts, 'whole' ) ); |
3090 preg_match( $attr_regex, $link_html, $rel_match ); |
3236 |
3091 } |
3237 if ( $is_escaped ) { |
3092 |
3238 $link_html = preg_replace( '/[\'"]/', '\\\\$0', $link_html ); |
3093 if ( ! empty( $rel_match[0] ) ) { |
|
3094 $parts = preg_split( '|\s+|', strtolower( $rel_match[2] ) ); |
|
3095 $parts = array_map( 'esc_attr', $parts ); |
|
3096 $needed = explode( ' ', $rel ); |
|
3097 $parts = array_unique( array_merge( $parts, $needed ) ); |
|
3098 $delimiter = trim( $rel_match[1] ) ? $rel_match[1] : '"'; |
|
3099 $rel = 'rel=' . $delimiter . trim( implode( ' ', $parts ) ) . $delimiter; |
|
3100 $link_html = str_replace( $rel_match[0], $rel, $link_html ); |
|
3101 } elseif ( preg_match( '|target\s*=\s*?\\\\"|', $link_html ) ) { |
|
3102 $link_html .= " rel=\\\"$rel\\\""; |
|
3103 } elseif ( preg_match( '#(target|href)\s*=\s*?\'#', $link_html ) ) { |
|
3104 $link_html .= " rel='$rel'"; |
|
3105 } else { |
|
3106 $link_html .= " rel=\"$rel\""; |
|
3107 } |
3239 } |
3108 |
3240 |
3109 return "<a $link_html>"; |
3241 return "<a $link_html>"; |
3110 } |
3242 } |
3111 |
3243 |
3183 $matches = array(); |
3315 $matches = array(); |
3184 $ext = preg_match( '/\.([^.]+)$/', $img, $matches ) ? strtolower( $matches[1] ) : false; |
3316 $ext = preg_match( '/\.([^.]+)$/', $img, $matches ) ? strtolower( $matches[1] ) : false; |
3185 $image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' ); |
3317 $image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' ); |
3186 |
3318 |
3187 // Don't convert smilies that aren't images - they're probably emoji. |
3319 // Don't convert smilies that aren't images - they're probably emoji. |
3188 if ( ! in_array( $ext, $image_exts ) ) { |
3320 if ( ! in_array( $ext, $image_exts, true ) ) { |
3189 return $img; |
3321 return $img; |
3190 } |
3322 } |
3191 |
3323 |
3192 /** |
3324 /** |
3193 * Filters the Smiley image URL before it's used in the image element. |
3325 * Filters the Smiley image URL before it's used in the image element. |
3218 */ |
3350 */ |
3219 function convert_smilies( $text ) { |
3351 function convert_smilies( $text ) { |
3220 global $wp_smiliessearch; |
3352 global $wp_smiliessearch; |
3221 $output = ''; |
3353 $output = ''; |
3222 if ( get_option( 'use_smilies' ) && ! empty( $wp_smiliessearch ) ) { |
3354 if ( get_option( 'use_smilies' ) && ! empty( $wp_smiliessearch ) ) { |
3223 // HTML loop taken from texturize function, could possible be consolidated |
3355 // HTML loop taken from texturize function, could possible be consolidated. |
3224 $textarr = preg_split( '/(<.*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // capture the tags as well as in between |
3356 $textarr = preg_split( '/(<.*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // Capture the tags as well as in between. |
3225 $stop = count( $textarr );// loop stuff |
3357 $stop = count( $textarr ); // Loop stuff. |
3226 |
3358 |
3227 // Ignore proessing of specific tags |
3359 // Ignore proessing of specific tags. |
3228 $tags_to_ignore = 'code|pre|style|script|textarea'; |
3360 $tags_to_ignore = 'code|pre|style|script|textarea'; |
3229 $ignore_block_element = ''; |
3361 $ignore_block_element = ''; |
3230 |
3362 |
3231 for ( $i = 0; $i < $stop; $i++ ) { |
3363 for ( $i = 0; $i < $stop; $i++ ) { |
3232 $content = $textarr[ $i ]; |
3364 $content = $textarr[ $i ]; |
3233 |
3365 |
3234 // If we're in an ignore block, wait until we find its closing tag |
3366 // If we're in an ignore block, wait until we find its closing tag. |
3235 if ( '' == $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')[^>]*>/', $content, $matches ) ) { |
3367 if ( '' === $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')[^>]*>/', $content, $matches ) ) { |
3236 $ignore_block_element = $matches[1]; |
3368 $ignore_block_element = $matches[1]; |
3237 } |
3369 } |
3238 |
3370 |
3239 // If it's not a tag and not in ignore block |
3371 // If it's not a tag and not in ignore block. |
3240 if ( '' == $ignore_block_element && strlen( $content ) > 0 && '<' != $content[0] ) { |
3372 if ( '' === $ignore_block_element && strlen( $content ) > 0 && '<' !== $content[0] ) { |
3241 $content = preg_replace_callback( $wp_smiliessearch, 'translate_smiley', $content ); |
3373 $content = preg_replace_callback( $wp_smiliessearch, 'translate_smiley', $content ); |
3242 } |
3374 } |
3243 |
3375 |
3244 // did we exit ignore block |
3376 // Did we exit ignore block? |
3245 if ( '' != $ignore_block_element && '</' . $ignore_block_element . '>' == $content ) { |
3377 if ( '' !== $ignore_block_element && '</' . $ignore_block_element . '>' === $content ) { |
3246 $ignore_block_element = ''; |
3378 $ignore_block_element = ''; |
3247 } |
3379 } |
3248 |
3380 |
3249 $output .= $content; |
3381 $output .= $content; |
3250 } |
3382 } |
3251 } else { |
3383 } else { |
3252 // return default text. |
3384 // Return default text. |
3253 $output = $text; |
3385 $output = $text; |
3254 } |
3386 } |
3255 return $output; |
3387 return $output; |
3256 } |
3388 } |
3257 |
3389 |
3262 * |
3394 * |
3263 * @since 0.71 |
3395 * @since 0.71 |
3264 * |
3396 * |
3265 * @param string $email Email address to verify. |
3397 * @param string $email Email address to verify. |
3266 * @param bool $deprecated Deprecated. |
3398 * @param bool $deprecated Deprecated. |
3267 * @return string|bool Either false or the valid email address. |
3399 * @return string|false Valid email address on success, false on failure. |
3268 */ |
3400 */ |
3269 function is_email( $email, $deprecated = false ) { |
3401 function is_email( $email, $deprecated = false ) { |
3270 if ( ! empty( $deprecated ) ) { |
3402 if ( ! empty( $deprecated ) ) { |
3271 _deprecated_argument( __FUNCTION__, '3.0.0' ); |
3403 _deprecated_argument( __FUNCTION__, '3.0.0' ); |
3272 } |
3404 } |
3273 |
3405 |
3274 // Test for the minimum length the email can be |
3406 // Test for the minimum length the email can be. |
3275 if ( strlen( $email ) < 6 ) { |
3407 if ( strlen( $email ) < 6 ) { |
3276 /** |
3408 /** |
3277 * Filters whether an email address is valid. |
3409 * Filters whether an email address is valid. |
3278 * |
3410 * |
3279 * This filter is evaluated under several different contexts, such as 'email_too_short', |
3411 * This filter is evaluated under several different contexts, such as 'email_too_short', |
3280 * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits', |
3412 * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits', |
3281 * 'domain_no_periods', 'sub_hyphen_limits', 'sub_invalid_chars', or no specific context. |
3413 * 'domain_no_periods', 'sub_hyphen_limits', 'sub_invalid_chars', or no specific context. |
3282 * |
3414 * |
3283 * @since 2.8.0 |
3415 * @since 2.8.0 |
3284 * |
3416 * |
3285 * @param bool $is_email Whether the email address has passed the is_email() checks. Default false. |
3417 * @param string|false $is_email The email address if successfully passed the is_email() checks, false otherwise. |
3286 * @param string $email The email address being checked. |
3418 * @param string $email The email address being checked. |
3287 * @param string $context Context under which the email was tested. |
3419 * @param string $context Context under which the email was tested. |
3288 */ |
3420 */ |
3289 return apply_filters( 'is_email', false, $email, 'email_too_short' ); |
3421 return apply_filters( 'is_email', false, $email, 'email_too_short' ); |
3290 } |
3422 } |
3291 |
3423 |
3292 // Test for an @ character after the first position |
3424 // Test for an @ character after the first position. |
3293 if ( strpos( $email, '@', 1 ) === false ) { |
3425 if ( strpos( $email, '@', 1 ) === false ) { |
3294 /** This filter is documented in wp-includes/formatting.php */ |
3426 /** This filter is documented in wp-includes/formatting.php */ |
3295 return apply_filters( 'is_email', false, $email, 'email_no_at' ); |
3427 return apply_filters( 'is_email', false, $email, 'email_no_at' ); |
3296 } |
3428 } |
3297 |
3429 |
3298 // Split out the local and domain parts |
3430 // Split out the local and domain parts. |
3299 list( $local, $domain ) = explode( '@', $email, 2 ); |
3431 list( $local, $domain ) = explode( '@', $email, 2 ); |
3300 |
3432 |
3301 // LOCAL PART |
3433 // LOCAL PART |
3302 // Test for invalid characters |
3434 // Test for invalid characters. |
3303 if ( ! preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) { |
3435 if ( ! preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) { |
3304 /** This filter is documented in wp-includes/formatting.php */ |
3436 /** This filter is documented in wp-includes/formatting.php */ |
3305 return apply_filters( 'is_email', false, $email, 'local_invalid_chars' ); |
3437 return apply_filters( 'is_email', false, $email, 'local_invalid_chars' ); |
3306 } |
3438 } |
3307 |
3439 |
3308 // DOMAIN PART |
3440 // DOMAIN PART |
3309 // Test for sequences of periods |
3441 // Test for sequences of periods. |
3310 if ( preg_match( '/\.{2,}/', $domain ) ) { |
3442 if ( preg_match( '/\.{2,}/', $domain ) ) { |
3311 /** This filter is documented in wp-includes/formatting.php */ |
3443 /** This filter is documented in wp-includes/formatting.php */ |
3312 return apply_filters( 'is_email', false, $email, 'domain_period_sequence' ); |
3444 return apply_filters( 'is_email', false, $email, 'domain_period_sequence' ); |
3313 } |
3445 } |
3314 |
3446 |
3315 // Test for leading and trailing periods and whitespace |
3447 // Test for leading and trailing periods and whitespace. |
3316 if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) { |
3448 if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) { |
3317 /** This filter is documented in wp-includes/formatting.php */ |
3449 /** This filter is documented in wp-includes/formatting.php */ |
3318 return apply_filters( 'is_email', false, $email, 'domain_period_limits' ); |
3450 return apply_filters( 'is_email', false, $email, 'domain_period_limits' ); |
3319 } |
3451 } |
3320 |
3452 |
3321 // Split the domain into subs |
3453 // Split the domain into subs. |
3322 $subs = explode( '.', $domain ); |
3454 $subs = explode( '.', $domain ); |
3323 |
3455 |
3324 // Assume the domain will have at least two subs |
3456 // Assume the domain will have at least two subs. |
3325 if ( 2 > count( $subs ) ) { |
3457 if ( 2 > count( $subs ) ) { |
3326 /** This filter is documented in wp-includes/formatting.php */ |
3458 /** This filter is documented in wp-includes/formatting.php */ |
3327 return apply_filters( 'is_email', false, $email, 'domain_no_periods' ); |
3459 return apply_filters( 'is_email', false, $email, 'domain_no_periods' ); |
3328 } |
3460 } |
3329 |
3461 |
3330 // Loop through each sub |
3462 // Loop through each sub. |
3331 foreach ( $subs as $sub ) { |
3463 foreach ( $subs as $sub ) { |
3332 // Test for leading and trailing hyphens and whitespace |
3464 // Test for leading and trailing hyphens and whitespace. |
3333 if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) { |
3465 if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) { |
3334 /** This filter is documented in wp-includes/formatting.php */ |
3466 /** This filter is documented in wp-includes/formatting.php */ |
3335 return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' ); |
3467 return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' ); |
3336 } |
3468 } |
3337 |
3469 |
3338 // Test for invalid characters |
3470 // Test for invalid characters. |
3339 if ( ! preg_match( '/^[a-z0-9-]+$/i', $sub ) ) { |
3471 if ( ! preg_match( '/^[a-z0-9-]+$/i', $sub ) ) { |
3340 /** This filter is documented in wp-includes/formatting.php */ |
3472 /** This filter is documented in wp-includes/formatting.php */ |
3341 return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' ); |
3473 return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' ); |
3342 } |
3474 } |
3343 } |
3475 } |
3344 |
3476 |
3345 // Congratulations your email made it! |
3477 // Congratulations, your email made it! |
3346 /** This filter is documented in wp-includes/formatting.php */ |
3478 /** This filter is documented in wp-includes/formatting.php */ |
3347 return apply_filters( 'is_email', $email, $email, null ); |
3479 return apply_filters( 'is_email', $email, $email, null ); |
3348 } |
3480 } |
3349 |
3481 |
3350 /** |
3482 /** |
3377 function _wp_iso_convert( $match ) { |
3509 function _wp_iso_convert( $match ) { |
3378 return chr( hexdec( strtolower( $match[1] ) ) ); |
3510 return chr( hexdec( strtolower( $match[1] ) ) ); |
3379 } |
3511 } |
3380 |
3512 |
3381 /** |
3513 /** |
3382 * Returns a date in the GMT equivalent. |
3514 * Given a date in the timezone of the site, returns that date in UTC. |
3383 * |
3515 * |
3384 * Requires and returns a date in the Y-m-d H:i:s format. If there is a |
3516 * Requires and returns a date in the Y-m-d H:i:s format. |
3385 * timezone_string available, the date is assumed to be in that timezone, |
3517 * Return format can be overridden using the $format parameter. |
3386 * otherwise it simply subtracts the value of the 'gmt_offset' option. Return |
|
3387 * format can be overridden using the $format parameter. |
|
3388 * |
3518 * |
3389 * @since 1.2.0 |
3519 * @since 1.2.0 |
3390 * |
3520 * |
3391 * @param string $string The date to be converted. |
3521 * @param string $string The date to be converted, in the timezone of the site. |
3392 * @param string $format The format string for the returned date (default is Y-m-d H:i:s) |
3522 * @param string $format The format string for the returned date. Default 'Y-m-d H:i:s'. |
3393 * @return string GMT version of the date provided. |
3523 * @return string Formatted version of the date, in UTC. |
3394 */ |
3524 */ |
3395 function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) { |
3525 function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) { |
3396 $tz = get_option( 'timezone_string' ); |
3526 $datetime = date_create( $string, wp_timezone() ); |
3397 if ( $tz ) { |
3527 |
3398 $datetime = date_create( $string, new DateTimeZone( $tz ) ); |
3528 if ( false === $datetime ) { |
3399 if ( ! $datetime ) { |
3529 return gmdate( $format, 0 ); |
3400 return gmdate( $format, 0 ); |
3530 } |
3401 } |
3531 |
3402 $datetime->setTimezone( new DateTimeZone( 'UTC' ) ); |
3532 return $datetime->setTimezone( new DateTimeZone( 'UTC' ) )->format( $format ); |
3403 $string_gmt = $datetime->format( $format ); |
3533 } |
3404 } else { |
3534 |
3405 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 ) ) { |
3535 /** |
3406 $datetime = strtotime( $string ); |
3536 * Given a date in UTC or GMT timezone, returns that date in the timezone of the site. |
3407 if ( false === $datetime ) { |
3537 * |
3408 return gmdate( $format, 0 ); |
3538 * Requires and returns a date in the Y-m-d H:i:s format. |
3409 } |
3539 * Return format can be overridden using the $format parameter. |
3410 return gmdate( $format, $datetime ); |
|
3411 } |
|
3412 $string_time = gmmktime( $matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1] ); |
|
3413 $string_gmt = gmdate( $format, $string_time - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); |
|
3414 } |
|
3415 return $string_gmt; |
|
3416 } |
|
3417 |
|
3418 /** |
|
3419 * Converts a GMT date into the correct format for the blog. |
|
3420 * |
|
3421 * Requires and returns a date in the Y-m-d H:i:s format. If there is a |
|
3422 * timezone_string available, the returned date is in that timezone, otherwise |
|
3423 * it simply adds the value of gmt_offset. Return format can be overridden |
|
3424 * using the $format parameter |
|
3425 * |
3540 * |
3426 * @since 1.2.0 |
3541 * @since 1.2.0 |
3427 * |
3542 * |
3428 * @param string $string The date to be converted. |
3543 * @param string $string The date to be converted, in UTC or GMT timezone. |
3429 * @param string $format The format string for the returned date (default is Y-m-d H:i:s) |
3544 * @param string $format The format string for the returned date. Default 'Y-m-d H:i:s'. |
3430 * @return string Formatted date relative to the timezone / GMT offset. |
3545 * @return string Formatted version of the date, in the site's timezone. |
3431 */ |
3546 */ |
3432 function get_date_from_gmt( $string, $format = 'Y-m-d H:i:s' ) { |
3547 function get_date_from_gmt( $string, $format = 'Y-m-d H:i:s' ) { |
3433 $tz = get_option( 'timezone_string' ); |
3548 $datetime = date_create( $string, new DateTimeZone( 'UTC' ) ); |
3434 if ( $tz ) { |
3549 |
3435 $datetime = date_create( $string, new DateTimeZone( 'UTC' ) ); |
3550 if ( false === $datetime ) { |
3436 if ( ! $datetime ) { |
3551 return gmdate( $format, 0 ); |
3437 return date( $format, 0 ); |
3552 } |
3438 } |
3553 |
3439 $datetime->setTimezone( new DateTimeZone( $tz ) ); |
3554 return $datetime->setTimezone( wp_timezone() )->format( $format ); |
3440 $string_localtime = $datetime->format( $format ); |
3555 } |
3441 } else { |
3556 |
3442 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 ) ) { |
3557 /** |
3443 return date( $format, 0 ); |
3558 * Given an ISO 8601 timezone, returns its UTC offset in seconds. |
3444 } |
|
3445 $string_time = gmmktime( $matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1] ); |
|
3446 $string_localtime = gmdate( $format, $string_time + get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); |
|
3447 } |
|
3448 return $string_localtime; |
|
3449 } |
|
3450 |
|
3451 /** |
|
3452 * Computes an offset in seconds from an iso8601 timezone. |
|
3453 * |
3559 * |
3454 * @since 1.5.0 |
3560 * @since 1.5.0 |
3455 * |
3561 * |
3456 * @param string $timezone Either 'Z' for 0 offset or '±hhmm'. |
3562 * @param string $timezone Either 'Z' for 0 offset or '±hhmm'. |
3457 * @return int|float The offset in seconds. |
3563 * @return int|float The offset in seconds. |
3458 */ |
3564 */ |
3459 function iso8601_timezone_to_offset( $timezone ) { |
3565 function iso8601_timezone_to_offset( $timezone ) { |
3460 // $timezone is either 'Z' or '[+|-]hhmm' |
3566 // $timezone is either 'Z' or '[+|-]hhmm'. |
3461 if ( $timezone == 'Z' ) { |
3567 if ( 'Z' === $timezone ) { |
3462 $offset = 0; |
3568 $offset = 0; |
3463 } else { |
3569 } else { |
3464 $sign = ( substr( $timezone, 0, 1 ) == '+' ) ? 1 : -1; |
3570 $sign = ( '+' === substr( $timezone, 0, 1 ) ) ? 1 : -1; |
3465 $hours = intval( substr( $timezone, 1, 2 ) ); |
3571 $hours = intval( substr( $timezone, 1, 2 ) ); |
3466 $minutes = intval( substr( $timezone, 3, 4 ) ) / 60; |
3572 $minutes = intval( substr( $timezone, 3, 4 ) ) / 60; |
3467 $offset = $sign * HOUR_IN_SECONDS * ( $hours + $minutes ); |
3573 $offset = $sign * HOUR_IN_SECONDS * ( $hours + $minutes ); |
3468 } |
3574 } |
3469 return $offset; |
3575 return $offset; |
3470 } |
3576 } |
3471 |
3577 |
3472 /** |
3578 /** |
3473 * Converts an iso8601 date to MySQL DateTime format used by post_date[_gmt]. |
3579 * Given an ISO 8601 (Ymd\TH:i:sO) date, returns a MySQL DateTime (Y-m-d H:i:s) format used by post_date[_gmt]. |
3474 * |
3580 * |
3475 * @since 1.5.0 |
3581 * @since 1.5.0 |
3476 * |
3582 * |
3477 * @param string $date_string Date and time in ISO 8601 format {@link https://en.wikipedia.org/wiki/ISO_8601}. |
3583 * @param string $date_string Date and time in ISO 8601 format {@link https://en.wikipedia.org/wiki/ISO_8601}. |
3478 * @param string $timezone Optional. If set to GMT returns the time minus gmt_offset. Default is 'user'. |
3584 * @param string $timezone Optional. If set to 'gmt' returns the result in UTC. Default 'user'. |
3479 * @return string The date and time in MySQL DateTime format - Y-m-d H:i:s. |
3585 * @return string|bool The date and time in MySQL DateTime format - Y-m-d H:i:s, or false on failure. |
3480 */ |
3586 */ |
3481 function iso8601_to_datetime( $date_string, $timezone = 'user' ) { |
3587 function iso8601_to_datetime( $date_string, $timezone = 'user' ) { |
3482 $timezone = strtolower( $timezone ); |
3588 $timezone = strtolower( $timezone ); |
3483 |
3589 $wp_timezone = wp_timezone(); |
3484 if ( $timezone == 'gmt' ) { |
3590 $datetime = date_create( $date_string, $wp_timezone ); // Timezone is ignored if input has one. |
3485 |
3591 |
3486 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 ); |
3592 if ( false === $datetime ) { |
3487 |
3593 return false; |
3488 if ( ! empty( $date_bits[7] ) ) { // we have a timezone, so let's compute an offset |
3594 } |
3489 $offset = iso8601_timezone_to_offset( $date_bits[7] ); |
3595 |
3490 } else { // we don't have a timezone, so we assume user local timezone (not server's!) |
3596 if ( 'gmt' === $timezone ) { |
3491 $offset = HOUR_IN_SECONDS * get_option( 'gmt_offset' ); |
3597 return $datetime->setTimezone( new DateTimeZone( 'UTC' ) )->format( 'Y-m-d H:i:s' ); |
3492 } |
3598 } |
3493 |
3599 |
3494 $timestamp = gmmktime( $date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1] ); |
3600 if ( 'user' === $timezone ) { |
3495 $timestamp -= $offset; |
3601 return $datetime->setTimezone( $wp_timezone )->format( 'Y-m-d H:i:s' ); |
3496 |
3602 } |
3497 return gmdate( 'Y-m-d H:i:s', $timestamp ); |
3603 |
3498 |
3604 return false; |
3499 } elseif ( $timezone == 'user' ) { |
|
3500 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 ); |
|
3501 } |
|
3502 } |
3605 } |
3503 |
3606 |
3504 /** |
3607 /** |
3505 * Strips out all characters that are not allowable in an email. |
3608 * Strips out all characters that are not allowable in an email. |
3506 * |
3609 * |
3508 * |
3611 * |
3509 * @param string $email Email address to filter. |
3612 * @param string $email Email address to filter. |
3510 * @return string Filtered email address. |
3613 * @return string Filtered email address. |
3511 */ |
3614 */ |
3512 function sanitize_email( $email ) { |
3615 function sanitize_email( $email ) { |
3513 // Test for the minimum length the email can be |
3616 // Test for the minimum length the email can be. |
3514 if ( strlen( $email ) < 6 ) { |
3617 if ( strlen( $email ) < 6 ) { |
3515 /** |
3618 /** |
3516 * Filters a sanitized email address. |
3619 * Filters a sanitized email address. |
3517 * |
3620 * |
3518 * This filter is evaluated under several contexts, including 'email_too_short', |
3621 * This filter is evaluated under several contexts, including 'email_too_short', |
3526 * @param string|null $message A message to pass to the user. null if email is sanitized. |
3629 * @param string|null $message A message to pass to the user. null if email is sanitized. |
3527 */ |
3630 */ |
3528 return apply_filters( 'sanitize_email', '', $email, 'email_too_short' ); |
3631 return apply_filters( 'sanitize_email', '', $email, 'email_too_short' ); |
3529 } |
3632 } |
3530 |
3633 |
3531 // Test for an @ character after the first position |
3634 // Test for an @ character after the first position. |
3532 if ( strpos( $email, '@', 1 ) === false ) { |
3635 if ( strpos( $email, '@', 1 ) === false ) { |
3533 /** This filter is documented in wp-includes/formatting.php */ |
3636 /** This filter is documented in wp-includes/formatting.php */ |
3534 return apply_filters( 'sanitize_email', '', $email, 'email_no_at' ); |
3637 return apply_filters( 'sanitize_email', '', $email, 'email_no_at' ); |
3535 } |
3638 } |
3536 |
3639 |
3537 // Split out the local and domain parts |
3640 // Split out the local and domain parts. |
3538 list( $local, $domain ) = explode( '@', $email, 2 ); |
3641 list( $local, $domain ) = explode( '@', $email, 2 ); |
3539 |
3642 |
3540 // LOCAL PART |
3643 // LOCAL PART |
3541 // Test for invalid characters |
3644 // Test for invalid characters. |
3542 $local = preg_replace( '/[^a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]/', '', $local ); |
3645 $local = preg_replace( '/[^a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]/', '', $local ); |
3543 if ( '' === $local ) { |
3646 if ( '' === $local ) { |
3544 /** This filter is documented in wp-includes/formatting.php */ |
3647 /** This filter is documented in wp-includes/formatting.php */ |
3545 return apply_filters( 'sanitize_email', '', $email, 'local_invalid_chars' ); |
3648 return apply_filters( 'sanitize_email', '', $email, 'local_invalid_chars' ); |
3546 } |
3649 } |
3547 |
3650 |
3548 // DOMAIN PART |
3651 // DOMAIN PART |
3549 // Test for sequences of periods |
3652 // Test for sequences of periods. |
3550 $domain = preg_replace( '/\.{2,}/', '', $domain ); |
3653 $domain = preg_replace( '/\.{2,}/', '', $domain ); |
3551 if ( '' === $domain ) { |
3654 if ( '' === $domain ) { |
3552 /** This filter is documented in wp-includes/formatting.php */ |
3655 /** This filter is documented in wp-includes/formatting.php */ |
3553 return apply_filters( 'sanitize_email', '', $email, 'domain_period_sequence' ); |
3656 return apply_filters( 'sanitize_email', '', $email, 'domain_period_sequence' ); |
3554 } |
3657 } |
3555 |
3658 |
3556 // Test for leading and trailing periods and whitespace |
3659 // Test for leading and trailing periods and whitespace. |
3557 $domain = trim( $domain, " \t\n\r\0\x0B." ); |
3660 $domain = trim( $domain, " \t\n\r\0\x0B." ); |
3558 if ( '' === $domain ) { |
3661 if ( '' === $domain ) { |
3559 /** This filter is documented in wp-includes/formatting.php */ |
3662 /** This filter is documented in wp-includes/formatting.php */ |
3560 return apply_filters( 'sanitize_email', '', $email, 'domain_period_limits' ); |
3663 return apply_filters( 'sanitize_email', '', $email, 'domain_period_limits' ); |
3561 } |
3664 } |
3562 |
3665 |
3563 // Split the domain into subs |
3666 // Split the domain into subs. |
3564 $subs = explode( '.', $domain ); |
3667 $subs = explode( '.', $domain ); |
3565 |
3668 |
3566 // Assume the domain will have at least two subs |
3669 // Assume the domain will have at least two subs. |
3567 if ( 2 > count( $subs ) ) { |
3670 if ( 2 > count( $subs ) ) { |
3568 /** This filter is documented in wp-includes/formatting.php */ |
3671 /** This filter is documented in wp-includes/formatting.php */ |
3569 return apply_filters( 'sanitize_email', '', $email, 'domain_no_periods' ); |
3672 return apply_filters( 'sanitize_email', '', $email, 'domain_no_periods' ); |
3570 } |
3673 } |
3571 |
3674 |
3572 // Create an array that will contain valid subs |
3675 // Create an array that will contain valid subs. |
3573 $new_subs = array(); |
3676 $new_subs = array(); |
3574 |
3677 |
3575 // Loop through each sub |
3678 // Loop through each sub. |
3576 foreach ( $subs as $sub ) { |
3679 foreach ( $subs as $sub ) { |
3577 // Test for leading and trailing hyphens |
3680 // Test for leading and trailing hyphens. |
3578 $sub = trim( $sub, " \t\n\r\0\x0B-" ); |
3681 $sub = trim( $sub, " \t\n\r\0\x0B-" ); |
3579 |
3682 |
3580 // Test for invalid characters |
3683 // Test for invalid characters. |
3581 $sub = preg_replace( '/[^a-z0-9-]+/i', '', $sub ); |
3684 $sub = preg_replace( '/[^a-z0-9-]+/i', '', $sub ); |
3582 |
3685 |
3583 // If there's anything left, add it to the valid subs |
3686 // If there's anything left, add it to the valid subs. |
3584 if ( '' !== $sub ) { |
3687 if ( '' !== $sub ) { |
3585 $new_subs[] = $sub; |
3688 $new_subs[] = $sub; |
3586 } |
3689 } |
3587 } |
3690 } |
3588 |
3691 |
3589 // If there aren't 2 or more valid subs |
3692 // If there aren't 2 or more valid subs. |
3590 if ( 2 > count( $new_subs ) ) { |
3693 if ( 2 > count( $new_subs ) ) { |
3591 /** This filter is documented in wp-includes/formatting.php */ |
3694 /** This filter is documented in wp-includes/formatting.php */ |
3592 return apply_filters( 'sanitize_email', '', $email, 'domain_no_valid_subs' ); |
3695 return apply_filters( 'sanitize_email', '', $email, 'domain_no_valid_subs' ); |
3593 } |
3696 } |
3594 |
3697 |
3595 // Join valid subs into the new domain |
3698 // Join valid subs into the new domain. |
3596 $domain = join( '.', $new_subs ); |
3699 $domain = join( '.', $new_subs ); |
3597 |
3700 |
3598 // Put the email back together |
3701 // Put the email back together. |
3599 $sanitized_email = $local . '@' . $domain; |
3702 $sanitized_email = $local . '@' . $domain; |
3600 |
3703 |
3601 // Congratulations your email made it! |
3704 // Congratulations, your email made it! |
3602 /** This filter is documented in wp-includes/formatting.php */ |
3705 /** This filter is documented in wp-includes/formatting.php */ |
3603 return apply_filters( 'sanitize_email', $sanitized_email, $email, null ); |
3706 return apply_filters( 'sanitize_email', $sanitized_email, $email, null ); |
3604 } |
3707 } |
3605 |
3708 |
3606 /** |
3709 /** |
3608 * |
3711 * |
3609 * The difference is returned in a human readable format such as "1 hour", |
3712 * The difference is returned in a human readable format such as "1 hour", |
3610 * "5 mins", "2 days". |
3713 * "5 mins", "2 days". |
3611 * |
3714 * |
3612 * @since 1.5.0 |
3715 * @since 1.5.0 |
3716 * @since 5.3.0 Added support for showing a difference in seconds. |
|
3613 * |
3717 * |
3614 * @param int $from Unix timestamp from which the difference begins. |
3718 * @param int $from Unix timestamp from which the difference begins. |
3615 * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. |
3719 * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. |
3616 * @return string Human readable time difference. |
3720 * @return string Human readable time difference. |
3617 */ |
3721 */ |
3618 function human_time_diff( $from, $to = '' ) { |
3722 function human_time_diff( $from, $to = 0 ) { |
3619 if ( empty( $to ) ) { |
3723 if ( empty( $to ) ) { |
3620 $to = time(); |
3724 $to = time(); |
3621 } |
3725 } |
3622 |
3726 |
3623 $diff = (int) abs( $to - $from ); |
3727 $diff = (int) abs( $to - $from ); |
3624 |
3728 |
3625 if ( $diff < HOUR_IN_SECONDS ) { |
3729 if ( $diff < MINUTE_IN_SECONDS ) { |
3730 $secs = $diff; |
|
3731 if ( $secs <= 1 ) { |
|
3732 $secs = 1; |
|
3733 } |
|
3734 /* translators: Time difference between two dates, in seconds. %s: Number of seconds. */ |
|
3735 $since = sprintf( _n( '%s second', '%s seconds', $secs ), $secs ); |
|
3736 } elseif ( $diff < HOUR_IN_SECONDS && $diff >= MINUTE_IN_SECONDS ) { |
|
3626 $mins = round( $diff / MINUTE_IN_SECONDS ); |
3737 $mins = round( $diff / MINUTE_IN_SECONDS ); |
3627 if ( $mins <= 1 ) { |
3738 if ( $mins <= 1 ) { |
3628 $mins = 1; |
3739 $mins = 1; |
3629 } |
3740 } |
3630 /* translators: Time difference between two dates, in minutes (min=minute). %s: Number of minutes */ |
3741 /* translators: Time difference between two dates, in minutes (min=minute). %s: Number of minutes. */ |
3631 $since = sprintf( _n( '%s min', '%s mins', $mins ), $mins ); |
3742 $since = sprintf( _n( '%s min', '%s mins', $mins ), $mins ); |
3632 } elseif ( $diff < DAY_IN_SECONDS && $diff >= HOUR_IN_SECONDS ) { |
3743 } elseif ( $diff < DAY_IN_SECONDS && $diff >= HOUR_IN_SECONDS ) { |
3633 $hours = round( $diff / HOUR_IN_SECONDS ); |
3744 $hours = round( $diff / HOUR_IN_SECONDS ); |
3634 if ( $hours <= 1 ) { |
3745 if ( $hours <= 1 ) { |
3635 $hours = 1; |
3746 $hours = 1; |
3636 } |
3747 } |
3637 /* translators: Time difference between two dates, in hours. %s: Number of hours */ |
3748 /* translators: Time difference between two dates, in hours. %s: Number of hours. */ |
3638 $since = sprintf( _n( '%s hour', '%s hours', $hours ), $hours ); |
3749 $since = sprintf( _n( '%s hour', '%s hours', $hours ), $hours ); |
3639 } elseif ( $diff < WEEK_IN_SECONDS && $diff >= DAY_IN_SECONDS ) { |
3750 } elseif ( $diff < WEEK_IN_SECONDS && $diff >= DAY_IN_SECONDS ) { |
3640 $days = round( $diff / DAY_IN_SECONDS ); |
3751 $days = round( $diff / DAY_IN_SECONDS ); |
3641 if ( $days <= 1 ) { |
3752 if ( $days <= 1 ) { |
3642 $days = 1; |
3753 $days = 1; |
3643 } |
3754 } |
3644 /* translators: Time difference between two dates, in days. %s: Number of days */ |
3755 /* translators: Time difference between two dates, in days. %s: Number of days. */ |
3645 $since = sprintf( _n( '%s day', '%s days', $days ), $days ); |
3756 $since = sprintf( _n( '%s day', '%s days', $days ), $days ); |
3646 } elseif ( $diff < MONTH_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) { |
3757 } elseif ( $diff < MONTH_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) { |
3647 $weeks = round( $diff / WEEK_IN_SECONDS ); |
3758 $weeks = round( $diff / WEEK_IN_SECONDS ); |
3648 if ( $weeks <= 1 ) { |
3759 if ( $weeks <= 1 ) { |
3649 $weeks = 1; |
3760 $weeks = 1; |
3650 } |
3761 } |
3651 /* translators: Time difference between two dates, in weeks. %s: Number of weeks */ |
3762 /* translators: Time difference between two dates, in weeks. %s: Number of weeks. */ |
3652 $since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks ); |
3763 $since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks ); |
3653 } elseif ( $diff < YEAR_IN_SECONDS && $diff >= MONTH_IN_SECONDS ) { |
3764 } elseif ( $diff < YEAR_IN_SECONDS && $diff >= MONTH_IN_SECONDS ) { |
3654 $months = round( $diff / MONTH_IN_SECONDS ); |
3765 $months = round( $diff / MONTH_IN_SECONDS ); |
3655 if ( $months <= 1 ) { |
3766 if ( $months <= 1 ) { |
3656 $months = 1; |
3767 $months = 1; |
3657 } |
3768 } |
3658 /* translators: Time difference between two dates, in months. %s: Number of months */ |
3769 /* translators: Time difference between two dates, in months. %s: Number of months. */ |
3659 $since = sprintf( _n( '%s month', '%s months', $months ), $months ); |
3770 $since = sprintf( _n( '%s month', '%s months', $months ), $months ); |
3660 } elseif ( $diff >= YEAR_IN_SECONDS ) { |
3771 } elseif ( $diff >= YEAR_IN_SECONDS ) { |
3661 $years = round( $diff / YEAR_IN_SECONDS ); |
3772 $years = round( $diff / YEAR_IN_SECONDS ); |
3662 if ( $years <= 1 ) { |
3773 if ( $years <= 1 ) { |
3663 $years = 1; |
3774 $years = 1; |
3664 } |
3775 } |
3665 /* translators: Time difference between two dates, in years. %s: Number of years */ |
3776 /* translators: Time difference between two dates, in years. %s: Number of years. */ |
3666 $since = sprintf( _n( '%s year', '%s years', $years ), $years ); |
3777 $since = sprintf( _n( '%s year', '%s years', $years ), $years ); |
3667 } |
3778 } |
3668 |
3779 |
3669 /** |
3780 /** |
3670 * Filters the human readable difference between two timestamps. |
3781 * Filters the human readable difference between two timestamps. |
3680 } |
3791 } |
3681 |
3792 |
3682 /** |
3793 /** |
3683 * Generates an excerpt from the content, if needed. |
3794 * Generates an excerpt from the content, if needed. |
3684 * |
3795 * |
3685 * The excerpt word amount will be 55 words and if the amount is greater than |
3796 * Returns a maximum of 55 words with an ellipsis appended if necessary. |
3686 * that, then the string ' […]' will be appended to the excerpt. If the string |
|
3687 * is less than 55 words, then the content will be returned as is. |
|
3688 * |
3797 * |
3689 * The 55 word limit can be modified by plugins/themes using the {@see 'excerpt_length'} filter |
3798 * The 55 word limit can be modified by plugins/themes using the {@see 'excerpt_length'} filter |
3690 * The ' […]' string can be modified by plugins/themes using the {@see 'excerpt_more'} filter |
3799 * The ' […]' string can be modified by plugins/themes using the {@see 'excerpt_more'} filter |
3691 * |
3800 * |
3692 * @since 1.5.0 |
3801 * @since 1.5.0 |
3693 * @since 5.2.0 Added the `$post` parameter. |
3802 * @since 5.2.0 Added the `$post` parameter. |
3694 * |
3803 * |
3695 * @param string $text Optional. The excerpt. If set to empty, an excerpt is generated. |
3804 * @param string $text Optional. The excerpt. If set to empty, an excerpt is generated. |
3696 * @param WP_Post|object|int $post Optional. WP_Post instance or Post ID/object. Default is null. |
3805 * @param WP_Post|object|int $post Optional. WP_Post instance or Post ID/object. Default null. |
3697 * @return string The excerpt. |
3806 * @return string The excerpt. |
3698 */ |
3807 */ |
3699 function wp_trim_excerpt( $text = '', $post = null ) { |
3808 function wp_trim_excerpt( $text = '', $post = null ) { |
3700 $raw_excerpt = $text; |
3809 $raw_excerpt = $text; |
3701 if ( '' == $text ) { |
3810 |
3811 if ( '' === trim( $text ) ) { |
|
3702 $post = get_post( $post ); |
3812 $post = get_post( $post ); |
3703 $text = get_the_content( '', false, $post ); |
3813 $text = get_the_content( '', false, $post ); |
3704 |
3814 |
3705 $text = strip_shortcodes( $text ); |
3815 $text = strip_shortcodes( $text ); |
3706 $text = excerpt_remove_blocks( $text ); |
3816 $text = excerpt_remove_blocks( $text ); |
3707 |
3817 |
3708 /** This filter is documented in wp-includes/post-template.php */ |
3818 /** This filter is documented in wp-includes/post-template.php */ |
3709 $text = apply_filters( 'the_content', $text ); |
3819 $text = apply_filters( 'the_content', $text ); |
3710 $text = str_replace( ']]>', ']]>', $text ); |
3820 $text = str_replace( ']]>', ']]>', $text ); |
3711 |
3821 |
3822 /* translators: Maximum number of words used in a post excerpt. */ |
|
3823 $excerpt_length = intval( _x( '55', 'excerpt_length' ) ); |
|
3824 |
|
3712 /** |
3825 /** |
3713 * Filters the number of words in an excerpt. |
3826 * Filters the maximum number of words in a post excerpt. |
3714 * |
3827 * |
3715 * @since 2.7.0 |
3828 * @since 2.7.0 |
3716 * |
3829 * |
3717 * @param int $number The number of words. Default 55. |
3830 * @param int $number The maximum number of words. Default 55. |
3718 */ |
3831 */ |
3719 $excerpt_length = apply_filters( 'excerpt_length', 55 ); |
3832 $excerpt_length = (int) apply_filters( 'excerpt_length', $excerpt_length ); |
3833 |
|
3720 /** |
3834 /** |
3721 * Filters the string in the "more" link displayed after a trimmed excerpt. |
3835 * Filters the string in the "more" link displayed after a trimmed excerpt. |
3722 * |
3836 * |
3723 * @since 2.9.0 |
3837 * @since 2.9.0 |
3724 * |
3838 * |
3725 * @param string $more_string The string shown within the more link. |
3839 * @param string $more_string The string shown within the more link. |
3726 */ |
3840 */ |
3727 $excerpt_more = apply_filters( 'excerpt_more', ' ' . '[…]' ); |
3841 $excerpt_more = apply_filters( 'excerpt_more', ' ' . '[…]' ); |
3728 $text = wp_trim_words( $text, $excerpt_length, $excerpt_more ); |
3842 $text = wp_trim_words( $text, $excerpt_length, $excerpt_more ); |
3729 } |
3843 } |
3844 |
|
3730 /** |
3845 /** |
3731 * Filters the trimmed excerpt string. |
3846 * Filters the trimmed excerpt string. |
3732 * |
3847 * |
3733 * @since 2.8.0 |
3848 * @since 2.8.0 |
3734 * |
3849 * |
3757 $more = __( '…' ); |
3872 $more = __( '…' ); |
3758 } |
3873 } |
3759 |
3874 |
3760 $original_text = $text; |
3875 $original_text = $text; |
3761 $text = wp_strip_all_tags( $text ); |
3876 $text = wp_strip_all_tags( $text ); |
3877 $num_words = (int) $num_words; |
|
3762 |
3878 |
3763 /* |
3879 /* |
3764 * translators: If your word count is based on single characters (e.g. East Asian characters), |
3880 * translators: If your word count is based on single characters (e.g. East Asian characters), |
3765 * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. |
3881 * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. |
3766 * Do not translate into your own language. |
3882 * Do not translate into your own language. |
3811 * |
3927 * |
3812 * A non-null string must be returned for the filter to be evaluated. |
3928 * A non-null string must be returned for the filter to be evaluated. |
3813 * |
3929 * |
3814 * @since 3.3.0 |
3930 * @since 3.3.0 |
3815 * |
3931 * |
3816 * @param null $converted_text The text to be converted. Default null. |
3932 * @param string|null $converted_text The text to be converted. Default null. |
3817 * @param string $text The text prior to entity conversion. |
3933 * @param string $text The text prior to entity conversion. |
3818 */ |
3934 */ |
3819 $filtered = apply_filters( 'pre_ent2ncr', null, $text ); |
3935 $filtered = apply_filters( 'pre_ent2ncr', null, $text ); |
3820 if ( null !== $filtered ) { |
3936 if ( null !== $filtered ) { |
3821 return $filtered; |
3937 return $filtered; |
3822 } |
3938 } |
4175 * (the default behaviour) ampersands are also replaced. The {@see 'clean_url'} filter |
4291 * (the default behaviour) ampersands are also replaced. The {@see 'clean_url'} filter |
4176 * is applied to the returned cleaned URL. |
4292 * is applied to the returned cleaned URL. |
4177 * |
4293 * |
4178 * @since 2.8.0 |
4294 * @since 2.8.0 |
4179 * |
4295 * |
4180 * @param string $url The URL to be cleaned. |
4296 * @param string $url The URL to be cleaned. |
4181 * @param array $protocols Optional. An array of acceptable protocols. |
4297 * @param string[] $protocols Optional. An array of acceptable protocols. |
4182 * Defaults to return value of wp_allowed_protocols() |
4298 * Defaults to return value of wp_allowed_protocols(). |
4183 * @param string $_context Private. Use esc_url_raw() for database usage. |
4299 * @param string $_context Private. Use esc_url_raw() for database usage. |
4184 * @return string The cleaned $url after the {@see 'clean_url'} filter is applied. |
4300 * @return string The cleaned URL after the {@see 'clean_url'} filter is applied. |
4185 */ |
4301 */ |
4186 function esc_url( $url, $protocols = null, $_context = 'display' ) { |
4302 function esc_url( $url, $protocols = null, $_context = 'display' ) { |
4187 $original_url = $url; |
4303 $original_url = $url; |
4188 |
4304 |
4189 if ( '' == $url ) { |
4305 if ( '' === $url ) { |
4190 return $url; |
4306 return $url; |
4191 } |
4307 } |
4192 |
4308 |
4193 $url = str_replace( ' ', '%20', $url ); |
4309 $url = str_replace( ' ', '%20', ltrim( $url ) ); |
4194 $url = preg_replace( '|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url ); |
4310 $url = preg_replace( '|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url ); |
4195 |
4311 |
4196 if ( '' === $url ) { |
4312 if ( '' === $url ) { |
4197 return $url; |
4313 return $url; |
4198 } |
4314 } |
4201 $strip = array( '%0d', '%0a', '%0D', '%0A' ); |
4317 $strip = array( '%0d', '%0a', '%0D', '%0A' ); |
4202 $url = _deep_replace( $strip, $url ); |
4318 $url = _deep_replace( $strip, $url ); |
4203 } |
4319 } |
4204 |
4320 |
4205 $url = str_replace( ';//', '://', $url ); |
4321 $url = str_replace( ';//', '://', $url ); |
4206 /* If the URL doesn't appear to contain a scheme, we |
4322 /* |
4207 * presume it needs http:// prepended (unless a relative |
4323 * If the URL doesn't appear to contain a scheme, we presume |
4208 * link starting with /, # or ? or a php file). |
4324 * it needs http:// prepended (unless it's a relative link |
4325 * starting with /, # or ?, or a PHP file). |
|
4209 */ |
4326 */ |
4210 if ( strpos( $url, ':' ) === false && ! in_array( $url[0], array( '/', '#', '?' ) ) && |
4327 if ( strpos( $url, ':' ) === false && ! in_array( $url[0], array( '/', '#', '?' ), true ) && |
4211 ! preg_match( '/^[a-z0-9-]+?\.php/i', $url ) ) { |
4328 ! preg_match( '/^[a-z0-9-]+?\.php/i', $url ) ) { |
4212 $url = 'http://' . $url; |
4329 $url = 'http://' . $url; |
4213 } |
4330 } |
4214 |
4331 |
4215 // Replace ampersands and single quotes only when displaying. |
4332 // Replace ampersands and single quotes only when displaying. |
4216 if ( 'display' == $_context ) { |
4333 if ( 'display' === $_context ) { |
4217 $url = wp_kses_normalize_entities( $url ); |
4334 $url = wp_kses_normalize_entities( $url ); |
4218 $url = str_replace( '&', '&', $url ); |
4335 $url = str_replace( '&', '&', $url ); |
4219 $url = str_replace( "'", ''', $url ); |
4336 $url = str_replace( "'", ''', $url ); |
4220 } |
4337 } |
4221 |
4338 |
4283 /** |
4400 /** |
4284 * Performs esc_url() for database usage. |
4401 * Performs esc_url() for database usage. |
4285 * |
4402 * |
4286 * @since 2.8.0 |
4403 * @since 2.8.0 |
4287 * |
4404 * |
4288 * @param string $url The URL to be cleaned. |
4405 * @param string $url The URL to be cleaned. |
4289 * @param array $protocols An array of acceptable protocols. |
4406 * @param string[] $protocols Optional. An array of acceptable protocols. |
4407 * Defaults to return value of wp_allowed_protocols(). |
|
4290 * @return string The cleaned URL. |
4408 * @return string The cleaned URL. |
4291 */ |
4409 */ |
4292 function esc_url_raw( $url, $protocols = null ) { |
4410 function esc_url_raw( $url, $protocols = null ) { |
4293 return esc_url( $url, $protocols, 'db' ); |
4411 return esc_url( $url, $protocols, 'db' ); |
4294 } |
4412 } |
4295 |
4413 |
4296 /** |
4414 /** |
4297 * Convert entities, while preserving already-encoded entities. |
4415 * Convert entities, while preserving already-encoded entities. |
4298 * |
4416 * |
4299 * @link https://secure.php.net/htmlentities Borrowed from the PHP Manual user notes. |
4417 * @link https://www.php.net/htmlentities Borrowed from the PHP Manual user notes. |
4300 * |
4418 * |
4301 * @since 1.2.2 |
4419 * @since 1.2.2 |
4302 * |
4420 * |
4303 * @param string $myHTML The text to be converted. |
4421 * @param string $myHTML The text to be converted. |
4304 * @return string Converted text. |
4422 * @return string Converted text. |
4408 * |
4526 * |
4409 * @param string $safe_text The text after it has been escaped. |
4527 * @param string $safe_text The text after it has been escaped. |
4410 * @param string $text The text prior to being escaped. |
4528 * @param string $text The text prior to being escaped. |
4411 */ |
4529 */ |
4412 return apply_filters( 'esc_textarea', $safe_text, $text ); |
4530 return apply_filters( 'esc_textarea', $safe_text, $text ); |
4531 } |
|
4532 |
|
4533 /** |
|
4534 * Escaping for XML blocks. |
|
4535 * |
|
4536 * @since 5.5.0 |
|
4537 * |
|
4538 * @param string $text Text to escape. |
|
4539 * @return string Escaped text. |
|
4540 */ |
|
4541 function esc_xml( $text ) { |
|
4542 $safe_text = wp_check_invalid_utf8( $text ); |
|
4543 |
|
4544 $cdata_regex = '\<\!\[CDATA\[.*?\]\]\>'; |
|
4545 $regex = <<<EOF |
|
4546 / |
|
4547 (?=.*?{$cdata_regex}) # lookahead that will match anything followed by a CDATA Section |
|
4548 (?<non_cdata_followed_by_cdata>(.*?)) # the "anything" matched by the lookahead |
|
4549 (?<cdata>({$cdata_regex})) # the CDATA Section matched by the lookahead |
|
4550 |
|
4551 | # alternative |
|
4552 |
|
4553 (?<non_cdata>(.*)) # non-CDATA Section |
|
4554 /sx |
|
4555 EOF; |
|
4556 |
|
4557 $safe_text = (string) preg_replace_callback( |
|
4558 $regex, |
|
4559 static function( $matches ) { |
|
4560 if ( ! $matches[0] ) { |
|
4561 return ''; |
|
4562 } |
|
4563 |
|
4564 if ( ! empty( $matches['non_cdata'] ) ) { |
|
4565 // escape HTML entities in the non-CDATA Section. |
|
4566 return _wp_specialchars( $matches['non_cdata'], ENT_XML1 ); |
|
4567 } |
|
4568 |
|
4569 // Return the CDATA Section unchanged, escape HTML entities in the rest. |
|
4570 return _wp_specialchars( $matches['non_cdata_followed_by_cdata'], ENT_XML1 ) . $matches['cdata']; |
|
4571 }, |
|
4572 $safe_text |
|
4573 ); |
|
4574 |
|
4575 /** |
|
4576 * Filters a string cleaned and escaped for output in XML. |
|
4577 * |
|
4578 * Text passed to esc_xml() is stripped of invalid or special characters |
|
4579 * before output. HTML named character references are converted to their |
|
4580 * equivalent code points. |
|
4581 * |
|
4582 * @since 5.5.0 |
|
4583 * |
|
4584 * @param string $safe_text The text after it has been escaped. |
|
4585 * @param string $text The text prior to being escaped. |
|
4586 */ |
|
4587 return apply_filters( 'esc_xml', $safe_text, $text ); |
|
4413 } |
4588 } |
4414 |
4589 |
4415 /** |
4590 /** |
4416 * Escape an HTML tag name. |
4591 * Escape an HTML tag name. |
4417 * |
4592 * |
4519 } |
4694 } |
4520 break; |
4695 break; |
4521 |
4696 |
4522 case 'default_ping_status': |
4697 case 'default_ping_status': |
4523 case 'default_comment_status': |
4698 case 'default_comment_status': |
4524 // Options that if not there have 0 value but need to be something like "closed" |
4699 // Options that if not there have 0 value but need to be something like "closed". |
4525 if ( $value == '0' || $value == '' ) { |
4700 if ( '0' == $value || '' === $value ) { |
4526 $value = 'closed'; |
4701 $value = 'closed'; |
4527 } |
4702 } |
4528 break; |
4703 break; |
4529 |
4704 |
4530 case 'blogdescription': |
4705 case 'blogdescription': |
4540 $value = esc_html( $value ); |
4715 $value = esc_html( $value ); |
4541 } |
4716 } |
4542 break; |
4717 break; |
4543 |
4718 |
4544 case 'blog_charset': |
4719 case 'blog_charset': |
4545 $value = preg_replace( '/[^a-zA-Z0-9_-]/', '', $value ); // strips slashes |
4720 $value = preg_replace( '/[^a-zA-Z0-9_-]/', '', $value ); // Strips slashes. |
4546 break; |
4721 break; |
4547 |
4722 |
4548 case 'blog_public': |
4723 case 'blog_public': |
4549 // This is the value if the settings checkbox is not checked on POST. Don't rely on this. |
4724 // This is the value if the settings checkbox is not checked on POST. Don't rely on this. |
4550 if ( null === $value ) { |
4725 if ( null === $value ) { |
4575 $value = array_filter( array_map( 'esc_url_raw', $value ) ); |
4750 $value = array_filter( array_map( 'esc_url_raw', $value ) ); |
4576 $value = implode( "\n", $value ); |
4751 $value = implode( "\n", $value ); |
4577 break; |
4752 break; |
4578 |
4753 |
4579 case 'gmt_offset': |
4754 case 'gmt_offset': |
4580 $value = preg_replace( '/[^0-9:.-]/', '', $value ); // strips slashes |
4755 $value = preg_replace( '/[^0-9:.-]/', '', $value ); // Strips slashes. |
4581 break; |
4756 break; |
4582 |
4757 |
4583 case 'siteurl': |
4758 case 'siteurl': |
4584 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4759 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4585 if ( is_wp_error( $value ) ) { |
4760 if ( is_wp_error( $value ) ) { |
4609 case 'WPLANG': |
4784 case 'WPLANG': |
4610 $allowed = get_available_languages(); |
4785 $allowed = get_available_languages(); |
4611 if ( ! is_multisite() && defined( 'WPLANG' ) && '' !== WPLANG && 'en_US' !== WPLANG ) { |
4786 if ( ! is_multisite() && defined( 'WPLANG' ) && '' !== WPLANG && 'en_US' !== WPLANG ) { |
4612 $allowed[] = WPLANG; |
4787 $allowed[] = WPLANG; |
4613 } |
4788 } |
4614 if ( ! in_array( $value, $allowed ) && ! empty( $value ) ) { |
4789 if ( ! in_array( $value, $allowed, true ) && ! empty( $value ) ) { |
4615 $value = get_option( $option ); |
4790 $value = get_option( $option ); |
4616 } |
4791 } |
4617 break; |
4792 break; |
4618 |
4793 |
4619 case 'illegal_names': |
4794 case 'illegal_names': |
4657 } |
4832 } |
4658 break; |
4833 break; |
4659 |
4834 |
4660 case 'timezone_string': |
4835 case 'timezone_string': |
4661 $allowed_zones = timezone_identifiers_list(); |
4836 $allowed_zones = timezone_identifiers_list(); |
4662 if ( ! in_array( $value, $allowed_zones ) && ! empty( $value ) ) { |
4837 if ( ! in_array( $value, $allowed_zones, true ) && ! empty( $value ) ) { |
4663 $error = __( 'The timezone you have entered is not valid. Please select a valid timezone.' ); |
4838 $error = __( 'The timezone you have entered is not valid. Please select a valid timezone.' ); |
4664 } |
4839 } |
4665 break; |
4840 break; |
4666 |
4841 |
4667 case 'permalink_structure': |
4842 case 'permalink_structure': |
4675 $value = str_replace( 'http://', '', $value ); |
4850 $value = str_replace( 'http://', '', $value ); |
4676 } |
4851 } |
4677 |
4852 |
4678 if ( 'permalink_structure' === $option && '' !== $value && ! preg_match( '/%[^\/%]+%/', $value ) ) { |
4853 if ( 'permalink_structure' === $option && '' !== $value && ! preg_match( '/%[^\/%]+%/', $value ) ) { |
4679 $error = sprintf( |
4854 $error = sprintf( |
4680 /* translators: %s: Codex URL */ |
4855 /* translators: %s: Documentation URL. */ |
4681 __( 'A structure tag is required when using custom permalinks. <a href="%s">Learn more</a>' ), |
4856 __( 'A structure tag is required when using custom permalinks. <a href="%s">Learn more</a>' ), |
4682 __( 'https://codex.wordpress.org/Using_Permalinks#Choosing_your_permalink_structure' ) |
4857 __( 'https://wordpress.org/support/article/using-permalinks/#choosing-your-permalink-structure' ) |
4683 ); |
4858 ); |
4684 } |
4859 } |
4685 break; |
4860 break; |
4686 |
4861 |
4687 case 'default_role': |
4862 case 'default_role': |
4689 $value = 'subscriber'; |
4864 $value = 'subscriber'; |
4690 } |
4865 } |
4691 break; |
4866 break; |
4692 |
4867 |
4693 case 'moderation_keys': |
4868 case 'moderation_keys': |
4694 case 'blacklist_keys': |
4869 case 'disallowed_keys': |
4695 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4870 $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); |
4696 if ( is_wp_error( $value ) ) { |
4871 if ( is_wp_error( $value ) ) { |
4697 $error = $value->get_error_message(); |
4872 $error = $value->get_error_message(); |
4698 } else { |
4873 } else { |
4699 $value = explode( "\n", $value ); |
4874 $value = explode( "\n", $value ); |
4753 } |
4928 } |
4754 |
4929 |
4755 /** |
4930 /** |
4756 * Parses a string into variables to be stored in an array. |
4931 * Parses a string into variables to be stored in an array. |
4757 * |
4932 * |
4758 * Uses {@link https://secure.php.net/parse_str parse_str()} and stripslashes if |
|
4759 * {@link https://secure.php.net/magic_quotes magic_quotes_gpc} is on. |
|
4760 * |
|
4761 * @since 2.2.1 |
4933 * @since 2.2.1 |
4762 * |
4934 * |
4763 * @param string $string The string to be parsed. |
4935 * @param string $string The string to be parsed. |
4764 * @param array $array Variables will be stored in this array. |
4936 * @param array $array Variables will be stored in this array. |
4765 */ |
4937 */ |
4766 function wp_parse_str( $string, &$array ) { |
4938 function wp_parse_str( $string, &$array ) { |
4767 parse_str( $string, $array ); |
4939 parse_str( $string, $array ); |
4768 if ( get_magic_quotes_gpc() ) { |
4940 |
4769 $array = stripslashes_deep( $array ); |
|
4770 } |
|
4771 /** |
4941 /** |
4772 * Filters the array of variables derived from a parsed string. |
4942 * Filters the array of variables derived from a parsed string. |
4773 * |
4943 * |
4774 * @since 2.3.0 |
4944 * @since 2.3.0 |
4775 * |
4945 * |
4806 } |
4976 } |
4807 return $matches[0]; |
4977 return $matches[0]; |
4808 } |
4978 } |
4809 |
4979 |
4810 /** |
4980 /** |
4981 * Remove non-allowable HTML from parsed block attribute values when filtering |
|
4982 * in the post context. |
|
4983 * |
|
4984 * @since 5.3.1 |
|
4985 * |
|
4986 * @param string $string Content to be run through KSES. |
|
4987 * @param array[]|string $allowed_html An array of allowed HTML elements |
|
4988 * and attributes, or a context name |
|
4989 * such as 'post'. |
|
4990 * @param string[] $allowed_protocols Array of allowed URL protocols. |
|
4991 * @return string Filtered text to run through KSES. |
|
4992 */ |
|
4993 function wp_pre_kses_block_attributes( $string, $allowed_html, $allowed_protocols ) { |
|
4994 /* |
|
4995 * `filter_block_content` is expected to call `wp_kses`. Temporarily remove |
|
4996 * the filter to avoid recursion. |
|
4997 */ |
|
4998 remove_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10 ); |
|
4999 $string = filter_block_content( $string, $allowed_html, $allowed_protocols ); |
|
5000 add_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10, 3 ); |
|
5001 |
|
5002 return $string; |
|
5003 } |
|
5004 |
|
5005 /** |
|
4811 * WordPress implementation of PHP sprintf() with filters. |
5006 * WordPress implementation of PHP sprintf() with filters. |
4812 * |
5007 * |
4813 * @since 2.5.0 |
5008 * @since 2.5.0 |
4814 * @link https://secure.php.net/sprintf |
5009 * @since 5.3.0 Formalized the existing and already documented `...$args` parameter |
4815 * |
5010 * by adding it to the function signature. |
4816 * @param string $pattern The string which formatted args are inserted. |
5011 * |
4817 * @param mixed $args ,... Arguments to be formatted into the $pattern string. |
5012 * @link https://www.php.net/sprintf |
5013 * |
|
5014 * @param string $pattern The string which formatted args are inserted. |
|
5015 * @param mixed ...$args Arguments to be formatted into the $pattern string. |
|
4818 * @return string The formatted string. |
5016 * @return string The formatted string. |
4819 */ |
5017 */ |
4820 function wp_sprintf( $pattern ) { |
5018 function wp_sprintf( $pattern, ...$args ) { |
4821 $args = func_get_args(); |
|
4822 $len = strlen( $pattern ); |
5019 $len = strlen( $pattern ); |
4823 $start = 0; |
5020 $start = 0; |
4824 $result = ''; |
5021 $result = ''; |
4825 $arg_index = 0; |
5022 $arg_index = 0; |
4826 while ( $len > $start ) { |
5023 while ( $len > $start ) { |
4827 // Last character: append and break |
5024 // Last character: append and break. |
4828 if ( strlen( $pattern ) - 1 == $start ) { |
5025 if ( strlen( $pattern ) - 1 == $start ) { |
4829 $result .= substr( $pattern, -1 ); |
5026 $result .= substr( $pattern, -1 ); |
4830 break; |
5027 break; |
4831 } |
5028 } |
4832 |
5029 |
4833 // Literal %: append and continue |
5030 // Literal %: append and continue. |
4834 if ( substr( $pattern, $start, 2 ) == '%%' ) { |
5031 if ( '%%' === substr( $pattern, $start, 2 ) ) { |
4835 $start += 2; |
5032 $start += 2; |
4836 $result .= '%'; |
5033 $result .= '%'; |
4837 continue; |
5034 continue; |
4838 } |
5035 } |
4839 |
5036 |
4840 // Get fragment before next % |
5037 // Get fragment before next %. |
4841 $end = strpos( $pattern, '%', $start + 1 ); |
5038 $end = strpos( $pattern, '%', $start + 1 ); |
4842 if ( false === $end ) { |
5039 if ( false === $end ) { |
4843 $end = $len; |
5040 $end = $len; |
4844 } |
5041 } |
4845 $fragment = substr( $pattern, $start, $end - $start ); |
5042 $fragment = substr( $pattern, $start, $end - $start ); |
4846 |
5043 |
4847 // Fragment has a specifier |
5044 // Fragment has a specifier. |
4848 if ( $pattern[ $start ] == '%' ) { |
5045 if ( '%' === $pattern[ $start ] ) { |
4849 // Find numbered arguments or take the next one in order |
5046 // Find numbered arguments or take the next one in order. |
4850 if ( preg_match( '/^%(\d+)\$/', $fragment, $matches ) ) { |
5047 if ( preg_match( '/^%(\d+)\$/', $fragment, $matches ) ) { |
4851 $arg = isset( $args[ $matches[1] ] ) ? $args[ $matches[1] ] : ''; |
5048 $index = $matches[1] - 1; // 0-based array vs 1-based sprintf() arguments. |
5049 $arg = isset( $args[ $index ] ) ? $args[ $index ] : ''; |
|
4852 $fragment = str_replace( "%{$matches[1]}$", '%', $fragment ); |
5050 $fragment = str_replace( "%{$matches[1]}$", '%', $fragment ); |
4853 } else { |
5051 } else { |
5052 $arg = isset( $args[ $arg_index ] ) ? $args[ $arg_index ] : ''; |
|
4854 ++$arg_index; |
5053 ++$arg_index; |
4855 $arg = isset( $args[ $arg_index ] ) ? $args[ $arg_index ] : ''; |
|
4856 } |
5054 } |
4857 |
5055 |
4858 /** |
5056 /** |
4859 * Filters a fragment from the pattern passed to wp_sprintf(). |
5057 * Filters a fragment from the pattern passed to wp_sprintf(). |
4860 * |
5058 * |
4871 } else { |
5069 } else { |
4872 $fragment = sprintf( $fragment, strval( $arg ) ); |
5070 $fragment = sprintf( $fragment, strval( $arg ) ); |
4873 } |
5071 } |
4874 } |
5072 } |
4875 |
5073 |
4876 // Append to result and move to next fragment |
5074 // Append to result and move to next fragment. |
4877 $result .= $fragment; |
5075 $result .= $fragment; |
4878 $start = $end; |
5076 $start = $end; |
4879 } |
5077 } |
5078 |
|
4880 return $result; |
5079 return $result; |
4881 } |
5080 } |
4882 |
5081 |
4883 /** |
5082 /** |
4884 * Localize list items before the rest of the content. |
5083 * Localize list items before the rest of the content. |
4892 * @param string $pattern Content containing '%l' at the beginning. |
5091 * @param string $pattern Content containing '%l' at the beginning. |
4893 * @param array $args List items to prepend to the content and replace '%l'. |
5092 * @param array $args List items to prepend to the content and replace '%l'. |
4894 * @return string Localized list items and rest of the content. |
5093 * @return string Localized list items and rest of the content. |
4895 */ |
5094 */ |
4896 function wp_sprintf_l( $pattern, $args ) { |
5095 function wp_sprintf_l( $pattern, $args ) { |
4897 // Not a match |
5096 // Not a match. |
4898 if ( substr( $pattern, 0, 2 ) != '%l' ) { |
5097 if ( '%l' !== substr( $pattern, 0, 2 ) ) { |
4899 return $pattern; |
5098 return $pattern; |
4900 } |
5099 } |
4901 |
5100 |
4902 // Nothing to work with |
5101 // Nothing to work with. |
4903 if ( empty( $args ) ) { |
5102 if ( empty( $args ) ) { |
4904 return ''; |
5103 return ''; |
4905 } |
5104 } |
4906 |
5105 |
4907 /** |
5106 /** |
4916 * @param array $delimiters An array of translated delimiters. |
5115 * @param array $delimiters An array of translated delimiters. |
4917 */ |
5116 */ |
4918 $l = apply_filters( |
5117 $l = apply_filters( |
4919 'wp_sprintf_l', |
5118 'wp_sprintf_l', |
4920 array( |
5119 array( |
4921 /* translators: used to join items in a list with more than 2 items */ |
5120 /* translators: Used to join items in a list with more than 2 items. */ |
4922 'between' => sprintf( __( '%1$s, %2$s' ), '', '' ), |
5121 'between' => sprintf( __( '%1$s, %2$s' ), '', '' ), |
4923 /* translators: used to join last two items in a list with more than 2 times */ |
5122 /* translators: Used to join last two items in a list with more than 2 times. */ |
4924 'between_last_two' => sprintf( __( '%1$s, and %2$s' ), '', '' ), |
5123 'between_last_two' => sprintf( __( '%1$s, and %2$s' ), '', '' ), |
4925 /* translators: used to join items in a list with only 2 items */ |
5124 /* translators: Used to join items in a list with only 2 items. */ |
4926 'between_only_two' => sprintf( __( '%1$s and %2$s' ), '', '' ), |
5125 'between_only_two' => sprintf( __( '%1$s and %2$s' ), '', '' ), |
4927 ) |
5126 ) |
4928 ); |
5127 ); |
4929 |
5128 |
4930 $args = (array) $args; |
5129 $args = (array) $args; |
4931 $result = array_shift( $args ); |
5130 $result = array_shift( $args ); |
4932 if ( count( $args ) == 1 ) { |
5131 if ( count( $args ) == 1 ) { |
4933 $result .= $l['between_only_two'] . array_shift( $args ); |
5132 $result .= $l['between_only_two'] . array_shift( $args ); |
4934 } |
5133 } |
4935 // Loop when more than two args |
5134 |
5135 // Loop when more than two args. |
|
4936 $i = count( $args ); |
5136 $i = count( $args ); |
4937 while ( $i ) { |
5137 while ( $i ) { |
4938 $arg = array_shift( $args ); |
5138 $arg = array_shift( $args ); |
4939 $i--; |
5139 $i--; |
4940 if ( 0 == $i ) { |
5140 if ( 0 == $i ) { |
4941 $result .= $l['between_last_two'] . $arg; |
5141 $result .= $l['between_last_two'] . $arg; |
4942 } else { |
5142 } else { |
4943 $result .= $l['between'] . $arg; |
5143 $result .= $l['between'] . $arg; |
4944 } |
5144 } |
4945 } |
5145 } |
5146 |
|
4946 return $result . substr( $pattern, 2 ); |
5147 return $result . substr( $pattern, 2 ); |
4947 } |
5148 } |
4948 |
5149 |
4949 /** |
5150 /** |
4950 * Safely extracts not more than the first $count characters from html string. |
5151 * Safely extracts not more than the first $count characters from HTML string. |
4951 * |
5152 * |
4952 * UTF-8, tags and entities safe prefix extraction. Entities inside will *NOT* |
5153 * UTF-8, tags and entities safe prefix extraction. Entities inside will *NOT* |
4953 * be counted as one character. For example & will be counted as 4, < as |
5154 * be counted as one character. For example & will be counted as 4, < as |
4954 * 3, etc. |
5155 * 3, etc. |
4955 * |
5156 * |
4962 */ |
5163 */ |
4963 function wp_html_excerpt( $str, $count, $more = null ) { |
5164 function wp_html_excerpt( $str, $count, $more = null ) { |
4964 if ( null === $more ) { |
5165 if ( null === $more ) { |
4965 $more = ''; |
5166 $more = ''; |
4966 } |
5167 } |
5168 |
|
4967 $str = wp_strip_all_tags( $str, true ); |
5169 $str = wp_strip_all_tags( $str, true ); |
4968 $excerpt = mb_substr( $str, 0, $count ); |
5170 $excerpt = mb_substr( $str, 0, $count ); |
4969 // remove part of an entity at the end |
5171 |
5172 // Remove part of an entity at the end. |
|
4970 $excerpt = preg_replace( '/&[^;\s]{0,6}$/', '', $excerpt ); |
5173 $excerpt = preg_replace( '/&[^;\s]{0,6}$/', '', $excerpt ); |
4971 if ( $str != $excerpt ) { |
5174 if ( $str != $excerpt ) { |
4972 $excerpt = trim( $excerpt ) . $more; |
5175 $excerpt = trim( $excerpt ) . $more; |
4973 } |
5176 } |
5177 |
|
4974 return $excerpt; |
5178 return $excerpt; |
4975 } |
5179 } |
4976 |
5180 |
4977 /** |
5181 /** |
4978 * Add a Base url to relative links in passed content. |
5182 * Add a Base url to relative links in passed content. |
5007 * @param string $m The matched link. |
5211 * @param string $m The matched link. |
5008 * @return string The processed link. |
5212 * @return string The processed link. |
5009 */ |
5213 */ |
5010 function _links_add_base( $m ) { |
5214 function _links_add_base( $m ) { |
5011 global $_links_add_base; |
5215 global $_links_add_base; |
5012 //1 = attribute name 2 = quotation mark 3 = URL |
5216 // 1 = attribute name 2 = quotation mark 3 = URL. |
5013 return $m[1] . '=' . $m[2] . |
5217 return $m[1] . '=' . $m[2] . |
5014 ( preg_match( '#^(\w{1,20}):#', $m[3], $protocol ) && in_array( $protocol[1], wp_allowed_protocols() ) ? |
5218 ( preg_match( '#^(\w{1,20}):#', $m[3], $protocol ) && in_array( $protocol[1], wp_allowed_protocols(), true ) ? |
5015 $m[3] : |
5219 $m[3] : |
5016 WP_Http::make_absolute_url( $m[3], $_links_add_base ) |
5220 WP_Http::make_absolute_url( $m[3], $_links_add_base ) |
5017 ) |
5221 ) |
5018 . $m[2]; |
5222 . $m[2]; |
5019 } |
5223 } |
5028 * |
5232 * |
5029 * @since 2.7.0 |
5233 * @since 2.7.0 |
5030 * |
5234 * |
5031 * @global string $_links_add_target |
5235 * @global string $_links_add_target |
5032 * |
5236 * |
5033 * @param string $content String to search for links in. |
5237 * @param string $content String to search for links in. |
5034 * @param string $target The Target to add to the links. |
5238 * @param string $target The Target to add to the links. |
5035 * @param array $tags An array of tags to apply to. |
5239 * @param string[] $tags An array of tags to apply to. |
5036 * @return string The processed content. |
5240 * @return string The processed content. |
5037 */ |
5241 */ |
5038 function links_add_target( $content, $target = '_blank', $tags = array( 'a' ) ) { |
5242 function links_add_target( $content, $target = '_blank', $tags = array( 'a' ) ) { |
5039 global $_links_add_target; |
5243 global $_links_add_target; |
5040 $_links_add_target = $target; |
5244 $_links_add_target = $target; |
5163 * Internal helper function to sanitize a string from user input or from the db |
5367 * Internal helper function to sanitize a string from user input or from the db |
5164 * |
5368 * |
5165 * @since 4.7.0 |
5369 * @since 4.7.0 |
5166 * @access private |
5370 * @access private |
5167 * |
5371 * |
5168 * @param string $str String to sanitize. |
5372 * @param string $str String to sanitize. |
5169 * @param bool $keep_newlines optional Whether to keep newlines. Default: false. |
5373 * @param bool $keep_newlines Optional. Whether to keep newlines. Default: false. |
5170 * @return string Sanitized string. |
5374 * @return string Sanitized string. |
5171 */ |
5375 */ |
5172 function _sanitize_text_fields( $str, $keep_newlines = false ) { |
5376 function _sanitize_text_fields( $str, $keep_newlines = false ) { |
5173 if ( is_object( $str ) || is_array( $str ) ) { |
5377 if ( is_object( $str ) || is_array( $str ) ) { |
5174 return ''; |
5378 return ''; |
5181 if ( strpos( $filtered, '<' ) !== false ) { |
5385 if ( strpos( $filtered, '<' ) !== false ) { |
5182 $filtered = wp_pre_kses_less_than( $filtered ); |
5386 $filtered = wp_pre_kses_less_than( $filtered ); |
5183 // This will strip extra whitespace for us. |
5387 // This will strip extra whitespace for us. |
5184 $filtered = wp_strip_all_tags( $filtered, false ); |
5388 $filtered = wp_strip_all_tags( $filtered, false ); |
5185 |
5389 |
5186 // Use html entities in a special case to make sure no later |
5390 // Use HTML entities in a special case to make sure no later |
5187 // newline stripping stage could lead to a functional tag |
5391 // newline stripping stage could lead to a functional tag. |
5188 $filtered = str_replace( "<\n", "<\n", $filtered ); |
5392 $filtered = str_replace( "<\n", "<\n", $filtered ); |
5189 } |
5393 } |
5190 |
5394 |
5191 if ( ! $keep_newlines ) { |
5395 if ( ! $keep_newlines ) { |
5192 $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered ); |
5396 $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered ); |
5226 * |
5430 * |
5227 * Violating our coding standards for a good function name. |
5431 * Violating our coding standards for a good function name. |
5228 * |
5432 * |
5229 * @since 3.0.0 |
5433 * @since 3.0.0 |
5230 * |
5434 * |
5231 * @staticvar string|false $dblq |
|
5232 * |
|
5233 * @param string $text The text to be modified. |
5435 * @param string $text The text to be modified. |
5234 * @return string The modified text. |
5436 * @return string The modified text. |
5235 */ |
5437 */ |
5236 function capital_P_dangit( $text ) { |
5438 function capital_P_dangit( $text ) { |
5237 // Simple replacement for titles |
5439 // Simple replacement for titles. |
5238 $current_filter = current_filter(); |
5440 $current_filter = current_filter(); |
5239 if ( 'the_title' === $current_filter || 'wp_title' === $current_filter ) { |
5441 if ( 'the_title' === $current_filter || 'wp_title' === $current_filter ) { |
5240 return str_replace( 'Wordpress', 'WordPress', $text ); |
5442 return str_replace( 'Wordpress', 'WordPress', $text ); |
5241 } |
5443 } |
5242 // Still here? Use the more judicious replacement |
5444 // Still here? Use the more judicious replacement. |
5243 static $dblq = false; |
5445 static $dblq = false; |
5244 if ( false === $dblq ) { |
5446 if ( false === $dblq ) { |
5245 $dblq = _x( '“', 'opening curly double quote' ); |
5447 $dblq = _x( '“', 'opening curly double quote' ); |
5246 } |
5448 } |
5247 return str_replace( |
5449 return str_replace( |
5303 */ |
5505 */ |
5304 return apply_filters( 'sanitize_trackback_urls', $urls_to_ping, $to_ping ); |
5506 return apply_filters( 'sanitize_trackback_urls', $urls_to_ping, $to_ping ); |
5305 } |
5507 } |
5306 |
5508 |
5307 /** |
5509 /** |
5308 * Add slashes to a string or array of strings. |
5510 * Add slashes to a string or array of strings, in a recursive manner. |
5309 * |
5511 * |
5310 * This should be used when preparing data for core API that expects slashed data. |
5512 * This should be used when preparing data for core API that expects slashed data. |
5311 * This should not be used to escape data going directly into an SQL query. |
5513 * This should not be used to escape data going directly into an SQL query. |
5312 * |
5514 * |
5313 * @since 3.6.0 |
5515 * @since 3.6.0 |
5314 * |
5516 * @since 5.5.0 Non-string values are left untouched. |
5315 * @param string|array $value String or array of strings to slash. |
5517 * |
5316 * @return string|array Slashed $value |
5518 * @param string|string[] $value String or array of strings to slash. |
5519 * @return string|string[] Slashed $value. |
|
5317 */ |
5520 */ |
5318 function wp_slash( $value ) { |
5521 function wp_slash( $value ) { |
5319 if ( is_array( $value ) ) { |
5522 if ( is_array( $value ) ) { |
5320 foreach ( $value as $k => $v ) { |
5523 $value = array_map( 'wp_slash', $value ); |
5321 if ( is_array( $v ) ) { |
5524 } |
5322 $value[ $k ] = wp_slash( $v ); |
5525 |
5323 } else { |
5526 if ( is_string( $value ) ) { |
5324 $value[ $k ] = addslashes( $v ); |
5527 return addslashes( $value ); |
5325 } |
|
5326 } |
|
5327 } else { |
|
5328 $value = addslashes( $value ); |
|
5329 } |
5528 } |
5330 |
5529 |
5331 return $value; |
5530 return $value; |
5332 } |
5531 } |
5333 |
5532 |
5337 * This should be used to remove slashes from data passed to core API that |
5536 * This should be used to remove slashes from data passed to core API that |
5338 * expects data to be unslashed. |
5537 * expects data to be unslashed. |
5339 * |
5538 * |
5340 * @since 3.6.0 |
5539 * @since 3.6.0 |
5341 * |
5540 * |
5342 * @param string|array $value String or array of strings to unslash. |
5541 * @param string|string[] $value String or array of strings to unslash. |
5343 * @return string|array Unslashed $value |
5542 * @return string|string[] Unslashed $value |
5344 */ |
5543 */ |
5345 function wp_unslash( $value ) { |
5544 function wp_unslash( $value ) { |
5346 return stripslashes_deep( $value ); |
5545 return stripslashes_deep( $value ); |
5546 } |
|
5547 |
|
5548 /** |
|
5549 * Adds slashes to only string values in an array of values. |
|
5550 * |
|
5551 * This should be used when preparing data for core APIs that expect slashed data. |
|
5552 * This should not be used to escape data going directly into an SQL query. |
|
5553 * |
|
5554 * @since 5.3.0 |
|
5555 * |
|
5556 * @param mixed $value Scalar or array of scalars. |
|
5557 * @return mixed Slashes $value |
|
5558 */ |
|
5559 function wp_slash_strings_only( $value ) { |
|
5560 return map_deep( $value, 'addslashes_strings_only' ); |
|
5561 } |
|
5562 |
|
5563 /** |
|
5564 * Adds slashes only if the provided value is a string. |
|
5565 * |
|
5566 * @since 5.3.0 |
|
5567 * |
|
5568 * @param mixed $value |
|
5569 * @return mixed |
|
5570 */ |
|
5571 function addslashes_strings_only( $value ) { |
|
5572 return is_string( $value ) ? addslashes( $value ) : $value; |
|
5347 } |
5573 } |
5348 |
5574 |
5349 /** |
5575 /** |
5350 * Extract and return the first URL from passed content. |
5576 * Extract and return the first URL from passed content. |
5351 * |
5577 * |
5368 |
5594 |
5369 /** |
5595 /** |
5370 * Returns the regexp for common whitespace characters. |
5596 * Returns the regexp for common whitespace characters. |
5371 * |
5597 * |
5372 * By default, spaces include new lines, tabs, nbsp entities, and the UTF-8 nbsp. |
5598 * By default, spaces include new lines, tabs, nbsp entities, and the UTF-8 nbsp. |
5373 * This is designed to replace the PCRE \s sequence. In ticket #22692, that |
5599 * This is designed to replace the PCRE \s sequence. In ticket #22692, that |
5374 * sequence was found to be unreliable due to random inclusion of the A0 byte. |
5600 * sequence was found to be unreliable due to random inclusion of the A0 byte. |
5375 * |
5601 * |
5376 * @since 4.0.0 |
5602 * @since 4.0.0 |
5377 * |
|
5378 * @staticvar string $spaces |
|
5379 * |
5603 * |
5380 * @return string The spaces regexp. |
5604 * @return string The spaces regexp. |
5381 */ |
5605 */ |
5382 function wp_spaces_regexp() { |
5606 function wp_spaces_regexp() { |
5383 static $spaces = ''; |
5607 static $spaces = ''; |
5403 |
5627 |
5404 /** |
5628 /** |
5405 * Print the important emoji-related styles. |
5629 * Print the important emoji-related styles. |
5406 * |
5630 * |
5407 * @since 4.2.0 |
5631 * @since 4.2.0 |
5408 * |
|
5409 * @staticvar bool $printed |
|
5410 */ |
5632 */ |
5411 function print_emoji_styles() { |
5633 function print_emoji_styles() { |
5412 static $printed = false; |
5634 static $printed = false; |
5413 |
5635 |
5414 if ( $printed ) { |
5636 if ( $printed ) { |
5415 return; |
5637 return; |
5416 } |
5638 } |
5417 |
5639 |
5418 $printed = true; |
5640 $printed = true; |
5641 |
|
5642 $type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/css"'; |
|
5419 ?> |
5643 ?> |
5420 <style type="text/css"> |
5644 <style<?php echo $type_attr; ?>> |
5421 img.wp-smiley, |
5645 img.wp-smiley, |
5422 img.emoji { |
5646 img.emoji { |
5423 display: inline !important; |
5647 display: inline !important; |
5424 border: none !important; |
5648 border: none !important; |
5425 box-shadow: none !important; |
5649 box-shadow: none !important; |
5436 |
5660 |
5437 /** |
5661 /** |
5438 * Print the inline Emoji detection script if it is not already printed. |
5662 * Print the inline Emoji detection script if it is not already printed. |
5439 * |
5663 * |
5440 * @since 4.2.0 |
5664 * @since 4.2.0 |
5441 * @staticvar bool $printed |
|
5442 */ |
5665 */ |
5443 function print_emoji_detection_script() { |
5666 function print_emoji_detection_script() { |
5444 static $printed = false; |
5667 static $printed = false; |
5445 |
5668 |
5446 if ( $printed ) { |
5669 if ( $printed ) { |
5451 |
5674 |
5452 _print_emoji_detection_script(); |
5675 _print_emoji_detection_script(); |
5453 } |
5676 } |
5454 |
5677 |
5455 /** |
5678 /** |
5456 * Prints inline Emoji dection script |
5679 * Prints inline Emoji detection script. |
5457 * |
5680 * |
5458 * @ignore |
5681 * @ignore |
5459 * @since 4.6.0 |
5682 * @since 4.6.0 |
5460 * @access private |
5683 * @access private |
5461 */ |
5684 */ |
5464 /** |
5687 /** |
5465 * Filters the URL where emoji png images are hosted. |
5688 * Filters the URL where emoji png images are hosted. |
5466 * |
5689 * |
5467 * @since 4.2.0 |
5690 * @since 4.2.0 |
5468 * |
5691 * |
5469 * @param string The emoji base URL for png images. |
5692 * @param string $url The emoji base URL for png images. |
5470 */ |
5693 */ |
5471 'baseUrl' => apply_filters( 'emoji_url', 'https://s.w.org/images/core/emoji/12.0.0-1/72x72/' ), |
5694 'baseUrl' => apply_filters( 'emoji_url', 'https://s.w.org/images/core/emoji/13.0.0/72x72/' ), |
5472 |
5695 |
5473 /** |
5696 /** |
5474 * Filters the extension of the emoji png files. |
5697 * Filters the extension of the emoji png files. |
5475 * |
5698 * |
5476 * @since 4.2.0 |
5699 * @since 4.2.0 |
5477 * |
5700 * |
5478 * @param string The emoji extension for png files. Default .png. |
5701 * @param string $extension The emoji extension for png files. Default .png. |
5479 */ |
5702 */ |
5480 'ext' => apply_filters( 'emoji_ext', '.png' ), |
5703 'ext' => apply_filters( 'emoji_ext', '.png' ), |
5481 |
5704 |
5482 /** |
5705 /** |
5483 * Filters the URL where emoji SVG images are hosted. |
5706 * Filters the URL where emoji SVG images are hosted. |
5484 * |
5707 * |
5485 * @since 4.6.0 |
5708 * @since 4.6.0 |
5486 * |
5709 * |
5487 * @param string The emoji base URL for svg images. |
5710 * @param string $url The emoji base URL for svg images. |
5488 */ |
5711 */ |
5489 'svgUrl' => apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/12.0.0-1/svg/' ), |
5712 'svgUrl' => apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/13.0.0/svg/' ), |
5490 |
5713 |
5491 /** |
5714 /** |
5492 * Filters the extension of the emoji SVG files. |
5715 * Filters the extension of the emoji SVG files. |
5493 * |
5716 * |
5494 * @since 4.6.0 |
5717 * @since 4.6.0 |
5495 * |
5718 * |
5496 * @param string The emoji extension for svg files. Default .svg. |
5719 * @param string $extension The emoji extension for svg files. Default .svg. |
5497 */ |
5720 */ |
5498 'svgExt' => apply_filters( 'emoji_svg_ext', '.svg' ), |
5721 'svgExt' => apply_filters( 'emoji_svg_ext', '.svg' ), |
5499 ); |
5722 ); |
5500 |
5723 |
5501 $version = 'ver=' . get_bloginfo( 'version' ); |
5724 $version = 'ver=' . get_bloginfo( 'version' ); |
5725 $type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/javascript"'; |
|
5502 |
5726 |
5503 if ( SCRIPT_DEBUG ) { |
5727 if ( SCRIPT_DEBUG ) { |
5504 $settings['source'] = array( |
5728 $settings['source'] = array( |
5505 /** This filter is documented in wp-includes/class.wp-scripts.php */ |
5729 /** This filter is documented in wp-includes/class.wp-scripts.php */ |
5506 'wpemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji.js?$version" ), 'wpemoji' ), |
5730 'wpemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji.js?$version" ), 'wpemoji' ), |
5507 /** This filter is documented in wp-includes/class.wp-scripts.php */ |
5731 /** This filter is documented in wp-includes/class.wp-scripts.php */ |
5508 'twemoji' => apply_filters( 'script_loader_src', includes_url( "js/twemoji.js?$version" ), 'twemoji' ), |
5732 'twemoji' => apply_filters( 'script_loader_src', includes_url( "js/twemoji.js?$version" ), 'twemoji' ), |
5509 ); |
5733 ); |
5510 |
5734 |
5511 ?> |
5735 ?> |
5512 <script type="text/javascript"> |
5736 <script<?php echo $type_attr; ?>> |
5513 window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>; |
5737 window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>; |
5514 <?php readfile( ABSPATH . WPINC . '/js/wp-emoji-loader.js' ); ?> |
5738 <?php readfile( ABSPATH . WPINC . '/js/wp-emoji-loader.js' ); ?> |
5515 </script> |
5739 </script> |
5516 <?php |
5740 <?php |
5517 } else { |
5741 } else { |
5520 'concatemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji-release.min.js?$version" ), 'concatemoji' ), |
5744 'concatemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji-release.min.js?$version" ), 'concatemoji' ), |
5521 ); |
5745 ); |
5522 |
5746 |
5523 /* |
5747 /* |
5524 * If you're looking at a src version of this file, you'll see an "include" |
5748 * If you're looking at a src version of this file, you'll see an "include" |
5525 * statement below. This is used by the `grunt build` process to directly |
5749 * statement below. This is used by the `npm run build` process to directly |
5526 * include a minified version of wp-emoji-loader.js, instead of using the |
5750 * include a minified version of wp-emoji-loader.js, instead of using the |
5527 * readfile() method from above. |
5751 * readfile() method from above. |
5528 * |
5752 * |
5529 * If you're looking at a build version of this file, you'll see a string of |
5753 * If you're looking at a build version of this file, you'll see a string of |
5530 * minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG |
5754 * minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG |
5531 * and edit wp-emoji-loader.js directly. |
5755 * and edit wp-emoji-loader.js directly. |
5532 */ |
5756 */ |
5533 ?> |
5757 ?> |
5534 <script type="text/javascript"> |
5758 <script<?php echo $type_attr; ?>> |
5535 window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>; |
5759 window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>; |
5536 !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([55357,56424,55356,57342,8205,55358,56605,8205,55357,56424,55356,57340],[55357,56424,55356,57342,8203,55358,56605,8203,55357,56424,55356,57340]),!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); |
5760 !function(e,a,t){var r,n,o,i,p=a.createElement("canvas"),s=p.getContext&&p.getContext("2d");function c(e,t){var a=String.fromCharCode;s.clearRect(0,0,p.width,p.height),s.fillText(a.apply(this,e),0,0);var r=p.toDataURL();return s.clearRect(0,0,p.width,p.height),s.fillText(a.apply(this,t),0,0),r===p.toDataURL()}function l(e){if(!s||!s.fillText)return!1;switch(s.textBaseline="top",s.font="600 32px Arial",e){case"flag":return!c([127987,65039,8205,9895,65039],[127987,65039,8203,9895,65039])&&(!c([55356,56826,55356,56819],[55356,56826,8203,55356,56819])&&!c([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]));case"emoji":return!c([55357,56424,8205,55356,57212],[55357,56424,8203,55356,57212])}return!1}function d(e){var t=a.createElement("script");t.src=e,t.defer=t.type="text/javascript",a.getElementsByTagName("head")[0].appendChild(t)}for(i=Array("flag","emoji"),t.supports={everything:!0,everythingExceptFlag:!0},o=0;o<i.length;o++)t.supports[i[o]]=l(i[o]),t.supports.everything=t.supports.everything&&t.supports[i[o]],"flag"!==i[o]&&(t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&t.supports[i[o]]);t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&!t.supports.flag,t.DOMReady=!1,t.readyCallback=function(){t.DOMReady=!0},t.supports.everything||(n=function(){t.readyCallback()},a.addEventListener?(a.addEventListener("DOMContentLoaded",n,!1),e.addEventListener("load",n,!1)):(e.attachEvent("onload",n),a.attachEvent("onreadystatechange",function(){"complete"===a.readyState&&t.readyCallback()})),(r=t.source||{}).concatemoji?d(r.concatemoji):r.wpemoji&&r.twemoji&&(d(r.twemoji),d(r.wpemoji)))}(window,document,window._wpemojiSettings); |
5537 </script> |
5761 </script> |
5538 <?php |
5762 <?php |
5539 } |
5763 } |
5540 } |
5764 } |
5541 |
5765 |
5548 * |
5772 * |
5549 * @param string $content The content to encode. |
5773 * @param string $content The content to encode. |
5550 * @return string The encoded content. |
5774 * @return string The encoded content. |
5551 */ |
5775 */ |
5552 function wp_encode_emoji( $content ) { |
5776 function wp_encode_emoji( $content ) { |
5553 $emoji = _wp_emoji_list( 'partials' ); |
5777 $emoji = _wp_emoji_list( 'partials' ); |
5554 $compat = version_compare( phpversion(), '5.4', '<' ); |
|
5555 |
5778 |
5556 foreach ( $emoji as $emojum ) { |
5779 foreach ( $emoji as $emojum ) { |
5557 if ( $compat ) { |
5780 $emoji_char = html_entity_decode( $emojum ); |
5558 $emoji_char = html_entity_decode( $emojum, ENT_COMPAT, 'UTF-8' ); |
|
5559 } else { |
|
5560 $emoji_char = html_entity_decode( $emojum ); |
|
5561 } |
|
5562 if ( false !== strpos( $content, $emoji_char ) ) { |
5781 if ( false !== strpos( $content, $emoji_char ) ) { |
5563 $content = preg_replace( "/$emoji_char/", $emojum, $content ); |
5782 $content = preg_replace( "/$emoji_char/", $emojum, $content ); |
5564 } |
5783 } |
5565 } |
5784 } |
5566 |
5785 |
5592 |
5811 |
5593 $emoji = _wp_emoji_list( 'entities' ); |
5812 $emoji = _wp_emoji_list( 'entities' ); |
5594 |
5813 |
5595 // Quickly narrow down the list of emoji that might be in the text and need replacing. |
5814 // Quickly narrow down the list of emoji that might be in the text and need replacing. |
5596 $possible_emoji = array(); |
5815 $possible_emoji = array(); |
5597 $compat = version_compare( phpversion(), '5.4', '<' ); |
|
5598 foreach ( $emoji as $emojum ) { |
5816 foreach ( $emoji as $emojum ) { |
5599 if ( false !== strpos( $text, $emojum ) ) { |
5817 if ( false !== strpos( $text, $emojum ) ) { |
5600 if ( $compat ) { |
5818 $possible_emoji[ $emojum ] = html_entity_decode( $emojum ); |
5601 $possible_emoji[ $emojum ] = html_entity_decode( $emojum, ENT_COMPAT, 'UTF-8' ); |
|
5602 } else { |
|
5603 $possible_emoji[ $emojum ] = html_entity_decode( $emojum ); |
|
5604 } |
|
5605 } |
5819 } |
5606 } |
5820 } |
5607 |
5821 |
5608 if ( ! $possible_emoji ) { |
5822 if ( ! $possible_emoji ) { |
5609 return $text; |
5823 return $text; |
5610 } |
5824 } |
5611 |
5825 |
5612 /** This filter is documented in wp-includes/formatting.php */ |
5826 /** This filter is documented in wp-includes/formatting.php */ |
5613 $cdn_url = apply_filters( 'emoji_url', 'https://s.w.org/images/core/emoji/12.0.0-1/72x72/' ); |
5827 $cdn_url = apply_filters( 'emoji_url', 'https://s.w.org/images/core/emoji/13.0.0/72x72/' ); |
5614 |
5828 |
5615 /** This filter is documented in wp-includes/formatting.php */ |
5829 /** This filter is documented in wp-includes/formatting.php */ |
5616 $ext = apply_filters( 'emoji_ext', '.png' ); |
5830 $ext = apply_filters( 'emoji_ext', '.png' ); |
5617 |
5831 |
5618 $output = ''; |
5832 $output = ''; |
5631 |
5845 |
5632 for ( $i = 0; $i < $stop; $i++ ) { |
5846 for ( $i = 0; $i < $stop; $i++ ) { |
5633 $content = $textarr[ $i ]; |
5847 $content = $textarr[ $i ]; |
5634 |
5848 |
5635 // If we're in an ignore block, wait until we find its closing tag. |
5849 // If we're in an ignore block, wait until we find its closing tag. |
5636 if ( '' == $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')>/', $content, $matches ) ) { |
5850 if ( '' === $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')>/', $content, $matches ) ) { |
5637 $ignore_block_element = $matches[1]; |
5851 $ignore_block_element = $matches[1]; |
5638 } |
5852 } |
5639 |
5853 |
5640 // If it's not a tag and not in ignore block. |
5854 // If it's not a tag and not in ignore block. |
5641 if ( '' == $ignore_block_element && strlen( $content ) > 0 && '<' != $content[0] && false !== strpos( $content, '&#x' ) ) { |
5855 if ( '' === $ignore_block_element && strlen( $content ) > 0 && '<' !== $content[0] && false !== strpos( $content, '&#x' ) ) { |
5642 foreach ( $possible_emoji as $emojum => $emoji_char ) { |
5856 foreach ( $possible_emoji as $emojum => $emoji_char ) { |
5643 if ( false === strpos( $content, $emojum ) ) { |
5857 if ( false === strpos( $content, $emojum ) ) { |
5644 continue; |
5858 continue; |
5645 } |
5859 } |
5646 |
5860 |
5651 |
5865 |
5652 $content = str_replace( $emojum, $entity, $content ); |
5866 $content = str_replace( $emojum, $entity, $content ); |
5653 } |
5867 } |
5654 } |
5868 } |
5655 |
5869 |
5656 // Did we exit ignore block. |
5870 // Did we exit ignore block? |
5657 if ( '' != $ignore_block_element && '</' . $ignore_block_element . '>' == $content ) { |
5871 if ( '' !== $ignore_block_element && '</' . $ignore_block_element . '>' === $content ) { |
5658 $ignore_block_element = ''; |
5872 $ignore_block_element = ''; |
5659 } |
5873 } |
5660 |
5874 |
5661 $output .= $content; |
5875 $output .= $content; |
5662 } |
5876 } |
5663 |
5877 |
5664 // Finally, remove any stray U+FE0F characters |
5878 // Finally, remove any stray U+FE0F characters. |
5665 $output = str_replace( '️', '', $output ); |
5879 $output = str_replace( '️', '', $output ); |
5666 |
5880 |
5667 return $output; |
5881 return $output; |
5668 } |
5882 } |
5669 |
5883 |
5736 |
5950 |
5737 /** |
5951 /** |
5738 * Returns arrays of emoji data. |
5952 * Returns arrays of emoji data. |
5739 * |
5953 * |
5740 * These arrays are automatically built from the regex in twemoji.js - if they need to be updated, |
5954 * These arrays are automatically built from the regex in twemoji.js - if they need to be updated, |
5741 * you should update the regex there, then run the `grunt precommit:emoji` job. |
5955 * you should update the regex there, then run the `npm run grunt precommit:emoji` job. |
5742 * |
5956 * |
5743 * @since 4.9.0 |
5957 * @since 4.9.0 |
5744 * @access private |
5958 * @access private |
5745 * |
5959 * |
5746 * @param string $type Optional. Which array type to return. Accepts 'partials' or 'entities', default 'entities'. |
5960 * @param string $type Optional. Which array type to return. Accepts 'partials' or 'entities', default 'entities'. |
5748 */ |
5962 */ |
5749 function _wp_emoji_list( $type = 'entities' ) { |
5963 function _wp_emoji_list( $type = 'entities' ) { |
5750 // Do not remove the START/END comments - they're used to find where to insert the arrays. |
5964 // Do not remove the START/END comments - they're used to find where to insert the arrays. |
5751 |
5965 |
5752 // START: emoji arrays |
5966 // START: emoji arrays |
5753 $entities = array( '👨‍❤️‍💋‍👨', '👩‍❤️‍💋‍👩', '👩‍❤️‍💋‍👨', '🏴󠁧󠁢󠁥󠁮󠁧󠁿', '🏴󠁧󠁢󠁳󠁣󠁴󠁿', '🏴󠁧󠁢󠁷󠁬󠁳󠁿', '🧑🏿‍🤝‍🧑🏻', '🧑🏾‍🤝‍🧑🏾', '🧑🏾‍🤝‍🧑🏽', '🧑🏾‍🤝‍🧑🏼', '🧑🏾‍🤝‍🧑🏻', '🧑🏽‍🤝‍🧑🏽', '🧑🏽‍🤝‍🧑🏼', '🧑🏽‍🤝‍🧑🏻', '🧑🏼‍🤝‍🧑🏼', '🧑🏼‍🤝‍🧑🏻', '🧑🏻‍🤝‍🧑🏻', '👩🏾‍🤝‍👩🏽', '🧑🏿‍🤝‍🧑🏿', '🧑🏿‍🤝‍🧑🏾', '👨🏼‍🤝‍👨🏻', '🧑🏿‍🤝‍🧑🏽', '🧑🏿‍🤝‍🧑🏼', '👩🏻‍🤝‍👨🏼', '👩🏻‍🤝‍👨🏽', '👩🏻‍🤝‍👨🏾', '👩🏻‍🤝‍👨🏿', '👨🏿‍🤝‍👨🏾', '👨🏿‍🤝‍👨🏽', '👨🏿‍🤝‍👨🏼', '👨🏿‍🤝‍👨🏻', '👩🏼‍🤝‍👨🏻', '👩🏼‍🤝‍👨🏽', '👨🏽‍🤝‍👨🏻', '👨🏽‍🤝‍👨🏼', '👩🏿‍🤝‍👩🏾', '👩🏿‍🤝‍👩🏽', '👩🏿‍🤝‍👩🏼', '👩🏿‍🤝‍👩🏻', '👩🏿‍🤝‍👨🏾', '👩🏿‍🤝‍👨🏽', '👩🏿‍🤝‍👨🏼', '👩🏿‍🤝‍👨🏻', '👩🏼‍🤝‍👨🏾', '👩🏾‍🤝‍👩🏼', '👩🏾‍🤝‍👩🏻', '👩🏾‍🤝‍👨🏿', '👩🏾‍🤝‍👨🏽', '👩🏾‍🤝‍👨🏼', '👨🏾‍🤝‍👨🏻', '👨🏾‍🤝‍👨🏼', '👨🏾‍🤝‍👨🏽', '👩🏾‍🤝‍👨🏻', '👩🏽‍🤝‍👩🏼', '👩🏽‍🤝‍👩🏻', '👩🏽‍🤝‍👨🏿', '👩🏽‍🤝‍👨🏾', '👩🏽‍🤝‍👨🏼', '👩🏽‍🤝‍👨🏻', '👩🏼‍🤝‍👩🏻', '👩🏼‍🤝‍👨🏿', '👨‍👨‍👧‍👦', '👩‍👩‍👧‍👦', '👩‍👩‍👧‍👧', '👨‍👨‍👦‍👦', '👩‍👩‍👦‍👦', '👨‍👨‍👧‍👧', '👨‍👩‍👦‍👦', '👨‍👩‍👧‍👦', '👨‍👩‍👧‍👧', '👨‍❤️‍👨', '👩‍❤️‍👨', '👩‍❤️‍👩', '👩‍👦‍👦', '👩‍👩‍👦', '👨‍👨‍👦', '👩‍👧‍👦', '👩‍👧‍👧', '👨‍👨‍👧', '👩‍👩‍👧', '👨‍👩‍👦', '🧑‍🤝‍🧑', '👨‍👦‍👦', '👨‍👩‍👧', '👨‍👧‍👦', '👨‍👧‍👧', '🧗🏽‍♀️', '🧗🏼‍♂️', '🧗🏼‍♀️', '🧗🏻‍♂️', '🧗🏻‍♀️', '👷🏿‍♀️', '💆🏻‍♀️', '🧖🏿‍♂️', '🧖🏿‍♀️', '🧖🏾‍♂️', '🧖🏾‍♀️', '🧖🏽‍♂️', '🧖🏽‍♀️', '🧖🏼‍♂️', '🧖🏼‍♀️', '🧖🏻‍♂️', '🧖🏻‍♀️', '💁🏿‍♀️', '💁🏾‍♂️', '💁🏾‍♀️', '💁🏽‍♂️', '💁🏽‍♀️', '💁🏼‍♂️', '💁🏼‍♀️', '💂🏻‍♀️', '🧝🏿‍♂️', '🧝🏿‍♀️', '🧝🏾‍♂️', '🧝🏾‍♀️', '🧝🏽‍♂️', '🧝🏽‍♀️', '🧝🏼‍♂️', '🧝🏼‍♀️', '👷🏾‍♂️', '👷🏾‍♀️', '🧏🏿‍♂️', '🧏🏿‍♀️', '🧏🏾‍♂️', '🧏🏾‍♀️', '🧏🏽‍♂️', '🧏🏽‍♀️', '🧏🏼‍♂️', '🧏🏼‍♀️', '🧏🏻‍♂️', '🧏🏻‍♀️', '💆🏻‍♂️', '👷🏽‍♂️', '🧎🏿‍♂️', '🧎🏿‍♀️', '🧎🏾‍♂️', '🧎🏾‍♀️', '🧎🏽‍♂️', '🧎🏽‍♀️', '🧎🏼‍♂️', '🧎🏼‍♀️', '🧎🏻‍♂️', '🧎🏻‍♀️', '👷🏽‍♀️', '💆🏼‍♀️', '🧍🏿‍♂️', '🧍🏿‍♀️', '🧍🏾‍♂️', '🧍🏾‍♀️', '🧍🏽‍♂️', '🧍🏽‍♀️', '🧍🏼‍♂️', '🧍🏼‍♀️', '🧍🏻‍♂️', '🧍🏻‍♀️', '👷🏼‍♂️', '👷🏼‍♀️', '🦹🏿‍♂️', '🦹🏿‍♀️', '🦹🏾‍♂️', '🦹🏾‍♀️', '🦹🏽‍♂️', '🦹🏽‍♀️', '🦹🏼‍♂️', '🦹🏼‍♀️', '🦹🏻‍♂️', '🦹🏻‍♀️', '💆🏼‍♂️', '👷🏻‍♂️', '🦸🏿‍♂️', '🦸🏿‍♀️', '🦸🏾‍♂️', '🦸🏾‍♀️', '🦸🏽‍♂️', '🦸🏽‍♀️', '🦸🏼‍♂️', '🦸🏼‍♀️', '🦸🏻‍♂️', '🦸🏻‍♀️', '👷🏻‍♀️', '💆🏽‍♀️', '🤾🏿‍♂️', '🤾🏿‍♀️', '🤾🏾‍♂️', '🤾🏾‍♀️', '🤾🏽‍♂️', '🤾🏽‍♀️', '🤾🏼‍♂️', '🤾🏼‍♀️', '🤾🏻‍♂️', '🤾🏻‍♀️', '💆🏽‍♂️', '💆🏾‍♀️', '🤽🏿‍♂️', '🤽🏿‍♀️', '🤽🏾‍♂️', '🤽🏾‍♀️', '🤽🏽‍♂️', '🤽🏽‍♀️', '🤽🏼‍♂️', '🤽🏼‍♀️', '🤽🏻‍♂️', '🤽🏻‍♀️', '💆🏾‍♂️', '💆🏿‍♀️', '💆🏿‍♂️', '💇🏻‍♀️', '🤹🏿‍♂️', '🤹🏿‍♀️', '🤹🏾‍♂️', '🤹🏾‍♀️', '🤹🏽‍♂️', '🤹🏽‍♀️', '🤹🏼‍♂️', '🤹🏼‍♀️', '🤹🏻‍♂️', '🤹🏻‍♀️', '💇🏻‍♂️', '💇🏼‍♀️', '🤸🏿‍♂️', '🤸🏿‍♀️', '🤸🏾‍♂️', '🤸🏾‍♀️', '🤸🏽‍♂️', '🤸🏽‍♀️', '🤸🏼‍♂️', '🤸🏼‍♀️', '🤸🏻‍♂️', '🤸🏻‍♀️', '💇🏼‍♂️', '💇🏽‍♀️', '🤷🏿‍♂️', '🤷🏿‍♀️', '🤷🏾‍♂️', '🤷🏾‍♀️', '🤷🏽‍♂️', '🤷🏽‍♀️', '🤷🏼‍♂️', '🤷🏼‍♀️', '🤷🏻‍♂️', '🤷🏻‍♀️', '💇🏽‍♂️', '💇🏾‍♀️', '🤵🏿‍♂️', '🤵🏿‍♀️', '🤵🏾‍♂️', '🤵🏾‍♀️', '🤵🏽‍♂️', '🤵🏽‍♀️', '🤵🏼‍♂️', '🤵🏼‍♀️', '🤵🏻‍♂️', '🤵🏻‍♀️', '💇🏾‍♂️', '👳🏿‍♂️', '🤦🏿‍♂️', '🤦🏿‍♀️', '🤦🏾‍♂️', '🏃🏻‍♀️', '🏃🏻‍♂️', '🤦🏾‍♀️', '🏃🏼‍♀️', '🏃🏼‍♂️', '🤦🏽‍♂️', '🏃🏽‍♀️', '🏃🏽‍♂️', '🤦🏽‍♀️', '🏃🏾‍♀️', '🏃🏾‍♂️', '🤦🏼‍♂️', '🏃🏿‍♀️', '🏃🏿‍♂️', '🤦🏼‍♀️', '👳🏿‍♀️', '💇🏿‍♀️', '🏄🏻‍♀️', '🏄🏻‍♂️', '🤦🏻‍♂️', '🏄🏼‍♀️', '🏄🏼‍♂️', '🤦🏻‍♀️', '🏄🏽‍♀️', '🏄🏽‍♂️', '💁🏿‍♂️', '🏄🏾‍♀️', '🏄🏾‍♂️', '👳🏾‍♀️', '🏄🏿‍♀️', '🏄🏿‍♂️', '🚶🏿‍♂️', '💇🏿‍♂️', '👳🏽‍♂️', '🚶🏿‍♀️', '🚶🏾‍♂️', '🚶🏾‍♀️', '🚶🏽‍♂️', '🚶🏽‍♀️', '🏊🏻‍♀️', '🏊🏻‍♂️', '🚶🏼‍♂️', '🏊🏼‍♀️', '🏊🏼‍♂️', '🚶🏼‍♀️', '🏊🏽‍♀️', '🏊🏽‍♂️', '🚶🏻‍♂️', '🏊🏾‍♀️', '🏊🏾‍♂️', '🚶🏻‍♀️', '🏊🏿‍♀️', '🏊🏿‍♂️', '👳🏽‍♀️', '👳🏼‍♂️', '👳🏼‍♀️', '🏋🏻‍♀️', '🏋🏻‍♂️', '👳🏻‍♂️', '🏋🏼‍♀️', '🏋🏼‍♂️', '🚵🏿‍♂️', '🏋🏽‍♀️', '🏋🏽‍♂️', '🚵🏿‍♀️', '🏋🏾‍♀️', '🏋🏾‍♂️', '🚵🏾‍♂️', '🏋🏿‍♀️', '🏋🏿‍♂️', '🚵🏾‍♀️', '🏌🏻‍♀️', '🏌🏻‍♂️', '🚵🏽‍♂️', '🏌🏼‍♀️', '🏌🏼‍♂️', '🚵🏽‍♀️', '🏌🏽‍♀️', '🏌🏽‍♂️', '🚵🏼‍♂️', '🏌🏾‍♀️', '🏌🏾‍♂️', '🚵🏼‍♀️', '🏌🏿‍♀️', '🏌🏿‍♂️', '🚵🏻‍♂️', '👳🏻‍♀️', '🕴🏻‍♀️', '🧝🏻‍♂️', '🧝🏻‍♀️', '💁🏻‍♂️', '🚵🏻‍♀️', '🕴🏻‍♂️', '🕴🏼‍♀️', '🚴🏿‍♂️', '🚴🏿‍♀️', '🚴🏾‍♂️', '🚴🏾‍♀️', '🚴🏽‍♂️', '🚴🏽‍♀️', '🚴🏼‍♂️', '🚴🏼‍♀️', '🚴🏻‍♂️', '🚴🏻‍♀️', '🕴🏼‍♂️', '🕴🏽‍♀️', '🚣🏿‍♂️', '🚣🏿‍♀️', '🚣🏾‍♂️', '🚣🏾‍♀️', '🚣🏽‍♂️', '🚣🏽‍♀️', '🚣🏼‍♂️', '🚣🏼‍♀️', '🚣🏻‍♂️', '🚣🏻‍♀️', '🕴🏽‍♂️', '👱🏿‍♂️', '🙎🏿‍♂️', '🙎🏿‍♀️', '🙎🏾‍♂️', '🙎🏾‍♀️', '🙎🏽‍♂️', '🙎🏽‍♀️', '🙎🏼‍♂️', '🙎🏼‍♀️', '🙎🏻‍♂️', '🙎🏻‍♀️', '👱🏿‍♀️', '🕴🏾‍♀️', '🙍🏿‍♂️', '🙍🏿‍♀️', '🙍🏾‍♂️', '🙍🏾‍♀️', '🙍🏽‍♂️', '🙍🏽‍♀️', '🙍🏼‍♂️', '🙍🏼‍♀️', '🙍🏻‍♂️', '🙍🏻‍♀️', '👱🏾‍♂️', '👱🏾‍♀️', '🙋🏿‍♂️', '🙋🏿‍♀️', '🙋🏾‍♂️', '🙋🏾‍♀️', '🙋🏽‍♂️', '🙋🏽‍♀️', '🙋🏼‍♂️', '🙋🏼‍♀️', '🙋🏻‍♂️', '🙋🏻‍♀️', '🕴🏾‍♂️', '👱🏽‍♂️', '🙇🏿‍♂️', '🙇🏿‍♀️', '🙇🏾‍♂️', '🙇🏾‍♀️', '🙇🏽‍♂️', '🙇🏽‍♀️', '🙇🏼‍♂️', '🙇🏼‍♀️', '🙇🏻‍♂️', '🙇🏻‍♀️', '👱🏽‍♀️', '🕴🏿‍♀️', '👱🏼‍♂️', '👱🏼‍♀️', '🕴🏿‍♂️', '👱🏻‍♂️', '👱🏻‍♀️', '🕵🏻‍♀️', '🕵🏻‍♂️', '🕵🏼‍♀️', '🕵🏼‍♂️', '👮🏿‍♂️', '👮🏿‍♀️', '🕵🏽‍♀️', '👮🏾‍♂️', '👮🏾‍♀️', '🕵🏽‍♂️', '👮🏽‍♂️', '👮🏽‍♀️', '👨🏻‍⚕️', '👨🏻‍⚖️', '👨🏻‍✈️', '🙆🏿‍♂️', '🕵🏾‍♀️', '👮🏼‍♂️', '👮🏼‍♀️', '🕵🏾‍♂️', '👮🏻‍♂️', '👮🏻‍♀️', '🕵🏿‍♀️', '🕵🏿‍♂️', '🙅🏻‍♀️', '🙅🏻‍♂️', '🙅🏼‍♀️', '💁🏻‍♀️', '🙅🏼‍♂️', '🙅🏽‍♀️', '🙅🏽‍♂️', '🙅🏾‍♀️', '🙅🏾‍♂️', '🙅🏿‍♀️', '🙅🏿‍♂️', '👨🏼‍⚕️', '👨🏼‍⚖️', '👨🏼‍✈️', '🙆🏿‍♀️', '🧜🏿‍♂️', '🧜🏿‍♀️', '🧜🏾‍♂️', '🧜🏾‍♀️', '🧜🏽‍♂️', '🧜🏽‍♀️', '🧜🏼‍♂️', '🧜🏼‍♀️', '🧜🏻‍♂️', '🧜🏻‍♀️', '💂🏻‍♂️', '💂🏼‍♀️', '👩🏿‍✈️', '🧛🏿‍♂️', '🧛🏿‍♀️', '👩🏿‍⚖️', '👩🏿‍⚕️', '🧛🏾‍♂️', '🧛🏾‍♀️', '🧛🏽‍♂️', '🧛🏽‍♀️', '🧛🏼‍♂️', '👨🏽‍⚕️', '👨🏽‍⚖️', '👨🏽‍✈️', '🙆🏾‍♂️', '🧛🏼‍♀️', '🧛🏻‍♂️', '🧛🏻‍♀️', '🙆🏻‍♀️', '👩🏾‍✈️', '👩🏾‍⚖️', '👩🏾‍⚕️', '💂🏼‍♂️', '💂🏽‍♀️', '🧚🏿‍♂️', '🧚🏿‍♀️', '🧚🏾‍♂️', '🧚🏾‍♀️', '🧚🏽‍♂️', '🧚🏽‍♀️', '🧚🏼‍♂️', '🧚🏼‍♀️', '🙆🏻‍♂️', '👩🏽‍✈️', '👩🏽‍⚖️', '👩🏽‍⚕️', '🧚🏻‍♂️', '🧚🏻‍♀️', '👨🏾‍⚕️', '👨🏾‍⚖️', '👨🏾‍✈️', '🙆🏾‍♀️', '💂🏽‍♂️', '💂🏾‍♀️', '🧙🏿‍♂️', '🧙🏿‍♀️', '🙆🏼‍♀️', '👩🏼‍✈️', '👩🏼‍⚖️', '👩🏼‍⚕️', '🧙🏾‍♂️', '🧙🏾‍♀️', '🧙🏽‍♂️', '🧙🏽‍♀️', '🧙🏼‍♂️', '🧙🏼‍♀️', '🧙🏻‍♂️', '🧙🏻‍♀️', '💂🏾‍♂️', '🙆🏼‍♂️', '👩🏻‍✈️', '👩🏻‍⚖️', '👩🏻‍⚕️', '💂🏿‍♀️', '🧘🏿‍♂️', '🧘🏿‍♀️', '👨🏿‍⚕️', '👨🏿‍⚖️', '👨🏿‍✈️', '🙆🏽‍♂️', '🧘🏾‍♂️', '🧘🏾‍♀️', '🧘🏽‍♂️', '🧘🏽‍♀️', '🧘🏼‍♂️', '🧘🏼‍♀️', '🧘🏻‍♂️', '🧘🏻‍♀️', '💂🏿‍♂️', '👷🏿‍♂️', '🧗🏿‍♂️', '🧗🏿‍♀️', '🧗🏾‍♂️', '🙆🏽‍♀️', '🧗🏾‍♀️', '🧗🏽‍♂️', '👳🏾‍♂️', '⛹🏼‍♂️', '🕴️‍♀️', '🕴️‍♂️', '⛹🏾‍♂️', '⛹🏿‍♀️', '⛹🏿‍♂️', '⛹🏼‍♀️', '🏌️‍♀️', '🏌️‍♂️', '⛹🏽‍♀️', '⛹🏻‍♂️', '🕵️‍♀️', '🕵️‍♂️', '⛹🏻‍♀️', '⛹🏽‍♂️', '⛹🏾‍♀️', '🏋️‍♀️', '🏋️‍♂️', '⛹️‍♀️', '⛹️‍♂️', '👨🏽‍🚒', '👩🏻‍🍳', '👩🏻‍🎓', '👩🏻‍🎤', '👩🏻‍🎨', '👩🏻‍🏫', '👩🏻‍🏭', '👩🏻‍💻', '👩🏻‍💼', '👩🏻‍🔧', '👩🏻‍🔬', '👩🏻‍🚀', '👩🏻‍🚒', '👨🏻‍🏫', '👨🏿‍🦽', '👨🏿‍🦼', '👨🏿‍🦳', '👩🏻‍🦯', '👩🏻‍🦰', '👩🏻‍🦱', '👩🏻‍🦲', '👩🏻‍🦳', '👩🏻‍🦼', '👩🏻‍🦽', '👨🏿‍🦲', '👨🏿‍🦱', '👨🏿‍🦰', '👨🏿‍🦯', '👩🏼‍🌾', '👩🏼‍🍳', '👩🏼‍🎓', '👩🏼‍🎤', '👩🏼‍🎨', '👩🏼‍🏫', '👩🏼‍🏭', '👩🏼‍💻', '👩🏼‍💼', '👩🏼‍🔧', '👩🏼‍🔬', '👩🏼‍🚀', '👩🏼‍🚒', '👨🏿‍🚒', '👨🏿‍🚀', '👨🏿‍🔬', '👨🏿‍🔧', '👨🏿‍💼', '👩🏼‍🦯', '👩🏼‍🦰', '👩🏼‍🦱', '👩🏼‍🦲', '👩🏼‍🦳', '👩🏼‍🦼', '👩🏼‍🦽', '👨🏿‍💻', '👨🏿‍🏭', '👨🏿‍🏫', '👨🏿‍🎨', '👩🏽‍🌾', '👩🏽‍🍳', '👩🏽‍🎓', '👩🏽‍🎤', '👩🏽‍🎨', '👩🏽‍🏫', '👩🏽‍🏭', '👩🏽‍💻', '👩🏽‍💼', '👩🏽‍🔧', '👩🏽‍🔬', '👩🏽‍🚀', '👩🏽‍🚒', '👨🏿‍🎤', '👨🏿‍🎓', '👨🏿‍🍳', '👨🏿‍🌾', '👨🏾‍🦽', '👨🏾‍🦼', '👩🏽‍🦯', '👩🏽‍🦰', '👩🏽‍🦱', '👩🏽‍🦲', '👩🏽‍🦳', '👩🏽‍🦼', '👩🏽‍🦽', '👨🏾‍🦳', '👨🏾‍🦲', '👨🏾‍🦱', '👨🏾‍🦰', '👩🏾‍🌾', '👩🏾‍🍳', '👩🏾‍🎓', '👩🏾‍🎤', '👩🏾‍🎨', '👩🏾‍🏫', '👩🏾‍🏭', '👩🏾‍💻', '👩🏾‍💼', '👩🏾‍🔧', '👩🏾‍🔬', '👩🏾‍🚀', '👩🏾‍🚒', '👨🏾‍🦯', '👨🏾‍🚒', '👨🏾‍🚀', '👨🏾‍🔬', '👨🏾‍🔧', '👨🏾‍💼', '👨🏾‍💻', '👩🏾‍🦯', '👩🏾‍🦰', '👩🏾‍🦱', '👩🏾‍🦲', '👩🏾‍🦳', '👩🏾‍🦼', '👩🏾‍🦽', '👨🏾‍🏭', '👨🏾‍🏫', '👨🏾‍🎨', '👨🏾‍🎤', '👩🏿‍🌾', '👩🏿‍🍳', '👩🏿‍🎓', '👩🏿‍🎤', '👩🏿‍🎨', '👩🏿‍🏫', '👩🏿‍🏭', '👩🏿‍💻', '👩🏿‍💼', '👩🏿‍🔧', '👩🏿‍🔬', '👩🏿‍🚀', '👩🏿‍🚒', '👨🏾‍🎓', '👨🏾‍🍳', '👨🏾‍🌾', '👨🏽‍🦽', '👨🏽‍🦼', '👨🏽‍🦳', '👨🏽‍🦲', '👨🏽‍🦱', '👩🏿‍🦯', '👩🏿‍🦰', '👩🏿‍🦱', '👩🏿‍🦲', '👩🏿‍🦳', '👩🏿‍🦼', '👩🏿‍🦽', '👨🏽‍🦰', '👨🏽‍🦯', '👩🏻‍🌾', '👨🏻‍🌾', '👨🏽‍🚀', '👨🏽‍🔬', '👨🏽‍🔧', '👨🏽‍💼', '👨🏽‍💻', '👨🏽‍🏭', '👨🏽‍🏫', '👨🏽‍🎨', '👨🏻‍🍳', '👨🏻‍🎓', '👨🏻‍🎤', '👨🏽‍🎤', '👨🏽‍🎓', '👨🏽‍🍳', '👨🏽‍🌾', '👨🏻‍🎨', '👨🏼‍🦽', '👨🏼‍🦼', '👨🏼‍🦳', '👨🏼‍🦲', '👨🏼‍🦱', '👨🏼‍🦰', '👨🏼‍🦯', '👨🏼‍🚒', '👨🏼‍🚀', '👨🏼‍🔬', '👨🏼‍🔧', '👨🏼‍💼', '👨🏼‍💻', '👨🏼‍🏭', '👨🏼‍🏫', '👨🏼‍🎨', '👨🏼‍🎤', '👨🏼‍🎓', '👨🏼‍🍳', '👨🏼‍🌾', '👨🏻‍🦽', '👨🏻‍🦼', '👨🏻‍🦳', '👨🏻‍🦲', '👨🏻‍🦱', '👨🏻‍🦰', '👨🏻‍🦯', '👨🏻‍🚒', '👨🏻‍🚀', '👨🏻‍🏭', '👨🏻‍💻', '👨🏻‍💼', '👨🏻‍🔧', '👨🏻‍🔬', '🏳️‍🌈', '🤹‍♀️', '👮‍♂️', '👮‍♀️', '🙅‍♀️', '👩‍✈️', '👩‍⚖️', '👩‍⚕️', '🙅‍♂️', '🙆‍♀️', '🙆‍♂️', '🙇‍♀️', '🙇‍♂️', '🙋‍♀️', '🙋‍♂️', '🙍‍♀️', '🙍‍♂️', '🙎‍♀️', '🙎‍♂️', '👱‍♀️', '👱‍♂️', '🚣‍♀️', '🚣‍♂️', '🚴‍♀️', '🚴‍♂️', '🏴‍☠️', '👯‍♂️', '🚵‍♀️', '💇‍♂️', '🏊‍♂️', '🏊‍♀️', '💇‍♀️', '🚵‍♂️', '🏄‍♂️', '🏄‍♀️', '🚶‍♀️', '🚶‍♂️', '🏃‍♂️', '🏃‍♀️', '🤦‍♀️', '🤦‍♂️', '👳‍♀️', '👳‍♂️', '🤵‍♀️', '🤵‍♂️', '🤷‍♀️', '🤷‍♂️', '🤸‍♀️', '🤸‍♂️', '👯‍♀️', '💆‍♂️', '💆‍♀️', '🤹‍♂️', '🤼‍♀️', '🤼‍♂️', '🤽‍♀️', '🤽‍♂️', '🤾‍♀️', '🤾‍♂️', '🦸‍♀️', '🦸‍♂️', '🦹‍♀️', '🦹‍♂️', '🧍‍♀️', '🧍‍♂️', '🧎‍♀️', '🧎‍♂️', '🧏‍♀️', '🧏‍♂️', '🧖‍♀️', '🧖‍♂️', '🧗‍♀️', '💂‍♂️', '👷‍♀️', '👷‍♂️', '💂‍♀️', '🧗‍♂️', '🧘‍♀️', '🧘‍♂️', '🧙‍♀️', '🧙‍♂️', '🧚‍♀️', '🧚‍♂️', '🧛‍♀️', '🧛‍♂️', '🧜‍♀️', '🧜‍♂️', '🧝‍♀️', '🧝‍♂️', '🧞‍♀️', '💁‍♂️', '🧞‍♂️', '🧟‍♀️', '💁‍♀️', '🧟‍♂️', '👨‍⚖️', '👨‍⚕️', '👨‍✈️', '👨‍🦳', '👨‍🦼', '👨‍🦽', '👨‍👧', '👨‍🌾', '👨‍🍳', '👨‍🎓', '👨‍🎤', '👨‍🎨', '👨‍🏫', '👨‍🏭', '🐕‍🦺', '👨‍👦', '👁‍🗨', '👩‍🌾', '👩‍🍳', '👩‍🎓', '👩‍🎤', '👩‍🎨', '👩‍🏫', '👩‍🏭', '👨‍💻', '👩‍👦', '👨‍💼', '👨‍🔧', '👩‍👧', '👨‍🔬', '👨‍🚀', '👨‍🚒', '👨‍🦯', '👨‍🦰', '👩‍💻', '👩‍💼', '👩‍🔧', '👩‍🔬', '👩‍🚀', '👩‍🚒', '👩‍🦯', '👩‍🦰', '👩‍🦱', '👩‍🦲', '👩‍🦳', '👩‍🦼', '👩‍🦽', '👨‍🦱', '👨‍🦲', '🎅🏽', '💁🏾', '💁🏽', '💁🏼', '💁🏻', '👼🏿', '💂🏻', '👼🏾', '👼🏽', '💂🏼', '👼🏼', '👼🏻', '💂🏽', '👸🏿', '👸🏾', '💂🏾', '👸🏽', '👸🏼', '💂🏿', '👸🏻', '👷🏿', '💃🏻', '💃🏼', '💃🏽', '💃🏾', '💃🏿', '💅🏻', '💅🏼', '💅🏽', '💅🏾', '💅🏿', '👷🏾', '👷🏽', '💆🏻', '👷🏼', '👷🏻', '💆🏼', '👶🏿', '👶🏾', '💆🏽', '👶🏽', '👶🏼', '💆🏾', '👶🏻', '👵🏿', '💆🏿', '👵🏾', '👵🏽', '👵🏼', '👵🏻', '💇🏻', '👴🏿', '👴🏾', '💇🏼', '👴🏽', '👴🏼', '💇🏽', '👴🏻', '👳🏿', '💇🏾', '👳🏾', '👳🏽', '💇🏿', '👳🏼', '👳🏻', '💪🏻', '💪🏼', '💪🏽', '💪🏾', '💪🏿', '👲🏿', '👲🏾', '🕴🏻', '👲🏽', '👲🏼', '🕴🏼', '👲🏻', '👱🏿', '🕴🏽', '👱🏾', '👱🏽', '🕴🏾', '👱🏼', '👱🏻', '🕴🏿', '👰🏿', '👰🏾', '👰🏽', '👰🏼', '🕵🏻', '👰🏻', '👮🏿', '🕵🏼', '👮🏾', '👮🏽', '🕵🏽', '👮🏼', '👮🏻', '🕵🏾', '👭🏿', '👭🏾', '🕵🏿', '👭🏽', '👭🏼', '🕺🏻', '🕺🏼', '🕺🏽', '🕺🏾', '🕺🏿', '🖐🏻', '🖐🏼', '🖐🏽', '🖐🏾', '🖐🏿', '🖕🏻', '🖕🏼', '🖕🏽', '🖕🏾', '🖕🏿', '🖖🏻', '🖖🏼', '🖖🏽', '🖖🏾', '🖖🏿', '👭🏻', '👬🏿', '🙅🏻', '👬🏾', '👬🏽', '🙅🏼', '👬🏼', '👬🏻', '🙅🏽', '👫🏿', '👫🏾', '🙅🏾', '👫🏽', '👫🏼', '🙅🏿', '👫🏻', '👩🏿', '👩🏾', '👩🏽', '🙆🏻', '👩🏼', '👩🏻', '🙆🏼', '🇦🇨', '👨🏿', '🙆🏽', '👨🏾', '👨🏽', '🙆🏾', '👨🏼', '👨🏻', '🙆🏿', '👧🏿', '👧🏾', '👧🏽', '👧🏼', '🙇🏻', '👧🏻', '👦🏿', '🙇🏼', '👦🏾', '👦🏽', '🙇🏽', '👦🏼', '👦🏻', '🙇🏾', '👐🏿', '👐🏾', '🙇🏿', '👐🏽', '👐🏼', '👐🏻', '👏🏿', '🙋🏻', '👏🏾', '👏🏽', '🙋🏼', '👏🏼', '👏🏻', '🙋🏽', '👎🏿', '👎🏾', '🙋🏾', '👎🏽', '👎🏼', '🙋🏿', '👎🏻', '👍🏿', '🙌🏻', '🙌🏼', '🙌🏽', '🙌🏾', '🙌🏿', '👍🏾', '👍🏽', '🙍🏻', '👍🏼', '👍🏻', '🙍🏼', '👌🏿', '👌🏾', '🙍🏽', '👌🏽', '👌🏼', '🙍🏾', '👌🏻', '👋🏿', '🙍🏿', '👋🏾', '👋🏽', '👋🏼', '👋🏻', '🙎🏻', '👊🏿', '👊🏾', '🙎🏼', '👊🏽', '👊🏼', '🙎🏽', '👊🏻', '👉🏿', '🙎🏾', '👉🏾', '👉🏽', '🙎🏿', '👉🏼', '👉🏻', '🙏🏻', '🙏🏼', '🙏🏽', '🙏🏾', '🙏🏿', '👈🏿', '👈🏾', '🚣🏻', '👈🏽', '👈🏼', '🚣🏼', '👈🏻', '👇🏿', '🚣🏽', '👇🏾', '👇🏽', '🚣🏾', '👇🏼', '👇🏻', '🚣🏿', '👆🏿', '👆🏾', '👆🏽', '👆🏼', '🚴🏻', '👆🏻', '👃🏿', '🚴🏼', '👃🏾', '👃🏽', '🚴🏽', '👃🏼', '👃🏻', '🚴🏾', '👂🏿', '👂🏾', '🚴🏿', '👂🏽', '👂🏼', '👂🏻', '🏌🏿', '🚵🏻', '🏌🏾', '🏌🏽', '🚵🏼', '🏌🏼', '🏌🏻', '🚵🏽', '🏋🏿', '🏋🏾', '🚵🏾', '🏋🏽', '🏋🏼', '🚵🏿', '🏋🏻', '🏊🏿', '🏊🏾', '🏊🏽', '🚶🏻', '🏊🏼', '🏊🏻', '🚶🏼', '🏇🏿', '🏇🏾', '🚶🏽', '🏇🏽', '🏇🏼', '🚶🏾', '🏇🏻', '🏄🏿', '🚶🏿', '🏄🏾', '🏄🏽', '🛀🏻', '🛀🏼', '🛀🏽', '🛀🏾', '🛀🏿', '🛌🏻', '🛌🏼', '🛌🏽', '🛌🏾', '🛌🏿', '🤏🏻', '🤏🏼', '🤏🏽', '🤏🏾', '🤏🏿', '🤘🏻', '🤘🏼', '🤘🏽', '🤘🏾', '🤘🏿', '🤙🏻', '🤙🏼', '🤙🏽', '🤙🏾', '🤙🏿', '🤚🏻', '🤚🏼', '🤚🏽', '🤚🏾', '🤚🏿', '🤛🏻', '🤛🏼', '🤛🏽', '🤛🏾', '🤛🏿', '🤜🏻', '🤜🏼', '🤜🏽', '🤜🏾', '🤜🏿', '🤞🏻', '🤞🏼', '🤞🏽', '🤞🏾', '🤞🏿', '🤟🏻', '🤟🏼', '🤟🏽', '🤟🏾', '🤟🏿', '🏄🏼', '🏄🏻', '🤦🏻', '🏃🏿', '🏃🏾', '🤦🏼', '🏃🏽', '🏃🏼', '🤦🏽', '🏃🏻', '🏂🏿', '🤦🏾', '🏂🏾', '🏂🏽', '🤦🏿', '🏂🏼', '🏂🏻', '🤰🏻', '🤰🏼', '🤰🏽', '🤰🏾', '🤰🏿', '🤱🏻', '🤱🏼', '🤱🏽', '🤱🏾', '🤱🏿', '🤲🏻', '🤲🏼', '🤲🏽', '🤲🏾', '🤲🏿', '🤳🏻', '🤳🏼', '🤳🏽', '🤳🏾', '🤳🏿', '🤴🏻', '🤴🏼', '🤴🏽', '🤴🏾', '🤴🏿', '🎅🏿', '🎅🏾', '🤵🏻', '💁🏿', '🎅🏼', '🤵🏼', '🎅🏻', '🇿🇼', '🤵🏽', '🇿🇲', '🇿🇦', '🤵🏾', '🇾🇹', '🇾🇪', '🤵🏿', '🇽🇰', '🇼🇸', '🤶🏻', '🤶🏼', '🤶🏽', '🤶🏾', '🤶🏿', '🇼🇫', '🇻🇺', '🤷🏻', '🇻🇳', '🇻🇮', '🤷🏼', '🇻🇬', '🇻🇪', '🤷🏽', '🇻🇨', '🇻🇦', '🤷🏾', '🇺🇿', '🇺🇾', '🤷🏿', '🇺🇸', '🇺🇳', '🇺🇲', '🇺🇬', '🤸🏻', '🇺🇦', '🇹🇿', '🤸🏼', '🇹🇼', '🇹🇻', '🤸🏽', '🇹🇹', '🇹🇷', '🤸🏾', '🇹🇴', '🇹🇳', '🤸🏿', '🇹🇲', '🇹🇱', '🇹🇰', '🇹🇯', '🤹🏻', '🇹🇭', '🇹🇬', '🤹🏼', '🇹🇫', '🇹🇩', '🤹🏽', '🇹🇨', '🇹🇦', '🤹🏾', '🇸🇿', '🇸🇾', '🤹🏿', '🇸🇽', '🇸🇻', '🇸🇹', '🇸🇸', '🇸🇷', '🇸🇴', '🤽🏻', '🇸🇳', '🇸🇲', '🤽🏼', '🇸🇱', '🇸🇰', '🤽🏽', '🇸🇯', '🇸🇮', '🤽🏾', '🇸🇭', '🇸🇬', '🤽🏿', '🇸🇪', '🇸🇩', '🇸🇨', '🇸🇧', '🤾🏻', '🇸🇦', '🇷🇼', '🤾🏼', '🇷🇺', '🇷🇸', '🤾🏽', '🇷🇴', '🇷🇪', '🤾🏾', '🇶🇦', '🇵🇾', '🤾🏿', '🇵🇼', '🇵🇹', '🦵🏻', '🦵🏼', '🦵🏽', '🦵🏾', '🦵🏿', '🦶🏻', '🦶🏼', '🦶🏽', '🦶🏾', '🦶🏿', '🇵🇸', '🇵🇷', '🦸🏻', '🇵🇳', '🇵🇲', '🦸🏼', '🇵🇱', '🇵🇰', '🦸🏽', '🇵🇭', '🇵🇬', '🦸🏾', '🇵🇫', '🇵🇪', '🦸🏿', '🇵🇦', '🇴🇲', '🇳🇿', '🇳🇺', '🦹🏻', '🇳🇷', '🇳🇵', '🦹🏼', '🇳🇴', '🇳🇱', '🦹🏽', '🇳🇮', '🇳🇬', '🦹🏾', '🇳🇫', '🇳🇪', '🦹🏿', '🇳🇨', '🇳🇦', '🦻🏻', '🦻🏼', '🦻🏽', '🦻🏾', '🦻🏿', '🇲🇿', '🇲🇾', '🧍🏻', '🇲🇽', '🇲🇼', '🧍🏼', '🇲🇻', '🇲🇺', '🧍🏽', '🇲🇹', '🇲🇸', '🧍🏾', '🇲🇷', '🇲🇶', '🧍🏿', '🇲🇵', '🇲🇴', '🇲🇳', '🇲🇲', '🧎🏻', '🇲🇱', '🇲🇰', '🧎🏼', '🇲🇭', '🇲🇬', '🧎🏽', '🇲🇫', '🇲🇪', '🧎🏾', '🇲🇩', '🇲🇨', '🧎🏿', '🇲🇦', '🇱🇾', '🇱🇻', '🇱🇺', '🧏🏻', '🇱🇹', '🇱🇸', '🧏🏼', '🇱🇷', '🇱🇰', '🧏🏽', '🇱🇮', '🇱🇨', '🧏🏾', '🇱🇧', '🇱🇦', '🧏🏿', '🇰🇿', '🇰🇾', '🇰🇼', '🧑🏻', '🇰🇷', '🇰🇵', '🧑🏼', '🇰🇳', '🇰🇲', '🇰🇮', '🧑🏽', '🇰🇭', '🇰🇬', '🇰🇪', '🇯🇵', '🧑🏾', '🇯🇴', '🇯🇲', '🇯🇪', '🇮🇹', '🇮🇸', '🧑🏿', '🇮🇷', '🧒🏻', '🧒🏼', '🧒🏽', '🧒🏾', '🧒🏿', '🧓🏻', '🧓🏼', '🧓🏽', '🧓🏾', '🧓🏿', '🧔🏻', '🧔🏼', '🧔🏽', '🧔🏾', '🧔🏿', '🧕🏻', '🧕🏼', '🧕🏽', '🧕🏾', '🧕🏿', '🇮🇶', '🇮🇴', '🧖🏻', '🇮🇳', '🇮🇲', '🧖🏼', '🇮🇱', '🇮🇪', '🧖🏽', '🇮🇩', '🇮🇨', '🧖🏾', '🇭🇺', '🇭🇹', '🧖🏿', '🇭🇷', '🇭🇳', '🇭🇲', '🇭🇰', '🧗🏻', '🇬🇾', '🇬🇼', '🧗🏼', '🇬🇺', '🇬🇹', '🧗🏽', '🇬🇸', '🇬🇷', '🧗🏾', '🇬🇶', '🇬🇵', '🧗🏿', '🇬🇳', '🇬🇲', '🇬🇱', '🇬🇮', '🧘🏻', '🇬🇭', '🇬🇬', '🧘🏼', '🇬🇫', '🇬🇪', '🧘🏽', '🇬🇩', '🇬🇧', '🧘🏾', '🇬🇦', '🇫🇷', '🧘🏿', '🇫🇴', '🇫🇲', '🇫🇰', '🇫🇯', '🧙🏻', '🇫🇮', '🇪🇺', '🧙🏼', '🇪🇹', '🇪🇸', '🧙🏽', '🇪🇷', '🇪🇭', '🧙🏾', '🇪🇬', '🇪🇪', '🧙🏿', '🇪🇨', '🇪🇦', '🇩🇿', '🇩🇴', '🧚🏻', '🇩🇲', '🇩🇰', '🧚🏼', '🇩🇯', '🇩🇬', '🧚🏽', '🇩🇪', '🇨🇿', '🧚🏾', '🇨🇾', '🇨🇽', '🧚🏿', '🇨🇼', '🇨🇻', '🇨🇺', '🇨🇷', '🧛🏻', '🇨🇵', '🇨🇴', '🧛🏼', '🇨🇳', '🇨🇲', '🧛🏽', '🇨🇱', '🇨🇰', '🧛🏾', '🇨🇮', '🇨🇭', '🧛🏿', '🇨🇬', '🇨🇫', '🇨🇩', '🇨🇨', '🧜🏻', '🇨🇦', '🇧🇿', '🧜🏼', '🇧🇾', '🇧🇼', '🧜🏽', '🇧🇻', '🇧🇹', '🧜🏾', '🇧🇸', '🇧🇷', '🧜🏿', '🇧🇶', '🇧🇴', '🇧🇳', '🇧🇲', '🧝🏻', '🇧🇱', '🇧🇯', '🧝🏼', '🇧🇮', '🇧🇭', '🧝🏽', '🇧🇬', '🇧🇫', '🧝🏾', '🇧🇪', '🇧🇩', '🧝🏿', '🇧🇧', '🇧🇦', '🇦🇿', '🇦🇽', '🇦🇼', '🇦🇺', '🇦🇹', '🇦🇸', '🇦🇷', '🇦🇶', '🇦🇴', '🇦🇲', '🇦🇱', '🇦🇮', '🇦🇬', '🇦🇫', '🇦🇪', '🇦🇩', '✍🏿', '⛹🏻', '✍🏾', '✍🏽', '✍🏼', '✍🏻', '✌🏿', '✌🏾', '✌🏽', '✌🏼', '✌🏻', '✋🏿', '✋🏾', '✋🏽', '✋🏼', '✋🏻', '✊🏿', '✊🏾', '✊🏽', '✊🏼', '✊🏻', '⛷🏽', '⛷🏾', '⛹🏿', '☝🏿', '☝🏾', '⛹🏾', '☝🏽', '☝🏼', '⛹🏽', '☝🏻', '⛷🏿', '⛹🏼', '⛷🏻', '⛷🏼', '4⃣', '#⃣', '0⃣', '1⃣', '2⃣', '3⃣', '*⃣', '5⃣', '6⃣', '7⃣', '8⃣', '9⃣', '🏌', '😛', '😜', '😝', '😞', '😟', '😠', '😡', '😢', '😣', '😤', '😥', '😦', '😧', '😨', '😩', '😪', '😫', '😬', '😭', '😮', '😯', '😰', '😱', '😲', '😳', '😴', '😵', '😶', '😷', '😸', '😹', '😺', '😻', '😼', '😽', '😾', '😿', '🙀', '🙁', '🙂', '🙃', '🙄', '🏮', '🏯', '🏰', '🌭', '🏳', '🌮', '🌯', '🌰', '🌱', '🏴', '🏵', '🏷', '🏸', '🏹', '🏺', '🏻', '🏼', '🙅', '🏽', '🏾', '🏿', '🐀', '🐁', '🐂', '🐃', '🐄', '🐅', '🐆', '🐇', '🐈', '🐉', '🐊', '🐋', '🐌', '🐍', '🙆', '🐎', '🐏', '🐐', '🐑', '🐒', '🐓', '🐔', '🌲', '🐕', '🐖', '🐗', '🐘', '🐙', '🐚', '🐛', '🐜', '🐝', '🙇', '🙈', '🙉', '🙊', '🐞', '🐟', '🐠', '🐡', '🐢', '🐣', '🐤', '🐥', '🐦', '🐧', '🐨', '🐩', '🐪', '🐫', '🐬', '🐭', '🐮', '🙋', '🐯', '🐰', '🐱', '🐲', '🐳', '🙌', '🐴', '🐵', '🐶', '🐷', '🐸', '🐹', '🐺', '🐻', '🐼', '🐽', '🐾', '🐿', '👀', '🌳', '👁', '🌴', '🌵', '🙍', '🌶', '🌷', '🌸', '👂', '🌹', '🌺', '🌻', '🌼', '🌽', '👃', '👄', '👅', '🌾', '🌿', '🍀', '🍁', '🍂', '🙎', '👆', '🍃', '🍄', '🍅', '🍆', '🙏', '🚀', '🚁', '🚂', '🚃', '🚄', '🚅', '🚆', '🚇', '🚈', '🚉', '🚊', '🚋', '🚌', '🚍', '🚎', '🚏', '🚐', '🚑', '🚒', '🚓', '🚔', '🚕', '🚖', '🚗', '🚘', '🚙', '🚚', '🚛', '🚜', '🚝', '🚞', '🚟', '🚠', '🚡', '🚢', '🍇', '👇', '🍈', '🍉', '🍊', '🍋', '🍌', '👈', '🍍', '🍎', '🍏', '🍐', '🍑', '👉', '🍒', '🍓', '🍔', '🚣', '🚤', '🚥', '🚦', '🚧', '🚨', '🚩', '🚪', '🚫', '🚬', '🚭', '🚮', '🚯', '🚰', '🚱', '🚲', '🚳', '🍕', '🍖', '👊', '🍗', '🍘', '🍙', '🍚', '🍛', '👋', '🍜', '🍝', '🍞', '🍟', '🍠', '👌', '🍡', '🍢', '🚴', '🍣', '🍤', '🍥', '👍', '🍦', '👩', '👪', '🍧', '🍨', '🍩', '🍪', '👎', '👫', '🍫', '🍬', '🍭', '🍮', '🚵', '🍯', '👬', '👏', '🍰', '🍱', '🍲', '🍳', '👭', '🍴', '👐', '👑', '👒', '👓', '👔', '👕', '👖', '👗', '🚶', '🚷', '🚸', '🚹', '🚺', '🚻', '🚼', '🚽', '🚾', '🚿', '👘', '👙', '👚', '👛', '👜', '🛀', '🛁', '🛂', '🛃', '🛄', '🛅', '🛋', '👝', '👞', '👟', '👮', '👠', '🛌', '🛍', '🛎', '🛏', '🛐', '🛑', '🛒', '🛕', '🛠', '🛡', '🛢', '🛣', '🛤', '🛥', '🛩', '🛫', '🛬', '🛰', '🛳', '🛴', '🛵', '🛶', '🛷', '🛸', '🛹', '🛺', '🟠', '🟡', '🟢', '🟣', '🟤', '🟥', '🟦', '🟧', '🟨', '🟩', '🟪', '🟫', '🤍', '🤎', '👡', '👯', '👢', '👣', '👤', '🤏', '🤐', '🤑', '🤒', '🤓', '🤔', '🤕', '🤖', '🤗', '👥', '🍵', '👰', '🍶', '🍷', '🤘', '🍸', '🍹', '👦', '🍺', '🍻', '🤙', '🍼', '🍽', '🍾', '👧', '🍿', '🤚', '🎀', '🎁', '🎂', '🎃', '🎄', '🤛', '👱', '🇵', '🅾', '🇶', '🇲', '🤜', '🤝', '🅿', '👲', '🎅', '🎆', '🎇', '🤞', '🎈', '🎉', '🎊', '🎋', '🎌', '🤟', '🤠', '🤡', '🤢', '🤣', '🤤', '🤥', '🎍', '🎎', '🎏', '🎐', '🎑', '🎒', '🎓', '🎖', '🎗', '👳', '🎙', '🎚', '🎛', '🎞', '🎟', '👴', '🎠', '🤦', '🤧', '🤨', '🤩', '🤪', '🤫', '🤬', '🤭', '🤮', '🤯', '🎡', '🎢', '🎣', '🎤', '👵', '🤰', '🎥', '🎦', '🎧', '🎨', '🎩', '🤱', '👶', '🎪', '🎫', '🎬', '🎭', '🤲', '🎮', '🎯', '🎰', '🎱', '🎲', '🤳', '🎳', '🎴', '🎵', '🎶', '🎷', '🤴', '🎸', '🎹', '🎺', '👷', '🎻', '🎼', '🎽', '🎾', '🎿', '👸', '👹', '👺', '👻', '🏀', '🏁', '🇧', '🇮', '🤵', '🇪', '👼', '👽', '👾', '👿', '🤶', '💀', '🇷', '🇱', '🏂', '🆎', '🆑', '🇨', '🇹', '🇯', '🆒', '🇬', '🆓', '🇳', '🆔', '🇴', '🇺', '🇫', '🤷', '🆕', '💁', '🆖', '🆗', '🇭', '🏃', '🆘', '🇩', '🇻', '🇰', '🆙', '🇼', '🆚', '🇽', '🇸', '🀄', '🇾', '🤸', '🇦', '🅰', '💂', '🅱', '🇿', '🈁', '🈂', '🏄', '💃', '💄', '🏅', '🏆', '🈚', '🈯', '🈲', '💅', '🈳', '🤹', '🤺', '🈴', '🏇', '🤼', '🏈', '🏉', '🈵', '🈶', '🈷', '🈸', '🈹', '🈺', '🉐', '🉑', '🌀', '🌁', '🌂', '🌃', '💆', '🌄', '🌅', '🤽', '🌆', '🌇', '🌈', '🏊', '🌉', '🌊', '🌋', '🌌', '🌍', '🌎', '🌏', '🌐', '🌑', '🌒', '🌓', '💇', '💈', '🤾', '🤿', '🥀', '🥁', '🥂', '🥃', '🥄', '🥅', '🥇', '🥈', '🥉', '🥊', '🥋', '🥌', '🥍', '🥎', '🥏', '🥐', '🥑', '🥒', '🥓', '🥔', '🥕', '🥖', '🥗', '🥘', '🥙', '🥚', '🥛', '🥜', '🥝', '🥞', '🥟', '🥠', '🥡', '🥢', '🥣', '🥤', '🥥', '🥦', '🥧', '🥨', '🥩', '🥪', '🥫', '🥬', '🥭', '🥮', '🥯', '🥰', '🥱', '🥳', '🥴', '🥵', '🥶', '🥺', '🥻', '🥼', '🥽', '🥾', '🥿', '🦀', '🦁', '🦂', '🦃', '🦄', '🦅', '🦆', '🦇', '🦈', '🦉', '🦊', '🦋', '🦌', '🦍', '🦎', '🦏', '🦐', '🦑', '🦒', '🦓', '🦔', '🦕', '🦖', '🦗', '🦘', '🦙', '🦚', '🦛', '🦜', '🦝', '🦞', '🦟', '🦠', '🦡', '🦢', '🦥', '🦦', '🦧', '🦨', '🦩', '🦪', '🦮', '🦯', '🦰', '🦱', '🦲', '🦳', '🦴', '💉', '💊', '💋', '💌', '💍', '🦵', '💎', '💏', '💐', '💑', '💒', '🦶', '🦷', '💓', '💔', '💕', '💖', '💗', '💘', '💙', '💚', '💛', '💜', '💝', '💞', '💟', '💠', '💡', '💢', '💣', '🦸', '💤', '💥', '💦', '💧', '💨', '💩', '🌔', '🌕', '🌖', '🌗', '🌘', '💪', '💫', '💬', '💭', '💮', '💯', '🦹', '🦺', '💰', '💱', '💲', '💳', '💴', '🦻', '🦼', '🦽', '🦾', '🦿', '🧀', '🧁', '🧂', '🧃', '🧄', '🧅', '🧆', '🧇', '🧈', '🧉', '🧊', '💵', '💶', '💷', '💸', '💹', '💺', '💻', '💼', '💽', '💾', '💿', '📀', '📁', '📂', '📃', '📄', '📅', '🧍', '📆', '📇', '📈', '📉', '📊', '📋', '📌', '📍', '📎', '📏', '📐', '📑', '📒', '📓', '📔', '📕', '📖', '🧎', '📗', '📘', '📙', '📚', '📛', '📜', '📝', '📞', '📟', '📠', '📡', '📢', '📣', '📤', '📥', '📦', '📧', '🧏', '🧐', '📨', '📩', '📪', '📫', '📬', '📭', '📮', '📯', '📰', '📱', '📲', '📳', '📴', '📵', '📶', '📷', '📸', '📹', '📺', '📻', '📼', '🧑', '📽', '📿', '🔀', '🔁', '🔂', '🧒', '🔃', '🔄', '🔅', '🔆', '🔇', '🧓', '🔈', '🔉', '🔊', '🔋', '🔌', '🧔', '🔍', '🔎', '🔏', '🔐', '🔑', '🧕', '🔒', '🔓', '🔔', '🔕', '🔖', '🔗', '🔘', '🔙', '🔚', '🔛', '🔜', '🔝', '🔞', '🔟', '🔠', '🔡', '🔢', '🧖', '🔣', '🔤', '🔥', '🔦', '🔧', '🔨', '🔩', '🔪', '🔫', '🔬', '🔭', '🔮', '🔯', '🔰', '🔱', '🔲', '🔳', '🧗', '🔴', '🔵', '🔶', '🔷', '🔸', '🔹', '🔺', '🔻', '🔼', '🔽', '🕉', '🕊', '🕋', '🕌', '🕍', '🕎', '🕐', '🧘', '🕑', '🕒', '🕓', '🕔', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚', '🕛', '🕜', '🕝', '🕞', '🕟', '🕠', '🕡', '🧙', '🕢', '🕣', '🕤', '🕥', '🕦', '🕧', '🕯', '🕰', '🕳', '🌙', '🏋', '🌚', '🌛', '🌜', '🌝', '🌞', '🌟', '🧚', '🌠', '🌡', '🌤', '🌥', '🌦', '🌧', '🌨', '🌩', '🌪', '🕴', '👨', '🌫', '🌬', '🃏', '🏍', '🏎', '🏏', '🧛', '🏐', '🏑', '🏒', '🏓', '🏔', '🏕', '🏖', '🏗', '🏘', '🏙', '🕵', '🕶', '🕷', '🕸', '🕹', '🏚', '🏛', '🧜', '🏜', '🏝', '🏞', '🕺', '🖇', '🖊', '🖋', '🖌', '🖍', '🏟', '🏠', '🏡', '🏢', '🏣', '🖐', '🏤', '🏥', '🧝', '🏦', '🏧', '🧞', '🏨', '🖕', '🧟', '🧠', '🧡', '🧢', '🧣', '🧤', '🧥', '🧦', '🧧', '🧨', '🧩', '🧪', '🧫', '🧬', '🧭', '🧮', '🧯', '🧰', '🧱', '🧲', '🧳', '🧴', '🧵', '🧶', '🧷', '🧸', '🧹', '🧺', '🧻', '🧼', '🧽', '🧾', '🧿', '🩰', '🩱', '🩲', '🩳', '🩸', '🩹', '🩺', '🪀', '🪁', '🪂', '🪐', '🪑', '🪒', '🪓', '🪔', '🪕', '🏩', '🏪', '🏫', '🏬', '🏭', '🖖', '🖤', '🖥', '🖨', '🖱', '🖲', '🖼', '🗂', '🗃', '🗄', '🗑', '🗒', '🗓', '🗜', '🗝', '🗞', '🗡', '🗣', '🗨', '🗯', '🗳', '🗺', '🗻', '🗼', '🗽', '🗾', '🗿', '😀', '😁', '😂', '😃', '😄', '😅', '😆', '😇', '😈', '😉', '😊', '😋', '😌', '😍', '😎', '😏', '😐', '😑', '😒', '😓', '😔', '😕', '😖', '😗', '😘', '😙', '😚', '▫', '☦', '☮', '☯', '☸', '☹', '☺', '♀', '♂', '♈', '♉', '♊', '♋', '♌', '♍', '♎', '♏', '♐', '♑', '♒', '♓', '♟', '♠', '♣', '♥', '♦', '♨', '♻', '♾', '♿', '⚒', '⚓', '⚔', '⚕', '⚖', '⚗', '⚙', '⚛', '⚜', '⚠', '⚡', '⚪', '⚫', '⚰', '⚱', '⚽', '⚾', '⛄', '⛅', '⛈', '⛎', '⛏', '⛑', '⛓', '⛔', '⛩', '⛪', '⛰', '⛱', '⛲', '⛳', '⛴', '⛵', '☣', '☢', '☠', '☝', '☘', '⛷', '⛸', '☕', '☔', '☑', '☎', '☄', '☃', '☂', '☁', '☀', '◾', '◽', '◼', '◻', '◀', '▶', '☪', '▪', '⛹', '⛺', '⛽', '✂', '✅', '✈', '✉', 'Ⓜ', '⏺', '⏹', '⏸', '⏳', '✊', '⏲', '⏱', '⏰', '⏯', '⏮', '✋', '⏭', '⏬', '⏫', '⏪', '⏩', '✌', '⏏', '⌨', '⌛', '⌚', '↪', '✍', '✏', '✒', '✔', '✖', '✝', '✡', '✨', '✳', '✴', '❄', '❇', '❌', '❎', '❓', '❔', '❕', '❗', '❣', '❤', '➕', '➖', '➗', '➡', '➰', '➿', '⤴', '⤵', '↩', '⬅', '⬆', '⬇', '⬛', '⬜', '⭐', '⭕', '↙', '〰', '〽', '↘', '↗', '㊗', '㊙', '↖', '↕', '↔', 'ℹ', '™', '⁉', '‼', '' ); |
5967 $entities = array( '👨‍❤️‍💋‍👨', '👩‍❤️‍💋‍👨', '👩‍❤️‍💋‍👩', '🏴󠁧󠁢󠁥󠁮󠁧󠁿', '🏴󠁧󠁢󠁳󠁣󠁴󠁿', '🏴󠁧󠁢󠁷󠁬󠁳󠁿', '👨🏻‍🤝‍👨🏼', '👨🏻‍🤝‍👨🏽', '👨🏻‍🤝‍👨🏾', '👨🏻‍🤝‍👨🏿', '👨🏼‍🤝‍👨🏻', '👨🏼‍🤝‍👨🏽', '👨🏼‍🤝‍👨🏾', '👨🏼‍🤝‍👨🏿', '👨🏽‍🤝‍👨🏻', '👨🏽‍🤝‍👨🏼', '👨🏽‍🤝‍👨🏾', '👨🏽‍🤝‍👨🏿', '👨🏾‍🤝‍👨🏻', '👨🏾‍🤝‍👨🏼', '👨🏾‍🤝‍👨🏽', '👨🏾‍🤝‍👨🏿', '👨🏿‍🤝‍👨🏻', '👨🏿‍🤝‍👨🏼', '👨🏿‍🤝‍👨🏽', '👨🏿‍🤝‍👨🏾', '👩🏻‍🤝‍👨🏼', '👩🏻‍🤝‍👨🏽', '👩🏻‍🤝‍👨🏾', '👩🏻‍🤝‍👨🏿', '👩🏻‍🤝‍👩🏼', '👩🏻‍🤝‍👩🏽', '👩🏻‍🤝‍👩🏾', '👩🏻‍🤝‍👩🏿', '👩🏼‍🤝‍👨🏻', '👩🏼‍🤝‍👨🏽', '👩🏼‍🤝‍👨🏾', '👩🏼‍🤝‍👨🏿', '👩🏼‍🤝‍👩🏻', '👩🏼‍🤝‍👩🏽', '👩🏼‍🤝‍👩🏾', '👩🏼‍🤝‍👩🏿', '👩🏽‍🤝‍👨🏻', '👩🏽‍🤝‍👨🏼', '👩🏽‍🤝‍👨🏾', '👩🏽‍🤝‍👨🏿', '👩🏽‍🤝‍👩🏻', '👩🏽‍🤝‍👩🏼', '👩🏽‍🤝‍👩🏾', '👩🏽‍🤝‍👩🏿', '👩🏾‍🤝‍👨🏻', '👩🏾‍🤝‍👨🏼', '👩🏾‍🤝‍👨🏽', '👩🏾‍🤝‍👨🏿', '👩🏾‍🤝‍👩🏻', '👩🏾‍🤝‍👩🏼', '👩🏾‍🤝‍👩🏽', '👩🏾‍🤝‍👩🏿', '👩🏿‍🤝‍👨🏻', '👩🏿‍🤝‍👨🏼', '👩🏿‍🤝‍👨🏽', '👩🏿‍🤝‍👨🏾', '👩🏿‍🤝‍👩🏻', '👩🏿‍🤝‍👩🏼', '👩🏿‍🤝‍👩🏽', '👩🏿‍🤝‍👩🏾', '🧑🏻‍🤝‍🧑🏻', '🧑🏻‍🤝‍🧑🏼', '🧑🏻‍🤝‍🧑🏽', '🧑🏻‍🤝‍🧑🏾', '🧑🏻‍🤝‍🧑🏿', '🧑🏼‍🤝‍🧑🏻', '🧑🏼‍🤝‍🧑🏼', '🧑🏼‍🤝‍🧑🏽', '🧑🏼‍🤝‍🧑🏾', '🧑🏼‍🤝‍🧑🏿', '🧑🏽‍🤝‍🧑🏻', '🧑🏽‍🤝‍🧑🏼', '🧑🏽‍🤝‍🧑🏽', '🧑🏽‍🤝‍🧑🏾', '🧑🏽‍🤝‍🧑🏿', '🧑🏾‍🤝‍🧑🏻', '🧑🏾‍🤝‍🧑🏼', '🧑🏾‍🤝‍🧑🏽', '🧑🏾‍🤝‍🧑🏾', '🧑🏾‍🤝‍🧑🏿', '🧑🏿‍🤝‍🧑🏻', '🧑🏿‍🤝‍🧑🏼', '🧑🏿‍🤝‍🧑🏽', '🧑🏿‍🤝‍🧑🏾', '🧑🏿‍🤝‍🧑🏿', '👨‍👨‍👦‍👦', '👨‍👨‍👧‍👦', '👨‍👨‍👧‍👧', '👨‍👩‍👦‍👦', '👨‍👩‍👧‍👦', '👨‍👩‍👧‍👧', '👩‍👩‍👦‍👦', '👩‍👩‍👧‍👦', '👩‍👩‍👧‍👧', '👨‍❤️‍👨', '👩‍❤️‍👨', '👩‍❤️‍👩', '👨‍👦‍👦', '👨‍👧‍👦', '👨‍👧‍👧', '👨‍👨‍👦', '👨‍👨‍👧', '👨‍👩‍👦', '👨‍👩‍👧', '👩‍👦‍👦', '👩‍👧‍👦', '👩‍👧‍👧', '👩‍👩‍👦', '👩‍👩‍👧', '🧑‍🤝‍🧑', '🏃🏻‍♀️', '🏃🏻‍♂️', '🏃🏼‍♀️', '🏃🏼‍♂️', '🏃🏽‍♀️', '🏃🏽‍♂️', '🏃🏾‍♀️', '🏃🏾‍♂️', '🏃🏿‍♀️', '🏃🏿‍♂️', '🏄🏻‍♀️', '🏄🏻‍♂️', '🏄🏼‍♀️', '🏄🏼‍♂️', '🏄🏽‍♀️', '🏄🏽‍♂️', '🏄🏾‍♀️', '🏄🏾‍♂️', '🏄🏿‍♀️', '🏄🏿‍♂️', '🏊🏻‍♀️', '🏊🏻‍♂️', '🏊🏼‍♀️', '🏊🏼‍♂️', '🏊🏽‍♀️', '🏊🏽‍♂️', '🏊🏾‍♀️', '🏊🏾‍♂️', '🏊🏿‍♀️', '🏊🏿‍♂️', '🏋🏻‍♀️', '🏋🏻‍♂️', '🏋🏼‍♀️', '🏋🏼‍♂️', '🏋🏽‍♀️', '🏋🏽‍♂️', '🏋🏾‍♀️', '🏋🏾‍♂️', '🏋🏿‍♀️', '🏋🏿‍♂️', '🏌🏻‍♀️', '🏌🏻‍♂️', '🏌🏼‍♀️', '🏌🏼‍♂️', '🏌🏽‍♀️', '🏌🏽‍♂️', '🏌🏾‍♀️', '🏌🏾‍♂️', '🏌🏿‍♀️', '🏌🏿‍♂️', '👨🏻‍⚕️', '👨🏻‍⚖️', '👨🏻‍✈️', '👨🏼‍⚕️', '👨🏼‍⚖️', '👨🏼‍✈️', '👨🏽‍⚕️', '👨🏽‍⚖️', '👨🏽‍✈️', '👨🏾‍⚕️', '👨🏾‍⚖️', '👨🏾‍✈️', '👨🏿‍⚕️', '👨🏿‍⚖️', '👨🏿‍✈️', '👩🏻‍⚕️', '👩🏻‍⚖️', '👩🏻‍✈️', '👩🏼‍⚕️', '👩🏼‍⚖️', '👩🏼‍✈️', '👩🏽‍⚕️', '👩🏽‍⚖️', '👩🏽‍✈️', '👩🏾‍⚕️', '👩🏾‍⚖️', '👩🏾‍✈️', '👩🏿‍⚕️', '👩🏿‍⚖️', '👩🏿‍✈️', '👮🏻‍♀️', '👮🏻‍♂️', '👮🏼‍♀️', '👮🏼‍♂️', '👮🏽‍♀️', '👮🏽‍♂️', '👮🏾‍♀️', '👮🏾‍♂️', '👮🏿‍♀️', '👮🏿‍♂️', '👰🏻‍♀️', '👰🏻‍♂️', '👰🏼‍♀️', '👰🏼‍♂️', '👰🏽‍♀️', '👰🏽‍♂️', '👰🏾‍♀️', '👰🏾‍♂️', '👰🏿‍♀️', '👰🏿‍♂️', '👱🏻‍♀️', '👱🏻‍♂️', '👱🏼‍♀️', '👱🏼‍♂️', '👱🏽‍♀️', '👱🏽‍♂️', '👱🏾‍♀️', '👱🏾‍♂️', '👱🏿‍♀️', '👱🏿‍♂️', '👳🏻‍♀️', '👳🏻‍♂️', '👳🏼‍♀️', '👳🏼‍♂️', '👳🏽‍♀️', '👳🏽‍♂️', '👳🏾‍♀️', '👳🏾‍♂️', '👳🏿‍♀️', '👳🏿‍♂️', '👷🏻‍♀️', '👷🏻‍♂️', '👷🏼‍♀️', '👷🏼‍♂️', '👷🏽‍♀️', '👷🏽‍♂️', '👷🏾‍♀️', '👷🏾‍♂️', '👷🏿‍♀️', '👷🏿‍♂️', '💁🏻‍♀️', '💁🏻‍♂️', '💁🏼‍♀️', '💁🏼‍♂️', '💁🏽‍♀️', '💁🏽‍♂️', '💁🏾‍♀️', '💁🏾‍♂️', '💁🏿‍♀️', '💁🏿‍♂️', '💂🏻‍♀️', '💂🏻‍♂️', '💂🏼‍♀️', '💂🏼‍♂️', '💂🏽‍♀️', '💂🏽‍♂️', '💂🏾‍♀️', '💂🏾‍♂️', '💂🏿‍♀️', '💂🏿‍♂️', '💆🏻‍♀️', '💆🏻‍♂️', '💆🏼‍♀️', '💆🏼‍♂️', '💆🏽‍♀️', '💆🏽‍♂️', '💆🏾‍♀️', '💆🏾‍♂️', '💆🏿‍♀️', '💆🏿‍♂️', '💇🏻‍♀️', '💇🏻‍♂️', '💇🏼‍♀️', '💇🏼‍♂️', '💇🏽‍♀️', '💇🏽‍♂️', '💇🏾‍♀️', '💇🏾‍♂️', '💇🏿‍♀️', '💇🏿‍♂️', '🕴🏻‍♀️', '🕴🏻‍♂️', '🕴🏼‍♀️', '🕴🏼‍♂️', '🕴🏽‍♀️', '🕴🏽‍♂️', '🕴🏾‍♀️', '🕴🏾‍♂️', '🕴🏿‍♀️', '🕴🏿‍♂️', '🕵🏻‍♀️', '🕵🏻‍♂️', '🕵🏼‍♀️', '🕵🏼‍♂️', '🕵🏽‍♀️', '🕵🏽‍♂️', '🕵🏾‍♀️', '🕵🏾‍♂️', '🕵🏿‍♀️', '🕵🏿‍♂️', '🙅🏻‍♀️', '🙅🏻‍♂️', '🙅🏼‍♀️', '🙅🏼‍♂️', '🙅🏽‍♀️', '🙅🏽‍♂️', '🙅🏾‍♀️', '🙅🏾‍♂️', '🙅🏿‍♀️', '🙅🏿‍♂️', '🙆🏻‍♀️', '🙆🏻‍♂️', '🙆🏼‍♀️', '🙆🏼‍♂️', '🙆🏽‍♀️', '🙆🏽‍♂️', '🙆🏾‍♀️', '🙆🏾‍♂️', '🙆🏿‍♀️', '🙆🏿‍♂️', '🙇🏻‍♀️', '🙇🏻‍♂️', '🙇🏼‍♀️', '🙇🏼‍♂️', '🙇🏽‍♀️', '🙇🏽‍♂️', '🙇🏾‍♀️', '🙇🏾‍♂️', '🙇🏿‍♀️', '🙇🏿‍♂️', '🙋🏻‍♀️', '🙋🏻‍♂️', '🙋🏼‍♀️', '🙋🏼‍♂️', '🙋🏽‍♀️', '🙋🏽‍♂️', '🙋🏾‍♀️', '🙋🏾‍♂️', '🙋🏿‍♀️', '🙋🏿‍♂️', '🙍🏻‍♀️', '🙍🏻‍♂️', '🙍🏼‍♀️', '🙍🏼‍♂️', '🙍🏽‍♀️', '🙍🏽‍♂️', '🙍🏾‍♀️', '🙍🏾‍♂️', '🙍🏿‍♀️', '🙍🏿‍♂️', '🙎🏻‍♀️', '🙎🏻‍♂️', '🙎🏼‍♀️', '🙎🏼‍♂️', '🙎🏽‍♀️', '🙎🏽‍♂️', '🙎🏾‍♀️', '🙎🏾‍♂️', '🙎🏿‍♀️', '🙎🏿‍♂️', '🚣🏻‍♀️', '🚣🏻‍♂️', '🚣🏼‍♀️', '🚣🏼‍♂️', '🚣🏽‍♀️', '🚣🏽‍♂️', '🚣🏾‍♀️', '🚣🏾‍♂️', '🚣🏿‍♀️', '🚣🏿‍♂️', '🚴🏻‍♀️', '🚴🏻‍♂️', '🚴🏼‍♀️', '🚴🏼‍♂️', '🚴🏽‍♀️', '🚴🏽‍♂️', '🚴🏾‍♀️', '🚴🏾‍♂️', '🚴🏿‍♀️', '🚴🏿‍♂️', '🚵🏻‍♀️', '🚵🏻‍♂️', '🚵🏼‍♀️', '🚵🏼‍♂️', '🚵🏽‍♀️', '🚵🏽‍♂️', '🚵🏾‍♀️', '🚵🏾‍♂️', '🚵🏿‍♀️', '🚵🏿‍♂️', '🚶🏻‍♀️', '🚶🏻‍♂️', '🚶🏼‍♀️', '🚶🏼‍♂️', '🚶🏽‍♀️', '🚶🏽‍♂️', '🚶🏾‍♀️', '🚶🏾‍♂️', '🚶🏿‍♀️', '🚶🏿‍♂️', '🤦🏻‍♀️', '🤦🏻‍♂️', '🤦🏼‍♀️', '🤦🏼‍♂️', '🤦🏽‍♀️', '🤦🏽‍♂️', '🤦🏾‍♀️', '🤦🏾‍♂️', '🤦🏿‍♀️', '🤦🏿‍♂️', '🤵🏻‍♀️', '🤵🏻‍♂️', '🤵🏼‍♀️', '🤵🏼‍♂️', '🤵🏽‍♀️', '🤵🏽‍♂️', '🤵🏾‍♀️', '🤵🏾‍♂️', '🤵🏿‍♀️', '🤵🏿‍♂️', '🤷🏻‍♀️', '🤷🏻‍♂️', '🤷🏼‍♀️', '🤷🏼‍♂️', '🤷🏽‍♀️', '🤷🏽‍♂️', '🤷🏾‍♀️', '🤷🏾‍♂️', '🤷🏿‍♀️', '🤷🏿‍♂️', '🤸🏻‍♀️', '🤸🏻‍♂️', '🤸🏼‍♀️', '🤸🏼‍♂️', '🤸🏽‍♀️', '🤸🏽‍♂️', '🤸🏾‍♀️', '🤸🏾‍♂️', '🤸🏿‍♀️', '🤸🏿‍♂️', '🤹🏻‍♀️', '🤹🏻‍♂️', '🤹🏼‍♀️', '🤹🏼‍♂️', '🤹🏽‍♀️', '🤹🏽‍♂️', '🤹🏾‍♀️', '🤹🏾‍♂️', '🤹🏿‍♀️', '🤹🏿‍♂️', '🤽🏻‍♀️', '🤽🏻‍♂️', '🤽🏼‍♀️', '🤽🏼‍♂️', '🤽🏽‍♀️', '🤽🏽‍♂️', '🤽🏾‍♀️', '🤽🏾‍♂️', '🤽🏿‍♀️', '🤽🏿‍♂️', '🤾🏻‍♀️', '🤾🏻‍♂️', '🤾🏼‍♀️', '🤾🏼‍♂️', '🤾🏽‍♀️', '🤾🏽‍♂️', '🤾🏾‍♀️', '🤾🏾‍♂️', '🤾🏿‍♀️', '🤾🏿‍♂️', '🦸🏻‍♀️', '🦸🏻‍♂️', '🦸🏼‍♀️', '🦸🏼‍♂️', '🦸🏽‍♀️', '🦸🏽‍♂️', '🦸🏾‍♀️', '🦸🏾‍♂️', '🦸🏿‍♀️', '🦸🏿‍♂️', '🦹🏻‍♀️', '🦹🏻‍♂️', '🦹🏼‍♀️', '🦹🏼‍♂️', '🦹🏽‍♀️', '🦹🏽‍♂️', '🦹🏾‍♀️', '🦹🏾‍♂️', '🦹🏿‍♀️', '🦹🏿‍♂️', '🧍🏻‍♀️', '🧍🏻‍♂️', '🧍🏼‍♀️', '🧍🏼‍♂️', '🧍🏽‍♀️', '🧍🏽‍♂️', '🧍🏾‍♀️', '🧍🏾‍♂️', '🧍🏿‍♀️', '🧍🏿‍♂️', '🧎🏻‍♀️', '🧎🏻‍♂️', '🧎🏼‍♀️', '🧎🏼‍♂️', '🧎🏽‍♀️', '🧎🏽‍♂️', '🧎🏾‍♀️', '🧎🏾‍♂️', '🧎🏿‍♀️', '🧎🏿‍♂️', '🧏🏻‍♀️', '🧏🏻‍♂️', '🧏🏼‍♀️', '🧏🏼‍♂️', '🧏🏽‍♀️', '🧏🏽‍♂️', '🧏🏾‍♀️', '🧏🏾‍♂️', '🧏🏿‍♀️', '🧏🏿‍♂️', '🧑🏻‍⚕️', '🧑🏻‍⚖️', '🧑🏻‍✈️', '🧑🏼‍⚕️', '🧑🏼‍⚖️', '🧑🏼‍✈️', '🧑🏽‍⚕️', '🧑🏽‍⚖️', '🧑🏽‍✈️', '🧑🏾‍⚕️', '🧑🏾‍⚖️', '🧑🏾‍✈️', '🧑🏿‍⚕️', '🧑🏿‍⚖️', '🧑🏿‍✈️', '🧖🏻‍♀️', '🧖🏻‍♂️', '🧖🏼‍♀️', '🧖🏼‍♂️', '🧖🏽‍♀️', '🧖🏽‍♂️', '🧖🏾‍♀️', '🧖🏾‍♂️', '🧖🏿‍♀️', '🧖🏿‍♂️', '🧗🏻‍♀️', '🧗🏻‍♂️', '🧗🏼‍♀️', '🧗🏼‍♂️', '🧗🏽‍♀️', '🧗🏽‍♂️', '🧗🏾‍♀️', '🧗🏾‍♂️', '🧗🏿‍♀️', '🧗🏿‍♂️', '🧘🏻‍♀️', '🧘🏻‍♂️', '🧘🏼‍♀️', '🧘🏼‍♂️', '🧘🏽‍♀️', '🧘🏽‍♂️', '🧘🏾‍♀️', '🧘🏾‍♂️', '🧘🏿‍♀️', '🧘🏿‍♂️', '🧙🏻‍♀️', '🧙🏻‍♂️', '🧙🏼‍♀️', '🧙🏼‍♂️', '🧙🏽‍♀️', '🧙🏽‍♂️', '🧙🏾‍♀️', '🧙🏾‍♂️', '🧙🏿‍♀️', '🧙🏿‍♂️', '🧚🏻‍♀️', '🧚🏻‍♂️', '🧚🏼‍♀️', '🧚🏼‍♂️', '🧚🏽‍♀️', '🧚🏽‍♂️', '🧚🏾‍♀️', '🧚🏾‍♂️', '🧚🏿‍♀️', '🧚🏿‍♂️', '🧛🏻‍♀️', '🧛🏻‍♂️', '🧛🏼‍♀️', '🧛🏼‍♂️', '🧛🏽‍♀️', '🧛🏽‍♂️', '🧛🏾‍♀️', '🧛🏾‍♂️', '🧛🏿‍♀️', '🧛🏿‍♂️', '🧜🏻‍♀️', '🧜🏻‍♂️', '🧜🏼‍♀️', '🧜🏼‍♂️', '🧜🏽‍♀️', '🧜🏽‍♂️', '🧜🏾‍♀️', '🧜🏾‍♂️', '🧜🏿‍♀️', '🧜🏿‍♂️', '🧝🏻‍♀️', '🧝🏻‍♂️', '🧝🏼‍♀️', '🧝🏼‍♂️', '🧝🏽‍♀️', '🧝🏽‍♂️', '🧝🏾‍♀️', '🧝🏾‍♂️', '🧝🏿‍♀️', '🧝🏿‍♂️', '🏋️‍♀️', '🏋️‍♂️', '🏌️‍♀️', '🏌️‍♂️', '🏳️‍⚧️', '🕴️‍♀️', '🕴️‍♂️', '🕵️‍♀️', '🕵️‍♂️', '⛹🏻‍♀️', '⛹🏻‍♂️', '⛹🏼‍♀️', '⛹🏼‍♂️', '⛹🏽‍♀️', '⛹🏽‍♂️', '⛹🏾‍♀️', '⛹🏾‍♂️', '⛹🏿‍♀️', '⛹🏿‍♂️', '⛹️‍♀️', '⛹️‍♂️', '👨🏻‍🌾', '👨🏻‍🍳', '👨🏻‍🍼', '👨🏻‍🎄', '👨🏻‍🎓', '👨🏻‍🎤', '👨🏻‍🎨', '👨🏻‍🏫', '👨🏻‍🏭', '👨🏻‍💻', '👨🏻‍💼', '👨🏻‍🔧', '👨🏻‍🔬', '👨🏻‍🚀', '👨🏻‍🚒', '👨🏻‍🦯', '👨🏻‍🦰', '👨🏻‍🦱', '👨🏻‍🦲', '👨🏻‍🦳', '👨🏻‍🦼', '👨🏻‍🦽', '👨🏼‍🌾', '👨🏼‍🍳', '👨🏼‍🍼', '👨🏼‍🎄', '👨🏼‍🎓', '👨🏼‍🎤', '👨🏼‍🎨', '👨🏼‍🏫', '👨🏼‍🏭', '👨🏼‍💻', '👨🏼‍💼', '👨🏼‍🔧', '👨🏼‍🔬', '👨🏼‍🚀', '👨🏼‍🚒', '👨🏼‍🦯', '👨🏼‍🦰', '👨🏼‍🦱', '👨🏼‍🦲', '👨🏼‍🦳', '👨🏼‍🦼', '👨🏼‍🦽', '👨🏽‍🌾', '👨🏽‍🍳', '👨🏽‍🍼', '👨🏽‍🎄', '👨🏽‍🎓', '👨🏽‍🎤', '👨🏽‍🎨', '👨🏽‍🏫', '👨🏽‍🏭', '👨🏽‍💻', '👨🏽‍💼', '👨🏽‍🔧', '👨🏽‍🔬', '👨🏽‍🚀', '👨🏽‍🚒', '👨🏽‍🦯', '👨🏽‍🦰', '👨🏽‍🦱', '👨🏽‍🦲', '👨🏽‍🦳', '👨🏽‍🦼', '👨🏽‍🦽', '👨🏾‍🌾', '👨🏾‍🍳', '👨🏾‍🍼', '👨🏾‍🎄', '👨🏾‍🎓', '👨🏾‍🎤', '👨🏾‍🎨', '👨🏾‍🏫', '👨🏾‍🏭', '👨🏾‍💻', '👨🏾‍💼', '👨🏾‍🔧', '👨🏾‍🔬', '👨🏾‍🚀', '👨🏾‍🚒', '👨🏾‍🦯', '👨🏾‍🦰', '👨🏾‍🦱', '👨🏾‍🦲', '👨🏾‍🦳', '👨🏾‍🦼', '👨🏾‍🦽', '👨🏿‍🌾', '👨🏿‍🍳', '👨🏿‍🍼', '👨🏿‍🎄', '👨🏿‍🎓', '👨🏿‍🎤', '👨🏿‍🎨', '👨🏿‍🏫', '👨🏿‍🏭', '👨🏿‍💻', '👨🏿‍💼', '👨🏿‍🔧', '👨🏿‍🔬', '👨🏿‍🚀', '👨🏿‍🚒', '👨🏿‍🦯', '👨🏿‍🦰', '👨🏿‍🦱', '👨🏿‍🦲', '👨🏿‍🦳', '👨🏿‍🦼', '👨🏿‍🦽', '👩🏻‍🌾', '👩🏻‍🍳', '👩🏻‍🍼', '👩🏻‍🎄', '👩🏻‍🎓', '👩🏻‍🎤', '👩🏻‍🎨', '👩🏻‍🏫', '👩🏻‍🏭', '👩🏻‍💻', '👩🏻‍💼', '👩🏻‍🔧', '👩🏻‍🔬', '👩🏻‍🚀', '👩🏻‍🚒', '👩🏻‍🦯', '👩🏻‍🦰', '👩🏻‍🦱', '👩🏻‍🦲', '👩🏻‍🦳', '👩🏻‍🦼', '👩🏻‍🦽', '👩🏼‍🌾', '👩🏼‍🍳', '👩🏼‍🍼', '👩🏼‍🎄', '👩🏼‍🎓', '👩🏼‍🎤', '👩🏼‍🎨', '👩🏼‍🏫', '👩🏼‍🏭', '👩🏼‍💻', '👩🏼‍💼', '👩🏼‍🔧', '👩🏼‍🔬', '👩🏼‍🚀', '👩🏼‍🚒', '👩🏼‍🦯', '👩🏼‍🦰', '👩🏼‍🦱', '👩🏼‍🦲', '👩🏼‍🦳', '👩🏼‍🦼', '👩🏼‍🦽', '👩🏽‍🌾', '👩🏽‍🍳', '👩🏽‍🍼', '👩🏽‍🎄', '👩🏽‍🎓', '👩🏽‍🎤', '👩🏽‍🎨', '👩🏽‍🏫', '👩🏽‍🏭', '👩🏽‍💻', '👩🏽‍💼', '👩🏽‍🔧', '👩🏽‍🔬', '👩🏽‍🚀', '👩🏽‍🚒', '👩🏽‍🦯', '👩🏽‍🦰', '👩🏽‍🦱', '👩🏽‍🦲', '👩🏽‍🦳', '👩🏽‍🦼', '👩🏽‍🦽', '👩🏾‍🌾', '👩🏾‍🍳', '👩🏾‍🍼', '👩🏾‍🎄', '👩🏾‍🎓', '👩🏾‍🎤', '👩🏾‍🎨', '👩🏾‍🏫', '👩🏾‍🏭', '👩🏾‍💻', '👩🏾‍💼', '👩🏾‍🔧', '👩🏾‍🔬', '👩🏾‍🚀', '👩🏾‍🚒', '👩🏾‍🦯', '👩🏾‍🦰', '👩🏾‍🦱', '👩🏾‍🦲', '👩🏾‍🦳', '👩🏾‍🦼', '👩🏾‍🦽', '👩🏿‍🌾', '👩🏿‍🍳', '👩🏿‍🍼', '👩🏿‍🎄', '👩🏿‍🎓', '👩🏿‍🎤', '👩🏿‍🎨', '👩🏿‍🏫', '👩🏿‍🏭', '👩🏿‍💻', '👩🏿‍💼', '👩🏿‍🔧', '👩🏿‍🔬', '👩🏿‍🚀', '👩🏿‍🚒', '👩🏿‍🦯', '👩🏿‍🦰', '👩🏿‍🦱', '👩🏿‍🦲', '👩🏿‍🦳', '👩🏿‍🦼', '👩🏿‍🦽', '🧑🏻‍🌾', '🧑🏻‍🍳', '🧑🏻‍🍼', '🧑🏻‍🎄', '🧑🏻‍🎓', '🧑🏻‍🎤', '🧑🏻‍🎨', '🧑🏻‍🏫', '🧑🏻‍🏭', '🧑🏻‍💻', '🧑🏻‍💼', '🧑🏻‍🔧', '🧑🏻‍🔬', '🧑🏻‍🚀', '🧑🏻‍🚒', '🧑🏻‍🦯', '🧑🏻‍🦰', '🧑🏻‍🦱', '🧑🏻‍🦲', '🧑🏻‍🦳', '🧑🏻‍🦼', '🧑🏻‍🦽', '🧑🏼‍🌾', '🧑🏼‍🍳', '🧑🏼‍🍼', '🧑🏼‍🎄', '🧑🏼‍🎓', '🧑🏼‍🎤', '🧑🏼‍🎨', '🧑🏼‍🏫', '🧑🏼‍🏭', '🧑🏼‍💻', '🧑🏼‍💼', '🧑🏼‍🔧', '🧑🏼‍🔬', '🧑🏼‍🚀', '🧑🏼‍🚒', '🧑🏼‍🦯', '🧑🏼‍🦰', '🧑🏼‍🦱', '🧑🏼‍🦲', '🧑🏼‍🦳', '🧑🏼‍🦼', '🧑🏼‍🦽', '🧑🏽‍🌾', '🧑🏽‍🍳', '🧑🏽‍🍼', '🧑🏽‍🎄', '🧑🏽‍🎓', '🧑🏽‍🎤', '🧑🏽‍🎨', '🧑🏽‍🏫', '🧑🏽‍🏭', '🧑🏽‍💻', '🧑🏽‍💼', '🧑🏽‍🔧', '🧑🏽‍🔬', '🧑🏽‍🚀', '🧑🏽‍🚒', '🧑🏽‍🦯', '🧑🏽‍🦰', '🧑🏽‍🦱', '🧑🏽‍🦲', '🧑🏽‍🦳', '🧑🏽‍🦼', '🧑🏽‍🦽', '🧑🏾‍🌾', '🧑🏾‍🍳', '🧑🏾‍🍼', '🧑🏾‍🎄', '🧑🏾‍🎓', '🧑🏾‍🎤', '🧑🏾‍🎨', '🧑🏾‍🏫', '🧑🏾‍🏭', '🧑🏾‍💻', '🧑🏾‍💼', '🧑🏾‍🔧', '🧑🏾‍🔬', '🧑🏾‍🚀', '🧑🏾‍🚒', '🧑🏾‍🦯', '🧑🏾‍🦰', '🧑🏾‍🦱', '🧑🏾‍🦲', '🧑🏾‍🦳', '🧑🏾‍🦼', '🧑🏾‍🦽', '🧑🏿‍🌾', '🧑🏿‍🍳', '🧑🏿‍🍼', '🧑🏿‍🎄', '🧑🏿‍🎓', '🧑🏿‍🎤', '🧑🏿‍🎨', '🧑🏿‍🏫', '🧑🏿‍🏭', '🧑🏿‍💻', '🧑🏿‍💼', '🧑🏿‍🔧', '🧑🏿‍🔬', '🧑🏿‍🚀', '🧑🏿‍🚒', '🧑🏿‍🦯', '🧑🏿‍🦰', '🧑🏿‍🦱', '🧑🏿‍🦲', '🧑🏿‍🦳', '🧑🏿‍🦼', '🧑🏿‍🦽', '🏳️‍🌈', '🏃‍♀️', '🏃‍♂️', '🏄‍♀️', '🏄‍♂️', '🏊‍♀️', '🏊‍♂️', '🏴‍☠️', '🐻‍❄️', '👨‍⚕️', '👨‍⚖️', '👨‍✈️', '👩‍⚕️', '👩‍⚖️', '👩‍✈️', '👮‍♀️', '👮‍♂️', '👯‍♀️', '👯‍♂️', '👰‍♀️', '👰‍♂️', '👱‍♀️', '👱‍♂️', '👳‍♀️', '👳‍♂️', '👷‍♀️', '👷‍♂️', '💁‍♀️', '💁‍♂️', '💂‍♀️', '💂‍♂️', '💆‍♀️', '💆‍♂️', '💇‍♀️', '💇‍♂️', '🙅‍♀️', '🙅‍♂️', '🙆‍♀️', '🙆‍♂️', '🙇‍♀️', '🙇‍♂️', '🙋‍♀️', '🙋‍♂️', '🙍‍♀️', '🙍‍♂️', '🙎‍♀️', '🙎‍♂️', '🚣‍♀️', '🚣‍♂️', '🚴‍♀️', '🚴‍♂️', '🚵‍♀️', '🚵‍♂️', '🚶‍♀️', '🚶‍♂️', '🤦‍♀️', '🤦‍♂️', '🤵‍♀️', '🤵‍♂️', '🤷‍♀️', '🤷‍♂️', '🤸‍♀️', '🤸‍♂️', '🤹‍♀️', '🤹‍♂️', '🤼‍♀️', '🤼‍♂️', '🤽‍♀️', '🤽‍♂️', '🤾‍♀️', '🤾‍♂️', '🦸‍♀️', '🦸‍♂️', '🦹‍♀️', '🦹‍♂️', '🧍‍♀️', '🧍‍♂️', '🧎‍♀️', '🧎‍♂️', '🧏‍♀️', '🧏‍♂️', '🧑‍⚕️', '🧑‍⚖️', '🧑‍✈️', '🧖‍♀️', '🧖‍♂️', '🧗‍♀️', '🧗‍♂️', '🧘‍♀️', '🧘‍♂️', '🧙‍♀️', '🧙‍♂️', '🧚‍♀️', '🧚‍♂️', '🧛‍♀️', '🧛‍♂️', '🧜‍♀️', '🧜‍♂️', '🧝‍♀️', '🧝‍♂️', '🧞‍♀️', '🧞‍♂️', '🧟‍♀️', '🧟‍♂️', '🐕‍🦺', '👁‍🗨', '👨‍🌾', '👨‍🍳', '👨‍🍼', '👨‍🎄', '👨‍🎓', '👨‍🎤', '👨‍🎨', '👨‍🏫', '👨‍🏭', '👨‍👦', '👨‍👧', '👨‍💻', '👨‍💼', '👨‍🔧', '👨‍🔬', '👨‍🚀', '👨‍🚒', '👨‍🦯', '👨‍🦰', '👨‍🦱', '👨‍🦲', '👨‍🦳', '👨‍🦼', '👨‍🦽', '👩‍🌾', '👩‍🍳', '👩‍🍼', '👩‍🎄', '👩‍🎓', '👩‍🎤', '👩‍🎨', '👩‍🏫', '👩‍🏭', '👩‍👦', '👩‍👧', '👩‍💻', '👩‍💼', '👩‍🔧', '👩‍🔬', '👩‍🚀', '👩‍🚒', '👩‍🦯', '👩‍🦰', '👩‍🦱', '👩‍🦲', '👩‍🦳', '👩‍🦼', '👩‍🦽', '🧑‍🌾', '🧑‍🍳', '🧑‍🍼', '🧑‍🎄', '🧑‍🎓', '🧑‍🎤', '🧑‍🎨', '🧑‍🏫', '🧑‍🏭', '🧑‍💻', '🧑‍💼', '🧑‍🔧', '🧑‍🔬', '🧑‍🚀', '🧑‍🚒', '🧑‍🦯', '🧑‍🦰', '🧑‍🦱', '🧑‍🦲', '🧑‍🦳', '🧑‍🦼', '🧑‍🦽', '🐈‍⬛', '🇦🇨', '🇦🇩', '🇦🇪', '🇦🇫', '🇦🇬', '🇦🇮', '🇦🇱', '🇦🇲', '🇦🇴', '🇦🇶', '🇦🇷', '🇦🇸', '🇦🇹', '🇦🇺', '🇦🇼', '🇦🇽', '🇦🇿', '🇧🇦', '🇧🇧', '🇧🇩', '🇧🇪', '🇧🇫', '🇧🇬', '🇧🇭', '🇧🇮', '🇧🇯', '🇧🇱', '🇧🇲', '🇧🇳', '🇧🇴', '🇧🇶', '🇧🇷', '🇧🇸', '🇧🇹', '🇧🇻', '🇧🇼', '🇧🇾', '🇧🇿', '🇨🇦', '🇨🇨', '🇨🇩', '🇨🇫', '🇨🇬', '🇨🇭', '🇨🇮', '🇨🇰', '🇨🇱', '🇨🇲', '🇨🇳', '🇨🇴', '🇨🇵', '🇨🇷', '🇨🇺', '🇨🇻', '🇨🇼', '🇨🇽', '🇨🇾', '🇨🇿', '🇩🇪', '🇩🇬', '🇩🇯', '🇩🇰', '🇩🇲', '🇩🇴', '🇩🇿', '🇪🇦', '🇪🇨', '🇪🇪', '🇪🇬', '🇪🇭', '🇪🇷', '🇪🇸', '🇪🇹', '🇪🇺', '🇫🇮', '🇫🇯', '🇫🇰', '🇫🇲', '🇫🇴', '🇫🇷', '🇬🇦', '🇬🇧', '🇬🇩', '🇬🇪', '🇬🇫', '🇬🇬', '🇬🇭', '🇬🇮', '🇬🇱', '🇬🇲', '🇬🇳', '🇬🇵', '🇬🇶', '🇬🇷', '🇬🇸', '🇬🇹', '🇬🇺', '🇬🇼', '🇬🇾', '🇭🇰', '🇭🇲', '🇭🇳', '🇭🇷', '🇭🇹', '🇭🇺', '🇮🇨', '🇮🇩', '🇮🇪', '🇮🇱', '🇮🇲', '🇮🇳', '🇮🇴', '🇮🇶', '🇮🇷', '🇮🇸', '🇮🇹', '🇯🇪', '🇯🇲', '🇯🇴', '🇯🇵', '🇰🇪', '🇰🇬', '🇰🇭', '🇰🇮', '🇰🇲', '🇰🇳', '🇰🇵', '🇰🇷', '🇰🇼', '🇰🇾', '🇰🇿', '🇱🇦', '🇱🇧', '🇱🇨', '🇱🇮', '🇱🇰', '🇱🇷', '🇱🇸', '🇱🇹', '🇱🇺', '🇱🇻', '🇱🇾', '🇲🇦', '🇲🇨', '🇲🇩', '🇲🇪', '🇲🇫', '🇲🇬', '🇲🇭', '🇲🇰', '🇲🇱', '🇲🇲', '🇲🇳', '🇲🇴', '🇲🇵', '🇲🇶', '🇲🇷', '🇲🇸', '🇲🇹', '🇲🇺', '🇲🇻', '🇲🇼', '🇲🇽', '🇲🇾', '🇲🇿', '🇳🇦', '🇳🇨', '🇳🇪', '🇳🇫', '🇳🇬', '🇳🇮', '🇳🇱', '🇳🇴', '🇳🇵', '🇳🇷', '🇳🇺', '🇳🇿', '🇴🇲', '🇵🇦', '🇵🇪', '🇵🇫', '🇵🇬', '🇵🇭', '🇵🇰', '🇵🇱', '🇵🇲', '🇵🇳', '🇵🇷', '🇵🇸', '🇵🇹', '🇵🇼', '🇵🇾', '🇶🇦', '🇷🇪', '🇷🇴', '🇷🇸', '🇷🇺', '🇷🇼', '🇸🇦', '🇸🇧', '🇸🇨', '🇸🇩', '🇸🇪', '🇸🇬', '🇸🇭', '🇸🇮', '🇸🇯', '🇸🇰', '🇸🇱', '🇸🇲', '🇸🇳', '🇸🇴', '🇸🇷', '🇸🇸', '🇸🇹', '🇸🇻', '🇸🇽', '🇸🇾', '🇸🇿', '🇹🇦', '🇹🇨', '🇹🇩', '🇹🇫', '🇹🇬', '🇹🇭', '🇹🇯', '🇹🇰', '🇹🇱', '🇹🇲', '🇹🇳', '🇹🇴', '🇹🇷', '🇹🇹', '🇹🇻', '🇹🇼', '🇹🇿', '🇺🇦', '🇺🇬', '🇺🇲', '🇺🇳', '🇺🇸', '🇺🇾', '🇺🇿', '🇻🇦', '🇻🇨', '🇻🇪', '🇻🇬', '🇻🇮', '🇻🇳', '🇻🇺', '🇼🇫', '🇼🇸', '🇽🇰', '🇾🇪', '🇾🇹', '🇿🇦', '🇿🇲', '🇿🇼', '🎅🏻', '🎅🏼', '🎅🏽', '🎅🏾', '🎅🏿', '🏂🏻', '🏂🏼', '🏂🏽', '🏂🏾', '🏂🏿', '🏃🏻', '🏃🏼', '🏃🏽', '🏃🏾', '🏃🏿', '🏄🏻', '🏄🏼', '🏄🏽', '🏄🏾', '🏄🏿', '🏇🏻', '🏇🏼', '🏇🏽', '🏇🏾', '🏇🏿', '🏊🏻', '🏊🏼', '🏊🏽', '🏊🏾', '🏊🏿', '🏋🏻', '🏋🏼', '🏋🏽', '🏋🏾', '🏋🏿', '🏌🏻', '🏌🏼', '🏌🏽', '🏌🏾', '🏌🏿', '👂🏻', '👂🏼', '👂🏽', '👂🏾', '👂🏿', '👃🏻', '👃🏼', '👃🏽', '👃🏾', '👃🏿', '👆🏻', '👆🏼', '👆🏽', '👆🏾', '👆🏿', '👇🏻', '👇🏼', '👇🏽', '👇🏾', '👇🏿', '👈🏻', '👈🏼', '👈🏽', '👈🏾', '👈🏿', '👉🏻', '👉🏼', '👉🏽', '👉🏾', '👉🏿', '👊🏻', '👊🏼', '👊🏽', '👊🏾', '👊🏿', '👋🏻', '👋🏼', '👋🏽', '👋🏾', '👋🏿', '👌🏻', '👌🏼', '👌🏽', '👌🏾', '👌🏿', '👍🏻', '👍🏼', '👍🏽', '👍🏾', '👍🏿', '👎🏻', '👎🏼', '👎🏽', '👎🏾', '👎🏿', '👏🏻', '👏🏼', '👏🏽', '👏🏾', '👏🏿', '👐🏻', '👐🏼', '👐🏽', '👐🏾', '👐🏿', '👦🏻', '👦🏼', '👦🏽', '👦🏾', '👦🏿', '👧🏻', '👧🏼', '👧🏽', '👧🏾', '👧🏿', '👨🏻', '👨🏼', '👨🏽', '👨🏾', '👨🏿', '👩🏻', '👩🏼', '👩🏽', '👩🏾', '👩🏿', '👫🏻', '👫🏼', '👫🏽', '👫🏾', '👫🏿', '👬🏻', '👬🏼', '👬🏽', '👬🏾', '👬🏿', '👭🏻', '👭🏼', '👭🏽', '👭🏾', '👭🏿', '👮🏻', '👮🏼', '👮🏽', '👮🏾', '👮🏿', '👰🏻', '👰🏼', '👰🏽', '👰🏾', '👰🏿', '👱🏻', '👱🏼', '👱🏽', '👱🏾', '👱🏿', '👲🏻', '👲🏼', '👲🏽', '👲🏾', '👲🏿', '👳🏻', '👳🏼', '👳🏽', '👳🏾', '👳🏿', '👴🏻', '👴🏼', '👴🏽', '👴🏾', '👴🏿', '👵🏻', '👵🏼', '👵🏽', '👵🏾', '👵🏿', '👶🏻', '👶🏼', '👶🏽', '👶🏾', '👶🏿', '👷🏻', '👷🏼', '👷🏽', '👷🏾', '👷🏿', '👸🏻', '👸🏼', '👸🏽', '👸🏾', '👸🏿', '👼🏻', '👼🏼', '👼🏽', '👼🏾', '👼🏿', '💁🏻', '💁🏼', '💁🏽', '💁🏾', '💁🏿', '💂🏻', '💂🏼', '💂🏽', '💂🏾', '💂🏿', '💃🏻', '💃🏼', '💃🏽', '💃🏾', '💃🏿', '💅🏻', '💅🏼', '💅🏽', '💅🏾', '💅🏿', '💆🏻', '💆🏼', '💆🏽', '💆🏾', '💆🏿', '💇🏻', '💇🏼', '💇🏽', '💇🏾', '💇🏿', '💪🏻', '💪🏼', '💪🏽', '💪🏾', '💪🏿', '🕴🏻', '🕴🏼', '🕴🏽', '🕴🏾', '🕴🏿', '🕵🏻', '🕵🏼', '🕵🏽', '🕵🏾', '🕵🏿', '🕺🏻', '🕺🏼', '🕺🏽', '🕺🏾', '🕺🏿', '🖐🏻', '🖐🏼', '🖐🏽', '🖐🏾', '🖐🏿', '🖕🏻', '🖕🏼', '🖕🏽', '🖕🏾', '🖕🏿', '🖖🏻', '🖖🏼', '🖖🏽', '🖖🏾', '🖖🏿', '🙅🏻', '🙅🏼', '🙅🏽', '🙅🏾', '🙅🏿', '🙆🏻', '🙆🏼', '🙆🏽', '🙆🏾', '🙆🏿', '🙇🏻', '🙇🏼', '🙇🏽', '🙇🏾', '🙇🏿', '🙋🏻', '🙋🏼', '🙋🏽', '🙋🏾', '🙋🏿', '🙌🏻', '🙌🏼', '🙌🏽', '🙌🏾', '🙌🏿', '🙍🏻', '🙍🏼', '🙍🏽', '🙍🏾', '🙍🏿', '🙎🏻', '🙎🏼', '🙎🏽', '🙎🏾', '🙎🏿', '🙏🏻', '🙏🏼', '🙏🏽', '🙏🏾', '🙏🏿', '🚣🏻', '🚣🏼', '🚣🏽', '🚣🏾', '🚣🏿', '🚴🏻', '🚴🏼', '🚴🏽', '🚴🏾', '🚴🏿', '🚵🏻', '🚵🏼', '🚵🏽', '🚵🏾', '🚵🏿', '🚶🏻', '🚶🏼', '🚶🏽', '🚶🏾', '🚶🏿', '🛀🏻', '🛀🏼', '🛀🏽', '🛀🏾', '🛀🏿', '🛌🏻', '🛌🏼', '🛌🏽', '🛌🏾', '🛌🏿', '🤌🏻', '🤌🏼', '🤌🏽', '🤌🏾', '🤌🏿', '🤏🏻', '🤏🏼', '🤏🏽', '🤏🏾', '🤏🏿', '🤘🏻', '🤘🏼', '🤘🏽', '🤘🏾', '🤘🏿', '🤙🏻', '🤙🏼', '🤙🏽', '🤙🏾', '🤙🏿', '🤚🏻', '🤚🏼', '🤚🏽', '🤚🏾', '🤚🏿', '🤛🏻', '🤛🏼', '🤛🏽', '🤛🏾', '🤛🏿', '🤜🏻', '🤜🏼', '🤜🏽', '🤜🏾', '🤜🏿', '🤞🏻', '🤞🏼', '🤞🏽', '🤞🏾', '🤞🏿', '🤟🏻', '🤟🏼', '🤟🏽', '🤟🏾', '🤟🏿', '🤦🏻', '🤦🏼', '🤦🏽', '🤦🏾', '🤦🏿', '🤰🏻', '🤰🏼', '🤰🏽', '🤰🏾', '🤰🏿', '🤱🏻', '🤱🏼', '🤱🏽', '🤱🏾', '🤱🏿', '🤲🏻', '🤲🏼', '🤲🏽', '🤲🏾', '🤲🏿', '🤳🏻', '🤳🏼', '🤳🏽', '🤳🏾', '🤳🏿', '🤴🏻', '🤴🏼', '🤴🏽', '🤴🏾', '🤴🏿', '🤵🏻', '🤵🏼', '🤵🏽', '🤵🏾', '🤵🏿', '🤶🏻', '🤶🏼', '🤶🏽', '🤶🏾', '🤶🏿', '🤷🏻', '🤷🏼', '🤷🏽', '🤷🏾', '🤷🏿', '🤸🏻', '🤸🏼', '🤸🏽', '🤸🏾', '🤸🏿', '🤹🏻', '🤹🏼', '🤹🏽', '🤹🏾', '🤹🏿', '🤽🏻', '🤽🏼', '🤽🏽', '🤽🏾', '🤽🏿', '🤾🏻', '🤾🏼', '🤾🏽', '🤾🏾', '🤾🏿', '🥷🏻', '🥷🏼', '🥷🏽', '🥷🏾', '🥷🏿', '🦵🏻', '🦵🏼', '🦵🏽', '🦵🏾', '🦵🏿', '🦶🏻', '🦶🏼', '🦶🏽', '🦶🏾', '🦶🏿', '🦸🏻', '🦸🏼', '🦸🏽', '🦸🏾', '🦸🏿', '🦹🏻', '🦹🏼', '🦹🏽', '🦹🏾', '🦹🏿', '🦻🏻', '🦻🏼', '🦻🏽', '🦻🏾', '🦻🏿', '🧍🏻', '🧍🏼', '🧍🏽', '🧍🏾', '🧍🏿', '🧎🏻', '🧎🏼', '🧎🏽', '🧎🏾', '🧎🏿', '🧏🏻', '🧏🏼', '🧏🏽', '🧏🏾', '🧏🏿', '🧑🏻', '🧑🏼', '🧑🏽', '🧑🏾', '🧑🏿', '🧒🏻', '🧒🏼', '🧒🏽', '🧒🏾', '🧒🏿', '🧓🏻', '🧓🏼', '🧓🏽', '🧓🏾', '🧓🏿', '🧔🏻', '🧔🏼', '🧔🏽', '🧔🏾', '🧔🏿', '🧕🏻', '🧕🏼', '🧕🏽', '🧕🏾', '🧕🏿', '🧖🏻', '🧖🏼', '🧖🏽', '🧖🏾', '🧖🏿', '🧗🏻', '🧗🏼', '🧗🏽', '🧗🏾', '🧗🏿', '🧘🏻', '🧘🏼', '🧘🏽', '🧘🏾', '🧘🏿', '🧙🏻', '🧙🏼', '🧙🏽', '🧙🏾', '🧙🏿', '🧚🏻', '🧚🏼', '🧚🏽', '🧚🏾', '🧚🏿', '🧛🏻', '🧛🏼', '🧛🏽', '🧛🏾', '🧛🏿', '🧜🏻', '🧜🏼', '🧜🏽', '🧜🏾', '🧜🏿', '🧝🏻', '🧝🏼', '🧝🏽', '🧝🏾', '🧝🏿', '☝🏻', '☝🏼', '☝🏽', '☝🏾', '☝🏿', '⛷🏻', '⛷🏼', '⛷🏽', '⛷🏾', '⛷🏿', '⛹🏻', '⛹🏼', '⛹🏽', '⛹🏾', '⛹🏿', '✊🏻', '✊🏼', '✊🏽', '✊🏾', '✊🏿', '✋🏻', '✋🏼', '✋🏽', '✋🏾', '✋🏿', '✌🏻', '✌🏼', '✌🏽', '✌🏾', '✌🏿', '✍🏻', '✍🏼', '✍🏽', '✍🏾', '✍🏿', '#⃣', '*⃣', '0⃣', '1⃣', '2⃣', '3⃣', '4⃣', '5⃣', '6⃣', '7⃣', '8⃣', '9⃣', '🀄', '🃏', '🅰', '🅱', '🅾', '🅿', '🆎', '🆑', '🆒', '🆓', '🆔', '🆕', '🆖', '🆗', '🆘', '🆙', '🆚', '🇦', '🇧', '🇨', '🇩', '🇪', '🇫', '🇬', '🇭', '🇮', '🇯', '🇰', '🇱', '🇲', '🇳', '🇴', '🇵', '🇶', '🇷', '🇸', '🇹', '🇺', '🇻', '🇼', '🇽', '🇾', '🇿', '🈁', '🈂', '🈚', '🈯', '🈲', '🈳', '🈴', '🈵', '🈶', '🈷', '🈸', '🈹', '🈺', '🉐', '🉑', '🌀', '🌁', '🌂', '🌃', '🌄', '🌅', '🌆', '🌇', '🌈', '🌉', '🌊', '🌋', '🌌', '🌍', '🌎', '🌏', '🌐', '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘', '🌙', '🌚', '🌛', '🌜', '🌝', '🌞', '🌟', '🌠', '🌡', '🌤', '🌥', '🌦', '🌧', '🌨', '🌩', '🌪', '🌫', '🌬', '🌭', '🌮', '🌯', '🌰', '🌱', '🌲', '🌳', '🌴', '🌵', '🌶', '🌷', '🌸', '🌹', '🌺', '🌻', '🌼', '🌽', '🌾', '🌿', '🍀', '🍁', '🍂', '🍃', '🍄', '🍅', '🍆', '🍇', '🍈', '🍉', '🍊', '🍋', '🍌', '🍍', '🍎', '🍏', '🍐', '🍑', '🍒', '🍓', '🍔', '🍕', '🍖', '🍗', '🍘', '🍙', '🍚', '🍛', '🍜', '🍝', '🍞', '🍟', '🍠', '🍡', '🍢', '🍣', '🍤', '🍥', '🍦', '🍧', '🍨', '🍩', '🍪', '🍫', '🍬', '🍭', '🍮', '🍯', '🍰', '🍱', '🍲', '🍳', '🍴', '🍵', '🍶', '🍷', '🍸', '🍹', '🍺', '🍻', '🍼', '🍽', '🍾', '🍿', '🎀', '🎁', '🎂', '🎃', '🎄', '🎅', '🎆', '🎇', '🎈', '🎉', '🎊', '🎋', '🎌', '🎍', '🎎', '🎏', '🎐', '🎑', '🎒', '🎓', '🎖', '🎗', '🎙', '🎚', '🎛', '🎞', '🎟', '🎠', '🎡', '🎢', '🎣', '🎤', '🎥', '🎦', '🎧', '🎨', '🎩', '🎪', '🎫', '🎬', '🎭', '🎮', '🎯', '🎰', '🎱', '🎲', '🎳', '🎴', '🎵', '🎶', '🎷', '🎸', '🎹', '🎺', '🎻', '🎼', '🎽', '🎾', '🎿', '🏀', '🏁', '🏂', '🏃', '🏄', '🏅', '🏆', '🏇', '🏈', '🏉', '🏊', '🏋', '🏌', '🏍', '🏎', '🏏', '🏐', '🏑', '🏒', '🏓', '🏔', '🏕', '🏖', '🏗', '🏘', '🏙', '🏚', '🏛', '🏜', '🏝', '🏞', '🏟', '🏠', '🏡', '🏢', '🏣', '🏤', '🏥', '🏦', '🏧', '🏨', '🏩', '🏪', '🏫', '🏬', '🏭', '🏮', '🏯', '🏰', '🏳', '🏴', '🏵', '🏷', '🏸', '🏹', '🏺', '🏻', '🏼', '🏽', '🏾', '🏿', '🐀', '🐁', '🐂', '🐃', '🐄', '🐅', '🐆', '🐇', '🐈', '🐉', '🐊', '🐋', '🐌', '🐍', '🐎', '🐏', '🐐', '🐑', '🐒', '🐓', '🐔', '🐕', '🐖', '🐗', '🐘', '🐙', '🐚', '🐛', '🐜', '🐝', '🐞', '🐟', '🐠', '🐡', '🐢', '🐣', '🐤', '🐥', '🐦', '🐧', '🐨', '🐩', '🐪', '🐫', '🐬', '🐭', '🐮', '🐯', '🐰', '🐱', '🐲', '🐳', '🐴', '🐵', '🐶', '🐷', '🐸', '🐹', '🐺', '🐻', '🐼', '🐽', '🐾', '🐿', '👀', '👁', '👂', '👃', '👄', '👅', '👆', '👇', '👈', '👉', '👊', '👋', '👌', '👍', '👎', '👏', '👐', '👑', '👒', '👓', '👔', '👕', '👖', '👗', '👘', '👙', '👚', '👛', '👜', '👝', '👞', '👟', '👠', '👡', '👢', '👣', '👤', '👥', '👦', '👧', '👨', '👩', '👪', '👫', '👬', '👭', '👮', '👯', '👰', '👱', '👲', '👳', '👴', '👵', '👶', '👷', '👸', '👹', '👺', '👻', '👼', '👽', '👾', '👿', '💀', '💁', '💂', '💃', '💄', '💅', '💆', '💇', '💈', '💉', '💊', '💋', '💌', '💍', '💎', '💏', '💐', '💑', '💒', '💓', '💔', '💕', '💖', '💗', '💘', '💙', '💚', '💛', '💜', '💝', '💞', '💟', '💠', '💡', '💢', '💣', '💤', '💥', '💦', '💧', '💨', '💩', '💪', '💫', '💬', '💭', '💮', '💯', '💰', '💱', '💲', '💳', '💴', '💵', '💶', '💷', '💸', '💹', '💺', '💻', '💼', '💽', '💾', '💿', '📀', '📁', '📂', '📃', '📄', '📅', '📆', '📇', '📈', '📉', '📊', '📋', '📌', '📍', '📎', '📏', '📐', '📑', '📒', '📓', '📔', '📕', '📖', '📗', '📘', '📙', '📚', '📛', '📜', '📝', '📞', '📟', '📠', '📡', '📢', '📣', '📤', '📥', '📦', '📧', '📨', '📩', '📪', '📫', '📬', '📭', '📮', '📯', '📰', '📱', '📲', '📳', '📴', '📵', '📶', '📷', '📸', '📹', '📺', '📻', '📼', '📽', '📿', '🔀', '🔁', '🔂', '🔃', '🔄', '🔅', '🔆', '🔇', '🔈', '🔉', '🔊', '🔋', '🔌', '🔍', '🔎', '🔏', '🔐', '🔑', '🔒', '🔓', '🔔', '🔕', '🔖', '🔗', '🔘', '🔙', '🔚', '🔛', '🔜', '🔝', '🔞', '🔟', '🔠', '🔡', '🔢', '🔣', '🔤', '🔥', '🔦', '🔧', '🔨', '🔩', '🔪', '🔫', '🔬', '🔭', '🔮', '🔯', '🔰', '🔱', '🔲', '🔳', '🔴', '🔵', '🔶', '🔷', '🔸', '🔹', '🔺', '🔻', '🔼', '🔽', '🕉', '🕊', '🕋', '🕌', '🕍', '🕎', '🕐', '🕑', '🕒', '🕓', '🕔', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚', '🕛', '🕜', '🕝', '🕞', '🕟', '🕠', '🕡', '🕢', '🕣', '🕤', '🕥', '🕦', '🕧', '🕯', '🕰', '🕳', '🕴', '🕵', '🕶', '🕷', '🕸', '🕹', '🕺', '🖇', '🖊', '🖋', '🖌', '🖍', '🖐', '🖕', '🖖', '🖤', '🖥', '🖨', '🖱', '🖲', '🖼', '🗂', '🗃', '🗄', '🗑', '🗒', '🗓', '🗜', '🗝', '🗞', '🗡', '🗣', '🗨', '🗯', '🗳', '🗺', '🗻', '🗼', '🗽', '🗾', '🗿', '😀', '😁', '😂', '😃', '😄', '😅', '😆', '😇', '😈', '😉', '😊', '😋', '😌', '😍', '😎', '😏', '😐', '😑', '😒', '😓', '😔', '😕', '😖', '😗', '😘', '😙', '😚', '😛', '😜', '😝', '😞', '😟', '😠', '😡', '😢', '😣', '😤', '😥', '😦', '😧', '😨', '😩', '😪', '😫', '😬', '😭', '😮', '😯', '😰', '😱', '😲', '😳', '😴', '😵', '😶', '😷', '😸', '😹', '😺', '😻', '😼', '😽', '😾', '😿', '🙀', '🙁', '🙂', '🙃', '🙄', '🙅', '🙆', '🙇', '🙈', '🙉', '🙊', '🙋', '🙌', '🙍', '🙎', '🙏', '🚀', '🚁', '🚂', '🚃', '🚄', '🚅', '🚆', '🚇', '🚈', '🚉', '🚊', '🚋', '🚌', '🚍', '🚎', '🚏', '🚐', '🚑', '🚒', '🚓', '🚔', '🚕', '🚖', '🚗', '🚘', '🚙', '🚚', '🚛', '🚜', '🚝', '🚞', '🚟', '🚠', '🚡', '🚢', '🚣', '🚤', '🚥', '🚦', '🚧', '🚨', '🚩', '🚪', '🚫', '🚬', '🚭', '🚮', '🚯', '🚰', '🚱', '🚲', '🚳', '🚴', '🚵', '🚶', '🚷', '🚸', '🚹', '🚺', '🚻', '🚼', '🚽', '🚾', '🚿', '🛀', '🛁', '🛂', '🛃', '🛄', '🛅', '🛋', '🛌', '🛍', '🛎', '🛏', '🛐', '🛑', '🛒', '🛕', '🛖', '🛗', '🛠', '🛡', '🛢', '🛣', '🛤', '🛥', '🛩', '🛫', '🛬', '🛰', '🛳', '🛴', '🛵', '🛶', '🛷', '🛸', '🛹', '🛺', '🛻', '🛼', '🟠', '🟡', '🟢', '🟣', '🟤', '🟥', '🟦', '🟧', '🟨', '🟩', '🟪', '🟫', '🤌', '🤍', '🤎', '🤏', '🤐', '🤑', '🤒', '🤓', '🤔', '🤕', '🤖', '🤗', '🤘', '🤙', '🤚', '🤛', '🤜', '🤝', '🤞', '🤟', '🤠', '🤡', '🤢', '🤣', '🤤', '🤥', '🤦', '🤧', '🤨', '🤩', '🤪', '🤫', '🤬', '🤭', '🤮', '🤯', '🤰', '🤱', '🤲', '🤳', '🤴', '🤵', '🤶', '🤷', '🤸', '🤹', '🤺', '🤼', '🤽', '🤾', '🤿', '🥀', '🥁', '🥂', '🥃', '🥄', '🥅', '🥇', '🥈', '🥉', '🥊', '🥋', '🥌', '🥍', '🥎', '🥏', '🥐', '🥑', '🥒', '🥓', '🥔', '🥕', '🥖', '🥗', '🥘', '🥙', '🥚', '🥛', '🥜', '🥝', '🥞', '🥟', '🥠', '🥡', '🥢', '🥣', '🥤', '🥥', '🥦', '🥧', '🥨', '🥩', '🥪', '🥫', '🥬', '🥭', '🥮', '🥯', '🥰', '🥱', '🥲', '🥳', '🥴', '🥵', '🥶', '🥷', '🥸', '🥺', '🥻', '🥼', '🥽', '🥾', '🥿', '🦀', '🦁', '🦂', '🦃', '🦄', '🦅', '🦆', '🦇', '🦈', '🦉', '🦊', '🦋', '🦌', '🦍', '🦎', '🦏', '🦐', '🦑', '🦒', '🦓', '🦔', '🦕', '🦖', '🦗', '🦘', '🦙', '🦚', '🦛', '🦜', '🦝', '🦞', '🦟', '🦠', '🦡', '🦢', '🦣', '🦤', '🦥', '🦦', '🦧', '🦨', '🦩', '🦪', '🦫', '🦬', '🦭', '🦮', '🦯', '🦰', '🦱', '🦲', '🦳', '🦴', '🦵', '🦶', '🦷', '🦸', '🦹', '🦺', '🦻', '🦼', '🦽', '🦾', '🦿', '🧀', '🧁', '🧂', '🧃', '🧄', '🧅', '🧆', '🧇', '🧈', '🧉', '🧊', '🧋', '🧍', '🧎', '🧏', '🧐', '🧑', '🧒', '🧓', '🧔', '🧕', '🧖', '🧗', '🧘', '🧙', '🧚', '🧛', '🧜', '🧝', '🧞', '🧟', '🧠', '🧡', '🧢', '🧣', '🧤', '🧥', '🧦', '🧧', '🧨', '🧩', '🧪', '🧫', '🧬', '🧭', '🧮', '🧯', '🧰', '🧱', '🧲', '🧳', '🧴', '🧵', '🧶', '🧷', '🧸', '🧹', '🧺', '🧻', '🧼', '🧽', '🧾', '🧿', '🩰', '🩱', '🩲', '🩳', '🩴', '🩸', '🩹', '🩺', '🪀', '🪁', '🪂', '🪃', '🪄', '🪅', '🪆', '🪐', '🪑', '🪒', '🪓', '🪔', '🪕', '🪖', '🪗', '🪘', '🪙', '🪚', '🪛', '🪜', '🪝', '🪞', '🪟', '🪠', '🪡', '🪢', '🪣', '🪤', '🪥', '🪦', '🪧', '🪨', '🪰', '🪱', '🪲', '🪳', '🪴', '🪵', '🪶', '🫀', '🫁', '🫂', '🫐', '🫑', '🫒', '🫓', '🫔', '🫕', '🫖', '‼', '⁉', '™', 'ℹ', '↔', '↕', '↖', '↗', '↘', '↙', '↩', '↪', '⌚', '⌛', '⌨', '⏏', '⏩', '⏪', '⏫', '⏬', '⏭', '⏮', '⏯', '⏰', '⏱', '⏲', '⏳', '⏸', '⏹', '⏺', 'Ⓜ', '▪', '▫', '▶', '◀', '◻', '◼', '◽', '◾', '☀', '☁', '☂', '☃', '☄', '☎', '☑', '☔', '☕', '☘', '☝', '☠', '☢', '☣', '☦', '☪', '☮', '☯', '☸', '☹', '☺', '♀', '♂', '♈', '♉', '♊', '♋', '♌', '♍', '♎', '♏', '♐', '♑', '♒', '♓', '♟', '♠', '♣', '♥', '♦', '♨', '♻', '♾', '♿', '⚒', '⚓', '⚔', '⚕', '⚖', '⚗', '⚙', '⚛', '⚜', '⚠', '⚡', '⚧', '⚪', '⚫', '⚰', '⚱', '⚽', '⚾', '⛄', '⛅', '⛈', '⛎', '⛏', '⛑', '⛓', '⛔', '⛩', '⛪', '⛰', '⛱', '⛲', '⛳', '⛴', '⛵', '⛷', '⛸', '⛹', '⛺', '⛽', '✂', '✅', '✈', '✉', '✊', '✋', '✌', '✍', '✏', '✒', '✔', '✖', '✝', '✡', '✨', '✳', '✴', '❄', '❇', '❌', '❎', '❓', '❔', '❕', '❗', '❣', '❤', '➕', '➖', '➗', '➡', '➰', '➿', '⤴', '⤵', '⬅', '⬆', '⬇', '⬛', '⬜', '⭐', '⭕', '〰', '〽', '㊗', '㊙', '' ); |
5754 $partials = array( '🀄', '🃏', '🅰', '🅱', '🅾', '🅿', '🆎', '🆑', '🆒', '🆓', '🆔', '🆕', '🆖', '🆗', '🆘', '🆙', '🆚', '🇦', '🇨', '🇩', '🇪', '🇫', '🇬', '🇮', '🇱', '🇲', '🇴', '🇶', '🇷', '🇸', '🇹', '🇺', '🇼', '🇽', '🇿', '🇧', '🇭', '🇯', '🇳', '🇻', '🇾', '🇰', '🇵', '🈁', '🈂', '🈚', '🈯', '🈲', '🈳', '🈴', '🈵', '🈶', '🈷', '🈸', '🈹', '🈺', '🉐', '🉑', '🌀', '🌁', '🌂', '🌃', '🌄', '🌅', '🌆', '🌇', '🌈', '🌉', '🌊', '🌋', '🌌', '🌍', '🌎', '🌏', '🌐', '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘', '🌙', '🌚', '🌛', '🌜', '🌝', '🌞', '🌟', '🌠', '🌡', '🌤', '🌥', '🌦', '🌧', '🌨', '🌩', '🌪', '🌫', '🌬', '🌭', '🌮', '🌯', '🌰', '🌱', '🌲', '🌳', '🌴', '🌵', '🌶', '🌷', '🌸', '🌹', '🌺', '🌻', '🌼', '🌽', '🌾', '🌿', '🍀', '🍁', '🍂', '🍃', '🍄', '🍅', '🍆', '🍇', '🍈', '🍉', '🍊', '🍋', '🍌', '🍍', '🍎', '🍏', '🍐', '🍑', '🍒', '🍓', '🍔', '🍕', '🍖', '🍗', '🍘', '🍙', '🍚', '🍛', '🍜', '🍝', '🍞', '🍟', '🍠', '🍡', '🍢', '🍣', '🍤', '🍥', '🍦', '🍧', '🍨', '🍩', '🍪', '🍫', '🍬', '🍭', '🍮', '🍯', '🍰', '🍱', '🍲', '🍳', '🍴', '🍵', '🍶', '🍷', '🍸', '🍹', '🍺', '🍻', '🍼', '🍽', '🍾', '🍿', '🎀', '🎁', '🎂', '🎃', '🎄', '🎅', '🏻', '🏼', '🏽', '🏾', '🏿', '🎆', '🎇', '🎈', '🎉', '🎊', '🎋', '🎌', '🎍', '🎎', '🎏', '🎐', '🎑', '🎒', '🎓', '🎖', '🎗', '🎙', '🎚', '🎛', '🎞', '🎟', '🎠', '🎡', '🎢', '🎣', '🎤', '🎥', '🎦', '🎧', '🎨', '🎩', '🎪', '🎫', '🎬', '🎭', '🎮', '🎯', '🎰', '🎱', '🎲', '🎳', '🎴', '🎵', '🎶', '🎷', '🎸', '🎹', '🎺', '🎻', '🎼', '🎽', '🎾', '🎿', '🏀', '🏁', '🏂', '🏃', '‍', '♀', '️', '♂', '🏄', '🏅', '🏆', '🏇', '🏈', '🏉', '🏊', '🏋', '🏌', '🏍', '🏎', '🏏', '🏐', '🏑', '🏒', '🏓', '🏔', '🏕', '🏖', '🏗', '🏘', '🏙', '🏚', '🏛', '🏜', '🏝', '🏞', '🏟', '🏠', '🏡', '🏢', '🏣', '🏤', '🏥', '🏦', '🏧', '🏨', '🏩', '🏪', '🏫', '🏬', '🏭', '🏮', '🏯', '🏰', '🏳', '🏴', '☠', '󠁧', '󠁢', '󠁥', '󠁮', '󠁿', '󠁳', '󠁣', '󠁴', '󠁷', '󠁬', '🏵', '🏷', '🏸', '🏹', '🏺', '🐀', '🐁', '🐂', '🐃', '🐄', '🐅', '🐆', '🐇', '🐈', '🐉', '🐊', '🐋', '🐌', '🐍', '🐎', '🐏', '🐐', '🐑', '🐒', '🐓', '🐔', '🐕', '🦺', '🐖', '🐗', '🐘', '🐙', '🐚', '🐛', '🐜', '🐝', '🐞', '🐟', '🐠', '🐡', '🐢', '🐣', '🐤', '🐥', '🐦', '🐧', '🐨', '🐩', '🐪', '🐫', '🐬', '🐭', '🐮', '🐯', '🐰', '🐱', '🐲', '🐳', '🐴', '🐵', '🐶', '🐷', '🐸', '🐹', '🐺', '🐻', '🐼', '🐽', '🐾', '🐿', '👀', '👁', '🗨', '👂', '👃', '👄', '👅', '👆', '👇', '👈', '👉', '👊', '👋', '👌', '👍', '👎', '👏', '👐', '👑', '👒', '👓', '👔', '👕', '👖', '👗', '👘', '👙', '👚', '👛', '👜', '👝', '👞', '👟', '👠', '👡', '👢', '👣', '👤', '👥', '👦', '👧', '👨', '💻', '💼', '🔧', '🔬', '🚀', '🚒', '🦯', '🦰', '🦱', '🦲', '🦳', '🦼', '🦽', '⚕', '⚖', '✈', '🤝', '👩', '❤', '💋', '👪', '👫', '👬', '👭', '👮', '👯', '👰', '👱', '👲', '👳', '👴', '👵', '👶', '👷', '👸', '👹', '👺', '👻', '👼', '👽', '👾', '👿', '💀', '💁', '💂', '💃', '💄', '💅', '💆', '💇', '💈', '💉', '💊', '💌', '💍', '💎', '💏', '💐', '💑', '💒', '💓', '💔', '💕', '💖', '💗', '💘', '💙', '💚', '💛', '💜', '💝', '💞', '💟', '💠', '💡', '💢', '💣', '💤', '💥', '💦', '💧', '💨', '💩', '💪', '💫', '💬', '💭', '💮', '💯', '💰', '💱', '💲', '💳', '💴', '💵', '💶', '💷', '💸', '💹', '💺', '💽', '💾', '💿', '📀', '📁', '📂', '📃', '📄', '📅', '📆', '📇', '📈', '📉', '📊', '📋', '📌', '📍', '📎', '📏', '📐', '📑', '📒', '📓', '📔', '📕', '📖', '📗', '📘', '📙', '📚', '📛', '📜', '📝', '📞', '📟', '📠', '📡', '📢', '📣', '📤', '📥', '📦', '📧', '📨', '📩', '📪', '📫', '📬', '📭', '📮', '📯', '📰', '📱', '📲', '📳', '📴', '📵', '📶', '📷', '📸', '📹', '📺', '📻', '📼', '📽', '📿', '🔀', '🔁', '🔂', '🔃', '🔄', '🔅', '🔆', '🔇', '🔈', '🔉', '🔊', '🔋', '🔌', '🔍', '🔎', '🔏', '🔐', '🔑', '🔒', '🔓', '🔔', '🔕', '🔖', '🔗', '🔘', '🔙', '🔚', '🔛', '🔜', '🔝', '🔞', '🔟', '🔠', '🔡', '🔢', '🔣', '🔤', '🔥', '🔦', '🔨', '🔩', '🔪', '🔫', '🔭', '🔮', '🔯', '🔰', '🔱', '🔲', '🔳', '🔴', '🔵', '🔶', '🔷', '🔸', '🔹', '🔺', '🔻', '🔼', '🔽', '🕉', '🕊', '🕋', '🕌', '🕍', '🕎', '🕐', '🕑', '🕒', '🕓', '🕔', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚', '🕛', '🕜', '🕝', '🕞', '🕟', '🕠', '🕡', '🕢', '🕣', '🕤', '🕥', '🕦', '🕧', '🕯', '🕰', '🕳', '🕴', '🕵', '🕶', '🕷', '🕸', '🕹', '🕺', '🖇', '🖊', '🖋', '🖌', '🖍', '🖐', '🖕', '🖖', '🖤', '🖥', '🖨', '🖱', '🖲', '🖼', '🗂', '🗃', '🗄', '🗑', '🗒', '🗓', '🗜', '🗝', '🗞', '🗡', '🗣', '🗯', '🗳', '🗺', '🗻', '🗼', '🗽', '🗾', '🗿', '😀', '😁', '😂', '😃', '😄', '😅', '😆', '😇', '😈', '😉', '😊', '😋', '😌', '😍', '😎', '😏', '😐', '😑', '😒', '😓', '😔', '😕', '😖', '😗', '😘', '😙', '😚', '😛', '😜', '😝', '😞', '😟', '😠', '😡', '😢', '😣', '😤', '😥', '😦', '😧', '😨', '😩', '😪', '😫', '😬', '😭', '😮', '😯', '😰', '😱', '😲', '😳', '😴', '😵', '😶', '😷', '😸', '😹', '😺', '😻', '😼', '😽', '😾', '😿', '🙀', '🙁', '🙂', '🙃', '🙄', '🙅', '🙆', '🙇', '🙈', '🙉', '🙊', '🙋', '🙌', '🙍', '🙎', '🙏', '🚁', '🚂', '🚃', '🚄', '🚅', '🚆', '🚇', '🚈', '🚉', '🚊', '🚋', '🚌', '🚍', '🚎', '🚏', '🚐', '🚑', '🚓', '🚔', '🚕', '🚖', '🚗', '🚘', '🚙', '🚚', '🚛', '🚜', '🚝', '🚞', '🚟', '🚠', '🚡', '🚢', '🚣', '🚤', '🚥', '🚦', '🚧', '🚨', '🚩', '🚪', '🚫', '🚬', '🚭', '🚮', '🚯', '🚰', '🚱', '🚲', '🚳', '🚴', '🚵', '🚶', '🚷', '🚸', '🚹', '🚺', '🚻', '🚼', '🚽', '🚾', '🚿', '🛀', '🛁', '🛂', '🛃', '🛄', '🛅', '🛋', '🛌', '🛍', '🛎', '🛏', '🛐', '🛑', '🛒', '🛕', '🛠', '🛡', '🛢', '🛣', '🛤', '🛥', '🛩', '🛫', '🛬', '🛰', '🛳', '🛴', '🛵', '🛶', '🛷', '🛸', '🛹', '🛺', '🟠', '🟡', '🟢', '🟣', '🟤', '🟥', '🟦', '🟧', '🟨', '🟩', '🟪', '🟫', '🤍', '🤎', '🤏', '🤐', '🤑', '🤒', '🤓', '🤔', '🤕', '🤖', '🤗', '🤘', '🤙', '🤚', '🤛', '🤜', '🤞', '🤟', '🤠', '🤡', '🤢', '🤣', '🤤', '🤥', '🤦', '🤧', '🤨', '🤩', '🤪', '🤫', '🤬', '🤭', '🤮', '🤯', '🤰', '🤱', '🤲', '🤳', '🤴', '🤵', '🤶', '🤷', '🤸', '🤹', '🤺', '🤼', '🤽', '🤾', '🤿', '🥀', '🥁', '🥂', '🥃', '🥄', '🥅', '🥇', '🥈', '🥉', '🥊', '🥋', '🥌', '🥍', '🥎', '🥏', '🥐', '🥑', '🥒', '🥓', '🥔', '🥕', '🥖', '🥗', '🥘', '🥙', '🥚', '🥛', '🥜', '🥝', '🥞', '🥟', '🥠', '🥡', '🥢', '🥣', '🥤', '🥥', '🥦', '🥧', '🥨', '🥩', '🥪', '🥫', '🥬', '🥭', '🥮', '🥯', '🥰', '🥱', '🥳', '🥴', '🥵', '🥶', '🥺', '🥻', '🥼', '🥽', '🥾', '🥿', '🦀', '🦁', '🦂', '🦃', '🦄', '🦅', '🦆', '🦇', '🦈', '🦉', '🦊', '🦋', '🦌', '🦍', '🦎', '🦏', '🦐', '🦑', '🦒', '🦓', '🦔', '🦕', '🦖', '🦗', '🦘', '🦙', '🦚', '🦛', '🦜', '🦝', '🦞', '🦟', '🦠', '🦡', '🦢', '🦥', '🦦', '🦧', '🦨', '🦩', '🦪', '🦮', '🦴', '🦵', '🦶', '🦷', '🦸', '🦹', '🦻', '🦾', '🦿', '🧀', '🧁', '🧂', '🧃', '🧄', '🧅', '🧆', '🧇', '🧈', '🧉', '🧊', '🧍', '🧎', '🧏', '🧐', '🧑', '🧒', '🧓', '🧔', '🧕', '🧖', '🧗', '🧘', '🧙', '🧚', '🧛', '🧜', '🧝', '🧞', '🧟', '🧠', '🧡', '🧢', '🧣', '🧤', '🧥', '🧦', '🧧', '🧨', '🧩', '🧪', '🧫', '🧬', '🧭', '🧮', '🧯', '🧰', '🧱', '🧲', '🧳', '🧴', '🧵', '🧶', '🧷', '🧸', '🧹', '🧺', '🧻', '🧼', '🧽', '🧾', '🧿', '🩰', '🩱', '🩲', '🩳', '🩸', '🩹', '🩺', '🪀', '🪁', '🪂', '🪐', '🪑', '🪒', '🪓', '🪔', '🪕', '‼', '⁉', '™', 'ℹ', '↔', '↕', '↖', '↗', '↘', '↙', '↩', '↪', '⃣', '⌚', '⌛', '⌨', '⏏', '⏩', '⏪', '⏫', '⏬', '⏭', '⏮', '⏯', '⏰', '⏱', '⏲', '⏳', '⏸', '⏹', '⏺', 'Ⓜ', '▪', '▫', '▶', '◀', '◻', '◼', '◽', '◾', '☀', '☁', '☂', '☃', '☄', '☎', '☑', '☔', '☕', '☘', '☝', '☢', '☣', '☦', '☪', '☮', '☯', '☸', '☹', '☺', '♈', '♉', '♊', '♋', '♌', '♍', '♎', '♏', '♐', '♑', '♒', '♓', '♟', '♠', '♣', '♥', '♦', '♨', '♻', '♾', '♿', '⚒', '⚓', '⚔', '⚗', '⚙', '⚛', '⚜', '⚠', '⚡', '⚪', '⚫', '⚰', '⚱', '⚽', '⚾', '⛄', '⛅', '⛈', '⛎', '⛏', '⛑', '⛓', '⛔', '⛩', '⛪', '⛰', '⛱', '⛲', '⛳', '⛴', '⛵', '⛷', '⛸', '⛹', '⛺', '⛽', '✂', '✅', '✉', '✊', '✋', '✌', '✍', '✏', '✒', '✔', '✖', '✝', '✡', '✨', '✳', '✴', '❄', '❇', '❌', '❎', '❓', '❔', '❕', '❗', '❣', '➕', '➖', '➗', '➡', '➰', '➿', '⤴', '⤵', '⬅', '⬆', '⬇', '⬛', '⬜', '⭐', '⭕', '〰', '〽', '㊗', '㊙', '' ); |
5968 $partials = array( '🀄', '🃏', '🅰', '🅱', '🅾', '🅿', '🆎', '🆑', '🆒', '🆓', '🆔', '🆕', '🆖', '🆗', '🆘', '🆙', '🆚', '🇦', '🇨', '🇩', '🇪', '🇫', '🇬', '🇮', '🇱', '🇲', '🇴', '🇶', '🇷', '🇸', '🇹', '🇺', '🇼', '🇽', '🇿', '🇧', '🇭', '🇯', '🇳', '🇻', '🇾', '🇰', '🇵', '🈁', '🈂', '🈚', '🈯', '🈲', '🈳', '🈴', '🈵', '🈶', '🈷', '🈸', '🈹', '🈺', '🉐', '🉑', '🌀', '🌁', '🌂', '🌃', '🌄', '🌅', '🌆', '🌇', '🌈', '🌉', '🌊', '🌋', '🌌', '🌍', '🌎', '🌏', '🌐', '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘', '🌙', '🌚', '🌛', '🌜', '🌝', '🌞', '🌟', '🌠', '🌡', '🌤', '🌥', '🌦', '🌧', '🌨', '🌩', '🌪', '🌫', '🌬', '🌭', '🌮', '🌯', '🌰', '🌱', '🌲', '🌳', '🌴', '🌵', '🌶', '🌷', '🌸', '🌹', '🌺', '🌻', '🌼', '🌽', '🌾', '🌿', '🍀', '🍁', '🍂', '🍃', '🍄', '🍅', '🍆', '🍇', '🍈', '🍉', '🍊', '🍋', '🍌', '🍍', '🍎', '🍏', '🍐', '🍑', '🍒', '🍓', '🍔', '🍕', '🍖', '🍗', '🍘', '🍙', '🍚', '🍛', '🍜', '🍝', '🍞', '🍟', '🍠', '🍡', '🍢', '🍣', '🍤', '🍥', '🍦', '🍧', '🍨', '🍩', '🍪', '🍫', '🍬', '🍭', '🍮', '🍯', '🍰', '🍱', '🍲', '🍳', '🍴', '🍵', '🍶', '🍷', '🍸', '🍹', '🍺', '🍻', '🍼', '🍽', '🍾', '🍿', '🎀', '🎁', '🎂', '🎃', '🎄', '🎅', '🏻', '🏼', '🏽', '🏾', '🏿', '🎆', '🎇', '🎈', '🎉', '🎊', '🎋', '🎌', '🎍', '🎎', '🎏', '🎐', '🎑', '🎒', '🎓', '🎖', '🎗', '🎙', '🎚', '🎛', '🎞', '🎟', '🎠', '🎡', '🎢', '🎣', '🎤', '🎥', '🎦', '🎧', '🎨', '🎩', '🎪', '🎫', '🎬', '🎭', '🎮', '🎯', '🎰', '🎱', '🎲', '🎳', '🎴', '🎵', '🎶', '🎷', '🎸', '🎹', '🎺', '🎻', '🎼', '🎽', '🎾', '🎿', '🏀', '🏁', '🏂', '🏃', '‍', '♀', '️', '♂', '🏄', '🏅', '🏆', '🏇', '🏈', '🏉', '🏊', '🏋', '🏌', '🏍', '🏎', '🏏', '🏐', '🏑', '🏒', '🏓', '🏔', '🏕', '🏖', '🏗', '🏘', '🏙', '🏚', '🏛', '🏜', '🏝', '🏞', '🏟', '🏠', '🏡', '🏢', '🏣', '🏤', '🏥', '🏦', '🏧', '🏨', '🏩', '🏪', '🏫', '🏬', '🏭', '🏮', '🏯', '🏰', '🏳', '⚧', '🏴', '☠', '󠁧', '󠁢', '󠁥', '󠁮', '󠁿', '󠁳', '󠁣', '󠁴', '󠁷', '󠁬', '🏵', '🏷', '🏸', '🏹', '🏺', '🐀', '🐁', '🐂', '🐃', '🐄', '🐅', '🐆', '🐇', '🐈', '⬛', '🐉', '🐊', '🐋', '🐌', '🐍', '🐎', '🐏', '🐐', '🐑', '🐒', '🐓', '🐔', '🐕', '🦺', '🐖', '🐗', '🐘', '🐙', '🐚', '🐛', '🐜', '🐝', '🐞', '🐟', '🐠', '🐡', '🐢', '🐣', '🐤', '🐥', '🐦', '🐧', '🐨', '🐩', '🐪', '🐫', '🐬', '🐭', '🐮', '🐯', '🐰', '🐱', '🐲', '🐳', '🐴', '🐵', '🐶', '🐷', '🐸', '🐹', '🐺', '🐻', '❄', '🐼', '🐽', '🐾', '🐿', '👀', '👁', '🗨', '👂', '👃', '👄', '👅', '👆', '👇', '👈', '👉', '👊', '👋', '👌', '👍', '👎', '👏', '👐', '👑', '👒', '👓', '👔', '👕', '👖', '👗', '👘', '👙', '👚', '👛', '👜', '👝', '👞', '👟', '👠', '👡', '👢', '👣', '👤', '👥', '👦', '👧', '👨', '💻', '💼', '🔧', '🔬', '🚀', '🚒', '🤝', '🦯', '🦰', '🦱', '🦲', '🦳', '🦼', '🦽', '⚕', '⚖', '✈', '👩', '❤', '💋', '👪', '👫', '👬', '👭', '👮', '👯', '👰', '👱', '👲', '👳', '👴', '👵', '👶', '👷', '👸', '👹', '👺', '👻', '👼', '👽', '👾', '👿', '💀', '💁', '💂', '💃', '💄', '💅', '💆', '💇', '💈', '💉', '💊', '💌', '💍', '💎', '💏', '💐', '💑', '💒', '💓', '💔', '💕', '💖', '💗', '💘', '💙', '💚', '💛', '💜', '💝', '💞', '💟', '💠', '💡', '💢', '💣', '💤', '💥', '💦', '💧', '💨', '💩', '💪', '💫', '💬', '💭', '💮', '💯', '💰', '💱', '💲', '💳', '💴', '💵', '💶', '💷', '💸', '💹', '💺', '💽', '💾', '💿', '📀', '📁', '📂', '📃', '📄', '📅', '📆', '📇', '📈', '📉', '📊', '📋', '📌', '📍', '📎', '📏', '📐', '📑', '📒', '📓', '📔', '📕', '📖', '📗', '📘', '📙', '📚', '📛', '📜', '📝', '📞', '📟', '📠', '📡', '📢', '📣', '📤', '📥', '📦', '📧', '📨', '📩', '📪', '📫', '📬', '📭', '📮', '📯', '📰', '📱', '📲', '📳', '📴', '📵', '📶', '📷', '📸', '📹', '📺', '📻', '📼', '📽', '📿', '🔀', '🔁', '🔂', '🔃', '🔄', '🔅', '🔆', '🔇', '🔈', '🔉', '🔊', '🔋', '🔌', '🔍', '🔎', '🔏', '🔐', '🔑', '🔒', '🔓', '🔔', '🔕', '🔖', '🔗', '🔘', '🔙', '🔚', '🔛', '🔜', '🔝', '🔞', '🔟', '🔠', '🔡', '🔢', '🔣', '🔤', '🔥', '🔦', '🔨', '🔩', '🔪', '🔫', '🔭', '🔮', '🔯', '🔰', '🔱', '🔲', '🔳', '🔴', '🔵', '🔶', '🔷', '🔸', '🔹', '🔺', '🔻', '🔼', '🔽', '🕉', '🕊', '🕋', '🕌', '🕍', '🕎', '🕐', '🕑', '🕒', '🕓', '🕔', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚', '🕛', '🕜', '🕝', '🕞', '🕟', '🕠', '🕡', '🕢', '🕣', '🕤', '🕥', '🕦', '🕧', '🕯', '🕰', '🕳', '🕴', '🕵', '🕶', '🕷', '🕸', '🕹', '🕺', '🖇', '🖊', '🖋', '🖌', '🖍', '🖐', '🖕', '🖖', '🖤', '🖥', '🖨', '🖱', '🖲', '🖼', '🗂', '🗃', '🗄', '🗑', '🗒', '🗓', '🗜', '🗝', '🗞', '🗡', '🗣', '🗯', '🗳', '🗺', '🗻', '🗼', '🗽', '🗾', '🗿', '😀', '😁', '😂', '😃', '😄', '😅', '😆', '😇', '😈', '😉', '😊', '😋', '😌', '😍', '😎', '😏', '😐', '😑', '😒', '😓', '😔', '😕', '😖', '😗', '😘', '😙', '😚', '😛', '😜', '😝', '😞', '😟', '😠', '😡', '😢', '😣', '😤', '😥', '😦', '😧', '😨', '😩', '😪', '😫', '😬', '😭', '😮', '😯', '😰', '😱', '😲', '😳', '😴', '😵', '😶', '😷', '😸', '😹', '😺', '😻', '😼', '😽', '😾', '😿', '🙀', '🙁', '🙂', '🙃', '🙄', '🙅', '🙆', '🙇', '🙈', '🙉', '🙊', '🙋', '🙌', '🙍', '🙎', '🙏', '🚁', '🚂', '🚃', '🚄', '🚅', '🚆', '🚇', '🚈', '🚉', '🚊', '🚋', '🚌', '🚍', '🚎', '🚏', '🚐', '🚑', '🚓', '🚔', '🚕', '🚖', '🚗', '🚘', '🚙', '🚚', '🚛', '🚜', '🚝', '🚞', '🚟', '🚠', '🚡', '🚢', '🚣', '🚤', '🚥', '🚦', '🚧', '🚨', '🚩', '🚪', '🚫', '🚬', '🚭', '🚮', '🚯', '🚰', '🚱', '🚲', '🚳', '🚴', '🚵', '🚶', '🚷', '🚸', '🚹', '🚺', '🚻', '🚼', '🚽', '🚾', '🚿', '🛀', '🛁', '🛂', '🛃', '🛄', '🛅', '🛋', '🛌', '🛍', '🛎', '🛏', '🛐', '🛑', '🛒', '🛕', '🛖', '🛗', '🛠', '🛡', '🛢', '🛣', '🛤', '🛥', '🛩', '🛫', '🛬', '🛰', '🛳', '🛴', '🛵', '🛶', '🛷', '🛸', '🛹', '🛺', '🛻', '🛼', '🟠', '🟡', '🟢', '🟣', '🟤', '🟥', '🟦', '🟧', '🟨', '🟩', '🟪', '🟫', '🤌', '🤍', '🤎', '🤏', '🤐', '🤑', '🤒', '🤓', '🤔', '🤕', '🤖', '🤗', '🤘', '🤙', '🤚', '🤛', '🤜', '🤞', '🤟', '🤠', '🤡', '🤢', '🤣', '🤤', '🤥', '🤦', '🤧', '🤨', '🤩', '🤪', '🤫', '🤬', '🤭', '🤮', '🤯', '🤰', '🤱', '🤲', '🤳', '🤴', '🤵', '🤶', '🤷', '🤸', '🤹', '🤺', '🤼', '🤽', '🤾', '🤿', '🥀', '🥁', '🥂', '🥃', '🥄', '🥅', '🥇', '🥈', '🥉', '🥊', '🥋', '🥌', '🥍', '🥎', '🥏', '🥐', '🥑', '🥒', '🥓', '🥔', '🥕', '🥖', '🥗', '🥘', '🥙', '🥚', '🥛', '🥜', '🥝', '🥞', '🥟', '🥠', '🥡', '🥢', '🥣', '🥤', '🥥', '🥦', '🥧', '🥨', '🥩', '🥪', '🥫', '🥬', '🥭', '🥮', '🥯', '🥰', '🥱', '🥲', '🥳', '🥴', '🥵', '🥶', '🥷', '🥸', '🥺', '🥻', '🥼', '🥽', '🥾', '🥿', '🦀', '🦁', '🦂', '🦃', '🦄', '🦅', '🦆', '🦇', '🦈', '🦉', '🦊', '🦋', '🦌', '🦍', '🦎', '🦏', '🦐', '🦑', '🦒', '🦓', '🦔', '🦕', '🦖', '🦗', '🦘', '🦙', '🦚', '🦛', '🦜', '🦝', '🦞', '🦟', '🦠', '🦡', '🦢', '🦣', '🦤', '🦥', '🦦', '🦧', '🦨', '🦩', '🦪', '🦫', '🦬', '🦭', '🦮', '🦴', '🦵', '🦶', '🦷', '🦸', '🦹', '🦻', '🦾', '🦿', '🧀', '🧁', '🧂', '🧃', '🧄', '🧅', '🧆', '🧇', '🧈', '🧉', '🧊', '🧋', '🧍', '🧎', '🧏', '🧐', '🧑', '🧒', '🧓', '🧔', '🧕', '🧖', '🧗', '🧘', '🧙', '🧚', '🧛', '🧜', '🧝', '🧞', '🧟', '🧠', '🧡', '🧢', '🧣', '🧤', '🧥', '🧦', '🧧', '🧨', '🧩', '🧪', '🧫', '🧬', '🧭', '🧮', '🧯', '🧰', '🧱', '🧲', '🧳', '🧴', '🧵', '🧶', '🧷', '🧸', '🧹', '🧺', '🧻', '🧼', '🧽', '🧾', '🧿', '🩰', '🩱', '🩲', '🩳', '🩴', '🩸', '🩹', '🩺', '🪀', '🪁', '🪂', '🪃', '🪄', '🪅', '🪆', '🪐', '🪑', '🪒', '🪓', '🪔', '🪕', '🪖', '🪗', '🪘', '🪙', '🪚', '🪛', '🪜', '🪝', '🪞', '🪟', '🪠', '🪡', '🪢', '🪣', '🪤', '🪥', '🪦', '🪧', '🪨', '🪰', '🪱', '🪲', '🪳', '🪴', '🪵', '🪶', '🫀', '🫁', '🫂', '🫐', '🫑', '🫒', '🫓', '🫔', '🫕', '🫖', '‼', '⁉', '™', 'ℹ', '↔', '↕', '↖', '↗', '↘', '↙', '↩', '↪', '⃣', '⌚', '⌛', '⌨', '⏏', '⏩', '⏪', '⏫', '⏬', '⏭', '⏮', '⏯', '⏰', '⏱', '⏲', '⏳', '⏸', '⏹', '⏺', 'Ⓜ', '▪', '▫', '▶', '◀', '◻', '◼', '◽', '◾', '☀', '☁', '☂', '☃', '☄', '☎', '☑', '☔', '☕', '☘', '☝', '☢', '☣', '☦', '☪', '☮', '☯', '☸', '☹', '☺', '♈', '♉', '♊', '♋', '♌', '♍', '♎', '♏', '♐', '♑', '♒', '♓', '♟', '♠', '♣', '♥', '♦', '♨', '♻', '♾', '♿', '⚒', '⚓', '⚔', '⚗', '⚙', '⚛', '⚜', '⚠', '⚡', '⚪', '⚫', '⚰', '⚱', '⚽', '⚾', '⛄', '⛅', '⛈', '⛎', '⛏', '⛑', '⛓', '⛔', '⛩', '⛪', '⛰', '⛱', '⛲', '⛳', '⛴', '⛵', '⛷', '⛸', '⛹', '⛺', '⛽', '✂', '✅', '✉', '✊', '✋', '✌', '✍', '✏', '✒', '✔', '✖', '✝', '✡', '✨', '✳', '✴', '❇', '❌', '❎', '❓', '❔', '❕', '❗', '❣', '➕', '➖', '➗', '➡', '➰', '➿', '⤴', '⤵', '⬅', '⬆', '⬇', '⬜', '⭐', '⭕', '〰', '〽', '㊗', '㊙', '' ); |
5755 // END: emoji arrays |
5969 // END: emoji arrays |
5756 |
5970 |
5757 if ( 'entities' === $type ) { |
5971 if ( 'entities' === $type ) { |
5758 return $entities; |
5972 return $entities; |
5759 } |
5973 } |
5806 /** |
6020 /** |
5807 * Sanitizes a hex color without a hash. Use sanitize_hex_color() when possible. |
6021 * Sanitizes a hex color without a hash. Use sanitize_hex_color() when possible. |
5808 * |
6022 * |
5809 * Saving hex colors without a hash puts the burden of adding the hash on the |
6023 * Saving hex colors without a hash puts the burden of adding the hash on the |
5810 * UI, which makes it difficult to use or upgrade to other color types such as |
6024 * UI, which makes it difficult to use or upgrade to other color types such as |
5811 * rgba, hsl, rgb, and html color names. |
6025 * rgba, hsl, rgb, and HTML color names. |
5812 * |
6026 * |
5813 * Returns either '', a 3 or 6 digit hex color (without a #), or null. |
6027 * Returns either '', a 3 or 6 digit hex color (without a #), or null. |
5814 * |
6028 * |
5815 * @since 3.4.0 |
6029 * @since 3.4.0 |
5816 * |
6030 * |
5837 * |
6051 * |
5838 * @param string $color |
6052 * @param string $color |
5839 * @return string |
6053 * @return string |
5840 */ |
6054 */ |
5841 function maybe_hash_hex_color( $color ) { |
6055 function maybe_hash_hex_color( $color ) { |
5842 if ( $unhashed = sanitize_hex_color_no_hash( $color ) ) { |
6056 $unhashed = sanitize_hex_color_no_hash( $color ); |
6057 if ( $unhashed ) { |
|
5843 return '#' . $unhashed; |
6058 return '#' . $unhashed; |
5844 } |
6059 } |
5845 |
6060 |
5846 return $color; |
6061 return $color; |
5847 } |
6062 } |