wp/wp-includes/functions.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
    76  * take over the format for the date. If it isn't, then the date format string
    76  * take over the format for the date. If it isn't, then the date format string
    77  * will be used instead.
    77  * will be used instead.
    78  *
    78  *
    79  * @since 0.71
    79  * @since 0.71
    80  *
    80  *
       
    81  * @global WP_Locale $wp_locale
       
    82  *
    81  * @param string   $dateformatstring Format to display the date.
    83  * @param string   $dateformatstring Format to display the date.
    82  * @param bool|int $unixtimestamp    Optional. Unix timestamp. Default false.
    84  * @param bool|int $unixtimestamp    Optional. Unix timestamp. Default false.
    83  * @param bool     $gmt              Optional. Whether to use GMT timezone. Default false.
    85  * @param bool     $gmt              Optional. Whether to use GMT timezone. Default false.
    84  *
    86  *
    85  * @return string The date, translated if locale specifies it.
    87  * @return string The date, translated if locale specifies it.
    87 function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
    89 function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
    88 	global $wp_locale;
    90 	global $wp_locale;
    89 	$i = $unixtimestamp;
    91 	$i = $unixtimestamp;
    90 
    92 
    91 	if ( false === $i ) {
    93 	if ( false === $i ) {
    92 		if ( ! $gmt )
    94 		$i = current_time( 'timestamp', $gmt );
    93 			$i = current_time( 'timestamp' );
       
    94 		else
       
    95 			$i = time();
       
    96 		// we should not let date() interfere with our
       
    97 		// specially computed timestamp
       
    98 		$gmt = true;
       
    99 	}
    95 	}
   100 
    96 
   101 	/*
    97 	/*
   102 	 * Store original value for language with untypical grammars.
    98 	 * Store original value for language with untypical grammars.
   103 	 * See https://core.trac.wordpress.org/ticket/9396
    99 	 * See https://core.trac.wordpress.org/ticket/9396
   104 	 */
   100 	 */
   105 	$req_format = $dateformatstring;
   101 	$req_format = $dateformatstring;
   106 
   102 
   107 	$datefunc = $gmt? 'gmdate' : 'date';
       
   108 
       
   109 	if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
   103 	if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
   110 		$datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
   104 		$datemonth = $wp_locale->get_month( date( 'm', $i ) );
   111 		$datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
   105 		$datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
   112 		$dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
   106 		$dateweekday = $wp_locale->get_weekday( date( 'w', $i ) );
   113 		$dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
   107 		$dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
   114 		$datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
   108 		$datemeridiem = $wp_locale->get_meridiem( date( 'a', $i ) );
   115 		$datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
   109 		$datemeridiem_capital = $wp_locale->get_meridiem( date( 'A', $i ) );
   116 		$dateformatstring = ' '.$dateformatstring;
   110 		$dateformatstring = ' '.$dateformatstring;
   117 		$dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
   111 		$dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
   118 		$dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
   112 		$dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
   119 		$dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
   113 		$dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
   120 		$dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
   114 		$dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
   128 	if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) {
   122 	if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) {
   129 		$timezone_string = get_option( 'timezone_string' );
   123 		$timezone_string = get_option( 'timezone_string' );
   130 		if ( $timezone_string ) {
   124 		if ( $timezone_string ) {
   131 			$timezone_object = timezone_open( $timezone_string );
   125 			$timezone_object = timezone_open( $timezone_string );
   132 			$date_object = date_create( null, $timezone_object );
   126 			$date_object = date_create( null, $timezone_object );
   133 			foreach( $timezone_formats as $timezone_format ) {
   127 			foreach ( $timezone_formats as $timezone_format ) {
   134 				if ( false !== strpos( $dateformatstring, $timezone_format ) ) {
   128 				if ( false !== strpos( $dateformatstring, $timezone_format ) ) {
   135 					$formatted = date_format( $date_object, $timezone_format );
   129 					$formatted = date_format( $date_object, $timezone_format );
   136 					$dateformatstring = ' '.$dateformatstring;
   130 					$dateformatstring = ' '.$dateformatstring;
   137 					$dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring );
   131 					$dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring );
   138 					$dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
   132 					$dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
   139 				}
   133 				}
   140 			}
   134 			}
   141 		}
   135 		}
   142 	}
   136 	}
   143 	$j = @$datefunc( $dateformatstring, $i );
   137 	$j = @date( $dateformatstring, $i );
   144 
   138 
   145 	/**
   139 	/**
   146 	 * Filter the date formatted based on the locale.
   140 	 * Filters the date formatted based on the locale.
   147 	 *
   141 	 *
   148 	 * @since 2.8.0
   142 	 * @since 2.8.0
   149 	 *
   143 	 *
   150 	 * @param string $j          Formatted date string.
   144 	 * @param string $j          Formatted date string.
   151 	 * @param string $req_format Format to display the date.
   145 	 * @param string $req_format Format to display the date.
   155 	$j = apply_filters( 'date_i18n', $j, $req_format, $i, $gmt );
   149 	$j = apply_filters( 'date_i18n', $j, $req_format, $i, $gmt );
   156 	return $j;
   150 	return $j;
   157 }
   151 }
   158 
   152 
   159 /**
   153 /**
   160  * Convert integer number to format based on the locale.
   154  * Determines if the date should be declined.
       
   155  *
       
   156  * If the locale specifies that month names require a genitive case in certain
       
   157  * formats (like 'j F Y'), the month name will be replaced with a correct form.
       
   158  *
       
   159  * @since 4.4.0
       
   160  *
       
   161  * @global WP_Locale $wp_locale
       
   162  *
       
   163  * @param string $date Formatted date string.
       
   164  * @return string The date, declined if locale specifies it.
       
   165  */
       
   166 function wp_maybe_decline_date( $date ) {
       
   167 	global $wp_locale;
       
   168 
       
   169 	// i18n functions are not available in SHORTINIT mode
       
   170 	if ( ! function_exists( '_x' ) ) {
       
   171 		return $date;
       
   172 	}
       
   173 
       
   174 	/* translators: If months in your language require a genitive case,
       
   175 	 * translate this to 'on'. Do not translate into your own language.
       
   176 	 */
       
   177 	if ( 'on' === _x( 'off', 'decline months names: on or off' ) ) {
       
   178 		// Match a format like 'j F Y' or 'j. F'
       
   179 		if ( @preg_match( '#^\d{1,2}\.? [^\d ]+#u', $date ) ) {
       
   180 			$months          = $wp_locale->month;
       
   181 			$months_genitive = $wp_locale->month_genitive;
       
   182 
       
   183 			foreach ( $months as $key => $month ) {
       
   184 				$months[ $key ] = '# ' . $month . '( |$)#u';
       
   185 			}
       
   186 
       
   187 			foreach ( $months_genitive as $key => $month ) {
       
   188 				$months_genitive[ $key ] = ' ' . $month . '$1';
       
   189 			}
       
   190 
       
   191 			$date = preg_replace( $months, $months_genitive, $date );
       
   192 		}
       
   193 	}
       
   194 
       
   195 	// Used for locale-specific rules
       
   196 	$locale = get_locale();
       
   197 
       
   198 	if ( 'ca' === $locale ) {
       
   199 		// " de abril| de agost| de octubre..." -> " d'abril| d'agost| d'octubre..."
       
   200 		$date = preg_replace( '# de ([ao])#i', " d'\\1", $date );
       
   201 	}
       
   202 
       
   203 	return $date;
       
   204 }
       
   205 
       
   206 /**
       
   207  * Convert float number to format based on the locale.
   161  *
   208  *
   162  * @since 2.3.0
   209  * @since 2.3.0
   163  *
   210  *
   164  * @param int $number   The number to convert based on locale.
   211  * @global WP_Locale $wp_locale
   165  * @param int $decimals Optional. Precision of the number of decimal places. Default 0.
   212  *
       
   213  * @param float $number   The number to convert based on locale.
       
   214  * @param int   $decimals Optional. Precision of the number of decimal places. Default 0.
   166  * @return string Converted number in string format.
   215  * @return string Converted number in string format.
   167  */
   216  */
   168 function number_format_i18n( $number, $decimals = 0 ) {
   217 function number_format_i18n( $number, $decimals = 0 ) {
   169 	global $wp_locale;
   218 	global $wp_locale;
   170 	$formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
   219 
       
   220 	if ( isset( $wp_locale ) ) {
       
   221 		$formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
       
   222 	} else {
       
   223 		$formatted = number_format( $number, absint( $decimals ) );
       
   224 	}
   171 
   225 
   172 	/**
   226 	/**
   173 	 * Filter the number formatted based on the locale.
   227 	 * Filters the number formatted based on the locale.
   174 	 *
   228 	 *
   175 	 * @since  2.8.0
   229 	 * @since 2.8.0
       
   230 	 * @since 4.9.0 The `$number` and `$decimals` arguments were added.
   176 	 *
   231 	 *
   177 	 * @param string $formatted Converted number in string format.
   232 	 * @param string $formatted Converted number in string format.
       
   233 	 * @param float  $number    The number to convert based on locale.
       
   234 	 * @param int    $decimals  Precision of the number of decimal places.
   178 	 */
   235 	 */
   179 	return apply_filters( 'number_format_i18n', $formatted );
   236 	return apply_filters( 'number_format_i18n', $formatted, $number, $decimals );
   180 }
   237 }
   181 
   238 
   182 /**
   239 /**
   183  * Convert number of bytes largest unit bytes will fit into.
   240  * Convert number of bytes largest unit bytes will fit into.
   184  *
   241  *
   185  * It is easier to read 1 kB than 1024 bytes and 1 MB than 1048576 bytes. Converts
   242  * It is easier to read 1 KB than 1024 bytes and 1 MB than 1048576 bytes. Converts
   186  * number of bytes to human readable number by taking the number of that unit
   243  * number of bytes to human readable number by taking the number of that unit
   187  * that the bytes will go into it. Supports TB value.
   244  * that the bytes will go into it. Supports TB value.
   188  *
   245  *
   189  * Please note that integers in PHP are limited to 32 bits, unless they are on
   246  * Please note that integers in PHP are limited to 32 bits, unless they are on
   190  * 64 bit architecture, then they have 64 bit size. If you need to place the
   247  * 64 bit architecture, then they have 64 bit size. If you need to place the
   199  * @param int        $decimals Optional. Precision of number of decimal places. Default 0.
   256  * @param int        $decimals Optional. Precision of number of decimal places. Default 0.
   200  * @return string|false False on failure. Number string on success.
   257  * @return string|false False on failure. Number string on success.
   201  */
   258  */
   202 function size_format( $bytes, $decimals = 0 ) {
   259 function size_format( $bytes, $decimals = 0 ) {
   203 	$quant = array(
   260 	$quant = array(
   204 		// ========================= Origin ====
   261 		'TB' => TB_IN_BYTES,
   205 		'TB' => 1099511627776,  // pow( 1024, 4)
   262 		'GB' => GB_IN_BYTES,
   206 		'GB' => 1073741824,     // pow( 1024, 3)
   263 		'MB' => MB_IN_BYTES,
   207 		'MB' => 1048576,        // pow( 1024, 2)
   264 		'KB' => KB_IN_BYTES,
   208 		'kB' => 1024,           // pow( 1024, 1)
   265 		'B'  => 1,
   209 		'B'  => 1,              // pow( 1024, 0)
       
   210 	);
   266 	);
       
   267 
       
   268 	if ( 0 === $bytes ) {
       
   269 		return number_format_i18n( 0, $decimals ) . ' B';
       
   270 	}
   211 
   271 
   212 	foreach ( $quant as $unit => $mag ) {
   272 	foreach ( $quant as $unit => $mag ) {
   213 		if ( doubleval( $bytes ) >= $mag ) {
   273 		if ( doubleval( $bytes ) >= $mag ) {
   214 			return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
   274 			return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
   215 		}
   275 		}
   250 		$weekday += 7;
   310 		$weekday += 7;
   251 
   311 
   252 	// The most recent week start day on or before $day.
   312 	// The most recent week start day on or before $day.
   253 	$start = $day - DAY_IN_SECONDS * ( $weekday - $start_of_week );
   313 	$start = $day - DAY_IN_SECONDS * ( $weekday - $start_of_week );
   254 
   314 
   255 	// $start + 7 days - 1 second.
   315 	// $start + 1 week - 1 second.
   256 	$end = $start + 7 * DAY_IN_SECONDS - 1;
   316 	$end = $start + WEEK_IN_SECONDS - 1;
   257 	return compact( 'start', 'end' );
   317 	return compact( 'start', 'end' );
   258 }
   318 }
   259 
   319 
   260 /**
   320 /**
   261  * Unserialize value only if it was serialized.
   321  * Unserialize value only if it was serialized.
   379 	if ( is_array( $data ) || is_object( $data ) )
   439 	if ( is_array( $data ) || is_object( $data ) )
   380 		return serialize( $data );
   440 		return serialize( $data );
   381 
   441 
   382 	// Double serialization is required for backward compatibility.
   442 	// Double serialization is required for backward compatibility.
   383 	// See https://core.trac.wordpress.org/ticket/12930
   443 	// See https://core.trac.wordpress.org/ticket/12930
       
   444 	// Also the world will end. See WP 3.6.1.
   384 	if ( is_serialized( $data, false ) )
   445 	if ( is_serialized( $data, false ) )
   385 		return serialize( $data );
   446 		return serialize( $data );
   386 
   447 
   387 	return $data;
   448 	return $data;
   388 }
   449 }
   488  * remove enclosures that are no longer in the post. This is called as
   549  * remove enclosures that are no longer in the post. This is called as
   489  * pingbacks and trackbacks.
   550  * pingbacks and trackbacks.
   490  *
   551  *
   491  * @since 1.5.0
   552  * @since 1.5.0
   492  *
   553  *
   493  * @see $wpdb
   554  * @global wpdb $wpdb WordPress database abstraction object.
   494  *
   555  *
   495  * @param string $content Post Content.
   556  * @param string $content Post Content.
   496  * @param int $post_ID Post ID.
   557  * @param int    $post_ID Post ID.
   497  */
   558  */
   498 function do_enclose( $content, $post_ID ) {
   559 function do_enclose( $content, $post_ID ) {
   499 	global $wpdb;
   560 	global $wpdb;
   500 
   561 
   501 	//TODO: Tidy this ghetto code up and make the debug code optional
   562 	//TODO: Tidy this ghetto code up and make the debug code optional
   524 				$post_links[] = $link_test;
   585 				$post_links[] = $link_test;
   525 			elseif ( isset($test['path']) && ( $test['path'] != '/' ) &&  ($test['path'] != '' ) )
   586 			elseif ( isset($test['path']) && ( $test['path'] != '/' ) &&  ($test['path'] != '' ) )
   526 				$post_links[] = $link_test;
   587 				$post_links[] = $link_test;
   527 		}
   588 		}
   528 	}
   589 	}
       
   590 
       
   591 	/**
       
   592 	 * Filters the list of enclosure links before querying the database.
       
   593 	 *
       
   594 	 * Allows for the addition and/or removal of potential enclosures to save
       
   595 	 * to postmeta before checking the database for existing enclosures.
       
   596 	 *
       
   597 	 * @since 4.4.0
       
   598 	 *
       
   599 	 * @param array $post_links An array of enclosure links.
       
   600 	 * @param int   $post_ID    Post ID.
       
   601 	 */
       
   602 	$post_links = apply_filters( 'enclosure_links', $post_links, $post_ID );
   529 
   603 
   530 	foreach ( (array) $post_links as $url ) {
   604 	foreach ( (array) $post_links as $url ) {
   531 		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, $wpdb->esc_like( $url ) . '%' ) ) ) {
   605 		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, $wpdb->esc_like( $url ) . '%' ) ) ) {
   532 
   606 
   533 			if ( $headers = wp_get_http_headers( $url) ) {
   607 			if ( $headers = wp_get_http_headers( $url) ) {
   557 		}
   631 		}
   558 	}
   632 	}
   559 }
   633 }
   560 
   634 
   561 /**
   635 /**
   562  * Perform a HTTP HEAD or GET request.
       
   563  *
       
   564  * If $file_path is a writable filename, this will do a GET request and write
       
   565  * the file to that path.
       
   566  *
       
   567  * @since 2.5.0
       
   568  *
       
   569  * @param string      $url       URL to fetch.
       
   570  * @param string|bool $file_path Optional. File path to write request to. Default false.
       
   571  * @param int         $red       Optional. The number of Redirects followed, Upon 5 being hit,
       
   572  *                               returns false. Default 1.
       
   573  * @return bool|string False on failure and string of headers if HEAD request.
       
   574  */
       
   575 function wp_get_http( $url, $file_path = false, $red = 1 ) {
       
   576 	@set_time_limit( 60 );
       
   577 
       
   578 	if ( $red > 5 )
       
   579 		return false;
       
   580 
       
   581 	$options = array();
       
   582 	$options['redirection'] = 5;
       
   583 
       
   584 	if ( false == $file_path )
       
   585 		$options['method'] = 'HEAD';
       
   586 	else
       
   587 		$options['method'] = 'GET';
       
   588 
       
   589 	$response = wp_safe_remote_request( $url, $options );
       
   590 
       
   591 	if ( is_wp_error( $response ) )
       
   592 		return false;
       
   593 
       
   594 	$headers = wp_remote_retrieve_headers( $response );
       
   595 	$headers['response'] = wp_remote_retrieve_response_code( $response );
       
   596 
       
   597 	// WP_HTTP no longer follows redirects for HEAD requests.
       
   598 	if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) {
       
   599 		return wp_get_http( $headers['location'], $file_path, ++$red );
       
   600 	}
       
   601 
       
   602 	if ( false == $file_path )
       
   603 		return $headers;
       
   604 
       
   605 	// GET request - write it to the supplied filename
       
   606 	$out_fp = fopen($file_path, 'w');
       
   607 	if ( !$out_fp )
       
   608 		return $headers;
       
   609 
       
   610 	fwrite( $out_fp,  wp_remote_retrieve_body( $response ) );
       
   611 	fclose($out_fp);
       
   612 	clearstatcache();
       
   613 
       
   614 	return $headers;
       
   615 }
       
   616 
       
   617 /**
       
   618  * Retrieve HTTP Headers from URL.
   636  * Retrieve HTTP Headers from URL.
   619  *
   637  *
   620  * @since 1.5.1
   638  * @since 1.5.1
   621  *
   639  *
   622  * @param string $url        URL to retrieve HTTP headers from.
   640  * @param string $url        URL to retrieve HTTP headers from.
   623  * @param bool   $deprecated Not Used.
   641  * @param bool   $deprecated Not Used.
   624  * @return bool|string False on failure, headers on success.
   642  * @return bool|string False on failure, headers on success.
   625  */
   643  */
   626 function wp_get_http_headers( $url, $deprecated = false ) {
   644 function wp_get_http_headers( $url, $deprecated = false ) {
   627 	if ( !empty( $deprecated ) )
   645 	if ( !empty( $deprecated ) )
   628 		_deprecated_argument( __FUNCTION__, '2.7' );
   646 		_deprecated_argument( __FUNCTION__, '2.7.0' );
   629 
   647 
   630 	$response = wp_safe_remote_head( $url );
   648 	$response = wp_safe_remote_head( $url );
   631 
   649 
   632 	if ( is_wp_error( $response ) )
   650 	if ( is_wp_error( $response ) )
   633 		return false;
   651 		return false;
   661  * separator to '&' and uses _http_build_query() function.
   679  * separator to '&' and uses _http_build_query() function.
   662  *
   680  *
   663  * @since 2.3.0
   681  * @since 2.3.0
   664  *
   682  *
   665  * @see _http_build_query() Used to build the query
   683  * @see _http_build_query() Used to build the query
   666  * @see http://us2.php.net/manual/en/function.http-build-query.php for more on what
   684  * @link https://secure.php.net/manual/en/function.http-build-query.php for more on what
   667  *		http_build_query() does.
   685  *		 http_build_query() does.
   668  *
   686  *
   669  * @param array $data URL-encode key/value pairs.
   687  * @param array $data URL-encode key/value pairs.
   670  * @return string URL-encoded string.
   688  * @return string URL-encoded string.
   671  */
   689  */
   672 function build_query( $data ) {
   690 function build_query( $data ) {
   677  * From php.net (modified by Mark Jaquith to behave like the native PHP5 function).
   695  * From php.net (modified by Mark Jaquith to behave like the native PHP5 function).
   678  *
   696  *
   679  * @since 3.2.0
   697  * @since 3.2.0
   680  * @access private
   698  * @access private
   681  *
   699  *
   682  * @see http://us1.php.net/manual/en/function.http-build-query.php
   700  * @see https://secure.php.net/manual/en/function.http-build-query.php
   683  *
   701  *
   684  * @param array|object  $data       An array or object of data. Converted to array.
   702  * @param array|object  $data       An array or object of data. Converted to array.
   685  * @param string        $prefix     Optional. Numeric index. If set, start parameter numbering with it.
   703  * @param string        $prefix     Optional. Numeric index. If set, start parameter numbering with it.
   686  *                                  Default null.
   704  *                                  Default null.
   687  * @param string        $sep        Optional. Argument separator; defaults to 'arg_separator.output'.
   705  * @param string        $sep        Optional. Argument separator; defaults to 'arg_separator.output'.
   719 
   737 
   720 	return implode($sep, $ret);
   738 	return implode($sep, $ret);
   721 }
   739 }
   722 
   740 
   723 /**
   741 /**
   724  * Retrieve a modified URL query string.
   742  * Retrieves a modified URL query string.
   725  *
   743  *
   726  * You can rebuild the URL and append a new query variable to the URL query by
   744  * You can rebuild the URL and append query variables to the URL query by using this function.
   727  * using this function. You can also retrieve the full URL with query data.
   745  * There are two ways to use this function; either a single key and value, or an associative array.
   728  *
   746  *
   729  * Adding a single key & value or an associative array. Setting a key value to
   747  * Using a single key and value:
   730  * an empty string removes the key. Omitting oldquery_or_uri uses the $_SERVER
   748  *
   731  * value. Additional values provided are expected to be encoded appropriately
   749  *     add_query_arg( 'key', 'value', 'http://example.com' );
   732  * with urlencode() or rawurlencode().
   750  *
       
   751  * Using an associative array:
       
   752  *
       
   753  *     add_query_arg( array(
       
   754  *         'key1' => 'value1',
       
   755  *         'key2' => 'value2',
       
   756  *     ), 'http://example.com' );
       
   757  *
       
   758  * Omitting the URL from either use results in the current URL being used
       
   759  * (the value of `$_SERVER['REQUEST_URI']`).
       
   760  *
       
   761  * Values are expected to be encoded appropriately with urlencode() or rawurlencode().
       
   762  *
       
   763  * Setting any query variable's value to boolean false removes the key (see remove_query_arg()).
       
   764  *
       
   765  * Important: The return value of add_query_arg() is not escaped by default. Output should be
       
   766  * late-escaped with esc_url() or similar to help prevent vulnerability to cross-site scripting
       
   767  * (XSS) attacks.
   733  *
   768  *
   734  * @since 1.5.0
   769  * @since 1.5.0
   735  *
   770  *
   736  * @param string|array $param1 Either newkey or an associative_array.
   771  * @param string|array $key   Either a query variable key, or an associative array of query variables.
   737  * @param string       $param2 Either newvalue or oldquery or URI.
   772  * @param string       $value Optional. Either a query variable value, or a URL to act upon.
   738  * @param string       $param3 Optional. Old query or URI.
   773  * @param string       $url   Optional. A URL to act upon.
   739  * @return string New URL query string.
   774  * @return string New URL query string (unescaped).
   740  */
   775  */
   741 function add_query_arg() {
   776 function add_query_arg() {
   742 	$args = func_get_args();
   777 	$args = func_get_args();
   743 	if ( is_array( $args[0] ) ) {
   778 	if ( is_array( $args[0] ) ) {
   744 		if ( count( $args ) < 2 || false === $args[1] )
   779 		if ( count( $args ) < 2 || false === $args[1] )
   800 	$ret = rtrim( $ret, '?' );
   835 	$ret = rtrim( $ret, '?' );
   801 	return $ret;
   836 	return $ret;
   802 }
   837 }
   803 
   838 
   804 /**
   839 /**
   805  * Removes an item or list from the query string.
   840  * Removes an item or items from a query string.
   806  *
   841  *
   807  * @since 1.5.0
   842  * @since 1.5.0
   808  *
   843  *
   809  * @param string|array $key   Query key or keys to remove.
   844  * @param string|array $key   Query key or keys to remove.
   810  * @param bool|string  $query Optional. When false uses the $_SERVER value. Default false.
   845  * @param bool|string  $query Optional. When false uses the current URL. Default false.
   811  * @return string New URL query string.
   846  * @return string New URL query string.
   812  */
   847  */
   813 function remove_query_arg( $key, $query = false ) {
   848 function remove_query_arg( $key, $query = false ) {
   814 	if ( is_array( $key ) ) { // removing multiple keys
   849 	if ( is_array( $key ) ) { // removing multiple keys
   815 		foreach ( $key as $k )
   850 		foreach ( $key as $k )
   816 			$query = add_query_arg( $k, false, $query );
   851 			$query = add_query_arg( $k, false, $query );
   817 		return $query;
   852 		return $query;
   818 	}
   853 	}
   819 	return add_query_arg( $key, false, $query );
   854 	return add_query_arg( $key, false, $query );
       
   855 }
       
   856 
       
   857 /**
       
   858  * Returns an array of single-use query variable names that can be removed from a URL.
       
   859  *
       
   860  * @since 4.4.0
       
   861  *
       
   862  * @return array An array of parameters to remove from the URL.
       
   863  */
       
   864 function wp_removable_query_args() {
       
   865 	$removable_query_args = array(
       
   866 		'activate',
       
   867 		'activated',
       
   868 		'approved',
       
   869 		'deactivate',
       
   870 		'deleted',
       
   871 		'disabled',
       
   872 		'enabled',
       
   873 		'error',
       
   874 		'hotkeys_highlight_first',
       
   875 		'hotkeys_highlight_last',
       
   876 		'locked',
       
   877 		'message',
       
   878 		'same',
       
   879 		'saved',
       
   880 		'settings-updated',
       
   881 		'skipped',
       
   882 		'spammed',
       
   883 		'trashed',
       
   884 		'unspammed',
       
   885 		'untrashed',
       
   886 		'update',
       
   887 		'updated',
       
   888 		'wp-post-new-reload',
       
   889 	);
       
   890 
       
   891 	/**
       
   892 	 * Filters the list of query variables to remove.
       
   893 	 *
       
   894 	 * @since 4.2.0
       
   895 	 *
       
   896 	 * @param array $removable_query_args An array of query variables to remove from a URL.
       
   897 	 */
       
   898 	return apply_filters( 'removable_query_args', $removable_query_args );
   820 }
   899 }
   821 
   900 
   822 /**
   901 /**
   823  * Walks the array while sanitizing the contents.
   902  * Walks the array while sanitizing the contents.
   824  *
   903  *
   868 /**
   947 /**
   869  * Set up the WordPress query.
   948  * Set up the WordPress query.
   870  *
   949  *
   871  * @since 2.0.0
   950  * @since 2.0.0
   872  *
   951  *
       
   952  * @global WP       $wp_locale
       
   953  * @global WP_Query $wp_query
       
   954  * @global WP_Query $wp_the_query
       
   955  *
   873  * @param string|array $query_vars Default WP_Query arguments.
   956  * @param string|array $query_vars Default WP_Query arguments.
   874  */
   957  */
   875 function wp( $query_vars = '' ) {
   958 function wp( $query_vars = '' ) {
   876 	global $wp, $wp_query, $wp_the_query;
   959 	global $wp, $wp_query, $wp_the_query;
   877 	$wp->main( $query_vars );
   960 	$wp->main( $query_vars );
   882 
   965 
   883 /**
   966 /**
   884  * Retrieve the description for the HTTP status.
   967  * Retrieve the description for the HTTP status.
   885  *
   968  *
   886  * @since 2.3.0
   969  * @since 2.3.0
       
   970  *
       
   971  * @global array $wp_header_to_desc
   887  *
   972  *
   888  * @param int $code HTTP status code.
   973  * @param int $code HTTP status code.
   889  * @return string Empty string if not found, or description if found.
   974  * @return string Empty string if not found, or description if found.
   890  */
   975  */
   891 function get_status_header_desc( $code ) {
   976 function get_status_header_desc( $code ) {
   915 			303 => 'See Other',
  1000 			303 => 'See Other',
   916 			304 => 'Not Modified',
  1001 			304 => 'Not Modified',
   917 			305 => 'Use Proxy',
  1002 			305 => 'Use Proxy',
   918 			306 => 'Reserved',
  1003 			306 => 'Reserved',
   919 			307 => 'Temporary Redirect',
  1004 			307 => 'Temporary Redirect',
       
  1005 			308 => 'Permanent Redirect',
   920 
  1006 
   921 			400 => 'Bad Request',
  1007 			400 => 'Bad Request',
   922 			401 => 'Unauthorized',
  1008 			401 => 'Unauthorized',
   923 			402 => 'Payment Required',
  1009 			402 => 'Payment Required',
   924 			403 => 'Forbidden',
  1010 			403 => 'Forbidden',
   935 			414 => 'Request-URI Too Long',
  1021 			414 => 'Request-URI Too Long',
   936 			415 => 'Unsupported Media Type',
  1022 			415 => 'Unsupported Media Type',
   937 			416 => 'Requested Range Not Satisfiable',
  1023 			416 => 'Requested Range Not Satisfiable',
   938 			417 => 'Expectation Failed',
  1024 			417 => 'Expectation Failed',
   939 			418 => 'I\'m a teapot',
  1025 			418 => 'I\'m a teapot',
       
  1026 			421 => 'Misdirected Request',
   940 			422 => 'Unprocessable Entity',
  1027 			422 => 'Unprocessable Entity',
   941 			423 => 'Locked',
  1028 			423 => 'Locked',
   942 			424 => 'Failed Dependency',
  1029 			424 => 'Failed Dependency',
   943 			426 => 'Upgrade Required',
  1030 			426 => 'Upgrade Required',
   944 			428 => 'Precondition Required',
  1031 			428 => 'Precondition Required',
   945 			429 => 'Too Many Requests',
  1032 			429 => 'Too Many Requests',
   946 			431 => 'Request Header Fields Too Large',
  1033 			431 => 'Request Header Fields Too Large',
       
  1034 			451 => 'Unavailable For Legal Reasons',
   947 
  1035 
   948 			500 => 'Internal Server Error',
  1036 			500 => 'Internal Server Error',
   949 			501 => 'Not Implemented',
  1037 			501 => 'Not Implemented',
   950 			502 => 'Bad Gateway',
  1038 			502 => 'Bad Gateway',
   951 			503 => 'Service Unavailable',
  1039 			503 => 'Service Unavailable',
   966 
  1054 
   967 /**
  1055 /**
   968  * Set HTTP status header.
  1056  * Set HTTP status header.
   969  *
  1057  *
   970  * @since 2.0.0
  1058  * @since 2.0.0
       
  1059  * @since 4.4.0 Added the `$description` parameter.
   971  *
  1060  *
   972  * @see get_status_header_desc()
  1061  * @see get_status_header_desc()
   973  *
  1062  *
   974  * @param int $code HTTP status code.
  1063  * @param int    $code        HTTP status code.
   975  */
  1064  * @param string $description Optional. A custom description for the HTTP status.
   976 function status_header( $code ) {
  1065  */
   977 	$description = get_status_header_desc( $code );
  1066 function status_header( $code, $description = '' ) {
   978 
  1067 	if ( ! $description ) {
   979 	if ( empty( $description ) )
  1068 		$description = get_status_header_desc( $code );
       
  1069 	}
       
  1070 
       
  1071 	if ( empty( $description ) ) {
   980 		return;
  1072 		return;
   981 
  1073 	}
   982 	$protocol = $_SERVER['SERVER_PROTOCOL'];
  1074 
   983 	if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
  1075 	$protocol = wp_get_server_protocol();
   984 		$protocol = 'HTTP/1.0';
       
   985 	$status_header = "$protocol $code $description";
  1076 	$status_header = "$protocol $code $description";
   986 	if ( function_exists( 'apply_filters' ) )
  1077 	if ( function_exists( 'apply_filters' ) )
   987 
  1078 
   988 		/**
  1079 		/**
   989 		 * Filter an HTTP status header.
  1080 		 * Filters an HTTP status header.
   990 		 *
  1081 		 *
   991 		 * @since 2.2.0
  1082 		 * @since 2.2.0
   992 		 *
  1083 		 *
   993 		 * @param string $status_header HTTP status header.
  1084 		 * @param string $status_header HTTP status header.
   994 		 * @param int    $code          HTTP status code.
  1085 		 * @param int    $code          HTTP status code.
  1012  */
  1103  */
  1013 function wp_get_nocache_headers() {
  1104 function wp_get_nocache_headers() {
  1014 	$headers = array(
  1105 	$headers = array(
  1015 		'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
  1106 		'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
  1016 		'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
  1107 		'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
  1017 		'Pragma' => 'no-cache',
       
  1018 	);
  1108 	);
  1019 
  1109 
  1020 	if ( function_exists('apply_filters') ) {
  1110 	if ( function_exists('apply_filters') ) {
  1021 		/**
  1111 		/**
  1022 		 * Filter the cache-controlling headers.
  1112 		 * Filters the cache-controlling headers.
  1023 		 *
  1113 		 *
  1024 		 * @since 2.8.0
  1114 		 * @since 2.8.0
  1025 		 *
  1115 		 *
  1026 		 * @see wp_get_nocache_headers()
  1116 		 * @see wp_get_nocache_headers()
  1027 		 *
  1117 		 *
  1028 		 * @param array $headers {
  1118 		 * @param array $headers {
  1029 		 *     Header names and field values.
  1119 		 *     Header names and field values.
  1030 		 *
  1120 		 *
  1031 		 *     @type string $Expires       Expires header.
  1121 		 *     @type string $Expires       Expires header.
  1032 		 *     @type string $Cache-Control Cache-Control header.
  1122 		 *     @type string $Cache-Control Cache-Control header.
  1033 		 *     @type string $Pragma        Pragma header.
       
  1034 		 * }
  1123 		 * }
  1035 		 */
  1124 		 */
  1036 		$headers = (array) apply_filters( 'nocache_headers', $headers );
  1125 		$headers = (array) apply_filters( 'nocache_headers', $headers );
  1037 	}
  1126 	}
  1038 	$headers['Last-Modified'] = false;
  1127 	$headers['Last-Modified'] = false;
  1067 				break;
  1156 				break;
  1068 			}
  1157 			}
  1069 		}
  1158 		}
  1070 	}
  1159 	}
  1071 
  1160 
  1072 	foreach( $headers as $name => $field_value )
  1161 	foreach ( $headers as $name => $field_value )
  1073 		@header("{$name}: {$field_value}");
  1162 		@header("{$name}: {$field_value}");
  1074 }
  1163 }
  1075 
  1164 
  1076 /**
  1165 /**
  1077  * Set the headers for caching for 10 days with JavaScript content type.
  1166  * Set the headers for caching for 10 days with JavaScript content type.
  1122  *
  1211  *
  1123  * It is better to only have one hook for each feed.
  1212  * It is better to only have one hook for each feed.
  1124  *
  1213  *
  1125  * @since 2.1.0
  1214  * @since 2.1.0
  1126  *
  1215  *
  1127  * @uses $wp_query Used to tell if the use a comment feed.
  1216  * @global WP_Query $wp_query Used to tell if the use a comment feed.
  1128  */
  1217  */
  1129 function do_feed() {
  1218 function do_feed() {
  1130 	global $wp_query;
  1219 	global $wp_query;
  1131 
  1220 
  1132 	$feed = get_query_var( 'feed' );
  1221 	$feed = get_query_var( 'feed' );
  1135 	$feed = preg_replace( '/^_+/', '', $feed );
  1224 	$feed = preg_replace( '/^_+/', '', $feed );
  1136 
  1225 
  1137 	if ( $feed == '' || $feed == 'feed' )
  1226 	if ( $feed == '' || $feed == 'feed' )
  1138 		$feed = get_default_feed();
  1227 		$feed = get_default_feed();
  1139 
  1228 
  1140 	$hook = 'do_feed_' . $feed;
  1229 	if ( ! has_action( "do_feed_{$feed}" ) ) {
  1141 	if ( ! has_action( $hook ) )
       
  1142 		wp_die( __( 'ERROR: This is not a valid feed template.' ), '', array( 'response' => 404 ) );
  1230 		wp_die( __( 'ERROR: This is not a valid feed template.' ), '', array( 'response' => 404 ) );
       
  1231 	}
  1143 
  1232 
  1144 	/**
  1233 	/**
  1145 	 * Fires once the given feed is loaded.
  1234 	 * Fires once the given feed is loaded.
  1146 	 *
  1235 	 *
  1147 	 * The dynamic hook name, $hook, refers to the feed name.
  1236 	 * The dynamic portion of the hook name, `$feed`, refers to the feed template name.
       
  1237 	 * Possible values include: 'rdf', 'rss', 'rss2', and 'atom'.
  1148 	 *
  1238 	 *
  1149 	 * @since 2.1.0
  1239 	 * @since 2.1.0
  1150 	 *
  1240 	 * @since 4.4.0 The `$feed` parameter was added.
  1151 	 * @param bool $is_comment_feed Whether the feed is a comment feed.
  1241 	 *
       
  1242 	 * @param bool   $is_comment_feed Whether the feed is a comment feed.
       
  1243 	 * @param string $feed            The feed name.
  1152 	 */
  1244 	 */
  1153 	do_action( $hook, $wp_query->is_comment_feed );
  1245 	do_action( "do_feed_{$feed}", $wp_query->is_comment_feed, $feed );
  1154 }
  1246 }
  1155 
  1247 
  1156 /**
  1248 /**
  1157  * Load the RDF RSS 0.91 Feed template.
  1249  * Load the RDF RSS 0.91 Feed template.
  1158  *
  1250  *
  1231 		$output .= "Disallow: /\n";
  1323 		$output .= "Disallow: /\n";
  1232 	} else {
  1324 	} else {
  1233 		$site_url = parse_url( site_url() );
  1325 		$site_url = parse_url( site_url() );
  1234 		$path = ( !empty( $site_url['path'] ) ) ? $site_url['path'] : '';
  1326 		$path = ( !empty( $site_url['path'] ) ) ? $site_url['path'] : '';
  1235 		$output .= "Disallow: $path/wp-admin/\n";
  1327 		$output .= "Disallow: $path/wp-admin/\n";
       
  1328 		$output .= "Allow: $path/wp-admin/admin-ajax.php\n";
  1236 	}
  1329 	}
  1237 
  1330 
  1238 	/**
  1331 	/**
  1239 	 * Filter the robots.txt output.
  1332 	 * Filters the robots.txt output.
  1240 	 *
  1333 	 *
  1241 	 * @since 3.0.0
  1334 	 * @since 3.0.0
  1242 	 *
  1335 	 *
  1243 	 * @param string $output Robots.txt output.
  1336 	 * @param string $output Robots.txt output.
  1244 	 * @param bool   $public Whether the site is considered "public".
  1337 	 * @param bool   $public Whether the site is considered "public".
  1245 	 */
  1338 	 */
  1246 	echo apply_filters( 'robots_txt', $output, $public );
  1339 	echo apply_filters( 'robots_txt', $output, $public );
  1247 }
  1340 }
  1248 
  1341 
  1249 /**
  1342 /**
  1250  * Test whether blog is already installed.
  1343  * Test whether WordPress is already installed.
  1251  *
  1344  *
  1252  * The cache will be checked first. If you have a cache plugin, which saves
  1345  * The cache will be checked first. If you have a cache plugin, which saves
  1253  * the cache values, then this will work. If you use the default WordPress
  1346  * the cache values, then this will work. If you use the default WordPress
  1254  * cache, and the database goes away, then you might have problems.
  1347  * cache, and the database goes away, then you might have problems.
  1255  *
  1348  *
  1257  *
  1350  *
  1258  * @since 2.1.0
  1351  * @since 2.1.0
  1259  *
  1352  *
  1260  * @global wpdb $wpdb WordPress database abstraction object.
  1353  * @global wpdb $wpdb WordPress database abstraction object.
  1261  *
  1354  *
  1262  * @return bool Whether the blog is already installed.
  1355  * @return bool Whether the site is already installed.
  1263  */
  1356  */
  1264 function is_blog_installed() {
  1357 function is_blog_installed() {
  1265 	global $wpdb;
  1358 	global $wpdb;
  1266 
  1359 
  1267 	/*
  1360 	/*
  1270 	 */
  1363 	 */
  1271 	if ( wp_cache_get( 'is_blog_installed' ) )
  1364 	if ( wp_cache_get( 'is_blog_installed' ) )
  1272 		return true;
  1365 		return true;
  1273 
  1366 
  1274 	$suppress = $wpdb->suppress_errors();
  1367 	$suppress = $wpdb->suppress_errors();
  1275 	if ( ! defined( 'WP_INSTALLING' ) ) {
  1368 	if ( ! wp_installing() ) {
  1276 		$alloptions = wp_load_alloptions();
  1369 		$alloptions = wp_load_alloptions();
  1277 	}
  1370 	}
  1278 	// If siteurl is not set to autoload, check it specifically
  1371 	// If siteurl is not set to autoload, check it specifically
  1279 	if ( !isset( $alloptions['siteurl'] ) )
  1372 	if ( !isset( $alloptions['siteurl'] ) )
  1280 		$installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
  1373 		$installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
  1293 		return true;
  1386 		return true;
  1294 
  1387 
  1295 	$suppress = $wpdb->suppress_errors();
  1388 	$suppress = $wpdb->suppress_errors();
  1296 
  1389 
  1297 	/*
  1390 	/*
  1298 	 * Loop over the WP tables. If none exist, then scratch install is allowed.
  1391 	 * Loop over the WP tables. If none exist, then scratch installation is allowed.
  1299 	 * If one or more exist, suggest table repair since we got here because the
  1392 	 * If one or more exist, suggest table repair since we got here because the
  1300 	 * options table could not be accessed.
  1393 	 * options table could not be accessed.
  1301 	 */
  1394 	 */
  1302 	$wp_tables = $wpdb->tables();
  1395 	$wp_tables = $wpdb->tables();
  1303 	foreach ( $wp_tables as $table ) {
  1396 	foreach ( $wp_tables as $table ) {
  1304 		// The existence of custom user tables shouldn't suggest an insane state or prevent a clean install.
  1397 		// The existence of custom user tables shouldn't suggest an insane state or prevent a clean installation.
  1305 		if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table )
  1398 		if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table )
  1306 			continue;
  1399 			continue;
  1307 		if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table )
  1400 		if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table )
  1308 			continue;
  1401 			continue;
  1309 
  1402 
  1313 		// One or more tables exist. We are insane.
  1406 		// One or more tables exist. We are insane.
  1314 
  1407 
  1315 		wp_load_translations_early();
  1408 		wp_load_translations_early();
  1316 
  1409 
  1317 		// Die with a DB error.
  1410 		// Die with a DB error.
  1318 		$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' );
  1411 		$wpdb->error = sprintf(
       
  1412 			/* translators: %s: database repair URL */
       
  1413 			__( 'One or more database tables are unavailable. The database may need to be <a href="%s">repaired</a>.' ),
       
  1414 			'maint/repair.php?referrer=is_blog_installed'
       
  1415 		);
       
  1416 
  1319 		dead_db();
  1417 		dead_db();
  1320 	}
  1418 	}
  1321 
  1419 
  1322 	$wpdb->suppress_errors( $suppress );
  1420 	$wpdb->suppress_errors( $suppress );
  1323 
  1421 
  1431  * @since 2.0.4
  1529  * @since 2.0.4
  1432  *
  1530  *
  1433  * @return false|string False on failure. Referer URL on success.
  1531  * @return false|string False on failure. Referer URL on success.
  1434  */
  1532  */
  1435 function wp_get_referer() {
  1533 function wp_get_referer() {
  1436 	if ( ! function_exists( 'wp_validate_redirect' ) )
  1534 	if ( ! function_exists( 'wp_validate_redirect' ) ) {
  1437 		return false;
  1535 		return false;
  1438 	$ref = false;
  1536 	}
  1439 	if ( ! empty( $_REQUEST['_wp_http_referer'] ) )
  1537 
  1440 		$ref = wp_unslash( $_REQUEST['_wp_http_referer'] );
  1538 	$ref = wp_get_raw_referer();
  1441 	elseif ( ! empty( $_SERVER['HTTP_REFERER'] ) )
  1539 
  1442 		$ref = wp_unslash( $_SERVER['HTTP_REFERER'] );
  1540 	if ( $ref && $ref !== wp_unslash( $_SERVER['REQUEST_URI'] ) && $ref !== home_url() . wp_unslash( $_SERVER['REQUEST_URI'] ) ) {
  1443 
       
  1444 	if ( $ref && $ref !== wp_unslash( $_SERVER['REQUEST_URI'] ) )
       
  1445 		return wp_validate_redirect( $ref, false );
  1541 		return wp_validate_redirect( $ref, false );
       
  1542 	}
       
  1543 
       
  1544 	return false;
       
  1545 }
       
  1546 
       
  1547 /**
       
  1548  * Retrieves unvalidated referer from '_wp_http_referer' or HTTP referer.
       
  1549  *
       
  1550  * Do not use for redirects, use wp_get_referer() instead.
       
  1551  *
       
  1552  * @since 4.5.0
       
  1553  *
       
  1554  * @return string|false Referer URL on success, false on failure.
       
  1555  */
       
  1556 function wp_get_raw_referer() {
       
  1557 	if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
       
  1558 		return wp_unslash( $_REQUEST['_wp_http_referer'] );
       
  1559 	} else if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
       
  1560 		return wp_unslash( $_SERVER['HTTP_REFERER'] );
       
  1561 	}
       
  1562 
  1446 	return false;
  1563 	return false;
  1447 }
  1564 }
  1448 
  1565 
  1449 /**
  1566 /**
  1450  * Retrieve original referer that was posted, if it exists.
  1567  * Retrieve original referer that was posted, if it exists.
  1471  */
  1588  */
  1472 function wp_mkdir_p( $target ) {
  1589 function wp_mkdir_p( $target ) {
  1473 	$wrapper = null;
  1590 	$wrapper = null;
  1474 
  1591 
  1475 	// Strip the protocol.
  1592 	// Strip the protocol.
  1476 	if( wp_is_stream( $target ) ) {
  1593 	if ( wp_is_stream( $target ) ) {
  1477 		list( $wrapper, $target ) = explode( '://', $target, 2 );
  1594 		list( $wrapper, $target ) = explode( '://', $target, 2 );
  1478 	}
  1595 	}
  1479 
  1596 
  1480 	// From php.net/mkdir user contributed notes.
  1597 	// From php.net/mkdir user contributed notes.
  1481 	$target = str_replace( '//', '/', $target );
  1598 	$target = str_replace( '//', '/', $target );
  1482 
  1599 
  1483 	// Put the wrapper back on the target.
  1600 	// Put the wrapper back on the target.
  1484 	if( $wrapper !== null ) {
  1601 	if ( $wrapper !== null ) {
  1485 		$target = $wrapper . '://' . $target;
  1602 		$target = $wrapper . '://' . $target;
  1486 	}
  1603 	}
  1487 
  1604 
  1488 	/*
  1605 	/*
  1489 	 * Safe mode fails with a trailing slash under certain PHP versions.
  1606 	 * Safe mode fails with a trailing slash under certain PHP versions.
  1496 	if ( file_exists( $target ) )
  1613 	if ( file_exists( $target ) )
  1497 		return @is_dir( $target );
  1614 		return @is_dir( $target );
  1498 
  1615 
  1499 	// We need to find the permissions of the parent folder that exists and inherit that.
  1616 	// We need to find the permissions of the parent folder that exists and inherit that.
  1500 	$target_parent = dirname( $target );
  1617 	$target_parent = dirname( $target );
  1501 	while ( '.' != $target_parent && ! is_dir( $target_parent ) ) {
  1618 	while ( '.' != $target_parent && ! is_dir( $target_parent ) && dirname( $target_parent ) !== $target_parent ) {
  1502 		$target_parent = dirname( $target_parent );
  1619 		$target_parent = dirname( $target_parent );
  1503 	}
  1620 	}
  1504 
  1621 
  1505 	// Get the permission bits.
  1622 	// Get the permission bits.
  1506 	if ( $stat = @stat( $target_parent ) ) {
  1623 	if ( $stat = @stat( $target_parent ) ) {
  1527 
  1644 
  1528 	return false;
  1645 	return false;
  1529 }
  1646 }
  1530 
  1647 
  1531 /**
  1648 /**
  1532  * Test if a give filesystem path is absolute.
  1649  * Test if a given filesystem path is absolute.
  1533  *
  1650  *
  1534  * For example, '/foo/bar', or 'c:\windows'.
  1651  * For example, '/foo/bar', or 'c:\windows'.
  1535  *
  1652  *
  1536  * @since 2.5.0
  1653  * @since 2.5.0
  1537  *
  1654  *
  1577 }
  1694 }
  1578 
  1695 
  1579 /**
  1696 /**
  1580  * Normalize a filesystem path.
  1697  * Normalize a filesystem path.
  1581  *
  1698  *
  1582  * Replaces backslashes with forward slashes for Windows systems, and ensures
  1699  * On windows systems, replaces backslashes with forward slashes
  1583  * no duplicate slashes exist.
  1700  * and forces upper-case drive letters.
       
  1701  * Allows for two leading slashes for Windows network shares, but
       
  1702  * ensures that all other duplicate slashes are reduced to a single.
  1584  *
  1703  *
  1585  * @since 3.9.0
  1704  * @since 3.9.0
       
  1705  * @since 4.4.0 Ensures upper-case drive letters on Windows systems.
       
  1706  * @since 4.5.0 Allows for Windows network shares.
       
  1707  * @since 4.9.7 Allows for PHP file wrappers.
  1586  *
  1708  *
  1587  * @param string $path Path to normalize.
  1709  * @param string $path Path to normalize.
  1588  * @return string Normalized path.
  1710  * @return string Normalized path.
  1589  */
  1711  */
  1590 function wp_normalize_path( $path ) {
  1712 function wp_normalize_path( $path ) {
       
  1713 	$wrapper = '';
       
  1714 	if ( wp_is_stream( $path ) ) {
       
  1715 		list( $wrapper, $path ) = explode( '://', $path, 2 );
       
  1716 		$wrapper .= '://';
       
  1717 	}
       
  1718 
       
  1719 	// Standardise all paths to use /
  1591 	$path = str_replace( '\\', '/', $path );
  1720 	$path = str_replace( '\\', '/', $path );
  1592 	$path = preg_replace( '|/+|','/', $path );
  1721 
  1593 	return $path;
  1722 	// Replace multiple slashes down to a singular, allowing for network shares having two slashes.
       
  1723 	$path = preg_replace( '|(?<=.)/+|', '/', $path );
       
  1724 
       
  1725 	// Windows paths should uppercase the drive letter
       
  1726 	if ( ':' === substr( $path, 1, 1 ) ) {
       
  1727 		$path = ucfirst( $path );
       
  1728 	}
       
  1729 
       
  1730 	return $wrapper . $path;
  1594 }
  1731 }
  1595 
  1732 
  1596 /**
  1733 /**
  1597  * Determine a writable directory for temporary files.
  1734  * Determine a writable directory for temporary files.
  1598  *
  1735  *
  1603  * In the event that this function does not find a writable location,
  1740  * In the event that this function does not find a writable location,
  1604  * It may be overridden by the WP_TEMP_DIR constant in your wp-config.php file.
  1741  * It may be overridden by the WP_TEMP_DIR constant in your wp-config.php file.
  1605  *
  1742  *
  1606  * @since 2.5.0
  1743  * @since 2.5.0
  1607  *
  1744  *
       
  1745  * @staticvar string $temp
       
  1746  *
  1608  * @return string Writable temporary directory.
  1747  * @return string Writable temporary directory.
  1609  */
  1748  */
  1610 function get_temp_dir() {
  1749 function get_temp_dir() {
  1611 	static $temp;
  1750 	static $temp = '';
  1612 	if ( defined('WP_TEMP_DIR') )
  1751 	if ( defined('WP_TEMP_DIR') )
  1613 		return trailingslashit(WP_TEMP_DIR);
  1752 		return trailingslashit(WP_TEMP_DIR);
  1614 
  1753 
  1615 	if ( $temp )
  1754 	if ( $temp )
  1616 		return trailingslashit( $temp );
  1755 		return trailingslashit( $temp );
  1627 
  1766 
  1628 	$temp = WP_CONTENT_DIR . '/';
  1767 	$temp = WP_CONTENT_DIR . '/';
  1629 	if ( is_dir( $temp ) && wp_is_writable( $temp ) )
  1768 	if ( is_dir( $temp ) && wp_is_writable( $temp ) )
  1630 		return $temp;
  1769 		return $temp;
  1631 
  1770 
  1632 	$temp = '/tmp/';
  1771 	return '/tmp/';
  1633 	return $temp;
       
  1634 }
  1772 }
  1635 
  1773 
  1636 /**
  1774 /**
  1637  * Determine if a directory is writable.
  1775  * Determine if a directory is writable.
  1638  *
  1776  *
  1661  * checking the ability to open files rather than relying
  1799  * checking the ability to open files rather than relying
  1662  * upon PHP to interprate the OS ACL.
  1800  * upon PHP to interprate the OS ACL.
  1663  *
  1801  *
  1664  * @since 2.8.0
  1802  * @since 2.8.0
  1665  *
  1803  *
  1666  * @see http://bugs.php.net/bug.php?id=27609
  1804  * @see https://bugs.php.net/bug.php?id=27609
  1667  * @see http://bugs.php.net/bug.php?id=30931
  1805  * @see https://bugs.php.net/bug.php?id=30931
  1668  *
  1806  *
  1669  * @param string $path Windows path to check for write-ability.
  1807  * @param string $path Windows path to check for write-ability.
  1670  * @return bool Whether the path is writable.
  1808  * @return bool Whether the path is writable.
  1671  */
  1809  */
  1672 function win_is_writable( $path ) {
  1810 function win_is_writable( $path ) {
  1686 		unlink( $path );
  1824 		unlink( $path );
  1687 	return true;
  1825 	return true;
  1688 }
  1826 }
  1689 
  1827 
  1690 /**
  1828 /**
       
  1829  * Retrieves uploads directory information.
       
  1830  *
       
  1831  * Same as wp_upload_dir() but "light weight" as it doesn't attempt to create the uploads directory.
       
  1832  * Intended for use in themes, when only 'basedir' and 'baseurl' are needed, generally in all cases
       
  1833  * when not uploading files.
       
  1834  *
       
  1835  * @since 4.5.0
       
  1836  *
       
  1837  * @see wp_upload_dir()
       
  1838  *
       
  1839  * @return array See wp_upload_dir() for description.
       
  1840  */
       
  1841 function wp_get_upload_dir() {
       
  1842 	return wp_upload_dir( null, false );
       
  1843 }
       
  1844 
       
  1845 /**
  1691  * Get an array containing the current upload directory's path and url.
  1846  * Get an array containing the current upload directory's path and url.
  1692  *
  1847  *
  1693  * Checks the 'upload_path' option, which should be from the web root folder,
  1848  * Checks the 'upload_path' option, which should be from the web root folder,
  1694  * and if it isn't empty it will be used. If it is empty, then the path will be
  1849  * and if it isn't empty it will be used. If it is empty, then the path will be
  1695  * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
  1850  * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
  1710  * 'path' - base directory and sub directory or full path to upload directory.
  1865  * 'path' - base directory and sub directory or full path to upload directory.
  1711  * 'url' - base url and sub directory or absolute URL to upload directory.
  1866  * 'url' - base url and sub directory or absolute URL to upload directory.
  1712  * 'subdir' - sub directory if uploads use year/month folders option is on.
  1867  * 'subdir' - sub directory if uploads use year/month folders option is on.
  1713  * 'basedir' - path without subdir.
  1868  * 'basedir' - path without subdir.
  1714  * 'baseurl' - URL path without subdir.
  1869  * 'baseurl' - URL path without subdir.
  1715  * 'error' - set to false.
  1870  * 'error' - false or error message.
  1716  *
  1871  *
  1717  * @since 2.0.0
  1872  * @since 2.0.0
       
  1873  * @uses _wp_upload_dir()
       
  1874  *
       
  1875  * @staticvar array $cache
       
  1876  * @staticvar array $tested_paths
  1718  *
  1877  *
  1719  * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null.
  1878  * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null.
       
  1879  * @param bool   $create_dir Optional. Whether to check and create the uploads directory.
       
  1880  *                           Default true for backward compatibility.
       
  1881  * @param bool   $refresh_cache Optional. Whether to refresh the cache. Default false.
  1720  * @return array See above for description.
  1882  * @return array See above for description.
  1721  */
  1883  */
  1722 function wp_upload_dir( $time = null ) {
  1884 function wp_upload_dir( $time = null, $create_dir = true, $refresh_cache = false ) {
       
  1885 	static $cache = array(), $tested_paths = array();
       
  1886 
       
  1887 	$key = sprintf( '%d-%s', get_current_blog_id(), (string) $time );
       
  1888 
       
  1889 	if ( $refresh_cache || empty( $cache[ $key ] ) ) {
       
  1890 		$cache[ $key ] = _wp_upload_dir( $time );
       
  1891 	}
       
  1892 
       
  1893 	/**
       
  1894 	 * Filters the uploads directory data.
       
  1895 	 *
       
  1896 	 * @since 2.0.0
       
  1897 	 *
       
  1898 	 * @param array $uploads Array of upload directory data with keys of 'path',
       
  1899 	 *                       'url', 'subdir, 'basedir', and 'error'.
       
  1900 	 */
       
  1901 	$uploads = apply_filters( 'upload_dir', $cache[ $key ] );
       
  1902 
       
  1903 	if ( $create_dir ) {
       
  1904 		$path = $uploads['path'];
       
  1905 
       
  1906 		if ( array_key_exists( $path, $tested_paths ) ) {
       
  1907 			$uploads['error'] = $tested_paths[ $path ];
       
  1908 		} else {
       
  1909 			if ( ! wp_mkdir_p( $path ) ) {
       
  1910 				if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) {
       
  1911 					$error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir'];
       
  1912 				} else {
       
  1913 					$error_path = basename( $uploads['basedir'] ) . $uploads['subdir'];
       
  1914 				}
       
  1915 
       
  1916 				$uploads['error'] = sprintf(
       
  1917 					/* translators: %s: directory path */
       
  1918 					__( 'Unable to create directory %s. Is its parent directory writable by the server?' ),
       
  1919 					esc_html( $error_path )
       
  1920 				);
       
  1921 			}
       
  1922 
       
  1923 			$tested_paths[ $path ] = $uploads['error'];
       
  1924 		}
       
  1925 	}
       
  1926 
       
  1927 	return $uploads;
       
  1928 }
       
  1929 
       
  1930 /**
       
  1931  * A non-filtered, non-cached version of wp_upload_dir() that doesn't check the path.
       
  1932  *
       
  1933  * @since 4.5.0
       
  1934  * @access private
       
  1935  *
       
  1936  * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null.
       
  1937  * @return array See wp_upload_dir()
       
  1938  */
       
  1939 function _wp_upload_dir( $time = null ) {
  1723 	$siteurl = get_option( 'siteurl' );
  1940 	$siteurl = get_option( 'siteurl' );
  1724 	$upload_path = trim( get_option( 'upload_path' ) );
  1941 	$upload_path = trim( get_option( 'upload_path' ) );
  1725 
  1942 
  1726 	if ( empty( $upload_path ) || 'wp-content/uploads' == $upload_path ) {
  1943 	if ( empty( $upload_path ) || 'wp-content/uploads' == $upload_path ) {
  1727 		$dir = WP_CONTENT_DIR . '/uploads';
  1944 		$dir = WP_CONTENT_DIR . '/uploads';
  1806 	}
  2023 	}
  1807 
  2024 
  1808 	$dir .= $subdir;
  2025 	$dir .= $subdir;
  1809 	$url .= $subdir;
  2026 	$url .= $subdir;
  1810 
  2027 
  1811 	/**
  2028 	return array(
  1812 	 * Filter the uploads directory data.
  2029 		'path'    => $dir,
  1813 	 *
  2030 		'url'     => $url,
  1814 	 * @since 2.0.0
  2031 		'subdir'  => $subdir,
  1815 	 *
  2032 		'basedir' => $basedir,
  1816 	 * @param array $uploads Array of upload directory data with keys of 'path',
  2033 		'baseurl' => $baseurl,
  1817 	 *                       'url', 'subdir, 'basedir', and 'error'.
  2034 		'error'   => false,
  1818 	 */
  2035 	);
  1819 	$uploads = apply_filters( 'upload_dir',
       
  1820 		array(
       
  1821 			'path'    => $dir,
       
  1822 			'url'     => $url,
       
  1823 			'subdir'  => $subdir,
       
  1824 			'basedir' => $basedir,
       
  1825 			'baseurl' => $baseurl,
       
  1826 			'error'   => false,
       
  1827 		) );
       
  1828 
       
  1829 	// Make sure we have an uploads directory.
       
  1830 	if ( ! wp_mkdir_p( $uploads['path'] ) ) {
       
  1831 		if ( 0 === strpos( $uploads['basedir'], ABSPATH ) )
       
  1832 			$error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir'];
       
  1833 		else
       
  1834 			$error_path = basename( $uploads['basedir'] ) . $uploads['subdir'];
       
  1835 
       
  1836 		$message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path );
       
  1837 		$uploads['error'] = $message;
       
  1838 	}
       
  1839 
       
  1840 	return $uploads;
       
  1841 }
  2036 }
  1842 
  2037 
  1843 /**
  2038 /**
  1844  * Get a filename that is sanitized and unique for the given directory.
  2039  * Get a filename that is sanitized and unique for the given directory.
  1845  *
  2040  *
  1852  *
  2047  *
  1853  * @since 2.5.0
  2048  * @since 2.5.0
  1854  *
  2049  *
  1855  * @param string   $dir                      Directory.
  2050  * @param string   $dir                      Directory.
  1856  * @param string   $filename                 File name.
  2051  * @param string   $filename                 File name.
  1857  * @param callback $unique_filename_callback Callback. Default null.
  2052  * @param callable $unique_filename_callback Callback. Default null.
  1858  * @return string New filename, if given wasn't unique.
  2053  * @return string New filename, if given wasn't unique.
  1859  */
  2054  */
  1860 function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
  2055 function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
  1861 	// Sanitize the file name before we begin processing.
  2056 	// Sanitize the file name before we begin processing.
  1862 	$filename = sanitize_file_name($filename);
  2057 	$filename = sanitize_file_name($filename);
  1863 
  2058 
  1864 	// Separate the filename into a name and extension.
  2059 	// Separate the filename into a name and extension.
  1865 	$info = pathinfo($filename);
  2060 	$ext = pathinfo( $filename, PATHINFO_EXTENSION );
  1866 	$ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
  2061 	$name = pathinfo( $filename, PATHINFO_BASENAME );
  1867 	$name = basename($filename, $ext);
  2062 	if ( $ext ) {
       
  2063 		$ext = '.' . $ext;
       
  2064 	}
  1868 
  2065 
  1869 	// Edge case: if file is named '.ext', treat as an empty name.
  2066 	// Edge case: if file is named '.ext', treat as an empty name.
  1870 	if ( $name === $ext )
  2067 	if ( $name === $ext ) {
  1871 		$name = '';
  2068 		$name = '';
       
  2069 	}
  1872 
  2070 
  1873 	/*
  2071 	/*
  1874 	 * Increment the file number until we have a unique file to save in $dir.
  2072 	 * Increment the file number until we have a unique file to save in $dir.
  1875 	 * Use callback if supplied.
  2073 	 * Use callback if supplied.
  1876 	 */
  2074 	 */
  1884 			$ext2 = strtolower($ext);
  2082 			$ext2 = strtolower($ext);
  1885 			$filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename );
  2083 			$filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename );
  1886 
  2084 
  1887 			// Check for both lower and upper case extension or image sub-sizes may be overwritten.
  2085 			// Check for both lower and upper case extension or image sub-sizes may be overwritten.
  1888 			while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) {
  2086 			while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) {
  1889 				$new_number = $number + 1;
  2087 				$new_number = (int) $number + 1;
  1890 				$filename = str_replace( "$number$ext", "$new_number$ext", $filename );
  2088 				$filename = str_replace( array( "-$number$ext", "$number$ext" ), "-$new_number$ext", $filename );
  1891 				$filename2 = str_replace( "$number$ext2", "$new_number$ext2", $filename2 );
  2089 				$filename2 = str_replace( array( "-$number$ext2", "$number$ext2" ), "-$new_number$ext2", $filename2 );
  1892 				$number = $new_number;
  2090 				$number = $new_number;
  1893 			}
  2091 			}
  1894 			return $filename2;
  2092 
       
  2093 			/**
       
  2094 			 * Filters the result when generating a unique file name.
       
  2095 			 *
       
  2096 			 * @since 4.5.0
       
  2097 			 *
       
  2098 			 * @param string        $filename                 Unique file name.
       
  2099 			 * @param string        $ext                      File extension, eg. ".png".
       
  2100 			 * @param string        $dir                      Directory path.
       
  2101 			 * @param callable|null $unique_filename_callback Callback function that generates the unique file name.
       
  2102 			 */
       
  2103 			return apply_filters( 'wp_unique_filename', $filename2, $ext, $dir, $unique_filename_callback );
  1895 		}
  2104 		}
  1896 
  2105 
  1897 		while ( file_exists( $dir . "/$filename" ) ) {
  2106 		while ( file_exists( $dir . "/$filename" ) ) {
  1898 			if ( '' == "$number$ext" )
  2107 			$new_number = (int) $number + 1;
  1899 				$filename = $filename . ++$number . $ext;
  2108 			if ( '' == "$number$ext" ) {
  1900 			else
  2109 				$filename = "$filename-" . $new_number;
  1901 				$filename = str_replace( "$number$ext", ++$number . $ext, $filename );
  2110 			} else {
  1902 		}
  2111 				$filename = str_replace( array( "-$number$ext", "$number$ext" ), "-" . $new_number . $ext, $filename );
  1903 	}
  2112 			}
  1904 
  2113 			$number = $new_number;
  1905 	return $filename;
  2114 		}
       
  2115 	}
       
  2116 
       
  2117 	/** This filter is documented in wp-includes/functions.php */
       
  2118 	return apply_filters( 'wp_unique_filename', $filename, $ext, $dir, $unique_filename_callback );
  1906 }
  2119 }
  1907 
  2120 
  1908 /**
  2121 /**
  1909  * Create a file in the upload folder with given content.
  2122  * Create a file in the upload folder with given content.
  1910  *
  2123  *
  1928  * @param string       $time       Optional. Time formatted in 'yyyy/mm'. Default null.
  2141  * @param string       $time       Optional. Time formatted in 'yyyy/mm'. Default null.
  1929  * @return array
  2142  * @return array
  1930  */
  2143  */
  1931 function wp_upload_bits( $name, $deprecated, $bits, $time = null ) {
  2144 function wp_upload_bits( $name, $deprecated, $bits, $time = null ) {
  1932 	if ( !empty( $deprecated ) )
  2145 	if ( !empty( $deprecated ) )
  1933 		_deprecated_argument( __FUNCTION__, '2.0' );
  2146 		_deprecated_argument( __FUNCTION__, '2.0.0' );
  1934 
  2147 
  1935 	if ( empty( $name ) )
  2148 	if ( empty( $name ) )
  1936 		return array( 'error' => __( 'Empty filename' ) );
  2149 		return array( 'error' => __( 'Empty filename' ) );
  1937 
  2150 
  1938 	$wp_filetype = wp_check_filetype( $name );
  2151 	$wp_filetype = wp_check_filetype( $name );
  1939 	if ( ! $wp_filetype['ext'] && ! current_user_can( 'unfiltered_upload' ) )
  2152 	if ( ! $wp_filetype['ext'] && ! current_user_can( 'unfiltered_upload' ) )
  1940 		return array( 'error' => __( 'Invalid file type' ) );
  2153 		return array( 'error' => __( 'Sorry, this file type is not permitted for security reasons.' ) );
  1941 
  2154 
  1942 	$upload = wp_upload_dir( $time );
  2155 	$upload = wp_upload_dir( $time );
  1943 
  2156 
  1944 	if ( $upload['error'] !== false )
  2157 	if ( $upload['error'] !== false )
  1945 		return $upload;
  2158 		return $upload;
  1946 
  2159 
  1947 	/**
  2160 	/**
  1948 	 * Filter whether to treat the upload bits as an error.
  2161 	 * Filters whether to treat the upload bits as an error.
  1949 	 *
  2162 	 *
  1950 	 * Passing a non-array to the filter will effectively short-circuit preparing
  2163 	 * Passing a non-array to the filter will effectively short-circuit preparing
  1951 	 * the upload bits, returning that value instead.
  2164 	 * the upload bits, returning that value instead.
  1952 	 *
  2165 	 *
  1953 	 * @since 3.0.0
  2166 	 * @since 3.0.0
  1967 		if ( 0 === strpos( $upload['basedir'], ABSPATH ) )
  2180 		if ( 0 === strpos( $upload['basedir'], ABSPATH ) )
  1968 			$error_path = str_replace( ABSPATH, '', $upload['basedir'] ) . $upload['subdir'];
  2181 			$error_path = str_replace( ABSPATH, '', $upload['basedir'] ) . $upload['subdir'];
  1969 		else
  2182 		else
  1970 			$error_path = basename( $upload['basedir'] ) . $upload['subdir'];
  2183 			$error_path = basename( $upload['basedir'] ) . $upload['subdir'];
  1971 
  2184 
  1972 		$message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path );
  2185 		$message = sprintf(
       
  2186 			/* translators: %s: directory path */
       
  2187 			__( 'Unable to create directory %s. Is its parent directory writable by the server?' ),
       
  2188 			$error_path
       
  2189 		);
  1973 		return array( 'error' => $message );
  2190 		return array( 'error' => $message );
  1974 	}
  2191 	}
  1975 
  2192 
  1976 	$ifp = @ fopen( $new_file, 'wb' );
  2193 	$ifp = @ fopen( $new_file, 'wb' );
  1977 	if ( ! $ifp )
  2194 	if ( ! $ifp )
  1989 	clearstatcache();
  2206 	clearstatcache();
  1990 
  2207 
  1991 	// Compute the URL
  2208 	// Compute the URL
  1992 	$url = $upload['url'] . "/$filename";
  2209 	$url = $upload['url'] . "/$filename";
  1993 
  2210 
  1994 	return array( 'file' => $new_file, 'url' => $url, 'error' => false );
  2211 	/** This filter is documented in wp-admin/includes/file.php */
       
  2212 	return apply_filters( 'wp_handle_upload', array( 'file' => $new_file, 'url' => $url, 'type' => $wp_filetype['type'], 'error' => false ), 'sideload' );
  1995 }
  2213 }
  1996 
  2214 
  1997 /**
  2215 /**
  1998  * Retrieve the file type based on the extension name.
  2216  * Retrieve the file type based on the extension name.
  1999  *
  2217  *
  2000  * @since 2.5.0
  2218  * @since 2.5.0
  2001  *
  2219  *
  2002  * @param string $ext The extension to search.
  2220  * @param string $ext The extension to search.
  2003  * @return string|null The file type, example: audio, video, document, spreadsheet, etc.
  2221  * @return string|void The file type, example: audio, video, document, spreadsheet, etc.
  2004  *                     Null if not found.
       
  2005  */
  2222  */
  2006 function wp_ext2type( $ext ) {
  2223 function wp_ext2type( $ext ) {
  2007 	$ext = strtolower( $ext );
  2224 	$ext = strtolower( $ext );
  2008 
  2225 
  2009 	/**
  2226 	$ext2type = wp_get_ext_types();
  2010 	 * Filter file type based on the extension name.
       
  2011 	 *
       
  2012 	 * @since 2.5.0
       
  2013 	 *
       
  2014 	 * @see wp_ext2type()
       
  2015 	 *
       
  2016 	 * @param array $ext2type Multi-dimensional array with extensions for a default set
       
  2017 	 *                        of file types.
       
  2018 	 */
       
  2019 	$ext2type = apply_filters( 'ext2type', array(
       
  2020 		'image'       => array( 'jpg', 'jpeg', 'jpe',  'gif',  'png',  'bmp',   'tif',  'tiff', 'ico' ),
       
  2021 		'audio'       => array( 'aac', 'ac3',  'aif',  'aiff', 'm3a',  'm4a',   'm4b',  'mka',  'mp1',  'mp2',  'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
       
  2022 		'video'       => array( '3g2',  '3gp', '3gpp', 'asf', 'avi',  'divx', 'dv',   'flv',  'm4v',   'mkv',  'mov',  'mp4',  'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt',  'rm', 'vob', 'wmv' ),
       
  2023 		'document'    => array( 'doc', 'docx', 'docm', 'dotm', 'odt',  'pages', 'pdf',  'xps',  'oxps', 'rtf',  'wp', 'wpd', 'psd', 'xcf' ),
       
  2024 		'spreadsheet' => array( 'numbers',     'ods',  'xls',  'xlsx', 'xlsm',  'xlsb' ),
       
  2025 		'interactive' => array( 'swf', 'key',  'ppt',  'pptx', 'pptm', 'pps',   'ppsx', 'ppsm', 'sldx', 'sldm', 'odp' ),
       
  2026 		'text'        => array( 'asc', 'csv',  'tsv',  'txt' ),
       
  2027 		'archive'     => array( 'bz2', 'cab',  'dmg',  'gz',   'rar',  'sea',   'sit',  'sqx',  'tar',  'tgz',  'zip', '7z' ),
       
  2028 		'code'        => array( 'css', 'htm',  'html', 'php',  'js' ),
       
  2029 	) );
       
  2030 
       
  2031 	foreach ( $ext2type as $type => $exts )
  2227 	foreach ( $ext2type as $type => $exts )
  2032 		if ( in_array( $ext, $exts ) )
  2228 		if ( in_array( $ext, $exts ) )
  2033 			return $type;
  2229 			return $type;
  2034 
       
  2035 	return null;
       
  2036 }
  2230 }
  2037 
  2231 
  2038 /**
  2232 /**
  2039  * Retrieve the file type from the file name.
  2233  * Retrieve the file type from the file name.
  2040  *
  2234  *
  2070  * If unable to, the file name extension will be used to determine type.
  2264  * If unable to, the file name extension will be used to determine type.
  2071  *
  2265  *
  2072  * If it's determined that the extension does not match the file's real type,
  2266  * If it's determined that the extension does not match the file's real type,
  2073  * then the "proper_filename" value will be set with a proper filename and extension.
  2267  * then the "proper_filename" value will be set with a proper filename and extension.
  2074  *
  2268  *
  2075  * Currently this function only supports validating images known to getimagesize().
  2269  * Currently this function only supports renaming images validated via wp_get_image_mime().
  2076  *
  2270  *
  2077  * @since 3.0.0
  2271  * @since 3.0.0
  2078  *
  2272  *
  2079  * @param string $file     Full path to the file.
  2273  * @param string $file     Full path to the file.
  2080  * @param string $filename The name of the file (may differ from $file due to $file being
  2274  * @param string $filename The name of the file (may differ from $file due to $file being
  2082  * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
  2276  * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
  2083  * @return array Values for the extension, MIME, and either a corrected filename or false
  2277  * @return array Values for the extension, MIME, and either a corrected filename or false
  2084  *               if original $filename is valid.
  2278  *               if original $filename is valid.
  2085  */
  2279  */
  2086 function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
  2280 function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
  2087 
       
  2088 	$proper_filename = false;
  2281 	$proper_filename = false;
  2089 
  2282 
  2090 	// Do basic extension validation and MIME mapping
  2283 	// Do basic extension validation and MIME mapping
  2091 	$wp_filetype = wp_check_filetype( $filename, $mimes );
  2284 	$wp_filetype = wp_check_filetype( $filename, $mimes );
  2092 	$ext = $wp_filetype['ext'];
  2285 	$ext = $wp_filetype['ext'];
  2095 	// We can't do any further validation without a file to work with
  2288 	// We can't do any further validation without a file to work with
  2096 	if ( ! file_exists( $file ) ) {
  2289 	if ( ! file_exists( $file ) ) {
  2097 		return compact( 'ext', 'type', 'proper_filename' );
  2290 		return compact( 'ext', 'type', 'proper_filename' );
  2098 	}
  2291 	}
  2099 
  2292 
  2100 	// We're able to validate images using GD
  2293 	$real_mime = false;
  2101 	if ( $type && 0 === strpos( $type, 'image/' ) && function_exists('getimagesize') ) {
  2294 
       
  2295 	// Validate image types.
       
  2296 	if ( $type && 0 === strpos( $type, 'image/' ) ) {
  2102 
  2297 
  2103 		// Attempt to figure out what type of image it actually is
  2298 		// Attempt to figure out what type of image it actually is
  2104 		$imgstats = @getimagesize( $file );
  2299 		$real_mime = wp_get_image_mime( $file );
  2105 
  2300 
  2106 		// If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
  2301 		if ( $real_mime && $real_mime != $type ) {
  2107 		if ( !empty($imgstats['mime']) && $imgstats['mime'] != $type ) {
       
  2108 			/**
  2302 			/**
  2109 			 * Filter the list mapping image mime types to their respective extensions.
  2303 			 * Filters the list mapping image mime types to their respective extensions.
  2110 			 *
  2304 			 *
  2111 			 * @since 3.0.0
  2305 			 * @since 3.0.0
  2112 			 *
  2306 			 *
  2113 			 * @param  array $mime_to_ext Array of image mime types and their matching extensions.
  2307 			 * @param  array $mime_to_ext Array of image mime types and their matching extensions.
  2114 			 */
  2308 			 */
  2119 				'image/bmp'  => 'bmp',
  2313 				'image/bmp'  => 'bmp',
  2120 				'image/tiff' => 'tif',
  2314 				'image/tiff' => 'tif',
  2121 			) );
  2315 			) );
  2122 
  2316 
  2123 			// Replace whatever is after the last period in the filename with the correct extension
  2317 			// Replace whatever is after the last period in the filename with the correct extension
  2124 			if ( ! empty( $mime_to_ext[ $imgstats['mime'] ] ) ) {
  2318 			if ( ! empty( $mime_to_ext[ $real_mime ] ) ) {
  2125 				$filename_parts = explode( '.', $filename );
  2319 				$filename_parts = explode( '.', $filename );
  2126 				array_pop( $filename_parts );
  2320 				array_pop( $filename_parts );
  2127 				$filename_parts[] = $mime_to_ext[ $imgstats['mime'] ];
  2321 				$filename_parts[] = $mime_to_ext[ $real_mime ];
  2128 				$new_filename = implode( '.', $filename_parts );
  2322 				$new_filename = implode( '.', $filename_parts );
  2129 
  2323 
  2130 				if ( $new_filename != $filename ) {
  2324 				if ( $new_filename != $filename ) {
  2131 					$proper_filename = $new_filename; // Mark that it changed
  2325 					$proper_filename = $new_filename; // Mark that it changed
  2132 				}
  2326 				}
  2133 				// Redefine the extension / MIME
  2327 				// Redefine the extension / MIME
  2134 				$wp_filetype = wp_check_filetype( $new_filename, $mimes );
  2328 				$wp_filetype = wp_check_filetype( $new_filename, $mimes );
  2135 				$ext = $wp_filetype['ext'];
  2329 				$ext = $wp_filetype['ext'];
  2136 				$type = $wp_filetype['type'];
  2330 				$type = $wp_filetype['type'];
       
  2331 			} else {
       
  2332 				// Reset $real_mime and try validating again.
       
  2333 				$real_mime = false;
  2137 			}
  2334 			}
  2138 		}
  2335 		}
  2139 	}
  2336 	}
  2140 
  2337 
       
  2338 	// Validate files that didn't get validated during previous checks.
       
  2339 	if ( $type && ! $real_mime && extension_loaded( 'fileinfo' ) ) {
       
  2340 		$finfo = finfo_open( FILEINFO_MIME_TYPE );
       
  2341 		$real_mime = finfo_file( $finfo, $file );
       
  2342 		finfo_close( $finfo );
       
  2343 
       
  2344 		/*
       
  2345 		 * If $real_mime doesn't match what we're expecting, we need to do some extra
       
  2346 		 * vetting of application mime types to make sure this type of file is allowed.
       
  2347 		 * Other mime types are assumed to be safe, but should be considered unverified.
       
  2348 		 */
       
  2349 		if ( $real_mime && ( $real_mime !== $type ) && ( 0 === strpos( $real_mime, 'application' ) ) ) {
       
  2350 			$allowed = get_allowed_mime_types();
       
  2351 
       
  2352 			if ( ! in_array( $real_mime, $allowed ) ) {
       
  2353 				$type = $ext = false;
       
  2354 			}
       
  2355 		}
       
  2356 	}
       
  2357 
  2141 	/**
  2358 	/**
  2142 	 * Filter the "real" file type of the given file.
  2359 	 * Filters the "real" file type of the given file.
  2143 	 *
  2360 	 *
  2144 	 * @since 3.0.0
  2361 	 * @since 3.0.0
  2145 	 *
  2362 	 *
  2146 	 * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
  2363 	 * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
  2147 	 *                                          'proper_filename' keys.
  2364 	 *                                          'proper_filename' keys.
  2152 	 */
  2369 	 */
  2153 	return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes );
  2370 	return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes );
  2154 }
  2371 }
  2155 
  2372 
  2156 /**
  2373 /**
       
  2374  * Returns the real mime type of an image file.
       
  2375  *
       
  2376  * This depends on exif_imagetype() or getimagesize() to determine real mime types.
       
  2377  *
       
  2378  * @since 4.7.1
       
  2379  *
       
  2380  * @param string $file Full path to the file.
       
  2381  * @return string|false The actual mime type or false if the type cannot be determined.
       
  2382  */
       
  2383 function wp_get_image_mime( $file ) {
       
  2384 	/*
       
  2385 	 * Use exif_imagetype() to check the mimetype if available or fall back to
       
  2386 	 * getimagesize() if exif isn't avaialbe. If either function throws an Exception
       
  2387 	 * we assume the file could not be validated.
       
  2388 	 */
       
  2389 	try {
       
  2390 		if ( is_callable( 'exif_imagetype' ) ) {
       
  2391 			$imagetype = exif_imagetype( $file );
       
  2392 			$mime = ( $imagetype ) ? image_type_to_mime_type( $imagetype ) : false;
       
  2393 		} elseif ( function_exists( 'getimagesize' ) ) {
       
  2394 			$imagesize = getimagesize( $file );
       
  2395 			$mime = ( isset( $imagesize['mime'] ) ) ? $imagesize['mime'] : false;
       
  2396 		} else {
       
  2397 			$mime = false;
       
  2398 		}
       
  2399 	} catch ( Exception $e ) {
       
  2400 		$mime = false;
       
  2401 	}
       
  2402 
       
  2403 	return $mime;
       
  2404 }
       
  2405 
       
  2406 /**
  2157  * Retrieve list of mime types and file extensions.
  2407  * Retrieve list of mime types and file extensions.
  2158  *
  2408  *
  2159  * @since 3.5.0
  2409  * @since 3.5.0
  2160  * @since 4.2.0 Support was added for GIMP (xcf) files.
  2410  * @since 4.2.0 Support was added for GIMP (xcf) files.
  2161  *
  2411  *
  2162  * @return array Array of mime types keyed by the file extension regex corresponding to those types.
  2412  * @return array Array of mime types keyed by the file extension regex corresponding to those types.
  2163  */
  2413  */
  2164 function wp_get_mime_types() {
  2414 function wp_get_mime_types() {
  2165 	/**
  2415 	/**
  2166 	 * Filter the list of mime types and file extensions.
  2416 	 * Filters the list of mime types and file extensions.
  2167 	 *
  2417 	 *
  2168 	 * This filter should be used to add, not remove, mime types. To remove
  2418 	 * This filter should be used to add, not remove, mime types. To remove
  2169 	 * mime types, use the 'upload_mimes' filter.
  2419 	 * mime types, use the {@see 'upload_mimes'} filter.
  2170 	 *
  2420 	 *
  2171 	 * @since 3.5.0
  2421 	 * @since 3.5.0
  2172 	 *
  2422 	 *
  2173 	 * @param array $wp_get_mime_types Mime types keyed by the file extension regex
  2423 	 * @param array $wp_get_mime_types Mime types keyed by the file extension regex
  2174 	 *                                 corresponding to those types.
  2424 	 *                                 corresponding to those types.
  2207 	'htm|html' => 'text/html',
  2457 	'htm|html' => 'text/html',
  2208 	'vtt' => 'text/vtt',
  2458 	'vtt' => 'text/vtt',
  2209 	'dfxp' => 'application/ttaf+xml',
  2459 	'dfxp' => 'application/ttaf+xml',
  2210 	// Audio formats.
  2460 	// Audio formats.
  2211 	'mp3|m4a|m4b' => 'audio/mpeg',
  2461 	'mp3|m4a|m4b' => 'audio/mpeg',
       
  2462 	'aac' => 'audio/aac',
  2212 	'ra|ram' => 'audio/x-realaudio',
  2463 	'ra|ram' => 'audio/x-realaudio',
  2213 	'wav' => 'audio/wav',
  2464 	'wav' => 'audio/wav',
  2214 	'ogg|oga' => 'audio/ogg',
  2465 	'ogg|oga' => 'audio/ogg',
       
  2466 	'flac' => 'audio/flac',
  2215 	'mid|midi' => 'audio/midi',
  2467 	'mid|midi' => 'audio/midi',
  2216 	'wma' => 'audio/x-ms-wma',
  2468 	'wma' => 'audio/x-ms-wma',
  2217 	'wax' => 'audio/x-ms-wax',
  2469 	'wax' => 'audio/x-ms-wax',
  2218 	'mka' => 'audio/x-matroska',
  2470 	'mka' => 'audio/x-matroska',
  2219 	// Misc application formats.
  2471 	// Misc application formats.
  2273 	'key' => 'application/vnd.apple.keynote',
  2525 	'key' => 'application/vnd.apple.keynote',
  2274 	'numbers' => 'application/vnd.apple.numbers',
  2526 	'numbers' => 'application/vnd.apple.numbers',
  2275 	'pages' => 'application/vnd.apple.pages',
  2527 	'pages' => 'application/vnd.apple.pages',
  2276 	) );
  2528 	) );
  2277 }
  2529 }
       
  2530 
       
  2531 /**
       
  2532  * Retrieves the list of common file extensions and their types.
       
  2533  *
       
  2534  * @since 4.6.0
       
  2535  *
       
  2536  * @return array Array of file extensions types keyed by the type of file.
       
  2537  */
       
  2538 function wp_get_ext_types() {
       
  2539 
       
  2540 	/**
       
  2541 	 * Filters file type based on the extension name.
       
  2542 	 *
       
  2543 	 * @since 2.5.0
       
  2544 	 *
       
  2545 	 * @see wp_ext2type()
       
  2546 	 *
       
  2547 	 * @param array $ext2type Multi-dimensional array with extensions for a default set
       
  2548 	 *                        of file types.
       
  2549 	 */
       
  2550 	return apply_filters( 'ext2type', array(
       
  2551 		'image'       => array( 'jpg', 'jpeg', 'jpe',  'gif',  'png',  'bmp',   'tif',  'tiff', 'ico' ),
       
  2552 		'audio'       => array( 'aac', 'ac3',  'aif',  'aiff', 'flac', 'm3a',  'm4a',   'm4b',  'mka',  'mp1',  'mp2',  'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
       
  2553 		'video'       => array( '3g2',  '3gp', '3gpp', 'asf', 'avi',  'divx', 'dv',   'flv',  'm4v',   'mkv',  'mov',  'mp4',  'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt',  'rm', 'vob', 'wmv' ),
       
  2554 		'document'    => array( 'doc', 'docx', 'docm', 'dotm', 'odt',  'pages', 'pdf',  'xps',  'oxps', 'rtf',  'wp', 'wpd', 'psd', 'xcf' ),
       
  2555 		'spreadsheet' => array( 'numbers',     'ods',  'xls',  'xlsx', 'xlsm',  'xlsb' ),
       
  2556 		'interactive' => array( 'swf', 'key',  'ppt',  'pptx', 'pptm', 'pps',   'ppsx', 'ppsm', 'sldx', 'sldm', 'odp' ),
       
  2557 		'text'        => array( 'asc', 'csv',  'tsv',  'txt' ),
       
  2558 		'archive'     => array( 'bz2', 'cab',  'dmg',  'gz',   'rar',  'sea',   'sit',  'sqx',  'tar',  'tgz',  'zip', '7z' ),
       
  2559 		'code'        => array( 'css', 'htm',  'html', 'php',  'js' ),
       
  2560 	) );
       
  2561 }
       
  2562 
  2278 /**
  2563 /**
  2279  * Retrieve list of allowed mime types and file extensions.
  2564  * Retrieve list of allowed mime types and file extensions.
  2280  *
  2565  *
  2281  * @since 2.8.6
  2566  * @since 2.8.6
  2282  *
  2567  *
  2289 
  2574 
  2290 	unset( $t['swf'], $t['exe'] );
  2575 	unset( $t['swf'], $t['exe'] );
  2291 	if ( function_exists( 'current_user_can' ) )
  2576 	if ( function_exists( 'current_user_can' ) )
  2292 		$unfiltered = $user ? user_can( $user, 'unfiltered_html' ) : current_user_can( 'unfiltered_html' );
  2577 		$unfiltered = $user ? user_can( $user, 'unfiltered_html' ) : current_user_can( 'unfiltered_html' );
  2293 
  2578 
  2294 	if ( empty( $unfiltered ) )
  2579 	if ( empty( $unfiltered ) ) {
  2295 		unset( $t['htm|html'] );
  2580 		unset( $t['htm|html'], $t['js'] );
       
  2581 	}
  2296 
  2582 
  2297 	/**
  2583 	/**
  2298 	 * Filter list of allowed mime types and file extensions.
  2584 	 * Filters list of allowed mime types and file extensions.
  2299 	 *
  2585 	 *
  2300 	 * @since 2.0.0
  2586 	 * @since 2.0.0
  2301 	 *
  2587 	 *
  2302 	 * @param array            $t    Mime types keyed by the file extension regex corresponding to
  2588 	 * @param array            $t    Mime types keyed by the file extension regex corresponding to
  2303 	 *                               those types. 'swf' and 'exe' removed from full list. 'htm|html' also
  2589 	 *                               those types. 'swf' and 'exe' removed from full list. 'htm|html' also
  2317  *
  2603  *
  2318  * @param string $action The nonce action.
  2604  * @param string $action The nonce action.
  2319  */
  2605  */
  2320 function wp_nonce_ays( $action ) {
  2606 function wp_nonce_ays( $action ) {
  2321 	if ( 'log-out' == $action ) {
  2607 	if ( 'log-out' == $action ) {
  2322 		$html = sprintf( __( 'You are attempting to log out of %s' ), get_bloginfo( 'name' ) ) . '</p><p>';
  2608 		$html = sprintf(
       
  2609 			/* translators: %s: site name */
       
  2610 			__( 'You are attempting to log out of %s' ),
       
  2611 			get_bloginfo( 'name' )
       
  2612 		);
       
  2613 		$html .= '</p><p>';
  2323 		$redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
  2614 		$redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
  2324 		$html .= sprintf( __( "Do you really want to <a href='%s'>log out</a>?"), wp_logout_url( $redirect_to ) );
  2615 		$html .= sprintf(
       
  2616 			/* translators: %s: logout URL */
       
  2617 			__( 'Do you really want to <a href="%s">log out</a>?' ),
       
  2618 			wp_logout_url( $redirect_to )
       
  2619 		);
  2325 	} else {
  2620 	} else {
  2326 		$html = __( 'Are you sure you want to do this?' );
  2621 		$html = __( 'The link you followed has expired.' );
  2327 		if ( wp_get_referer() )
  2622 		if ( wp_get_referer() ) {
  2328 			$html .= "</p><p><a href='" . esc_url( remove_query_arg( 'updated', wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>";
  2623 			$html .= '</p><p>';
  2329 	}
  2624 			$html .= sprintf( '<a href="%s">%s</a>',
  2330 
  2625 				esc_url( remove_query_arg( 'updated', wp_get_referer() ) ),
  2331 	wp_die( $html, __( 'WordPress Failure Notice' ), 403 );
  2626 				__( 'Please try again.' )
       
  2627 			);
       
  2628 		}
       
  2629 	}
       
  2630 
       
  2631 	wp_die( $html, __( 'Something went wrong.' ), 403 );
  2332 }
  2632 }
  2333 
  2633 
  2334 /**
  2634 /**
  2335  * Kill WordPress execution and display HTML message with error message.
  2635  * Kill WordPress execution and display HTML message with error message.
  2336  *
  2636  *
  2345  *
  2645  *
  2346  * @since 2.0.4
  2646  * @since 2.0.4
  2347  * @since 4.1.0 The `$title` and `$args` parameters were changed to optionally accept
  2647  * @since 4.1.0 The `$title` and `$args` parameters were changed to optionally accept
  2348  *              an integer to be used as the response code.
  2648  *              an integer to be used as the response code.
  2349  *
  2649  *
  2350  * @param string|WP_Error  $message Optional. Error message. If this is a {@see WP_Error} object,
  2650  * @param string|WP_Error  $message Optional. Error message. If this is a WP_Error object,
  2351  *                                  the error's messages are used. Default empty.
  2651  *                                  and not an Ajax or XML-RPC request, the error's messages are used.
       
  2652  *                                  Default empty.
  2352  * @param string|int       $title   Optional. Error title. If `$message` is a `WP_Error` object,
  2653  * @param string|int       $title   Optional. Error title. If `$message` is a `WP_Error` object,
  2353  *                                  error data with the key 'title' may be used to specify the title.
  2654  *                                  error data with the key 'title' may be used to specify the title.
  2354  *                                  If `$title` is an integer, then it is treated as the response
  2655  *                                  If `$title` is an integer, then it is treated as the response
  2355  *                                  code. Default empty.
  2656  *                                  code. Default empty.
  2356  * @param string|array|int $args {
  2657  * @param string|array|int $args {
  2357  *     Optional. Arguments to control behavior. If `$args` is an integer, then it is treated
  2658  *     Optional. Arguments to control behavior. If `$args` is an integer, then it is treated
  2358  *     as the response code. Default empty array.
  2659  *     as the response code. Default empty array.
  2359  *
  2660  *
  2360  *     @type int    $response       The HTTP response code. Default 500.
  2661  *     @type int    $response       The HTTP response code. Default 200 for Ajax requests, 500 otherwise.
  2361  *     @type bool   $back_link      Whether to include a link to go back. Default false.
  2662  *     @type bool   $back_link      Whether to include a link to go back. Default false.
  2362  *     @type string $text_direction The text direction. This is only useful internally, when WordPress
  2663  *     @type string $text_direction The text direction. This is only useful internally, when WordPress
  2363  *                                  is still loading and the site's locale is not set up yet. Accepts 'rtl'.
  2664  *                                  is still loading and the site's locale is not set up yet. Accepts 'rtl'.
  2364  *                                  Default is the value of {@see is_rtl()}.
  2665  *                                  Default is the value of is_rtl().
  2365  * }
  2666  * }
  2366  */
  2667  */
  2367 function wp_die( $message = '', $title = '', $args = array() ) {
  2668 function wp_die( $message = '', $title = '', $args = array() ) {
  2368 
  2669 
  2369 	if ( is_int( $args ) ) {
  2670 	if ( is_int( $args ) ) {
  2371 	} elseif ( is_int( $title ) ) {
  2672 	} elseif ( is_int( $title ) ) {
  2372 		$args  = array( 'response' => $title );
  2673 		$args  = array( 'response' => $title );
  2373 		$title = '';
  2674 		$title = '';
  2374 	}
  2675 	}
  2375 
  2676 
  2376 	if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
  2677 	if ( wp_doing_ajax() ) {
  2377 		/**
  2678 		/**
  2378 		 * Filter callback for killing WordPress execution for AJAX requests.
  2679 		 * Filters the callback for killing WordPress execution for Ajax requests.
  2379 		 *
  2680 		 *
  2380 		 * @since 3.4.0
  2681 		 * @since 3.4.0
  2381 		 *
  2682 		 *
  2382 		 * @param callback $function Callback function name.
  2683 		 * @param callable $function Callback function name.
  2383 		 */
  2684 		 */
  2384 		$function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
  2685 		$function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
  2385 	} elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
  2686 	} elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
  2386 		/**
  2687 		/**
  2387 		 * Filter callback for killing WordPress execution for XML-RPC requests.
  2688 		 * Filters the callback for killing WordPress execution for XML-RPC requests.
  2388 		 *
  2689 		 *
  2389 		 * @since 3.4.0
  2690 		 * @since 3.4.0
  2390 		 *
  2691 		 *
  2391 		 * @param callback $function Callback function name.
  2692 		 * @param callable $function Callback function name.
  2392 		 */
  2693 		 */
  2393 		$function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
  2694 		$function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
  2394 	} else {
  2695 	} else {
  2395 		/**
  2696 		/**
  2396 		 * Filter callback for killing WordPress execution for all non-AJAX, non-XML-RPC requests.
  2697 		 * Filters the callback for killing WordPress execution for all non-Ajax, non-XML-RPC requests.
  2397 		 *
  2698 		 *
  2398 		 * @since 3.0.0
  2699 		 * @since 3.0.0
  2399 		 *
  2700 		 *
  2400 		 * @param callback $function Callback function name.
  2701 		 * @param callable $function Callback function name.
  2401 		 */
  2702 		 */
  2402 		$function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
  2703 		$function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
  2403 	}
  2704 	}
  2404 
  2705 
  2405 	call_user_func( $function, $message, $title, $args );
  2706 	call_user_func( $function, $message, $title, $args );
  2406 }
  2707 }
  2407 
  2708 
  2408 /**
  2709 /**
  2409  * Kill WordPress execution and display HTML message with error message.
  2710  * Kills WordPress execution and display HTML message with error message.
  2410  *
  2711  *
  2411  * This is the default handler for wp_die if you want a custom one for your
  2712  * This is the default handler for wp_die if you want a custom one for your
  2412  * site then you can overload using the wp_die_handler filter in wp_die
  2713  * site then you can overload using the {@see 'wp_die_handler'} filter in wp_die().
  2413  *
  2714  *
  2414  * @since 3.0.0
  2715  * @since 3.0.0
  2415  * @access private
  2716  * @access private
  2416  *
  2717  *
  2417  * @param string       $message Error message.
  2718  * @param string|WP_Error $message Error message or WP_Error object.
  2418  * @param string       $title   Optional. Error title. Default empty.
  2719  * @param string          $title   Optional. Error title. Default empty.
  2419  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
  2720  * @param string|array    $args    Optional. Arguments to control behavior. Default empty array.
  2420  */
  2721  */
  2421 function _default_wp_die_handler( $message, $title = '', $args = array() ) {
  2722 function _default_wp_die_handler( $message, $title = '', $args = array() ) {
  2422 	$defaults = array( 'response' => 500 );
  2723 	$defaults = array( 'response' => 500 );
  2423 	$r = wp_parse_args($args, $defaults);
  2724 	$r = wp_parse_args($args, $defaults);
  2424 
  2725 
  2466 			$text_direction = 'rtl';
  2767 			$text_direction = 'rtl';
  2467 		elseif ( function_exists( 'is_rtl' ) && is_rtl() )
  2768 		elseif ( function_exists( 'is_rtl' ) && is_rtl() )
  2468 			$text_direction = 'rtl';
  2769 			$text_direction = 'rtl';
  2469 ?>
  2770 ?>
  2470 <!DOCTYPE html>
  2771 <!DOCTYPE html>
  2471 <!-- 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
       
  2472 -->
       
  2473 <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'"; ?>>
  2772 <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'"; ?>>
  2474 <head>
  2773 <head>
  2475 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  2774 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
       
  2775 	<meta name="viewport" content="width=device-width">
       
  2776 	<?php
       
  2777 	if ( function_exists( 'wp_no_robots' ) ) {
       
  2778 		wp_no_robots();
       
  2779 	}
       
  2780 	?>
  2476 	<title><?php echo $title ?></title>
  2781 	<title><?php echo $title ?></title>
  2477 	<style type="text/css">
  2782 	<style type="text/css">
  2478 		html {
  2783 		html {
  2479 			background: #f1f1f1;
  2784 			background: #f1f1f1;
  2480 		}
  2785 		}
  2481 		body {
  2786 		body {
  2482 			background: #fff;
  2787 			background: #fff;
  2483 			color: #444;
  2788 			color: #444;
  2484 			font-family: "Open Sans", sans-serif;
  2789 			font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  2485 			margin: 2em auto;
  2790 			margin: 2em auto;
  2486 			padding: 1em 2em;
  2791 			padding: 1em 2em;
  2487 			max-width: 700px;
  2792 			max-width: 700px;
  2488 			-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13);
  2793 			-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13);
  2489 			box-shadow: 0 1px 3px rgba(0,0,0,0.13);
  2794 			box-shadow: 0 1px 3px rgba(0,0,0,0.13);
  2490 		}
  2795 		}
  2491 		h1 {
  2796 		h1 {
  2492 			border-bottom: 1px solid #dadada;
  2797 			border-bottom: 1px solid #dadada;
  2493 			clear: both;
  2798 			clear: both;
  2494 			color: #666;
  2799 			color: #666;
  2495 			font: 24px "Open Sans", sans-serif;
  2800 			font-size: 24px;
  2496 			margin: 30px 0 0 0;
  2801 			margin: 30px 0 0 0;
  2497 			padding: 0;
  2802 			padding: 0;
  2498 			padding-bottom: 7px;
  2803 			padding-bottom: 7px;
  2499 		}
  2804 		}
  2500 		#error-page {
  2805 		#error-page {
  2511 		ul li {
  2816 		ul li {
  2512 			margin-bottom: 10px;
  2817 			margin-bottom: 10px;
  2513 			font-size: 14px ;
  2818 			font-size: 14px ;
  2514 		}
  2819 		}
  2515 		a {
  2820 		a {
  2516 			color: #21759B;
  2821 			color: #0073aa;
  2517 			text-decoration: none;
  2822 		}
  2518 		}
  2823 		a:hover,
  2519 		a:hover {
  2824 		a:active {
  2520 			color: #D54E21;
  2825 			color: #00a0d2;
       
  2826 		}
       
  2827 		a:focus {
       
  2828 			color: #124964;
       
  2829 		    -webkit-box-shadow:
       
  2830 		    	0 0 0 1px #5b9dd9,
       
  2831 				0 0 2px 1px rgba(30, 140, 190, .8);
       
  2832 		    box-shadow:
       
  2833 		    	0 0 0 1px #5b9dd9,
       
  2834 				0 0 2px 1px rgba(30, 140, 190, .8);
       
  2835 			outline: none;
  2521 		}
  2836 		}
  2522 		.button {
  2837 		.button {
  2523 			background: #f7f7f7;
  2838 			background: #f7f7f7;
  2524 			border: 1px solid #cccccc;
  2839 			border: 1px solid #ccc;
  2525 			color: #555;
  2840 			color: #555;
  2526 			display: inline-block;
  2841 			display: inline-block;
  2527 			text-decoration: none;
  2842 			text-decoration: none;
  2528 			font-size: 13px;
  2843 			font-size: 13px;
  2529 			line-height: 26px;
  2844 			line-height: 26px;
  2537 			white-space: nowrap;
  2852 			white-space: nowrap;
  2538 			-webkit-box-sizing: border-box;
  2853 			-webkit-box-sizing: border-box;
  2539 			-moz-box-sizing:    border-box;
  2854 			-moz-box-sizing:    border-box;
  2540 			box-sizing:         border-box;
  2855 			box-sizing:         border-box;
  2541 
  2856 
  2542 			-webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba(0,0,0,.08);
  2857 			-webkit-box-shadow: 0 1px 0 #ccc;
  2543 			box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba(0,0,0,.08);
  2858 			box-shadow: 0 1px 0 #ccc;
  2544 		 	vertical-align: top;
  2859 		 	vertical-align: top;
  2545 		}
  2860 		}
  2546 
  2861 
  2547 		.button.button-large {
  2862 		.button.button-large {
  2548 			height: 29px;
  2863 			height: 30px;
  2549 			line-height: 28px;
  2864 			line-height: 28px;
  2550 			padding: 0 12px;
  2865 			padding: 0 12px 2px;
  2551 		}
  2866 		}
  2552 
  2867 
  2553 		.button:hover,
  2868 		.button:hover,
  2554 		.button:focus {
  2869 		.button:focus {
  2555 			background: #fafafa;
  2870 			background: #fafafa;
  2556 			border-color: #999;
  2871 			border-color: #999;
  2557 			color: #222;
  2872 			color: #23282d;
  2558 		}
  2873 		}
  2559 
  2874 
  2560 		.button:focus  {
  2875 		.button:focus  {
  2561 			-webkit-box-shadow: 1px 1px 1px rgba(0,0,0,.2);
  2876 			border-color: #5b9dd9;
  2562 			box-shadow: 1px 1px 1px rgba(0,0,0,.2);
  2877 			-webkit-box-shadow: 0 0 3px rgba( 0, 115, 170, .8 );
       
  2878 			box-shadow: 0 0 3px rgba( 0, 115, 170, .8 );
       
  2879 			outline: none;
  2563 		}
  2880 		}
  2564 
  2881 
  2565 		.button:active {
  2882 		.button:active {
  2566 			background: #eee;
  2883 			background: #eee;
  2567 			border-color: #999;
  2884 			border-color: #999;
  2568 			color: #333;
  2885 		 	-webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
  2569 			-webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
       
  2570 		 	box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
  2886 		 	box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
  2571 		}
  2887 		 	-webkit-transform: translateY(1px);
  2572 
  2888 		 	-ms-transform: translateY(1px);
  2573 		<?php if ( 'rtl' == $text_direction ) : ?>
  2889 		 	transform: translateY(1px);
  2574 		body { font-family: Tahoma, Arial; }
  2890 		}
  2575 		<?php endif; ?>
  2891 
       
  2892 		<?php
       
  2893 		if ( 'rtl' == $text_direction ) {
       
  2894 			echo 'body { font-family: Tahoma, Arial; }';
       
  2895 		}
       
  2896 		?>
  2576 	</style>
  2897 	</style>
  2577 </head>
  2898 </head>
  2578 <body id="error-page">
  2899 <body id="error-page">
  2579 <?php endif; // ! did_action( 'admin_head' ) ?>
  2900 <?php endif; // ! did_action( 'admin_head' ) ?>
  2580 	<?php echo $message; ?>
  2901 	<?php echo $message; ?>
  2590  * This is the handler for wp_die when processing XMLRPC requests.
  2911  * This is the handler for wp_die when processing XMLRPC requests.
  2591  *
  2912  *
  2592  * @since 3.2.0
  2913  * @since 3.2.0
  2593  * @access private
  2914  * @access private
  2594  *
  2915  *
       
  2916  * @global wp_xmlrpc_server $wp_xmlrpc_server
       
  2917  *
  2595  * @param string       $message Error message.
  2918  * @param string       $message Error message.
  2596  * @param string       $title   Optional. Error title. Default empty.
  2919  * @param string       $title   Optional. Error title. Default empty.
  2597  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
  2920  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
  2598  */
  2921  */
  2599 function _xmlrpc_wp_die_handler( $message, $title = '', $args = array() ) {
  2922 function _xmlrpc_wp_die_handler( $message, $title = '', $args = array() ) {
  2615  * This is the handler for wp_die when processing Ajax requests.
  2938  * This is the handler for wp_die when processing Ajax requests.
  2616  *
  2939  *
  2617  * @since 3.4.0
  2940  * @since 3.4.0
  2618  * @access private
  2941  * @access private
  2619  *
  2942  *
  2620  * @param string $message Optional. Response to print. Default empty.
  2943  * @param string       $message Error message.
  2621  */
  2944  * @param string       $title   Optional. Error title (unused). Default empty.
  2622 function _ajax_wp_die_handler( $message = '' ) {
  2945  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
       
  2946  */
       
  2947 function _ajax_wp_die_handler( $message, $title = '', $args = array() ) {
       
  2948 	$defaults = array(
       
  2949 		'response' => 200,
       
  2950 	);
       
  2951 	$r = wp_parse_args( $args, $defaults );
       
  2952 
       
  2953 	if ( ! headers_sent() && null !== $r['response'] ) {
       
  2954 		status_header( $r['response'] );
       
  2955 	}
       
  2956 
  2623 	if ( is_scalar( $message ) )
  2957 	if ( is_scalar( $message ) )
  2624 		die( (string) $message );
  2958 		die( (string) $message );
  2625 	die( '0' );
  2959 	die( '0' );
  2626 }
  2960 }
  2627 
  2961 
  2648  *
  2982  *
  2649  * @param mixed $data    Variable (usually an array or object) to encode as JSON.
  2983  * @param mixed $data    Variable (usually an array or object) to encode as JSON.
  2650  * @param int   $options Optional. Options to be passed to json_encode(). Default 0.
  2984  * @param int   $options Optional. Options to be passed to json_encode(). Default 0.
  2651  * @param int   $depth   Optional. Maximum depth to walk through $data. Must be
  2985  * @param int   $depth   Optional. Maximum depth to walk through $data. Must be
  2652  *                       greater than 0. Default 512.
  2986  *                       greater than 0. Default 512.
  2653  * @return bool|string The JSON encoded string, or false if it cannot be encoded.
  2987  * @return string|false The JSON encoded string, or false if it cannot be encoded.
  2654  */
  2988  */
  2655 function wp_json_encode( $data, $options = 0, $depth = 512 ) {
  2989 function wp_json_encode( $data, $options = 0, $depth = 512 ) {
  2656 	/*
  2990 	/*
  2657 	 * json_encode() has had extra params added over the years.
  2991 	 * json_encode() has had extra params added over the years.
  2658 	 * $options was added in 5.3, and $depth in 5.5.
  2992 	 * $options was added in 5.3, and $depth in 5.5.
  2664 		$args = array( $data, $options );
  2998 		$args = array( $data, $options );
  2665 	} else {
  2999 	} else {
  2666 		$args = array( $data );
  3000 		$args = array( $data );
  2667 	}
  3001 	}
  2668 
  3002 
  2669 	$json = call_user_func_array( 'json_encode', $args );
  3003 	// Prepare the data for JSON serialization.
       
  3004 	$args[0] = _wp_json_prepare_data( $data );
       
  3005 
       
  3006 	$json = @call_user_func_array( 'json_encode', $args );
  2670 
  3007 
  2671 	// If json_encode() was successful, no need to do more sanity checking.
  3008 	// If json_encode() was successful, no need to do more sanity checking.
  2672 	// ... unless we're in an old version of PHP, and json_encode() returned
  3009 	// ... unless we're in an old version of PHP, and json_encode() returned
  2673 	// a string containing 'null'. Then we need to do more sanity checking.
  3010 	// a string containing 'null'. Then we need to do more sanity checking.
  2674 	if ( false !== $json && ( version_compare( PHP_VERSION, '5.5', '>=' ) || false === strpos( $json, 'null' ) ) )  {
  3011 	if ( false !== $json && ( version_compare( PHP_VERSION, '5.5', '>=' ) || false === strpos( $json, 'null' ) ) )  {
  2754  * @since 4.1.0
  3091  * @since 4.1.0
  2755  * @access private
  3092  * @access private
  2756  *
  3093  *
  2757  * @see _wp_json_sanity_check()
  3094  * @see _wp_json_sanity_check()
  2758  *
  3095  *
       
  3096  * @staticvar bool $use_mb
       
  3097  *
  2759  * @param string $string The string which is to be converted.
  3098  * @param string $string The string which is to be converted.
  2760  * @return string The checked string.
  3099  * @return string The checked string.
  2761  */
  3100  */
  2762 function _wp_json_convert_string( $string ) {
  3101 function _wp_json_convert_string( $string ) {
  2763 	static $use_mb = null;
  3102 	static $use_mb = null;
  2776 		return wp_check_invalid_utf8( $string, true );
  3115 		return wp_check_invalid_utf8( $string, true );
  2777 	}
  3116 	}
  2778 }
  3117 }
  2779 
  3118 
  2780 /**
  3119 /**
       
  3120  * Prepares response data to be serialized to JSON.
       
  3121  *
       
  3122  * This supports the JsonSerializable interface for PHP 5.2-5.3 as well.
       
  3123  *
       
  3124  * @ignore
       
  3125  * @since 4.4.0
       
  3126  * @access private
       
  3127  *
       
  3128  * @param mixed $data Native representation.
       
  3129  * @return bool|int|float|null|string|array Data ready for `json_encode()`.
       
  3130  */
       
  3131 function _wp_json_prepare_data( $data ) {
       
  3132 	if ( ! defined( 'WP_JSON_SERIALIZE_COMPATIBLE' ) || WP_JSON_SERIALIZE_COMPATIBLE === false ) {
       
  3133 		return $data;
       
  3134 	}
       
  3135 
       
  3136 	switch ( gettype( $data ) ) {
       
  3137 		case 'boolean':
       
  3138 		case 'integer':
       
  3139 		case 'double':
       
  3140 		case 'string':
       
  3141 		case 'NULL':
       
  3142 			// These values can be passed through.
       
  3143 			return $data;
       
  3144 
       
  3145 		case 'array':
       
  3146 			// Arrays must be mapped in case they also return objects.
       
  3147 			return array_map( '_wp_json_prepare_data', $data );
       
  3148 
       
  3149 		case 'object':
       
  3150 			// If this is an incomplete object (__PHP_Incomplete_Class), bail.
       
  3151 			if ( ! is_object( $data ) ) {
       
  3152 				return null;
       
  3153 			}
       
  3154 
       
  3155 			if ( $data instanceof JsonSerializable ) {
       
  3156 				$data = $data->jsonSerialize();
       
  3157 			} else {
       
  3158 				$data = get_object_vars( $data );
       
  3159 			}
       
  3160 
       
  3161 			// Now, pass the array (or whatever was returned from jsonSerialize through).
       
  3162 			return _wp_json_prepare_data( $data );
       
  3163 
       
  3164 		default:
       
  3165 			return null;
       
  3166 	}
       
  3167 }
       
  3168 
       
  3169 /**
  2781  * Send a JSON response back to an Ajax request.
  3170  * Send a JSON response back to an Ajax request.
  2782  *
  3171  *
  2783  * @since 3.5.0
  3172  * @since 3.5.0
  2784  *
  3173  * @since 4.7.0 The `$status_code` parameter was added.
  2785  * @param mixed $response Variable (usually an array or object) to encode as JSON,
  3174  *
  2786  *                        then print and die.
  3175  * @param mixed $response    Variable (usually an array or object) to encode as JSON,
  2787  */
  3176  *                           then print and die.
  2788 function wp_send_json( $response ) {
  3177  * @param int   $status_code The HTTP status code to output.
       
  3178  */
       
  3179 function wp_send_json( $response, $status_code = null ) {
  2789 	@header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
  3180 	@header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
       
  3181 	if ( null !== $status_code ) {
       
  3182 		status_header( $status_code );
       
  3183 	}
  2790 	echo wp_json_encode( $response );
  3184 	echo wp_json_encode( $response );
  2791 	if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
  3185 
  2792 		wp_die();
  3186 	if ( wp_doing_ajax() ) {
  2793 	else
  3187 		wp_die( '', '', array(
       
  3188 			'response' => null,
       
  3189 		) );
       
  3190 	} else {
  2794 		die;
  3191 		die;
       
  3192 	}
  2795 }
  3193 }
  2796 
  3194 
  2797 /**
  3195 /**
  2798  * Send a JSON response back to an Ajax request, indicating success.
  3196  * Send a JSON response back to an Ajax request, indicating success.
  2799  *
  3197  *
  2800  * @since 3.5.0
  3198  * @since 3.5.0
  2801  *
  3199  * @since 4.7.0 The `$status_code` parameter was added.
  2802  * @param mixed $data Data to encode as JSON, then print and die.
  3200  *
  2803  */
  3201  * @param mixed $data        Data to encode as JSON, then print and die.
  2804 function wp_send_json_success( $data = null ) {
  3202  * @param int   $status_code The HTTP status code to output.
       
  3203  */
       
  3204 function wp_send_json_success( $data = null, $status_code = null ) {
  2805 	$response = array( 'success' => true );
  3205 	$response = array( 'success' => true );
  2806 
  3206 
  2807 	if ( isset( $data ) )
  3207 	if ( isset( $data ) )
  2808 		$response['data'] = $data;
  3208 		$response['data'] = $data;
  2809 
  3209 
  2810 	wp_send_json( $response );
  3210 	wp_send_json( $response, $status_code );
  2811 }
  3211 }
  2812 
  3212 
  2813 /**
  3213 /**
  2814  * Send a JSON response back to an Ajax request, indicating failure.
  3214  * Send a JSON response back to an Ajax request, indicating failure.
  2815  *
  3215  *
  2816  * If the `$data` parameter is a {@see WP_Error} object, the errors
  3216  * If the `$data` parameter is a WP_Error object, the errors
  2817  * within the object are processed and output as an array of error
  3217  * within the object are processed and output as an array of error
  2818  * codes and corresponding messages. All other types are output
  3218  * codes and corresponding messages. All other types are output
  2819  * without further processing.
  3219  * without further processing.
  2820  *
  3220  *
  2821  * @since 3.5.0
  3221  * @since 3.5.0
  2822  * @since 4.1.0 The `$data` parameter is now processed if a {@see WP_Error}
  3222  * @since 4.1.0 The `$data` parameter is now processed if a WP_Error object is passed in.
  2823  *              object is passed in.
  3223  * @since 4.7.0 The `$status_code` parameter was added.
  2824  *
  3224  *
  2825  * @param mixed $data Data to encode as JSON, then print and die.
  3225  * @param mixed $data        Data to encode as JSON, then print and die.
  2826  */
  3226  * @param int   $status_code The HTTP status code to output.
  2827 function wp_send_json_error( $data = null ) {
  3227  */
       
  3228 function wp_send_json_error( $data = null, $status_code = null ) {
  2828 	$response = array( 'success' => false );
  3229 	$response = array( 'success' => false );
  2829 
  3230 
  2830 	if ( isset( $data ) ) {
  3231 	if ( isset( $data ) ) {
  2831 		if ( is_wp_error( $data ) ) {
  3232 		if ( is_wp_error( $data ) ) {
  2832 			$result = array();
  3233 			$result = array();
  2840 		} else {
  3241 		} else {
  2841 			$response['data'] = $data;
  3242 			$response['data'] = $data;
  2842 		}
  3243 		}
  2843 	}
  3244 	}
  2844 
  3245 
  2845 	wp_send_json( $response );
  3246 	wp_send_json( $response, $status_code );
       
  3247 }
       
  3248 
       
  3249 /**
       
  3250  * Checks that a JSONP callback is a valid JavaScript callback.
       
  3251  *
       
  3252  * Only allows alphanumeric characters and the dot character in callback
       
  3253  * function names. This helps to mitigate XSS attacks caused by directly
       
  3254  * outputting user input.
       
  3255  *
       
  3256  * @since 4.6.0
       
  3257  *
       
  3258  * @param string $callback Supplied JSONP callback function.
       
  3259  * @return bool True if valid callback, otherwise false.
       
  3260  */
       
  3261 function wp_check_jsonp_callback( $callback ) {
       
  3262 	if ( ! is_string( $callback ) ) {
       
  3263 		return false;
       
  3264 	}
       
  3265 
       
  3266 	preg_replace( '/[^\w\.]/', '', $callback, -1, $illegal_char_count );
       
  3267 
       
  3268 	return 0 === $illegal_char_count;
  2846 }
  3269 }
  2847 
  3270 
  2848 /**
  3271 /**
  2849  * Retrieve the WordPress home page URL.
  3272  * Retrieve the WordPress home page URL.
  2850  *
  3273  *
  2886 		return untrailingslashit( WP_SITEURL );
  3309 		return untrailingslashit( WP_SITEURL );
  2887 	return $url;
  3310 	return $url;
  2888 }
  3311 }
  2889 
  3312 
  2890 /**
  3313 /**
       
  3314  * Delete the fresh site option.
       
  3315  *
       
  3316  * @since 4.7.0
       
  3317  * @access private
       
  3318  */
       
  3319 function _delete_option_fresh_site() {
       
  3320 	update_option( 'fresh_site', '0' );
       
  3321 }
       
  3322 
       
  3323 /**
  2891  * Set the localized direction for MCE plugin.
  3324  * Set the localized direction for MCE plugin.
  2892  *
  3325  *
  2893  * Will only set the direction to 'rtl', if the WordPress locale has
  3326  * Will only set the direction to 'rtl', if the WordPress locale has
  2894  * the text direction set to 'rtl'.
  3327  * the text direction set to 'rtl'.
  2895  *
  3328  *
  2896  * Fills in the 'directionality' setting, enables the 'directionality'
  3329  * Fills in the 'directionality' setting, enables the 'directionality'
  2897  * plugin, and adds the 'ltr' button to 'toolbar1', formerly
  3330  * plugin, and adds the 'ltr' button to 'toolbar1', formerly
  2898  * 'theme_advanced_buttons1' array keys. These keys are then returned
  3331  * 'theme_advanced_buttons1' array keys. These keys are then returned
  2899  * in the $input (TinyMCE settings) array.
  3332  * in the $mce_init (TinyMCE settings) array.
  2900  *
  3333  *
  2901  * @since 2.1.0
  3334  * @since 2.1.0
  2902  * @access private
  3335  * @access private
  2903  *
  3336  *
  2904  * @param array $input MCE settings array.
  3337  * @param array $mce_init MCE settings array.
  2905  * @return array Direction set for 'rtl', if needed by locale.
  3338  * @return array Direction set for 'rtl', if needed by locale.
  2906  */
  3339  */
  2907 function _mce_set_direction( $input ) {
  3340 function _mce_set_direction( $mce_init ) {
  2908 	if ( is_rtl() ) {
  3341 	if ( is_rtl() ) {
  2909 		$input['directionality'] = 'rtl';
  3342 		$mce_init['directionality'] = 'rtl';
  2910 
  3343 		$mce_init['rtl_ui'] = true;
  2911 		if ( ! empty( $input['plugins'] ) && strpos( $input['plugins'], 'directionality' ) === false ) {
  3344 
  2912 			$input['plugins'] .= ',directionality';
  3345 		if ( ! empty( $mce_init['plugins'] ) && strpos( $mce_init['plugins'], 'directionality' ) === false ) {
  2913 		}
  3346 			$mce_init['plugins'] .= ',directionality';
  2914 
  3347 		}
  2915 		if ( ! empty( $input['toolbar1'] ) && ! preg_match( '/\bltr\b/', $input['toolbar1'] ) ) {
  3348 
  2916 			$input['toolbar1'] .= ',ltr';
  3349 		if ( ! empty( $mce_init['toolbar1'] ) && ! preg_match( '/\bltr\b/', $mce_init['toolbar1'] ) ) {
  2917 		}
  3350 			$mce_init['toolbar1'] .= ',ltr';
  2918 	}
  3351 		}
  2919 
  3352 	}
  2920 	return $input;
  3353 
       
  3354 	return $mce_init;
  2921 }
  3355 }
  2922 
  3356 
  2923 
  3357 
  2924 /**
  3358 /**
  2925  * Convert smiley code to the icon graphic file equivalent.
  3359  * Convert smiley code to the icon graphic file equivalent.
  2955 		':mrgreen:' => 'mrgreen.png',
  3389 		':mrgreen:' => 'mrgreen.png',
  2956 		':neutral:' => "\xf0\x9f\x98\x90",
  3390 		':neutral:' => "\xf0\x9f\x98\x90",
  2957 		':twisted:' => "\xf0\x9f\x98\x88",
  3391 		':twisted:' => "\xf0\x9f\x98\x88",
  2958 		  ':arrow:' => "\xe2\x9e\xa1",
  3392 		  ':arrow:' => "\xe2\x9e\xa1",
  2959 		  ':shock:' => "\xf0\x9f\x98\xaf",
  3393 		  ':shock:' => "\xf0\x9f\x98\xaf",
  2960 		  ':smile:' => 'simple-smile.png',
  3394 		  ':smile:' => "\xf0\x9f\x99\x82",
  2961 		    ':???:' => "\xf0\x9f\x98\x95",
  3395 		    ':???:' => "\xf0\x9f\x98\x95",
  2962 		   ':cool:' => "\xf0\x9f\x98\x8e",
  3396 		   ':cool:' => "\xf0\x9f\x98\x8e",
  2963 		   ':evil:' => "\xf0\x9f\x91\xbf",
  3397 		   ':evil:' => "\xf0\x9f\x91\xbf",
  2964 		   ':grin:' => "\xf0\x9f\x98\x80",
  3398 		   ':grin:' => "\xf0\x9f\x98\x80",
  2965 		   ':idea:' => "\xf0\x9f\x92\xa1",
  3399 		   ':idea:' => "\xf0\x9f\x92\xa1",
  2966 		   ':oops:' => "\xf0\x9f\x98\xb3",
  3400 		   ':oops:' => "\xf0\x9f\x98\xb3",
  2967 		   ':razz:' => "\xf0\x9f\x98\x9b",
  3401 		   ':razz:' => "\xf0\x9f\x98\x9b",
  2968 		   ':roll:' => 'rolleyes.png',
  3402 		   ':roll:' => "\xf0\x9f\x99\x84",
  2969 		   ':wink:' => "\xf0\x9f\x98\x89",
  3403 		   ':wink:' => "\xf0\x9f\x98\x89",
  2970 		    ':cry:' => "\xf0\x9f\x98\xa5",
  3404 		    ':cry:' => "\xf0\x9f\x98\xa5",
  2971 		    ':eek:' => "\xf0\x9f\x98\xae",
  3405 		    ':eek:' => "\xf0\x9f\x98\xae",
  2972 		    ':lol:' => "\xf0\x9f\x98\x86",
  3406 		    ':lol:' => "\xf0\x9f\x98\x86",
  2973 		    ':mad:' => "\xf0\x9f\x98\xa1",
  3407 		    ':mad:' => "\xf0\x9f\x98\xa1",
  2974 		    ':sad:' => 'frownie.png',
  3408 		    ':sad:' => "\xf0\x9f\x99\x81",
  2975 		      '8-)' => "\xf0\x9f\x98\x8e",
  3409 		      '8-)' => "\xf0\x9f\x98\x8e",
  2976 		      '8-O' => "\xf0\x9f\x98\xaf",
  3410 		      '8-O' => "\xf0\x9f\x98\xaf",
  2977 		      ':-(' => 'frownie.png',
  3411 		      ':-(' => "\xf0\x9f\x99\x81",
  2978 		      ':-)' => 'simple-smile.png',
  3412 		      ':-)' => "\xf0\x9f\x99\x82",
  2979 		      ':-?' => "\xf0\x9f\x98\x95",
  3413 		      ':-?' => "\xf0\x9f\x98\x95",
  2980 		      ':-D' => "\xf0\x9f\x98\x80",
  3414 		      ':-D' => "\xf0\x9f\x98\x80",
  2981 		      ':-P' => "\xf0\x9f\x98\x9b",
  3415 		      ':-P' => "\xf0\x9f\x98\x9b",
  2982 		      ':-o' => "\xf0\x9f\x98\xae",
  3416 		      ':-o' => "\xf0\x9f\x98\xae",
  2983 		      ':-x' => "\xf0\x9f\x98\xa1",
  3417 		      ':-x' => "\xf0\x9f\x98\xa1",
  2984 		      ':-|' => "\xf0\x9f\x98\x90",
  3418 		      ':-|' => "\xf0\x9f\x98\x90",
  2985 		      ';-)' => "\xf0\x9f\x98\x89",
  3419 		      ';-)' => "\xf0\x9f\x98\x89",
  2986 		// This one transformation breaks regular text with frequency.
  3420 		// This one transformation breaks regular text with frequency.
  2987 		//     '8)' => "\xf0\x9f\x98\x8e",
  3421 		//     '8)' => "\xf0\x9f\x98\x8e",
  2988 		       '8O' => "\xf0\x9f\x98\xaf",
  3422 		       '8O' => "\xf0\x9f\x98\xaf",
  2989 		       ':(' => 'frownie.png',
  3423 		       ':(' => "\xf0\x9f\x99\x81",
  2990 		       ':)' => 'simple-smile.png',
  3424 		       ':)' => "\xf0\x9f\x99\x82",
  2991 		       ':?' => "\xf0\x9f\x98\x95",
  3425 		       ':?' => "\xf0\x9f\x98\x95",
  2992 		       ':D' => "\xf0\x9f\x98\x80",
  3426 		       ':D' => "\xf0\x9f\x98\x80",
  2993 		       ':P' => "\xf0\x9f\x98\x9b",
  3427 		       ':P' => "\xf0\x9f\x98\x9b",
  2994 		       ':o' => "\xf0\x9f\x98\xae",
  3428 		       ':o' => "\xf0\x9f\x98\xae",
  2995 		       ':x' => "\xf0\x9f\x98\xa1",
  3429 		       ':x' => "\xf0\x9f\x98\xa1",
  2998 		      ':!:' => "\xe2\x9d\x97",
  3432 		      ':!:' => "\xe2\x9d\x97",
  2999 		      ':?:' => "\xe2\x9d\x93",
  3433 		      ':?:' => "\xe2\x9d\x93",
  3000 		);
  3434 		);
  3001 	}
  3435 	}
  3002 
  3436 
       
  3437 	/**
       
  3438 	 * Filters all the smilies.
       
  3439 	 *
       
  3440 	 * This filter must be added before `smilies_init` is run, as
       
  3441 	 * it is normally only run once to setup the smilies regex.
       
  3442 	 *
       
  3443 	 * @since 4.7.0
       
  3444 	 *
       
  3445 	 * @param array $wpsmiliestrans List of the smilies.
       
  3446 	 */
       
  3447 	$wpsmiliestrans = apply_filters('smilies', $wpsmiliestrans);
       
  3448 
  3003 	if (count($wpsmiliestrans) == 0) {
  3449 	if (count($wpsmiliestrans) == 0) {
  3004 		return;
  3450 		return;
  3005 	}
  3451 	}
  3006 
  3452 
  3007 	/*
  3453 	/*
  3044  *
  3490  *
  3045  * This function is used throughout WordPress to allow for both string or array
  3491  * This function is used throughout WordPress to allow for both string or array
  3046  * to be merged into another array.
  3492  * to be merged into another array.
  3047  *
  3493  *
  3048  * @since 2.2.0
  3494  * @since 2.2.0
  3049  *
  3495  * @since 2.3.0 `$args` can now also be an object.
  3050  * @param string|array $args     Value to merge with $defaults
  3496  *
  3051  * @param array        $defaults Optional. Array that serves as the defaults. Default empty.
  3497  * @param string|array|object $args     Value to merge with $defaults.
       
  3498  * @param array               $defaults Optional. Array that serves as the defaults. Default empty.
  3052  * @return array Merged user defined values with defaults.
  3499  * @return array Merged user defined values with defaults.
  3053  */
  3500  */
  3054 function wp_parse_args( $args, $defaults = '' ) {
  3501 function wp_parse_args( $args, $defaults = '' ) {
  3055 	if ( is_object( $args ) )
  3502 	if ( is_object( $args ) )
  3056 		$r = get_object_vars( $args );
  3503 		$r = get_object_vars( $args );
  3078 
  3525 
  3079 	return array_unique(array_map('absint', $list));
  3526 	return array_unique(array_map('absint', $list));
  3080 }
  3527 }
  3081 
  3528 
  3082 /**
  3529 /**
       
  3530  * Clean up an array, comma- or space-separated list of slugs.
       
  3531  *
       
  3532  * @since 4.7.0
       
  3533  *
       
  3534  * @param  array|string $list List of slugs.
       
  3535  * @return array Sanitized array of slugs.
       
  3536  */
       
  3537 function wp_parse_slug_list( $list ) {
       
  3538 	if ( ! is_array( $list ) ) {
       
  3539 		$list = preg_split( '/[\s,]+/', $list );
       
  3540 	}
       
  3541 
       
  3542 	foreach ( $list as $key => $value ) {
       
  3543 		$list[ $key ] = sanitize_title( $value );
       
  3544 	}
       
  3545 
       
  3546 	return array_unique( $list );
       
  3547 }
       
  3548 
       
  3549 /**
  3083  * Extract a slice of an array, given a list of keys.
  3550  * Extract a slice of an array, given a list of keys.
  3084  *
  3551  *
  3085  * @since 3.1.0
  3552  * @since 3.1.0
  3086  *
  3553  *
  3087  * @param array $array The original array.
  3554  * @param array $array The original array.
  3096 
  3563 
  3097 	return $slice;
  3564 	return $slice;
  3098 }
  3565 }
  3099 
  3566 
  3100 /**
  3567 /**
       
  3568  * Determines if the variable is a numeric-indexed array.
       
  3569  *
       
  3570  * @since 4.4.0
       
  3571  *
       
  3572  * @param mixed $data Variable to check.
       
  3573  * @return bool Whether the variable is a list.
       
  3574  */
       
  3575 function wp_is_numeric_array( $data ) {
       
  3576 	if ( ! is_array( $data ) ) {
       
  3577 		return false;
       
  3578 	}
       
  3579 
       
  3580 	$keys = array_keys( $data );
       
  3581 	$string_keys = array_filter( $keys, 'is_string' );
       
  3582 	return count( $string_keys ) === 0;
       
  3583 }
       
  3584 
       
  3585 /**
  3101  * Filters a list of objects, based on a set of key => value arguments.
  3586  * Filters a list of objects, based on a set of key => value arguments.
  3102  *
  3587  *
  3103  * @since 3.0.0
  3588  * @since 3.0.0
       
  3589  * @since 4.7.0 Uses WP_List_Util class.
  3104  *
  3590  *
  3105  * @param array       $list     An array of objects to filter
  3591  * @param array       $list     An array of objects to filter
  3106  * @param array       $args     Optional. An array of key => value arguments to match
  3592  * @param array       $args     Optional. An array of key => value arguments to match
  3107  *                              against each object. Default empty array.
  3593  *                              against each object. Default empty array.
  3108  * @param string      $operator Optional. The logical operation to perform. 'or' means
  3594  * @param string      $operator Optional. The logical operation to perform. 'or' means
  3109  *                              only one element from the array needs to match; 'and'
  3595  *                              only one element from the array needs to match; 'and'
  3110  *                              means all elements must match. Default 'and'.
  3596  *                              means all elements must match; 'not' means no elements may
       
  3597  *                              match. Default 'and'.
  3111  * @param bool|string $field    A field from the object to place instead of the entire object.
  3598  * @param bool|string $field    A field from the object to place instead of the entire object.
  3112  *                              Default false.
  3599  *                              Default false.
  3113  * @return array A list of objects or object fields.
  3600  * @return array A list of objects or object fields.
  3114  */
  3601  */
  3115 function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
  3602 function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
  3116 	if ( ! is_array( $list ) )
  3603 	if ( ! is_array( $list ) ) {
  3117 		return array();
  3604 		return array();
  3118 
  3605 	}
  3119 	$list = wp_list_filter( $list, $args, $operator );
  3606 
  3120 
  3607 	$util = new WP_List_Util( $list );
  3121 	if ( $field )
  3608 
  3122 		$list = wp_list_pluck( $list, $field );
  3609 	$util->filter( $args, $operator );
  3123 
  3610 
  3124 	return $list;
  3611 	if ( $field ) {
       
  3612 		$util->pluck( $field );
       
  3613 	}
       
  3614 
       
  3615 	return $util->get_output();
  3125 }
  3616 }
  3126 
  3617 
  3127 /**
  3618 /**
  3128  * Filters a list of objects, based on a set of key => value arguments.
  3619  * Filters a list of objects, based on a set of key => value arguments.
  3129  *
  3620  *
  3130  * @since 3.1.0
  3621  * @since 3.1.0
       
  3622  * @since 4.7.0 Uses WP_List_Util class.
  3131  *
  3623  *
  3132  * @param array  $list     An array of objects to filter.
  3624  * @param array  $list     An array of objects to filter.
  3133  * @param array  $args     Optional. An array of key => value arguments to match
  3625  * @param array  $args     Optional. An array of key => value arguments to match
  3134  *                         against each object. Default empty array.
  3626  *                         against each object. Default empty array.
  3135  * @param string $operator Optional. The logical operation to perform. 'AND' means
  3627  * @param string $operator Optional. The logical operation to perform. 'AND' means
  3137  *                         one element needs to match. 'NOT' means no elements may
  3629  *                         one element needs to match. 'NOT' means no elements may
  3138  *                         match. Default 'AND'.
  3630  *                         match. Default 'AND'.
  3139  * @return array Array of found values.
  3631  * @return array Array of found values.
  3140  */
  3632  */
  3141 function wp_list_filter( $list, $args = array(), $operator = 'AND' ) {
  3633 function wp_list_filter( $list, $args = array(), $operator = 'AND' ) {
  3142 	if ( ! is_array( $list ) )
  3634 	if ( ! is_array( $list ) ) {
  3143 		return array();
  3635 		return array();
  3144 
  3636 	}
  3145 	if ( empty( $args ) )
  3637 
  3146 		return $list;
  3638 	$util = new WP_List_Util( $list );
  3147 
  3639 	return $util->filter( $args, $operator );
  3148 	$operator = strtoupper( $operator );
       
  3149 	$count = count( $args );
       
  3150 	$filtered = array();
       
  3151 
       
  3152 	foreach ( $list as $key => $obj ) {
       
  3153 		$to_match = (array) $obj;
       
  3154 
       
  3155 		$matched = 0;
       
  3156 		foreach ( $args as $m_key => $m_value ) {
       
  3157 			if ( array_key_exists( $m_key, $to_match ) && $m_value == $to_match[ $m_key ] )
       
  3158 				$matched++;
       
  3159 		}
       
  3160 
       
  3161 		if ( ( 'AND' == $operator && $matched == $count )
       
  3162 		  || ( 'OR' == $operator && $matched > 0 )
       
  3163 		  || ( 'NOT' == $operator && 0 == $matched ) ) {
       
  3164 			$filtered[$key] = $obj;
       
  3165 		}
       
  3166 	}
       
  3167 
       
  3168 	return $filtered;
       
  3169 }
  3640 }
  3170 
  3641 
  3171 /**
  3642 /**
  3172  * Pluck a certain field out of each object in a list.
  3643  * Pluck a certain field out of each object in a list.
  3173  *
  3644  *
  3174  * This has the same functionality and prototype of
  3645  * This has the same functionality and prototype of
  3175  * array_column() (PHP 5.5) but also supports objects.
  3646  * array_column() (PHP 5.5) but also supports objects.
  3176  *
  3647  *
  3177  * @since 3.1.0
  3648  * @since 3.1.0
  3178  * @since 4.0.0 $index_key parameter added.
  3649  * @since 4.0.0 $index_key parameter added.
       
  3650  * @since 4.7.0 Uses WP_List_Util class.
  3179  *
  3651  *
  3180  * @param array      $list      List of objects or arrays
  3652  * @param array      $list      List of objects or arrays
  3181  * @param int|string $field     Field from the object to place instead of the entire object
  3653  * @param int|string $field     Field from the object to place instead of the entire object
  3182  * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
  3654  * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
  3183  *                              Default null.
  3655  *                              Default null.
  3184  * @return array Array of found values. If `$index_key` is set, an array of found values with keys
  3656  * @return array Array of found values. If `$index_key` is set, an array of found values with keys
  3185  *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
  3657  *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
  3186  *               `$list` will be preserved in the results.
  3658  *               `$list` will be preserved in the results.
  3187  */
  3659  */
  3188 function wp_list_pluck( $list, $field, $index_key = null ) {
  3660 function wp_list_pluck( $list, $field, $index_key = null ) {
  3189 	if ( ! $index_key ) {
  3661 	$util = new WP_List_Util( $list );
  3190 		/*
  3662 	return $util->pluck( $field, $index_key );
  3191 		 * This is simple. Could at some point wrap array_column()
  3663 }
  3192 		 * if we knew we had an array of arrays.
  3664 
  3193 		 */
  3665 /**
  3194 		foreach ( $list as $key => $value ) {
  3666  * Sorts a list of objects, based on one or more orderby arguments.
  3195 			if ( is_object( $value ) ) {
  3667  *
  3196 				$list[ $key ] = $value->$field;
  3668  * @since 4.7.0
  3197 			} else {
  3669  *
  3198 				$list[ $key ] = $value[ $field ];
  3670  * @param array        $list          An array of objects to filter.
  3199 			}
  3671  * @param string|array $orderby       Optional. Either the field name to order by or an array
  3200 		}
  3672  *                                    of multiple orderby fields as $orderby => $order.
  3201 		return $list;
  3673  * @param string       $order         Optional. Either 'ASC' or 'DESC'. Only used if $orderby
  3202 	}
  3674  *                                    is a string.
  3203 
  3675  * @param bool         $preserve_keys Optional. Whether to preserve keys. Default false.
  3204 	/*
  3676  * @return array The sorted array.
  3205 	 * When index_key is not set for a particular item, push the value
  3677  */
  3206 	 * to the end of the stack. This is how array_column() behaves.
  3678 function wp_list_sort( $list, $orderby = array(), $order = 'ASC', $preserve_keys = false ) {
  3207 	 */
  3679 	if ( ! is_array( $list ) ) {
  3208 	$newlist = array();
  3680 		return array();
  3209 	foreach ( $list as $value ) {
  3681 	}
  3210 		if ( is_object( $value ) ) {
  3682 
  3211 			if ( isset( $value->$index_key ) ) {
  3683 	$util = new WP_List_Util( $list );
  3212 				$newlist[ $value->$index_key ] = $value->$field;
  3684 	return $util->sort( $orderby, $order, $preserve_keys );
  3213 			} else {
       
  3214 				$newlist[] = $value->$field;
       
  3215 			}
       
  3216 		} else {
       
  3217 			if ( isset( $value[ $index_key ] ) ) {
       
  3218 				$newlist[ $value[ $index_key ] ] = $value[ $field ];
       
  3219 			} else {
       
  3220 				$newlist[] = $value[ $field ];
       
  3221 			}
       
  3222 		}
       
  3223 	}
       
  3224 
       
  3225 	return $newlist;
       
  3226 }
  3685 }
  3227 
  3686 
  3228 /**
  3687 /**
  3229  * Determines if Widgets library should be loaded.
  3688  * Determines if Widgets library should be loaded.
  3230  *
  3689  *
  3233  *
  3692  *
  3234  * @since 2.2.0
  3693  * @since 2.2.0
  3235  */
  3694  */
  3236 function wp_maybe_load_widgets() {
  3695 function wp_maybe_load_widgets() {
  3237 	/**
  3696 	/**
  3238 	 * Filter whether to load the Widgets library.
  3697 	 * Filters whether to load the Widgets library.
  3239 	 *
  3698 	 *
  3240 	 * Passing a falsey value to the filter will effectively short-circuit
  3699 	 * Passing a falsey value to the filter will effectively short-circuit
  3241 	 * the Widgets library from loading.
  3700 	 * the Widgets library from loading.
  3242 	 *
  3701 	 *
  3243 	 * @since 2.8.0
  3702 	 * @since 2.8.0
  3256 
  3715 
  3257 /**
  3716 /**
  3258  * Append the Widgets menu to the themes main menu.
  3717  * Append the Widgets menu to the themes main menu.
  3259  *
  3718  *
  3260  * @since 2.2.0
  3719  * @since 2.2.0
       
  3720  *
       
  3721  * @global array $submenu
  3261  */
  3722  */
  3262 function wp_widgets_add_menu() {
  3723 function wp_widgets_add_menu() {
  3263 	global $submenu;
  3724 	global $submenu;
  3264 
  3725 
  3265 	if ( ! current_theme_supports( 'widgets' ) )
  3726 	if ( ! current_theme_supports( 'widgets' ) )
  3310 		require_once( WP_CONTENT_DIR . '/db-error.php' );
  3771 		require_once( WP_CONTENT_DIR . '/db-error.php' );
  3311 		die();
  3772 		die();
  3312 	}
  3773 	}
  3313 
  3774 
  3314 	// If installing or in the admin, provide the verbose message.
  3775 	// If installing or in the admin, provide the verbose message.
  3315 	if ( defined('WP_INSTALLING') || defined('WP_ADMIN') )
  3776 	if ( wp_installing() || defined( 'WP_ADMIN' ) )
  3316 		wp_die($wpdb->error);
  3777 		wp_die($wpdb->error);
  3317 
  3778 
  3318 	// Otherwise, be terse.
  3779 	// Otherwise, be terse.
  3319 	status_header( 500 );
  3780 	status_header( 500 );
  3320 	nocache_headers();
  3781 	nocache_headers();
  3348 }
  3809 }
  3349 
  3810 
  3350 /**
  3811 /**
  3351  * Mark a function as deprecated and inform when it has been used.
  3812  * Mark a function as deprecated and inform when it has been used.
  3352  *
  3813  *
  3353  * There is a hook deprecated_function_run that will be called that can be used
  3814  * There is a {@see 'hook deprecated_function_run'} that will be called that can be used
  3354  * to get the backtrace up to what file and function called the deprecated
  3815  * to get the backtrace up to what file and function called the deprecated
  3355  * function.
  3816  * function.
  3356  *
  3817  *
  3357  * The current behavior is to trigger a user error if WP_DEBUG is true.
  3818  * The current behavior is to trigger a user error if `WP_DEBUG` is true.
  3358  *
  3819  *
  3359  * This function is to be used in every function that is deprecated.
  3820  * This function is to be used in every function that is deprecated.
  3360  *
  3821  *
  3361  * @since 2.5.0
  3822  * @since 2.5.0
  3362  * @access private
  3823  * @access private
  3377 	 * @param string $version     The version of WordPress that deprecated the function.
  3838 	 * @param string $version     The version of WordPress that deprecated the function.
  3378 	 */
  3839 	 */
  3379 	do_action( 'deprecated_function_run', $function, $replacement, $version );
  3840 	do_action( 'deprecated_function_run', $function, $replacement, $version );
  3380 
  3841 
  3381 	/**
  3842 	/**
  3382 	 * Filter whether to trigger an error for deprecated functions.
  3843 	 * Filters whether to trigger an error for deprecated functions.
  3383 	 *
  3844 	 *
  3384 	 * @since 2.5.0
  3845 	 * @since 2.5.0
  3385 	 *
  3846 	 *
  3386 	 * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
  3847 	 * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
  3387 	 */
  3848 	 */
  3388 	if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
  3849 	if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
  3389 		if ( function_exists( '__' ) ) {
  3850 		if ( function_exists( '__' ) ) {
  3390 			if ( ! is_null( $replacement ) )
  3851 			if ( ! is_null( $replacement ) ) {
       
  3852 				/* translators: 1: PHP function name, 2: version number, 3: alternative function name */
  3391 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) );
  3853 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) );
  3392 			else
  3854 			} else {
       
  3855 				/* translators: 1: PHP function name, 2: version number */
  3393 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
  3856 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
       
  3857 			}
  3394 		} else {
  3858 		} else {
  3395 			if ( ! is_null( $replacement ) )
  3859 			if ( ! is_null( $replacement ) ) {
  3396 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $function, $version, $replacement ) );
  3860 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $function, $version, $replacement ) );
  3397 			else
  3861 			} else {
  3398 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $function, $version ) );
  3862 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $function, $version ) );
  3399 		}
  3863 			}
  3400 	}
  3864 		}
       
  3865 	}
       
  3866 }
       
  3867 
       
  3868 /**
       
  3869  * Marks a constructor as deprecated and informs when it has been used.
       
  3870  *
       
  3871  * Similar to _deprecated_function(), but with different strings. Used to
       
  3872  * remove PHP4 style constructors.
       
  3873  *
       
  3874  * The current behavior is to trigger a user error if `WP_DEBUG` is true.
       
  3875  *
       
  3876  * This function is to be used in every PHP4 style constructor method that is deprecated.
       
  3877  *
       
  3878  * @since 4.3.0
       
  3879  * @since 4.5.0 Added the `$parent_class` parameter.
       
  3880  *
       
  3881  * @access private
       
  3882  *
       
  3883  * @param string $class        The class containing the deprecated constructor.
       
  3884  * @param string $version      The version of WordPress that deprecated the function.
       
  3885  * @param string $parent_class Optional. The parent class calling the deprecated constructor.
       
  3886  *                             Default empty string.
       
  3887  */
       
  3888 function _deprecated_constructor( $class, $version, $parent_class = '' ) {
       
  3889 
       
  3890 	/**
       
  3891 	 * Fires when a deprecated constructor is called.
       
  3892 	 *
       
  3893 	 * @since 4.3.0
       
  3894 	 * @since 4.5.0 Added the `$parent_class` parameter.
       
  3895 	 *
       
  3896 	 * @param string $class        The class containing the deprecated constructor.
       
  3897 	 * @param string $version      The version of WordPress that deprecated the function.
       
  3898 	 * @param string $parent_class The parent class calling the deprecated constructor.
       
  3899 	 */
       
  3900 	do_action( 'deprecated_constructor_run', $class, $version, $parent_class );
       
  3901 
       
  3902 	/**
       
  3903 	 * Filters whether to trigger an error for deprecated functions.
       
  3904 	 *
       
  3905 	 * `WP_DEBUG` must be true in addition to the filter evaluating to true.
       
  3906 	 *
       
  3907 	 * @since 4.3.0
       
  3908 	 *
       
  3909 	 * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
       
  3910 	 */
       
  3911 	if ( WP_DEBUG && apply_filters( 'deprecated_constructor_trigger_error', true ) ) {
       
  3912 		if ( function_exists( '__' ) ) {
       
  3913 			if ( ! empty( $parent_class ) ) {
       
  3914 				/* translators: 1: PHP class name, 2: PHP parent class name, 3: version number, 4: __construct() method */
       
  3915 				trigger_error( sprintf( __( 'The called constructor method for %1$s in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.' ),
       
  3916 					$class, $parent_class, $version, '<pre>__construct()</pre>' ) );
       
  3917 			} else {
       
  3918 				/* translators: 1: PHP class name, 2: version number, 3: __construct() method */
       
  3919 				trigger_error( sprintf( __( 'The called constructor method for %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
       
  3920 					$class, $version, '<pre>__construct()</pre>' ) );
       
  3921 			}
       
  3922 		} else {
       
  3923 			if ( ! empty( $parent_class ) ) {
       
  3924 				trigger_error( sprintf( 'The called constructor method for %1$s in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.',
       
  3925 					$class, $parent_class, $version, '<pre>__construct()</pre>' ) );
       
  3926 			} else {
       
  3927 				trigger_error( sprintf( 'The called constructor method for %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
       
  3928 					$class, $version, '<pre>__construct()</pre>' ) );
       
  3929 			}
       
  3930 		}
       
  3931 	}
       
  3932 
  3401 }
  3933 }
  3402 
  3934 
  3403 /**
  3935 /**
  3404  * Mark a file as deprecated and inform when it has been used.
  3936  * Mark a file as deprecated and inform when it has been used.
  3405  *
  3937  *
  3406  * There is a hook deprecated_file_included that will be called that can be used
  3938  * There is a hook {@see 'deprecated_file_included'} that will be called that can be used
  3407  * to get the backtrace up to what file and function included the deprecated
  3939  * to get the backtrace up to what file and function included the deprecated
  3408  * file.
  3940  * file.
  3409  *
  3941  *
  3410  * The current behavior is to trigger a user error if WP_DEBUG is true.
  3942  * The current behavior is to trigger a user error if `WP_DEBUG` is true.
  3411  *
  3943  *
  3412  * This function is to be used in every file that is deprecated.
  3944  * This function is to be used in every file that is deprecated.
  3413  *
  3945  *
  3414  * @since 2.5.0
  3946  * @since 2.5.0
  3415  * @access private
  3947  * @access private
  3433 	 * @param string $message     A message regarding the change.
  3965 	 * @param string $message     A message regarding the change.
  3434 	 */
  3966 	 */
  3435 	do_action( 'deprecated_file_included', $file, $replacement, $version, $message );
  3967 	do_action( 'deprecated_file_included', $file, $replacement, $version, $message );
  3436 
  3968 
  3437 	/**
  3969 	/**
  3438 	 * Filter whether to trigger an error for deprecated files.
  3970 	 * Filters whether to trigger an error for deprecated files.
  3439 	 *
  3971 	 *
  3440 	 * @since 2.5.0
  3972 	 * @since 2.5.0
  3441 	 *
  3973 	 *
  3442 	 * @param bool $trigger Whether to trigger the error for deprecated files. Default true.
  3974 	 * @param bool $trigger Whether to trigger the error for deprecated files. Default true.
  3443 	 */
  3975 	 */
  3444 	if ( WP_DEBUG && apply_filters( 'deprecated_file_trigger_error', true ) ) {
  3976 	if ( WP_DEBUG && apply_filters( 'deprecated_file_trigger_error', true ) ) {
  3445 		$message = empty( $message ) ? '' : ' ' . $message;
  3977 		$message = empty( $message ) ? '' : ' ' . $message;
  3446 		if ( function_exists( '__' ) ) {
  3978 		if ( function_exists( '__' ) ) {
  3447 			if ( ! is_null( $replacement ) )
  3979 			if ( ! is_null( $replacement ) ) {
       
  3980 				/* translators: 1: PHP file name, 2: version number, 3: alternative file name */
  3448 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) . $message );
  3981 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) . $message );
  3449 			else
  3982 			} else {
       
  3983 				/* translators: 1: PHP file name, 2: version number */
  3450 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $file, $version ) . $message );
  3984 				trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $file, $version ) . $message );
       
  3985 			}
  3451 		} else {
  3986 		} else {
  3452 			if ( ! is_null( $replacement ) )
  3987 			if ( ! is_null( $replacement ) ) {
  3453 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $file, $version, $replacement ) . $message );
  3988 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $file, $version, $replacement ) . $message );
  3454 			else
  3989 			} else {
  3455 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $file, $version ) . $message );
  3990 				trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $file, $version ) . $message );
       
  3991 			}
  3456 		}
  3992 		}
  3457 	}
  3993 	}
  3458 }
  3994 }
  3459 /**
  3995 /**
  3460  * Mark a function argument as deprecated and inform when it has been used.
  3996  * Mark a function argument as deprecated and inform when it has been used.
  3463  * Before this function is called, the argument must be checked for whether it was
  3999  * Before this function is called, the argument must be checked for whether it was
  3464  * used by comparing it to its default value or evaluating whether it is empty.
  4000  * used by comparing it to its default value or evaluating whether it is empty.
  3465  * For example:
  4001  * For example:
  3466  *
  4002  *
  3467  *     if ( ! empty( $deprecated ) ) {
  4003  *     if ( ! empty( $deprecated ) ) {
  3468  *         _deprecated_argument( __FUNCTION__, '3.0' );
  4004  *         _deprecated_argument( __FUNCTION__, '3.0.0' );
  3469  *     }
  4005  *     }
  3470  *
  4006  *
  3471  *
  4007  *
  3472  * There is a hook deprecated_argument_run that will be called that can be used
  4008  * There is a hook deprecated_argument_run that will be called that can be used
  3473  * to get the backtrace up to what file and function used the deprecated
  4009  * to get the backtrace up to what file and function used the deprecated
  3494 	 * @param string $version  The version of WordPress that deprecated the argument used.
  4030 	 * @param string $version  The version of WordPress that deprecated the argument used.
  3495 	 */
  4031 	 */
  3496 	do_action( 'deprecated_argument_run', $function, $message, $version );
  4032 	do_action( 'deprecated_argument_run', $function, $message, $version );
  3497 
  4033 
  3498 	/**
  4034 	/**
  3499 	 * Filter whether to trigger an error for deprecated arguments.
  4035 	 * Filters whether to trigger an error for deprecated arguments.
  3500 	 *
  4036 	 *
  3501 	 * @since 3.0.0
  4037 	 * @since 3.0.0
  3502 	 *
  4038 	 *
  3503 	 * @param bool $trigger Whether to trigger the error for deprecated arguments. Default true.
  4039 	 * @param bool $trigger Whether to trigger the error for deprecated arguments. Default true.
  3504 	 */
  4040 	 */
  3505 	if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) {
  4041 	if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) {
  3506 		if ( function_exists( '__' ) ) {
  4042 		if ( function_exists( '__' ) ) {
  3507 			if ( ! is_null( $message ) )
  4043 			if ( ! is_null( $message ) ) {
       
  4044 				/* translators: 1: PHP function name, 2: version number, 3: optional message regarding the change */
  3508 				trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s'), $function, $version, $message ) );
  4045 				trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s'), $function, $version, $message ) );
  3509 			else
  4046 			} else {
       
  4047 				/* translators: 1: PHP function name, 2: version number */
  3510 				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 ) );
  4048 				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 ) );
       
  4049 			}
  3511 		} else {
  4050 		} else {
  3512 			if ( ! is_null( $message ) )
  4051 			if ( ! is_null( $message ) ) {
  3513 				trigger_error( sprintf( '%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s', $function, $version, $message ) );
  4052 				trigger_error( sprintf( '%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s', $function, $version, $message ) );
  3514 			else
  4053 			} else {
  3515 				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 ) );
  4054 				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 ) );
       
  4055 			}
       
  4056 		}
       
  4057 	}
       
  4058 }
       
  4059 
       
  4060 /**
       
  4061  * Marks a deprecated action or filter hook as deprecated and throws a notice.
       
  4062  *
       
  4063  * Use the {@see 'deprecated_hook_run'} action to get the backtrace describing where
       
  4064  * the deprecated hook was called.
       
  4065  *
       
  4066  * Default behavior is to trigger a user error if `WP_DEBUG` is true.
       
  4067  *
       
  4068  * This function is called by the do_action_deprecated() and apply_filters_deprecated()
       
  4069  * functions, and so generally does not need to be called directly.
       
  4070  *
       
  4071  * @since 4.6.0
       
  4072  * @access private
       
  4073  *
       
  4074  * @param string $hook        The hook that was used.
       
  4075  * @param string $version     The version of WordPress that deprecated the hook.
       
  4076  * @param string $replacement Optional. The hook that should have been used.
       
  4077  * @param string $message     Optional. A message regarding the change.
       
  4078  */
       
  4079 function _deprecated_hook( $hook, $version, $replacement = null, $message = null ) {
       
  4080 	/**
       
  4081 	 * Fires when a deprecated hook is called.
       
  4082 	 *
       
  4083 	 * @since 4.6.0
       
  4084 	 *
       
  4085 	 * @param string $hook        The hook that was called.
       
  4086 	 * @param string $replacement The hook that should be used as a replacement.
       
  4087 	 * @param string $version     The version of WordPress that deprecated the argument used.
       
  4088 	 * @param string $message     A message regarding the change.
       
  4089 	 */
       
  4090 	do_action( 'deprecated_hook_run', $hook, $replacement, $version, $message );
       
  4091 
       
  4092 	/**
       
  4093 	 * Filters whether to trigger deprecated hook errors.
       
  4094 	 *
       
  4095 	 * @since 4.6.0
       
  4096 	 *
       
  4097 	 * @param bool $trigger Whether to trigger deprecated hook errors. Requires
       
  4098 	 *                      `WP_DEBUG` to be defined true.
       
  4099 	 */
       
  4100 	if ( WP_DEBUG && apply_filters( 'deprecated_hook_trigger_error', true ) ) {
       
  4101 		$message = empty( $message ) ? '' : ' ' . $message;
       
  4102 		if ( ! is_null( $replacement ) ) {
       
  4103 			/* translators: 1: WordPress hook name, 2: version number, 3: alternative hook name */
       
  4104 			trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ), $hook, $version, $replacement ) . $message );
       
  4105 		} else {
       
  4106 			/* translators: 1: WordPress hook name, 2: version number */
       
  4107 			trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ), $hook, $version ) . $message );
  3516 		}
  4108 		}
  3517 	}
  4109 	}
  3518 }
  4110 }
  3519 
  4111 
  3520 /**
  4112 /**
  3521  * Mark something as being incorrectly called.
  4113  * Mark something as being incorrectly called.
  3522  *
  4114  *
  3523  * There is a hook doing_it_wrong_run that will be called that can be used
  4115  * There is a hook {@see 'doing_it_wrong_run'} that will be called that can be used
  3524  * to get the backtrace up to what file and function called the deprecated
  4116  * to get the backtrace up to what file and function called the deprecated
  3525  * function.
  4117  * function.
  3526  *
  4118  *
  3527  * The current behavior is to trigger a user error if WP_DEBUG is true.
  4119  * The current behavior is to trigger a user error if `WP_DEBUG` is true.
  3528  *
  4120  *
  3529  * @since 3.1.0
  4121  * @since 3.1.0
  3530  * @access private
  4122  * @access private
  3531  *
  4123  *
  3532  * @param string $function The function that was called.
  4124  * @param string $function The function that was called.
  3545 	 * @param string $version  The version of WordPress where the message was added.
  4137 	 * @param string $version  The version of WordPress where the message was added.
  3546 	 */
  4138 	 */
  3547 	do_action( 'doing_it_wrong_run', $function, $message, $version );
  4139 	do_action( 'doing_it_wrong_run', $function, $message, $version );
  3548 
  4140 
  3549 	/**
  4141 	/**
  3550 	 * Filter whether to trigger an error for _doing_it_wrong() calls.
  4142 	 * Filters whether to trigger an error for _doing_it_wrong() calls.
  3551 	 *
  4143 	 *
  3552 	 * @since 3.1.0
  4144 	 * @since 3.1.0
  3553 	 *
  4145 	 *
  3554 	 * @param bool $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
  4146 	 * @param bool $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
  3555 	 */
  4147 	 */
  3556 	if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
  4148 	if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
  3557 		if ( function_exists( '__' ) ) {
  4149 		if ( function_exists( '__' ) ) {
  3558 			$version = is_null( $version ) ? '' : sprintf( __( '(This message was added in version %s.)' ), $version );
  4150 			if ( is_null( $version ) ) {
  3559 			$message .= ' ' . __( 'Please see <a href="https://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information.' );
  4151 				$version = '';
       
  4152 			} else {
       
  4153 				/* translators: %s: version number */
       
  4154 				$version = sprintf( __( '(This message was added in version %s.)' ), $version );
       
  4155 			}
       
  4156 			/* translators: %s: Codex URL */
       
  4157 			$message .= ' ' . sprintf( __( 'Please see <a href="%s">Debugging in WordPress</a> for more information.' ),
       
  4158 				__( 'https://codex.wordpress.org/Debugging_in_WordPress' )
       
  4159 			);
       
  4160 			/* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: Version information message */
  3560 			trigger_error( sprintf( __( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s' ), $function, $message, $version ) );
  4161 			trigger_error( sprintf( __( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s' ), $function, $message, $version ) );
  3561 		} else {
  4162 		} else {
  3562 			$version = is_null( $version ) ? '' : sprintf( '(This message was added in version %s.)', $version );
  4163 			if ( is_null( $version ) ) {
  3563 			$message .= ' Please see <a href="https://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information.';
  4164 				$version = '';
       
  4165 			} else {
       
  4166 				$version = sprintf( '(This message was added in version %s.)', $version );
       
  4167 			}
       
  4168 			$message .= sprintf( ' Please see <a href="%s">Debugging in WordPress</a> for more information.',
       
  4169 				'https://codex.wordpress.org/Debugging_in_WordPress'
       
  4170 			);
  3564 			trigger_error( sprintf( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s', $function, $message, $version ) );
  4171 			trigger_error( sprintf( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s', $function, $message, $version ) );
  3565 		}
  4172 		}
  3566 	}
  4173 	}
  3567 }
  4174 }
  3568 
  4175 
  3581 
  4188 
  3582 /**
  4189 /**
  3583  * Does the specified module exist in the Apache config?
  4190  * Does the specified module exist in the Apache config?
  3584  *
  4191  *
  3585  * @since 2.5.0
  4192  * @since 2.5.0
       
  4193  *
       
  4194  * @global bool $is_apache
  3586  *
  4195  *
  3587  * @param string $mod     The module, e.g. mod_rewrite.
  4196  * @param string $mod     The module, e.g. mod_rewrite.
  3588  * @param bool   $default Optional. The default return value if the module is not found. Default false.
  4197  * @param bool   $default Optional. The default return value if the module is not found. Default false.
  3589  * @return bool Whether the specified module is loaded.
  4198  * @return bool Whether the specified module is loaded.
  3590  */
  4199  */
  3610 
  4219 
  3611 /**
  4220 /**
  3612  * Check if IIS 7+ supports pretty permalinks.
  4221  * Check if IIS 7+ supports pretty permalinks.
  3613  *
  4222  *
  3614  * @since 2.8.0
  4223  * @since 2.8.0
       
  4224  *
       
  4225  * @global bool $is_iis7
  3615  *
  4226  *
  3616  * @return bool Whether IIS7 supports permalinks.
  4227  * @return bool Whether IIS7 supports permalinks.
  3617  */
  4228  */
  3618 function iis7_supports_permalinks() {
  4229 function iis7_supports_permalinks() {
  3619 	global $is_iis7;
  4230 	global $is_iis7;
  3627 		 * Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the web site. When
  4238 		 * Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the web site. When
  3628 		 * URL Rewrite 1.1 is loaded it always sets a server variable called 'IIS_UrlRewriteModule'.
  4239 		 * URL Rewrite 1.1 is loaded it always sets a server variable called 'IIS_UrlRewriteModule'.
  3629 		 * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
  4240 		 * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
  3630 		 * via ISAPI then pretty permalinks will not work.
  4241 		 * via ISAPI then pretty permalinks will not work.
  3631 		 */
  4242 		 */
  3632 		$supports_permalinks = class_exists('DOMDocument') && isset($_SERVER['IIS_UrlRewriteModule']) && ( PHP_SAPI == 'cgi-fcgi' );
  4243 		$supports_permalinks = class_exists( 'DOMDocument', false ) && isset($_SERVER['IIS_UrlRewriteModule']) && ( PHP_SAPI == 'cgi-fcgi' );
  3633 	}
  4244 	}
  3634 
  4245 
  3635 	/**
  4246 	/**
  3636 	 * Filter whether IIS 7+ supports pretty permalinks.
  4247 	 * Filters whether IIS 7+ supports pretty permalinks.
  3637 	 *
  4248 	 *
  3638 	 * @since 2.8.0
  4249 	 * @since 2.8.0
  3639 	 *
  4250 	 *
  3640 	 * @param bool $supports_permalinks Whether IIS7 supports permalinks. Default false.
  4251 	 * @param bool $supports_permalinks Whether IIS7 supports permalinks. Default false.
  3641 	 */
  4252 	 */
  3642 	return apply_filters( 'iis7_supports_permalinks', $supports_permalinks );
  4253 	return apply_filters( 'iis7_supports_permalinks', $supports_permalinks );
  3643 }
  4254 }
  3644 
  4255 
  3645 /**
  4256 /**
  3646  * File validates against allowed set of defined rules.
  4257  * Validates a file name and path against an allowed set of rules.
  3647  *
  4258  *
  3648  * A return value of '1' means that the $file contains either '..' or './'. A
  4259  * A return value of `1` means the file path contains directory traversal.
  3649  * return value of '2' means that the $file contains ':' after the first
  4260  *
  3650  * character. A return value of '3' means that the file is not in the allowed
  4261  * A return value of `2` means the file path contains a Windows drive path.
  3651  * files list.
  4262  *
       
  4263  * A return value of `3` means the file is not in the allowed files list.
  3652  *
  4264  *
  3653  * @since 1.2.0
  4265  * @since 1.2.0
  3654  *
  4266  *
  3655  * @param string $file File path.
  4267  * @param string $file          File path.
  3656  * @param array $allowed_files List of allowed files.
  4268  * @param array  $allowed_files Optional. List of allowed files.
  3657  * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
  4269  * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
  3658  */
  4270  */
  3659 function validate_file( $file, $allowed_files = '' ) {
  4271 function validate_file( $file, $allowed_files = array() ) {
  3660 	if ( false !== strpos( $file, '..' ) )
  4272 	// `../` on its own is not allowed:
       
  4273 	if ( '../' === $file ) {
  3661 		return 1;
  4274 		return 1;
  3662 
  4275 	}
  3663 	if ( false !== strpos( $file, './' ) )
  4276 
       
  4277 	// More than one occurence of `../` is not allowed:
       
  4278 	if ( preg_match_all( '#\.\./#', $file, $matches, PREG_SET_ORDER ) && ( count( $matches ) > 1 ) ) {
  3664 		return 1;
  4279 		return 1;
  3665 
  4280 	}
       
  4281 
       
  4282 	// `../` which does not occur at the end of the path is not allowed:
       
  4283 	if ( false !== strpos( $file, '../' ) && '../' !== mb_substr( $file, -3, 3 ) ) {
       
  4284 		return 1;
       
  4285 	}
       
  4286 
       
  4287 	// Files not in the allowed file list are not allowed:
  3666 	if ( ! empty( $allowed_files ) && ! in_array( $file, $allowed_files ) )
  4288 	if ( ! empty( $allowed_files ) && ! in_array( $file, $allowed_files ) )
  3667 		return 3;
  4289 		return 3;
  3668 
  4290 
       
  4291 	// Absolute Windows drive paths are not allowed:
  3669 	if (':' == substr( $file, 1, 1 ) )
  4292 	if (':' == substr( $file, 1, 1 ) )
  3670 		return 2;
  4293 		return 2;
  3671 
  4294 
  3672 	return 0;
  4295 	return 0;
  3673 }
  4296 }
  3674 
  4297 
  3675 /**
  4298 /**
  3676  * Determine if SSL is used.
  4299  * Whether to force SSL used for the Administration Screens.
  3677  *
  4300  *
  3678  * @since 2.6.0
  4301  * @since 2.6.0
  3679  *
  4302  *
  3680  * @return bool True if SSL, false if not used.
  4303  * @staticvar bool $forced
  3681  */
       
  3682 function is_ssl() {
       
  3683 	if ( isset($_SERVER['HTTPS']) ) {
       
  3684 		if ( 'on' == strtolower($_SERVER['HTTPS']) )
       
  3685 			return true;
       
  3686 		if ( '1' == $_SERVER['HTTPS'] )
       
  3687 			return true;
       
  3688 	} elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
       
  3689 		return true;
       
  3690 	}
       
  3691 	return false;
       
  3692 }
       
  3693 
       
  3694 /**
       
  3695  * Whether SSL login should be forced.
       
  3696  *
       
  3697  * @since 2.6.0
       
  3698  *
       
  3699  * @see force_ssl_admin()
       
  3700  *
       
  3701  * @param string|bool $force Optional Whether to force SSL login. Default null.
       
  3702  * @return bool True if forced, false if not forced.
       
  3703  */
       
  3704 function force_ssl_login( $force = null ) {
       
  3705 	return force_ssl_admin( $force );
       
  3706 }
       
  3707 
       
  3708 /**
       
  3709  * Whether to force SSL used for the Administration Screens.
       
  3710  *
       
  3711  * @since 2.6.0
       
  3712  *
  4304  *
  3713  * @param string|bool $force Optional. Whether to force SSL in admin screens. Default null.
  4305  * @param string|bool $force Optional. Whether to force SSL in admin screens. Default null.
  3714  * @return bool True if forced, false if not forced.
  4306  * @return bool True if forced, false if not forced.
  3715  */
  4307  */
  3716 function force_ssl_admin( $force = null ) {
  4308 function force_ssl_admin( $force = null ) {
  3753 
  4345 
  3754 		} else {
  4346 		} else {
  3755 			if ( false !== strpos( $_SERVER['SCRIPT_FILENAME'], $abspath_fix ) ) {
  4347 			if ( false !== strpos( $_SERVER['SCRIPT_FILENAME'], $abspath_fix ) ) {
  3756 				// Request is hitting a file inside ABSPATH
  4348 				// Request is hitting a file inside ABSPATH
  3757 				$directory = str_replace( ABSPATH, '', $script_filename_dir );
  4349 				$directory = str_replace( ABSPATH, '', $script_filename_dir );
  3758 				// Strip off the sub directory, and any file/query paramss
  4350 				// Strip off the sub directory, and any file/query params
  3759 				$path = preg_replace( '#/' . preg_quote( $directory, '#' ) . '/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] );
  4351 				$path = preg_replace( '#/' . preg_quote( $directory, '#' ) . '/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] );
  3760 			} elseif ( false !== strpos( $abspath_fix, $script_filename_dir ) ) {
  4352 			} elseif ( false !== strpos( $abspath_fix, $script_filename_dir ) ) {
  3761 				// Request is hitting a file above ABSPATH
  4353 				// Request is hitting a file above ABSPATH
  3762 				$subdirectory = substr( $abspath_fix, strpos( $abspath_fix, $script_filename_dir ) + strlen( $script_filename_dir ) );
  4354 				$subdirectory = substr( $abspath_fix, strpos( $abspath_fix, $script_filename_dir ) + strlen( $script_filename_dir ) );
  3763 				// Strip off any file/query params from the path, appending the sub directory to the install
  4355 				// Strip off any file/query params from the path, appending the sub directory to the installation
  3764 				$path = preg_replace( '#/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] ) . $subdirectory;
  4356 				$path = preg_replace( '#/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] ) . $subdirectory;
  3765 			} else {
  4357 			} else {
  3766 				$path = $_SERVER['REQUEST_URI'];
  4358 				$path = $_SERVER['REQUEST_URI'];
  3767 			}
  4359 			}
  3768 		}
  4360 		}
  3784  * Suspension lasts for a single page load at most. Remember to call this
  4376  * Suspension lasts for a single page load at most. Remember to call this
  3785  * function again if you wish to re-enable cache adds earlier.
  4377  * function again if you wish to re-enable cache adds earlier.
  3786  *
  4378  *
  3787  * @since 3.3.0
  4379  * @since 3.3.0
  3788  *
  4380  *
       
  4381  * @staticvar bool $_suspend
       
  4382  *
  3789  * @param bool $suspend Optional. Suspends additions if true, re-enables them if false.
  4383  * @param bool $suspend Optional. Suspends additions if true, re-enables them if false.
  3790  * @return bool The current suspend setting
  4384  * @return bool The current suspend setting
  3791  */
  4385  */
  3792 function wp_suspend_cache_addition( $suspend = null ) {
  4386 function wp_suspend_cache_addition( $suspend = null ) {
  3793 	static $_suspend = false;
  4387 	static $_suspend = false;
  3799 }
  4393 }
  3800 
  4394 
  3801 /**
  4395 /**
  3802  * Suspend cache invalidation.
  4396  * Suspend cache invalidation.
  3803  *
  4397  *
  3804  * Turns cache invalidation on and off. Useful during imports where you don't wont to do
  4398  * Turns cache invalidation on and off. Useful during imports where you don't want to do
  3805  * invalidations every time a post is inserted. Callers must be sure that what they are
  4399  * invalidations every time a post is inserted. Callers must be sure that what they are
  3806  * doing won't lead to an inconsistent cache when invalidation is suspended.
  4400  * doing won't lead to an inconsistent cache when invalidation is suspended.
  3807  *
  4401  *
  3808  * @since 2.7.0
  4402  * @since 2.7.0
       
  4403  *
       
  4404  * @global bool $_wp_suspend_cache_invalidation
  3809  *
  4405  *
  3810  * @param bool $suspend Optional. Whether to suspend or enable cache invalidation. Default true.
  4406  * @param bool $suspend Optional. Whether to suspend or enable cache invalidation. Default true.
  3811  * @return bool The current suspend setting.
  4407  * @return bool The current suspend setting.
  3812  */
  4408  */
  3813 function wp_suspend_cache_invalidation( $suspend = true ) {
  4409 function wp_suspend_cache_invalidation( $suspend = true ) {
  3820 
  4416 
  3821 /**
  4417 /**
  3822  * Determine whether a site is the main site of the current network.
  4418  * Determine whether a site is the main site of the current network.
  3823  *
  4419  *
  3824  * @since 3.0.0
  4420  * @since 3.0.0
  3825  *
  4421  * @since 4.9.0 The $network_id parameter has been added.
  3826  * @param int $site_id Optional. Site ID to test. Defaults to current site.
  4422  *
  3827  *                     Defaults to current site.
  4423  * @param int $site_id    Optional. Site ID to test. Defaults to current site.
       
  4424  * @param int $network_id Optional. Network ID of the network to check for.
       
  4425  *                        Defaults to current network.
  3828  * @return bool True if $site_id is the main site of the network, or if not
  4426  * @return bool True if $site_id is the main site of the network, or if not
  3829  *              running Multisite.
  4427  *              running Multisite.
  3830  */
  4428  */
  3831 function is_main_site( $site_id = null ) {
  4429 function is_main_site( $site_id = null, $network_id = null ) {
  3832 	// This is the current network's information; 'site' is old terminology.
  4430 	if ( ! is_multisite() ) {
  3833 	global $current_site;
       
  3834 
       
  3835 	if ( ! is_multisite() )
       
  3836 		return true;
  4431 		return true;
  3837 
  4432 	}
  3838 	if ( ! $site_id )
  4433 
       
  4434 	if ( ! $site_id ) {
  3839 		$site_id = get_current_blog_id();
  4435 		$site_id = get_current_blog_id();
  3840 
  4436 	}
  3841 	return (int) $site_id === (int) $current_site->blog_id;
  4437 
  3842 }
  4438 	$site_id = (int) $site_id;
  3843 
  4439 
  3844 /**
  4440 	return $site_id === get_main_site_id( $network_id );
  3845  * Determine whether a network is the main network of the Multisite install.
  4441 }
       
  4442 
       
  4443 /**
       
  4444  * Gets the main site ID.
       
  4445  *
       
  4446  * @since 4.9.0
       
  4447  *
       
  4448  * @param int $network_id Optional. The ID of the network for which to get the main site.
       
  4449  *                        Defaults to the current network.
       
  4450  * @return int The ID of the main site.
       
  4451  */
       
  4452 function get_main_site_id( $network_id = null ) {
       
  4453 	if ( ! is_multisite() ) {
       
  4454 		return get_current_blog_id();
       
  4455 	}
       
  4456 
       
  4457 	$network = get_network( $network_id );
       
  4458 	if ( ! $network ) {
       
  4459 		return 0;
       
  4460 	}
       
  4461 
       
  4462 	return $network->site_id;
       
  4463 }
       
  4464 
       
  4465 /**
       
  4466  * Determine whether a network is the main network of the Multisite installation.
  3846  *
  4467  *
  3847  * @since 3.7.0
  4468  * @since 3.7.0
  3848  *
  4469  *
  3849  * @param int $network_id Optional. Network ID to test. Defaults to current network.
  4470  * @param int $network_id Optional. Network ID to test. Defaults to current network.
  3850  * @return bool True if $network_id is the main network, or if not running Multisite.
  4471  * @return bool True if $network_id is the main network, or if not running Multisite.
  3851  */
  4472  */
  3852 function is_main_network( $network_id = null ) {
  4473 function is_main_network( $network_id = null ) {
  3853 	global $wpdb;
  4474 	if ( ! is_multisite() ) {
  3854 
       
  3855 	if ( ! is_multisite() )
       
  3856 		return true;
  4475 		return true;
  3857 
  4476 	}
  3858 	$current_network_id = (int) get_current_site()->id;
  4477 
  3859 
  4478 	if ( null === $network_id ) {
  3860 	if ( ! $network_id )
  4479 		$network_id = get_current_network_id();
  3861 		$network_id = $current_network_id;
  4480 	}
       
  4481 
  3862 	$network_id = (int) $network_id;
  4482 	$network_id = (int) $network_id;
  3863 
  4483 
  3864 	if ( defined( 'PRIMARY_NETWORK_ID' ) )
  4484 	return ( $network_id === get_main_network_id() );
  3865 		return $network_id === (int) PRIMARY_NETWORK_ID;
  4485 }
  3866 
  4486 
  3867 	if ( 1 === $current_network_id )
  4487 /**
  3868 		return $network_id === $current_network_id;
  4488  * Get the main network ID.
  3869 
  4489  *
  3870 	$primary_network_id = (int) wp_cache_get( 'primary_network_id', 'site-options' );
  4490  * @since 4.3.0
  3871 
  4491  *
  3872 	if ( $primary_network_id )
  4492  * @return int The ID of the main network.
  3873 		return $network_id === $primary_network_id;
  4493  */
  3874 
  4494 function get_main_network_id() {
  3875 	$primary_network_id = (int) $wpdb->get_var( "SELECT id FROM $wpdb->site ORDER BY id LIMIT 1" );
  4495 	if ( ! is_multisite() ) {
  3876 	wp_cache_add( 'primary_network_id', $primary_network_id, 'site-options' );
  4496 		return 1;
  3877 
  4497 	}
  3878 	return $network_id === $primary_network_id;
  4498 
       
  4499 	$current_network = get_network();
       
  4500 
       
  4501 	if ( defined( 'PRIMARY_NETWORK_ID' ) ) {
       
  4502 		$main_network_id = PRIMARY_NETWORK_ID;
       
  4503 	} elseif ( isset( $current_network->id ) && 1 === (int) $current_network->id ) {
       
  4504 		// If the current network has an ID of 1, assume it is the main network.
       
  4505 		$main_network_id = 1;
       
  4506 	} else {
       
  4507 		$_networks = get_networks( array( 'fields' => 'ids', 'number' => 1 ) );
       
  4508 		$main_network_id = array_shift( $_networks );
       
  4509 	}
       
  4510 
       
  4511 	/**
       
  4512 	 * Filters the main network ID.
       
  4513 	 *
       
  4514 	 * @since 4.3.0
       
  4515 	 *
       
  4516 	 * @param int $main_network_id The ID of the main network.
       
  4517 	 */
       
  4518 	return (int) apply_filters( 'get_main_network_id', $main_network_id );
  3879 }
  4519 }
  3880 
  4520 
  3881 /**
  4521 /**
  3882  * Determine whether global terms are enabled.
  4522  * Determine whether global terms are enabled.
  3883  *
  4523  *
  3884  * @since 3.0.0
  4524  * @since 3.0.0
       
  4525  *
       
  4526  * @staticvar bool $global_terms
  3885  *
  4527  *
  3886  * @return bool True if multisite and global terms enabled.
  4528  * @return bool True if multisite and global terms enabled.
  3887  */
  4529  */
  3888 function global_terms_enabled() {
  4530 function global_terms_enabled() {
  3889 	if ( ! is_multisite() )
  4531 	if ( ! is_multisite() )
  3891 
  4533 
  3892 	static $global_terms = null;
  4534 	static $global_terms = null;
  3893 	if ( is_null( $global_terms ) ) {
  4535 	if ( is_null( $global_terms ) ) {
  3894 
  4536 
  3895 		/**
  4537 		/**
  3896 		 * Filter whether global terms are enabled.
  4538 		 * Filters whether global terms are enabled.
  3897 		 *
  4539 		 *
  3898 		 * Passing a non-null value to the filter will effectively short-circuit the function,
  4540 		 * Passing a non-null value to the filter will effectively short-circuit the function,
  3899 		 * returning the value of the 'global_terms_enabled' site option instead.
  4541 		 * returning the value of the 'global_terms_enabled' site option instead.
  3900 		 *
  4542 		 *
  3901 		 * @since 3.0.0
  4543 		 * @since 3.0.0
  3902 		 *
  4544 		 *
  3903 		 * @param null $anbled Whether global terms are enabled.
  4545 		 * @param null $enabled Whether global terms are enabled.
  3904 		 */
  4546 		 */
  3905 		$filter = apply_filters( 'global_terms_enabled', null );
  4547 		$filter = apply_filters( 'global_terms_enabled', null );
  3906 		if ( ! is_null( $filter ) )
  4548 		if ( ! is_null( $filter ) )
  3907 			$global_terms = (bool) $filter;
  4549 			$global_terms = (bool) $filter;
  3908 		else
  4550 		else
  3916  *
  4558  *
  3917  * Overrides the gmt_offset option if we have a timezone_string available.
  4559  * Overrides the gmt_offset option if we have a timezone_string available.
  3918  *
  4560  *
  3919  * @since 2.8.0
  4561  * @since 2.8.0
  3920  *
  4562  *
  3921  * @return float|bool Timezone GMT offset, false otherwise.
  4563  * @return float|false Timezone GMT offset, false otherwise.
  3922  */
  4564  */
  3923 function wp_timezone_override_offset() {
  4565 function wp_timezone_override_offset() {
  3924 	if ( !$timezone_string = get_option( 'timezone_string' ) ) {
  4566 	if ( !$timezone_string = get_option( 'timezone_string' ) ) {
  3925 		return false;
  4567 		return false;
  3926 	}
  4568 	}
  3983 
  4625 
  3984 /**
  4626 /**
  3985  * Gives a nicely-formatted list of timezone strings.
  4627  * Gives a nicely-formatted list of timezone strings.
  3986  *
  4628  *
  3987  * @since 2.9.0
  4629  * @since 2.9.0
       
  4630  * @since 4.7.0 Added the `$locale` parameter.
       
  4631  *
       
  4632  * @staticvar bool $mo_loaded
       
  4633  * @staticvar string $locale_loaded
  3988  *
  4634  *
  3989  * @param string $selected_zone Selected timezone.
  4635  * @param string $selected_zone Selected timezone.
       
  4636  * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
  3990  * @return string
  4637  * @return string
  3991  */
  4638  */
  3992 function wp_timezone_choice( $selected_zone ) {
  4639 function wp_timezone_choice( $selected_zone, $locale = null ) {
  3993 	static $mo_loaded = false;
  4640 	static $mo_loaded = false, $locale_loaded = null;
  3994 
  4641 
  3995 	$continents = array( 'Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
  4642 	$continents = array( 'Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
  3996 
  4643 
  3997 	// Load translations for continents and cities
  4644 	// Load translations for continents and cities.
  3998 	if ( !$mo_loaded ) {
  4645 	if ( ! $mo_loaded || $locale !== $locale_loaded ) {
  3999 		$locale = get_locale();
  4646 		$locale_loaded = $locale ? $locale : get_locale();
  4000 		$mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
  4647 		$mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
       
  4648 		unload_textdomain( 'continents-cities' );
  4001 		load_textdomain( 'continents-cities', $mofile );
  4649 		load_textdomain( 'continents-cities', $mofile );
  4002 		$mo_loaded = true;
  4650 		$mo_loaded = true;
  4003 	}
  4651 	}
  4004 
  4652 
  4005 	$zonen = array();
  4653 	$zonen = array();
  4130  * of 'trash' for the number of days defined in EMPTY_TRASH_DAYS.
  4778  * of 'trash' for the number of days defined in EMPTY_TRASH_DAYS.
  4131  *
  4779  *
  4132  * The default value of `EMPTY_TRASH_DAYS` is 30 (days).
  4780  * The default value of `EMPTY_TRASH_DAYS` is 30 (days).
  4133  *
  4781  *
  4134  * @since 2.9.0
  4782  * @since 2.9.0
       
  4783  *
       
  4784  * @global wpdb $wpdb WordPress database abstraction object.
  4135  */
  4785  */
  4136 function wp_scheduled_delete() {
  4786 function wp_scheduled_delete() {
  4137 	global $wpdb;
  4787 	global $wpdb;
  4138 
  4788 
  4139 	$delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
  4789 	$delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
  4140 
  4790 
  4141 	$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);
  4791 	$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);
  4142 
  4792 
  4143 	foreach ( (array) $posts_to_delete as $post ) {
  4793 	foreach ( (array) $posts_to_delete as $post ) {
  4144 		$post_id = (int) $post['post_id'];
  4794 		$post_id = (int) $post['post_id'];
  4145 		if ( !$post_id )
  4795 		if ( !$post_id )
  4146 			continue;
  4796 			continue;
  4153 		} else {
  4803 		} else {
  4154 			wp_delete_post($post_id);
  4804 			wp_delete_post($post_id);
  4155 		}
  4805 		}
  4156 	}
  4806 	}
  4157 
  4807 
  4158 	$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);
  4808 	$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);
  4159 
  4809 
  4160 	foreach ( (array) $comments_to_delete as $comment ) {
  4810 	foreach ( (array) $comments_to_delete as $comment ) {
  4161 		$comment_id = (int) $comment['comment_id'];
  4811 		$comment_id = (int) $comment['comment_id'];
  4162 		if ( !$comment_id )
  4812 		if ( !$comment_id )
  4163 			continue;
  4813 			continue;
  4166 
  4816 
  4167 		if ( !$del_comment || 'trash' != $del_comment->comment_approved ) {
  4817 		if ( !$del_comment || 'trash' != $del_comment->comment_approved ) {
  4168 			delete_comment_meta($comment_id, '_wp_trash_meta_time');
  4818 			delete_comment_meta($comment_id, '_wp_trash_meta_time');
  4169 			delete_comment_meta($comment_id, '_wp_trash_meta_status');
  4819 			delete_comment_meta($comment_id, '_wp_trash_meta_status');
  4170 		} else {
  4820 		} else {
  4171 			wp_delete_comment($comment_id);
  4821 			wp_delete_comment( $del_comment );
  4172 		}
  4822 		}
  4173 	}
  4823 	}
  4174 }
  4824 }
  4175 
  4825 
  4176 /**
  4826 /**
  4187  *
  4837  *
  4188  * @since 2.9.0
  4838  * @since 2.9.0
  4189  *
  4839  *
  4190  * @param string $file            Path to the file.
  4840  * @param string $file            Path to the file.
  4191  * @param array  $default_headers List of headers, in the format array('HeaderKey' => 'Header Name').
  4841  * @param array  $default_headers List of headers, in the format array('HeaderKey' => 'Header Name').
  4192  * @param string $context         Optional. If specified adds filter hook "extra_{$context}_headers".
  4842  * @param string $context         Optional. If specified adds filter hook {@see 'extra_$context_headers'}.
  4193  *                                Default empty.
  4843  *                                Default empty.
  4194  * @return array Array of file headers in `HeaderKey => Header Value` format.
  4844  * @return array Array of file headers in `HeaderKey => Header Value` format.
  4195  */
  4845  */
  4196 function get_file_data( $file, $default_headers, $context = '' ) {
  4846 function get_file_data( $file, $default_headers, $context = '' ) {
  4197 	// We don't need to write to the file, so just open for reading.
  4847 	// We don't need to write to the file, so just open for reading.
  4205 
  4855 
  4206 	// Make sure we catch CR-only line endings.
  4856 	// Make sure we catch CR-only line endings.
  4207 	$file_data = str_replace( "\r", "\n", $file_data );
  4857 	$file_data = str_replace( "\r", "\n", $file_data );
  4208 
  4858 
  4209 	/**
  4859 	/**
  4210 	 * Filter extra file headers by context.
  4860 	 * Filters extra file headers by context.
  4211 	 *
  4861 	 *
  4212 	 * The dynamic portion of the hook name, `$context`, refers to
  4862 	 * The dynamic portion of the hook name, `$context`, refers to
  4213 	 * the context where extra headers might be loaded.
  4863 	 * the context where extra headers might be loaded.
  4214 	 *
  4864 	 *
  4215 	 * @since 2.9.0
  4865 	 * @since 2.9.0
  4240  *
  4890  *
  4241  * @since 3.0.0
  4891  * @since 3.0.0
  4242  *
  4892  *
  4243  * @see __return_false()
  4893  * @see __return_false()
  4244  *
  4894  *
  4245  * @return bool True.
  4895  * @return true True.
  4246  */
  4896  */
  4247 function __return_true() {
  4897 function __return_true() {
  4248 	return true;
  4898 	return true;
  4249 }
  4899 }
  4250 
  4900 
  4255  *
  4905  *
  4256  * @since 3.0.0
  4906  * @since 3.0.0
  4257  *
  4907  *
  4258  * @see __return_true()
  4908  * @see __return_true()
  4259  *
  4909  *
  4260  * @return bool False.
  4910  * @return false False.
  4261  */
  4911  */
  4262 function __return_false() {
  4912 function __return_false() {
  4263 	return false;
  4913 	return false;
  4264 }
  4914 }
  4265 
  4915 
  4320 /**
  4970 /**
  4321  * Send a HTTP header to disable content type sniffing in browsers which support it.
  4971  * Send a HTTP header to disable content type sniffing in browsers which support it.
  4322  *
  4972  *
  4323  * @since 3.0.0
  4973  * @since 3.0.0
  4324  *
  4974  *
  4325  * @see http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
  4975  * @see https://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
  4326  * @see http://src.chromium.org/viewvc/chrome?view=rev&revision=6985
  4976  * @see https://src.chromium.org/viewvc/chrome?view=rev&revision=6985
  4327  */
  4977  */
  4328 function send_nosniff_header() {
  4978 function send_nosniff_header() {
  4329 	@header( 'X-Content-Type-Options: nosniff' );
  4979 	@header( 'X-Content-Type-Options: nosniff' );
  4330 }
  4980 }
  4331 
  4981 
  4358  * Find hierarchy loops using a callback function that maps object IDs to parent IDs.
  5008  * Find hierarchy loops using a callback function that maps object IDs to parent IDs.
  4359  *
  5009  *
  4360  * @since 3.1.0
  5010  * @since 3.1.0
  4361  * @access private
  5011  * @access private
  4362  *
  5012  *
  4363  * @param callback $callback      Function that accepts ( ID, $callback_args ) and outputs parent_ID.
  5013  * @param callable $callback      Function that accepts ( ID, $callback_args ) and outputs parent_ID.
  4364  * @param int      $start         The ID to start the loop check at.
  5014  * @param int      $start         The ID to start the loop check at.
  4365  * @param int      $start_parent  The parent_ID of $start to use instead of calling $callback( $start ).
  5015  * @param int      $start_parent  The parent_ID of $start to use instead of calling $callback( $start ).
  4366  *                                Use null to always use $callback
  5016  *                                Use null to always use $callback
  4367  * @param array    $callback_args Optional. Additional arguments to send to $callback.
  5017  * @param array    $callback_args Optional. Additional arguments to send to $callback.
  4368  * @return array IDs of all members of loop.
  5018  * @return array IDs of all members of loop.
  4383  * If the hare ever laps the tortoise, there must be a loop.
  5033  * If the hare ever laps the tortoise, there must be a loop.
  4384  *
  5034  *
  4385  * @since 3.1.0
  5035  * @since 3.1.0
  4386  * @access private
  5036  * @access private
  4387  *
  5037  *
  4388  * @param callback $callback      Function that accepts ( ID, callback_arg, ... ) and outputs parent_ID.
  5038  * @param callable $callback      Function that accepts ( ID, callback_arg, ... ) and outputs parent_ID.
  4389  * @param int      $start         The ID to start the loop check at.
  5039  * @param int      $start         The ID to start the loop check at.
  4390  * @param array    $override      Optional. An array of ( ID => parent_ID, ... ) to use instead of $callback.
  5040  * @param array    $override      Optional. An array of ( ID => parent_ID, ... ) to use instead of $callback.
  4391  *                                Default empty array.
  5041  *                                Default empty array.
  4392  * @param array    $callback_args Optional. Additional arguments to send to $callback. Default empty array.
  5042  * @param array    $callback_args Optional. Additional arguments to send to $callback. Default empty array.
  4393  * @param bool     $_return_loop  Optional. Return loop members or just detect presence of loop? Only set
  5043  * @param bool     $_return_loop  Optional. Return loop members or just detect presence of loop? Only set
  4436 
  5086 
  4437 /**
  5087 /**
  4438  * Retrieve a list of protocols to allow in HTML attributes.
  5088  * Retrieve a list of protocols to allow in HTML attributes.
  4439  *
  5089  *
  4440  * @since 3.3.0
  5090  * @since 3.3.0
       
  5091  * @since 4.3.0 Added 'webcal' to the protocols array.
       
  5092  * @since 4.7.0 Added 'urn' to the protocols array.
  4441  *
  5093  *
  4442  * @see wp_kses()
  5094  * @see wp_kses()
  4443  * @see esc_url()
  5095  * @see esc_url()
  4444  *
  5096  *
  4445  * @return array Array of allowed protocols.
  5097  * @staticvar array $protocols
       
  5098  *
       
  5099  * @return array Array of allowed protocols. Defaults to an array containing 'http', 'https',
       
  5100  *               'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet',
       
  5101  *               'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp', 'webcal', and 'urn'.
  4446  */
  5102  */
  4447 function wp_allowed_protocols() {
  5103 function wp_allowed_protocols() {
  4448 	static $protocols;
  5104 	static $protocols = array();
  4449 
  5105 
  4450 	if ( empty( $protocols ) ) {
  5106 	if ( empty( $protocols ) ) {
  4451 		$protocols = array( 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp' );
  5107 		$protocols = array( 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp', 'webcal', 'urn' );
  4452 
  5108 	}
       
  5109 
       
  5110 	if ( ! did_action( 'wp_loaded' ) ) {
  4453 		/**
  5111 		/**
  4454 		 * Filter the list of protocols allowed in HTML attributes.
  5112 		 * Filters the list of protocols allowed in HTML attributes.
  4455 		 *
  5113 		 *
  4456 		 * @since 3.0.0
  5114 		 * @since 3.0.0
  4457 		 *
  5115 		 *
  4458 		 * @param array $protocols Array of allowed protocols e.g. 'http', 'ftp', 'tel', and more.
  5116 		 * @param array $protocols Array of allowed protocols e.g. 'http', 'ftp', 'tel', and more.
  4459 		 */
  5117 		 */
  4460 		$protocols = apply_filters( 'kses_allowed_protocols', $protocols );
  5118 		$protocols = array_unique( (array) apply_filters( 'kses_allowed_protocols', $protocols ) );
  4461 	}
  5119 	}
  4462 
  5120 
  4463 	return $protocols;
  5121 	return $protocols;
  4464 }
  5122 }
  4465 
  5123 
  4541  * Test if the current device has the capability to upload files.
  5199  * Test if the current device has the capability to upload files.
  4542  *
  5200  *
  4543  * @since 3.4.0
  5201  * @since 3.4.0
  4544  * @access private
  5202  * @access private
  4545  *
  5203  *
  4546  * @return bool true|false Whether the device is able to upload files.
  5204  * @return bool Whether the device is able to upload files.
  4547  */
  5205  */
  4548 function _device_can_upload() {
  5206 function _device_can_upload() {
  4549 	if ( ! wp_is_mobile() )
  5207 	if ( ! wp_is_mobile() )
  4550 		return true;
  5208 		return true;
  4551 
  5209 
  4561 }
  5219 }
  4562 
  5220 
  4563 /**
  5221 /**
  4564  * Test if a given path is a stream URL
  5222  * Test if a given path is a stream URL
  4565  *
  5223  *
       
  5224  * @since 3.5.0
       
  5225  *
  4566  * @param string $path The resource path or URL.
  5226  * @param string $path The resource path or URL.
  4567  * @return bool True if the path is a stream URL.
  5227  * @return bool True if the path is a stream URL.
  4568  */
  5228  */
  4569 function wp_is_stream( $path ) {
  5229 function wp_is_stream( $path ) {
  4570 	$wrappers = stream_get_wrappers();
  5230 	if ( false === strpos( $path, '://' ) ) {
  4571 	$wrappers_re = '(' . join('|', $wrappers) . ')';
  5231 		// $path isn't a stream
       
  5232 		return false;
       
  5233 	}
       
  5234 
       
  5235 	$wrappers    = stream_get_wrappers();
       
  5236 	$wrappers    = array_map( 'preg_quote', $wrappers );
       
  5237 	$wrappers_re = '(' . join( '|', $wrappers ) . ')';
  4572 
  5238 
  4573 	return preg_match( "!^$wrappers_re://!", $path ) === 1;
  5239 	return preg_match( "!^$wrappers_re://!", $path ) === 1;
  4574 }
  5240 }
  4575 
  5241 
  4576 /**
  5242 /**
  4586  * @param  string $source_date The date to filter.
  5252  * @param  string $source_date The date to filter.
  4587  * @return bool True if valid date, false if not valid date.
  5253  * @return bool True if valid date, false if not valid date.
  4588  */
  5254  */
  4589 function wp_checkdate( $month, $day, $year, $source_date ) {
  5255 function wp_checkdate( $month, $day, $year, $source_date ) {
  4590 	/**
  5256 	/**
  4591 	 * Filter whether the given date is valid for the Gregorian calendar.
  5257 	 * Filters whether the given date is valid for the Gregorian calendar.
  4592 	 *
  5258 	 *
  4593 	 * @since 3.5.0
  5259 	 * @since 3.5.0
  4594 	 *
  5260 	 *
  4595 	 * @param bool   $checkdate   Whether the given date is valid.
  5261 	 * @param bool   $checkdate   Whether the given date is valid.
  4596 	 * @param string $source_date Date to check.
  5262 	 * @param string $source_date Date to check.
  4602  * Load the auth check for monitoring whether the user is still logged in.
  5268  * Load the auth check for monitoring whether the user is still logged in.
  4603  *
  5269  *
  4604  * Can be disabled with remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' );
  5270  * Can be disabled with remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' );
  4605  *
  5271  *
  4606  * This is disabled for certain screens where a login screen could cause an
  5272  * This is disabled for certain screens where a login screen could cause an
  4607  * inconvenient interruption. A filter called wp_auth_check_load can be used
  5273  * inconvenient interruption. A filter called {@see 'wp_auth_check_load'} can be used
  4608  * for fine-grained control.
  5274  * for fine-grained control.
  4609  *
  5275  *
  4610  * @since 3.6.0
  5276  * @since 3.6.0
  4611  */
  5277  */
  4612 function wp_auth_check_load() {
  5278 function wp_auth_check_load() {
  4619 	$screen = get_current_screen();
  5285 	$screen = get_current_screen();
  4620 	$hidden = array( 'update', 'update-network', 'update-core', 'update-core-network', 'upgrade', 'upgrade-network', 'network' );
  5286 	$hidden = array( 'update', 'update-network', 'update-core', 'update-core-network', 'upgrade', 'upgrade-network', 'network' );
  4621 	$show = ! in_array( $screen->id, $hidden );
  5287 	$show = ! in_array( $screen->id, $hidden );
  4622 
  5288 
  4623 	/**
  5289 	/**
  4624 	 * Filter whether to load the authentication check.
  5290 	 * Filters whether to load the authentication check.
  4625 	 *
  5291 	 *
  4626 	 * Passing a falsey value to the filter will effectively short-circuit
  5292 	 * Passing a falsey value to the filter will effectively short-circuit
  4627 	 * loading the authentication check.
  5293 	 * loading the authentication check.
  4628 	 *
  5294 	 *
  4629 	 * @since 3.6.0
  5295 	 * @since 3.6.0
  4649 	$login_url = wp_login_url();
  5315 	$login_url = wp_login_url();
  4650 	$current_domain = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
  5316 	$current_domain = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
  4651 	$same_domain = ( strpos( $login_url, $current_domain ) === 0 );
  5317 	$same_domain = ( strpos( $login_url, $current_domain ) === 0 );
  4652 
  5318 
  4653 	/**
  5319 	/**
  4654 	 * Filter whether the authentication check originated at the same domain.
  5320 	 * Filters whether the authentication check originated at the same domain.
  4655 	 *
  5321 	 *
  4656 	 * @since 3.6.0
  5322 	 * @since 3.6.0
  4657 	 *
  5323 	 *
  4658 	 * @param bool $same_domain Whether the authentication check originated at the same domain.
  5324 	 * @param bool $same_domain Whether the authentication check originated at the same domain.
  4659 	 */
  5325 	 */
  4662 
  5328 
  4663 	?>
  5329 	?>
  4664 	<div id="wp-auth-check-wrap" class="<?php echo $wrap_class; ?>">
  5330 	<div id="wp-auth-check-wrap" class="<?php echo $wrap_class; ?>">
  4665 	<div id="wp-auth-check-bg"></div>
  5331 	<div id="wp-auth-check-bg"></div>
  4666 	<div id="wp-auth-check">
  5332 	<div id="wp-auth-check">
  4667 	<div class="wp-auth-check-close" tabindex="0" title="<?php esc_attr_e('Close'); ?>"></div>
  5333 	<button type="button" class="wp-auth-check-close button-link"><span class="screen-reader-text"><?php _e( 'Close dialog' ); ?></span></button>
  4668 	<?php
  5334 	<?php
  4669 
  5335 
  4670 	if ( $same_domain ) {
  5336 	if ( $same_domain ) {
       
  5337 		$login_src = add_query_arg( array(
       
  5338 			'interim-login' => '1',
       
  5339 			'wp_lang'       => get_user_locale(),
       
  5340 		), $login_url );
  4671 		?>
  5341 		?>
  4672 		<div id="wp-auth-check-form" data-src="<?php echo esc_url( add_query_arg( array( 'interim-login' => 1 ), $login_url ) ); ?>"></div>
  5342 		<div id="wp-auth-check-form" class="loading" data-src="<?php echo esc_url( $login_src ); ?>"></div>
  4673 		<?php
  5343 		<?php
  4674 	}
  5344 	}
  4675 
  5345 
  4676 	?>
  5346 	?>
  4677 	<div class="wp-auth-fallback">
  5347 	<div class="wp-auth-fallback">
  4690  * Send a result that shows a log-in box if the user is no longer logged in,
  5360  * Send a result that shows a log-in box if the user is no longer logged in,
  4691  * or if their cookie is within the grace period.
  5361  * or if their cookie is within the grace period.
  4692  *
  5362  *
  4693  * @since 3.6.0
  5363  * @since 3.6.0
  4694  *
  5364  *
  4695  * @param array|object $response  The Heartbeat response object or array.
  5365  * @global int $login_grace_period
  4696  * @return array|object $response The Heartbeat response object or array with 'wp-auth-check'
  5366  *
  4697  *                                value set.
  5367  * @param array $response  The Heartbeat response.
       
  5368  * @return array $response The Heartbeat response with 'wp-auth-check' value set.
  4698  */
  5369  */
  4699 function wp_auth_check( $response ) {
  5370 function wp_auth_check( $response ) {
  4700 	$response['wp-auth-check'] = is_user_logged_in() && empty( $GLOBALS['login_grace_period'] );
  5371 	$response['wp-auth-check'] = is_user_logged_in() && empty( $GLOBALS['login_grace_period'] );
  4701 	return $response;
  5372 	return $response;
  4702 }
  5373 }
  4734  *
  5405  *
  4735  * @param string $charset A charset name.
  5406  * @param string $charset A charset name.
  4736  * @return string The canonical form of the charset.
  5407  * @return string The canonical form of the charset.
  4737  */
  5408  */
  4738 function _canonical_charset( $charset ) {
  5409 function _canonical_charset( $charset ) {
  4739 	if ( 'UTF-8' === $charset || 'utf-8' === $charset || 'utf8' === $charset ||
  5410 	if ( 'utf-8' === strtolower( $charset ) || 'utf8' === strtolower( $charset) ) {
  4740 		'UTF8' === $charset )
  5411 
  4741 		return 'UTF-8';
  5412 		return 'UTF-8';
  4742 
  5413 	}
  4743 	if ( 'ISO-8859-1' === $charset || 'iso-8859-1' === $charset ||
  5414 
  4744 		'iso8859-1' === $charset || 'ISO8859-1' === $charset )
  5415 	if ( 'iso-8859-1' === strtolower( $charset ) || 'iso8859-1' === strtolower( $charset ) ) {
       
  5416 
  4745 		return 'ISO-8859-1';
  5417 		return 'ISO-8859-1';
       
  5418 	}
  4746 
  5419 
  4747 	return $charset;
  5420 	return $charset;
  4748 }
  5421 }
  4749 
  5422 
  4750 /**
  5423 /**
  4764  * of `reset_mbstring_encoding()` calls.
  5437  * of `reset_mbstring_encoding()` calls.
  4765  *
  5438  *
  4766  * @since 3.7.0
  5439  * @since 3.7.0
  4767  *
  5440  *
  4768  * @see reset_mbstring_encoding()
  5441  * @see reset_mbstring_encoding()
       
  5442  *
       
  5443  * @staticvar array $encodings
       
  5444  * @staticvar bool  $overloaded
  4769  *
  5445  *
  4770  * @param bool $reset Optional. Whether to reset the encoding back to a previously-set encoding.
  5446  * @param bool $reset Optional. Whether to reset the encoding back to a previously-set encoding.
  4771  *                    Default false.
  5447  *                    Default false.
  4772  */
  5448  */
  4773 function mbstring_binary_safe_encoding( $reset = false ) {
  5449 function mbstring_binary_safe_encoding( $reset = false ) {
  4832  *
  5508  *
  4833  * @param string $file The path to the file to delete.
  5509  * @param string $file The path to the file to delete.
  4834  */
  5510  */
  4835 function wp_delete_file( $file ) {
  5511 function wp_delete_file( $file ) {
  4836 	/**
  5512 	/**
  4837 	 * Filter the path of the file to delete.
  5513 	 * Filters the path of the file to delete.
  4838 	 *
  5514 	 *
  4839 	 * @since 2.1.0
  5515 	 * @since 2.1.0
  4840 	 *
  5516 	 *
  4841 	 * @param string $medium Path to the file to delete.
  5517 	 * @param string $file Path to the file to delete.
  4842 	 */
  5518 	 */
  4843 	$delete = apply_filters( 'wp_delete_file', $file );
  5519 	$delete = apply_filters( 'wp_delete_file', $file );
  4844 	if ( ! empty( $delete ) ) {
  5520 	if ( ! empty( $delete ) ) {
  4845 		@unlink( $delete );
  5521 		@unlink( $delete );
  4846 	}
  5522 	}
  4847 }
  5523 }
       
  5524 
       
  5525 /**
       
  5526  * Deletes a file if its path is within the given directory.
       
  5527  *
       
  5528  * @since 4.9.7
       
  5529  *
       
  5530  * @param string $file      Absolute path to the file to delete.
       
  5531  * @param string $directory Absolute path to a directory.
       
  5532  * @return bool True on success, false on failure.
       
  5533  */
       
  5534 function wp_delete_file_from_directory( $file, $directory ) {
       
  5535 	$real_file = realpath( wp_normalize_path( $file ) );
       
  5536 	$real_directory = realpath( wp_normalize_path( $directory ) );
       
  5537 
       
  5538 	if ( false === $real_file || false === $real_directory || strpos( wp_normalize_path( $real_file ), trailingslashit( wp_normalize_path( $real_directory ) ) ) !== 0 ) {
       
  5539 		return false;
       
  5540 	}
       
  5541 
       
  5542 	wp_delete_file( $file );
       
  5543 
       
  5544 	return true;
       
  5545 }
       
  5546 
       
  5547 /**
       
  5548  * Outputs a small JS snippet on preview tabs/windows to remove `window.name` on unload.
       
  5549  *
       
  5550  * This prevents reusing the same tab for a preview when the user has navigated away.
       
  5551  *
       
  5552  * @since 4.3.0
       
  5553  *
       
  5554  * @global WP_Post $post
       
  5555  */
       
  5556 function wp_post_preview_js() {
       
  5557 	global $post;
       
  5558 
       
  5559 	if ( ! is_preview() || empty( $post ) ) {
       
  5560 		return;
       
  5561 	}
       
  5562 
       
  5563 	// Has to match the window name used in post_submit_meta_box()
       
  5564 	$name = 'wp-preview-' . (int) $post->ID;
       
  5565 
       
  5566 	?>
       
  5567 	<script>
       
  5568 	( function() {
       
  5569 		var query = document.location.search;
       
  5570 
       
  5571 		if ( query && query.indexOf( 'preview=true' ) !== -1 ) {
       
  5572 			window.name = '<?php echo $name; ?>';
       
  5573 		}
       
  5574 
       
  5575 		if ( window.addEventListener ) {
       
  5576 			window.addEventListener( 'unload', function() { window.name = ''; }, false );
       
  5577 		}
       
  5578 	}());
       
  5579 	</script>
       
  5580 	<?php
       
  5581 }
       
  5582 
       
  5583 /**
       
  5584  * Parses and formats a MySQL datetime (Y-m-d H:i:s) for ISO8601/RFC3339.
       
  5585  *
       
  5586  * Explicitly strips timezones, as datetimes are not saved with any timezone
       
  5587  * information. Including any information on the offset could be misleading.
       
  5588  *
       
  5589  * @since 4.4.0
       
  5590  *
       
  5591  * @param string $date_string Date string to parse and format.
       
  5592  * @return string Date formatted for ISO8601/RFC3339.
       
  5593  */
       
  5594 function mysql_to_rfc3339( $date_string ) {
       
  5595 	$formatted = mysql2date( 'c', $date_string, false );
       
  5596 
       
  5597 	// Strip timezone information
       
  5598 	return preg_replace( '/(?:Z|[+-]\d{2}(?::\d{2})?)$/', '', $formatted );
       
  5599 }
       
  5600 
       
  5601 /**
       
  5602  * Attempts to raise the PHP memory limit for memory intensive processes.
       
  5603  *
       
  5604  * Only allows raising the existing limit and prevents lowering it.
       
  5605  *
       
  5606  * @since 4.6.0
       
  5607  *
       
  5608  * @param string $context Optional. Context in which the function is called. Accepts either 'admin',
       
  5609  *                        'image', or an arbitrary other context. If an arbitrary context is passed,
       
  5610  *                        the similarly arbitrary {@see '{$context}_memory_limit'} filter will be
       
  5611  *                        invoked. Default 'admin'.
       
  5612  * @return bool|int|string The limit that was set or false on failure.
       
  5613  */
       
  5614 function wp_raise_memory_limit( $context = 'admin' ) {
       
  5615 	// Exit early if the limit cannot be changed.
       
  5616 	if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) {
       
  5617 		return false;
       
  5618 	}
       
  5619 
       
  5620 	$current_limit     = @ini_get( 'memory_limit' );
       
  5621 	$current_limit_int = wp_convert_hr_to_bytes( $current_limit );
       
  5622 
       
  5623 	if ( -1 === $current_limit_int ) {
       
  5624 		return false;
       
  5625 	}
       
  5626 
       
  5627 	$wp_max_limit     = WP_MAX_MEMORY_LIMIT;
       
  5628 	$wp_max_limit_int = wp_convert_hr_to_bytes( $wp_max_limit );
       
  5629 	$filtered_limit   = $wp_max_limit;
       
  5630 
       
  5631 	switch ( $context ) {
       
  5632 		case 'admin':
       
  5633 			/**
       
  5634 			 * Filters the maximum memory limit available for administration screens.
       
  5635 			 *
       
  5636 			 * This only applies to administrators, who may require more memory for tasks
       
  5637 			 * like updates. Memory limits when processing images (uploaded or edited by
       
  5638 			 * users of any role) are handled separately.
       
  5639 			 *
       
  5640 			 * The `WP_MAX_MEMORY_LIMIT` constant specifically defines the maximum memory
       
  5641 			 * limit available when in the administration back end. The default is 256M
       
  5642 			 * (256 megabytes of memory) or the original `memory_limit` php.ini value if
       
  5643 			 * this is higher.
       
  5644 			 *
       
  5645 			 * @since 3.0.0
       
  5646 			 * @since 4.6.0 The default now takes the original `memory_limit` into account.
       
  5647 			 *
       
  5648 			 * @param int|string $filtered_limit The maximum WordPress memory limit. Accepts an integer
       
  5649 			 *                                   (bytes), or a shorthand string notation, such as '256M'.
       
  5650 			 */
       
  5651 			$filtered_limit = apply_filters( 'admin_memory_limit', $filtered_limit );
       
  5652 			break;
       
  5653 
       
  5654 		case 'image':
       
  5655 			/**
       
  5656 			 * Filters the memory limit allocated for image manipulation.
       
  5657 			 *
       
  5658 			 * @since 3.5.0
       
  5659 			 * @since 4.6.0 The default now takes the original `memory_limit` into account.
       
  5660 			 *
       
  5661 			 * @param int|string $filtered_limit Maximum memory limit to allocate for images.
       
  5662 			 *                                   Default `WP_MAX_MEMORY_LIMIT` or the original
       
  5663 			 *                                   php.ini `memory_limit`, whichever is higher.
       
  5664 			 *                                   Accepts an integer (bytes), or a shorthand string
       
  5665 			 *                                   notation, such as '256M'.
       
  5666 			 */
       
  5667 			$filtered_limit = apply_filters( 'image_memory_limit', $filtered_limit );
       
  5668 			break;
       
  5669 
       
  5670 		default:
       
  5671 			/**
       
  5672 			 * Filters the memory limit allocated for arbitrary contexts.
       
  5673 			 *
       
  5674 			 * The dynamic portion of the hook name, `$context`, refers to an arbitrary
       
  5675 			 * context passed on calling the function. This allows for plugins to define
       
  5676 			 * their own contexts for raising the memory limit.
       
  5677 			 *
       
  5678 			 * @since 4.6.0
       
  5679 			 *
       
  5680 			 * @param int|string $filtered_limit Maximum memory limit to allocate for images.
       
  5681 			 *                                   Default '256M' or the original php.ini `memory_limit`,
       
  5682 			 *                                   whichever is higher. Accepts an integer (bytes), or a
       
  5683 			 *                                   shorthand string notation, such as '256M'.
       
  5684 			 */
       
  5685 			$filtered_limit = apply_filters( "{$context}_memory_limit", $filtered_limit );
       
  5686 			break;
       
  5687 	}
       
  5688 
       
  5689 	$filtered_limit_int = wp_convert_hr_to_bytes( $filtered_limit );
       
  5690 
       
  5691 	if ( -1 === $filtered_limit_int || ( $filtered_limit_int > $wp_max_limit_int && $filtered_limit_int > $current_limit_int ) ) {
       
  5692 		if ( false !== @ini_set( 'memory_limit', $filtered_limit ) ) {
       
  5693 			return $filtered_limit;
       
  5694 		} else {
       
  5695 			return false;
       
  5696 		}
       
  5697 	} elseif ( -1 === $wp_max_limit_int || $wp_max_limit_int > $current_limit_int ) {
       
  5698 		if ( false !== @ini_set( 'memory_limit', $wp_max_limit ) ) {
       
  5699 			return $wp_max_limit;
       
  5700 		} else {
       
  5701 			return false;
       
  5702 		}
       
  5703 	}
       
  5704 
       
  5705 	return false;
       
  5706 }
       
  5707 
       
  5708 /**
       
  5709  * Generate a random UUID (version 4).
       
  5710  *
       
  5711  * @since 4.7.0
       
  5712  *
       
  5713  * @return string UUID.
       
  5714  */
       
  5715 function wp_generate_uuid4() {
       
  5716 	return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
       
  5717 		mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
       
  5718 		mt_rand( 0, 0xffff ),
       
  5719 		mt_rand( 0, 0x0fff ) | 0x4000,
       
  5720 		mt_rand( 0, 0x3fff ) | 0x8000,
       
  5721 		mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
       
  5722 	);
       
  5723 }
       
  5724 
       
  5725 /**
       
  5726  * Validates that a UUID is valid.
       
  5727  *
       
  5728  * @since 4.9.0
       
  5729  *
       
  5730  * @param mixed $uuid    UUID to check.
       
  5731  * @param int   $version Specify which version of UUID to check against. Default is none, to accept any UUID version. Otherwise, only version allowed is `4`.
       
  5732  * @return bool The string is a valid UUID or false on failure.
       
  5733  */
       
  5734 function wp_is_uuid( $uuid, $version = null ) {
       
  5735 
       
  5736 	if ( ! is_string( $uuid ) ) {
       
  5737 		return false;
       
  5738 	}
       
  5739 
       
  5740 	if ( is_numeric( $version ) ) {
       
  5741 		if ( 4 !== (int) $version ) {
       
  5742 			_doing_it_wrong( __FUNCTION__, __( 'Only UUID V4 is supported at this time.' ), '4.9.0' );
       
  5743 			return false;
       
  5744 		}
       
  5745 		$regex = '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/';
       
  5746 	} else {
       
  5747 		$regex = '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/';
       
  5748 	}
       
  5749 
       
  5750 	return (bool) preg_match( $regex, $uuid );
       
  5751 }
       
  5752 
       
  5753 /**
       
  5754  * Get last changed date for the specified cache group.
       
  5755  *
       
  5756  * @since 4.7.0
       
  5757  *
       
  5758  * @param string $group Where the cache contents are grouped.
       
  5759  *
       
  5760  * @return string $last_changed UNIX timestamp with microseconds representing when the group was last changed.
       
  5761  */
       
  5762 function wp_cache_get_last_changed( $group ) {
       
  5763 	$last_changed = wp_cache_get( 'last_changed', $group );
       
  5764 
       
  5765 	if ( ! $last_changed ) {
       
  5766 		$last_changed = microtime();
       
  5767 		wp_cache_set( 'last_changed', $last_changed, $group );
       
  5768 	}
       
  5769 
       
  5770 	return $last_changed;
       
  5771 }
       
  5772 
       
  5773 /**
       
  5774  * Send an email to the old site admin email address when the site admin email address changes.
       
  5775  *
       
  5776  * @since 4.9.0
       
  5777  *
       
  5778  * @param string $old_email   The old site admin email address.
       
  5779  * @param string $new_email   The new site admin email address.
       
  5780  * @param string $option_name The relevant database option name.
       
  5781  */
       
  5782 function wp_site_admin_email_change_notification( $old_email, $new_email, $option_name ) {
       
  5783 	$send = true;
       
  5784 
       
  5785 	// Don't send the notification to the default 'admin_email' value.
       
  5786 	if ( 'you@example.com' === $old_email ) {
       
  5787 		$send = false;
       
  5788 	}
       
  5789 
       
  5790 	/**
       
  5791 	 * Filters whether to send the site admin email change notification email.
       
  5792 	 *
       
  5793 	 * @since 4.9.0
       
  5794 	 *
       
  5795 	 * @param bool   $send      Whether to send the email notification.
       
  5796 	 * @param string $old_email The old site admin email address.
       
  5797 	 * @param string $new_email The new site admin email address.
       
  5798 	 */
       
  5799 	$send = apply_filters( 'send_site_admin_email_change_email', $send, $old_email, $new_email );
       
  5800 
       
  5801 	if ( ! $send ) {
       
  5802 		return;
       
  5803 	}
       
  5804 
       
  5805 	/* translators: Do not translate OLD_EMAIL, NEW_EMAIL, SITENAME, SITEURL: those are placeholders. */
       
  5806 	$email_change_text = __( 'Hi,
       
  5807 
       
  5808 This notice confirms that the admin email address was changed on ###SITENAME###.
       
  5809 
       
  5810 The new admin email address is ###NEW_EMAIL###.
       
  5811 
       
  5812 This email has been sent to ###OLD_EMAIL###
       
  5813 
       
  5814 Regards,
       
  5815 All at ###SITENAME###
       
  5816 ###SITEURL###' );
       
  5817 
       
  5818 	$email_change_email = array(
       
  5819 		'to'      => $old_email,
       
  5820 		/* translators: Site admin email change notification email subject. %s: Site title */
       
  5821 		'subject' => __( '[%s] Notice of Admin Email Change' ),
       
  5822 		'message' => $email_change_text,
       
  5823 		'headers' => '',
       
  5824 	);
       
  5825 	// get site name
       
  5826 	$site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
       
  5827 
       
  5828 	/**
       
  5829 	 * Filters the contents of the email notification sent when the site admin email address is changed.
       
  5830 	 *
       
  5831 	 * @since 4.9.0
       
  5832 	 *
       
  5833 	 * @param array $email_change_email {
       
  5834 	 *            Used to build wp_mail().
       
  5835 	 *
       
  5836 	 *            @type string $to      The intended recipient.
       
  5837 	 *            @type string $subject The subject of the email.
       
  5838 	 *            @type string $message The content of the email.
       
  5839 	 *                The following strings have a special meaning and will get replaced dynamically:
       
  5840 	 *                - ###OLD_EMAIL### The old site admin email address.
       
  5841 	 *                - ###NEW_EMAIL### The new site admin email address.
       
  5842 	 *                - ###SITENAME###  The name of the site.
       
  5843 	 *                - ###SITEURL###   The URL to the site.
       
  5844 	 *            @type string $headers Headers.
       
  5845 	 *        }
       
  5846 	 * @param string $old_email The old site admin email address.
       
  5847 	 * @param string $new_email The new site admin email address.
       
  5848 	 */
       
  5849 	$email_change_email = apply_filters( 'site_admin_email_change_email', $email_change_email, $old_email, $new_email );
       
  5850 
       
  5851 	$email_change_email['message'] = str_replace( '###OLD_EMAIL###', $old_email, $email_change_email['message'] );
       
  5852 	$email_change_email['message'] = str_replace( '###NEW_EMAIL###', $new_email, $email_change_email['message'] );
       
  5853 	$email_change_email['message'] = str_replace( '###SITENAME###',  $site_name, $email_change_email['message'] );
       
  5854 	$email_change_email['message'] = str_replace( '###SITEURL###',   home_url(), $email_change_email['message'] );
       
  5855 
       
  5856 	wp_mail( $email_change_email['to'], sprintf(
       
  5857 		$email_change_email['subject'],
       
  5858 		$site_name
       
  5859 	), $email_change_email['message'], $email_change_email['headers'] );
       
  5860 }
       
  5861 
       
  5862 /**
       
  5863  * Return an anonymized IPv4 or IPv6 address.
       
  5864  *
       
  5865  * @since 4.9.6 Abstracted from `WP_Community_Events::get_unsafe_client_ip()`.
       
  5866  *
       
  5867  * @param  string $ip_addr        The IPv4 or IPv6 address to be anonymized.
       
  5868  * @param  bool   $ipv6_fallback  Optional. Whether to return the original IPv6 address if the needed functions
       
  5869  *                                to anonymize it are not present. Default false, return `::` (unspecified address).
       
  5870  * @return string  The anonymized IP address.
       
  5871  */
       
  5872 function wp_privacy_anonymize_ip( $ip_addr, $ipv6_fallback = false ) {
       
  5873 	// Detect what kind of IP address this is.
       
  5874 	$ip_prefix = '';
       
  5875 	$is_ipv6   = substr_count( $ip_addr, ':' ) > 1;
       
  5876 	$is_ipv4   = ( 3 === substr_count( $ip_addr, '.' ) );
       
  5877 
       
  5878 	if ( $is_ipv6 && $is_ipv4 ) {
       
  5879 		// IPv6 compatibility mode, temporarily strip the IPv6 part, and treat it like IPv4.
       
  5880 		$ip_prefix = '::ffff:';
       
  5881 		$ip_addr   = preg_replace( '/^\[?[0-9a-f:]*:/i', '', $ip_addr );
       
  5882 		$ip_addr   = str_replace( ']', '', $ip_addr );
       
  5883 		$is_ipv6   = false;
       
  5884 	}
       
  5885 
       
  5886 	if ( $is_ipv6 ) {
       
  5887 		// IPv6 addresses will always be enclosed in [] if there's a port.
       
  5888 		$left_bracket  = strpos( $ip_addr, '[' );
       
  5889 		$right_bracket = strpos( $ip_addr, ']' );
       
  5890 		$percent       = strpos( $ip_addr, '%' );
       
  5891 		$netmask       = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000';
       
  5892 
       
  5893 		// Strip the port (and [] from IPv6 addresses), if they exist.
       
  5894 		if ( false !== $left_bracket && false !== $right_bracket ) {
       
  5895 			$ip_addr = substr( $ip_addr, $left_bracket + 1, $right_bracket - $left_bracket - 1 );
       
  5896 		} elseif ( false !== $left_bracket || false !== $right_bracket ) {
       
  5897 			// The IP has one bracket, but not both, so it's malformed.
       
  5898 			return '::';
       
  5899 		}
       
  5900 
       
  5901 		// Strip the reachability scope.
       
  5902 		if ( false !== $percent ) {
       
  5903 			$ip_addr = substr( $ip_addr, 0, $percent );
       
  5904 		}
       
  5905 
       
  5906 		// No invalid characters should be left.
       
  5907 		if ( preg_match( '/[^0-9a-f:]/i', $ip_addr ) ) {
       
  5908 			return '::';
       
  5909 		}
       
  5910 
       
  5911 		// Partially anonymize the IP by reducing it to the corresponding network ID.
       
  5912 		if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) {
       
  5913 			$ip_addr = inet_ntop( inet_pton( $ip_addr ) & inet_pton( $netmask ) );
       
  5914 			if ( false === $ip_addr) {
       
  5915 				return '::';
       
  5916 			}
       
  5917 		} elseif ( ! $ipv6_fallback ) {
       
  5918 			return '::';
       
  5919 		}
       
  5920 	} elseif ( $is_ipv4 ) {
       
  5921 		// Strip any port and partially anonymize the IP.
       
  5922 		$last_octet_position = strrpos( $ip_addr, '.' );
       
  5923 		$ip_addr             = substr( $ip_addr, 0, $last_octet_position ) . '.0';
       
  5924 	} else {
       
  5925 		return '0.0.0.0';
       
  5926 	}
       
  5927 
       
  5928 	// Restore the IPv6 prefix to compatibility mode addresses.
       
  5929 	return $ip_prefix . $ip_addr;
       
  5930 }
       
  5931 
       
  5932 /**
       
  5933  * Return uniform "anonymous" data by type.
       
  5934  *
       
  5935  * @since 4.9.6
       
  5936  *
       
  5937  * @param  string $type The type of data to be anonymized.
       
  5938  * @param  string $data Optional The data to be anonymized.
       
  5939  * @return string The anonymous data for the requested type.
       
  5940  */
       
  5941 function wp_privacy_anonymize_data( $type, $data = '' ) {
       
  5942 
       
  5943 	switch ( $type ) {
       
  5944 		case 'email':
       
  5945 			$anonymous = 'deleted@site.invalid';
       
  5946 			break;
       
  5947 		case 'url':
       
  5948 			$anonymous = 'https://site.invalid';
       
  5949 			break;
       
  5950 		case 'ip':
       
  5951 			$anonymous = wp_privacy_anonymize_ip( $data );
       
  5952 			break;
       
  5953 		case 'date':
       
  5954 			$anonymous = '0000-00-00 00:00:00';
       
  5955 			break;
       
  5956 		case 'text':
       
  5957 			/* translators: deleted text */
       
  5958 			$anonymous = __( '[deleted]' );
       
  5959 			break;
       
  5960 		case 'longtext':
       
  5961 			/* translators: deleted long text */
       
  5962 			$anonymous = __( 'This content was deleted by the author.' );
       
  5963 			break;
       
  5964 		default:
       
  5965 			$anonymous = '';
       
  5966 	}
       
  5967 
       
  5968 	/**
       
  5969 	 * Filters the anonymous data for each type.
       
  5970 	 *
       
  5971 	 * @since 4.9.6
       
  5972 	 *
       
  5973 	 * @param string $anonymous Anonymized data.
       
  5974 	 * @param string $type      Type of the data.
       
  5975 	 * @param string $data      Original data.
       
  5976 	 */
       
  5977 	return apply_filters( 'wp_privacy_anonymize_data', $anonymous, $type, $data );
       
  5978 }
       
  5979 
       
  5980 /**
       
  5981  * Returns the directory used to store personal data export files.
       
  5982  *
       
  5983  * @since 4.9.6
       
  5984  *
       
  5985  * @see wp_privacy_exports_url
       
  5986  *
       
  5987  * @return string Exports directory.
       
  5988  */
       
  5989 function wp_privacy_exports_dir() {
       
  5990 	$upload_dir  = wp_upload_dir();
       
  5991 	$exports_dir = trailingslashit( $upload_dir['basedir'] ) . 'wp-personal-data-exports/';
       
  5992 
       
  5993 	/**
       
  5994 	 * Filters the directory used to store personal data export files.
       
  5995 	 *
       
  5996 	 * @since 4.9.6
       
  5997 	 *
       
  5998 	 * @param string $exports_dir Exports directory.
       
  5999 	 */
       
  6000 	return apply_filters( 'wp_privacy_exports_dir', $exports_dir );
       
  6001 }
       
  6002 
       
  6003 /**
       
  6004  * Returns the URL of the directory used to store personal data export files.
       
  6005  *
       
  6006  * @since 4.9.6
       
  6007  *
       
  6008  * @see wp_privacy_exports_dir
       
  6009  *
       
  6010  * @return string Exports directory URL.
       
  6011  */
       
  6012 function wp_privacy_exports_url() {
       
  6013 	$upload_dir  = wp_upload_dir();
       
  6014 	$exports_url = trailingslashit( $upload_dir['baseurl'] ) . 'wp-personal-data-exports/';
       
  6015 
       
  6016 	/**
       
  6017 	 * Filters the URL of the directory used to store personal data export files.
       
  6018 	 *
       
  6019 	 * @since 4.9.6
       
  6020 	 *
       
  6021 	 * @param string $exports_url Exports directory URL.
       
  6022 	 */
       
  6023 	return apply_filters( 'wp_privacy_exports_url', $exports_url );
       
  6024 }
       
  6025 
       
  6026 /**
       
  6027  * Schedule a `WP_Cron` job to delete expired export files.
       
  6028  *
       
  6029  * @since 4.9.6
       
  6030  */
       
  6031 function wp_schedule_delete_old_privacy_export_files() {
       
  6032 	if ( wp_installing() ) {
       
  6033 		return;
       
  6034 	}
       
  6035 
       
  6036 	if ( ! wp_next_scheduled( 'wp_privacy_delete_old_export_files' ) ) {
       
  6037 		wp_schedule_event( time(), 'hourly', 'wp_privacy_delete_old_export_files' );
       
  6038 	}
       
  6039 }
       
  6040 
       
  6041 /**
       
  6042  * Cleans up export files older than three days old.
       
  6043  *
       
  6044  * The export files are stored in `wp-content/uploads`, and are therefore publicly
       
  6045  * accessible. A CSPRN is appended to the filename to mitigate the risk of an
       
  6046  * unauthorized person downloading the file, but it is still possible. Deleting
       
  6047  * the file after the data subject has had a chance to delete it adds an additional
       
  6048  * layer of protection.
       
  6049  *
       
  6050  * @since 4.9.6
       
  6051  */
       
  6052 function wp_privacy_delete_old_export_files() {
       
  6053 	require_once( ABSPATH . 'wp-admin/includes/file.php' );
       
  6054 
       
  6055 	$exports_dir  = wp_privacy_exports_dir();
       
  6056 	$export_files = list_files( $exports_dir, 100, array( 'index.html' ) );
       
  6057 
       
  6058 	/**
       
  6059 	 * Filters the lifetime, in seconds, of a personal data export file.
       
  6060 	 *
       
  6061 	 * By default, the lifetime is 3 days. Once the file reaches that age, it will automatically
       
  6062 	 * be deleted by a cron job.
       
  6063 	 *
       
  6064 	 * @since 4.9.6
       
  6065 	 *
       
  6066 	 * @param int $expiration The expiration age of the export, in seconds.
       
  6067 	 */
       
  6068 	$expiration = apply_filters( 'wp_privacy_export_expiration', 3 * DAY_IN_SECONDS );
       
  6069 
       
  6070 	foreach ( (array) $export_files as $export_file ) {
       
  6071 		$file_age_in_seconds = time() - filemtime( $export_file );
       
  6072 
       
  6073 		if ( $expiration < $file_age_in_seconds ) {
       
  6074 			unlink( $export_file );
       
  6075 		}
       
  6076 	}
       
  6077 }