Index: wp-rss.php =================================================================== --- wp-rss.php (.../2.1.3) (revision 5482) +++ wp-rss.php (.../2.2) (revision 5482) @@ -5,33 +5,6 @@ wp('feed=rss'); } -header('Content-type: text/xml; charset=' . get_option('blog_charset'), true); -$more = 1; +require (ABSPATH . WPINC . '/feed-rss.php'); -?> -'; ?> - - - - <?php bloginfo_rss('name') ?> - - - - http://backend.userland.com/rss092 - - - - - - <?php the_title_rss() ?> - - ]]> - - - - - - - - - +?> \ No newline at end of file Index: wp-login.php =================================================================== --- wp-login.php (.../2.1.3) (revision 5482) +++ wp-login.php (.../2.2) (revision 5482) @@ -46,7 +46,7 @@ -

+

ERROR: The e-mail field is empty.'); do_action('lostpassword_post'); - + if ( empty( $errors ) ) { $user_data = get_userdatabylogin(trim($_POST['user_login'])); // redefining user_login ensures we return the right case in the email @@ -145,7 +145,7 @@

-

+

@@ -153,9 +153,9 @@
  • -
  • +
  • -
  • +
  • @@ -194,8 +194,11 @@ die('

    ' . __('The e-mail could not be sent.') . "
    \n" . __('Possible reason: your host may have disabled the mail() function...') . '

    '); } else { // send a copy of password change notification to the admin - $message = sprintf(__('Password Lost and Changed for user: %s'), $user->user_login) . "\r\n"; - wp_mail(get_option('admin_email'), sprintf(__('[%s] Password Lost/Changed'), get_option('blogname')), $message); + // but check to see if it's the admin whose password we're changing, and skip this + if ($user->user_email != get_option('admin_email')) { + $message = sprintf(__('Password Lost and Changed for user: %s'), $user->user_login) . "\r\n"; + wp_mail(get_option('admin_email'), sprintf(__('[%s] Password Lost/Changed'), get_option('blogname')), $message); + } wp_redirect('wp-login.php?checkemail=newpass'); exit(); @@ -265,14 +268,14 @@

    -

    +

    @@ -325,7 +328,7 @@ $errors['expiredsession'] = __('Your session has expired.'); } } - + if ( $_POST && empty( $user_login ) ) $errors['user_login'] = __('ERROR: The username field is empty.'); if ( $_POST && empty( $user_pass ) ) @@ -353,7 +356,7 @@

    - +

    @@ -363,9 +366,9 @@
  • -
  • +
  • -
  • +
  • Index: wp-comments-post.php =================================================================== --- wp-comments-post.php (.../2.1.3) (revision 5482) +++ wp-comments-post.php (.../2.2) (revision 5482) @@ -1,4 +1,10 @@ wp-config.php file. I need this before we can get started. Need more help? We got it. You can create a wp-config.php file through a web interface, but this doesn't work for all server setups. The safest way is to manually create the file.", "WordPress › Error"); + require_once( dirname(__FILE__) . '/wp-includes/classes.php'); + require_once( dirname(__FILE__) . '/wp-includes/functions.php'); + require_once( dirname(__FILE__) . '/wp-includes/plugin.php'); + wp_die("There doesn't seem to be a wp-config.php file. I need this before we can get started. Need more help? We got it. You can create a wp-config.php file through a web interface, but this doesn't work for all server setups. The safest way is to manually create the file.", "WordPress › Error"); } $wp_did_header = true; Index: wp-rdf.php =================================================================== --- wp-rdf.php (.../2.1.3) (revision 5482) +++ wp-rdf.php (.../2.2) (revision 5482) @@ -5,53 +5,6 @@ wp('feed=rdf'); } -header('Content-type: application/rdf+xml; charset=' . get_option('blog_charset'), true); -$more = 1; +require (ABSPATH . WPINC . '/feed-rdf.php'); -?> -'; ?> - - -> -"> - <?php bloginfo_rss('name') ?> - - - - - hourly - 1 - 2000-01-01T12:00+00:00 - - - - - - - - - - - - <?php the_title_rss() ?> - - post_date_gmt, false); ?> - - - - - - - ]]> - - - - - +?> \ No newline at end of file Index: wp-includes/feed-rss2.php =================================================================== --- wp-includes/feed-rss2.php (.../2.1.3) (revision 0) +++ wp-includes/feed-rss2.php (.../2.2) (revision 5482) @@ -0,0 +1,50 @@ + +'; ?> + + + +> + + + <?php bloginfo_rss('name'); wp_title_rss(); ?> + + + + http://wordpress.org/?v= + + + + + <?php the_title_rss() ?> + + + + + + + + + ]]> + + ]]> + post_content ) > 0 ) : ?> + ]]> + + ]]> + + + + + + + + + Property changes on: wp-includes/feed-rss2.php ___________________________________________________________________ Name: svn:eol-style + native Index: wp-includes/default-filters.php =================================================================== --- wp-includes/default-filters.php (.../2.1.3) (revision 5482) +++ wp-includes/default-filters.php (.../2.2) (revision 5482) @@ -45,7 +45,7 @@ add_filter('comment_url', 'clean_url'); add_filter('comment_text', 'convert_chars'); -add_filter('comment_text', 'make_clickable'); +add_filter('comment_text', 'make_clickable', 9); add_filter('comment_text', 'force_balance_tags', 25); add_filter('comment_text', 'wpautop', 30); add_filter('comment_text', 'convert_smilies', 20); @@ -145,6 +145,8 @@ // Misc filters add_filter('option_ping_sites', 'privacy_ping_filter'); add_filter('option_blog_charset', 'wp_specialchars'); +add_filter('option_home', '_config_wp_home'); +add_filter('option_siteurl', '_config_wp_siteurl'); add_filter('mce_plugins', '_mce_load_rtl_plugin'); add_filter('mce_buttons', '_mce_add_direction_buttons'); @@ -170,4 +172,8 @@ add_action('sanitize_comment_cookies', 'sanitize_comment_cookies'); add_action('admin_print_scripts', 'wp_print_scripts', 20); add_action('mce_options', '_mce_set_direction'); -?> +add_action('init', 'smilies_init', 5); +add_action( 'plugins_loaded', 'wp_maybe_load_widgets', 0 ); +add_action( 'shutdown', 'wp_ob_end_flush_all', 1); + +?> \ No newline at end of file Index: wp-includes/plugin.php =================================================================== --- wp-includes/plugin.php (.../2.1.3) (revision 5482) +++ wp-includes/plugin.php (.../2.2) (revision 5482) @@ -1,99 +1,146 @@ $function_to_add to. + * @param callback $function_to_add The name of the function to be called when the filter is applied. + * @param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action. + * @param int $accepted_args optional. The number of arguments the function accept (default 1). In WordPress 1.5.1+, hooked functions can take extra arguments that are set when the matching do_action() or apply_filters() call is run. + * @return boolean true if the $function_to_add is added succesfully to filter $tag. How many arguments your function takes. In WordPress 1.5.1+, hooked functions can take extra arguments that are set when the matching do_action() or apply_filters() call is run. For example, the action comment_id_not_found will pass any functions that hook onto it the ID of the requested comment. + */ function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) { - global $wp_filter; + global $wp_filter, $merged_filters; - // check that we don't already have the same filter at the same priority - if ( isset($wp_filter[$tag]["$priority"]) ) { - foreach ( $wp_filter[$tag]["$priority"] as $filter ) { - // uncomment if we want to match function AND accepted_args - // if ( $filter == array($function, $accepted_args) ) { - if ( $filter['function'] == $function_to_add ) - return true; - } - } - - // So the format is wp_filter['tag']['array of priorities']['array of ['array (functions, accepted_args)]'] - $wp_filter[$tag]["$priority"][] = array('function'=>$function_to_add, 'accepted_args'=>$accepted_args); + // So the format is wp_filter['tag']['array of priorities']['array of functions serialized']['array of ['array (functions, accepted_args)]'] + $wp_filter[$tag][$priority][serialize($function_to_add)] = array('function' => $function_to_add, 'accepted_args' => $accepted_args); + unset( $merged_filters[ $tag ] ); return true; } +/** + * Call the functions added to a filter hook. + * + * The callback functions attached to filter hook $tag are invoked by + * calling this function. This function can be used to create a new filter hook + * by simply calling this function with the name of the new hook specified using + * the $tag parameter. + * @uses merge_filters Merges the filter hooks using this function. + * @param string $tag The name of the filter hook. + * @param string $string The text on which the filters hooked to $tag are applied on. + * @param mixed $var,... Additional variables passed to the functions hooked to $tag. + * @return string The text in $string after all hooked functions are applied to it. + */ function apply_filters($tag, $string) { - global $wp_filter; + global $wp_filter, $merged_filters; - $args = array(); - for ( $a = 2; $a < func_num_args(); $a++ ) - $args[] = func_get_arg($a); + if ( !isset( $merged_filters[ $tag ] ) ) + merge_filters($tag); - merge_filters($tag); - if ( !isset($wp_filter[$tag]) ) return $string; - foreach ( (array) $wp_filter[$tag] as $priority => $functions ) { - if ( !is_null($functions) ) { - foreach ( (array) $functions as $function ) { - $function_name = $function['function']; - $accepted_args = $function['accepted_args']; - $the_args = $args; - array_unshift($the_args, $string); - if ( $accepted_args > 0 ) - $the_args = array_slice($the_args, 0, $accepted_args); - elseif ( 0 == $accepted_args ) - $the_args = NULL; - $string = call_user_func_array($function_name, $the_args); + reset( $wp_filter[ $tag ] ); + + $args = func_get_args(); + + do{ + foreach( (array) current($wp_filter[$tag]) as $the_ ) + if ( !is_null($the_['function']) ){ + $args[1] = $string; + $string = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args'])); } - } - } + + } while ( next($wp_filter[$tag]) ); + return $string; } +/** + * Merge the filter functions of a specific filter hook with generic filter functions. + * + * It is possible to defined generic filter functions using the filter hook + * all. These functions are called for every filter tag. This function + * merges the functions attached to the all hook with the functions + * of a specific hoook defined by $tag. + * @param string $tag The filter hook of which the functions should be merged. + */ function merge_filters($tag) { - global $wp_filter; - if ( isset($wp_filter['all']) ) { - foreach ( (array) $wp_filter['all'] as $priority => $functions ) { - if ( isset($wp_filter[$tag][$priority]) ) - $wp_filter[$tag][$priority] = array_merge($wp_filter['all'][$priority], $wp_filter[$tag][$priority]); - else - $wp_filter[$tag][$priority] = array_merge($wp_filter['all'][$priority], array()); - $wp_filter[$tag][$priority] = array_unique($wp_filter[$tag][$priority]); - } + global $wp_filter, $merged_filters; + + if ( isset($wp_filter['all']) && is_array($wp_filter['all']) ) + $wp_filter[$tag] = array_merge($wp_filter['all'], (array) $wp_filter[$tag]); + + if ( isset($wp_filter[$tag]) ){ + reset($wp_filter[$tag]); + uksort($wp_filter[$tag], "strnatcasecmp"); } - - if ( isset($wp_filter[$tag]) ) - uksort( $wp_filter[$tag], "strnatcasecmp" ); + $merged_filters[ $tag ] = true; } +/** + * Removes a function from a specified filter hook. + * + * This function removes a function attached to a specified filter hook. This + * method can be used to remove default functions attached to a specific filter + * hook and possibly replace them with a substitute. + * @param string $tag The filter hook to which the function to be removed is hooked. + * @param callback $function_to_remove The name of the function which should be removed. + * @param int $priority optional. The priority of the function (default: 10). + * @param int $accepted_args optional. The number of arguments the function accpets (default: 1). + * @return boolean Whether the function is removed. + */ function remove_filter($tag, $function_to_remove, $priority = 10, $accepted_args = 1) { - global $wp_filter; + global $wp_filter, $merged_filters; - // rebuild the list of filters - if ( isset($wp_filter[$tag]["$priority"]) ) { - $new_function_list = array(); - foreach ( (array) $wp_filter[$tag]["$priority"] as $filter ) { - if ( $filter['function'] != $function_to_remove ) - $new_function_list[] = $filter; - } - $wp_filter[$tag]["$priority"] = $new_function_list; - } + unset($GLOBALS['wp_filter'][$tag][$priority][serialize($function_to_remove)]); + unset( $merged_filters[ $tag ] ); + return true; } -// -// Action functions -// - +/** + * Hooks a function on to a specific action. + * + * Actions are the hooks that the WordPress core launches at specific points + * during execution, or when specific events occur. Plugins can specify that + * one or more of its PHP functions are executed at these points, using the + * Action API. + * + * @param string $tag The name of the action to which the $function_to-add is hooked. + * @param callback $function_to_add The name of the function you wish to be called. Note: any of the syntaxes explained in the PHP documentation for the 'callback' type (http://us2.php.net/manual/en/language.pseudo-types.php#language.types.callback) are valid. + * @param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action. + * @param int $accepted_args optional. The number of arguments the function accept (default 1). In WordPress 1.5.1+, hooked functions can take extra arguments that are set when the matching do_action() or apply_filters() call is run. + * @return boolean Always true. + */ function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) { add_filter($tag, $function_to_add, $priority, $accepted_args); } +/** + * Execute functions hooked on a specific action hook. + * + * This function invokes all functions attached to action hook $tag. + * It is possible to create new action hooks by simply calling this function, + * specifying the name of the new hook using the $tag parameter. + * @uses merge_filters + * @param string $tag The name of the action to be executed. + * @param mixed $arg,... Optional additional arguments which are passed on to the functions hooked to the action. + */ function do_action($tag, $arg = '') { global $wp_filter, $wp_actions; + if ( is_array($wp_actions) ) + $wp_actions[] = $tag; + else + $wp_actions = array($tag); + $args = array(); if ( is_array($arg) && 1 == count($arg) && is_object($arg[0]) ) // array(&$this) $args[] =& $arg[0]; @@ -107,37 +154,37 @@ if ( !isset($wp_filter[$tag]) ) return; - foreach ( (array) $wp_filter[$tag] as $priority => $functions ) { - if ( !is_null($functions) ) { - foreach ( (array) $functions as $function ) { - $function_name = $function['function']; - $accepted_args = $function['accepted_args']; + do{ + foreach( (array) current($wp_filter[$tag]) as $the_ ) + if ( !is_null($the_['function']) ) + call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); - if ( $accepted_args > 0 ) - $the_args = array_slice($args, 0, $accepted_args); - elseif ( $accepted_args == 0 ) - $the_args = NULL; - else - $the_args = $args; + } while ( next($wp_filter[$tag]) ); - call_user_func_array($function_name, $the_args); - } - } - } - - if ( is_array($wp_actions) ) - $wp_actions[] = $tag; - else - $wp_actions = array($tag); } -// Returns the number of times an action has been done +/** + * Return the number times an action is fired. + * @param string $tag The name of the action hook. + * @return int The number of times action hook $tag is fired + */ function did_action($tag) { global $wp_actions; + if ( empty($wp_actions) ) + return 0; + return count(array_keys($wp_actions, $tag)); } +/** + * Execute functions hooked on a specific action hook, specifying arguments in a array. + * + * This function is identical to {@link do_action}, but the argumetns passe to + * the functions hooked to $tag are supplied using an array. + * @param string $tag The name of the action to be executed. + * @param array $args The arguments supplied to the functions hooked to $tag + */ function do_action_ref_array($tag, $args) { global $wp_filter, $wp_actions; @@ -151,24 +198,27 @@ if ( !isset($wp_filter[$tag]) ) return; - foreach ( (array) $wp_filter[$tag] as $priority => $functions ) { - if ( !is_null($functions) ) { - foreach ( (array) $functions as $function ) { - $function_name = $function['function']; - $accepted_args = $function['accepted_args']; - if ( $accepted_args > 0 ) - $the_args = array_slice($args, 0, $accepted_args); - elseif ( 0 == $accepted_args ) - $the_args = NULL; - else - $the_args = $args; + do{ + foreach( (array) current($wp_filter[$tag]) as $the_ ) + if ( !is_null($the_['function']) ) + call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); - call_user_func_array($function_name, $the_args); - } - } - } + } while ( next($wp_filter[$tag]) ); + } +/** + * Removes a function from a specified action hook. + * + * This function removes a function attached to a specified action hook. This + * method can be used to remove default functions attached to a specific filter + * hook and possibly replace them with a substitute. + * @param string $tag The action hook to which the function to be removed is hooked. + * @param callback $function_to_remove The name of the function which should be removed. + * @param int $priority optional The priority of the function (default: 10). + * @param int $accepted_args optional. The number of arguments the function accpets (default: 1). + * @return boolean Whether the function is removed. + */ function remove_action($tag, $function_to_remove, $priority = 10, $accepted_args = 1) { remove_filter($tag, $function_to_remove, $priority, $accepted_args); } @@ -177,17 +227,52 @@ // Functions for handling plugins. // +/** + * Gets the basename of a plugin. + * + * This method extract the name of a plugin from its filename. + * @param string $file The filename of plugin. + * @return string The name of a plugin. + */ function plugin_basename($file) { $file = preg_replace('|\\\\+|', '\\\\', $file); $file = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', $file); return $file; } +/** + * Hook a function on a plugin activation action hook. + * + * When a plugin is activated, the action 'activate_PLUGINNAME' hook is + * activated. In the name of this hook, PLUGINNAME is replaced with the name of + * the plugin, including the optional subdirectory. For example, when the plugin + * is located in wp-content/plugin/sampleplugin/sample.php, then the + * name of this hook will become 'activate_sampleplugin/sample.php'. + * When the plugin consists of only one file and is (as by default) located at + * wp-content/plugin/sample.php the name of this hook will be + * 'activate_sample.php'. + * @param string $file The filename of the plugin including the path. + * @param string $function the function hooked to the 'activate_PLUGIN' action. + */ function register_activation_hook($file, $function) { $file = plugin_basename($file); add_action('activate_' . $file, $function); } +/** + * Hook a function on a plugin deactivation action hook. + * + * When a plugin is deactivated, the action 'deactivate_PLUGINNAME' hook is + * deactivated. In the name of this hook, PLUGINNAME is replaced with the name of + * the plugin, including the optional subdirectory. For example, when the plugin + * is located in wp-content/plugin/sampleplugin/sample.php, then the + * name of this hook will become 'activate_sampleplugin/sample.php'. + * When the plugin consists of only one file and is (as by default) located at + * wp-content/plugin/sample.php the name of this hook will be + * 'activate_sample.php'. + * @param string $file The filename of the plugin including the path. + * @param string $function the function hooked to the 'activate_PLUGIN' action. + */ function register_deactivation_hook($file, $function) { $file = plugin_basename($file); add_action('deactivate_' . $file, $function); Index: wp-includes/post-template.php =================================================================== --- wp-includes/post-template.php (.../2.1.3) (revision 5482) +++ wp-includes/post-template.php (.../2.2) (revision 5482) @@ -80,7 +80,7 @@ $page = count($pages); // give them the highest numbered page that DOES exist $content = $pages[$page-1]; - if ( preg_match('//', $content, $matches) ) { + if ( preg_match('//', $content, $matches) ) { $content = explode($matches[0], $content, 2); if ( !empty($matches[1]) && !empty($more_link_text) ) $more_link_text = strip_tags(wp_kses_no_null(trim($matches[1]))); @@ -95,13 +95,13 @@ $output .= $teaser; if ( count($content) > 1 ) { if ( $more ) { - $output .= ''.$content[1]; + $output .= ''.$content[1]; } else { $output = balanceTags($output); if ( ! empty($more_link_text) ) $output .= ' $more_link_text"; } - + } if ( $preview ) // preview fix for javascript bug with foreign languages $output = preg_replace('/\%u([0-9A-F]{4,4})/e', "'&#'.base_convert('\\1',16,10).';'", $output); @@ -131,6 +131,8 @@ function wp_link_pages($args = '') { + global $post; + if ( is_array($args) ) $r = &$args; else @@ -155,10 +157,14 @@ $j = str_replace('%',"$i",$pagelink); $output .= ' '; if ( ($i != $page) || ((!$more) && ($page==1)) ) { - if ( '' == get_option('permalink_structure') ) - $output .= ''; - else - $output .= ''; + if ( 1 == $i ) { + $output .= ''; + } else { + if ( '' == get_option('permalink_structure') || 'draft' == $post->post_status ) + $output .= ''; + else + $output .= ''; + } } $output .= $j; if ( ($i != $page) || ((!$more) && ($page==1)) ) @@ -170,17 +176,25 @@ $output .= $before; $i = $page - 1; if ( $i && $more ) { - if ( '' == get_option('permalink_structure') ) - $output .= '' . $previouspagelink . ''; - else - $output .= ''.$previouspagelink.''; + if ( 1 == $i ) { + $output .= '' . $previouspagelink . ''; + } else { + if ( '' == get_option('permalink_structure') || 'draft' == $post->post_status ) + $output .= '' . $previouspagelink . ''; + else + $output .= '' . $previouspagelink . ''; + } } $i = $page + 1; if ( $i <= $numpages && $more ) { - if ( '' == get_option('permalink_structure') ) - $output .= ''.$nextpagelink.''; - else - $output .= '' . $nextpagelink . ''; + if ( 1 == $i ) { + $output .= '' . $nextpagelink . ''; + } else { + if ( '' == get_option('permalink_structure') || 'draft' == $post->post_status ) + $output .= '' . $nextpagelink . ''; + else + $output .= '' . $nextpagelink . ''; + } } $output .= $after; } @@ -221,7 +235,7 @@ continue; $values = array_map('trim', get_post_custom_values($key)); $value = implode($values,', '); - echo "
  • $value
  • \n"; + echo apply_filters('the_meta_key', "
  • $value
  • \n", $key, $value); } echo "\n"; } @@ -269,7 +283,7 @@ parse_str($args, $r); $defaults = array('depth' => 0, 'show_date' => '', 'date_format' => get_option('date_format'), - 'child_of' => 0, 'exclude' => '', 'title_li' => __('Pages'), 'echo' => 1, 'authors' => ''); + 'child_of' => 0, 'exclude' => '', 'title_li' => __('Pages'), 'echo' => 1, 'authors' => '', 'sort_column' => 'menu_order, post_title'); $r = array_merge($defaults, $r); $output = ''; @@ -333,7 +347,7 @@ $id = (int) $id; $_post = & get_post($id); - if ( ('attachment' != $_post->post_type) || !$url = wp_get_attachment_url() ) + if ( ('attachment' != $_post->post_type) || !$url = wp_get_attachment_url($_post->ID) ) return __('Missing Attachment'); $post_title = attribute_escape($_post->post_title); Index: wp-includes/locale.php =================================================================== --- wp-includes/locale.php (.../2.1.3) (revision 5482) +++ wp-includes/locale.php (.../2.2) (revision 5482) @@ -12,7 +12,7 @@ var $meridiem; - var $text_direction = ''; + var $text_direction = 'ltr'; var $locale_vars = array('text_direction'); function init() { Index: wp-includes/feed-atom.php =================================================================== --- wp-includes/feed-atom.php (.../2.1.3) (revision 0) +++ wp-includes/feed-atom.php (.../2.2) (revision 5482) @@ -0,0 +1,45 @@ + +'; ?> + + > + <?php bloginfo_rss('name'); wp_title_rss(); ?> + + + + WordPress + + + + + + + + + + + + + <![CDATA[<?php the_title_rss() ?>]]> + + + + + + ]]> + + ]]> + + + + + + \ No newline at end of file Property changes on: wp-includes/feed-atom.php ___________________________________________________________________ Name: svn:eol-style + native Index: wp-includes/cache.php =================================================================== --- wp-includes/cache.php (.../2.1.3) (revision 5482) +++ wp-includes/cache.php (.../2.2) (revision 5482) @@ -194,21 +194,8 @@ foreach ($dogs as $catt) $this->cache['category'][$catt->cat_ID] = $catt; } - } else - if ('options' == $group) { - $wpdb->hide_errors(); - if (!$options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'")) { - $options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options"); - } - $wpdb->show_errors(); + } - if ( ! $options ) - return; - - foreach ($options as $option) { - $this->cache['options'][$option->option_name] = $option->option_value; - } - } } function make_group_dir($group, $perms) { @@ -353,10 +340,9 @@ fputs($fd, $serial); fclose($fd); if (!@ rename($temp_file, $cache_file)) { - if (@ copy($temp_file, $cache_file)) - @ unlink($temp_file); - else + if (!@ copy($temp_file, $cache_file)) $errors++; + @ unlink($temp_file); } @ chmod($cache_file, $file_perms); } @@ -399,7 +385,7 @@ function WP_Object_Cache() { return $this->__construct(); } - + function __construct() { global $blog_id; @@ -442,7 +428,7 @@ function __destruct() { $this->save(); - return true; + return true; } } ?> Index: wp-includes/bookmark.php =================================================================== --- wp-includes/bookmark.php (.../2.1.3) (revision 5482) +++ wp-includes/bookmark.php (.../2.2) (revision 5482) @@ -73,7 +73,7 @@ } if (!empty($exclusions)) $exclusions .= ')'; - + if ( ! empty($category_name) ) { if ( $cat_id = $wpdb->get_var("SELECT cat_ID FROM $wpdb->categories WHERE cat_name='$category_name' LIMIT 1") ) $category = $cat_id; @@ -136,7 +136,7 @@ $results = $wpdb->get_results($query); $cache[ $key ] = $results; - wp_cache_set( 'get_bookmarks', $cache, 'bookmark' ); + wp_cache_add( 'get_bookmarks', $cache, 'bookmark' ); return apply_filters('get_bookmarks', $results, $r); } Index: wp-includes/query.php =================================================================== --- wp-includes/query.php (.../2.1.3) (revision 5482) +++ wp-includes/query.php (.../2.2) (revision 5482) @@ -10,6 +10,12 @@ return $wp_query->get($var); } +function set_query_var($var, $value) { + global $wp_query; + + return $wp_query->set($var, $value); +} + function &query_posts($query) { unset($GLOBALS['wp_query']); $GLOBALS['wp_query'] =& new WP_Query(); @@ -23,7 +29,7 @@ function is_admin () { global $wp_query; - return ( $wp_query->is_admin || strstr($_SERVER['REQUEST_URI'], 'wp-admin/') ); + return ($wp_query->is_admin || (strpos($_SERVER['REQUEST_URI'], 'wp-admin/') !== false)); } function is_archive () { @@ -194,7 +200,7 @@ function is_singular() { global $wp_query; - return $wp_query->is_singular; + return $wp_query->is_singular; } function is_time () { @@ -250,6 +256,20 @@ } /* + * Comments loop. + */ + +function have_comments() { + global $wp_query; + return $wp_query->have_comments(); +} + +function the_comment() { + global $wp_query; + return $wp_query->the_comment(); +} + +/* * WP_Query */ @@ -266,6 +286,11 @@ var $in_the_loop = false; var $post; + var $comments; + var $comment_count = 0; + var $current_comment = -1; + var $comment; + var $found_posts = 0; var $max_num_pages = 0; @@ -282,6 +307,7 @@ var $is_category = false; var $is_search = false; var $is_feed = false; + var $is_comment_feed = false; var $is_trackback = false; var $is_home = false; var $is_404 = false; @@ -305,6 +331,7 @@ $this->is_category = false; $this->is_search = false; $this->is_feed = false; + $this->is_comment_feed = false; $this->is_trackback = false; $this->is_home = false; $this->is_404 = false; @@ -333,7 +360,7 @@ function parse_query_vars() { $this->parse_query(''); } - + function fill_query_vars($array) { $keys = array( 'error' @@ -368,7 +395,7 @@ if ( !isset($array[$key])) $array[$key] = ''; } - + return $array; } @@ -377,15 +404,15 @@ if ( !empty($query) || !isset($this->query) ) { $this->init(); if ( is_array($query) ) - $qv = & $query; + $this->query_vars = $query; else - parse_str($query, $qv); + parse_str($query, $this->query_vars); $this->query = $query; - $this->query_vars = $qv; } - - $qv = $this->fill_query_vars($qv); - + + $this->query_vars = $this->fill_query_vars($this->query_vars); + $qv = &$this->query_vars; + if ( ! empty($qv['robots']) ) { $this->is_robots = true; return; @@ -399,8 +426,16 @@ return; } + $qv['p'] = (int) $qv['p']; + $qv['page_id'] = (int) $qv['page_id']; + $qv['year'] = (int) $qv['year']; + $qv['monthnum'] = (int) $qv['monthnum']; + $qv['day'] = (int) $qv['day']; + $qv['w'] = (int) $qv['w']; $qv['m'] = (int) $qv['m']; - $qv['p'] = (int) $qv['p']; + if ( '' != $qv['hour'] ) $qv['hour'] = (int) $qv['hour']; + if ( '' != $qv['minute'] ) $qv['minute'] = (int) $qv['minute']; + if ( '' != $qv['second'] ) $qv['second'] = (int) $qv['second']; // Compat. Map subpost to attachment. if ( '' != $qv['subpost'] ) @@ -408,62 +443,64 @@ if ( '' != $qv['subpost_id'] ) $qv['attachment_id'] = $qv['subpost_id']; - if ( ('' != $qv['attachment']) || (int) $qv['attachment_id'] ) { + $qv['attachment_id'] = (int) $qv['attachment_id']; + + if ( ('' != $qv['attachment']) || !empty($qv['attachment_id']) ) { $this->is_single = true; $this->is_attachment = true; - } elseif ('' != $qv['name']) { + } elseif ( '' != $qv['name'] ) { $this->is_single = true; } elseif ( $qv['p'] ) { $this->is_single = true; - } elseif (('' != $qv['hour']) && ('' != $qv['minute']) &&('' != $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day'])) { + } elseif ( ('' != $qv['hour']) && ('' != $qv['minute']) &&('' != $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day']) ) { // If year, month, day, hour, minute, and second are set, a single // post is being queried. $this->is_single = true; - } elseif ('' != $qv['static'] || '' != $qv['pagename'] || (int) $qv['page_id']) { + } elseif ( '' != $qv['static'] || '' != $qv['pagename'] || !empty($qv['page_id']) ) { $this->is_page = true; $this->is_single = false; - } elseif (!empty($qv['s'])) { + } elseif ( !empty($qv['s']) ) { $this->is_search = true; } else { // Look for archive queries. Dates, categories, authors. - if ( (int) $qv['second']) { + if ( '' != $qv['second'] ) { $this->is_time = true; $this->is_date = true; } - if ( (int) $qv['minute']) { + if ( '' != $qv['minute'] ) { $this->is_time = true; $this->is_date = true; } - if ( (int) $qv['hour']) { + if ( '' != $qv['hour'] ) { $this->is_time = true; $this->is_date = true; } - if ( (int) $qv['day']) { + if ( $qv['day'] ) { if (! $this->is_date) { $this->is_day = true; $this->is_date = true; } } - if ( (int) $qv['monthnum']) { + if ( $qv['monthnum'] ) { if (! $this->is_date) { $this->is_month = true; $this->is_date = true; } } - if ( (int) $qv['year']) { + if ( $qv['year'] ) { if (! $this->is_date) { $this->is_year = true; $this->is_date = true; } } - if ( (int) $qv['m']) { + if ( $qv['m'] ) { $this->is_date = true; if (strlen($qv['m']) > 9) { $this->is_time = true; @@ -480,70 +517,103 @@ $this->is_date = true; } - if (empty($qv['cat']) || ($qv['cat'] == '0')) { + if ( empty($qv['cat']) || ($qv['cat'] == '0') ) { $this->is_category = false; } else { - if (stristr($qv['cat'],'-')) { + if (strpos($qv['cat'], '-') !== false) { $this->is_category = false; } else { $this->is_category = true; } } - if ('' != $qv['category_name']) { + if ( '' != $qv['category_name'] ) { $this->is_category = true; } - if ((empty($qv['author'])) || ($qv['author'] == '0')) { + if ( empty($qv['author']) || ($qv['author'] == '0') ) { $this->is_author = false; } else { $this->is_author = true; } - if ('' != $qv['author_name']) { + if ( '' != $qv['author_name'] ) { $this->is_author = true; } - if ( ($this->is_date || $this->is_author || $this->is_category)) { + if ( ($this->is_date || $this->is_author || $this->is_category) ) $this->is_archive = true; - } } - if ('' != $qv['feed']) { + if ( '' != $qv['feed'] ) $this->is_feed = true; - } - if ('' != $qv['tb']) { + if ( '' != $qv['tb'] ) $this->is_trackback = true; - } - if ('' != $qv['paged']) { + if ( '' != $qv['paged'] ) $this->is_paged = true; - } - if ('' != $qv['comments_popup']) { + if ( '' != $qv['comments_popup'] ) $this->is_comments_popup = true; - } - //if we're previewing inside the write screen - if ('' != $qv['preview']) { + // if we're previewing inside the write screen + if ('' != $qv['preview']) $this->is_preview = true; - } - if (strstr($_SERVER['PHP_SELF'], 'wp-admin/')) { + if ( strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false ) $this->is_admin = true; + + if ( false !== strpos($qv['feed'], 'comments-') ) { + $qv['feed'] = str_replace('comments-', '', $qv['feed']); + $qv['withcomments'] = 1; } - if ( $this->is_single || $this->is_page || $this->is_attachment ) - $this->is_singular = true; + $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment; - if ( ! ($this->is_singular || $this->is_archive || $this->is_search || $this->is_feed || $this->is_trackback || $this->is_404 || $this->is_admin || $this->is_comments_popup)) { + if ( $this->is_feed && ( !empty($qv['withcomments']) || ( empty($qv['withoutcomments']) && $this->is_singular ) ) ) + $this->is_comment_feed = true; + + if ( !( $this->is_singular || $this->is_archive || $this->is_search || $this->is_feed || $this->is_trackback || $this->is_404 || $this->is_admin || $this->is_comments_popup ) ) $this->is_home = true; + + // Correct is_* for page_on_front and page_for_posts + if ( $this->is_home && ( empty($this->query) || $qv['preview'] == 'true' ) && 'page' == get_option('show_on_front') && get_option('page_on_front') ) { + $this->is_page = true; + $this->is_home = false; + $qv['page_id'] = get_option('page_on_front'); } - if ( !empty($query) ) { + if ( '' != $qv['pagename'] ) { + $this->queried_object =& get_page_by_path($qv['pagename']); + if ( !empty($this->queried_object) ) + $this->queried_object_id = (int) $this->queried_object->ID; + else + unset($this->queried_object); + + if ( 'page' == get_option('show_on_front') && isset($this->queried_object_id) && $this->queried_object_id == get_option('page_for_posts') ) { + $this->is_page = false; + $this->is_home = true; + $this->is_posts_page = true; + } + } + + if ( $qv['page_id'] ) { + if ( 'page' == get_option('show_on_front') && $qv['page_id'] == get_option('page_for_posts') ) { + $this->is_page = false; + $this->is_home = true; + $this->is_posts_page = true; + } + } + + if ( $this->is_posts_page && !$qv['withcomments'] ) + $this->is_comment_feed = false; + + $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment; + // Done correcting is_* for page_on_front and page_for_posts + + if ( !empty($query) ) do_action_ref_array('parse_query', array(&$this)); - } } function set_404() { @@ -574,7 +644,7 @@ // Shorthand. $q = &$this->query_vars; - + $q = $this->fill_query_vars($q); // First let's clear some variables @@ -634,7 +704,7 @@ $wp_posts_post_date_field = "post_date"; // "DATE_ADD(post_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)"; // If a month is specified in the querystring, load that month - if ( (int) $q['m'] ) { + if ( $q['m'] ) { $q['m'] = '' . preg_replace('|[^0-9]|', '', $q['m']); $where .= ' AND YEAR(post_date)=' . substr($q['m'], 0, 4); if (strlen($q['m'])>5) @@ -649,58 +719,39 @@ $where .= ' AND SECOND(post_date)=' . substr($q['m'], 12, 2); } - if ( (int) $q['hour'] ) { - $q['hour'] = '' . intval($q['hour']); + if ( '' != $q['hour'] ) $where .= " AND HOUR(post_date)='" . $q['hour'] . "'"; - } - if ( (int) $q['minute'] ) { - $q['minute'] = '' . intval($q['minute']); + if ( '' != $q['minute'] ) $where .= " AND MINUTE(post_date)='" . $q['minute'] . "'"; - } - if ( (int) $q['second'] ) { - $q['second'] = '' . intval($q['second']); + if ( '' != $q['second'] ) $where .= " AND SECOND(post_date)='" . $q['second'] . "'"; - } - if ( (int) $q['year'] ) { - $q['year'] = '' . intval($q['year']); + if ( $q['year'] ) $where .= " AND YEAR(post_date)='" . $q['year'] . "'"; - } - if ( (int) $q['monthnum'] ) { - $q['monthnum'] = '' . intval($q['monthnum']); + if ( $q['monthnum'] ) $where .= " AND MONTH(post_date)='" . $q['monthnum'] . "'"; - } - if ( (int) $q['day'] ) { - $q['day'] = '' . intval($q['day']); + if ( $q['day'] ) $where .= " AND DAYOFMONTH(post_date)='" . $q['day'] . "'"; - } - // Compat. Map subpost to attachment. - if ( '' != $q['subpost'] ) - $q['attachment'] = $q['subpost']; - if ( '' != $q['subpost_id'] ) - $q['attachment_id'] = $q['subpost_id']; - if ('' != $q['name']) { $q['name'] = sanitize_title($q['name']); $where .= " AND post_name = '" . $q['name'] . "'"; } else if ('' != $q['pagename']) { - $reqpage = get_page_by_path($q['pagename']); - if ( !empty($reqpage) ) - $reqpage = $reqpage->ID; - else - $reqpage = 0; + if ( isset($this->queried_object_id) ) + $reqpage = $this->queried_object_id; + else { + $reqpage = get_page_by_path($q['pagename']); + if ( !empty($reqpage) ) + $reqpage = $reqpage->ID; + else + $reqpage = 0; + } - if ( ('page' == get_option('show_on_front') ) && ( $reqpage == get_option('page_for_posts') ) ) { - $this->is_singular = false; - $this->is_page = false; - $this->is_home = true; - $this->is_posts_page = true; - } else { + if ( ('page' != get_option('show_on_front') ) || ( $reqpage != get_option('page_for_posts') ) ) { $q['pagename'] = str_replace('%2F', '/', urlencode(urldecode($q['pagename']))); $page_paths = '/' . trim($q['pagename'], '/'); $q['pagename'] = sanitize_title(basename($page_paths)); @@ -715,39 +766,29 @@ $where .= " AND post_name = '" . $q['attachment'] . "'"; } - if ( (int) $q['w'] ) { - $q['w'] = ''.intval($q['w']); + if ( $q['w'] ) $where .= " AND WEEK(post_date, 1)='" . $q['w'] . "'"; - } if ( intval($q['comments_popup']) ) $q['p'] = intval($q['comments_popup']); - // If a attachment is requested by number, let it supercede any post number. - if ( ($q['attachment_id'] != '') && (intval($q['attachment_id']) != 0) ) - $q['p'] = (int) $q['attachment_id']; + // If an attachment is requested by number, let it supercede any post number. + if ( $q['attachment_id'] ) + $q['p'] = $q['attachment_id']; // If a post number is specified, load that post - if (($q['p'] != '') && intval($q['p']) != 0) { - $q['p'] = (int) $q['p']; + if ( $q['p'] ) $where = ' AND ID = ' . $q['p']; - } - if (($q['page_id'] != '') && (intval($q['page_id']) != 0)) { - $q['page_id'] = intval($q['page_id']); - if ( ('page' == get_option('show_on_front') ) && ( $q['page_id'] == get_option('page_for_posts') ) ) { - $this->is_singular = false; - $this->is_page = false; - $this->is_home = true; - $this->is_posts_page = true; - } else { + if ( $q['page_id'] ) { + if ( ('page' != get_option('show_on_front') ) || ( $q['page_id'] != get_option('page_for_posts') ) ) { $q['p'] = $q['page_id']; - $where = ' AND ID = '.$q['page_id']; + $where = ' AND ID = ' . $q['page_id']; } } // If a search pattern is specified, load the posts that match - if (!empty($q['s'])) { + if ( !empty($q['s']) ) { // added slashes screw with quote grouping when done early, so done later $q['s'] = stripslashes($q['s']); if ($q['sentence']) { @@ -774,10 +815,10 @@ // Category stuff - if ((empty($q['cat'])) || ($q['cat'] == '0') || + if ( empty($q['cat']) || ($q['cat'] == '0') || // Bypass cat checks if fetching specific posts - ( $this->is_single || $this->is_page )) { - $whichcat=''; + $this->is_singular ) { + $whichcat = ''; } else { $q['cat'] = ''.urldecode($q['cat']).''; $q['cat'] = addslashes_gpc($q['cat']); @@ -786,7 +827,7 @@ $in_cats = $out_cats = $out_posts = ''; foreach ( $cat_array as $cat ) { $cat = intval($cat); - $in = strstr($cat, '-') ? false : true; + $in = (strpos($cat, '-') !== false) ? false : true; $cat = trim($cat, '-'); if ( $in ) $in_cats .= "$cat, " . get_category_children($cat, '', ', '); @@ -814,7 +855,7 @@ } // Category stuff for nice URLs - if ('' != $q['category_name']) { + if ( '' != $q['category_name'] ) { $reqcat = get_category_by_path($q['category_name']); $q['category_name'] = str_replace('%2F', '/', urlencode(urldecode($q['category_name']))); $cat_paths = '/' . trim($q['category_name'], '/'); @@ -847,14 +888,16 @@ $groupby = "{$wpdb->posts}.ID"; } + + // Author/user stuff - if ((empty($q['author'])) || ($q['author'] == '0')) { + if ( empty($q['author']) || ($q['author'] == '0') ) { $whichauthor=''; } else { $q['author'] = ''.urldecode($q['author']).''; $q['author'] = addslashes_gpc($q['author']); - if (stristr($q['author'], '-')) { + if (strpos($q['author'], '-') !== false) { $eq = '!='; $andor = 'AND'; $q['author'] = explode('-', $q['author']); @@ -874,7 +917,7 @@ // Author stuff for nice URLs if ('' != $q['author_name']) { - if (stristr($q['author_name'],'/')) { + if (strpos($q['author_name'], '/') !== false) { $q['author_name'] = explode('/',$q['author_name']); if ($q['author_name'][count($q['author_name'])-1]) { $q['author_name'] = $q['author_name'][count($q['author_name'])-1];#no trailing slash @@ -889,12 +932,11 @@ $where .= $search.$whichcat.$whichauthor; - if ((empty($q['order'])) || ((strtoupper($q['order']) != 'ASC') && (strtoupper($q['order']) != 'DESC'))) { - $q['order']='DESC'; - } + if ( empty($q['order']) || ((strtoupper($q['order']) != 'ASC') && (strtoupper($q['order']) != 'DESC')) ) + $q['order'] = 'DESC'; // Order by - if (empty($q['orderby'])) { + if ( empty($q['orderby']) ) { $q['orderby'] = 'post_date '.$q['order']; } else { // Used to filter values @@ -950,7 +992,7 @@ $join = apply_filters('posts_join', $join); // Paging - if (empty($q['nopaging']) && !$this->is_singular) { + if ( empty($q['nopaging']) && !$this->is_singular ) { $page = abs(intval($q['paged'])); if (empty($page)) { $page = 1; @@ -967,6 +1009,38 @@ } } + // Comments feeds + if ( $this->is_comment_feed && ( $this->is_archive || $this->is_search || !$this->is_singular ) ) { + if ( $this->is_archive || $this->is_search ) { + $cjoin = "LEFT JOIN $wpdb->posts ON ($wpdb->comments.comment_post_ID = $wpdb->posts.ID) $join "; + $cwhere = "WHERE comment_approved = '1' $where"; + $cgroupby = "GROUP BY $wpdb->comments.comment_id"; + } else { // Other non singular e.g. front + $cjoin = "LEFT JOIN $wpdb->posts ON ( $wpdb->comments.comment_post_ID = $wpdb->posts.ID )"; + $cwhere = "WHERE post_status = 'publish' AND comment_approved = '1'"; + $cgroupby = ''; + } + + $cjoin = apply_filters('comment_feed_join', $cjoin); + $cwhere = apply_filters('comment_feed_where', $cwhere); + $cgroupby = apply_filters('comment_feed_groupby', $cgroupby); + + $this->comments = (array) $wpdb->get_results("SELECT $distinct $wpdb->comments.* FROM $wpdb->comments $cjoin $cwhere $cgroupby ORDER BY comment_date_gmt DESC LIMIT " . get_option('posts_per_rss')); + $this->comment_count = count($this->comments); + + $post_ids = array(); + + foreach ($this->comments as $comment) + $post_ids[] = (int) $comment->comment_post_ID; + + $post_ids = join(',', $post_ids); + $join = ''; + if ( $post_ids ) + $where = "AND $wpdb->posts.ID IN ($post_ids) "; + else + $where = "AND 0"; + } + // Apply post-paging filters on where and join. Only plugins that // manipulate paging queries should use these hooks. $where = apply_filters('posts_where_paged', $where); @@ -986,12 +1060,22 @@ $this->request = apply_filters('posts_request', $request); $this->posts = $wpdb->get_results($this->request); + + if ( $this->is_comment_feed && $this->is_singular ) { + $cjoin = apply_filters('comment_feed_join', ''); + $cwhere = apply_filters('comment_feed_where', "WHERE comment_post_ID = {$this->posts[0]->ID} AND comment_approved = '1'"); + $comments_request = "SELECT $wpdb->comments.* FROM $wpdb->comments $cjoin $cwhere ORDER BY comment_date_gmt DESC LIMIT " . get_option('posts_per_rss'); + $this->comments = $wpdb->get_results($comments_request); + $this->comment_count = count($this->comments); + } + if ( !empty($limits) ) { $found_posts_query = apply_filters( 'found_posts_query', 'SELECT FOUND_ROWS()' ); $this->found_posts = $wpdb->get_var( $found_posts_query ); $this->found_posts = apply_filters( 'found_posts', $this->found_posts ); $this->max_num_pages = ceil($this->found_posts / $q['posts_per_page']); } + // Check post status to determine if post should be displayed. if ( !empty($this->posts) && ($this->is_single || $this->is_page) ) { $status = get_post_status($this->posts[0]); @@ -1072,6 +1156,40 @@ } } + function next_comment() { + $this->current_comment++; + + $this->comment = $this->comments[$this->current_comment]; + return $this->comment; + } + + function the_comment() { + global $comment; + + $comment = $this->next_comment(); + + if ($this->current_comment == 0) { + do_action('comment_loop_start'); + } + } + + function have_comments() { + if ($this->current_comment + 1 < $this->comment_count) { + return true; + } elseif ($this->current_comment + 1 == $this->comment_count) { + $this->rewind_comments(); + } + + return false; + } + + function rewind_comments() { + $this->current_comment = -1; + if ($this->comment_count > 0) { + $this->comment = $this->comments[0]; + } + } + function &query($query) { $this->parse_query($query); return $this->get_posts(); @@ -1089,18 +1207,18 @@ $cat = $this->get('cat'); $category = &get_category($cat); $this->queried_object = &$category; - $this->queried_object_id = $cat; + $this->queried_object_id = (int) $cat; } else if ($this->is_posts_page) { $this->queried_object = & get_page(get_option('page_for_posts')); - $this->queried_object_id = $this->queried_object->ID; + $this->queried_object_id = (int) $this->queried_object->ID; } else if ($this->is_single) { $this->queried_object = $this->post; - $this->queried_object_id = $this->post->ID; + $this->queried_object_id = (int) $this->post->ID; } else if ($this->is_page) { $this->queried_object = $this->post; - $this->queried_object_id = $this->post->ID; + $this->queried_object_id = (int) $this->post->ID; } else if ($this->is_author) { - $author_id = $this->get('author'); + $author_id = (int) $this->get('author'); $author = get_userdata($author_id); $this->queried_object = $author; $this->queried_object_id = $author_id; @@ -1169,7 +1287,7 @@ global $id, $postdata, $authordata, $day, $page, $pages, $multipage, $more, $numpages, $wp_query; global $pagenow; - $id = $post->ID; + $id = (int) $post->ID; $authordata = get_userdata($post->post_author); Index: wp-includes/link-template.php =================================================================== --- wp-includes/link-template.php (.../2.1.3) (revision 5482) +++ wp-includes/link-template.php (.../2.2) (revision 5482) @@ -11,6 +11,28 @@ } +/** + * Conditionally adds a trailing slash if the permalink structure + * has a trailing slash, strips the trailing slash if not + * @global object Uses $wp_rewrite + * @param $string string a URL with or without a trailing slash + * @param $type_of_url string the type of URL being considered (e.g. single, category, etc) for use in the filter + * @return string + */ +function user_trailingslashit($string, $type_of_url = '') { + global $wp_rewrite; + if ( $wp_rewrite->use_trailing_slashes ) + $string = trailingslashit($string); + else + $string = untrailingslashit($string); + + // Note that $type_of_url can be one of following: + // single, single_trackback, single_feed, single_paged, feed, category, page, year, month, day, paged + $string = apply_filters('user_trailingslashit', $string, $type_of_url); + return $string; +} + + function permalink_anchor($mode = 'id') { global $post; switch ( strtolower($mode) ) { @@ -53,7 +75,7 @@ $unixtime = strtotime($post->post_date); $category = ''; - if ( strstr($permalink, '%category%') ) { + if (strpos($permalink, '%category%') !== false) { $cats = get_the_category($post->ID); $category = $cats[0]->category_nicename; if ( $parent=$cats[0]->category_parent ) @@ -77,7 +99,9 @@ $author, $post->post_name, ); - return apply_filters('post_link', get_option('home') . str_replace($rewritecode, $rewritereplace, $permalink), $post); + $permalink = get_option('home') . str_replace($rewritecode, $rewritereplace, $permalink); + $permalink = user_trailingslashit($permalink, 'single'); + return apply_filters('post_link', $permalink, $post); } else { // if they're not using the fancy permalink option $permalink = get_option('home') . '/?p=' . $post->ID; return apply_filters('post_link', $permalink, $post); @@ -117,7 +141,8 @@ if ( '' != $pagestruct && 'draft' != $post->post_status ) { $link = get_page_uri($id); $link = str_replace('%pagename%', $link, $pagestruct); - $link = get_option('home') . "/$link/"; + $link = get_option('home') . "/$link"; + $link = user_trailingslashit($link, 'page'); } else { $link = get_option('home') . "/?page_id=$id"; } @@ -141,12 +166,12 @@ $parentlink = _get_page_link( $object->post_parent ); // Ignores page_on_front else $parentlink = get_permalink( $object->post_parent ); - if (! strstr($parentlink, '?') ) + if (strpos($parentlink, '?') === false) $link = trim($parentlink, '/') . '/' . $object->post_name . '/'; } if (! $link ) { - $link = get_bloginfo('home') . "/?attachment_id=$id"; + $link = get_bloginfo('url') . "/?attachment_id=$id"; } return apply_filters('attachment_link', $link, $id); @@ -159,7 +184,7 @@ $yearlink = $wp_rewrite->get_year_permastruct(); if ( !empty($yearlink) ) { $yearlink = str_replace('%year%', $year, $yearlink); - return apply_filters('year_link', get_option('home') . trailingslashit($yearlink), $year); + return apply_filters('year_link', get_option('home') . user_trailingslashit($yearlink, 'year'), $year); } else { return apply_filters('year_link', get_option('home') . '/?m=' . $year, $year); } @@ -175,7 +200,7 @@ if ( !empty($monthlink) ) { $monthlink = str_replace('%year%', $year, $monthlink); $monthlink = str_replace('%monthnum%', zeroise(intval($month), 2), $monthlink); - return apply_filters('month_link', get_option('home') . trailingslashit($monthlink), $year, $month); + return apply_filters('month_link', get_option('home') . user_trailingslashit($monthlink, 'month'), $year, $month); } else { return apply_filters('month_link', get_option('home') . '/?m=' . $year . zeroise($month, 2), $year, $month); } @@ -195,7 +220,7 @@ $daylink = str_replace('%year%', $year, $daylink); $daylink = str_replace('%monthnum%', zeroise(intval($month), 2), $daylink); $daylink = str_replace('%day%', zeroise(intval($day), 2), $daylink); - return apply_filters('day_link', get_option('home') . trailingslashit($daylink), $year, $month, $day); + return apply_filters('day_link', get_option('home') . user_trailingslashit($daylink, 'day'), $year, $month, $day); } else { return apply_filters('day_link', get_option('home') . '/?m=' . $year . zeroise($month, 2) . zeroise($day, 2), $year, $month, $day); } @@ -218,8 +243,8 @@ $feed = ''; $permalink = str_replace('%feed%', $feed, $permalink); - $permalink = preg_replace('#/+#', '/', "/$permalink/"); - $output = get_option('home') . $permalink; + $permalink = preg_replace('#/+#', '/', "/$permalink"); + $output = get_option('home') . user_trailingslashit($permalink, 'feed'); } else { if ( false !== strpos($feed, 'comments_') ) $feed = str_replace('comments_', 'comments-', $feed); @@ -230,6 +255,24 @@ return apply_filters('feed_link', $output, $feed); } +function get_post_comments_feed_link($post_id = '', $feed = 'rss2') { + global $id; + + if ( empty($post_id) ) + $post_id = (int) $id; + + if ( '' != get_option('permalink_structure') ) { + $url = trailingslashit( get_permalink() ) . 'feed'; + if ( 'rss2' != $feed ) + $url .= "/$feed"; + $url = user_trailingslashit($url, 'single_feed'); + } else { + $url = get_option('home') . "/?feed=$feed&p=$id"; + } + + return apply_filters('post_comments_feed_link', $url); +} + function edit_post_link($link = 'Edit This', $before = '', $after = '') { global $post; @@ -398,7 +441,7 @@ $index = preg_replace('|^/+|', '', $index); // if we already have a QUERY style page string - if ( stristr( $qstr, $page_querystring ) ) { + if ( stripos( $qstr, $page_querystring ) !== false ) { $replacement = "$page_querystring=$pagenum"; $qstr = preg_replace("/".$page_querystring."[^\d]+\d+/", $replacement, $qstr); // if we already have a mod_rewrite style page string @@ -411,7 +454,7 @@ } else { // we need to know the way queries are being written // if there's a querystring_start (a "?" usually), it's definitely not mod_rewritten - if ( stristr( $qstr, '?' ) ) { + if ( stripos( $qstr, '?' ) !== false ) { // so append the query string (using &, since we already have ?) $qstr .= '&' . $page_querystring . '=' . $pagenum; // otherwise, it could be rewritten, OR just the default index ... @@ -436,12 +479,13 @@ $qstr = preg_replace('|^/+|', '', $qstr); if ( $permalink ) - $qstr = trailingslashit($qstr); + $qstr = user_trailingslashit($qstr, 'paged'); $qstr = preg_replace('/&([^#])(?![a-z]{1,8};)/', '&$1', trailingslashit( get_option('home') ) . $qstr ); // showing /page/1/ or ?paged=1 is redundant if ( 1 === $pagenum ) { - $qstr = str_replace('page/1/', '', $qstr); // for mod_rewrite style + $qstr = str_replace(user_trailingslashit('index.php/page/1', 'paged'), '', $qstr); // for PATHINFO style + $qstr = str_replace(user_trailingslashit('page/1', 'paged'), '', $qstr); // for mod_rewrite style $qstr = remove_query_arg('paged', $qstr); // for query style } return $qstr; Index: wp-includes/wp-db.php =================================================================== --- wp-includes/wp-db.php (.../2.1.3) (revision 5482) +++ wp-includes/wp-db.php (.../2.2) (revision 5482) @@ -35,6 +35,9 @@ var $optiongroup_options; var $postmeta; + var $charset; + var $collate; + /** * Connects to the database server and selects a database * @param string $dbuser @@ -45,10 +48,16 @@ function wpdb($dbuser, $dbpassword, $dbname, $dbhost) { return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost); } - + function __construct($dbuser, $dbpassword, $dbname, $dbhost) { register_shutdown_function(array(&$this, "__destruct")); + if ( defined('DB_CHARSET') ) + $this->charset = DB_CHARSET; + + if ( defined('DB_COLLATE') ) + $this->collate = DB_COLLATE; + $this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword); if (!$this->dbh) { $this->bail(" @@ -63,11 +72,14 @@ "); } + if ( !empty($this->charset) && version_compare(mysql_get_server_info(), '4.1.0', '>=') ) + $this->query("SET NAMES '$this->charset'"); + $this->select($dbname); } function __destruct() { - return true; + return true; } /** @@ -169,7 +181,7 @@ $this->result = @mysql_query($query, $this->dbh); ++$this->num_queries; - + if (SAVEQUERIES) $this->queries[] = array( $query, $this->timer_stop() ); @@ -180,7 +192,7 @@ } if ( preg_match("/^\\s*(insert|delete|update|replace) /i",$query) ) { - $this->rows_affected = mysql_affected_rows(); + $this->rows_affected = mysql_affected_rows($this->dbh); // Take note of the insert_id if ( preg_match("/^\\s*(insert|replace) /i",$query) ) { $this->insert_id = mysql_insert_id($this->dbh); @@ -243,7 +255,7 @@ $this->func_call = "\$db->get_row(\"$query\",$output,$y)"; if ( $query ) $this->query($query); - + if ( !isset($this->last_result[$y]) ) return null; @@ -360,7 +372,7 @@ header('Content-Type: text/html; charset=utf-8'); - if ( strstr($_SERVER['PHP_SELF'], 'wp-admin') ) + if (strpos($_SERVER['PHP_SELF'], 'wp-admin') !== false) $admin_dir = ''; else $admin_dir = 'wp-admin/'; Index: wp-includes/formatting.php =================================================================== --- wp-includes/formatting.php (.../2.1.3) (revision 5482) +++ wp-includes/formatting.php (.../2.2) (revision 5482) @@ -21,7 +21,7 @@ $static_replacements = array_merge(array('—', ' — ', '–', 'xn--', '…', '“', '’s', '”', ' ™'), $cockneyreplace); $dynamic_characters = array('/\'(\d\d(?:’|\')?s)/', '/(\s|\A|")\'/', '/(\d+)"/', '/(\d+)\'/', '/(\S)\'([^\'\s])/', '/(\s|\A)"(?!\s)/', '/"(\s|\S|\Z)/', '/\'([\s.]|\Z)/', '/(\d+)x(\d+)/'); - $dynamic_replacements = array('’$1','$1‘', '$1″', '$1′', '$1’$2', '$1“$2', '”$1', '’$1', '$1×$2'); + $dynamic_replacements = array('’$1','$1‘', '$1″', '$1′', '$1’$2', '$1“$2', '”$1', '’$1', '$1×$2'); for ( $i = 0; $i < $stop; $i++ ) { $curl = $textarr[$i]; @@ -29,10 +29,9 @@ if (isset($curl{0}) && '<' != $curl{0} && $next) { // If it's not a tag // static strings $curl = str_replace($static_characters, $static_replacements, $curl); - // regular expressions $curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl); - } elseif ( strstr($curl, '\s*
    |', "\n\n", $pee); // Space things out a little - $allblocks = '(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|style|script|object|input|param|p|h[1-6])'; + $allblocks = '(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|map|area|blockquote|address|math|style|input|p|h[1-6]|hr)'; $pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee); $pee = preg_replace('!()!', "$1\n\n", $pee); $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines @@ -78,7 +77,7 @@ } $pee = preg_replace('!(]*>)\s*
    !', "$1", $pee); $pee = preg_replace('!
    (\s*]*>)!', '$1', $pee); - if ( strstr( $pee, ')(.*?)!ise', " stripslashes('$1') . stripslashes(clean_pre('$2')) . '' ", $pee); $pee = preg_replace( "|\n

    $|", '

    ', $pee ); @@ -564,12 +563,13 @@ } function trailingslashit($string) { - if ( '/' != substr($string, -1)) { - $string .= '/'; - } - return $string; + return untrailingslashit($string) . '/'; } +function untrailingslashit($string) { + return rtrim($string, '/'); +} + function addslashes_gpc($gpc) { global $wpdb; @@ -581,15 +581,22 @@ } -function stripslashes_deep($value) -{ +function stripslashes_deep($value) { $value = is_array($value) ? - array_map('stripslashes_deep', $value) : - stripslashes($value); + array_map('stripslashes_deep', $value) : + stripslashes($value); return $value; } +function urlencode_deep($value) { + $value = is_array($value) ? + array_map('urlencode_deep', $value) : + urlencode($value); + + return $value; +} + function antispambot($emailaddy, $mailto=0) { $emailNOSPAMaddy = ''; srand ((float) microtime() * 1000000); @@ -658,7 +665,7 @@ function is_email($user_email) { $chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,6}\$/i"; - if(strstr($user_email, '@') && strstr($user_email, '.')) { + if (strpos($user_email, '@') !== false && strpos($user_email, '.') !== false) { if (preg_match($chars, $user_email)) { return true; } else { @@ -1074,7 +1081,7 @@ $url = str_replace(';//', '://', $url); // Append http unless a relative link starting with / or a php file. if ( strpos($url, '://') === false && - substr( $url, 0, 1 ) != '/' && !preg_match('/^[a-z0-9]+?\.php/i', $url) ) + substr( $url, 0, 1 ) != '/' && !preg_match('/^[a-z0-9-]+?\.php/i', $url) ) $url = 'http://' . $url; $url = preg_replace('/&([^#])(?![a-z]{2,8};)/', '&$1', $url); Index: wp-includes/author-template.php =================================================================== --- wp-includes/author-template.php (.../2.1.3) (revision 5482) +++ wp-includes/author-template.php (.../2.2) (revision 5482) @@ -173,6 +173,8 @@ } function wp_list_authors($args = '') { + global $wpdb; + if ( is_array($args) ) $r = &$args; else @@ -182,15 +184,18 @@ 'feed' => '', 'feed_image' => ''); $r = array_merge($defaults, $r); extract($r); - - global $wpdb; + // TODO: Move select to get_authors(). - $query = "SELECT ID, user_nicename from $wpdb->users " . ($exclude_admin ? "WHERE user_login <> 'admin' " : '') . "ORDER BY display_name"; - $authors = $wpdb->get_results($query); + $authors = $wpdb->get_results("SELECT ID, user_nicename from $wpdb->users " . ($exclude_admin ? "WHERE user_login <> 'admin' " : '') . "ORDER BY display_name"); + + $author_count = array(); + foreach ((array) $wpdb->get_results("SELECT DISTINCT post_author, COUNT(ID) AS count FROM $wpdb->posts WHERE post_status = 'publish' GROUP BY post_author") as $row) { + $author_count[$row->post_author] = $row->count; + } foreach ( (array) $authors as $author ) { $author = get_userdata( $author->ID ); - $posts = get_usernumposts($author->ID); + $posts = (isset($author_count[$author->ID])) ? $author_count[$author->ID] : 0; $name = $author->nickname; if ( $show_fullname && ($author->first_name != '' && $author->last_name != '') ) Index: wp-includes/feed-rss2-comments.php =================================================================== --- wp-includes/feed-rss2-comments.php (.../2.1.3) (revision 0) +++ wp-includes/feed-rss2-comments.php (.../2.2) (revision 5482) @@ -0,0 +1,55 @@ +'; +?> + + + + <?php + if ( is_singular() ) + printf(__('Comments on: %s'), get_the_title_rss()); + elseif ( is_search() ) + printf(__('Comments for %s searching on %s'), get_bloginfo_rss( 'name' ), attribute_escape($wp_query->query_vars['s'])); + else + printf(__('Comments for %s'), get_bloginfo_rss( 'name' ) . get_wp_title_rss()); + ?> + + + + http://wordpress.org/?v= + +comment_post_ID); + get_post_custom($comment_post->ID); +?> + + <?php + if ( !is_singular() ) { + $title = get_the_title($comment_post->ID); + $title = apply_filters('the_title', $title); + $title = apply_filters('the_title_rss', $title); + printf(__('Comment on %1$s by %2$s'), $title, get_comment_author_rss()); + } else { + printf(__('By: %s'), get_comment_author_rss()); + } + ?> + + + + +post_password) && $_COOKIE['wp-postpass'] != $comment_post->post_password) : ?> + + ]]> + + + ]]> +comment_ID, $comment_post->ID); +?> + + + + Property changes on: wp-includes/feed-rss2-comments.php ___________________________________________________________________ Name: svn:eol-style + native Index: wp-includes/category.php =================================================================== --- wp-includes/category.php (.../2.1.3) (revision 5482) +++ wp-includes/category.php (.../2.2) (revision 5482) @@ -5,7 +5,7 @@ if ( ! $cat_ids = wp_cache_get('all_category_ids', 'category') ) { $cat_ids = $wpdb->get_col("SELECT cat_ID FROM $wpdb->categories"); - wp_cache_set('all_category_ids', $cat_ids, 'category'); + wp_cache_add('all_category_ids', $cat_ids, 'category'); } return $cat_ids; @@ -105,8 +105,11 @@ unset($cat_stamps); } - if ( $child_of || $hierarchical ) - $categories = & _get_cat_children($child_of, $categories); + if ( $child_of || $hierarchical ) { + $children = _get_category_hierarchy(); + if ( ! empty($children) ) + $categories = & _get_cat_children($child_of, $categories); + } // Update category counts to include children. if ( $pad_counts ) @@ -129,9 +132,10 @@ reset ( $categories ); $cache[ $key ] = $categories; - wp_cache_set( 'get_categories', $cache, 'category' ); + wp_cache_add( 'get_categories', $cache, 'category' ); - return apply_filters('get_categories', $categories, $r); + $categories = apply_filters('get_categories', $categories, $r); + return $categories; } // Retrieves category data given a category ID or category object. @@ -149,7 +153,7 @@ $category = (int) $category; if ( ! $_category = wp_cache_get($category, 'category') ) { $_category = $wpdb->get_row("SELECT * FROM $wpdb->categories WHERE cat_ID = '$category' LIMIT 1"); - wp_cache_set($category, $_category, 'category'); + wp_cache_add($category, $_category, 'category'); } } @@ -247,12 +251,21 @@ return array(); $category_list = array(); + $has_children = _get_category_hierarchy(); + + if ( ( 0 != $category_id ) && ! isset($has_children[$category_id]) ) + return array(); + foreach ( $categories as $category ) { if ( $category->cat_ID == $category_id ) continue; if ( $category->category_parent == $category_id ) { $category_list[] = $category; + + if ( !isset($has_children[$category->cat_ID]) ) + continue; + if ( $children = _get_cat_children($category->cat_ID, $categories) ) $category_list = array_merge($category_list, $children); } @@ -300,4 +313,19 @@ $cats[$id]->{'link' == $type ? 'link_count' : 'category_count'} = count($items); } +function _get_category_hierarchy() { + $children = get_option('category_children'); + if ( is_array($children) ) + return $children; + + $children = array(); + $categories = get_categories('hide_empty=0&hierarchical=0'); + foreach ( $categories as $cat ) { + if ( $cat->category_parent > 0 ) + $children[$cat->category_parent][] = $cat->cat_ID; + } + update_option('category_children', $children); + + return $children; +} ?> Index: wp-includes/images/rss.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: wp-includes/images/rss.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: wp-includes/template-loader.php =================================================================== --- wp-includes/template-loader.php (.../2.1.3) (revision 5482) +++ wp-includes/template-loader.php (.../2.2) (revision 5482) @@ -3,70 +3,70 @@ do_action('template_redirect'); if ( is_robots() ) { do_action('do_robots'); - exit; + return; } else if ( is_feed() ) { do_feed(); - exit; + return; } else if ( is_trackback() ) { include(ABSPATH . '/wp-trackback.php'); - exit; + return; } else if ( is_404() && $template = get_404_template() ) { include($template); - exit; + return; } else if ( is_search() && $template = get_search_template() ) { include($template); - exit; + return; } else if ( is_home() && $template = get_home_template() ) { include($template); - exit; + return; } else if ( is_attachment() && $template = get_attachment_template() ) { include($template); - exit; + return; } else if ( is_single() && $template = get_single_template() ) { if ( is_attachment() ) add_filter('the_content', 'prepend_attachment'); include($template); - exit; + return; } else if ( is_page() && $template = get_page_template() ) { if ( is_attachment() ) add_filter('the_content', 'prepend_attachment'); include($template); - exit; + return; } else if ( is_category() && $template = get_category_template()) { include($template); - exit; + return; } else if ( is_author() && $template = get_author_template() ) { include($template); - exit; + return; } else if ( is_date() && $template = get_date_template() ) { include($template); - exit; + return; } else if ( is_archive() && $template = get_archive_template() ) { include($template); - exit; + return; } else if ( is_comments_popup() && $template = get_comments_popup_template() ) { include($template); - exit; + return; } else if ( is_paged() && $template = get_paged_template() ) { include($template); - exit; + return; } else if ( file_exists(TEMPLATEPATH . "/index.php") ) { if ( is_attachment() ) add_filter('the_content', 'prepend_attachment'); include(TEMPLATEPATH . "/index.php"); - exit; + return; } } else { // Process feeds and trackbacks even if not using themes. if ( is_robots() ) { do_action('do_robots'); - exit; + return; } else if ( is_feed() ) { do_feed(); - exit; + return; } else if ( is_trackback() ) { include(ABSPATH . '/wp-trackback.php'); - exit; + return; } } Index: wp-includes/rewrite.php =================================================================== --- wp-includes/rewrite.php (.../2.1.3) (revision 5482) +++ wp-includes/rewrite.php (.../2.2) (revision 5482) @@ -50,7 +50,7 @@ define('EP_PAGES', 2048); //pseudo-places define('EP_NONE', 0 ); -define('EP_ALL', 255); +define('EP_ALL', 4095); //and an endpoint, like /trackback/ function add_rewrite_endpoint($name, $places) { @@ -62,6 +62,8 @@ // determine the post ID it represents. function url_to_postid($url) { global $wp_rewrite; + + $url = apply_filters('url_to_postid', $url); // First, check to see if there is a 'p=N' or 'page_id=N' to match against preg_match('#[?&](p|page_id)=(\d+)#', $url, $values); @@ -148,6 +150,7 @@ class WP_Rewrite { var $permalink_structure; + var $use_trailing_slashes; var $category_base; var $category_structure; var $author_base = 'author'; @@ -581,6 +584,16 @@ if ($paged) //...and /page/xx ones $rewrite = array_merge($rewrite, array($pagematch => $pagequery)); + //do endpoints + if ($endpoints) { + foreach ($ep_query_append as $regex => $ep) { + //add the endpoints on if the mask fits + if ($ep[0] & $ep_mask || $ep[0] & $ep_mask_specific) { + $rewrite[$match . $regex] = $index . '?' . $query . $ep[1] . $this->preg_index($num_toks + 2); + } + } + } + //if we've got some tags in this dir if ($num_toks) { $post = false; @@ -590,24 +603,14 @@ //individual post. Do this by checking it contains at least one of 1) post name, //2) post ID, 3) page name, 4) timestamp (year, month, day, hour, second and //minute all present). Set these flags now as we need them for the endpoints. - if (strstr($struct, '%postname%') || strstr($struct, '%post_id%') - || strstr($struct, '%pagename%') - || (strstr($struct, '%year%') && strstr($struct, '%monthnum%') && strstr($struct, '%day%') && strstr($struct, '%hour%') && strstr($struct, '%minute') && strstr($struct, '%second%'))) { + if (strpos($struct, '%postname%') !== false || strpos($struct, '%post_id%') !== false + || strpos($struct, '%pagename%') !== false + || (strpos($struct, '%year%') !== false && strpos($struct, '%monthnum%') !== false && strpos($struct, '%day%') !== false && strpos($struct, '%hour%') !== false && strpos($struct, '%minute%') !== false && strpos($struct, '%second%') !== false)) { $post = true; - if ( strstr($struct, '%pagename%') ) + if (strpos($struct, '%pagename%') !== false) $page = true; } - //do endpoints - if ($endpoints) { - foreach ($ep_query_append as $regex => $ep) { - //add the endpoints on if the mask fits - if ($ep[0] & $ep_mask || $ep[0] & $ep_mask_specific) { - $rewrite[$match . $regex] = $index . '?' . $query . $ep[1] . $this->preg_index($num_toks + 2); - } - } - } - //if we're creating rules for a permalink, do all the endpoints like attachments etc if ($post) { $post = true; @@ -808,7 +811,7 @@ //nada. } - if (strstr($query, $this->index)) { + if (strpos($query, $this->index) !== false) { $rules .= 'RewriteRule ^' . $match . ' ' . $home_root . $query . " [QSA,L]\n"; } else { $rules .= 'RewriteRule ^' . $match . ' ' . $site_root . $query . " [QSA,L]\n"; @@ -876,6 +879,7 @@ unset($this->search_structure); unset($this->feed_structure); unset($this->comment_feed_structure); + $this->use_trailing_slashes = ( substr($this->permalink_structure, -1, 1) == '/' ) ? true : false; } function set_permalink_structure($permalink_structure) { @@ -897,4 +901,4 @@ } } -?> +?> \ No newline at end of file Index: wp-includes/compat.php =================================================================== --- wp-includes/compat.php (.../2.1.3) (revision 5482) +++ wp-includes/compat.php (.../2.2) (revision 5482) @@ -118,4 +118,11 @@ } } +// Added in PHP 5.0 +if (!function_exists('stripos')) { + function stripos($haystack, $needle, $offset = 0) { + return strpos(strtolower($haystack), strtolower($needle), $offset); + } +} + ?> Index: wp-includes/gettext.php =================================================================== --- wp-includes/gettext.php (.../2.1.3) (revision 5482) +++ wp-includes/gettext.php (.../2.2) (revision 5482) @@ -1,32 +1,32 @@ . - Copyright (c) 2005 Nico Kaiser - - This file is part of PHP-gettext. + Copyright (c) 2003 Danilo Segan . + Copyright (c) 2005 Nico Kaiser - PHP-gettext is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This file is part of PHP-gettext. - PHP-gettext is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + PHP-gettext is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. - You should have received a copy of the GNU General Public License - along with PHP-gettext; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + PHP-gettext is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with PHP-gettext; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ - + /** * Provides a simple gettext replacement that works independently from * the system's gettext abilities. * It can read MO files and use them for translating strings. * The files are passed to gettext_reader as a Stream (see streams.php) - * + * * This version has the ability to cache all strings and translations to * speed up the string lookup. * While the cache is enabled by default, it can be switched off with the @@ -34,331 +34,361 @@ * that you don't want to keep in memory) */ class gettext_reader { - //public: - var $error = 0; // public variable that holds error code (0 if no error) - - //private: - var $BYTEORDER = 0; // 0: low endian, 1: big endian - var $STREAM = NULL; - var $short_circuit = false; - var $enable_cache = false; - var $originals = NULL; // offset of original table - var $translations = NULL; // offset of translation table - var $pluralheader = NULL; // cache header field for plural forms - var $total = 0; // total string count - var $table_originals = NULL; // table for original strings (offsets) - var $table_translations = NULL; // table for translated strings (offsets) - var $cache_translations = NULL; // original -> translation mapping + //public: + var $error = 0; // public variable that holds error code (0 if no error) + //private: + var $BYTEORDER = 0; // 0: low endian, 1: big endian + var $STREAM = NULL; + var $short_circuit = false; + var $enable_cache = false; + var $originals = NULL; // offset of original table + var $translations = NULL; // offset of translation table + var $pluralheader = NULL; // cache header field for plural forms + var $select_string_function = NULL; // cache function, which chooses plural forms + var $total = 0; // total string count + var $table_originals = NULL; // table for original strings (offsets) + var $table_translations = NULL; // table for translated strings (offsets) + var $cache_translations = NULL; // original -> translation mapping - /* Methods */ - - - /** - * Reads a 32bit Integer from the Stream - * - * @access private - * @return Integer from the Stream - */ - function readint() { - if ($this->BYTEORDER == 0) { - // low endian - $low_end = unpack('V', $this->STREAM->read(4)); - return array_shift($low_end); - } else { - // big endian - $big_end = unpack('N', $this->STREAM->read(4)); - return array_shift($big_end); - } - } - /** - * Reads an array of Integers from the Stream - * - * @param int count How many elements should be read - * @return Array of Integers - */ - function readintarray($count) { - if ($this->BYTEORDER == 0) { - // low endian - return unpack('V'.$count, $this->STREAM->read(4 * $count)); - } else { - // big endian - return unpack('N'.$count, $this->STREAM->read(4 * $count)); - } - } - - /** - * Constructor - * - * @param object Reader the StreamReader object - * @param boolean enable_cache Enable or disable caching of strings (default on) - */ - function gettext_reader($Reader, $enable_cache = true) { - // If there isn't a StreamReader, turn on short circuit mode. - if (! $Reader || isset($Reader->error) ) { - $this->short_circuit = true; - return; - } - - // Caching can be turned off - $this->enable_cache = $enable_cache; + /* Methods */ - // $MAGIC1 = (int)0x950412de; //bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565 - $MAGIC1 = (int) - 1794895138; - // $MAGIC2 = (int)0xde120495; //bug - $MAGIC2 = (int) - 569244523; - $this->STREAM = $Reader; - $magic = $this->readint(); - if ($magic == ($MAGIC1 & 0xFFFFFFFF)) { // to make sure it works for 64-bit platforms - $this->BYTEORDER = 0; - } elseif ($magic == ($MAGIC2 & 0xFFFFFFFF)) { - $this->BYTEORDER = 1; - } else { - $this->error = 1; // not MO file - return false; - } - - // FIXME: Do we care about revision? We should. - $revision = $this->readint(); - - $this->total = $this->readint(); - $this->originals = $this->readint(); - $this->translations = $this->readint(); - } - - /** - * Loads the translation tables from the MO file into the cache - * If caching is enabled, also loads all strings into a cache - * to speed up translation lookups - * - * @access private - */ - function load_tables() { - if (is_array($this->cache_translations) && - is_array($this->table_originals) && - is_array($this->table_translations)) - return; - - /* get original and translations tables */ - $this->STREAM->seekto($this->originals); - $this->table_originals = $this->readintarray($this->total * 2); - $this->STREAM->seekto($this->translations); - $this->table_translations = $this->readintarray($this->total * 2); - - if ($this->enable_cache) { - $this->cache_translations = array (); - /* read all strings in the cache */ - for ($i = 0; $i < $this->total; $i++) { - $this->STREAM->seekto($this->table_originals[$i * 2 + 2]); - $original = $this->STREAM->read($this->table_originals[$i * 2 + 1]); - $this->STREAM->seekto($this->table_translations[$i * 2 + 2]); - $translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]); - $this->cache_translations[$original] = $translation; - } - } - } - - /** - * Returns a string from the "originals" table - * - * @access private - * @param int num Offset number of original string - * @return string Requested string if found, otherwise '' - */ - function get_original_string($num) { - $length = $this->table_originals[$num * 2 + 1]; - $offset = $this->table_originals[$num * 2 + 2]; - if (! $length) - return ''; - $this->STREAM->seekto($offset); - $data = $this->STREAM->read($length); - return (string)$data; - } - - /** - * Returns a string from the "translations" table - * - * @access private - * @param int num Offset number of original string - * @return string Requested string if found, otherwise '' - */ - function get_translation_string($num) { - $length = $this->table_translations[$num * 2 + 1]; - $offset = $this->table_translations[$num * 2 + 2]; - if (! $length) - return ''; - $this->STREAM->seekto($offset); - $data = $this->STREAM->read($length); - return (string)$data; - } - - /** - * Binary search for string - * - * @access private - * @param string string - * @param int start (internally used in recursive function) - * @param int end (internally used in recursive function) - * @return int string number (offset in originals table) - */ - function find_string($string, $start = -1, $end = -1) { - if (($start == -1) or ($end == -1)) { - // find_string is called with only one parameter, set start end end - $start = 0; - $end = $this->total; - } - if (abs($start - $end) <= 1) { - // We're done, now we either found the string, or it doesn't exist - $txt = $this->get_original_string($start); - if ($string == $txt) - return $start; - else - return -1; - } else if ($start > $end) { - // start > end -> turn around and start over - return $this->find_string($string, $end, $start); - } else { - // Divide table in two parts - $half = (int)(($start + $end) / 2); - $cmp = strcmp($string, $this->get_original_string($half)); - if ($cmp == 0) - // string is exactly in the middle => return it - return $half; - else if ($cmp < 0) - // The string is in the upper half - return $this->find_string($string, $start, $half); - else - // The string is in the lower half - return $this->find_string($string, $half, $end); - } - } - - /** - * Translates a string - * - * @access public - * @param string string to be translated - * @return string translated string (or original, if not found) - */ - function translate($string) { - if ($this->short_circuit) - return $string; - $this->load_tables(); - - if ($this->enable_cache) { - // Caching enabled, get translated string from cache - if (array_key_exists($string, $this->cache_translations)) - return $this->cache_translations[$string]; - else - return $string; - } else { - // Caching not enabled, try to find string - $num = $this->find_string($string); - if ($num == -1) - return $string; - else - return $this->get_translation_string($num); - } - } + /** + * Reads a 32bit Integer from the Stream + * + * @access private + * @return Integer from the Stream + */ + function readint() { + if ($this->BYTEORDER == 0) { + // low endian + $low_end = unpack('V', $this->STREAM->read(4)); + return array_shift($low_end); + } else { + // big endian + $big_end = unpack('N', $this->STREAM->read(4)); + return array_shift($big_end); + } + } - /** - * Get possible plural forms from MO header - * - * @access private - * @return string plural form header - */ - function get_plural_forms() { - // lets assume message number 0 is header - // this is true, right? - $this->load_tables(); - - // cache header field for plural forms - if (! is_string($this->pluralheader)) { - if ($this->enable_cache) { - $header = $this->cache_translations[""]; - } else { - $header = $this->get_translation_string(0); - } - if (eregi("plural-forms: ([^\n]*)\n", $header, $regs)) - $expr = $regs[1]; - else - $expr = "nplurals=2; plural=n == 1 ? 0 : 1;"; - $this->pluralheader = $expr; - } - return $this->pluralheader; - } + /** + * Reads an array of Integers from the Stream + * + * @param int count How many elements should be read + * @return Array of Integers + */ + function readintarray($count) { + if ($this->BYTEORDER == 0) { + // low endian + return unpack('V'.$count, $this->STREAM->read(4 * $count)); + } else { + // big endian + return unpack('N'.$count, $this->STREAM->read(4 * $count)); + } + } - /** - * Detects which plural form to take - * - * @access private - * @param n count - * @return int array index of the right plural form - */ - function select_string($n) { - $string = $this->get_plural_forms(); - $string = str_replace('nplurals',"\$total",$string); - $string = str_replace("n",$n,$string); - $string = str_replace('plural',"\$plural",$string); + /** + * Constructor + * + * @param object Reader the StreamReader object + * @param boolean enable_cache Enable or disable caching of strings (default on) + */ + function gettext_reader($Reader, $enable_cache = true) { + // If there isn't a StreamReader, turn on short circuit mode. + if (! $Reader || isset($Reader->error) ) { + $this->short_circuit = true; + return; + } - # poEdit doesn't put any semicolons, which - # results in parse error in eval - $string .= ';'; - - $total = 0; - $plural = 0; + // Caching can be turned off + $this->enable_cache = $enable_cache; - eval("$string"); - if ($plural >= $total) $plural = $total - 1; - return $plural; - } + // $MAGIC1 = (int)0x950412de; //bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565 + $MAGIC1 = (int) - 1794895138; + // $MAGIC2 = (int)0xde120495; //bug + $MAGIC2 = (int) - 569244523; + // 64-bit fix + $MAGIC3 = (int) 2500072158; - /** - * Plural version of gettext - * - * @access public - * @param string single - * @param string plural - * @param string number - * @return translated plural form - */ - function ngettext($single, $plural, $number) { - if ($this->short_circuit) { - if ($number != 1) - return $plural; - else - return $single; - } + $this->STREAM = $Reader; + $magic = $this->readint(); + if ($magic == ($MAGIC1 & 0xFFFFFFFF) || $magic == ($MAGIC3 & 0xFFFFFFFF)) { // to make sure it works for 64-bit platforms + $this->BYTEORDER = 0; + } elseif ($magic == ($MAGIC2 & 0xFFFFFFFF)) { + $this->BYTEORDER = 1; + } else { + $this->error = 1; // not MO file + return false; + } - // find out the appropriate form - $select = $this->select_string($number); - - // this should contains all strings separated by NULLs - $key = $single.chr(0).$plural; - - - if ($this->enable_cache) { - if (! array_key_exists($key, $this->cache_translations)) { - return ($number != 1) ? $plural : $single; - } else { - $result = $this->cache_translations[$key]; - $list = explode(chr(0), $result); - return $list[$select]; - } - } else { - $num = $this->find_string($key); - if ($num == -1) { - return ($number != 1) ? $plural : $single; - } else { - $result = $this->get_translation_string($num); - $list = explode(chr(0), $result); - return $list[$select]; - } - } - } + // FIXME: Do we care about revision? We should. + $revision = $this->readint(); + $this->total = $this->readint(); + $this->originals = $this->readint(); + $this->translations = $this->readint(); + } + + /** + * Loads the translation tables from the MO file into the cache + * If caching is enabled, also loads all strings into a cache + * to speed up translation lookups + * + * @access private + */ + function load_tables() { + if (is_array($this->cache_translations) && + is_array($this->table_originals) && + is_array($this->table_translations)) + return; + + /* get original and translations tables */ + $this->STREAM->seekto($this->originals); + $this->table_originals = $this->readintarray($this->total * 2); + $this->STREAM->seekto($this->translations); + $this->table_translations = $this->readintarray($this->total * 2); + + if ($this->enable_cache) { + $this->cache_translations = array (); + /* read all strings in the cache */ + for ($i = 0; $i < $this->total; $i++) { + $this->STREAM->seekto($this->table_originals[$i * 2 + 2]); + $original = $this->STREAM->read($this->table_originals[$i * 2 + 1]); + $this->STREAM->seekto($this->table_translations[$i * 2 + 2]); + $translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]); + $this->cache_translations[$original] = $translation; + } + } + } + + /** + * Returns a string from the "originals" table + * + * @access private + * @param int num Offset number of original string + * @return string Requested string if found, otherwise '' + */ + function get_original_string($num) { + $length = $this->table_originals[$num * 2 + 1]; + $offset = $this->table_originals[$num * 2 + 2]; + if (! $length) + return ''; + $this->STREAM->seekto($offset); + $data = $this->STREAM->read($length); + return (string)$data; + } + + /** + * Returns a string from the "translations" table + * + * @access private + * @param int num Offset number of original string + * @return string Requested string if found, otherwise '' + */ + function get_translation_string($num) { + $length = $this->table_translations[$num * 2 + 1]; + $offset = $this->table_translations[$num * 2 + 2]; + if (! $length) + return ''; + $this->STREAM->seekto($offset); + $data = $this->STREAM->read($length); + return (string)$data; + } + + /** + * Binary search for string + * + * @access private + * @param string string + * @param int start (internally used in recursive function) + * @param int end (internally used in recursive function) + * @return int string number (offset in originals table) + */ + function find_string($string, $start = -1, $end = -1) { + if (($start == -1) or ($end == -1)) { + // find_string is called with only one parameter, set start end end + $start = 0; + $end = $this->total; + } + if (abs($start - $end) <= 1) { + // We're done, now we either found the string, or it doesn't exist + $txt = $this->get_original_string($start); + if ($string == $txt) + return $start; + else + return -1; + } else if ($start > $end) { + // start > end -> turn around and start over + return $this->find_string($string, $end, $start); + } else { + // Divide table in two parts + $half = (int)(($start + $end) / 2); + $cmp = strcmp($string, $this->get_original_string($half)); + if ($cmp == 0) + // string is exactly in the middle => return it + return $half; + else if ($cmp < 0) + // The string is in the upper half + return $this->find_string($string, $start, $half); + else + // The string is in the lower half + return $this->find_string($string, $half, $end); + } + } + + /** + * Translates a string + * + * @access public + * @param string string to be translated + * @return string translated string (or original, if not found) + */ + function translate($string) { + if ($this->short_circuit) + return $string; + $this->load_tables(); + + if ($this->enable_cache) { + // Caching enabled, get translated string from cache + if (array_key_exists($string, $this->cache_translations)) + return $this->cache_translations[$string]; + else + return $string; + } else { + // Caching not enabled, try to find string + $num = $this->find_string($string); + if ($num == -1) + return $string; + else + return $this->get_translation_string($num); + } + } + + /** + * Get possible plural forms from MO header + * + * @access private + * @return string plural form header + */ + function get_plural_forms() { + // lets assume message number 0 is header + // this is true, right? + $this->load_tables(); + + // cache header field for plural forms + if (! is_string($this->pluralheader)) { + if ($this->enable_cache) { + $header = $this->cache_translations[""]; + } else { + $header = $this->get_translation_string(0); + } + $header .= "\n"; //make sure our regex matches + if (eregi("plural-forms: ([^\n]*)\n", $header, $regs)) + $expr = $regs[1]; + else + $expr = "nplurals=2; plural=n == 1 ? 0 : 1;"; + + // add parentheses + // important since PHP's ternary evaluates from left to right + $expr.= ';'; + $res= ''; + $p= 0; + for ($i= 0; $i < strlen($expr); $i++) { + $ch= $expr[$i]; + switch ($ch) { + case '?': + $res.= ' ? ('; + $p++; + break; + case ':': + $res.= ') : ('; + break; + case ';': + $res.= str_repeat( ')', $p) . ';'; + $p= 0; + break; + default: + $res.= $ch; + } + } + $this->pluralheader = $res; + } + + return $this->pluralheader; + } + + /** + * Detects which plural form to take + * + * @access private + * @param n count + * @return int array index of the right plural form + */ + function select_string($n) { + if (is_null($this->select_string_function)) { + $string = $this->get_plural_forms(); + if (preg_match("/nplurals\s*=\s*(\d+)\s*\;\s*plural\s*=\s*(.*?)\;+/", $string, $matches)) { + $nplurals = $matches[1]; + $expression = $matches[2]; + $expression = str_replace("n", '$n', $expression); + } else { + $nplurals = 2; + $expression = ' $n == 1 ? 0 : 1 '; + } + $func_body = " + \$plural = ($expression); + return (\$plural <= $nplurals)? \$plural : \$plural - 1;"; + $this->select_string_function = create_function('$n', $func_body); + } + return call_user_func($this->select_string_function, $n); + } + + /** + * Plural version of gettext + * + * @access public + * @param string single + * @param string plural + * @param string number + * @return translated plural form + */ + function ngettext($single, $plural, $number) { + if ($this->short_circuit) { + if ($number != 1) + return $plural; + else + return $single; + } + + // find out the appropriate form + $select = $this->select_string($number); + + // this should contains all strings separated by NULLs + $key = $single.chr(0).$plural; + + + if ($this->enable_cache) { + if (! array_key_exists($key, $this->cache_translations)) { + return ($number != 1) ? $plural : $single; + } else { + $result = $this->cache_translations[$key]; + $list = explode(chr(0), $result); + return $list[$select]; + } + } else { + $num = $this->find_string($key); + if ($num == -1) { + return ($number != 1) ? $plural : $single; + } else { + $result = $this->get_translation_string($num); + $list = explode(chr(0), $result); + return $list[$select]; + } + } + } + } ?> Index: wp-includes/class-phpmailer.php =================================================================== --- wp-includes/class-phpmailer.php (.../2.1.3) (revision 0) +++ wp-includes/class-phpmailer.php (.../2.2) (revision 5482) @@ -0,0 +1,1498 @@ +ContentType = "text/html"; + else + $this->ContentType = "text/plain"; + } + + /** + * Sets Mailer to send message using SMTP. + * @return void + */ + function IsSMTP() { + $this->Mailer = "smtp"; + } + + /** + * Sets Mailer to send message using PHP mail() function. + * @return void + */ + function IsMail() { + $this->Mailer = "mail"; + } + + /** + * Sets Mailer to send message using the $Sendmail program. + * @return void + */ + function IsSendmail() { + $this->Mailer = "sendmail"; + } + + /** + * Sets Mailer to send message using the qmail MTA. + * @return void + */ + function IsQmail() { + $this->Sendmail = "/var/qmail/bin/sendmail"; + $this->Mailer = "sendmail"; + } + + + ///////////////////////////////////////////////// + // RECIPIENT METHODS + ///////////////////////////////////////////////// + + /** + * Adds a "To" address. + * @param string $address + * @param string $name + * @return void + */ + function AddAddress($address, $name = "") { + $cur = count($this->to); + $this->to[$cur][0] = trim($address); + $this->to[$cur][1] = $name; + } + + /** + * Adds a "Cc" address. Note: this function works + * with the SMTP mailer on win32, not with the "mail" + * mailer. + * @param string $address + * @param string $name + * @return void + */ + function AddCC($address, $name = "") { + $cur = count($this->cc); + $this->cc[$cur][0] = trim($address); + $this->cc[$cur][1] = $name; + } + + /** + * Adds a "Bcc" address. Note: this function works + * with the SMTP mailer on win32, not with the "mail" + * mailer. + * @param string $address + * @param string $name + * @return void + */ + function AddBCC($address, $name = "") { + $cur = count($this->bcc); + $this->bcc[$cur][0] = trim($address); + $this->bcc[$cur][1] = $name; + } + + /** + * Adds a "Reply-to" address. + * @param string $address + * @param string $name + * @return void + */ + function AddReplyTo($address, $name = "") { + $cur = count($this->ReplyTo); + $this->ReplyTo[$cur][0] = trim($address); + $this->ReplyTo[$cur][1] = $name; + } + + + ///////////////////////////////////////////////// + // MAIL SENDING METHODS + ///////////////////////////////////////////////// + + /** + * Creates message and assigns Mailer. If the message is + * not sent successfully then it returns false. Use the ErrorInfo + * variable to view description of the error. + * @return bool + */ + function Send() { + $header = ""; + $body = ""; + $result = true; + + if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) + { + $this->SetError($this->Lang("provide_address")); + return false; + } + + // Set whether the message is multipart/alternative + if(!empty($this->AltBody)) + $this->ContentType = "multipart/alternative"; + + $this->error_count = 0; // reset errors + $this->SetMessageType(); + $header .= $this->CreateHeader(); + $body = $this->CreateBody(); + + if($body == "") { return false; } + + // Choose the mailer + switch($this->Mailer) + { + case "sendmail": + $result = $this->SendmailSend($header, $body); + break; + case "mail": + $result = $this->MailSend($header, $body); + break; + case "smtp": + $result = $this->SmtpSend($header, $body); + break; + default: + $this->SetError($this->Mailer . $this->Lang("mailer_not_supported")); + $result = false; + break; + } + + return $result; + } + + /** + * Sends mail using the $Sendmail program. + * @access private + * @return bool + */ + function SendmailSend($header, $body) { + if ($this->Sender != "") + $sendmail = sprintf("%s -oi -f %s -t", $this->Sendmail, $this->Sender); + else + $sendmail = sprintf("%s -oi -t", $this->Sendmail); + + if(!@$mail = popen($sendmail, "w")) + { + $this->SetError($this->Lang("execute") . $this->Sendmail); + return false; + } + + fputs($mail, $header); + fputs($mail, $body); + + $result = pclose($mail) >> 8 & 0xFF; + if($result != 0) + { + $this->SetError($this->Lang("execute") . $this->Sendmail); + return false; + } + + return true; + } + + /** + * Sends mail using the PHP mail() function. + * @access private + * @return bool + */ + function MailSend($header, $body) { + $to = ""; + for($i = 0; $i < count($this->to); $i++) + { + if($i != 0) { $to .= ", "; } + $to .= $this->to[$i][0]; + } + + if ($this->Sender != "" && strlen(ini_get("safe_mode"))< 1) + { + $old_from = ini_get("sendmail_from"); + ini_set("sendmail_from", $this->Sender); + $params = sprintf("-oi -f %s", $this->Sender); + $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, + $header, $params); + } + else + $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, $header); + + if (isset($old_from)) + ini_set("sendmail_from", $old_from); + + if(!$rt) + { + $this->SetError($this->Lang("instantiate")); + return false; + } + + return true; + } + + /** + * Sends mail via SMTP using PhpSMTP (Author: + * Chris Ryan). Returns bool. Returns false if there is a + * bad MAIL FROM, RCPT, or DATA input. + * @access private + * @return bool + */ + function SmtpSend($header, $body) { + include_once($this->PluginDir . "class.smtp.php"); + $error = ""; + $bad_rcpt = array(); + + if(!$this->SmtpConnect()) + return false; + + $smtp_from = ($this->Sender == "") ? $this->From : $this->Sender; + if(!$this->smtp->Mail($smtp_from)) + { + $error = $this->Lang("from_failed") . $smtp_from; + $this->SetError($error); + $this->smtp->Reset(); + return false; + } + + // Attempt to send attach all recipients + for($i = 0; $i < count($this->to); $i++) + { + if(!$this->smtp->Recipient($this->to[$i][0])) + $bad_rcpt[] = $this->to[$i][0]; + } + for($i = 0; $i < count($this->cc); $i++) + { + if(!$this->smtp->Recipient($this->cc[$i][0])) + $bad_rcpt[] = $this->cc[$i][0]; + } + for($i = 0; $i < count($this->bcc); $i++) + { + if(!$this->smtp->Recipient($this->bcc[$i][0])) + $bad_rcpt[] = $this->bcc[$i][0]; + } + + if(count($bad_rcpt) > 0) // Create error message + { + for($i = 0; $i < count($bad_rcpt); $i++) + { + if($i != 0) { $error .= ", "; } + $error .= $bad_rcpt[$i]; + } + $error = $this->Lang("recipients_failed") . $error; + $this->SetError($error); + $this->smtp->Reset(); + return false; + } + + if(!$this->smtp->Data($header . $body)) + { + $this->SetError($this->Lang("data_not_accepted")); + $this->smtp->Reset(); + return false; + } + if($this->SMTPKeepAlive == true) + $this->smtp->Reset(); + else + $this->SmtpClose(); + + return true; + } + + /** + * Initiates a connection to an SMTP server. Returns false if the + * operation failed. + * @access private + * @return bool + */ + function SmtpConnect() { + if($this->smtp == NULL) { $this->smtp = new SMTP(); } + + $this->smtp->do_debug = $this->SMTPDebug; + $hosts = explode(";", $this->Host); + $index = 0; + $connection = ($this->smtp->Connected()); + + // Retry while there is no connection + while($index < count($hosts) && $connection == false) + { + if(strstr($hosts[$index], ":")) + list($host, $port) = explode(":", $hosts[$index]); + else + { + $host = $hosts[$index]; + $port = $this->Port; + } + + if($this->smtp->Connect($host, $port, $this->Timeout)) + { + if ($this->Helo != '') + $this->smtp->Hello($this->Helo); + else + $this->smtp->Hello($this->ServerHostname()); + + if($this->SMTPAuth) + { + if(!$this->smtp->Authenticate($this->Username, + $this->Password)) + { + $this->SetError($this->Lang("authenticate")); + $this->s