wp/wp-includes/functions.php
changeset 0 d970ebf37754
child 5 5e2f62d02dcd
equal deleted inserted replaced
-1:000000000000 0:d970ebf37754
       
     1 <?php
       
     2 /**
       
     3  * Main WordPress API
       
     4  *
       
     5  * @package WordPress
       
     6  */
       
     7 
       
     8 require( ABSPATH . WPINC . '/option.php' );
       
     9 
       
    10 /**
       
    11  * Converts given date string into a different format.
       
    12  *
       
    13  * $format should be either a PHP date format string, e.g. 'U' for a Unix
       
    14  * timestamp, or 'G' for a Unix timestamp assuming that $date is GMT.
       
    15  *
       
    16  * If $translate is true then the given date and format string will
       
    17  * be passed to date_i18n() for translation.
       
    18  *
       
    19  * @since 0.71
       
    20  *
       
    21  * @param string $format Format of the date to return.
       
    22  * @param string $date Date string to convert.
       
    23  * @param bool $translate Whether the return date should be translated. Default is true.
       
    24  * @return string|int Formatted date string, or Unix timestamp.
       
    25  */
       
    26 function mysql2date( $format, $date, $translate = true ) {
       
    27 	if ( empty( $date ) )
       
    28 		return false;
       
    29 
       
    30 	if ( 'G' == $format )
       
    31 		return strtotime( $date . ' +0000' );
       
    32 
       
    33 	$i = strtotime( $date );
       
    34 
       
    35 	if ( 'U' == $format )
       
    36 		return $i;
       
    37 
       
    38 	if ( $translate )
       
    39 		return date_i18n( $format, $i );
       
    40 	else
       
    41 		return date( $format, $i );
       
    42 }
       
    43 
       
    44 /**
       
    45  * Retrieve the current time based on specified type.
       
    46  *
       
    47  * The 'mysql' type will return the time in the format for MySQL DATETIME field.
       
    48  * The 'timestamp' type will return the current timestamp.
       
    49  *
       
    50  * If $gmt is set to either '1' or 'true', then both types will use GMT time.
       
    51  * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option.
       
    52  *
       
    53  * @since 1.0.0
       
    54  *
       
    55  * @param string $type Either 'mysql' or 'timestamp'.
       
    56  * @param int|bool $gmt Optional. Whether to use GMT timezone. Default is false.
       
    57  * @return int|string String if $type is 'gmt', int if $type is 'timestamp'.
       
    58  */
       
    59 function current_time( $type, $gmt = 0 ) {
       
    60 	switch ( $type ) {
       
    61 		case 'mysql':
       
    62 			return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) ) );
       
    63 			break;
       
    64 		case 'timestamp':
       
    65 			return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
       
    66 			break;
       
    67 	}
       
    68 }
       
    69 
       
    70 /**
       
    71  * Retrieve the date in localized format, based on timestamp.
       
    72  *
       
    73  * If the locale specifies the locale month and weekday, then the locale will
       
    74  * take over the format for the date. If it isn't, then the date format string
       
    75  * will be used instead.
       
    76  *
       
    77  * @since 0.71
       
    78  *
       
    79  * @param string $dateformatstring Format to display the date.
       
    80  * @param int $unixtimestamp Optional. Unix timestamp.
       
    81  * @param bool $gmt Optional, default is false. Whether to convert to GMT for time.
       
    82  * @return string The date, translated if locale specifies it.
       
    83  */
       
    84 function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
       
    85 	global $wp_locale;
       
    86 	$i = $unixtimestamp;
       
    87 
       
    88 	if ( false === $i ) {
       
    89 		if ( ! $gmt )
       
    90 			$i = current_time( 'timestamp' );
       
    91 		else
       
    92 			$i = time();
       
    93 		// we should not let date() interfere with our
       
    94 		// specially computed timestamp
       
    95 		$gmt = true;
       
    96 	}
       
    97 
       
    98 	// store original value for language with untypical grammars
       
    99 	// see http://core.trac.wordpress.org/ticket/9396
       
   100 	$req_format = $dateformatstring;
       
   101 
       
   102 	$datefunc = $gmt? 'gmdate' : 'date';
       
   103 
       
   104 	if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
       
   105 		$datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
       
   106 		$datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
       
   107 		$dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
       
   108 		$dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
       
   109 		$datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
       
   110 		$datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
       
   111 		$dateformatstring = ' '.$dateformatstring;
       
   112 		$dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
       
   113 		$dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
       
   114 		$dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
       
   115 		$dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
       
   116 		$dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
       
   117 		$dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
       
   118 
       
   119 		$dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
       
   120 	}
       
   121 	$timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' );
       
   122 	$timezone_formats_re = implode( '|', $timezone_formats );
       
   123 	if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) {
       
   124 		$timezone_string = get_option( 'timezone_string' );
       
   125 		if ( $timezone_string ) {
       
   126 			$timezone_object = timezone_open( $timezone_string );
       
   127 			$date_object = date_create( null, $timezone_object );
       
   128 			foreach( $timezone_formats as $timezone_format ) {
       
   129 				if ( false !== strpos( $dateformatstring, $timezone_format ) ) {
       
   130 					$formatted = date_format( $date_object, $timezone_format );
       
   131 					$dateformatstring = ' '.$dateformatstring;
       
   132 					$dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring );
       
   133 					$dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
       
   134 				}
       
   135 			}
       
   136 		}
       
   137 	}
       
   138 	$j = @$datefunc( $dateformatstring, $i );
       
   139 	// allow plugins to redo this entirely for languages with untypical grammars
       
   140 	$j = apply_filters('date_i18n', $j, $req_format, $i, $gmt);
       
   141 	return $j;
       
   142 }
       
   143 
       
   144 /**
       
   145  * Convert integer number to format based on the locale.
       
   146  *
       
   147  * @since 2.3.0
       
   148  *
       
   149  * @param int $number The number to convert based on locale.
       
   150  * @param int $decimals Precision of the number of decimal places.
       
   151  * @return string Converted number in string format.
       
   152  */
       
   153 function number_format_i18n( $number, $decimals = 0 ) {
       
   154 	global $wp_locale;
       
   155 	$formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
       
   156 	return apply_filters( 'number_format_i18n', $formatted );
       
   157 }
       
   158 
       
   159 /**
       
   160  * Convert number of bytes largest unit bytes will fit into.
       
   161  *
       
   162  * It is easier to read 1kB than 1024 bytes and 1MB than 1048576 bytes. Converts
       
   163  * number of bytes to human readable number by taking the number of that unit
       
   164  * that the bytes will go into it. Supports TB value.
       
   165  *
       
   166  * Please note that integers in PHP are limited to 32 bits, unless they are on
       
   167  * 64 bit architecture, then they have 64 bit size. If you need to place the
       
   168  * larger size then what PHP integer type will hold, then use a string. It will
       
   169  * be converted to a double, which should always have 64 bit length.
       
   170  *
       
   171  * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
       
   172  * @link http://en.wikipedia.org/wiki/Byte
       
   173  *
       
   174  * @since 2.3.0
       
   175  *
       
   176  * @param int|string $bytes Number of bytes. Note max integer size for integers.
       
   177  * @param int $decimals Precision of number of decimal places. Deprecated.
       
   178  * @return bool|string False on failure. Number string on success.
       
   179  */
       
   180 function size_format( $bytes, $decimals = 0 ) {
       
   181 	$quant = array(
       
   182 		// ========================= Origin ====
       
   183 		'TB' => 1099511627776,  // pow( 1024, 4)
       
   184 		'GB' => 1073741824,     // pow( 1024, 3)
       
   185 		'MB' => 1048576,        // pow( 1024, 2)
       
   186 		'kB' => 1024,           // pow( 1024, 1)
       
   187 		'B ' => 1,              // pow( 1024, 0)
       
   188 	);
       
   189 	foreach ( $quant as $unit => $mag )
       
   190 		if ( doubleval($bytes) >= $mag )
       
   191 			return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
       
   192 
       
   193 	return false;
       
   194 }
       
   195 
       
   196 /**
       
   197  * Get the week start and end from the datetime or date string from mysql.
       
   198  *
       
   199  * @since 0.71
       
   200  *
       
   201  * @param string $mysqlstring Date or datetime field type from mysql.
       
   202  * @param int $start_of_week Optional. Start of the week as an integer.
       
   203  * @return array Keys are 'start' and 'end'.
       
   204  */
       
   205 function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
       
   206 	$my = substr( $mysqlstring, 0, 4 ); // Mysql string Year
       
   207 	$mm = substr( $mysqlstring, 8, 2 ); // Mysql string Month
       
   208 	$md = substr( $mysqlstring, 5, 2 ); // Mysql string day
       
   209 	$day = mktime( 0, 0, 0, $md, $mm, $my ); // The timestamp for mysqlstring day.
       
   210 	$weekday = date( 'w', $day ); // The day of the week from the timestamp
       
   211 	if ( !is_numeric($start_of_week) )
       
   212 		$start_of_week = get_option( 'start_of_week' );
       
   213 
       
   214 	if ( $weekday < $start_of_week )
       
   215 		$weekday += 7;
       
   216 
       
   217 	$start = $day - DAY_IN_SECONDS * ( $weekday - $start_of_week ); // The most recent week start day on or before $day
       
   218 	$end = $start + 7 * DAY_IN_SECONDS - 1; // $start + 7 days - 1 second
       
   219 	return compact( 'start', 'end' );
       
   220 }
       
   221 
       
   222 /**
       
   223  * Unserialize value only if it was serialized.
       
   224  *
       
   225  * @since 2.0.0
       
   226  *
       
   227  * @param string $original Maybe unserialized original, if is needed.
       
   228  * @return mixed Unserialized data can be any type.
       
   229  */
       
   230 function maybe_unserialize( $original ) {
       
   231 	if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
       
   232 		return @unserialize( $original );
       
   233 	return $original;
       
   234 }
       
   235 
       
   236 /**
       
   237  * Check value to find if it was serialized.
       
   238  *
       
   239  * If $data is not an string, then returned value will always be false.
       
   240  * Serialized data is always a string.
       
   241  *
       
   242  * @since 2.0.5
       
   243  *
       
   244  * @param mixed $data Value to check to see if was serialized.
       
   245  * @param bool $strict Optional. Whether to be strict about the end of the string. Defaults true.
       
   246  * @return bool False if not serialized and true if it was.
       
   247  */
       
   248 function is_serialized( $data, $strict = true ) {
       
   249 	// if it isn't a string, it isn't serialized
       
   250 	if ( ! is_string( $data ) )
       
   251 		return false;
       
   252 	$data = trim( $data );
       
   253  	if ( 'N;' == $data )
       
   254 		return true;
       
   255 	$length = strlen( $data );
       
   256 	if ( $length < 4 )
       
   257 		return false;
       
   258 	if ( ':' !== $data[1] )
       
   259 		return false;
       
   260 	if ( $strict ) {
       
   261 		$lastc = $data[ $length - 1 ];
       
   262 		if ( ';' !== $lastc && '}' !== $lastc )
       
   263 			return false;
       
   264 	} else {
       
   265 		$semicolon = strpos( $data, ';' );
       
   266 		$brace     = strpos( $data, '}' );
       
   267 		// Either ; or } must exist.
       
   268 		if ( false === $semicolon && false === $brace )
       
   269 			return false;
       
   270 		// But neither must be in the first X characters.
       
   271 		if ( false !== $semicolon && $semicolon < 3 )
       
   272 			return false;
       
   273 		if ( false !== $brace && $brace < 4 )
       
   274 			return false;
       
   275 	}
       
   276 	$token = $data[0];
       
   277 	switch ( $token ) {
       
   278 		case 's' :
       
   279 			if ( $strict ) {
       
   280 				if ( '"' !== $data[ $length - 2 ] )
       
   281 					return false;
       
   282 			} elseif ( false === strpos( $data, '"' ) ) {
       
   283 				return false;
       
   284 			}
       
   285 			// or else fall through
       
   286 		case 'a' :
       
   287 		case 'O' :
       
   288 			return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
       
   289 		case 'b' :
       
   290 		case 'i' :
       
   291 		case 'd' :
       
   292 			$end = $strict ? '$' : '';
       
   293 			return (bool) preg_match( "/^{$token}:[0-9.E-]+;$end/", $data );
       
   294 	}
       
   295 	return false;
       
   296 }
       
   297 
       
   298 /**
       
   299  * Check whether serialized data is of string type.
       
   300  *
       
   301  * @since 2.0.5
       
   302  *
       
   303  * @param mixed $data Serialized data
       
   304  * @return bool False if not a serialized string, true if it is.
       
   305  */
       
   306 function is_serialized_string( $data ) {
       
   307 	// if it isn't a string, it isn't a serialized string
       
   308 	if ( !is_string( $data ) )
       
   309 		return false;
       
   310 	$data = trim( $data );
       
   311 	$length = strlen( $data );
       
   312 	if ( $length < 4 )
       
   313 		return false;
       
   314 	elseif ( ':' !== $data[1] )
       
   315 		return false;
       
   316 	elseif ( ';' !== $data[$length-1] )
       
   317 		return false;
       
   318 	elseif ( $data[0] !== 's' )
       
   319 		return false;
       
   320 	elseif ( '"' !== $data[$length-2] )
       
   321 		return false;
       
   322 	else
       
   323 		return true;
       
   324 }
       
   325 
       
   326 /**
       
   327  * Serialize data, if needed.
       
   328  *
       
   329  * @since 2.0.5
       
   330  *
       
   331  * @param mixed $data Data that might be serialized.
       
   332  * @return mixed A scalar data
       
   333  */
       
   334 function maybe_serialize( $data ) {
       
   335 	if ( is_array( $data ) || is_object( $data ) )
       
   336 		return serialize( $data );
       
   337 
       
   338 	// Double serialization is required for backward compatibility.
       
   339 	// See http://core.trac.wordpress.org/ticket/12930
       
   340 	if ( is_serialized( $data, false ) )
       
   341 		return serialize( $data );
       
   342 
       
   343 	return $data;
       
   344 }
       
   345 
       
   346 /**
       
   347  * Retrieve post title from XMLRPC XML.
       
   348  *
       
   349  * If the title element is not part of the XML, then the default post title from
       
   350  * the $post_default_title will be used instead.
       
   351  *
       
   352  * @package WordPress
       
   353  * @subpackage XMLRPC
       
   354  * @since 0.71
       
   355  *
       
   356  * @global string $post_default_title Default XMLRPC post title.
       
   357  *
       
   358  * @param string $content XMLRPC XML Request content
       
   359  * @return string Post title
       
   360  */
       
   361 function xmlrpc_getposttitle( $content ) {
       
   362 	global $post_default_title;
       
   363 	if ( preg_match( '/<title>(.+?)<\/title>/is', $content, $matchtitle ) ) {
       
   364 		$post_title = $matchtitle[1];
       
   365 	} else {
       
   366 		$post_title = $post_default_title;
       
   367 	}
       
   368 	return $post_title;
       
   369 }
       
   370 
       
   371 /**
       
   372  * Retrieve the post category or categories from XMLRPC XML.
       
   373  *
       
   374  * If the category element is not found, then the default post category will be
       
   375  * used. The return type then would be what $post_default_category. If the
       
   376  * category is found, then it will always be an array.
       
   377  *
       
   378  * @package WordPress
       
   379  * @subpackage XMLRPC
       
   380  * @since 0.71
       
   381  *
       
   382  * @global string $post_default_category Default XMLRPC post category.
       
   383  *
       
   384  * @param string $content XMLRPC XML Request content
       
   385  * @return string|array List of categories or category name.
       
   386  */
       
   387 function xmlrpc_getpostcategory( $content ) {
       
   388 	global $post_default_category;
       
   389 	if ( preg_match( '/<category>(.+?)<\/category>/is', $content, $matchcat ) ) {
       
   390 		$post_category = trim( $matchcat[1], ',' );
       
   391 		$post_category = explode( ',', $post_category );
       
   392 	} else {
       
   393 		$post_category = $post_default_category;
       
   394 	}
       
   395 	return $post_category;
       
   396 }
       
   397 
       
   398 /**
       
   399  * XMLRPC XML content without title and category elements.
       
   400  *
       
   401  * @package WordPress
       
   402  * @subpackage XMLRPC
       
   403  * @since 0.71
       
   404  *
       
   405  * @param string $content XMLRPC XML Request content
       
   406  * @return string XMLRPC XML Request content without title and category elements.
       
   407  */
       
   408 function xmlrpc_removepostdata( $content ) {
       
   409 	$content = preg_replace( '/<title>(.+?)<\/title>/si', '', $content );
       
   410 	$content = preg_replace( '/<category>(.+?)<\/category>/si', '', $content );
       
   411 	$content = trim( $content );
       
   412 	return $content;
       
   413 }
       
   414 
       
   415 /**
       
   416  * Use RegEx to extract URLs from arbitrary content
       
   417  *
       
   418  * @since 3.7.0
       
   419  *
       
   420  * @param string $content
       
   421  * @return array URLs found in passed string
       
   422  */
       
   423 function wp_extract_urls( $content ) {
       
   424 	preg_match_all(
       
   425 		"#((?:[\w-]+://?|[\w\d]+[.])[^\s()<>]+[.](?:\([\w\d]+\)|(?:[^`!()\[\]{};:'\".,<>?«»“”‘’\s]|(?:[:]\d+)?/?)+))#",
       
   426 		$content,
       
   427 		$post_links
       
   428 	);
       
   429 
       
   430 	$post_links = array_unique( array_map( 'html_entity_decode', $post_links[0] ) );
       
   431 
       
   432 	return array_values( $post_links );
       
   433 }
       
   434 
       
   435 /**
       
   436  * Check content for video and audio links to add as enclosures.
       
   437  *
       
   438  * Will not add enclosures that have already been added and will
       
   439  * remove enclosures that are no longer in the post. This is called as
       
   440  * pingbacks and trackbacks.
       
   441  *
       
   442  * @package WordPress
       
   443  * @since 1.5.0
       
   444  *
       
   445  * @uses $wpdb
       
   446  *
       
   447  * @param string $content Post Content
       
   448  * @param int $post_ID Post ID
       
   449  */
       
   450 function do_enclose( $content, $post_ID ) {
       
   451 	global $wpdb;
       
   452 
       
   453 	//TODO: Tidy this ghetto code up and make the debug code optional
       
   454 	include_once( ABSPATH . WPINC . '/class-IXR.php' );
       
   455 
       
   456 	$post_links = array();
       
   457 
       
   458 	$pung = get_enclosed( $post_ID );
       
   459 
       
   460 	$post_links_temp = wp_extract_urls( $content );
       
   461 
       
   462 	foreach ( $pung as $link_test ) {
       
   463 		if ( ! in_array( $link_test, $post_links_temp ) ) { // link no longer in post
       
   464 			$mids = $wpdb->get_col( $wpdb->prepare("SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE (%s)", $post_ID, like_escape( $link_test ) . '%') );
       
   465 			foreach ( $mids as $mid )
       
   466 				delete_metadata_by_mid( 'post', $mid );
       
   467 		}
       
   468 	}
       
   469 
       
   470 	foreach ( (array) $post_links_temp as $link_test ) {
       
   471 		if ( !in_array( $link_test, $pung ) ) { // If we haven't pung it already
       
   472 			$test = @parse_url( $link_test );
       
   473 			if ( false === $test )
       
   474 				continue;
       
   475 			if ( isset( $test['query'] ) )
       
   476 				$post_links[] = $link_test;
       
   477 			elseif ( isset($test['path']) && ( $test['path'] != '/' ) &&  ($test['path'] != '' ) )
       
   478 				$post_links[] = $link_test;
       
   479 		}
       
   480 	}
       
   481 
       
   482 	foreach ( (array) $post_links as $url ) {
       
   483 		if ( $url != '' && !$wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE (%s)", $post_ID, like_escape( $url ) . '%' ) ) ) {
       
   484 
       
   485 			if ( $headers = wp_get_http_headers( $url) ) {
       
   486 				$len = isset( $headers['content-length'] ) ? (int) $headers['content-length'] : 0;
       
   487 				$type = isset( $headers['content-type'] ) ? $headers['content-type'] : '';
       
   488 				$allowed_types = array( 'video', 'audio' );
       
   489 
       
   490 				// Check to see if we can figure out the mime type from
       
   491 				// the extension
       
   492 				$url_parts = @parse_url( $url );
       
   493 				if ( false !== $url_parts ) {
       
   494 					$extension = pathinfo( $url_parts['path'], PATHINFO_EXTENSION );
       
   495 					if ( !empty( $extension ) ) {
       
   496 						foreach ( wp_get_mime_types() as $exts => $mime ) {
       
   497 							if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
       
   498 								$type = $mime;
       
   499 								break;
       
   500 							}
       
   501 						}
       
   502 					}
       
   503 				}
       
   504 
       
   505 				if ( in_array( substr( $type, 0, strpos( $type, "/" ) ), $allowed_types ) ) {
       
   506 					add_post_meta( $post_ID, 'enclosure', "$url\n$len\n$mime\n" );
       
   507 				}
       
   508 			}
       
   509 		}
       
   510 	}
       
   511 }
       
   512 
       
   513 /**
       
   514  * Perform a HTTP HEAD or GET request.
       
   515  *
       
   516  * If $file_path is a writable filename, this will do a GET request and write
       
   517  * the file to that path.
       
   518  *
       
   519  * @since 2.5.0
       
   520  *
       
   521  * @param string $url URL to fetch.
       
   522  * @param string|bool $file_path Optional. File path to write request to.
       
   523  * @param int $red (private) The number of Redirects followed, Upon 5 being hit, returns false.
       
   524  * @return bool|string False on failure and string of headers if HEAD request.
       
   525  */
       
   526 function wp_get_http( $url, $file_path = false, $red = 1 ) {
       
   527 	@set_time_limit( 60 );
       
   528 
       
   529 	if ( $red > 5 )
       
   530 		return false;
       
   531 
       
   532 	$options = array();
       
   533 	$options['redirection'] = 5;
       
   534 
       
   535 	if ( false == $file_path )
       
   536 		$options['method'] = 'HEAD';
       
   537 	else
       
   538 		$options['method'] = 'GET';
       
   539 
       
   540 	$response = wp_safe_remote_request( $url, $options );
       
   541 
       
   542 	if ( is_wp_error( $response ) )
       
   543 		return false;
       
   544 
       
   545 	$headers = wp_remote_retrieve_headers( $response );
       
   546 	$headers['response'] = wp_remote_retrieve_response_code( $response );
       
   547 
       
   548 	// WP_HTTP no longer follows redirects for HEAD requests.
       
   549 	if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) {
       
   550 		return wp_get_http( $headers['location'], $file_path, ++$red );
       
   551 	}
       
   552 
       
   553 	if ( false == $file_path )
       
   554 		return $headers;
       
   555 
       
   556 	// GET request - write it to the supplied filename
       
   557 	$out_fp = fopen($file_path, 'w');
       
   558 	if ( !$out_fp )
       
   559 		return $headers;
       
   560 
       
   561 	fwrite( $out_fp,  wp_remote_retrieve_body( $response ) );
       
   562 	fclose($out_fp);
       
   563 	clearstatcache();
       
   564 
       
   565 	return $headers;
       
   566 }
       
   567 
       
   568 /**
       
   569  * Retrieve HTTP Headers from URL.
       
   570  *
       
   571  * @since 1.5.1
       
   572  *
       
   573  * @param string $url
       
   574  * @param bool $deprecated Not Used.
       
   575  * @return bool|string False on failure, headers on success.
       
   576  */
       
   577 function wp_get_http_headers( $url, $deprecated = false ) {
       
   578 	if ( !empty( $deprecated ) )
       
   579 		_deprecated_argument( __FUNCTION__, '2.7' );
       
   580 
       
   581 	$response = wp_safe_remote_head( $url );
       
   582 
       
   583 	if ( is_wp_error( $response ) )
       
   584 		return false;
       
   585 
       
   586 	return wp_remote_retrieve_headers( $response );
       
   587 }
       
   588 
       
   589 /**
       
   590  * Whether today is a new day.
       
   591  *
       
   592  * @since 0.71
       
   593  * @uses $day Today
       
   594  * @uses $previousday Previous day
       
   595  *
       
   596  * @return int 1 when new day, 0 if not a new day.
       
   597  */
       
   598 function is_new_day() {
       
   599 	global $currentday, $previousday;
       
   600 	if ( $currentday != $previousday )
       
   601 		return 1;
       
   602 	else
       
   603 		return 0;
       
   604 }
       
   605 
       
   606 /**
       
   607  * Build URL query based on an associative and, or indexed array.
       
   608  *
       
   609  * This is a convenient function for easily building url queries. It sets the
       
   610  * separator to '&' and uses _http_build_query() function.
       
   611  *
       
   612  * @see _http_build_query() Used to build the query
       
   613  * @link http://us2.php.net/manual/en/function.http-build-query.php more on what
       
   614  *		http_build_query() does.
       
   615  *
       
   616  * @since 2.3.0
       
   617  *
       
   618  * @param array $data URL-encode key/value pairs.
       
   619  * @return string URL encoded string
       
   620  */
       
   621 function build_query( $data ) {
       
   622 	return _http_build_query( $data, null, '&', '', false );
       
   623 }
       
   624 
       
   625 // from php.net (modified by Mark Jaquith to behave like the native PHP5 function)
       
   626 function _http_build_query($data, $prefix=null, $sep=null, $key='', $urlencode=true) {
       
   627 	$ret = array();
       
   628 
       
   629 	foreach ( (array) $data as $k => $v ) {
       
   630 		if ( $urlencode)
       
   631 			$k = urlencode($k);
       
   632 		if ( is_int($k) && $prefix != null )
       
   633 			$k = $prefix.$k;
       
   634 		if ( !empty($key) )
       
   635 			$k = $key . '%5B' . $k . '%5D';
       
   636 		if ( $v === null )
       
   637 			continue;
       
   638 		elseif ( $v === FALSE )
       
   639 			$v = '0';
       
   640 
       
   641 		if ( is_array($v) || is_object($v) )
       
   642 			array_push($ret,_http_build_query($v, '', $sep, $k, $urlencode));
       
   643 		elseif ( $urlencode )
       
   644 			array_push($ret, $k.'='.urlencode($v));
       
   645 		else
       
   646 			array_push($ret, $k.'='.$v);
       
   647 	}
       
   648 
       
   649 	if ( null === $sep )
       
   650 		$sep = ini_get('arg_separator.output');
       
   651 
       
   652 	return implode($sep, $ret);
       
   653 }
       
   654 
       
   655 /**
       
   656  * Retrieve a modified URL query string.
       
   657  *
       
   658  * You can rebuild the URL and append a new query variable to the URL query by
       
   659  * using this function. You can also retrieve the full URL with query data.
       
   660  *
       
   661  * Adding a single key & value or an associative array. Setting a key value to
       
   662  * an empty string removes the key. Omitting oldquery_or_uri uses the $_SERVER
       
   663  * value. Additional values provided are expected to be encoded appropriately
       
   664  * with urlencode() or rawurlencode().
       
   665  *
       
   666  * @since 1.5.0
       
   667  *
       
   668  * @param mixed $param1 Either newkey or an associative_array
       
   669  * @param mixed $param2 Either newvalue or oldquery or uri
       
   670  * @param mixed $param3 Optional. Old query or uri
       
   671  * @return string New URL query string.
       
   672  */
       
   673 function add_query_arg() {
       
   674 	$ret = '';
       
   675 	$args = func_get_args();
       
   676 	if ( is_array( $args[0] ) ) {
       
   677 		if ( count( $args ) < 2 || false === $args[1] )
       
   678 			$uri = $_SERVER['REQUEST_URI'];
       
   679 		else
       
   680 			$uri = $args[1];
       
   681 	} else {
       
   682 		if ( count( $args ) < 3 || false === $args[2] )
       
   683 			$uri = $_SERVER['REQUEST_URI'];
       
   684 		else
       
   685 			$uri = $args[2];
       
   686 	}
       
   687 
       
   688 	if ( $frag = strstr( $uri, '#' ) )
       
   689 		$uri = substr( $uri, 0, -strlen( $frag ) );
       
   690 	else
       
   691 		$frag = '';
       
   692 
       
   693 	if ( 0 === stripos( $uri, 'http://' ) ) {
       
   694 		$protocol = 'http://';
       
   695 		$uri = substr( $uri, 7 );
       
   696 	} elseif ( 0 === stripos( $uri, 'https://' ) ) {
       
   697 		$protocol = 'https://';
       
   698 		$uri = substr( $uri, 8 );
       
   699 	} else {
       
   700 		$protocol = '';
       
   701 	}
       
   702 
       
   703 	if ( strpos( $uri, '?' ) !== false ) {
       
   704 		list( $base, $query ) = explode( '?', $uri, 2 );
       
   705 		$base .= '?';
       
   706 	} elseif ( $protocol || strpos( $uri, '=' ) === false ) {
       
   707 		$base = $uri . '?';
       
   708 		$query = '';
       
   709 	} else {
       
   710 		$base = '';
       
   711 		$query = $uri;
       
   712 	}
       
   713 
       
   714 	wp_parse_str( $query, $qs );
       
   715 	$qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
       
   716 	if ( is_array( $args[0] ) ) {
       
   717 		$kayvees = $args[0];
       
   718 		$qs = array_merge( $qs, $kayvees );
       
   719 	} else {
       
   720 		$qs[ $args[0] ] = $args[1];
       
   721 	}
       
   722 
       
   723 	foreach ( $qs as $k => $v ) {
       
   724 		if ( $v === false )
       
   725 			unset( $qs[$k] );
       
   726 	}
       
   727 
       
   728 	$ret = build_query( $qs );
       
   729 	$ret = trim( $ret, '?' );
       
   730 	$ret = preg_replace( '#=(&|$)#', '$1', $ret );
       
   731 	$ret = $protocol . $base . $ret . $frag;
       
   732 	$ret = rtrim( $ret, '?' );
       
   733 	return $ret;
       
   734 }
       
   735 
       
   736 /**
       
   737  * Removes an item or list from the query string.
       
   738  *
       
   739  * @since 1.5.0
       
   740  *
       
   741  * @param string|array $key Query key or keys to remove.
       
   742  * @param bool $query When false uses the $_SERVER value.
       
   743  * @return string New URL query string.
       
   744  */
       
   745 function remove_query_arg( $key, $query=false ) {
       
   746 	if ( is_array( $key ) ) { // removing multiple keys
       
   747 		foreach ( $key as $k )
       
   748 			$query = add_query_arg( $k, false, $query );
       
   749 		return $query;
       
   750 	}
       
   751 	return add_query_arg( $key, false, $query );
       
   752 }
       
   753 
       
   754 /**
       
   755  * Walks the array while sanitizing the contents.
       
   756  *
       
   757  * @since 0.71
       
   758  *
       
   759  * @param array $array Array to walk while sanitizing contents.
       
   760  * @return array Sanitized $array.
       
   761  */
       
   762 function add_magic_quotes( $array ) {
       
   763 	foreach ( (array) $array as $k => $v ) {
       
   764 		if ( is_array( $v ) ) {
       
   765 			$array[$k] = add_magic_quotes( $v );
       
   766 		} else {
       
   767 			$array[$k] = addslashes( $v );
       
   768 		}
       
   769 	}
       
   770 	return $array;
       
   771 }
       
   772 
       
   773 /**
       
   774  * HTTP request for URI to retrieve content.
       
   775  *
       
   776  * @since 1.5.1
       
   777  * @uses wp_remote_get()
       
   778  *
       
   779  * @param string $uri URI/URL of web page to retrieve.
       
   780  * @return bool|string HTTP content. False on failure.
       
   781  */
       
   782 function wp_remote_fopen( $uri ) {
       
   783 	$parsed_url = @parse_url( $uri );
       
   784 
       
   785 	if ( !$parsed_url || !is_array( $parsed_url ) )
       
   786 		return false;
       
   787 
       
   788 	$options = array();
       
   789 	$options['timeout'] = 10;
       
   790 
       
   791 	$response = wp_safe_remote_get( $uri, $options );
       
   792 
       
   793 	if ( is_wp_error( $response ) )
       
   794 		return false;
       
   795 
       
   796 	return wp_remote_retrieve_body( $response );
       
   797 }
       
   798 
       
   799 /**
       
   800  * Set up the WordPress query.
       
   801  *
       
   802  * @since 2.0.0
       
   803  *
       
   804  * @param string $query_vars Default WP_Query arguments.
       
   805  */
       
   806 function wp( $query_vars = '' ) {
       
   807 	global $wp, $wp_query, $wp_the_query;
       
   808 	$wp->main( $query_vars );
       
   809 
       
   810 	if ( !isset($wp_the_query) )
       
   811 		$wp_the_query = $wp_query;
       
   812 }
       
   813 
       
   814 /**
       
   815  * Retrieve the description for the HTTP status.
       
   816  *
       
   817  * @since 2.3.0
       
   818  *
       
   819  * @param int $code HTTP status code.
       
   820  * @return string Empty string if not found, or description if found.
       
   821  */
       
   822 function get_status_header_desc( $code ) {
       
   823 	global $wp_header_to_desc;
       
   824 
       
   825 	$code = absint( $code );
       
   826 
       
   827 	if ( !isset( $wp_header_to_desc ) ) {
       
   828 		$wp_header_to_desc = array(
       
   829 			100 => 'Continue',
       
   830 			101 => 'Switching Protocols',
       
   831 			102 => 'Processing',
       
   832 
       
   833 			200 => 'OK',
       
   834 			201 => 'Created',
       
   835 			202 => 'Accepted',
       
   836 			203 => 'Non-Authoritative Information',
       
   837 			204 => 'No Content',
       
   838 			205 => 'Reset Content',
       
   839 			206 => 'Partial Content',
       
   840 			207 => 'Multi-Status',
       
   841 			226 => 'IM Used',
       
   842 
       
   843 			300 => 'Multiple Choices',
       
   844 			301 => 'Moved Permanently',
       
   845 			302 => 'Found',
       
   846 			303 => 'See Other',
       
   847 			304 => 'Not Modified',
       
   848 			305 => 'Use Proxy',
       
   849 			306 => 'Reserved',
       
   850 			307 => 'Temporary Redirect',
       
   851 
       
   852 			400 => 'Bad Request',
       
   853 			401 => 'Unauthorized',
       
   854 			402 => 'Payment Required',
       
   855 			403 => 'Forbidden',
       
   856 			404 => 'Not Found',
       
   857 			405 => 'Method Not Allowed',
       
   858 			406 => 'Not Acceptable',
       
   859 			407 => 'Proxy Authentication Required',
       
   860 			408 => 'Request Timeout',
       
   861 			409 => 'Conflict',
       
   862 			410 => 'Gone',
       
   863 			411 => 'Length Required',
       
   864 			412 => 'Precondition Failed',
       
   865 			413 => 'Request Entity Too Large',
       
   866 			414 => 'Request-URI Too Long',
       
   867 			415 => 'Unsupported Media Type',
       
   868 			416 => 'Requested Range Not Satisfiable',
       
   869 			417 => 'Expectation Failed',
       
   870 			422 => 'Unprocessable Entity',
       
   871 			423 => 'Locked',
       
   872 			424 => 'Failed Dependency',
       
   873 			426 => 'Upgrade Required',
       
   874 
       
   875 			500 => 'Internal Server Error',
       
   876 			501 => 'Not Implemented',
       
   877 			502 => 'Bad Gateway',
       
   878 			503 => 'Service Unavailable',
       
   879 			504 => 'Gateway Timeout',
       
   880 			505 => 'HTTP Version Not Supported',
       
   881 			506 => 'Variant Also Negotiates',
       
   882 			507 => 'Insufficient Storage',
       
   883 			510 => 'Not Extended'
       
   884 		);
       
   885 	}
       
   886 
       
   887 	if ( isset( $wp_header_to_desc[$code] ) )
       
   888 		return $wp_header_to_desc[$code];
       
   889 	else
       
   890 		return '';
       
   891 }
       
   892 
       
   893 /**
       
   894  * Set HTTP status header.
       
   895  *
       
   896  * @since 2.0.0
       
   897  * @uses apply_filters() Calls 'status_header' on status header string, HTTP
       
   898  *		HTTP code, HTTP code description, and protocol string as separate
       
   899  *		parameters.
       
   900  *
       
   901  * @param int $header HTTP status code
       
   902  * @return unknown
       
   903  */
       
   904 function status_header( $header ) {
       
   905 	$text = get_status_header_desc( $header );
       
   906 
       
   907 	if ( empty( $text ) )
       
   908 		return false;
       
   909 
       
   910 	$protocol = $_SERVER["SERVER_PROTOCOL"];
       
   911 	if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
       
   912 		$protocol = 'HTTP/1.0';
       
   913 	$status_header = "$protocol $header $text";
       
   914 	if ( function_exists( 'apply_filters' ) )
       
   915 		$status_header = apply_filters( 'status_header', $status_header, $header, $text, $protocol );
       
   916 
       
   917 	return @header( $status_header, true, $header );
       
   918 }
       
   919 
       
   920 /**
       
   921  * Gets the header information to prevent caching.
       
   922  *
       
   923  * The several different headers cover the different ways cache prevention is handled
       
   924  * by different browsers
       
   925  *
       
   926  * @since 2.8.0
       
   927  *
       
   928  * @uses apply_filters()
       
   929  * @return array The associative array of header names and field values.
       
   930  */
       
   931 function wp_get_nocache_headers() {
       
   932 	$headers = array(
       
   933 		'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
       
   934 		'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
       
   935 		'Pragma' => 'no-cache',
       
   936 	);
       
   937 
       
   938 	if ( function_exists('apply_filters') ) {
       
   939 		$headers = (array) apply_filters('nocache_headers', $headers);
       
   940 	}
       
   941 	$headers['Last-Modified'] = false;
       
   942 	return $headers;
       
   943 }
       
   944 
       
   945 /**
       
   946  * Sets the headers to prevent caching for the different browsers.
       
   947  *
       
   948  * Different browsers support different nocache headers, so several headers must
       
   949  * be sent so that all of them get the point that no caching should occur.
       
   950  *
       
   951  * @since 2.0.0
       
   952  * @uses wp_get_nocache_headers()
       
   953  */
       
   954 function nocache_headers() {
       
   955 	$headers = wp_get_nocache_headers();
       
   956 
       
   957 	unset( $headers['Last-Modified'] );
       
   958 
       
   959 	// In PHP 5.3+, make sure we are not sending a Last-Modified header.
       
   960 	if ( function_exists( 'header_remove' ) ) {
       
   961 		@header_remove( 'Last-Modified' );
       
   962 	} else {
       
   963 		// In PHP 5.2, send an empty Last-Modified header, but only as a
       
   964 		// last resort to override a header already sent. #WP23021
       
   965 		foreach ( headers_list() as $header ) {
       
   966 			if ( 0 === stripos( $header, 'Last-Modified' ) ) {
       
   967 				$headers['Last-Modified'] = '';
       
   968 				break;
       
   969 			}
       
   970 		}
       
   971 	}
       
   972 
       
   973 	foreach( $headers as $name => $field_value )
       
   974 		@header("{$name}: {$field_value}");
       
   975 }
       
   976 
       
   977 /**
       
   978  * Set the headers for caching for 10 days with JavaScript content type.
       
   979  *
       
   980  * @since 2.1.0
       
   981  */
       
   982 function cache_javascript_headers() {
       
   983 	$expiresOffset = 10 * DAY_IN_SECONDS;
       
   984 	header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) );
       
   985 	header( "Vary: Accept-Encoding" ); // Handle proxies
       
   986 	header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $expiresOffset ) . " GMT" );
       
   987 }
       
   988 
       
   989 /**
       
   990  * Retrieve the number of database queries during the WordPress execution.
       
   991  *
       
   992  * @since 2.0.0
       
   993  *
       
   994  * @return int Number of database queries
       
   995  */
       
   996 function get_num_queries() {
       
   997 	global $wpdb;
       
   998 	return $wpdb->num_queries;
       
   999 }
       
  1000 
       
  1001 /**
       
  1002  * Whether input is yes or no. Must be 'y' to be true.
       
  1003  *
       
  1004  * @since 1.0.0
       
  1005  *
       
  1006  * @param string $yn Character string containing either 'y' or 'n'
       
  1007  * @return bool True if yes, false on anything else
       
  1008  */
       
  1009 function bool_from_yn( $yn ) {
       
  1010 	return ( strtolower( $yn ) == 'y' );
       
  1011 }
       
  1012 
       
  1013 /**
       
  1014  * Loads the feed template from the use of an action hook.
       
  1015  *
       
  1016  * If the feed action does not have a hook, then the function will die with a
       
  1017  * message telling the visitor that the feed is not valid.
       
  1018  *
       
  1019  * It is better to only have one hook for each feed.
       
  1020  *
       
  1021  * @since 2.1.0
       
  1022  * @uses $wp_query Used to tell if the use a comment feed.
       
  1023  * @uses do_action() Calls 'do_feed_$feed' hook, if a hook exists for the feed.
       
  1024  */
       
  1025 function do_feed() {
       
  1026 	global $wp_query;
       
  1027 
       
  1028 	$feed = get_query_var( 'feed' );
       
  1029 
       
  1030 	// Remove the pad, if present.
       
  1031 	$feed = preg_replace( '/^_+/', '', $feed );
       
  1032 
       
  1033 	if ( $feed == '' || $feed == 'feed' )
       
  1034 		$feed = get_default_feed();
       
  1035 
       
  1036 	$hook = 'do_feed_' . $feed;
       
  1037 	if ( ! has_action( $hook ) )
       
  1038 		wp_die( __( 'ERROR: This is not a valid feed template.' ), '', array( 'response' => 404 ) );
       
  1039 
       
  1040 	do_action( $hook, $wp_query->is_comment_feed );
       
  1041 }
       
  1042 
       
  1043 /**
       
  1044  * Load the RDF RSS 0.91 Feed template.
       
  1045  *
       
  1046  * @since 2.1.0
       
  1047  */
       
  1048 function do_feed_rdf() {
       
  1049 	load_template( ABSPATH . WPINC . '/feed-rdf.php' );
       
  1050 }
       
  1051 
       
  1052 /**
       
  1053  * Load the RSS 1.0 Feed Template.
       
  1054  *
       
  1055  * @since 2.1.0
       
  1056  */
       
  1057 function do_feed_rss() {
       
  1058 	load_template( ABSPATH . WPINC . '/feed-rss.php' );
       
  1059 }
       
  1060 
       
  1061 /**
       
  1062  * Load either the RSS2 comment feed or the RSS2 posts feed.
       
  1063  *
       
  1064  * @since 2.1.0
       
  1065  *
       
  1066  * @param bool $for_comments True for the comment feed, false for normal feed.
       
  1067  */
       
  1068 function do_feed_rss2( $for_comments ) {
       
  1069 	if ( $for_comments )
       
  1070 		load_template( ABSPATH . WPINC . '/feed-rss2-comments.php' );
       
  1071 	else
       
  1072 		load_template( ABSPATH . WPINC . '/feed-rss2.php' );
       
  1073 }
       
  1074 
       
  1075 /**
       
  1076  * Load either Atom comment feed or Atom posts feed.
       
  1077  *
       
  1078  * @since 2.1.0
       
  1079  *
       
  1080  * @param bool $for_comments True for the comment feed, false for normal feed.
       
  1081  */
       
  1082 function do_feed_atom( $for_comments ) {
       
  1083 	if ($for_comments)
       
  1084 		load_template( ABSPATH . WPINC . '/feed-atom-comments.php');
       
  1085 	else
       
  1086 		load_template( ABSPATH . WPINC . '/feed-atom.php' );
       
  1087 }
       
  1088 
       
  1089 /**
       
  1090  * Display the robots.txt file content.
       
  1091  *
       
  1092  * The echo content should be with usage of the permalinks or for creating the
       
  1093  * robots.txt file.
       
  1094  *
       
  1095  * @since 2.1.0
       
  1096  * @uses do_action() Calls 'do_robotstxt' hook for displaying robots.txt rules.
       
  1097  */
       
  1098 function do_robots() {
       
  1099 	header( 'Content-Type: text/plain; charset=utf-8' );
       
  1100 
       
  1101 	do_action( 'do_robotstxt' );
       
  1102 
       
  1103 	$output = "User-agent: *\n";
       
  1104 	$public = get_option( 'blog_public' );
       
  1105 	if ( '0' == $public ) {
       
  1106 		$output .= "Disallow: /\n";
       
  1107 	} else {
       
  1108 		$site_url = parse_url( site_url() );
       
  1109 		$path = ( !empty( $site_url['path'] ) ) ? $site_url['path'] : '';
       
  1110 		$output .= "Disallow: $path/wp-admin/\n";
       
  1111 		$output .= "Disallow: $path/wp-includes/\n";
       
  1112 	}
       
  1113 
       
  1114 	echo apply_filters('robots_txt', $output, $public);
       
  1115 }
       
  1116 
       
  1117 /**
       
  1118  * Test whether blog is already installed.
       
  1119  *
       
  1120  * The cache will be checked first. If you have a cache plugin, which saves the
       
  1121  * cache values, then this will work. If you use the default WordPress cache,
       
  1122  * and the database goes away, then you might have problems.
       
  1123  *
       
  1124  * Checks for the option siteurl for whether WordPress is installed.
       
  1125  *
       
  1126  * @since 2.1.0
       
  1127  * @uses $wpdb
       
  1128  *
       
  1129  * @return bool Whether blog is already installed.
       
  1130  */
       
  1131 function is_blog_installed() {
       
  1132 	global $wpdb;
       
  1133 
       
  1134 	// Check cache first. If options table goes away and we have true cached, oh well.
       
  1135 	if ( wp_cache_get( 'is_blog_installed' ) )
       
  1136 		return true;
       
  1137 
       
  1138 	$suppress = $wpdb->suppress_errors();
       
  1139 	if ( ! defined( 'WP_INSTALLING' ) ) {
       
  1140 		$alloptions = wp_load_alloptions();
       
  1141 	}
       
  1142 	// If siteurl is not set to autoload, check it specifically
       
  1143 	if ( !isset( $alloptions['siteurl'] ) )
       
  1144 		$installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
       
  1145 	else
       
  1146 		$installed = $alloptions['siteurl'];
       
  1147 	$wpdb->suppress_errors( $suppress );
       
  1148 
       
  1149 	$installed = !empty( $installed );
       
  1150 	wp_cache_set( 'is_blog_installed', $installed );
       
  1151 
       
  1152 	if ( $installed )
       
  1153 		return true;
       
  1154 
       
  1155 	// If visiting repair.php, return true and let it take over.
       
  1156 	if ( defined( 'WP_REPAIRING' ) )
       
  1157 		return true;
       
  1158 
       
  1159 	$suppress = $wpdb->suppress_errors();
       
  1160 
       
  1161 	// Loop over the WP tables. If none exist, then scratch install is allowed.
       
  1162 	// If one or more exist, suggest table repair since we got here because the options
       
  1163 	// table could not be accessed.
       
  1164 	$wp_tables = $wpdb->tables();
       
  1165 	foreach ( $wp_tables as $table ) {
       
  1166 		// The existence of custom user tables shouldn't suggest an insane state or prevent a clean install.
       
  1167 		if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table )
       
  1168 			continue;
       
  1169 		if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table )
       
  1170 			continue;
       
  1171 
       
  1172 		if ( ! $wpdb->get_results( "DESCRIBE $table;" ) )
       
  1173 			continue;
       
  1174 
       
  1175 		// One or more tables exist. We are insane.
       
  1176 
       
  1177 		wp_load_translations_early();
       
  1178 
       
  1179 		// Die with a DB error.
       
  1180 		$wpdb->error = sprintf( __( 'One or more database tables are unavailable. The database may need to be <a href="%s">repaired</a>.' ), 'maint/repair.php?referrer=is_blog_installed' );
       
  1181 		dead_db();
       
  1182 	}
       
  1183 
       
  1184 	$wpdb->suppress_errors( $suppress );
       
  1185 
       
  1186 	wp_cache_set( 'is_blog_installed', false );
       
  1187 
       
  1188 	return false;
       
  1189 }
       
  1190 
       
  1191 /**
       
  1192  * Retrieve URL with nonce added to URL query.
       
  1193  *
       
  1194  * @package WordPress
       
  1195  * @subpackage Security
       
  1196  * @since 2.0.4
       
  1197  *
       
  1198  * @param string $actionurl URL to add nonce action.
       
  1199  * @param string $action Optional. Nonce action name.
       
  1200  * @param string $name Optional. Nonce name.
       
  1201  * @return string URL with nonce action added.
       
  1202  */
       
  1203 function wp_nonce_url( $actionurl, $action = -1, $name = '_wpnonce' ) {
       
  1204 	$actionurl = str_replace( '&amp;', '&', $actionurl );
       
  1205 	return esc_html( add_query_arg( $name, wp_create_nonce( $action ), $actionurl ) );
       
  1206 }
       
  1207 
       
  1208 /**
       
  1209  * Retrieve or display nonce hidden field for forms.
       
  1210  *
       
  1211  * The nonce field is used to validate that the contents of the form came from
       
  1212  * the location on the current site and not somewhere else. The nonce does not
       
  1213  * offer absolute protection, but should protect against most cases. It is very
       
  1214  * important to use nonce field in forms.
       
  1215  *
       
  1216  * The $action and $name are optional, but if you want to have better security,
       
  1217  * it is strongly suggested to set those two parameters. It is easier to just
       
  1218  * call the function without any parameters, because validation of the nonce
       
  1219  * doesn't require any parameters, but since crackers know what the default is
       
  1220  * it won't be difficult for them to find a way around your nonce and cause
       
  1221  * damage.
       
  1222  *
       
  1223  * The input name will be whatever $name value you gave. The input value will be
       
  1224  * the nonce creation value.
       
  1225  *
       
  1226  * @package WordPress
       
  1227  * @subpackage Security
       
  1228  * @since 2.0.4
       
  1229  *
       
  1230  * @param string $action Optional. Action name.
       
  1231  * @param string $name Optional. Nonce name.
       
  1232  * @param bool $referer Optional, default true. Whether to set the referer field for validation.
       
  1233  * @param bool $echo Optional, default true. Whether to display or return hidden form field.
       
  1234  * @return string Nonce field.
       
  1235  */
       
  1236 function wp_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) {
       
  1237 	$name = esc_attr( $name );
       
  1238 	$nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />';
       
  1239 
       
  1240 	if ( $referer )
       
  1241 		$nonce_field .= wp_referer_field( false );
       
  1242 
       
  1243 	if ( $echo )
       
  1244 		echo $nonce_field;
       
  1245 
       
  1246 	return $nonce_field;
       
  1247 }
       
  1248 
       
  1249 /**
       
  1250  * Retrieve or display referer hidden field for forms.
       
  1251  *
       
  1252  * The referer link is the current Request URI from the server super global. The
       
  1253  * input name is '_wp_http_referer', in case you wanted to check manually.
       
  1254  *
       
  1255  * @package WordPress
       
  1256  * @subpackage Security
       
  1257  * @since 2.0.4
       
  1258  *
       
  1259  * @param bool $echo Whether to echo or return the referer field.
       
  1260  * @return string Referer field.
       
  1261  */
       
  1262 function wp_referer_field( $echo = true ) {
       
  1263 	$referer_field = '<input type="hidden" name="_wp_http_referer" value="'. esc_attr( wp_unslash( $_SERVER['REQUEST_URI'] ) ) . '" />';
       
  1264 
       
  1265 	if ( $echo )
       
  1266 		echo $referer_field;
       
  1267 	return $referer_field;
       
  1268 }
       
  1269 
       
  1270 /**
       
  1271  * Retrieve or display original referer hidden field for forms.
       
  1272  *
       
  1273  * The input name is '_wp_original_http_referer' and will be either the same
       
  1274  * value of {@link wp_referer_field()}, if that was posted already or it will
       
  1275  * be the current page, if it doesn't exist.
       
  1276  *
       
  1277  * @package WordPress
       
  1278  * @subpackage Security
       
  1279  * @since 2.0.4
       
  1280  *
       
  1281  * @param bool $echo Whether to echo the original http referer
       
  1282  * @param string $jump_back_to Optional, default is 'current'. Can be 'previous' or page you want to jump back to.
       
  1283  * @return string Original referer field.
       
  1284  */
       
  1285 function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) {
       
  1286 	if ( ! $ref = wp_get_original_referer() ) {
       
  1287 		$ref = 'previous' == $jump_back_to ? wp_get_referer() : wp_unslash( $_SERVER['REQUEST_URI'] );
       
  1288 	}
       
  1289 	$orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . esc_attr( $ref ) . '" />';
       
  1290 	if ( $echo )
       
  1291 		echo $orig_referer_field;
       
  1292 	return $orig_referer_field;
       
  1293 }
       
  1294 
       
  1295 /**
       
  1296  * Retrieve referer from '_wp_http_referer' or HTTP referer. If it's the same
       
  1297  * as the current request URL, will return false.
       
  1298  *
       
  1299  * @package WordPress
       
  1300  * @subpackage Security
       
  1301  * @since 2.0.4
       
  1302  *
       
  1303  * @return string|bool False on failure. Referer URL on success.
       
  1304  */
       
  1305 function wp_get_referer() {
       
  1306 	if ( ! function_exists( 'wp_validate_redirect' ) )
       
  1307 		return false;
       
  1308 	$ref = false;
       
  1309 	if ( ! empty( $_REQUEST['_wp_http_referer'] ) )
       
  1310 		$ref = wp_unslash( $_REQUEST['_wp_http_referer'] );
       
  1311 	else if ( ! empty( $_SERVER['HTTP_REFERER'] ) )
       
  1312 		$ref = wp_unslash( $_SERVER['HTTP_REFERER'] );
       
  1313 
       
  1314 	if ( $ref && $ref !== wp_unslash( $_SERVER['REQUEST_URI'] ) )
       
  1315 		return wp_validate_redirect( $ref, false );
       
  1316 	return false;
       
  1317 }
       
  1318 
       
  1319 /**
       
  1320  * Retrieve original referer that was posted, if it exists.
       
  1321  *
       
  1322  * @package WordPress
       
  1323  * @subpackage Security
       
  1324  * @since 2.0.4
       
  1325  *
       
  1326  * @return string|bool False if no original referer or original referer if set.
       
  1327  */
       
  1328 function wp_get_original_referer() {
       
  1329 	if ( ! empty( $_REQUEST['_wp_original_http_referer'] ) && function_exists( 'wp_validate_redirect' ) )
       
  1330 		return wp_validate_redirect( wp_unslash( $_REQUEST['_wp_original_http_referer'] ), false );
       
  1331 	return false;
       
  1332 }
       
  1333 
       
  1334 /**
       
  1335  * Recursive directory creation based on full path.
       
  1336  *
       
  1337  * Will attempt to set permissions on folders.
       
  1338  *
       
  1339  * @since 2.0.1
       
  1340  *
       
  1341  * @param string $target Full path to attempt to create.
       
  1342  * @return bool Whether the path was created. True if path already exists.
       
  1343  */
       
  1344 function wp_mkdir_p( $target ) {
       
  1345 	$wrapper = null;
       
  1346 
       
  1347 	// strip the protocol
       
  1348 	if( wp_is_stream( $target ) ) {
       
  1349 		list( $wrapper, $target ) = explode( '://', $target, 2 );
       
  1350 	}
       
  1351 
       
  1352 	// from php.net/mkdir user contributed notes
       
  1353 	$target = str_replace( '//', '/', $target );
       
  1354 
       
  1355 	// put the wrapper back on the target
       
  1356 	if( $wrapper !== null ) {
       
  1357 		$target = $wrapper . '://' . $target;
       
  1358 	}
       
  1359 
       
  1360 	// safe mode fails with a trailing slash under certain PHP versions.
       
  1361 	$target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
       
  1362 	if ( empty($target) )
       
  1363 		$target = '/';
       
  1364 
       
  1365 	if ( file_exists( $target ) )
       
  1366 		return @is_dir( $target );
       
  1367 
       
  1368 	// We need to find the permissions of the parent folder that exists and inherit that.
       
  1369 	$target_parent = dirname( $target );
       
  1370 	while ( '.' != $target_parent && ! is_dir( $target_parent ) ) {
       
  1371 		$target_parent = dirname( $target_parent );
       
  1372 	}
       
  1373 
       
  1374 	// Get the permission bits.
       
  1375 	if ( $target_parent && '.' != $target_parent ) {
       
  1376 		$stat = @stat( $target_parent );
       
  1377 		$dir_perms = $stat['mode'] & 0007777;
       
  1378 	} else {
       
  1379 		$dir_perms = 0777;
       
  1380 	}
       
  1381 
       
  1382 	if ( @mkdir( $target, $dir_perms, true ) ) {
       
  1383 		return true;
       
  1384 	}
       
  1385 
       
  1386 	return false;
       
  1387 }
       
  1388 
       
  1389 /**
       
  1390  * Test if a give filesystem path is absolute ('/foo/bar', 'c:\windows').
       
  1391  *
       
  1392  * @since 2.5.0
       
  1393  *
       
  1394  * @param string $path File path
       
  1395  * @return bool True if path is absolute, false is not absolute.
       
  1396  */
       
  1397 function path_is_absolute( $path ) {
       
  1398 	// this is definitive if true but fails if $path does not exist or contains a symbolic link
       
  1399 	if ( realpath($path) == $path )
       
  1400 		return true;
       
  1401 
       
  1402 	if ( strlen($path) == 0 || $path[0] == '.' )
       
  1403 		return false;
       
  1404 
       
  1405 	// windows allows absolute paths like this
       
  1406 	if ( preg_match('#^[a-zA-Z]:\\\\#', $path) )
       
  1407 		return true;
       
  1408 
       
  1409 	// a path starting with / or \ is absolute; anything else is relative
       
  1410 	return ( $path[0] == '/' || $path[0] == '\\' );
       
  1411 }
       
  1412 
       
  1413 /**
       
  1414  * Join two filesystem paths together (e.g. 'give me $path relative to $base').
       
  1415  *
       
  1416  * If the $path is absolute, then it the full path is returned.
       
  1417  *
       
  1418  * @since 2.5.0
       
  1419  *
       
  1420  * @param string $base
       
  1421  * @param string $path
       
  1422  * @return string The path with the base or absolute path.
       
  1423  */
       
  1424 function path_join( $base, $path ) {
       
  1425 	if ( path_is_absolute($path) )
       
  1426 		return $path;
       
  1427 
       
  1428 	return rtrim($base, '/') . '/' . ltrim($path, '/');
       
  1429 }
       
  1430 
       
  1431 /**
       
  1432  * Determines a writable directory for temporary files.
       
  1433  * Function's preference is the return value of <code>sys_get_temp_dir()</code>,
       
  1434  * followed by your PHP temporary upload directory, followed by WP_CONTENT_DIR,
       
  1435  * before finally defaulting to /tmp/
       
  1436  *
       
  1437  * In the event that this function does not find a writable location,
       
  1438  * It may be overridden by the <code>WP_TEMP_DIR</code> constant in
       
  1439  * your <code>wp-config.php</code> file.
       
  1440  *
       
  1441  * @since 2.5.0
       
  1442  *
       
  1443  * @return string Writable temporary directory
       
  1444  */
       
  1445 function get_temp_dir() {
       
  1446 	static $temp;
       
  1447 	if ( defined('WP_TEMP_DIR') )
       
  1448 		return trailingslashit(WP_TEMP_DIR);
       
  1449 
       
  1450 	if ( $temp )
       
  1451 		return trailingslashit( rtrim( $temp, '\\' ) );
       
  1452 
       
  1453 	if ( function_exists('sys_get_temp_dir') ) {
       
  1454 		$temp = sys_get_temp_dir();
       
  1455 		if ( @is_dir( $temp ) && wp_is_writable( $temp ) )
       
  1456 			return trailingslashit( rtrim( $temp, '\\' ) );
       
  1457 	}
       
  1458 
       
  1459 	$temp = ini_get('upload_tmp_dir');
       
  1460 	if ( @is_dir( $temp ) && wp_is_writable( $temp ) )
       
  1461 		return trailingslashit( rtrim( $temp, '\\' ) );
       
  1462 
       
  1463 	$temp = WP_CONTENT_DIR . '/';
       
  1464 	if ( is_dir( $temp ) && wp_is_writable( $temp ) )
       
  1465 		return $temp;
       
  1466 
       
  1467 	$temp = '/tmp/';
       
  1468 	return $temp;
       
  1469 }
       
  1470 
       
  1471 /**
       
  1472  * Determine if a directory is writable.
       
  1473  *
       
  1474  * This function is used to work around certain ACL issues
       
  1475  * in PHP primarily affecting Windows Servers.
       
  1476  *
       
  1477  * @see win_is_writable()
       
  1478  *
       
  1479  * @since 3.6.0
       
  1480  *
       
  1481  * @param string $path
       
  1482  * @return bool
       
  1483  */
       
  1484 function wp_is_writable( $path ) {
       
  1485 	if ( 'WIN' === strtoupper( substr( PHP_OS, 0, 3 ) ) )
       
  1486 		return win_is_writable( $path );
       
  1487 	else
       
  1488 		return @is_writable( $path );
       
  1489 }
       
  1490 
       
  1491 /**
       
  1492  * Workaround for Windows bug in is_writable() function
       
  1493  *
       
  1494  * PHP has issues with Windows ACL's for determine if a
       
  1495  * directory is writable or not, this works around them by
       
  1496  * checking the ability to open files rather than relying
       
  1497  * upon PHP to interprate the OS ACL.
       
  1498  *
       
  1499  * @link http://bugs.php.net/bug.php?id=27609
       
  1500  * @link http://bugs.php.net/bug.php?id=30931
       
  1501  *
       
  1502  * @since 2.8.0
       
  1503  *
       
  1504  * @param string $path
       
  1505  * @return bool
       
  1506  */
       
  1507 function win_is_writable( $path ) {
       
  1508 
       
  1509 	if ( $path[strlen( $path ) - 1] == '/' ) // if it looks like a directory, check a random file within the directory
       
  1510 		return win_is_writable( $path . uniqid( mt_rand() ) . '.tmp');
       
  1511 	else if ( is_dir( $path ) ) // If it's a directory (and not a file) check a random file within the directory
       
  1512 		return win_is_writable( $path . '/' . uniqid( mt_rand() ) . '.tmp' );
       
  1513 
       
  1514 	// check tmp file for read/write capabilities
       
  1515 	$should_delete_tmp_file = !file_exists( $path );
       
  1516 	$f = @fopen( $path, 'a' );
       
  1517 	if ( $f === false )
       
  1518 		return false;
       
  1519 	fclose( $f );
       
  1520 	if ( $should_delete_tmp_file )
       
  1521 		unlink( $path );
       
  1522 	return true;
       
  1523 }
       
  1524 
       
  1525 /**
       
  1526  * Get an array containing the current upload directory's path and url.
       
  1527  *
       
  1528  * Checks the 'upload_path' option, which should be from the web root folder,
       
  1529  * and if it isn't empty it will be used. If it is empty, then the path will be
       
  1530  * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
       
  1531  * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path.
       
  1532  *
       
  1533  * The upload URL path is set either by the 'upload_url_path' option or by using
       
  1534  * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path.
       
  1535  *
       
  1536  * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in
       
  1537  * the administration settings panel), then the time will be used. The format
       
  1538  * will be year first and then month.
       
  1539  *
       
  1540  * If the path couldn't be created, then an error will be returned with the key
       
  1541  * 'error' containing the error message. The error suggests that the parent
       
  1542  * directory is not writable by the server.
       
  1543  *
       
  1544  * On success, the returned array will have many indices:
       
  1545  * 'path' - base directory and sub directory or full path to upload directory.
       
  1546  * 'url' - base url and sub directory or absolute URL to upload directory.
       
  1547  * 'subdir' - sub directory if uploads use year/month folders option is on.
       
  1548  * 'basedir' - path without subdir.
       
  1549  * 'baseurl' - URL path without subdir.
       
  1550  * 'error' - set to false.
       
  1551  *
       
  1552  * @since 2.0.0
       
  1553  * @uses apply_filters() Calls 'upload_dir' on returned array.
       
  1554  *
       
  1555  * @param string $time Optional. Time formatted in 'yyyy/mm'.
       
  1556  * @return array See above for description.
       
  1557  */
       
  1558 function wp_upload_dir( $time = null ) {
       
  1559 	$siteurl = get_option( 'siteurl' );
       
  1560 	$upload_path = trim( get_option( 'upload_path' ) );
       
  1561 
       
  1562 	if ( empty( $upload_path ) || 'wp-content/uploads' == $upload_path ) {
       
  1563 		$dir = WP_CONTENT_DIR . '/uploads';
       
  1564 	} elseif ( 0 !== strpos( $upload_path, ABSPATH ) ) {
       
  1565 		// $dir is absolute, $upload_path is (maybe) relative to ABSPATH
       
  1566 		$dir = path_join( ABSPATH, $upload_path );
       
  1567 	} else {
       
  1568 		$dir = $upload_path;
       
  1569 	}
       
  1570 
       
  1571 	if ( !$url = get_option( 'upload_url_path' ) ) {
       
  1572 		if ( empty($upload_path) || ( 'wp-content/uploads' == $upload_path ) || ( $upload_path == $dir ) )
       
  1573 			$url = WP_CONTENT_URL . '/uploads';
       
  1574 		else
       
  1575 			$url = trailingslashit( $siteurl ) . $upload_path;
       
  1576 	}
       
  1577 
       
  1578 	// Obey the value of UPLOADS. This happens as long as ms-files rewriting is disabled.
       
  1579 	// We also sometimes obey UPLOADS when rewriting is enabled -- see the next block.
       
  1580 	if ( defined( 'UPLOADS' ) && ! ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) ) {
       
  1581 		$dir = ABSPATH . UPLOADS;
       
  1582 		$url = trailingslashit( $siteurl ) . UPLOADS;
       
  1583 	}
       
  1584 
       
  1585 	// If multisite (and if not the main site in a post-MU network)
       
  1586 	if ( is_multisite() && ! ( is_main_network() && is_main_site() && defined( 'MULTISITE' ) ) ) {
       
  1587 
       
  1588 		if ( ! get_site_option( 'ms_files_rewriting' ) ) {
       
  1589 			// If ms-files rewriting is disabled (networks created post-3.5), it is fairly straightforward:
       
  1590 			// Append sites/%d if we're not on the main site (for post-MU networks). (The extra directory
       
  1591 			// prevents a four-digit ID from conflicting with a year-based directory for the main site.
       
  1592 			// But if a MU-era network has disabled ms-files rewriting manually, they don't need the extra
       
  1593 			// directory, as they never had wp-content/uploads for the main site.)
       
  1594 
       
  1595 			if ( defined( 'MULTISITE' ) )
       
  1596 				$ms_dir = '/sites/' . get_current_blog_id();
       
  1597 			else
       
  1598 				$ms_dir = '/' . get_current_blog_id();
       
  1599 
       
  1600 			$dir .= $ms_dir;
       
  1601 			$url .= $ms_dir;
       
  1602 
       
  1603 		} elseif ( defined( 'UPLOADS' ) && ! ms_is_switched() ) {
       
  1604 			// Handle the old-form ms-files.php rewriting if the network still has that enabled.
       
  1605 			// When ms-files rewriting is enabled, then we only listen to UPLOADS when:
       
  1606 			//   1) we are not on the main site in a post-MU network,
       
  1607 			//      as wp-content/uploads is used there, and
       
  1608 			//   2) we are not switched, as ms_upload_constants() hardcodes
       
  1609 			//      these constants to reflect the original blog ID.
       
  1610 			//
       
  1611 			// Rather than UPLOADS, we actually use BLOGUPLOADDIR if it is set, as it is absolute.
       
  1612 			// (And it will be set, see ms_upload_constants().) Otherwise, UPLOADS can be used, as
       
  1613 			// as it is relative to ABSPATH. For the final piece: when UPLOADS is used with ms-files
       
  1614 			// rewriting in multisite, the resulting URL is /files. (#WP22702 for background.)
       
  1615 
       
  1616 			if ( defined( 'BLOGUPLOADDIR' ) )
       
  1617 				$dir = untrailingslashit( BLOGUPLOADDIR );
       
  1618 			else
       
  1619 				$dir = ABSPATH . UPLOADS;
       
  1620 			$url = trailingslashit( $siteurl ) . 'files';
       
  1621 		}
       
  1622 	}
       
  1623 
       
  1624 	$basedir = $dir;
       
  1625 	$baseurl = $url;
       
  1626 
       
  1627 	$subdir = '';
       
  1628 	if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
       
  1629 		// Generate the yearly and monthly dirs
       
  1630 		if ( !$time )
       
  1631 			$time = current_time( 'mysql' );
       
  1632 		$y = substr( $time, 0, 4 );
       
  1633 		$m = substr( $time, 5, 2 );
       
  1634 		$subdir = "/$y/$m";
       
  1635 	}
       
  1636 
       
  1637 	$dir .= $subdir;
       
  1638 	$url .= $subdir;
       
  1639 
       
  1640 	$uploads = apply_filters( 'upload_dir',
       
  1641 		array(
       
  1642 			'path'    => $dir,
       
  1643 			'url'     => $url,
       
  1644 			'subdir'  => $subdir,
       
  1645 			'basedir' => $basedir,
       
  1646 			'baseurl' => $baseurl,
       
  1647 			'error'   => false,
       
  1648 		) );
       
  1649 
       
  1650 	// Make sure we have an uploads dir
       
  1651 	if ( ! wp_mkdir_p( $uploads['path'] ) ) {
       
  1652 		if ( 0 === strpos( $uploads['basedir'], ABSPATH ) )
       
  1653 			$error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir'];
       
  1654 		else
       
  1655 			$error_path = basename( $uploads['basedir'] ) . $uploads['subdir'];
       
  1656 
       
  1657 		$message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path );
       
  1658 		$uploads['error'] = $message;
       
  1659 	}
       
  1660 
       
  1661 	return $uploads;
       
  1662 }
       
  1663 
       
  1664 /**
       
  1665  * Get a filename that is sanitized and unique for the given directory.
       
  1666  *
       
  1667  * If the filename is not unique, then a number will be added to the filename
       
  1668  * before the extension, and will continue adding numbers until the filename is
       
  1669  * unique.
       
  1670  *
       
  1671  * The callback is passed three parameters, the first one is the directory, the
       
  1672  * second is the filename, and the third is the extension.
       
  1673  *
       
  1674  * @since 2.5.0
       
  1675  *
       
  1676  * @param string $dir
       
  1677  * @param string $filename
       
  1678  * @param mixed $unique_filename_callback Callback.
       
  1679  * @return string New filename, if given wasn't unique.
       
  1680  */
       
  1681 function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
       
  1682 	// sanitize the file name before we begin processing
       
  1683 	$filename = sanitize_file_name($filename);
       
  1684 
       
  1685 	// separate the filename into a name and extension
       
  1686 	$info = pathinfo($filename);
       
  1687 	$ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
       
  1688 	$name = basename($filename, $ext);
       
  1689 
       
  1690 	// edge case: if file is named '.ext', treat as an empty name
       
  1691 	if ( $name === $ext )
       
  1692 		$name = '';
       
  1693 
       
  1694 	// Increment the file number until we have a unique file to save in $dir. Use callback if supplied.
       
  1695 	if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) {
       
  1696 		$filename = call_user_func( $unique_filename_callback, $dir, $name, $ext );
       
  1697 	} else {
       
  1698 		$number = '';
       
  1699 
       
  1700 		// change '.ext' to lower case
       
  1701 		if ( $ext && strtolower($ext) != $ext ) {
       
  1702 			$ext2 = strtolower($ext);
       
  1703 			$filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename );
       
  1704 
       
  1705 			// check for both lower and upper case extension or image sub-sizes may be overwritten
       
  1706 			while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) {
       
  1707 				$new_number = $number + 1;
       
  1708 				$filename = str_replace( "$number$ext", "$new_number$ext", $filename );
       
  1709 				$filename2 = str_replace( "$number$ext2", "$new_number$ext2", $filename2 );
       
  1710 				$number = $new_number;
       
  1711 			}
       
  1712 			return $filename2;
       
  1713 		}
       
  1714 
       
  1715 		while ( file_exists( $dir . "/$filename" ) ) {
       
  1716 			if ( '' == "$number$ext" )
       
  1717 				$filename = $filename . ++$number . $ext;
       
  1718 			else
       
  1719 				$filename = str_replace( "$number$ext", ++$number . $ext, $filename );
       
  1720 		}
       
  1721 	}
       
  1722 
       
  1723 	return $filename;
       
  1724 }
       
  1725 
       
  1726 /**
       
  1727  * Create a file in the upload folder with given content.
       
  1728  *
       
  1729  * If there is an error, then the key 'error' will exist with the error message.
       
  1730  * If success, then the key 'file' will have the unique file path, the 'url' key
       
  1731  * will have the link to the new file. and the 'error' key will be set to false.
       
  1732  *
       
  1733  * This function will not move an uploaded file to the upload folder. It will
       
  1734  * create a new file with the content in $bits parameter. If you move the upload
       
  1735  * file, read the content of the uploaded file, and then you can give the
       
  1736  * filename and content to this function, which will add it to the upload
       
  1737  * folder.
       
  1738  *
       
  1739  * The permissions will be set on the new file automatically by this function.
       
  1740  *
       
  1741  * @since 2.0.0
       
  1742  *
       
  1743  * @param string $name
       
  1744  * @param null $deprecated Never used. Set to null.
       
  1745  * @param mixed $bits File content
       
  1746  * @param string $time Optional. Time formatted in 'yyyy/mm'.
       
  1747  * @return array
       
  1748  */
       
  1749 function wp_upload_bits( $name, $deprecated, $bits, $time = null ) {
       
  1750 	if ( !empty( $deprecated ) )
       
  1751 		_deprecated_argument( __FUNCTION__, '2.0' );
       
  1752 
       
  1753 	if ( empty( $name ) )
       
  1754 		return array( 'error' => __( 'Empty filename' ) );
       
  1755 
       
  1756 	$wp_filetype = wp_check_filetype( $name );
       
  1757 	if ( ! $wp_filetype['ext'] && ! current_user_can( 'unfiltered_upload' ) )
       
  1758 		return array( 'error' => __( 'Invalid file type' ) );
       
  1759 
       
  1760 	$upload = wp_upload_dir( $time );
       
  1761 
       
  1762 	if ( $upload['error'] !== false )
       
  1763 		return $upload;
       
  1764 
       
  1765 	$upload_bits_error = apply_filters( 'wp_upload_bits', array( 'name' => $name, 'bits' => $bits, 'time' => $time ) );
       
  1766 	if ( !is_array( $upload_bits_error ) ) {
       
  1767 		$upload[ 'error' ] = $upload_bits_error;
       
  1768 		return $upload;
       
  1769 	}
       
  1770 
       
  1771 	$filename = wp_unique_filename( $upload['path'], $name );
       
  1772 
       
  1773 	$new_file = $upload['path'] . "/$filename";
       
  1774 	if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
       
  1775 		if ( 0 === strpos( $upload['basedir'], ABSPATH ) )
       
  1776 			$error_path = str_replace( ABSPATH, '', $upload['basedir'] ) . $upload['subdir'];
       
  1777 		else
       
  1778 			$error_path = basename( $upload['basedir'] ) . $upload['subdir'];
       
  1779 
       
  1780 		$message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path );
       
  1781 		return array( 'error' => $message );
       
  1782 	}
       
  1783 
       
  1784 	$ifp = @ fopen( $new_file, 'wb' );
       
  1785 	if ( ! $ifp )
       
  1786 		return array( 'error' => sprintf( __( 'Could not write file %s' ), $new_file ) );
       
  1787 
       
  1788 	@fwrite( $ifp, $bits );
       
  1789 	fclose( $ifp );
       
  1790 	clearstatcache();
       
  1791 
       
  1792 	// Set correct file permissions
       
  1793 	$stat = @ stat( dirname( $new_file ) );
       
  1794 	$perms = $stat['mode'] & 0007777;
       
  1795 	$perms = $perms & 0000666;
       
  1796 	@ chmod( $new_file, $perms );
       
  1797 	clearstatcache();
       
  1798 
       
  1799 	// Compute the URL
       
  1800 	$url = $upload['url'] . "/$filename";
       
  1801 
       
  1802 	return array( 'file' => $new_file, 'url' => $url, 'error' => false );
       
  1803 }
       
  1804 
       
  1805 /**
       
  1806  * Retrieve the file type based on the extension name.
       
  1807  *
       
  1808  * @package WordPress
       
  1809  * @since 2.5.0
       
  1810  * @uses apply_filters() Calls 'ext2type' hook on default supported types.
       
  1811  *
       
  1812  * @param string $ext The extension to search.
       
  1813  * @return string|null The file type, example: audio, video, document, spreadsheet, etc. Null if not found.
       
  1814  */
       
  1815 function wp_ext2type( $ext ) {
       
  1816 	$ext = strtolower( $ext );
       
  1817 	$ext2type = apply_filters( 'ext2type', array(
       
  1818 		'image'       => array( 'jpg', 'jpeg', 'jpe',  'gif',  'png',  'bmp',   'tif',  'tiff', 'ico' ),
       
  1819 		'audio'       => array( 'aac', 'ac3',  'aif',  'aiff', 'm3a',  'm4a',   'm4b',  'mka',  'mp1',  'mp2',  'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
       
  1820 		'video'       => array( 'asf', 'avi',  'divx', 'dv',   'flv',  'm4v',   'mkv',  'mov',  'mp4',  'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt',  'rm', 'vob', 'wmv' ),
       
  1821 		'document'    => array( 'doc', 'docx', 'docm', 'dotm', 'odt',  'pages', 'pdf',  'rtf',  'wp',   'wpd' ),
       
  1822 		'spreadsheet' => array( 'numbers',     'ods',  'xls',  'xlsx', 'xlsm',  'xlsb' ),
       
  1823 		'interactive' => array( 'swf', 'key',  'ppt',  'pptx', 'pptm', 'pps',   'ppsx', 'ppsm', 'sldx', 'sldm', 'odp' ),
       
  1824 		'text'        => array( 'asc', 'csv',  'tsv',  'txt' ),
       
  1825 		'archive'     => array( 'bz2', 'cab',  'dmg',  'gz',   'rar',  'sea',   'sit',  'sqx',  'tar',  'tgz',  'zip', '7z' ),
       
  1826 		'code'        => array( 'css', 'htm',  'html', 'php',  'js' ),
       
  1827 	) );
       
  1828 
       
  1829 	foreach ( $ext2type as $type => $exts )
       
  1830 		if ( in_array( $ext, $exts ) )
       
  1831 			return $type;
       
  1832 
       
  1833 	return null;
       
  1834 }
       
  1835 
       
  1836 /**
       
  1837  * Retrieve the file type from the file name.
       
  1838  *
       
  1839  * You can optionally define the mime array, if needed.
       
  1840  *
       
  1841  * @since 2.0.4
       
  1842  *
       
  1843  * @param string $filename File name or path.
       
  1844  * @param array $mimes Optional. Key is the file extension with value as the mime type.
       
  1845  * @return array Values with extension first and mime type.
       
  1846  */
       
  1847 function wp_check_filetype( $filename, $mimes = null ) {
       
  1848 	if ( empty($mimes) )
       
  1849 		$mimes = get_allowed_mime_types();
       
  1850 	$type = false;
       
  1851 	$ext = false;
       
  1852 
       
  1853 	foreach ( $mimes as $ext_preg => $mime_match ) {
       
  1854 		$ext_preg = '!\.(' . $ext_preg . ')$!i';
       
  1855 		if ( preg_match( $ext_preg, $filename, $ext_matches ) ) {
       
  1856 			$type = $mime_match;
       
  1857 			$ext = $ext_matches[1];
       
  1858 			break;
       
  1859 		}
       
  1860 	}
       
  1861 
       
  1862 	return compact( 'ext', 'type' );
       
  1863 }
       
  1864 
       
  1865 /**
       
  1866  * Attempt to determine the real file type of a file.
       
  1867  * If unable to, the file name extension will be used to determine type.
       
  1868  *
       
  1869  * If it's determined that the extension does not match the file's real type,
       
  1870  * then the "proper_filename" value will be set with a proper filename and extension.
       
  1871  *
       
  1872  * Currently this function only supports validating images known to getimagesize().
       
  1873  *
       
  1874  * @since 3.0.0
       
  1875  *
       
  1876  * @param string $file Full path to the file.
       
  1877  * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
       
  1878  * @param array $mimes Optional. Key is the file extension with value as the mime type.
       
  1879  * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
       
  1880  */
       
  1881 function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
       
  1882 
       
  1883 	$proper_filename = false;
       
  1884 
       
  1885 	// Do basic extension validation and MIME mapping
       
  1886 	$wp_filetype = wp_check_filetype( $filename, $mimes );
       
  1887 	extract( $wp_filetype );
       
  1888 
       
  1889 	// We can't do any further validation without a file to work with
       
  1890 	if ( ! file_exists( $file ) )
       
  1891 		return compact( 'ext', 'type', 'proper_filename' );
       
  1892 
       
  1893 	// We're able to validate images using GD
       
  1894 	if ( $type && 0 === strpos( $type, 'image/' ) && function_exists('getimagesize') ) {
       
  1895 
       
  1896 		// Attempt to figure out what type of image it actually is
       
  1897 		$imgstats = @getimagesize( $file );
       
  1898 
       
  1899 		// If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
       
  1900 		if ( !empty($imgstats['mime']) && $imgstats['mime'] != $type ) {
       
  1901 			// This is a simplified array of MIMEs that getimagesize() can detect and their extensions
       
  1902 			// You shouldn't need to use this filter, but it's here just in case
       
  1903 			$mime_to_ext = apply_filters( 'getimagesize_mimes_to_exts', array(
       
  1904 				'image/jpeg' => 'jpg',
       
  1905 				'image/png'  => 'png',
       
  1906 				'image/gif'  => 'gif',
       
  1907 				'image/bmp'  => 'bmp',
       
  1908 				'image/tiff' => 'tif',
       
  1909 			) );
       
  1910 
       
  1911 			// Replace whatever is after the last period in the filename with the correct extension
       
  1912 			if ( ! empty( $mime_to_ext[ $imgstats['mime'] ] ) ) {
       
  1913 				$filename_parts = explode( '.', $filename );
       
  1914 				array_pop( $filename_parts );
       
  1915 				$filename_parts[] = $mime_to_ext[ $imgstats['mime'] ];
       
  1916 				$new_filename = implode( '.', $filename_parts );
       
  1917 
       
  1918 				if ( $new_filename != $filename )
       
  1919 					$proper_filename = $new_filename; // Mark that it changed
       
  1920 
       
  1921 				// Redefine the extension / MIME
       
  1922 				$wp_filetype = wp_check_filetype( $new_filename, $mimes );
       
  1923 				extract( $wp_filetype );
       
  1924 			}
       
  1925 		}
       
  1926 	}
       
  1927 
       
  1928 	// Let plugins try and validate other types of files
       
  1929 	// Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
       
  1930 	return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes );
       
  1931 }
       
  1932 
       
  1933 /**
       
  1934  * Retrieve list of mime types and file extensions.
       
  1935  *
       
  1936  * @since 3.5.0
       
  1937  *
       
  1938  * @uses apply_filters() Calls 'mime_types' on returned array. This filter should
       
  1939  * be used to add types, not remove them. To remove types use the upload_mimes filter.
       
  1940  *
       
  1941  * @return array Array of mime types keyed by the file extension regex corresponding to those types.
       
  1942  */
       
  1943 function wp_get_mime_types() {
       
  1944 	// Accepted MIME types are set here as PCRE unless provided.
       
  1945 	return apply_filters( 'mime_types', array(
       
  1946 	// Image formats
       
  1947 	'jpg|jpeg|jpe' => 'image/jpeg',
       
  1948 	'gif' => 'image/gif',
       
  1949 	'png' => 'image/png',
       
  1950 	'bmp' => 'image/bmp',
       
  1951 	'tif|tiff' => 'image/tiff',
       
  1952 	'ico' => 'image/x-icon',
       
  1953 	// Video formats
       
  1954 	'asf|asx' => 'video/x-ms-asf',
       
  1955 	'wmv' => 'video/x-ms-wmv',
       
  1956 	'wmx' => 'video/x-ms-wmx',
       
  1957 	'wm' => 'video/x-ms-wm',
       
  1958 	'avi' => 'video/avi',
       
  1959 	'divx' => 'video/divx',
       
  1960 	'flv' => 'video/x-flv',
       
  1961 	'mov|qt' => 'video/quicktime',
       
  1962 	'mpeg|mpg|mpe' => 'video/mpeg',
       
  1963 	'mp4|m4v' => 'video/mp4',
       
  1964 	'ogv' => 'video/ogg',
       
  1965 	'webm' => 'video/webm',
       
  1966 	'mkv' => 'video/x-matroska',
       
  1967 	// Text formats
       
  1968 	'txt|asc|c|cc|h' => 'text/plain',
       
  1969 	'csv' => 'text/csv',
       
  1970 	'tsv' => 'text/tab-separated-values',
       
  1971 	'ics' => 'text/calendar',
       
  1972 	'rtx' => 'text/richtext',
       
  1973 	'css' => 'text/css',
       
  1974 	'htm|html' => 'text/html',
       
  1975 	// Audio formats
       
  1976 	'mp3|m4a|m4b' => 'audio/mpeg',
       
  1977 	'ra|ram' => 'audio/x-realaudio',
       
  1978 	'wav' => 'audio/wav',
       
  1979 	'ogg|oga' => 'audio/ogg',
       
  1980 	'mid|midi' => 'audio/midi',
       
  1981 	'wma' => 'audio/x-ms-wma',
       
  1982 	'wax' => 'audio/x-ms-wax',
       
  1983 	'mka' => 'audio/x-matroska',
       
  1984 	// Misc application formats
       
  1985 	'rtf' => 'application/rtf',
       
  1986 	'js' => 'application/javascript',
       
  1987 	'pdf' => 'application/pdf',
       
  1988 	'swf' => 'application/x-shockwave-flash',
       
  1989 	'class' => 'application/java',
       
  1990 	'tar' => 'application/x-tar',
       
  1991 	'zip' => 'application/zip',
       
  1992 	'gz|gzip' => 'application/x-gzip',
       
  1993 	'rar' => 'application/rar',
       
  1994 	'7z' => 'application/x-7z-compressed',
       
  1995 	'exe' => 'application/x-msdownload',
       
  1996 	// MS Office formats
       
  1997 	'doc' => 'application/msword',
       
  1998 	'pot|pps|ppt' => 'application/vnd.ms-powerpoint',
       
  1999 	'wri' => 'application/vnd.ms-write',
       
  2000 	'xla|xls|xlt|xlw' => 'application/vnd.ms-excel',
       
  2001 	'mdb' => 'application/vnd.ms-access',
       
  2002 	'mpp' => 'application/vnd.ms-project',
       
  2003 	'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
       
  2004 	'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
       
  2005 	'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
       
  2006 	'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
       
  2007 	'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
       
  2008 	'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
       
  2009 	'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
       
  2010 	'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
       
  2011 	'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
       
  2012 	'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
       
  2013 	'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
       
  2014 	'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
       
  2015 	'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
       
  2016 	'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
       
  2017 	'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
       
  2018 	'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
       
  2019 	'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
       
  2020 	'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
       
  2021 	'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
       
  2022 	'onetoc|onetoc2|onetmp|onepkg' => 'application/onenote',
       
  2023 	// OpenOffice formats
       
  2024 	'odt' => 'application/vnd.oasis.opendocument.text',
       
  2025 	'odp' => 'application/vnd.oasis.opendocument.presentation',
       
  2026 	'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
       
  2027 	'odg' => 'application/vnd.oasis.opendocument.graphics',
       
  2028 	'odc' => 'application/vnd.oasis.opendocument.chart',
       
  2029 	'odb' => 'application/vnd.oasis.opendocument.database',
       
  2030 	'odf' => 'application/vnd.oasis.opendocument.formula',
       
  2031 	// WordPerfect formats
       
  2032 	'wp|wpd' => 'application/wordperfect',
       
  2033 	// iWork formats
       
  2034 	'key' => 'application/vnd.apple.keynote',
       
  2035 	'numbers' => 'application/vnd.apple.numbers',
       
  2036 	'pages' => 'application/vnd.apple.pages',
       
  2037 	) );
       
  2038 }
       
  2039 /**
       
  2040  * Retrieve list of allowed mime types and file extensions.
       
  2041  *
       
  2042  * @since 2.8.6
       
  2043  *
       
  2044  * @uses apply_filters() Calls 'upload_mimes' on returned array
       
  2045  * @uses wp_get_upload_mime_types() to fetch the list of mime types
       
  2046  *
       
  2047  * @param int|WP_User $user Optional. User to check. Defaults to current user.
       
  2048  * @return array Array of mime types keyed by the file extension regex corresponding to those types.
       
  2049  */
       
  2050 function get_allowed_mime_types( $user = null ) {
       
  2051 	$t = wp_get_mime_types();
       
  2052 
       
  2053 	unset( $t['swf'], $t['exe'] );
       
  2054 	if ( function_exists( 'current_user_can' ) )
       
  2055 		$unfiltered = $user ? user_can( $user, 'unfiltered_html' ) : current_user_can( 'unfiltered_html' );
       
  2056 
       
  2057 	if ( empty( $unfiltered ) )
       
  2058 		unset( $t['htm|html'] );
       
  2059 
       
  2060 	return apply_filters( 'upload_mimes', $t, $user );
       
  2061 }
       
  2062 
       
  2063 /**
       
  2064  * Display "Are You Sure" message to confirm the action being taken.
       
  2065  *
       
  2066  * If the action has the nonce explain message, then it will be displayed along
       
  2067  * with the "Are you sure?" message.
       
  2068  *
       
  2069  * @package WordPress
       
  2070  * @subpackage Security
       
  2071  * @since 2.0.4
       
  2072  *
       
  2073  * @param string $action The nonce action.
       
  2074  */
       
  2075 function wp_nonce_ays( $action ) {
       
  2076 	$title = __( 'WordPress Failure Notice' );
       
  2077 	if ( 'log-out' == $action ) {
       
  2078 		$html = sprintf( __( 'You are attempting to log out of %s' ), get_bloginfo( 'name' ) ) . '</p><p>';
       
  2079 		$html .= sprintf( __( "Do you really want to <a href='%s'>log out</a>?"), wp_logout_url() );
       
  2080 	} else {
       
  2081 		$html = __( 'Are you sure you want to do this?' );
       
  2082 		if ( wp_get_referer() )
       
  2083 			$html .= "</p><p><a href='" . esc_url( remove_query_arg( 'updated', wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>";
       
  2084 	}
       
  2085 
       
  2086 	wp_die( $html, $title, array('response' => 403) );
       
  2087 }
       
  2088 
       
  2089 /**
       
  2090  * Kill WordPress execution and display HTML message with error message.
       
  2091  *
       
  2092  * This function complements the die() PHP function. The difference is that
       
  2093  * HTML will be displayed to the user. It is recommended to use this function
       
  2094  * only, when the execution should not continue any further. It is not
       
  2095  * recommended to call this function very often and try to handle as many errors
       
  2096  * as possible silently.
       
  2097  *
       
  2098  * @since 2.0.4
       
  2099  *
       
  2100  * @param string $message Error message.
       
  2101  * @param string $title Error title.
       
  2102  * @param string|array $args Optional arguments to control behavior.
       
  2103  */
       
  2104 function wp_die( $message = '', $title = '', $args = array() ) {
       
  2105 	if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
       
  2106 		$function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
       
  2107 	elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST )
       
  2108 		$function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
       
  2109 	else
       
  2110 		$function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
       
  2111 
       
  2112 	call_user_func( $function, $message, $title, $args );
       
  2113 }
       
  2114 
       
  2115 /**
       
  2116  * Kill WordPress execution and display HTML message with error message.
       
  2117  *
       
  2118  * This is the default handler for wp_die if you want a custom one for your
       
  2119  * site then you can overload using the wp_die_handler filter in wp_die
       
  2120  *
       
  2121  * @since 3.0.0
       
  2122  * @access private
       
  2123  *
       
  2124  * @param string $message Error message.
       
  2125  * @param string $title Error title.
       
  2126  * @param string|array $args Optional arguments to control behavior.
       
  2127  */
       
  2128 function _default_wp_die_handler( $message, $title = '', $args = array() ) {
       
  2129 	$defaults = array( 'response' => 500 );
       
  2130 	$r = wp_parse_args($args, $defaults);
       
  2131 
       
  2132 	$have_gettext = function_exists('__');
       
  2133 
       
  2134 	if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
       
  2135 		if ( empty( $title ) ) {
       
  2136 			$error_data = $message->get_error_data();
       
  2137 			if ( is_array( $error_data ) && isset( $error_data['title'] ) )
       
  2138 				$title = $error_data['title'];
       
  2139 		}
       
  2140 		$errors = $message->get_error_messages();
       
  2141 		switch ( count( $errors ) ) :
       
  2142 		case 0 :
       
  2143 			$message = '';
       
  2144 			break;
       
  2145 		case 1 :
       
  2146 			$message = "<p>{$errors[0]}</p>";
       
  2147 			break;
       
  2148 		default :
       
  2149 			$message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>";
       
  2150 			break;
       
  2151 		endswitch;
       
  2152 	} elseif ( is_string( $message ) ) {
       
  2153 		$message = "<p>$message</p>";
       
  2154 	}
       
  2155 
       
  2156 	if ( isset( $r['back_link'] ) && $r['back_link'] ) {
       
  2157 		$back_text = $have_gettext? __('&laquo; Back') : '&laquo; Back';
       
  2158 		$message .= "\n<p><a href='javascript:history.back()'>$back_text</a></p>";
       
  2159 	}
       
  2160 
       
  2161 	if ( ! did_action( 'admin_head' ) ) :
       
  2162 		if ( !headers_sent() ) {
       
  2163 			status_header( $r['response'] );
       
  2164 			nocache_headers();
       
  2165 			header( 'Content-Type: text/html; charset=utf-8' );
       
  2166 		}
       
  2167 
       
  2168 		if ( empty($title) )
       
  2169 			$title = $have_gettext ? __('WordPress &rsaquo; Error') : 'WordPress &rsaquo; Error';
       
  2170 
       
  2171 		$text_direction = 'ltr';
       
  2172 		if ( isset($r['text_direction']) && 'rtl' == $r['text_direction'] )
       
  2173 			$text_direction = 'rtl';
       
  2174 		elseif ( function_exists( 'is_rtl' ) && is_rtl() )
       
  2175 			$text_direction = 'rtl';
       
  2176 ?>
       
  2177 <!DOCTYPE html>
       
  2178 <!-- Ticket #11289, IE bug fix: always pad the error page with enough characters such that it is greater than 512 bytes, even after gzip compression abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono
       
  2179 -->
       
  2180 <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) && function_exists( 'is_rtl' ) ) language_attributes(); else echo "dir='$text_direction'"; ?>>
       
  2181 <head>
       
  2182 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
       
  2183 	<title><?php echo $title ?></title>
       
  2184 	<style type="text/css">
       
  2185 		html {
       
  2186 			background: #f9f9f9;
       
  2187 		}
       
  2188 		body {
       
  2189 			background: #fff;
       
  2190 			color: #333;
       
  2191 			font-family: sans-serif;
       
  2192 			margin: 2em auto;
       
  2193 			padding: 1em 2em;
       
  2194 			-webkit-border-radius: 3px;
       
  2195 			border-radius: 3px;
       
  2196 			border: 1px solid #dfdfdf;
       
  2197 			max-width: 700px;
       
  2198 		}
       
  2199 		h1 {
       
  2200 			border-bottom: 1px solid #dadada;
       
  2201 			clear: both;
       
  2202 			color: #666;
       
  2203 			font: 24px Georgia, "Times New Roman", Times, serif;
       
  2204 			margin: 30px 0 0 0;
       
  2205 			padding: 0;
       
  2206 			padding-bottom: 7px;
       
  2207 		}
       
  2208 		#error-page {
       
  2209 			margin-top: 50px;
       
  2210 		}
       
  2211 		#error-page p {
       
  2212 			font-size: 14px;
       
  2213 			line-height: 1.5;
       
  2214 			margin: 25px 0 20px;
       
  2215 		}
       
  2216 		#error-page code {
       
  2217 			font-family: Consolas, Monaco, monospace;
       
  2218 		}
       
  2219 		ul li {
       
  2220 			margin-bottom: 10px;
       
  2221 			font-size: 14px ;
       
  2222 		}
       
  2223 		a {
       
  2224 			color: #21759B;
       
  2225 			text-decoration: none;
       
  2226 		}
       
  2227 		a:hover {
       
  2228 			color: #D54E21;
       
  2229 		}
       
  2230 		.button {
       
  2231 			display: inline-block;
       
  2232 			text-decoration: none;
       
  2233 			font-size: 14px;
       
  2234 			line-height: 23px;
       
  2235 			height: 24px;
       
  2236 			margin: 0;
       
  2237 			padding: 0 10px 1px;
       
  2238 			cursor: pointer;
       
  2239 			border-width: 1px;
       
  2240 			border-style: solid;
       
  2241 			-webkit-border-radius: 3px;
       
  2242 			border-radius: 3px;
       
  2243 			white-space: nowrap;
       
  2244 			-webkit-box-sizing: border-box;
       
  2245 			-moz-box-sizing:    border-box;
       
  2246 			box-sizing:         border-box;
       
  2247 			background: #f3f3f3;
       
  2248 			background-image: -webkit-gradient(linear, left top, left bottom, from(#fefefe), to(#f4f4f4));
       
  2249 			background-image: -webkit-linear-gradient(top, #fefefe, #f4f4f4);
       
  2250 			background-image:    -moz-linear-gradient(top, #fefefe, #f4f4f4);
       
  2251 			background-image:      -o-linear-gradient(top, #fefefe, #f4f4f4);
       
  2252 			background-image:   linear-gradient(to bottom, #fefefe, #f4f4f4);
       
  2253 			border-color: #bbb;
       
  2254 		 	color: #333;
       
  2255 			text-shadow: 0 1px 0 #fff;
       
  2256 		}
       
  2257 
       
  2258 		.button.button-large {
       
  2259 			height: 29px;
       
  2260 			line-height: 28px;
       
  2261 			padding: 0 12px;
       
  2262 		}
       
  2263 
       
  2264 		.button:hover,
       
  2265 		.button:focus {
       
  2266 			background: #f3f3f3;
       
  2267 			background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f3f3f3));
       
  2268 			background-image: -webkit-linear-gradient(top, #fff, #f3f3f3);
       
  2269 			background-image:    -moz-linear-gradient(top, #fff, #f3f3f3);
       
  2270 			background-image:     -ms-linear-gradient(top, #fff, #f3f3f3);
       
  2271 			background-image:      -o-linear-gradient(top, #fff, #f3f3f3);
       
  2272 			background-image:   linear-gradient(to bottom, #fff, #f3f3f3);
       
  2273 			border-color: #999;
       
  2274 			color: #222;
       
  2275 		}
       
  2276 
       
  2277 		.button:focus  {
       
  2278 			-webkit-box-shadow: 1px 1px 1px rgba(0,0,0,.2);
       
  2279 			box-shadow: 1px 1px 1px rgba(0,0,0,.2);
       
  2280 		}
       
  2281 
       
  2282 		.button:active {
       
  2283 			outline: none;
       
  2284 			background: #eee;
       
  2285 			background-image: -webkit-gradient(linear, left top, left bottom, from(#f4f4f4), to(#fefefe));
       
  2286 			background-image: -webkit-linear-gradient(top, #f4f4f4, #fefefe);
       
  2287 			background-image:    -moz-linear-gradient(top, #f4f4f4, #fefefe);
       
  2288 			background-image:     -ms-linear-gradient(top, #f4f4f4, #fefefe);
       
  2289 			background-image:      -o-linear-gradient(top, #f4f4f4, #fefefe);
       
  2290 			background-image:   linear-gradient(to bottom, #f4f4f4, #fefefe);
       
  2291 			border-color: #999;
       
  2292 			color: #333;
       
  2293 			text-shadow: 0 -1px 0 #fff;
       
  2294 			-webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
       
  2295 		 	box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
       
  2296 		}
       
  2297 
       
  2298 		<?php if ( 'rtl' == $text_direction ) : ?>
       
  2299 		body { font-family: Tahoma, Arial; }
       
  2300 		<?php endif; ?>
       
  2301 	</style>
       
  2302 </head>
       
  2303 <body id="error-page">
       
  2304 <?php endif; // ! did_action( 'admin_head' ) ?>
       
  2305 	<?php echo $message; ?>
       
  2306 </body>
       
  2307 </html>
       
  2308 <?php
       
  2309 	die();
       
  2310 }
       
  2311 
       
  2312 /**
       
  2313  * Kill WordPress execution and display XML message with error message.
       
  2314  *
       
  2315  * This is the handler for wp_die when processing XMLRPC requests.
       
  2316  *
       
  2317  * @since 3.2.0
       
  2318  * @access private
       
  2319  *
       
  2320  * @param string $message Error message.
       
  2321  * @param string $title Error title.
       
  2322  * @param string|array $args Optional arguments to control behavior.
       
  2323  */
       
  2324 function _xmlrpc_wp_die_handler( $message, $title = '', $args = array() ) {
       
  2325 	global $wp_xmlrpc_server;
       
  2326 	$defaults = array( 'response' => 500 );
       
  2327 
       
  2328 	$r = wp_parse_args($args, $defaults);
       
  2329 
       
  2330 	if ( $wp_xmlrpc_server ) {
       
  2331 		$error = new IXR_Error( $r['response'] , $message);
       
  2332 		$wp_xmlrpc_server->output( $error->getXml() );
       
  2333 	}
       
  2334 	die();
       
  2335 }
       
  2336 
       
  2337 /**
       
  2338  * Kill WordPress ajax execution.
       
  2339  *
       
  2340  * This is the handler for wp_die when processing Ajax requests.
       
  2341  *
       
  2342  * @since 3.4.0
       
  2343  * @access private
       
  2344  *
       
  2345  * @param string $message Optional. Response to print.
       
  2346  */
       
  2347 function _ajax_wp_die_handler( $message = '' ) {
       
  2348 	if ( is_scalar( $message ) )
       
  2349 		die( (string) $message );
       
  2350 	die( '0' );
       
  2351 }
       
  2352 
       
  2353 /**
       
  2354  * Kill WordPress execution.
       
  2355  *
       
  2356  * This is the handler for wp_die when processing APP requests.
       
  2357  *
       
  2358  * @since 3.4.0
       
  2359  * @access private
       
  2360  *
       
  2361  * @param string $message Optional. Response to print.
       
  2362  */
       
  2363 function _scalar_wp_die_handler( $message = '' ) {
       
  2364 	if ( is_scalar( $message ) )
       
  2365 		die( (string) $message );
       
  2366 	die();
       
  2367 }
       
  2368 
       
  2369 /**
       
  2370  * Send a JSON response back to an Ajax request.
       
  2371  *
       
  2372  * @since 3.5.0
       
  2373  *
       
  2374  * @param mixed $response Variable (usually an array or object) to encode as JSON, then print and die.
       
  2375  */
       
  2376 function wp_send_json( $response ) {
       
  2377 	@header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
       
  2378 	echo json_encode( $response );
       
  2379 	if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
       
  2380 		wp_die();
       
  2381 	else
       
  2382 		die;
       
  2383 }
       
  2384 
       
  2385 /**
       
  2386  * Send a JSON response back to an Ajax request, indicating success.
       
  2387  *
       
  2388  * @since 3.5.0
       
  2389  *
       
  2390  * @param mixed $data Data to encode as JSON, then print and die.
       
  2391  */
       
  2392 function wp_send_json_success( $data = null ) {
       
  2393 	$response = array( 'success' => true );
       
  2394 
       
  2395 	if ( isset( $data ) )
       
  2396 		$response['data'] = $data;
       
  2397 
       
  2398 	wp_send_json( $response );
       
  2399 }
       
  2400 
       
  2401 /**
       
  2402  * Send a JSON response back to an Ajax request, indicating failure.
       
  2403  *
       
  2404  * @since 3.5.0
       
  2405  *
       
  2406  * @param mixed $data Data to encode as JSON, then print and die.
       
  2407  */
       
  2408 function wp_send_json_error( $data = null ) {
       
  2409 	$response = array( 'success' => false );
       
  2410 
       
  2411 	if ( isset( $data ) )
       
  2412 		$response['data'] = $data;
       
  2413 
       
  2414 	wp_send_json( $response );
       
  2415 }
       
  2416 
       
  2417 /**
       
  2418  * Retrieve the WordPress home page URL.
       
  2419  *
       
  2420  * If the constant named 'WP_HOME' exists, then it will be used and returned by
       
  2421  * the function. This can be used to counter the redirection on your local
       
  2422  * development environment.
       
  2423  *
       
  2424  * @access private
       
  2425  * @package WordPress
       
  2426  * @since 2.2.0
       
  2427  *
       
  2428  * @param string $url URL for the home location
       
  2429  * @return string Homepage location.
       
  2430  */
       
  2431 function _config_wp_home( $url = '' ) {
       
  2432 	if ( defined( 'WP_HOME' ) )
       
  2433 		return untrailingslashit( WP_HOME );
       
  2434 	return $url;
       
  2435 }
       
  2436 
       
  2437 /**
       
  2438  * Retrieve the WordPress site URL.
       
  2439  *
       
  2440  * If the constant named 'WP_SITEURL' is defined, then the value in that
       
  2441  * constant will always be returned. This can be used for debugging a site on
       
  2442  * your localhost while not having to change the database to your URL.
       
  2443  *
       
  2444  * @access private
       
  2445  * @package WordPress
       
  2446  * @since 2.2.0
       
  2447  *
       
  2448  * @param string $url URL to set the WordPress site location.
       
  2449  * @return string The WordPress Site URL
       
  2450  */
       
  2451 function _config_wp_siteurl( $url = '' ) {
       
  2452 	if ( defined( 'WP_SITEURL' ) )
       
  2453 		return untrailingslashit( WP_SITEURL );
       
  2454 	return $url;
       
  2455 }
       
  2456 
       
  2457 /**
       
  2458  * Set the localized direction for MCE plugin.
       
  2459  *
       
  2460  * Will only set the direction to 'rtl', if the WordPress locale has the text
       
  2461  * direction set to 'rtl'.
       
  2462  *
       
  2463  * Fills in the 'directionality', 'plugins', and 'theme_advanced_button1' array
       
  2464  * keys. These keys are then returned in the $input array.
       
  2465  *
       
  2466  * @access private
       
  2467  * @package WordPress
       
  2468  * @subpackage MCE
       
  2469  * @since 2.1.0
       
  2470  *
       
  2471  * @param array $input MCE plugin array.
       
  2472  * @return array Direction set for 'rtl', if needed by locale.
       
  2473  */
       
  2474 function _mce_set_direction( $input ) {
       
  2475 	if ( is_rtl() ) {
       
  2476 		$input['directionality'] = 'rtl';
       
  2477 		$input['plugins'] .= ',directionality';
       
  2478 		$input['theme_advanced_buttons1'] .= ',ltr';
       
  2479 	}
       
  2480 
       
  2481 	return $input;
       
  2482 }
       
  2483 
       
  2484 /**
       
  2485  * Convert smiley code to the icon graphic file equivalent.
       
  2486  *
       
  2487  * You can turn off smilies, by going to the write setting screen and unchecking
       
  2488  * the box, or by setting 'use_smilies' option to false or removing the option.
       
  2489  *
       
  2490  * Plugins may override the default smiley list by setting the $wpsmiliestrans
       
  2491  * to an array, with the key the code the blogger types in and the value the
       
  2492  * image file.
       
  2493  *
       
  2494  * The $wp_smiliessearch global is for the regular expression and is set each
       
  2495  * time the function is called.
       
  2496  *
       
  2497  * The full list of smilies can be found in the function and won't be listed in
       
  2498  * the description. Probably should create a Codex page for it, so that it is
       
  2499  * available.
       
  2500  *
       
  2501  * @global array $wpsmiliestrans
       
  2502  * @global array $wp_smiliessearch
       
  2503  * @since 2.2.0
       
  2504  */
       
  2505 function smilies_init() {
       
  2506 	global $wpsmiliestrans, $wp_smiliessearch;
       
  2507 
       
  2508 	// don't bother setting up smilies if they are disabled
       
  2509 	if ( !get_option( 'use_smilies' ) )
       
  2510 		return;
       
  2511 
       
  2512 	if ( !isset( $wpsmiliestrans ) ) {
       
  2513 		$wpsmiliestrans = array(
       
  2514 		':mrgreen:' => 'icon_mrgreen.gif',
       
  2515 		':neutral:' => 'icon_neutral.gif',
       
  2516 		':twisted:' => 'icon_twisted.gif',
       
  2517 		  ':arrow:' => 'icon_arrow.gif',
       
  2518 		  ':shock:' => 'icon_eek.gif',
       
  2519 		  ':smile:' => 'icon_smile.gif',
       
  2520 		    ':???:' => 'icon_confused.gif',
       
  2521 		   ':cool:' => 'icon_cool.gif',
       
  2522 		   ':evil:' => 'icon_evil.gif',
       
  2523 		   ':grin:' => 'icon_biggrin.gif',
       
  2524 		   ':idea:' => 'icon_idea.gif',
       
  2525 		   ':oops:' => 'icon_redface.gif',
       
  2526 		   ':razz:' => 'icon_razz.gif',
       
  2527 		   ':roll:' => 'icon_rolleyes.gif',
       
  2528 		   ':wink:' => 'icon_wink.gif',
       
  2529 		    ':cry:' => 'icon_cry.gif',
       
  2530 		    ':eek:' => 'icon_surprised.gif',
       
  2531 		    ':lol:' => 'icon_lol.gif',
       
  2532 		    ':mad:' => 'icon_mad.gif',
       
  2533 		    ':sad:' => 'icon_sad.gif',
       
  2534 		      '8-)' => 'icon_cool.gif',
       
  2535 		      '8-O' => 'icon_eek.gif',
       
  2536 		      ':-(' => 'icon_sad.gif',
       
  2537 		      ':-)' => 'icon_smile.gif',
       
  2538 		      ':-?' => 'icon_confused.gif',
       
  2539 		      ':-D' => 'icon_biggrin.gif',
       
  2540 		      ':-P' => 'icon_razz.gif',
       
  2541 		      ':-o' => 'icon_surprised.gif',
       
  2542 		      ':-x' => 'icon_mad.gif',
       
  2543 		      ':-|' => 'icon_neutral.gif',
       
  2544 		      ';-)' => 'icon_wink.gif',
       
  2545 		// This one transformation breaks regular text with frequency.
       
  2546 		//     '8)' => 'icon_cool.gif',
       
  2547 		       '8O' => 'icon_eek.gif',
       
  2548 		       ':(' => 'icon_sad.gif',
       
  2549 		       ':)' => 'icon_smile.gif',
       
  2550 		       ':?' => 'icon_confused.gif',
       
  2551 		       ':D' => 'icon_biggrin.gif',
       
  2552 		       ':P' => 'icon_razz.gif',
       
  2553 		       ':o' => 'icon_surprised.gif',
       
  2554 		       ':x' => 'icon_mad.gif',
       
  2555 		       ':|' => 'icon_neutral.gif',
       
  2556 		       ';)' => 'icon_wink.gif',
       
  2557 		      ':!:' => 'icon_exclaim.gif',
       
  2558 		      ':?:' => 'icon_question.gif',
       
  2559 		);
       
  2560 	}
       
  2561 
       
  2562 	if (count($wpsmiliestrans) == 0) {
       
  2563 		return;
       
  2564 	}
       
  2565 
       
  2566 	/*
       
  2567 	 * NOTE: we sort the smilies in reverse key order. This is to make sure
       
  2568 	 * we match the longest possible smilie (:???: vs :?) as the regular
       
  2569 	 * expression used below is first-match
       
  2570 	 */
       
  2571 	krsort($wpsmiliestrans);
       
  2572 
       
  2573 	$wp_smiliessearch = '/(?:\s|^)';
       
  2574 
       
  2575 	$subchar = '';
       
  2576 	foreach ( (array) $wpsmiliestrans as $smiley => $img ) {
       
  2577 		$firstchar = substr($smiley, 0, 1);
       
  2578 		$rest = substr($smiley, 1);
       
  2579 
       
  2580 		// new subpattern?
       
  2581 		if ($firstchar != $subchar) {
       
  2582 			if ($subchar != '') {
       
  2583 				$wp_smiliessearch .= ')|(?:\s|^)';
       
  2584 			}
       
  2585 			$subchar = $firstchar;
       
  2586 			$wp_smiliessearch .= preg_quote($firstchar, '/') . '(?:';
       
  2587 		} else {
       
  2588 			$wp_smiliessearch .= '|';
       
  2589 		}
       
  2590 		$wp_smiliessearch .= preg_quote($rest, '/');
       
  2591 	}
       
  2592 
       
  2593 	$wp_smiliessearch .= ')(?:\s|$)/m';
       
  2594 }
       
  2595 
       
  2596 /**
       
  2597  * Merge user defined arguments into defaults array.
       
  2598  *
       
  2599  * This function is used throughout WordPress to allow for both string or array
       
  2600  * to be merged into another array.
       
  2601  *
       
  2602  * @since 2.2.0
       
  2603  *
       
  2604  * @param string|array $args Value to merge with $defaults
       
  2605  * @param array $defaults Array that serves as the defaults.
       
  2606  * @return array Merged user defined values with defaults.
       
  2607  */
       
  2608 function wp_parse_args( $args, $defaults = '' ) {
       
  2609 	if ( is_object( $args ) )
       
  2610 		$r = get_object_vars( $args );
       
  2611 	elseif ( is_array( $args ) )
       
  2612 		$r =& $args;
       
  2613 	else
       
  2614 		wp_parse_str( $args, $r );
       
  2615 
       
  2616 	if ( is_array( $defaults ) )
       
  2617 		return array_merge( $defaults, $r );
       
  2618 	return $r;
       
  2619 }
       
  2620 
       
  2621 /**
       
  2622  * Clean up an array, comma- or space-separated list of IDs.
       
  2623  *
       
  2624  * @since 3.0.0
       
  2625  *
       
  2626  * @param array|string $list
       
  2627  * @return array Sanitized array of IDs
       
  2628  */
       
  2629 function wp_parse_id_list( $list ) {
       
  2630 	if ( !is_array($list) )
       
  2631 		$list = preg_split('/[\s,]+/', $list);
       
  2632 
       
  2633 	return array_unique(array_map('absint', $list));
       
  2634 }
       
  2635 
       
  2636 /**
       
  2637  * Extract a slice of an array, given a list of keys.
       
  2638  *
       
  2639  * @since 3.1.0
       
  2640  *
       
  2641  * @param array $array The original array
       
  2642  * @param array $keys The list of keys
       
  2643  * @return array The array slice
       
  2644  */
       
  2645 function wp_array_slice_assoc( $array, $keys ) {
       
  2646 	$slice = array();
       
  2647 	foreach ( $keys as $key )
       
  2648 		if ( isset( $array[ $key ] ) )
       
  2649 			$slice[ $key ] = $array[ $key ];
       
  2650 
       
  2651 	return $slice;
       
  2652 }
       
  2653 
       
  2654 /**
       
  2655  * Filters a list of objects, based on a set of key => value arguments.
       
  2656  *
       
  2657  * @since 3.0.0
       
  2658  *
       
  2659  * @param array $list An array of objects to filter
       
  2660  * @param array $args An array of key => value arguments to match against each object
       
  2661  * @param string $operator The logical operation to perform. 'or' means only one element
       
  2662  *	from the array needs to match; 'and' means all elements must match. The default is 'and'.
       
  2663  * @param bool|string $field A field from the object to place instead of the entire object
       
  2664  * @return array A list of objects or object fields
       
  2665  */
       
  2666 function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
       
  2667 	if ( ! is_array( $list ) )
       
  2668 		return array();
       
  2669 
       
  2670 	$list = wp_list_filter( $list, $args, $operator );
       
  2671 
       
  2672 	if ( $field )
       
  2673 		$list = wp_list_pluck( $list, $field );
       
  2674 
       
  2675 	return $list;
       
  2676 }
       
  2677 
       
  2678 /**
       
  2679  * Filters a list of objects, based on a set of key => value arguments.
       
  2680  *
       
  2681  * @since 3.1.0
       
  2682  *
       
  2683  * @param array $list An array of objects to filter
       
  2684  * @param array $args An array of key => value arguments to match against each object
       
  2685  * @param string $operator The logical operation to perform:
       
  2686  *    'AND' means all elements from the array must match;
       
  2687  *    'OR' means only one element needs to match;
       
  2688  *    'NOT' means no elements may match.
       
  2689  *   The default is 'AND'.
       
  2690  * @return array
       
  2691  */
       
  2692 function wp_list_filter( $list, $args = array(), $operator = 'AND' ) {
       
  2693 	if ( ! is_array( $list ) )
       
  2694 		return array();
       
  2695 
       
  2696 	if ( empty( $args ) )
       
  2697 		return $list;
       
  2698 
       
  2699 	$operator = strtoupper( $operator );
       
  2700 	$count = count( $args );
       
  2701 	$filtered = array();
       
  2702 
       
  2703 	foreach ( $list as $key => $obj ) {
       
  2704 		$to_match = (array) $obj;
       
  2705 
       
  2706 		$matched = 0;
       
  2707 		foreach ( $args as $m_key => $m_value ) {
       
  2708 			if ( array_key_exists( $m_key, $to_match ) && $m_value == $to_match[ $m_key ] )
       
  2709 				$matched++;
       
  2710 		}
       
  2711 
       
  2712 		if ( ( 'AND' == $operator && $matched == $count )
       
  2713 		  || ( 'OR' == $operator && $matched > 0 )
       
  2714 		  || ( 'NOT' == $operator && 0 == $matched ) ) {
       
  2715 			$filtered[$key] = $obj;
       
  2716 		}
       
  2717 	}
       
  2718 
       
  2719 	return $filtered;
       
  2720 }
       
  2721 
       
  2722 /**
       
  2723  * Pluck a certain field out of each object in a list.
       
  2724  *
       
  2725  * @since 3.1.0
       
  2726  *
       
  2727  * @param array $list A list of objects or arrays
       
  2728  * @param int|string $field A field from the object to place instead of the entire object
       
  2729  * @return array
       
  2730  */
       
  2731 function wp_list_pluck( $list, $field ) {
       
  2732 	foreach ( $list as $key => $value ) {
       
  2733 		if ( is_object( $value ) )
       
  2734 			$list[ $key ] = $value->$field;
       
  2735 		else
       
  2736 			$list[ $key ] = $value[ $field ];
       
  2737 	}
       
  2738 
       
  2739 	return $list;
       
  2740 }
       
  2741 
       
  2742 /**
       
  2743  * Determines if Widgets library should be loaded.
       
  2744  *
       
  2745  * Checks to make sure that the widgets library hasn't already been loaded. If
       
  2746  * it hasn't, then it will load the widgets library and run an action hook.
       
  2747  *
       
  2748  * @since 2.2.0
       
  2749  * @uses add_action() Calls '_admin_menu' hook with 'wp_widgets_add_menu' value.
       
  2750  */
       
  2751 function wp_maybe_load_widgets() {
       
  2752 	if ( ! apply_filters('load_default_widgets', true) )
       
  2753 		return;
       
  2754 	require_once( ABSPATH . WPINC . '/default-widgets.php' );
       
  2755 	add_action( '_admin_menu', 'wp_widgets_add_menu' );
       
  2756 }
       
  2757 
       
  2758 /**
       
  2759  * Append the Widgets menu to the themes main menu.
       
  2760  *
       
  2761  * @since 2.2.0
       
  2762  * @uses $submenu The administration submenu list.
       
  2763  */
       
  2764 function wp_widgets_add_menu() {
       
  2765 	global $submenu;
       
  2766 
       
  2767 	if ( ! current_theme_supports( 'widgets' ) )
       
  2768 		return;
       
  2769 
       
  2770 	$submenu['themes.php'][7] = array( __( 'Widgets' ), 'edit_theme_options', 'widgets.php' );
       
  2771 	ksort( $submenu['themes.php'], SORT_NUMERIC );
       
  2772 }
       
  2773 
       
  2774 /**
       
  2775  * Flush all output buffers for PHP 5.2.
       
  2776  *
       
  2777  * Make sure all output buffers are flushed before our singletons our destroyed.
       
  2778  *
       
  2779  * @since 2.2.0
       
  2780  */
       
  2781 function wp_ob_end_flush_all() {
       
  2782 	$levels = ob_get_level();
       
  2783 	for ($i=0; $i<$levels; $i++)
       
  2784 		ob_end_flush();
       
  2785 }
       
  2786 
       
  2787 /**
       
  2788  * Load custom DB error or display WordPress DB error.
       
  2789  *
       
  2790  * If a file exists in the wp-content directory named db-error.php, then it will
       
  2791  * be loaded instead of displaying the WordPress DB error. If it is not found,
       
  2792  * then the WordPress DB error will be displayed instead.
       
  2793  *
       
  2794  * The WordPress DB error sets the HTTP status header to 500 to try to prevent
       
  2795  * search engines from caching the message. Custom DB messages should do the
       
  2796  * same.
       
  2797  *
       
  2798  * This function was backported to WordPress 2.3.2, but originally was added
       
  2799  * in WordPress 2.5.0.
       
  2800  *
       
  2801  * @since 2.3.2
       
  2802  * @uses $wpdb
       
  2803  */
       
  2804 function dead_db() {
       
  2805 	global $wpdb;
       
  2806 
       
  2807 	// Load custom DB error template, if present.
       
  2808 	if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
       
  2809 		require_once( WP_CONTENT_DIR . '/db-error.php' );
       
  2810 		die();
       
  2811 	}
       
  2812 
       
  2813 	// If installing or in the admin, provide the verbose message.
       
  2814 	if ( defined('WP_INSTALLING') || defined('WP_ADMIN') )
       
  2815 		wp_die($wpdb->error);
       
  2816 
       
  2817 	// Otherwise, be terse.
       
  2818 	status_header( 500 );
       
  2819 	nocache_headers();
       
  2820 	header( 'Content-Type: text/html; charset=utf-8' );
       
  2821 
       
  2822 	wp_load_translations_early();
       
  2823 ?>
       
  2824 <!DOCTYPE html>
       
  2825 <html xmlns="http://www.w3.org/1999/xhtml"<?php if ( is_rtl() ) echo ' dir="rtl"'; ?>>
       
  2826 <head>
       
  2827 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
       
  2828 	<title><?php _e( 'Database Error' ); ?></title>
       
  2829 
       
  2830 </head>
       
  2831 <body>
       
  2832 	<h1><?php _e( 'Error establishing a database connection' ); ?></h1>
       
  2833 </body>
       
  2834 </html>
       
  2835 <?php
       
  2836 	die();
       
  2837 }
       
  2838 
       
  2839 /**
       
  2840  * Converts value to nonnegative integer.
       
  2841  *
       
  2842  * @since 2.5.0
       
  2843  *
       
  2844  * @param mixed $maybeint Data you wish to have converted to a nonnegative integer
       
  2845  * @return int An nonnegative integer
       
  2846  */
       
  2847 function absint( $maybeint ) {
       
  2848 	return abs( intval( $maybeint ) );
       
  2849 }
       
  2850 
       
  2851 /**
       
  2852  * Determines if the blog can be accessed over SSL.
       
  2853  *
       
  2854  * Determines if blog can be accessed over SSL by using cURL to access the site
       
  2855  * using the https in the siteurl. Requires cURL extension to work correctly.
       
  2856  *
       
  2857  * @since 2.5.0
       
  2858  *
       
  2859  * @param string $url
       
  2860  * @return bool Whether SSL access is available
       
  2861  */
       
  2862 function url_is_accessable_via_ssl($url)
       
  2863 {
       
  2864 	if ( in_array( 'curl', get_loaded_extensions() ) ) {
       
  2865 		$ssl = set_url_scheme( $url, 'https' );
       
  2866 
       
  2867 		$ch = curl_init();
       
  2868 		curl_setopt($ch, CURLOPT_URL, $ssl);
       
  2869 		curl_setopt($ch, CURLOPT_FAILONERROR, true);
       
  2870 		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
       
  2871 		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
       
  2872 		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
       
  2873 
       
  2874 		curl_exec($ch);
       
  2875 
       
  2876 		$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
       
  2877 		curl_close ($ch);
       
  2878 
       
  2879 		if ($status == 200 || $status == 401) {
       
  2880 			return true;
       
  2881 		}
       
  2882 	}
       
  2883 	return false;
       
  2884 }
       
  2885 
       
  2886 /**
       
  2887  * Marks a function as deprecated and informs when it has been used.
       
  2888  *
       
  2889  * There is a hook deprecated_function_run that will be called that can be used
       
  2890  * to get the backtrace up to what file and function called the deprecated
       
  2891  * function.
       
  2892  *
       
  2893  * The current behavior is to trigger a user error if WP_DEBUG is true.
       
  2894  *
       
  2895  * This function is to be used in every function that is deprecated.
       
  2896  *
       
  2897  * @package WordPress
       
  2898  * @subpackage Debug
       
  2899  * @since 2.5.0
       
  2900  * @access private
       
  2901  *
       
  2902  * @uses do_action() Calls 'deprecated_function_run' and passes the function name, what to use instead,
       
  2903  *   and the version the function was deprecated in.
       
  2904  * @uses apply_filters() Calls 'deprecated_function_trigger_error' and expects boolean value of true to do
       
  2905  *   trigger or false to not trigger error.
       
  2906  *
       
  2907  * @param string $function The function that was called
       
  2908  * @param string $version The version of WordPress that deprecated the function
       
  2909  * @param string $replacement Optional. The function that should have been called
       
  2910  */
       
  2911 function _deprecated_function( $function, $version, $replacement = null ) {
       
  2912 
       
  2913 	do_action( 'deprecated_function_run', $function, $replacement, $version );
       
  2914 
       
  2915 	// Allow plugin to filter the output error trigger
       
  2916 	if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
       
  2917 		if ( function_exists( '__' ) ) {
       
  2918 			if ( ! is_null( $replacement ) )
       
  2919 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) );
       
  2920 			else
       
  2921 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
       
  2922 		} else {
       
  2923 			if ( ! is_null( $replacement ) )
       
  2924 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $function, $version, $replacement ) );
       
  2925 			else
       
  2926 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $function, $version ) );
       
  2927 		}
       
  2928 	}
       
  2929 }
       
  2930 
       
  2931 /**
       
  2932  * Marks a file as deprecated and informs when it has been used.
       
  2933  *
       
  2934  * There is a hook deprecated_file_included that will be called that can be used
       
  2935  * to get the backtrace up to what file and function included the deprecated
       
  2936  * file.
       
  2937  *
       
  2938  * The current behavior is to trigger a user error if WP_DEBUG is true.
       
  2939  *
       
  2940  * This function is to be used in every file that is deprecated.
       
  2941  *
       
  2942  * @package WordPress
       
  2943  * @subpackage Debug
       
  2944  * @since 2.5.0
       
  2945  * @access private
       
  2946  *
       
  2947  * @uses do_action() Calls 'deprecated_file_included' and passes the file name, what to use instead,
       
  2948  *   the version in which the file was deprecated, and any message regarding the change.
       
  2949  * @uses apply_filters() Calls 'deprecated_file_trigger_error' and expects boolean value of true to do
       
  2950  *   trigger or false to not trigger error.
       
  2951  *
       
  2952  * @param string $file The file that was included
       
  2953  * @param string $version The version of WordPress that deprecated the file
       
  2954  * @param string $replacement Optional. The file that should have been included based on ABSPATH
       
  2955  * @param string $message Optional. A message regarding the change
       
  2956  */
       
  2957 function _deprecated_file( $file, $version, $replacement = null, $message = '' ) {
       
  2958 
       
  2959 	do_action( 'deprecated_file_included', $file, $replacement, $version, $message );
       
  2960 
       
  2961 	// Allow plugin to filter the output error trigger
       
  2962 	if ( WP_DEBUG && apply_filters( 'deprecated_file_trigger_error', true ) ) {
       
  2963 		$message = empty( $message ) ? '' : ' ' . $message;
       
  2964 		if ( function_exists( '__' ) ) {
       
  2965 			if ( ! is_null( $replacement ) )
       
  2966 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) . $message );
       
  2967 			else
       
  2968 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $file, $version ) . $message );
       
  2969 		} else {
       
  2970 			if ( ! is_null( $replacement ) )
       
  2971 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $file, $version, $replacement ) . $message );
       
  2972 			else
       
  2973 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $file, $version ) . $message );
       
  2974 		}
       
  2975 	}
       
  2976 }
       
  2977 /**
       
  2978  * Marks a function argument as deprecated and informs when it has been used.
       
  2979  *
       
  2980  * This function is to be used whenever a deprecated function argument is used.
       
  2981  * Before this function is called, the argument must be checked for whether it was
       
  2982  * used by comparing it to its default value or evaluating whether it is empty.
       
  2983  * For example:
       
  2984  * <code>
       
  2985  * if ( !empty($deprecated) )
       
  2986  * 	_deprecated_argument( __FUNCTION__, '3.0' );
       
  2987  * </code>
       
  2988  *
       
  2989  * There is a hook deprecated_argument_run that will be called that can be used
       
  2990  * to get the backtrace up to what file and function used the deprecated
       
  2991  * argument.
       
  2992  *
       
  2993  * The current behavior is to trigger a user error if WP_DEBUG is true.
       
  2994  *
       
  2995  * @package WordPress
       
  2996  * @subpackage Debug
       
  2997  * @since 3.0.0
       
  2998  * @access private
       
  2999  *
       
  3000  * @uses do_action() Calls 'deprecated_argument_run' and passes the function name, a message on the change,
       
  3001  *   and the version in which the argument was deprecated.
       
  3002  * @uses apply_filters() Calls 'deprecated_argument_trigger_error' and expects boolean value of true to do
       
  3003  *   trigger or false to not trigger error.
       
  3004  *
       
  3005  * @param string $function The function that was called
       
  3006  * @param string $version The version of WordPress that deprecated the argument used
       
  3007  * @param string $message Optional. A message regarding the change.
       
  3008  */
       
  3009 function _deprecated_argument( $function, $version, $message = null ) {
       
  3010 
       
  3011 	do_action( 'deprecated_argument_run', $function, $message, $version );
       
  3012 
       
  3013 	// Allow plugin to filter the output error trigger
       
  3014 	if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) {
       
  3015 		if ( function_exists( '__' ) ) {
       
  3016 			if ( ! is_null( $message ) )
       
  3017 				trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s'), $function, $version, $message ) );
       
  3018 			else
       
  3019 				trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
       
  3020 		} else {
       
  3021 			if ( ! is_null( $message ) )
       
  3022 				trigger_error( sprintf( '%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s', $function, $version, $message ) );
       
  3023 			else
       
  3024 				trigger_error( sprintf( '%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.', $function, $version ) );
       
  3025 		}
       
  3026 	}
       
  3027 }
       
  3028 
       
  3029 /**
       
  3030  * Marks something as being incorrectly called.
       
  3031  *
       
  3032  * There is a hook doing_it_wrong_run that will be called that can be used
       
  3033  * to get the backtrace up to what file and function called the deprecated
       
  3034  * function.
       
  3035  *
       
  3036  * The current behavior is to trigger a user error if WP_DEBUG is true.
       
  3037  *
       
  3038  * @package WordPress
       
  3039  * @subpackage Debug
       
  3040  * @since 3.1.0
       
  3041  * @access private
       
  3042  *
       
  3043  * @uses do_action() Calls 'doing_it_wrong_run' and passes the function arguments.
       
  3044  * @uses apply_filters() Calls 'doing_it_wrong_trigger_error' and expects boolean value of true to do
       
  3045  *   trigger or false to not trigger error.
       
  3046  *
       
  3047  * @param string $function The function that was called.
       
  3048  * @param string $message A message explaining what has been done incorrectly.
       
  3049  * @param string $version The version of WordPress where the message was added.
       
  3050  */
       
  3051 function _doing_it_wrong( $function, $message, $version ) {
       
  3052 
       
  3053 	do_action( 'doing_it_wrong_run', $function, $message, $version );
       
  3054 
       
  3055 	// Allow plugin to filter the output error trigger
       
  3056 	if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
       
  3057 		if ( function_exists( '__' ) ) {
       
  3058 			$version = is_null( $version ) ? '' : sprintf( __( '(This message was added in version %s.)' ), $version );
       
  3059 			$message .= ' ' . __( 'Please see <a href="http://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information.' );
       
  3060 			trigger_error( sprintf( __( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s' ), $function, $message, $version ) );
       
  3061 		} else {
       
  3062 			$version = is_null( $version ) ? '' : sprintf( '(This message was added in version %s.)', $version );
       
  3063 			$message .= ' Please see <a href="http://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information.';
       
  3064 			trigger_error( sprintf( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s', $function, $message, $version ) );
       
  3065 		}
       
  3066 	}
       
  3067 }
       
  3068 
       
  3069 /**
       
  3070  * Is the server running earlier than 1.5.0 version of lighttpd?
       
  3071  *
       
  3072  * @since 2.5.0
       
  3073  *
       
  3074  * @return bool Whether the server is running lighttpd < 1.5.0
       
  3075  */
       
  3076 function is_lighttpd_before_150() {
       
  3077 	$server_parts = explode( '/', isset( $_SERVER['SERVER_SOFTWARE'] )? $_SERVER['SERVER_SOFTWARE'] : '' );
       
  3078 	$server_parts[1] = isset( $server_parts[1] )? $server_parts[1] : '';
       
  3079 	return  'lighttpd' == $server_parts[0] && -1 == version_compare( $server_parts[1], '1.5.0' );
       
  3080 }
       
  3081 
       
  3082 /**
       
  3083  * Does the specified module exist in the Apache config?
       
  3084  *
       
  3085  * @since 2.5.0
       
  3086  *
       
  3087  * @param string $mod e.g. mod_rewrite
       
  3088  * @param bool $default The default return value if the module is not found
       
  3089  * @return bool
       
  3090  */
       
  3091 function apache_mod_loaded($mod, $default = false) {
       
  3092 	global $is_apache;
       
  3093 
       
  3094 	if ( !$is_apache )
       
  3095 		return false;
       
  3096 
       
  3097 	if ( function_exists('apache_get_modules') ) {
       
  3098 		$mods = apache_get_modules();
       
  3099 		if ( in_array($mod, $mods) )
       
  3100 			return true;
       
  3101 	} elseif ( function_exists('phpinfo') ) {
       
  3102 			ob_start();
       
  3103 			phpinfo(8);
       
  3104 			$phpinfo = ob_get_clean();
       
  3105 			if ( false !== strpos($phpinfo, $mod) )
       
  3106 				return true;
       
  3107 	}
       
  3108 	return $default;
       
  3109 }
       
  3110 
       
  3111 /**
       
  3112  * Check if IIS 7+ supports pretty permalinks.
       
  3113  *
       
  3114  * @since 2.8.0
       
  3115  *
       
  3116  * @return bool
       
  3117  */
       
  3118 function iis7_supports_permalinks() {
       
  3119 	global $is_iis7;
       
  3120 
       
  3121 	$supports_permalinks = false;
       
  3122 	if ( $is_iis7 ) {
       
  3123 		/* First we check if the DOMDocument class exists. If it does not exist, then we cannot
       
  3124 		 * easily update the xml configuration file, hence we just bail out and tell user that
       
  3125 		 * pretty permalinks cannot be used.
       
  3126 		 *
       
  3127 		 * Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the web site. When
       
  3128 		 * URL Rewrite 1.1 is loaded it always sets a server variable called 'IIS_UrlRewriteModule'.
       
  3129 		 * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
       
  3130 		 * via ISAPI then pretty permalinks will not work.
       
  3131 		 */
       
  3132 		$supports_permalinks = class_exists('DOMDocument') && isset($_SERVER['IIS_UrlRewriteModule']) && ( php_sapi_name() == 'cgi-fcgi' );
       
  3133 	}
       
  3134 
       
  3135 	return apply_filters('iis7_supports_permalinks', $supports_permalinks);
       
  3136 }
       
  3137 
       
  3138 /**
       
  3139  * File validates against allowed set of defined rules.
       
  3140  *
       
  3141  * A return value of '1' means that the $file contains either '..' or './'. A
       
  3142  * return value of '2' means that the $file contains ':' after the first
       
  3143  * character. A return value of '3' means that the file is not in the allowed
       
  3144  * files list.
       
  3145  *
       
  3146  * @since 1.2.0
       
  3147  *
       
  3148  * @param string $file File path.
       
  3149  * @param array $allowed_files List of allowed files.
       
  3150  * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
       
  3151  */
       
  3152 function validate_file( $file, $allowed_files = '' ) {
       
  3153 	if ( false !== strpos( $file, '..' ) )
       
  3154 		return 1;
       
  3155 
       
  3156 	if ( false !== strpos( $file, './' ) )
       
  3157 		return 1;
       
  3158 
       
  3159 	if ( ! empty( $allowed_files ) && ! in_array( $file, $allowed_files ) )
       
  3160 		return 3;
       
  3161 
       
  3162 	if (':' == substr( $file, 1, 1 ) )
       
  3163 		return 2;
       
  3164 
       
  3165 	return 0;
       
  3166 }
       
  3167 
       
  3168 /**
       
  3169  * Determine if SSL is used.
       
  3170  *
       
  3171  * @since 2.6.0
       
  3172  *
       
  3173  * @return bool True if SSL, false if not used.
       
  3174  */
       
  3175 function is_ssl() {
       
  3176 	if ( isset($_SERVER['HTTPS']) ) {
       
  3177 		if ( 'on' == strtolower($_SERVER['HTTPS']) )
       
  3178 			return true;
       
  3179 		if ( '1' == $_SERVER['HTTPS'] )
       
  3180 			return true;
       
  3181 	} elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
       
  3182 		return true;
       
  3183 	}
       
  3184 	return false;
       
  3185 }
       
  3186 
       
  3187 /**
       
  3188  * Whether SSL login should be forced.
       
  3189  *
       
  3190  * @since 2.6.0
       
  3191  *
       
  3192  * @param string|bool $force Optional.
       
  3193  * @return bool True if forced, false if not forced.
       
  3194  */
       
  3195 function force_ssl_login( $force = null ) {
       
  3196 	static $forced = false;
       
  3197 
       
  3198 	if ( !is_null( $force ) ) {
       
  3199 		$old_forced = $forced;
       
  3200 		$forced = $force;
       
  3201 		return $old_forced;
       
  3202 	}
       
  3203 
       
  3204 	return $forced;
       
  3205 }
       
  3206 
       
  3207 /**
       
  3208  * Whether to force SSL used for the Administration Screens.
       
  3209  *
       
  3210  * @since 2.6.0
       
  3211  *
       
  3212  * @param string|bool $force
       
  3213  * @return bool True if forced, false if not forced.
       
  3214  */
       
  3215 function force_ssl_admin( $force = null ) {
       
  3216 	static $forced = false;
       
  3217 
       
  3218 	if ( !is_null( $force ) ) {
       
  3219 		$old_forced = $forced;
       
  3220 		$forced = $force;
       
  3221 		return $old_forced;
       
  3222 	}
       
  3223 
       
  3224 	return $forced;
       
  3225 }
       
  3226 
       
  3227 /**
       
  3228  * Guess the URL for the site.
       
  3229  *
       
  3230  * Will remove wp-admin links to retrieve only return URLs not in the wp-admin
       
  3231  * directory.
       
  3232  *
       
  3233  * @since 2.6.0
       
  3234  *
       
  3235  * @return string
       
  3236  */
       
  3237 function wp_guess_url() {
       
  3238 	if ( defined('WP_SITEURL') && '' != WP_SITEURL ) {
       
  3239 		$url = WP_SITEURL;
       
  3240 	} else {
       
  3241 		$abspath_fix = str_replace( '\\', '/', ABSPATH );
       
  3242 		$script_filename_dir = dirname( $_SERVER['SCRIPT_FILENAME'] );
       
  3243 
       
  3244 		// The request is for the admin
       
  3245 		if ( strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) !== false || strpos( $_SERVER['REQUEST_URI'], 'wp-login.php' ) !== false ) {
       
  3246 			$path = preg_replace( '#/(wp-admin/.*|wp-login.php)#i', '', $_SERVER['REQUEST_URI'] );
       
  3247 
       
  3248 		// The request is for a file in ABSPATH
       
  3249 		} elseif ( $script_filename_dir . '/' == $abspath_fix ) {
       
  3250 			// Strip off any file/query params in the path
       
  3251 			$path = preg_replace( '#/[^/]*$#i', '', $_SERVER['PHP_SELF'] );
       
  3252 
       
  3253 		} else {
       
  3254 			if ( false !== strpos( $_SERVER['SCRIPT_FILENAME'], $abspath_fix ) ) {
       
  3255 				// Request is hitting a file inside ABSPATH
       
  3256 				$directory = str_replace( ABSPATH, '', $script_filename_dir );
       
  3257 				// Strip off the sub directory, and any file/query paramss
       
  3258 				$path = preg_replace( '#/' . preg_quote( $directory, '#' ) . '/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] );
       
  3259 			} elseif ( false !== strpos( $abspath_fix, $script_filename_dir ) ) {
       
  3260 				// Request is hitting a file above ABSPATH
       
  3261 				$subdirectory = str_replace( $script_filename_dir, '', $abspath_fix );
       
  3262 				// Strip off any file/query params from the path, appending the sub directory to the install
       
  3263 				$path = preg_replace( '#/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] ) . $subdirectory;
       
  3264 			} else {
       
  3265 				$path = $_SERVER['REQUEST_URI'];
       
  3266 			}
       
  3267 		}
       
  3268 
       
  3269 		$schema = is_ssl() ? 'https://' : 'http://'; // set_url_scheme() is not defined yet
       
  3270 		$url = $schema . $_SERVER['HTTP_HOST'] . $path;
       
  3271 	}
       
  3272 
       
  3273 	return rtrim($url, '/');
       
  3274 }
       
  3275 
       
  3276 /**
       
  3277  * Temporarily suspend cache additions.
       
  3278  *
       
  3279  * Stops more data being added to the cache, but still allows cache retrieval.
       
  3280  * This is useful for actions, such as imports, when a lot of data would otherwise
       
  3281  * be almost uselessly added to the cache.
       
  3282  *
       
  3283  * Suspension lasts for a single page load at most. Remember to call this
       
  3284  * function again if you wish to re-enable cache adds earlier.
       
  3285  *
       
  3286  * @since 3.3.0
       
  3287  *
       
  3288  * @param bool $suspend Optional. Suspends additions if true, re-enables them if false.
       
  3289  * @return bool The current suspend setting
       
  3290  */
       
  3291 function wp_suspend_cache_addition( $suspend = null ) {
       
  3292 	static $_suspend = false;
       
  3293 
       
  3294 	if ( is_bool( $suspend ) )
       
  3295 		$_suspend = $suspend;
       
  3296 
       
  3297 	return $_suspend;
       
  3298 }
       
  3299 
       
  3300 /**
       
  3301  * Suspend cache invalidation.
       
  3302  *
       
  3303  * Turns cache invalidation on and off. Useful during imports where you don't wont to do invalidations
       
  3304  * every time a post is inserted. Callers must be sure that what they are doing won't lead to an inconsistent
       
  3305  * cache when invalidation is suspended.
       
  3306  *
       
  3307  * @since 2.7.0
       
  3308  *
       
  3309  * @param bool $suspend Whether to suspend or enable cache invalidation
       
  3310  * @return bool The current suspend setting
       
  3311  */
       
  3312 function wp_suspend_cache_invalidation($suspend = true) {
       
  3313 	global $_wp_suspend_cache_invalidation;
       
  3314 
       
  3315 	$current_suspend = $_wp_suspend_cache_invalidation;
       
  3316 	$_wp_suspend_cache_invalidation = $suspend;
       
  3317 	return $current_suspend;
       
  3318 }
       
  3319 
       
  3320 /**
       
  3321  * Whether a site is the main site of the current network.
       
  3322  *
       
  3323  * @since 3.0.0
       
  3324  *
       
  3325  * @param int $site_id Optional. Site ID to test. Defaults to current site.
       
  3326  * @return bool True if $site_id is the main site of the network, or if not running multisite.
       
  3327  */
       
  3328 function is_main_site( $site_id = null ) {
       
  3329 	// This is the current network's information; 'site' is old terminology.
       
  3330 	global $current_site;
       
  3331 
       
  3332 	if ( ! is_multisite() )
       
  3333 		return true;
       
  3334 
       
  3335 	if ( ! $site_id )
       
  3336 		$site_id = get_current_blog_id();
       
  3337 
       
  3338 	return (int) $site_id === (int) $current_site->blog_id;
       
  3339 }
       
  3340 
       
  3341 /**
       
  3342  * Whether a network is the main network of the multisite install.
       
  3343  *
       
  3344  * @since 3.7.0
       
  3345  *
       
  3346  * @param int $network_id Optional. Network ID to test. Defaults to current network.
       
  3347  * @return bool True if $network_id is the main network, or if not running multisite.
       
  3348  */
       
  3349 function is_main_network( $network_id = null ) {
       
  3350 	global $current_site, $wpdb;
       
  3351 
       
  3352 	if ( ! is_multisite() )
       
  3353 		return true;
       
  3354 
       
  3355 	$current_network_id = (int) $current_site->id;
       
  3356 
       
  3357 	if ( ! $network_id )
       
  3358 		$network_id = $current_network_id;
       
  3359 	$network_id = (int) $network_id;
       
  3360 
       
  3361 	if ( defined( 'PRIMARY_NETWORK_ID' ) )
       
  3362 		return $network_id === (int) PRIMARY_NETWORK_ID;
       
  3363 
       
  3364 	if ( 1 === $current_network_id )
       
  3365 		return $network_id === $current_network_id;
       
  3366 
       
  3367 	$primary_network_id = (int) wp_cache_get( 'primary_network_id', 'site-options' );
       
  3368 
       
  3369 	if ( $primary_network_id )
       
  3370 		return $network_id === $primary_network_id;
       
  3371 
       
  3372 	$primary_network_id = (int) $wpdb->get_var( "SELECT id FROM $wpdb->site ORDER BY id LIMIT 1" );
       
  3373 	wp_cache_add( 'primary_network_id', $primary_network_id, 'site-options' );
       
  3374 
       
  3375 	return $network_id === $primary_network_id;
       
  3376 }
       
  3377 
       
  3378 /**
       
  3379  * Whether global terms are enabled.
       
  3380  *
       
  3381  *
       
  3382  * @since 3.0.0
       
  3383  * @package WordPress
       
  3384  *
       
  3385  * @return bool True if multisite and global terms enabled
       
  3386  */
       
  3387 function global_terms_enabled() {
       
  3388 	if ( ! is_multisite() )
       
  3389 		return false;
       
  3390 
       
  3391 	static $global_terms = null;
       
  3392 	if ( is_null( $global_terms ) ) {
       
  3393 		$filter = apply_filters( 'global_terms_enabled', null );
       
  3394 		if ( ! is_null( $filter ) )
       
  3395 			$global_terms = (bool) $filter;
       
  3396 		else
       
  3397 			$global_terms = (bool) get_site_option( 'global_terms_enabled', false );
       
  3398 	}
       
  3399 	return $global_terms;
       
  3400 }
       
  3401 
       
  3402 /**
       
  3403  * gmt_offset modification for smart timezone handling.
       
  3404  *
       
  3405  * Overrides the gmt_offset option if we have a timezone_string available.
       
  3406  *
       
  3407  * @since 2.8.0
       
  3408  *
       
  3409  * @return float|bool
       
  3410  */
       
  3411 function wp_timezone_override_offset() {
       
  3412 	if ( !$timezone_string = get_option( 'timezone_string' ) ) {
       
  3413 		return false;
       
  3414 	}
       
  3415 
       
  3416 	$timezone_object = timezone_open( $timezone_string );
       
  3417 	$datetime_object = date_create();
       
  3418 	if ( false === $timezone_object || false === $datetime_object ) {
       
  3419 		return false;
       
  3420 	}
       
  3421 	return round( timezone_offset_get( $timezone_object, $datetime_object ) / HOUR_IN_SECONDS, 2 );
       
  3422 }
       
  3423 
       
  3424 /**
       
  3425  * Sort-helper for timezones.
       
  3426  *
       
  3427  * @since 2.9.0
       
  3428  *
       
  3429  * @param array $a
       
  3430  * @param array $b
       
  3431  * @return int
       
  3432  */
       
  3433 function _wp_timezone_choice_usort_callback( $a, $b ) {
       
  3434 	// Don't use translated versions of Etc
       
  3435 	if ( 'Etc' === $a['continent'] && 'Etc' === $b['continent'] ) {
       
  3436 		// Make the order of these more like the old dropdown
       
  3437 		if ( 'GMT+' === substr( $a['city'], 0, 4 ) && 'GMT+' === substr( $b['city'], 0, 4 ) ) {
       
  3438 			return -1 * ( strnatcasecmp( $a['city'], $b['city'] ) );
       
  3439 		}
       
  3440 		if ( 'UTC' === $a['city'] ) {
       
  3441 			if ( 'GMT+' === substr( $b['city'], 0, 4 ) ) {
       
  3442 				return 1;
       
  3443 			}
       
  3444 			return -1;
       
  3445 		}
       
  3446 		if ( 'UTC' === $b['city'] ) {
       
  3447 			if ( 'GMT+' === substr( $a['city'], 0, 4 ) ) {
       
  3448 				return -1;
       
  3449 			}
       
  3450 			return 1;
       
  3451 		}
       
  3452 		return strnatcasecmp( $a['city'], $b['city'] );
       
  3453 	}
       
  3454 	if ( $a['t_continent'] == $b['t_continent'] ) {
       
  3455 		if ( $a['t_city'] == $b['t_city'] ) {
       
  3456 			return strnatcasecmp( $a['t_subcity'], $b['t_subcity'] );
       
  3457 		}
       
  3458 		return strnatcasecmp( $a['t_city'], $b['t_city'] );
       
  3459 	} else {
       
  3460 		// Force Etc to the bottom of the list
       
  3461 		if ( 'Etc' === $a['continent'] ) {
       
  3462 			return 1;
       
  3463 		}
       
  3464 		if ( 'Etc' === $b['continent'] ) {
       
  3465 			return -1;
       
  3466 		}
       
  3467 		return strnatcasecmp( $a['t_continent'], $b['t_continent'] );
       
  3468 	}
       
  3469 }
       
  3470 
       
  3471 /**
       
  3472  * Gives a nicely formatted list of timezone strings.
       
  3473  *
       
  3474  * @since 2.9.0
       
  3475  *
       
  3476  * @param string $selected_zone Selected Zone
       
  3477  * @return string
       
  3478  */
       
  3479 function wp_timezone_choice( $selected_zone ) {
       
  3480 	static $mo_loaded = false;
       
  3481 
       
  3482 	$continents = array( 'Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
       
  3483 
       
  3484 	// Load translations for continents and cities
       
  3485 	if ( !$mo_loaded ) {
       
  3486 		$locale = get_locale();
       
  3487 		$mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
       
  3488 		load_textdomain( 'continents-cities', $mofile );
       
  3489 		$mo_loaded = true;
       
  3490 	}
       
  3491 
       
  3492 	$zonen = array();
       
  3493 	foreach ( timezone_identifiers_list() as $zone ) {
       
  3494 		$zone = explode( '/', $zone );
       
  3495 		if ( !in_array( $zone[0], $continents ) ) {
       
  3496 			continue;
       
  3497 		}
       
  3498 
       
  3499 		// This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
       
  3500 		$exists = array(
       
  3501 			0 => ( isset( $zone[0] ) && $zone[0] ),
       
  3502 			1 => ( isset( $zone[1] ) && $zone[1] ),
       
  3503 			2 => ( isset( $zone[2] ) && $zone[2] ),
       
  3504 		);
       
  3505 		$exists[3] = ( $exists[0] && 'Etc' !== $zone[0] );
       
  3506 		$exists[4] = ( $exists[1] && $exists[3] );
       
  3507 		$exists[5] = ( $exists[2] && $exists[3] );
       
  3508 
       
  3509 		$zonen[] = array(
       
  3510 			'continent'   => ( $exists[0] ? $zone[0] : '' ),
       
  3511 			'city'        => ( $exists[1] ? $zone[1] : '' ),
       
  3512 			'subcity'     => ( $exists[2] ? $zone[2] : '' ),
       
  3513 			't_continent' => ( $exists[3] ? translate( str_replace( '_', ' ', $zone[0] ), 'continents-cities' ) : '' ),
       
  3514 			't_city'      => ( $exists[4] ? translate( str_replace( '_', ' ', $zone[1] ), 'continents-cities' ) : '' ),
       
  3515 			't_subcity'   => ( $exists[5] ? translate( str_replace( '_', ' ', $zone[2] ), 'continents-cities' ) : '' )
       
  3516 		);
       
  3517 	}
       
  3518 	usort( $zonen, '_wp_timezone_choice_usort_callback' );
       
  3519 
       
  3520 	$structure = array();
       
  3521 
       
  3522 	if ( empty( $selected_zone ) ) {
       
  3523 		$structure[] = '<option selected="selected" value="">' . __( 'Select a city' ) . '</option>';
       
  3524 	}
       
  3525 
       
  3526 	foreach ( $zonen as $key => $zone ) {
       
  3527 		// Build value in an array to join later
       
  3528 		$value = array( $zone['continent'] );
       
  3529 
       
  3530 		if ( empty( $zone['city'] ) ) {
       
  3531 			// It's at the continent level (generally won't happen)
       
  3532 			$display = $zone['t_continent'];
       
  3533 		} else {
       
  3534 			// It's inside a continent group
       
  3535 
       
  3536 			// Continent optgroup
       
  3537 			if ( !isset( $zonen[$key - 1] ) || $zonen[$key - 1]['continent'] !== $zone['continent'] ) {
       
  3538 				$label = $zone['t_continent'];
       
  3539 				$structure[] = '<optgroup label="'. esc_attr( $label ) .'">';
       
  3540 			}
       
  3541 
       
  3542 			// Add the city to the value
       
  3543 			$value[] = $zone['city'];
       
  3544 
       
  3545 			$display = $zone['t_city'];
       
  3546 			if ( !empty( $zone['subcity'] ) ) {
       
  3547 				// Add the subcity to the value
       
  3548 				$value[] = $zone['subcity'];
       
  3549 				$display .= ' - ' . $zone['t_subcity'];
       
  3550 			}
       
  3551 		}
       
  3552 
       
  3553 		// Build the value
       
  3554 		$value = join( '/', $value );
       
  3555 		$selected = '';
       
  3556 		if ( $value === $selected_zone ) {
       
  3557 			$selected = 'selected="selected" ';
       
  3558 		}
       
  3559 		$structure[] = '<option ' . $selected . 'value="' . esc_attr( $value ) . '">' . esc_html( $display ) . "</option>";
       
  3560 
       
  3561 		// Close continent optgroup
       
  3562 		if ( !empty( $zone['city'] ) && ( !isset($zonen[$key + 1]) || (isset( $zonen[$key + 1] ) && $zonen[$key + 1]['continent'] !== $zone['continent']) ) ) {
       
  3563 			$structure[] = '</optgroup>';
       
  3564 		}
       
  3565 	}
       
  3566 
       
  3567 	// Do UTC
       
  3568 	$structure[] = '<optgroup label="'. esc_attr__( 'UTC' ) .'">';
       
  3569 	$selected = '';
       
  3570 	if ( 'UTC' === $selected_zone )
       
  3571 		$selected = 'selected="selected" ';
       
  3572 	$structure[] = '<option ' . $selected . 'value="' . esc_attr( 'UTC' ) . '">' . __('UTC') . '</option>';
       
  3573 	$structure[] = '</optgroup>';
       
  3574 
       
  3575 	// Do manual UTC offsets
       
  3576 	$structure[] = '<optgroup label="'. esc_attr__( 'Manual Offsets' ) .'">';
       
  3577 	$offset_range = array (-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5,
       
  3578 		0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
       
  3579 	foreach ( $offset_range as $offset ) {
       
  3580 		if ( 0 <= $offset )
       
  3581 			$offset_name = '+' . $offset;
       
  3582 		else
       
  3583 			$offset_name = (string) $offset;
       
  3584 
       
  3585 		$offset_value = $offset_name;
       
  3586 		$offset_name = str_replace(array('.25','.5','.75'), array(':15',':30',':45'), $offset_name);
       
  3587 		$offset_name = 'UTC' . $offset_name;
       
  3588 		$offset_value = 'UTC' . $offset_value;
       
  3589 		$selected = '';
       
  3590 		if ( $offset_value === $selected_zone )
       
  3591 			$selected = 'selected="selected" ';
       
  3592 		$structure[] = '<option ' . $selected . 'value="' . esc_attr( $offset_value ) . '">' . esc_html( $offset_name ) . "</option>";
       
  3593 
       
  3594 	}
       
  3595 	$structure[] = '</optgroup>';
       
  3596 
       
  3597 	return join( "\n", $structure );
       
  3598 }
       
  3599 
       
  3600 /**
       
  3601  * Strip close comment and close php tags from file headers used by WP.
       
  3602  * See http://core.trac.wordpress.org/ticket/8497
       
  3603  *
       
  3604  * @since 2.8.0
       
  3605  *
       
  3606  * @param string $str
       
  3607  * @return string
       
  3608  */
       
  3609 function _cleanup_header_comment($str) {
       
  3610 	return trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $str));
       
  3611 }
       
  3612 
       
  3613 /**
       
  3614  * Permanently deletes posts, pages, attachments, and comments which have been in the trash for EMPTY_TRASH_DAYS.
       
  3615  *
       
  3616  * @since 2.9.0
       
  3617  */
       
  3618 function wp_scheduled_delete() {
       
  3619 	global $wpdb;
       
  3620 
       
  3621 	$delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
       
  3622 
       
  3623 	$posts_to_delete = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A);
       
  3624 
       
  3625 	foreach ( (array) $posts_to_delete as $post ) {
       
  3626 		$post_id = (int) $post['post_id'];
       
  3627 		if ( !$post_id )
       
  3628 			continue;
       
  3629 
       
  3630 		$del_post = get_post($post_id);
       
  3631 
       
  3632 		if ( !$del_post || 'trash' != $del_post->post_status ) {
       
  3633 			delete_post_meta($post_id, '_wp_trash_meta_status');
       
  3634 			delete_post_meta($post_id, '_wp_trash_meta_time');
       
  3635 		} else {
       
  3636 			wp_delete_post($post_id);
       
  3637 		}
       
  3638 	}
       
  3639 
       
  3640 	$comments_to_delete = $wpdb->get_results($wpdb->prepare("SELECT comment_id FROM $wpdb->commentmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A);
       
  3641 
       
  3642 	foreach ( (array) $comments_to_delete as $comment ) {
       
  3643 		$comment_id = (int) $comment['comment_id'];
       
  3644 		if ( !$comment_id )
       
  3645 			continue;
       
  3646 
       
  3647 		$del_comment = get_comment($comment_id);
       
  3648 
       
  3649 		if ( !$del_comment || 'trash' != $del_comment->comment_approved ) {
       
  3650 			delete_comment_meta($comment_id, '_wp_trash_meta_time');
       
  3651 			delete_comment_meta($comment_id, '_wp_trash_meta_status');
       
  3652 		} else {
       
  3653 			wp_delete_comment($comment_id);
       
  3654 		}
       
  3655 	}
       
  3656 }
       
  3657 
       
  3658 /**
       
  3659  * Retrieve metadata from a file.
       
  3660  *
       
  3661  * Searches for metadata in the first 8kiB of a file, such as a plugin or theme.
       
  3662  * Each piece of metadata must be on its own line. Fields can not span multiple
       
  3663  * lines, the value will get cut at the end of the first line.
       
  3664  *
       
  3665  * If the file data is not within that first 8kiB, then the author should correct
       
  3666  * their plugin file and move the data headers to the top.
       
  3667  *
       
  3668  * @see http://codex.wordpress.org/File_Header
       
  3669  *
       
  3670  * @since 2.9.0
       
  3671  * @param string $file Path to the file
       
  3672  * @param array $default_headers List of headers, in the format array('HeaderKey' => 'Header Name')
       
  3673  * @param string $context If specified adds filter hook "extra_{$context}_headers"
       
  3674  */
       
  3675 function get_file_data( $file, $default_headers, $context = '' ) {
       
  3676 	// We don't need to write to the file, so just open for reading.
       
  3677 	$fp = fopen( $file, 'r' );
       
  3678 
       
  3679 	// Pull only the first 8kiB of the file in.
       
  3680 	$file_data = fread( $fp, 8192 );
       
  3681 
       
  3682 	// PHP will close file handle, but we are good citizens.
       
  3683 	fclose( $fp );
       
  3684 
       
  3685 	// Make sure we catch CR-only line endings.
       
  3686 	$file_data = str_replace( "\r", "\n", $file_data );
       
  3687 
       
  3688 	if ( $context && $extra_headers = apply_filters( "extra_{$context}_headers", array() ) ) {
       
  3689 		$extra_headers = array_combine( $extra_headers, $extra_headers ); // keys equal values
       
  3690 		$all_headers = array_merge( $extra_headers, (array) $default_headers );
       
  3691 	} else {
       
  3692 		$all_headers = $default_headers;
       
  3693 	}
       
  3694 
       
  3695 	foreach ( $all_headers as $field => $regex ) {
       
  3696 		if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && $match[1] )
       
  3697 			$all_headers[ $field ] = _cleanup_header_comment( $match[1] );
       
  3698 		else
       
  3699 			$all_headers[ $field ] = '';
       
  3700 	}
       
  3701 
       
  3702 	return $all_headers;
       
  3703 }
       
  3704 
       
  3705 /**
       
  3706  * Returns true.
       
  3707  *
       
  3708  * Useful for returning true to filters easily.
       
  3709  *
       
  3710  * @since 3.0.0
       
  3711  * @see __return_false()
       
  3712  * @return bool true
       
  3713  */
       
  3714 function __return_true() {
       
  3715 	return true;
       
  3716 }
       
  3717 
       
  3718 /**
       
  3719  * Returns false.
       
  3720  *
       
  3721  * Useful for returning false to filters easily.
       
  3722  *
       
  3723  * @since 3.0.0
       
  3724  * @see __return_true()
       
  3725  * @return bool false
       
  3726  */
       
  3727 function __return_false() {
       
  3728 	return false;
       
  3729 }
       
  3730 
       
  3731 /**
       
  3732  * Returns 0.
       
  3733  *
       
  3734  * Useful for returning 0 to filters easily.
       
  3735  *
       
  3736  * @since 3.0.0
       
  3737  * @see __return_zero()
       
  3738  * @return int 0
       
  3739  */
       
  3740 function __return_zero() {
       
  3741 	return 0;
       
  3742 }
       
  3743 
       
  3744 /**
       
  3745  * Returns an empty array.
       
  3746  *
       
  3747  * Useful for returning an empty array to filters easily.
       
  3748  *
       
  3749  * @since 3.0.0
       
  3750  * @see __return_zero()
       
  3751  * @return array Empty array
       
  3752  */
       
  3753 function __return_empty_array() {
       
  3754 	return array();
       
  3755 }
       
  3756 
       
  3757 /**
       
  3758  * Returns null.
       
  3759  *
       
  3760  * Useful for returning null to filters easily.
       
  3761  *
       
  3762  * @since 3.4.0
       
  3763  * @return null
       
  3764  */
       
  3765 function __return_null() {
       
  3766 	return null;
       
  3767 }
       
  3768 
       
  3769 /**
       
  3770  * Returns an empty string.
       
  3771  *
       
  3772  * Useful for returning an empty string to filters easily.
       
  3773  *
       
  3774  * @since 3.7.0
       
  3775  * @see __return_null()
       
  3776  * @return string Empty string
       
  3777  */
       
  3778 function __return_empty_string() {
       
  3779 	return '';
       
  3780 }
       
  3781 
       
  3782 /**
       
  3783  * Send a HTTP header to disable content type sniffing in browsers which support it.
       
  3784  *
       
  3785  * @link http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
       
  3786  * @link http://src.chromium.org/viewvc/chrome?view=rev&revision=6985
       
  3787  *
       
  3788  * @since 3.0.0
       
  3789  * @return none
       
  3790  */
       
  3791 function send_nosniff_header() {
       
  3792 	@header( 'X-Content-Type-Options: nosniff' );
       
  3793 }
       
  3794 
       
  3795 /**
       
  3796  * Returns a MySQL expression for selecting the week number based on the start_of_week option.
       
  3797  *
       
  3798  * @internal
       
  3799  * @since 3.0.0
       
  3800  * @param string $column
       
  3801  * @return string
       
  3802  */
       
  3803 function _wp_mysql_week( $column ) {
       
  3804 	switch ( $start_of_week = (int) get_option( 'start_of_week' ) ) {
       
  3805 	default :
       
  3806 	case 0 :
       
  3807 		return "WEEK( $column, 0 )";
       
  3808 	case 1 :
       
  3809 		return "WEEK( $column, 1 )";
       
  3810 	case 2 :
       
  3811 	case 3 :
       
  3812 	case 4 :
       
  3813 	case 5 :
       
  3814 	case 6 :
       
  3815 		return "WEEK( DATE_SUB( $column, INTERVAL $start_of_week DAY ), 0 )";
       
  3816 	}
       
  3817 }
       
  3818 
       
  3819 /**
       
  3820  * Finds hierarchy loops using a callback function that maps object IDs to parent IDs.
       
  3821  *
       
  3822  * @since 3.1.0
       
  3823  * @access private
       
  3824  *
       
  3825  * @param callback $callback function that accepts ( ID, $callback_args ) and outputs parent_ID
       
  3826  * @param int $start The ID to start the loop check at
       
  3827  * @param int $start_parent the parent_ID of $start to use instead of calling $callback( $start ). Use null to always use $callback
       
  3828  * @param array $callback_args optional additional arguments to send to $callback
       
  3829  * @return array IDs of all members of loop
       
  3830  */
       
  3831 function wp_find_hierarchy_loop( $callback, $start, $start_parent, $callback_args = array() ) {
       
  3832 	$override = is_null( $start_parent ) ? array() : array( $start => $start_parent );
       
  3833 
       
  3834 	if ( !$arbitrary_loop_member = wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override, $callback_args ) )
       
  3835 		return array();
       
  3836 
       
  3837 	return wp_find_hierarchy_loop_tortoise_hare( $callback, $arbitrary_loop_member, $override, $callback_args, true );
       
  3838 }
       
  3839 
       
  3840 /**
       
  3841  * Uses the "The Tortoise and the Hare" algorithm to detect loops.
       
  3842  *
       
  3843  * For every step of the algorithm, the hare takes two steps and the tortoise one.
       
  3844  * If the hare ever laps the tortoise, there must be a loop.
       
  3845  *
       
  3846  * @since 3.1.0
       
  3847  * @access private
       
  3848  *
       
  3849  * @param callback $callback function that accepts ( ID, callback_arg, ... ) and outputs parent_ID
       
  3850  * @param int $start The ID to start the loop check at
       
  3851  * @param array $override an array of ( ID => parent_ID, ... ) to use instead of $callback
       
  3852  * @param array $callback_args optional additional arguments to send to $callback
       
  3853  * @param bool $_return_loop Return loop members or just detect presence of loop?
       
  3854  *             Only set to true if you already know the given $start is part of a loop
       
  3855  *             (otherwise the returned array might include branches)
       
  3856  * @return mixed scalar ID of some arbitrary member of the loop, or array of IDs of all members of loop if $_return_loop
       
  3857  */
       
  3858 function wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override = array(), $callback_args = array(), $_return_loop = false ) {
       
  3859 	$tortoise = $hare = $evanescent_hare = $start;
       
  3860 	$return = array();
       
  3861 
       
  3862 	// Set evanescent_hare to one past hare
       
  3863 	// Increment hare two steps
       
  3864 	while (
       
  3865 		$tortoise
       
  3866 	&&
       
  3867 		( $evanescent_hare = isset( $override[$hare] ) ? $override[$hare] : call_user_func_array( $callback, array_merge( array( $hare ), $callback_args ) ) )
       
  3868 	&&
       
  3869 		( $hare = isset( $override[$evanescent_hare] ) ? $override[$evanescent_hare] : call_user_func_array( $callback, array_merge( array( $evanescent_hare ), $callback_args ) ) )
       
  3870 	) {
       
  3871 		if ( $_return_loop )
       
  3872 			$return[$tortoise] = $return[$evanescent_hare] = $return[$hare] = true;
       
  3873 
       
  3874 		// tortoise got lapped - must be a loop
       
  3875 		if ( $tortoise == $evanescent_hare || $tortoise == $hare )
       
  3876 			return $_return_loop ? $return : $tortoise;
       
  3877 
       
  3878 		// Increment tortoise by one step
       
  3879 		$tortoise = isset( $override[$tortoise] ) ? $override[$tortoise] : call_user_func_array( $callback, array_merge( array( $tortoise ), $callback_args ) );
       
  3880 	}
       
  3881 
       
  3882 	return false;
       
  3883 }
       
  3884 
       
  3885 /**
       
  3886  * Send a HTTP header to limit rendering of pages to same origin iframes.
       
  3887  *
       
  3888  * @link https://developer.mozilla.org/en/the_x-frame-options_response_header
       
  3889  *
       
  3890  * @since 3.1.3
       
  3891  * @return none
       
  3892  */
       
  3893 function send_frame_options_header() {
       
  3894 	@header( 'X-Frame-Options: SAMEORIGIN' );
       
  3895 }
       
  3896 
       
  3897 /**
       
  3898  * Retrieve a list of protocols to allow in HTML attributes.
       
  3899  *
       
  3900  * @since 3.3.0
       
  3901  * @see wp_kses()
       
  3902  * @see esc_url()
       
  3903  *
       
  3904  * @return array Array of allowed protocols
       
  3905  */
       
  3906 function wp_allowed_protocols() {
       
  3907 	static $protocols;
       
  3908 
       
  3909 	if ( empty( $protocols ) ) {
       
  3910 		$protocols = array( 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp' );
       
  3911 		$protocols = apply_filters( 'kses_allowed_protocols', $protocols );
       
  3912 	}
       
  3913 
       
  3914 	return $protocols;
       
  3915 }
       
  3916 
       
  3917 /**
       
  3918  * Return a comma separated string of functions that have been called to get to the current point in code.
       
  3919  *
       
  3920  * @link http://core.trac.wordpress.org/ticket/19589
       
  3921  * @since 3.4
       
  3922  *
       
  3923  * @param string $ignore_class A class to ignore all function calls within - useful when you want to just give info about the callee
       
  3924  * @param int $skip_frames A number of stack frames to skip - useful for unwinding back to the source of the issue
       
  3925  * @param bool $pretty Whether or not you want a comma separated string or raw array returned
       
  3926  * @return string|array Either a string containing a reversed comma separated trace or an array of individual calls.
       
  3927  */
       
  3928 function wp_debug_backtrace_summary( $ignore_class = null, $skip_frames = 0, $pretty = true ) {
       
  3929 	if ( version_compare( PHP_VERSION, '5.2.5', '>=' ) )
       
  3930 		$trace = debug_backtrace( false );
       
  3931 	else
       
  3932 		$trace = debug_backtrace();
       
  3933 
       
  3934 	$caller = array();
       
  3935 	$check_class = ! is_null( $ignore_class );
       
  3936 	$skip_frames++; // skip this function
       
  3937 
       
  3938 	foreach ( $trace as $call ) {
       
  3939 		if ( $skip_frames > 0 ) {
       
  3940 			$skip_frames--;
       
  3941 		} elseif ( isset( $call['class'] ) ) {
       
  3942 			if ( $check_class && $ignore_class == $call['class'] )
       
  3943 				continue; // Filter out calls
       
  3944 
       
  3945 			$caller[] = "{$call['class']}{$call['type']}{$call['function']}";
       
  3946 		} else {
       
  3947 			if ( in_array( $call['function'], array( 'do_action', 'apply_filters' ) ) ) {
       
  3948 				$caller[] = "{$call['function']}('{$call['args'][0]}')";
       
  3949 			} elseif ( in_array( $call['function'], array( 'include', 'include_once', 'require', 'require_once' ) ) ) {
       
  3950 				$caller[] = $call['function'] . "('" . str_replace( array( WP_CONTENT_DIR, ABSPATH ) , '', $call['args'][0] ) . "')";
       
  3951 			} else {
       
  3952 				$caller[] = $call['function'];
       
  3953 			}
       
  3954 		}
       
  3955 	}
       
  3956 	if ( $pretty )
       
  3957 		return join( ', ', array_reverse( $caller ) );
       
  3958 	else
       
  3959 		return $caller;
       
  3960 }
       
  3961 
       
  3962 /**
       
  3963  * Retrieve ids that are not already present in the cache
       
  3964  *
       
  3965  * @since 3.4.0
       
  3966  *
       
  3967  * @param array $object_ids ID list
       
  3968  * @param string $cache_key The cache bucket to check against
       
  3969  *
       
  3970  * @return array
       
  3971  */
       
  3972 function _get_non_cached_ids( $object_ids, $cache_key ) {
       
  3973 	$clean = array();
       
  3974 	foreach ( $object_ids as $id ) {
       
  3975 		$id = (int) $id;
       
  3976 		if ( !wp_cache_get( $id, $cache_key ) ) {
       
  3977 			$clean[] = $id;
       
  3978 		}
       
  3979 	}
       
  3980 
       
  3981 	return $clean;
       
  3982 }
       
  3983 
       
  3984 /**
       
  3985  * Test if the current device has the capability to upload files.
       
  3986  *
       
  3987  * @since 3.4.0
       
  3988  * @access private
       
  3989  *
       
  3990  * @return bool true|false
       
  3991  */
       
  3992 function _device_can_upload() {
       
  3993 	if ( ! wp_is_mobile() )
       
  3994 		return true;
       
  3995 
       
  3996 	$ua = $_SERVER['HTTP_USER_AGENT'];
       
  3997 
       
  3998 	if ( strpos($ua, 'iPhone') !== false
       
  3999 		|| strpos($ua, 'iPad') !== false
       
  4000 		|| strpos($ua, 'iPod') !== false ) {
       
  4001 			return preg_match( '#OS ([\d_]+) like Mac OS X#', $ua, $version ) && version_compare( $version[1], '6', '>=' );
       
  4002 	}
       
  4003 
       
  4004 	return true;
       
  4005 }
       
  4006 
       
  4007 /**
       
  4008  * Test if a given path is a stream URL
       
  4009  *
       
  4010  * @param string $path The resource path or URL
       
  4011  * @return bool True if the path is a stream URL
       
  4012  */
       
  4013 function wp_is_stream( $path ) {
       
  4014 	$wrappers = stream_get_wrappers();
       
  4015 	$wrappers_re = '(' . join('|', $wrappers) . ')';
       
  4016 
       
  4017 	return preg_match( "!^$wrappers_re://!", $path ) === 1;
       
  4018 }
       
  4019 
       
  4020 /**
       
  4021  * Test if the supplied date is valid for the Gregorian calendar
       
  4022  *
       
  4023  * @since 3.5.0
       
  4024  *
       
  4025  * @return bool true|false
       
  4026  */
       
  4027 function wp_checkdate( $month, $day, $year, $source_date ) {
       
  4028 	return apply_filters( 'wp_checkdate', checkdate( $month, $day, $year ), $source_date );
       
  4029 }
       
  4030 
       
  4031 /**
       
  4032  * Load the auth check for monitoring whether the user is still logged in.
       
  4033  *
       
  4034  * Can be disabled with remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' );
       
  4035  *
       
  4036  * This is disabled for certain screens where a login screen could cause an
       
  4037  * inconvenient interruption. A filter called wp_auth_check_load can be used
       
  4038  * for fine-grained control.
       
  4039  *
       
  4040  * @since 3.6.0
       
  4041  */
       
  4042 function wp_auth_check_load() {
       
  4043 	if ( ! is_admin() && ! is_user_logged_in() )
       
  4044 		return;
       
  4045 
       
  4046 	if ( defined( 'IFRAME_REQUEST' ) )
       
  4047 		return;
       
  4048 
       
  4049 	$screen = get_current_screen();
       
  4050 	$hidden = array( 'update', 'update-network', 'update-core', 'update-core-network', 'upgrade', 'upgrade-network', 'network' );
       
  4051 	$show = ! in_array( $screen->id, $hidden );
       
  4052 
       
  4053 	if ( apply_filters( 'wp_auth_check_load', $show, $screen ) ) {
       
  4054 		wp_enqueue_style( 'wp-auth-check' );
       
  4055 		wp_enqueue_script( 'wp-auth-check' );
       
  4056 
       
  4057 		add_action( 'admin_print_footer_scripts', 'wp_auth_check_html', 5 );
       
  4058 		add_action( 'wp_print_footer_scripts', 'wp_auth_check_html', 5 );
       
  4059 	}
       
  4060 }
       
  4061 
       
  4062 /**
       
  4063  * Output the HTML that shows the wp-login dialog when the user is no longer logged in.
       
  4064  *
       
  4065  * @since 3.6.0
       
  4066  */
       
  4067 function wp_auth_check_html() {
       
  4068 	$login_url = wp_login_url();
       
  4069 	$current_domain = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
       
  4070 	$same_domain = ( strpos( $login_url, $current_domain ) === 0 );
       
  4071 
       
  4072 	if ( $same_domain && force_ssl_login() && ! force_ssl_admin() )
       
  4073 		$same_domain = false;
       
  4074 
       
  4075 	// Let plugins change this if they know better.
       
  4076 	$same_domain = apply_filters( 'wp_auth_check_same_domain', $same_domain );
       
  4077 	$wrap_class = $same_domain ? 'hidden' : 'hidden fallback';
       
  4078 
       
  4079 	?>
       
  4080 	<div id="wp-auth-check-wrap" class="<?php echo $wrap_class; ?>">
       
  4081 	<div id="wp-auth-check-bg"></div>
       
  4082 	<div id="wp-auth-check">
       
  4083 	<div class="wp-auth-check-close" tabindex="0" title="<?php esc_attr_e('Close'); ?>"></div>
       
  4084 	<?php
       
  4085 
       
  4086 	if ( $same_domain ) {
       
  4087 		?>
       
  4088 		<div id="wp-auth-check-form" data-src="<?php echo esc_url( add_query_arg( array( 'interim-login' => 1 ), $login_url ) ); ?>"></div>
       
  4089 		<?php
       
  4090 	}
       
  4091 
       
  4092 	?>
       
  4093 	<div class="wp-auth-fallback">
       
  4094 		<p><b class="wp-auth-fallback-expired" tabindex="0"><?php _e('Session expired'); ?></b></p>
       
  4095 		<p><a href="<?php echo esc_url( $login_url ); ?>" target="_blank"><?php _e('Please log in again.'); ?></a>
       
  4096 		<?php _e('The login page will open in a new window. After logging in you can close it and return to this page.'); ?></p>
       
  4097 	</div>
       
  4098 	</div>
       
  4099 	</div>
       
  4100 	<?php
       
  4101 }
       
  4102 
       
  4103 /**
       
  4104  * Check whether a user is still logged in, for the heartbeat.
       
  4105  *
       
  4106  * Send a result that shows a log-in box if the user is no longer logged in,
       
  4107  * or if their cookie is within the grace period.
       
  4108  *
       
  4109  * @since 3.6.0
       
  4110  */
       
  4111 function wp_auth_check( $response, $data ) {
       
  4112 	$response['wp-auth-check'] = is_user_logged_in() && empty( $GLOBALS['login_grace_period'] );
       
  4113 	return $response;
       
  4114 }
       
  4115 
       
  4116 /**
       
  4117  * Return RegEx body to liberally match an opening HTML tag that:
       
  4118  * 1. Is self-closing or
       
  4119  * 2. Has no body but has a closing tag of the same name or
       
  4120  * 3. Contains a body and a closing tag of the same name
       
  4121  *
       
  4122  * Note: this RegEx does not balance inner tags and does not attempt to produce valid HTML
       
  4123  *
       
  4124  * @since 3.6.0
       
  4125  *
       
  4126  * @param string $tag An HTML tag name. Example: 'video'
       
  4127  * @return string
       
  4128  */
       
  4129 function get_tag_regex( $tag ) {
       
  4130 	if ( empty( $tag ) )
       
  4131 		return;
       
  4132 	return sprintf( '<%1$s[^<]*(?:>[\s\S]*<\/%1$s>|\s*\/>)', tag_escape( $tag ) );
       
  4133 }
       
  4134 
       
  4135 /**
       
  4136  * Return a canonical form of the provided charset appropriate for passing to PHP
       
  4137  * functions such as htmlspecialchars() and charset html attributes.
       
  4138  *
       
  4139  * @link http://core.trac.wordpress.org/ticket/23688
       
  4140  * @since 3.6.0
       
  4141  *
       
  4142  * @param string A charset name
       
  4143  * @return string The canonical form of the charset
       
  4144  */
       
  4145 function _canonical_charset( $charset ) {
       
  4146 	if ( 'UTF-8' === $charset || 'utf-8' === $charset || 'utf8' === $charset ||
       
  4147 		'UTF8' === $charset )
       
  4148 		return 'UTF-8';
       
  4149 
       
  4150 	if ( 'ISO-8859-1' === $charset || 'iso-8859-1' === $charset ||
       
  4151 		'iso8859-1' === $charset || 'ISO8859-1' === $charset )
       
  4152 		return 'ISO-8859-1';
       
  4153 
       
  4154 	return $charset;
       
  4155 }
       
  4156 
       
  4157 /**
       
  4158  * Sets the mbstring internal encoding to a binary safe encoding whne func_overload is enabled.
       
  4159  *
       
  4160  * When mbstring.func_overload is in use for multi-byte encodings, the results from strlen() and
       
  4161  * similar functions respect the utf8 characters, causing binary data to return incorrect lengths.
       
  4162  *
       
  4163  * This function overrides the mbstring encoding to a binary-safe encoding, and resets it to the
       
  4164  * users expected encoding afterwards through the `reset_mbstring_encoding` function.
       
  4165  *
       
  4166  * It is safe to recursively call this function, however each `mbstring_binary_safe_encoding()`
       
  4167  * call must be followed up with an equal number of `reset_mbstring_encoding()` calls.
       
  4168  *
       
  4169  * @see reset_mbstring_encoding()
       
  4170  *
       
  4171  * @since 3.7.0
       
  4172  *
       
  4173  * @param bool $reset Whether to reset the encoding back to a previously-set encoding.
       
  4174  */
       
  4175 function mbstring_binary_safe_encoding( $reset = false ) {
       
  4176 	static $encodings = array();
       
  4177 	static $overloaded = null;
       
  4178 
       
  4179 	if ( is_null( $overloaded ) )
       
  4180 		$overloaded = function_exists( 'mb_internal_encoding' ) && ( ini_get( 'mbstring.func_overload' ) & 2 );
       
  4181 
       
  4182 	if ( false === $overloaded )
       
  4183 		return;
       
  4184 
       
  4185 	if ( ! $reset ) {
       
  4186 		$encoding = mb_internal_encoding();
       
  4187 		array_push( $encodings, $encoding );
       
  4188 		mb_internal_encoding( 'ISO-8859-1' );
       
  4189 	}
       
  4190 
       
  4191 	if ( $reset && $encodings ) {
       
  4192 		$encoding = array_pop( $encodings );
       
  4193 		mb_internal_encoding( $encoding );
       
  4194 	}
       
  4195 }
       
  4196 
       
  4197 /**
       
  4198  * Resets the mbstring internal encoding to a users previously set encoding.
       
  4199  *
       
  4200  * @see mbstring_binary_safe_encoding()
       
  4201  *
       
  4202  * @since 3.7.0
       
  4203  */
       
  4204 function reset_mbstring_encoding() {
       
  4205 	mbstring_binary_safe_encoding( true );
       
  4206 }