| [ Index ] |
PHP Cross Reference of Wordpress 2.7.1 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Main Wordpress Formatting API. 4 * 5 * Handles many functions for formatting output. 6 * 7 * @package WordPress 8 **/ 9 10 /** 11 * Replaces common plain text characters into formatted entities 12 * 13 * As an example, 14 * <code> 15 * 'cause today's effort makes it worth tomorrow's "holiday"... 16 * </code> 17 * Becomes: 18 * <code> 19 * ’cause today’s effort makes it worth tomorrow’s “holiday”… 20 * </code> 21 * Code within certain html blocks are skipped. 22 * 23 * @since 0.71 24 * @uses $wp_cockneyreplace Array of formatted entities for certain common phrases 25 * 26 * @param string $text The text to be formatted 27 * @return string The string replaced with html entities 28 */ 29 function wptexturize($text) { 30 global $wp_cockneyreplace; 31 $next = true; 32 $has_pre_parent = false; 33 $output = ''; 34 $curl = ''; 35 $textarr = preg_split('/(<.*>|\[.*\])/Us', $text, -1, PREG_SPLIT_DELIM_CAPTURE); 36 $stop = count($textarr); 37 38 // if a plugin has provided an autocorrect array, use it 39 if ( isset($wp_cockneyreplace) ) { 40 $cockney = array_keys($wp_cockneyreplace); 41 $cockneyreplace = array_values($wp_cockneyreplace); 42 } else { 43 $cockney = array("'tain't","'twere","'twas","'tis","'twill","'til","'bout","'nuff","'round","'cause"); 44 $cockneyreplace = array("’tain’t","’twere","’twas","’tis","’twill","’til","’bout","’nuff","’round","’cause"); 45 } 46 47 $static_characters = array_merge(array('---', ' -- ', '--', 'xn–', '...', '``', '\'s', '\'\'', ' (tm)'), $cockney); 48 $static_replacements = array_merge(array('—', ' — ', '–', 'xn--', '…', '“', '’s', '”', ' ™'), $cockneyreplace); 49 50 $dynamic_characters = array('/\'(\d\d(?:’|\')?s)/', '/(\s|\A|")\'/', '/(\d+)"/', '/(\d+)\'/', '/(\S)\'([^\'\s])/', '/(\s|\A)"(?!\s)/', '/"(\s|\S|\Z)/', '/\'([\s.]|\Z)/', '/(\d+)x(\d+)/'); 51 $dynamic_replacements = array('’$1','$1‘', '$1″', '$1′', '$1’$2', '$1“$2', '”$1', '’$1', '$1×$2'); 52 53 for ( $i = 0; $i < $stop; $i++ ) { 54 $curl = $textarr[$i]; 55 56 if ( !empty($curl) && '<' != $curl{0} && '[' != $curl{0} && $next && !$has_pre_parent) { // If it's not a tag 57 // static strings 58 $curl = str_replace($static_characters, $static_replacements, $curl); 59 // regular expressions 60 $curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl); 61 } elseif (strpos($curl, '<code') !== false || strpos($curl, '<kbd') !== false || strpos($curl, '<style') !== false || strpos($curl, '<script') !== false) { 62 $next = false; 63 } elseif (strpos($curl, '<pre') !== false) { 64 $has_pre_parent = true; 65 } elseif (strpos($curl, '</pre>') !== false) { 66 $has_pre_parent = false; 67 } else { 68 $next = true; 69 } 70 71 $curl = preg_replace('/&([^#])(?![a-zA-Z1-4]{1,8};)/', '&$1', $curl); 72 $output .= $curl; 73 } 74 75 return $output; 76 } 77 78 /** 79 * Accepts matches array from preg_replace_callback in wpautop() or a string. 80 * 81 * Ensures that the contents of a <<pre>>...<</pre>> HTML block are not 82 * converted into paragraphs or line-breaks. 83 * 84 * @since 1.2.0 85 * 86 * @param array|string $matches The array or string 87 * @return string The pre block without paragraph/line-break conversion. 88 */ 89 function clean_pre($matches) { 90 if ( is_array($matches) ) 91 $text = $matches[1] . $matches[2] . "</pre>"; 92 else 93 $text = $matches; 94 95 $text = str_replace('<br />', '', $text); 96 $text = str_replace('<p>', "\n", $text); 97 $text = str_replace('</p>', '', $text); 98 99 return $text; 100 } 101 102 /** 103 * Replaces double line-breaks with paragraph elements. 104 * 105 * A group of regex replaces used to identify text formatted with newlines and 106 * replace double line-breaks with HTML paragraph tags. The remaining 107 * line-breaks after conversion become <<br />> tags, unless $br is set to '0' 108 * or 'false'. 109 * 110 * @since 0.71 111 * 112 * @param string $pee The text which has to be formatted. 113 * @param int|bool $br Optional. If set, this will convert all remaining line-breaks after paragraphing. Default true. 114 * @return string Text which has been converted into correct paragraph tags. 115 */ 116 function wpautop($pee, $br = 1) { 117 $pee = $pee . "\n"; // just to make things a little easier, pad the end 118 $pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee); 119 // Space things out a little 120 $allblocks = '(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|map|area|blockquote|address|math|style|input|p|h[1-6]|hr)'; 121 $pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee); 122 $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee); 123 $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines 124 if ( strpos($pee, '<object') !== false ) { 125 $pee = preg_replace('|\s*<param([^>]*)>\s*|', "<param$1>", $pee); // no pee inside object/embed 126 $pee = preg_replace('|\s*</embed>\s*|', '</embed>', $pee); 127 } 128 $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates 129 // make paragraphs, including one at the end 130 $pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY); 131 $pee = ''; 132 foreach ( $pees as $tinkle ) 133 $pee .= '<p>' . trim($tinkle, "\n") . "</p>\n"; 134 $pee = preg_replace('|<p>\s*?</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace 135 $pee = preg_replace('!<p>([^<]+)\s*?(</(?:div|address|form)[^>]*>)!', "<p>$1</p>$2", $pee); 136 $pee = preg_replace( '|<p>|', "$1<p>", $pee ); 137 $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); // don't pee all over a tag 138 $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists 139 $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee); 140 $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee); 141 $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee); 142 $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); 143 if ($br) { 144 $pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', create_function('$matches', 'return str_replace("\n", "<WPPreserveNewline />", $matches[0]);'), $pee); 145 $pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); // optionally make line breaks 146 $pee = str_replace('<WPPreserveNewline />', "\n", $pee); 147 } 148 $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee); 149 $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee); 150 if (strpos($pee, '<pre') !== false) 151 $pee = preg_replace_callback('!(<pre.*?>)(.*?)</pre>!is', 'clean_pre', $pee ); 152 $pee = preg_replace( "|\n</p>$|", '</p>', $pee ); 153 $pee = preg_replace('/<p>\s*?(' . get_shortcode_regex() . ')\s*<\/p>/s', '$1', $pee); // don't auto-p wrap shortcodes that stand alone 154 155 return $pee; 156 } 157 158 /** 159 * Checks to see if a string is utf8 encoded. 160 * 161 * @author bmorel at ssi dot fr 162 * 163 * @since 1.2.1 164 * 165 * @param string $Str The string to be checked 166 * @return bool True if $Str fits a UTF-8 model, false otherwise. 167 */ 168 function seems_utf8($Str) { # by bmorel at ssi dot fr 169 $length = strlen($Str); 170 for ($i=0; $i < $length; $i++) { 171 if (ord($Str[$i]) < 0x80) continue; # 0bbbbbbb 172 elseif ((ord($Str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb 173 elseif ((ord($Str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb 174 elseif ((ord($Str[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb 175 elseif ((ord($Str[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb 176 elseif ((ord($Str[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b 177 else return false; # Does not match any model 178 for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ? 179 if ((++$i == $length) || ((ord($Str[$i]) & 0xC0) != 0x80)) 180 return false; 181 } 182 } 183 return true; 184 } 185 186 /** 187 * Converts a number of special characters into their HTML entities. 188 * 189 * Specifically deals with: &, <, >, ", and '. 190 * 191 * $quote_style can be set to ENT_COMPAT to encode " to 192 * ", or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded. 193 * 194 * @since 1.2.2 195 * 196 * @param string $string The text which is to be encoded. 197 * @param mixed $quote_style Optional. Converts double quotes if set to ENT_COMPAT, both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. Also compatible with old values; converting single quotes if set to 'single', double if set to 'double' or both if otherwise set. Default is ENT_NOQUOTES. 198 * @param string $charset Optional. The character encoding of the string. Default is false. 199 * @param boolean $double_encode Optional. Whether or not to encode existing html entities. Default is false. 200 * @return string The encoded text with HTML entities. 201 */ 202 function wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) 203 { 204 $string = (string) $string; 205 206 if ( 0 === strlen( $string ) ) { 207 return ''; 208 } 209 210 // Don't bother if there are no specialchars - saves some processing 211 if ( !preg_match( '/[&<>"\']/', $string ) ) { 212 return $string; 213 } 214 215 // Account for the previous behaviour of the function when the $quote_style is not an accepted value 216 if ( empty( $quote_style ) ) { 217 $quote_style = ENT_NOQUOTES; 218 } elseif ( !in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) { 219 $quote_style = ENT_QUOTES; 220 } 221 222 // Store the site charset as a static to avoid multiple calls to wp_load_alloptions() 223 if ( !$charset ) { 224 static $_charset; 225 if ( !isset( $_charset ) ) { 226 $alloptions = wp_load_alloptions(); 227 $_charset = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : ''; 228 } 229 $charset = $_charset; 230 } 231 if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ) ) ) { 232 $charset = 'UTF-8'; 233 } 234 235 $_quote_style = $quote_style; 236 237 if ( $quote_style === 'double' ) { 238 $quote_style = ENT_COMPAT; 239 $_quote_style = ENT_COMPAT; 240 } elseif ( $quote_style === 'single' ) { 241 $quote_style = ENT_NOQUOTES; 242 } 243 244 // Handle double encoding ourselves 245 if ( !$double_encode ) { 246 $string = wp_specialchars_decode( $string, $_quote_style ); 247 $string = preg_replace( '/&(#?x?[0-9]+|[a-z]+);/i', '|wp_entity|$1|/wp_entity|', $string ); 248 } 249 250 $string = @htmlspecialchars( $string, $quote_style, $charset ); 251 252 // Handle double encoding ourselves 253 if ( !$double_encode ) { 254 $string = str_replace( array( '|wp_entity|', '|/wp_entity|' ), array( '&', ';' ), $string ); 255 } 256 257 // Backwards compatibility 258 if ( 'single' === $_quote_style ) { 259 $string = str_replace( "'", ''', $string ); 260 } 261 262 return $string; 263 } 264 265 /** 266 * Converts a number of HTML entities into their special characters. 267 * 268 * Specifically deals with: &, <, >, ", and '. 269 * 270 * $quote_style can be set to ENT_COMPAT to decode " entities, 271 * or ENT_QUOTES to do both " and '. Default is ENT_NOQUOTES where no quotes are decoded. 272 * 273 * @since 2.8 274 * 275 * @param string $string The text which is to be decoded. 276 * @param mixed $quote_style Optional. Converts double quotes if set to ENT_COMPAT, both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. Also compatible with old wp_specialchars() values; converting single quotes if set to 'single', double if set to 'double' or both if otherwise set. Default is ENT_NOQUOTES. 277 * @return string The decoded text without HTML entities. 278 */ 279 function wp_specialchars_decode( $string, $quote_style = ENT_NOQUOTES ) 280 { 281 $string = (string) $string; 282 283 if ( 0 === strlen( $string ) ) { 284 return ''; 285 } 286 287 // Don't bother if there are no entities - saves a lot of processing 288 if ( strpos( $string, '&' ) === false ) { 289 return $string; 290 } 291 292 // Match the previous behaviour of wp_specialchars() when the $quote_style is not an accepted value 293 if ( empty( $quote_style ) ) { 294 $quote_style = ENT_NOQUOTES; 295 } elseif ( !in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) { 296 $quote_style = ENT_QUOTES; 297 } 298 299 // More complete than get_html_translation_table( HTML_SPECIALCHARS ) 300 $single = array( ''' => '\'', ''' => '\'' ); 301 $single_preg = array( '/�*39;/' => ''', '/�*27;/i' => ''' ); 302 $double = array( '"' => '"', '"' => '"', '"' => '"' ); 303 $double_preg = array( '/�*34;/' => '"', '/�*22;/i' => '"' ); 304 $others = array( '<' => '<', '<' => '<', '>' => '>', '>' => '>', '&' => '&', '&' => '&', '&' => '&' ); 305 $others_preg = array( '/�*60;/' => '<', '/�*62;/' => '>', '/�*38;/' => '&', '/�*26;/i' => '&' ); 306 307 if ( $quote_style === ENT_QUOTES ) { 308 $translation = array_merge( $single, $double, $others ); 309 $translation_preg = array_merge( $single_preg, $double_preg, $others_preg ); 310 } elseif ( $quote_style === ENT_COMPAT || $quote_style === 'double' ) { 311 $translation = array_merge( $double, $others ); 312 $translation_preg = array_merge( $double_preg, $others_preg ); 313 } elseif ( $quote_style === 'single' ) { 314 $translation = array_merge( $single, $others ); 315 $translation_preg = array_merge( $single_preg, $others_preg ); 316 } elseif ( $quote_style === ENT_NOQUOTES ) { 317 $translation = $others; 318 $translation_preg = $others_preg; 319 } 320 321 // Remove zero padding on numeric entities 322 $string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string ); 323 324 // Replace characters according to translation table 325 return strtr( $string, $translation ); 326 } 327 328 /** 329 * Checks for invalid UTF8 in a string. 330 * 331 * @since 2.8 332 * 333 * @param string $string The text which is to be checked. 334 * @param boolean $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false. 335 * @return string The checked text. 336 */ 337 function wp_check_invalid_utf8( $string, $strip = false ) 338 { 339 $string = (string) $string; 340 341 if ( 0 === strlen( $string ) ) { 342 return ''; 343 } 344 345 // Store the site charset as a static to avoid multiple calls to get_option() 346 static $is_utf8; 347 if ( !isset( $is_utf8 ) ) { 348 $is_utf8 = in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ); 349 } 350 if ( !$is_utf8 ) { 351 return $string; 352 } 353 354 // Check for support for utf8 in the installed PCRE library once and store the result in a static 355 static $utf8_pcre; 356 if ( !isset( $utf8_pcre ) ) { 357 $utf8_pcre = @preg_match( '/^./u', 'a' ); 358 } 359 // We can't demand utf8 in the PCRE installation, so just return the string in those cases 360 if ( !$utf8_pcre ) { 361 return $string; 362 } 363 364 // preg_match fails when it encounters invalid UTF8 in $string 365 if ( 1 === @preg_match( '/^./us', $string ) ) { 366 return $string; 367 } 368 369 // Attempt to strip the bad chars if requested (not recommended) 370 if ( $strip && function_exists( 'iconv' ) ) { 371 return iconv( 'utf-8', 'utf-8', $string ); 372 } 373 374 return ''; 375 } 376 377 /** 378 * Encode the Unicode values to be used in the URI. 379 * 380 * @since 1.5.0 381 * 382 * @param string $utf8_string 383 * @param int $length Max length of the string 384 * @return string String with Unicode encoded for URI. 385 */ 386 function utf8_uri_encode( $utf8_string, $length = 0 ) { 387 $unicode = ''; 388 $values = array(); 389 $num_octets = 1; 390 $unicode_length = 0; 391 392 $string_length = strlen( $utf8_string ); 393 for ($i = 0; $i < $string_length; $i++ ) { 394 395 $value = ord( $utf8_string[ $i ] ); 396 397 if ( $value < 128 ) { 398 if ( $length && ( $unicode_length >= $length ) ) 399 break; 400 $unicode .= chr($value); 401 $unicode_length++; 402 } else { 403 if ( count( $values ) == 0 ) $num_octets = ( $value < 224 ) ? 2 : 3; 404 405 $values[] = $value; 406 407 if ( $length && ( $unicode_length + ($num_octets * 3) ) > $length ) 408 break; 409 if ( count( $values ) == $num_octets ) { 410 if ($num_octets == 3) { 411 $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]) . '%' . dechex($values[2]); 412 $unicode_length += 9; 413 } else { 414 $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]); 415 $unicode_length += 6; 416 } 417 418 $values = array(); 419 $num_octets = 1; 420 } 421 } 422 } 423 424 return $unicode; 425 } 426 427 /** 428 * Converts all accent characters to ASCII characters. 429 * 430 * If there are no accent characters, then the string given is just returned. 431 * 432 * @since 1.2.1 433 * 434 * @param string $string Text that might have accent characters 435 * @return string Filtered string with replaced "nice" characters. 436 */ 437 function remove_accents($string) { 438 if ( !preg_match('/[\x80-\xff]/', $string) ) 439 return $string; 440 441 if (seems_utf8($string)) { 442 $chars = array( 443 // Decompositions for Latin-1 Supplement 444 chr(195).chr(128) => 'A', chr(195).chr(129) => 'A', 445 chr(195).chr(130) => 'A', chr(195).chr(131) => 'A', 446 chr(195).chr(132) => 'A', chr(195).chr(133) => 'A', 447 chr(195).chr(135) => 'C', chr(195).chr(136) => 'E', 448 chr(195).chr(137) => 'E', chr(195).chr(138) => 'E', 449 chr(195).chr(139) => 'E', chr(195).chr(140) => 'I', 450 chr(195).chr(141) => 'I', chr(195).chr(142) => 'I', 451 chr(195).chr(143) => 'I', chr(195).chr(145) => 'N', 452 chr(195).chr(146) => 'O', chr(195).chr(147) => 'O', 453 chr(195).chr(148) => 'O', chr(195).chr(149) => 'O', 454 chr(195).chr(150) => 'O', chr(195).chr(153) => 'U', 455 chr(195).chr(154) => 'U', chr(195).chr(155) => 'U', 456 chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y', 457 chr(195).chr(159) => 's', chr(195).chr(160) => 'a', 458 chr(195).chr(161) => 'a', chr(195).chr(162) => 'a', 459 chr(195).chr(163) => 'a', chr(195).chr(164) => 'a', 460 chr(195).chr(165) => 'a', chr(195).chr(167) => 'c', 461 chr(195).chr(168) => 'e', chr(195).chr(169) => 'e', 462 chr(195).chr(170) => 'e', chr(195).chr(171) => 'e', 463 chr(195).chr(172) => 'i', chr(195).chr(173) => 'i', 464 chr(195).chr(174) => 'i', chr(195).chr(175) => 'i', 465 chr(195).chr(177) => 'n', chr(195).chr(178) => 'o', 466 chr(195).chr(179) => 'o', chr(195).chr(180) => 'o', 467 chr(195).chr(181) => 'o', chr(195).chr(182) => 'o', 468 chr(195).chr(182) => 'o', chr(195).chr(185) => 'u', 469 chr(195).chr(186) => 'u', chr(195).chr(187) => 'u', 470 chr(195).chr(188) => 'u', chr(195).chr(189) => 'y', 471 chr(195).chr(191) => 'y', 472 // Decompositions for Latin Extended-A 473 chr(196).chr(128) => 'A', chr(196).chr(129) => 'a', 474 chr(196).chr(130) => 'A', chr(196).chr(131) => 'a', 475 chr(196).chr(132) => 'A', chr(196).chr(133) => 'a', 476 chr(196).chr(134) => 'C', chr(196).chr(135) => 'c', 477 chr(196).chr(136) => 'C', chr(196).chr(137) => 'c', 478 chr(196).chr(138) => 'C', chr(196).chr(139) => 'c', 479 chr(196).chr(140) => 'C', chr(196).chr(141) => 'c', 480 chr(196).chr(142) => 'D', chr(196).chr(143) => 'd', 481 chr(196).chr(144) => 'D', chr(196).chr(145) => 'd', 482 chr(196).chr(146) => 'E', chr(196).chr(147) => 'e', 483 chr(196).chr(148) => 'E', chr(196).chr(149) => 'e', 484 chr(196).chr(150) => 'E', chr(196).chr(151) => 'e', 485 chr(196).chr(152) => 'E', chr(196).chr(153) => 'e', 486 chr(196).chr(154) => 'E', chr(196).chr(155) => 'e', 487 chr(196).chr(156) => 'G', chr(196).chr(157) => 'g', 488 chr(196).chr(158) => 'G', chr(196).chr(159) => 'g', 489 chr(196).chr(160) => 'G', chr(196).chr(161) => 'g', 490 chr(196).chr(162) => 'G', chr(196).chr(163) => 'g', 491 chr(196).chr(164) => 'H', chr(196).chr(165) => 'h', 492 chr(196).chr(166) => 'H', chr(196).chr(167) => 'h', 493 chr(196).chr(168) => 'I', chr(196).chr(169) => 'i', 494 chr(196).chr(170) => 'I', chr(196).chr(171) => 'i', 495 chr(196).chr(172) => 'I', chr(196).chr(173) => 'i', 496 chr(196).chr(174) => 'I', chr(196).chr(175) => 'i', 497 chr(196).chr(176) => 'I', chr(196).chr(177) => 'i', 498 chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij', 499 chr(196).chr(180) => 'J', chr(196).chr(181) => 'j', 500 chr(196).chr(182) => 'K', chr(196).chr(183) => 'k', 501 chr(196).chr(184) => 'k', chr(196).chr(185) => 'L', 502 chr(196).chr(186) => 'l', chr(196).chr(187) => 'L', 503 chr(196).chr(188) => 'l', chr(196).chr(189) => 'L', 504 chr(196).chr(190) => 'l', chr(196).chr(191) => 'L', 505 chr(197).chr(128) => 'l', chr(197).chr(129) => 'L', 506 chr(197).chr(130) => 'l', chr(197).chr(131) => 'N', 507 chr(197).chr(132) => 'n', chr(197).chr(133) => 'N', 508 chr(197).chr(134) => 'n', chr(197).chr(135) => 'N', 509 chr(197).chr(136) => 'n', chr(197).chr(137) => 'N', 510 chr(197).chr(138) => 'n', chr(197).chr(139) => 'N', 511 chr(197).chr(140) => 'O', chr(197).chr(141) => 'o', 512 chr(197).chr(142) => 'O', chr(197).chr(143) => 'o', 513 chr(197).chr(144) => 'O', chr(197).chr(145) => 'o', 514 chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe', 515 chr(197).chr(148) => 'R',chr(197).chr(149) => 'r', 516 chr(197).chr(150) => 'R',chr(197).chr(151) => 'r', 517 chr(197).chr(152) => 'R',chr(197).chr(153) => 'r', 518 chr(197).chr(154) => 'S',chr(197).chr(155) => 's', 519 chr(197).chr(156) => 'S',chr(197).chr(157) => 's', 520 chr(197).chr(158) => 'S',chr(197).chr(159) => 's', 521 chr(197).chr(160) => 'S', chr(197).chr(161) => 's', 522 chr(197).chr(162) => 'T', chr(197).chr(163) => 't', 523 chr(197).chr(164) => 'T', chr(197).chr(165) => 't', 524 chr(197).chr(166) => 'T', chr(197).chr(167) => 't', 525 chr(197).chr(168) => 'U', chr(197).chr(169) => 'u', 526 chr(197).chr(170) => 'U', chr(197).chr(171) => 'u', 527 chr(197).chr(172) => 'U', chr(197).chr(173) => 'u', 528 chr(197).chr(174) => 'U', chr(197).chr(175) => 'u', 529 chr(197).chr(176) => 'U', chr(197).chr(177) => 'u', 530 chr(197).chr(178) => 'U', chr(197).chr(179) => 'u', 531 chr(197).chr(180) => 'W', chr(197).chr(181) => 'w', 532 chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y', 533 chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z', 534 chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z', 535 chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z', 536 chr(197).chr(190) => 'z', chr(197).chr(191) => 's', 537 // Euro Sign 538 chr(226).chr(130).chr(172) => 'E', 539 // GBP (Pound) Sign 540 chr(194).chr(163) => ''); 541 542 $string = strtr($string, $chars); 543 } else { 544 // Assume ISO-8859-1 if not UTF-8 545 $chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158) 546 .chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194) 547 .chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202) 548 .chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210) 549 .chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218) 550 .chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227) 551 .chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235) 552 .chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243) 553 .chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251) 554 .chr(252).chr(253).chr(255); 555 556 $chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy"; 557 558 $string = strtr($string, $chars['in'], $chars['out']); 559 $double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254)); 560 $double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'); 561 $string = str_replace($double_chars['in'], $double_chars['out'], $string); 562 } 563 564 return $string; 565 } 566 567 /** 568 * Filters certain characters from the file name. 569 * 570 * Turns all strings to lowercase removing most characters except alphanumeric 571 * with spaces, dashes and periods. All spaces and underscores are converted to 572 * dashes. Multiple dashes are converted to a single dash. Finally, if the file 573 * name ends with a dash, it is removed. 574 * 575 * @since 2.1.0 576 * 577 * @param string $name The file name 578 * @return string Sanitized file name 579 */ 580 function sanitize_file_name( $name ) { // Like sanitize_title, but with periods 581 $name = strtolower( $name ); 582 $name = preg_replace('/&.+?;/', '', $name); // kill entities 583 $name = str_replace( '_', '-', $name ); 584 $name = preg_replace('/[^a-z0-9\s-.]/', '', $name); 585 $name = preg_replace('/\s+/', '-', $name); 586 $name = preg_replace('|-+|', '-', $name); 587 $name = trim($name, '-'); 588 return $name; 589 } 590 591 /** 592 * Sanitize username stripping out unsafe characters. 593 * 594 * If $strict is true, only alphanumeric characters (as well as _, space, ., -, 595 * @) are returned. 596 * Removes tags, octets, entities, and if strict is enabled, will remove all 597 * non-ASCII characters. After sanitizing, it passes the username, raw username 598 * (the username in the parameter), and the strict parameter as parameters for 599 * the filter. 600 * 601 * @since 2.0.0 602 * @uses apply_filters() Calls 'sanitize_user' hook on username, raw username, 603 * and $strict parameter. 604 * 605 * @param string $username The username to be sanitized. 606 * @param bool $strict If set limits $username to specific characters. Default false. 607 * @return string The sanitized username, after passing through filters. 608 */ 609 function sanitize_user( $username, $strict = false ) { 610 $raw_username = $username; 611 $username = strip_tags($username); 612 // Kill octets 613 $username = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '', $username); 614 $username = preg_replace('/&.+?;/', '', $username); // Kill entities 615 616 // If strict, reduce to ASCII for max portability. 617 if ( $strict ) 618 $username = preg_replace('|[^a-z0-9 _.\-@]|i', '', $username); 619 620 // Consolidate contiguous whitespace 621 $username = preg_replace('|\s+|', ' ', $username); 622 623 return apply_filters('sanitize_user', $username, $raw_username, $strict); 624 } 625 626 /** 627 * Sanitizes title or use fallback title. 628 * 629 * Specifically, HTML and PHP tags are stripped. Further actions can be added 630 * via the plugin API. If $title is empty and $fallback_title is set, the latter 631 * will be used. 632 * 633 * @since 1.0.0 634 * 635 * @param string $title The string to be sanitized. 636 * @param string $fallback_title Optional. A title to use if $title is empty. 637 * @return string The sanitized string. 638 */ 639 function sanitize_title($title, $fallback_title = '') { 640 $title = strip_tags($title); 641 $title = apply_filters('sanitize_title', $title); 642 643 if ( '' === $title || false === $title ) 644 $title = $fallback_title; 645 646 return $title; 647 } 648 649 /** 650 * Sanitizes title, replacing whitespace with dashes. 651 * 652 * Limits the output to alphanumeric characters, underscore (_) and dash (-). 653 * Whitespace becomes a dash. 654 * 655 * @since 1.2.0 656 * 657 * @param string $title The title to be sanitized. 658 * @return string The sanitized title. 659 */ 660 function sanitize_title_with_dashes($title) { 661 $title = strip_tags($title); 662 // Preserve escaped octets. 663 $title = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '---$1---', $title); 664 // Remove percent signs that are not part of an octet. 665 $title = str_replace('%', '', $title); 666 // Restore octets. 667 $title = preg_replace('|---([a-fA-F0-9][a-fA-F0-9])---|', '%$1', $title); 668 669 $title = remove_accents($title); 670 if (seems_utf8($title)) { 671 if (function_exists('mb_strtolower')) { 672 $title = mb_strtolower($title, 'UTF-8'); 673 } 674 $title = utf8_uri_encode($title, 200); 675 } 676 677 $title = strtolower($title); 678 $title = preg_replace('/&.+?;/', '', $title); // kill entities 679 $title = preg_replace('/[^%a-z0-9 _-]/', '', $title); 680 $title = preg_replace('/\s+/', '-', $title); 681 $title = preg_replace('|-+|', '-', $title); 682 $title = trim($title, '-'); 683 684 return $title; 685 } 686 687 /** 688 * Ensures a string is a valid SQL order by clause. 689 * 690 * Accepts one or more columns, with or without ASC/DESC, and also accepts 691 * RAND(). 692 * 693 * @since 2.5.1 694 * 695 * @param string $orderby Order by string to be checked. 696 * @return string|false Returns the order by clause if it is a match, false otherwise. 697 */ 698 function sanitize_sql_orderby( $orderby ){ 699 preg_match('/^\s*([a-z0-9_]+(\s+(ASC|DESC))?(\s*,\s*|\s*$))+|^\s*RAND\(\s*\)\s*$/i', $orderby, $obmatches); 700 if ( !$obmatches ) 701 return false; 702 return $orderby; 703 } 704 705 /** 706 * Converts a number of characters from a string. 707 * 708 * Metadata tags <<title>> and <<category>> are removed, <<br>> and <<hr>> are 709 * converted into correct XHTML and Unicode characters are converted to the 710 * valid range. 711 * 712 * @since 0.71 713 * 714 * @param string $content String of characters to be converted. 715 * @param string $deprecated Not used. 716 * @return string Converted string. 717 */ 718 function convert_chars($content, $deprecated = '') { 719 // Translation of invalid Unicode references range to valid range 720 $wp_htmltranswinuni = array( 721 '€' => '€', // the Euro sign 722 '' => '', 723 '‚' => '‚', // these are Windows CP1252 specific characters 724 'ƒ' => 'ƒ', // they would look weird on non-Windows browsers 725 '„' => '„', 726 '…' => '…', 727 '†' => '†', 728 '‡' => '‡', 729 'ˆ' => 'ˆ', 730 '‰' => '‰', 731 'Š' => 'Š', 732 '‹' => '‹', 733 'Œ' => 'Œ', 734 '' => '', 735 'Ž' => 'ž', 736 '' => '', 737 '' => '', 738 '‘' => '‘', 739 '’' => '’', 740 '“' => '“', 741 '”' => '”', 742 '•' => '•', 743 '–' => '–', 744 '—' => '—', 745 '˜' => '˜', 746 '™' => '™', 747 'š' => 'š', 748 '›' => '›', 749 'œ' => 'œ', 750 '' => '', 751 'ž' => '', 752 'Ÿ' => 'Ÿ' 753 ); 754 755 // Remove metadata tags 756 $content = preg_replace('/<title>(.+?)<\/title>/','',$content); 757 $content = preg_replace('/<category>(.+?)<\/category>/','',$content); 758 759 // Converts lone & characters into & (a.k.a. &) 760 $content = preg_replace('/&([^#])(?![a-z1-4]{1,8};)/i', '&$1', $content); 761 762 // Fix Word pasting 763 $content = strtr($content, $wp_htmltranswinuni); 764 765 // Just a little XHTML help 766 $content = str_replace('<br>', '<br />', $content); 767 $content = str_replace('<hr>', '<hr />', $content); 768 769 return $content; 770 } 771 772 /** 773 * Fixes javascript bugs in browsers. 774 * 775 * Converts unicode characters to HTML numbered entities. 776 * 777 * @since 1.5.0 778 * @uses $is_macIE 779 * @uses $is_winIE 780 * 781 * @param string $text Text to be made safe. 782 * @return string Fixed text. 783 */ 784 function funky_javascript_fix($text) { 785 // Fixes for browsers' javascript bugs 786 global $is_macIE, $is_winIE; 787 788 /** @todo use preg_replace_callback() instead */ 789 if ( $is_winIE || $is_macIE ) 790 $text = preg_replace("/\%u([0-9A-F]{4,4})/e", "'&#'.base_convert('\\1',16,10).';'", $text); 791 792 return $text; 793 } 794 795 /** 796 * Will only balance the tags if forced to and the option is set to balance tags. 797 * 798 * The option 'use_balanceTags' is used for whether the tags will be balanced. 799 * Both the $force parameter and 'use_balanceTags' option will have to be true 800 * before the tags will be balanced. 801 * 802 * @since 0.71 803 * 804 * @param string $text Text to be balanced 805 * @param bool $force Forces balancing, ignoring the value of the option. Default false. 806 * @return string Balanced text 807 */ 808 function balanceTags( $text, $force = false ) { 809 if ( !$force && get_option('use_balanceTags') == 0 ) 810 return $text; 811 return force_balance_tags( $text ); 812 } 813 814 /** 815 * Balances tags of string using a modified stack. 816 * 817 * @since 2.0.4 818 * 819 * @author Leonard Lin <leonard@acm.org> 820 * @license GPL v2.0 821 * @copyright November 4, 2001 822 * @version 1.1 823 * @todo Make better - change loop condition to $text in 1.2 824 * @internal Modified by Scott Reilly (coffee2code) 02 Aug 2004 825 * 1.1 Fixed handling of append/stack pop order of end text 826 * Added Cleaning Hooks 827 * 1.0 First Version 828 * 829 * @param string $text Text to be balanced. 830 * @return string Balanced text. 831 */ 832 function force_balance_tags( $text ) { 833 $tagstack = array(); $stacksize = 0; $tagqueue = ''; $newtext = ''; 834 $single_tags = array('br', 'hr', 'img', 'input'); //Known single-entity/self-closing tags 835 $nestable_tags = array('blockquote', 'div', 'span'); //Tags that can be immediately nested within themselves 836 837 # WP bug fix for comments - in case you REALLY meant to type '< !--' 838 $text = str_replace('< !--', '< !--', $text); 839 # WP bug fix for LOVE <3 (and other situations with '<' before a number) 840 $text = preg_replace('#<([0-9]{1})#', '<$1', $text); 841 842 while (preg_match("/<(\/?\w*)\s*([^>]*)>/",$text,$regex)) { 843 $newtext .= $tagqueue; 844 845 $i = strpos($text,$regex[0]); 846 $l = strlen($regex[0]); 847 848 // clear the shifter 849 $tagqueue = ''; 850 // Pop or Push 851 if ($regex[1][0] == "/") { // End Tag 852 $tag = strtolower(substr($regex[1],1)); 853 // if too many closing tags 854 if($stacksize <= 0) { 855 $tag = ''; 856 //or close to be safe $tag = '/' . $tag; 857 } 858 // if stacktop value = tag close value then pop 859 else if ($tagstack[$stacksize - 1] == $tag) { // found closing tag 860 $tag = '</' . $tag . '>'; // Close Tag 861 // Pop 862 array_pop ($tagstack); 863 $stacksize--; 864 } else { // closing tag not at top, search for it 865 for ($j=$stacksize-1;$j>=0;$j--) { 866 if ($tagstack[$j] == $tag) { 867 // add tag to tagqueue 868 for ($k=$stacksize-1;$k>=$j;$k--){ 869 $tagqueue .= '</' . array_pop ($tagstack) . '>'; 870 $stacksize--; 871 } 872 break; 873 } 874 } 875 $tag = ''; 876 } 877 } else { // Begin Tag 878 $tag = strtolower($regex[1]); 879 880 // Tag Cleaning 881 882 // If self-closing or '', don't do anything. 883 if((substr($regex[2],-1) == '/') || ($tag == '')) { 884 } 885 // ElseIf it's a known single-entity tag but it doesn't close itself, do so 886 elseif ( in_array($tag, $single_tags) ) { 887 $regex[2] .= '/'; 888 } else { // Push the tag onto the stack 889 // If the top of the stack is the same as the tag we want to push, close previous tag 890 if (($stacksize > 0) && !in_array($tag, $nestable_tags) && ($tagstack[$stacksize - 1] == $tag)) { 891 $tagqueue = '</' . array_pop ($tagstack) . '>'; 892 $stacksize--; 893 } 894 $stacksize = array_push ($tagstack, $tag); 895 } 896 897 // Attributes 898 $attributes = $regex[2]; 899 if($attributes) { 900 $attributes = ' '.$attributes; 901 } 902 $tag = '<'.$tag.$attributes.'>'; 903 //If already queuing a close tag, then put this tag on, too 904 if ($tagqueue) { 905 $tagqueue .= $tag; 906 $tag = ''; 907 } 908 } 909 $newtext .= substr($text,0,$i) . $tag; 910 $text = substr($text,$i+$l); 911 } 912 913 // Clear Tag Queue 914 $newtext .= $tagqueue; 915 916 // Add Remaining text 917 $newtext .= $text; 918 919 // Empty Stack 920 while($x = array_pop($tagstack)) { 921 $newtext .= '</' . $x . '>'; // Add remaining tags to close 922 } 923 924 // WP fix for the bug with HTML comments 925 $newtext = str_replace("< !--","<!--",$newtext); 926 $newtext = str_replace("< !--","< !--",$newtext); 927 928 return $newtext; 929 } 930 931 /** 932 * Acts on text which is about to be edited. 933 * 934 * Unless $richedit is set, it is simply a holder for the 'format_to_edit' 935 * filter. If $richedit is set true htmlspecialchars() will be run on the 936 * content, converting special characters to HTMl entities. 937 * 938 * @since 0.71 939 * 940 * @param string $content The text about to be edited. 941 * @param bool $richedit Whether or not the $content should pass through htmlspecialchars(). Default false. 942 * @return string The text after the filter (and possibly htmlspecialchars()) has been run. 943 */ 944 function format_to_edit($content, $richedit = false) { 945 $content = apply_filters('format_to_edit', $content); 946 if (! $richedit ) 947 $content = htmlspecialchars($content); 948 return $content; 949 } 950 951 /** 952 * Holder for the 'format_to_post' filter. 953 * 954 * @since 0.71 955 * 956 * @param string $content The text to pass through the filter. 957 * @return string Text returned from the 'format_to_post' filter. 958 */ 959 function format_to_post($content) { 960 $content = apply_filters('format_to_post', $content); 961 return $content; 962 } 963 964 /** 965 * Add leading zeros when necessary. 966 * 967 * If you set the threshold to '4' and the number is '10', then you will get 968 * back '0010'. If you set the number to '4' and the number is '5000', then you 969 * will get back '5000'. 970 * 971 * Uses sprintf to append the amount of zeros based on the $threshold parameter 972 * and the size of the number. If the number is large enough, then no zeros will 973 * be appended. 974 * 975 * @since 0.71 976 * 977 * @param mixed $number Number to append zeros to if not greater than threshold. 978 * @param int $threshold Digit places number needs to be to not have zeros added. 979 * @return string Adds leading zeros to number if needed. 980 */ 981 function zeroise($number, $threshold) { 982 return sprintf('%0'.$threshold.'s', $number); 983 } 984 985 /** 986 * Adds backslashes before letters and before a number at the start of a string. 987 * 988 * @since 0.71 989 * 990 * @param string $string Value to which backslashes will be added. 991 * @return string String with backslashes inserted. 992 */ 993 function backslashit($string) { 994 $string = preg_replace('/^([0-9])/', '\\\\\\\\\1', $string); 995 $string = preg_replace('/([a-z])/i', '\\\\\1', $string); 996 return $string; 997 } 998 999 /** 1000 * Appends a trailing slash. 1001 * 1002 * Will remove trailing slash if it exists already before adding a trailing 1003 * slash. This prevents double slashing a string or path. 1004 * 1005 * The primary use of this is for paths and thus should be used for paths. It is 1006 * not restricted to paths and offers no specific path support. 1007 * 1008 * @since 1.2.0 1009 * @uses untrailingslashit() Unslashes string if it was slashed already. 1010 * 1011 * @param string $string What to add the trailing slash to. 1012 * @return string String with trailing slash added. 1013 */ 1014 function trailingslashit($string) { 1015 return untrailingslashit($string) . '/'; 1016 } 1017 1018 /** 1019 * Removes trailing slash if it exists. 1020 * 1021 * The primary use of this is for paths and thus should be used for paths. It is 1022 * not restricted to paths and offers no specific path support. 1023 * 1024 * @since 2.2.0 1025 * 1026 * @param string $string What to remove the trailing slash from. 1027 * @return string String without the trailing slash. 1028 */ 1029 function untrailingslashit($string) { 1030 return rtrim($string, '/'); 1031 } 1032 1033 /** 1034 * Adds slashes to escape strings. 1035 * 1036 * Slashes will first be removed if magic_quotes_gpc is set, see {@link 1037 * http://www.php.net/magic_quotes} for more details. 1038 * 1039 * @since 0.71 1040 * 1041 * @param string $gpc The string returned from HTTP request data. 1042 * @return string Returns a string escaped with slashes. 1043 */ 1044 function addslashes_gpc($gpc) { 1045 global $wpdb; 1046 1047 if (get_magic_quotes_gpc()) { 1048 $gpc = stripslashes($gpc); 1049 } 1050 1051 return $wpdb->escape($gpc); 1052 } 1053 1054 /** 1055 * Navigates through an array and removes slashes from the values. 1056 * 1057 * If an array is passed, the array_map() function causes a callback to pass the 1058 * value back to the function. The slashes from this value will removed. 1059 * 1060 * @since 2.0.0 1061 * 1062 * @param array|string $value The array or string to be striped. 1063 * @return array|string Stripped array (or string in the callback). 1064 */ 1065 function stripslashes_deep($value) { 1066 $value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value); 1067 return $value; 1068 } 1069 1070 /** 1071 * Navigates through an array and encodes the values to be used in a URL. 1072 * 1073 * Uses a callback to pass the value of the array back to the function as a 1074 * string. 1075 * 1076 * @since 2.2.0 1077 * 1078 * @param array|string $value The array or string to be encoded. 1079 * @return array|string $value The encoded array (or string from the callback). 1080 */ 1081 function urlencode_deep($value) { 1082 $value = is_array($value) ? array_map('urlencode_deep', $value) : urlencode($value); 1083 return $value; 1084 } 1085 1086 /** 1087 * Converts email addresses characters to HTML entities to block spam bots. 1088 * 1089 * @since 0.71 1090 * 1091 * @param string $emailaddy Email address. 1092 * @param int $mailto Optional. Range from 0 to 1. Used for encoding. 1093 * @return string Converted email address. 1094 */ 1095 function antispambot($emailaddy, $mailto=0) { 1096 $emailNOSPAMaddy = ''; 1097 srand ((float) microtime() * 1000000); 1098 for ($i = 0; $i < strlen($emailaddy); $i = $i + 1) { 1099 $j = floor(rand(0, 1+$mailto)); 1100 if ($j==0) { 1101 $emailNOSPAMaddy .= '&#'.ord(substr($emailaddy,$i,1)).';'; 1102 } elseif ($j==1) { 1103 $emailNOSPAMaddy .= substr($emailaddy,$i,1); 1104 } elseif ($j==2) { 1105 $emailNOSPAMaddy .= '%'.zeroise(dechex(ord(substr($emailaddy, $i, 1))), 2); 1106 } 1107 } 1108 $emailNOSPAMaddy = str_replace('@','@',$emailNOSPAMaddy); 1109 return $emailNOSPAMaddy; 1110 } 1111 1112 /** 1113 * Callback to convert URI match to HTML A element. 1114 * 1115 * This function was backported from 2.5.0 to 2.3.2. Regex callback for {@link 1116 * make_clickable()}. 1117 * 1118 * @since 2.3.2 1119 * @access private 1120 * 1121 * @param array $matches Single Regex Match. 1122 * @return string HTML A element with URI address. 1123 */ 1124 function _make_url_clickable_cb($matches) { 1125 $ret = ''; 1126 $url = $matches[2]; 1127 $url = clean_url($url); 1128 if ( empty($url) ) 1129 return $matches[0]; 1130 // removed trailing [.,;:] from URL 1131 if ( in_array(substr($url, -1), array('.', ',', ';', ':')) === true ) { 1132 $ret = substr($url, -1); 1133 $url = substr($url, 0, strlen($url)-1); 1134 } 1135 return $matches[1] . "<a href=\"$url\" rel=\"nofollow\">$url</a>" . $ret; 1136 } 1137 1138 /** 1139 * Callback to convert URL match to HTML A element. 1140 * 1141 * This function was backported from 2.5.0 to 2.3.2. Regex callback for {@link 1142 * make_clickable()}. 1143 * 1144 * @since 2.3.2 1145 * @access private 1146 * 1147 * @param array $matches Single Regex Match. 1148 * @return string HTML A element with URL address. 1149 */ 1150 function _make_web_ftp_clickable_cb($matches) { 1151 $ret = ''; 1152 $dest = $matches[2]; 1153 $dest = 'http://' . $dest; 1154 $dest = clean_url($dest); 1155 if ( empty($dest) ) 1156 return $matches[0]; 1157 // removed trailing [,;:] from URL 1158 if ( in_array(substr($dest, -1), array('.', ',', ';', ':')) === true ) { 1159 $ret = substr($dest, -1); 1160 $dest = substr($dest, 0, strlen($dest)-1); 1161 } 1162 return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>" . $ret; 1163 } 1164 1165 /** 1166 * Callback to convert email address match to HTML A element. 1167 * 1168 * This function was backported from 2.5.0 to 2.3.2. Regex callback for {@link 1169 * make_clickable()}. 1170 * 1171 * @since 2.3.2 1172 * @access private 1173 * 1174 * @param array $matches Single Regex Match. 1175 * @return string HTML A element with email address. 1176 */ 1177 function _make_email_clickable_cb($matches) { 1178 $email = $matches[2] . '@' . $matches[3]; 1179 return $matches[1] . "<a href=\"mailto:$email\">$email</a>"; 1180 } 1181 1182 /** 1183 * Convert plaintext URI to HTML links. 1184 * 1185 * Converts URI, www and ftp, and email addresses. Finishes by fixing links 1186 * within links. 1187 * 1188 * @since 0.71 1189 * 1190 * @param string $ret Content to convert URIs. 1191 * @return string Content with converted URIs. 1192 */ 1193 function make_clickable($ret) { 1194 $ret = ' ' . $ret; 1195 // in testing, using arrays here was found to be faster 1196 $ret = preg_replace_callback('#([\s>])([\w]+?://[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_url_clickable_cb', $ret); 1197 $ret = preg_replace_callback('#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_web_ftp_clickable_cb', $ret); 1198 $ret = preg_replace_callback('#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret); 1199 // this one is not in an array because we need it to run last, for cleanup of accidental links within links 1200 $ret = preg_replace("#(<a( [^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i", "$1$3</a>", $ret); 1201 $ret = trim($ret); 1202 return $ret; 1203 } 1204 1205 /** 1206 * Adds rel nofollow string to all HTML A elements in content. 1207 * 1208 * @since 1.5.0 1209 * 1210 * @param string $text Content that may contain HTML A elements. 1211 * @return string Converted content. 1212 */ 1213 function wp_rel_nofollow( $text ) { 1214 global $wpdb; 1215 // This is a pre save filter, so text is already escaped. 1216 $text = stripslashes($text); 1217 $text = preg_replace_callback('|<a (.+?)>|i', 'wp_rel_nofollow_callback', $text); 1218 $text = $wpdb->escape($text); 1219 return $text; 1220 } 1221 1222 /** 1223 * Callback to used to add rel=nofollow string to HTML A element. 1224 * 1225 * Will remove already existing rel="nofollow" and rel='nofollow' from the 1226 * string to prevent from invalidating (X)HTML. 1227 * 1228 * @since 2.3.0 1229 * 1230 * @param array $matches Single Match 1231 * @return string HTML A Element with rel nofollow. 1232 */ 1233 function wp_rel_nofollow_callback( $matches ) { 1234 $text = $matches[1]; 1235 $text = str_replace(array(' rel="nofollow"', " rel='nofollow'"), '', $text); 1236 return "<a $text rel=\"nofollow\">"; 1237 } 1238 1239 /** 1240 * Convert text equivalent of smilies to images. 1241 * 1242 * Will only convert smilies if the option 'use_smilies' is true and the globals 1243 * used in the function aren't empty. 1244 * 1245 * @since 0.71 1246 * @uses $wp_smiliessearch, $wp_smiliesreplace Smiley replacement arrays. 1247 * 1248 * @param string $text Content to convert smilies from text. 1249 * @return string Converted content with text smilies replaced with images. 1250 */ 1251 function convert_smilies($text) { 1252 global $wp_smiliessearch, $wp_smiliesreplace; 1253 $output = ''; 1254 if ( get_option('use_smilies') && !empty($wp_smiliessearch) && !empty($wp_smiliesreplace) ) { 1255 // HTML loop taken from texturize function, could possible be consolidated 1256 $textarr = preg_split("/(<.*>)/U", $text, -1, PREG_SPLIT_DELIM_CAPTURE); // capture the tags as well as in between 1257 $stop = count($textarr);// loop stuff 1258 for ($i = 0; $i < $stop; $i++) { 1259 $content = $textarr[$i]; 1260 if ((strlen($content) > 0) && ('<' != $content{0})) { // If it's not a tag 1261 $content = preg_replace($wp_smiliessearch, $wp_smiliesreplace, $content); 1262 } 1263 $output .= $content; 1264 } 1265 } else { 1266 // return default text. 1267 $output = $text; 1268 } 1269 return $output; 1270 } 1271 1272 /** 1273 * Checks to see if the text is a valid email address. 1274 * 1275 * @since 0.71 1276 * 1277 * @param string $user_email The email address to be checked. 1278 * @return bool Returns true if valid, otherwise false. 1279 */ 1280 function is_email($user_email) { 1281 $chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,6}\$/i"; 1282 if (strpos($user_email, '@') !== false && strpos($user_email, '.') !== false) { 1283 if (preg_match($chars, $user_email)) { 1284 return true; 1285 } else { 1286 return false; 1287 } 1288 } else { 1289 return false; 1290 } 1291 } 1292 1293 /** 1294 * Convert to ASCII from email subjects. 1295 * 1296 * @since 1.2.0 1297 * @usedby wp_mail() handles charsets in email subjects 1298 * 1299 * @param string $string Subject line 1300 * @return string Converted string to ASCII 1301 */ 1302 function wp_iso_descrambler($string) { 1303 /* this may only work with iso-8859-1, I'm afraid */ 1304 if (!preg_match('#\=\?(.+)\?Q\?(.+)\?\=#i', $string, $matches)) { 1305 return $string; 1306 } else { 1307 $subject = str_replace('_', ' ', $matches[2]); 1308 $subject = preg_replace_callback('#\=([0-9a-f]{2})#i', create_function('$match', 'return chr(hexdec(strtolower($match[1])));'), $subject); 1309 return $subject; 1310 } 1311 } 1312 1313 /** 1314 * Returns a date in the GMT equivalent. 1315 * 1316 * Requires and returns a date in the Y-m-d H:i:s format. Simply subtracts the 1317 * value of the 'gmt_offset' option. 1318 * 1319 * @since 1.2.0 1320 * 1321 * @uses get_option() to retrieve the the value of 'gmt_offset'. 1322 * @param string $string The date to be converted. 1323 * @return string GMT version of the date provided. 1324 */ 1325 function get_gmt_from_date($string) { 1326 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); 1327 $string_time = gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]); 1328 $string_gmt = gmdate('Y-m-d H:i:s', $string_time - get_option('gmt_offset') * 3600); 1329 return $string_gmt; 1330 } 1331 1332 /** 1333 * Converts a GMT date into the correct format for the blog. 1334 * 1335 * Requires and returns in the Y-m-d H:i:s format. Simply adds the value of 1336 * gmt_offset. 1337 * 1338 * @since 1.2.0 1339 * 1340 * @param string $string The date to be converted. 1341 * @return string Formatted date relative to the GMT offset. 1342 */ 1343 function get_date_from_gmt($string) { 1344 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); 1345 $string_time = gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]); 1346 $string_localtime = gmdate('Y-m-d H:i:s', $string_time + get_option('gmt_offset')*3600); 1347 return $string_localtime; 1348 } 1349 1350 /** 1351 * Computes an offset in seconds from an iso8601 timezone. 1352 * 1353 * @since 1.5.0 1354 * 1355 * @param string $timezone Either 'Z' for 0 offset or '±hhmm'. 1356 * @return int|float The offset in seconds. 1357 */ 1358 function iso8601_timezone_to_offset($timezone) { 1359 // $timezone is either 'Z' or '[+|-]hhmm' 1360 if ($timezone == 'Z') { 1361 $offset = 0; 1362 } else { 1363 $sign = (substr($timezone, 0, 1) == '+') ? 1 : -1; 1364 $hours = intval(substr($timezone, 1, 2)); 1365 $minutes = intval(substr($timezone, 3, 4)) / 60; 1366 $offset = $sign * 3600 * ($hours + $minutes); 1367 } 1368 return $offset; 1369 } 1370 1371 /** 1372 * Converts an iso8601 date to MySQL DateTime format used by post_date[_gmt]. 1373 * 1374 * @since 1.5.0 1375 * 1376 * @param string $date_string Date and time in ISO 8601 format {@link http://en.wikipedia.org/wiki/ISO_8601}. 1377 * @param string $timezone Optional. If set to GMT returns the time minus gmt_offset. Default is 'user'. 1378 * @return string The date and time in MySQL DateTime format - Y-m-d H:i:s. 1379 */ 1380 function iso8601_to_datetime($date_string, $timezone = 'user') { 1381 $timezone = strtolower($timezone); 1382 1383 if ($timezone == 'gmt') { 1384 1385 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); 1386 1387 if (!empty($date_bits[7])) { // we have a timezone, so let's compute an offset 1388 $offset = iso8601_timezone_to_offset($date_bits[7]); 1389 } else { // we don't have a timezone, so we assume user local timezone (not server's!) 1390 $offset = 3600 * get_option('gmt_offset'); 1391 } 1392 1393 $timestamp = gmmktime($date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1]); 1394 $timestamp -= $offset; 1395 1396 return gmdate('Y-m-d H:i:s', $timestamp); 1397 1398 } else if ($timezone == 'user') { 1399 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); 1400 } 1401 } 1402 1403 /** 1404 * Adds a element attributes to open links in new windows. 1405 * 1406 * Comment text in popup windows should be filtered through this. Right now it's 1407 * a moderately dumb function, ideally it would detect whether a target or rel 1408 * attribute was already there and adjust its actions accordingly. 1409 * 1410 * @since 0.71 1411 * 1412 * @param string $text Content to replace links to open in a new window. 1413 * @return string Content that has filtered links. 1414 */ 1415 function popuplinks($text) { 1416 $text = preg_replace('/<a (.+?)>/i', "<a $1 target='_blank' rel='external'>", $text); 1417 return $text; 1418 } 1419 1420 /** 1421 * Strips out all characters that are not allowable in an email. 1422 * 1423 * @since 1.5.0 1424 * 1425 * @param string $email Email address to filter. 1426 * @return string Filtered email address. 1427 */ 1428 function sanitize_email($email) { 1429 return preg_replace('/[^a-z0-9+_.@-]/i', '', $email); 1430 } 1431 1432 /** 1433 * Determines the difference between two timestamps. 1434 * 1435 * The difference is returned in a human readable format such as "1 hour", 1436 * "5 mins", "2 days". 1437 * 1438 * @since 1.5.0 1439 * 1440 * @param int $from Unix timestamp from which the difference begins. 1441 * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. 1442 * @return string Human readable time difference. 1443 */ 1444 function human_time_diff( $from, $to = '' ) { 1445 if ( empty($to) ) 1446 $to = time(); 1447 $diff = (int) abs($to - $from); 1448 if ($diff <= 3600) { 1449 $mins = round($diff / 60); 1450 if ($mins <= 1) { 1451 $mins = 1; 1452 } 1453 $since = sprintf(__ngettext('%s min', '%s mins', $mins), $mins); 1454 } else if (($diff <= 86400) && ($diff > 3600)) { 1455 $hours = round($diff / 3600); 1456 if ($hours <= 1) { 1457 $hours = 1; 1458 } 1459 $since = sprintf(__ngettext('%s hour', '%s hours', $hours), $hours); 1460 } elseif ($diff >= 86400) { 1461 $days = round($diff / 86400); 1462 if ($days <= 1) { 1463 $days = 1; 1464 } 1465 $since = sprintf(__ngettext('%s day', '%s days', $days), $days); 1466 } 1467 return $since; 1468 } 1469 1470 /** 1471 * Generates an excerpt from the content, if needed. 1472 * 1473 * The excerpt word amount will be 55 words and if the amount is greater than 1474 * that, then the string '[...]' will be appended to the excerpt. If the string 1475 * is less than 55 words, then the content will be returned as is. 1476 * 1477 * @since 1.5.0 1478 * 1479 * @param string $text The exerpt. If set to empty an excerpt is generated. 1480 * @return string The excerpt. 1481 */ 1482 function wp_trim_excerpt($text) { 1483 if ( '' == $text ) { 1484 $text = get_the_content(''); 1485 1486 $text = strip_shortcodes( $text ); 1487 1488 $text = apply_filters('the_content', $text); 1489 $text = str_replace(']]>', ']]>', $text); 1490 $text = strip_tags($text); 1491 $excerpt_length = apply_filters('excerpt_length', 55); 1492 $words = explode(' ', $text, $excerpt_length + 1); 1493 if (count($words) > $excerpt_length) { 1494 array_pop($words); 1495 array_push($words, '[...]'); 1496 $text = implode(' ', $words); 1497 } 1498 } 1499 return $text; 1500 } 1501 1502 /** 1503 * Converts named entities into numbered entities. 1504 * 1505 * @since 1.5.1 1506 * 1507 * @param string $text The text within which entities will be converted. 1508 * @return string Text with converted entities. 1509 */ 1510 function ent2ncr($text) { 1511 $to_ncr = array( 1512 '"' => '"', 1513 '&' => '&', 1514 '⁄' => '/', 1515 '<' => '<', 1516 '>' => '>', 1517 '|' => '|', 1518 ' ' => ' ', 1519 '¡' => '¡', 1520 '¢' => '¢', 1521 '£' => '£', 1522 '¤' => '¤', 1523 '¥' => '¥', 1524 '¦' => '¦', 1525 '&brkbar;' => '¦', 1526 '§' => '§', 1527 '¨' => '¨', 1528 '¨' => '¨', 1529 '©' => '©', 1530 'ª' => 'ª', 1531 '«' => '«', 1532 '¬' => '¬', 1533 '­' => '­', 1534 '®' => '®', 1535 '¯' => '¯', 1536 '&hibar;' => '¯', 1537 '°' => '°', 1538 '±' => '±', 1539 '²' => '²', 1540 '³' => '³', 1541 '´' => '´', 1542 'µ' => 'µ', 1543 '¶' => '¶', 1544 '·' => '·', 1545 '¸' => '¸', 1546 '¹' => '¹', 1547 'º' => 'º', 1548 '»' => '»', 1549 '¼' => '¼', 1550 '½' => '½', 1551 '¾' => '¾', 1552 '¿' => '¿', 1553 'À' => 'À', 1554 'Á' => 'Á', 1555 'Â' => 'Â', 1556 'Ã' => 'Ã', 1557 'Ä' => 'Ä', 1558 'Å' => 'Å', 1559 'Æ' => 'Æ', 1560 'Ç' => 'Ç', 1561 'È' => 'È', 1562 'É' => 'É', 1563 'Ê' => 'Ê', 1564 'Ë' => 'Ë', 1565 'Ì' => 'Ì', 1566 'Í' => 'Í', 1567 'Î' => 'Î', 1568 'Ï' => 'Ï', 1569 'Ð' => 'Ð', 1570 'Ñ' => 'Ñ', 1571 'Ò' => 'Ò', 1572 'Ó' => 'Ó', 1573 'Ô' => 'Ô', 1574 'Õ' => 'Õ', 1575 'Ö' => 'Ö', 1576 '×' => '×', 1577 'Ø' => 'Ø', 1578 'Ù' => 'Ù', 1579 'Ú' => 'Ú', 1580 'Û' => 'Û', 1581 'Ü' => 'Ü', 1582 'Ý' => 'Ý', 1583 'Þ' => 'Þ', 1584 'ß' => 'ß', 1585 'à' => 'à', 1586 'á' => 'á', 1587 'â' => 'â', 1588 'ã' => 'ã', 1589 'ä' => 'ä', 1590 'å' => 'å', 1591 'æ' => 'æ', 1592 'ç' => 'ç', 1593 'è' => 'è', 1594 'é' => 'é', 1595 'ê' => 'ê', 1596 'ë' => 'ë', 1597 'ì' => 'ì', 1598 'í' => 'í', 1599 'î' => 'î', 1600 'ï' => 'ï', 1601 'ð' => 'ð', 1602 'ñ' => 'ñ', 1603 'ò' => 'ò', 1604 'ó' => 'ó', 1605 'ô' => 'ô', 1606 'õ' => 'õ', 1607 'ö' => 'ö', 1608 '÷' => '÷', 1609 'ø' => 'ø', 1610 'ù' => 'ù', 1611 'ú' => 'ú', 1612 'û' => 'û', 1613 'ü' => 'ü', 1614 'ý' => 'ý', 1615 'þ' => 'þ', 1616 'ÿ' => 'ÿ', 1617 'Œ' => 'Œ', 1618 'œ' => 'œ', 1619 'Š' => 'Š', 1620 'š' => 'š', 1621 'Ÿ' => 'Ÿ', 1622 'ƒ' => 'ƒ', 1623 'ˆ' => 'ˆ', 1624 '˜' => '˜', 1625 'Α' => 'Α', 1626 'Β' => 'Β', 1627 'Γ' => 'Γ', 1628 'Δ' => 'Δ', 1629 'Ε' => 'Ε', 1630 'Ζ' => 'Ζ', 1631 'Η' => 'Η', 1632 'Θ' => 'Θ', 1633 'Ι' => 'Ι', 1634 'Κ' => 'Κ', 1635 'Λ' => 'Λ', 1636 'Μ' => 'Μ', 1637 'Ν' => 'Ν', 1638 'Ξ' => 'Ξ', 1639 'Ο' => 'Ο', 1640 'Π' => 'Π', 1641 'Ρ' => 'Ρ', 1642 'Σ' => 'Σ', 1643 'Τ' => 'Τ', 1644 'Υ' => 'Υ', 1645 'Φ' => 'Φ', 1646 'Χ' => 'Χ', 1647 'Ψ' => 'Ψ', 1648 'Ω' => 'Ω', 1649 'α' => 'α', 1650 'β' => 'β', 1651 'γ' => 'γ', 1652 'δ' => 'δ', 1653 'ε' => 'ε', 1654 'ζ' => 'ζ', 1655 'η' => 'η', 1656 'θ' => 'θ', 1657 'ι' => 'ι', 1658 'κ' => 'κ', 1659 'λ' => 'λ', 1660 'μ' => 'μ', 1661 'ν' => 'ν', 1662 'ξ' => 'ξ', 1663 'ο' => 'ο', 1664 'π' => 'π', 1665 'ρ' => 'ρ', 1666 'ς' => 'ς', 1667 'σ' => 'σ', 1668 'τ' => 'τ', 1669 'υ' => 'υ', 1670 'φ' => 'φ', 1671 'χ' => 'χ', 1672 'ψ' => 'ψ', 1673 'ω' => 'ω', 1674 'ϑ' => 'ϑ', 1675 'ϒ' => 'ϒ', 1676 'ϖ' => 'ϖ', 1677 ' ' => ' ', 1678 ' ' => ' ', 1679 ' ' => ' ', 1680 '‌' => '‌', 1681 '‍' => '‍', 1682 '‎' => '‎', 1683 '‏' => '‏', 1684 '–' => '–', 1685 '—' => '—', 1686 '‘' => '‘', 1687 '’' => '’', 1688 '‚' => '‚', 1689 '“' => '“', 1690 '”' => '”', 1691 '„' => '„', 1692 '†' => '†', 1693 '‡' => '‡', 1694 '•' => '•', 1695 '…' => '…', 1696 '‰' => '‰', 1697 '′' => '′', 1698 '″' => '″', 1699 '‹' => '‹', 1700 '›' => '›', 1701 '‾' => '‾', 1702 '⁄' => '⁄', 1703 '€' => '€', 1704 'ℑ' => 'ℑ', 1705 '℘' => '℘', 1706 'ℜ' => 'ℜ', 1707 '™' => '™', 1708 'ℵ' => 'ℵ', 1709 '↵' => '↵', 1710 '⇐' => '⇐', 1711 '⇑' => '⇑', 1712 '⇒' => '⇒', 1713 '⇓' => '⇓', 1714 '⇔' => '⇔', 1715 '∀' => '∀', 1716 '∂' => '∂', 1717 '∃' => '∃', 1718 '∅' => '∅', 1719 '∇' => '∇', 1720 '∈' => '∈', 1721 '∉' => '∉', 1722 '∋' => '∋', 1723 '∏' => '∏', 1724 '∑' => '∑', 1725 '−' => '−', 1726 '∗' => '∗', 1727 '√' => '√', 1728 '∝' => '∝', 1729 '∞' => '∞', 1730 '∠' => '∠', 1731 '∧' => '∧', 1732 '∨' => '∨', 1733 '∩' => '∩', 1734 '∪' => '∪', 1735 '∫' => '∫', 1736 '∴' => '∴', 1737 '∼' => '∼', 1738 '≅' => '≅', 1739 '≈' => '≈', 1740 '≠' => '≠', 1741 '≡' => '≡', 1742 '≤' => '≤', 1743 '≥' => '≥', 1744 '⊂' => '⊂', 1745 '⊃' => '⊃', 1746 '⊄' => '⊄', 1747 '⊆' => '⊆', 1748 '⊇' => '⊇', 1749 '⊕' => '⊕', 1750 '⊗' => '⊗', 1751 '⊥' => '⊥', 1752 '⋅' => '⋅', 1753 '⌈' => '⌈', 1754 '⌉' => '⌉', 1755 '⌊' => '⌊', 1756 '⌋' => '⌋', 1757 '⟨' => '〈', 1758 '⟩' => '〉', 1759 '←' => '←', 1760 '↑' => '↑', 1761 '→' => '→', 1762 '↓' => '↓', 1763 '↔' => '↔', 1764 '◊' => '◊', 1765 '♠' => '♠', 1766 '♣' => '♣', 1767 '♥' => '♥', 1768 '♦' => '♦' 1769 ); 1770 1771 return str_replace( array_keys($to_ncr), array_values($to_ncr), $text ); 1772 } 1773 1774 /** 1775 * Formats text for the rich text editor. 1776 * 1777 * The filter 'richedit_pre' is applied here. If $text is empty the filter will 1778 * be applied to an empty string. 1779 * 1780 * @since 2.0.0 1781 * 1782 * @param string $text The text to be formatted. 1783 * @return string The formatted text after filter is applied. 1784 */ 1785 function wp_richedit_pre($text) { 1786 // Filtering a blank results in an annoying <br />\n 1787 if ( empty($text) ) return apply_filters('richedit_pre', ''); 1788 1789 $output = convert_chars($text); 1790 $output = wpautop($output); 1791 $output = htmlspecialchars($output, ENT_NOQUOTES); 1792 1793 return apply_filters('richedit_pre', $output); 1794 } 1795 1796 /** 1797 * Formats text for the HTML editor. 1798 * 1799 * Unless $output is empty it will pass through htmlspecialchars before the 1800 * 'htmledit_pre' filter is applied. 1801 * 1802 * @since 2.5.0 1803 * 1804 * @param string $output The text to be formatted. 1805 * @return string Formatted text after filter applied. 1806 */ 1807 function wp_htmledit_pre($output) { 1808 if ( !empty($output) ) 1809 $output = htmlspecialchars($output, ENT_NOQUOTES); // convert only < > & 1810 1811 return apply_filters('htmledit_pre', $output); 1812 } 1813 1814 /** 1815 * Checks and cleans a URL. 1816 * 1817 * A number of characters are removed from the URL. If the URL is for displaying 1818 * (the default behaviour) amperstands are also replaced. The 'clean_url' filter 1819 * is applied to the returned cleaned URL. 1820 * 1821 * @since 1.2.0 1822 * @uses wp_kses_bad_protocol() To only permit protocols in the URL set 1823 * via $protocols or the common ones set in the function. 1824 * 1825 * @param string $url The URL to be cleaned. 1826 * @param array $protocols Optional. An array of acceptable protocols. 1827 * Defaults to 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet' if not set. 1828 * @param string $context Optional. How the URL will be used. Default is 'display'. 1829 * @return string The cleaned $url after the 'cleaned_url' filter is applied. 1830 */ 1831 function clean_url( $url, $protocols = null, $context = 'display' ) { 1832 $original_url = $url; 1833 1834 if ('' == $url) return $url; 1835 $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$*\'()\\x80-\\xff]|i', '', $url); 1836 $strip = array('%0d', '%0a'); 1837 $url = str_replace($strip, '', $url); 1838 $url = str_replace(';//', '://', $url); 1839 /* If the URL doesn't appear to contain a scheme, we 1840 * presume it needs http:// appended (unless a relative 1841 * link starting with / or a php file). 1842 */ 1843 if ( strpos($url, ':') === false && 1844 substr( $url, 0, 1 ) != '/' && !preg_match('/^[a-z0-9-]+?\.php/i', $url) ) 1845 $url = 'http://' . $url; 1846 1847 // Replace ampersands and single quotes only when displaying. 1848 if ( 'display' == $context ) { 1849 $url = preg_replace('/&([^#])(?![a-z]{2,8};)/', '&$1', $url); 1850 $url = str_replace( "'", ''', $url ); 1851 } 1852 1853 if ( !is_array($protocols) ) 1854 $protocols = array('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet'); 1855 if ( wp_kses_bad_protocol( $url, $protocols ) != $url ) 1856 return ''; 1857 1858 return apply_filters('clean_url', $url, $original_url, $context); 1859 } 1860 1861 /** 1862 * Performs clean_url() for database usage. 1863 * 1864 * @see clean_url() 1865 * 1866 * @since 2.3.1 1867 * 1868 * @param string $url The URL to be cleaned. 1869 * @param array $protocols An array of acceptable protocols. 1870 * @return string The cleaned URL. 1871 */ 1872 function sanitize_url( $url, $protocols = null ) { 1873 return clean_url( $url, $protocols, 'db' ); 1874 } 1875 1876 /** 1877 * Convert entities, while preserving already-encoded entities. 1878 * 1879 * @link http://www.php.net/htmlentities Borrowed from the PHP Manual user notes. 1880 * 1881 * @since 1.2.2 1882 * 1883 * @param string $myHTML The text to be converted. 1884 * @return string Converted text. 1885 */ 1886 function htmlentities2($myHTML) { 1887 $translation_table = get_html_translation_table( HTML_ENTITIES, ENT_QUOTES ); 1888 $translation_table[chr(38)] = '&'; 1889 return preg_replace( "/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/", "&", strtr($myHTML, $translation_table) ); 1890 } 1891 1892 /** 1893 * Escape single quotes, specialchar double quotes, and fix line endings. 1894 * 1895 * The filter 'js_escape' is also applied here. 1896 * 1897 * @since 2.0.4 1898 * 1899 * @param string $text The text to be escaped. 1900 * @return string Escaped text. 1901 */ 1902 function js_escape($text) { 1903 $safe_text = wp_check_invalid_utf8( $text ); 1904 $safe_text = wp_specialchars( $safe_text, ENT_COMPAT ); 1905 $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) ); 1906 $safe_text = preg_replace( "/\r?\n/", "\\n", addslashes( $safe_text ) ); 1907 return apply_filters( 'js_escape', $safe_text, $text ); 1908 } 1909 1910 /** 1911 * Escaping for HTML attributes. 1912 * 1913 * @since 2.0.6 1914 * 1915 * @param string $text 1916 * @return string 1917 */ 1918 function attribute_escape( $text ) { 1919 $safe_text = wp_check_invalid_utf8( $text ); 1920 $safe_text = wp_specialchars( $safe_text, ENT_QUOTES ); 1921 return apply_filters( 'attribute_escape', $safe_text, $text ); 1922 } 1923 1924 /** 1925 * Escape a HTML tag name. 1926 * 1927 * @since 2.5.0 1928 * 1929 * @param string $tag_name 1930 * @return string 1931 */ 1932 function tag_escape($tag_name) { 1933 $safe_tag = strtolower( preg_replace('/[^a-zA-Z_:]/', '', $tag_name) ); 1934 return apply_filters('tag_escape', $safe_tag, $tag_name); 1935 } 1936 1937 /** 1938 * Escapes text for SQL LIKE special characters % and _. 1939 * 1940 * @since 2.5.0 1941 * 1942 * @param string $text The text to be escaped. 1943 * @return string text, safe for inclusion in LIKE query. 1944 */ 1945 function like_escape($text) { 1946 return str_replace(array("%", "_"), array("\\%", "\\_"), $text); 1947 } 1948 1949 /** 1950 * Convert full URL paths to absolute paths. 1951 * 1952 * Removes the http or https protocols and the domain. Keeps the path '/' at the 1953 * beginning, so it isn't a true relative link, but from the web root base. 1954 * 1955 * @since 2.1.0 1956 * 1957 * @param string $link Full URL path. 1958 * @return string Absolute path. 1959 */ 1960 function wp_make_link_relative( $link ) { 1961 return preg_replace( '|https?://[^/]+(/.*)|i', '$1', $link ); 1962 } 1963 1964 /** 1965 * Sanitises various option values based on the nature of the option. 1966 * 1967 * This is basically a switch statement which will pass $value through a number 1968 * of functions depending on the $option. 1969 * 1970 * @since 2.0.5 1971 * 1972 * @param string $option The name of the option. 1973 * @param string $value The unsanitised value. 1974 * @return string Sanitized value. 1975 */ 1976 function sanitize_option($option, $value) { 1977 1978 switch ($option) { 1979 case 'admin_email': 1980 $value = sanitize_email($value); 1981 break; 1982 1983 case 'thumbnail_size_w': 1984 case 'thumbnail_size_h': 1985 case 'medium_size_w': 1986 case 'medium_size_h': 1987 case 'large_size_w': 1988 case 'large_size_h': 1989 case 'default_post_edit_rows': 1990 case 'mailserver_port': 1991 case 'comment_max_links': 1992 case 'page_on_front': 1993 case 'rss_excerpt_length': 1994 case 'default_category': 1995 case 'default_email_category': 1996 case 'default_link_category': 1997 case 'close_comments_days_old': 1998 case 'comments_per_page': 1999 case 'thread_comments_depth': 2000 $value = abs((int) $value); 2001 break; 2002 2003 case 'posts_per_page': 2004 case 'posts_per_rss': 2005 $value = (int) $value; 2006 if ( empty($value) ) $value = 1; 2007 if ( $value < -1 ) $value = abs($value); 2008 break; 2009 2010 case 'default_ping_status': 2011 case 'default_comment_status': 2012 // Options that if not there have 0 value but need to be something like "closed" 2013 if ( $value == '0' || $value == '') 2014 $value = 'closed'; 2015 break; 2016 2017 case 'blogdescription': 2018 case 'blogname': 2019 $value = addslashes($value); 2020 $value = wp_filter_post_kses( $value ); // calls stripslashes then addslashes 2021 $value = stripslashes($value); 2022 $value = wp_specialchars( $value ); 2023 break; 2024 2025 case 'blog_charset': 2026 $value = preg_replace('/[^a-zA-Z0-9_-]/', '', $value); // strips slashes 2027 break; 2028 2029 case 'date_format': 2030 case 'time_format': 2031 case 'mailserver_url': 2032 case 'mailserver_login': 2033 case 'mailserver_pass': 2034 case 'ping_sites': 2035 case 'upload_path': 2036 $value = strip_tags($value); 2037 $value = addslashes($value); 2038 $value = wp_filter_kses($value); // calls stripslashes then addslashes 2039 $value = stripslashes($value); 2040 break; 2041 2042 case 'gmt_offset': 2043 $value = preg_replace('/[^0-9:.-]/', '', $value); // strips slashes 2044 break; 2045 2046 case 'siteurl': 2047 case 'home': 2048 $value = stripslashes($value); 2049 $value = clean_url($value); 2050 break; 2051 default : 2052 $value = apply_filters("sanitize_option_{$option}", $value, $option); 2053 break; 2054 } 2055 2056 return $value; 2057 } 2058 2059 /** 2060 * Parses a string into variables to be stored in an array. 2061 * 2062 * Uses {@link http://www.php.net/parse_str parse_str()} and stripslashes if 2063 * {@link http://www.php.net/magic_quotes magic_quotes_gpc} is on. 2064 * 2065 * @since 2.2.1 2066 * @uses apply_filters() for the 'wp_parse_str' filter. 2067 * 2068 * @param string $string The string to be parsed. 2069 * @param array $array Variables will be stored in this array. 2070 */ 2071 function wp_parse_str( $string, &$array ) { 2072 parse_str( $string, $array ); 2073 if ( get_magic_quotes_gpc() ) 2074 $array = stripslashes_deep( $array ); 2075 $array = apply_filters( 'wp_parse_str', $array ); 2076 } 2077 2078 /** 2079 * Convert lone less than signs. 2080 * 2081 * KSES already converts lone greater than signs. 2082 * 2083 * @uses wp_pre_kses_less_than_callback in the callback function. 2084 * @since 2.3.0 2085 * 2086 * @param string $text Text to be converted. 2087 * @return string Converted text. 2088 */ 2089 function wp_pre_kses_less_than( $text ) { 2090 return preg_replace_callback('%<[^>]*?((?=<)|>|$)%', 'wp_pre_kses_less_than_callback', $text); 2091 } 2092 2093 /** 2094 * Callback function used by preg_replace. 2095 * 2096 * @uses wp_specialchars to format the $matches text. 2097 * @since 2.3.0 2098 * 2099 * @param array $matches Populated by matches to preg_replace. 2100 * @return string The text returned after wp_specialchars if needed. 2101 */ 2102 function wp_pre_kses_less_than_callback( $matches ) { 2103 if ( false === strpos($matches[0], '>') ) 2104 return wp_specialchars($matches[0]); 2105 return $matches[0]; 2106 } 2107 2108 /** 2109 * WordPress implementation of PHP sprintf() with filters. 2110 * 2111 * @since 2.5.0 2112 * @link http://www.php.net/sprintf 2113 * 2114 * @param string $pattern The string which formatted args are inserted. 2115 * @param mixed $args,... Arguments to be formatted into the $pattern string. 2116 * @return string The formatted string. 2117 */ 2118 function wp_sprintf( $pattern ) { 2119 $args = func_get_args( ); 2120 $len = strlen($pattern); 2121 $start = 0; 2122 $result = ''; 2123 $arg_index = 0; 2124 while ( $len > $start ) { 2125 // Last character: append and break 2126 if ( strlen($pattern) - 1 == $start ) { 2127 $result .= substr($pattern, -1); 2128 break; 2129 } 2130 2131 // Literal %: append and continue 2132 if ( substr($pattern, $start, 2) == '%%' ) { 2133 $start += 2; 2134 $result .= '%'; 2135 continue; 2136 } 2137 2138 // Get fragment before next % 2139 $end = strpos($pattern, '%', $start + 1); 2140 if ( false === $end ) 2141 $end = $len; 2142 $fragment = substr($pattern, $start, $end - $start); 2143 2144 // Fragment has a specifier 2145 if ( $pattern{$start} == '%' ) { 2146 // Find numbered arguments or take the next one in order 2147 if ( preg_match('/^%(\d+)\$/', $fragment, $matches) ) { 2148 $arg = isset($args[$matches[1]]) ? $args[$matches[1]] : ''; 2149 $fragment = str_replace("%{$matches[1]}$", '%', $fragment); 2150 } else { 2151 ++$arg_index; 2152 $arg = isset($args[$arg_index]) ? $args[$arg_index] : ''; 2153 } 2154 2155 // Apply filters OR sprintf 2156 $_fragment = apply_filters( 'wp_sprintf', $fragment, $arg ); 2157 if ( $_fragment != $fragment ) 2158 $fragment = $_fragment; 2159 else 2160 $fragment = sprintf($fragment, strval($arg) ); 2161 } 2162 2163 // Append to result and move to next fragment 2164 $result .= $fragment; 2165 $start = $end; 2166 } 2167 return $result; 2168 } 2169 2170 /** 2171 * Localize list items before the rest of the content. 2172 * 2173 * The '%l' must be at the first characters can then contain the rest of the 2174 * content. The list items will have ', ', ', and', and ' and ' added depending 2175 * on the amount of list items in the $args parameter. 2176 * 2177 * @since 2.5.0 2178 * 2179 * @param string $pattern Content containing '%l' at the beginning. 2180 * @param array $args List items to prepend to the content and replace '%l'. 2181 * @return string Localized list items and rest of the content. 2182 */ 2183 function wp_sprintf_l($pattern, $args) { 2184 // Not a match 2185 if ( substr($pattern, 0, 2) != '%l' ) 2186 return $pattern; 2187 2188 // Nothing to work with 2189 if ( empty($args) ) 2190 return ''; 2191 2192 // Translate and filter the delimiter set (avoid ampersands and entities here) 2193 $l = apply_filters('wp_sprintf_l', array( 2194 'between' => _c(', |between list items'), 2195 'between_last_two' => _c(', and |between last two list items'), 2196 'between_only_two' => _c(' and |between only two list items'), 2197 )); 2198 2199 $args = (array) $args; 2200 $result = array_shift($args); 2201 if ( count($args) == 1 ) 2202 $result .= $l['between_only_two'] . array_shift($args); 2203 // Loop when more than two args 2204 $i = count($args); 2205 while ( $i ) { 2206 $arg = array_shift($args); 2207 $i--; 2208 if ( $i == 1 ) 2209 $result .= $l['between_last_two'] . $arg; 2210 else 2211 $result .= $l['between'] . $arg; 2212 } 2213 return $result . substr($pattern, 2); 2214 } 2215 2216 /** 2217 * Safely extracts not more than the first $count characters from html string. 2218 * 2219 * UTF-8, tags and entities safe prefix extraction. Entities inside will *NOT* 2220 * be counted as one character. For example & will be counted as 4, < as 2221 * 3, etc. 2222 * 2223 * @since 2.5.0 2224 * 2225 * @param integer $str String to get the excerpt from. 2226 * @param integer $count Maximum number of characters to take. 2227 * @return string The excerpt. 2228 */ 2229 function wp_html_excerpt( $str, $count ) { 2230 $str = strip_tags( $str ); 2231 $str = mb_strcut( $str, 0, $count ); 2232 // remove part of an entity at the end 2233 $str = preg_replace( '/&[^;\s]{0,6}$/', '', $str ); 2234 return $str; 2235 } 2236 2237 /** 2238 * Add a Base url to relative links in passed content. 2239 * 2240 * By default it supports the 'src' and 'href' attributes. However this can be 2241 * changed via the 3rd param. 2242 * 2243 * @since 2.7.0 2244 * 2245 * @param string $content String to search for links in. 2246 * @param string $base The base URL to prefix to links. 2247 * @param array $attrs The attributes which should be processed. 2248 * @return string The processed content. 2249 */ 2250 function links_add_base_url( $content, $base, $attrs = array('src', 'href') ) { 2251 $attrs = implode('|', (array)$attrs); 2252 return preg_replace_callback("!($attrs)=(['\"])(.+?)\\2!i", 2253 create_function('$m', 'return _links_add_base($m, "' . $base . '");'), 2254 $content); 2255 } 2256 2257 /** 2258 * Callback to add a base url to relative links in passed content. 2259 * 2260 * @since 2.7.0 2261 * @access private 2262 * 2263 * @param string $m The matched link. 2264 * @param string $base The base URL to prefix to links. 2265 * @return string The processed link. 2266 */ 2267 function _links_add_base($m, $base) { 2268 //1 = attribute name 2 = quotation mark 3 = URL 2269 return $m[1] . '=' . $m[2] . 2270 (strpos($m[3], 'http://') === false ? 2271 path_join($base, $m[3]) : 2272 $m[3]) 2273 . $m[2]; 2274 } 2275 2276 /** 2277 * Adds a Target attribute to all links in passed content. 2278 * 2279 * This function by default only applies to <a> tags, however this can be 2280 * modified by the 3rd param. 2281 * 2282 * <b>NOTE:</b> Any current target attributed will be striped and replaced. 2283 * 2284 * @since 2.7.0 2285 * 2286 * @param string $content String to search for links in. 2287 * @param string $target The Target to add to the links. 2288 * @param array $tags An array of tags to apply to. 2289 * @return string The processed content. 2290 */ 2291 function links_add_target( $content, $target = '_blank', $tags = array('a') ) { 2292 $tags = implode('|', (array)$tags); 2293 return preg_replace_callback("!<($tags)(.+?)>!i", 2294 create_function('$m', 'return _links_add_target($m, "' . $target . '");'), 2295 $content); 2296 } 2297 /** 2298 * Callback to add a target attribute to all links in passed content. 2299 * 2300 * @since 2.7.0 2301 * @access private 2302 * 2303 * @param string $m The matched link. 2304 * @param string $target The Target to add to the links. 2305 * @return string The processed link. 2306 */ 2307 function _links_add_target( $m, $target ) { 2308 $tag = $m[1]; 2309 $link = preg_replace('|(target=[\'"](.*?)[\'"])|i', '', $m[2]); 2310 return '<' . $tag . $link . ' target="' . $target . '">'; 2311 } 2312 2313 // normalize EOL characters and strip duplicate whitespace 2314 function normalize_whitespace( $str ) { 2315 $str = trim($str); 2316 $str = str_replace("\r", "\n", $str); 2317 $str = preg_replace( array( '/\n+/', '/[ \t]+/' ), array( "\n", ' ' ), $str ); 2318 return $str; 2319 } 2320 2321 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Mar 23 16:23:02 2009 | Cross-referenced by PHPXref 0.7 |