diff options
author | donncha <donncha@7be80a69-a1ef-0310-a953-fb0f7c49ff36> | 2007-05-21 18:37:58 +0000 |
---|---|---|
committer | donncha <donncha@7be80a69-a1ef-0310-a953-fb0f7c49ff36> | 2007-05-21 18:37:58 +0000 |
commit | 89fe0ff804e7c6497ebacc8b341ac89974f6f255 (patch) | |
tree | 3fce310b29c685008fdbb75c5ab531bc3a6ae12a /wp-includes | |
parent | a139071806ba941346a109fbefb2d5f22bae1cc4 (diff) | |
download | wordpress-mu-89fe0ff804e7c6497ebacc8b341ac89974f6f255.tar.gz wordpress-mu-89fe0ff804e7c6497ebacc8b341ac89974f6f255.tar.xz wordpress-mu-89fe0ff804e7c6497ebacc8b341ac89974f6f255.zip |
WP Merge to rev 5499, this is a big one! Test it before you put it live!
Test only, not for production use yet
git-svn-id: http://svn.automattic.com/wordpress-mu/trunk@972 7be80a69-a1ef-0310-a953-fb0f7c49ff36
Diffstat (limited to 'wp-includes')
72 files changed, 6131 insertions, 4251 deletions
diff --git a/wp-includes/author-template.php b/wp-includes/author-template.php index aa4013d..6006cf3 100644 --- a/wp-includes/author-template.php +++ b/wp-includes/author-template.php @@ -173,24 +173,28 @@ function get_author_name( $auth_id ) { } function wp_list_authors($args = '') { - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('optioncount' => false, 'exclude_admin' => true, 'show_fullname' => false, 'hide_empty' => true, - 'feed' => '', 'feed_image' => ''); - $r = array_merge($defaults, $r); - extract($r); - global $wpdb; + + $defaults = array( + 'optioncount' => false, 'exclude_admin' => true, + 'show_fullname' => false, 'hide_empty' => true, + 'feed' => '', 'feed_image' => '' + ); + + $r = wp_parse_args( $args, $defaults ); + extract($r); + // 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 != '') ) diff --git a/wp-includes/bookmark-template.php b/wp-includes/bookmark-template.php index e7a8480..2a06cf2 100644 --- a/wp-includes/bookmark-template.php +++ b/wp-includes/bookmark-template.php @@ -9,28 +9,23 @@ **/ function wp_get_links($args = '') { global $wpdb; - - if ( empty($args) ) - return; - - if ( false === strpos($args, '=') ) { + + if ( strpos( $args, '=' ) === false ) { $cat_id = $args; - $args = add_query_arg('category', $cat_id, $args); + $args = add_query_arg( 'category', $cat_id, $args ); } - - parse_str($args); - - if ( !isset($category) ) $category = -1; - if ( !isset($before) ) $before = ''; - if ( !isset($after) ) $after = '<br />'; - if ( !isset($between) ) $between = ' '; - if ( !isset($show_images) ) $show_images = true; - if ( !isset($orderby) ) $orderby = 'name'; - if ( !isset($show_description) ) $show_description = true; - if ( !isset($show_rating) ) $show_rating = false; - if ( !isset($limit) ) $limit = -1; - if ( !isset($show_updated) ) $show_updated = 1; - if ( !isset($echo) ) $echo = true; + + $defaults = array( + 'category' => -1, 'before' => '', + 'after' => '<br />', 'between' => ' ', + 'show_images' => true, 'orderby' => 'name', + 'show_description' => true, 'show_rating' => false, + 'limit' => -1, 'show_updated' => true, + 'echo' => true + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); return get_links($category, $before, $after, $between, $show_images, $orderby, $show_description, $show_rating, $limit, $show_updated, $echo); } // end wp_get_links @@ -136,6 +131,10 @@ function get_links($category = -1, if ( $show_description && '' != $desc ) $output .= $between . $desc; + + if ($show_rating) { + $output .= $between . get_linkrating($row); + } $output .= "$after\n"; } // end while @@ -241,15 +240,14 @@ function get_links_list($order = 'name', $hide_if_empty = 'obsolete') { } function _walk_bookmarks($bookmarks, $args = '' ) { - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('show_updated' => 0, 'show_description' => 0, 'show_images' => 1, 'before' => '<li>', - 'after' => '</li>', 'between' => "\n"); - $r = array_merge($defaults, $r); - extract($r); + $defaults = array( + 'show_updated' => 0, 'show_description' => 0, + 'show_images' => 1, 'before' => '<li>', + 'after' => '</li>', 'between' => "\n" + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); foreach ( (array) $bookmarks as $bookmark ) { if ( !isset($bookmark->recently_updated) ) @@ -304,6 +302,11 @@ function _walk_bookmarks($bookmarks, $args = '' ) { if ( $show_description && '' != $desc ) $output .= $between . $desc; + + if ($show_rating) { + $output .= $between . get_linkrating($bookmark); + } + $output .= "$after\n"; } // end while @@ -311,18 +314,20 @@ function _walk_bookmarks($bookmarks, $args = '' ) { } function wp_list_bookmarks($args = '') { - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('orderby' => 'name', 'order' => 'ASC', 'limit' => -1, 'category' => '', - 'category_name' => '', 'hide_invisible' => 1, 'show_updated' => 0, 'echo' => 1, - 'categorize' => 1, 'title_li' => __('Bookmarks'), 'title_before' => '<h2>', 'title_after' => '</h2>', - 'category_orderby' => 'name', 'category_order' => 'ASC', 'class' => 'linkcat', - 'category_before' => '<li id="%id" class="%class">', 'category_after' => '</li>'); - $r = array_merge($defaults, $r); - extract($r); + $defaults = array( + 'orderby' => 'name', 'order' => 'ASC', + 'limit' => -1, 'category' => '', + 'category_name' => '', 'hide_invisible' => 1, + 'show_updated' => 0, 'echo' => 1, + 'categorize' => 1, 'title_li' => __('Bookmarks'), + 'title_before' => '<h2>', 'title_after' => '</h2>', + 'category_orderby' => 'name', 'category_order' => 'ASC', + 'class' => 'linkcat', 'category_before' => '<li id="%id" class="%class">', + 'category_after' => '</li>' + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); $output = ''; diff --git a/wp-includes/bookmark.php b/wp-includes/bookmark.php index 5aea9a8..ad2e696 100644 --- a/wp-includes/bookmark.php +++ b/wp-includes/bookmark.php @@ -3,6 +3,7 @@ function get_bookmark($bookmark_id, $output = OBJECT) { global $wpdb; + $bookmark_id = (int) $bookmark_id; $link = $wpdb->get_row("SELECT * FROM $wpdb->links WHERE link_id = '$bookmark_id'"); $link->link_category = wp_get_link_cats($bookmark_id); @@ -24,16 +25,17 @@ function get_link($bookmark_id, $output = OBJECT) { function get_bookmarks($args = '') { global $wpdb; - - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('orderby' => 'name', 'order' => 'ASC', 'limit' => -1, 'category' => '', - 'category_name' => '', 'hide_invisible' => 1, 'show_updated' => 0, 'include' => '', 'exclude' => ''); - $r = array_merge($defaults, $r); - extract($r); + + $defaults = array( + 'orderby' => 'name', 'order' => 'ASC', + 'limit' => -1, 'category' => '', + 'category_name' => '', 'hide_invisible' => 1, + 'show_updated' => 0, 'include' => '', + 'exclude' => '' + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); $key = md5( serialize( $r ) ); if ( $cache = wp_cache_get( 'get_bookmarks', 'bookmark' ) ) @@ -135,7 +137,7 @@ function get_bookmarks($args = '') { $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); } diff --git a/wp-includes/cache.php b/wp-includes/cache.php index e89e5f6..6901a6b 100644 --- a/wp-includes/cache.php +++ b/wp-includes/cache.php @@ -364,10 +364,9 @@ class WP_Object_Cache { 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);
}
diff --git a/wp-includes/category-template.php b/wp-includes/category-template.php index db45dc0..d4c521e 100644 --- a/wp-includes/category-template.php +++ b/wp-includes/category-template.php @@ -172,20 +172,21 @@ function category_description($category = 0) { } function wp_dropdown_categories($args = '') { - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('show_option_all' => '', 'show_option_none' => '', 'orderby' => 'ID', - 'order' => 'ASC', 'show_last_update' => 0, 'show_count' => 0, - 'hide_empty' => 1, 'child_of' => 0, 'exclude' => '', 'echo' => 1, - 'selected' => 0, 'hierarchical' => 0, 'name' => 'cat', - 'class' => 'postform'); + $defaults = array( + 'show_option_all' => '', 'show_option_none' => '', + 'orderby' => 'ID', 'order' => 'ASC', + 'show_last_update' => 0, 'show_count' => 0, + 'hide_empty' => 1, 'child_of' => 0, + 'exclude' => '', 'echo' => 1, + 'selected' => 0, 'hierarchical' => 0, + 'name' => 'cat', 'class' => 'postform' + ); + $defaults['selected'] = ( is_category() ) ? get_query_var('cat') : 0; - $r = array_merge($defaults, $r); + + $r = wp_parse_args( $args, $defaults ); $r['include_last_update_time'] = $r['show_last_update']; - extract($r); + extract( $r ); $categories = get_categories($r); @@ -221,23 +222,28 @@ function wp_dropdown_categories($args = '') { } function wp_list_categories($args = '') { - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('show_option_all' => '', 'orderby' => 'name', - 'order' => 'ASC', 'show_last_update' => 0, 'style' => 'list', - 'show_count' => 0, 'hide_empty' => 1, 'use_desc_for_title' => 1, - 'child_of' => 0, 'feed' => '', 'feed_image' => '', 'exclude' => '', - 'hierarchical' => true, 'title_li' => __('Categories')); - $r = array_merge($defaults, $r); - if ( !isset($r['pad_counts']) && $r['show_count'] && $r['hierarchical'] ) + $defaults = array( + 'show_option_all' => '', 'orderby' => 'name', + 'order' => 'ASC', 'show_last_update' => 0, + 'style' => 'list', 'show_count' => 0, + 'hide_empty' => 1, 'use_desc_for_title' => 1, + 'child_of' => 0, 'feed' => '', + 'feed_image' => '', 'exclude' => '', + 'hierarchical' => true, 'title_li' => __('Categories') + ); + + $r = wp_parse_args( $args, $defaults ); + + if ( !isset( $r['pad_counts'] ) && $r['show_count'] && $r['hierarchical'] ) { $r['pad_counts'] = true; - if ( isset($r['show_date']) ) + } + + if ( isset( $r['show_date'] ) ) { $r['include_last_update_time'] = $r['show_date']; - extract($r); - + } + + extract( $r ); + $categories = get_categories($r); $output = ''; @@ -251,7 +257,13 @@ function wp_list_categories($args = '') { $output .= __("No categories"); } else { global $wp_query; - + + if( !empty($show_option_all) ) + if ('list' == $style ) + $output .= '<li><a href="' . get_bloginfo('url') . '">' . $show_option_all . '</a></li>'; + else + $output .= '<a href="' . get_bloginfo('url') . '">' . $show_option_all . '</a>'; + if ( is_category() ) $r['current_category'] = $wp_query->get_queried_object_id(); diff --git a/wp-includes/category.php b/wp-includes/category.php index 2ba3d30..b14685d 100644 --- a/wp-includes/category.php +++ b/wp-includes/category.php @@ -13,22 +13,25 @@ function get_all_category_ids() { function &get_categories($args = '') { global $wpdb, $category_links; - - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('type' => 'post', 'child_of' => 0, 'orderby' => 'name', 'order' => 'ASC', - 'hide_empty' => true, 'include_last_update_time' => false, 'hierarchical' => 1, 'exclude' => '', 'include' => '', - 'number' => '', 'pad_counts' => false); - $r = array_merge($defaults, $r); - if ( 'count' == $r['orderby'] ) + + $defaults = array( + 'type' => 'post', 'child_of' => 0, + 'orderby' => 'name', 'order' => 'ASC', + 'hide_empty' => true, 'include_last_update_time' => false, + 'hierarchical' => 1, 'exclude' => '', + 'include' => '', 'number' => '', + 'pad_counts' => false + ); + + $r = wp_parse_args( $args, $defaults ); + + if ( $r['orderby'] == 'count' ) { $r['orderby'] = 'category_count'; - else - $r['orderby'] = "cat_" . $r['orderby']; // restricts order by to cat_ID and cat_name fields - $r['number'] = (int) $r['number']; - extract($r); + } else { + $r['orderby'] = 'cat_' . $r['orderby']; + } + + extract( $r ); $key = md5( serialize( $r ) ); if ( $cache = wp_cache_get( 'get_categories', 'category' ) ) @@ -79,6 +82,8 @@ function &get_categories($args = '') { $where .= ' AND category_count > 0'; } + + if ( !empty($number) ) $number = 'LIMIT ' . $number; else @@ -105,8 +110,11 @@ function &get_categories($args = '') { 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 ) @@ -131,7 +139,8 @@ function &get_categories($args = '') { $cache[ $key ] = $categories; wp_cache_set( '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. @@ -146,6 +155,7 @@ function &get_category(&$category, $output = OBJECT) { wp_cache_add($category->cat_ID, $category, 'category'); $_category = $category; } else { + $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'); @@ -201,6 +211,15 @@ function get_category_by_path($category_path, $full_match = true, $output = OBJE return NULL; } +function get_category_by_slug( $slug ) { + global $wpdb; + $slug = sanitize_title( $slug ); + if ( empty( $slug ) ) + return false; + $category = $wpdb->get_var( "SELECT * FROM $wpdb->categories WHERE category_nicename = '$slug' " ); + return get_category( $category ); +} + // Get the ID of a category from its name function get_cat_ID($cat_name='General') { global $wpdb; @@ -246,12 +265,21 @@ function &_get_cat_children($category_id, $categories) { 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); } @@ -299,4 +327,20 @@ function _pad_category_counts($type, &$categories) { $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; +} + ?> diff --git a/wp-includes/class-phpmailer.php b/wp-includes/class-phpmailer.php index de6b277..ad439fe 100644 --- a/wp-includes/class-phpmailer.php +++ b/wp-includes/class-phpmailer.php @@ -1,1498 +1,1498 @@ -<?php
-////////////////////////////////////////////////////
-// PHPMailer - PHP email class
-//
-// Class for sending email using either
-// sendmail, PHP mail(), or SMTP. Methods are
-// based upon the standard AspEmail(tm) classes.
-//
-// Copyright (C) 2001 - 2003 Brent R. Matzelle
-//
-// License: LGPL, see LICENSE
-////////////////////////////////////////////////////
-
-/**
- * PHPMailer - PHP email transport class
- * @package PHPMailer
- * @author Brent R. Matzelle
- * @copyright 2001 - 2003 Brent R. Matzelle
- */
-class PHPMailer
-{
- /////////////////////////////////////////////////
- // PUBLIC VARIABLES
- /////////////////////////////////////////////////
-
- /**
- * Email priority (1 = High, 3 = Normal, 5 = low).
- * @var int
- */
- var $Priority = 3;
-
- /**
- * Sets the CharSet of the message.
- * @var string
- */
- var $CharSet = "UTF-8";
-
- /**
- * Sets the Content-type of the message.
- * @var string
- */
- var $ContentType = "text/plain";
-
- /**
- * Sets the Encoding of the message. Options for this are "8bit",
- * "7bit", "binary", "base64", and "quoted-printable".
- * @var string
- */
- var $Encoding = "8bit";
-
- /**
- * Holds the most recent mailer error message.
- * @var string
- */
- var $ErrorInfo = "";
-
- /**
- * Sets the From email address for the message.
- * @var string
- */
- var $From = "support@wordpress.com";
-
- /**
- * Sets the From name of the message.
- * @var string
- */
- var $FromName = "Support";
-
- /**
- * Sets the Sender email (Return-Path) of the message. If not empty,
- * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
- * @var string
- */
- var $Sender = "";
-
- /**
- * Sets the Subject of the message.
- * @var string
- */
- var $Subject = "";
-
- /**
- * Sets the Body of the message. This can be either an HTML or text body.
- * If HTML then run IsHTML(true).
- * @var string
- */
- var $Body = "";
-
- /**
- * Sets the text-only body of the message. This automatically sets the
- * email to multipart/alternative. This body can be read by mail
- * clients that do not have HTML email capability such as mutt. Clients
- * that can read HTML will view the normal Body.
- * @var string
- */
- var $AltBody = "";
-
- /**
- * Sets word wrapping on the body of the message to a given number of
- * characters.
- * @var int
- */
- var $WordWrap = 0;
-
- /**
- * Method to send mail: ("mail", "sendmail", or "smtp").
- * @var string
- */
- var $Mailer = "mail";
-
- /**
- * Sets the path of the sendmail program.
- * @var string
- */
- var $Sendmail = "/usr/sbin/sendmail";
-
- /**
- * Path to PHPMailer plugins. This is now only useful if the SMTP class
- * is in a different directory than the PHP include path.
- * @var string
- */
- var $PluginDir = "";
-
- /**
- * Holds PHPMailer version.
- * @var string
- */
- var $Version = "1.73";
-
- /**
- * Sets the email address that a reading confirmation will be sent.
- * @var string
- */
- var $ConfirmReadingTo = "";
-
- /**
- * Sets the hostname to use in Message-Id and Received headers
- * and as default HELO string. If empty, the value returned
- * by SERVER_NAME is used or 'localhost.localdomain'.
- * @var string
- */
- var $Hostname = "";
-
- /////////////////////////////////////////////////
- // SMTP VARIABLES
- /////////////////////////////////////////////////
-
- /**
- * Sets the SMTP hosts. All hosts must be separated by a
- * semicolon. You can also specify a different port
- * for each host by using this format: [hostname:port]
- * (e.g. "smtp1.example.com:25;smtp2.example.com").
- * Hosts will be tried in order.
- * @var string
- */
- var $Host = "localhost";
-
- /**
- * Sets the default SMTP server port.
- * @var int
- */
- var $Port = 25;
-
- /**
- * Sets the SMTP HELO of the message (Default is $Hostname).
- * @var string
- */
- var $Helo = "";
-
- /**
- * Sets SMTP authentication. Utilizes the Username and Password variables.
- * @var bool
- */
- var $SMTPAuth = false;
-
- /**
- * Sets SMTP username.
- * @var string
- */
- var $Username = "";
-
- /**
- * Sets SMTP password.
- * @var string
- */
- var $Password = "";
-
- /**
- * Sets the SMTP server timeout in seconds. This function will not
- * work with the win32 version.
- * @var int
- */
- var $Timeout = 10;
-
- /**
- * Sets SMTP class debugging on or off.
- * @var bool
- */
- var $SMTPDebug = false;
-
- /**
- * Prevents the SMTP connection from being closed after each mail
- * sending. If this is set to true then to close the connection
- * requires an explicit call to SmtpClose().
- * @var bool
- */
- var $SMTPKeepAlive = false;
-
- /**#@+
- * @access private
- */
- var $smtp = NULL;
- var $to = array();
- var $cc = array();
- var $bcc = array();
- var $ReplyTo = array();
- var $attachment = array();
- var $CustomHeader = array();
- var $message_type = "";
- var $boundary = array();
- var $language = array();
- var $error_count = 0;
- var $LE = "\n";
- /**#@-*/
-
- /////////////////////////////////////////////////
- // VARIABLE METHODS
- /////////////////////////////////////////////////
-
- /**
- * Sets message type to HTML.
- * @param bool $bool
- * @return void
- */
- function IsHTML($bool) {
- if($bool == true)
- $this->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->smtp->Reset();
- $connection = false;
- }
- }
- $connection = true;
- }
- $index++;
- }
- if(!$connection)
- $this->SetError($this->Lang("connect_host"));
-
- return $connection;
- }
-
- /**
- * Closes the active SMTP session if one exists.
- * @return void
- */
- function SmtpClose() {
- if($this->smtp != NULL)
- {
- if($this->smtp->Connected())
- {
- $this->smtp->Quit();
- $this->smtp->Close();
- }
- }
- }
-
- /**
- * Sets the language for all class error messages. Returns false
- * if it cannot load the language file. The default language type
- * is English.
- * @param string $lang_type Type of language (e.g. Portuguese: "br")
- * @param string $lang_path Path to the language file directory
- * @access public
- * @return bool
- */
- function SetLanguage($lang_type, $lang_path = "language/") {
- if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php'))
- include($lang_path.'phpmailer.lang-'.$lang_type.'.php');
- else if(file_exists($lang_path.'phpmailer.lang-en.php'))
- include($lang_path.'phpmailer.lang-en.php');
- else
- {
- $this->SetError("Could not load language file");
- return false;
- }
- $this->language = $PHPMAILER_LANG;
-
- return true;
- }
-
- /////////////////////////////////////////////////
- // MESSAGE CREATION METHODS
- /////////////////////////////////////////////////
-
- /**
- * Creates recipient headers.
- * @access private
- * @return string
- */
- function AddrAppend($type, $addr) {
- $addr_str = $type . ": ";
- $addr_str .= $this->AddrFormat($addr[0]);
- if(count($addr) > 1)
- {
- for($i = 1; $i < count($addr); $i++)
- $addr_str .= ", " . $this->AddrFormat($addr[$i]);
- }
- $addr_str .= $this->LE;
-
- return $addr_str;
- }
-
- /**
- * Formats an address correctly.
- * @access private
- * @return string
- */
- function AddrFormat($addr) {
- if(empty($addr[1]))
- $formatted = $addr[0];
- else
- {
- $formatted = $this->EncodeHeader($addr[1], 'phrase') . " <" .
- $addr[0] . ">";
- }
-
- return $formatted;
- }
-
- /**
- * Wraps message for use with mailers that do not
- * automatically perform wrapping and for quoted-printable.
- * Original written by philippe.
- * @access private
- * @return string
- */
- function WrapText($message, $length, $qp_mode = false) {
- $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
-
- $message = $this->FixEOL($message);
- if (substr($message, -1) == $this->LE)
- $message = substr($message, 0, -1);
-
- $line = explode($this->LE, $message);
- $message = "";
- for ($i=0 ;$i < count($line); $i++)
- {
- $line_part = explode(" ", $line[$i]);
- $buf = "";
- for ($e = 0; $e<count($line_part); $e++)
- {
- $word = $line_part[$e];
- if ($qp_mode and (strlen($word) > $length))
- {
- $space_left = $length - strlen($buf) - 1;
- if ($e != 0)
- {
- if ($space_left > 20)
- {
- $len = $space_left;
- if (substr($word, $len - 1, 1) == "=")
- $len--;
- elseif (substr($word, $len - 2, 1) == "=")
- $len -= 2;
- $part = substr($word, 0, $len);
- $word = substr($word, $len);
- $buf .= " " . $part;
- $message .= $buf . sprintf("=%s", $this->LE);
- }
- else
- {
- $message .= $buf . $soft_break;
- }
- $buf = "";
- }
- while (strlen($word) > 0)
- {
- $len = $length;
- if (substr($word, $len - 1, 1) == "=")
- $len--;
- elseif (substr($word, $len - 2, 1) == "=")
- $len -= 2;
- $part = substr($word, 0, $len);
- $word = substr($word, $len);
-
- if (strlen($word) > 0)
- $message .= $part . sprintf("=%s", $this->LE);
- else
- $buf = $part;
- }
- }
- else
- {
- $buf_o = $buf;
- $buf .= ($e == 0) ? $word : (" " . $word);
-
- if (strlen($buf) > $length and $buf_o != "")
- {
- $message .= $buf_o . $soft_break;
- $buf = $word;
- }
- }
- }
- $message .= $buf . $this->LE;
- }
-
- return $message;
- }
-
- /**
- * Set the body wrapping.
- * @access private
- * @return void
- */
- function SetWordWrap() {
- if($this->WordWrap < 1)
- return;
-
- switch($this->message_type)
- {
- case "alt":
- // fall through
- case "alt_attachments":
- $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
- break;
- default:
- $this->Body = $this->WrapText($this->Body, $this->WordWrap);
- break;
- }
- }
-
- /**
- * Assembles message header.
- * @access private
- * @return string
- */
- function CreateHeader() {
- $result = "";
-
- // Set the boundaries
- $uniq_id = md5(uniqid(time()));
- $this->boundary[1] = "b1_" . $uniq_id;
- $this->boundary[2] = "b2_" . $uniq_id;
-
- $result .= $this->HeaderLine("Date", $this->RFCDate());
- if($this->Sender == "")
- $result .= $this->HeaderLine("Return-Path", trim($this->From));
- else
- $result .= $this->HeaderLine("Return-Path", trim($this->Sender));
-
- // To be created automatically by mail()
- if($this->Mailer != "mail")
- {
- if(count($this->to) > 0)
- $result .= $this->AddrAppend("To", $this->to);
- else if (count($this->cc) == 0)
- $result .= $this->HeaderLine("To", "undisclosed-recipients:;");
- if(count($this->cc) > 0)
- $result .= $this->AddrAppend("Cc", $this->cc);
- }
-
- $from = array();
- $from[0][0] = trim($this->From);
- $from[0][1] = $this->FromName;
- $result .= $this->AddrAppend("From", $from);
-
- // sendmail and mail() extract Bcc from the header before sending
- if((($this->Mailer == "sendmail") || ($this->Mailer == "mail")) && (count($this->bcc) > 0))
- $result .= $this->AddrAppend("Bcc", $this->bcc);
-
- if(count($this->ReplyTo) > 0)
- $result .= $this->AddrAppend("Reply-to", $this->ReplyTo);
-
- // mail() sets the subject itself
- if($this->Mailer != "mail")
- $result .= $this->HeaderLine("Subject", $this->EncodeHeader(trim($this->Subject)));
-
- $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
- $result .= $this->HeaderLine("X-Priority", $this->Priority);
-
- if($this->ConfirmReadingTo != "")
- {
- $result .= $this->HeaderLine("Disposition-Notification-To",
- "<" . trim($this->ConfirmReadingTo) . ">");
- }
-
- // Add custom headers
- for($index = 0; $index < count($this->CustomHeader); $index++)
- {
- $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]),
- $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
- }
- $result .= $this->HeaderLine("MIME-Version", "1.0");
-
- switch($this->message_type)
- {
- case "plain":
- $result .= $this->HeaderLine("Content-Transfer-Encoding", $this->Encoding);
- $result .= sprintf("Content-Type: %s; charset=\"%s\"",
- $this->ContentType, $this->CharSet);
- break;
- case "attachments":
- // fall through
- case "alt_attachments":
- if($this->InlineImageExists())
- {
- $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s",
- "multipart/related", $this->LE, $this->LE,
- $this->boundary[1], $this->LE);
- }
- else
- {
- $result .= $this->HeaderLine("Content-Type", "multipart/mixed;");
- $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
- }
- break;
- case "alt":
- $result .= $this->HeaderLine("Content-Type", "multipart/alternative;");
- $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
- break;
- }
-
- if($this->Mailer != "mail")
- $result .= $this->LE.$this->LE;
-
- return $result;
- }
-
- /**
- * Assembles the message body. Returns an empty string on failure.
- * @access private
- * @return string
- */
- function CreateBody() {
- $result = "";
-
- $this->SetWordWrap();
-
- switch($this->message_type)
- {
- case "alt":
- $result .= $this->GetBoundary($this->boundary[1], "",
- "text/plain", "");
- $result .= $this->EncodeString($this->AltBody, $this->Encoding);
- $result .= $this->LE.$this->LE;
- $result .= $this->GetBoundary($this->boundary[1], "",
- "text/html", "");
-
- $result .= $this->EncodeString($this->Body, $this->Encoding);
- $result .= $this->LE.$this->LE;
-
- $result .= $this->EndBoundary($this->boundary[1]);
- break;
- case "plain":
- $result .= $this->EncodeString($this->Body, $this->Encoding);
- break;
- case "attachments":
- $result .= $this->GetBoundary($this->boundary[1], "", "", "");
- $result .= $this->EncodeString($this->Body, $this->Encoding);
- $result .= $this->LE;
-
- $result .= $this->AttachAll();
- break;
- case "alt_attachments":
- $result .= sprintf("--%s%s", $this->boundary[1], $this->LE);
- $result .= sprintf("Content-Type: %s;%s" .
- "\tboundary=\"%s\"%s",
- "multipart/alternative", $this->LE,
- $this->boundary[2], $this->LE.$this->LE);
-
- // Create text body
- $result .= $this->GetBoundary($this->boundary[2], "",
- "text/plain", "") . $this->LE;
-
- $result .= $this->EncodeString($this->AltBody, $this->Encoding);
- $result .= $this->LE.$this->LE;
-
- // Create the HTML body
- $result .= $this->GetBoundary($this->boundary[2], "",
- "text/html", "") . $this->LE;
-
- $result .= $this->EncodeString($this->Body, $this->Encoding);
- $result .= $this->LE.$this->LE;
-
- $result .= $this->EndBoundary($this->boundary[2]);
-
- $result .= $this->AttachAll();
- break;
- }
- if($this->IsError())
- $result = "";
-
- return $result;
- }
-
- /**
- * Returns the start of a message boundary.
- * @access private
- */
- function GetBoundary($boundary, $charSet, $contentType, $encoding) {
- $result = "";
- if($charSet == "") { $charSet = $this->CharSet; }
- if($contentType == "") { $contentType = $this->ContentType; }
- if($encoding == "") { $encoding = $this->Encoding; }
-
- $result .= $this->TextLine("--" . $boundary);
- $result .= sprintf("Content-Type: %s; charset = \"%s\"",
- $contentType, $charSet);
- $result .= $this->LE;
- $result .= $this->HeaderLine("Content-Transfer-Encoding", $encoding);
- $result .= $this->LE;
-
- return $result;
- }
-
- /**
- * Returns the end of a message boundary.
- * @access private
- */
- function EndBoundary($boundary) {
- return $this->LE . "--" . $boundary . "--" . $this->LE;
- }
-
- /**
- * Sets the message type.
- * @access private
- * @return void
- */
- function SetMessageType() {
- if(count($this->attachment) < 1 && strlen($this->AltBody) < 1)
- $this->message_type = "plain";
- else
- {
- if(count($this->attachment) > 0)
- $this->message_type = "attachments";
- if(strlen($this->AltBody) > 0 && count($this->attachment) < 1)
- $this->message_type = "alt";
- if(strlen($this->AltBody) > 0 && count($this->attachment) > 0)
- $this->message_type = "alt_attachments";
- }
- }
-
- /**
- * Returns a formatted header line.
- * @access private
- * @return string
- */
- function HeaderLine($name, $value) {
- return $name . ": " . $value . $this->LE;
- }
-
- /**
- * Returns a formatted mail line.
- * @access private
- * @return string
- */
- function TextLine($value) {
- return $value . $this->LE;
- }
-
- /////////////////////////////////////////////////
- // ATTACHMENT METHODS
- /////////////////////////////////////////////////
-
- /**
- * Adds an attachment from a path on the filesystem.
- * Returns false if the file could not be found
- * or accessed.
- * @param string $path Path to the attachment.
- * @param string $name Overrides the attachment name.
- * @param string $encoding File encoding (see $Encoding).
- * @param string $type File extension (MIME) type.
- * @return bool
- */
- function AddAttachment($path, $name = "", $encoding = "base64",
- $type = "application/octet-stream") {
- if(!@is_file($path))
- {
- $this->SetError($this->Lang("file_access") . $path);
- return false;
- }
-
- $filename = basename($path);
- if($name == "")
- $name = $filename;
-
- $cur = count($this->attachment);
- $this->attachment[$cur][0] = $path;
- $this->attachment[$cur][1] = $filename;
- $this->attachment[$cur][2] = $name;
- $this->attachment[$cur][3] = $encoding;
- $this->attachment[$cur][4] = $type;
- $this->attachment[$cur][5] = false; // isStringAttachment
- $this->attachment[$cur][6] = "attachment";
- $this->attachment[$cur][7] = 0;
-
- return true;
- }
-
- /**
- * Attaches all fs, string, and binary attachments to the message.
- * Returns an empty string on failure.
- * @access private
- * @return string
- */
- function AttachAll() {
- // Return text of body
- $mime = array();
-
- // Add all attachments
- for($i = 0; $i < count($this->attachment); $i++)
- {
- // Check for string attachment
- $bString = $this->attachment[$i][5];
- if ($bString)
- $string = $this->attachment[$i][0];
- else
- $path = $this->attachment[$i][0];
-
- $filename = $this->attachment[$i][1];
- $name = $this->attachment[$i][2];
- $encoding = $this->attachment[$i][3];
- $type = $this->attachment[$i][4];
- $disposition = $this->attachment[$i][6];
- $cid = $this->attachment[$i][7];
-
- $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
- $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);
- $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
-
- if($disposition == "inline")
- $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
-
- $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s",
- $disposition, $name, $this->LE.$this->LE);
-
- // Encode as string attachment
- if($bString)
- {
- $mime[] = $this->EncodeString($string, $encoding);
- if($this->IsError()) { return ""; }
- $mime[] = $this->LE.$this->LE;
- }
- else
- {
- $mime[] = $this->EncodeFile($path, $encoding);
- if($this->IsError()) { return ""; }
- $mime[] = $this->LE.$this->LE;
- }
- }
-
- $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
-
- return join("", $mime);
- }
-
- /**
- * Encodes attachment in requested format. Returns an
- * empty string on failure.
- * @access private
- * @return string
- */
- function EncodeFile ($path, $encoding = "base64") {
- if(!@$fd = fopen($path, "rb"))
- {
- $this->SetError($this->Lang("file_open") . $path);
- return "";
- }
- $magic_quotes = get_magic_quotes_runtime();
- set_magic_quotes_runtime(0);
- $file_buffer = fread($fd, filesize($path));
- $file_buffer = $this->EncodeString($file_buffer, $encoding);
- fclose($fd);
- set_magic_quotes_runtime($magic_quotes);
-
- return $file_buffer;
- }
-
- /**
- * Encodes string to requested format. Returns an
- * empty string on failure.
- * @access private
- * @return string
- */
- function EncodeString ($str, $encoding = "base64") {
- $encoded = "";
- switch(strtolower($encoding)) {
- case "base64":
- // chunk_split is found in PHP >= 3.0.6
- $encoded = chunk_split(base64_encode($str), 76, $this->LE);
- break;
- case "7bit":
- case "8bit":
- $encoded = $this->FixEOL($str);
- if (substr($encoded, -(strlen($this->LE))) != $this->LE)
- $encoded .= $this->LE;
- break;
- case "binary":
- $encoded = $str;
- break;
- case "quoted-printable":
- $encoded = $this->EncodeQP($str);
- break;
- default:
- $this->SetError($this->Lang("encoding") . $encoding);
- break;
- }
- return $encoded;
- }
-
- /**
- * Encode a header string to best of Q, B, quoted or none.
- * @access private
- * @return string
- */
- function EncodeHeader ($str, $position = 'text') {
- $x = 0;
-
- switch (strtolower($position)) {
- case 'phrase':
- if (!preg_match('/[\200-\377]/', $str)) {
- // Can't use addslashes as we don't know what value has magic_quotes_sybase.
- $encoded = addcslashes($str, "\0..\37\177\\\"");
-
- if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str))
- return ($encoded);
- else
- return ("\"$encoded\"");
- }
- $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
- break;
- case 'comment':
- $x = preg_match_all('/[()"]/', $str, $matches);
- // Fall-through
- case 'text':
- default:
- $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
- break;
- }
-
- if ($x == 0)
- return ($str);
-
- $maxlen = 75 - 7 - strlen($this->CharSet);
- // Try to select the encoding which should produce the shortest output
- if (strlen($str)/3 < $x) {
- $encoding = 'B';
- $encoded = base64_encode($str);
- $maxlen -= $maxlen % 4;
- $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
- } else {
- $encoding = 'Q';
- $encoded = $this->EncodeQ($str, $position);
- $encoded = $this->WrapText($encoded, $maxlen, true);
- $encoded = str_replace("=".$this->LE, "\n", trim($encoded));
- }
-
- $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
- $encoded = trim(str_replace("\n", $this->LE, $encoded));
-
- return $encoded;
- }
-
- /**
- * Encode string to quoted-printable.
- * @access private
- * @return string
- */
- function EncodeQP ($str) {
- $encoded = $this->FixEOL($str);
- if (substr($encoded, -(strlen($this->LE))) != $this->LE)
- $encoded .= $this->LE;
-
- // Replace every high ascii, control and = characters
- $encoded = preg_replace('/([\000-\010\013\014\016-\037\075\177-\377])/e',
- "'='.sprintf('%02X', ord('\\1'))", $encoded);
- // Replace every spaces and tabs when it's the last character on a line
- $encoded = preg_replace("/([\011\040])".$this->LE."/e",
- "'='.sprintf('%02X', ord('\\1')).'".$this->LE."'", $encoded);
-
- // Maximum line length of 76 characters before CRLF (74 + space + '=')
- $encoded = $this->WrapText($encoded, 74, true);
-
- return $encoded;
- }
-
- /**
- * Encode string to q encoding.
- * @access private
- * @return string
- */
- function EncodeQ ($str, $position = "text") {
- // There should not be any EOL in the string
- $encoded = preg_replace("[\r\n]", "", $str);
-
- switch (strtolower($position)) {
- case "phrase":
- $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
- break;
- case "comment":
- $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
- case "text":
- default:
- // Replace every high ascii, control =, ? and _ characters
- $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
- "'='.sprintf('%02X', ord('\\1'))", $encoded);
- break;
- }
-
- // Replace every spaces to _ (more readable than =20)
- $encoded = str_replace(" ", "_", $encoded);
-
- return $encoded;
- }
-
- /**
- * Adds a string or binary attachment (non-filesystem) to the list.
- * This method can be used to attach ascii or binary data,
- * such as a BLOB record from a database.
- * @param string $string String attachment data.
- * @param string $filename Name of the attachment.
- * @param string $encoding File encoding (see $Encoding).
- * @param string $type File extension (MIME) type.
- * @return void
- */
- function AddStringAttachment($string, $filename, $encoding = "base64",
- $type = "application/octet-stream") {
- // Append to $attachment array
- $cur = count($this->attachment);
- $this->attachment[$cur][0] = $string;
- $this->attachment[$cur][1] = $filename;
- $this->attachment[$cur][2] = $filename;
- $this->attachment[$cur][3] = $encoding;
- $this->attachment[$cur][4] = $type;
- $this->attachment[$cur][5] = true; // isString
- $this->attachment[$cur][6] = "attachment";
- $this->attachment[$cur][7] = 0;
- }
-
- /**
- * Adds an embedded attachment. This can include images, sounds, and
- * just about any other document. Make sure to set the $type to an
- * image type. For JPEG images use "image/jpeg" and for GIF images
- * use "image/gif".
- * @param string $path Path to the attachment.
- * @param string $cid Content ID of the attachment. Use this to identify
- * the Id for accessing the image in an HTML form.
- * @param string $name Overrides the attachment name.
- * @param string $encoding File encoding (see $Encoding).
- * @param string $type File extension (MIME) type.
- * @return bool
- */
- function AddEmbeddedImage($path, $cid, $name = "", $encoding = "base64",
- $type = "application/octet-stream") {
-
- if(!@is_file($path))
- {
- $this->SetError($this->Lang("file_access") . $path);
- return false;
- }
-
- $filename = basename($path);
- if($name == "")
- $name = $filename;
-
- // Append to $attachment array
- $cur = count($this->attachment);
- $this->attachment[$cur][0] = $path;
- $this->attachment[$cur][1] = $filename;
- $this->attachment[$cur][2] = $name;
- $this->attachment[$cur][3] = $encoding;
- $this->attachment[$cur][4] = $type;
- $this->attachment[$cur][5] = false; // isStringAttachment
- $this->attachment[$cur][6] = "inline";
- $this->attachment[$cur][7] = $cid;
-
- return true;
- }
-
- /**
- * Returns true if an inline attachment is present.
- * @access private
- * @return bool
- */
- function InlineImageExists() {
- $result = false;
- for($i = 0; $i < count($this->attachment); $i++)
- {
- if($this->attachment[$i][6] == "inline")
- {
- $result = true;
- break;
- }
- }
-
- return $result;
- }
-
- /////////////////////////////////////////////////
- // MESSAGE RESET METHODS
- /////////////////////////////////////////////////
-
- /**
- * Clears all recipients assigned in the TO array. Returns void.
- * @return void
- */
- function ClearAddresses() {
- $this->to = array();
- }
-
- /**
- * Clears all recipients assigned in the CC array. Returns void.
- * @return void
- */
- function ClearCCs() {
- $this->cc = array();
- }
-
- /**
- * Clears all recipients assigned in the BCC array. Returns void.
- * @return void
- */
- function ClearBCCs() {
- $this->bcc = array();
- }
-
- /**
- * Clears all recipients assigned in the ReplyTo array. Returns void.
- * @return void
- */
- function ClearReplyTos() {
- $this->ReplyTo = array();
- }
-
- /**
- * Clears all recipients assigned in the TO, CC and BCC
- * array. Returns void.
- * @return void
- */
- function ClearAllRecipients() {
- $this->to = array();
- $this->cc = array();
- $this->bcc = array();
- }
-
- /**
- * Clears all previously set filesystem, string, and binary
- * attachments. Returns void.
- * @return void
- */
- function ClearAttachments() {
- $this->attachment = array();
- }
-
- /**
- * Clears all custom headers. Returns void.
- * @return void
- */
- function ClearCustomHeaders() {
- $this->CustomHeader = array();
- }
-
-
- /////////////////////////////////////////////////
- // MISCELLANEOUS METHODS
- /////////////////////////////////////////////////
-
- /**
- * Adds the error message to the error container.
- * Returns void.
- * @access private
- * @return void
- */
- function SetError($msg) {
- $this->error_count++;
- $this->ErrorInfo = $msg;
- }
-
- /**
- * Returns the proper RFC 822 formatted date.
- * @access private
- * @return string
- */
- function RFCDate() {
- $tz = date("Z");
- $tzs = ($tz < 0) ? "-" : "+";
- $tz = abs($tz);
- $tz = ($tz/3600)*100 + ($tz%3600)/60;
- $result = sprintf("%s %s%04d", date("D, j M Y H:i:s"), $tzs, $tz);
-
- return $result;
- }
-
- /**
- * Returns the appropriate server variable. Should work with both
- * PHP 4.1.0+ as well as older versions. Returns an empty string
- * if nothing is found.
- * @access private
- * @return mixed
- */
- function ServerVar($varName) {
- global $HTTP_SERVER_VARS;
- global $HTTP_ENV_VARS;
-
- if(!isset($_SERVER))
- {
- $_SERVER = $HTTP_SERVER_VARS;
- if(!isset($_SERVER["REMOTE_ADDR"]))
- $_SERVER = $HTTP_ENV_VARS; // must be Apache
- }
-
- if(isset($_SERVER[$varName]))
- return $_SERVER[$varName];
- else
- return "";
- }
-
- /**
- * Returns the server hostname or 'localhost.localdomain' if unknown.
- * @access private
- * @return string
- */
- function ServerHostname() {
- if ($this->Hostname != "")
- $result = $this->Hostname;
- elseif ($this->ServerVar('SERVER_NAME') != "")
- $result = $this->ServerVar('SERVER_NAME');
- else
- $result = "localhost.localdomain";
-
- return $result;
- }
-
- /**
- * Returns a message in the appropriate language.
- * @access private
- * @return string
- */
- function Lang($key) {
- if(count($this->language) < 1)
- $this->SetLanguage("en"); // set the default language
-
- if(isset($this->language[$key]))
- return $this->language[$key];
- else
- return "Language string failed to load: " . $key;
- }
-
- /**
- * Returns true if an error occurred.
- * @return bool
- */
- function IsError() {
- return ($this->error_count > 0);
- }
-
- /**
- * Changes every end of line from CR or LF to CRLF.
- * @access private
- * @return string
- */
- function FixEOL($str) {
- $str = str_replace("\r\n", "\n", $str);
- $str = str_replace("\r", "\n", $str);
- $str = str_replace("\n", $this->LE, $str);
- return $str;
- }
-
- /**
- * Adds a custom header.
- * @return void
- */
- function AddCustomHeader($custom_header) {
- $this->CustomHeader[] = explode(":", $custom_header, 2);
- }
-}
-
-?>
+<?php +//////////////////////////////////////////////////// +// PHPMailer - PHP email class +// +// Class for sending email using either +// sendmail, PHP mail(), or SMTP. Methods are +// based upon the standard AspEmail(tm) classes. +// +// Copyright (C) 2001 - 2003 Brent R. Matzelle +// +// License: LGPL, see LICENSE +//////////////////////////////////////////////////// + +/** + * PHPMailer - PHP email transport class + * @package PHPMailer + * @author Brent R. Matzelle + * @copyright 2001 - 2003 Brent R. Matzelle + */ +class PHPMailer +{ + ///////////////////////////////////////////////// + // PUBLIC VARIABLES + ///////////////////////////////////////////////// + + /** + * Email priority (1 = High, 3 = Normal, 5 = low). + * @var int + */ + var $Priority = 3; + + /** + * Sets the CharSet of the message. + * @var string + */ + var $CharSet = "UTF-8"; + + /** + * Sets the Content-type of the message. + * @var string + */ + var $ContentType = "text/plain"; + + /** + * Sets the Encoding of the message. Options for this are "8bit", + * "7bit", "binary", "base64", and "quoted-printable". + * @var string + */ + var $Encoding = "8bit"; + + /** + * Holds the most recent mailer error message. + * @var string + */ + var $ErrorInfo = ""; + + /** + * Sets the From email address for the message. + * @var string + */ + var $From = "support@wordpress.com"; + + /** + * Sets the From name of the message. + * @var string + */ + var $FromName = "Support"; + + /** + * Sets the Sender email (Return-Path) of the message. If not empty, + * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. + * @var string + */ + var $Sender = ""; + + /** + * Sets the Subject of the message. + * @var string + */ + var $Subject = ""; + + /** + * Sets the Body of the message. This can be either an HTML or text body. + * If HTML then run IsHTML(true). + * @var string + */ + var $Body = ""; + + /** + * Sets the text-only body of the message. This automatically sets the + * email to multipart/alternative. This body can be read by mail + * clients that do not have HTML email capability such as mutt. Clients + * that can read HTML will view the normal Body. + * @var string + */ + var $AltBody = ""; + + /** + * Sets word wrapping on the body of the message to a given number of + * characters. + * @var int + */ + var $WordWrap = 0; + + /** + * Method to send mail: ("mail", "sendmail", or "smtp"). + * @var string + */ + var $Mailer = "mail"; + + /** + * Sets the path of the sendmail program. + * @var string + */ + var $Sendmail = "/usr/sbin/sendmail"; + + /** + * Path to PHPMailer plugins. This is now only useful if the SMTP class + * is in a different directory than the PHP include path. + * @var string + */ + var $PluginDir = ""; + + /** + * Holds PHPMailer version. + * @var string + */ + var $Version = "1.73"; + + /** + * Sets the email address that a reading confirmation will be sent. + * @var string + */ + var $ConfirmReadingTo = ""; + + /** + * Sets the hostname to use in Message-Id and Received headers + * and as default HELO string. If empty, the value returned + * by SERVER_NAME is used or 'localhost.localdomain'. + * @var string + */ + var $Hostname = ""; + + ///////////////////////////////////////////////// + // SMTP VARIABLES + ///////////////////////////////////////////////// + + /** + * Sets the SMTP hosts. All hosts must be separated by a + * semicolon. You can also specify a different port + * for each host by using this format: [hostname:port] + * (e.g. "smtp1.example.com:25;smtp2.example.com"). + * Hosts will be tried in order. + * @var string + */ + var $Host = "localhost"; + + /** + * Sets the default SMTP server port. + * @var int + */ + var $Port = 25; + + /** + * Sets the SMTP HELO of the message (Default is $Hostname). + * @var string + */ + var $Helo = ""; + + /** + * Sets SMTP authentication. Utilizes the Username and Password variables. + * @var bool + */ + var $SMTPAuth = false; + + /** + * Sets SMTP username. + * @var string + */ + var $Username = ""; + + /** + * Sets SMTP password. + * @var string + */ + var $Password = ""; + + /** + * Sets the SMTP server timeout in seconds. This function will not + * work with the win32 version. + * @var int + */ + var $Timeout = 10; + + /** + * Sets SMTP class debugging on or off. + * @var bool + */ + var $SMTPDebug = false; + + /** + * Prevents the SMTP connection from being closed after each mail + * sending. If this is set to true then to close the connection + * requires an explicit call to SmtpClose(). + * @var bool + */ + var $SMTPKeepAlive = false; + + /**#@+ + * @access private + */ + var $smtp = NULL; + var $to = array(); + var $cc = array(); + var $bcc = array(); + var $ReplyTo = array(); + var $attachment = array(); + var $CustomHeader = array(); + var $message_type = ""; + var $boundary = array(); + var $language = array(); + var $error_count = 0; + var $LE = "\n"; + /**#@-*/ + + ///////////////////////////////////////////////// + // VARIABLE METHODS + ///////////////////////////////////////////////// + + /** + * Sets message type to HTML. + * @param bool $bool + * @return void + */ + function IsHTML($bool) { + if($bool == true) + $this->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->smtp->Reset(); + $connection = false; + } + } + $connection = true; + } + $index++; + } + if(!$connection) + $this->SetError($this->Lang("connect_host")); + + return $connection; + } + + /** + * Closes the active SMTP session if one exists. + * @return void + */ + function SmtpClose() { + if($this->smtp != NULL) + { + if($this->smtp->Connected()) + { + $this->smtp->Quit(); + $this->smtp->Close(); + } + } + } + + /** + * Sets the language for all class error messages. Returns false + * if it cannot load the language file. The default language type + * is English. + * @param string $lang_type Type of language (e.g. Portuguese: "br") + * @param string $lang_path Path to the language file directory + * @access public + * @return bool + */ + function SetLanguage($lang_type, $lang_path = "language/") { + if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php')) + include($lang_path.'phpmailer.lang-'.$lang_type.'.php'); + else if(file_exists($lang_path.'phpmailer.lang-en.php')) + include($lang_path.'phpmailer.lang-en.php'); + else + { + $this->SetError("Could not load language file"); + return false; + } + $this->language = $PHPMAILER_LANG; + + return true; + } + + ///////////////////////////////////////////////// + // MESSAGE CREATION METHODS + ///////////////////////////////////////////////// + + /** + * Creates recipient headers. + * @access private + * @return string + */ + function AddrAppend($type, $addr) { + $addr_str = $type . ": "; + $addr_str .= $this->AddrFormat($addr[0]); + if(count($addr) > 1) + { + for($i = 1; $i < count($addr); $i++) + $addr_str .= ", " . $this->AddrFormat($addr[$i]); + } + $addr_str .= $this->LE; + + return $addr_str; + } + + /** + * Formats an address correctly. + * @access private + * @return string + */ + function AddrFormat($addr) { + if(empty($addr[1])) + $formatted = $addr[0]; + else + { + $formatted = $this->EncodeHeader($addr[1], 'phrase') . " <" . + $addr[0] . ">"; + } + + return $formatted; + } + + /** + * Wraps message for use with mailers that do not + * automatically perform wrapping and for quoted-printable. + * Original written by philippe. + * @access private + * @return string + */ + function WrapText($message, $length, $qp_mode = false) { + $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE; + + $message = $this->FixEOL($message); + if (substr($message, -1) == $this->LE) + $message = substr($message, 0, -1); + + $line = explode($this->LE, $message); + $message = ""; + for ($i=0 ;$i < count($line); $i++) + { + $line_part = explode(" ", $line[$i]); + $buf = ""; + for ($e = 0; $e<count($line_part); $e++) + { + $word = $line_part[$e]; + if ($qp_mode and (strlen($word) > $length)) + { + $space_left = $length - strlen($buf) - 1; + if ($e != 0) + { + if ($space_left > 20) + { + $len = $space_left; + if (substr($word, $len - 1, 1) == "=") + $len--; + elseif (substr($word, $len - 2, 1) == "=") + $len -= 2; + $part = substr($word, 0, $len); + $word = substr($word, $len); + $buf .= " " . $part; + $message .= $buf . sprintf("=%s", $this->LE); + } + else + { + $message .= $buf . $soft_break; + } + $buf = ""; + } + while (strlen($word) > 0) + { + $len = $length; + if (substr($word, $len - 1, 1) == "=") + $len--; + elseif (substr($word, $len - 2, 1) == "=") + $len -= 2; + $part = substr($word, 0, $len); + $word = substr($word, $len); + + if (strlen($word) > 0) + $message .= $part . sprintf("=%s", $this->LE); + else + $buf = $part; + } + } + else + { + $buf_o = $buf; + $buf .= ($e == 0) ? $word : (" " . $word); + + if (strlen($buf) > $length and $buf_o != "") + { + $message .= $buf_o . $soft_break; + $buf = $word; + } + } + } + $message .= $buf . $this->LE; + } + + return $message; + } + + /** + * Set the body wrapping. + * @access private + * @return void + */ + function SetWordWrap() { + if($this->WordWrap < 1) + return; + + switch($this->message_type) + { + case "alt": + // fall through + case "alt_attachments": + $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); + break; + default: + $this->Body = $this->WrapText($this->Body, $this->WordWrap); + break; + } + } + + /** + * Assembles message header. + * @access private + * @return string + */ + function CreateHeader() { + $result = ""; + + // Set the boundaries + $uniq_id = md5(uniqid(time())); + $this->boundary[1] = "b1_" . $uniq_id; + $this->boundary[2] = "b2_" . $uniq_id; + + $result .= $this->HeaderLine("Date", $this->RFCDate()); + if($this->Sender == "") + $result .= $this->HeaderLine("Return-Path", trim($this->From)); + else + $result .= $this->HeaderLine("Return-Path", trim($this->Sender)); + + // To be created automatically by mail() + if($this->Mailer != "mail") + { + if(count($this->to) > 0) + $result .= $this->AddrAppend("To", $this->to); + else if (count($this->cc) == 0) + $result .= $this->HeaderLine("To", "undisclosed-recipients:;"); + if(count($this->cc) > 0) + $result .= $this->AddrAppend("Cc", $this->cc); + } + + $from = array(); + $from[0][0] = trim($this->From); + $from[0][1] = $this->FromName; + $result .= $this->AddrAppend("From", $from); + + // sendmail and mail() extract Bcc from the header before sending + if((($this->Mailer == "sendmail") || ($this->Mailer == "mail")) && (count($this->bcc) > 0)) + $result .= $this->AddrAppend("Bcc", $this->bcc); + + if(count($this->ReplyTo) > 0) + $result .= $this->AddrAppend("Reply-to", $this->ReplyTo); + + // mail() sets the subject itself + if($this->Mailer != "mail") + $result .= $this->HeaderLine("Subject", $this->EncodeHeader(trim($this->Subject))); + + $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); + $result .= $this->HeaderLine("X-Priority", $this->Priority); + + if($this->ConfirmReadingTo != "") + { + $result .= $this->HeaderLine("Disposition-Notification-To", + "<" . trim($this->ConfirmReadingTo) . ">"); + } + + // Add custom headers + for($index = 0; $index < count($this->CustomHeader); $index++) + { + $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), + $this->EncodeHeader(trim($this->CustomHeader[$index][1]))); + } + $result .= $this->HeaderLine("MIME-Version", "1.0"); + + switch($this->message_type) + { + case "plain": + $result .= $this->HeaderLine("Content-Transfer-Encoding", $this->Encoding); + $result .= sprintf("Content-Type: %s; charset=\"%s\"", + $this->ContentType, $this->CharSet); + break; + case "attachments": + // fall through + case "alt_attachments": + if($this->InlineImageExists()) + { + $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", + "multipart/related", $this->LE, $this->LE, + $this->boundary[1], $this->LE); + } + else + { + $result .= $this->HeaderLine("Content-Type", "multipart/mixed;"); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + } + break; + case "alt": + $result .= $this->HeaderLine("Content-Type", "multipart/alternative;"); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + } + + if($this->Mailer != "mail") + $result .= $this->LE.$this->LE; + + return $result; + } + + /** + * Assembles the message body. Returns an empty string on failure. + * @access private + * @return string + */ + function CreateBody() { + $result = ""; + + $this->SetWordWrap(); + + switch($this->message_type) + { + case "alt": + $result .= $this->GetBoundary($this->boundary[1], "", + "text/plain", ""); + $result .= $this->EncodeString($this->AltBody, $this->Encoding); + $result .= $this->LE.$this->LE; + $result .= $this->GetBoundary($this->boundary[1], "", + "text/html", ""); + + $result .= $this->EncodeString($this->Body, $this->Encoding); + $result .= $this->LE.$this->LE; + + $result .= $this->EndBoundary($this->boundary[1]); + break; + case "plain": + $result .= $this->EncodeString($this->Body, $this->Encoding); + break; + case "attachments": + $result .= $this->GetBoundary($this->boundary[1], "", "", ""); + $result .= $this->EncodeString($this->Body, $this->Encoding); + $result .= $this->LE; + + $result .= $this->AttachAll(); + break; + case "alt_attachments": + $result .= sprintf("--%s%s", $this->boundary[1], $this->LE); + $result .= sprintf("Content-Type: %s;%s" . + "\tboundary=\"%s\"%s", + "multipart/alternative", $this->LE, + $this->boundary[2], $this->LE.$this->LE); + + // Create text body + $result .= $this->GetBoundary($this->boundary[2], "", + "text/plain", "") . $this->LE; + + $result .= $this->EncodeString($this->AltBody, $this->Encoding); + $result .= $this->LE.$this->LE; + + // Create the HTML body + $result .= $this->GetBoundary($this->boundary[2], "", + "text/html", "") . $this->LE; + + $result .= $this->EncodeString($this->Body, $this->Encoding); + $result .= $this->LE.$this->LE; + + $result .= $this->EndBoundary($this->boundary[2]); + + $result .= $this->AttachAll(); + break; + } + if($this->IsError()) + $result = ""; + + return $result; + } + + /** + * Returns the start of a message boundary. + * @access private + */ + function GetBoundary($boundary, $charSet, $contentType, $encoding) { + $result = ""; + if($charSet == "") { $charSet = $this->CharSet; } + if($contentType == "") { $contentType = $this->ContentType; } + if($encoding == "") { $encoding = $this->Encoding; } + + $result .= $this->TextLine("--" . $boundary); + $result .= sprintf("Content-Type: %s; charset = \"%s\"", + $contentType, $charSet); + $result .= $this->LE; + $result .= $this->HeaderLine("Content-Transfer-Encoding", $encoding); + $result .= $this->LE; + + return $result; + } + + /** + * Returns the end of a message boundary. + * @access private + */ + function EndBoundary($boundary) { + return $this->LE . "--" . $boundary . "--" . $this->LE; + } + + /** + * Sets the message type. + * @access private + * @return void + */ + function SetMessageType() { + if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) + $this->message_type = "plain"; + else + { + if(count($this->attachment) > 0) + $this->message_type = "attachments"; + if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) + $this->message_type = "alt"; + if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) + $this->message_type = "alt_attachments"; + } + } + + /** + * Returns a formatted header line. + * @access private + * @return string + */ + function HeaderLine($name, $value) { + return $name . ": " . $value . $this->LE; + } + + /** + * Returns a formatted mail line. + * @access private + * @return string + */ + function TextLine($value) { + return $value . $this->LE; + } + + ///////////////////////////////////////////////// + // ATTACHMENT METHODS + ///////////////////////////////////////////////// + + /** + * Adds an attachment from a path on the filesystem. + * Returns false if the file could not be found + * or accessed. + * @param string $path Path to the attachment. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return bool + */ + function AddAttachment($path, $name = "", $encoding = "base64", + $type = "application/octet-stream") { + if(!@is_file($path)) + { + $this->SetError($this->Lang("file_access") . $path); + return false; + } + + $filename = basename($path); + if($name == "") + $name = $filename; + + $cur = count($this->attachment); + $this->attachment[$cur][0] = $path; + $this->attachment[$cur][1] = $filename; + $this->attachment[$cur][2] = $name; + $this->attachment[$cur][3] = $encoding; + $this->attachment[$cur][4] = $type; + $this->attachment[$cur][5] = false; // isStringAttachment + $this->attachment[$cur][6] = "attachment"; + $this->attachment[$cur][7] = 0; + + return true; + } + + /** + * Attaches all fs, string, and binary attachments to the message. + * Returns an empty string on failure. + * @access private + * @return string + */ + function AttachAll() { + // Return text of body + $mime = array(); + + // Add all attachments + for($i = 0; $i < count($this->attachment); $i++) + { + // Check for string attachment + $bString = $this->attachment[$i][5]; + if ($bString) + $string = $this->attachment[$i][0]; + else + $path = $this->attachment[$i][0]; + + $filename = $this->attachment[$i][1]; + $name = $this->attachment[$i][2]; + $encoding = $this->attachment[$i][3]; + $type = $this->attachment[$i][4]; + $disposition = $this->attachment[$i][6]; + $cid = $this->attachment[$i][7]; + + $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE); + $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE); + $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); + + if($disposition == "inline") + $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); + + $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", + $disposition, $name, $this->LE.$this->LE); + + // Encode as string attachment + if($bString) + { + $mime[] = $this->EncodeString($string, $encoding); + if($this->IsError()) { return ""; } + $mime[] = $this->LE.$this->LE; + } + else + { + $mime[] = $this->EncodeFile($path, $encoding); + if($this->IsError()) { return ""; } + $mime[] = $this->LE.$this->LE; + } + } + + $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE); + + return join("", $mime); + } + + /** + * Encodes attachment in requested format. Returns an + * empty string on failure. + * @access private + * @return string + */ + function EncodeFile ($path, $encoding = "base64") { + if(!@$fd = fopen($path, "rb")) + { + $this->SetError($this->Lang("file_open") . $path); + return ""; + } + $magic_quotes = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + $file_buffer = fread($fd, filesize($path)); + $file_buffer = $this->EncodeString($file_buffer, $encoding); + fclose($fd); + set_magic_quotes_runtime($magic_quotes); + + return $file_buffer; + } + + /** + * Encodes string to requested format. Returns an + * empty string on failure. + * @access private + * @return string + */ + function EncodeString ($str, $encoding = "base64") { + $encoded = ""; + switch(strtolower($encoding)) { + case "base64": + // chunk_split is found in PHP >= 3.0.6 + $encoded = chunk_split(base64_encode($str), 76, $this->LE); + break; + case "7bit": + case "8bit": + $encoded = $this->FixEOL($str); + if (substr($encoded, -(strlen($this->LE))) != $this->LE) + $encoded .= $this->LE; + break; + case "binary": + $encoded = $str; + break; + case "quoted-printable": + $encoded = $this->EncodeQP($str); + break; + default: + $this->SetError($this->Lang("encoding") . $encoding); + break; + } + return $encoded; + } + + /** + * Encode a header string to best of Q, B, quoted or none. + * @access private + * @return string + */ + function EncodeHeader ($str, $position = 'text') { + $x = 0; + + switch (strtolower($position)) { + case 'phrase': + if (!preg_match('/[\200-\377]/', $str)) { + // Can't use addslashes as we don't know what value has magic_quotes_sybase. + $encoded = addcslashes($str, "\0..\37\177\\\""); + + if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) + return ($encoded); + else + return ("\"$encoded\""); + } + $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); + break; + case 'comment': + $x = preg_match_all('/[()"]/', $str, $matches); + // Fall-through + case 'text': + default: + $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); + break; + } + + if ($x == 0) + return ($str); + + $maxlen = 75 - 7 - strlen($this->CharSet); + // Try to select the encoding which should produce the shortest output + if (strlen($str)/3 < $x) { + $encoding = 'B'; + $encoded = base64_encode($str); + $maxlen -= $maxlen % 4; + $encoded = trim(chunk_split($encoded, $maxlen, "\n")); + } else { + $encoding = 'Q'; + $encoded = $this->EncodeQ($str, $position); + $encoded = $this->WrapText($encoded, $maxlen, true); + $encoded = str_replace("=".$this->LE, "\n", trim($encoded)); + } + + $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); + $encoded = trim(str_replace("\n", $this->LE, $encoded)); + + return $encoded; + } + + /** + * Encode string to quoted-printable. + * @access private + * @return string + */ + function EncodeQP ($str) { + $encoded = $this->FixEOL($str); + if (substr($encoded, -(strlen($this->LE))) != $this->LE) + $encoded .= $this->LE; + + // Replace every high ascii, control and = characters + $encoded = preg_replace('/([\000-\010\013\014\016-\037\075\177-\377])/e', + "'='.sprintf('%02X', ord('\\1'))", $encoded); + // Replace every spaces and tabs when it's the last character on a line + $encoded = preg_replace("/([\011\040])".$this->LE."/e", + "'='.sprintf('%02X', ord('\\1')).'".$this->LE."'", $encoded); + + // Maximum line length of 76 characters before CRLF (74 + space + '=') + $encoded = $this->WrapText($encoded, 74, true); + + return $encoded; + } + + /** + * Encode string to q encoding. + * @access private + * @return string + */ + function EncodeQ ($str, $position = "text") { + // There should not be any EOL in the string + $encoded = preg_replace("[\r\n]", "", $str); + + switch (strtolower($position)) { + case "phrase": + $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); + break; + case "comment": + $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); + case "text": + default: + // Replace every high ascii, control =, ? and _ characters + $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e', + "'='.sprintf('%02X', ord('\\1'))", $encoded); + break; + } + + // Replace every spaces to _ (more readable than =20) + $encoded = str_replace(" ", "_", $encoded); + + return $encoded; + } + + /** + * Adds a string or binary attachment (non-filesystem) to the list. + * This method can be used to attach ascii or binary data, + * such as a BLOB record from a database. + * @param string $string String attachment data. + * @param string $filename Name of the attachment. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return void + */ + function AddStringAttachment($string, $filename, $encoding = "base64", + $type = "application/octet-stream") { + // Append to $attachment array + $cur = count($this->attachment); + $this->attachment[$cur][0] = $string; + $this->attachment[$cur][1] = $filename; + $this->attachment[$cur][2] = $filename; + $this->attachment[$cur][3] = $encoding; + $this->attachment[$cur][4] = $type; + $this->attachment[$cur][5] = true; // isString + $this->attachment[$cur][6] = "attachment"; + $this->attachment[$cur][7] = 0; + } + + /** + * Adds an embedded attachment. This can include images, sounds, and + * just about any other document. Make sure to set the $type to an + * image type. For JPEG images use "image/jpeg" and for GIF images + * use "image/gif". + * @param string $path Path to the attachment. + * @param string $cid Content ID of the attachment. Use this to identify + * the Id for accessing the image in an HTML form. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return bool + */ + function AddEmbeddedImage($path, $cid, $name = "", $encoding = "base64", + $type = "application/octet-stream") { + + if(!@is_file($path)) + { + $this->SetError($this->Lang("file_access") . $path); + return false; + } + + $filename = basename($path); + if($name == "") + $name = $filename; + + // Append to $attachment array + $cur = count($this->attachment); + $this->attachment[$cur][0] = $path; + $this->attachment[$cur][1] = $filename; + $this->attachment[$cur][2] = $name; + $this->attachment[$cur][3] = $encoding; + $this->attachment[$cur][4] = $type; + $this->attachment[$cur][5] = false; // isStringAttachment + $this->attachment[$cur][6] = "inline"; + $this->attachment[$cur][7] = $cid; + + return true; + } + + /** + * Returns true if an inline attachment is present. + * @access private + * @return bool + */ + function InlineImageExists() { + $result = false; + for($i = 0; $i < count($this->attachment); $i++) + { + if($this->attachment[$i][6] == "inline") + { + $result = true; + break; + } + } + + return $result; + } + + ///////////////////////////////////////////////// + // MESSAGE RESET METHODS + ///////////////////////////////////////////////// + + /** + * Clears all recipients assigned in the TO array. Returns void. + * @return void + */ + function ClearAddresses() { + $this->to = array(); + } + + /** + * Clears all recipients assigned in the CC array. Returns void. + * @return void + */ + function ClearCCs() { + $this->cc = array(); + } + + /** + * Clears all recipients assigned in the BCC array. Returns void. + * @return void + */ + function ClearBCCs() { + $this->bcc = array(); + } + + /** + * Clears all recipients assigned in the ReplyTo array. Returns void. + * @return void + */ + function ClearReplyTos() { + $this->ReplyTo = array(); + } + + /** + * Clears all recipients assigned in the TO, CC and BCC + * array. Returns void. + * @return void + */ + function ClearAllRecipients() { + $this->to = array(); + $this->cc = array(); + $this->bcc = array(); + } + + /** + * Clears all previously set filesystem, string, and binary + * attachments. Returns void. + * @return void + */ + function ClearAttachments() { + $this->attachment = array(); + } + + /** + * Clears all custom headers. Returns void. + * @return void + */ + function ClearCustomHeaders() { + $this->CustomHeader = array(); + } + + + ///////////////////////////////////////////////// + // MISCELLANEOUS METHODS + ///////////////////////////////////////////////// + + /** + * Adds the error message to the error container. + * Returns void. + * @access private + * @return void + */ + function SetError($msg) { + $this->error_count++; + $this->ErrorInfo = $msg; + } + + /** + * Returns the proper RFC 822 formatted date. + * @access private + * @return string + */ + function RFCDate() { + $tz = date("Z"); + $tzs = ($tz < 0) ? "-" : "+"; + $tz = abs($tz); + $tz = ($tz/3600)*100 + ($tz%3600)/60; + $result = sprintf("%s %s%04d", date("D, j M Y H:i:s"), $tzs, $tz); + + return $result; + } + + /** + * Returns the appropriate server variable. Should work with both + * PHP 4.1.0+ as well as older versions. Returns an empty string + * if nothing is found. + * @access private + * @return mixed + */ + function ServerVar($varName) { + global $HTTP_SERVER_VARS; + global $HTTP_ENV_VARS; + + if(!isset($_SERVER)) + { + $_SERVER = $HTTP_SERVER_VARS; + if(!isset($_SERVER["REMOTE_ADDR"])) + $_SERVER = $HTTP_ENV_VARS; // must be Apache + } + + if(isset($_SERVER[$varName])) + return $_SERVER[$varName]; + else + return ""; + } + + /** + * Returns the server hostname or 'localhost.localdomain' if unknown. + * @access private + * @return string + */ + function ServerHostname() { + if ($this->Hostname != "") + $result = $this->Hostname; + elseif ($this->ServerVar('SERVER_NAME') != "") + $result = $this->ServerVar('SERVER_NAME'); + else + $result = "localhost.localdomain"; + + return $result; + } + + /** + * Returns a message in the appropriate language. + * @access private + * @return string + */ + function Lang($key) { + if(count($this->language) < 1) + $this->SetLanguage("en"); // set the default language + + if(isset($this->language[$key])) + return $this->language[$key]; + else + return "Language string failed to load: " . $key; + } + + /** + * Returns true if an error occurred. + * @return bool + */ + function IsError() { + return ($this->error_count > 0); + } + + /** + * Changes every end of line from CR or LF to CRLF. + * @access private + * @return string + */ + function FixEOL($str) { + $str = str_replace("\r\n", "\n", $str); + $str = str_replace("\r", "\n", $str); + $str = str_replace("\n", $this->LE, $str); + return $str; + } + + /** + * Adds a custom header. + * @return void + */ + function AddCustomHeader($custom_header) { + $this->CustomHeader[] = explode(":", $custom_header, 2); + } +} + +?> diff --git a/wp-includes/class-smtp.php b/wp-includes/class-smtp.php index df3cfb5..9c18e83 100644 --- a/wp-includes/class-smtp.php +++ b/wp-includes/class-smtp.php @@ -1,1045 +1,1045 @@ -<?php
-////////////////////////////////////////////////////
-// SMTP - PHP SMTP class
-//
-// Version 1.02
-//
-// Define an SMTP class that can be used to connect
-// and communicate with any SMTP server. It implements
-// all the SMTP functions defined in RFC821 except TURN.
-//
-// Author: Chris Ryan
-//
-// License: LGPL, see LICENSE
-////////////////////////////////////////////////////
-
-/**
- * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
- * commands except TURN which will always return a not implemented
- * error. SMTP also provides some utility methods for sending mail
- * to an SMTP server.
- * @package PHPMailer
- * @author Chris Ryan
- */
-class SMTP
-{
- /**
- * SMTP server port
- * @var int
- */
- var $SMTP_PORT = 25;
-
- /**
- * SMTP reply line ending
- * @var string
- */
- var $CRLF = "\r\n";
-
- /**
- * Sets whether debugging is turned on
- * @var bool
- */
- var $do_debug; # the level of debug to perform
-
- /**#@+
- * @access private
- */
- var $smtp_conn; # the socket to the server
- var $error; # error if any on the last call
- var $helo_rply; # the reply the server sent to us for HELO
- /**#@-*/
-
- /**
- * Initialize the class so that the data is in a known state.
- * @access public
- * @return void
- */
- function SMTP() {
- $this->smtp_conn = 0;
- $this->error = null;
- $this->helo_rply = null;
-
- $this->do_debug = 0;
- }
-
- /*************************************************************
- * CONNECTION FUNCTIONS *
- ***********************************************************/
-
- /**
- * Connect to the server specified on the port specified.
- * If the port is not specified use the default SMTP_PORT.
- * If tval is specified then a connection will try and be
- * established with the server for that number of seconds.
- * If tval is not specified the default is 30 seconds to
- * try on the connection.
- *
- * SMTP CODE SUCCESS: 220
- * SMTP CODE FAILURE: 421
- * @access public
- * @return bool
- */
- function Connect($host,$port=0,$tval=30) {
- # set the error val to null so there is no confusion
- $this->error = null;
-
- # make sure we are __not__ connected
- if($this->connected()) {
- # ok we are connected! what should we do?
- # for now we will just give an error saying we
- # are already connected
- $this->error =
- array("error" => "Already connected to a server");
- return false;
- }
-
- if(empty($port)) {
- $port = $this->SMTP_PORT;
- }
-
- #connect to the smtp server
- $this->smtp_conn = fsockopen($host, # the host of the server
- $port, # the port to use
- $errno, # error number if any
- $errstr, # error message if any
- $tval); # give up after ? secs
- # verify we connected properly
- if(empty($this->smtp_conn)) {
- $this->error = array("error" => "Failed to connect to server",
- "errno" => $errno,
- "errstr" => $errstr);
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": $errstr ($errno)" . $this->CRLF;
- }
- return false;
- }
-
- # sometimes the SMTP server takes a little longer to respond
- # so we will give it a longer timeout for the first read
- // Windows still does not have support for this timeout function
- if(substr(PHP_OS, 0, 3) != "WIN")
- socket_set_timeout($this->smtp_conn, $tval, 0);
-
- # get any announcement stuff
- $announce = $this->get_lines();
-
- # set the timeout of any socket functions at 1/10 of a second
- //if(function_exists("socket_set_timeout"))
- // socket_set_timeout($this->smtp_conn, 0, 100000);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
- }
-
- return true;
- }
-
- /**
- * Performs SMTP authentication. Must be run after running the
- * Hello() method. Returns true if successfully authenticated.
- * @access public
- * @return bool
- */
- function Authenticate($username, $password) {
- // Start authentication
- fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($code != 334) {
- $this->error =
- array("error" => "AUTH not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
-
- // Send encoded username
- fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($code != 334) {
- $this->error =
- array("error" => "Username not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
-
- // Send encoded password
- fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($code != 235) {
- $this->error =
- array("error" => "Password not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Returns true if connected to a server otherwise false
- * @access private
- * @return bool
- */
- function Connected() {
- if(!empty($this->smtp_conn)) {
- $sock_status = socket_get_status($this->smtp_conn);
- if($sock_status["eof"]) {
- # hmm this is an odd situation... the socket is
- # valid but we aren't connected anymore
- if($this->do_debug >= 1) {
- echo "SMTP -> NOTICE:" . $this->CRLF .
- "EOF caught while checking if connected";
- }
- $this->Close();
- return false;
- }
- return true; # everything looks good
- }
- return false;
- }
-
- /**
- * Closes the socket and cleans up the state of the class.
- * It is not considered good to use this function without
- * first trying to use QUIT.
- * @access public
- * @return void
- */
- function Close() {
- $this->error = null; # so there is no confusion
- $this->helo_rply = null;
- if(!empty($this->smtp_conn)) {
- # close the connection and cleanup
- fclose($this->smtp_conn);
- $this->smtp_conn = 0;
- }
- }
-
-
- /***************************************************************
- * SMTP COMMANDS *
- *************************************************************/
-
- /**
- * Issues a data command and sends the msg_data to the server
- * finializing the mail transaction. $msg_data is the message
- * that is to be send with the headers. Each header needs to be
- * on a single line followed by a <CRLF> with the message headers
- * and the message body being seperated by and additional <CRLF>.
- *
- * Implements rfc 821: DATA <CRLF>
- *
- * SMTP CODE INTERMEDIATE: 354
- * [data]
- * <CRLF>.<CRLF>
- * SMTP CODE SUCCESS: 250
- * SMTP CODE FAILURE: 552,554,451,452
- * SMTP CODE FAILURE: 451,554
- * SMTP CODE ERROR : 500,501,503,421
- * @access public
- * @return bool
- */
- function Data($msg_data) {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Data() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"DATA" . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 354) {
- $this->error =
- array("error" => "DATA command not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
-
- # the server is ready to accept data!
- # according to rfc 821 we should not send more than 1000
- # including the CRLF
- # characters on a single line so we will break the data up
- # into lines by \r and/or \n then if needed we will break
- # each of those into smaller lines to fit within the limit.
- # in addition we will be looking for lines that start with
- # a period '.' and append and additional period '.' to that
- # line. NOTE: this does not count towards are limit.
-
- # normalize the line breaks so we know the explode works
- $msg_data = str_replace("\r\n","\n",$msg_data);
- $msg_data = str_replace("\r","\n",$msg_data);
- $lines = explode("\n",$msg_data);
-
- # we need to find a good way to determine is headers are
- # in the msg_data or if it is a straight msg body
- # currently I'm assuming rfc 822 definitions of msg headers
- # and if the first field of the first line (':' sperated)
- # does not contain a space then it _should_ be a header
- # and we can process all lines before a blank "" line as
- # headers.
- $field = substr($lines[0],0,strpos($lines[0],":"));
- $in_headers = false;
- if(!empty($field) && !strstr($field," ")) {
- $in_headers = true;
- }
-
- $max_line_length = 998; # used below; set here for ease in change
-
- while(list(,$line) = @each($lines)) {
- $lines_out = null;
- if($line == "" && $in_headers) {
- $in_headers = false;
- }
- # ok we need to break this line up into several
- # smaller lines
- while(strlen($line) > $max_line_length) {
- $pos = strrpos(substr($line,0,$max_line_length)," ");
-
- # Patch to fix DOS attack
- if(!$pos) {
- $pos = $max_line_length - 1;
- }
-
- $lines_out[] = substr($line,0,$pos);
- $line = substr($line,$pos + 1);
- # if we are processing headers we need to
- # add a LWSP-char to the front of the new line
- # rfc 822 on long msg headers
- if($in_headers) {
- $line = "\t" . $line;
- }
- }
- $lines_out[] = $line;
-
- # now send the lines to the server
- while(list(,$line_out) = @each($lines_out)) {
- if(strlen($line_out) > 0)
- {
- if(substr($line_out, 0, 1) == ".") {
- $line_out = "." . $line_out;
- }
- }
- fputs($this->smtp_conn,$line_out . $this->CRLF);
- }
- }
-
- # ok all the message data has been sent so lets get this
- # over with aleady
- fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250) {
- $this->error =
- array("error" => "DATA not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
- return true;
- }
-
- /**
- * Expand takes the name and asks the server to list all the
- * people who are members of the _list_. Expand will return
- * back and array of the result or false if an error occurs.
- * Each value in the array returned has the format of:
- * [ <full-name> <sp> ] <path>
- * The definition of <path> is defined in rfc 821
- *
- * Implements rfc 821: EXPN <SP> <string> <CRLF>
- *
- * SMTP CODE SUCCESS: 250
- * SMTP CODE FAILURE: 550
- * SMTP CODE ERROR : 500,501,502,504,421
- * @access public
- * @return string array
- */
- function Expand($name) {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Expand() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250) {
- $this->error =
- array("error" => "EXPN not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
-
- # parse the reply and place in our array to return to user
- $entries = explode($this->CRLF,$rply);
- while(list(,$l) = @each($entries)) {
- $list[] = substr($l,4);
- }
-
- return $list;
- }
-
- /**
- * Sends the HELO command to the smtp server.
- * This makes sure that we and the server are in
- * the same known state.
- *
- * Implements from rfc 821: HELO <SP> <domain> <CRLF>
- *
- * SMTP CODE SUCCESS: 250
- * SMTP CODE ERROR : 500, 501, 504, 421
- * @access public
- * @return bool
- */
- function Hello($host="") {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Hello() without being connected");
- return false;
- }
-
- # if a hostname for the HELO wasn't specified determine
- # a suitable one to send
- if(empty($host)) {
- # we need to determine some sort of appopiate default
- # to send to the server
- $host = "localhost";
- }
-
- // Send extended hello first (RFC 2821)
- if(!$this->SendHello("EHLO", $host))
- {
- if(!$this->SendHello("HELO", $host))
- return false;
- }
-
- return true;
- }
-
- /**
- * Sends a HELO/EHLO command.
- * @access private
- * @return bool
- */
- function SendHello($hello, $host) {
- fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
- }
-
- if($code != 250) {
- $this->error =
- array("error" => $hello . " not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
-
- $this->helo_rply = $rply;
-
- return true;
- }
-
- /**
- * Gets help information on the keyword specified. If the keyword
- * is not specified then returns generic help, ussually contianing
- * A list of keywords that help is available on. This function
- * returns the results back to the user. It is up to the user to
- * handle the returned data. If an error occurs then false is
- * returned with $this->error set appropiately.
- *
- * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
- *
- * SMTP CODE SUCCESS: 211,214
- * SMTP CODE ERROR : 500,501,502,504,421
- * @access public
- * @return string
- */
- function Help($keyword="") {
- $this->error = null; # to avoid confusion
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Help() without being connected");
- return false;
- }
-
- $extra = "";
- if(!empty($keyword)) {
- $extra = " " . $keyword;
- }
-
- fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 211 && $code != 214) {
- $this->error =
- array("error" => "HELP not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
-
- return $rply;
- }
-
- /**
- * Starts a mail transaction from the email address specified in
- * $from. Returns true if successful or false otherwise. If True
- * the mail transaction is started and then one or more Recipient
- * commands may be called followed by a Data command.
- *
- * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
- *
- * SMTP CODE SUCCESS: 250
- * SMTP CODE SUCCESS: 552,451,452
- * SMTP CODE SUCCESS: 500,501,421
- * @access public
- * @return bool
- */
- function Mail($from) {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Mail() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250) {
- $this->error =
- array("error" => "MAIL not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
- return true;
- }
-
- /**
- * Sends the command NOOP to the SMTP server.
- *
- * Implements from rfc 821: NOOP <CRLF>
- *
- * SMTP CODE SUCCESS: 250
- * SMTP CODE ERROR : 500, 421
- * @access public
- * @return bool
- */
- function Noop() {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Noop() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"NOOP" . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250) {
- $this->error =
- array("error" => "NOOP not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
- return true;
- }
-
- /**
- * Sends the quit command to the server and then closes the socket
- * if there is no error or the $close_on_error argument is true.
- *
- * Implements from rfc 821: QUIT <CRLF>
- *
- * SMTP CODE SUCCESS: 221
- * SMTP CODE ERROR : 500
- * @access public
- * @return bool
- */
- function Quit($close_on_error=true) {
- $this->error = null; # so there is no confusion
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Quit() without being connected");
- return false;
- }
-
- # send the quit command to the server
- fputs($this->smtp_conn,"quit" . $this->CRLF);
-
- # get any good-bye messages
- $byemsg = $this->get_lines();
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
- }
-
- $rval = true;
- $e = null;
-
- $code = substr($byemsg,0,3);
- if($code != 221) {
- # use e as a tmp var cause Close will overwrite $this->error
- $e = array("error" => "SMTP server rejected quit command",
- "smtp_code" => $code,
- "smtp_rply" => substr($byemsg,4));
- $rval = false;
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $e["error"] . ": " .
- $byemsg . $this->CRLF;
- }
- }
-
- if(empty($e) || $close_on_error) {
- $this->Close();
- }
-
- return $rval;
- }
-
- /**
- * Sends the command RCPT to the SMTP server with the TO: argument of $to.
- * Returns true if the recipient was accepted false if it was rejected.
- *
- * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
- *
- * SMTP CODE SUCCESS: 250,251
- * SMTP CODE FAILURE: 550,551,552,553,450,451,452
- * SMTP CODE ERROR : 500,501,503,421
- * @access public
- * @return bool
- */
- function Recipient($to) {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Recipient() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250 && $code != 251) {
- $this->error =
- array("error" => "RCPT not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
- return true;
- }
-
- /**
- * Sends the RSET command to abort and transaction that is
- * currently in progress. Returns true if successful false
- * otherwise.
- *
- * Implements rfc 821: RSET <CRLF>
- *
- * SMTP CODE SUCCESS: 250
- * SMTP CODE ERROR : 500,501,504,421
- * @access public
- * @return bool
- */
- function Reset() {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Reset() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"RSET" . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250) {
- $this->error =
- array("error" => "RSET failed",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Starts a mail transaction from the email address specified in
- * $from. Returns true if successful or false otherwise. If True
- * the mail transaction is started and then one or more Recipient
- * commands may be called followed by a Data command. This command
- * will send the message to the users terminal if they are logged
- * in.
- *
- * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>
- *
- * SMTP CODE SUCCESS: 250
- * SMTP CODE SUCCESS: 552,451,452
- * SMTP CODE SUCCESS: 500,501,502,421
- * @access public
- * @return bool
- */
- function Send($from) {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Send() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250) {
- $this->error =
- array("error" => "SEND not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
- return true;
- }
-
- /**
- * Starts a mail transaction from the email address specified in
- * $from. Returns true if successful or false otherwise. If True
- * the mail transaction is started and then one or more Recipient
- * commands may be called followed by a Data command. This command
- * will send the message to the users terminal if they are logged
- * in and send them an email.
- *
- * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
- *
- * SMTP CODE SUCCESS: 250
- * SMTP CODE SUCCESS: 552,451,452
- * SMTP CODE SUCCESS: 500,501,502,421
- * @access public
- * @return bool
- */
- function SendAndMail($from) {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called SendAndMail() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250) {
- $this->error =
- array("error" => "SAML not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
- return true;
- }
-
- /**
- * Starts a mail transaction from the email address specified in
- * $from. Returns true if successful or false otherwise. If True
- * the mail transaction is started and then one or more Recipient
- * commands may be called followed by a Data command. This command
- * will send the message to the users terminal if they are logged
- * in or mail it to them if they are not.
- *
- * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>
- *
- * SMTP CODE SUCCESS: 250
- * SMTP CODE SUCCESS: 552,451,452
- * SMTP CODE SUCCESS: 500,501,502,421
- * @access public
- * @return bool
- */
- function SendOrMail($from) {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called SendOrMail() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250) {
- $this->error =
- array("error" => "SOML not accepted from server",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
- return true;
- }
-
- /**
- * This is an optional command for SMTP that this class does not
- * support. This method is here to make the RFC821 Definition
- * complete for this class and __may__ be implimented in the future
- *
- * Implements from rfc 821: TURN <CRLF>
- *
- * SMTP CODE SUCCESS: 250
- * SMTP CODE FAILURE: 502
- * SMTP CODE ERROR : 500, 503
- * @access public
- * @return bool
- */
- function Turn() {
- $this->error = array("error" => "This method, TURN, of the SMTP ".
- "is not implemented");
- if($this->do_debug >= 1) {
- echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
- }
- return false;
- }
-
- /**
- * Verifies that the name is recognized by the server.
- * Returns false if the name could not be verified otherwise
- * the response from the server is returned.
- *
- * Implements rfc 821: VRFY <SP> <string> <CRLF>
- *
- * SMTP CODE SUCCESS: 250,251
- * SMTP CODE FAILURE: 550,551,553
- * SMTP CODE ERROR : 500,501,502,421
- * @access public
- * @return int
- */
- function Verify($name) {
- $this->error = null; # so no confusion is caused
-
- if(!$this->connected()) {
- $this->error = array(
- "error" => "Called Verify() without being connected");
- return false;
- }
-
- fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply,0,3);
-
- if($this->do_debug >= 2) {
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
- }
-
- if($code != 250 && $code != 251) {
- $this->error =
- array("error" => "VRFY failed on name '$name'",
- "smtp_code" => $code,
- "smtp_msg" => substr($rply,4));
- if($this->do_debug >= 1) {
- echo "SMTP -> ERROR: " . $this->error["error"] .
- ": " . $rply . $this->CRLF;
- }
- return false;
- }
- return $rply;
- }
-
- /*******************************************************************
- * INTERNAL FUNCTIONS *
- ******************************************************************/
-
- /**
- * Read in as many lines as possible
- * either before eof or socket timeout occurs on the operation.
- * With SMTP we can tell if we have more lines to read if the
- * 4th character is '-' symbol. If it is a space then we don't
- * need to read anything else.
- * @access private
- * @return string
- */
- function get_lines() {
- $data = "";
- while($str = fgets($this->smtp_conn,515)) {
- if($this->do_debug >= 4) {
- echo "SMTP -> get_lines(): \$data was \"$data\"" .
- $this->CRLF;
- echo "SMTP -> get_lines(): \$str is \"$str\"" .
- $this->CRLF;
- }
- $data .= $str;
- if($this->do_debug >= 4) {
- echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
- }
- # if the 4th character is a space then we are done reading
- # so just break the loop
- if(substr($str,3,1) == " ") { break; }
- }
- return $data;
- }
-
-}
-
-
- ?>
+<?php +//////////////////////////////////////////////////// +// SMTP - PHP SMTP class +// +// Version 1.02 +// +// Define an SMTP class that can be used to connect +// and communicate with any SMTP server. It implements +// all the SMTP functions defined in RFC821 except TURN. +// +// Author: Chris Ryan +// +// License: LGPL, see LICENSE +//////////////////////////////////////////////////// + +/** + * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP + * commands except TURN which will always return a not implemented + * error. SMTP also provides some utility methods for sending mail + * to an SMTP server. + * @package PHPMailer + * @author Chris Ryan + */ +class SMTP +{ + /** + * SMTP server port + * @var int + */ + var $SMTP_PORT = 25; + + /** + * SMTP reply line ending + * @var string + */ + var $CRLF = "\r\n"; + + /** + * Sets whether debugging is turned on + * @var bool + */ + var $do_debug; # the level of debug to perform + + /**#@+ + * @access private + */ + var $smtp_conn; # the socket to the server + var $error; # error if any on the last call + var $helo_rply; # the reply the server sent to us for HELO + /**#@-*/ + + /** + * Initialize the class so that the data is in a known state. + * @access public + * @return void + */ + function SMTP() { + $this->smtp_conn = 0; + $this->error = null; + $this->helo_rply = null; + + $this->do_debug = 0; + } + + /************************************************************* + * CONNECTION FUNCTIONS * + ***********************************************************/ + + /** + * Connect to the server specified on the port specified. + * If the port is not specified use the default SMTP_PORT. + * If tval is specified then a connection will try and be + * established with the server for that number of seconds. + * If tval is not specified the default is 30 seconds to + * try on the connection. + * + * SMTP CODE SUCCESS: 220 + * SMTP CODE FAILURE: 421 + * @access public + * @return bool + */ + function Connect($host,$port=0,$tval=30) { + # set the error val to null so there is no confusion + $this->error = null; + + # make sure we are __not__ connected + if($this->connected()) { + # ok we are connected! what should we do? + # for now we will just give an error saying we + # are already connected + $this->error = + array("error" => "Already connected to a server"); + return false; + } + + if(empty($port)) { + $port = $this->SMTP_PORT; + } + + #connect to the smtp server + $this->smtp_conn = fsockopen($host, # the host of the server + $port, # the port to use + $errno, # error number if any + $errstr, # error message if any + $tval); # give up after ? secs + # verify we connected properly + if(empty($this->smtp_conn)) { + $this->error = array("error" => "Failed to connect to server", + "errno" => $errno, + "errstr" => $errstr); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": $errstr ($errno)" . $this->CRLF; + } + return false; + } + + # sometimes the SMTP server takes a little longer to respond + # so we will give it a longer timeout for the first read + // Windows still does not have support for this timeout function + if(substr(PHP_OS, 0, 3) != "WIN") + socket_set_timeout($this->smtp_conn, $tval, 0); + + # get any announcement stuff + $announce = $this->get_lines(); + + # set the timeout of any socket functions at 1/10 of a second + //if(function_exists("socket_set_timeout")) + // socket_set_timeout($this->smtp_conn, 0, 100000); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce; + } + + return true; + } + + /** + * Performs SMTP authentication. Must be run after running the + * Hello() method. Returns true if successfully authenticated. + * @access public + * @return bool + */ + function Authenticate($username, $password) { + // Start authentication + fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 334) { + $this->error = + array("error" => "AUTH not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + // Send encoded username + fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 334) { + $this->error = + array("error" => "Username not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + // Send encoded password + fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 235) { + $this->error = + array("error" => "Password not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + return true; + } + + /** + * Returns true if connected to a server otherwise false + * @access private + * @return bool + */ + function Connected() { + if(!empty($this->smtp_conn)) { + $sock_status = socket_get_status($this->smtp_conn); + if($sock_status["eof"]) { + # hmm this is an odd situation... the socket is + # valid but we aren't connected anymore + if($this->do_debug >= 1) { + echo "SMTP -> NOTICE:" . $this->CRLF . + "EOF caught while checking if connected"; + } + $this->Close(); + return false; + } + return true; # everything looks good + } + return false; + } + + /** + * Closes the socket and cleans up the state of the class. + * It is not considered good to use this function without + * first trying to use QUIT. + * @access public + * @return void + */ + function Close() { + $this->error = null; # so there is no confusion + $this->helo_rply = null; + if(!empty($this->smtp_conn)) { + # close the connection and cleanup + fclose($this->smtp_conn); + $this->smtp_conn = 0; + } + } + + + /*************************************************************** + * SMTP COMMANDS * + *************************************************************/ + + /** + * Issues a data command and sends the msg_data to the server + * finializing the mail transaction. $msg_data is the message + * that is to be send with the headers. Each header needs to be + * on a single line followed by a <CRLF> with the message headers + * and the message body being seperated by and additional <CRLF>. + * + * Implements rfc 821: DATA <CRLF> + * + * SMTP CODE INTERMEDIATE: 354 + * [data] + * <CRLF>.<CRLF> + * SMTP CODE SUCCESS: 250 + * SMTP CODE FAILURE: 552,554,451,452 + * SMTP CODE FAILURE: 451,554 + * SMTP CODE ERROR : 500,501,503,421 + * @access public + * @return bool + */ + function Data($msg_data) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Data() without being connected"); + return false; + } + + fputs($this->smtp_conn,"DATA" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 354) { + $this->error = + array("error" => "DATA command not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + # the server is ready to accept data! + # according to rfc 821 we should not send more than 1000 + # including the CRLF + # characters on a single line so we will break the data up + # into lines by \r and/or \n then if needed we will break + # each of those into smaller lines to fit within the limit. + # in addition we will be looking for lines that start with + # a period '.' and append and additional period '.' to that + # line. NOTE: this does not count towards are limit. + + # normalize the line breaks so we know the explode works + $msg_data = str_replace("\r\n","\n",$msg_data); + $msg_data = str_replace("\r","\n",$msg_data); + $lines = explode("\n",$msg_data); + + # we need to find a good way to determine is headers are + # in the msg_data or if it is a straight msg body + # currently I'm assuming rfc 822 definitions of msg headers + # and if the first field of the first line (':' sperated) + # does not contain a space then it _should_ be a header + # and we can process all lines before a blank "" line as + # headers. + $field = substr($lines[0],0,strpos($lines[0],":")); + $in_headers = false; + if(!empty($field) && !strstr($field," ")) { + $in_headers = true; + } + + $max_line_length = 998; # used below; set here for ease in change + + while(list(,$line) = @each($lines)) { + $lines_out = null; + if($line == "" && $in_headers) { + $in_headers = false; + } + # ok we need to break this line up into several + # smaller lines + while(strlen($line) > $max_line_length) { + $pos = strrpos(substr($line,0,$max_line_length)," "); + + # Patch to fix DOS attack + if(!$pos) { + $pos = $max_line_length - 1; + } + + $lines_out[] = substr($line,0,$pos); + $line = substr($line,$pos + 1); + # if we are processing headers we need to + # add a LWSP-char to the front of the new line + # rfc 822 on long msg headers + if($in_headers) { + $line = "\t" . $line; + } + } + $lines_out[] = $line; + + # now send the lines to the server + while(list(,$line_out) = @each($lines_out)) { + if(strlen($line_out) > 0) + { + if(substr($line_out, 0, 1) == ".") { + $line_out = "." . $line_out; + } + } + fputs($this->smtp_conn,$line_out . $this->CRLF); + } + } + + # ok all the message data has been sent so lets get this + # over with aleady + fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "DATA not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Expand takes the name and asks the server to list all the + * people who are members of the _list_. Expand will return + * back and array of the result or false if an error occurs. + * Each value in the array returned has the format of: + * [ <full-name> <sp> ] <path> + * The definition of <path> is defined in rfc 821 + * + * Implements rfc 821: EXPN <SP> <string> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE FAILURE: 550 + * SMTP CODE ERROR : 500,501,502,504,421 + * @access public + * @return string array + */ + function Expand($name) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Expand() without being connected"); + return false; + } + + fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "EXPN not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + # parse the reply and place in our array to return to user + $entries = explode($this->CRLF,$rply); + while(list(,$l) = @each($entries)) { + $list[] = substr($l,4); + } + + return $list; + } + + /** + * Sends the HELO command to the smtp server. + * This makes sure that we and the server are in + * the same known state. + * + * Implements from rfc 821: HELO <SP> <domain> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE ERROR : 500, 501, 504, 421 + * @access public + * @return bool + */ + function Hello($host="") { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Hello() without being connected"); + return false; + } + + # if a hostname for the HELO wasn't specified determine + # a suitable one to send + if(empty($host)) { + # we need to determine some sort of appopiate default + # to send to the server + $host = "localhost"; + } + + // Send extended hello first (RFC 2821) + if(!$this->SendHello("EHLO", $host)) + { + if(!$this->SendHello("HELO", $host)) + return false; + } + + return true; + } + + /** + * Sends a HELO/EHLO command. + * @access private + * @return bool + */ + function SendHello($hello, $host) { + fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => $hello . " not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + $this->helo_rply = $rply; + + return true; + } + + /** + * Gets help information on the keyword specified. If the keyword + * is not specified then returns generic help, ussually contianing + * A list of keywords that help is available on. This function + * returns the results back to the user. It is up to the user to + * handle the returned data. If an error occurs then false is + * returned with $this->error set appropiately. + * + * Implements rfc 821: HELP [ <SP> <string> ] <CRLF> + * + * SMTP CODE SUCCESS: 211,214 + * SMTP CODE ERROR : 500,501,502,504,421 + * @access public + * @return string + */ + function Help($keyword="") { + $this->error = null; # to avoid confusion + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Help() without being connected"); + return false; + } + + $extra = ""; + if(!empty($keyword)) { + $extra = " " . $keyword; + } + + fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 211 && $code != 214) { + $this->error = + array("error" => "HELP not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + return $rply; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. + * + * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,421 + * @access public + * @return bool + */ + function Mail($from) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Mail() without being connected"); + return false; + } + + fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "MAIL not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Sends the command NOOP to the SMTP server. + * + * Implements from rfc 821: NOOP <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE ERROR : 500, 421 + * @access public + * @return bool + */ + function Noop() { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Noop() without being connected"); + return false; + } + + fputs($this->smtp_conn,"NOOP" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "NOOP not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Sends the quit command to the server and then closes the socket + * if there is no error or the $close_on_error argument is true. + * + * Implements from rfc 821: QUIT <CRLF> + * + * SMTP CODE SUCCESS: 221 + * SMTP CODE ERROR : 500 + * @access public + * @return bool + */ + function Quit($close_on_error=true) { + $this->error = null; # so there is no confusion + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Quit() without being connected"); + return false; + } + + # send the quit command to the server + fputs($this->smtp_conn,"quit" . $this->CRLF); + + # get any good-bye messages + $byemsg = $this->get_lines(); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg; + } + + $rval = true; + $e = null; + + $code = substr($byemsg,0,3); + if($code != 221) { + # use e as a tmp var cause Close will overwrite $this->error + $e = array("error" => "SMTP server rejected quit command", + "smtp_code" => $code, + "smtp_rply" => substr($byemsg,4)); + $rval = false; + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $e["error"] . ": " . + $byemsg . $this->CRLF; + } + } + + if(empty($e) || $close_on_error) { + $this->Close(); + } + + return $rval; + } + + /** + * Sends the command RCPT to the SMTP server with the TO: argument of $to. + * Returns true if the recipient was accepted false if it was rejected. + * + * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> + * + * SMTP CODE SUCCESS: 250,251 + * SMTP CODE FAILURE: 550,551,552,553,450,451,452 + * SMTP CODE ERROR : 500,501,503,421 + * @access public + * @return bool + */ + function Recipient($to) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Recipient() without being connected"); + return false; + } + + fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250 && $code != 251) { + $this->error = + array("error" => "RCPT not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Sends the RSET command to abort and transaction that is + * currently in progress. Returns true if successful false + * otherwise. + * + * Implements rfc 821: RSET <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE ERROR : 500,501,504,421 + * @access public + * @return bool + */ + function Reset() { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Reset() without being connected"); + return false; + } + + fputs($this->smtp_conn,"RSET" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "RSET failed", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + return true; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. This command + * will send the message to the users terminal if they are logged + * in. + * + * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,502,421 + * @access public + * @return bool + */ + function Send($from) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Send() without being connected"); + return false; + } + + fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "SEND not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. This command + * will send the message to the users terminal if they are logged + * in and send them an email. + * + * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,502,421 + * @access public + * @return bool + */ + function SendAndMail($from) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called SendAndMail() without being connected"); + return false; + } + + fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "SAML not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. This command + * will send the message to the users terminal if they are logged + * in or mail it to them if they are not. + * + * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,502,421 + * @access public + * @return bool + */ + function SendOrMail($from) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called SendOrMail() without being connected"); + return false; + } + + fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "SOML not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * This is an optional command for SMTP that this class does not + * support. This method is here to make the RFC821 Definition + * complete for this class and __may__ be implimented in the future + * + * Implements from rfc 821: TURN <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE FAILURE: 502 + * SMTP CODE ERROR : 500, 503 + * @access public + * @return bool + */ + function Turn() { + $this->error = array("error" => "This method, TURN, of the SMTP ". + "is not implemented"); + if($this->do_debug >= 1) { + echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF; + } + return false; + } + + /** + * Verifies that the name is recognized by the server. + * Returns false if the name could not be verified otherwise + * the response from the server is returned. + * + * Implements rfc 821: VRFY <SP> <string> <CRLF> + * + * SMTP CODE SUCCESS: 250,251 + * SMTP CODE FAILURE: 550,551,553 + * SMTP CODE ERROR : 500,501,502,421 + * @access public + * @return int + */ + function Verify($name) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Verify() without being connected"); + return false; + } + + fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250 && $code != 251) { + $this->error = + array("error" => "VRFY failed on name '$name'", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return $rply; + } + + /******************************************************************* + * INTERNAL FUNCTIONS * + ******************************************************************/ + + /** + * Read in as many lines as possible + * either before eof or socket timeout occurs on the operation. + * With SMTP we can tell if we have more lines to read if the + * 4th character is '-' symbol. If it is a space then we don't + * need to read anything else. + * @access private + * @return string + */ + function get_lines() { + $data = ""; + while($str = fgets($this->smtp_conn,515)) { + if($this->do_debug >= 4) { + echo "SMTP -> get_lines(): \$data was \"$data\"" . + $this->CRLF; + echo "SMTP -> get_lines(): \$str is \"$str\"" . + $this->CRLF; + } + $data .= $str; + if($this->do_debug >= 4) { + echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF; + } + # if the 4th character is a space then we are done reading + # so just break the loop + if(substr($str,3,1) == " ") { break; } + } + return $data; + } + +} + + + ?> diff --git a/wp-includes/class-snoopy.php b/wp-includes/class-snoopy.php index 9bf56b3..5e88787 100644 --- a/wp-includes/class-snoopy.php +++ b/wp-includes/class-snoopy.php @@ -796,7 +796,7 @@ class Snoopy $headers .= "User-Agent: ".$this->agent."\r\n"; if(!empty($this->host) && !isset($this->rawheaders['Host'])) { $headers .= "Host: ".$this->host; - if(!empty($this->port)) + if(!empty($this->port) && $this->port != 80) $headers .= ":".$this->port; $headers .= "\r\n"; } diff --git a/wp-includes/classes.php b/wp-includes/classes.php index 6bdfb2e..3ca1926 100644 --- a/wp-includes/classes.php +++ b/wp-includes/classes.php @@ -514,7 +514,7 @@ class Walker_Page extends Walker { elseif ( $_current_page && $page->ID == $_current_page->post_parent ) $css_class .= ' current_page_parent'; - $output .= $indent . '<li class="' . $css_class . '"><a href="' . get_page_link($page->ID) . '" title="' . attribute_escape($page->post_title) . '">' . $page->post_title . '</a>'; + $output .= $indent . '<li class="' . $css_class . '"><a href="' . get_page_link($page->ID) . '" title="' . attribute_escape(apply_filters('the_title', $page->post_title)) . '">' . apply_filters('the_title', $page->post_title) . '</a>'; if ( !empty($show_date) ) { if ( 'modified' == $show_date ) @@ -687,16 +687,14 @@ class WP_Ajax_Response { // a WP_Error object can be passed in 'id' or 'data' function add( $args = '' ) { - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('what' => 'object', 'action' => false, 'id' => '0', 'old_id' => false, - 'data' => '', 'supplemental' => array()); - - $r = array_merge($defaults, $r); - extract($r); + $defaults = array( + 'what' => 'object', 'action' => false, + 'id' => '0', 'old_id' => false, + 'data' => '', 'supplemental' => array() + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); if ( is_wp_error($id) ) { $data = $id; diff --git a/wp-includes/comment-template.php b/wp-includes/comment-template.php index 0c16240..ed41bb6 100644 --- a/wp-includes/comment-template.php +++ b/wp-includes/comment-template.php @@ -228,7 +228,7 @@ function get_trackback_url() { if ( '' != get_option('permalink_structure') ) $tb_url = trailingslashit(get_permalink()) . user_trailingslashit('trackback', 'single_trackback'); - return $tb_url; + return apply_filters('trackback_url', $tb_url); } function trackback_url( $display = true ) { if ( $display) @@ -288,7 +288,9 @@ function comments_template( $file = '/comments.php' ) { extract($commenter); // TODO: Use API instead of SELECTs. - if ( empty($comment_author) ) { + if ( $user_ID) { + $comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_post_ID = '$post->ID' AND (comment_approved = '1' OR ( user_id = '$user_ID' AND comment_approved = '0' ) ) ORDER BY comment_date"); + } else if ( empty($comment_author) ) { $comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_post_ID = '$post->ID' AND comment_approved = '1' ORDER BY comment_date"); } else { $author_db = $wpdb->escape($comment_author); @@ -331,7 +333,7 @@ function comments_popup_link($zero='No Comments', $one='1 Comment', $more='% Com $number = get_comments_number($id); if ( 0 == $number && 'closed' == $post->comment_status && 'closed' == $post->ping_status ) { - echo $none; + echo '<span' . ((!empty($CSSclass)) ? ' class="' . $CSSclass . '"' : '') . '>' . $none . '</span>'; return; } diff --git a/wp-includes/comment.php b/wp-includes/comment.php index 6da2264..b1aee83 100644 --- a/wp-includes/comment.php +++ b/wp-includes/comment.php @@ -73,15 +73,20 @@ function get_approved_comments($post_id) { function &get_comment(&$comment, $output = OBJECT) { global $comment_cache, $wpdb; - if ( empty($comment) ) - return null; - - if ( is_object($comment) ) { + if ( empty($comment) ) { + if ( isset($GLOBALS['comment']) ) + $_comment = & $GLOBALS['comment']; + else + $_comment = null; + } elseif ( is_object($comment) ) { if ( !isset($comment_cache[$comment->comment_ID]) ) $comment_cache[$comment->comment_ID] = &$comment; $_comment = & $comment_cache[$comment->comment_ID]; } else { - if ( !isset($comment_cache[$comment]) ) { + $comment = (int) $comment; + if ( isset($GLOBALS['comment']) && ($GLOBALS['comment']->comment_ID == $comment) ) { + $_comment = & $GLOBALS['comment']; + } elseif ( !isset($comment_cache[$comment]) ) { $_comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment' LIMIT 1"); $comment_cache[$comment->comment_ID] = & $_comment; } else { @@ -671,9 +676,7 @@ function pingback($content, $post_ID) { include_once(ABSPATH . WPINC . '/class-IXR.php'); // original code by Mort (http://mort.mine.nu:8080) - $log = debug_fopen(ABSPATH . '/pingback.log', 'a'); $post_links = array(); - debug_fwrite($log, 'BEGIN ' . date('YmdHis', time()) . "\n"); $pung = get_pung($post_ID); @@ -689,10 +692,6 @@ function pingback($content, $post_ID) { // http://www.phpfreaks.com/quickcode/Extract_All_URLs_on_a_Page/15.php preg_match_all("{\b http : [$any] +? (?= [$punc] * [^$any] | $)}x", $content, $post_links_temp); - // Debug - debug_fwrite($log, 'Post contents:'); - debug_fwrite($log, $content."\n"); - // Step 2. // Walking thru the links array // first we get rid of links pointing to sites, not to specific files @@ -716,16 +715,12 @@ function pingback($content, $post_ID) { do_action_ref_array('pre_ping', array(&$post_links, &$pung)); foreach ( (array) $post_links as $pagelinkedto ) { - debug_fwrite($log, "Processing -- $pagelinkedto\n"); $pingback_server_url = discover_pingback_server_uri($pagelinkedto, 2048); if ( $pingback_server_url ) { @ set_time_limit( 60 ); // Now, the RPC call - debug_fwrite($log, "Page Linked To: $pagelinkedto \n"); - debug_fwrite($log, 'Page Linked From: '); $pagelinkedfrom = get_permalink($post_ID); - debug_fwrite($log, $pagelinkedfrom."\n"); // using a timeout of 3 seconds should be enough to cover slow servers $client = new IXR_Client($pingback_server_url); @@ -737,13 +732,8 @@ function pingback($content, $post_ID) { if ( $client->query('pingback.ping', $pagelinkedfrom, $pagelinkedto ) ) add_ping( $post_ID, $pagelinkedto ); - else - debug_fwrite($log, "Error.\n Fault code: ".$client->getErrorCode()." : ".$client->getErrorMessage()."\n"); } } - - debug_fwrite($log, "\nEND: ".time()."\n****************************\n"); - debug_fclose($log); } @@ -780,16 +770,6 @@ function trackback($trackback_url, $title, $excerpt, $ID) { $trackback_url['port'] = 80; $fs = @fsockopen($trackback_url['host'], $trackback_url['port'], $errno, $errstr, 4); @fputs($fs, $http_request); -/* - $debug_file = 'trackback.log'; - $fp = fopen($debug_file, 'a'); - fwrite($fp, "\n*****\nRequest:\n\n$http_request\n\nResponse:\n\n"); - while(!@feof($fs)) { - fwrite($fp, @fgets($fs, 4096)); - } - fwrite($fp, "\n\n"); - fclose($fp); -*/ @fclose($fs); $tb_url = addslashes( $tb_url ); @@ -814,4 +794,4 @@ function weblog_ping($server = '', $path = '') { $client->query('weblogUpdates.ping', get_option('blogname'), $home); } -?> +?>
\ No newline at end of file diff --git a/wp-includes/compat.php b/wp-includes/compat.php index 997307f..e68ec2a 100644 --- a/wp-includes/compat.php +++ b/wp-includes/compat.php @@ -118,4 +118,11 @@ if ( !function_exists('_') ) { } } +// Added in PHP 5.0 +if (!function_exists('stripos')) { + function stripos($haystack, $needle, $offset = 0) { + return strpos(strtolower($haystack), strtolower($needle), $offset); + } +} + ?> diff --git a/wp-includes/cron.php b/wp-includes/cron.php index e9a6462..f81c6ad 100644 --- a/wp-includes/cron.php +++ b/wp-includes/cron.php @@ -97,7 +97,7 @@ function spawn_cron() { if ( $argyle )
fputs( $argyle,
- "GET {$parts['path']}?check=" . md5(DB_PASS . '187425') . " HTTP/1.0\r\n"
+ "GET {$parts['path']}?check=" . wp_hash('187425') . " HTTP/1.0\r\n"
. "Host: {$_SERVER['HTTP_HOST']}\r\n\r\n"
);
}
diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php index cda3cc9..0861361 100644 --- a/wp-includes/default-filters.php +++ b/wp-includes/default-filters.php @@ -45,7 +45,7 @@ add_filter('comment_flood_filter', 'wp_throttle_comment_flood', 10, 3); 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); @@ -173,4 +173,7 @@ 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 diff --git a/wp-includes/deprecated.php b/wp-includes/deprecated.php index b72c07f..0caba44 100644 --- a/wp-includes/deprecated.php +++ b/wp-includes/deprecated.php @@ -427,10 +427,7 @@ function list_cats($optionall = 1, $all = 'All', $sort_column = 'ID', $sort_orde }
function wp_list_cats($args = '') {
- if ( is_array($args) )
- $r = &$args;
- else
- parse_str($args, $r);
+ $r = wp_parse_args( $args );
// Map to new names.
if ( isset($r['optionall']) && isset($r['all']))
diff --git a/wp-includes/feed-atom-comments.php b/wp-includes/feed-atom-comments.php index 7efb3f9..f7aaba8 100644 --- a/wp-includes/feed-atom-comments.php +++ b/wp-includes/feed-atom-comments.php @@ -20,7 +20,7 @@ echo '<?xml version="1.0" encoding="' . get_option('blog_charset') . '" ?' . '>' <updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastcommentmodified('GMT')); ?></updated> <generator uri="http://wordpress.org/" version="<?php bloginfo('version'); ?>">WordPress</generator> - <link rel="alternate" type="<?php bloginfo_rss('html_type'); ?>" content="<?php bloginfo_rss('home'); ?>" /> + <link rel="alternate" type="<?php bloginfo_rss('html_type'); ?>" href="<?php bloginfo_rss('home'); ?>" /> <link rel="self" type="application/atom+xml" href="<?php bloginfo_rss('comments_atom_url'); ?>" /> <id><?php bloginfo_rss('comments_atom_url'); ?></id> @@ -49,8 +49,8 @@ if ( have_comments() ) : while ( have_comments() ) : the_comment(); </author> <id><?php comment_link(); ?></id> - <updated><?php echo mysql2date('D, d M Y H:i:s +0000', get_comment_time('Y-m-d H:i:s', true), false); ?></updated> - <published><?php echo mysql2date('D, d M Y H:i:s +0000', get_comment_time('Y-m-d H:i:s', true), false); ?></published> + <updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_comment_time('Y-m-d H:i:s', true), false); ?></updated> + <published><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_comment_time('Y-m-d H:i:s', true), false); ?></published> <?php if (!empty($comment_post->post_password) && $_COOKIE['wp-postpass'] != $comment_post->post_password) : ?> <content type="html" xml:base="<?php comment_link(); ?>"><![CDATA[<?php echo get_the_password_form(); ?>]]></content> <?php else : // post pass ?> diff --git a/wp-includes/feed-atom.php b/wp-includes/feed-atom.php index 8a52d1c..2eb7c2f 100644 --- a/wp-includes/feed-atom.php +++ b/wp-includes/feed-atom.php @@ -11,7 +11,7 @@ $more = 1; xml:base="<?php bloginfo_rss('home') ?>/wp-atom.php" <?php do_action('atom_ns'); ?> > - <title type="text"><?php bloginfo_rss('name') ?></title> + <title type="text"><?php bloginfo_rss('name'); wp_title_rss(); ?></title> <subtitle type="text"><?php bloginfo_rss("description") ?></subtitle> <updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT')); ?></updated> diff --git a/wp-includes/feed-rdf.php b/wp-includes/feed-rdf.php index 80b1d6d..d1ac458 100644 --- a/wp-includes/feed-rdf.php +++ b/wp-includes/feed-rdf.php @@ -15,7 +15,7 @@ $more = 1; <?php do_action('rdf_ns'); ?> > <channel rdf:about="<?php bloginfo_rss("url") ?>"> - <title><?php bloginfo_rss('name') ?></title> + <title><?php bloginfo_rss('name'); wp_title_rss(); ?></title> <link><?php bloginfo_rss('url') ?></link> <description><?php bloginfo_rss('description') ?></description> <dc:date><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></dc:date> diff --git a/wp-includes/feed-rss.php b/wp-includes/feed-rss.php index 97e0610..447dd59 100644 --- a/wp-includes/feed-rss.php +++ b/wp-includes/feed-rss.php @@ -7,7 +7,7 @@ $more = 1; <!-- generator="wordpress/<?php echo $wp_version ?>" --> <rss version="0.92"> <channel> - <title><?php bloginfo_rss('name') ?></title> + <title><?php bloginfo_rss('name'); wp_title_rss(); ?></title> <link><?php bloginfo_rss('url') ?></link> <description><?php bloginfo_rss('description') ?></description> <lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate> diff --git a/wp-includes/feed-rss2.php b/wp-includes/feed-rss2.php index 03711df..588a063 100644 --- a/wp-includes/feed-rss2.php +++ b/wp-includes/feed-rss2.php @@ -14,7 +14,7 @@ $more = 1; > <channel> - <title><?php bloginfo_rss('name'); ?></title> + <title><?php bloginfo_rss('name'); wp_title_rss(); ?></title> <link><?php bloginfo_rss('url') ?></link> <description><?php bloginfo_rss("description") ?></description> <pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></pubDate> diff --git a/wp-includes/feed.php b/wp-includes/feed.php index 26eb4da..4a0c5ac 100644 --- a/wp-includes/feed.php +++ b/wp-includes/feed.php @@ -2,12 +2,12 @@ function get_bloginfo_rss($show = '') { $info = strip_tags(get_bloginfo($show)); - return apply_filters('bloginfo_rss', convert_chars($info)); + return apply_filters('get_bloginfo_rss', convert_chars($info)); } function bloginfo_rss($show = '') { - echo get_bloginfo_rss($show); + echo apply_filters('bloginfo_rss', get_bloginfo_rss($show)); } function get_wp_title_rss($sep = '»') { @@ -16,6 +16,10 @@ function get_wp_title_rss($sep = '»') { return $title; } +function wp_title_rss($sep = '»') { + echo apply_filters('wp_title_rss', get_wp_title_rss($sep)); +} + function get_the_title_rss() { $title = get_the_title(); $title = apply_filters('the_title', $title); diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php index d497819..14eb5b8 100644 --- a/wp-includes/formatting.php +++ b/wp-includes/formatting.php @@ -55,7 +55,7 @@ function wpautop($pee, $br = 1) { $pee = $pee . "\n"; // just to make things a little easier, pad the end $pee = preg_replace('|<br />\s*<br />|', "\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|map|area|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('!(</' . $allblocks . '>)!', "$1\n\n", $pee); $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines @@ -581,11 +581,18 @@ function addslashes_gpc($gpc) { } -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; } @@ -1074,7 +1081,7 @@ function clean_url( $url, $protocols = null ) { $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); diff --git a/wp-includes/functions.php b/wp-includes/functions.php index df7ad74..97b9915 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -8,7 +8,10 @@ function mysql2date($dateformatstring, $mysqlstring, $translate = true) { if ( empty($m) ) { return false; } - $i = mktime(substr($m,11,2),substr($m,14,2),substr($m,17,2),substr($m,5,2),substr($m,8,2),substr($m,0,4)); + $i = mktime( + (int) substr( $m, 11, 2 ), (int) substr( $m, 14, 2 ), (int) substr( $m, 17, 2 ), + (int) substr( $m, 5, 2 ), (int) substr( $m, 8, 2 ), (int) substr( $m, 0, 4 ) + ); if( 'U' == $dateformatstring ) return $i; @@ -80,6 +83,14 @@ function date_i18n($dateformatstring, $unixtimestamp) { return $j; } +function number_format_i18n($number, $decimals = null) { + global $wp_locale; + // let the user override the precision only + $decimals = is_null($decimals)? $wp_locale->number_format['decimals'] : intval($decimals); + + return number_format($number, $decimals, $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep']); +} + function get_weekstartend($mysqlstring, $start_of_week) { $my = substr($mysqlstring,0,4); $mm = substr($mysqlstring,8,2); @@ -328,7 +339,7 @@ function update_option($option_name, $newvalue) { } $notoptions = wp_cache_get('notoptions', 'options'); - if ( isset($notoptions[$option_name]) ) { + if ( is_array($notoptions) && isset($notoptions[$option_name]) ) { unset($notoptions[$option_name]); wp_cache_set('notoptions', $notoptions, 'options'); } @@ -362,7 +373,7 @@ function add_option($name, $value = '', $description = '', $autoload = 'yes') { // Make sure the option doesn't already exist we can check the cache before we ask for a db query $notoptions = wp_cache_get('notoptions', 'options'); - if ( isset($notoptions[$name]) ) { + if ( is_array($notoptions) && isset($notoptions[$name]) ) { unset($notoptions[$name]); wp_cache_set('notoptions', $notoptions, 'options'); } elseif ( false !== get_option($name) ) { @@ -759,6 +770,7 @@ function clean_category_cache($id) { wp_cache_delete($id, 'category'); wp_cache_delete('all_category_ids', 'category'); wp_cache_delete('get_categories', 'category'); + delete_option('category_children'); } /* @@ -815,6 +827,9 @@ function add_query_arg() { } parse_str($query, $qs); + if ( get_magic_quotes_gpc() ) + $qs = stripslashes_deep($qs); // parse_str() adds slashes if magicquotes is on. See: http://php.net/parse_str + $qs = urlencode_deep($qs); if ( is_array(func_get_arg(0)) ) { $kayvees = func_get_arg(0); $qs = array_merge($qs, $kayvees); @@ -832,10 +847,10 @@ function add_query_arg() { $ret .= "$k=$v"; } } + $ret = trim($ret, '?'); $ret = $protocol . $base . $ret . $frag; - if ( get_magic_quotes_gpc() ) - $ret = stripslashes($ret); // parse_str() adds slashes if magicquotes is on. See: http://php.net/parse_str - return trim($ret, '?'); + $ret = trim($ret, '?'); + return $ret; } /* @@ -911,24 +926,35 @@ function wp($query_vars = '') { $wp->main($query_vars); } +function get_status_header_desc( $code ) { + global $wp_header_to_desc; + + $code = (int) $code; + + if ( isset( $wp_header_to_desc[$code] ) ) { + return $wp_header_to_desc[$code]; + } else { + return ''; + } +} + function status_header( $header ) { - if ( 200 == $header ) - $text = 'OK'; - elseif ( 301 == $header ) - $text = 'Moved Permanently'; - elseif ( 302 == $header ) - $text = 'Moved Temporarily'; - elseif ( 304 == $header ) - $text = 'Not Modified'; - elseif ( 404 == $header ) - $text = 'Not Found'; - elseif ( 410 == $header ) - $text = 'Gone'; - - if ( version_compare(phpversion(), '4.3.0', '>=') ) - @header("HTTP/1.1 $header $text", true, $header); - else - @header("HTTP/1.1 $header $text"); + $text = get_status_header_desc( $header ); + + if ( empty( $text ) ) + return false; + + $protocol = $_SERVER["SERVER_PROTOCOL"]; + if ( ('HTTP/1.1' != $protocol) && ('HTTP/1.0' != $protocol) ) + $protocol = 'HTTP/1.0'; + $status_header = "$protocol $header $text"; + $status_header = apply_filters('status_header', $status_header, $header, $text, $protocol); + + if ( version_compare( phpversion(), '4.3.0', '>=' ) ) { + return @header( $status_header, true, $header ); + } else { + return @header( $status_header ); + } } function nocache_headers() { @@ -996,6 +1022,8 @@ function do_feed_atom($for_comments) { function do_robots() { global $current_blog; + header('Content-type: text/plain; charset=utf-8'); + do_action('do_robotstxt'); if ( '0' == $current_blog->public ) { @@ -1196,6 +1224,7 @@ function wp_check_filetype($filename, $mimes = null) { 'js' => 'application/javascript', 'pdf' => 'application/pdf', 'doc' => 'application/msword', + 'odt' => 'application/vnd.oasis.opendocument.text', 'pot|pps|ppt' => 'application/vnd.ms-powerpoint', 'wri' => 'application/vnd.ms-write', 'xla|xls|xlt|xlw' => 'application/vnd.ms-excel', @@ -1243,10 +1272,10 @@ function wp_explain_nonce($action) { $trans['bulk']['comments'] = array(__('Are you sure you want to bulk modify comments?'), false); $trans['moderate']['comments'] = array(__('Are you sure you want to moderate comments?'), false); - $trans['add']['bookmark'] = array(__('Are you sure you want to add this bookmark?'), false); - $trans['delete']['bookmark'] = array(__('Are you sure you want to delete this bookmark: "%s"?'), 'use_id'); - $trans['update']['bookmark'] = array(__('Are you sure you want to edit this bookmark: "%s"?'), 'use_id'); - $trans['bulk']['bookmarks'] = array(__('Are you sure you want to bulk modify bookmarks?'), false); + $trans['add']['bookmark'] = array(__('Are you sure you want to add this link?'), false); + $trans['delete']['bookmark'] = array(__('Are you sure you want to delete this link: "%s"?'), 'use_id'); + $trans['update']['bookmark'] = array(__('Are you sure you want to edit this link: "%s"?'), 'use_id'); + $trans['bulk']['bookmarks'] = array(__('Are you sure you want to bulk modify links?'), false); $trans['add']['page'] = array(__('Are you sure you want to add this page?'), false); $trans['delete']['page'] = array(__('Are you sure you want to delete this page: "%s"?'), 'get_the_title'); @@ -1341,15 +1370,18 @@ function wp_die( $message, $title = '' ) { $message = "<p>$message</p>"; } + if (strpos($_SERVER['PHP_SELF'], 'wp-admin') !== false) + $admin_dir = ''; + else + $admin_dir = 'wp-admin/'; + + if ( !did_action('admin_head') ) : header('Content-Type: text/html; charset=utf-8'); if ( empty($title) ) $title = __('WordPress › Error'); - if (strpos($_SERVER['PHP_SELF'], 'wp-admin') !== false) - $admin_dir = ''; - else - $admin_dir = 'wp-admin/'; + ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> @@ -1358,11 +1390,13 @@ function wp_die( $message, $title = '' ) { <title><?php echo $title ?></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="<?php echo $admin_dir; ?>install.css" type="text/css" /> -<?php if ( ('rtl' == $wp_locale->text_direction) ) : ?> +<?php +if ( ( $wp_locale ) && ('rtl' == $wp_locale->text_direction) ) : ?> <link rel="stylesheet" href="<?php echo $admin_dir; ?>install-rtl.css" type="text/css" /> <?php endif; ?> </head> <body> +<?php endif; ?> <h1 id="logo"><img alt="WordPress" src="<?php echo $admin_dir; ?>images/wordpress-logo.png" /></h1> <?php echo $message; ?> @@ -1469,11 +1503,49 @@ function smilies_init() { ); } + $siteurl = get_option('siteurl'); foreach ( (array) $wpsmiliestrans as $smiley => $img ) { $wp_smiliessearch[] = '/(\s|^)'.preg_quote($smiley, '/').'(\s|$)/'; $smiley_masked = htmlspecialchars(trim($smiley), ENT_QUOTES); - $wp_smiliesreplace[] = " <img src='" . get_option('siteurl') . "/wp-includes/images/smilies/$img' alt='$smiley_masked' class='wp-smiley' /> "; + $wp_smiliesreplace[] = " <img src='$siteurl/wp-includes/images/smilies/$img' alt='$smiley_masked' class='wp-smiley' /> "; } } +function wp_parse_args( $args, $defaults = '' ) { + if ( is_array( $args ) ) { + $r =& $args; + } else { + parse_str( $args, $r ); + if ( get_magic_quotes_gpc() ) { + $r = stripslashes_deep( $r ); + } + } + + if ( is_array( $defaults ) ) { + return array_merge( $defaults, $r ); + } else { + return $r; + } +} + +function wp_maybe_load_widgets() { + if ( !function_exists( 'dynamic_sidebar' ) ) { + require_once ABSPATH . WPINC . '/widgets.php'; + add_action( '_admin_menu', 'wp_widgets_add_menu' ); + } +} + +function wp_widgets_add_menu() { + global $submenu; + $submenu['themes.php'][7] = array( __( 'Widgets' ), 'switch_themes', 'widgets.php' ); + ksort($submenu['themes.php'], SORT_NUMERIC); +} + +// For PHP 5.2, make sure all output buffers are flushed +// before our singletons our destroyed. +function wp_ob_end_flush_all() +{ + while ( @ob_end_flush() ); +} + ?> diff --git a/wp-includes/general-template.php b/wp-includes/general-template.php index 7b21003..7980319 100644 --- a/wp-includes/general-template.php +++ b/wp-includes/general-template.php @@ -21,6 +21,7 @@ function get_footer() { function get_sidebar() { + do_action( 'get_sidebar' ); if ( file_exists( TEMPLATEPATH . '/sidebar.php') ) load_template( TEMPLATEPATH . '/sidebar.php'); else @@ -200,7 +201,7 @@ function wp_title($sep = '»', $display = true) { // If there's a month if ( !empty($m) ) { $my_year = substr($m, 0, 4); - $my_month = $wp_locale->get_month($m); + $my_month = $wp_locale->get_month(substr($m, 4, 2)); $my_day = intval(substr($m, 6, 2)); $title = "$my_year" . ($my_month ? "$sep $my_month" : "") . ($my_day ? "$sep $my_day" : ""); } @@ -312,16 +313,16 @@ function get_archives_link($url, $text, $format = 'html', $before = '', $after = function wp_get_archives($args = '') { - global $wp_locale, $wpdb; - - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('type' => 'monthly', 'limit' => '', 'format' => 'html', 'before' => '', 'after' => '', 'show_post_count' => false); - $r = array_merge($defaults, $r); - extract($r); + global $wpdb, $wp_locale; + + $defaults = array( + 'type' => 'monthly', 'limit' => '', + 'format' => 'html', 'before' => '', + 'after' => '', 'show_post_count' => false + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); if ( '' == $type ) $type = 'monthly'; @@ -424,7 +425,7 @@ function wp_get_archives($args = '') { $url = get_permalink($arcresult); $arc_title = $arcresult->post_title; if ( $arc_title ) - $text = strip_tags($arc_title); + $text = strip_tags(apply_filters('the_title', $arc_title)); else $text = $arcresult->ID; echo get_archives_link($url, $text, $format, $before, $after); @@ -634,7 +635,7 @@ function get_calendar($initial = true) { ob_end_clean(); echo $output; $cache[ $key ] = $output; - wp_cache_set( 'get_calendar', $cache, 'calendar' ); + wp_cache_add( 'get_calendar', $cache, 'calendar' ); } function delete_get_calendar_cache() { @@ -809,9 +810,16 @@ function rich_edit_exists() { function user_can_richedit() { global $wp_rich_edit, $pagenow; - - if ( !isset($wp_rich_edit) ) - $wp_rich_edit = ( 'true' == get_user_option('rich_editing') && !preg_match('!opera[ /][2-8]|konqueror|safari!i', $_SERVER['HTTP_USER_AGENT']) && 'comment.php' != $pagenow && rich_edit_exists() ) ? true : false; + + if ( !isset( $wp_rich_edit) ) { + if ( get_user_option( 'rich_editing' ) == 'true' && + ( ( preg_match( '!AppleWebKit/(\d+)!', $_SERVER['HTTP_USER_AGENT'], $match ) && intval($match[1]) >= 420 ) || + !preg_match( '!opera[ /][2-8]|konqueror|safari!i', $_SERVER['HTTP_USER_AGENT'] ) ) ) { + $wp_rich_edit = true; + } else { + $wp_rich_edit = false; + } + } return apply_filters('user_can_richedit', $wp_rich_edit); } diff --git a/wp-includes/gettext.php b/wp-includes/gettext.php index aabd9cf..72558cc 100644 --- a/wp-includes/gettext.php +++ b/wp-includes/gettext.php @@ -1,32 +1,32 @@ <?php /* - Copyright (c) 2003 Danilo Segan <danilo@kvota.net>. - Copyright (c) 2005 Nico Kaiser <nico@siriux.net> - - This file is part of PHP-gettext. + Copyright (c) 2003 Danilo Segan <danilo@kvota.net>. + Copyright (c) 2005 Nico Kaiser <nico@siriux.net> - 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,332 +34,360 @@ * 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 - - - /* 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; - - // $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; - - $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; - } - - // 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); - } - 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; - } - - /** - * 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); - - # poEdit doesn't put any semicolons, which - # results in parse error in eval - $string .= ';'; - - $total = 0; - $plural = 0; - - eval("$string"); - if ($plural >= $total) $plural = $total - 1; - return $plural; - } - - /** - * 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]; - } - } - } + //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; + + // $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; + + $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; + } + + // 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]; + } + } + } } diff --git a/wp-includes/images/rss.png b/wp-includes/images/rss.png Binary files differnew file mode 100644 index 0000000..6e7b676 --- /dev/null +++ b/wp-includes/images/rss.png diff --git a/wp-includes/js/prototype.js b/wp-includes/js/prototype.js index 6253917..842385a 100644 --- a/wp-includes/js/prototype.js +++ b/wp-includes/js/prototype.js @@ -1,19 +1,33 @@ -/* Prototype JavaScript framework, version 1.5.0 +/* Prototype JavaScript framework, version 1.5.1 * (c) 2005-2007 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://prototype.conio.net/ + * For details, see the Prototype web site: http://www.prototypejs.org/ * /*--------------------------------------------------------------------------*/ var Prototype = { - Version: '1.5.0', + Version: '1.5.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + BrowserFeatures: { - XPath: !!document.evaluate + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) }, - ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', - emptyFunction: function() {}, + ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, K: function(x) { return x } } @@ -46,6 +60,26 @@ Object.extend(Object, { } }, + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + keys: function(object) { var keys = []; for (var property in object) @@ -75,15 +109,13 @@ Function.prototype.bind = function() { Function.prototype.bindAsEventListener = function(object) { var __method = this, args = $A(arguments), object = args.shift(); return function(event) { - return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); + return __method.apply(object, [event || window.event].concat(args)); } } Object.extend(Number.prototype, { toColorPart: function() { - var digits = this.toString(16); - if (this < 16) return '0' + digits; - return digits; + return this.toPaddedString(2, 16); }, succ: function() { @@ -93,9 +125,27 @@ Object.extend(Number.prototype, { times: function(iterator) { $R(0, this, true).each(iterator); return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; } }); +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + var Try = { these: function() { var returnValue; @@ -145,9 +195,19 @@ PeriodicalExecuter.prototype = { } } } -String.interpret = function(value){ - return value == null ? '' : String(value); -} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); Object.extend(String.prototype, { gsub: function(pattern, replacement) { @@ -213,17 +273,16 @@ Object.extend(String.prototype, { }, escapeHTML: function() { - var div = document.createElement('div'); - var text = document.createTextNode(this); - div.appendChild(text); - return div.innerHTML; + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; }, unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? (div.childNodes.length > 1 ? - $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) : + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : div.childNodes[0].nodeValue) : ''; }, @@ -233,15 +292,15 @@ Object.extend(String.prototype, { return match[1].split(separator || '&').inject({}, function(hash, pair) { if ((pair = pair.split('='))[0]) { - var name = decodeURIComponent(pair[0]); - var value = pair[1] ? decodeURIComponent(pair[1]) : undefined; + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); - if (hash[name] !== undefined) { - if (hash[name].constructor != Array) - hash[name] = [hash[name]]; - if (value) hash[name].push(value); + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); } - else hash[name] = value; + else hash[key] = value; } return hash; }); @@ -256,6 +315,12 @@ Object.extend(String.prototype, { String.fromCharCode(this.charCodeAt(this.length - 1) + 1); }, + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + camelize: function() { var parts = this.split('-'), len = parts.length; if (len == 1) return parts[0]; @@ -270,7 +335,7 @@ Object.extend(String.prototype, { return camelized; }, - capitalize: function(){ + capitalize: function() { return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); }, @@ -283,11 +348,59 @@ Object.extend(String.prototype, { }, inspect: function(useDoubleQuotes) { - var escapedString = this.replace(/\\/g, '\\\\'); - if (useDoubleQuotes) - return '"' + escapedString.replace(/"/g, '\\"') + '"'; - else - return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); } }); @@ -299,6 +412,13 @@ String.prototype.gsub.prepareReplacement = function(replacement) { String.prototype.parseQuery = String.prototype.toQueryParams; +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + var Template = Class.create(); Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; Template.prototype = { @@ -316,19 +436,14 @@ Template.prototype = { } } -var $break = new Object(); -var $continue = new Object(); +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { - try { - iterator(value, index++); - } catch (e) { - if (e != $continue) throw e; - } + iterator(value, index++); }); } catch (e) { if (e != $break) throw e; @@ -530,6 +645,21 @@ var $A = Array.from = function(iterable) { } } +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + Object.extend(Array.prototype, Enumerable); if (!Array.prototype._reverse) @@ -588,9 +718,11 @@ Object.extend(Array.prototype, { return this.length > 1 ? this : this[0]; }, - uniq: function() { - return this.inject([], function(array, value) { - return array.include(value) ? array : array.concat([value]); + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; }); }, @@ -604,23 +736,32 @@ Object.extend(Array.prototype, { inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; } }); Array.prototype.toArray = Array.prototype.clone; -function $w(string){ +function $w(string) { string = string.strip(); return string ? string.split(/\s+/) : []; } -if(window.opera){ - Array.prototype.concat = function(){ +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { var array = []; - for(var i = 0, length = this.length; i < length; i++) array.push(this[i]); - for(var i = 0, length = arguments.length; i < length; i++) { - if(arguments[i].constructor == Array) { - for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) array.push(arguments[i][j]); } else { array.push(arguments[i]); @@ -629,37 +770,48 @@ if(window.opera){ return array; } } -var Hash = function(obj) { - Object.extend(this, obj || {}); +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); }; Object.extend(Hash, { toQueryString: function(obj) { var parts = []; + parts.add = arguments.callee.addPair; - this.prototype._each.call(obj, function(pair) { + this.prototype._each.call(obj, function(pair) { if (!pair.key) return; + var value = pair.value; - if (pair.value && pair.value.constructor == Array) { - var values = pair.value.compact(); - if (values.length < 2) pair.value = values.reduce(); - else { - key = encodeURIComponent(pair.key); - values.each(function(value) { - value = value != undefined ? encodeURIComponent(value) : ''; - parts.push(key + '=' + encodeURIComponent(value)); - }); - return; - } + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; } - if (pair.value == undefined) pair[1] = ''; - parts.push(pair.map(encodeURIComponent).join('=')); - }); + parts.add(pair.key, value); + }); return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; } }); +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + Object.extend(Hash.prototype, Enumerable); Object.extend(Hash.prototype, { _each: function(iterator) { @@ -713,13 +865,36 @@ Object.extend(Hash.prototype, { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; + }, + + toJSON: function() { + return Hash.toJSON(this); } }); function $H(object) { - if (object && object.constructor == Hash) return object; + if (object instanceof Hash) return object; return new Hash(object); }; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; ObjectRange = Class.create(); Object.extend(ObjectRange.prototype, Enumerable); Object.extend(ObjectRange.prototype, { @@ -834,7 +1009,7 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { request: function(url) { this.url = url; this.method = this.options.method; - var params = this.options.parameters; + var params = Object.clone(this.options.parameters); if (!['get', 'post'].include(this.method)) { // simulate other verbs over post @@ -842,14 +1017,18 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { this.method = 'post'; } - params = Hash.toQueryString(params); - if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' + this.parameters = params; - // when GET, append parameters to URL - if (this.method == 'get' && params) - this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params; + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } try { + if (this.options.onCreate) this.options.onCreate(this.transport); Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.method.toUpperCase(), this.url, @@ -861,9 +1040,8 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { this.transport.onreadystatechange = this.onStateChange.bind(this); this.setRequestHeaders(); - var body = this.method == 'post' ? (this.options.postBody || params) : null; - - this.transport.send(body); + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); /* Force Firefox to handle ready state 4 for synchronous requests */ if (!this.options.asynchronous && this.transport.overrideMimeType) @@ -935,7 +1113,8 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { this.dispatchException(e); } - if ((this.getHeader('Content-type') || 'text/javascript').strip(). + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) this.evalResponse(); } @@ -962,13 +1141,13 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { evalJSON: function() { try { var json = this.getHeader('X-JSON'); - return json ? eval('(' + json + ')') : null; + return json ? json.evalJSON() : null; } catch (e) { return null } }, evalResponse: function() { try { - return eval(this.transport.responseText); + return eval((this.transport.responseText || '').unfilterJSON()); } catch (e) { this.dispatchException(e); } @@ -1083,50 +1262,52 @@ if (Prototype.BrowserFeatures.XPath) { results.push(query.snapshotItem(i)); return results; }; -} -document.getElementsByClassName = function(className, parentElement) { - if (Prototype.BrowserFeatures.XPath) { + document.getElementsByClassName = function(className, parentElement) { var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; return document._getElementsByXPath(q, parentElement); - } else { - var children = ($(parentElement) || document.body).getElementsByTagName('*'); - var elements = [], child; - for (var i = 0, length = children.length; i < length; i++) { - child = children[i]; - if (Element.hasClassName(child, className)) - elements.push(Element.extend(child)); - } - return elements; } + +} else document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; }; /*--------------------------------------------------------------------------*/ -if (!window.Element) - var Element = new Object(); +if (!window.Element) var Element = {}; Element.extend = function(element) { - if (!element || _nativeExtensions || element.nodeType == 3) return element; - - if (!element._extended && element.tagName && element != window) { - var methods = Object.clone(Element.Methods), cache = Element.extend.cache; + var F = Prototype.BrowserFeatures; + if (!element || !element.tagName || element.nodeType == 3 || + element._extended || F.SpecificElementExtensions || element == window) + return element; - if (element.tagName == 'FORM') - Object.extend(methods, Form.Methods); - if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName)) - Object.extend(methods, Form.Element.Methods); + var methods = {}, tagName = element.tagName, cache = Element.extend.cache, + T = Element.Methods.ByTag; + // extend methods for all tags (Safari doesn't need this) + if (!F.ElementExtensions) { + Object.extend(methods, Element.Methods), Object.extend(methods, Element.Methods.Simulated); + } - for (var property in methods) { - var value = methods[property]; - if (typeof value == 'function' && !(property in element)) - element[property] = cache.findOrStore(value); - } + // extend methods for specific tags + if (T[tagName]) Object.extend(methods, T[tagName]); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); } - element._extended = true; + element._extended = Prototype.emptyFunction; return element; }; @@ -1212,7 +1393,13 @@ Element.Methods = { }, descendants: function(element) { - return $A($(element).getElementsByTagName('*')); + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); }, immediateDescendants: function(element) { @@ -1242,19 +1429,35 @@ Element.Methods = { }, up: function(element, expression, index) { - return Selector.findElement($(element).ancestors(), expression, index); + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return expression ? Selector.findElement(ancestors, expression, index) : + ancestors[index || 0]; }, down: function(element, expression, index) { - return Selector.findElement($(element).descendants(), expression, index); + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); + return expression ? Selector.findElement(descendants, expression, index) : + descendants[index || 0]; }, previous: function(element, expression, index) { - return Selector.findElement($(element).previousSiblings(), expression, index); + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return expression ? Selector.findElement(previousSiblings, expression, index) : + previousSiblings[index || 0]; }, next: function(element, expression, index) { - return Selector.findElement($(element).nextSiblings(), expression, index); + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return expression ? Selector.findElement(nextSiblings, expression, index) : + nextSiblings[index || 0]; }, getElementsBySelector: function() { @@ -1268,12 +1471,13 @@ Element.Methods = { readAttribute: function(element, name) { element = $(element); - if (document.all && !window.opera) { + if (Prototype.Browser.IE) { + if (!element.attributes) return null; var t = Element._attributeTranslations; if (t.values[name]) return t.values[name](element, name); if (t.names[name]) name = t.names[name]; var attribute = element.attributes[name]; - if(attribute) return attribute.nodeValue; + return attribute ? attribute.nodeValue : null; } return element.getAttribute(name); }, @@ -1342,7 +1546,7 @@ Element.Methods = { }, empty: function(element) { - return $(element).innerHTML.match(/^\s*$/); + return $(element).innerHTML.blank(); }, descendantOf: function(element, ancestor) { @@ -1361,55 +1565,38 @@ Element.Methods = { getStyle: function(element, style) { element = $(element); - if (['float','cssFloat'].include(style)) - style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat'); - style = style.camelize(); + style = style == 'float' ? 'cssFloat' : style.camelize(); var value = element.style[style]; if (!value) { - if (document.defaultView && document.defaultView.getComputedStyle) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css[style] : null; - } else if (element.currentStyle) { - value = element.currentStyle[style]; - } + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, - if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none')) - value = element['offset'+style.capitalize()] + 'px'; + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, - if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) - if (Element.getStyle(element, 'position') == 'static') value = 'auto'; - if(style == 'opacity') { - if(value) return parseFloat(value); - if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) - if(value[1]) return parseFloat(value[1]) / 100; - return 1.0; - } - return value == 'auto' ? null : value; + setStyle: function(element, styles, camelized) { + element = $(element); + var elementStyle = element.style; + + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]) + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + (camelized ? property : property.camelize())] = styles[property]; + + return element; }, - setStyle: function(element, style) { + setOpacity: function(element, value) { element = $(element); - for (var name in style) { - var value = style[name]; - if(name == 'opacity') { - if (value == 1) { - value = (/Gecko/.test(navigator.userAgent) && - !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0; - if(/MSIE/.test(navigator.userAgent) && !window.opera) - element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); - } else if(value == '') { - if(/MSIE/.test(navigator.userAgent) && !window.opera) - element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); - } else { - if(value < 0.00001) value = 0; - if(/MSIE/.test(navigator.userAgent) && !window.opera) - element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') + - 'alpha(opacity='+value*100+')'; - } - } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat'; - element.style[name.camelize()] = value; - } + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; return element; }, @@ -1483,61 +1670,58 @@ Element.Methods = { } }; -Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf}); - -Element._attributeTranslations = {}; - -Element._attributeTranslations.names = { - colspan: "colSpan", - rowspan: "rowSpan", - valign: "vAlign", - datetime: "dateTime", - accesskey: "accessKey", - tabindex: "tabIndex", - enctype: "encType", - maxlength: "maxLength", - readonly: "readOnly", - longdesc: "longDesc" -}; - -Element._attributeTranslations.values = { - _getAttr: function(element, attribute) { - return element.getAttribute(attribute, 2); - }, - - _flag: function(element, attribute) { - return $(element).hasAttribute(attribute) ? attribute : null; - }, +Object.extend(Element.Methods, { + childOf: Element.Methods.descendantOf, + childElements: Element.Methods.immediateDescendants +}); - style: function(element) { - return element.style.cssText.toLowerCase(); - }, +if (Prototype.Browser.Opera) { + Element.Methods._getStyle = Element.Methods.getStyle; + Element.Methods.getStyle = function(element, style) { + switch(style) { + case 'left': + case 'top': + case 'right': + case 'bottom': + if (Element._getStyle(element, 'position') == 'static') return null; + default: return Element._getStyle(element, style); + } + }; +} +else if (Prototype.Browser.IE) { + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; - title: function(element) { - var node = element.getAttributeNode('title'); - return node.specified ? node.nodeValue : null; - } -}; + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } -Object.extend(Element._attributeTranslations.values, { - href: Element._attributeTranslations.values._getAttr, - src: Element._attributeTranslations.values._getAttr, - disabled: Element._attributeTranslations.values._flag, - checked: Element._attributeTranslations.values._flag, - readonly: Element._attributeTranslations.values._flag, - multiple: Element._attributeTranslations.values._flag -}); + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset'+style.capitalize()] + 'px'; + return null; + } + return value; + }; -Element.Methods.Simulated = { - hasAttribute: function(element, attribute) { - var t = Element._attributeTranslations; - attribute = t.names[attribute] || attribute; - return $(element).getAttributeNode(attribute).specified; - } -}; + Element.Methods.setOpacity = function(element, value) { + element = $(element); + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); + return element; + } else if (value < 0.00001) value = 0; + style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; -// IE is missing .innerHTML support for TABLE-related elements -if (document.all && !window.opera){ + // IE is missing .innerHTML support for TABLE-related elements Element.Methods.update = function(element, html) { element = $(element); html = typeof html == 'undefined' ? '' : html.toString(); @@ -1558,35 +1742,123 @@ if (document.all && !window.opera){ div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; depth = 4; } - $A(element.childNodes).each(function(node){ - element.removeChild(node) - }); - depth.times(function(){ div = div.firstChild }); - - $A(div.childNodes).each( - function(node){ element.appendChild(node) }); + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + depth.times(function() { div = div.firstChild }); + $A(div.childNodes).each(function(node) { element.appendChild(node) }); } else { element.innerHTML = html.stripScripts(); } - setTimeout(function() {html.evalScripts()}, 10); + setTimeout(function() { html.evalScripts() }, 10); + return element; + } +} +else if (Prototype.Browser.Gecko) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; return element; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } } }; +(function() { + Object.extend(this, { + href: this._getAttr, + src: this._getAttr, + type: this._getAttr, + disabled: this._flag, + checked: this._flag, + readonly: this._flag, + multiple: this._flag + }); +}).call(Element._attributeTranslations.values); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations, node; + attribute = t.names[attribute] || attribute; + node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = {}; + Object.extend(Element, Element.Methods); -var _nativeExtensions = false; +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { + window.HTMLElement = {}; + window.HTMLElement.prototype = document.createElement('div').__proto__; + Prototype.BrowserFeatures.ElementExtensions = true; +} -if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) { - var className = 'HTML' + tag + 'Element'; - if(window[className]) return; - var klass = window[className] = {}; - klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__; - }); +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; Element.addMethods = function(methods) { - Object.extend(Element.Methods, methods || {}); + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || {}); + else { + if (tagName.constructor == Array) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = {}; + Object.extend(Element.Methods.ByTag[tagName], methods); + } function copy(methods, destination, onlyIfAbsent) { onlyIfAbsent = onlyIfAbsent || false; @@ -1598,19 +1870,49 @@ Element.addMethods = function(methods) { } } - if (typeof HTMLElement != 'undefined') { + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = {}; + window[klass].prototype = document.createElement(tagName).__proto__; + return window[klass]; + } + + if (F.ElementExtensions) { copy(Element.Methods, HTMLElement.prototype); copy(Element.Methods.Simulated, HTMLElement.prototype, true); - copy(Form.Methods, HTMLFormElement.prototype); - [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) { - copy(Form.Element.Methods, klass.prototype); - }); - _nativeExtensions = true; } -} -var Toggle = new Object(); -Toggle.display = Element.toggle; + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (typeof klass == "undefined") continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; +}; + +var Toggle = { display: Element.toggle }; /*--------------------------------------------------------------------------*/ @@ -1741,129 +2043,572 @@ Element.ClassNames.prototype = { }; Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + var Selector = Class.create(); + Selector.prototype = { initialize: function(expression) { - this.params = {classNames: []}; - this.expression = expression.toString().strip(); - this.parseExpression(); + this.expression = expression.strip(); this.compileMatcher(); }, - parseExpression: function() { - function abort(message) { throw 'Parse error in selector: ' + message; } + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); - if (this.expression == '') abort('empty expression'); + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; - var params = this.params, expr = this.expression, match, modifier, clause, rest; - while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { - params.attributes = params.attributes || []; - params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); - expr = match[1]; + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; } - - if (expr == '*') return this.params.wildcard = true; - - while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { - modifier = match[1], clause = match[2], rest = match[3]; - switch (modifier) { - case '#': params.id = clause; break; - case '.': params.classNames.push(clause); break; - case '': - case undefined: params.tagName = clause.toUpperCase(); break; - default: abort(expr.inspect()); + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } } - expr = rest; } - if (expr.length > 0) abort(expr.inspect()); + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; }, - buildMatchExpression: function() { - var params = this.params, conditions = [], clause; + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; - if (params.wildcard) - conditions.push('true'); - if (clause = params.id) - conditions.push('element.readAttribute("id") == ' + clause.inspect()); - if (clause = params.tagName) - conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); - if ((clause = params.classNames).length > 0) - for (var i = 0, length = clause.length; i < length; i++) - conditions.push('element.hasClassName(' + clause[i].inspect() + ')'); - if (clause = params.attributes) { - clause.each(function(attribute) { - var value = 'element.readAttribute(' + attribute.name.inspect() + ')'; - var splitValueBy = function(delimiter) { - return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; - } + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } - switch (attribute.operator) { - case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; - case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; - case '|=': conditions.push( - splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() - ); break; - case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; - case '': - case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break; - default: throw 'Unknown operator ' + attribute.operator + ' in selector'; + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; } - }); + } } - return conditions.join(' && '); + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; }, - compileMatcher: function() { - this.match = new Function('element', 'if (!element.tagName) return false; \ - element = $(element); \ - return ' + this.buildMatchExpression()); + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); }, - findElements: function(scope) { - var element; - - if (element = $(this.params.id)) - if (this.match(element)) - if (!scope || Element.childOf(element, scope)) - return [element]; - - scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); - - var results = []; - for (var i = 0, length = scope.length; i < length; i++) - if (this.match(element = scope[i])) - results.push(Element.extend(element)); - - return results; + match: function(element) { + return this.findElements(document).include(element); }, toString: function() { return this.expression; + }, + + inspect: function() { + return "#<Selector:" + this.expression.inspect() + ">"; } -} +}; Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + matchElements: function(elements, expression) { - var selector = new Selector(expression); - return elements.select(selector.match.bind(selector)).map(Element.extend); + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; }, findElement: function(elements, expression, index) { - if (typeof expression == 'number') index = expression, expression = false; + if (typeof expression == 'number') { + index = expression; expression = false; + } return Selector.matchElements(elements, expression || '*')[index || 0]; }, findChildElements: function(element, expressions) { - return expressions.map(function(expression) { - return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) { - var selector = new Selector(expr); - return results.inject([], function(elements, result) { - return elements.concat(selector.findElements(result || element)); - }); - }); - }).flatten(); + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; } }); @@ -1880,8 +2625,8 @@ var Form = { var data = elements.inject({}, function(result, element) { if (!element.disabled && element.name) { var key = element.name, value = $(element).getValue(); - if (value != undefined) { - if (result[key]) { + if (value != null) { + if (key in result) { if (result[key].constructor != Array) result[key] = [result[key]]; result[key].push(value); } @@ -1928,18 +2673,13 @@ Form.Methods = { disable: function(form) { form = $(form); - form.getElements().each(function(element) { - element.blur(); - element.disabled = 'true'; - }); + Form.getElements(form).invoke('disable'); return form; }, enable: function(form) { form = $(form); - form.getElements().each(function(element) { - element.disabled = ''; - }); + Form.getElements(form).invoke('enable'); return form; }, @@ -1954,11 +2694,26 @@ Form.Methods = { form = $(form); form.findFirstElement().activate(); return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); } } -Object.extend(Form, Form.Methods); - /*--------------------------------------------------------------------------*/ Form.Element = { @@ -2004,30 +2759,33 @@ Form.Element.Methods = { activate: function(element) { element = $(element); - element.focus(); - if (element.select && ( element.tagName.toLowerCase() != 'input' || - !['button', 'reset', 'submit'].include(element.type) ) ) - element.select(); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) {} return element; }, disable: function(element) { element = $(element); + element.blur(); element.disabled = true; return element; }, enable: function(element) { element = $(element); - element.blur(); element.disabled = false; return element; } } -Object.extend(Form.Element, Form.Element.Methods); +/*--------------------------------------------------------------------------*/ + var Field = Form.Element; -var $F = Form.Element.getValue; +var $F = Form.Element.Methods.getValue; /*--------------------------------------------------------------------------*/ @@ -2194,7 +2952,7 @@ Object.extend(Event, { KEY_PAGEDOWN: 34, element: function(event) { - return event.target || event.srcElement; + return $(event.target || event.srcElement); }, isLeftClick: function(event) { @@ -2259,8 +3017,7 @@ Object.extend(Event, { useCapture = useCapture || false; if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.attachEvent)) + (Prototype.Browser.WebKit || element.attachEvent)) name = 'keydown'; Event._observeAndCache(element, name, observer, useCapture); @@ -2271,8 +3028,7 @@ Object.extend(Event, { useCapture = useCapture || false; if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.detachEvent)) + (Prototype.Browser.WebKit || element.attachEvent)) name = 'keydown'; if (element.removeEventListener) { @@ -2286,7 +3042,7 @@ Object.extend(Event, { }); /* prevent memory leaks in IE */ -if (navigator.appVersion.match(/\bMSIE\b/)) +if (Prototype.Browser.IE) Event.observe(window, 'unload', Event.unloadCache, false); var Position = { // set to true if needed, warning: firefox performance problems @@ -2400,7 +3156,7 @@ var Position = { valueL += element.offsetLeft || 0; // Safari fix - if (element.offsetParent==document.body) + if (element.offsetParent == document.body) if (Element.getStyle(element,'position')=='absolute') break; } while (element = element.offsetParent); @@ -2496,7 +3252,7 @@ var Position = { // Safari returns margins on body which is incorrect if the child is absolutely // positioned. For performance reasons, redefine Position.cumulativeOffset for // KHTML/WebKit only. -if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { +if (Prototype.Browser.WebKit) { Position.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { diff --git a/wp-includes/js/quicktags.js b/wp-includes/js/quicktags.js index 12a95c7..0837d84 100644 --- a/wp-includes/js/quicktags.js +++ b/wp-includes/js/quicktags.js @@ -168,7 +168,7 @@ function edShowButton(button, i) { } function edShowLinks() { - var tempStr = '<select onchange="edQuickLink(this.options[this.selectedIndex].value, this);"><option value="-1" selected>(Quick Links)</option>'; + var tempStr = '<select onchange="edQuickLink(this.options[this.selectedIndex].value, this);"><option value="-1" selected>' + quicktagsL10n.quickLinks + '</option>'; for (i = 0; i < edLinks.length; i++) { tempStr += '<option value="' + i + '">' + edLinks[i].display + '</option>'; } @@ -248,7 +248,7 @@ function edSpell(myField) { } } if (word == '') { - word = prompt('Enter a word to look up:', ''); + word = prompt(quicktagsL10n.wordLookup, ''); } if (word !== null && /^\w[\w ]*$/.test(word)) { window.open('http://www.answers.com/' + escape(word)); @@ -260,8 +260,8 @@ function edToolbar() { for (i = 0; i < edButtons.length; i++) { edShowButton(edButtons[i], i); } - document.write('<input type="button" id="ed_spell" class="ed_button" onclick="edSpell(edCanvas);" title="Dictionary lookup" value="lookup" />'); - document.write('<input type="button" id="ed_close" class="ed_button" onclick="edCloseAllTags();" title="Close all open tags" value="Close Tags" />'); + document.write('<input type="button" id="ed_spell" class="ed_button" onclick="edSpell(edCanvas);" title="' + quicktagsL10n.dictionaryLookup + '" value="' + quicktagsL10n.lookup + '" />'); + document.write('<input type="button" id="ed_close" class="ed_button" onclick="edCloseAllTags();" title="' + quicktagsL10n.closeAllOpenTags + '" value="' + quicktagsL10n.closeTags + '" />'); // edShowLinks(); // disabled by default document.write('</div>'); } @@ -366,7 +366,7 @@ function edInsertLink(myField, i, defaultValue) { defaultValue = 'http://'; } if (!edCheckOpenTags(i)) { - var URL = prompt('Enter the URL' ,defaultValue); + var URL = prompt(quicktagsL10n.enterURL, defaultValue); if (URL) { edButtons[i].tagStart = '<a href="' + URL + '">'; edInsertTag(myField, i); @@ -378,11 +378,11 @@ function edInsertLink(myField, i, defaultValue) { } function edInsertImage(myField) { - var myValue = prompt('Enter the URL of the image', 'http://'); + var myValue = prompt(quicktagsL10n.enterImageURL, 'http://'); if (myValue) { myValue = '<img src="' + myValue - + '" alt="' + prompt('Enter a description of the image', '') + + '" alt="' + prompt(quicktagsL10n.enterImageDescription, '') + '" />'; edInsertContent(myField, myValue); } diff --git a/wp-includes/js/scriptaculous/builder.js b/wp-includes/js/scriptaculous/builder.js index 199afc1..69a1506 100644 --- a/wp-includes/js/scriptaculous/builder.js +++ b/wp-includes/js/scriptaculous/builder.js @@ -1,6 +1,6 @@ -// script.aculo.us builder.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 +// script.aculo.us builder.js v1.7.1_beta2, Sat Apr 28 15:20:12 CEST 2007 -// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ @@ -48,7 +48,8 @@ var Builder = { // attributes (or text) if(arguments[1]) if(this._isStringOrNumber(arguments[1]) || - (arguments[1] instanceof Array)) { + (arguments[1] instanceof Array) || + arguments[1].tagName) { this._children(element, arguments[1]); } else { var attrs = this._attributes(arguments[1]); @@ -66,7 +67,7 @@ var Builder = { } if(element.tagName.toUpperCase() != elementName) element = parentElement.getElementsByTagName(elementName)[0]; - } + } } // text, or array of children @@ -92,6 +93,10 @@ var Builder = { return attrs.join(" "); }, _children: function(element, children) { + if(children.tagName) { + element.appendChild(children); + return; + } if(typeof children=='object') { // array can hold nodes and text children.flatten().each( function(e) { if(typeof e=='object') @@ -101,8 +106,8 @@ var Builder = { element.appendChild(Builder._text(e)); }); } else - if(Builder._isStringOrNumber(children)) - element.appendChild(Builder._text(children)); + if(Builder._isStringOrNumber(children)) + element.appendChild(Builder._text(children)); }, _isStringOrNumber: function(param) { return(typeof param=='string' || typeof param=='number'); diff --git a/wp-includes/js/scriptaculous/controls.js b/wp-includes/js/scriptaculous/controls.js index 46f2cc1..feea27e 100644 --- a/wp-includes/js/scriptaculous/controls.js +++ b/wp-includes/js/scriptaculous/controls.js @@ -1,8 +1,8 @@ -// script.aculo.us controls.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 +// script.aculo.us controls.js v1.7.1_beta2, Sat Apr 28 15:20:12 CEST 2007 -// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com) +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) // Contributors: // Richard Livsey // Rahul Bhargava @@ -43,7 +43,8 @@ var Autocompleter = {} Autocompleter.Base = function() {}; Autocompleter.Base.prototype = { baseInitialize: function(element, update, options) { - this.element = $(element); + element = $(element) + this.element = element; this.update = $(update); this.hasFocus = false; this.changed = false; @@ -83,15 +84,20 @@ Autocompleter.Base.prototype = { Element.hide(this.update); - Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this)); - Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this)); + Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this)); + + // Turn autocomplete back on when the user leaves the page, so that the + // field's value will be remembered on Mozilla-based browsers. + Event.observe(window, 'beforeunload', function(){ + element.setAttribute('autocomplete', 'on'); + }); }, show: function() { if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); if(!this.iefix && - (navigator.appVersion.indexOf('MSIE')>0) && - (navigator.userAgent.indexOf('Opera')<0) && + (Prototype.Browser.IE) && (Element.getStyle(this.update, 'position')=='absolute')) { new Insertion.After(this.update, '<iframe id="' + this.update.id + '_iefix" '+ @@ -141,17 +147,17 @@ Autocompleter.Base.prototype = { case Event.KEY_UP: this.markPrevious(); this.render(); - if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event); + if(Prototype.Browser.WebKit) Event.stop(event); return; case Event.KEY_DOWN: this.markNext(); this.render(); - if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event); + if(Prototype.Browser.WebKit) Event.stop(event); return; } else if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || - (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return; + (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; this.changed = true; this.hasFocus = true; @@ -197,7 +203,6 @@ Autocompleter.Base.prototype = { this.index==i ? Element.addClassName(this.getEntry(i),"selected") : Element.removeClassName(this.getEntry(i),"selected"); - if(this.hasFocus) { this.show(); this.active = true; @@ -299,7 +304,6 @@ Autocompleter.Base.prototype = { onObserverEvent: function() { this.changed = false; if(this.getToken().length>=this.options.minChars) { - this.startIndicator(); this.getUpdatedChoices(); } else { this.active = false; @@ -340,7 +344,9 @@ Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.pro }, getUpdatedChoices: function() { - entry = encodeURIComponent(this.options.paramName) + '=' + + this.startIndicator(); + + var entry = encodeURIComponent(this.options.paramName) + '=' + encodeURIComponent(this.getToken()); this.options.parameters = this.options.callback ? @@ -348,7 +354,7 @@ Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.pro if(this.options.defaultParams) this.options.parameters += '&' + this.options.defaultParams; - + new Ajax.Request(this.url, this.options); }, @@ -477,9 +483,14 @@ Ajax.InPlaceEditor.prototype = { this.options = Object.extend({ paramName: "value", okButton: true, + okLink: false, okText: "ok", + cancelButton: false, cancelLink: true, cancelText: "cancel", + textBeforeControls: '', + textBetweenControls: '', + textAfterControls: '', savingText: "Saving...", clickToEditText: "Click to edit", okText: "ok", @@ -567,23 +578,52 @@ Ajax.InPlaceEditor.prototype = { var br = document.createElement("br"); this.form.appendChild(br); } + + if (this.options.textBeforeControls) + this.form.appendChild(document.createTextNode(this.options.textBeforeControls)); if (this.options.okButton) { - okButton = document.createElement("input"); + var okButton = document.createElement("input"); okButton.type = "submit"; okButton.value = this.options.okText; okButton.className = 'editor_ok_button'; this.form.appendChild(okButton); } + + if (this.options.okLink) { + var okLink = document.createElement("a"); + okLink.href = "#"; + okLink.appendChild(document.createTextNode(this.options.okText)); + okLink.onclick = this.onSubmit.bind(this); + okLink.className = 'editor_ok_link'; + this.form.appendChild(okLink); + } + + if (this.options.textBetweenControls && + (this.options.okLink || this.options.okButton) && + (this.options.cancelLink || this.options.cancelButton)) + this.form.appendChild(document.createTextNode(this.options.textBetweenControls)); + + if (this.options.cancelButton) { + var cancelButton = document.createElement("input"); + cancelButton.type = "submit"; + cancelButton.value = this.options.cancelText; + cancelButton.onclick = this.onclickCancel.bind(this); + cancelButton.className = 'editor_cancel_button'; + this.form.appendChild(cancelButton); + } if (this.options.cancelLink) { - cancelLink = document.createElement("a"); + var cancelLink = document.createElement("a"); cancelLink.href = "#"; cancelLink.appendChild(document.createTextNode(this.options.cancelText)); cancelLink.onclick = this.onclickCancel.bind(this); - cancelLink.className = 'editor_cancel'; + cancelLink.className = 'editor_cancel editor_cancel_link'; this.form.appendChild(cancelLink); } + + if (this.options.textAfterControls) + this.form.appendChild(document.createTextNode(this.options.textAfterControls)); }, hasHTMLLineBreaks: function(string) { if (!this.options.handleLineBreaks) return false; diff --git a/wp-includes/js/scriptaculous/dragdrop.js b/wp-includes/js/scriptaculous/dragdrop.js index 32c91bc..58fe342 100644 --- a/wp-includes/js/scriptaculous/dragdrop.js +++ b/wp-includes/js/scriptaculous/dragdrop.js @@ -1,7 +1,7 @@ -// script.aculo.us dragdrop.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 +// script.aculo.us dragdrop.js v1.7.1_beta2, Sat Apr 28 15:20:12 CEST 2007 -// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005, 2006 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ @@ -112,8 +112,10 @@ var Droppables = { Position.prepare(); if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) - if (this.last_active.onDrop) - this.last_active.onDrop(element, this.last_active.element, event); + if (this.last_active.onDrop) { + this.last_active.onDrop(element, this.last_active.element, event); + return true; + } }, reset: function() { @@ -245,6 +247,7 @@ Draggable.prototype = { }, zindex: 1000, revert: false, + quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, @@ -353,8 +356,12 @@ Draggable.prototype = { updateDrag: function(event, pointer) { if(!this.dragging) this.startDrag(event); - Position.prepare(); - Droppables.show(pointer, this.element); + + if(!this.options.quiet){ + Position.prepare(); + Droppables.show(pointer, this.element); + } + Draggables.notify('onDrag', this, event); this.draw(pointer); @@ -382,13 +389,19 @@ Draggable.prototype = { } // fix AppleWebKit rendering - if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); + if(Prototype.Browser.WebKit) window.scrollBy(0,0); Event.stop(event); }, finishDrag: function(event, success) { this.dragging = false; + + if(this.options.quiet){ + Position.prepare(); + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + Droppables.show(pointer, this.element); + } if(this.options.ghosting) { Position.relativize(this.element); @@ -396,7 +409,12 @@ Draggable.prototype = { this._clone = null; } - if(success) Droppables.fire(event, this.element); + var dropped = false; + if(success) { + dropped = Droppables.fire(event, this.element); + if (!dropped) dropped = false; + } + if(dropped && this.options.onDropped) this.options.onDropped(this.element); Draggables.notify('onEnd', this, event); var revert = this.options.revert; @@ -404,8 +422,9 @@ Draggable.prototype = { var d = this.currentDelta(); if(revert && this.options.reverteffect) { - this.options.reverteffect(this.element, - d[1]-this.delta[1], d[0]-this.delta[0]); + if (dropped == 0 || revert != 'failure') + this.options.reverteffect(this.element, + d[1]-this.delta[1], d[0]-this.delta[0]); } else { this.delta = d; } @@ -614,6 +633,7 @@ var Sortable = { delay: 0, hoverclass: null, ghosting: false, + quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, @@ -628,6 +648,7 @@ var Sortable = { // build options for the draggables var options_for_draggable = { revert: true, + quiet: options.quiet, scroll: options.scroll, scrollSpeed: options.scrollSpeed, scrollSensitivity: options.scrollSensitivity, diff --git a/wp-includes/js/scriptaculous/effects.js b/wp-includes/js/scriptaculous/effects.js index 6b7e5c3..596b62e 100644 --- a/wp-includes/js/scriptaculous/effects.js +++ b/wp-includes/js/scriptaculous/effects.js @@ -1,6 +1,6 @@ -// script.aculo.us effects.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 +// script.aculo.us effects.js v1.7.1_beta2, Sat Apr 28 15:20:12 CEST 2007 -// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Contributors: // Justin Palmer (http://encytemedia.com/) // Mark Pilgrim (http://diveintomark.org/) @@ -45,18 +45,10 @@ Element.collectTextNodesIgnoreClass = function(element, className) { Element.setContentZoom = function(element, percent) { element = $(element); element.setStyle({fontSize: (percent/100) + 'em'}); - if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); + if(Prototype.Browser.WebKit) window.scrollBy(0,0); return element; } -Element.getOpacity = function(element){ - return $(element).getStyle('opacity'); -} - -Element.setOpacity = function(element, value){ - return $(element).setStyle({opacity:value}); -} - Element.getInlineOpacity = function(element){ return $(element).style.opacity || ''; } @@ -89,7 +81,7 @@ var Effect = { throw("Effect.tagifyText requires including script.aculo.us' builder.js library"); var tagifyStyle = 'position:relative'; - if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1'; + if(Prototype.Browser.IE) tagifyStyle += ';zoom:1'; element = $(element); $A(element.childNodes).each( function(child) { @@ -152,7 +144,8 @@ Effect.Transitions = { return 1-pos; }, flicker: function(pos) { - return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; + var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; + return (pos > 1 ? 1 : pos); }, wobble: function(pos) { return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; @@ -179,7 +172,7 @@ Effect.ScopedQueue = Class.create(); Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { initialize: function() { this.effects = []; - this.interval = null; + this.interval = null; }, _each: function(iterator) { this.effects._each(iterator); @@ -213,7 +206,7 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) this.effects.push(effect); - if(!this.interval) + if(!this.interval) this.interval = setInterval(this.loop.bind(this), 15); }, remove: function(effect) { @@ -226,7 +219,7 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { loop: function() { var timePos = new Date().getTime(); for(var i=0, len=this.effects.length;i<len;i++) - if(this.effects[i]) this.effects[i].loop(timePos); + this.effects[i] && this.effects[i].loop(timePos); } }); @@ -246,7 +239,7 @@ Effect.Queue = Effect.Queues.get('global'); Effect.DefaultOptions = { transition: Effect.Transitions.sinoidal, duration: 1.0, // seconds - fps: 60.0, // max. 60fps due to Effect.Queue implementation + fps: 100, // 100= assume 66fps max. sync: false, // true for combining from: 0.0, to: 1.0, @@ -258,11 +251,35 @@ Effect.Base = function() {}; Effect.Base.prototype = { position: null, start: function(options) { + function codeForEvent(options,eventName){ + return ( + (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + + (options[eventName] ? 'this.options.'+eventName+'(this);' : '') + ); + } + if(options.transition === false) options.transition = Effect.Transitions.linear; this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); this.currentFrame = 0; this.state = 'idle'; this.startOn = this.options.delay*1000; - this.finishOn = this.startOn + (this.options.duration*1000); + this.finishOn = this.startOn+(this.options.duration*1000); + this.fromToDelta = this.options.to-this.options.from; + this.totalTime = this.finishOn-this.startOn; + this.totalFrames = this.options.fps*this.options.duration; + + eval('this.render = function(pos){ '+ + 'if(this.state=="idle"){this.state="running";'+ + codeForEvent(options,'beforeSetup')+ + (this.setup ? 'this.setup();':'')+ + codeForEvent(options,'afterSetup')+ + '};if(this.state=="running"){'+ + 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+ + 'this.position=pos;'+ + codeForEvent(options,'beforeUpdate')+ + (this.update ? 'this.update(pos);':'')+ + codeForEvent(options,'afterUpdate')+ + '}}'); + this.event('beforeStart'); if(!this.options.sync) Effect.Queues.get(typeof this.options.queue == 'string' ? @@ -278,31 +295,14 @@ Effect.Base.prototype = { this.event('afterFinish'); return; } - var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); - var frame = Math.round(pos * this.options.fps * this.options.duration); + var pos = (timePos - this.startOn) / this.totalTime, + frame = Math.round(pos * this.totalFrames); if(frame > this.currentFrame) { this.render(pos); this.currentFrame = frame; } } }, - render: function(pos) { - if(this.state == 'idle') { - this.state = 'running'; - this.event('beforeSetup'); - if(this.setup) this.setup(); - this.event('afterSetup'); - } - if(this.state == 'running') { - if(this.options.transition) pos = this.options.transition(pos); - pos *= (this.options.to-this.options.from); - pos += this.options.from; - this.position = pos; - this.event('beforeUpdate'); - if(this.update) this.update(pos); - this.event('afterUpdate'); - } - }, cancel: function() { if(!this.options.sync) Effect.Queues.get(typeof this.options.queue == 'string' ? @@ -358,7 +358,7 @@ Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { this.element = $(element); if(!this.element) throw(Effect._elementDoesNotExistError); // make this work on IE on elements without 'layout' - if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) + if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); var options = Object.extend({ from: this.element.getOpacity() || 0.0, @@ -953,7 +953,7 @@ Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { effect.element.addClassName(effect.options.style); effect.transforms.each(function(transform) { if(transform.style != 'opacity') - effect.element.style[transform.style.camelize()] = ''; + effect.element.style[transform.style] = ''; }); } } else this.style = options.style.parseStyle(); @@ -969,26 +969,28 @@ Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { }); } this.transforms = this.style.map(function(pair){ - var property = pair[0].underscore().dasherize(), value = pair[1], unit = null; + var property = pair[0], value = pair[1], unit = null; if(value.parseColor('#zzzzzz') != '#zzzzzz') { value = value.parseColor(); unit = 'color'; } else if(property == 'opacity') { value = parseFloat(value); - if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) + if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); - } else if(Element.CSS_LENGTH.test(value)) - var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/), - value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null; + } else if(Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } var originalValue = this.element.getStyle(property); - return $H({ - style: property, + return { + style: property.camelize(), originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), targetValue: unit=='color' ? parseColor(value) : value, unit: unit - }); + }; }.bind(this)).reject(function(transform){ return ( (transform.originalValue == transform.targetValue) || @@ -1000,17 +1002,19 @@ Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { }); }, update: function(position) { - var style = $H(), value = null; - this.transforms.each(function(transform){ - value = transform.unit=='color' ? - $R(0,2).inject('#',function(m,v,i){ - return m+(Math.round(transform.originalValue[i]+ - (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) : + var style = {}, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : transform.originalValue + Math.round( ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit; - style[transform.style] = value; - }); - this.element.setStyle(style); + this.element.setStyle(style, true); } }); @@ -1057,14 +1061,14 @@ Element.CSS_PROPERTIES = $w( Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; String.prototype.parseStyle = function(){ - var element = Element.extend(document.createElement('div')); + var element = document.createElement('div'); element.innerHTML = '<div style="' + this + '"></div>'; - var style = element.down().style, styleRules = $H(); + var style = element.childNodes[0].style, styleRules = $H(); Element.CSS_PROPERTIES.each(function(property){ if(style[property]) styleRules[property] = style[property]; }); - if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) { + if(Prototype.Browser.IE && this.indexOf('opacity') > -1) { styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]; } return styleRules; @@ -1075,13 +1079,13 @@ Element.morph = function(element, style) { return element; }; -['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', +['getInlineOpacity','forceRerendering','setContentZoom', 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( function(f) { Element.Methods[f] = Element[f]; } ); Element.Methods.visualEffect = function(element, effect, options) { - s = effect.gsub(/_/, '-').camelize(); + s = effect.dasherize().camelize(); effect_class = s.charAt(0).toUpperCase() + s.substring(1); new Effect[effect_class](element, options); return $(element); diff --git a/wp-includes/js/scriptaculous/scriptaculous.js b/wp-includes/js/scriptaculous/scriptaculous.js index 0844cef..5f403a3 100644 --- a/wp-includes/js/scriptaculous/scriptaculous.js +++ b/wp-includes/js/scriptaculous/scriptaculous.js @@ -1,6 +1,6 @@ -// script.aculo.us scriptaculous.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 +// script.aculo.us scriptaculous.js v1.7.1_beta2, Sat Apr 28 15:20:12 CEST 2007 -// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -24,25 +24,32 @@ // For details, see the script.aculo.us web site: http://script.aculo.us/ var Scriptaculous = { - Version: '1.7.0', + Version: '1.7.1_beta2', require: function(libraryName) { // inserting via DOM fails in Safari 2.0, so brute force approach document.write('<script type="text/javascript" src="'+libraryName+'"></script>'); }, + REQUIRED_PROTOTYPE: '1.5.1', load: function() { + function convertVersionString(versionString){ + var r = versionString.split('.'); + return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]); + } + if((typeof Prototype=='undefined') || (typeof Element == 'undefined') || (typeof Element.Methods=='undefined') || - parseFloat(Prototype.Version.split(".")[0] + "." + - Prototype.Version.split(".")[1]) < 1.5) - throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0"); + (convertVersionString(Prototype.Version) < + convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE))) + throw("script.aculo.us requires the Prototype JavaScript framework >= " + + Scriptaculous.REQUIRED_PROTOTYPE); $A(document.getElementsByTagName("script")).findAll( function(s) { return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/)) }).each( function(s) { var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,''); var includes = s.src.match(/\?.*load=([a-z,]*)/); - (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each( + (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each( function(include) { Scriptaculous.require(path+include+'.js') }); }); } diff --git a/wp-includes/js/scriptaculous/slider.js b/wp-includes/js/scriptaculous/slider.js index 4899587..4db286b 100644 --- a/wp-includes/js/scriptaculous/slider.js +++ b/wp-includes/js/scriptaculous/slider.js @@ -1,6 +1,6 @@ -// script.aculo.us slider.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 +// script.aculo.us slider.js v1.7.1_beta2, Sat Apr 28 15:20:12 CEST 2007 -// Copyright (c) 2005, 2006 Marty Haught, Thomas Fuchs +// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ @@ -242,8 +242,7 @@ Control.Slider.prototype = { if(this.active) { if(!this.dragging) this.dragging = true; this.draw(event); - // fix AppleWebKit rendering - if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); + if(Prototype.Browser.WebKit) window.scrollBy(0,0); Event.stop(event); } }, diff --git a/wp-includes/js/scriptaculous/sound.js b/wp-includes/js/scriptaculous/sound.js new file mode 100644 index 0000000..fab10e8 --- /dev/null +++ b/wp-includes/js/scriptaculous/sound.js @@ -0,0 +1,60 @@ +// script.aculo.us sound.js v1.7.1_beta2, Sat Apr 28 15:20:12 CEST 2007 + +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// +// Based on code created by Jules Gravinese (http://www.webveteran.com/) +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +Sound = { + tracks: {}, + _enabled: true, + template: + new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'), + enable: function(){ + Sound._enabled = true; + }, + disable: function(){ + Sound._enabled = false; + }, + play: function(url){ + if(!Sound._enabled) return; + var options = Object.extend({ + track: 'global', url: url, replace: false + }, arguments[1] || {}); + + if(options.replace && this.tracks[options.track]) { + $R(0, this.tracks[options.track].id).each(function(id){ + var sound = $('sound_'+options.track+'_'+id); + sound.Stop && sound.Stop(); + sound.remove(); + }) + this.tracks[options.track] = null; + } + + if(!this.tracks[options.track]) + this.tracks[options.track] = { id: 0 } + else + this.tracks[options.track].id++; + + options.id = this.tracks[options.track].id; + if (Prototype.Browser.IE) { + var sound = document.createElement('bgsound'); + sound.setAttribute('id','sound_'+options.track+'_'+options.id); + sound.setAttribute('src',options.url); + sound.setAttribute('loop','1'); + sound.setAttribute('autostart','true'); + $$('body')[0].appendChild(sound); + } + else + new Insertion.Bottom($$('body')[0], Sound.template.evaluate(options)); + } +}; + +if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){ + if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 })) + Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>') + else + Sound.play = function(){} +} diff --git a/wp-includes/js/scriptaculous/unittest.js b/wp-includes/js/scriptaculous/unittest.js index f272ab2..f46cca4 100644 --- a/wp-includes/js/scriptaculous/unittest.js +++ b/wp-includes/js/scriptaculous/unittest.js @@ -1,8 +1,8 @@ -// script.aculo.us unittest.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 +// script.aculo.us unittest.js v1.7.1_beta2, Sat Apr 28 15:20:12 CEST 2007 -// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com) -// (c) 2005, 2006 Michael Schuerig (http://www.schuerig.de/michael/) +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) +// (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ diff --git a/wp-includes/js/tinymce/plugins/autosave/editor_plugin.js b/wp-includes/js/tinymce/plugins/autosave/editor_plugin.js index 1ab5d1e..f76aeeb 100644 --- a/wp-includes/js/tinymce/plugins/autosave/editor_plugin.js +++ b/wp-includes/js/tinymce/plugins/autosave/editor_plugin.js @@ -1,5 +1,5 @@ /**
- * $Id: editor_plugin_src.js 162 2007-01-03 16:16:52Z spocke $
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
*
* @author Moxiecode
* @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
@@ -14,7 +14,7 @@ var TinyMCE_AutoSavePlugin = { longname : 'Auto save',
author : 'Moxiecode Systems AB',
authorurl : 'http://tinymce.moxiecode.com',
- infourl : 'http://tinymce.moxiecode.com/tinymce/docs/plugin_autosave.html',
+ infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',
version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
};
},
diff --git a/wp-includes/js/tinymce/plugins/directionality/editor_plugin.js b/wp-includes/js/tinymce/plugins/directionality/editor_plugin.js index eb758f5..eb106f1 100644 --- a/wp-includes/js/tinymce/plugins/directionality/editor_plugin.js +++ b/wp-includes/js/tinymce/plugins/directionality/editor_plugin.js @@ -1,5 +1,5 @@ /**
- * $Id: editor_plugin_src.js 162 2007-01-03 16:16:52Z spocke $
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
*
* @author Moxiecode
* @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
@@ -14,7 +14,7 @@ var TinyMCE_DirectionalityPlugin = { longname : 'Directionality',
author : 'Moxiecode Systems AB',
authorurl : 'http://tinymce.moxiecode.com',
- infourl : 'http://tinymce.moxiecode.com/tinymce/docs/plugin_directionality.html',
+ infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',
version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
};
},
diff --git a/wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin.js b/wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin.js index 9f75e29..8f844a7 100644 --- a/wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin.js +++ b/wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin.js @@ -1,5 +1,5 @@ /**
- * $Id: editor_plugin_src.js 172 2007-01-09 11:37:11Z spocke $
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
*
* Moxiecode DHTML Windows script.
*
@@ -15,7 +15,7 @@ var TinyMCE_InlinePopupsPlugin = { longname : 'Inline Popups',
author : 'Moxiecode Systems AB',
authorurl : 'http://tinymce.moxiecode.com',
- infourl : 'http://tinymce.moxiecode.com/tinymce/docs/plugin_inlinepopups.html',
+ infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',
version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
};
}
@@ -26,6 +26,7 @@ tinyMCE.addPlugin("inlinepopups", TinyMCE_InlinePopupsPlugin); // Patch openWindow, closeWindow TinyMCE functions
TinyMCE_Engine.prototype.orgOpenWindow = TinyMCE_Engine.prototype.openWindow;
+TinyMCE_Engine.prototype.orgCloseWindow = TinyMCE_Engine.prototype.closeWindow;
TinyMCE_Engine.prototype.openWindow = function(template, args) {
// Does the caller support inline
@@ -52,6 +53,12 @@ TinyMCE_Engine.prototype.openWindow = function(template, args) { if (!(height = parseInt(template['height'])))
height = 200;
+ if (!(minWidth = parseInt(template['minWidth'])))
+ minWidth = 100;
+
+ if (!(minHeight = parseInt(template['minHeight'])))
+ minHeight = 100;
+
resizable = (args && args['resizable']) ? args['resizable'] : "no";
scrollbars = (args && args['scrollbars']) ? args['scrollbars'] : "no";
@@ -78,16 +85,23 @@ TinyMCE_Engine.prototype.openWindow = function(template, args) { url += tinyMCE.settings['imp_version'] ? (url.indexOf('?')==-1?'?':'&') + 'ver=' + tinyMCE.settings['imp_version'] : ''; // WordPress cache buster
- mcWindows.open(url, mcWindows.idCounter++, "modal=yes,width=" + width+ ",height=" + height + ",resizable=" + resizable + ",scrollbars=" + scrollbars + ",statusbar=" + resizable + ",left=" + pos.absLeft + ",top=" + pos.absTop);
+ mcWindows.open(url, mcWindows.idCounter++, "modal=yes,width=" + width+ ",height=" + height + ",resizable=" + resizable + ",scrollbars=" + scrollbars + ",statusbar=" + resizable + ",left=" + pos.absLeft + ",top=" + pos.absTop + ",minWidth=" + minWidth + ",minHeight=" + minHeight );
};
-TinyMCE_Engine.prototype.orgCloseWindow = TinyMCE_Engine.prototype.closeWindow;
-
TinyMCE_Engine.prototype.closeWindow = function(win) {
- if (mcWindows.selectedWindow != null)
- mcWindows.selectedWindow.close();
- else
+ var gotit = false, n, w;
+ for (n in mcWindows.windows) {
+ w = mcWindows.windows[n];
+ if (typeof(w) == 'function') continue;
+ if (win.name == w.id + '_iframe') {
+ w.close();
+ gotit = true;
+ }
+ }
+ if (!gotit)
this.orgCloseWindow(win);
+
+ tinyMCE.selectedInstance.getWin().focus();
};
TinyMCE_Engine.prototype.setWindowTitle = function(win_ref, title) {
@@ -135,9 +149,46 @@ TinyMCE_Windows.prototype.init = function(settings) { this.addEvent(document, "mouseup", mcWindows.eventDispatcher);
+ this.addEvent(window, "resize", mcWindows.eventDispatcher);
+ this.addEvent(document, "scroll", mcWindows.eventDispatcher);
+
this.doc = document;
};
+TinyMCE_Windows.prototype.getBounds = function() {
+ if (!this.bounds) {
+ var vp = tinyMCE.getViewPort(window);
+ var top, left, bottom, right, docEl = this.doc.documentElement;
+
+ top = vp.top;
+ left = vp.left;
+ bottom = vp.height + top - 2;
+ right = vp.width + left - 22; // TODO this number is platform dependant
+ // x1, y1, x2, y2
+ this.bounds = [left, top, right, bottom];
+ }
+ return this.bounds;
+};
+
+TinyMCE_Windows.prototype.clampBoxPosition = function(x, y, w, h, minW, minH) {
+ var bounds = this.getBounds();
+
+ x = Math.max(bounds[0], Math.min(bounds[2], x + w) - w);
+ y = Math.max(bounds[1], Math.min(bounds[3], y + h) - h);
+
+ return this.clampBoxSize(x, y, w, h, minW, minH);
+};
+
+TinyMCE_Windows.prototype.clampBoxSize = function(x, y, w, h, minW, minH) {
+ var bounds = this.getBounds();
+
+ return [
+ x, y,
+ Math.max(minW, Math.min(bounds[2], x + w) - x),
+ Math.max(minH, Math.min(bounds[3], y + h) - y)
+ ];
+};
+
TinyMCE_Windows.prototype.getParam = function(name, default_value) {
var value = null;
@@ -186,6 +237,43 @@ TinyMCE_Windows.prototype.eventDispatcher = function(e) { case "focus":
mcWindows.selectedWindow.onFocus(e);
break;
+ case "scroll":
+ case "resize":
+ if (mcWindows.clampUpdateTimeout)
+ clearTimeout(mcWindows.clampUpdateTimeout);
+ mcWindows.clampEventType = e.type;
+ mcWindows.clampUpdateTimeout =
+ setTimeout(function () {mcWindows.updateClamping()}, 100);
+ break;
+ }
+};
+
+TinyMCE_Windows.prototype.updateClamping = function () {
+ var clamp, oversize, etype = mcWindows.clampEventType;
+
+ this.bounds = null; // Recalc window bounds on resize/scroll
+ this.clampUpdateTimeout = null;
+
+ for (var n in this.windows) {
+ win = this.windows[n];
+ if (typeof(win) == 'function' || ! win.winElement) continue;
+
+ clamp = mcWindows.clampBoxPosition(
+ win.left, win.top,
+ win.winElement.scrollWidth,
+ win.winElement.scrollHeight,
+ win.features.minWidth,
+ win.features.minHeight
+ );
+ oversize = (
+ clamp[2] != win.winElement.scrollWidth ||
+ clamp[3] != win.winElement.scrollHeight
+ ) ? true : false;
+
+ if (!oversize || win.features.resizable == "yes" || etype != "scroll")
+ win.moveTo(clamp[0], clamp[1]);
+ if (oversize && win.features.resizable == "yes")
+ win.resizeTo(clamp[2], clamp[3]);
}
};
@@ -193,7 +281,7 @@ TinyMCE_Windows.prototype.addEvent = function(obj, name, handler) { if (this.isMSIE)
obj.attachEvent("on" + name, handler);
else
- obj.addEventListener(name, handler, true);
+ obj.addEventListener(name, handler, false);
};
TinyMCE_Windows.prototype.cancelEvent = function(e) {
@@ -217,6 +305,8 @@ TinyMCE_Windows.prototype.parseFeatures = function(opts) { options['top'] = "10";
options['width'] = "300";
options['height'] = "300";
+ options['minwidth'] = "100";
+ options['minheight'] = "100";
options['resizable'] = "yes";
options['minimizable'] = "yes";
options['maximizable'] = "yes";
@@ -240,6 +330,8 @@ TinyMCE_Windows.prototype.parseFeatures = function(opts) { options['top'] = parseInt(options['top']);
options['width'] = parseInt(options['width']);
options['height'] = parseInt(options['height']);
+ options['minWidth'] = parseInt(options['minwidth']);
+ options['minHeight'] = parseInt(options['minheight']);
return options;
};
@@ -253,6 +345,21 @@ TinyMCE_Windows.prototype.open = function(url, name, features) { features = this.parseFeatures(features);
+ // Clamp specified dimensions
+ var clamp = mcWindows.clampBoxPosition(
+ features['left'], features['top'],
+ features['width'], features['height'],
+ features['minWidth'], features['minHeight']
+ );
+
+ features['left'] = clamp[0];
+ features['top'] = clamp[1];
+
+ if (features['resizable'] == "yes") {
+ features['width'] = clamp[2];
+ features['height'] = clamp[3];
+ }
+
// Create div
id = "mcWindow_" + name;
win.deltaHeight = 18;
@@ -285,9 +392,9 @@ TinyMCE_Windows.prototype.open = function(url, name, features) { html += '<html>';
html += '<head>';
html += '<title>Wrapper iframe</title>';
+ if (this.isMac) html += '<style type="text/css">.mceWindowTitle{float:none;margin:0;width:100%;text-align:center;}.mceWindowClose{float:none;position:absolute;left:0px;top:0px;}</style>';
html += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';
html += '<link href="' + this.getParam("css_file") + '" rel="stylesheet" type="text/css" />';
- if ( this.isMac ) html += '<style type="text/css">.mceWindowTitle{float:none;margin:0;text-align:center;}.mceWindowClose{float:none;position:absolute;left:0px;top:0px;}</style>';
html += '</head>';
html += '<body onload="parent.mcWindows.onLoad(\'' + name + '\');">';
@@ -297,8 +404,9 @@ TinyMCE_Windows.prototype.open = function(url, name, features) { html += ' onselectstart="return false;" unselectable="on" style="-moz-user-select: none !important;"></div>';
html += ' <div class="mceWindowHeadTools">';
html += ' <a href="javascript:parent.mcWindows.windows[\'' + name + '\'].close();" target="_self" onmousedown="return false;" class="mceWindowClose"><img border="0" src="' + imgPath + '/window_close.gif" /></a>';
-// html += ' <a href="javascript:mcWindows.windows[\'' + name + '\'].maximize();" target="_self" onmousedown="return false;" class="mceWindowMaximize"></a>';
-// html += ' <a href="javascript:mcWindows.windows[\'' + name + '\'].minimize();" target="_self" onmousedown="return false;" class="mceWindowMinimize"></a>';
+ if (features['resizable'] == "yes" && features['maximizable'] == "yes")
+ html += ' <a href="javascript:parent.mcWindows.windows[\'' + name + '\'].maximize();" target="_self" onmousedown="return false;" class="mceWindowMaximize"><img border="0" src="' + imgPath + '/window_maximize.gif" /></a>';
+ // html += ' <a href="javascript:mcWindows.windows[\'' + name + '\'].minimize();" target="_self" onmousedown="return false;" class="mceWindowMinimize"></a>';
html += ' </div>';
html += '</div><div id="' + id + '_body" class="mceWindowBody" style="width: ' + width + 'px; height: ' + height + 'px;">';
html += '<iframe id="' + id + '_iframe" name="' + id + '_iframe" frameborder="0" width="' + iframeWidth + '" height="' + iframeHeight + '" src="' + url + '" class="mceWindowBodyIframe" scrolling="' + features['scrollbars'] + '"></iframe></div>';
@@ -447,6 +555,7 @@ TinyMCE_Windows.prototype.createFloatingIFrame = function(id_prefix, left, top, div.setAttribute("width", width);
div.setAttribute("height", (height));
div.style.position = "absolute";
+
div.style.left = left + "px";
div.style.top = top + "px";
div.style.width = width + "px";
@@ -473,7 +582,7 @@ TinyMCE_Windows.prototype.createFloatingIFrame = function(id_prefix, left, top, iframe.setAttribute("topMargin", "0");
iframe.setAttribute("width", iframeWidth);
iframe.setAttribute("height", iframeHeight);
-// iframe.setAttribute("src", "../jscripts/tiny_mce/blank.htm");
+ // iframe.setAttribute("src", "../jscripts/tiny_mce/blank.htm");
// iframe.setAttribute("allowtransparency", "false");
iframe.setAttribute("scrolling", "no");
iframe.style.width = iframeWidth + "px";
@@ -522,7 +631,24 @@ TinyMCE_Window.prototype.minimize = function() { };
TinyMCE_Window.prototype.maximize = function() {
-
+ if (this.restoreSize) {
+ this.moveTo(this.restoreSize[0], this.restoreSize[1]);
+ this.resizeTo(this.restoreSize[2], this.restoreSize[3]);
+ this.updateClamping();
+ this.restoreSize = null;
+ } else {
+ var bounds = mcWindows.getBounds();
+ this.restoreSize = [
+ this.left, this.top,
+ this.winElement.scrollWidth,
+ this.winElement.scrollHeight
+ ];
+ this.moveTo(bounds[0], bounds[1]);
+ this.resizeTo(
+ bounds[2] - bounds[0],
+ bounds[3] - bounds[1]
+ );
+ }
};
TinyMCE_Window.prototype.startResize = function() {
@@ -552,7 +678,7 @@ TinyMCE_Window.prototype.close = function() { mcWindows.windows = mcWindowsNew;
-// alert(mcWindows.doc.getElementById(this.id + "_iframe"));
+ // alert(mcWindows.doc.getElementById(this.id + "_iframe"));
var e = mcWindows.doc.getElementById(this.id + "_iframe");
e.parentNode.removeChild(e);
@@ -561,42 +687,24 @@ TinyMCE_Window.prototype.close = function() { e.parentNode.removeChild(e);
mcWindows.setDocumentLock(false);
-
- tinyMCE.selectedInstance.getWin().focus(); // WordPress: focus on the editor after closing a popup
};
TinyMCE_Window.prototype.onMouseMove = function(e) {
- var scrollX = 0;//this.doc.body.scrollLeft;
- var scrollY = 0;//this.doc.body.scrollTop;
-
+ var clamp;
// Calculate real X, Y
var dx = e.screenX - mcWindows.mouseDownScreenX;
var dy = e.screenY - mcWindows.mouseDownScreenY;
switch (mcWindows.action) {
case "resize":
- width = mcWindows.mouseDownWidth + (e.screenX - mcWindows.mouseDownScreenX);
- height = mcWindows.mouseDownHeight + (e.screenY - mcWindows.mouseDownScreenY);
+ clamp = mcWindows.clampBoxSize(
+ this.left, this.top,
+ mcWindows.mouseDownWidth + (e.screenX - mcWindows.mouseDownScreenX),
+ mcWindows.mouseDownHeight + (e.screenY - mcWindows.mouseDownScreenY),
+ this.features.minWidth, this.features.minHeight
+ );
- width = width < 100 ? 100 : width;
- height = height < 100 ? 100 : height;
-
- this.wrapperIFrameElement.style.width = (width+2) + 'px';
- this.wrapperIFrameElement.style.height = (height+2) + 'px';
- this.wrapperIFrameElement.width = width+2;
- this.wrapperIFrameElement.height = height+2;
- this.winElement.style.width = width + 'px';
- this.winElement.style.height = height + 'px';
-
- height = height - this.deltaHeight;
-
- this.containerElement.style.width = width + 'px';
- this.iframeElement.style.width = width + 'px';
- this.iframeElement.style.height = height + 'px';
- this.bodyElement.style.width = width + 'px';
- this.bodyElement.style.height = height + 'px';
- this.headElement.style.width = width + 'px';
- //this.statusElement.style.width = width + 'px';
+ this.resizeTo(clamp[2], clamp[3]);
mcWindows.cancelEvent(e);
break;
@@ -604,14 +712,59 @@ TinyMCE_Window.prototype.onMouseMove = function(e) { case "move":
this.left = mcWindows.mouseDownLayerX + (e.screenX - mcWindows.mouseDownScreenX);
this.top = mcWindows.mouseDownLayerY + (e.screenY - mcWindows.mouseDownScreenY);
- this.winElement.style.left = this.left + "px";
- this.winElement.style.top = this.top + "px";
+ this.updateClamping();
mcWindows.cancelEvent(e);
break;
}
};
+TinyMCE_Window.prototype.moveTo = function (x, y) {
+ this.left = x;
+ this.top = y;
+
+ this.winElement.style.left = this.left + "px";
+ this.winElement.style.top = this.top + "px";
+};
+
+TinyMCE_Window.prototype.resizeTo = function (width, height) {
+ this.wrapperIFrameElement.style.width = (width+2) + 'px';
+ this.wrapperIFrameElement.style.height = (height+2) + 'px';
+ this.wrapperIFrameElement.width = width+2;
+ this.wrapperIFrameElement.height = height+2;
+ this.winElement.style.width = width + 'px';
+ this.winElement.style.height = height + 'px';
+
+ height = height - this.deltaHeight;
+
+ this.containerElement.style.width = width + 'px';
+ this.iframeElement.style.width = width + 'px';
+ this.iframeElement.style.height = height + 'px';
+ this.bodyElement.style.width = width + 'px';
+ this.bodyElement.style.height = height + 'px';
+ this.headElement.style.width = width + 'px';
+ //this.statusElement.style.width = width + 'px';
+};
+
+TinyMCE_Window.prototype.updateClamping = function () {
+ var clamp, oversize;
+
+ clamp = mcWindows.clampBoxPosition(
+ this.left, this.top,
+ this.winElement.scrollWidth,
+ this.winElement.scrollHeight,
+ this.features.minWidth, this.features.minHeight
+ );
+ oversize = (
+ clamp[2] != this.winElement.scrollWidth ||
+ clamp[3] != this.winElement.scrollHeight
+ ) ? true : false;
+
+ this.moveTo(clamp[0], clamp[1]);
+ if (this.features.resizable == "yes" && oversize)
+ this.resizeTo(clamp[2], clamp[3]);
+};
+
function debug(msg) {
document.getElementById('debug').value += msg + "\n";
}
@@ -639,9 +792,6 @@ TinyMCE_Window.prototype.onFocus = function(e) { TinyMCE_Window.prototype.onMouseDown = function(e) {
var elm = mcWindows.isMSIE ? this.wrapperFrame.event.srcElement : e.target;
- var scrollX = 0;//this.doc.body.scrollLeft;
- var scrollY = 0;//this.doc.body.scrollTop;
-
mcWindows.mouseDownScreenX = e.screenX;
mcWindows.mouseDownScreenY = e.screenY;
mcWindows.mouseDownLayerX = this.left;
diff --git a/wp-includes/js/tinymce/plugins/paste/editor_plugin.js b/wp-includes/js/tinymce/plugins/paste/editor_plugin.js index 3ef1d7a..5e884cf 100644 --- a/wp-includes/js/tinymce/plugins/paste/editor_plugin.js +++ b/wp-includes/js/tinymce/plugins/paste/editor_plugin.js @@ -1,5 +1,5 @@ /** - * $Id: editor_plugin_src.js 162 2007-01-03 16:16:52Z spocke $ + * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $ * * @author Moxiecode * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved. @@ -14,7 +14,7 @@ var TinyMCE_PastePlugin = { longname : 'Paste text/word', author : 'Moxiecode Systems AB', authorurl : 'http://tinymce.moxiecode.com', - infourl : 'http://tinymce.moxiecode.com/tinymce/docs/plugin_paste.html', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste', version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion }; }, @@ -24,6 +24,16 @@ var TinyMCE_PastePlugin = { tinyMCE.addEvent(inst.getBody(), "paste", TinyMCE_PastePlugin._handlePasteEvent); }, + handleEvent : function(e) { + // Force paste dialog if non IE browser + if (!tinyMCE.isRealIE && tinyMCE.getParam("paste_auto_cleanup_on_paste", false) && e.ctrlKey && e.keyCode == 86 && e.type == "keydown") { + window.setTimeout('tinyMCE.selectedInstance.execCommand("mcePasteText",true)', 1); + return tinyMCE.cancelEvent(e); + } + + return true; + }, + getControlHTML : function(cn) { switch (cn) { case "pastetext": diff --git a/wp-includes/js/tinymce/plugins/spellchecker/classes/TinyGoogleSpell.class.php b/wp-includes/js/tinymce/plugins/spellchecker/classes/TinyGoogleSpell.class.php index cf3d800..0127ff1 100755 --- a/wp-includes/js/tinymce/plugins/spellchecker/classes/TinyGoogleSpell.class.php +++ b/wp-includes/js/tinymce/plugins/spellchecker/classes/TinyGoogleSpell.class.php @@ -78,19 +78,8 @@ class TinyGoogleSpell { $header .= $xml;
//$this->_debugData($xml);
- // Use raw sockets
- $fp = fsockopen("ssl://" . $server, $port, $errno, $errstr, 30);
- if ($fp) {
- // Send request
- fwrite($fp, $header);
-
- // Read response
- $xml = "";
- while (!feof($fp))
- $xml .= fgets($fp, 128);
-
- fclose($fp);
- } else {
+ // Use curl if it exists
+ if (function_exists('curl_init')) {
// Use curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
@@ -99,6 +88,21 @@ class TinyGoogleSpell { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$xml = curl_exec($ch);
curl_close($ch);
+ } else {
+ // Use raw sockets
+ $fp = fsockopen("ssl://" . $server, $port, $errno, $errstr, 30);
+ if ($fp) {
+ // Send request
+ fwrite($fp, $header);
+
+ // Read response
+ $xml = "";
+ while (!feof($fp))
+ $xml .= fgets($fp, 128);
+
+ fclose($fp);
+ } else
+ echo "Could not open SSL connection to google.";
}
//$this->_debugData($xml);
diff --git a/wp-includes/js/tinymce/plugins/wordpress/editor_plugin.js b/wp-includes/js/tinymce/plugins/wordpress/editor_plugin.js index ede6576..f834e97 100644 --- a/wp-includes/js/tinymce/plugins/wordpress/editor_plugin.js +++ b/wp-includes/js/tinymce/plugins/wordpress/editor_plugin.js @@ -515,7 +515,7 @@ function switchEditors(id) { ta.style.height = (ta.clientHeight + y1 - y2) + 'px'; // Tweak the widths - ta.parentNode.style.paddingRight = '2px'; + ta.parentNode.style.paddingRight = '12px'; if ( tinyMCE.isMSIE && !tinyMCE.isOpera ) { } else { diff --git a/wp-includes/js/tinymce/plugins/wordpress/langs/en.js b/wp-includes/js/tinymce/plugins/wordpress/langs/en.js index 2d4e1e3..68ca7ba 100644 --- a/wp-includes/js/tinymce/plugins/wordpress/langs/en.js +++ b/wp-includes/js/tinymce/plugins/wordpress/langs/en.js @@ -4,6 +4,10 @@ if (navigator.userAgent.indexOf('Mac OS') != -1) { // Mac OS browsers use Ctrl to hit accesskeys
var metaKey = 'Ctrl';
}
+else if (navigator.userAgent.indexOf('Firefox/2') != -1) {
+// Firefox 2.x uses Alt+Shift to hit accesskeys
+ var metaKey = 'Alt+Shift';
+}
else {
var metaKey = 'Alt';
}
diff --git a/wp-includes/js/tinymce/themes/advanced/color_picker.htm b/wp-includes/js/tinymce/themes/advanced/color_picker.htm index e5fdc9f..5e24920 100644 --- a/wp-includes/js/tinymce/themes/advanced/color_picker.htm +++ b/wp-includes/js/tinymce/themes/advanced/color_picker.htm @@ -2,12 +2,73 @@ <head> <title>{$lang_theme_colorpicker_title}</title> <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script> <script language="javascript" type="text/javascript" src="jscripts/color_picker.js"></script> + <link href="css/colorpicker.css" rel="stylesheet" type="text/css" /> <base target="_self" /> </head> -<body onload="tinyMCEPopup.executeOnLoad('init();');" style="margin: 3px; display: none"> - <div align="center"> - <script language="javascript" type="text/javascript">renderColorMap();</script> +<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none"> + <div class="tabs"> + <ul> + <li id="picker_tab" class="current"><span><a href="javascript:mcTabs.displayTab('picker_tab','picker_panel');" onmousedown="return false;">{$lang_color_picker_tab}</a></span></li> + <li id="rgb_tab"><span><a href="#" onclick="generateWebColors();mcTabs.displayTab('rgb_tab','rgb_panel');" onmousedown="return false;">{$lang_web_colors_tab}</a></span></li> + <li id="named_tab"><span><a href="#" onclick="generateNamedColors();javascript:mcTabs.displayTab('named_tab','named_panel');" onmousedown="return false;">{$lang_named_colors_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="picker_panel" class="panel current"> + <fieldset> + <legend>{$lang_color_picker}</legend> + <div id="picker"> + <img id="colorpicker" src="images/colors.jpg" onclick="computeColor(event)" onmousedown="isMouseDown = true;return false;" onmouseup="isMouseDown = false;" onmousemove="if (isMouseDown && isMouseOver) computeColor(event); return false;" onmouseover="isMouseOver=true;" onmouseout="isMouseOver=false;" /> + + <div id="light"> + <!-- Will be filled with divs --> + </div> + + <br style="clear: both" /> + </div> + </fieldset> + </div> + + <div id="rgb_panel" class="panel"> + <fieldset> + <legend>{$lang_web_colors}</legend> + <div id="webcolors"> + <!-- Gets filled with web safe colors--> + </div> + + <br style="clear: both" /> + </fieldset> + </div> + + <div id="named_panel" class="panel"> + <fieldset> + <legend>{$lang_named_colors}</legend> + <div id="namedcolors"> + <!-- Gets filled with named colors--> + </div> + + <br style="clear: both" /> + + <div id="colornamecontainer"> + {$lang_color_name} <span id="colorname"></span> + </div> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <div style="float: left"> + <input type="button" id="insert" name="insert" value="{$lang_theme_colorpicker_apply}" onclick="insertAction();" /> + </div> + + <div id="preview"></div> + + <div id="previewblock"> + <label for="color">{$lang_color}</label> <input id="color" type="text" size="8" maxlength="8" class="text" /> + </div> </div> </body> </html> diff --git a/wp-includes/js/tinymce/themes/advanced/css/colorpicker.css b/wp-includes/js/tinymce/themes/advanced/css/colorpicker.css new file mode 100644 index 0000000..4b0360b --- /dev/null +++ b/wp-includes/js/tinymce/themes/advanced/css/colorpicker.css @@ -0,0 +1,53 @@ +/* Colorpicker dialog specific CSS */
+
+#preview {
+ float: right;
+ width: 50px;
+ height: 14px;
+ line-height: 1px;
+ border: 1px solid black;
+ margin-left: 5px;
+}
+
+#colorpicker {
+ float: left;
+ cursor: crosshair;
+}
+
+#light {
+ border: 1px solid gray;
+ margin-left: 5px;
+ float: left;
+ width: 15px;
+ cursor: crosshair;
+}
+
+#light div {
+ overflow: hidden;
+}
+
+#previewblock {
+ float: right;
+ padding-left: 10px;
+ height: 20px;
+}
+
+.panel_wrapper div.current {
+ height: 175px;
+}
+
+#namedcolors {
+ width: 150px;
+}
+
+#namedcolors a {
+ display: block;
+ float: left;
+ width: 10px; height: 10px;
+ margin: 1px 1px 0 0;
+ overflow: hidden;
+}
+
+#colornamecontainer {
+ margin-top: 5px;
+}
\ No newline at end of file diff --git a/wp-includes/js/tinymce/themes/advanced/css/editor_ui.css b/wp-includes/js/tinymce/themes/advanced/css/editor_ui.css index 58e6b8e..851837d 100644 --- a/wp-includes/js/tinymce/themes/advanced/css/editor_ui.css +++ b/wp-includes/js/tinymce/themes/advanced/css/editor_ui.css @@ -11,7 +11,7 @@ .mceToolbarTop, .mceToolbarBottom {background: #F0F0EE; line-height: 1px; font-size: 1px;}
.mceToolbarTop {border-bottom: 1px solid #cccccc; padding-bottom: 1px;}
.mceToolbarBottom {border-top: 1px solid #cccccc;}
-.mceToolbarContainer {position: relative; left: 0; top: 0; display: block;}
+.mceToolbarContainer {display: block; position: relative; left: 0; top: 0; width: 100%;}
.mceStatusbarTop, .mceStatusbarBottom, .mceStatusbar {height: 20px;}
.mceStatusbarTop .mceStatusbarPathText, .mceStatusbarBottom .mceStatusbarPathText, .mceStatusbar .mceStatusbarPathText {font-family: 'MS Sans Serif', sans-serif, Verdana, Arial; font-size: 9pt; padding: 2px; line-height: 16px; overflow: visible;}
.mceStatusbarTop {border-bottom: 1px solid #cccccc;}
@@ -49,7 +49,7 @@ span.mceMenuButtonSelected.mceMenuHover img.mceMenuButton {border: 1px solid #0A /* Menu */
-.mceMenu {position: absolute; left: 0; top: 0; display: none; z-index: 100; background-color: white; border: 1px solid gray; font-weight: normal;}
+.mceMenu {position: absolute; left: 0; top: 0; display: none; z-index: 1000; background-color: white; border: 1px solid gray; font-weight: normal;}
.mceMenu a, .mceMenuTitle, .mceMenuDisabled {display: block; width: 100%; text-decoration: none; background-color: white; font-family: Tahoma, Verdana, Arial, Helvetica; font-size: 11px; line-height: 20px; color: black;}
.mceMenu a:hover {background-color: #B6BDD2; color: black; text-decoration: none !important;}
.mceMenu span {padding-left: 10px; padding-right: 10px; display: block; line-height: 20px;}
@@ -61,7 +61,7 @@ span.mceMenuSelectedItem {background-image: url('../images/menu_check.gif'); bac span.mceMenuCheckItem {padding-left: 20px;}
span.mceMenuLine {display: block; position: absolute; left: 0; top: -1px; background-color: #F5F4F2; width: 30px; height: 1px; overflow: hidden; padding-left: 0; padding-right: 0;}
.mceColors table, .mceColors td {margin: 0; padding: 2px;}
-a.mceMoreColors {width: 130px; margin: 0; padding: 0; margin-left: 3px; margin-bottom: 3px; text-align: center; border: 1px solid white;}
+a.mceMoreColors {width: auto; padding: 0; margin: 0 3px 3px 3px; text-align: center; border: 1px solid white; text-decoration: none !important;}
.mceColorPreview {position: absolute; overflow:hidden; left: 0; top: 0; margin-left: 3px; margin-top: 15px; width: 16px; height: 4px; background-color: red;}
a.mceMoreColors:hover {border: 1px solid #0A246A;}
.mceColors td a {width: 9px; height: 9px; overflow: hidden; border: 1px solid #808080;}
@@ -77,7 +77,7 @@ a.mceMoreColors:hover {border: 1px solid #0A246A;} * html .mceSelectList {margin-top: 2px;}
* html span.mceMenuButton, * html span.mceMenuButtonFocus {position: relative; left: 0; top: 0;}
* html span.mceMenuButton img, * html span.mceMenuButtonSelected img, * html span.mceMenuButtonFocus img {position: relative; top: 1px;}
-* html a.mceMoreColors {width: 132px;}
+* html a.mceMoreColors {width: auto;}
* html .mceColors td a {width: 10px; height: 10px;}
* html .mceColorPreview {margin-left: 2px; margin-top: 14px;}
@@ -92,6 +92,6 @@ a.mceMoreColors:hover {border: 1px solid #0A246A;} *:first-child+html .mceSelectList {margin-top: 2px;}
*:first-child+html span.mceMenuButton, *:first-child+html span.mceMenuButtonFocus {position: relative; left: 0; top: 0;}
*:first-child+html span.mceMenuButton img, *:first-child+html span.mceMenuButtonSelected img, *:first-child+html span.mceMenuButtonFocus img {position: relative; top: 1px;}
-*:first-child+html a.mceMoreColors {width: 132px;}
+*:first-child+html a.mceMoreColors {width: 137px;}
*:first-child+html .mceColors td a {width: 10px; height: 10px;}
*:first-child+html .mceColorPreview {margin: 0; padding-left: 4px; margin-top: 14px; width: 14px;}
diff --git a/wp-includes/js/tinymce/themes/advanced/editor_template.js b/wp-includes/js/tinymce/themes/advanced/editor_template.js index 3d91891..b8e3685 100644 --- a/wp-includes/js/tinymce/themes/advanced/editor_template.js +++ b/wp-includes/js/tinymce/themes/advanced/editor_template.js @@ -1,5 +1,5 @@ /** - * $Id: editor_template_src.js 166 2007-01-05 10:31:50Z spocke $ + * $Id: editor_template_src.js 218 2007-02-13 11:08:01Z spocke $ * * @author Moxiecode * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved. @@ -43,7 +43,9 @@ var TinyMCE_AdvancedTheme = { ['sub', 'sub.gif', 'lang_theme_sub_desc', 'subscript'], ['sup', 'sup.gif', 'lang_theme_sup_desc', 'superscript'], ['forecolor', 'forecolor.gif', 'lang_theme_forecolor_desc', 'forecolor', true], + ['forecolorpicker', 'forecolor.gif', 'lang_theme_forecolor_desc', 'forecolorpicker', true], ['backcolor', 'backcolor.gif', 'lang_theme_backcolor_desc', 'HiliteColor', true], + ['backcolorpicker', 'backcolor.gif', 'lang_theme_backcolor_desc', 'backcolorpicker', true], ['charmap', 'charmap.gif', 'lang_theme_charmap_desc', 'mceCharMap'], ['visualaid', 'visualaid.gif', 'lang_theme_visualaid_desc', 'mceToggleVisualAid'], ['anchor', 'anchor.gif', 'lang_theme_anchor_desc', 'mceInsertAnchor'], @@ -356,6 +358,10 @@ var TinyMCE_AdvancedTheme = { return false; + case "forecolorpicker": + this._pickColor(editor_id, 'forecolor'); + return true; + case "forecolorMenu": TinyMCE_AdvancedTheme._hideMenus(editor_id); @@ -420,15 +426,21 @@ var TinyMCE_AdvancedTheme = { ml.show(); return true; + + case "backcolorpicker": + this._pickColor(editor_id, 'HiliteColor'); + return true; case "mceColorPicker": if (user_interface) { - var template = new Array(); - var inputColor = value['document'].getElementById(value['element_id']).value; + var template = []; + + if (!value['callback'] && !value['color']) + value['color'] = value['document'].getElementById(value['element_id']).value; template['file'] = 'color_picker.htm'; - template['width'] = 220; - template['height'] = 190; + template['width'] = 380; + template['height'] = 250; template['close_previous'] = "no"; template['width'] += tinyMCE.getLang('lang_theme_advanced_colorpicker_delta_width', 0); @@ -438,10 +450,16 @@ var TinyMCE_AdvancedTheme = { value['store_selection'] = true; tinyMCE.lastColorPickerValue = value; - tinyMCE.openWindow(template, {editor_id : editor_id, mce_store_selection : value['store_selection'], inline : "yes", command : "mceColorPicker", input_color : inputColor}); + tinyMCE.openWindow(template, {editor_id : editor_id, mce_store_selection : value['store_selection'], inline : "yes", command : "mceColorPicker", input_color : value['color']}); } else { - var savedVal = tinyMCE.lastColorPickerValue; - var elm = savedVal['document'].getElementById(savedVal['element_id']); + var savedVal = tinyMCE.lastColorPickerValue, elm; + + if (savedVal['callback']) { + savedVal['callback'](value); + return true; + } + + elm = savedVal['document'].getElementById(savedVal['element_id']); elm.value = value; if (elm.onchange != null && elm.onchange != '') @@ -599,9 +617,8 @@ var TinyMCE_AdvancedTheme = { // Setup template html template['html'] = '<table class="mceEditor" border="0" cellpadding="0" cellspacing="0" width="{$width}" height="{$height}" style="width:{$width_style};height:{$height_style}"><tbody>'; - if (toolbarLocation == "top") { - template['html'] += '<tr><td class="mceToolbarTop" align="' + toolbarAlign + '" height="1" nowrap="nowrap"><span id="' + editorId + '_toolbar" class="mceToolbarContainer">' + toolbarHTML + '</span></td></tr>'; - } + if (toolbarLocation == "top") + template['html'] += '<tr><td dir="ltr" class="mceToolbarTop" align="' + toolbarAlign + '" height="1" nowrap="nowrap"><span id="' + editorId + '_toolbar" class="mceToolbarContainer">' + toolbarHTML + '</span></td></tr>'; if (statusbarLocation == "top") { template['html'] += '<tr><td class="mceStatusbarTop" height="1">' + statusbarHTML + '</td></tr>'; @@ -610,9 +627,8 @@ var TinyMCE_AdvancedTheme = { template['html'] += '<tr><td align="center"><span id="{$editor_id}"></span></td></tr>'; - if (toolbarLocation == "bottom") { - template['html'] += '<tr><td class="mceToolbarBottom" align="' + toolbarAlign + '" height="1"><span id="' + editorId + '_toolbar" class="mceToolbarContainer">' + toolbarHTML + '</span></td></tr>'; - } + if (toolbarLocation == "bottom") + template['html'] += '<tr><td dir="ltr" class="mceToolbarBottom" align="' + toolbarAlign + '" height="1"><span id="' + editorId + '_toolbar" class="mceToolbarContainer">' + toolbarHTML + '</span></td></tr>'; // External toolbar changes if (toolbarLocation == "external") { @@ -738,9 +754,12 @@ var TinyMCE_AdvancedTheme = { }, removeInstance : function(inst) { - var fcm = new TinyMCE_Layer(inst.editorId + '_fcMenu'); + new TinyMCE_Layer(inst.editorId + '_fcMenu').remove(); + new TinyMCE_Layer(inst.editorId + '_bcMenu').remove(); + }, - fcm.remove(); + hideInstance : function(inst) { + TinyMCE_AdvancedTheme._hideMenus(inst.editorId); }, _handleMenuEvent : function(e) { @@ -1224,6 +1243,7 @@ var TinyMCE_AdvancedTheme = { if (set_w) tableElm.style.width = w + "px"; + if ( !tinyMCE.isMSIE || tinyMCE.isMSIE7 || tinyMCE.isOpera ) // WordPress: do this later to avoid creeping toolbar bug in MSIE6 tableElm.style.height = h + "px"; iw = iframe.clientWidth + dx; @@ -1232,10 +1252,12 @@ var TinyMCE_AdvancedTheme = { iw = iw < 1 ? 30 : iw; ih = ih < 1 ? 30 : ih; +/* WordPress found that this led to a shrinking editor with every resize. (Gray background creeps in 1px at a time.) if (tinyMCE.isGecko) { iw -= 2; ih -= 2; } +*/ if (set_w) iframe.style.width = iw + "px"; @@ -1253,6 +1275,8 @@ var TinyMCE_AdvancedTheme = { } } + tableElm.style.height = h + "px"; // WordPress: see above + // Remove pesky table controls inst.useCSS = false; }, @@ -1378,13 +1402,27 @@ var TinyMCE_AdvancedTheme = { } h += '</tr></table>'; - /* - h += '<a href="" class="mceMoreColors">More colors</a>'; - */ + + if (tinyMCE.getParam("theme_advanced_more_colors", true)) + h += '<a href="#" onclick="TinyMCE_AdvancedTheme._pickColor(\'' + id + '\',\'' + cm + '\');" class="mceMoreColors">' + tinyMCE.getLang('lang_more_colors') + '</a>'; return h; }, + _pickColor : function(id, cm) { + var inputColor, inst = tinyMCE.selectedInstance; + + if (cm == 'forecolor' && inst) + inputColor = inst.foreColor; + + if ((cm == 'backcolor' || cm == 'HiliteColor') && inst) + inputColor = inst.backColor; + + tinyMCE.execCommand('mceColorPicker', true, {color : inputColor, callback : function(c) { + tinyMCE.execInstanceCommand(id, cm, false, c); + }}); + }, + _insertImage : function(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout) { tinyMCE.execCommand('mceBeginUndoLevel'); diff --git a/wp-includes/js/tinymce/themes/advanced/images/colors.jpg b/wp-includes/js/tinymce/themes/advanced/images/colors.jpg Binary files differnew file mode 100644 index 0000000..b4c542d --- /dev/null +++ b/wp-includes/js/tinymce/themes/advanced/images/colors.jpg diff --git a/wp-includes/js/tinymce/themes/advanced/jscripts/color_picker.js b/wp-includes/js/tinymce/themes/advanced/jscripts/color_picker.js index aa80714..78425e4 100644 --- a/wp-includes/js/tinymce/themes/advanced/jscripts/color_picker.js +++ b/wp-includes/js/tinymce/themes/advanced/jscripts/color_picker.js @@ -1,19 +1,4 @@ -function init() { - if (tinyMCE.isMSIE) - tinyMCEPopup.resizeToInnerSize(); -} - -function selectColor() { - var color = document.getElementById("selectedColorBox").value; - - tinyMCEPopup.execCommand(tinyMCE.getWindowArg('command'), false, color); - tinyMCEPopup.close(); -} - -function showColor(color) { - document.getElementById("selectedColor").style.backgroundColor = color; - document.getElementById("selectedColorBox").value = color; -} +var detail = 50, strhex = "0123456789abcdef", i, isMouseDown = false, isMouseOver = false; var colors = new Array( "#000000","#000033","#000066","#000099","#0000cc","#0000ff","#330000","#330033", @@ -45,9 +30,71 @@ var colors = new Array( "#ccffcc","#ccffff","#ffff00","#ffff33","#ffff66","#ffff99","#ffffcc","#ffffff" ); +var named = { + '#F0F8FF':'AliceBlue','#FAEBD7':'AntiqueWhite','#00FFFF':'Aqua','#7FFFD4':'Aquamarine','#F0FFFF':'Azure','#F5F5DC':'Beige', + '#FFE4C4':'Bisque','#000000':'Black','#FFEBCD':'BlanchedAlmond','#0000FF':'Blue','#8A2BE2':'BlueViolet','#A52A2A':'Brown', + '#DEB887':'BurlyWood','#5F9EA0':'CadetBlue','#7FFF00':'Chartreuse','#D2691E':'Chocolate','#FF7F50':'Coral','#6495ED':'CornflowerBlue', + '#FFF8DC':'Cornsilk','#DC143C':'Crimson','#00FFFF':'Cyan','#00008B':'DarkBlue','#008B8B':'DarkCyan','#B8860B':'DarkGoldenRod', + '#A9A9A9':'DarkGray','#A9A9A9':'DarkGrey','#006400':'DarkGreen','#BDB76B':'DarkKhaki','#8B008B':'DarkMagenta','#556B2F':'DarkOliveGreen', + '#FF8C00':'Darkorange','#9932CC':'DarkOrchid','#8B0000':'DarkRed','#E9967A':'DarkSalmon','#8FBC8F':'DarkSeaGreen','#483D8B':'DarkSlateBlue', + '#2F4F4F':'DarkSlateGray','#2F4F4F':'DarkSlateGrey','#00CED1':'DarkTurquoise','#9400D3':'DarkViolet','#FF1493':'DeepPink','#00BFFF':'DeepSkyBlue', + '#696969':'DimGray','#696969':'DimGrey','#1E90FF':'DodgerBlue','#B22222':'FireBrick','#FFFAF0':'FloralWhite','#228B22':'ForestGreen', + '#FF00FF':'Fuchsia','#DCDCDC':'Gainsboro','#F8F8FF':'GhostWhite','#FFD700':'Gold','#DAA520':'GoldenRod','#808080':'Gray','#808080':'Grey', + '#008000':'Green','#ADFF2F':'GreenYellow','#F0FFF0':'HoneyDew','#FF69B4':'HotPink','#CD5C5C':'IndianRed','#4B0082':'Indigo','#FFFFF0':'Ivory', + '#F0E68C':'Khaki','#E6E6FA':'Lavender','#FFF0F5':'LavenderBlush','#7CFC00':'LawnGreen','#FFFACD':'LemonChiffon','#ADD8E6':'LightBlue', + '#F08080':'LightCoral','#E0FFFF':'LightCyan','#FAFAD2':'LightGoldenRodYellow','#D3D3D3':'LightGray','#D3D3D3':'LightGrey','#90EE90':'LightGreen', + '#FFB6C1':'LightPink','#FFA07A':'LightSalmon','#20B2AA':'LightSeaGreen','#87CEFA':'LightSkyBlue','#778899':'LightSlateGray','#778899':'LightSlateGrey', + '#B0C4DE':'LightSteelBlue','#FFFFE0':'LightYellow','#00FF00':'Lime','#32CD32':'LimeGreen','#FAF0E6':'Linen','#FF00FF':'Magenta','#800000':'Maroon', + '#66CDAA':'MediumAquaMarine','#0000CD':'MediumBlue','#BA55D3':'MediumOrchid','#9370D8':'MediumPurple','#3CB371':'MediumSeaGreen','#7B68EE':'MediumSlateBlue', + '#00FA9A':'MediumSpringGreen','#48D1CC':'MediumTurquoise','#C71585':'MediumVioletRed','#191970':'MidnightBlue','#F5FFFA':'MintCream','#FFE4E1':'MistyRose','#FFE4B5':'Moccasin', + '#FFDEAD':'NavajoWhite','#000080':'Navy','#FDF5E6':'OldLace','#808000':'Olive','#6B8E23':'OliveDrab','#FFA500':'Orange','#FF4500':'OrangeRed','#DA70D6':'Orchid', + '#EEE8AA':'PaleGoldenRod','#98FB98':'PaleGreen','#AFEEEE':'PaleTurquoise','#D87093':'PaleVioletRed','#FFEFD5':'PapayaWhip','#FFDAB9':'PeachPuff', + '#CD853F':'Peru','#FFC0CB':'Pink','#DDA0DD':'Plum','#B0E0E6':'PowderBlue','#800080':'Purple','#FF0000':'Red','#BC8F8F':'RosyBrown','#4169E1':'RoyalBlue', + '#8B4513':'SaddleBrown','#FA8072':'Salmon','#F4A460':'SandyBrown','#2E8B57':'SeaGreen','#FFF5EE':'SeaShell','#A0522D':'Sienna','#C0C0C0':'Silver', + '#87CEEB':'SkyBlue','#6A5ACD':'SlateBlue','#708090':'SlateGray','#708090':'SlateGrey','#FFFAFA':'Snow','#00FF7F':'SpringGreen', + '#4682B4':'SteelBlue','#D2B48C':'Tan','#008080':'Teal','#D8BFD8':'Thistle','#FF6347':'Tomato','#40E0D0':'Turquoise','#EE82EE':'Violet', + '#F5DEB3':'Wheat','#FFFFFF':'White','#F5F5F5':'WhiteSmoke','#FFFF00':'Yellow','#9ACD32':'YellowGreen' +}; + +function init() { + var inputColor = convertRGBToHex(tinyMCE.getWindowArg('input_color')); + + if (tinyMCE.isMSIE) + tinyMCEPopup.resizeToInnerSize(); + + generatePicker(); + + if (inputColor) { + changeFinalColor(inputColor); + + col = convertHexToRGB(inputColor); + + if (col) + updateLight(col.r, col.g, col.b); + } +} + +function insertAction() { + var color = document.getElementById("color").value; + + tinyMCEPopup.execCommand(tinyMCE.getWindowArg('command'), false, color); + tinyMCEPopup.close(); +} + +function showColor(color, name) { + if (name) + document.getElementById("colorname").innerHTML = name; + + document.getElementById("preview").style.backgroundColor = color; + document.getElementById("color").value = color; +} + function convertRGBToHex(col) { var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); + if (!col) + return col; + var rgb = col.replace(re, "$1,$2,$3").split(','); if (rgb.length == 3) { r = parseInt(rgb[0]).toString(16); @@ -72,37 +119,131 @@ function convertHexToRGB(col) { g = parseInt(col.substring(2, 4), 16); b = parseInt(col.substring(4, 6), 16); - return "rgb(" + r + "," + g + "," + b + ")"; + return {r : r, g : g, b : b}; } - return col; + return null; } -function renderColorMap() { - var html = ""; - var inputColor = convertRGBToHex(tinyMCE.getWindowArg('input_color')); +function generatePicker() { + var el = document.getElementById('light'), h = '', i; + + for (i = 0; i < detail; i++){ + h += '<div id="gs'+i+'" style="background-color:#000000; width:15px; height:3px; border-style:none; border-width:0px;"' + + ' onclick="changeFinalColor(this.style.backgroundColor)"' + + ' onmousedown="isMouseDown = true; return false;"' + + ' onmouseup="isMouseDown = false;"' + + ' onmousemove="if (isMouseDown && isMouseOver) changeFinalColor(this.style.backgroundColor); return false;"' + + ' onmouseover="isMouseOver = true;"' + + ' onmouseout="isMouseOver = false;"' + + '></div>'; + } + + el.innerHTML = h; +} + +function generateWebColors() { + var el = document.getElementById('webcolors'), h = '', i; + + if (el.className == 'generated') + return; - html += '<table border="0" cellspacing="1" cellpadding="0">' + h += '<table border="0" cellspacing="1" cellpadding="0">' + '<tr>'; - for (var i=0; i<colors.length; i++) { - html += '<td bgcolor="' + colors[i] + '">' + + for (i=0; i<colors.length; i++) { + h += '<td bgcolor="' + colors[i] + '">' + '<a href="javascript:selectColor();" onfocus="showColor(\'' + colors[i] + '\');" onmouseover="showColor(\'' + colors[i] + '\');">' + '<img border="0" src="images/spacer.gif" width="10" height="10" title="' + colors[i] + '" alt="' + colors[i] + '" /></a></td>'; if ((i+1) % 18 == 0) - html += '</tr><tr>'; + h += '</tr><tr>'; + } + + h += '</table>'; + + el.innerHTML = h; + el.className = 'generated'; +} + +function generateNamedColors() { + var el = document.getElementById('namedcolors'), h = '', n, v, i = 0; + + if (el.className == 'generated') + return; + + for (n in named) { + v = named[n]; + h += '<a href="javascript:selectColor();" onmouseover="showColor(\'' + n + '\',\'' + v + '\');" style="background-color: ' + n + '"><!-- IE --></a>' + } + + el.innerHTML = h; + el.className = 'generated'; +} + +function selectColor() { + var color = document.getElementById("color").value; + + if(window.opener) + window.opener.tinyMCE.execInstanceCommand(tinyMCE.getWindowArg('editor_id'),tinyMCE.getWindowArg('command'),false,color); + + window.close(); +} + +function dechex(n) { + return strhex.charAt(Math.floor(n / 16)) + strhex.charAt(n % 16); +} + +function computeColor(e) { + var x, y, partWidth, partDetail, imHeight, r, g, b, coef, i, finalCoef, finalR, finalG, finalB; + + x = e.offsetX ? e.offsetX : (e.target ? e.clientX - e.target.x : 0); + y = e.offsetY ? e.offsetY : (e.target ? e.clientY - e.target.y : 0); + + partWidth = document.getElementById('colorpicker').width / 6; + partDetail = detail / 2; + imHeight = document.getElementById('colorpicker').height; + + r = (x >= 0)*(x < partWidth)*255 + (x >= partWidth)*(x < 2*partWidth)*(2*255 - x * 255 / partWidth) + (x >= 4*partWidth)*(x < 5*partWidth)*(-4*255 + x * 255 / partWidth) + (x >= 5*partWidth)*(x < 6*partWidth)*255; + g = (x >= 0)*(x < partWidth)*(x * 255 / partWidth) + (x >= partWidth)*(x < 3*partWidth)*255 + (x >= 3*partWidth)*(x < 4*partWidth)*(4*255 - x * 255 / partWidth); + b = (x >= 2*partWidth)*(x < 3*partWidth)*(-2*255 + x * 255 / partWidth) + (x >= 3*partWidth)*(x < 5*partWidth)*255 + (x >= 5*partWidth)*(x < 6*partWidth)*(6*255 - x * 255 / partWidth); + + coef = (imHeight - y) / imHeight; + r = 128 + (r - 128) * coef; + g = 128 + (g - 128) * coef; + b = 128 + (b - 128) * coef; + + changeFinalColor('#' + dechex(r) + dechex(g) + dechex(b)); + updateLight(r, g, b); +} + +function updateLight(r, g, b) { + var i, partDetail = detail / 2, finalCoef, finalR, finalG, finalB, color; + + for (i=0; i<detail; i++) { + if ((i>=0) && (i<partDetail)) { + finalCoef = i / partDetail; + finalR = dechex(255 - (255 - r) * finalCoef); + finalG = dechex(255 - (255 - g) * finalCoef); + finalB = dechex(255 - (255 - b) * finalCoef); + } else { + finalCoef = 2 - i / partDetail; + finalR = dechex(r * finalCoef); + finalG = dechex(g * finalCoef); + finalB = dechex(b * finalCoef); + } + + color = finalR + finalG + finalB; + + document.getElementById('gs' + i).style.backgroundColor = '#'+color; } - html += '<tr><td colspan="18">' - + '<table width="100%" border="0" cellspacing="0" cellpadding="0">' - + '<tr><td>' - + '<img id="selectedColor" style="background-color:' + tinyMCE.getWindowArg('input_color') + '" border="0" src="images/spacer.gif" width="80" height="16" />' - + '</td><td align="right">' - + '<input id="selectedColorBox" name="selectedColorBox" type="text" size="7" maxlength="7" style="width:65px" value="' + inputColor + '" />' - + '</td></tr>' - + '</table>' - + '<div style="float: left"><input type="button" id="insert" name="insert" value="{$lang_theme_colorpicker_apply}" style="margin-top:3px" onclick="selectColor();"></div>' - + '<div style="float: right"><input type="button" name="cancel" value="{$lang_cancel}" style="margin-top:3px" onclick="tinyMCEPopup.close();" id="cancel" /></div>' - + '</td></tr>' - + '</table>'; - - document.write(html); -}
\ No newline at end of file +} + +function changeFinalColor(color) { + if (color.indexOf('#') == -1) + color = convertRGBToHex(color); + + document.getElementById('preview').style.backgroundColor = color; + document.getElementById('color').value = color; +} + +window.focus();
\ No newline at end of file diff --git a/wp-includes/js/tinymce/themes/advanced/jscripts/link.js b/wp-includes/js/tinymce/themes/advanced/jscripts/link.js index 990b7a4..9adac22 100644 --- a/wp-includes/js/tinymce/themes/advanced/jscripts/link.js +++ b/wp-includes/js/tinymce/themes/advanced/jscripts/link.js @@ -27,6 +27,7 @@ function init() { document.forms[0].href.value = tinyMCE.getWindowArg('href') || 'http://'; document.forms[0].href.select(); + document.forms[0].href.focus(); document.forms[0].linktitle.value = tinyMCE.getWindowArg('title'); document.forms[0].insert.value = tinyMCE.getLang('lang_' + tinyMCE.getWindowArg('action'), 'Insert', true); @@ -57,8 +58,8 @@ function insertLink() { var title = document.forms[0].linktitle.value; var style_class = document.forms[0].styleSelect ? document.forms[0].styleSelect.value : ""; var dummy; - - // Make anchors absolute + + // WordPress: Make anchors absolute; if (href.charAt(0) == '#') href = tinyMCE.settings['document_base_url'] + href; diff --git a/wp-includes/js/tinymce/themes/advanced/langs/en.js b/wp-includes/js/tinymce/themes/advanced/langs/en.js index fd915ea..c658d6d 100644 --- a/wp-includes/js/tinymce/themes/advanced/langs/en.js +++ b/wp-includes/js/tinymce/themes/advanced/langs/en.js @@ -78,5 +78,14 @@ help : 'Help', not_set : '-- Not set --',
close : 'Close',
toolbar_focus : 'Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - Alt-X',
-invalid_data : 'Error: Invalid values entered, these are marked in red.'
+invalid_data : 'Error: Invalid values entered, these are marked in red.',
+more_colors : 'More colors',
+color_picker_tab : 'Picker',
+color_picker : 'Color picker',
+web_colors_tab : 'Web safe',
+web_colors : 'Web safe colors',
+named_colors_tab : 'Named',
+named_colors : 'Named colors',
+color : 'Color:',
+color_name : 'Name:'
});
diff --git a/wp-includes/js/tinymce/tiny_mce.js b/wp-includes/js/tinymce/tiny_mce.js index c3f2159..e425a1e 100644 --- a/wp-includes/js/tinymce/tiny_mce.js +++ b/wp-includes/js/tinymce/tiny_mce.js @@ -5,8 +5,8 @@ function TinyMCE_Engine() { var ua; this.majorVersion = "2"; - this.minorVersion = "0.9"; - this.releaseDate = "2007-01-09"; + this.minorVersion = "1.0"; + this.releaseDate = "2007-02-13"; this.instances = new Array(); this.switchClassCache = new Array(); @@ -186,7 +186,7 @@ TinyMCE_Engine.prototype = { this._def("custom_shortcuts", true); this._def("convert_on_click", false); this._def("content_css", ''); - this._def("fix_list_elements", false); + this._def("fix_list_elements", true); this._def("fix_table_elements", false); this._def("strict_loading_mode", document.contentType == 'application/xhtml+xml'); this._def("hidden_tab_class", ''); @@ -241,7 +241,7 @@ TinyMCE_Engine.prototype = { this.blockElms = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP'; this.blockRegExp = new RegExp("^(" + this.blockElms + ")$", "i"); this.posKeyCodes = new Array(13,45,36,35,33,34,37,38,39,40); - this.uniqueURL = 'javascript:TINYMCE_UNIQUEURL();'; // Make unique URL non real URL + this.uniqueURL = 'javascript:void(091039730);'; // Make unique URL non real URL this.uniqueTag = '<div id="mceTMPElement" style="display: none">TMP</div>'; this.callbacks = new Array('onInit', 'getInfo', 'getEditorTemplate', 'setupContent', 'onChange', 'onPageLoad', 'handleNodeChange', 'initInstance', 'execCommand', 'getControlHTML', 'handleEvent', 'cleanup', 'removeInstance'); @@ -740,6 +740,35 @@ TinyMCE_Engine.prototype = { tinyMCE.removeMCEControl(value); return; + case "mceToggleEditor": + var inst = tinyMCE.getInstanceById(value), pe, te; + + if (inst) { + pe = document.getElementById(inst.editorId + '_parent'); + te = inst.oldTargetElement; + + if (typeof(inst.enabled) == 'undefined') + inst.enabled = true; + + inst.enabled = !inst.enabled; + + if (!inst.enabled) { + pe.style.display = 'none'; + te.value = inst.getHTML(); + te.style.display = inst.oldTargetDisplay; + tinyMCE.dispatchCallback(inst, 'hide_instance_callback', 'hideInstance', inst); + } else { + pe.style.display = 'block'; + te.style.display = 'none'; + inst.setHTML(te.value); + inst.useCSS = false; + tinyMCE.dispatchCallback(inst, 'show_instance_callback', 'showInstance', inst); + } + } else + tinyMCE.addMCEControl(tinyMCE._getElementById(value), value); + + return; + case "mceResetDesignMode": // Resets the designmode state of the editors in Gecko if (!tinyMCE.isIE) { @@ -961,10 +990,6 @@ TinyMCE_Engine.prototype = { // Fix for bug #957681 //inst.getDoc().designMode = inst.getDoc().designMode; - // Setup element references - var parentElm = inst.targetDoc.getElementById(inst.editorId + '_parent'); - inst.formElement = tinyMCE.isGecko ? parentElm.previousSibling : parentElm.nextSibling; - tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings['visual'], inst); tinyMCE.dispatchCallback(inst, 'setupcontent_callback', 'setupContent', editor_id, inst.getBody(), inst.getDoc()); @@ -1445,9 +1470,9 @@ TinyMCE_Engine.prototype = { h += '</a></span>'; } else { if (tinyMCE.isRealIE) - h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">'; + h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">'; else - h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton">'; + h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton">'; h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceMenuButtonNormal" target="_self">'; h += '<img src="' + img + '" title="{$' + lang + '}" /></a>'; @@ -1693,7 +1718,7 @@ TinyMCE_Engine.prototype = { }, triggerNodeChange : function(focus, setup_content) { - var elm, inst, editorId, undoIndex = -1, undoLevels = -1, doc, anySelection = false; + var elm, inst, editorId, undoIndex = -1, undoLevels = -1, doc, anySelection = false, st; if (tinyMCE.selectedInstance) { inst = tinyMCE.selectedInstance; @@ -1705,7 +1730,7 @@ TinyMCE_Engine.prototype = { inst.lastTriggerEl = elm;*/ editorId = inst.editorId; - selectedText = inst.selection.getSelectedText(); + st = inst.selection.getSelectedText(); if (tinyMCE.settings.auto_resize) inst.resizeToContent(); @@ -1716,7 +1741,7 @@ TinyMCE_Engine.prototype = { inst.switchSettings(); if (tinyMCE.selectedElement) - anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (selectedText && selectedText.length > 0); + anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (st && st.length > 0); if (tinyMCE.settings['custom_undo_redo']) { undoIndex = inst.undoRedo.undoIndex; @@ -2180,11 +2205,11 @@ TinyMCE_Engine.prototype = { }, getCSSClasses : function(editor_id, doc) { - var output = new Array(); + var inst = tinyMCE.getInstanceById(editor_id); // Is cached, use that - if (typeof(tinyMCE.cssClasses) != "undefined") - return tinyMCE.cssClasses; + if (inst && inst.cssClasses.length > 0) + return inst.cssClasses; if (typeof(editor_id) == "undefined" && typeof(doc) == "undefined") { var instance; @@ -2242,13 +2267,13 @@ TinyMCE_Engine.prototype = { var cssClass = rule.substring(rule.indexOf('.') + 1); var addClass = true; - for (var p=0; p<output.length && addClass; p++) { - if (output[p] == cssClass) + for (var p=0; p<inst.cssClasses.length && addClass; p++) { + if (inst.cssClasses[p] == cssClass) addClass = false; } if (addClass) - output[output.length] = cssClass; + inst.cssClasses[inst.cssClasses.length] = cssClass; } } } @@ -2257,11 +2282,7 @@ TinyMCE_Engine.prototype = { } } - // Cache em - if (output.length > 0) - tinyMCE.cssClasses = output; - - return output; + return inst.cssClasses; }, regexpReplace : function(in_str, reg_exp, replace_str, opts) { @@ -2289,19 +2310,27 @@ TinyMCE_Engine.prototype = { }, getControlHTML : function(c) { - var i, l, n, o, v; + var i, l, n, o, v, rtl = tinyMCE.getLang('lang_dir') == 'rtl'; l = tinyMCE.plugins; for (n in l) { o = l[n]; - if (o.getControlHTML && (v = o.getControlHTML(c)) != '') + if (o.getControlHTML && (v = o.getControlHTML(c)) != '') { + if (rtl) + return '<span dir="rtl">' + tinyMCE.replaceVar(v, "pluginurl", o.baseURL) + '</span>'; + return tinyMCE.replaceVar(v, "pluginurl", o.baseURL); + } } o = tinyMCE.themes[tinyMCE.settings['theme']]; - if (o.getControlHTML && (v = o.getControlHTML(c)) != '') + if (o.getControlHTML && (v = o.getControlHTML(c)) != '') { + if (rtl) + return '<span dir="rtl">' + v + '</span>'; + return v; + } return ''; }, @@ -2433,6 +2462,7 @@ function TinyMCE_Control(settings) { this.hasMouseMoved = false; this.foreColor = this.backColor = "#999999"; this.data = {}; + this.cssClasses = []; this.cleanup.init({ valid_elements : s.valid_elements, @@ -2865,7 +2895,7 @@ TinyMCE_Control.prototype = { if (tinyMCE.isGecko && this.getSel().isCollapsed) { focusElm = tinyMCE.getParentElement(focusElm, 'A'); - if (focusElm && this.getRng(0).endOffset > 0 && this.getRng(0).endOffset != focusElm.innerHTML.length) // WordPress mod to prevent unlinking if caret at start/end of link + if (focusElm) this.selection.selectNode(focusElm, false); } @@ -3690,6 +3720,7 @@ TinyMCE_Control.prototype = { hc = '<textarea wrap="off" id="' + form_element_name + '" name="' + form_element_name + '" cols="100" rows="15"></textarea>'; } else { hc = '<input type="hidden" id="' + form_element_name + '" name="' + form_element_name + '" />'; + this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline'); this.oldTargetElement.style.display = "none"; } @@ -3715,8 +3746,10 @@ TinyMCE_Control.prototype = { // Just hide the textarea element this.oldTargetElement = replace_element; - if (!tinyMCE.settings['debug']) + if (!tinyMCE.settings['debug']) { + this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline'); this.oldTargetElement.style.display = "none"; + } // Output HTML and set editable if (tinyMCE.isGecko) { @@ -3790,6 +3823,10 @@ TinyMCE_Control.prototype = { if (tinyMCE.isIE) window.setTimeout("tinyMCE.addEventHandlers(tinyMCE.instances[\"" + this.editorId + "\"]);", 1); + // Setup element references + var parentElm = this.targetDoc.getElementById(this.editorId + '_parent'); + this.formElement = tinyMCE.isGecko ? parentElm.previousSibling : parentElm.nextSibling; + tinyMCE.setupContent(this.editorId, true); return true; @@ -4865,7 +4902,7 @@ TinyMCE_Cleanup.prototype = { if (r.forceAttribs && (t = r.forceAttribs[an])) av = t; - if (os && av.length != 0 && this.settings.url_converter.length != 0 && /^(src|href|longdesc)$/.test(an)) + if (os && av.length != 0 && /^(src|href|longdesc)$/.test(an)) av = this._urlConverter(this, n, av); if (av.length != 0 && r.validAttribValues && r.validAttribValues[an] && !r.validAttribValues[an].test(av)) @@ -5186,9 +5223,10 @@ TinyMCE_Engine.prototype.setInnerHTML = function(e, h) { // Convert all strong/em to b/i in Gecko if (tinyMCE.isGecko) { - h = h.replace(/<strong/gi, '<b'); - h = h.replace(/<em(\/?)/gi, '<i'); - h = h.replace(/<em /gi, '<i'); + h = h.replace(/<embed([^>]*)>/gi, '<tmpembed$1>'); + h = h.replace(/<em([^>]*)>/gi, '<i$1>'); + h = h.replace(/<tmpembed([^>]*)>/gi, '<embed$1>'); + h = h.replace(/<strong([^>]*)>/gi, '<b$1>'); h = h.replace(/<\/strong>/gi, '</b>'); h = h.replace(/<\/em>/gi, '</i>'); } @@ -5503,6 +5541,32 @@ TinyMCE_Engine.prototype.getViewPort = function(w) { }; }; +TinyMCE_Engine.prototype.getStyle = function(n, na, d) { + if (!n) + return false; + + // Gecko + if (tinyMCE.isGecko && n.ownerDocument.defaultView) { + try { + return n.ownerDocument.defaultView.getComputedStyle(n, null).getPropertyValue(na); + } catch (n) { + // Old safari might fail + return null; + } + } + + // Camelcase it, if needed + na = na.replace(/-(\D)/g, function(a, b){ + return b.toUpperCase(); + }); + + // IE & Opera + if (n.currentStyle) + return n.currentStyle[na]; + + return false; +}; + /* file:jscripts/tiny_mce/classes/TinyMCE_URL.class.js */ TinyMCE_Engine.prototype.parseURL = function(url_str) { @@ -7132,13 +7196,21 @@ TinyMCE_Layer.prototype = { }, show : function() { - this.getElement().style.display = 'block'; - this.updateBlocker(); + var el = this.getElement(); + + if (el) { + el.style.display = 'block'; + this.updateBlocker(); + } }, hide : function() { - this.getElement().style.display = 'none'; - this.updateBlocker(); + var el = this.getElement(); + + if (el) { + el.style.display = 'none'; + this.updateBlocker(); + } }, isVisible : function() { diff --git a/wp-includes/js/tinymce/tiny_mce_config.php b/wp-includes/js/tinymce/tiny_mce_config.php index 9e06575..de01c67 100644 --- a/wp-includes/js/tinymce/tiny_mce_config.php +++ b/wp-includes/js/tinymce/tiny_mce_config.php @@ -29,7 +29,7 @@ $plugins = apply_filters('mce_plugins', $plugins); $plugins = implode($plugins, ','); - $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', 'separator', 'bullist', 'numlist', 'outdent', 'indent', 'separator', 'justifyleft', 'justifycenter', 'justifyright', 'separator', 'link', 'unlink', 'image', 'wp_more', 'separator', 'spellchecker', 'separator', 'wp_help', 'wp_adv_start', 'wp_adv', 'separator', 'formatselect', 'underline', 'justifyfull', 'forecolor', 'separator', 'pastetext', 'pasteword', 'separator', 'removeformat', 'cleanup', 'separator', 'charmap', 'separator', 'undo', 'redo', 'wp_adv_end')); + $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', 'separator', 'bullist', 'numlist', 'outdent', 'indent', 'separator', 'justifyleft', 'justifycenter', 'justifyright', 'separator', 'link', 'unlink', 'image', 'wp_more', 'separator', 'spellchecker', 'separator', 'wp_help', 'wp_adv', 'wp_adv_start', 'formatselect', 'underline', 'justifyfull', 'forecolor', 'separator', 'pastetext', 'pasteword', 'separator', 'removeformat', 'cleanup', 'separator', 'charmap', 'separator', 'undo', 'redo', 'wp_adv_end')); $mce_buttons = implode($mce_buttons, ','); $mce_buttons_2 = apply_filters('mce_buttons_2', array()); @@ -48,6 +48,8 @@ $mce_css = str_replace('http://', 'https://', $mce_css); $mce_popups_css = str_replace('http://', 'https://', $mce_popups_css); } + + $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower(get_locale()); ?> initArray = { @@ -58,7 +60,7 @@ initArray = { theme_advanced_buttons1 : "<?php echo $mce_buttons; ?>", theme_advanced_buttons2 : "<?php echo $mce_buttons_2; ?>", theme_advanced_buttons3 : "<?php echo $mce_buttons_3; ?>", - language : "<?php echo strtolower(get_locale()); ?>", + language : "<?php echo $mce_locale; ?>", theme_advanced_toolbar_location : "top", theme_advanced_toolbar_align : "left", theme_advanced_path_location : "bottom", @@ -76,6 +78,7 @@ initArray = { fix_list_elements : true, gecko_spellcheck : true, entities : "38,amp,60,lt,62,gt", + button_tile_map : true, content_css : "<?php echo $mce_css; ?>", valid_elements : "<?php echo $valid_elements; ?>", save_callback : 'TinyMCE_wordpressPlugin.saveCallback', diff --git a/wp-includes/js/tinymce/tiny_mce_gzip.php b/wp-includes/js/tinymce/tiny_mce_gzip.php index 59af4b6..14ffba3 100644 --- a/wp-includes/js/tinymce/tiny_mce_gzip.php +++ b/wp-includes/js/tinymce/tiny_mce_gzip.php @@ -84,7 +84,7 @@ if (isset($_SERVER['HTTP_ACCEPT_ENCODING'])) $encodings = explode(',', strtolower(preg_replace("/\s+/", "", $_SERVER['HTTP_ACCEPT_ENCODING']))); - if ((in_array('gzip', $encodings) || in_array('x-gzip', $encodings) || isset($_SERVER['---------------'])) && function_exists('ob_gzhandler') && !ini_get('zlib.output_compression')) { + if ((in_array('gzip', $encodings) || in_array('x-gzip', $encodings) || isset($_SERVER['---------------'])) && function_exists('ob_gzhandler') && !ini_get('zlib.output_compression') && ini_get('output_handler') != 'ob_gzhandler') { $enc = in_array('x-gzip', $encodings) ? "x-gzip" : "gzip"; $supportsGzip = true; } diff --git a/wp-includes/js/wp-ajax.js b/wp-includes/js/wp-ajax.js index cc3bb5a..e3f63f7 100644 --- a/wp-includes/js/wp-ajax.js +++ b/wp-includes/js/wp-ajax.js @@ -27,9 +27,9 @@ Object.extend(WPAjax.prototype, { this.getResponseElement(responseEl); }, addArg: function(key, value) { - var a = []; + var a = $H(); a[encodeURIComponent(key)] = encodeURIComponent(value); - this.options.parameters = $H(this.options.parameters).merge($H(a)); + this.options.parameters = $H(this.options.parameters).merge(a); }, getResponseElement: function(r) { var p = $(r + '-p'); diff --git a/wp-includes/kses.php b/wp-includes/kses.php index aa9e465..4b5a284 100644 --- a/wp-includes/kses.php +++ b/wp-includes/kses.php @@ -18,253 +18,207 @@ if (!defined('CUSTOM_TAGS')) // You can override this in your my-hacks.php file if (!CUSTOM_TAGS) { - $allowedposttags = array ( - 'address' => array (), - 'a' => array ( - 'class' => array (), - 'href' => array (), - 'id' => array (), - 'title' => array (), - 'rel' => array (), - 'rev' => array (), - 'name' => array (), - 'target' => array()), - 'abbr' => array ( - 'title' => array ()), - 'acronym' => array ( - 'title' => array ()), - 'b' => array (), - 'big' => array (), - 'blockquote' => array ( - 'id' => array (), - 'cite' => array ()), - 'br' => array ( - 'class' => array ()), - 'button' => array ( - 'disabled' => array (), - 'name' => array (), - 'type' => array (), - 'value' => array ()), - 'caption' => array ( - 'align' => array (), - 'class' => array ()), - 'cite' => array ( - 'class' => array(), - 'dir' => array(), - 'lang' => array(), - 'title' => array ()), - 'code' => array (), - 'col' => array ( - 'align' => array (), - 'char' => array (), - 'charoff' => array (), - 'span' => array (), - 'dir' => array(), - 'valign' => array (), - 'width' => array ()), - 'del' => array ( - 'datetime' => array ()), - 'dd' => array (), - 'div' => array ( - 'align' => array (), - 'class' => array (), - 'dir' => array ()), - 'dl' => array (), - 'dt' => array (), - 'em' => array (), - 'fieldset' => array (), - 'font' => array ( - 'color' => array (), - 'face' => array (), - 'size' => array ()), - 'form' => array ( - 'action' => array (), - 'accept' => array (), - 'accept-charset' => array (), - 'enctype' => array (), - 'method' => array (), - 'name' => array (), - 'target' => array ()), - 'h1' => array ( - 'align' => array (), - 'class' => array ()), - 'h2' => array ( - 'align' => array (), - 'class' => array ()), - 'h3' => array ( - 'align' => array (), - 'class' => array ()), - 'h4' => array ( - 'align' => array (), - 'class' => array ()), - 'h5' => array ( - 'align' => array (), - 'class' => array ()), - 'h6' => array ( - 'align' => array (), - 'class' => array ()), - 'hr' => array ( - 'align' => array (), - 'class' => array (), - 'noshade' => array (), - 'size' => array (), - 'width' => array ()), - 'i' => array (), - 'img' => array ( - 'alt' => array (), - 'align' => array (), - 'border' => array (), - 'class' => array (), - 'height' => array (), - 'hspace' => array (), - 'longdesc' => array (), - 'vspace' => array (), - 'src' => array (), - 'width' => array ()), - 'ins' => array ( - 'datetime' => array (), - 'cite' => array ()), - 'kbd' => array (), - 'label' => array ( - 'for' => array ()), - 'legend' => array ( - 'align' => array ()), - 'li' => array ( - 'align' => array (), - 'class' => array ()), - 'p' => array ( - 'class' => array (), - 'align' => array (), - 'dir' => array()), - 'pre' => array ( - 'width' => array ()), - 'q' => array ( - 'cite' => array ()), - 's' => array (), - 'span' => array ( - 'class' => array (), - 'dir' => array (), - 'align' => array ()), - 'strike' => array (), - 'strong' => array (), - 'sub' => array (), - 'sup' => array (), - 'table' => array ( - 'align' => array (), - 'bgcolor' => array (), - 'border' => array (), - 'cellpadding' => array (), - 'cellspacing' => array (), - 'class' => array (), - 'dir' => array(), - 'rules' => array (), - 'summary' => array (), - 'width' => array ()), - 'tbody' => array ( - 'align' => array (), - 'char' => array (), - 'charoff' => array (), - 'valign' => array ()), - 'td' => array ( - 'abbr' => array (), - 'align' => array (), - 'axis' => array (), - 'bgcolor' => array (), - 'char' => array (), - 'charoff' => array (), - 'class' => array (), - 'colspan' => array (), - 'dir' => array(), - 'headers' => array (), - 'height' => array (), - 'nowrap' => array (), - 'rowspan' => array (), - 'scope' => array (), - 'valign' => array (), - 'width' => array ()), - 'textarea' => array ( - 'cols' => array (), - 'rows' => array (), - 'disabled' => array (), - 'name' => array (), - 'readonly' => array ()), - 'tfoot' => array ( - 'align' => array (), - 'char' => array (), - 'class' => array (), - 'charoff' => array (), - 'valign' => array ()), - 'th' => array ( - 'abbr' => array (), - 'align' => array (), - 'axis' => array (), - 'bgcolor' => array (), - 'char' => array (), - 'charoff' => array (), - 'class' => array (), - 'colspan' => array (), - 'headers' => array (), - 'height' => array (), - 'nowrap' => array (), - 'rowspan' => array (), - 'scope' => array (), - 'valign' => array (), - 'width' => array ()), - 'thead' => array ( - 'align' => array (), - 'char' => array (), - 'charoff' => array (), - 'class' => array (), - 'valign' => array ()), - 'title' => array (), - 'tr' => array ( - 'align' => array (), - 'bgcolor' => array (), - 'char' => array (), - 'charoff' => array (), - 'class' => array (), - 'valign' => array ()), - 'tt' => array (), - 'u' => array (), - 'ul' => array ( - 'class' => array ()), - 'ol' => array ( - 'class' => array ()), - 'var' => array ()); - $allowedtags = array ( - 'a' => array ( - 'href' => array (), - 'title' => array ()), - 'abbr' => array ( - 'title' => array ()), - 'acronym' => array ( - 'title' => array ()), - 'b' => array (), - 'blockquote' => array ( - 'cite' => array ()), - // 'br' => array(), - 'cite' => array (), - 'code' => array (), + $allowedposttags = array( + 'address' => array(), + 'a' => array( + 'href' => array(), 'title' => array(), + 'rel' => array(), 'rev' => array(), + 'name' => array() + ), + 'abbr' => array( + 'title' => array(), 'class' => array() + ), + 'acronym' => array( + 'title' => array() + ), + 'b' => array(), + 'big' => array(), + 'blockquote' => array( + 'cite' => array(), 'xml:lang' => array(), + 'lang' => array() + ), + 'br' => array(), + 'button' => array( + 'disabled' => array(), 'name' => array(), + 'type' => array(), 'value' => array() + ), + 'caption' => array( + 'align' => array() + ), + 'code' => array(), + 'col' => array( + 'align' => array(), 'char' => array(), + 'charoff' => array(), 'span' => array(), + 'valign' => array(), 'width' => array() + ), 'del' => array( - 'datetime' => array ()), - // 'dd' => array(), - // 'dl' => array(), - // 'dt' => array(), - 'em' => array (), 'i' => array (), - // 'ins' => array('datetime' => array(), 'cite' => array()), - // 'li' => array(), - // 'ol' => array(), - // 'p' => array(), + 'datetime' => array() + ), + 'dd' => array(), + 'div' => array( + 'align' => array(), 'xml:lang' => array(), + 'lang' => array() + ), + 'dl' => array(), + 'dt' => array(), + 'em' => array(), + 'fieldset' => array(), + 'font' => array( + 'color' => array(), 'face' => array(), + 'size' => array() + ), + 'form' => array( + 'action' => array(), 'accept' => array(), + 'accept-charset' => array(), 'enctype' => array(), + 'method' => array(), 'name' => array(), + 'target' => array() + ), + 'h1' => array( + 'align' => array() + ), + 'h2' => array( + 'align' => array() + ), + 'h3' => array( + 'align' => array() + ), + 'h4' => array( + 'align' => array() + ), + 'h5' => array( + 'align' => array() + ), + 'h6' => array( + 'align' => array() + ), + 'hr' => array( + 'align' => array(), 'noshade' => array(), + 'size' => array(), 'width' => array() + ), + 'i' => array(), + 'img' => array( + 'alt' => array(), 'align' => array(), + 'border' => array(), 'height' => array(), + 'hspace' => array(), 'longdesc' => array(), + 'vspace' => array(), 'src' => array(), + 'width' => array() + ), + 'ins' => array( + 'datetime' => array(), 'cite' => array() + ), + 'kbd' => array(), + 'label' => array( + 'for' => array() + ), + 'legend' => array( + 'align' => array() + ), + 'li' => array(), + 'p' => array( + 'align' => array(), 'xml:lang' => array(), + 'lang' => array() + ), + 'pre' => array( + 'width' => array() + ), 'q' => array( - 'cite' => array ()), - 'strike' => array (), - 'strong' => array (), - // 'sub' => array(), - // 'sup' => array(), - // 'u' => array(), - // 'ul' => array(), + 'cite' => array() + ), + 's' => array(), + 'strike' => array(), + 'strong' => array(), + 'sub' => array(), + 'sup' => array(), + 'table' => array( + 'align' => array(), 'bgcolor' => array(), + 'border' => array(), 'cellpadding' => array(), + 'cellspacing' => array(), 'rules' => array(), + 'summary' => array(), 'width' => array() + ), + 'tbody' => array( + 'align' => array(), 'char' => array(), + 'charoff' => array(), 'valign' => array() + ), + 'td' => array( + 'abbr' => array(), 'align' => array(), + 'axis' => array(), 'bgcolor' => array(), + 'char' => array(), 'charoff' => array(), + 'colspan' => array(), 'headers' => array(), + 'height' => array(), 'nowrap' => array(), + 'rowspan' => array(), 'scope' => array(), + 'valign' => array(), 'width' => array() + ), + 'textarea' => array( + 'cols' => array(), 'rows' => array(), + 'disabled' => array(), 'name' => array(), + 'readonly' => array() + ), + 'tfoot' => array( + 'align' => array(), 'char' => array(), + 'charoff' => array(), 'valign' => array() + ), + 'th' => array( + 'abbr' => array(), 'align' => array(), + 'axis' => array(), 'bgcolor' => array(), + 'char' => array(), 'charoff' => array(), + 'colspan' => array(), 'headers' => array(), + 'height' => array(), 'nowrap' => array(), + 'rowspan' => array(), 'scope' => array(), + 'valign' => array(), 'width' => array() + ), + 'thead' => array( + 'align' => array(), 'char' => array(), + 'charoff' => array(), 'valign' => array() + ), + 'title' => array(), + 'tr' => array( + 'align' => array(), 'bgcolor' => array(), + 'char' => array(), 'charoff' => array(), + 'valign' => array() + ), + 'tt' => array(), + 'u' => array(), + 'ul' => array(), + 'ol' => array(), + 'var' => array() + ); + + $allowedtags = array( + 'a' => array( + 'href' => array(), 'title' => array() + ), + 'abbr' => array( + 'title' => array() + ), + 'acronym' => array( + 'title' => array() + ), + 'b' => array(), + 'blockquote' => array( + 'cite' => array() + ), + // 'br' => array(), + 'code' => array(), + // 'del' => array('datetime' => array()), + // 'dd' => array(), + // 'dl' => array(), + // 'dt' => array(), + 'em' => array(), + 'i' => array(), + // 'ins' => array('datetime' => array(), 'cite' => array()), + // 'li' => array(), + // 'ol' => array(), + // 'p' => array(), + // 'q' => array(), + 'strike' => array(), + 'strong' => array(), + // 'sub' => array(), + // 'sup' => array(), + // 'u' => array(), + // 'ul' => array(), ); } + function wp_kses($string, $allowed_html, $allowed_protocols = array ('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet')) ############################################################################### # This function makes sure that only the allowed HTML element names, attribute diff --git a/wp-includes/l10n.php b/wp-includes/l10n.php index 0847ea3..4dba679 100644 --- a/wp-includes/l10n.php +++ b/wp-includes/l10n.php @@ -17,8 +17,7 @@ function get_locale() { return $locale; } -// Return a translated string. -function __($text, $domain = 'default') { +function translate($text, $domain) { global $l10n; if (isset($l10n[$domain])) @@ -27,29 +26,24 @@ function __($text, $domain = 'default') { return $text; } +// Return a translated string. +function __($text, $domain = 'default') { + return translate($text, $domain); +} + // Echo a translated string. function _e($text, $domain = 'default') { - global $l10n; - - if (isset($l10n[$domain])) - echo apply_filters('gettext', $l10n[$domain]->translate($text), $text); - else - echo $text; + echo translate($text, $domain); } function _c($text, $domain = 'default') { - global $l10n; - - if ( isset($l10n[$domain]) ) - $whole = apply_filters('gettext', $l10n[$domain]->translate($text), $text); - else - $whole = $text; - - $trans = explode('|', $whole, 2); - if ( isset( $trans[1] ) ) - return $trans[1]; - else - return $trans[0]; + $whole = translate($text, $domain); + $last_bar = strrpos($whole, '|'); + if ( false == $last_bar ) { + return $whole; + } else { + return substr($whole, 0, $last_bar); + } } // Return the plural form. @@ -57,7 +51,7 @@ function __ngettext($single, $plural, $number, $domain = 'default') { global $l10n; if (isset($l10n[$domain])) { - return $l10n[$domain]->ngettext($single, $plural, $number); + return apply_filters('ngettext', $l10n[$domain]->ngettext($single, $plural, $number), $single, $plural, $number); } else { if ($number != 1) return $plural; diff --git a/wp-includes/link-template.php b/wp-includes/link-template.php index a7f9601..99b8ae0 100644 --- a/wp-includes/link-template.php +++ b/wp-includes/link-template.php @@ -109,7 +109,7 @@ function get_permalink($id = 0) { } // get permalink from post ID -function post_permalink($post_id = 0, $mode = '') { // $mode legacy +function post_permalink($post_id = 0, $deprecated = '') { return get_permalink($post_id); } @@ -273,39 +273,80 @@ function get_post_comments_feed_link($post_id = '', $feed = 'rss2') { return apply_filters('post_comments_feed_link', $url); } -function edit_post_link($link = 'Edit This', $before = '', $after = '') { +function get_edit_post_link( $id = 0 ) { + $post = &get_post( $id ); + + if ( $post->post_type == 'attachment' ) { + return; + } elseif ( $post->post_type == 'page' ) { + if ( !current_user_can( 'edit_page', $post->ID ) ) + return; + + $file = 'page'; + } else { + if ( !current_user_can( 'edit_post', $post->ID ) ) + return; + + $file = 'post'; + } + + return apply_filters( 'get_edit_post_link', get_bloginfo( 'wpurl' ) . '/wp-admin/' . $file . '.php?action=edit&post=' . $post->ID, $post->ID ); +} + +function edit_post_link( $link = 'Edit This', $before = '', $after = '' ) { global $post; - if ( is_attachment() ) + if ( $post->post_type == 'attachment' ) { return; - - if( $post->post_type == 'page' ) { - if ( ! current_user_can('edit_page', $post->ID) ) + } elseif ( $post->post_type == 'page' ) { + if ( !current_user_can( 'edit_page', $post->ID ) ) return; + $file = 'page'; } else { - if ( ! current_user_can('edit_post', $post->ID) ) + if ( !current_user_can( 'edit_post', $post->ID ) ) return; + $file = 'post'; } - $location = get_option('siteurl') . "/wp-admin/{$file}.php?action=edit&post=$post->ID"; - echo $before . "<a href=\"$location\">$link</a>" . $after; + $link = '<a href="' . get_edit_post_link( $post->ID ) . '" title="' . __( 'Edit post' ) . '">' . $link . '</a>'; + echo $before . apply_filters( 'edit_post_link', $link, $post->ID ) . $after; } -function edit_comment_link($link = 'Edit This', $before = '', $after = '') { - global $post, $comment; +function get_edit_comment_link( $comment_id = 0 ) { + $comment = &get_comment( $comment_id ); + $post = &get_post( $comment->comment_post_ID ); + + if ( $post->post_type == 'attachment' ) { + return; + } elseif ( $post->post_type == 'page' ) { + if ( !current_user_can( 'edit_page', $post->ID ) ) + return; + } else { + if ( !current_user_can( 'edit_post', $post->ID ) ) + return; + } - if( $post->post_type == 'page' ){ - if ( ! current_user_can('edit_page', $post->ID) ) + $location = get_bloginfo( 'wpurl' ) . '/wp-admin/comment.php?action=editcomment&c=' . $comment->comment_ID; + return apply_filters( 'get_edit_comment_link', $location ); +} + +function edit_comment_link( $link = 'Edit This', $before = '', $after = '' ) { + global $comment, $post; + + if ( $post->post_type == 'attachment' ) { + return; + } elseif ( $post->post_type == 'page' ) { + if ( !current_user_can( 'edit_page', $post->ID ) ) return; } else { - if ( ! current_user_can('edit_post', $post->ID) ) + if ( !current_user_can( 'edit_post', $post->ID ) ) return; } - $location = get_option('siteurl') . "/wp-admin/comment.php?action=editcomment&c=$comment->comment_ID"; - echo $before . "<a href='$location'>$link</a>" . $after; + $link = '<a href="' . get_edit_comment_link( $comment->comment_ID ) . '" title="' . __( 'Edit comment' ) . '">' . $link . '</a>'; + echo $before . apply_filters( 'edit_comment_link', $link, $comment->comment_ID ) . $after; } // Navigation links @@ -422,73 +463,55 @@ function next_post_link($format='%link »', $link='%title', $in_same_cat = function get_pagenum_link($pagenum = 1) { global $wp_rewrite; - - $qstr = $_SERVER['REQUEST_URI']; - - $page_querystring = "paged"; - $page_modstring = "page/"; - $page_modregex = "page/?"; - $permalink = 0; - + + $pagenum = (int) $pagenum; + + $request = remove_query_arg( 'paged' ); + $home_root = parse_url(get_option('home')); $home_root = $home_root['path']; - $home_root = trailingslashit($home_root); - $qstr = preg_replace('|^'. $home_root . '|', '', $qstr); - $qstr = preg_replace('|^/+|', '', $qstr); - - $index = $_SERVER['PHP_SELF']; - $index = preg_replace('|^'. $home_root . '|', '', $index); - $index = preg_replace('|^/+|', '', $index); - - // if we already have a QUERY style page string - if ( stristr( $qstr, $page_querystring ) ) { - $replacement = "$page_querystring=$pagenum"; - $qstr = preg_replace("/".$page_querystring."[^\d]+\d+/", $replacement, $qstr); - // if we already have a mod_rewrite style page string - } elseif ( preg_match( '|'.$page_modregex.'\d+|', $qstr ) ) { - $permalink = 1; - $qstr = preg_replace('|'.$page_modregex.'\d+|',"$page_modstring$pagenum",$qstr); - - // if we don't have a page string at all ... - // lets see what sort of URL we have... + $home_root = preg_quote( trailingslashit( $home_root ), '|' ); + + $request = preg_replace('|^'. $home_root . '|', '', $request); + $request = preg_replace('|^/+|', '', $request); + + if ( !$wp_rewrite->using_permalinks() ) { + $base = trailingslashit( get_bloginfo( 'home' ) ); + + if ( $pagenum > 1 ) { + $result = add_query_arg( 'paged', $pagenum, $base . $request ); + } else { + $result = $base . $request; + } } 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, '?' ) ) { - // so append the query string (using &, since we already have ?) - $qstr .= '&' . $page_querystring . '=' . $pagenum; - // otherwise, it could be rewritten, OR just the default index ... - } elseif( '' != get_option('permalink_structure') && ! is_admin() ) { - $permalink = 1; - $index = $wp_rewrite->index; - // If it's not a path info permalink structure, trim the index. - if ( !$wp_rewrite->using_index_permalinks() ) { - $qstr = preg_replace("#/*" . $index . "/*#", '/', $qstr); - } else { - // If using path info style permalinks, make sure the index is in - // the URL. - if ( strpos($qstr, $index) === false ) - $qstr = '/' . $index . $qstr; - } - - $qstr = trailingslashit($qstr) . $page_modstring . $pagenum; + $request = preg_replace( '|/?page/(.+)/?$|', '', $request); + + $qs_regex = '|\?.*?$|'; + preg_match( $qs_regex, $request, $qs_match ); + + if ( $qs_match[0] ) { + $query_string = $qs_match[0]; + $request = preg_replace( $qs_regex, '', $request ); } else { - $qstr = $index . '?' . $page_querystring . '=' . $pagenum; + $query_string = ''; } + + $base = trailingslashit( get_bloginfo( 'url' ) ); + + if ( $wp_rewrite->using_index_permalinks() && $pagenum > 1 ) { + $base .= 'index.php/'; + } + + if ( $pagenum > 1 ) { + $request = ( ( !empty( $request ) ) ? trailingslashit( $request ) : $request ) . user_trailingslashit( 'page/' . $pagenum, 'paged' ); + } else { + $request = user_trailingslashit( $request ); + } + + $result = $base . $request . $query_string; } - - $qstr = preg_replace('|^/+|', '', $qstr); - if ( $permalink ) - $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(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; + + return $result; } function get_next_posts_page_link($max_page = 0) { diff --git a/wp-includes/locale.php b/wp-includes/locale.php index 0c8ec8b..af3fc13 100644 --- a/wp-includes/locale.php +++ b/wp-includes/locale.php @@ -87,6 +87,18 @@ class WP_Locale { $this->meridiem['AM'] = __('AM'); $this->meridiem['PM'] = __('PM'); + // Numbers formatting + // See http://php.net/number_format + + $trans = __('number_format_decimals'); + $this->number_format['decimals'] = ('number_format_decimals' == $trans) ? 0 : $trans; + + $trans = __('number_format_decimal_point'); + $this->number_format['decimal_point'] = ('number_format_decimal_point' == $trans) ? '.' : $trans; + + $trans = __('number_format_thousands_sep'); + $this->number_format['thousands_sep'] = ('number_format_thousands_sep' == $trans) ? ',' : $trans; + // Import global locale vars set during inclusion of $locale.php. foreach ( $this->locale_vars as $var ) { if ( isset($GLOBALS[$var]) ) diff --git a/wp-includes/pluggable.php b/wp-includes/pluggable.php index 5f00e1d..949e603 100644 --- a/wp-includes/pluggable.php +++ b/wp-includes/pluggable.php @@ -121,6 +121,8 @@ function get_userdatabylogin($user_login) { if ( $userdata ) return $userdata; + $user_login = $wpdb->escape($user_login); + if ( !$user = $wpdb->get_row("SELECT * FROM $wpdb->users WHERE user_login = '$user_login'") ) return false; diff --git a/wp-includes/plugin.php b/wp-includes/plugin.php index 61580e7..b8bf524 100644 --- a/wp-includes/plugin.php +++ b/wp-includes/plugin.php @@ -1,25 +1,53 @@ <?php -// -// Filter functions, the core of the WP plugin architecture. -// - +/** + * Hooks a function to a specific filter action. + * + * Filters are the hooks that WordPress launches to modify text of various types + * before adding it to the database or sending it to the browser screen. Plugins + * can specify that one or more of its PHP functions is executed to + * modify specific types of text at these times, using the Filter API. + * See the [Plugin API] for a list of filter hooks. + * + * @param string $tag The name of the filter to hook the <tt>$function_to_add</tt> 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 <tt>$function_to_add</tt> is added succesfully to filter <tt>$tag</tt>. How many arguments your function takes. In WordPress 1.5.1+, hooked functions can take extra arguments that are set when the matching <tt>do_action()</tt> or <tt>apply_filters()</tt> call is run. For example, the action <tt>comment_id_not_found</tt> 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; // 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 <tt>$tag</tt> 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 <tt>$tag</a> 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 <tt>$tag</tt> are applied on. + * @param mixed $var,... Additional variables passed to the functions hooked to <tt>$tag</tt>. + * @return string The text in <tt>$string</tt> after all hooked functions are applied to it. + */ function apply_filters($tag, $string) { - global $wp_filter; + global $wp_filter, $merged_filters; - merge_filters($tag); + if ( !isset( $merged_filters[ $tag ] ) ) + merge_filters($tag); if ( !isset($wp_filter[$tag]) ) return $string; + reset( $wp_filter[ $tag ] ); + $args = func_get_args(); do{ @@ -34,37 +62,87 @@ function apply_filters($tag, $string) { 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 + * <em>all</e>. These functions are called for every filter tag. This function + * merges the functions attached to the <em>all</em> hook with the functions + * of a specific hoook defined by <tt>$tag</tt>. + * @param string $tag The filter hook of which the functions should be merged. + */ function merge_filters($tag) { - global $wp_filter; + global $wp_filter, $merged_filters; - if ( isset($wp_filter['all']) ) + 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"); } + $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; + $function_to_remove = serialize($function_to_remove); - unset($GLOBALS['wp_filter'][$tag][$priority][serialize($function_to_remove)]); + $r = isset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]); - return true; -} + unset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]); + unset($GLOBALS['merged_filters'][$tag]); -// -// Action functions -// + return $r; +} +/** + * 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 <tt>$function_to-add</tt> 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 <tt>$tag</tt>. + * It is possible to create new action hooks by simply calling this function, + * specifying the name of the new hook using the <tt>$tag</tt> 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]; @@ -85,19 +163,30 @@ function do_action($tag, $arg = '') { } while ( next($wp_filter[$tag]) ); - 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 <tt>$tag</tt> 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 <tt>$tag</tt> 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 <tt>$tag</tt> + */ function do_action_ref_array($tag, $args) { global $wp_filter, $wp_actions; @@ -120,25 +209,72 @@ function do_action_ref_array($tag, $args) { } +/** + * 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); + return remove_filter($tag, $function_to_remove, $priority, $accepted_args); } // // 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 <tt>wp-content/plugin/sampleplugin/sample.php</tt>, 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 + * <tt>wp-content/plugin/sample.php</tt> 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 <tt>wp-content/plugin/sampleplugin/sample.php</tt>, 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 + * <tt>wp-content/plugin/sample.php</tt> 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); diff --git a/wp-includes/post-template.php b/wp-includes/post-template.php index 94d2876..cee198b 100644 --- a/wp-includes/post-template.php +++ b/wp-includes/post-template.php @@ -80,7 +80,7 @@ function get_the_content($more_link_text = '(more...)', $stripteaser = 0, $more_ $page = count($pages); // give them the highest numbered page that DOES exist $content = $pages[$page-1]; - if ( preg_match('/<!--more(.+?)?-->/', $content, $matches) ) { + if ( preg_match('/<!--more(.*?)?-->/', $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]))); @@ -129,19 +129,23 @@ function get_the_excerpt($fakeit = true) { return apply_filters('get_the_excerpt', $output); } +function has_excerpt( $id = 0 ) { + $post = &get_post( $id ); + return ( !empty( $post->post_excerpt ) ); +} function wp_link_pages($args = '') { - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('before' => '<p>' . __('Pages:'), 'after' => '</p>', 'next_or_number' => 'number', 'nextpagelink' => __('Next page'), - 'previouspagelink' => __('Previous page'), 'pagelink' => '%', 'more_file' => '', 'echo' => 1); - $r = array_merge($defaults, $r); - extract($r); - - global $id, $page, $numpages, $multipage, $more, $pagenow; + $defaults = array( + 'before' => '<p>' . __('Pages:'), 'after' => '</p>', + 'next_or_number' => 'number', 'nextpagelink' => __('Next page'), + 'previouspagelink' => __('Previous page'), 'pagelink' => '%', + 'more_file' => '', 'echo' => 1 + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); + + global $post, $id, $page, $numpages, $multipage, $more, $pagenow; if ( $more_file != '' ) $file = $more_file; else @@ -158,7 +162,7 @@ function wp_link_pages($args = '') { if ( 1 == $i ) { $output .= '<a href="' . get_permalink() . '">'; } else { - if ( '' == get_option('permalink_structure') ) + if ( '' == get_option('permalink_structure') || 'draft' == $post->post_status ) $output .= '<a href="' . get_permalink() . '&page=' . $i . '">'; else $output .= '<a href="' . trailingslashit(get_permalink()) . user_trailingslashit($i, 'single_paged') . '">'; @@ -177,7 +181,7 @@ function wp_link_pages($args = '') { if ( 1 == $i ) { $output .= '<a href="' . get_permalink() . '">' . $previouspagelink . '</a>'; } else { - if ( '' == get_option('permalink_structure') ) + if ( '' == get_option('permalink_structure') || 'draft' == $post->post_status ) $output .= '<a href="' . get_permalink() . '&page=' . $i . '">' . $previouspagelink . '</a>'; else $output .= '<a href="' . trailingslashit(get_permalink()) . user_trailingslashit($i, 'single_paged') . '">' . $previouspagelink . '</a>'; @@ -188,7 +192,7 @@ function wp_link_pages($args = '') { if ( 1 == $i ) { $output .= '<a href="' . get_permalink() . '">' . $nextpagelink . '</a>'; } else { - if ( '' == get_option('permalink_structure') ) + if ( '' == get_option('permalink_structure') || 'draft' == $post->post_status ) $output .= '<a href="' . get_permalink() . '&page=' . $i . '">' . $nextpagelink . '</a>'; else $output .= '<a href="' . trailingslashit(get_permalink()) . user_trailingslashit($i, 'single_paged') . '">' . $nextpagelink . '</a>'; @@ -233,7 +237,7 @@ function the_meta() { continue; $values = array_map('trim', get_post_custom_values($key)); $value = implode($values,', '); - echo "<li><span class='post-meta-key'>$key:</span> $value</li>\n"; + echo apply_filters('the_meta_key', "<li><span class='post-meta-key'>$key:</span> $value</li>\n", $key, $value); } echo "</ul>\n"; } @@ -245,15 +249,14 @@ function the_meta() { // function wp_dropdown_pages($args = '') { - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('depth' => 0, 'child_of' => 0, 'selected' => 0, 'echo' => 1, - 'name' => 'page_id', 'show_option_none' => ''); - $r = array_merge($defaults, $r); - extract($r); + $defaults = array( + 'depth' => 0, 'child_of' => 0, + 'selected' => 0, 'echo' => 1, + 'name' => 'page_id', 'show_option_none' => '' + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); $pages = get_pages($r); $output = ''; @@ -275,14 +278,16 @@ function wp_dropdown_pages($args = '') { } function wp_list_pages($args = '') { - if ( is_array($args) ) - $r = &$args; - else - 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' => '', 'sort_column' => 'menu_order, post_title'); - $r = array_merge($defaults, $r); + $defaults = array( + 'depth' => 0, 'show_date' => '', + 'date_format' => get_option('date_format'), + 'child_of' => 0, 'exclude' => '', + 'title_li' => __('Pages'), 'echo' => 1, + 'authors' => '', 'sort_column' => 'menu_order, post_title' + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); $output = ''; $current_page = 0; @@ -345,7 +350,7 @@ function get_the_attachment_link($id = 0, $fullsize = false, $max_dims = false) $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); diff --git a/wp-includes/post.php b/wp-includes/post.php index 0c0dfb6..9c6929a 100644 --- a/wp-includes/post.php +++ b/wp-includes/post.php @@ -27,23 +27,25 @@ function update_attached_file( $attachment_id, $file ) { function &get_children($args = '', $output = OBJECT) { global $post_cache, $wpdb, $blog_id; - - if ( empty($args) ) { - if ( isset($GLOBALS['post']) ) - $r = array('post_parent' => & $GLOBALS['post']->post_parent); - else + + if ( empty( $args ) ) { + if ( isset( $GLOBALS['post'] ) ) { + $args = 'post_parent=' . (int) $GLOBALS['post']->post_parent; + } else { return false; - } elseif ( is_object($args) ) - $r = array('post_parent' => $post->post_parent); - elseif ( is_numeric($args) ) - $r = array('post_parent' => $args); - elseif ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('numberposts' => -1, 'post_type' => '', 'post_status' => '', 'post_parent' => 0); - $r = array_merge($defaults, $r); + } + } elseif ( is_object( $args ) ) { + $args = 'post_parent=' . (int) $args->post_parent; + } elseif ( is_numeric( $args ) ) { + $args = 'post_parent=' . (int) $args; + } + + $defaults = array( + 'numberposts' => -1, 'post_type' => '', + 'post_status' => '', 'post_parent' => 0 + ); + + $r = wp_parse_args( $args, $defaults ); $children = get_posts( $r ); @@ -74,7 +76,7 @@ function &get_children($args = '', $output = OBJECT) { // get extended entry info (<!--more-->) function get_extended($post) { //Match the new style more links - if ( preg_match('/<!--more(.*?)-->/', $post, $matches) ) { + if ( preg_match('/<!--more(.*?)?-->/', $post, $matches) ) { list($main, $extended) = explode($matches[0], $post, 2); } else { $main = $post; @@ -172,17 +174,19 @@ function get_post_type($post = false) { function get_posts($args) { global $wpdb; - - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('numberposts' => 5, 'offset' => 0, 'category' => 0, - 'orderby' => 'post_date', 'order' => 'DESC', 'include' => '', 'exclude' => '', - 'meta_key' => '', 'meta_value' =>'', 'post_type' => 'post', 'post_status' => 'publish', 'post_parent' => 0); - $r = array_merge($defaults, $r); - extract($r); + + $defaults = array( + 'numberposts' => 5, 'offset' => 0, + 'category' => 0, 'orderby' => 'post_date', + 'order' => 'DESC', 'include' => '', + 'exclude' => '', 'meta_key' => '', + 'meta_value' =>'', 'post_type' => 'post', + 'post_status' => 'publish', 'post_parent' => 0 + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); + $numberposts = (int) $numberposts; $offset = (int) $offset; $category = (int) $category; @@ -225,14 +229,6 @@ function get_posts($args) { if (!empty($exclusions)) $exclusions .= ')'; - $query ="SELECT DISTINCT * FROM $wpdb->posts " ; - $query .= ( empty( $category ) ? "" : ", $wpdb->post2cat " ); - $query .= ( empty( $meta_key ) ? "" : ", $wpdb->postmeta " ); - $query .= " WHERE (post_type = 'post' AND post_status = 'publish') $exclusions $inclusions "; - $query .= ( empty( $category ) ? "" : "AND ($wpdb->posts.ID = $wpdb->post2cat.post_id AND $wpdb->post2cat.category_id = " . $category. ") " ); - $query .= ( empty( $meta_key ) | empty($meta_value) ? "" : " AND ($wpdb->posts.ID = $wpdb->postmeta.post_id AND $wpdb->postmeta.meta_key = '$meta_key' AND $wpdb->postmeta.meta_value = '$meta_value' )" ); - $query .= " GROUP BY $wpdb->posts.ID ORDER BY " . $orderby . " " . $order . " LIMIT " . $offset . ',' . $numberposts; - $query = "SELECT DISTINCT * FROM $wpdb->posts "; $query .= empty( $category ) ? '' : ", $wpdb->post2cat "; $query .= empty( $meta_key ) ? '' : ", $wpdb->postmeta "; @@ -443,8 +439,8 @@ function wp_delete_post($postid = 0) { $wp_rewrite->flush_rules(); } - do_action('post_deleted', $postid); - + do_action('deleted_post', $postid); + return $post; } @@ -653,7 +649,7 @@ function wp_insert_post($postarr = array()) { $wpdb->query( "UPDATE $wpdb->posts SET post_name = '$post_name' WHERE ID = '$post_ID'" ); } - wp_set_post_categories($post_ID, $post_category); + wp_set_post_categories( $post_ID, $post_category ); if ( 'page' == $post_type ) { clean_page_cache($post_ID); @@ -1066,16 +1062,17 @@ function get_page_uri($page_id) { function &get_pages($args = '') { global $wpdb; - - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); - - $defaults = array('child_of' => 0, 'sort_order' => 'ASC', 'sort_column' => 'post_title', - 'hierarchical' => 1, 'exclude' => '', 'include' => '', 'meta_key' => '', 'meta_value' => '', 'authors' => ''); - $r = array_merge($defaults, $r); - extract($r); + + $defaults = array( + 'child_of' => 0, 'sort_order' => 'ASC', + 'sort_column' => 'post_title', 'hierarchical' => 1, + 'exclude' => '', 'include' => '', + 'meta_key' => '', 'meta_value' => '', + 'authors' => '' + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r ); $key = md5( serialize( $r ) ); if ( $cache = wp_cache_get( 'get_pages', 'page' ) ) @@ -1568,4 +1565,50 @@ function wp_check_for_changed_slugs($post_id) { return $post_id; } +/** + * This function provides a standardized way to appropriately select on + * the post_status of posts/pages. The function will return a piece of + * SQL code that can be added to a WHERE clause; this SQL is constructed + * to allow all published posts, and all private posts to which the user + * has access. + * + * @param string $post_type currently only supports 'post' or 'page'. + * @return string SQL code that can be added to a where clause. + */ +function get_private_posts_cap_sql($post_type) { + global $user_ID; + $cap = ''; + + // Private posts + if ($post_type == 'post') { + $cap = 'read_private_posts'; + // Private pages + } elseif ($post_type == 'page') { + $cap = 'read_private_pages'; + // Dunno what it is, maybe plugins have their own post type? + } else { + $cap = apply_filters('pub_priv_sql_capability', $cap); + + if (empty($cap)) { + // We don't know what it is, filters don't change anything, + // so set the SQL up to return nothing. + return '1 = 0'; + } + } + + $sql = '(post_status = \'publish\''; + + if (current_user_can($cap)) { + // Does the user have the capability to view private posts? Guess so. + $sql .= ' OR post_status = \'private\''; + } elseif (is_user_logged_in()) { + // Users can view their own private posts. + $sql .= ' OR post_status = \'private\' AND post_author = \'' . $user_ID . '\''; + } + + $sql .= ')'; + + return $sql; +} + ?> diff --git a/wp-includes/query.php b/wp-includes/query.php index 26e1afc..05dc692 100644 --- a/wp-includes/query.php +++ b/wp-includes/query.php @@ -888,6 +888,8 @@ class WP_Query { $groupby = "{$wpdb->posts}.ID";
}
+
+
// Author/user stuff
if ( empty($q['author']) || ($q['author'] == '0') ) {
@@ -1023,7 +1025,7 @@ class WP_Query { $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_settings('posts_per_rss'));
+ $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();
@@ -1062,7 +1064,7 @@ class WP_Query { 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_settings('posts_per_rss');
+ $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);
}
diff --git a/wp-includes/rewrite.php b/wp-includes/rewrite.php index d22d3fc..eb10bf7 100644 --- a/wp-includes/rewrite.php +++ b/wp-includes/rewrite.php @@ -46,11 +46,11 @@ define('EP_ROOT', 64 ); define('EP_COMMENTS', 128 );
define('EP_SEARCH', 256 );
define('EP_CATEGORIES', 512 );
-define('EP_AUTHORS', 1024);
-define('EP_PAGES', 2048);
+define('EP_AUTHORS', 2048);
+define('EP_PAGES', 4096);
//pseudo-places
define('EP_NONE', 0 );
-define('EP_ALL', 255);
+define('EP_ALL', 8191);
//and an endpoint, like /trackback/
function add_rewrite_endpoint($name, $places) {
@@ -62,6 +62,8 @@ function add_rewrite_endpoint($name, $places) { // 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);
@@ -197,6 +199,7 @@ class WP_Rewrite { '([^/]+)',
'([0-9]+)',
'(.+?)',
+ '(.+?)',
'([^/]+)',
'([^/]+)',
'(.+)'
@@ -582,6 +585,16 @@ class WP_Rewrite { 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;
@@ -599,16 +612,6 @@ class WP_Rewrite { $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;
@@ -869,7 +872,7 @@ class WP_Rewrite { if ($this->using_index_permalinks()) {
$this->root = $this->index . '/';
}
- $this->category_base = get_option('category_base');
+ $this->category_base = get_option( 'category_base' );
unset($this->category_structure);
unset($this->author_structure);
unset($this->date_structure);
diff --git a/wp-includes/rss.php b/wp-includes/rss.php index 44005a7..da7bc1b 100644 --- a/wp-includes/rss.php +++ b/wp-includes/rss.php @@ -815,7 +815,8 @@ function parse_w3cdtf ( $date_str ) { else { return -1; } - } +} + function wp_rss ($url, $num_items) { //ini_set("display_errors", false); uncomment to suppress php errors thrown if the feed is not returned. $rss = fetch_rss($url); @@ -832,7 +833,7 @@ function wp_rss ($url, $num_items) { echo "</ul>"; } else { - echo "an error has occured the feed is probably down, try again later."; + echo 'An error has occurred the feed is probably down, try again later.'; } } diff --git a/wp-includes/script-loader.php b/wp-includes/script-loader.php index c4a318a..bc180cf 100644 --- a/wp-includes/script-loader.php +++ b/wp-includes/script-loader.php @@ -11,14 +11,32 @@ class WP_Scripts { function default_scripts() { $this->add( 'dbx', '/wp-includes/js/dbx.js', false, '2.05' ); + $this->add( 'fat', '/wp-includes/js/fat.js', false, '1.0-RC1_3660' ); + $this->add( 'sack', '/wp-includes/js/tw-sack.js', false, '1.6.1' ); - $this->add( 'quicktags', '/wp-includes/js/quicktags.js', false, '3517' ); + + $this->add( 'quicktags', '/wp-includes/js/quicktags.js', false, '3958' ); + $this->localize( 'quicktags', 'quicktagsL10n', array( + 'quickLinks' => __('(Quick Links)'), + 'wordLookup' => __('Enter a word to look up:'), + 'dictionaryLookup' => attribute_escape(__('Dictionary lookup')), + 'lookup' => attribute_escape(__('lookup')), + 'closeAllOpenTags' => attribute_escape(__('Close all open tags')), + 'closeTags' => attribute_escape(__('close tags')), + 'enterURL' => __('Enter the URL'), + 'enterImageURL' => __('Enter the URL of the image'), + 'enterImageDescription' => __('Enter a description of the image') + ) ); + $this->add( 'colorpicker', '/wp-includes/js/colorpicker.js', false, '3517' ); + $this->add( 'tiny_mce', '/wp-includes/js/tinymce/tiny_mce_gzip.php', false, '20070326' ); $mce_config = apply_filters('tiny_mce_config_url', '/wp-includes/js/tinymce/tiny_mce_config.php'); $this->add( 'wp_tiny_mce', $mce_config, array('tiny_mce'), '20070225' ); - $this->add( 'prototype', '/wp-includes/js/prototype.js', false, '1.5.0-0'); + + $this->add( 'prototype', '/wp-includes/js/prototype.js', false, '1.5.1'); + $this->add( 'autosave', '/wp-includes/js/autosave.js', array('prototype', 'sack'), '20070306'); $this->localize( 'autosave', 'autosaveL10n', array( 'autosaveInterval' => apply_filters('autosave_interval', '120'), @@ -27,6 +45,7 @@ class WP_Scripts { 'requestFile' => get_option( 'siteurl' ) . '/wp-admin/admin-ajax.php', 'savingText' => __('Saving Draft...') ) ); + $this->add( 'wp-ajax', '/wp-includes/js/wp-ajax.js', array('prototype'), '20070306'); $this->localize( 'wp-ajax', 'WPAjaxL10n', array( 'defaultUrl' => get_option( 'siteurl' ) . '/wp-admin/admin-ajax.php', @@ -34,21 +53,27 @@ class WP_Scripts { 'strangeText' => __("Something strange happened. Try refreshing the page."), 'whoaText' => __("Slow down, I'm still sending your data!") ) ); - $this->add( 'listman', '/wp-includes/js/list-manipulation.js', array('wp-ajax', 'fat'), '20070306'); + + $this->add( 'listman', '/wp-includes/js/list-manipulation.js', array('wp-ajax', 'fat'), '20070306' ); $this->localize( 'listman', 'listManL10n', array( 'jumpText' => __('Jump to new item'), 'delText' => __('Are you sure you want to delete this %thing%?') ) ); - $this->add( 'scriptaculous-root', '/wp-includes/js/scriptaculous/wp-scriptaculous.js', array('prototype'), '1.7.0'); - $this->add( 'scriptaculous-builder', '/wp-includes/js/scriptaculous/builder.js', array('scriptaculous-root'), '1.7.0'); - $this->add( 'scriptaculous-dragdrop', '/wp-includes/js/scriptaculous/dragdrop.js', array('scriptaculous-builder', 'scriptaculous-effects'), '1.7.0'); - $this->add( 'scriptaculous-effects', '/wp-includes/js/scriptaculous/effects.js', array('scriptaculous-root'), '1.7.0'); - $this->add( 'scriptaculous-slider', '/wp-includes/js/scriptaculous/slider.js', array('scriptaculous-effects'), '1.7.0'); - $this->add( 'scriptaculous-controls', '/wp-includes/js/scriptaculous/controls.js', array('scriptaculous-root'), '1.7.0'); - $this->add( 'scriptaculous', '', array('scriptaculous-dragdrop', 'scriptaculous-slider', 'scriptaculous-controls'), '1.7.0'); + + $this->add( 'scriptaculous-root', '/wp-includes/js/scriptaculous/wp-scriptaculous.js', array('prototype'), '1.7.1-b2'); + $this->add( 'scriptaculous-builder', '/wp-includes/js/scriptaculous/builder.js', array('scriptaculous-root'), '1.7.1-b2'); + $this->add( 'scriptaculous-dragdrop', '/wp-includes/js/scriptaculous/dragdrop.js', array('scriptaculous-builder', 'scriptaculous-effects'), '1.7.1-b2'); + $this->add( 'scriptaculous-effects', '/wp-includes/js/scriptaculous/effects.js', array('scriptaculous-root'), '1.7.1-b2'); + $this->add( 'scriptaculous-slider', '/wp-includes/js/scriptaculous/slider.js', array('scriptaculous-effects'), '1.7.1-b2'); + $this->add( 'scriptaculous-sound', '/wp-includes/js/scriptaculous/sound.js', array( 'scriptaculous-root' ), '1.7.1-b2' ); + $this->add( 'scriptaculous-controls', '/wp-includes/js/scriptaculous/controls.js', array('scriptaculous-root'), '1.7.1-b2'); + $this->add( 'scriptaculous', '', array('scriptaculous-dragdrop', 'scriptaculous-slider', 'scriptaculous-controls'), '1.7.1-b2'); + $this->add( 'cropper', '/wp-includes/js/crop/cropper.js', array('scriptaculous-dragdrop'), '20070118'); - $this->add( 'jquery', '/wp-includes/js/jquery/jquery.js', false, '1.1.1'); - $this->add( 'interface', '/wp-includes/js/jquery/interface.js', array('jquery'), '1.1.1'); + + $this->add( 'jquery', '/wp-includes/js/jquery/jquery.js', false, '1.1.2'); + $this->add( 'interface', '/wp-includes/js/jquery/interface.js', array('jquery'), '1.2'); + if ( is_admin() ) { global $pagenow; $man = false; @@ -67,7 +92,7 @@ class WP_Scripts { break; endswitch; if ( $man ) { - $this->add( 'dbx-admin-key', '/wp-admin/dbx-admin-key.js', array('dbx'), '20070306' ); + $this->add( 'dbx-admin-key', '/wp-admin/dbx-admin-key.js', array('dbx'), '20070417' ); $this->localize( 'dbx-admin-key', 'dbxL10n', array( 'manager' => $man, 'open' => __('open'), @@ -78,14 +103,14 @@ class WP_Scripts { 'toggleKey' => __(', or press the enter key to %toggle% it'), ) ); } - $this->add( 'ajaxcat', '/wp-admin/cat.js', array('listman'), '20070306' ); + $this->add( 'ajaxcat', '/wp-admin/cat.js', array('listman'), '20070417' ); $this->localize( 'ajaxcat', 'catL10n', array( 'add' => attribute_escape(__('Add')), 'how' => __('Separate multiple categories with commas.') ) ); $this->add( 'admin-categories', '/wp-admin/categories.js', array('listman'), '3684' ); $this->add( 'admin-custom-fields', '/wp-admin/custom-fields.js', array('listman'), '3733' ); - $this->add( 'admin-comments', '/wp-admin/edit-comments.js', array('listman'), '3847' ); + $this->add( 'admin-comments', '/wp-admin/edit-comments.js', array('listman'), '20070327' ); $this->add( 'admin-users', '/wp-admin/users.js', array('listman'), '4583' ); $this->add( 'xfn', '/wp-admin/xfn.js', false, '3517' ); $this->add( 'upload', '/wp-admin/upload.js', array('prototype'), '20070306' ); @@ -150,6 +175,12 @@ class WP_Scripts { if ( isset($this->args[$handle]) ) $ver .= '&' . $this->args[$handle]; $src = 0 === strpos($this->scripts[$handle]->src, 'http://') ? $this->scripts[$handle]->src : get_option( 'siteurl' ) . $this->scripts[$handle]->src; + $src = $this->scripts[$handle]->src; + + if (!preg_match('|^https?://|', $src)) { + $src = get_option('siteurl') . $src; + } + $src = add_query_arg('ver', $ver, $src); $src = clean_url(apply_filters( 'script_loader_src', $src )); echo "<script type='text/javascript' src='$src'></script>\n"; diff --git a/wp-includes/theme.php b/wp-includes/theme.php index 2a7ac8c..c251935 100644 --- a/wp-includes/theme.php +++ b/wp-includes/theme.php @@ -56,6 +56,21 @@ function get_template_directory_uri() { } function get_theme_data( $theme_file ) { + $themes_allowed_tags = array( + 'a' => array( + 'href' => array(),'title' => array() + ), + 'abbr' => array( + 'title' => array() + ), + 'acronym' => array( + 'title' => array() + ), + 'code' => array(), + 'em' => array(), + 'strong' => array() + ); + $theme_data = implode( '', file( $theme_file ) ); $theme_data = str_replace ( '\r', '\n', $theme_data ); preg_match( '|Theme Name:(.*)|i', $theme_data, $theme_name ); @@ -64,26 +79,28 @@ function get_theme_data( $theme_file ) { preg_match( '|Author:(.*)|i', $theme_data, $author_name ); preg_match( '|Author URI:(.*)|i', $theme_data, $author_uri ); preg_match( '|Template:(.*)|i', $theme_data, $template ); + if ( preg_match( '|Version:(.*)|i', $theme_data, $version ) ) - $version = trim( $version[1] ); + $version = wp_kses( trim( $version[1] ), $themes_allowed_tags ); else - $version =''; + $version = ''; + if ( preg_match('|Status:(.*)|i', $theme_data, $status) ) - $status = trim($status[1]); + $status = wp_kses( trim( $status[1] ), $themes_allowed_tags ); else $status = 'publish'; - - $description = wptexturize( trim( $description[1] ) ); - - $name = $theme_name[1]; - $name = trim( $name ); - $theme = $name; - $theme_uri = trim( $theme_uri[1] ); - - if ( '' == $author_uri[1] ) { - $author = trim( $author_name[1] ); + + $name = $theme = wp_kses( trim( $theme_name[1] ), $themes_allowed_tags ); + $theme_uri = clean_url( trim( $theme_uri[1] ) ); + $description = wptexturize( wp_kses( trim( $description[1] ), $themes_allowed_tags ) ); + $template = wp_kses( trim( $template[1] ), $themes_allowed_tags ); + + $author_uri = clean_url( trim( $author_uri[1] ) ); + + if ( empty( $author_uri[1] ) ) { + $author = wp_kses( trim( $author_name[1] ), $themes_allowed_tags ); } else { - $author = '<a href="' . trim( $author_uri[1] ) . '" title="' . __('Visit author homepage') . '">' . trim( $author_name[1] ) . '</a>'; + $author = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $author_uri, __( 'Visit author homepage' ), wp_kses( trim( $author_name[1] ), $themes_allowed_tags ) ); } return array( 'Name' => $name, 'Title' => $theme, 'URI' => $theme_uri, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => $template[1], 'Status' => $status ); @@ -163,6 +180,7 @@ function get_themes() { $template = $theme_data['Template']; $stylesheet = dirname($theme_file); + $screenshot = false; foreach ( array('png', 'gif', 'jpg', 'jpeg') as $ext ) { if (file_exists("$theme_root/$stylesheet/screenshot.$ext")) { $screenshot = "screenshot.$ext"; diff --git a/wp-includes/user.php b/wp-includes/user.php index 14de35a..ca4006b 100644 --- a/wp-includes/user.php +++ b/wp-includes/user.php @@ -10,7 +10,7 @@ function get_profile($field, $user = false) { function get_usernumposts($userid) { global $wpdb; $userid = (int) $userid; - return $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_author = '$userid' AND post_type = 'post' AND post_status = 'publish'"); + return $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_author = '$userid' AND post_type = 'post' AND " . get_private_posts_cap_sql('post')); } // TODO: xmlrpc only. Maybe move to xmlrpc.php. diff --git a/wp-includes/vars.php b/wp-includes/vars.php index 0f749be..010d174 100644 --- a/wp-includes/vars.php +++ b/wp-includes/vars.php @@ -35,4 +35,50 @@ $is_IE = ( $is_macIE || $is_winIE ); $is_apache = ((strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) || (strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false)) ? true : false; $is_IIS = (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false) ? true : false; +$wp_header_to_desc = apply_filters( 'wp_header_to_desc_array', array( + 100 => 'Continue', + 101 => 'Switching Protocols', + + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 307 => 'Temporary Redirect', + + 400 => 'Bad Request', + 401 => 'Unauthorized', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported' +) ); + ?> diff --git a/wp-includes/version.php b/wp-includes/version.php index 5355c5c..ca88592 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -3,6 +3,6 @@ // This holds the version number in a separate file so we can bump it without cluttering the SVN $wp_version = 'wordpress-mu-1.2.1'; // Let's just avoid confusion -$wp_db_version = 4860; +$wp_db_version = 5200; ?> |