Wordpress 3.0-scripts
[autoinstalls/wordpress.git] / wp-includes / functions.php
1 <?php
2 /**
3  * Main WordPress API
4  *
5  * @package WordPress
6  */
7
8 /**
9  * Converts MySQL DATETIME field to user specified date format.
10  *
11  * If $dateformatstring has 'G' value, then gmmktime() function will be used to
12  * make the time. If $dateformatstring is set to 'U', then mktime() function
13  * will be used to make the time.
14  *
15  * The $translate will only be used, if it is set to true and it is by default
16  * and if the $wp_locale object has the month and weekday set.
17  *
18  * @since 0.71
19  *
20  * @param string $dateformatstring Either 'G', 'U', or php date format.
21  * @param string $mysqlstring Time from mysql DATETIME field.
22  * @param bool $translate Optional. Default is true. Will switch format to locale.
23  * @return string Date formated by $dateformatstring or locale (if available).
24  */
25 function mysql2date( $dateformatstring, $mysqlstring, $translate = true ) {
26         $m = $mysqlstring;
27         if ( empty( $m ) )
28                 return false;
29
30         if ( 'G' == $dateformatstring ) {
31                 return strtotime( $m . ' +0000' );
32         }
33
34         $i = strtotime( $m );
35
36         if ( 'U' == $dateformatstring )
37                 return $i;
38
39         if ( $translate)
40             return date_i18n( $dateformatstring, $i );
41         else
42             return date( $dateformatstring, $i );
43 }
44
45 /**
46  * Retrieve the current time based on specified type.
47  *
48  * The 'mysql' type will return the time in the format for MySQL DATETIME field.
49  * The 'timestamp' type will return the current timestamp.
50  *
51  * If $gmt is set to either '1' or 'true', then both types will use GMT time.
52  * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option.
53  *
54  * @since 1.0.0
55  *
56  * @param string $type Either 'mysql' or 'timestamp'.
57  * @param int|bool $gmt Optional. Whether to use GMT timezone. Default is false.
58  * @return int|string String if $type is 'gmt', int if $type is 'timestamp'.
59  */
60 function current_time( $type, $gmt = 0 ) {
61         switch ( $type ) {
62                 case 'mysql':
63                         return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * 3600 ) ) );
64                         break;
65                 case 'timestamp':
66                         return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * 3600 );
67                         break;
68         }
69 }
70
71 /**
72  * Retrieve the date in localized format, based on timestamp.
73  *
74  * If the locale specifies the locale month and weekday, then the locale will
75  * take over the format for the date. If it isn't, then the date format string
76  * will be used instead.
77  *
78  * @since 0.71
79  *
80  * @param string $dateformatstring Format to display the date.
81  * @param int $unixtimestamp Optional. Unix timestamp.
82  * @param bool $gmt Optional, default is false. Whether to convert to GMT for time.
83  * @return string The date, translated if locale specifies it.
84  */
85 function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
86         global $wp_locale;
87         $i = $unixtimestamp;
88         // Sanity check for PHP 5.1.0-
89         if ( false === $i || intval($i) < 0 ) {
90                 if ( ! $gmt )
91                         $i = current_time( 'timestamp' );
92                 else
93                         $i = time();
94                 // we should not let date() interfere with our
95                 // specially computed timestamp
96                 $gmt = true;
97         }
98
99         // store original value for language with untypical grammars
100         // see http://core.trac.wordpress.org/ticket/9396
101         $req_format = $dateformatstring;
102
103         $datefunc = $gmt? 'gmdate' : 'date';
104
105         if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
106                 $datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
107                 $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
108                 $dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
109                 $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
110                 $datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
111                 $datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
112                 $dateformatstring = ' '.$dateformatstring;
113                 $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
114                 $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
115                 $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
116                 $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
117                 $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
118                 $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
119
120                 $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
121         }
122         $j = @$datefunc( $dateformatstring, $i );
123         // allow plugins to redo this entirely for languages with untypical grammars
124         $j = apply_filters('date_i18n', $j, $req_format, $i, $gmt);
125         return $j;
126 }
127
128 /**
129  * Convert integer number to format based on the locale.
130  *
131  * @since 2.3.0
132  *
133  * @param int $number The number to convert based on locale.
134  * @param int $decimals Precision of the number of decimal places.
135  * @return string Converted number in string format.
136  */
137 function number_format_i18n( $number, $decimals = 0 ) {
138         global $wp_locale;
139         $formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
140         return apply_filters( 'number_format_i18n', $formatted );
141 }
142
143 /**
144  * Convert number of bytes largest unit bytes will fit into.
145  *
146  * It is easier to read 1kB than 1024 bytes and 1MB than 1048576 bytes. Converts
147  * number of bytes to human readable number by taking the number of that unit
148  * that the bytes will go into it. Supports TB value.
149  *
150  * Please note that integers in PHP are limited to 32 bits, unless they are on
151  * 64 bit architecture, then they have 64 bit size. If you need to place the
152  * larger size then what PHP integer type will hold, then use a string. It will
153  * be converted to a double, which should always have 64 bit length.
154  *
155  * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
156  * @link http://en.wikipedia.org/wiki/Byte
157  *
158  * @since 2.3.0
159  *
160  * @param int|string $bytes Number of bytes. Note max integer size for integers.
161  * @param int $decimals Precision of number of decimal places. Deprecated.
162  * @return bool|string False on failure. Number string on success.
163  */
164 function size_format( $bytes, $decimals = 0 ) {
165         $quant = array(
166                 // ========================= Origin ====
167                 'TB' => 1099511627776,  // pow( 1024, 4)
168                 'GB' => 1073741824,     // pow( 1024, 3)
169                 'MB' => 1048576,        // pow( 1024, 2)
170                 'kB' => 1024,           // pow( 1024, 1)
171                 'B ' => 1,              // pow( 1024, 0)
172         );
173         foreach ( $quant as $unit => $mag )
174                 if ( doubleval($bytes) >= $mag )
175                         return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
176
177         return false;
178 }
179
180 /**
181  * Get the week start and end from the datetime or date string from mysql.
182  *
183  * @since 0.71
184  *
185  * @param string $mysqlstring Date or datetime field type from mysql.
186  * @param int $start_of_week Optional. Start of the week as an integer.
187  * @return array Keys are 'start' and 'end'.
188  */
189 function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
190         $my = substr( $mysqlstring, 0, 4 ); // Mysql string Year
191         $mm = substr( $mysqlstring, 8, 2 ); // Mysql string Month
192         $md = substr( $mysqlstring, 5, 2 ); // Mysql string day
193         $day = mktime( 0, 0, 0, $md, $mm, $my ); // The timestamp for mysqlstring day.
194         $weekday = date( 'w', $day ); // The day of the week from the timestamp
195         if ( !is_numeric($start_of_week) )
196                 $start_of_week = get_option( 'start_of_week' );
197
198         if ( $weekday < $start_of_week )
199                 $weekday += 7;
200
201         $start = $day - 86400 * ( $weekday - $start_of_week ); // The most recent week start day on or before $day
202         $end = $start + 604799; // $start + 7 days - 1 second
203         return compact( 'start', 'end' );
204 }
205
206 /**
207  * Unserialize value only if it was serialized.
208  *
209  * @since 2.0.0
210  *
211  * @param string $original Maybe unserialized original, if is needed.
212  * @return mixed Unserialized data can be any type.
213  */
214 function maybe_unserialize( $original ) {
215         if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
216                 return @unserialize( $original );
217         return $original;
218 }
219
220 /**
221  * Check value to find if it was serialized.
222  *
223  * If $data is not an string, then returned value will always be false.
224  * Serialized data is always a string.
225  *
226  * @since 2.0.5
227  *
228  * @param mixed $data Value to check to see if was serialized.
229  * @return bool False if not serialized and true if it was.
230  */
231 function is_serialized( $data ) {
232         // if it isn't a string, it isn't serialized
233         if ( !is_string( $data ) )
234                 return false;
235         $data = trim( $data );
236         if ( 'N;' == $data )
237                 return true;
238         if ( !preg_match( '/^([adObis]):/', $data, $badions ) )
239                 return false;
240         switch ( $badions[1] ) {
241                 case 'a' :
242                 case 'O' :
243                 case 's' :
244                         if ( preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data ) )
245                                 return true;
246                         break;
247                 case 'b' :
248                 case 'i' :
249                 case 'd' :
250                         if ( preg_match( "/^{$badions[1]}:[0-9.E-]+;\$/", $data ) )
251                                 return true;
252                         break;
253         }
254         return false;
255 }
256
257 /**
258  * Check whether serialized data is of string type.
259  *
260  * @since 2.0.5
261  *
262  * @param mixed $data Serialized data
263  * @return bool False if not a serialized string, true if it is.
264  */
265 function is_serialized_string( $data ) {
266         // if it isn't a string, it isn't a serialized string
267         if ( !is_string( $data ) )
268                 return false;
269         $data = trim( $data );
270         if ( preg_match( '/^s:[0-9]+:.*;$/s', $data ) ) // this should fetch all serialized strings
271                 return true;
272         return false;
273 }
274
275 /**
276  * Retrieve option value based on name of option.
277  *
278  * If the option does not exist or does not have a value, then the return value
279  * will be false. This is useful to check whether you need to install an option
280  * and is commonly used during installation of plugin options and to test
281  * whether upgrading is required.
282  *
283  * If the option was serialized then it will be unserialized when it is returned.
284  *
285  * @since 1.5.0
286  * @package WordPress
287  * @subpackage Option
288  * @uses apply_filters() Calls 'pre_option_$option' before checking the option.
289  *      Any value other than false will "short-circuit" the retrieval of the option
290  *      and return the returned value. You should not try to override special options,
291  *      but you will not be prevented from doing so.
292  * @uses apply_filters() Calls 'option_$option', after checking the option, with
293  *      the option value.
294  *
295  * @param string $option Name of option to retrieve. Expected to not be SQL-escaped.
296  * @return mixed Value set for the option.
297  */
298 function get_option( $option, $default = false ) {
299         global $wpdb;
300
301         // Allow plugins to short-circuit options.
302         $pre = apply_filters( 'pre_option_' . $option, false );
303         if ( false !== $pre )
304                 return $pre;
305
306         $option = trim($option);
307         if ( empty($option) )
308                 return false;
309
310         if ( defined( 'WP_SETUP_CONFIG' ) )
311                 return false;
312
313         if ( ! defined( 'WP_INSTALLING' ) ) {
314                 // prevent non-existent options from triggering multiple queries
315                 $notoptions = wp_cache_get( 'notoptions', 'options' );
316                 if ( isset( $notoptions[$option] ) )
317                         return $default;
318
319                 $alloptions = wp_load_alloptions();
320
321                 if ( isset( $alloptions[$option] ) ) {
322                         $value = $alloptions[$option];
323                 } else {
324                         $value = wp_cache_get( $option, 'options' );
325
326                         if ( false === $value ) {
327                                 $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
328
329                                 // Has to be get_row instead of get_var because of funkiness with 0, false, null values
330                                 if ( is_object( $row ) ) {
331                                         $value = $row->option_value;
332                                         wp_cache_add( $option, $value, 'options' );
333                                 } else { // option does not exist, so we must cache its non-existence
334                                         $notoptions[$option] = true;
335                                         wp_cache_set( 'notoptions', $notoptions, 'options' );
336                                         return $default;
337                                 }
338                         }
339                 }
340         } else {
341                 $suppress = $wpdb->suppress_errors();
342                 $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
343                 $wpdb->suppress_errors( $suppress );
344                 if ( is_object( $row ) )
345                         $value = $row->option_value;
346                 else
347                         return $default;
348         }
349
350         // If home is not set use siteurl.
351         if ( 'home' == $option && '' == $value )
352                 return get_option( 'siteurl' );
353
354         if ( in_array( $option, array('siteurl', 'home', 'category_base', 'tag_base') ) )
355                 $value = untrailingslashit( $value );
356
357         return apply_filters( 'option_' . $option, maybe_unserialize( $value ) );
358 }
359
360 /**
361  * Protect WordPress special option from being modified.
362  *
363  * Will die if $option is in protected list. Protected options are 'alloptions'
364  * and 'notoptions' options.
365  *
366  * @since 2.2.0
367  * @package WordPress
368  * @subpackage Option
369  *
370  * @param string $option Option name.
371  */
372 function wp_protect_special_option( $option ) {
373         $protected = array( 'alloptions', 'notoptions' );
374         if ( in_array( $option, $protected ) )
375                 wp_die( sprintf( __( '%s is a protected WP option and may not be modified' ), esc_html( $option ) ) );
376 }
377
378 /**
379  * Print option value after sanitizing for forms.
380  *
381  * @uses attr Sanitizes value.
382  * @since 1.5.0
383  * @package WordPress
384  * @subpackage Option
385  *
386  * @param string $option Option name.
387  */
388 function form_option( $option ) {
389         echo esc_attr( get_option( $option ) );
390 }
391
392 /**
393  * Loads and caches all autoloaded options, if available or all options.
394  *
395  * @since 2.2.0
396  * @package WordPress
397  * @subpackage Option
398  *
399  * @return array List of all options.
400  */
401 function wp_load_alloptions() {
402         global $wpdb;
403
404         if ( !defined( 'WP_INSTALLING' ) || !is_multisite() )
405                 $alloptions = wp_cache_get( 'alloptions', 'options' );
406         else
407                 $alloptions = false;
408
409         if ( !$alloptions ) {
410                 $suppress = $wpdb->suppress_errors();
411                 if ( !$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" ) )
412                         $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
413                 $wpdb->suppress_errors($suppress);
414                 $alloptions = array();
415                 foreach ( (array) $alloptions_db as $o )
416                         $alloptions[$o->option_name] = $o->option_value;
417                         if ( !defined( 'WP_INSTALLING' ) || !is_multisite() )
418                                 wp_cache_add( 'alloptions', $alloptions, 'options' );
419         }
420
421         return $alloptions;
422 }
423
424 /**
425  * Loads and caches certain often requested site options if is_multisite() and a peristent cache is not being used.
426  *
427  * @since 3.0.0
428  * @package WordPress
429  * @subpackage Option
430  *
431  * @param int $site_id Optional site ID for which to query the options. Defaults to the current site.
432  */
433 function wp_load_core_site_options( $site_id = null ) {
434         global $wpdb, $_wp_using_ext_object_cache;
435
436         if ( !is_multisite() || $_wp_using_ext_object_cache || defined( 'WP_INSTALLING' ) )
437                 return;
438
439         if ( empty($site_id) )
440                 $site_id = $wpdb->siteid;
441
442         $core_options = array('site_name', 'siteurl', 'active_sitewide_plugins', '_site_transient_timeout_theme_roots', '_site_transient_theme_roots', 'site_admins', 'dashboard_blog', 'can_compress_scripts', 'global_terms_enabled' );
443
444         $core_options_in = "'" . implode("', '", $core_options) . "'";
445         $options = $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value FROM $wpdb->sitemeta WHERE meta_key IN ($core_options_in) AND site_id = %d", $site_id) );
446
447         foreach ( $options as $option ) {
448                 $key = $option->meta_key;
449                 $cache_key = "{$site_id}:$key";
450                 $option->meta_value = maybe_unserialize( $option->meta_value );
451
452                 wp_cache_set( $cache_key, $option->meta_value, 'site-options' );
453         }
454 }
455
456 /**
457  * Update the value of an option that was already added.
458  *
459  * You do not need to serialize values. If the value needs to be serialized, then
460  * it will be serialized before it is inserted into the database. Remember,
461  * resources can not be serialized or added as an option.
462  *
463  * If the option does not exist, then the option will be added with the option
464  * value, but you will not be able to set whether it is autoloaded. If you want
465  * to set whether an option is autoloaded, then you need to use the add_option().
466  *
467  * @since 1.0.0
468  * @package WordPress
469  * @subpackage Option
470  *
471  * @uses apply_filters() Calls 'pre_update_option_$option' hook to allow overwriting the
472  *      option value to be stored.
473  * @uses do_action() Calls 'update_option' hook before updating the option.
474  * @uses do_action() Calls 'update_option_$option' and 'updated_option' hooks on success.
475  *
476  * @param string $option Option name. Expected to not be SQL-escaped.
477  * @param mixed $newvalue Option value. Expected to not be SQL-escaped.
478  * @return bool False if value was not updated and true if value was updated.
479  */
480 function update_option( $option, $newvalue ) {
481         global $wpdb;
482
483         $option = trim($option);
484         if ( empty($option) )
485                 return false;
486
487         wp_protect_special_option( $option );
488
489         if ( is_object($newvalue) )
490                 $newvalue = wp_clone($newvalue);
491
492         $newvalue = sanitize_option( $option, $newvalue );
493         $oldvalue = get_option( $option );
494         $newvalue = apply_filters( 'pre_update_option_' . $option, $newvalue, $oldvalue );
495
496         // If the new and old values are the same, no need to update.
497         if ( $newvalue === $oldvalue )
498                 return false;
499
500         if ( false === $oldvalue )
501                 return add_option( $option, $newvalue );
502
503         $notoptions = wp_cache_get( 'notoptions', 'options' );
504         if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
505                 unset( $notoptions[$option] );
506                 wp_cache_set( 'notoptions', $notoptions, 'options' );
507         }
508
509         $_newvalue = $newvalue;
510         $newvalue = maybe_serialize( $newvalue );
511
512         do_action( 'update_option', $option, $oldvalue, $_newvalue );
513         if ( ! defined( 'WP_INSTALLING' ) ) {
514                 $alloptions = wp_load_alloptions();
515                 if ( isset( $alloptions[$option] ) ) {
516                         $alloptions[$option] = $_newvalue;
517                         wp_cache_set( 'alloptions', $alloptions, 'options' );
518                 } else {
519                         wp_cache_set( $option, $_newvalue, 'options' );
520                 }
521         }
522
523         $result = $wpdb->update( $wpdb->options, array( 'option_value' => $newvalue ), array( 'option_name' => $option ) );
524
525         if ( $result ) {
526                 do_action( "update_option_{$option}", $oldvalue, $_newvalue );
527                 do_action( 'updated_option', $option, $oldvalue, $_newvalue );
528                 return true;
529         }
530         return false;
531 }
532
533 /**
534  * Add a new option.
535  *
536  * You do not need to serialize values. If the value needs to be serialized, then
537  * it will be serialized before it is inserted into the database. Remember,
538  * resources can not be serialized or added as an option.
539  *
540  * You can create options without values and then add values later. Does not
541  * check whether the option has already been added, but does check that you
542  * aren't adding a protected WordPress option. Care should be taken to not name
543  * options the same as the ones which are protected and to not add options
544  * that were already added.
545  *
546  * @package WordPress
547  * @subpackage Option
548  * @since 1.0.0
549  * @link http://alex.vort-x.net/blog/ Thanks Alex Stapleton
550  *
551  * @uses do_action() Calls 'add_option' hook before adding the option.
552  * @uses do_action() Calls 'add_option_$option' and 'added_option' hooks on success.
553  *
554  * @param string $option Name of option to add. Expected to not be SQL-escaped.
555  * @param mixed $value Optional. Option value, can be anything. Expected to not be SQL-escaped.
556  * @param mixed $deprecated Optional. Description. Not used anymore.
557  * @param bool $autoload Optional. Default is enabled. Whether to load the option when WordPress starts up.
558  * @return null returns when finished.
559  */
560 function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) {
561         global $wpdb;
562
563         if ( !empty( $deprecated ) )
564                 _deprecated_argument( __FUNCTION__, '2.3' );
565
566         $option = trim($option);
567         if ( empty($option) )
568                 return false;
569
570         wp_protect_special_option( $option );
571
572         if ( is_object($value) )
573                 $value = wp_clone($value);
574
575         $value = sanitize_option( $option, $value );
576
577         // Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
578         $notoptions = wp_cache_get( 'notoptions', 'options' );
579         if ( !is_array( $notoptions ) || !isset( $notoptions[$option] ) )
580                 if ( false !== get_option( $option ) )
581                         return;
582
583         $_value = $value;
584         $value = maybe_serialize( $value );
585         $autoload = ( 'no' === $autoload ) ? 'no' : 'yes';
586         do_action( 'add_option', $option, $_value );
587         if ( ! defined( 'WP_INSTALLING' ) ) {
588                 if ( 'yes' == $autoload ) {
589                         $alloptions = wp_load_alloptions();
590                         $alloptions[$option] = $value;
591                         wp_cache_set( 'alloptions', $alloptions, 'options' );
592                 } else {
593                         wp_cache_set( $option, $value, 'options' );
594                 }
595         }
596
597         // This option exists now
598         $notoptions = wp_cache_get( 'notoptions', 'options' ); // yes, again... we need it to be fresh
599         if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
600                 unset( $notoptions[$option] );
601                 wp_cache_set( 'notoptions', $notoptions, 'options' );
602         }
603
604         $result = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)", $option, $value, $autoload ) );
605
606         if ( $result ) {
607                 do_action( "add_option_{$option}", $option, $_value );
608                 do_action( 'added_option', $option, $_value );
609                 return true;
610         }
611         return false;
612 }
613
614 /**
615  * Removes option by name. Prevents removal of protected WordPress options.
616  *
617  * @package WordPress
618  * @subpackage Option
619  * @since 1.2.0
620  *
621  * @uses do_action() Calls 'delete_option' hook before option is deleted.
622  * @uses do_action() Calls 'deleted_option' and 'delete_option_$option' hooks on success.
623  *
624  * @param string $option Name of option to remove. Expected to not be SQL-escaped.
625  * @return bool True, if option is successfully deleted. False on failure.
626  */
627 function delete_option( $option ) {
628         global $wpdb;
629
630         wp_protect_special_option( $option );
631
632         // Get the ID, if no ID then return
633         $row = $wpdb->get_row( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s", $option ) );
634         if ( is_null( $row ) )
635                 return false;
636         do_action( 'delete_option', $option );
637         $result = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name = %s", $option) );
638         if ( ! defined( 'WP_INSTALLING' ) ) {
639                 if ( 'yes' == $row->autoload ) {
640                         $alloptions = wp_load_alloptions();
641                         if ( is_array( $alloptions ) && isset( $alloptions[$option] ) ) {
642                                 unset( $alloptions[$option] );
643                                 wp_cache_set( 'alloptions', $alloptions, 'options' );
644                         }
645                 } else {
646                         wp_cache_delete( $option, 'options' );
647                 }
648         }
649         if ( $result ) {
650                 do_action( "delete_option_$option", $option );
651                 do_action( 'deleted_option', $option );
652                 return true;
653         }
654         return false;
655 }
656
657 /**
658  * Delete a transient
659  *
660  * @since 2.8.0
661  * @package WordPress
662  * @subpackage Transient
663  *
664  * @uses do_action() Calls 'delete_transient_$transient' hook before transient is deleted.
665  * @uses do_action() Calls 'deleted_transient' hook on success.
666  *
667  * @param string $transient Transient name. Expected to not be SQL-escaped.
668  * @return bool true if successful, false otherwise
669  */
670 function delete_transient( $transient ) {
671         global $_wp_using_ext_object_cache;
672
673     do_action( 'delete_transient_' . $transient, $transient );
674
675         if ( $_wp_using_ext_object_cache ) {
676                 $result = wp_cache_delete( $transient, 'transient' );
677         } else {
678                 $option_timeout = '_transient_timeout_' . $transient;
679                 $option = '_transient_' . $transient;
680                 $result = delete_option( $option );
681                 if ( $result )
682                         delete_option( $option_timeout );
683         }
684
685         if ( $result )
686                 do_action( 'deleted_transient', $transient );
687         return $result;
688 }
689
690 /**
691  * Get the value of a transient
692  *
693  * If the transient does not exist or does not have a value, then the return value
694  * will be false.
695  *
696  * @uses apply_filters() Calls 'pre_transient_$transient' hook before checking the transient.
697  *      Any value other than false will "short-circuit" the retrieval of the transient
698  *      and return the returned value.
699  * @uses apply_filters() Calls 'transient_$option' hook, after checking the transient, with
700  *      the transient value.
701  *
702  * @since 2.8.0
703  * @package WordPress
704  * @subpackage Transient
705  *
706  * @param string $transient Transient name. Expected to not be SQL-escaped
707  * @return mixed Value of transient
708  */
709 function get_transient( $transient ) {
710         global $_wp_using_ext_object_cache;
711
712         $pre = apply_filters( 'pre_transient_' . $transient, false );
713         if ( false !== $pre )
714                 return $pre;
715
716         if ( $_wp_using_ext_object_cache ) {
717                 $value = wp_cache_get( $transient, 'transient' );
718         } else {
719                 $transient_option = '_transient_' . $transient;
720                 if ( ! defined( 'WP_INSTALLING' ) ) {
721                         // If option is not in alloptions, it is not autoloaded and thus has a timeout
722                         $alloptions = wp_load_alloptions();
723                         if ( !isset( $alloptions[$transient_option] ) ) {
724                                 $transient_timeout = '_transient_timeout_' . $transient;
725                                 if ( get_option( $transient_timeout ) < time() ) {
726                                         delete_option( $transient_option  );
727                                         delete_option( $transient_timeout );
728                                         return false;
729                                 }
730                         }
731                 }
732
733                 $value = get_option( $transient_option );
734         }
735
736         return apply_filters( 'transient_' . $transient, $value );
737 }
738
739 /**
740  * Set/update the value of a transient
741  *
742  * You do not need to serialize values. If the value needs to be serialized, then
743  * it will be serialized before it is set.
744  *
745  * @since 2.8.0
746  * @package WordPress
747  * @subpackage Transient
748  *
749  * @uses apply_filters() Calls 'pre_set_transient_$transient' hook to allow overwriting the
750  *      transient value to be stored.
751  * @uses do_action() Calls 'set_transient_$transient' and 'setted_transient' hooks on success.
752  *
753  * @param string $transient Transient name. Expected to not be SQL-escaped.
754  * @param mixed $value Transient value. Expected to not be SQL-escaped.
755  * @param int $expiration Time until expiration in seconds, default 0
756  * @return bool False if value was not set and true if value was set.
757  */
758 function set_transient( $transient, $value, $expiration = 0 ) {
759         global $_wp_using_ext_object_cache;
760
761     $value = apply_filters( 'pre_set_transient_' . $transient, $value );
762
763         if ( $_wp_using_ext_object_cache ) {
764                 $result = wp_cache_set( $transient, $value, 'transient', $expiration );
765         } else {
766                 $transient_timeout = '_transient_timeout_' . $transient;
767                 $transient = '_transient_' . $transient;
768                 if ( false === get_option( $transient ) ) {
769                         $autoload = 'yes';
770                         if ( $expiration ) {
771                                 $autoload = 'no';
772                                 add_option( $transient_timeout, time() + $expiration, '', 'no' );
773                         }
774                         $result = add_option( $transient, $value, '', $autoload );
775                 } else {
776                         if ( $expiration )
777                                 update_option( $transient_timeout, time() + $expiration );
778                         $result = update_option( $transient, $value );
779                 }
780         }
781         if ( $result ) {
782                 do_action( 'set_transient_' . $transient );
783                 do_action( 'setted_transient', $transient );
784         }
785         return $result;
786 }
787
788 /**
789  * Saves and restores user interface settings stored in a cookie.
790  *
791  * Checks if the current user-settings cookie is updated and stores it. When no
792  * cookie exists (different browser used), adds the last saved cookie restoring
793  * the settings.
794  *
795  * @package WordPress
796  * @subpackage Option
797  * @since 2.7.0
798  */
799 function wp_user_settings() {
800
801         if ( ! is_admin() )
802                 return;
803
804         if ( defined('DOING_AJAX') )
805                 return;
806
807         if ( ! $user = wp_get_current_user() )
808                 return;
809
810         $settings = get_user_option( 'user-settings', $user->ID );
811
812         if ( isset( $_COOKIE['wp-settings-' . $user->ID] ) ) {
813                 $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user->ID] );
814
815                 if ( ! empty( $cookie ) && strpos( $cookie, '=' ) ) {
816                         if ( $cookie == $settings )
817                                 return;
818
819                         $last_time = (int) get_user_option( 'user-settings-time', $user->ID );
820                         $saved = isset( $_COOKIE['wp-settings-time-' . $user->ID]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user->ID] ) : 0;
821
822                         if ( $saved > $last_time ) {
823                                 update_user_option( $user->ID, 'user-settings', $cookie, false );
824                                 update_user_option( $user->ID, 'user-settings-time', time() - 5, false );
825                                 return;
826                         }
827                 }
828         }
829
830         setcookie( 'wp-settings-' . $user->ID, $settings, time() + 31536000, SITECOOKIEPATH );
831         setcookie( 'wp-settings-time-' . $user->ID, time(), time() + 31536000, SITECOOKIEPATH );
832         $_COOKIE['wp-settings-' . $user->ID] = $settings;
833 }
834
835 /**
836  * Retrieve user interface setting value based on setting name.
837  *
838  * @package WordPress
839  * @subpackage Option
840  * @since 2.7.0
841  *
842  * @param string $name The name of the setting.
843  * @param string $default Optional default value to return when $name is not set.
844  * @return mixed the last saved user setting or the default value/false if it doesn't exist.
845  */
846 function get_user_setting( $name, $default = false ) {
847
848         $all = get_all_user_settings();
849
850         return isset($all[$name]) ? $all[$name] : $default;
851 }
852
853 /**
854  * Add or update user interface setting.
855  *
856  * Both $name and $value can contain only ASCII letters, numbers and underscores.
857  * This function has to be used before any output has started as it calls setcookie().
858  *
859  * @package WordPress
860  * @subpackage Option
861  * @since 2.8.0
862  *
863  * @param string $name The name of the setting.
864  * @param string $value The value for the setting.
865  * @return bool true if set successfully/false if not.
866  */
867 function set_user_setting( $name, $value ) {
868
869         if ( headers_sent() )
870                 return false;
871
872         $all = get_all_user_settings();
873         $name = preg_replace( '/[^A-Za-z0-9_]+/', '', $name );
874
875         if ( empty($name) )
876                 return false;
877
878         $all[$name] = $value;
879
880         return wp_set_all_user_settings($all);
881 }
882
883 /**
884  * Delete user interface settings.
885  *
886  * Deleting settings would reset them to the defaults.
887  * This function has to be used before any output has started as it calls setcookie().
888  *
889  * @package WordPress
890  * @subpackage Option
891  * @since 2.7.0
892  *
893  * @param mixed $names The name or array of names of the setting to be deleted.
894  * @return bool true if deleted successfully/false if not.
895  */
896 function delete_user_setting( $names ) {
897
898         if ( headers_sent() )
899                 return false;
900
901         $all = get_all_user_settings();
902         $names = (array) $names;
903
904         foreach ( $names as $name ) {
905                 if ( isset($all[$name]) ) {
906                         unset($all[$name]);
907                         $deleted = true;
908                 }
909         }
910
911         if ( isset($deleted) )
912                 return wp_set_all_user_settings($all);
913
914         return false;
915 }
916
917 /**
918  * Retrieve all user interface settings.
919  *
920  * @package WordPress
921  * @subpackage Option
922  * @since 2.7.0
923  *
924  * @return array the last saved user settings or empty array.
925  */
926 function get_all_user_settings() {
927         global $_updated_user_settings;
928
929         if ( ! $user = wp_get_current_user() )
930                 return array();
931
932         if ( isset($_updated_user_settings) && is_array($_updated_user_settings) )
933                 return $_updated_user_settings;
934
935         $all = array();
936         if ( isset($_COOKIE['wp-settings-' . $user->ID]) ) {
937                 $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user->ID] );
938
939                 if ( $cookie && strpos($cookie, '=') ) // the '=' cannot be 1st char
940                         parse_str($cookie, $all);
941
942         } else {
943                 $option = get_user_option('user-settings', $user->ID);
944                 if ( $option && is_string($option) )
945                         parse_str( $option, $all );
946         }
947
948         return $all;
949 }
950
951 /**
952  * Private. Set all user interface settings.
953  *
954  * @package WordPress
955  * @subpackage Option
956  * @since 2.8.0
957  *
958  * @param unknown $all
959  * @return bool
960  */
961 function wp_set_all_user_settings($all) {
962         global $_updated_user_settings;
963
964         if ( ! $user = wp_get_current_user() )
965                 return false;
966
967         $_updated_user_settings = $all;
968         $settings = '';
969         foreach ( $all as $k => $v ) {
970                 $v = preg_replace( '/[^A-Za-z0-9_]+/', '', $v );
971                 $settings .= $k . '=' . $v . '&';
972         }
973
974         $settings = rtrim($settings, '&');
975
976         update_user_option( $user->ID, 'user-settings', $settings, false );
977         update_user_option( $user->ID, 'user-settings-time', time(), false );
978
979         return true;
980 }
981
982 /**
983  * Delete the user settings of the current user.
984  *
985  * @package WordPress
986  * @subpackage Option
987  * @since 2.7.0
988  */
989 function delete_all_user_settings() {
990         if ( ! $user = wp_get_current_user() )
991                 return;
992
993         update_user_option( $user->ID, 'user-settings', '', false );
994         setcookie('wp-settings-' . $user->ID, ' ', time() - 31536000, SITECOOKIEPATH);
995 }
996
997 /**
998  * Serialize data, if needed.
999  *
1000  * @since 2.0.5
1001  *
1002  * @param mixed $data Data that might be serialized.
1003  * @return mixed A scalar data
1004  */
1005 function maybe_serialize( $data ) {
1006         if ( is_array( $data ) || is_object( $data ) )
1007                 return serialize( $data );
1008
1009         if ( is_serialized( $data ) )
1010                 return serialize( $data );
1011
1012         return $data;
1013 }
1014
1015 /**
1016  * Retrieve post title from XMLRPC XML.
1017  *
1018  * If the title element is not part of the XML, then the default post title from
1019  * the $post_default_title will be used instead.
1020  *
1021  * @package WordPress
1022  * @subpackage XMLRPC
1023  * @since 0.71
1024  *
1025  * @global string $post_default_title Default XMLRPC post title.
1026  *
1027  * @param string $content XMLRPC XML Request content
1028  * @return string Post title
1029  */
1030 function xmlrpc_getposttitle( $content ) {
1031         global $post_default_title;
1032         if ( preg_match( '/<title>(.+?)<\/title>/is', $content, $matchtitle ) ) {
1033                 $post_title = $matchtitle[1];
1034         } else {
1035                 $post_title = $post_default_title;
1036         }
1037         return $post_title;
1038 }
1039
1040 /**
1041  * Retrieve the post category or categories from XMLRPC XML.
1042  *
1043  * If the category element is not found, then the default post category will be
1044  * used. The return type then would be what $post_default_category. If the
1045  * category is found, then it will always be an array.
1046  *
1047  * @package WordPress
1048  * @subpackage XMLRPC
1049  * @since 0.71
1050  *
1051  * @global string $post_default_category Default XMLRPC post category.
1052  *
1053  * @param string $content XMLRPC XML Request content
1054  * @return string|array List of categories or category name.
1055  */
1056 function xmlrpc_getpostcategory( $content ) {
1057         global $post_default_category;
1058         if ( preg_match( '/<category>(.+?)<\/category>/is', $content, $matchcat ) ) {
1059                 $post_category = trim( $matchcat[1], ',' );
1060                 $post_category = explode( ',', $post_category );
1061         } else {
1062                 $post_category = $post_default_category;
1063         }
1064         return $post_category;
1065 }
1066
1067 /**
1068  * XMLRPC XML content without title and category elements.
1069  *
1070  * @package WordPress
1071  * @subpackage XMLRPC
1072  * @since 0.71
1073  *
1074  * @param string $content XMLRPC XML Request content
1075  * @return string XMLRPC XML Request content without title and category elements.
1076  */
1077 function xmlrpc_removepostdata( $content ) {
1078         $content = preg_replace( '/<title>(.+?)<\/title>/si', '', $content );
1079         $content = preg_replace( '/<category>(.+?)<\/category>/si', '', $content );
1080         $content = trim( $content );
1081         return $content;
1082 }
1083
1084 /**
1085  * Open the file handle for debugging.
1086  *
1087  * This function is used for XMLRPC feature, but it is general purpose enough
1088  * to be used in anywhere.
1089  *
1090  * @see fopen() for mode options.
1091  * @package WordPress
1092  * @subpackage Debug
1093  * @since 0.71
1094  * @uses $debug Used for whether debugging is enabled.
1095  *
1096  * @param string $filename File path to debug file.
1097  * @param string $mode Same as fopen() mode parameter.
1098  * @return bool|resource File handle. False on failure.
1099  */
1100 function debug_fopen( $filename, $mode ) {
1101         global $debug;
1102         if ( 1 == $debug ) {
1103                 $fp = fopen( $filename, $mode );
1104                 return $fp;
1105         } else {
1106                 return false;
1107         }
1108 }
1109
1110 /**
1111  * Write contents to the file used for debugging.
1112  *
1113  * Technically, this can be used to write to any file handle when the global
1114  * $debug is set to 1 or true.
1115  *
1116  * @package WordPress
1117  * @subpackage Debug
1118  * @since 0.71
1119  * @uses $debug Used for whether debugging is enabled.
1120  *
1121  * @param resource $fp File handle for debugging file.
1122  * @param string $string Content to write to debug file.
1123  */
1124 function debug_fwrite( $fp, $string ) {
1125         global $debug;
1126         if ( 1 == $debug )
1127                 fwrite( $fp, $string );
1128 }
1129
1130 /**
1131  * Close the debugging file handle.
1132  *
1133  * Technically, this can be used to close any file handle when the global $debug
1134  * is set to 1 or true.
1135  *
1136  * @package WordPress
1137  * @subpackage Debug
1138  * @since 0.71
1139  * @uses $debug Used for whether debugging is enabled.
1140  *
1141  * @param resource $fp Debug File handle.
1142  */
1143 function debug_fclose( $fp ) {
1144         global $debug;
1145         if ( 1 == $debug )
1146                 fclose( $fp );
1147 }
1148
1149 /**
1150  * Check content for video and audio links to add as enclosures.
1151  *
1152  * Will not add enclosures that have already been added and will
1153  * remove enclosures that are no longer in the post. This is called as
1154  * pingbacks and trackbacks.
1155  *
1156  * @package WordPress
1157  * @since 1.5.0
1158  *
1159  * @uses $wpdb
1160  *
1161  * @param string $content Post Content
1162  * @param int $post_ID Post ID
1163  */
1164 function do_enclose( $content, $post_ID ) {
1165         global $wpdb;
1166         include_once( ABSPATH . WPINC . '/class-IXR.php' );
1167
1168         $log = debug_fopen( ABSPATH . 'enclosures.log', 'a' );
1169         $post_links = array();
1170         debug_fwrite( $log, 'BEGIN ' . date( 'YmdHis', time() ) . "\n" );
1171
1172         $pung = get_enclosed( $post_ID );
1173
1174         $ltrs = '\w';
1175         $gunk = '/#~:.?+=&%@!\-';
1176         $punc = '.:?\-';
1177         $any = $ltrs . $gunk . $punc;
1178
1179         preg_match_all( "{\b http : [$any] +? (?= [$punc] * [^$any] | $)}x", $content, $post_links_temp );
1180
1181         debug_fwrite( $log, 'Post contents:' );
1182         debug_fwrite( $log, $content . "\n" );
1183
1184         foreach ( $pung as $link_test ) {
1185                 if ( !in_array( $link_test, $post_links_temp[0] ) ) { // link no longer in post
1186                         $mid = $wpdb->get_col( $wpdb->prepare("SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE (%s)", $post_ID, $link_test . '%') );
1187                         do_action( 'delete_postmeta', $mid );
1188                         $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id IN(%s)", implode( ',', $mid ) ) );
1189                         do_action( 'deleted_postmeta', $mid );
1190                 }
1191         }
1192
1193         foreach ( (array) $post_links_temp[0] as $link_test ) {
1194                 if ( !in_array( $link_test, $pung ) ) { // If we haven't pung it already
1195                         $test = @parse_url( $link_test );
1196                         if ( false === $test )
1197                                 continue;
1198                         if ( isset( $test['query'] ) )
1199                                 $post_links[] = $link_test;
1200                         elseif ( $test['path'] != '/' && $test['path'] != '' )
1201                                 $post_links[] = $link_test;
1202                 }
1203         }
1204
1205         foreach ( (array) $post_links as $url ) {
1206                 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, $url . '%' ) ) ) {
1207
1208                         if ( $headers = wp_get_http_headers( $url) ) {
1209                                 $len = (int) $headers['content-length'];
1210                                 $type = $headers['content-type'];
1211                                 $allowed_types = array( 'video', 'audio' );
1212
1213                                 // Check to see if we can figure out the mime type from
1214                                 // the extension
1215                                 $url_parts = @parse_url( $url );
1216                                 if ( false !== $url_parts ) {
1217                                         $extension = pathinfo( $url_parts['path'], PATHINFO_EXTENSION );
1218                                         if ( !empty( $extension ) ) {
1219                                                 foreach ( get_allowed_mime_types( ) as $exts => $mime ) {
1220                                                         if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
1221                                                                 $type = $mime;
1222                                                                 break;
1223                                                         }
1224                                                 }
1225                                         }
1226                                 }
1227
1228                                 if ( in_array( substr( $type, 0, strpos( $type, "/" ) ), $allowed_types ) ) {
1229                                         $meta_value = "$url\n$len\n$type\n";
1230                                         $wpdb->insert($wpdb->postmeta, array('post_id' => $post_ID, 'meta_key' => 'enclosure', 'meta_value' => $meta_value) );
1231                                         do_action( 'added_postmeta', $wpdb->insert_id, $post_ID, 'enclosure', $meta_value );
1232                                 }
1233                         }
1234                 }
1235         }
1236 }
1237
1238 /**
1239  * Perform a HTTP HEAD or GET request.
1240  *
1241  * If $file_path is a writable filename, this will do a GET request and write
1242  * the file to that path.
1243  *
1244  * @since 2.5.0
1245  *
1246  * @param string $url URL to fetch.
1247  * @param string|bool $file_path Optional. File path to write request to.
1248  * @param int $red (private) The number of Redirects followed, Upon 5 being hit, returns false.
1249  * @return bool|string False on failure and string of headers if HEAD request.
1250  */
1251 function wp_get_http( $url, $file_path = false, $red = 1 ) {
1252         @set_time_limit( 60 );
1253
1254         if ( $red > 5 )
1255                 return false;
1256
1257         $options = array();
1258         $options['redirection'] = 5;
1259
1260         if ( false == $file_path )
1261                 $options['method'] = 'HEAD';
1262         else
1263                 $options['method'] = 'GET';
1264
1265         $response = wp_remote_request($url, $options);
1266
1267         if ( is_wp_error( $response ) )
1268                 return false;
1269
1270         $headers = wp_remote_retrieve_headers( $response );
1271         $headers['response'] = $response['response']['code'];
1272
1273         // WP_HTTP no longer follows redirects for HEAD requests.
1274         if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) {
1275                 return wp_get_http( $headers['location'], $file_path, ++$red );
1276         }
1277
1278         if ( false == $file_path )
1279                 return $headers;
1280
1281         // GET request - write it to the supplied filename
1282         $out_fp = fopen($file_path, 'w');
1283         if ( !$out_fp )
1284                 return $headers;
1285
1286         fwrite( $out_fp,  $response['body']);
1287         fclose($out_fp);
1288         clearstatcache();
1289
1290         return $headers;
1291 }
1292
1293 /**
1294  * Retrieve HTTP Headers from URL.
1295  *
1296  * @since 1.5.1
1297  *
1298  * @param string $url
1299  * @param bool $deprecated Not Used.
1300  * @return bool|string False on failure, headers on success.
1301  */
1302 function wp_get_http_headers( $url, $deprecated = false ) {
1303         if ( !empty( $deprecated ) )
1304                 _deprecated_argument( __FUNCTION__, '2.7' );
1305
1306         $response = wp_remote_head( $url );
1307
1308         if ( is_wp_error( $response ) )
1309                 return false;
1310
1311         return wp_remote_retrieve_headers( $response );
1312 }
1313
1314 /**
1315  * Whether today is a new day.
1316  *
1317  * @since 0.71
1318  * @uses $day Today
1319  * @uses $previousday Previous day
1320  *
1321  * @return int 1 when new day, 0 if not a new day.
1322  */
1323 function is_new_day() {
1324         global $day, $previousday;
1325         if ( $day != $previousday )
1326                 return 1;
1327         else
1328                 return 0;
1329 }
1330
1331 /**
1332  * Build URL query based on an associative and, or indexed array.
1333  *
1334  * This is a convenient function for easily building url queries. It sets the
1335  * separator to '&' and uses _http_build_query() function.
1336  *
1337  * @see _http_build_query() Used to build the query
1338  * @link http://us2.php.net/manual/en/function.http-build-query.php more on what
1339  *              http_build_query() does.
1340  *
1341  * @since 2.3.0
1342  *
1343  * @param array $data URL-encode key/value pairs.
1344  * @return string URL encoded string
1345  */
1346 function build_query( $data ) {
1347         return _http_build_query( $data, null, '&', '', false );
1348 }
1349
1350 /**
1351  * Retrieve a modified URL query string.
1352  *
1353  * You can rebuild the URL and append a new query variable to the URL query by
1354  * using this function. You can also retrieve the full URL with query data.
1355  *
1356  * Adding a single key & value or an associative array. Setting a key value to
1357  * emptystring removes the key. Omitting oldquery_or_uri uses the $_SERVER
1358  * value.
1359  *
1360  * @since 1.5.0
1361  *
1362  * @param mixed $param1 Either newkey or an associative_array
1363  * @param mixed $param2 Either newvalue or oldquery or uri
1364  * @param mixed $param3 Optional. Old query or uri
1365  * @return string New URL query string.
1366  */
1367 function add_query_arg() {
1368         $ret = '';
1369         if ( is_array( func_get_arg(0) ) ) {
1370                 if ( @func_num_args() < 2 || false === @func_get_arg( 1 ) )
1371                         $uri = $_SERVER['REQUEST_URI'];
1372                 else
1373                         $uri = @func_get_arg( 1 );
1374         } else {
1375                 if ( @func_num_args() < 3 || false === @func_get_arg( 2 ) )
1376                         $uri = $_SERVER['REQUEST_URI'];
1377                 else
1378                         $uri = @func_get_arg( 2 );
1379         }
1380
1381         if ( $frag = strstr( $uri, '#' ) )
1382                 $uri = substr( $uri, 0, -strlen( $frag ) );
1383         else
1384                 $frag = '';
1385
1386         if ( preg_match( '|^https?://|i', $uri, $matches ) ) {
1387                 $protocol = $matches[0];
1388                 $uri = substr( $uri, strlen( $protocol ) );
1389         } else {
1390                 $protocol = '';
1391         }
1392
1393         if ( strpos( $uri, '?' ) !== false ) {
1394                 $parts = explode( '?', $uri, 2 );
1395                 if ( 1 == count( $parts ) ) {
1396                         $base = '?';
1397                         $query = $parts[0];
1398                 } else {
1399                         $base = $parts[0] . '?';
1400                         $query = $parts[1];
1401                 }
1402         } elseif ( !empty( $protocol ) || strpos( $uri, '=' ) === false ) {
1403                 $base = $uri . '?';
1404                 $query = '';
1405         } else {
1406                 $base = '';
1407                 $query = $uri;
1408         }
1409
1410         wp_parse_str( $query, $qs );
1411         $qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
1412         if ( is_array( func_get_arg( 0 ) ) ) {
1413                 $kayvees = func_get_arg( 0 );
1414                 $qs = array_merge( $qs, $kayvees );
1415         } else {
1416                 $qs[func_get_arg( 0 )] = func_get_arg( 1 );
1417         }
1418
1419         foreach ( (array) $qs as $k => $v ) {
1420                 if ( $v === false )
1421                         unset( $qs[$k] );
1422         }
1423
1424         $ret = build_query( $qs );
1425         $ret = trim( $ret, '?' );
1426         $ret = preg_replace( '#=(&|$)#', '$1', $ret );
1427         $ret = $protocol . $base . $ret . $frag;
1428         $ret = rtrim( $ret, '?' );
1429         return $ret;
1430 }
1431
1432 /**
1433  * Removes an item or list from the query string.
1434  *
1435  * @since 1.5.0
1436  *
1437  * @param string|array $key Query key or keys to remove.
1438  * @param bool $query When false uses the $_SERVER value.
1439  * @return string New URL query string.
1440  */
1441 function remove_query_arg( $key, $query=false ) {
1442         if ( is_array( $key ) ) { // removing multiple keys
1443                 foreach ( $key as $k )
1444                         $query = add_query_arg( $k, false, $query );
1445                 return $query;
1446         }
1447         return add_query_arg( $key, false, $query );
1448 }
1449
1450 /**
1451  * Walks the array while sanitizing the contents.
1452  *
1453  * @since 0.71
1454  *
1455  * @param array $array Array to used to walk while sanitizing contents.
1456  * @return array Sanitized $array.
1457  */
1458 function add_magic_quotes( $array ) {
1459         foreach ( (array) $array as $k => $v ) {
1460                 if ( is_array( $v ) ) {
1461                         $array[$k] = add_magic_quotes( $v );
1462                 } else {
1463                         $array[$k] = addslashes( $v );
1464                 }
1465         }
1466         return $array;
1467 }
1468
1469 /**
1470  * HTTP request for URI to retrieve content.
1471  *
1472  * @since 1.5.1
1473  * @uses wp_remote_get()
1474  *
1475  * @param string $uri URI/URL of web page to retrieve.
1476  * @return bool|string HTTP content. False on failure.
1477  */
1478 function wp_remote_fopen( $uri ) {
1479         $parsed_url = @parse_url( $uri );
1480
1481         if ( !$parsed_url || !is_array( $parsed_url ) )
1482                 return false;
1483
1484         $options = array();
1485         $options['timeout'] = 10;
1486
1487         $response = wp_remote_get( $uri, $options );
1488
1489         if ( is_wp_error( $response ) )
1490                 return false;
1491
1492         return $response['body'];
1493 }
1494
1495 /**
1496  * Set up the WordPress query.
1497  *
1498  * @since 2.0.0
1499  *
1500  * @param string $query_vars Default WP_Query arguments.
1501  */
1502 function wp( $query_vars = '' ) {
1503         global $wp, $wp_query, $wp_the_query;
1504         $wp->main( $query_vars );
1505
1506         if ( !isset($wp_the_query) )
1507                 $wp_the_query = $wp_query;
1508 }
1509
1510 /**
1511  * Retrieve the description for the HTTP status.
1512  *
1513  * @since 2.3.0
1514  *
1515  * @param int $code HTTP status code.
1516  * @return string Empty string if not found, or description if found.
1517  */
1518 function get_status_header_desc( $code ) {
1519         global $wp_header_to_desc;
1520
1521         $code = absint( $code );
1522
1523         if ( !isset( $wp_header_to_desc ) ) {
1524                 $wp_header_to_desc = array(
1525                         100 => 'Continue',
1526                         101 => 'Switching Protocols',
1527                         102 => 'Processing',
1528
1529                         200 => 'OK',
1530                         201 => 'Created',
1531                         202 => 'Accepted',
1532                         203 => 'Non-Authoritative Information',
1533                         204 => 'No Content',
1534                         205 => 'Reset Content',
1535                         206 => 'Partial Content',
1536                         207 => 'Multi-Status',
1537                         226 => 'IM Used',
1538
1539                         300 => 'Multiple Choices',
1540                         301 => 'Moved Permanently',
1541                         302 => 'Found',
1542                         303 => 'See Other',
1543                         304 => 'Not Modified',
1544                         305 => 'Use Proxy',
1545                         306 => 'Reserved',
1546                         307 => 'Temporary Redirect',
1547
1548                         400 => 'Bad Request',
1549                         401 => 'Unauthorized',
1550                         402 => 'Payment Required',
1551                         403 => 'Forbidden',
1552                         404 => 'Not Found',
1553                         405 => 'Method Not Allowed',
1554                         406 => 'Not Acceptable',
1555                         407 => 'Proxy Authentication Required',
1556                         408 => 'Request Timeout',
1557                         409 => 'Conflict',
1558                         410 => 'Gone',
1559                         411 => 'Length Required',
1560                         412 => 'Precondition Failed',
1561                         413 => 'Request Entity Too Large',
1562                         414 => 'Request-URI Too Long',
1563                         415 => 'Unsupported Media Type',
1564                         416 => 'Requested Range Not Satisfiable',
1565                         417 => 'Expectation Failed',
1566                         422 => 'Unprocessable Entity',
1567                         423 => 'Locked',
1568                         424 => 'Failed Dependency',
1569                         426 => 'Upgrade Required',
1570
1571                         500 => 'Internal Server Error',
1572                         501 => 'Not Implemented',
1573                         502 => 'Bad Gateway',
1574                         503 => 'Service Unavailable',
1575                         504 => 'Gateway Timeout',
1576                         505 => 'HTTP Version Not Supported',
1577                         506 => 'Variant Also Negotiates',
1578                         507 => 'Insufficient Storage',
1579                         510 => 'Not Extended'
1580                 );
1581         }
1582
1583         if ( isset( $wp_header_to_desc[$code] ) )
1584                 return $wp_header_to_desc[$code];
1585         else
1586                 return '';
1587 }
1588
1589 /**
1590  * Set HTTP status header.
1591  *
1592  * @since 2.0.0
1593  * @uses apply_filters() Calls 'status_header' on status header string, HTTP
1594  *              HTTP code, HTTP code description, and protocol string as separate
1595  *              parameters.
1596  *
1597  * @param int $header HTTP status code
1598  * @return unknown
1599  */
1600 function status_header( $header ) {
1601         $text = get_status_header_desc( $header );
1602
1603         if ( empty( $text ) )
1604                 return false;
1605
1606         $protocol = $_SERVER["SERVER_PROTOCOL"];
1607         if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
1608                 $protocol = 'HTTP/1.0';
1609         $status_header = "$protocol $header $text";
1610         if ( function_exists( 'apply_filters' ) )
1611                 $status_header = apply_filters( 'status_header', $status_header, $header, $text, $protocol );
1612
1613         return @header( $status_header, true, $header );
1614 }
1615
1616 /**
1617  * Gets the header information to prevent caching.
1618  *
1619  * The several different headers cover the different ways cache prevention is handled
1620  * by different browsers
1621  *
1622  * @since 2.8
1623  *
1624  * @uses apply_filters()
1625  * @return array The associative array of header names and field values.
1626  */
1627 function wp_get_nocache_headers() {
1628         $headers = array(
1629                 'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
1630                 'Last-Modified' => gmdate( 'D, d M Y H:i:s' ) . ' GMT',
1631                 'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
1632                 'Pragma' => 'no-cache',
1633         );
1634
1635         if ( function_exists('apply_filters') ) {
1636                 $headers = apply_filters('nocache_headers', $headers);
1637         }
1638         return $headers;
1639 }
1640
1641 /**
1642  * Sets the headers to prevent caching for the different browsers.
1643  *
1644  * Different browsers support different nocache headers, so several headers must
1645  * be sent so that all of them get the point that no caching should occur.
1646  *
1647  * @since 2.0.0
1648  * @uses wp_get_nocache_headers()
1649  */
1650 function nocache_headers() {
1651         $headers = wp_get_nocache_headers();
1652         foreach( (array) $headers as $name => $field_value )
1653                 @header("{$name}: {$field_value}");
1654 }
1655
1656 /**
1657  * Set the headers for caching for 10 days with JavaScript content type.
1658  *
1659  * @since 2.1.0
1660  */
1661 function cache_javascript_headers() {
1662         $expiresOffset = 864000; // 10 days
1663         header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) );
1664         header( "Vary: Accept-Encoding" ); // Handle proxies
1665         header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $expiresOffset ) . " GMT" );
1666 }
1667
1668 /**
1669  * Retrieve the number of database queries during the WordPress execution.
1670  *
1671  * @since 2.0.0
1672  *
1673  * @return int Number of database queries
1674  */
1675 function get_num_queries() {
1676         global $wpdb;
1677         return $wpdb->num_queries;
1678 }
1679
1680 /**
1681  * Whether input is yes or no. Must be 'y' to be true.
1682  *
1683  * @since 1.0.0
1684  *
1685  * @param string $yn Character string containing either 'y' or 'n'
1686  * @return bool True if yes, false on anything else
1687  */
1688 function bool_from_yn( $yn ) {
1689         return ( strtolower( $yn ) == 'y' );
1690 }
1691
1692 /**
1693  * Loads the feed template from the use of an action hook.
1694  *
1695  * If the feed action does not have a hook, then the function will die with a
1696  * message telling the visitor that the feed is not valid.
1697  *
1698  * It is better to only have one hook for each feed.
1699  *
1700  * @since 2.1.0
1701  * @uses $wp_query Used to tell if the use a comment feed.
1702  * @uses do_action() Calls 'do_feed_$feed' hook, if a hook exists for the feed.
1703  */
1704 function do_feed() {
1705         global $wp_query;
1706
1707         $feed = get_query_var( 'feed' );
1708
1709         // Remove the pad, if present.
1710         $feed = preg_replace( '/^_+/', '', $feed );
1711
1712         if ( $feed == '' || $feed == 'feed' )
1713                 $feed = get_default_feed();
1714
1715         $hook = 'do_feed_' . $feed;
1716         if ( !has_action($hook) ) {
1717                 $message = sprintf( __( 'ERROR: %s is not a valid feed template.' ), esc_html($feed));
1718                 wp_die( $message, '', array( 'response' => 404 ) );
1719         }
1720
1721         do_action( $hook, $wp_query->is_comment_feed );
1722 }
1723
1724 /**
1725  * Load the RDF RSS 0.91 Feed template.
1726  *
1727  * @since 2.1.0
1728  */
1729 function do_feed_rdf() {
1730         load_template( ABSPATH . WPINC . '/feed-rdf.php' );
1731 }
1732
1733 /**
1734  * Load the RSS 1.0 Feed Template
1735  *
1736  * @since 2.1.0
1737  */
1738 function do_feed_rss() {
1739         load_template( ABSPATH . WPINC . '/feed-rss.php' );
1740 }
1741
1742 /**
1743  * Load either the RSS2 comment feed or the RSS2 posts feed.
1744  *
1745  * @since 2.1.0
1746  *
1747  * @param bool $for_comments True for the comment feed, false for normal feed.
1748  */
1749 function do_feed_rss2( $for_comments ) {
1750         if ( $for_comments )
1751                 load_template( ABSPATH . WPINC . '/feed-rss2-comments.php' );
1752         else
1753                 load_template( ABSPATH . WPINC . '/feed-rss2.php' );
1754 }
1755
1756 /**
1757  * Load either Atom comment feed or Atom posts feed.
1758  *
1759  * @since 2.1.0
1760  *
1761  * @param bool $for_comments True for the comment feed, false for normal feed.
1762  */
1763 function do_feed_atom( $for_comments ) {
1764         if ($for_comments)
1765                 load_template( ABSPATH . WPINC . '/feed-atom-comments.php');
1766         else
1767                 load_template( ABSPATH . WPINC . '/feed-atom.php' );
1768 }
1769
1770 /**
1771  * Display the robot.txt file content.
1772  *
1773  * The echo content should be with usage of the permalinks or for creating the
1774  * robot.txt file.
1775  *
1776  * @since 2.1.0
1777  * @uses do_action() Calls 'do_robotstxt' hook for displaying robot.txt rules.
1778  */
1779 function do_robots() {
1780         header( 'Content-Type: text/plain; charset=utf-8' );
1781
1782         do_action( 'do_robotstxt' );
1783
1784         $output = '';
1785         $public = get_option( 'blog_public' );
1786         if ( '0' ==  $public ) {
1787                 $output .= "User-agent: *\n";
1788                 $output .= "Disallow: /\n";
1789         } else {
1790                 $output .= "User-agent: *\n";
1791                 $output .= "Disallow:\n";
1792         }
1793
1794         echo apply_filters('robots_txt', $output, $public);
1795 }
1796
1797 /**
1798  * Test whether blog is already installed.
1799  *
1800  * The cache will be checked first. If you have a cache plugin, which saves the
1801  * cache values, then this will work. If you use the default WordPress cache,
1802  * and the database goes away, then you might have problems.
1803  *
1804  * Checks for the option siteurl for whether WordPress is installed.
1805  *
1806  * @since 2.1.0
1807  * @uses $wpdb
1808  *
1809  * @return bool Whether blog is already installed.
1810  */
1811 function is_blog_installed() {
1812         global $wpdb;
1813
1814         // Check cache first. If options table goes away and we have true cached, oh well.
1815         if ( wp_cache_get( 'is_blog_installed' ) )
1816                 return true;
1817
1818         $suppress = $wpdb->suppress_errors();
1819         if ( ! defined( 'WP_INSTALLING' ) ) {
1820                 $alloptions = wp_load_alloptions();
1821         }
1822         // If siteurl is not set to autoload, check it specifically
1823         if ( !isset( $alloptions['siteurl'] ) )
1824                 $installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
1825         else
1826                 $installed = $alloptions['siteurl'];
1827         $wpdb->suppress_errors( $suppress );
1828
1829         $installed = !empty( $installed );
1830         wp_cache_set( 'is_blog_installed', $installed );
1831
1832         if ( $installed )
1833                 return true;
1834
1835         $suppress = $wpdb->suppress_errors();
1836         $tables = $wpdb->get_col('SHOW TABLES');
1837         $wpdb->suppress_errors( $suppress );
1838
1839         $wp_tables = $wpdb->tables();
1840         // Loop over the WP tables.  If none exist, then scratch install is allowed.
1841         // If one or more exist, suggest table repair since we got here because the options
1842         // table could not be accessed.
1843         foreach ( $wp_tables as $table ) {
1844                 // If one of the WP tables exist, then we are in an insane state.
1845                 if ( in_array( $table, $tables ) ) {
1846                         // The existence of custom user tables shouldn't suggest an insane state or prevent a clean install.
1847                         if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table )
1848                                 continue;
1849                         if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table )
1850                                 continue;
1851
1852                         // If visiting repair.php, return true and let it take over.
1853                         if ( defined('WP_REPAIRING') )
1854                                 return true;
1855                         // Die with a DB error.
1856                         $wpdb->error = sprintf( /*WP_I18N_NO_TABLES*/'One or more database tables are unavailable.  The database may need to be <a href="%s">repaired</a>.'/*/WP_I18N_NO_TABLES*/, 'maint/repair.php?referrer=is_blog_installed' );
1857                         dead_db();
1858                 }
1859         }
1860
1861         wp_cache_set( 'is_blog_installed', false );
1862
1863         return false;
1864 }
1865
1866 /**
1867  * Retrieve URL with nonce added to URL query.
1868  *
1869  * @package WordPress
1870  * @subpackage Security
1871  * @since 2.0.4
1872  *
1873  * @param string $actionurl URL to add nonce action
1874  * @param string $action Optional. Nonce action name
1875  * @return string URL with nonce action added.
1876  */
1877 function wp_nonce_url( $actionurl, $action = -1 ) {
1878         $actionurl = str_replace( '&amp;', '&', $actionurl );
1879         return esc_html( add_query_arg( '_wpnonce', wp_create_nonce( $action ), $actionurl ) );
1880 }
1881
1882 /**
1883  * Retrieve or display nonce hidden field for forms.
1884  *
1885  * The nonce field is used to validate that the contents of the form came from
1886  * the location on the current site and not somewhere else. The nonce does not
1887  * offer absolute protection, but should protect against most cases. It is very
1888  * important to use nonce field in forms.
1889  *
1890  * If you set $echo to true and set $referer to true, then you will need to
1891  * retrieve the {@link wp_referer_field() wp referer field}. If you have the
1892  * $referer set to true and are echoing the nonce field, it will also echo the
1893  * referer field.
1894  *
1895  * The $action and $name are optional, but if you want to have better security,
1896  * it is strongly suggested to set those two parameters. It is easier to just
1897  * call the function without any parameters, because validation of the nonce
1898  * doesn't require any parameters, but since crackers know what the default is
1899  * it won't be difficult for them to find a way around your nonce and cause
1900  * damage.
1901  *
1902  * The input name will be whatever $name value you gave. The input value will be
1903  * the nonce creation value.
1904  *
1905  * @package WordPress
1906  * @subpackage Security
1907  * @since 2.0.4
1908  *
1909  * @param string $action Optional. Action name.
1910  * @param string $name Optional. Nonce name.
1911  * @param bool $referer Optional, default true. Whether to set the referer field for validation.
1912  * @param bool $echo Optional, default true. Whether to display or return hidden form field.
1913  * @return string Nonce field.
1914  */
1915 function wp_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) {
1916         $name = esc_attr( $name );
1917         $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />';
1918         if ( $echo )
1919                 echo $nonce_field;
1920
1921         if ( $referer )
1922                 wp_referer_field( $echo );
1923
1924         return $nonce_field;
1925 }
1926
1927 /**
1928  * Retrieve or display referer hidden field for forms.
1929  *
1930  * The referer link is the current Request URI from the server super global. The
1931  * input name is '_wp_http_referer', in case you wanted to check manually.
1932  *
1933  * @package WordPress
1934  * @subpackage Security
1935  * @since 2.0.4
1936  *
1937  * @param bool $echo Whether to echo or return the referer field.
1938  * @return string Referer field.
1939  */
1940 function wp_referer_field( $echo = true ) {
1941         $ref = esc_attr( $_SERVER['REQUEST_URI'] );
1942         $referer_field = '<input type="hidden" name="_wp_http_referer" value="'. $ref . '" />';
1943
1944         if ( $echo )
1945                 echo $referer_field;
1946         return $referer_field;
1947 }
1948
1949 /**
1950  * Retrieve or display original referer hidden field for forms.
1951  *
1952  * The input name is '_wp_original_http_referer' and will be either the same
1953  * value of {@link wp_referer_field()}, if that was posted already or it will
1954  * be the current page, if it doesn't exist.
1955  *
1956  * @package WordPress
1957  * @subpackage Security
1958  * @since 2.0.4
1959  *
1960  * @param bool $echo Whether to echo the original http referer
1961  * @param string $jump_back_to Optional, default is 'current'. Can be 'previous' or page you want to jump back to.
1962  * @return string Original referer field.
1963  */
1964 function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) {
1965         $jump_back_to = ( 'previous' == $jump_back_to ) ? wp_get_referer() : $_SERVER['REQUEST_URI'];
1966         $ref = ( wp_get_original_referer() ) ? wp_get_original_referer() : $jump_back_to;
1967         $orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . esc_attr( stripslashes( $ref ) ) . '" />';
1968         if ( $echo )
1969                 echo $orig_referer_field;
1970         return $orig_referer_field;
1971 }
1972
1973 /**
1974  * Retrieve referer from '_wp_http_referer', HTTP referer, or current page respectively.
1975  *
1976  * @package WordPress
1977  * @subpackage Security
1978  * @since 2.0.4
1979  *
1980  * @return string|bool False on failure. Referer URL on success.
1981  */
1982 function wp_get_referer() {
1983         $ref = '';
1984         if ( ! empty( $_REQUEST['_wp_http_referer'] ) )
1985                 $ref = $_REQUEST['_wp_http_referer'];
1986         else if ( ! empty( $_SERVER['HTTP_REFERER'] ) )
1987                 $ref = $_SERVER['HTTP_REFERER'];
1988
1989         if ( $ref !== $_SERVER['REQUEST_URI'] )
1990                 return $ref;
1991         return false;
1992 }
1993
1994 /**
1995  * Retrieve original referer that was posted, if it exists.
1996  *
1997  * @package WordPress
1998  * @subpackage Security
1999  * @since 2.0.4
2000  *
2001  * @return string|bool False if no original referer or original referer if set.
2002  */
2003 function wp_get_original_referer() {
2004         if ( !empty( $_REQUEST['_wp_original_http_referer'] ) )
2005                 return $_REQUEST['_wp_original_http_referer'];
2006         return false;
2007 }
2008
2009 /**
2010  * Recursive directory creation based on full path.
2011  *
2012  * Will attempt to set permissions on folders.
2013  *
2014  * @since 2.0.1
2015  *
2016  * @param string $target Full path to attempt to create.
2017  * @return bool Whether the path was created. True if path already exists.
2018  */
2019 function wp_mkdir_p( $target ) {
2020         // from php.net/mkdir user contributed notes
2021         $target = str_replace( '//', '/', $target );
2022
2023         // safe mode fails with a trailing slash under certain PHP versions.
2024         $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
2025         if ( empty($target) )
2026                 $target = '/';
2027
2028         if ( file_exists( $target ) )
2029                 return @is_dir( $target );
2030
2031         // Attempting to create the directory may clutter up our display.
2032         if ( @mkdir( $target ) ) {
2033                 $stat = @stat( dirname( $target ) );
2034                 $dir_perms = $stat['mode'] & 0007777;  // Get the permission bits.
2035                 @chmod( $target, $dir_perms );
2036                 return true;
2037         } elseif ( is_dir( dirname( $target ) ) ) {
2038                         return false;
2039         }
2040
2041         // If the above failed, attempt to create the parent node, then try again.
2042         if ( ( $target != '/' ) && ( wp_mkdir_p( dirname( $target ) ) ) )
2043                 return wp_mkdir_p( $target );
2044
2045         return false;
2046 }
2047
2048 /**
2049  * Test if a give filesystem path is absolute ('/foo/bar', 'c:\windows').
2050  *
2051  * @since 2.5.0
2052  *
2053  * @param string $path File path
2054  * @return bool True if path is absolute, false is not absolute.
2055  */
2056 function path_is_absolute( $path ) {
2057         // this is definitive if true but fails if $path does not exist or contains a symbolic link
2058         if ( realpath($path) == $path )
2059                 return true;
2060
2061         if ( strlen($path) == 0 || $path{0} == '.' )
2062                 return false;
2063
2064         // windows allows absolute paths like this
2065         if ( preg_match('#^[a-zA-Z]:\\\\#', $path) )
2066                 return true;
2067
2068         // a path starting with / or \ is absolute; anything else is relative
2069         return (bool) preg_match('#^[/\\\\]#', $path);
2070 }
2071
2072 /**
2073  * Join two filesystem paths together (e.g. 'give me $path relative to $base').
2074  *
2075  * If the $path is absolute, then it the full path is returned.
2076  *
2077  * @since 2.5.0
2078  *
2079  * @param string $base
2080  * @param string $path
2081  * @return string The path with the base or absolute path.
2082  */
2083 function path_join( $base, $path ) {
2084         if ( path_is_absolute($path) )
2085                 return $path;
2086
2087         return rtrim($base, '/') . '/' . ltrim($path, '/');
2088 }
2089
2090 /**
2091  * Get an array containing the current upload directory's path and url.
2092  *
2093  * Checks the 'upload_path' option, which should be from the web root folder,
2094  * and if it isn't empty it will be used. If it is empty, then the path will be
2095  * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
2096  * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path.
2097  *
2098  * The upload URL path is set either by the 'upload_url_path' option or by using
2099  * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path.
2100  *
2101  * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in
2102  * the administration settings panel), then the time will be used. The format
2103  * will be year first and then month.
2104  *
2105  * If the path couldn't be created, then an error will be returned with the key
2106  * 'error' containing the error message. The error suggests that the parent
2107  * directory is not writable by the server.
2108  *
2109  * On success, the returned array will have many indices:
2110  * 'path' - base directory and sub directory or full path to upload directory.
2111  * 'url' - base url and sub directory or absolute URL to upload directory.
2112  * 'subdir' - sub directory if uploads use year/month folders option is on.
2113  * 'basedir' - path without subdir.
2114  * 'baseurl' - URL path without subdir.
2115  * 'error' - set to false.
2116  *
2117  * @since 2.0.0
2118  * @uses apply_filters() Calls 'upload_dir' on returned array.
2119  *
2120  * @param string $time Optional. Time formatted in 'yyyy/mm'.
2121  * @return array See above for description.
2122  */
2123 function wp_upload_dir( $time = null ) {
2124         global $switched;
2125         $siteurl = get_option( 'siteurl' );
2126         $upload_path = get_option( 'upload_path' );
2127         $upload_path = trim($upload_path);
2128         $main_override = defined( 'MULTISITE' ) && is_main_site();
2129         if ( empty($upload_path) ) {
2130                 $dir = WP_CONTENT_DIR . '/uploads';
2131         } else {
2132                 $dir = $upload_path;
2133                 if ( 'wp-content/uploads' == $upload_path ) {
2134                         $dir = WP_CONTENT_DIR . '/uploads';
2135                 } elseif ( 0 !== strpos($dir, ABSPATH) ) {
2136                         // $dir is absolute, $upload_path is (maybe) relative to ABSPATH
2137                         $dir = path_join( ABSPATH, $dir );
2138                 }
2139         }
2140
2141         if ( !$url = get_option( 'upload_url_path' ) ) {
2142                 if ( empty($upload_path) || ( 'wp-content/uploads' == $upload_path ) || ( $upload_path == $dir ) )
2143                         $url = WP_CONTENT_URL . '/uploads';
2144                 else
2145                         $url = trailingslashit( $siteurl ) . $upload_path;
2146         }
2147
2148         if ( defined('UPLOADS') && !$main_override && ( !isset( $switched ) || $switched === false ) ) {
2149                 $dir = ABSPATH . UPLOADS;
2150                 $url = trailingslashit( $siteurl ) . UPLOADS;
2151         }
2152
2153         if ( is_multisite() && !$main_override && ( !isset( $switched ) || $switched === false ) ) {
2154                 if ( defined( 'BLOGUPLOADDIR' ) )
2155                         $dir = untrailingslashit(BLOGUPLOADDIR);
2156                 $url = str_replace( UPLOADS, 'files', $url );
2157         }
2158
2159         $bdir = $dir;
2160         $burl = $url;
2161
2162         $subdir = '';
2163         if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
2164                 // Generate the yearly and monthly dirs
2165                 if ( !$time )
2166                         $time = current_time( 'mysql' );
2167                 $y = substr( $time, 0, 4 );
2168                 $m = substr( $time, 5, 2 );
2169                 $subdir = "/$y/$m";
2170         }
2171
2172         $dir .= $subdir;
2173         $url .= $subdir;
2174
2175         $uploads = apply_filters( 'upload_dir', array( 'path' => $dir, 'url' => $url, 'subdir' => $subdir, 'basedir' => $bdir, 'baseurl' => $burl, 'error' => false ) );
2176
2177         // Make sure we have an uploads dir
2178         if ( ! wp_mkdir_p( $uploads['path'] ) ) {
2179                 $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $uploads['path'] );
2180                 return array( 'error' => $message );
2181         }
2182
2183         return $uploads;
2184 }
2185
2186 /**
2187  * Get a filename that is sanitized and unique for the given directory.
2188  *
2189  * If the filename is not unique, then a number will be added to the filename
2190  * before the extension, and will continue adding numbers until the filename is
2191  * unique.
2192  *
2193  * The callback must accept two parameters, the first one is the directory and
2194  * the second is the filename. The callback must be a function.
2195  *
2196  * @since 2.5
2197  *
2198  * @param string $dir
2199  * @param string $filename
2200  * @param string $unique_filename_callback Function name, must be a function.
2201  * @return string New filename, if given wasn't unique.
2202  */
2203 function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
2204         // sanitize the file name before we begin processing
2205         $filename = sanitize_file_name($filename);
2206
2207         // separate the filename into a name and extension
2208         $info = pathinfo($filename);
2209         $ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
2210         $name = basename($filename, $ext);
2211
2212         // edge case: if file is named '.ext', treat as an empty name
2213         if ( $name === $ext )
2214                 $name = '';
2215
2216         // Increment the file number until we have a unique file to save in $dir. Use $override['unique_filename_callback'] if supplied.
2217         if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) {
2218                 $filename = $unique_filename_callback( $dir, $name );
2219         } else {
2220                 $number = '';
2221
2222                 // change '.ext' to lower case
2223                 if ( $ext && strtolower($ext) != $ext ) {
2224                         $ext2 = strtolower($ext);
2225                         $filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename );
2226
2227                         // check for both lower and upper case extension or image sub-sizes may be overwritten
2228                         while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) {
2229                                 $new_number = $number + 1;
2230                                 $filename = str_replace( "$number$ext", "$new_number$ext", $filename );
2231                                 $filename2 = str_replace( "$number$ext2", "$new_number$ext2", $filename2 );
2232                                 $number = $new_number;
2233                         }
2234                         return $filename2;
2235                 }
2236
2237                 while ( file_exists( $dir . "/$filename" ) ) {
2238                         if ( '' == "$number$ext" )
2239                                 $filename = $filename . ++$number . $ext;
2240                         else
2241                                 $filename = str_replace( "$number$ext", ++$number . $ext, $filename );
2242                 }
2243         }
2244
2245         return $filename;
2246 }
2247
2248 /**
2249  * Create a file in the upload folder with given content.
2250  *
2251  * If there is an error, then the key 'error' will exist with the error message.
2252  * If success, then the key 'file' will have the unique file path, the 'url' key
2253  * will have the link to the new file. and the 'error' key will be set to false.
2254  *
2255  * This function will not move an uploaded file to the upload folder. It will
2256  * create a new file with the content in $bits parameter. If you move the upload
2257  * file, read the content of the uploaded file, and then you can give the
2258  * filename and content to this function, which will add it to the upload
2259  * folder.
2260  *
2261  * The permissions will be set on the new file automatically by this function.
2262  *
2263  * @since 2.0.0
2264  *
2265  * @param string $name
2266  * @param null $deprecated Never used. Set to null.
2267  * @param mixed $bits File content
2268  * @param string $time Optional. Time formatted in 'yyyy/mm'.
2269  * @return array
2270  */
2271 function wp_upload_bits( $name, $deprecated, $bits, $time = null ) {
2272         if ( !empty( $deprecated ) )
2273                 _deprecated_argument( __FUNCTION__, '2.0' );
2274
2275         if ( empty( $name ) )
2276                 return array( 'error' => __( 'Empty filename' ) );
2277
2278         $wp_filetype = wp_check_filetype( $name );
2279         if ( !$wp_filetype['ext'] )
2280                 return array( 'error' => __( 'Invalid file type' ) );
2281
2282         $upload = wp_upload_dir( $time );
2283
2284         if ( $upload['error'] !== false )
2285                 return $upload;
2286
2287         $upload_bits_error = apply_filters( 'wp_upload_bits', array( 'name' => $name, 'bits' => $bits, 'time' => $time ) );
2288         if ( !is_array( $upload_bits_error ) ) {
2289                 $upload[ 'error' ] = $upload_bits_error;
2290                 return $upload;
2291         }
2292
2293         $filename = wp_unique_filename( $upload['path'], $name );
2294
2295         $new_file = $upload['path'] . "/$filename";
2296         if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
2297                 $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), dirname( $new_file ) );
2298                 return array( 'error' => $message );
2299         }
2300
2301         $ifp = @ fopen( $new_file, 'wb' );
2302         if ( ! $ifp )
2303                 return array( 'error' => sprintf( __( 'Could not write file %s' ), $new_file ) );
2304
2305         @fwrite( $ifp, $bits );
2306         fclose( $ifp );
2307         clearstatcache();
2308
2309         // Set correct file permissions
2310         $stat = @ stat( dirname( $new_file ) );
2311         $perms = $stat['mode'] & 0007777;
2312         $perms = $perms & 0000666;
2313         @ chmod( $new_file, $perms );
2314         clearstatcache();
2315
2316         // Compute the URL
2317         $url = $upload['url'] . "/$filename";
2318
2319         return array( 'file' => $new_file, 'url' => $url, 'error' => false );
2320 }
2321
2322 /**
2323  * Retrieve the file type based on the extension name.
2324  *
2325  * @package WordPress
2326  * @since 2.5.0
2327  * @uses apply_filters() Calls 'ext2type' hook on default supported types.
2328  *
2329  * @param string $ext The extension to search.
2330  * @return string|null The file type, example: audio, video, document, spreadsheet, etc. Null if not found.
2331  */
2332 function wp_ext2type( $ext ) {
2333         $ext2type = apply_filters( 'ext2type', array(
2334                 'audio'       => array( 'aac', 'ac3',  'aif',  'aiff', 'm3a',  'm4a',   'm4b', 'mka', 'mp1', 'mp2',  'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
2335                 'video'       => array( 'asf', 'avi',  'divx', 'dv',   'flv',  'm4v',   'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt',  'rm', 'vob', 'wmv' ),
2336                 'document'    => array( 'doc', 'docx', 'docm', 'dotm', 'odt',  'pages', 'pdf', 'rtf', 'wp',  'wpd' ),
2337                 'spreadsheet' => array( 'numbers',     'ods',  'xls',  'xlsx', 'xlsb',  'xlsm' ),
2338                 'interactive' => array( 'key', 'ppt',  'pptx', 'pptm', 'odp',  'swf' ),
2339                 'text'        => array( 'asc', 'csv',  'tsv',  'txt' ),
2340                 'archive'     => array( 'bz2', 'cab',  'dmg',  'gz',   'rar',  'sea',   'sit', 'sqx', 'tar', 'tgz',  'zip' ),
2341                 'code'        => array( 'css', 'htm',  'html', 'php',  'js' ),
2342         ));
2343         foreach ( $ext2type as $type => $exts )
2344                 if ( in_array( $ext, $exts ) )
2345                         return $type;
2346 }
2347
2348 /**
2349  * Retrieve the file type from the file name.
2350  *
2351  * You can optionally define the mime array, if needed.
2352  *
2353  * @since 2.0.4
2354  *
2355  * @param string $filename File name or path.
2356  * @param array $mimes Optional. Key is the file extension with value as the mime type.
2357  * @return array Values with extension first and mime type.
2358  */
2359 function wp_check_filetype( $filename, $mimes = null ) {
2360         if ( empty($mimes) )
2361                 $mimes = get_allowed_mime_types();
2362         $type = false;
2363         $ext = false;
2364
2365         foreach ( $mimes as $ext_preg => $mime_match ) {
2366                 $ext_preg = '!\.(' . $ext_preg . ')$!i';
2367                 if ( preg_match( $ext_preg, $filename, $ext_matches ) ) {
2368                         $type = $mime_match;
2369                         $ext = $ext_matches[1];
2370                         break;
2371                 }
2372         }
2373
2374         return compact( 'ext', 'type' );
2375 }
2376
2377 /**
2378  * Attempt to determine the real file type of a file.
2379  * If unable to, the file name extension will be used to determine type.
2380  *
2381  * If it's determined that the extension does not match the file's real type,
2382  * then the "proper_filename" value will be set with a proper filename and extension.
2383  *
2384  * Currently this function only supports validating images known to getimagesize().
2385  *
2386  * @since 3.0.0
2387  *
2388  * @param string $file Full path to the image.
2389  * @param string $filename The filename of the image (may differ from $file due to $file being in a tmp directory)
2390  * @param array $mimes Optional. Key is the file extension with value as the mime type.
2391  * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
2392  */
2393 function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
2394
2395         $proper_filename = false;
2396
2397         // Do basic extension validation and MIME mapping
2398         $wp_filetype = wp_check_filetype( $filename, $mimes );
2399         extract( $wp_filetype );
2400
2401         // We can't do any further validation without a file to work with
2402         if ( ! file_exists( $file ) )
2403                 return compact( 'ext', 'type', 'proper_filename' );
2404
2405         // We're able to validate images using GD
2406         if ( $type && 0 === strpos( $type, 'image/' ) && function_exists('getimagesize') ) {
2407
2408                 // Attempt to figure out what type of image it actually is
2409                 $imgstats = @getimagesize( $file );
2410
2411                 // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
2412                 if ( !empty($imgstats['mime']) && $imgstats['mime'] != $type ) {
2413                         // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
2414                         // You shouldn't need to use this filter, but it's here just in case
2415                         $mime_to_ext = apply_filters( 'getimagesize_mimes_to_exts', array(
2416                                 'image/jpeg' => 'jpg',
2417                                 'image/png'  => 'png',
2418                                 'image/gif'  => 'gif',
2419                                 'image/bmp'  => 'bmp',
2420                                 'image/tiff' => 'tif',
2421                         ) );
2422
2423                         // Replace whatever is after the last period in the filename with the correct extension
2424                         if ( ! empty( $mime_to_ext[ $imgstats['mime'] ] ) ) {
2425                                 $filename_parts = explode( '.', $filename );
2426                                 array_pop( $filename_parts );
2427                                 $filename_parts[] = $mime_to_ext[ $imgstats['mime'] ];
2428                                 $new_filename = implode( '.', $filename_parts );
2429
2430                                 if ( $new_filename != $filename )
2431                                         $proper_filename = $new_filename; // Mark that it changed
2432
2433                                 // Redefine the extension / MIME
2434                                 $wp_filetype = wp_check_filetype( $new_filename, $mimes );
2435                                 extract( $wp_filetype );
2436                         }
2437                 }
2438         }
2439
2440         // Let plugins try and validate other types of files
2441         // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
2442         return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes );
2443 }
2444
2445 /**
2446  * Retrieve list of allowed mime types and file extensions.
2447  *
2448  * @since 2.8.6
2449  *
2450  * @return array Array of mime types keyed by the file extension regex corresponding to those types.
2451  */
2452 function get_allowed_mime_types() {
2453         static $mimes = false;
2454
2455         if ( !$mimes ) {
2456                 // Accepted MIME types are set here as PCRE unless provided.
2457                 $mimes = apply_filters( 'upload_mimes', array(
2458                 'jpg|jpeg|jpe' => 'image/jpeg',
2459                 'gif' => 'image/gif',
2460                 'png' => 'image/png',
2461                 'bmp' => 'image/bmp',
2462                 'tif|tiff' => 'image/tiff',
2463                 'ico' => 'image/x-icon',
2464                 'asf|asx|wax|wmv|wmx' => 'video/asf',
2465                 'avi' => 'video/avi',
2466                 'divx' => 'video/divx',
2467                 'flv' => 'video/x-flv',
2468                 'mov|qt' => 'video/quicktime',
2469                 'mpeg|mpg|mpe' => 'video/mpeg',
2470                 'txt|asc|c|cc|h' => 'text/plain',
2471                 'csv' => 'text/csv',
2472                 'tsv' => 'text/tab-separated-values',
2473                 'rtx' => 'text/richtext',
2474                 'css' => 'text/css',
2475                 'htm|html' => 'text/html',
2476                 'mp3|m4a|m4b' => 'audio/mpeg',
2477                 'mp4|m4v' => 'video/mp4',
2478                 'ra|ram' => 'audio/x-realaudio',
2479                 'wav' => 'audio/wav',
2480                 'ogg|oga' => 'audio/ogg',
2481                 'ogv' => 'video/ogg',
2482                 'mid|midi' => 'audio/midi',
2483                 'wma' => 'audio/wma',
2484                 'mka' => 'audio/x-matroska',
2485                 'mkv' => 'video/x-matroska',
2486                 'rtf' => 'application/rtf',
2487                 'js' => 'application/javascript',
2488                 'pdf' => 'application/pdf',
2489                 'doc|docx' => 'application/msword',
2490                 'pot|pps|ppt|pptx|ppam|pptm|sldm|ppsm|potm' => 'application/vnd.ms-powerpoint',
2491                 'wri' => 'application/vnd.ms-write',
2492                 'xla|xls|xlsx|xlt|xlw|xlam|xlsb|xlsm|xltm' => 'application/vnd.ms-excel',
2493                 'mdb' => 'application/vnd.ms-access',
2494                 'mpp' => 'application/vnd.ms-project',
2495                 'docm|dotm' => 'application/vnd.ms-word',
2496                 'pptx|sldx|ppsx|potx' => 'application/vnd.openxmlformats-officedocument.presentationml',
2497                 'xlsx|xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml',
2498                 'docx|dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml',
2499                 'onetoc|onetoc2|onetmp|onepkg' => 'application/onenote',
2500                 'swf' => 'application/x-shockwave-flash',
2501                 'class' => 'application/java',
2502                 'tar' => 'application/x-tar',
2503                 'zip' => 'application/zip',
2504                 'gz|gzip' => 'application/x-gzip',
2505                 'exe' => 'application/x-msdownload',
2506                 // openoffice formats
2507                 'odt' => 'application/vnd.oasis.opendocument.text',
2508                 'odp' => 'application/vnd.oasis.opendocument.presentation',
2509                 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
2510                 'odg' => 'application/vnd.oasis.opendocument.graphics',
2511                 'odc' => 'application/vnd.oasis.opendocument.chart',
2512                 'odb' => 'application/vnd.oasis.opendocument.database',
2513                 'odf' => 'application/vnd.oasis.opendocument.formula',
2514                 // wordperfect formats
2515                 'wp|wpd' => 'application/wordperfect',
2516                 ) );
2517         }
2518
2519         return $mimes;
2520 }
2521
2522 /**
2523  * Retrieve nonce action "Are you sure" message.
2524  *
2525  * The action is split by verb and noun. The action format is as follows:
2526  * verb-action_extra. The verb is before the first dash and has the format of
2527  * letters and no spaces and numbers. The noun is after the dash and before the
2528  * underscore, if an underscore exists. The noun is also only letters.
2529  *
2530  * The filter will be called for any action, which is not defined by WordPress.
2531  * You may use the filter for your plugin to explain nonce actions to the user,
2532  * when they get the "Are you sure?" message. The filter is in the format of
2533  * 'explain_nonce_$verb-$noun' with the $verb replaced by the found verb and the
2534  * $noun replaced by the found noun. The two parameters that are given to the
2535  * hook are the localized "Are you sure you want to do this?" message with the
2536  * extra text (the text after the underscore).
2537  *
2538  * @package WordPress
2539  * @subpackage Security
2540  * @since 2.0.4
2541  *
2542  * @param string $action Nonce action.
2543  * @return string Are you sure message.
2544  */
2545 function wp_explain_nonce( $action ) {
2546         if ( $action !== -1 && preg_match( '/([a-z]+)-([a-z]+)(_(.+))?/', $action, $matches ) ) {
2547                 $verb = $matches[1];
2548                 $noun = $matches[2];
2549
2550                 $trans = array();
2551                 $trans['update']['attachment'] = array( __( 'Your attempt to edit this attachment: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2552
2553                 $trans['add']['category']      = array( __( 'Your attempt to add this category has failed.' ), false );
2554                 $trans['delete']['category']   = array( __( 'Your attempt to delete this category: &#8220;%s&#8221; has failed.' ), 'get_cat_name' );
2555                 $trans['update']['category']   = array( __( 'Your attempt to edit this category: &#8220;%s&#8221; has failed.' ), 'get_cat_name' );
2556
2557                 $trans['delete']['comment']    = array( __( 'Your attempt to delete this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
2558                 $trans['unapprove']['comment'] = array( __( 'Your attempt to unapprove this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
2559                 $trans['approve']['comment']   = array( __( 'Your attempt to approve this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
2560                 $trans['update']['comment']    = array( __( 'Your attempt to edit this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
2561                 $trans['bulk']['comments']     = array( __( 'Your attempt to bulk modify comments has failed.' ), false );
2562                 $trans['moderate']['comments'] = array( __( 'Your attempt to moderate comments has failed.' ), false );
2563
2564                 $trans['add']['bookmark']      = array( __( 'Your attempt to add this link has failed.' ), false );
2565                 $trans['delete']['bookmark']   = array( __( 'Your attempt to delete this link: &#8220;%s&#8221; has failed.' ), 'use_id' );
2566                 $trans['update']['bookmark']   = array( __( 'Your attempt to edit this link: &#8220;%s&#8221; has failed.' ), 'use_id' );
2567                 $trans['bulk']['bookmarks']    = array( __( 'Your attempt to bulk modify links has failed.' ), false );
2568
2569                 $trans['add']['page']          = array( __( 'Your attempt to add this page has failed.' ), false );
2570                 $trans['delete']['page']       = array( __( 'Your attempt to delete this page: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2571                 $trans['update']['page']       = array( __( 'Your attempt to edit this page: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2572
2573                 $trans['edit']['plugin']       = array( __( 'Your attempt to edit this plugin file: &#8220;%s&#8221; has failed.' ), 'use_id' );
2574                 $trans['activate']['plugin']   = array( __( 'Your attempt to activate this plugin: &#8220;%s&#8221; has failed.' ), 'use_id' );
2575                 $trans['deactivate']['plugin'] = array( __( 'Your attempt to deactivate this plugin: &#8220;%s&#8221; has failed.' ), 'use_id' );
2576                 $trans['upgrade']['plugin']    = array( __( 'Your attempt to upgrade this plugin: &#8220;%s&#8221; has failed.' ), 'use_id' );
2577
2578                 $trans['add']['post']          = array( __( 'Your attempt to add this post has failed.' ), false );
2579                 $trans['delete']['post']       = array( __( 'Your attempt to delete this post: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2580                 $trans['update']['post']       = array( __( 'Your attempt to edit this post: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2581
2582                 $trans['add']['user']          = array( __( 'Your attempt to add this user has failed.' ), false );
2583                 $trans['delete']['users']      = array( __( 'Your attempt to delete users has failed.' ), false );
2584                 $trans['bulk']['users']        = array( __( 'Your attempt to bulk modify users has failed.' ), false );
2585                 $trans['update']['user']       = array( __( 'Your attempt to edit this user: &#8220;%s&#8221; has failed.' ), 'get_the_author_meta', 'display_name' );
2586                 $trans['update']['profile']    = array( __( 'Your attempt to modify the profile for: &#8220;%s&#8221; has failed.' ), 'get_the_author_meta', 'display_name' );
2587
2588                 $trans['update']['options']    = array( __( 'Your attempt to edit your settings has failed.' ), false );
2589                 $trans['update']['permalink']  = array( __( 'Your attempt to change your permalink structure to: %s has failed.' ), 'use_id' );
2590                 $trans['edit']['file']         = array( __( 'Your attempt to edit this file: &#8220;%s&#8221; has failed.' ), 'use_id' );
2591                 $trans['edit']['theme']        = array( __( 'Your attempt to edit this theme file: &#8220;%s&#8221; has failed.' ), 'use_id' );
2592                 $trans['switch']['theme']      = array( __( 'Your attempt to switch to this theme: &#8220;%s&#8221; has failed.' ), 'use_id' );
2593
2594                 $trans['log']['out']           = array( sprintf( __( 'You are attempting to log out of %s' ), get_bloginfo( 'sitename' ) ), false );
2595
2596                 if ( isset( $trans[$verb][$noun] ) ) {
2597                         if ( !empty( $trans[$verb][$noun][1] ) ) {
2598                                 $lookup = $trans[$verb][$noun][1];
2599                                 if ( isset($trans[$verb][$noun][2]) )
2600                                         $lookup_value = $trans[$verb][$noun][2];
2601                                 $object = $matches[4];
2602                                 if ( 'use_id' != $lookup ) {
2603                                         if ( isset( $lookup_value ) )
2604                                                 $object = call_user_func( $lookup, $lookup_value, $object );
2605                                         else
2606                                                 $object = call_user_func( $lookup, $object );
2607                                 }
2608                                 return sprintf( $trans[$verb][$noun][0], esc_html($object) );
2609                         } else {
2610                                 return $trans[$verb][$noun][0];
2611                         }
2612                 }
2613
2614                 return apply_filters( 'explain_nonce_' . $verb . '-' . $noun, __( 'Are you sure you want to do this?' ), isset($matches[4]) ? $matches[4] : '' );
2615         } else {
2616                 return apply_filters( 'explain_nonce_' . $action, __( 'Are you sure you want to do this?' ) );
2617         }
2618 }
2619
2620 /**
2621  * Display "Are You Sure" message to confirm the action being taken.
2622  *
2623  * If the action has the nonce explain message, then it will be displayed along
2624  * with the "Are you sure?" message.
2625  *
2626  * @package WordPress
2627  * @subpackage Security
2628  * @since 2.0.4
2629  *
2630  * @param string $action The nonce action.
2631  */
2632 function wp_nonce_ays( $action ) {
2633         $title = __( 'WordPress Failure Notice' );
2634         $html = esc_html( wp_explain_nonce( $action ) );
2635         if ( 'log-out' == $action )
2636                 $html .= "</p><p>" . sprintf( __( "Do you really want to <a href='%s'>log out</a>?"), wp_logout_url() );
2637         elseif ( wp_get_referer() )
2638                 $html .= "</p><p><a href='" . esc_url( remove_query_arg( 'updated', wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>";
2639
2640         wp_die( $html, $title, array('response' => 403) );
2641 }
2642
2643
2644 /**
2645  * Kill WordPress execution and display HTML message with error message.
2646  *
2647  * This function complements the die() PHP function. The difference is that
2648  * HTML will be displayed to the user. It is recommended to use this function
2649  * only, when the execution should not continue any further. It is not
2650  * recommended to call this function very often and try to handle as many errors
2651  * as possible siliently.
2652  *
2653  * @since 2.0.4
2654  *
2655  * @param string $message Error message.
2656  * @param string $title Error title.
2657  * @param string|array $args Optional arguements to control behaviour.
2658  */
2659 function wp_die( $message, $title = '', $args = array() ) {
2660         if ( function_exists( 'apply_filters' ) ) {
2661                 $function = apply_filters( 'wp_die_handler', '_default_wp_die_handler');
2662         }else {
2663                 $function = '_default_wp_die_handler';
2664         }
2665
2666         call_user_func( $function, $message, $title, $args );
2667 }
2668
2669 /**
2670  * Kill WordPress execution and display HTML message with error message.
2671  *
2672  * This is the default handler for wp_die if you want a custom one for your
2673  * site then you can overload using the wp_die_handler filter in wp_die
2674  *
2675  * @since 3.0.0
2676  * @access private
2677  *
2678  * @param string $message Error message.
2679  * @param string $title Error title.
2680  * @param string|array $args Optional arguements to control behaviour.
2681  */
2682 function _default_wp_die_handler( $message, $title = '', $args = array() ) {
2683         $defaults = array( 'response' => 500 );
2684         $r = wp_parse_args($args, $defaults);
2685
2686         $have_gettext = function_exists('__');
2687
2688         if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
2689                 if ( empty( $title ) ) {
2690                         $error_data = $message->get_error_data();
2691                         if ( is_array( $error_data ) && isset( $error_data['title'] ) )
2692                                 $title = $error_data['title'];
2693                 }
2694                 $errors = $message->get_error_messages();
2695                 switch ( count( $errors ) ) :
2696                 case 0 :
2697                         $message = '';
2698                         break;
2699                 case 1 :
2700                         $message = "<p>{$errors[0]}</p>";
2701                         break;
2702                 default :
2703                         $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>";
2704                         break;
2705                 endswitch;
2706         } elseif ( is_string( $message ) ) {
2707                 $message = "<p>$message</p>";
2708         }
2709
2710         if ( isset( $r['back_link'] ) && $r['back_link'] ) {
2711                 $back_text = $have_gettext? __('&laquo; Back') : '&laquo; Back';
2712                 $message .= "\n<p><a href='javascript:history.back()'>$back_text</p>";
2713         }
2714
2715         if ( defined( 'WP_SITEURL' ) && '' != WP_SITEURL )
2716                 $admin_dir = WP_SITEURL . '/wp-admin/';
2717         elseif ( function_exists( 'get_bloginfo' ) && '' != get_bloginfo( 'wpurl' ) )
2718                 $admin_dir = get_bloginfo( 'wpurl' ) . '/wp-admin/';
2719         elseif ( strpos( $_SERVER['PHP_SELF'], 'wp-admin' ) !== false )
2720                 $admin_dir = '';
2721         else
2722                 $admin_dir = 'wp-admin/';
2723
2724         if ( !function_exists( 'did_action' ) || !did_action( 'admin_head' ) ) :
2725         if ( !headers_sent() ) {
2726                 status_header( $r['response'] );
2727                 nocache_headers();
2728                 header( 'Content-Type: text/html; charset=utf-8' );
2729         }
2730
2731         if ( empty($title) )
2732                 $title = $have_gettext ? __('WordPress &rsaquo; Error') : 'WordPress &rsaquo; Error';
2733
2734         $text_direction = 'ltr';
2735         if ( isset($r['text_direction']) && 'rtl' == $r['text_direction'] )
2736                 $text_direction = 'rtl';
2737         elseif ( function_exists( 'is_rtl' ) && is_rtl() )
2738                 $text_direction = 'rtl';
2739 ?>
2740 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2741 <!-- 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 -->
2742 <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) ) language_attributes(); ?>>
2743 <head>
2744         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2745         <title><?php echo $title ?></title>
2746         <link rel="stylesheet" href="<?php echo $admin_dir; ?>css/install.css" type="text/css" />
2747 <?php
2748 if ( 'rtl' == $text_direction ) : ?>
2749         <link rel="stylesheet" href="<?php echo $admin_dir; ?>css/install-rtl.css" type="text/css" />
2750 <?php endif; ?>
2751 </head>
2752 <body id="error-page">
2753 <?php endif; ?>
2754         <?php echo $message; ?>
2755 </body>
2756 </html>
2757 <?php
2758         die();
2759 }
2760
2761 /**
2762  * Retrieve the WordPress home page URL.
2763  *
2764  * If the constant named 'WP_HOME' exists, then it willl be used and returned by
2765  * the function. This can be used to counter the redirection on your local
2766  * development environment.
2767  *
2768  * @access private
2769  * @package WordPress
2770  * @since 2.2.0
2771  *
2772  * @param string $url URL for the home location
2773  * @return string Homepage location.
2774  */
2775 function _config_wp_home( $url = '' ) {
2776         if ( defined( 'WP_HOME' ) )
2777                 return WP_HOME;
2778         return $url;
2779 }
2780
2781 /**
2782  * Retrieve the WordPress site URL.
2783  *
2784  * If the constant named 'WP_SITEURL' is defined, then the value in that
2785  * constant will always be returned. This can be used for debugging a site on
2786  * your localhost while not having to change the database to your URL.
2787  *
2788  * @access private
2789  * @package WordPress
2790  * @since 2.2.0
2791  *
2792  * @param string $url URL to set the WordPress site location.
2793  * @return string The WordPress Site URL
2794  */
2795 function _config_wp_siteurl( $url = '' ) {
2796         if ( defined( 'WP_SITEURL' ) )
2797                 return WP_SITEURL;
2798         return $url;
2799 }
2800
2801 /**
2802  * Set the localized direction for MCE plugin.
2803  *
2804  * Will only set the direction to 'rtl', if the WordPress locale has the text
2805  * direction set to 'rtl'.
2806  *
2807  * Fills in the 'directionality', 'plugins', and 'theme_advanced_button1' array
2808  * keys. These keys are then returned in the $input array.
2809  *
2810  * @access private
2811  * @package WordPress
2812  * @subpackage MCE
2813  * @since 2.1.0
2814  *
2815  * @param array $input MCE plugin array.
2816  * @return array Direction set for 'rtl', if needed by locale.
2817  */
2818 function _mce_set_direction( $input ) {
2819         if ( is_rtl() ) {
2820                 $input['directionality'] = 'rtl';
2821                 $input['plugins'] .= ',directionality';
2822                 $input['theme_advanced_buttons1'] .= ',ltr';
2823         }
2824
2825         return $input;
2826 }
2827
2828
2829 /**
2830  * Convert smiley code to the icon graphic file equivalent.
2831  *
2832  * You can turn off smilies, by going to the write setting screen and unchecking
2833  * the box, or by setting 'use_smilies' option to false or removing the option.
2834  *
2835  * Plugins may override the default smiley list by setting the $wpsmiliestrans
2836  * to an array, with the key the code the blogger types in and the value the
2837  * image file.
2838  *
2839  * The $wp_smiliessearch global is for the regular expression and is set each
2840  * time the function is called.
2841  *
2842  * The full list of smilies can be found in the function and won't be listed in
2843  * the description. Probably should create a Codex page for it, so that it is
2844  * available.
2845  *
2846  * @global array $wpsmiliestrans
2847  * @global array $wp_smiliessearch
2848  * @since 2.2.0
2849  */
2850 function smilies_init() {
2851         global $wpsmiliestrans, $wp_smiliessearch;
2852
2853         // don't bother setting up smilies if they are disabled
2854         if ( !get_option( 'use_smilies' ) )
2855                 return;
2856
2857         if ( !isset( $wpsmiliestrans ) ) {
2858                 $wpsmiliestrans = array(
2859                 ':mrgreen:' => 'icon_mrgreen.gif',
2860                 ':neutral:' => 'icon_neutral.gif',
2861                 ':twisted:' => 'icon_twisted.gif',
2862                   ':arrow:' => 'icon_arrow.gif',
2863                   ':shock:' => 'icon_eek.gif',
2864                   ':smile:' => 'icon_smile.gif',
2865                     ':???:' => 'icon_confused.gif',
2866                    ':cool:' => 'icon_cool.gif',
2867                    ':evil:' => 'icon_evil.gif',
2868                    ':grin:' => 'icon_biggrin.gif',
2869                    ':idea:' => 'icon_idea.gif',
2870                    ':oops:' => 'icon_redface.gif',
2871                    ':razz:' => 'icon_razz.gif',
2872                    ':roll:' => 'icon_rolleyes.gif',
2873                    ':wink:' => 'icon_wink.gif',
2874                     ':cry:' => 'icon_cry.gif',
2875                     ':eek:' => 'icon_surprised.gif',
2876                     ':lol:' => 'icon_lol.gif',
2877                     ':mad:' => 'icon_mad.gif',
2878                     ':sad:' => 'icon_sad.gif',
2879                       '8-)' => 'icon_cool.gif',
2880                       '8-O' => 'icon_eek.gif',
2881                       ':-(' => 'icon_sad.gif',
2882                       ':-)' => 'icon_smile.gif',
2883                       ':-?' => 'icon_confused.gif',
2884                       ':-D' => 'icon_biggrin.gif',
2885                       ':-P' => 'icon_razz.gif',
2886                       ':-o' => 'icon_surprised.gif',
2887                       ':-x' => 'icon_mad.gif',
2888                       ':-|' => 'icon_neutral.gif',
2889                       ';-)' => 'icon_wink.gif',
2890                        '8)' => 'icon_cool.gif',
2891                        '8O' => 'icon_eek.gif',
2892                        ':(' => 'icon_sad.gif',
2893                        ':)' => 'icon_smile.gif',
2894                        ':?' => 'icon_confused.gif',
2895                        ':D' => 'icon_biggrin.gif',
2896                        ':P' => 'icon_razz.gif',
2897                        ':o' => 'icon_surprised.gif',
2898                        ':x' => 'icon_mad.gif',
2899                        ':|' => 'icon_neutral.gif',
2900                        ';)' => 'icon_wink.gif',
2901                       ':!:' => 'icon_exclaim.gif',
2902                       ':?:' => 'icon_question.gif',
2903                 );
2904         }
2905
2906         if (count($wpsmiliestrans) == 0) {
2907                 return;
2908         }
2909
2910         /*
2911          * NOTE: we sort the smilies in reverse key order. This is to make sure
2912          * we match the longest possible smilie (:???: vs :?) as the regular
2913          * expression used below is first-match
2914          */
2915         krsort($wpsmiliestrans);
2916
2917         $wp_smiliessearch = '/(?:\s|^)';
2918
2919         $subchar = '';
2920         foreach ( (array) $wpsmiliestrans as $smiley => $img ) {
2921                 $firstchar = substr($smiley, 0, 1);
2922                 $rest = substr($smiley, 1);
2923
2924                 // new subpattern?
2925                 if ($firstchar != $subchar) {
2926                         if ($subchar != '') {
2927                                 $wp_smiliessearch .= ')|(?:\s|^)';
2928                         }
2929                         $subchar = $firstchar;
2930                         $wp_smiliessearch .= preg_quote($firstchar, '/') . '(?:';
2931                 } else {
2932                         $wp_smiliessearch .= '|';
2933                 }
2934                 $wp_smiliessearch .= preg_quote($rest, '/');
2935         }
2936
2937         $wp_smiliessearch .= ')(?:\s|$)/m';
2938 }
2939
2940 /**
2941  * Merge user defined arguments into defaults array.
2942  *
2943  * This function is used throughout WordPress to allow for both string or array
2944  * to be merged into another array.
2945  *
2946  * @since 2.2.0
2947  *
2948  * @param string|array $args Value to merge with $defaults
2949  * @param array $defaults Array that serves as the defaults.
2950  * @return array Merged user defined values with defaults.
2951  */
2952 function wp_parse_args( $args, $defaults = '' ) {
2953         if ( is_object( $args ) )
2954                 $r = get_object_vars( $args );
2955         elseif ( is_array( $args ) )
2956                 $r =& $args;
2957         else
2958                 wp_parse_str( $args, $r );
2959
2960         if ( is_array( $defaults ) )
2961                 return array_merge( $defaults, $r );
2962         return $r;
2963 }
2964
2965 /**
2966  * Clean up an array, comma- or space-separated list of IDs
2967  *
2968  * @since 3.0.0
2969  *
2970  * @param array|string $list
2971  * @return array Sanitized array of IDs
2972  */
2973 function wp_parse_id_list( $list ) {
2974         if ( !is_array($list) )
2975                 $list = preg_split('/[\s,]+/', $list);
2976
2977         return array_unique(array_map('absint', $list));
2978 }
2979
2980 /**
2981  * Filters a list of objects, based on a set of key => value arguments
2982  *
2983  * @since 3.0.0
2984  *
2985  * @param array $list An array of objects to filter
2986  * @param array $args An array of key => value arguments to match against each object
2987  * @param string $operator The logical operation to perform. 'or' means only one element
2988  *      from the array needs to match; 'and' means all elements must match. The default is 'and'.
2989  * @param bool|string $field A field from the object to place instead of the entire object
2990  * @return array A list of objects or object fields
2991  */
2992 function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
2993         if ( !is_array($list) )
2994                 return array();
2995
2996         if ( empty($args) )
2997                 $args = array();
2998
2999         if ( empty($args) && !$field )
3000                 return $list;   // nothing to do
3001
3002         $count = count($args);
3003
3004         $filtered = array();
3005
3006         foreach ( $list as $key => $obj ) {
3007                 $matched = count(array_intersect_assoc(get_object_vars($obj), $args));
3008                 if ( ('and' == $operator && $matched == $count) || ('or' == $operator && $matched <= $count) ) {
3009                         if ( $field )
3010                                 $filtered[] = $obj->$field;
3011                         else
3012                                 $filtered[$key] = $obj;
3013                 }
3014         }
3015
3016         return $filtered;
3017 }
3018
3019 /**
3020  * Determines if default embed handlers should be loaded.
3021  *
3022  * Checks to make sure that the embeds library hasn't already been loaded. If
3023  * it hasn't, then it will load the embeds library.
3024  *
3025  * @since 2.9.0
3026  */
3027 function wp_maybe_load_embeds() {
3028         if ( ! apply_filters('load_default_embeds', true) )
3029                 return;
3030         require_once( ABSPATH . WPINC . '/default-embeds.php' );
3031 }
3032
3033 /**
3034  * Determines if Widgets library should be loaded.
3035  *
3036  * Checks to make sure that the widgets library hasn't already been loaded. If
3037  * it hasn't, then it will load the widgets library and run an action hook.
3038  *
3039  * @since 2.2.0
3040  * @uses add_action() Calls '_admin_menu' hook with 'wp_widgets_add_menu' value.
3041  */
3042 function wp_maybe_load_widgets() {
3043         if ( ! apply_filters('load_default_widgets', true) )
3044                 return;
3045         require_once( ABSPATH . WPINC . '/default-widgets.php' );
3046         add_action( '_admin_menu', 'wp_widgets_add_menu' );
3047 }
3048
3049 /**
3050  * Append the Widgets menu to the themes main menu.
3051  *
3052  * @since 2.2.0
3053  * @uses $submenu The administration submenu list.
3054  */
3055 function wp_widgets_add_menu() {
3056         global $submenu;
3057         $submenu['themes.php'][7] = array( __( 'Widgets' ), 'edit_theme_options', 'widgets.php' );
3058         ksort( $submenu['themes.php'], SORT_NUMERIC );
3059 }
3060
3061 /**
3062  * Flush all output buffers for PHP 5.2.
3063  *
3064  * Make sure all output buffers are flushed before our singletons our destroyed.
3065  *
3066  * @since 2.2.0
3067  */
3068 function wp_ob_end_flush_all() {
3069         $levels = ob_get_level();
3070         for ($i=0; $i<$levels; $i++)
3071                 ob_end_flush();
3072 }
3073
3074 /**
3075  * Load the correct database class file.
3076  *
3077  * This function is used to load the database class file either at runtime or by
3078  * wp-admin/setup-config.php We must globalise $wpdb to ensure that it is
3079  * defined globally by the inline code in wp-db.php.
3080  *
3081  * @since 2.5.0
3082  * @global $wpdb WordPress Database Object
3083  */
3084 function require_wp_db() {
3085         global $wpdb;
3086         if ( file_exists( WP_CONTENT_DIR . '/db.php' ) )
3087                 require_once( WP_CONTENT_DIR . '/db.php' );
3088         else
3089                 require_once( ABSPATH . WPINC . '/wp-db.php' );
3090 }
3091
3092 /**
3093  * Load custom DB error or display WordPress DB error.
3094  *
3095  * If a file exists in the wp-content directory named db-error.php, then it will
3096  * be loaded instead of displaying the WordPress DB error. If it is not found,
3097  * then the WordPress DB error will be displayed instead.
3098  *
3099  * The WordPress DB error sets the HTTP status header to 500 to try to prevent
3100  * search engines from caching the message. Custom DB messages should do the
3101  * same.
3102  *
3103  * This function was backported to the the WordPress 2.3.2, but originally was
3104  * added in WordPress 2.5.0.
3105  *
3106  * @since 2.3.2
3107  * @uses $wpdb
3108  */
3109 function dead_db() {
3110         global $wpdb;
3111
3112         // Load custom DB error template, if present.
3113         if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
3114                 require_once( WP_CONTENT_DIR . '/db-error.php' );
3115                 die();
3116         }
3117
3118         // If installing or in the admin, provide the verbose message.
3119         if ( defined('WP_INSTALLING') || defined('WP_ADMIN') )
3120                 wp_die($wpdb->error);
3121
3122         // Otherwise, be terse.
3123         status_header( 500 );
3124         nocache_headers();
3125         header( 'Content-Type: text/html; charset=utf-8' );
3126 ?>
3127 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3128 <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) ) language_attributes(); ?>>
3129 <head>
3130 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
3131         <title>Database Error</title>
3132
3133 </head>
3134 <body>
3135         <h1>Error establishing a database connection</h1>
3136 </body>
3137 </html>
3138 <?php
3139         die();
3140 }
3141
3142 /**
3143  * Converts value to nonnegative integer.
3144  *
3145  * @since 2.5.0
3146  *
3147  * @param mixed $maybeint Data you wish to have convered to an nonnegative integer
3148  * @return int An nonnegative integer
3149  */
3150 function absint( $maybeint ) {
3151         return abs( intval( $maybeint ) );
3152 }
3153
3154 /**
3155  * Determines if the blog can be accessed over SSL.
3156  *
3157  * Determines if blog can be accessed over SSL by using cURL to access the site
3158  * using the https in the siteurl. Requires cURL extension to work correctly.
3159  *
3160  * @since 2.5.0
3161  *
3162  * @param string $url
3163  * @return bool Whether SSL access is available
3164  */
3165 function url_is_accessable_via_ssl($url)
3166 {
3167         if (in_array('curl', get_loaded_extensions())) {
3168                 $ssl = preg_replace( '/^http:\/\//', 'https://',  $url );
3169
3170                 $ch = curl_init();
3171                 curl_setopt($ch, CURLOPT_URL, $ssl);
3172                 curl_setopt($ch, CURLOPT_FAILONERROR, true);
3173                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
3174                 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
3175                 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
3176
3177                 curl_exec($ch);
3178
3179                 $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
3180                 curl_close ($ch);
3181
3182                 if ($status == 200 || $status == 401) {
3183                         return true;
3184                 }
3185         }
3186         return false;
3187 }
3188
3189 /**
3190  * Secure URL, if available or the given URL.
3191  *
3192  * @since 2.5.0
3193  *
3194  * @param string $url Complete URL path with transport.
3195  * @return string Secure or regular URL path.
3196  */
3197 function atom_service_url_filter($url)
3198 {
3199         if ( url_is_accessable_via_ssl($url) )
3200                 return preg_replace( '/^http:\/\//', 'https://',  $url );
3201         else
3202                 return $url;
3203 }
3204
3205 /**
3206  * Marks a function as deprecated and informs when it has been used.
3207  *
3208  * There is a hook deprecated_function_run that will be called that can be used
3209  * to get the backtrace up to what file and function called the deprecated
3210  * function.
3211  *
3212  * The current behavior is to trigger an user error if WP_DEBUG is true.
3213  *
3214  * This function is to be used in every function in depreceated.php
3215  *
3216  * @package WordPress
3217  * @subpackage Debug
3218  * @since 2.5.0
3219  * @access private
3220  *
3221  * @uses do_action() Calls 'deprecated_function_run' and passes the function name, what to use instead,
3222  *   and the version the function was deprecated in.
3223  * @uses apply_filters() Calls 'deprecated_function_trigger_error' and expects boolean value of true to do
3224  *   trigger or false to not trigger error.
3225  *
3226  * @param string $function The function that was called
3227  * @param string $version The version of WordPress that deprecated the function
3228  * @param string $replacement Optional. The function that should have been called
3229  */
3230 function _deprecated_function( $function, $version, $replacement=null ) {
3231
3232         do_action( 'deprecated_function_run', $function, $replacement, $version );
3233
3234         // Allow plugin to filter the output error trigger
3235         if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
3236                 if ( ! is_null($replacement) )
3237                         trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) );
3238                 else
3239                         trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
3240         }
3241 }
3242
3243 /**
3244  * Marks a file as deprecated and informs when it has been used.
3245  *
3246  * There is a hook deprecated_file_included that will be called that can be used
3247  * to get the backtrace up to what file and function included the deprecated
3248  * file.
3249  *
3250  * The current behavior is to trigger an user error if WP_DEBUG is true.
3251  *
3252  * This function is to be used in every file that is depreceated
3253  *
3254  * @package WordPress
3255  * @subpackage Debug
3256  * @since 2.5.0
3257  * @access private
3258  *
3259  * @uses do_action() Calls 'deprecated_file_included' and passes the file name, what to use instead,
3260  *   the version in which the file was deprecated, and any message regarding the change.
3261  * @uses apply_filters() Calls 'deprecated_file_trigger_error' and expects boolean value of true to do
3262  *   trigger or false to not trigger error.
3263  *
3264  * @param string $file The file that was included
3265  * @param string $version The version of WordPress that deprecated the file
3266  * @param string $replacement Optional. The file that should have been included based on ABSPATH
3267  * @param string $message Optional. A message regarding the change
3268  */
3269 function _deprecated_file( $file, $version, $replacement = null, $message = '' ) {
3270
3271         do_action( 'deprecated_file_included', $file, $replacement, $version, $message );
3272
3273         // Allow plugin to filter the output error trigger
3274         if ( WP_DEBUG && apply_filters( 'deprecated_file_trigger_error', true ) ) {
3275                 $message = empty( $message ) ? '' : ' ' . $message;
3276                 if ( ! is_null( $replacement ) )
3277                         trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) . $message );
3278                 else
3279                         trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $file, $version ) . $message );
3280         }
3281 }
3282 /**
3283  * Marks a function argument as deprecated and informs when it has been used.
3284  *
3285  * This function is to be used whenever a deprecated function argument is used.
3286  * Before this function is called, the argument must be checked for whether it was
3287  * used by comparing it to its default value or evaluating whether it is empty.
3288  * For example:
3289  * <code>
3290  * if ( !empty($deprecated) )
3291  *      _deprecated_argument( __FUNCTION__, '3.0' );
3292  * </code>
3293  *
3294  * There is a hook deprecated_argument_run that will be called that can be used
3295  * to get the backtrace up to what file and function used the deprecated
3296  * argument.
3297  *
3298  * The current behavior is to trigger an user error if WP_DEBUG is true.
3299  *
3300  * @package WordPress
3301  * @subpackage Debug
3302  * @since 3.0.0
3303  * @access private
3304  *
3305  * @uses do_action() Calls 'deprecated_argument_run' and passes the function name, a message on the change,
3306  *   and the version in which the argument was deprecated.
3307  * @uses apply_filters() Calls 'deprecated_argument_trigger_error' and expects boolean value of true to do
3308  *   trigger or false to not trigger error.
3309  *
3310  * @param string $function The function that was called
3311  * @param string $version The version of WordPress that deprecated the argument used
3312  * @param string $message Optional. A message regarding the change.
3313  */
3314 function _deprecated_argument( $function, $version, $message = null ) {
3315
3316         do_action( 'deprecated_argument_run', $function, $message, $version );
3317
3318         // Allow plugin to filter the output error trigger
3319         if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) {
3320                 if ( ! is_null( $message ) )
3321                         trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s'), $function, $version, $message ) );
3322                 else
3323                         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 ) );
3324         }
3325 }
3326
3327 /**
3328  * Is the server running earlier than 1.5.0 version of lighttpd
3329  *
3330  * @since 2.5.0
3331  *
3332  * @return bool Whether the server is running lighttpd < 1.5.0
3333  */
3334 function is_lighttpd_before_150() {
3335         $server_parts = explode( '/', isset( $_SERVER['SERVER_SOFTWARE'] )? $_SERVER['SERVER_SOFTWARE'] : '' );
3336         $server_parts[1] = isset( $server_parts[1] )? $server_parts[1] : '';
3337         return  'lighttpd' == $server_parts[0] && -1 == version_compare( $server_parts[1], '1.5.0' );
3338 }
3339
3340 /**
3341  * Does the specified module exist in the apache config?
3342  *
3343  * @since 2.5.0
3344  *
3345  * @param string $mod e.g. mod_rewrite
3346  * @param bool $default The default return value if the module is not found
3347  * @return bool
3348  */
3349 function apache_mod_loaded($mod, $default = false) {
3350         global $is_apache;
3351
3352         if ( !$is_apache )
3353                 return false;
3354
3355         if ( function_exists('apache_get_modules') ) {
3356                 $mods = apache_get_modules();
3357                 if ( in_array($mod, $mods) )
3358                         return true;
3359         } elseif ( function_exists('phpinfo') ) {
3360                         ob_start();
3361                         phpinfo(8);
3362                         $phpinfo = ob_get_clean();
3363                         if ( false !== strpos($phpinfo, $mod) )
3364                                 return true;
3365         }
3366         return $default;
3367 }
3368
3369 /**
3370  * File validates against allowed set of defined rules.
3371  *
3372  * A return value of '1' means that the $file contains either '..' or './'. A
3373  * return value of '2' means that the $file contains ':' after the first
3374  * character. A return value of '3' means that the file is not in the allowed
3375  * files list.
3376  *
3377  * @since 1.2.0
3378  *
3379  * @param string $file File path.
3380  * @param array $allowed_files List of allowed files.
3381  * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
3382  */
3383 function validate_file( $file, $allowed_files = '' ) {
3384         if ( false !== strpos( $file, '..' ))
3385                 return 1;
3386
3387         if ( false !== strpos( $file, './' ))
3388                 return 1;
3389
3390         if (!empty ( $allowed_files ) && (!in_array( $file, $allowed_files ) ) )
3391                 return 3;
3392
3393         if (':' == substr( $file, 1, 1 ))
3394                 return 2;
3395
3396         return 0;
3397 }
3398
3399 /**
3400  * Determine if SSL is used.
3401  *
3402  * @since 2.6.0
3403  *
3404  * @return bool True if SSL, false if not used.
3405  */
3406 function is_ssl() {
3407         if ( isset($_SERVER['HTTPS']) ) {
3408                 if ( 'on' == strtolower($_SERVER['HTTPS']) )
3409                         return true;
3410                 if ( '1' == $_SERVER['HTTPS'] )
3411                         return true;
3412         } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
3413                 return true;
3414         }
3415         return false;
3416 }
3417
3418 /**
3419  * Whether SSL login should be forced.
3420  *
3421  * @since 2.6.0
3422  *
3423  * @param string|bool $force Optional.
3424  * @return bool True if forced, false if not forced.
3425  */
3426 function force_ssl_login( $force = null ) {
3427         static $forced = false;
3428
3429         if ( !is_null( $force ) ) {
3430                 $old_forced = $forced;
3431                 $forced = $force;
3432                 return $old_forced;
3433         }
3434
3435         return $forced;
3436 }
3437
3438 /**
3439  * Whether to force SSL used for the Administration Panels.
3440  *
3441  * @since 2.6.0
3442  *
3443  * @param string|bool $force
3444  * @return bool True if forced, false if not forced.
3445  */
3446 function force_ssl_admin( $force = null ) {
3447         static $forced = false;
3448
3449         if ( !is_null( $force ) ) {
3450                 $old_forced = $forced;
3451                 $forced = $force;
3452                 return $old_forced;
3453         }
3454
3455         return $forced;
3456 }
3457
3458 /**
3459  * Guess the URL for the site.
3460  *
3461  * Will remove wp-admin links to retrieve only return URLs not in the wp-admin
3462  * directory.
3463  *
3464  * @since 2.6.0
3465  *
3466  * @return string
3467  */
3468 function wp_guess_url() {
3469         if ( defined('WP_SITEURL') && '' != WP_SITEURL ) {
3470                 $url = WP_SITEURL;
3471         } else {
3472                 $schema = is_ssl() ? 'https://' : 'http://';
3473                 $url = preg_replace('|/wp-admin/.*|i', '', $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
3474         }
3475         return $url;
3476 }
3477
3478 /**
3479  * Suspend cache invalidation.
3480  *
3481  * Turns cache invalidation on and off.  Useful during imports where you don't wont to do invalidations
3482  * every time a post is inserted.  Callers must be sure that what they are doing won't lead to an inconsistent
3483  * cache when invalidation is suspended.
3484  *
3485  * @since 2.7.0
3486  *
3487  * @param bool $suspend Whether to suspend or enable cache invalidation
3488  * @return bool The current suspend setting
3489  */
3490 function wp_suspend_cache_invalidation($suspend = true) {
3491         global $_wp_suspend_cache_invalidation;
3492
3493         $current_suspend = $_wp_suspend_cache_invalidation;
3494         $_wp_suspend_cache_invalidation = $suspend;
3495         return $current_suspend;
3496 }
3497
3498 /**
3499  * Retrieve site option value based on name of option.
3500  *
3501  * @see get_option()
3502  * @package WordPress
3503  * @subpackage Option
3504  * @since 2.8.0
3505  *
3506  * @uses apply_filters() Calls 'pre_site_option_$option' before checking the option.
3507  *      Any value other than false will "short-circuit" the retrieval of the option
3508  *      and return the returned value.
3509  * @uses apply_filters() Calls 'site_option_$option', after checking the  option, with
3510  *      the option value.
3511  *
3512  * @param string $option Name of option to retrieve. Expected to not be SQL-escaped.
3513  * @param mixed $default Optional value to return if option doesn't exist. Default false.
3514  * @param bool $use_cache Whether to use cache. Multisite only. Default true.
3515  * @return mixed Value set for the option.
3516  */
3517 function get_site_option( $option, $default = false, $use_cache = true ) {
3518         global $wpdb;
3519
3520         // Allow plugins to short-circuit site options.
3521         $pre = apply_filters( 'pre_site_option_' . $option, false );
3522         if ( false !== $pre )
3523                 return $pre;
3524
3525         if ( !is_multisite() ) {
3526                 $value = get_option($option, $default);
3527         } else {
3528                 $cache_key = "{$wpdb->siteid}:$option";
3529                 if ( $use_cache )
3530                         $value = wp_cache_get($cache_key, 'site-options');
3531
3532                 if ( !isset($value) || (false === $value) ) {
3533                         $row = $wpdb->get_row( $wpdb->prepare("SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) );
3534
3535                         // Has to be get_row instead of get_var because of funkiness with 0, false, null values
3536                         if ( is_object( $row ) )
3537                                 $value = $row->meta_value;
3538                         else
3539                                 $value = $default;
3540
3541                         $value = maybe_unserialize( $value );
3542
3543                         wp_cache_set( $cache_key, $value, 'site-options' );
3544                 }
3545         }
3546
3547         return apply_filters( 'site_option_' . $option, $value );
3548 }
3549
3550 /**
3551  * Add a new site option.
3552  *
3553  * @see add_option()
3554  * @package WordPress
3555  * @subpackage Option
3556  * @since 2.8.0
3557  *
3558  * @uses apply_filters() Calls 'pre_add_site_option_$option' hook to allow overwriting the
3559  *      option value to be stored.
3560  * @uses do_action() Calls 'add_site_option_$option' and 'add_site_option' hooks on success.
3561  *
3562  * @param string $option Name of option to add. Expected to not be SQL-escaped.
3563  * @param mixed $value Optional. Option value, can be anything. Expected to not be SQL-escaped.
3564  * @return bool False if option was not added and true if option was added.
3565  */
3566 function add_site_option( $option, $value ) {
3567         global $wpdb;
3568
3569         $value = apply_filters( 'pre_add_site_option_' . $option, $value );
3570
3571         if ( !is_multisite() ) {
3572                 $result = add_option( $option, $value );
3573         } else {
3574                 $cache_key = "{$wpdb->siteid}:$option";
3575
3576                 if ( $wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) ) )
3577                         return update_site_option( $option, $value );
3578
3579                 $value = sanitize_option( $option, $value );
3580                 wp_cache_set( $cache_key, $value, 'site-options' );
3581
3582                 $_value = $value;
3583                 $value = maybe_serialize($value);
3584                 $result = $wpdb->insert( $wpdb->sitemeta, array('site_id' => $wpdb->siteid, 'meta_key' => $option, 'meta_value' => $value ) );
3585                 $value = $_value;
3586         }
3587
3588         do_action( "add_site_option_{$option}", $option, $value );
3589         do_action( "add_site_option", $option, $value );
3590
3591         return $result;
3592 }
3593
3594 /**
3595  * Removes site option by name.
3596  *
3597  * @see delete_option()
3598  * @package WordPress
3599  * @subpackage Option
3600  * @since 2.8.0
3601  *
3602  * @uses do_action() Calls 'pre_delete_site_option_$option' hook before option is deleted.
3603  * @uses do_action() Calls 'delete_site_option' and 'delete_site_option_$option'
3604  *      hooks on success.
3605  *
3606  * @param string $option Name of option to remove. Expected to not be SQL-escaped.
3607  * @return bool True, if succeed. False, if failure.
3608  */
3609 function delete_site_option( $option ) {
3610         global $wpdb;
3611
3612         // ms_protect_special_option( $option ); @todo
3613
3614         do_action( 'pre_delete_site_option_' . $option );
3615
3616         if ( !is_multisite() ) {
3617                 $result = delete_option( $option );
3618         } else {
3619                 $row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM {$wpdb->sitemeta} WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) );
3620                 if ( is_null( $row ) || !$row->meta_id )
3621                         return false;
3622                 $cache_key = "{$wpdb->siteid}:$option";
3623                 wp_cache_delete( $cache_key, 'site-options' );
3624
3625                 $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->sitemeta} WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) );
3626         }
3627
3628         if ( $result ) {
3629                 do_action( "delete_site_option_{$option}", $option );
3630                 do_action( "delete_site_option", $option );
3631                 return true;
3632         }
3633         return false;
3634 }
3635
3636 /**
3637  * Update the value of a site option that was already added.
3638  *
3639  * @see update_option()
3640  * @since 2.8.0
3641  * @package WordPress
3642  * @subpackage Option
3643  *
3644  * @uses apply_filters() Calls 'pre_update_site_option_$option' hook to allow overwriting the
3645  *      option value to be stored.
3646  * @uses do_action() Calls 'update_site_option_$option' and 'update_site_option' hooks on success.
3647  *
3648  * @param string $option Name of option. Expected to not be SQL-escaped.
3649  * @param mixed $value Option value. Expected to not be SQL-escaped.
3650  * @return bool False if value was not updated and true if value was updated.
3651  */
3652 function update_site_option( $option, $value ) {
3653         global $wpdb;
3654
3655         $oldvalue = get_site_option( $option );
3656         $value = apply_filters( 'pre_update_site_option_' . $option, $value, $oldvalue );
3657
3658         if ( $value === $oldvalue )
3659                 return false;
3660
3661         if ( !is_multisite() ) {
3662                 $result = update_option( $option, $value );
3663         } else {
3664                 $cache_key = "{$wpdb->siteid}:$option";
3665
3666                 if ( $value && !$wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) ) )
3667                         return add_site_option( $option, $value );
3668                 $value = sanitize_option( $option, $value );
3669                 wp_cache_set( $cache_key, $value, 'site-options' );
3670
3671                 $_value = $value;
3672                 $value = maybe_serialize( $value );
3673                 $result = $wpdb->update( $wpdb->sitemeta, array( 'meta_value' => $value ), array( 'site_id' => $wpdb->siteid, 'meta_key' => $option ) );
3674                 $value = $_value;
3675         }
3676
3677         if ( $result ) {
3678                 do_action( "update_site_option_{$option}", $option, $value );
3679                 do_action( "update_site_option", $option, $value );
3680                 return true;
3681         }
3682         return false;
3683 }
3684
3685 /**
3686  * Delete a site transient
3687  *
3688  * @since 2.9.0
3689  * @package WordPress
3690  * @subpackage Transient
3691  *
3692  * @uses do_action() Calls 'delete_site_transient_$transient' hook before transient is deleted.
3693  * @uses do_action() Calls 'deleted_site_transient' hook on success.
3694  *
3695  * @param string $transient Transient name. Expected to not be SQL-escaped.
3696  * @return bool True if successful, false otherwise
3697  */
3698 function delete_site_transient( $transient ) {
3699         global $_wp_using_ext_object_cache;
3700
3701         do_action( 'delete_site_transient_' . $transient, $transient );
3702         if ( $_wp_using_ext_object_cache ) {
3703                 $result = wp_cache_delete( $transient, 'site-transient' );
3704         } else {
3705                 $option_timeout = '_site_transient_timeout_' . $transient;
3706                 $option = '_site_transient_' . $transient;
3707                 $result = delete_site_option( $option );
3708                 if ( $result )
3709                         delete_site_option( $option_timeout );
3710         }
3711         if ( $result )
3712                 do_action( 'deleted_site_transient', $transient );
3713         return $result;
3714 }
3715
3716 /**
3717  * Get the value of a site transient
3718  *
3719  * If the transient does not exist or does not have a value, then the return value
3720  * will be false.
3721  *
3722  * @see get_transient()
3723  * @since 2.9.0
3724  * @package WordPress
3725  * @subpackage Transient
3726  *
3727  * @uses apply_filters() Calls 'pre_site_transient_$transient' hook before checking the transient.
3728  *      Any value other than false will "short-circuit" the retrieval of the transient
3729  *      and return the returned value.
3730  * @uses apply_filters() Calls 'site_transient_$option' hook, after checking the transient, with
3731  *      the transient value.
3732  *
3733  * @param string $transient Transient name. Expected to not be SQL-escaped.
3734  * @return mixed Value of transient
3735  */
3736 function get_site_transient( $transient ) {
3737         global $_wp_using_ext_object_cache;
3738
3739         $pre = apply_filters( 'pre_site_transient_' . $transient, false );
3740         if ( false !== $pre )
3741                 return $pre;
3742
3743         if ( $_wp_using_ext_object_cache ) {
3744                 $value = wp_cache_get( $transient, 'site-transient' );
3745         } else {
3746                 // Core transients that do not have a timeout. Listed here so querying timeouts can be avoided.
3747                 $no_timeout = array('update_core', 'update_plugins', 'update_themes');
3748                 $transient_option = '_site_transient_' . $transient;
3749                 if ( ! in_array( $transient, $no_timeout ) ) {
3750                         $transient_timeout = '_site_transient_timeout_' . $transient;
3751                         $timeout = get_site_option( $transient_timeout );
3752                         if ( false !== $timeout && $timeout < time() ) {
3753                                 delete_site_option( $transient_option  );
3754                                 delete_site_option( $transient_timeout );
3755                                 return false;
3756                         }
3757                 }
3758
3759                 $value = get_site_option( $transient_option );
3760         }
3761
3762         return apply_filters( 'site_transient_' . $transient, $value );
3763 }
3764
3765 /**
3766  * Set/update the value of a site transient
3767  *
3768  * You do not need to serialize values, if the value needs to be serialize, then
3769  * it will be serialized before it is set.
3770  *
3771  * @see set_transient()
3772  * @since 2.9.0
3773  * @package WordPress
3774  * @subpackage Transient
3775  *
3776  * @uses apply_filters() Calls 'pre_set_site_transient_$transient' hook to allow overwriting the
3777  *      transient value to be stored.
3778  * @uses do_action() Calls 'set_site_transient_$transient' and 'setted_site_transient' hooks on success.
3779  *
3780  * @param string $transient Transient name. Expected to not be SQL-escaped.
3781  * @param mixed $value Transient value. Expected to not be SQL-escaped.
3782  * @param int $expiration Time until expiration in seconds, default 0
3783  * @return bool False if value was not set and true if value was set.
3784  */
3785 function set_site_transient( $transient, $value, $expiration = 0 ) {
3786         global $_wp_using_ext_object_cache;
3787
3788     $value = apply_filters( 'pre_set_site_transient_' . $transient, $value );
3789
3790         if ( $_wp_using_ext_object_cache ) {
3791                 $result = wp_cache_set( $transient, $value, 'site-transient', $expiration );
3792         } else {
3793                 $transient_timeout = '_site_transient_timeout_' . $transient;
3794                 $transient = '_site_transient_' . $transient;
3795                 if ( false === get_site_option( $transient ) ) {
3796                         if ( $expiration )
3797                                 add_site_option( $transient_timeout, time() + $expiration );
3798                         $result = add_site_option( $transient, $value );
3799                 } else {
3800                         if ( $expiration )
3801                                 update_site_option( $transient_timeout, time() + $expiration );
3802                         $result = update_site_option( $transient, $value );
3803                 }
3804         }
3805         if ( $result ) {
3806                 do_action( 'set_site_transient_' . $transient );
3807                 do_action( 'setted_site_transient', $transient );
3808  &n