atible with old values; converting single quotes if set to 'single', * double if set to 'double' or both if otherwise set. * Default is ENT_NOQUOTES. * @param string $charset Optional. The character encoding of the string. Default is false. * @param bool $double_encode Optional. Whether to encode existing html entities. Default is false. * @return string The encoded text with HTML entities. */ function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { $string = (string) $string; if ( 0 === strlen( $string ) ) return ''; // Don't bother if there are no specialchars - saves some processing if ( ! preg_match( '/[&<>"\']/', $string ) ) return $string; // Account for the previous behaviour of the function when the $quote_style is not an accepted value if ( empty( $quote_style ) ) $quote_style = ENT_NOQUOTES; elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) $quote_style = ENT_QUOTES; // Store the site charset as a static to avoid multiple calls to wp_load_alloptions() if ( ! $charset ) { static $_charset = null; if ( ! isset( $_charset ) ) { $alloptions = wp_load_alloptions(); $_charset = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : ''; } $charset = $_charset; } if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ) ) ) $charset = 'UTF-8'; $_quote_style = $quote_style; if ( $quote_style === 'double' ) { $quote_style = ENT_COMPAT; $_quote_style = ENT_COMPAT; } elseif ( $quote_style === 'single' ) { $quote_style = ENT_NOQUOTES; } if ( ! $double_encode ) { // Guarantee every &entity; is valid, convert &garbage; into &garbage; // This is required for PHP < 5.4.0 because ENT_HTML401 flag is unavailable. $string = wp_kses_normalize_entities( $string ); } $string = @htmlspecialchars( $string, $quote_style, $charset, $double_encode ); // Back-compat. if ( 'single' === $_quote_style ) $string = str_replace( "'", ''', $string ); return $string; } /** * Converts a number of HTML entities into their special characters. * * Specifically deals with: &, <, >, ", and '. * * $quote_style can be set to ENT_COMPAT to decode " entities, * or ENT_QUOTES to do both " and '. Default is ENT_NOQUOTES where no quotes are decoded. * * @since 2.8.0 * * @param string $string The text which is to be decoded. * @param string|int $quote_style Optional. Converts double quotes if set to ENT_COMPAT, * both single and double if set to ENT_QUOTES or * none if set to ENT_NOQUOTES. * Also compatible with old _wp_specialchars() values; * converting single quotes if set to 'single', * double if set to 'double' or both if otherwise set. * Default is ENT_NOQUOTES. * @return string The decoded text without HTML entities. */ function wp_specialchars_decode( $string, $quote_style = ENT_NOQUOTES ) { $string = (string) $string; if ( 0 === strlen( $string ) ) { return ''; } // Don't bother if there are no entities - saves a lot of processing if ( strpos( $string, '&' ) === false ) { return $string; } // Match the previous behaviour of _wp_specialchars() when the $quote_style is not an accepted value if ( empty( $quote_style ) ) { $quote_style = ENT_NOQUOTES; } elseif ( !in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) { $quote_style = ENT_QUOTES; } // More complete than get_html_translation_table( HTML_SPECIALCHARS ) $single = array( ''' => '\'', ''' => '\'' ); $single_preg = array( '/�*39;/' => ''', '/�*27;/i' => ''' ); $double = array( '"' => '"', '"' => '"', '"' => '"' ); $double_preg = array( '/�*34;/' => '"', '/�*22;/i' => '"' ); $others = array( '<' => '<', '<' => '<', '>' => '>', '>' => '>', '&' => '&', '&' => '&', '&' => '&' ); $others_preg = array( '/�*60;/' => '<', '/�*62;/' => '>', '/�*38;/' => '&', '/�*26;/i' => '&' ); if ( $quote_style === ENT_QUOTES ) { $translation = array_merge( $single, $double, $others ); $translation_preg = array_merge( $single_preg, $double_preg, $others_preg ); } elseif ( $quote_style === ENT_COMPAT || $quote_style === 'double' ) { $translation = array_merge( $double, $others ); $translation_preg = array_merge( $double_preg, $others_preg ); } elseif ( $quote_style === 'single' ) { $translation = array_merge( $single, $others ); $translation_preg = array_merge( $single_preg, $others_preg ); } elseif ( $quote_style === ENT_NOQUOTES ) { $translation = $others; $translation_preg = $others_preg; } // Remove zero padding on numeric entities $string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string ); // Replace characters according to translation table return strtr( $string, $translation ); } /** * Checks for invalid UTF8 in a string. * * @since 2.8.0 * * @staticvar bool $is_utf8 * @staticvar bool $utf8_pcre * * @param string $string The text which is to be checked. * @param bool $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false. * @return string The checked text. */ function wp_check_invalid_utf8( $string, $strip = false ) { $string = (string) $string; if ( 0 === strlen( $string ) ) { return ''; } // Store the site charset as a static to avoid multiple calls to get_option() static $is_utf8 = null; if ( ! isset( $is_utf8 ) ) { $is_utf8 = in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ); } if ( ! $is_utf8 ) { return $string; } // Check for support for utf8 in the installed PCRE library once and store the result in a static static $utf8_pcre = null; if ( ! isset( $utf8_pcre ) ) { $utf8_pcre = @preg_match( '/^./u', 'a' ); } // We can't demand utf8 in the PCRE installation, so just return the string in those cases if ( !$utf8_pcre ) { return $string; } // preg_match fails when it encounters invalid UTF8 in $string if ( 1 === @preg_match( '/^./us', $string ) ) { return $string; } // Attempt to strip the bad chars if requested (not recommended) if ( $strip && function_exists( 'iconv' ) ) { return iconv( 'utf-8', 'utf-8', $string ); } return ''; } /** * Encode the Unicode values to be used in the URI. * * @since 1.5.0 * * @param string $utf8_string * @param int $length Max length of the string * @return string String with Unicode encoded for URI. */ function utf8_uri_encode( $utf8_string, $length = 0 ) { $unicode = ''; $values = array(); $num_octets = 1; $unicode_length = 0; mbstring_binary_safe_encoding(); $string_length = strlen( $utf8_string ); reset_mbstring_encoding(); for ($i = 0; $i < $string_length; $i++ ) { $value = ord( $utf8_string[ $i ] ); if ( $value < 128 ) { if ( $length && ( $unicode_length >= $length ) ) { break; } $unicode .= chr( $value ); $unicode_length++; } else { if ( count( $values ) == 0 ) { if ( $value < 224 ) { $num_octets = 2; } elseif ( $value < 240 ) { $num_octets = 3; } else { $num_octets = 4; } } $values[] = $value; if ( $length && ( $unicode_length + ($num_octets * 3) ) > $length ) break; if ( count( $values ) == $num_octets ) { for ( $j = 0; $j < $num_octets; $j++ ) { $unicode .= '%' . dechex( $values[ $j ] ); } $unicode_length += $num_octets * 3; $values = array(); $num_octets = 1; } } } return $unicode; } /** * Converts all accent characters to ASCII characters. * * If there are no accent characters, then the string given is just returned. * * **Accent characters converted:** * * Currency signs: * * | Code | Glyph | Replacement | Description | * | -------- | ----- | ----------- | ------------------- | * | U+00A3 | £ | (empty) | British Pound sign | * | U+20AC | € | E | Euro sign | * * Decompositions for Latin-1 Supplement: * * | Code | Glyph | Replacement | Description | * | ------- | ----- | ----------- | -------------------------------------- | * | U+00AA | ª | a | Feminine ordinal indicator | * | U+00BA | º | o | Masculine ordinal indicator | * | U+00C0 | À | A | Latin capital letter A with grave | * | U+00C1 | Á | A | Latin capital letter A with acute | * | U+00C2 |  | A | Latin capital letter A with circumflex | * | U+00C3 | à | A | Latin capital letter A with tilde | * | U+00C4 | Ä | A | Latin capital letter A with diaeresis | * | U+00C5 | Å | A | Latin capital letter A with ring above | * | U+00C6 | Æ | AE | Latin capital letter AE | * | U+00C7 | Ç | C | Latin capital letter C with cedilla | * | U+00C8 | È | E | Latin capital letter E with grave | * | U+00C9 | É | E | Latin capital letter E with acute | * | U+00CA | Ê | E | Latin capital letter E with circumflex | * | U+00CB | Ë | E | Latin capital letter E with diaeresis | * | U+00CC | Ì | I | Latin capital letter I with grave | * | U+00CD | Í | I | Latin capital letter I with acute | * | U+00CE | Î | I | Latin capital letter I with circumflex | * | U+00CF | Ï | I | Latin capital letter I with diaeresis | * | U+00D0 | Ð | D | Latin capital letter Eth | * | U+00D1 | Ñ | N | Latin capital letter N with tilde | * | U+00D2 | Ò | O | Latin capital letter O with grave | * | U+00D3 | Ó | O | Latin capital letter O with acute | * | U+00D4 | Ô | O | Latin capital letter O with circumflex | * | U+00D5 | Õ | O | Latin capital letter O with tilde | * | U+00D6 | Ö | O | Latin capital letter O with diaeresis | * | U+00D8 | Ø | O | Latin capital letter O with stroke | * | U+00D9 | Ù | U | Latin capital letter U with grave | * | U+00DA | Ú | U | Latin capital letter U with acute | * | U+00DB | Û | U | Latin capital letter U with circumflex | * | U+00DC | Ü | U | Latin capital letter U with diaeresis | * | U+00DD | Ý | Y | Latin capital letter Y with acute | * | U+00DE | Þ | TH | Latin capital letter Thorn | * | U+00DF | ß | s | Latin small letter sharp s | * | U+00E0 | à | a | Latin small letter a with grave | * | U+00E1 | á | a | Latin small letter a with acute | * | U+00E2 | â | a | Latin small letter a with circumflex | * | U+00E3 | ã | a | Latin small letter a with tilde | * | U+00E4 | ä | a | Latin small letter a with diaeresis | * | U+00E5 | å | a | Latin small letter a with ring above | * | U+00E6 | æ | ae | Latin small letter ae | * | U+00E7 | ç | c | Latin small letter c with cedilla | * | U+00E8 | è | e | Latin small letter e with grave | * | U+00E9 | é | e | Latin small letter e with acute | * | U+00EA | ê | e | Latin small letter e with circumflex | * | U+00EB | ë | e | Latin small letter e with diaeresis | * | U+00EC | ì | i | Latin small letter i with grave | * | U+00ED | í | i | Latin small letter i with acute | * | U+00EE | î | i | Latin small letter i with circumflex | * | U+00EF | ï | i | Latin small letter i with diaeresis | * | U+00F0 | ð | d | Latin small letter Eth | * | U+00F1 | ñ | n | Latin small letter n with tilde | * | U+00F2 | ò | o | Latin small letter o with grave | * | U+00F3 | ó | o | Latin small letter o with acute | * | U+00F4 | ô | o | Latin small letter o with circumflex | * | U+00F5 | õ | o | Latin small letter o with tilde | * | U+00F6 | ö | o | Latin small letter o with diaeresis | * | U+00F8 | ø | o | Latin small letter o with stroke | * | U+00F9 | ù | u | Latin small letter u with grave | * | U+00FA | ú | u | Latin small letter u with acute | * | U+00FB | û | u | Latin small letter u with circumflex | * | U+00FC | ü | u | Latin small letter u with diaeresis | * | U+00FD | ý | y | Latin small letter y with acute | * | U+00FE | þ | th | Latin small letter Thorn | * | U+00FF | ÿ | y | Latin small letter y with diaeresis | * * Decompositions for Latin Extended-A: * * | Code | Glyph | Replacement | Description | * | ------- | ----- | ----------- | ------------------------------------------------- | * | U+0100 | Ā | A | Latin capital letter A with macron | * | U+0101 | ā | a | Latin small letter a with macron | * | U+0102 | Ă | A | Latin capital letter A with breve | * | U+0103 | ă | a | Latin small letter a with breve | * | U+0104 | Ą | A | Latin capital letter A with ogonek | * | U+0105 | ą | a | Latin small letter a with ogonek | * | U+01006 | Ć | C | Latin capital letter C with acute | * | U+0107 | ć | c | Latin small letter c with acute | * | U+0108 | Ĉ | C | Latin capital letter C with circumflex | * | U+0109 | ĉ | c | Latin small letter c with circumflex | * | U+010A | Ċ | C | Latin capital letter C with dot above | * | U+010B | ċ | c | Latin small letter c with dot above | * | U+010C | Č | C | Latin capital letter C with caron | * | U+010D | č | c | Latin small letter c with caron | * | U+010E | Ď | D | Latin capital letter D with caron | * | U+010F | ď | d | Latin small letter d with caron | * | U+0110 | Đ | D | Latin capital letter D with stroke | * | U+0111 | đ | d | Latin small letter d with stroke | * | U+0112 | Ē | E | Latin capital letter E with macron | * | U+0113 | ē | e | Latin small letter e with macron | * | U+0114 | Ĕ | E | Latin capital letter E with breve | * | U+0115 | ĕ | e | Latin small letter e with breve | * | U+0116 | Ė | E | Latin capital letter E with dot above | * | U+0117 | ė | e | Latin small letter e with dot above | * | U+0118 | Ę | E | Latin capital letter E with ogonek | * | U+0119 | ę | e | Latin small letter e with ogonek | * | U+011A | Ě | E | Latin capital letter E with caron | * | U+011B | ě | e | Latin small letter e with caron | * | U+011C | Ĝ | G | Latin capital letter G with circumflex | * | U+011D | ĝ | g | Latin small letter g with circumflex | * | U+011E | Ğ | G | Latin capital letter G with breve | * | U+011F | ğ | g | Latin small letter g with breve | * | U+0120 | Ġ | G | Latin capital letter G with dot above | * | U+0121 | ġ | g | Latin small letter g with dot above | * | U+0122 | Ģ | G | Latin capital letter G with cedilla | * | U+0123 | ģ | g | Latin small letter g with cedilla | * | U+0124 | Ĥ | H | Latin capital letter H with circumflex | * | U+0125 | ĥ | h | Latin small letter h with circumflex | * | U+0126 | Ħ | H | Latin capital letter H with stroke | * | U+0127 | ħ | h | Latin small letter h with stroke | * | U+0128 | Ĩ | I | Latin capital letter I with tilde | * | U+0129 | ĩ | i | Latin small letter i with tilde | * | U+012A | Ī | I | Latin capital letter I with macron | * | U+012B | ī | i | Latin small letter i with macron | * | U+012C | Ĭ | I | Latin capital letter I with breve | * | U+012D | ĭ | i | Latin small letter i with breve | * | U+012E | Į | I | Latin capital letter I with ogonek | * | U+012F | į | i | Latin small letter i with ogonek | * | U+0130 | İ | I | Latin capital letter I with dot above | * | U+0131 | ı | i | Latin small letter dotless i | * | U+0132 | IJ | IJ | Latin capital ligature IJ | * | U+0133 | ij | ij | Latin small ligature ij | * | U+0134 | Ĵ | J | Latin capital letter J with circumflex | * | U+0135 | ĵ | j | Latin small letter j with circumflex | * | U+0136 | Ķ | K | Latin capital letter K with cedilla | * | U+0137 | ķ | k | Latin small letter k with cedilla | * | U+0138 | ĸ | k | Latin small letter Kra | * | U+0139 | Ĺ | L | Latin capital letter L with acute | * | U+013A | ĺ | l | Latin small letter l with acute | * | U+013B | Ļ | L | Latin capital letter L with cedilla | * | U+013C | ļ | l | Latin small letter l with cedilla | * | U+013D | Ľ | L | Latin capital letter L with caron | * | U+013E | ľ | l | Latin small letter l with caron | * | U+013F | Ŀ | L | Latin capital letter L with middle dot | * | U+0140 | ŀ | l | Latin small letter l with middle dot | * | U+0141 | Ł | L | Latin capital letter L with stroke | * | U+0142 | ł | l | Latin small letter l with stroke | * | U+0143 | Ń | N | Latin capital letter N with acute | * | U+0144 | ń | n | Latin small letter N with acute | * | U+0145 | Ņ | N | Latin capital letter N with cedilla | * | U+0146 | ņ | n | Latin small letter n with cedilla | * | U+0147 | Ň | N | Latin capital letter N with caron | * | U+0148 | ň | n | Latin small letter n with caron | * | U+0149 | ʼn | n | Latin small letter n preceded by apostrophe | * | U+014A | Ŋ | N | Latin capital letter Eng | * | U+014B | ŋ | n | Latin small letter Eng | * | U+014C | Ō | O | Latin capital letter O with macron | * | U+014D | ō | o | Latin small letter o with macron | * | U+014E | Ŏ | O | Latin capital letter O with breve | * | U+014F | ŏ | o | Latin small letter o with breve | * | U+0150 | Ő | O | Latin capital letter O with double acute | * | U+0151 | ő | o | Latin small letter o with double acute | * | U+0152 | Œ | OE | Latin capital ligature OE | * | U+0153 | œ | oe | Latin small ligature oe | * | U+0154 | Ŕ | R | Latin capital letter R with acute | * | U+0155 | ŕ | r | Latin small letter r with acute | * | U+0156 | Ŗ | R | Latin capital letter R with cedilla | * | U+0157 | ŗ | r | Latin small letter r with cedilla | * | U+0158 | Ř | R | Latin capital letter R with caron | * | U+0159 | ř | r | Latin small letter r with caron | * | U+015A | Ś | S | Latin capital letter S with acute | * | U+015B | ś | s | Latin small letter s with acute | * | U+015C | Ŝ | S | Latin capital letter S with circumflex | * | U+015D | ŝ | s | Latin small letter s with circumflex | * | U+015E | Ş | S | Latin capital letter S with cedilla | * | U+015F | ş | s | Latin small letter s with cedilla | * | U+0160 | Š | S | Latin capital letter S with caron | * | U+0161 | š | s | Latin small letter s with caron | * | U+0162 | Ţ | T | Latin capital letter T with cedilla | * | U+0163 | ţ | t | Latin small letter t with cedilla | * | U+0164 | Ť | T | Latin capital letter T with caron | * | U+0165 | ť | t | Latin small letter t with caron | * | U+0166 | Ŧ | T | Latin capital letter T with stroke | * | U+0167 | ŧ | t | Latin small letter t with stroke | * | U+0168 | Ũ | U | Latin capital letter U with tilde | * | U+0169 | ũ | u | Latin small letter u with tilde | * | U+016A | Ū | U | Latin capital letter U with macron | * | U+016B | ū | u | Latin small letter u with macron | * | U+016C | Ŭ | U | Latin capital letter U with breve | * | U+016D | ŭ | u | Latin small letter u with breve | * | U+016E | Ů | U | Latin capital letter U with ring above | * | U+016F | ů | u | Latin small letter u with ring above | * | U+0170 | Ű | U | Latin capital letter U with double acute | * | U+0171 | ű | u | Latin small letter u with double acute | * | U+0172 | Ų | U | Latin capital letter U with ogonek | * | U+0173 | ų | u | Latin small letter u with ogonek | * | U+0174 | Ŵ | W | Latin capital letter W with circumflex | * | U+0175 | ŵ | w | Latin small letter w with circumflex | * | U+0176 | Ŷ | Y | Latin capital letter Y with circumflex | * | U+0177 | ŷ | y | Latin small letter y with circumflex | * | U+0178 | Ÿ | Y | Latin capital letter Y with diaeresis | * | U+0179 | Ź | Z | Latin capital letter Z with acute | * | U+017A | ź | z | Latin small letter z with acute | * | U+017B | Ż | Z | Latin capital letter Z with dot above | * | U+017C | ż | z | Latin small letter z with dot above | * | U+017D | Ž | Z | Latin capital letter Z with caron | * | U+017E | ž | z | Latin small letter z with caron | * | U+017F | ſ | s | Latin small letter long s | * | U+01A0 | Ơ | O | Latin capital letter O with horn | * | U+01A1 | ơ | o | Latin small letter o with horn | * | U+01AF | Ư | U | Latin capital letter U with horn | * | U+01B0 | ư | u | Latin small letter u with horn | * | U+01CD | Ǎ | A | Latin capital letter A with caron | * | U+01CE | ǎ | a | Latin small letter a with caron | * | U+01CF | Ǐ | I | Latin capital letter I with caron | * | U+01D0 | ǐ | i | Latin small letter i with caron | * | U+01D1 | Ǒ | O | Latin capital letter O with caron | * | U+01D2 | ǒ | o | Latin small letter o with caron | * | U+01D3 | Ǔ | U | Latin capital letter U with caron | * | U+01D4 | ǔ | u | Latin small letter u with caron | * | U+01D5 | Ǖ | U | Latin capital letter U with diaeresis and macron | * | U+01D6 | ǖ | u | Latin small letter u with diaeresis and macron | * | U+01D7 | Ǘ | U | Latin capital letter U with diaeresis and acute | * | U+01D8 | ǘ | u | Latin small letter u with diaeresis and acute | * | U+01D9 | Ǚ | U | Latin capital letter U with diaeresis and caron | * | U+01DA | ǚ | u | Latin small letter u with diaeresis and caron | * | U+01DB | Ǜ | U | Latin capital letter U with diaeresis and grave | * | U+01DC | ǜ | u | Latin small letter u with diaeresis and grave | * * Decompositions for Latin Extended-B: * * | Code | Glyph | Replacement | Description | * | -------- | ----- | ----------- | ----------------------------------------- | * | U+0218 | Ș | S | Latin capital letter S with comma below | * | U+0219 | ș | s | Latin small letter s with comma below | * | U+021A | Ț | T | Latin capital letter T with comma below | * | U+021B | ț | t | Latin small letter t with comma below | * * Vowels with diacritic (Chinese, Hanyu Pinyin): * * | Code | Glyph | Replacement | Description | * | -------- | ----- | ----------- | ----------------------------------------------------- | * | U+0251 | ɑ | a | Latin small letter alpha | * | U+1EA0 | Ạ | A | Latin capital letter A with dot below | * | U+1EA1 | ạ | a | Latin small letter a with dot below | * | U+1EA2 | Ả | A | Latin capital letter A with hook above | * | U+1EA3 | ả | a | Latin small letter a with hook above | * | U+1EA4 | Ấ | A | Latin capital letter A with circumflex and acute | * | U+1EA5 | ấ | a | Latin small letter a with circumflex and acute | * | U+1EA6 | Ầ | A | Latin capital letter A with circumflex and grave | * | U+1EA7 | ầ | a | Latin small letter a with circumflex and grave | * | U+1EA8 | Ẩ | A | Latin capital letter A with circumflex and hook above | * | U+1EA9 | ẩ | a | Latin small letter a with circumflex and hook above | * | U+1EAA | Ẫ | A | Latin capital letter A with circumflex and tilde | * | U+1EAB | ẫ | a | Latin small letter a with circumflex and tilde | * | U+1EA6 | Ậ | A | Latin capital letter A with circumflex and dot below | * | U+1EAD | ậ | a | Latin small letter a with circumflex and dot below | * | U+1EAE | Ắ | A | Latin capital letter A with breve and acute | * | U+1EAF | ắ | a | Latin small letter a with breve and acute | * | U+1EB0 | Ằ | A | Latin capital letter A with breve and grave | * | U+1EB1 | ằ | a | Latin small letter a with breve and grave | * | U+1EB2 | Ẳ | A | Latin capital letter A with breve and hook above | * | U+1EB3 | ẳ | a | Latin small letter a with breve and hook above | * | U+1EB4 | Ẵ | A | Latin capital letter A with breve and tilde | * | U+1EB5 | ẵ | a | Latin small letter a with breve and tilde | * | U+1EB6 | Ặ | A | Latin capital letter A with breve and dot below | * | U+1EB7 | ặ | a | Latin small letter a with breve and dot below | * | U+1EB8 | Ẹ | E | Latin capital letter E with dot below | * | U+1EB9 | ẹ | e | Latin small letter e with dot below | * | U+1EBA | Ẻ | E | Latin capital letter E with hook above | * | U+1EBB | ẻ | e | Latin small letter e with hook above | * | U+1EBC | Ẽ | E | Latin capital letter E with tilde | * | U+1EBD | ẽ | e | Latin small letter e with tilde | * | U+1EBE | Ế | E | Latin capital letter E with circumflex and acute | * | U+1EBF | ế | e | Latin small letter e with circumflex and acute | * | U+1EC0 | Ề | E | Latin capital letter E with circumflex and grave | * | U+1EC1 | ề | e | Latin small letter e with circumflex and grave | * | U+1EC2 | Ể | E | Latin capital letter E with circumflex and hook above | * | U+1EC3 | ể | e | Latin small letter e with circumflex and hook above | * | U+1EC4 | Ễ | E | Latin capital letter E with circumflex and tilde | * | U+1EC5 | ễ | e | Latin small letter e with circumflex and tilde | * | U+1EC6 | Ệ | E | Latin capital letter E with circumflex and dot below | * | U+1EC7 | ệ | e | Latin small letter e with circumflex and dot below | * | U+1EC8 | Ỉ | I | Latin capital letter I with hook above | * | U+1EC9 | ỉ | i | Latin small letter i with hook above | * | U+1ECA | Ị | I | Latin capital letter I with dot below | * | U+1ECB | ị | i | Latin small letter i with dot below | * | U+1ECC | Ọ | O | Latin capital letter O with dot below | * | U+1ECD | ọ | o | Latin small letter o with dot below | * | U+1ECE | Ỏ | O | Latin capital letter O with hook above | * | U+1ECF | ỏ | o | Latin small letter o with hook above | * | U+1ED0 | Ố | O | Latin capital letter O with circumflex and acute | * | U+1ED1 | ố | o | Latin small letter o with circusince 0.71 * * @param string $string Value to which backslashes will be added. * @return string String with backslashes inserted. */ function backslashit( $string ) { if ( isset( $string[0] ) && $string[0] >= '0' && $string[0] <= '9' ) $string = '\\\\' . $string; return addcslashes( $string, 'A..Za..z' ); } /** * Appends a trailing slash. * * Will remove trailing forward and backslashes if it exists already before adding * a trailing forward slash. This prevents double slashing a string or path. * * The primary use of this is for paths and thus should be used for paths. It is * not restricted to paths and offers no specific path support. * * @since 1.2.0 * * @param string $string What to add the trailing slash to. * @return string String with trailing slash added. */ function trailingslashit( $string ) { return untrailingslashit( $string ) . '/'; } /** * Removes trailing forward slashes and backslashes if they exist. * * The primary use of this is for paths and thus should be used for paths. It is * not restricted to paths and offers no specific path support. * * @since 2.2.0 * * @param string $string What to remove the trailing slashes from. * @return string String without the trailing slashes. */ function untrailingslashit( $string ) { return rtrim( $string, '/\\' ); } /** * Adds slashes to escape strings. * * Slashes will first be removed if magic_quotes_gpc is set, see {@link * https://secure.php.net/magic_quotes} for more details. * * @since 0.71 * * @param string $gpc The string returned from HTTP request data. * @return string Returns a string escaped with slashes. */ function addslashes_gpc($gpc) { if ( get_magic_quotes_gpc() ) $gpc = stripslashes($gpc); return wp_slash($gpc); } /** * Navigates through an array, object, or scalar, and removes slashes from the values. * * @since 2.0.0 * * @param mixed $value The value to be stripped. * @return mixed Stripped value. */ function stripslashes_deep( $value ) { return map_deep( $value, 'stripslashes_from_strings_only' ); } /** * Callback function for `stripslashes_deep()` which strips slashes from strings. * * @since 4.4.0 * * @param mixed $value The array or string to be stripped. * @return mixed $value The stripped value. */ function stripslashes_from_strings_only( $value ) { return is_string( $value ) ? stripslashes( $value ) : $value; } /** * Navigates through an array, object, or scalar, and encodes the values to be used in a URL. * * @since 2.2.0 * * @param mixed $value The array or string to be encoded. * @return mixed $value The encoded value. */ function urlencode_deep( $value ) { return map_deep( $value, 'urlencode' ); } /** * Navigates through an array, object, or scalar, and raw-encodes the values to be used in a URL. * * @since 3.4.0 * * @param mixed $value The array or string to be encoded. * @return mixed $value The encoded value. */ function rawurlencode_deep( $value ) { return map_deep( $value, 'rawurlencode' ); } /** * Navigates through an array, object, or scalar, and decodes URL-encoded values * * @since 4.4.0 * * @param mixed $value The array or string to be decoded. * @return mixed $value The decoded value. */ function urldecode_deep( $value ) { return map_deep( $value, 'urldecode' ); } /** * Converts email addresses characters to HTML entities to block spam bots. * * @since 0.71 * * @param string $email_address Email address. * @param int $hex_encoding Optional. Set to 1 to enable hex encoding. * @return string Converted email address. */ function antispambot( $email_address, $hex_encoding = 0 ) { $email_no_spam_address = ''; for ( $i = 0, $len = strlen( $email_address ); $i < $len; $i++ ) { $j = rand( 0, 1 + $hex_encoding ); if ( $j == 0 ) { $email_no_spam_address .= '&#' . ord( $email_address[$i] ) . ';'; } elseif ( $j == 1 ) { $email_no_spam_address .= $email_address[$i]; } elseif ( $j == 2 ) { $email_no_spam_address .= '%' . zeroise( dechex( ord( $email_address[$i] ) ), 2 ); } } return str_replace( '@', '@', $email_no_spam_address ); } /** * Callback to convert URI match to HTML A element. * * This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable(). * * @since 2.3.2 * @access private * * @param array $matches Single Regex Match. * @return string HTML A element with URI address. */ function _make_url_clickable_cb( $matches ) { $url = $matches[2]; if ( ')' == $matches[3] && strpos( $url, '(' ) ) { // If the trailing character is a closing parethesis, and the URL has an opening parenthesis in it, add the closing parenthesis to the URL. // Then we can let the parenthesis balancer do its thing below. $url .= $matches[3]; $suffix = ''; } else { $suffix = $matches[3]; } // Include parentheses in the URL only if paired while ( substr_count( $url, '(' ) < substr_count( $url, ')' ) ) { $suffix = strrchr( $url, ')' ) . $suffix; $url = substr( $url, 0, strrpos( $url, ')' ) ); } $url = esc_url($url); if ( empty($url) ) return $matches[0]; return $matches[1] . "$url" . $suffix; } /** * Callback to convert URL match to HTML A element. * * This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable(). * * @since 2.3.2 * @access private * * @param array $matches Single Regex Match. * @return string HTML A element with URL address. */ function _make_web_ftp_clickable_cb( $matches ) { $ret = ''; $dest = $matches[2]; $dest = 'http://' . $dest; // removed trailing [.,;:)] from URL if ( in_array( substr($dest, -1), array('.', ',', ';', ':', ')') ) === true ) { $ret = substr($dest, -1); $dest = substr($dest, 0, strlen($dest)-1); } $dest = esc_url($dest); if ( empty($dest) ) return $matches[0]; return $matches[1] . "$dest$ret"; } /** * Callback to convert email address match to HTML A element. * * This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable(). * * @since 2.3.2 * @access private * * @param array $matches Single Regex Match. * @return string HTML A element with email address. */ function _make_email_clickable_cb( $matches ) { $email = $matches[2] . '@' . $matches[3]; return $matches[1] . "$email"; } /** * Convert plaintext URI to HTML links. * * Converts URI, www and ftp, and email addresses. Finishes by fixing links * within links. * * @since 0.71 * * @param string $text Content to convert URIs. * @return string Content with converted URIs. */ function make_clickable( $text ) { $r = ''; $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // split out HTML tags $nested_code_pre = 0; // Keep track of how many levels link is nested inside
 or 
	foreach ( $textarr as $piece ) {

		if ( preg_match( '|^]|i', $piece ) || preg_match( '|^]|i', $piece ) || preg_match( '|^]|i', $piece ) || preg_match( '|^]|i', $piece ) )
			$nested_code_pre++;
		elseif ( $nested_code_pre && ( '' === strtolower( $piece ) || '
' === strtolower( $piece ) || '' === strtolower( $piece ) || '' === strtolower( $piece ) ) ) $nested_code_pre--; if ( $nested_code_pre || empty( $piece ) || ( $piece[0] === '<' && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) ) ) { $r .= $piece; continue; } // Long strings might contain expensive edge cases ... if ( 10000 < strlen( $piece ) ) { // ... break it up foreach ( _split_str_by_whitespace( $piece, 2100 ) as $chunk ) { // 2100: Extra room for scheme and leading and trailing paretheses if ( 2101 < strlen( $chunk ) ) { $r .= $chunk; // Too big, no whitespace: bail. } else { $r .= make_clickable( $chunk ); } } } else { $ret = " $piece "; // Pad with whitespace to simplify the regexes $url_clickable = '~ ([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation ( # 2: URL [\\w]{1,20}+:// # Scheme and hier-part prefix (?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character (?: # Unroll the Loop: Only allow puctuation URL character if followed by a non-punctuation URL character [\'.,;:!?)] # Punctuation URL character [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character )* ) (\)?) # 3: Trailing closing parenthesis (for parethesis balancing post processing) ~xS'; // The regex is a non-anchored pattern and does not have a single fixed starting character. // Tell PCRE to spend more time optimizing since, when used on a page load, it will probably be used several times. $ret = preg_replace_callback( $url_clickable, '_make_url_clickable_cb', $ret ); $ret = preg_replace_callback( '#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is', '_make_web_ftp_clickable_cb', $ret ); $ret = preg_replace_callback( '#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret ); $ret = substr( $ret, 1, -1 ); // Remove our whitespace padding. $r .= $ret; } } // Cleanup of accidental links within links return preg_replace( '#(]+?>|>))]+?>([^>]+?)#i', "$1$3", $r ); } /** * Breaks a string into chunks by splitting at whitespace characters. * The length of each returned chunk is as close to the specified length goal as possible, * with the caveat that each chunk includes its trailing delimiter. * Chunks longer than the goal are guaranteed to not have any inner whitespace. * * Joining the returned chunks with empty delimiters reconstructs the input string losslessly. * * Input string must have no null characters (or eventual transformations on output chunks must not care about null characters) * * _split_str_by_whitespace( "1234 67890 1234 67890a cd 1234 890 123456789 1234567890a 45678 1 3 5 7 90 ", 10 ) == * array ( * 0 => '1234 67890 ', // 11 characters: Perfect split * 1 => '1234 ', // 5 characters: '1234 67890a' was too long * 2 => '67890a cd ', // 10 characters: '67890a cd 1234' was too long * 3 => '1234 890 ', // 11 characters: Perfect split * 4 => '123456789 ', // 10 characters: '123456789 1234567890a' was too long * 5 => '1234567890a ', // 12 characters: Too long, but no inner whitespace on which to split * 6 => ' 45678 ', // 11 characters: Perfect split * 7 => '1 3 5 7 90 ', // 11 characters: End of $string * ); * * @since 3.4.0 * @access private * * @param string $string The string to split. * @param int $goal The desired chunk length. * @return array Numeric array of chunks. */ function _split_str_by_whitespace( $string, $goal ) { $chunks = array(); $string_nullspace = strtr( $string, "\r\n\t\v\f ", "\000\000\000\000\000\000" ); while ( $goal < strlen( $string_nullspace ) ) { $pos = strrpos( substr( $string_nullspace, 0, $goal + 1 ), "\000" ); if ( false === $pos ) { $pos = strpos( $string_nullspace, "\000", $goal + 1 ); if ( false === $pos ) { break; } } $chunks[] = substr( $string, 0, $pos + 1 ); $string = substr( $string, $pos + 1 ); $string_nullspace = substr( $string_nullspace, $pos + 1 ); } if ( $string ) { $chunks[] = $string; } return $chunks; } /** * Adds rel nofollow string to all HTML A elements in content. * * @since 1.5.0 * * @param string $text Content that may contain HTML A elements. * @return string Converted content. */ function wp_rel_nofollow( $text ) { // This is a pre save filter, so text is already escaped. $text = stripslashes($text); $text = preg_replace_callback('||i', 'wp_rel_nofollow_callback', $text); return wp_slash( $text ); } /** * Callback to add rel=nofollow string to HTML A element. * * Will remove already existing rel="nofollow" and rel='nofollow' from the * string to prevent from invalidating (X)HTML. * * @since 2.3.0 * * @param array $matches Single Match * @return string HTML A Element with rel nofollow. */ function wp_rel_nofollow_callback( $matches ) { $text = $matches[1]; $atts = wp_kses_hair( $matches[1], wp_allowed_protocols() ); $rel = 'nofollow'; if ( ! empty( $atts['href'] ) ) { if ( in_array( strtolower( wp_parse_url( $atts['href']['value'], PHP_URL_SCHEME ) ), array( 'http', 'https' ), true ) ) { if ( strtolower( wp_parse_url( $atts['href']['value'], PHP_URL_HOST ) ) === strtolower( wp_parse_url( home_url(), PHP_URL_HOST ) ) ) { return ""; } } } if ( ! empty( $atts['rel'] ) ) { $parts = array_map( 'trim', explode( ' ', $atts['rel']['value'] ) ); if ( false === array_search( 'nofollow', $parts ) ) { $parts[] = 'nofollow'; } $rel = implode( ' ', $parts ); unset( $atts['rel'] ); $html = ''; foreach ( $atts as $name => $value ) { if ( isset( $value['vless'] ) && 'y' === $value['vless'] ) { $html .= $name . ' '; } else { $html .= "{$name}=\"" . esc_attr( $value['value'] ) . '" '; } } $text = trim( $html ); } return ""; } /** * Convert one smiley code to the icon graphic file equivalent. * * Callback handler for convert_smilies(). * * Looks up one smiley code in the $wpsmiliestrans global array and returns an * `` string for that smiley. * * @since 2.8.0 * * @global array $wpsmiliestrans * * @param array $matches Single match. Smiley code to convert to image. * @return string Image string for smiley. */ function translate_smiley( $matches ) { global $wpsmiliestrans; if ( count( $matches ) == 0 ) return ''; $smiley = trim( reset( $matches ) ); $img = $wpsmiliestrans[ $smiley ]; $matches = array(); $ext = preg_match( '/\.([^.]+)$/', $img, $matches ) ? strtolower( $matches[1] ) : false; $image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' ); // Don't convert smilies that aren't images - they're probably emoji. if ( ! in_array( $ext, $image_exts ) ) { return $img; } /** * Filters the Smiley image URL before it's used in the image element. * * @since 2.9.0 * * @param string $smiley_url URL for the smiley image. * @param string $img Filename for the smiley image. * @param string $site_url Site URL, as returned by site_url(). */ $src_url = apply_filters( 'smilies_src', includes_url( "images/smilies/$img" ), $img, site_url() ); return sprintf( '%s', esc_url( $src_url ), esc_attr( $smiley ) ); } /** * Convert text equivalent of smilies to images. * * Will only convert smilies if the option 'use_smilies' is true and the global * used in the function isn't empty. * * @since 0.71 * * @global string|array $wp_smiliessearch * * @param string $text Content to convert smilies from text. * @return string Converted content with text smilies replaced with images. */ function convert_smilies( $text ) { global $wp_smiliessearch; $output = ''; if ( get_option( 'use_smilies' ) && ! empty( $wp_smiliessearch ) ) { // HTML loop taken from texturize function, could possible be consolidated $textarr = preg_split( '/(<.*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // capture the tags as well as in between $stop = count( $textarr );// loop stuff // Ignore proessing of specific tags $tags_to_ignore = 'code|pre|style|script|textarea'; $ignore_block_element = ''; for ( $i = 0; $i < $stop; $i++ ) { $content = $textarr[$i]; // If we're in an ignore block, wait until we find its closing tag if ( '' == $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')>/', $content, $matches ) ) { $ignore_block_element = $matches[1]; } // If it's not a tag and not in ignore block if ( '' == $ignore_block_element && strlen( $content ) > 0 && '<' != $content[0] ) { $content = preg_replace_callback( $wp_smiliessearch, 'translate_smiley', $content ); } // did we exit ignore block if ( '' != $ignore_block_element && '' == $content ) { $ignore_block_element = ''; } $output .= $content; } } else { // return default text. $output = $text; } return $output; } /** * Verifies that an email is valid. * * Does not grok i18n domains. Not RFC compliant. * * @since 0.71 * * @param string $email Email address to verify. * @param bool $deprecated Deprecated. * @return string|bool Either false or the valid email address. */ function is_email( $email, $deprecated = false ) { if ( ! empty( $deprecated ) ) _deprecated_argument( __FUNCTION__, '3.0.0' ); // Test for the minimum length the email can be if ( strlen( $email ) < 6 ) { /** * Filters whether an email address is valid. * * This filter is evaluated under several different contexts, such as 'email_too_short', * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits', * 'domain_no_periods', 'sub_hyphen_limits', 'sub_invalid_chars', or no specific context. * * @since 2.8.0 * * @param bool $is_email Whether the email address has passed the is_email() checks. Default false. * @param string $email The email address being checked. * @param string $context Context under which the email was tested. */ return apply_filters( 'is_email', false, $email, 'email_too_short' ); } // Test for an @ character after the first position if ( strpos( $email, '@', 1 ) === false ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'is_email', false, $email, 'email_no_at' ); } // Split out the local and domain parts list( $local, $domain ) = explode( '@', $email, 2 ); // LOCAL PART // Test for invalid characters if ( !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'is_email', false, $email, 'local_invalid_chars' ); } // DOMAIN PART // Test for sequences of periods if ( preg_match( '/\.{2,}/', $domain ) ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'is_email', false, $email, 'domain_period_sequence' ); } // Test for leading and trailing periods and whitespace if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'is_email', false, $email, 'domain_period_limits' ); } // Split the domain into subs $subs = explode( '.', $domain ); // Assume the domain will have at least two subs if ( 2 > count( $subs ) ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'is_email', false, $email, 'domain_no_periods' ); } // Loop through each sub foreach ( $subs as $sub ) { // Test for leading and trailing hyphens and whitespace if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' ); } // Test for invalid characters if ( !preg_match('/^[a-z0-9-]+$/i', $sub ) ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' ); } } // Congratulations your email made it! /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'is_email', $email, $email, null ); } /** * Convert to ASCII from email subjects. * * @since 1.2.0 * * @param string $string Subject line * @return string Converted string to ASCII */ function wp_iso_descrambler( $string ) { /* this may only work with iso-8859-1, I'm afraid */ if (!preg_match('#\=\?(.+)\?Q\?(.+)\?\=#i', $string, $matches)) { return $string; } else { $subject = str_replace('_', ' ', $matches[2]); return preg_replace_callback( '#\=([0-9a-f]{2})#i', '_wp_iso_convert', $subject ); } } /** * Helper function to convert hex encoded chars to ASCII * * @since 3.1.0 * @access private * * @param array $match The preg_replace_callback matches array * @return string Converted chars */ function _wp_iso_convert( $match ) { return chr( hexdec( strtolower( $match[1] ) ) ); } /** * Returns a date in the GMT equivalent. * * Requires and returns a date in the Y-m-d H:i:s format. If there is a * timezone_string available, the date is assumed to be in that timezone, * otherwise it simply subtracts the value of the 'gmt_offset' option. Return * format can be overridden using the $format parameter. * * @since 1.2.0 * * @param string $string The date to be converted. * @param string $format The format string for the returned date (default is Y-m-d H:i:s) * @return string GMT version of the date provided. */ function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) { $tz = get_option( 'timezone_string' ); if ( $tz ) { $datetime = date_create( $string, new DateTimeZone( $tz ) ); if ( ! $datetime ) { return gmdate( $format, 0 ); } $datetime->setTimezone( new DateTimeZone( 'UTC' ) ); $string_gmt = $datetime->format( $format ); } else { if ( ! preg_match( '#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches ) ) { $datetime = strtotime( $string ); if ( false === $datetime ) { return gmdate( $format, 0 ); } return gmdate( $format, $datetime ); } $string_time = gmmktime( $matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1] ); $string_gmt = gmdate( $format, $string_time - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); } return $string_gmt; } /** * Converts a GMT date into the correct format for the blog. * * Requires and returns a date in the Y-m-d H:i:s format. If there is a * timezone_string available, the returned date is in that timezone, otherwise * it simply adds the value of gmt_offset. Return format can be overridden * using the $format parameter * * @since 1.2.0 * * @param string $string The date to be converted. * @param string $format The format string for the returned date (default is Y-m-d H:i:s) * @return string Formatted date relative to the timezone / GMT offset. */ function get_date_from_gmt( $string, $format = 'Y-m-d H:i:s' ) { $tz = get_option( 'timezone_string' ); if ( $tz ) { $datetime = date_create( $string, new DateTimeZone( 'UTC' ) ); if ( ! $datetime ) return date( $format, 0 ); $datetime->setTimezone( new DateTimeZone( $tz ) ); $string_localtime = $datetime->format( $format ); } else { if ( ! preg_match('#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches) ) return date( $format, 0 ); $string_time = gmmktime( $matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1] ); $string_localtime = gmdate( $format, $string_time + get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); } return $string_localtime; } /** * Computes an offset in seconds from an iso8601 timezone. * * @since 1.5.0 * * @param string $timezone Either 'Z' for 0 offset or '±hhmm'. * @return int|float The offset in seconds. */ function iso8601_timezone_to_offset( $timezone ) { // $timezone is either 'Z' or '[+|-]hhmm' if ($timezone == 'Z') { $offset = 0; } else { $sign = (substr($timezone, 0, 1) == '+') ? 1 : -1; $hours = intval(substr($timezone, 1, 2)); $minutes = intval(substr($timezone, 3, 4)) / 60; $offset = $sign * HOUR_IN_SECONDS * ($hours + $minutes); } return $offset; } /** * Converts an iso8601 date to MySQL DateTime format used by post_date[_gmt]. * * @since 1.5.0 * * @param string $date_string Date and time in ISO 8601 format {@link https://en.wikipedia.org/wiki/ISO_8601}. * @param string $timezone Optional. If set to GMT returns the time minus gmt_offset. Default is 'user'. * @return string The date and time in MySQL DateTime format - Y-m-d H:i:s. */ function iso8601_to_datetime( $date_string, $timezone = 'user' ) { $timezone = strtolower($timezone); if ($timezone == 'gmt') { 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); if (!empty($date_bits[7])) { // we have a timezone, so let's compute an offset $offset = iso8601_timezone_to_offset($date_bits[7]); } else { // we don't have a timezone, so we assume user local timezone (not server's!) $offset = HOUR_IN_SECONDS * get_option('gmt_offset'); } $timestamp = gmmktime($date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1]); $timestamp -= $offset; return gmdate('Y-m-d H:i:s', $timestamp); } elseif ($timezone == 'user') { 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); } } /** * Strips out all characters that are not allowable in an email. * * @since 1.5.0 * * @param string $email Email address to filter. * @return string Filtered email address. */ function sanitize_email( $email ) { // Test for the minimum length the email can be if ( strlen( $email ) < 6 ) { /** * Filters a sanitized email address. * * This filter is evaluated under several contexts, including 'email_too_short', * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits', * 'domain_no_periods', 'domain_no_valid_subs', or no context. * * @since 2.8.0 * * @param string $email The sanitized email address. * @param string $email The email address, as provided to sanitize_email(). * @param string $message A message to pass to the user. */ return apply_filters( 'sanitize_email', '', $email, 'email_too_short' ); } // Test for an @ character after the first position if ( strpos( $email, '@', 1 ) === false ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'sanitize_email', '', $email, 'email_no_at' ); } // Split out the local and domain parts list( $local, $domain ) = explode( '@', $email, 2 ); // LOCAL PART // Test for invalid characters $local = preg_replace( '/[^a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]/', '', $local ); if ( '' === $local ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'sanitize_email', '', $email, 'local_invalid_chars' ); } // DOMAIN PART // Test for sequences of periods $domain = preg_replace( '/\.{2,}/', '', $domain ); if ( '' === $domain ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'sanitize_email', '', $email, 'domain_period_sequence' ); } // Test for leading and trailing periods and whitespace $domain = trim( $domain, " \t\n\r\0\x0B." ); if ( '' === $domain ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'sanitize_email', '', $email, 'domain_period_limits' ); } // Split the domain into subs $subs = explode( '.', $domain ); // Assume the domain will have at least two subs if ( 2 > count( $subs ) ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'sanitize_email', '', $email, 'domain_no_periods' ); } // Create an array that will contain valid subs $new_subs = array(); // Loop through each sub foreach ( $subs as $sub ) { // Test for leading and trailing hyphens $sub = trim( $sub, " \t\n\r\0\x0B-" ); // Test for invalid characters $sub = preg_replace( '/[^a-z0-9-]+/i', '', $sub ); // If there's anything left, add it to the valid subs if ( '' !== $sub ) { $new_subs[] = $sub; } } // If there aren't 2 or more valid subs if ( 2 > count( $new_subs ) ) { /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'sanitize_email', '', $email, 'domain_no_valid_subs' ); } // Join valid subs into the new domain $domain = join( '.', $new_subs ); // Put the email back together $email = $local . '@' . $domain; // Congratulations your email made it! /** This filter is documented in wp-includes/formatting.php */ return apply_filters( 'sanitize_email', $email, $email, null ); } /** * Determines the difference between two timestamps. * * The difference is returned in a human readable format such as "1 hour", * "5 mins", "2 days". * * @since 1.5.0 * * @param int $from Unix timestamp from which the difference begins. * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. * @return string Human readable time difference. */ function human_time_diff( $from, $to = '' ) { if ( empty( $to ) ) { $to = time(); } $diff = (int) abs( $to - $from ); if ( $diff < HOUR_IN_SECONDS ) { $mins = round( $diff / MINUTE_IN_SECONDS ); if ( $mins <= 1 ) $mins = 1; /* translators: Time difference between two dates, in minutes (min=minute). 1: Number of minutes */ $since = sprintf( _n( '%s min', '%s mins', $mins ), $mins ); } elseif ( $diff < DAY_IN_SECONDS && $diff >= HOUR_IN_SECONDS ) { $hours = round( $diff / HOUR_IN_SECONDS ); if ( $hours <= 1 ) $hours = 1; /* translators: Time difference between two dates, in hours. 1: Number of hours */ $since = sprintf( _n( '%s hour', '%s hours', $hours ), $hours ); } elseif ( $diff < WEEK_IN_SECONDS && $diff >= DAY_IN_SECONDS ) { $days = round( $diff / DAY_IN_SECONDS ); if ( $days <= 1 ) $days = 1; /* translators: Time difference between two dates, in days. 1: Number of days */ $since = sprintf( _n( '%s day', '%s days', $days ), $days ); } elseif ( $diff < MONTH_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) { $weeks = round( $diff / WEEK_IN_SECONDS ); if ( $weeks <= 1 ) $weeks = 1; /* translators: Time difference between two dates, in weeks. 1: Number of weeks */ $since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks ); } elseif ( $diff < YEAR_IN_SECONDS && $diff >= MONTH_IN_SECONDS ) { $months = round( $diff / MONTH_IN_SECONDS ); if ( $months <= 1 ) $months = 1; /* translators: Time difference between two dates, in months. 1: Number of months */ $since = sprintf( _n( '%s month', '%s months', $months ), $months ); } elseif ( $diff >= YEAR_IN_SECONDS ) { $years = round( $diff / YEAR_IN_SECONDS ); if ( $years <= 1 ) $years = 1; /* translators: Time difference between two dates, in years. 1: Number of years */ $since = sprintf( _n( '%s year', '%s years', $years ), $years ); } /** * Filters the human readable difference between two timestamps. * * @since 4.0.0 * * @param string $since The difference in human readable text. * @param int $diff The difference in seconds. * @param int $from Unix timestamp from which the difference begins. * @param int $to Unix timestamp to end the time difference. */ return apply_filters( 'human_time_diff', $since, $diff, $from, $to ); } /** * Generates an excerpt from the content, if needed. * * The excerpt word amount will be 55 words and if the amount is greater than * that, then the string ' […]' will be appended to the excerpt. If the string * is less than 55 words, then the content will be returned as is. * * The 55 word limit can be modified by plugins/themes using the {@see 'excerpt_length'} filter * The ' […]' string can be modified by plugins/themes using the {@see 'excerpt_more'} filter * * @since 1.5.0 * * @param string $text Optional. The excerpt. If set to empty, an excerpt is generated. * @return string The excerpt. */ function wp_trim_excerpt( $text = '' ) { $raw_excerpt = $text; if ( '' == $text ) { $text = get_the_content(''); $text = strip_shortcodes( $text ); /** This filter is documented in wp-includes/post-template.php */ $text = apply_filters( 'the_content', $text ); $text = str_replace(']]>', ']]>', $text); /** * Filters the number of words in an excerpt. * * @since 2.7.0 * * @param int $number The number of words. Default 55. */ $excerpt_length = apply_filters( 'excerpt_length', 55 ); /** * Filters the string in the "more" link displayed after a trimmed excerpt. * * @since 2.9.0 * * @param string $more_string The string shown within the more link. */ $excerpt_more = apply_filters( 'excerpt_more', ' ' . '[…]' ); $text = wp_trim_words( $text, $excerpt_length, $excerpt_more ); } /** * Filters the trimmed excerpt string. * * @since 2.8.0 * * @param string $text The trimmed text. * @param string $raw_excerpt The text prior to trimming. */ return apply_filters( 'wp_trim_excerpt', $text, $raw_excerpt ); } /** * Trims text to a certain number of words. * * This function is localized. For languages that count 'words' by the individual * character (such as East Asian languages), the $num_words argument will apply * to the number of individual characters. * * @since 3.3.0 * * @param string $text Text to trim. * @param int $num_words Number of words. Default 55. * @param string $more Optional. What to append if $text needs to be trimmed. Default '…'. * @return string Trimmed text. */ function wp_trim_words( $text, $num_words = 55, $more = null ) { if ( null === $more ) { $more = __( '…' ); } $original_text = $text; $text = wp_strip_all_tags( $text ); /* * translators: If your word count is based on single characters (e.g. East Asian characters), * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. * Do not translate into your own language. */ if ( strpos( _x( 'words', 'Word count type. Do not translate!' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) { $text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' ); preg_match_all( '/./u', $text, $words_array ); $words_array = array_slice( $words_array[0], 0, $num_words + 1 ); $sep = ''; } else { $words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY ); $sep = ' '; } if ( count( $words_array ) > $num_words ) { array_pop( $words_array ); $text = implode( $sep, $words_array ); $text = $text . $more; } else { $text = implode( $sep, $words_array ); } /** * Filters the text content after words have been trimmed. * * @since 3.3.0 * * @param string $text The trimmed text. * @param int $num_words The number of words to trim the text to. Default 55. * @param string $more An optional string to append to the end of the trimmed text, e.g. …. * @param string $original_text The text before it was trimmed. */ return apply_filters( 'wp_trim_words', $text, $num_words, $more, $original_text ); } /** * Converts named entities into numbered entities. * * @since 1.5.1 * * @param string $text The text within which entities will be converted. * @return string Text with converted entities. */ function ent2ncr( $text ) { /** * Filters text before named entities are converted into numbered entities. * * A non-null string must be returned for the filter to be evaluated. * * @since 3.3.0 * * @param null $converted_text The text to be converted. Default null. * @param string $text The text prior to entity conversion. */ $filtered = apply_filters( 'pre_ent2ncr', null, $text ); if ( null !== $filtered ) return $filtered; $to_ncr = array( '"' => '"', '&' => '&', '<' => '<', '>' => '>', '|' => '|', ' ' => ' ', '¡' => '¡', '¢' => '¢', '£' => '£', '¤' => '¤', '¥' => '¥', '¦' => '¦', '&brkbar;' => '¦', '§' => '§', '¨' => '¨', '¨' => '¨', '©' => '©', 'ª' => 'ª', '«' => '«', '¬' => '¬', '­' => '­', '®' => '®', '¯' => '¯', '&hibar;' => '¯', '°' => '°', '±' => '±', '²' => '²', '³' => '³', '´' => '´', 'µ' => 'µ', '¶' => '¶', '·' => '·', '¸' => '¸', '¹' => '¹', 'º' => 'º', '»' => '»', '¼' => '¼', '½' => '½', '¾' => '¾', '¿' => '¿', 'À' => 'À', 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', 'Æ' => 'Æ', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', 'Ð' => 'Ð', 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', '×' => '×', 'Ø' => 'Ø', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', 'Ü' => 'Ü', 'Ý' => 'Ý', 'Þ' => 'Þ', 'ß' => 'ß', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'æ' => 'æ', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ð' => 'ð', 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', '÷' => '÷', 'ø' => 'ø', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'þ' => 'þ', 'ÿ' => 'ÿ', 'Œ' => 'Œ', 'œ' => 'œ', 'Š' => 'Š', 'š' => 'š', 'Ÿ' => 'Ÿ', 'ƒ' => 'ƒ', 'ˆ' => 'ˆ', '˜' => '˜', 'Α' => 'Α', 'Β' => 'Β', 'Γ' => 'Γ', 'Δ' => 'Δ', 'Ε' => 'Ε', 'Ζ' => 'Ζ', 'Η' => 'Η', 'Θ' => 'Θ', 'Ι' => 'Ι', 'Κ' => 'Κ', 'Λ' => 'Λ', 'Μ' => 'Μ', 'Ν' => 'Ν', 'Ξ' => 'Ξ', 'Ο' => 'Ο', 'Π' => 'Π', 'Ρ' => 'Ρ', 'Σ' => 'Σ', 'Τ' => 'Τ', 'Υ' => 'Υ', 'Φ' => 'Φ', 'Χ' => 'Χ', 'Ψ' => 'Ψ', 'Ω' => 'Ω', 'α' => 'α', 'β' => 'β', 'γ' => 'γ', 'δ' => 'δ', 'ε' => 'ε', 'ζ' => 'ζ', 'η' => 'η', 'θ' => 'θ', 'ι' => 'ι', 'κ' => 'κ', 'λ' => 'λ', 'μ' => 'μ', 'ν' => 'ν', 'ξ' => 'ξ', 'ο' => 'ο', 'π' => 'π', 'ρ' => 'ρ', 'ς' => 'ς', 'σ' => 'σ', 'τ' => 'τ', 'υ' => 'υ', 'φ' => 'φ', 'χ' => 'χ', 'ψ' => 'ψ', 'ω' => 'ω', 'ϑ' => 'ϑ', 'ϒ' => 'ϒ', 'ϖ' => 'ϖ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '‌' => '‌', '‍' => '‍', '‎' => '‎', '‏' => '‏', '–' => '–', '—' => '—', '‘' => '‘', '’' => '’', '‚' => '‚', '“' => '“', '”' => '”', '„' => '„', '†' => '†', '‡' => '‡', '•' => '•', '…' => '…', '‰' => '‰', '′' => '′', '″' => '″', '‹' => '‹', '›' => '›', '‾' => '‾', '⁄' => '⁄', '€' => '€', 'ℑ' => 'ℑ', '℘' => '℘', 'ℜ' => 'ℜ', '™' => '™', 'ℵ' => 'ℵ', '↵' => '↵', '⇐' => '⇐', '⇑' => '⇑', '⇒' => '⇒', '⇓' => '⇓', '⇔' => '⇔', '∀' => '∀', '∂' => '∂', '∃' => '∃', '∅' => '∅', '∇' => '∇', '∈' => '∈', '∉' => '∉', '∋' => '∋', '∏' => '∏', '∑' => '∑', '−' => '−', '∗' => '∗', '√' => '√', '∝' => '∝', '∞' => '∞', '∠' => '∠', '∧' => '∧', '∨' => '∨', '∩' => '∩', '∪' => '∪', '∫' => '∫', '∴' => '∴', '∼' => '∼', '≅' => '≅', '≈' => '≈', '≠' => '≠', '≡' => '≡', '≤' => '≤', '≥' => '≥', '⊂' => '⊂', '⊃' => '⊃', '⊄' => '⊄', '⊆' => '⊆', '⊇' => '⊇', '⊕' => '⊕', '⊗' => '⊗', '⊥' => '⊥', '⋅' => '⋅', '⌈' => '⌈', '⌉' => '⌉', '⌊' => '⌊', '⌋' => '⌋', '⟨' => '〈', '⟩' => '〉', '←' => '←', '↑' => '↑', '→' => '→', '↓' => '↓', '↔' => '↔', '◊' => '◊', '♠' => '♠', '♣' => '♣', '♥' => '♥', '♦' => '♦' ); return str_replace( array_keys($to_ncr), array_values($to_ncr), $text ); } /** * Formats text for the editor. * * Generally the browsers treat everything inside a textarea as text, but * it is still a good idea to HTML entity encode `<`, `>` and `&` in the content. * * The filter {@see 'format_for_editor'} is applied here. If `$text` is empty the * filter will be applied to an empty string. * * @since 4.3.0 * * @see _WP_Editors::editor() * * @param string $text The text to be formatted. * @param string $default_editor The default editor for the current user. * It is usually either 'html' or 'tinymce'. * @return string The formatted text after filter is applied. */ function format_for_editor( $text, $default_editor = null ) { if ( $text ) { $text = htmlspecialchars( $text, ENT_NOQUOTES, get_option( 'blog_charset' ) ); } /** * Filters the text after it is formatted for the editor. * * @since 4.3.0 * * @param string $text The formatted text. * @param string $default_editor The default editor for the current user. * It is usually either 'html' or 'tinymce'. */ return apply_filters( 'format_for_editor', $text, $default_editor ); } /** * Perform a deep string replace operation to ensure the values in $search are no longer present * * Repeats the replacement operation until it no longer replaces anything so as to remove "nested" values * e.g. $subject = '%0%0%0DDD', $search ='%0D', $result ='' rather than the '%0%0DD' that * str_replace would return * * @since 2.8.1 * @access private * * @param string|array $search The value being searched for, otherwise known as the needle. * An array may be used to designate multiple needles. * @param string $subject The string being searched and replaced on, otherwise known as the haystack. * @return string The string with the replaced svalues. */ function _deep_replace( $search, $subject ) { $subject = (string) $subject; $count = 1; while ( $count ) { $subject = str_replace( $search, '', $subject, $count ); } return $subject; } /** * Escapes data for use in a MySQL query. * * Usually you should prepare queries using wpdb::prepare(). * Sometimes, spot-escaping is required or useful. One example * is preparing an array for use in an IN clause. * * NOTE: Since 4.8.3, '%' characters will be replaced with a placeholder string, * this prevents certain SQLi attacks from taking place. This change in behaviour * may cause issues for code that expects the return value of esc_sql() to be useable * for other purposes. * * @since 2.8.0 * * @global wpdb $wpdb WordPress database abstraction object. * * @param string|array $data Unescaped data * @return string|array Escaped data */ function esc_sql( $data ) { global $wpdb; return $wpdb->_escape( $data ); } /** * Checks and cleans a URL. * * A number of characters are removed from the URL. If the URL is for displaying * (the default behaviour) ampersands are also replaced. The {@see 'clean_url'} filter * is applied to the returned cleaned URL. * * @since 2.8.0 * * @param string $url The URL to be cleaned. * @param array $protocols Optional. An array of acceptable protocols. * Defaults to return value of wp_allowed_protocols() * @param string $_context Private. Use esc_url_raw() for database usage. * @return string The cleaned $url after the {@see 'clean_url'} filter is applied. */ function esc_url( $url, $protocols = null, $_context = 'display' ) { $original_url = $url; if ( '' == $url ) return $url; $url = str_replace( ' ', '%20', $url ); $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url); if ( '' === $url ) { return $url; } if ( 0 !== stripos( $url, 'mailto:' ) ) { $strip = array('%0d', '%0a', '%0D', '%0A'); $url = _deep_replace($strip, $url); } $url = str_replace(';//', '://', $url); /* If the URL doesn't appear to contain a scheme, we * presume it needs http:// prepended (unless a relative * link starting with /, # or ? or a php file). */ if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) && ! preg_match('/^[a-z0-9-]+?\.php/i', $url) ) $url = 'http://' . $url; // Replace ampersands and single quotes only when displaying. if ( 'display' == $_context ) { $url = wp_kses_normalize_entities( $url ); $url = str_replace( '&', '&', $url ); $url = str_replace( "'", ''', $url ); } if ( ( false !== strpos( $url, '[' ) ) || ( false !== strpos( $url, ']' ) ) ) { $parsed = wp_parse_url( $url ); $front = ''; if ( isset( $parsed['scheme'] ) ) { $front .= $parsed['scheme'] . '://'; } elseif ( '/' === $url[0] ) { $front .= '//'; } if ( isset( $parsed['user'] ) ) { $front .= $parsed['user']; } if ( isset( $parsed['pass'] ) ) { $front .= ':' . $parsed['pass']; } if ( isset( $parsed['user'] ) || isset( $parsed['pass'] ) ) { $front .= '@'; } if ( isset( $parsed['host'] ) ) { $front .= $parsed['host']; } if ( isset( $parsed['port'] ) ) { $front .= ':' . $parsed['port']; } $end_dirty = str_replace( $front, '', $url ); $end_clean = str_replace( array( '[', ']' ), array( '%5B', '%5D' ), $end_dirty ); $url = str_replace( $end_dirty, $end_clean, $url ); } if ( '/' === $url[0] ) { $good_protocol_url = $url; } else { if ( ! is_array( $protocols ) ) $protocols = wp_allowed_protocols(); $good_protocol_url = wp_kses_bad_protocol( $url, $protocols ); if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) return ''; } /** * Filters a string cleaned and escaped for output as a URL. * * @since 2.3.0 * * @param string $good_protocol_url The cleaned URL to be returned. * @param string $original_url The URL prior to cleaning. * @param string $_context If 'display', replace ampersands and single quotes only. */ return apply_filters( 'clean_url', $good_protocol_url, $original_url, $_context ); } /** * Performs esc_url() for database usage. * * @since 2.8.0 * * @param string $url The URL to be cleaned. * @param array $protocols An array of acceptable protocols. * @return string The cleaned URL. */ function esc_url_raw( $url, $protocols = null ) { return esc_url( $url, $protocols, 'db' ); } /** * Convert entities, while preserving already-encoded entities. * * @link https://secure.php.net/htmlentities Borrowed from the PHP Manual user notes. * * @since 1.2.2 * * @param string $myHTML The text to be converted. * @return string Converted text. */ function htmlentities2( $myHTML ) { $translation_table = get_html_translation_table( HTML_ENTITIES, ENT_QUOTES ); $translation_table[chr(38)] = '&'; return preg_replace( "/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/", "&", strtr($myHTML, $translation_table) ); } /** * Escape single quotes, htmlspecialchar " < > &, and fix line endings. * * Escapes text strings for echoing in JS. It is intended to be used for inline JS * (in a tag attribute, for example onclick="..."). Note that the strings have to * be in single quotes. The {@see 'js_escape'} filter is also applied here. * * @since 2.8.0 * * @param string $text The text to be escaped. * @return string Escaped text. */ function esc_js( $text ) { $safe_text = wp_check_invalid_utf8( $text ); $safe_text = _wp_specialchars( $safe_text, ENT_COMPAT ); $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) ); $safe_text = str_replace( "\r", '', $safe_text ); $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) ); /** * Filters a string cleaned and escaped for output in JavaScript. * * Text passed to esc_js() is stripped of invalid or special characters, * and properly slashed for output. * * @since 2.0.6 * * @param string $safe_text The text after it has been escaped. * @param string $text The text prior to being escaped. */ return apply_filters( 'js_escape', $safe_text, $text ); } /** * Escaping for HTML blocks. * * @since 2.8.0 * * @param string $text * @return string */ function esc_html( $text ) { $safe_text = wp_check_invalid_utf8( $text ); $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); /** * Filters a string cleaned and escaped for output in HTML. * * Text passed to esc_html() is stripped of invalid or special characters * before output. * * @since 2.8.0 * * @param string $safe_text The text after it has been escaped. * @param string $text The text prior to being escaped. */ return apply_filters( 'esc_html', $safe_text, $text ); } /** * Escaping for HTML attributes. * * @since 2.8.0 * * @param string $text * @return string */ function esc_attr( $text ) { $safe_text = wp_check_invalid_utf8( $text ); $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); /** * Filters a string cleaned and escaped for output in an HTML attribute. * * Text passed to esc_attr() is stripped of invalid or special characters * before output. * * @since 2.0.6 * * @param string $safe_text The text after it has been escaped. * @param string $text The text prior to being escaped. */ return apply_filters( 'attribute_escape', $safe_text, $text ); } /** * Escaping for textarea values. * * @since 3.1.0 * * @param string $text * @return string */ function esc_textarea( $text ) { $safe_text = htmlspecialchars( $text, ENT_QUOTES, get_option( 'blog_charset' ) ); /** * Filters a string cleaned and escaped for output in a textarea element. * * @since 3.1.0 * * @param string $safe_text The text after it has been escaped. * @param string $text The text prior to being escaped. */ return apply_filters( 'esc_textarea', $safe_text, $text ); } /** * Escape an HTML tag name. * * @since 2.5.0 * * @param string $tag_name * @return string */ function tag_escape( $tag_name ) { $safe_tag = strtolower( preg_replace('/[^a-zA-Z0-9_:]/', '', $tag_name) ); /** * Filters a string cleaned and escaped for output as an HTML tag. * * @since 2.8.0 * * @param string $safe_tag The tag name after it has been escaped. * @param string $tag_name The text before it was escaped. */ return apply_filters( 'tag_escape', $safe_tag, $tag_name ); } /** * Convert full URL paths to absolute paths. * * Removes the http or https protocols and the domain. Keeps the path '/' at the * beginning, so it isn't a true relative link, but from the web root base. * * @since 2.1.0 * @since 4.1.0 Support was added for relative URLs. * * @param string $link Full URL path. * @return string Absolute path. */ function wp_make_link_relative( $link ) { return preg_replace( '|^(https?:)?//[^/]+(/?.*)|i', '$2', $link ); } /** * Sanitises various option values based on the nature of the option. * * This is basically a switch statement which will pass $value through a number * of functions depending on the $option. * * @since 2.0.5 * * @global wpdb $wpdb WordPress database abstraction object. * * @param string $option The name of the option. * @param string $value The unsanitised value. * @return string Sanitized value. */ function sanitize_option( $option, $value ) { global $wpdb; $original_value = $value; $error = ''; switch ( $option ) { case 'admin_email' : case 'new_admin_email' : $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); if ( is_wp_error( $value ) ) { $error = $value->get_error_message(); } else { $value = sanitize_email( $value ); if ( ! is_email( $value ) ) { $error = __( 'The email address entered did not appear to be a valid email address. Please enter a valid email address.' ); } } break; case 'thumbnail_size_w': case 'thumbnail_size_h': case 'medium_size_w': case 'medium_size_h': case 'medium_large_size_w': case 'medium_large_size_h': case 'large_size_w': case 'large_size_h': case 'mailserver_port': case 'comment_max_links': case 'page_on_front': case 'page_for_posts': case 'rss_excerpt_length': case 'default_category': case 'default_email_category': case 'default_link_category': case 'close_comments_days_old': case 'comments_per_page': case 'thread_comments_depth': case 'users_can_register': case 'start_of_week': case 'site_icon': $value = absint( $value ); break; case 'posts_per_page': case 'posts_per_rss': $value = (int) $value; if ( empty($value) ) $value = 1; if ( $value < -1 ) $value = abs($value); break; case 'default_ping_status': case 'default_comment_status': // Options that if not there have 0 value but need to be something like "closed" if ( $value == '0' || $value == '') $value = 'closed'; break; case 'blogdescription': case 'blogname': $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); if ( $value !== $original_value ) { $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', wp_encode_emoji( $original_value ) ); } if ( is_wp_error( $value ) ) { $error = $value->get_error_message(); } else { $value = esc_html( $value ); } break; case 'blog_charset': $value = preg_replace('/[^a-zA-Z0-9_-]/', '', $value); // strips slashes break; case 'blog_public': // This is the value if the settings checkbox is not checked on POST. Don't rely on this. if ( null === $value ) $value = 1; else $value = intval( $value ); break; case 'date_format': case 'time_format': case 'mailserver_url': case 'mailserver_login': case 'mailserver_pass': case 'upload_path': $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); if ( is_wp_error( $value ) ) { $error = $value->get_error_message(); } else { $value = strip_tags( $value ); $value = wp_kses_data( $value ); } break; case 'ping_sites': $value = explode( "\n", $value ); $value = array_filter( array_map( 'trim', $value ) ); $value = array_filter( array_map( 'esc_url_raw', $value ) ); $value = implode( "\n", $value ); break; case 'gmt_offset': $value = preg_replace('/[^0-9:.-]/', '', $value); // strips slashes break; case 'siteurl': $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); if ( is_wp_error( $value ) ) { $error = $value->get_error_message(); } else { if ( preg_match( '#http(s?)://(.+)#i', $value ) ) { $value = esc_url_raw( $value ); } else { $error = __( 'The WordPress address you entered did not appear to be a valid URL. Please enter a valid URL.' ); } } break; case 'home': $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); if ( is_wp_error( $value ) ) { $error = $value->get_error_message(); } else { if ( preg_match( '#http(s?)://(.+)#i', $value ) ) { $value = esc_url_raw( $value ); } else { $error = __( 'The Site address you entered did not appear to be a valid URL. Please enter a valid URL.' ); } } break; case 'WPLANG': $allowed = get_available_languages(); if ( ! is_multisite() && defined( 'WPLANG' ) && '' !== WPLANG && 'en_US' !== WPLANG ) { $allowed[] = WPLANG; } if ( ! in_array( $value, $allowed ) && ! empty( $value ) ) { $value = get_option( $option ); } break; case 'illegal_names': $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); if ( is_wp_error( $value ) ) { $error = $value->get_error_message(); } else { if ( ! is_array( $value ) ) $value = explode( ' ', $value ); $value = array_values( array_filter( array_map( 'trim', $value ) ) ); if ( ! $value ) $value = ''; } break; case 'limited_email_domains': case 'banned_email_domains': $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); if ( is_wp_error( $value ) ) { $error = $value->get_error_message(); } else { if ( ! is_array( $value ) ) $value = explode( "\n", $value ); $domains = array_values( array_filter( array_map( 'trim', $value ) ) ); $value = array(); foreach ( $domains as $domain ) { if ( ! preg_match( '/(--|\.\.)/', $domain ) && preg_match( '|^([a-zA-Z0-9-\.])+$|', $domain ) ) { $value[] = $domain; } } if ( ! $value ) $value = ''; } break; case 'timezone_string': $allowed_zones = timezone_identifiers_list(); if ( ! in_array( $value, $allowed_zones ) && ! empty( $value ) ) { $error = __( 'The timezone you have entered is not valid. Please select a valid timezone.' ); } break; case 'permalink_structure': case 'category_base': case 'tag_base': $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); if ( is_wp_error( $value ) ) { $error = $value->get_error_message(); } else { $value = esc_url_raw( $value ); $value = str_replace( 'http://', '', $value ); } if ( 'permalink_structure' === $option && '' !== $value && ! preg_match( '/%[^\/%]+%/', $value ) ) { $error = sprintf( /* translators: %s: Codex URL */ __( 'A structure tag is required when using custom permalinks. Learn more' ), __( 'https://codex.wordpress.org/Using_Permalinks#Choosing_your_permalink_structure' ) ); } break; case 'default_role' : if ( ! get_role( $value ) && get_role( 'subscriber' ) ) $value = 'subscriber'; break; case 'moderation_keys': case 'blacklist_keys': $value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value ); if ( is_wp_error( $value ) ) { $error = $value->get_error_message(); } else { $value = explode( "\n", $value ); $value = array_filter( array_map( 'trim', $value ) ); $value = array_unique( $value ); $value = implode( "\n", $value ); } break; } if ( ! empty( $error ) ) { $value = get_option( $option ); if ( function_exists( 'add_settings_error' ) ) { add_settings_error( $option, "invalid_{$option}", $error ); } } /** * Filters an option value following sanitization. * * @since 2.3.0 * @since 4.3.0 Added the `$original_value` parameter. * * @param string $value The sanitized option value. * @param string $option The option name. * @param string $original_value The original value passed to the function. */ return apply_filters( "sanitize_option_{$option}", $value, $option, $original_value ); } /** * Maps a function to all non-iterable elements of an array or an object. * * This is similar to `array_walk_recursive()` but acts upon objects too. * * @since 4.4.0 * * @param mixed $value The array, object, or scalar. * @param callable $callback The function to map onto $value. * @return mixed The value with the callback applied to all non-arrays and non-objects inside it. */ function map_deep( $value, $callback ) { if ( is_array( $value ) ) { foreach ( $value as $index => $item ) { $value[ $index ] = map_deep( $item, $callback ); } } elseif ( is_object( $value ) ) { $object_vars = get_object_vars( $value ); foreach ( $object_vars as $property_name => $property_value ) { $value->$property_name = map_deep( $property_value, $callback ); } } else { $value = call_user_func( $callback, $value ); } return $value; } /** * Parses a string into variables to be stored in an array. * * Uses {@link https://secure.php.net/parse_str parse_str()} and stripslashes if * {@link https://secure.php.net/magic_quotes magic_quotes_gpc} is on. * * @since 2.2.1 * * @param string $string The string to be parsed. * @param array $array Variables will be stored in this array. */ function wp_parse_str( $string, &$array ) { parse_str( $string, $array ); if ( get_magic_quotes_gpc() ) $array = stripslashes_deep( $array ); /** * Filters the array of variables derived from a parsed string. * * @since 2.3.0 * * @param array $array The array populated with variables. */ $array = apply_filters( 'wp_parse_str', $array ); } /** * Convert lone less than signs. * * KSES already converts lone greater than signs. * * @since 2.3.0 * * @param string $text Text to be converted. * @return string Converted text. */ function wp_pre_kses_less_than( $text ) { return preg_replace_callback('%<[^>]*?((?=<)|>|$)%', 'wp_pre_kses_less_than_callback', $text); } /** * Callback function used by preg_replace. * * @since 2.3.0 * * @param array $matches Populated by matches to preg_replace. * @return string The text returned after esc_html if needed. */ function wp_pre_kses_less_than_callback( $matches ) { if ( false === strpos($matches[0], '>') ) return esc_html($matches[0]); return $matches[0]; } /** * WordPress implementation of PHP sprintf() with filters. * * @since 2.5.0 * @link https://secure.php.net/sprintf * * @param string $pattern The string which formatted args are inserted. * @param mixed $args ,... Arguments to be formatted into the $pattern string. * @return string The formatted string. */ function wp_sprintf( $pattern ) { $args = func_get_args(); $len = strlen($pattern); $start = 0; $result = ''; $arg_index = 0; while ( $len > $start ) { // Last character: append and break if ( strlen($pattern) - 1 == $start ) { $result .= substr($pattern, -1); break; } // Literal %: append and continue if ( substr($pattern, $start, 2) == '%%' ) { $start += 2; $result .= '%'; continue; } // Get fragment before next % $end = strpos($pattern, '%', $start + 1); if ( false === $end ) $end = $len; $fragment = substr($pattern, $start, $end - $start); // Fragment has a specifier if ( $pattern[$start] == '%' ) { // Find numbered arguments or take the next one in order if ( preg_match('/^%(\d+)\$/', $fragment, $matches) ) { $arg = isset($args[$matches[1]]) ? $args[$matches[1]] : ''; $fragment = str_replace("%{$matches[1]}$", '%', $fragment); } else { ++$arg_index; $arg = isset($args[$arg_index]) ? $args[$arg_index] : ''; } /** * Filters a fragment from the pattern passed to wp_sprintf(). * * If the fragment is unchanged, then sprintf() will be run on the fragment. * * @since 2.5.0 * * @param string $fragment A fragment from the pattern. * @param string $arg The argument. */ $_fragment = apply_filters( 'wp_sprintf', $fragment, $arg ); if ( $_fragment != $fragment ) $fragment = $_fragment; else $fragment = sprintf($fragment, strval($arg) ); } // Append to result and move to next fragment $result .= $fragment; $start = $end; } return $result; } /** * Localize list items before the rest of the content. * * The '%l' must be at the first characters can then contain the rest of the *