diff options
| author | donncha <donncha@7be80a69-a1ef-0310-a953-fb0f7c49ff36> | 2007-10-12 16:21:15 +0000 |
|---|---|---|
| committer | donncha <donncha@7be80a69-a1ef-0310-a953-fb0f7c49ff36> | 2007-10-12 16:21:15 +0000 |
| commit | 3a4570b0fc8b3d6339bef71d17d7701554e0bbf7 (patch) | |
| tree | 2a06e5261263c68d8afd95a6328879dc289cb909 /wp-includes | |
| parent | b83c34a7010faee0223f6037025c350da12e05e6 (diff) | |
| download | wordpress-mu-3a4570b0fc8b3d6339bef71d17d7701554e0bbf7.tar.gz wordpress-mu-3a4570b0fc8b3d6339bef71d17d7701554e0bbf7.tar.xz wordpress-mu-3a4570b0fc8b3d6339bef71d17d7701554e0bbf7.zip | |
Merge with WP 2.3 - testing use only!
Move pluggable functions out of wpmu-functions and into pluggable.php, fixes #439
git-svn-id: http://svn.automattic.com/wordpress-mu/trunk@1069 7be80a69-a1ef-0310-a953-fb0f7c49ff36
Diffstat (limited to 'wp-includes')
78 files changed, 10995 insertions, 5845 deletions
diff --git a/wp-includes/atomlib.php b/wp-includes/atomlib.php new file mode 100644 index 0000000..a518908 --- /dev/null +++ b/wp-includes/atomlib.php @@ -0,0 +1,313 @@ +<?php +/* + * atomlib.php - Atom Syndication Format PHP Library + * + * Project: http://code.google.com/p/phpatomlib/ + * + * Author: Elias Torres <elias@torrez.us> + * Version: 0.4 + * + */ + +class AtomFeed { + var $links = array(); + var $categories = array(); + + var $entries = array(); +} + +class AtomEntry { + var $links = array(); + var $categories = array(); +} + +class AtomParser { + + var $NS = 'http://www.w3.org/2005/Atom'; + var $ATOM_CONTENT_ELEMENTS = array('content','summary','title','subtitle','rights'); + var $ATOM_SIMPLE_ELEMENTS = array('id','updated','published','draft'); + + var $debug = false; + + var $depth = 0; + var $indent = 2; + var $in_content; + var $ns_contexts = array(); + var $ns_decls = array(); + var $content_ns_decls = array(); + var $content_ns_contexts = array(); + var $is_xhtml = false; + var $is_html = false; + var $is_text = true; + var $skipped_div = false; + + var $FILE = "php://input"; + + var $feed; + var $current; + + function AtomParser() { + + $this->feed = new AtomFeed(); + $this->current = null; + $this->map_attrs_func = create_function('$k,$v', 'return "$k=\"$v\"";'); + $this->map_xmlns_func = create_function('$p,$n', '$xd = "xmlns"; if(strlen($n[0])>0) $xd .= ":{$n[0]}"; return "{$xd}=\"{$n[1]}\"";'); + } + + function _p($msg) { + if($this->debug) { + print str_repeat(" ", $this->depth * $this->indent) . $msg ."\n"; + } + } + + function error_handler($log_level, $log_text, $error_file, $error_line) { + $this->error = $log_text; + } + + function parse() { + + set_error_handler(array(&$this, 'error_handler')); + + array_unshift($this->ns_contexts, array()); + + $parser = xml_parser_create_ns(); + xml_set_object($parser, $this); + xml_set_element_handler($parser, "start_element", "end_element"); + xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); + xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0); + xml_set_character_data_handler($parser, "cdata"); + xml_set_default_handler($parser, "_default"); + xml_set_start_namespace_decl_handler($parser, "start_ns"); + xml_set_end_namespace_decl_handler($parser, "end_ns"); + + $this->content = ''; + + $ret = true; + + $fp = fopen($this->FILE, "r"); + while ($data = fread($fp, 4096)) { + if($this->debug) $this->content .= $data; + + if(!xml_parse($parser, $data, feof($fp))) { + trigger_error(sprintf(__('XML error: %s at line %d')."\n", + xml_error_string(xml_get_error_code($xml_parser)), + xml_get_current_line_number($xml_parser))); + $ret = false; + break; + } + } + fclose($fp); + + xml_parser_free($parser); + + restore_error_handler(); + + return $ret; + } + + function start_element($parser, $name, $attrs) { + + $tag = array_pop(split(":", $name)); + + switch($name) { + case $this->NS . ':feed': + $this->current = $this->feed; + break; + case $this->NS . ':entry': + $this->current = new AtomEntry(); + break; + }; + + $this->_p("start_element('$name')"); + #$this->_p(print_r($this->ns_contexts,true)); + #$this->_p('current(' . $this->current . ')'); + + array_unshift($this->ns_contexts, $this->ns_decls); + + $this->depth++; + + if(!empty($this->in_content)) { + + $this->content_ns_decls = array(); + + if($this->is_html || $this->is_text) + trigger_error("Invalid content in element found. Content must not be of type text or html if it contains markup."); + + $attrs_prefix = array(); + + // resolve prefixes for attributes + foreach($attrs as $key => $value) { + $with_prefix = $this->ns_to_prefix($key, true); + $attrs_prefix[$with_prefix[1]] = $this->xml_escape($value); + } + + $attrs_str = join(' ', array_map($this->map_attrs_func, array_keys($attrs_prefix), array_values($attrs_prefix))); + if(strlen($attrs_str) > 0) { + $attrs_str = " " . $attrs_str; + } + + $with_prefix = $this->ns_to_prefix($name); + + if(!$this->is_declared_content_ns($with_prefix[0])) { + array_push($this->content_ns_decls, $with_prefix[0]); + } + + $xmlns_str = ''; + if(count($this->content_ns_decls) > 0) { + array_unshift($this->content_ns_contexts, $this->content_ns_decls); + $xmlns_str .= join(' ', array_map($this->map_xmlns_func, array_keys($this->content_ns_contexts[0]), array_values($this->content_ns_contexts[0]))); + if(strlen($xmlns_str) > 0) { + $xmlns_str = " " . $xmlns_str; + } + } + + array_push($this->in_content, array($tag, $this->depth, "<". $with_prefix[1] ."{$xmlns_str}{$attrs_str}" . ">")); + + } else if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS) || in_array($tag, $this->ATOM_SIMPLE_ELEMENTS)) { + $this->in_content = array(); + $this->is_xhtml = $attrs['type'] == 'xhtml'; + $this->is_html = $attrs['type'] == 'html' || $attrs['type'] == 'text/html'; + $this->is_text = !in_array('type',array_keys($attrs)) || $attrs['type'] == 'text'; + $type = $this->is_xhtml ? 'XHTML' : ($this->is_html ? 'HTML' : ($this->is_text ? 'TEXT' : $attrs['type'])); + + if(in_array('src',array_keys($attrs))) { + $this->current->$tag = $attrs; + } else { + array_push($this->in_content, array($tag,$this->depth, $type)); + } + } else if($tag == 'link') { + array_push($this->current->links, $attrs); + } else if($tag == 'category') { + array_push($this->current->categories, $attrs); + } + + $this->ns_decls = array(); + } + + function end_element($parser, $name) { + + $tag = array_pop(split(":", $name)); + + $ccount = count($this->in_content); + + # if we are *in* content, then let's proceed to serialize it + if(!empty($this->in_content)) { + # if we are ending the original content element + # then let's finalize the content + if($this->in_content[0][0] == $tag && + $this->in_content[0][1] == $this->depth) { + $origtype = $this->in_content[0][2]; + array_shift($this->in_content); + $newcontent = array(); + foreach($this->in_content as $c) { + if(count($c) == 3) { + array_push($newcontent, $c[2]); + } else { + if($this->is_xhtml || $this->is_text) { + array_push($newcontent, $this->xml_escape($c)); + } else { + array_push($newcontent, $c); + } + } + } + if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS)) { + $this->current->$tag = array($origtype, join('',$newcontent)); + } else { + $this->current->$tag = join('',$newcontent); + } + $this->in_content = array(); + } else if($this->in_content[$ccount-1][0] == $tag && + $this->in_content[$ccount-1][1] == $this->depth) { + $this->in_content[$ccount-1][2] = substr($this->in_content[$ccount-1][2],0,-1) . "/>"; + } else { + # else, just finalize the current element's content + $endtag = $this->ns_to_prefix($name); + array_push($this->in_content, array($tag, $this->depth, "</$endtag[1]>")); + } + } + + array_shift($this->ns_contexts); + + $this->depth--; + + if($name == ($this->NS . ':entry')) { + array_push($this->feed->entries, $this->current); + $this->current = null; + } + + $this->_p("end_element('$name')"); + } + + function start_ns($parser, $prefix, $uri) { + $this->_p("starting: " . $prefix . ":" . $uri); + array_push($this->ns_decls, array($prefix,$uri)); + } + + function end_ns($parser, $prefix) { + $this->_p("ending: #" . $prefix . "#"); + } + + function cdata($parser, $data) { + $this->_p("data: #" . str_replace(array("\n"), array("\\n"), trim($data)) . "#"); + if(!empty($this->in_content)) { + array_push($this->in_content, $data); + } + } + + function _default($parser, $data) { + # when does this gets called? + } + + + function ns_to_prefix($qname, $attr=false) { + # split 'http://www.w3.org/1999/xhtml:div' into ('http','//www.w3.org/1999/xhtml','div') + $components = split(":", $qname); + + # grab the last one (e.g 'div') + $name = array_pop($components); + + if(!empty($components)) { + # re-join back the namespace component + $ns = join(":",$components); + foreach($this->ns_contexts as $context) { + foreach($context as $mapping) { + if($mapping[1] == $ns && strlen($mapping[0]) > 0) { + return array($mapping, "$mapping[0]:$name"); + } + } + } + } + + if($attr) { + return array(null, $name); + } else { + foreach($this->ns_contexts as $context) { + foreach($context as $mapping) { + if(strlen($mapping[0]) == 0) { + return array($mapping, $name); + } + } + } + } + } + + function is_declared_content_ns($new_mapping) { + foreach($this->content_ns_contexts as $context) { + foreach($context as $mapping) { + if($new_mapping == $mapping) { + return true; + } + } + } + return false; + } + + function xml_escape($string) + { + return str_replace(array('&','"',"'",'<','>'), + array('&','"',''','<','>'), + $string ); + } +} + +?> diff --git a/wp-includes/author-template.php b/wp-includes/author-template.php index cc67faf..57bc3a9 100644 --- a/wp-includes/author-template.php +++ b/wp-includes/author-template.php @@ -1,86 +1,191 @@ <?php +/** + * Get the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @param string $deprecated Deprecated. + * @return string The author's display name. + */ function get_the_author($deprecated = '') { global $authordata; return apply_filters('the_author', $authordata->display_name); } -// Using echo = false is deprecated. Use get_the_author instead. +/** + * Echo the name of the author of the current post in the Loop. + * @see get_the_author() + * @param string $deprecated Deprecated. + * @param string $deprecated_echo Echo the string or return it. Deprecated, use get_the_author(). + * @return string The author's display name, from get_the_author(). + */ function the_author($deprecated = '', $deprecated_echo = true) { if ( $deprecated_echo ) echo get_the_author(); return get_the_author(); } +/** + * Get the description of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's description. + */ function get_the_author_description() { global $authordata; return $authordata->description; } + +/** + * Echo the description of the author of the current post in the Loop. + * @see get_the_author_description() + * @return null + */ function the_author_description() { echo get_the_author_description(); } +/** + * Get the login name of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's login name (username). + */ function get_the_author_login() { global $authordata; return $authordata->user_login; } +/** + * Echo the login name of the author of the current post in the Loop. + * @see get_the_author_login() + * @return null + */ function the_author_login() { echo get_the_author_login(); } +/** + * Get the first name of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's first name. + */ function get_the_author_firstname() { global $authordata; return $authordata->first_name; } + +/** + * Echo the first name of the author of the current post in the Loop. + * @see get_the_author_firstname() + * @return null + */ function the_author_firstname() { echo get_the_author_firstname(); } +/** + * Get the last name of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's last name. + */ function get_the_author_lastname() { global $authordata; return $authordata->last_name; } +/** + * Echo the last name of the author of the current post in the Loop. + * @see get_the_author_lastname() + * @return null + */ function the_author_lastname() { echo get_the_author_lastname(); } +/** + * Get the nickname of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's nickname. + */ function get_the_author_nickname() { global $authordata; return $authordata->nickname; } +/** + * Echo the nickname of the author of the current post in the Loop. + * @see get_the_author_nickname() + * @return null + */ function the_author_nickname() { echo get_the_author_nickname(); } +/** + * Get the ID of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return int The author's ID. + */ function get_the_author_ID() { global $authordata; - return $authordata->ID; + return (int) $authordata->ID; } + +/** + * Echo the ID of the author of the current post in the Loop. + * @see get_the_author_ID() + * @return null + */ function the_author_ID() { echo get_the_author_id(); } +/** + * Get the email of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's username. + */ function get_the_author_email() { global $authordata; return $authordata->user_email; } +/** + * Echo the email of the author of the current post in the Loop. + * @see get_the_author_email() + * @return null + */ function the_author_email() { echo apply_filters('the_author_email', get_the_author_email() ); } +/** + * Get the URL to the home page of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The URL to the author's page. + */ function get_the_author_url() { global $authordata; + + if ( 'http://' == $authordata->user_url ) + return ''; + return $authordata->user_url; } +/** + * Echo the URL to the home page of the author of the current post in the Loop. + * @see get_the_author_url() + * @return null + */ function the_author_url() { echo get_the_author_url(); } +/** + * If the author has a home page set, echo an HTML link, otherwise just echo the author's name. + * @see get_the_author_url() + * @see the_author() + * @return null + */ function the_author_link() { if (get_the_author_url()) { echo '<a href="' . get_the_author_url() . '" title="' . sprintf(__("Visit %s's website"), get_the_author()) . '" rel="external">' . get_the_author() . '</a>'; @@ -89,61 +194,129 @@ function the_author_link() { } } +/** + * Get the ICQ number of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's ICQ number. + */ function get_the_author_icq() { global $authordata; return $authordata->icq; } +/** + * Echo the ICQ number of the author of the current post in the Loop. + * @see get_the_author_icq() + * @return null + */ function the_author_icq() { echo get_the_author_icq(); } +/** + * Get the AIM name of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's AIM name. + */ function get_the_author_aim() { global $authordata; return str_replace(' ', '+', $authordata->aim); } +/** + * Echo the AIM name of the author of the current post in the Loop. + * @see get_the_author_aim() + * @return null + */ function the_author_aim() { echo get_the_author_aim(); } +/** + * Get the Yahoo! IM name of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's Yahoo! IM name. + */ function get_the_author_yim() { global $authordata; return $authordata->yim; } +/** + * Echo the Yahoo! IM name of the author of the current post in the Loop. + * @see get_the_author_yim() + * @return null + */ function the_author_yim() { echo get_the_author_yim(); } +/** + * Get the MSN address of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @return string The author's MSN address. + */ function get_the_author_msn() { global $authordata; return $authordata->msn; } +/** + * Echo the MSN address of the author of the current post in the Loop. + * @see get_the_author_msn() + * @return null + */ function the_author_msn() { echo get_the_author_msn(); } +/** + * Get the number of posts by the author of the current post in the Loop. + * @global object $post The current post in the Loop's DB object. + * @see get_usernumposts() + * @return int The number of posts by the author. + */ function get_the_author_posts() { global $post; - $posts = get_usernumposts($post->post_author); - return $posts; + return get_usernumposts($post->post_author); } +/** + * Echo the number of posts by the author of the current post in the Loop. + * @see get_the_author_posts() + * @return null + */ function the_author_posts() { echo get_the_author_posts(); } +/** + * Echo an HTML link to the author page of the author of the current post in the Loop. + * @global object $authordata The current author's DB object. + * @see get_author_posts_url() + * @see get_the_author() + * @return null + */ /* the_author_posts_link() requires no get_, use get_author_posts_url() */ function the_author_posts_link($deprecated = '') { global $authordata; - - echo '<a href="' . get_author_posts_url($authordata->ID, $authordata->user_nicename) . '" title="' . sprintf(__("Posts by %s"), attribute_escape(get_the_author())) . '">' . get_the_author() . '</a>'; -} - + printf( + '<a href="%1$s" title="%2$s">%3$s</a>', + get_author_posts_url( $authordata->ID, $authordata->user_nicename ), + sprintf( __( 'Posts by %s' ), attribute_escape( get_the_author() ) ), + get_the_author() + ); +} + +/** + * Get the URL to the author page of the author of the current post in the Loop. + * @global object $wpdb WordPress database layer. + * @global object $wp_rewrite WP_Rewrite + * @global object $post The current post in the Loop's DB object. + * @return string The URL to the author's page. + */ function get_author_posts_url($author_id, $author_nicename = '') { - global $wpdb, $wp_rewrite, $post, $cache_userdata; + global $wpdb, $wp_rewrite, $post; $auth_ID = (int) $author_id; $link = $wp_rewrite->get_author_permastruct(); @@ -165,44 +338,60 @@ function get_author_posts_url($author_id, $author_nicename = '') { return $link; } -// Get author's preferred display name +/** + * Get the specified author's preferred display name. + * @param int $auth_id The ID of the author. + * @return string The author's display name. + */ function get_author_name( $auth_id ) { $authordata = get_userdata( $auth_id ); - return $authordata->display_name; } +/** + * List all the authors of the blog, with several options available. + * optioncount (boolean) (false): Show the count in parenthesis next to the author's name. + * exclude_admin (boolean) (true): Exclude the 'admin' user that is installed by default. + * show_fullname (boolean) (false): Show their full names. + * hide_empty (boolean) (true): Don't show authors without any posts. + * feed (string) (''): If isn't empty, show links to author's feeds. + * feed_image (string) (''): If isn't empty, use this image to link to feeds. + * echo (boolean) (true): Set to false to return the output, instead of echoing. + * @param array $args The argument array. + * @return null|string The output, if echo is set to false. + */ function wp_list_authors($args = '') { global $wpdb; - - 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); + + $defaults = array( + 'optioncount' => false, 'exclude_admin' => true, + 'show_fullname' => false, 'hide_empty' => true, + 'feed' => '', 'feed_image' => '', 'echo' => true + ); + + $r = wp_parse_args( $args, $defaults ); extract($r, EXTR_SKIP); - + + $return = ''; + // TODO: Move select to get_authors(). $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) { + foreach ((array) $wpdb->get_results("SELECT DISTINCT post_author, COUNT(ID) AS count FROM $wpdb->posts WHERE post_type = 'post' AND " . get_private_posts_cap_sql( 'post' ) . " GROUP BY post_author") as $row) { $author_count[$row->post_author] = $row->count; } foreach ( (array) $authors as $author ) { $author = get_userdata( $author->ID ); $posts = (isset($author_count[$author->ID])) ? $author_count[$author->ID] : 0; - $name = $author->nickname; + $name = $author->display_name; if ( $show_fullname && ($author->first_name != '' && $author->last_name != '') ) $name = "$author->first_name $author->last_name"; if ( !($posts == 0 && $hide_empty) ) - echo "<li>"; + $return .= '<li>'; if ( $posts == 0 ) { if ( !$hide_empty ) $link = $name; @@ -241,8 +430,11 @@ function wp_list_authors($args = '') { } if ( !($posts == 0 && $hide_empty) ) - echo "$link</li>"; + $return .= $link . '</li>'; } + if ( !$echo ) + return $return; + echo $return; } ?> diff --git a/wp-includes/bookmark-template.php b/wp-includes/bookmark-template.php index 79bf8a3..68a2842 100644 --- a/wp-includes/bookmark-template.php +++ b/wp-includes/bookmark-template.php @@ -1,259 +1,14 @@ <?php -/** function wp_get_links() - ** Gets the links associated with category n. - ** Parameters: - ** category (no default) - The category to use. - ** or: - ** a query string - **/ -function wp_get_links($args = '') { - global $wpdb; - - if ( empty($args) ) - return; - - if ( false === strpos($args, '=') ) { - $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; - - return get_links($category, $before, $after, $between, $show_images, $orderby, $show_description, $show_rating, $limit, $show_updated, $echo); -} // end wp_get_links - -/** function get_links() - ** Gets the links associated with category n. - ** Parameters: - ** category (default -1) - The category to use. If no category supplied - ** uses all - ** before (default '') - the html to output before the link - ** after (default '<br />') - the html to output after the link - ** between (default ' ') - the html to output between the link/image - ** and its description. Not used if no image or show_images == true - ** show_images (default true) - whether to show images (if defined). - ** orderby (default 'id') - the order to output the links. E.g. 'id', 'name', - ** 'url', 'description', or 'rating'. Or maybe owner. If you start the - ** name with an underscore the order will be reversed. - ** You can also specify 'rand' as the order which will return links in a - ** random order. - ** show_description (default true) - whether to show the description if - ** show_images=false/not defined . - ** show_rating (default false) - show rating stars/chars - ** limit (default -1) - Limit to X entries. If not specified, all entries - ** are shown. - ** show_updated (default 0) - whether to show last updated timestamp - ** echo (default true) - whether to echo the results, or return them instead - */ -function get_links($category = -1, - $before = '', - $after = '<br />', - $between = ' ', - $show_images = true, - $orderby = 'name', - $show_description = true, - $show_rating = false, - $limit = -1, - $show_updated = 1, - $echo = true) { - - global $wpdb; - - $order = 'ASC'; - if ( substr($orderby, 0, 1) == '_' ) { - $order = 'DESC'; - $orderby = substr($orderby, 1); - } - - if ( $category == -1 ) //get_bookmarks uses '' to signify all categories - $category = ''; - - $results = get_bookmarks("category=$category&orderby=$orderby&order=$order&show_updated=$show_updated&limit=$limit"); - - if ( !$results ) - return; - - $output = ''; - - foreach ( (array) $results as $row ) { - if ( !isset($row->recently_updated) ) - $row->recently_updated = false; - $output .= $before; - if ( $show_updated && $row->recently_updated ) - $output .= get_option('links_recently_updated_prepend'); - $the_link = '#'; - if ( !empty($row->link_url) ) - $the_link = clean_url($row->link_url); - $rel = $row->link_rel; - if ( '' != $rel ) - $rel = ' rel="' . $rel . '"'; - - $desc = attribute_escape($row->link_description); - $name = attribute_escape($row->link_name); - $title = $desc; - - if ( $show_updated ) - if (substr($row->link_updated_f, 0, 2) != '00') - $title .= ' ('.__('Last updated') . ' ' . date(get_option('links_updated_date_format'), $row->link_updated_f + (get_option('gmt_offset') * 3600)) . ')'; - - if ( '' != $title ) - $title = ' title="' . $title . '"'; - - $alt = ' alt="' . $name . '"'; - - $target = $row->link_target; - if ( '' != $target ) - $target = ' target="' . $target . '"'; - - $output .= '<a href="' . $the_link . '"' . $rel . $title . $target. '>'; - - if ( $row->link_image != null && $show_images ) { - if ( strpos($row->link_image, 'http') !== false ) - $output .= "<img src=\"$row->link_image\" $alt $title />"; - else // If it's a relative path - $output .= "<img src=\"" . get_option('siteurl') . "$row->link_image\" $alt $title />"; - } else { - $output .= $name; - } - - $output .= '</a>'; - - if ( $show_updated && $row->recently_updated ) - $output .= get_option('links_recently_updated_append'); - - if ( $show_description && '' != $desc ) - $output .= $between . $desc; - - if ($show_rating) { - $output .= $between . get_linkrating($row); - } - - $output .= "$after\n"; - } // end while - - if ( !$echo ) - return $output; - echo $output; -} - -function get_linkrating($link) { - return apply_filters('link_rating', $link->link_rating); -} - -/** function get_linkcatname() - ** Gets the name of category n. - ** Parameters: id (default 0) - The category to get. If no category supplied - ** uses 0 - */ -function get_linkcatname($id = 0) { - $id = (int) $id; - - if ( empty($id) ) - return ''; - - $cats = wp_get_link_cats($id); - - if ( empty($cats) || ! is_array($cats) ) - return ''; - - $cat_id = (int) $cats[0]; // Take the first cat. - - $cat = get_category($cat_id); - return $cat->cat_name; -} - -/** function links_popup_script() - ** This function contributed by Fullo -- http://sprite.csr.unibo.it/fullo/ - ** Show the link to the links popup and the number of links - ** Parameters: - ** text (default Links) - the text of the link - ** width (default 400) - the width of the popup window - ** height (default 400) - the height of the popup window - ** file (default linkspopup.php) - the page to open in the popup window - ** count (default true) - the number of links in the db - */ -function links_popup_script($text = 'Links', $width=400, $height=400, $file='links.all.php', $count = true) { - if ( $count ) - $counts = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->links"); - - $javascript = "<a href=\"#\" onclick=\"javascript:window.open('$file?popup=1', '_blank', 'width=$width,height=$height,scrollbars=yes,status=no'); return false\">"; - $javascript .= $text; - - if ( $count ) - $javascript .= " ($counts)"; - - $javascript .= "</a>\n\n"; - echo $javascript; -} - - -/* - * function get_links_list() - * - * added by Dougal - * - * Output a list of all links, listed by category, using the - * settings in $wpdb->linkcategories and output it as a nested - * HTML unordered list. - * - * Parameters: - * order (default 'name') - Sort link categories by 'name' or 'id' - * hide_if_empty (default true) - Supress listing empty link categories - */ -function get_links_list($order = 'name', $hide_if_empty = 'obsolete') { - $order = strtolower($order); - - // Handle link category sorting - $direction = 'ASC'; - if ( '_' == substr($order,0,1) ) { - $direction = 'DESC'; - $order = substr($order,1); - } - - if ( !isset($direction) ) - $direction = ''; - - $cats = get_categories("type=link&orderby=$order&order=$direction&hierarchical=0"); - - // Display each category - if ( $cats ) { - foreach ( (array) $cats as $cat ) { - // Handle each category. - - // Display the category name - echo ' <li id="linkcat-' . $cat->cat_ID . '" class="linkcat"><h2>' . $cat->cat_name . "</h2>\n\t<ul>\n"; - // Call get_links() with all the appropriate params - get_links($cat->cat_ID, '<li>', "</li>", "\n", true, 'name', false); - - // Close the last category - echo "\n\t</ul>\n</li>\n"; - } - } -} - 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" + ); - $defaults = array('show_updated' => 0, 'show_description' => 0, 'show_images' => 1, 'before' => '<li>', - 'after' => '</li>', 'between' => "\n"); - $r = array_merge($defaults, $r); - extract($r, EXTR_SKIP); + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); foreach ( (array) $bookmarks as $bookmark ) { if ( !isset($bookmark->recently_updated) ) @@ -270,8 +25,8 @@ function _walk_bookmarks($bookmarks, $args = '' ) { if ( '' != $rel ) $rel = ' rel="' . $rel . '"'; - $desc = attribute_escape(apply_filters('link_description', $bookmark->link_description)); - $name = attribute_escape(apply_filters('link_title', $bookmark->link_name)); + $desc = attribute_escape(sanitize_bookmark_field('link_description', $bookmark->link_description, $bookmark->link_id, 'display')); + $name = attribute_escape(sanitize_bookmark_field('link_name', $bookmark->link_name, $bookmark->link_id, 'display')); $title = $desc; if ( $show_updated ) @@ -308,11 +63,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 @@ -320,32 +75,34 @@ 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, EXTR_SKIP); + $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, EXTR_SKIP ); $output = ''; if ( $categorize ) { //Split the bookmarks into ul's for each category - $cats = get_categories("type=link&category_name=$category_name&include=$category&orderby=$category_orderby&order=$category_order&hierarchical=0"); + $cats = get_terms('link_category', "category_name=$category_name&include=$category&orderby=$category_orderby&order=$category_order&hierarchical=0"); foreach ( (array) $cats as $cat ) { - $params = array_merge($r, array('category'=>$cat->cat_ID)); + $params = array_merge($r, array('category'=>$cat->term_id)); $bookmarks = get_bookmarks($params); if ( empty($bookmarks) ) continue; - $output .= str_replace(array('%id', '%class'), array("linkcat-$cat->cat_ID", $class), $category_before); - $catname = apply_filters( "link_category", $cat->cat_name ); + $output .= str_replace(array('%id', '%class'), array("linkcat-$cat->term_id", $class), $category_before); + $catname = apply_filters( "link_category", $cat->name ); $output .= "$title_before$catname$title_after\n\t<ul>\n"; $output .= _walk_bookmarks($bookmarks, $r); $output .= "\n\t</ul>\n$category_after\n"; diff --git a/wp-includes/bookmark.php b/wp-includes/bookmark.php index aca1e72..a8c1a3f 100644 --- a/wp-includes/bookmark.php +++ b/wp-includes/bookmark.php @@ -1,11 +1,13 @@ <?php -function get_bookmark($bookmark_id, $output = OBJECT) { +function get_bookmark($bookmark_id, $output = OBJECT, $filter = 'raw') { 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); + $link = $wpdb->get_row("SELECT * FROM $wpdb->links WHERE link_id = '$bookmark_id' LIMIT 1"); + $link->link_category = array_unique( wp_get_object_terms($link_id, 'link_category', 'fields=ids') ); + + $link = sanitize_bookmark($link, $filter); if ( $output == OBJECT ) { return $link; @@ -18,6 +20,22 @@ function get_bookmark($bookmark_id, $output = OBJECT) { } } +function get_bookmark_field( $field, $bookmark, $context = 'display' ) { + $bookmark = (int) $bookmark; + $bookmark = get_bookmark( $bookmark ); + + if ( is_wp_error($bookmark) ) + return $bookmark; + + if ( !is_object($bookmark) ) + return ''; + + if ( !isset($bookmark->$field) ) + return ''; + + return sanitize_bookmark_field($field, $bookmark->$field, $bookmark->link_id, $context); +} + // Deprecate function get_link($bookmark_id, $output = OBJECT) { return get_bookmark($bookmark_id, $output); @@ -26,15 +44,16 @@ 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' => '' + ); - $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, EXTR_SKIP); + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); $key = md5( serialize( $r ) ); if ( $cache = wp_cache_get( 'get_bookmarks', 'bookmark' ) ) @@ -75,8 +94,8 @@ function get_bookmarks($args = '') { $exclusions .= ')'; if ( ! empty($category_name) ) { - if ( $cat_id = $wpdb->get_var("SELECT cat_ID FROM $wpdb->categories WHERE cat_name='$category_name' LIMIT 1") ) - $category = $cat_id; + if ( $category = get_term_by('name', $category_name, 'link_category') ) + $category = $category->term_id; } $category_query = ''; @@ -86,15 +105,15 @@ function get_bookmarks($args = '') { if ( count($incategories) ) { foreach ( $incategories as $incat ) { if (empty($category_query)) - $category_query = ' AND ( category_id = ' . intval($incat) . ' '; + $category_query = ' AND ( tt.term_id = ' . intval($incat) . ' '; else - $category_query .= ' OR category_id = ' . intval($incat) . ' '; + $category_query .= ' OR tt.term_id = ' . intval($incat) . ' '; } } } if (!empty($category_query)) { - $category_query .= ')'; - $join = " LEFT JOIN $wpdb->link2cat ON ($wpdb->links.link_id = $wpdb->link2cat.link_id) "; + $category_query .= ") AND taxonomy = 'link_category'"; + $join = " LEFT JOIN $wpdb->term_relationships AS tr ON ($wpdb->links.link_id = tr.object_id) LEFT JOIN $wpdb->term_taxonomy as tt ON tt.term_taxonomy_id = tr.term_taxonomy_id"; } if (get_option('links_recently_updated_time')) { @@ -136,11 +155,72 @@ function get_bookmarks($args = '') { $results = $wpdb->get_results($query); $cache[ $key ] = $results; - wp_cache_add( 'get_bookmarks', $cache, 'bookmark' ); + wp_cache_set( 'get_bookmarks', $cache, 'bookmark' ); return apply_filters('get_bookmarks', $results, $r); } +function sanitize_bookmark($bookmark, $context = 'display') { + $fields = array('link_id', 'link_url', 'link_name', 'link_image', 'link_target', 'link_category', + 'link_description', 'link_visible', 'link_owner', 'link_rating', 'link_updated', + 'link_rel', 'link_notes', 'link_rss', ); + + $do_object = false; + if ( is_object($bookmark) ) + $do_object = true; + + foreach ( $fields as $field ) { + if ( $do_object ) + $bookmark->$field = sanitize_bookmark_field($field, $bookmark->$field, $bookmark->link_id, $context); + else + $bookmark[$field] = sanitize_bookmark_field($field, $bookmark[$field], $bookmark['link_id'], $context); + } + + return $bookmark; +} + +function sanitize_bookmark_field($field, $value, $bookmark_id, $context) { + $int_fields = array('link_id', 'link_rating'); + if ( in_array($field, $int_fields) ) + $value = (int) $value; + + $yesno = array('link_visible'); + if ( in_array($field, $yesno) ) + $value = preg_replace('/[^YNyn]/', '', $value); + + if ( 'link_target' == $field ) { + $targets = array('_top', '_blank'); + if ( ! in_array($value, $targets) ) + $value = ''; + } + + if ( 'raw' == $context ) + return $value; + + if ( 'edit' == $context ) { + $format_to_edit = array('link_notes'); + $value = apply_filters("edit_$field", $value, $bookmark_id); + + if ( in_array($field, $format_to_edit) ) { + $value = format_to_edit($value); + } else { + $value = attribute_escape($value); + } + } else if ( 'db' == $context ) { + $value = apply_filters("pre_$field", $value); + } else { + // Use display filters by default. + $value = apply_filters($field, $value, $bookmark_id, $context); + } + + if ( 'attribute' == $context ) + $value = attribute_escape($value); + else if ( 'js' == $context ) + $value = js_escape($value); + + return $value; +} + function delete_get_bookmark_cache() { wp_cache_delete( 'get_bookmarks', 'bookmark' ); } diff --git a/wp-includes/cache.php b/wp-includes/cache.php index 695a986..1b300d4 100644 --- a/wp-includes/cache.php +++ b/wp-includes/cache.php @@ -63,6 +63,7 @@ class WP_Object_Cache { var $dirty_objects = array (); var $non_existant_objects = array (); var $global_groups = array ('users', 'userlogins', 'usermeta', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details'); + var $non_persistent_groups = array('comment'); var $blog_id; var $cold_cache_hits = 0; var $warm_cache_hits = 0; @@ -207,18 +208,7 @@ class WP_Object_Cache { } function load_group_from_db($group) { - global $wpdb; - - if ('category' == $group) { - $this->cache['category'] = array (); - if ($dogs = $wpdb->get_results("SELECT * FROM $wpdb->categories")) { - foreach ($dogs as $catt) { - $this->cache['category'][$catt->cat_ID] = $catt; - $this->cache[$this->key( $catt->cat_ID, 'category' )] = $catt; - } - } - } - + return; } function make_group_dir($group, $perms) { @@ -384,14 +374,14 @@ class WP_Object_Cache { function stats() { echo "<p>"; - echo "<strong>Cold Cache Hits:</strong> {$this->cold_cache_hits}<br/>"; - echo "<strong>Warm Cache Hits:</strong> {$this->warm_cache_hits}<br/>"; - echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br/>"; + echo "<strong>Cold Cache Hits:</strong> {$this->cold_cache_hits}<br />"; + echo "<strong>Warm Cache Hits:</strong> {$this->warm_cache_hits}<br />"; + echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />"; echo "</p>"; foreach ($this->cache as $group => $cache) { echo "<p>"; - echo "<strong>Group:</strong> $group<br/>"; + echo "<strong>Group:</strong> $group<br />"; echo "<strong>Cache:</strong>"; echo "<pre>"; print_r($cache); diff --git a/wp-includes/canonical.php b/wp-includes/canonical.php new file mode 100644 index 0000000..8027a1c --- /dev/null +++ b/wp-includes/canonical.php @@ -0,0 +1,201 @@ +<?php +// Based on "Permalink Redirect" from Scott Yang and "Enforce www. Preference" by Mark Jaquith + +function redirect_canonical($requested_url=NULL, $do_redirect=true) { + global $wp_rewrite, $posts, $is_IIS; + + if ( is_feed() || is_trackback() || is_search() || is_comments_popup() || is_admin() || $is_IIS || ( isset($_POST) && count($_POST) ) ) + return; + + if ( !$requested_url ) { + // build the URL in the address bar + $requested_url = ( isset($_SERVER['HTTPS'] ) && strtolower($_SERVER['HTTPS']) == 'on' ) ? 'https://' : 'http://'; + $requested_url .= $_SERVER['HTTP_HOST']; + $requested_url .= $_SERVER['REQUEST_URI']; + } + + $original = @parse_url($requested_url); + if ( false === $original ) + return; + + // Some PHP setups turn requests for / into /index.php in REQUEST_URI + $original['path'] = preg_replace('|/index\.php$|', '/', $original['path']); + + $redirect = $original; + $redirect_url = false; + + // These tests give us a WP-generated permalink + if ( is_404() ) { + $redirect_url = redirect_guess_404_permalink(); + } elseif ( is_object($wp_rewrite) && $wp_rewrite->using_permalinks() ) { + // rewriting of old ?p=X, ?m=2004, ?m=200401, ?m=20040101 + if ( is_single() && isset($_GET['p']) ) { + if ( $redirect_url = get_permalink(get_query_var('p')) ) + $redirect['query'] = remove_query_arg('p', $redirect['query']); + } elseif ( is_page() && isset($_GET['page_id']) ) { + if ( $redirect_url = get_permalink(get_query_var('page_id')) ) + $redirect['query'] = remove_query_arg('page_id', $redirect['query']); + } elseif ( isset($_GET['m']) && ( is_year() || is_month() || is_day() ) ) { + $m = get_query_var('m'); + switch ( strlen($m) ) { + case 4: // Yearly + $redirect_url = get_year_link($m); + break; + case 6: // Monthly + $redirect_url = get_month_link( substr($m, 0, 4), substr($m, 4, 2) ); + break; + case 8: // Daily + $redirect_url = get_day_link(substr($m, 0, 4), substr($m, 4, 2), substr($m, 6, 2)); + break; + } + if ( $redirect_url ) + $redirect['query'] = remove_query_arg('m', $redirect['query']); + // now moving on to non ?m=X year/month/day links + } elseif ( is_day() && get_query_var('year') && get_query_var('monthnum') && isset($_GET['day']) ) { + if ( $redirect_url = get_day_link(get_query_var('year'), get_query_var('monthnum'), get_query_var('day')) ) + $redirect['query'] = remove_query_arg(array('year', 'monthnum', 'day'), $redirect['query']); + } elseif ( is_month() && get_query_var('year') && isset($_GET['monthnum']) ) { + if ( $redirect_url = get_month_link(get_query_var('year'), get_query_var('monthnum')) ) + $redirect['query'] = remove_query_arg(array('year', 'monthnum'), $redirect['query']); + } elseif ( is_year() && isset($_GET['year']) ) { + if ( $redirect_url = get_year_link(get_query_var('year')) ) + $redirect['query'] = remove_query_arg('year', $redirect['query']); + } elseif ( is_category() && isset($_GET['cat']) ) { + if ( $redirect_url = get_category_link(get_query_var('cat')) ) + $redirect['query'] = remove_query_arg('cat', $redirect['query']); + } elseif ( is_author() && isset($_GET['author']) ) { + $author = get_userdata(get_query_var('author')); + if ( false !== $author && $redirect_url = get_author_link(false, $author->ID, $author->user_nicename) ) + $redirect['query'] = remove_query_arg('author', $redirect['author']); + } + + // paging + if ( $paged = get_query_var('paged') ) { + if ( $paged > 0 ) { + if ( !$redirect_url ) + $redirect_url = $requested_url; + $paged_redirect = @parse_url($redirect_url); + $paged_redirect['path'] = preg_replace('|/page/[0-9]+?(/+)?$|', '/', $paged_redirect['path']); // strip off any existing paging + $paged_redirect['path'] = preg_replace('|/index.php/?$|', '/', $paged_redirect['path']); // strip off trailing /index.php/ + if ( $paged > 1 && !is_single() ) { + $paged_redirect['path'] = trailingslashit($paged_redirect['path']); + if ( $wp_rewrite->using_index_permalinks() && strpos($paged_redirect['path'], '/index.php/') === false ) + $paged_redirect['path'] .= 'index.php/'; + $paged_redirect['path'] .= user_trailingslashit("page/$paged", 'paged'); + } elseif ( !is_home() && !is_single() ){ + $paged_redirect['path'] = user_trailingslashit($paged_redirect['path'], 'paged'); + } + $redirect_url = $paged_redirect['scheme'] . '://' . $paged_redirect['host'] . $paged_redirect['path']; + $redirect['path'] = $paged_redirect['path']; + } + $redirect['query'] = remove_query_arg('paged', $redirect['query']); + } + } + + // tack on any additional query vars + if ( $redirect_url && $redirect['query'] ) { + if ( strpos($redirect_url, '?') !== false ) + $redirect_url .= '&'; + else + $redirect_url .= '?'; + $redirect_url .= $redirect['query']; + } + + if ( $redirect_url ) + $redirect = @parse_url($redirect_url); + + // www.example.com vs example.com + $user_home = @parse_url(get_option('home')); + $redirect['host'] = $user_home['host']; + + // Handle ports + if ( isset($user_home['port']) ) + $redirect['port'] = $user_home['port']; + else + unset($redirect['port']); + + // trailing /index.php/ + $redirect['path'] = preg_replace('|/index.php/$|', '/', $redirect['path']); + + // strip /index.php/ when we're not using PATHINFO permalinks + if ( !$wp_rewrite->using_index_permalinks() ) + $redirect['path'] = str_replace('/index.php/', '/', $redirect['path']); + + // trailing slashes + if ( is_object($wp_rewrite) && $wp_rewrite->using_permalinks() && !is_404() && (!is_home() || ( is_home() && (get_query_var('paged') > 1) ) ) ) { + $user_ts_type = ''; + if ( get_query_var('paged') > 0 ) { + $user_ts_type = 'paged'; + } else { + foreach ( array('single', 'category', 'page', 'day', 'month', 'year') as $type ) { + $func = 'is_' . $type; + if ( call_user_func($func) ) + $user_ts_type = $type; + break; + } + } + $redirect['path'] = user_trailingslashit($redirect['path'], $user_ts_type); + } elseif ( is_home() ) { + $redirect['path'] = trailingslashit($redirect['path']); + } + + // Always trailing slash the 'home' URL + if ( $redirect['path'] == $user_home['path'] ) + $redirect['path'] = trailingslashit($redirect['path']); + + // Ignore differences in host capitalization, as this can lead to infinite redirects + if ( strtolower($original['host']) == strtolower($redirect['host']) ) + $redirect['host'] = $original['host']; + + if ( array($original['host'], $original['port'], $original['path'], $original['query']) !== array($redirect['host'], $redirect['port'], $redirect['path'], $redirect['query']) ) { + $redirect_url = $redirect['scheme'] . '://' . $redirect['host']; + if ( isset($redirect['port']) ) + $redirect_url .= ':' . $redirect['port']; + $redirect_url .= $redirect['path']; + if ( $redirect['query'] ) + $redirect_url .= '?' . $redirect['query']; + } + + if ( $redirect_url && $redirect_url != $requested_url ) { + // var_dump($redirect_url); die(); + $redirect_url = apply_filters('redirect_canonical', $redirect_url, $requested_url); + if ( $do_redirect) { + // protect against chained redirects + if ( !redirect_canonical($redirect_url, false) ) { + wp_redirect($redirect_url, 301); + exit(); + } else { + return false; + } + } else { + return $redirect_url; + } + } else { + return false; + } +} + +function redirect_guess_404_permalink() { + global $wp_query, $wpdb; + if ( !get_query_var('name') ) + return false; + + $where = "post_name LIKE '" . $wpdb->escape(get_query_var('name')) . "%'"; + + // if any of year, monthnum, or day are set, use them to refine the query + if ( get_query_var('year') ) + $where .= " AND YEAR(post_date) = '" . $wpdb->escape(get_query_var('year')) . "'"; + if ( get_query_var('monthnum') ) + $where .= " AND MONTH(post_date) = '" . $wpdb->escape(get_query_var('monthnum')) . "'"; + if ( get_query_var('day') ) + $where .= " AND DAYOFMONTH(post_date) = '" . $wpdb->escape(get_query_var('day')) . "'"; + + $post_id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE $where AND post_status = 'publish'"); + if ( !$post_id ) + return false; + return get_permalink($post_id); +} + +add_action('template_redirect', 'redirect_canonical'); + +?>
\ No newline at end of file diff --git a/wp-includes/capabilities.php b/wp-includes/capabilities.php index eccde97..3c3594d 100644 --- a/wp-includes/capabilities.php +++ b/wp-includes/capabilities.php @@ -267,7 +267,7 @@ class WP_User { // Must have ALL requested caps $capabilities = apply_filters('user_has_cap', $this->allcaps, $caps, $args); foreach ($caps as $cap) { - //echo "Checking cap $cap<br/>"; + //echo "Checking cap $cap<br />"; if(empty($capabilities[$cap]) || !$capabilities[$cap]) return false; } @@ -295,14 +295,14 @@ function map_meta_cap($cap, $user_id) { break; case 'delete_post': $author_data = get_userdata($user_id); - //echo "post ID: {$args[0]}<br/>"; + //echo "post ID: {$args[0]}<br />"; $post = get_post($args[0]); if ( 'page' == $post->post_type ) { $args = array_merge(array('delete_page', $user_id), $args); return call_user_func_array('map_meta_cap', $args); } $post_author_data = get_userdata($post->post_author); - //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br/>"; + //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br />"; // If the user is the author... if ($user_id == $post_author_data->ID) { // If the post is published... @@ -323,10 +323,10 @@ function map_meta_cap($cap, $user_id) { break; case 'delete_page': $author_data = get_userdata($user_id); - //echo "post ID: {$args[0]}<br/>"; + //echo "post ID: {$args[0]}<br />"; $page = get_page($args[0]); $page_author_data = get_userdata($page->post_author); - //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br/>"; + //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />"; // If the user is the author... if ($user_id == $page_author_data->ID) { // If the page is published... @@ -349,14 +349,14 @@ function map_meta_cap($cap, $user_id) { // edit_others_posts case 'edit_post': $author_data = get_userdata($user_id); - //echo "post ID: {$args[0]}<br/>"; + //echo "post ID: {$args[0]}<br />"; $post = get_post($args[0]); if ( 'page' == $post->post_type ) { $args = array_merge(array('edit_page', $user_id), $args); return call_user_func_array('map_meta_cap', $args); } $post_author_data = get_userdata($post->post_author); - //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br/>"; + //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br />"; // If the user is the author... if ($user_id == $post_author_data->ID) { // If the post is published... @@ -377,10 +377,10 @@ function map_meta_cap($cap, $user_id) { break; case 'edit_page': $author_data = get_userdata($user_id); - //echo "post ID: {$args[0]}<br/>"; + //echo "post ID: {$args[0]}<br />"; $page = get_page($args[0]); $page_author_data = get_userdata($page->post_author); - //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br/>"; + //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />"; // If the user is the author... if ($user_id == $page_author_data->ID) { // If the page is published... @@ -445,12 +445,12 @@ function map_meta_cap($cap, $user_id) { function current_user_can($capability) { $current_user = wp_get_current_user(); - $args = array_slice(func_get_args(), 1); - $args = array_merge(array($capability), $args); - if ( empty($current_user) ) return false; + $args = array_slice(func_get_args(), 1); + $args = array_merge(array($capability), $args); + return call_user_func_array(array(&$current_user, 'has_cap'), $args); } diff --git a/wp-includes/category-template.php b/wp-includes/category-template.php index 5eaabfb..cd8dbcb 100644 --- a/wp-includes/category-template.php +++ b/wp-includes/category-template.php @@ -5,16 +5,18 @@ function get_category_children($id, $before = '/', $after = '') { return ''; $chain = ''; - + // TODO: consult hierarchy $cat_ids = get_all_category_ids(); foreach ( $cat_ids as $cat_id ) { - if ( $cat_id == $id) + if ( $cat_id == $id ) continue; $category = get_category($cat_id); - if ( $category->category_parent == $id ) { - $chain .= $before.$category->cat_ID.$after; - $chain .= get_category_children($category->cat_ID, $before, $after); + if ( is_wp_error( $category ) ) + return $category; + if ( $category->parent == $id ) { + $chain .= $before.$category->term_id.$after; + $chain .= get_category_children($category->term_id, $before, $after); } } return $chain; @@ -29,12 +31,11 @@ function get_category_link($category_id) { $catlink = $file . '?cat=' . $category_id; } else { $category = &get_category($category_id); - $category_nicename = $category->category_nicename; - - if ( $category->category_parent == $category_id ) // recursive recursion - $category->category_parent = 0; + if ( is_wp_error( $category ) ) + return $category; + $category_nicename = $category->slug; - if ( $parent = $category->category_parent ) + if ( $parent = $category->parent ) $category_nicename = get_category_parents($parent, false, '/', true) . $category_nicename; $catlink = str_replace('%category%', $category_nicename, $catlink); @@ -46,50 +47,55 @@ function get_category_link($category_id) { function get_category_parents($id, $link = FALSE, $separator = '/', $nicename = FALSE){ $chain = ''; $parent = &get_category($id); + if ( is_wp_error( $parent ) ) + return $parent; if ( $nicename ) - $name = $parent->category_nicename; + $name = $parent->slug; else $name = $parent->cat_name; - if ( $parent->category_parent && ($parent->category_parent != $parent->cat_ID) ) - $chain .= get_category_parents($parent->category_parent, $link, $separator, $nicename); + if ( $parent->parent && ($parent->parent != $parent->term_id) ) + $chain .= get_category_parents($parent->parent, $link, $separator, $nicename); if ( $link ) - $chain .= '<a href="' . get_category_link($parent->cat_ID) . '" title="' . sprintf(__("View all posts in %s"), $parent->cat_name) . '">'.$name.'</a>' . $separator; + $chain .= '<a href="' . get_category_link($parent->term_id) . '" title="' . sprintf(__("View all posts in %s"), $parent->cat_name) . '">'.$name.'</a>' . $separator; else $chain .= $name.$separator; return $chain; } function get_the_category($id = false) { -global $post, $category_cache, $blog_id; + global $post, $term_cache, $blog_id; $id = (int) $id; if ( !$id ) $id = (int) $post->ID; - if ( !isset($category_cache[$blog_id][$id]) ) - update_post_category_cache($id); - - $categories = $category_cache[$blog_id][$id]; + $categories = get_object_term_cache($id, 'category'); + if ( false === $categories ) + $categories = wp_get_object_terms($id, 'category'); if ( !empty($categories) ) - usort($categories, '_get_the_category_usort'); + usort($categories, '_usort_terms_by_name'); else $categories = array(); + foreach(array_keys($categories) as $key) { + _make_cat_compat($categories[$key]); + } + return $categories; } -function _get_the_category_usort($a, $b) { - return strcmp($a->category_name, $b->category_name); +function _usort_terms_by_name($a, $b) { + return strcmp($a->name, $b->name); } -function _get_the_category_usort_by_ID($a, $b) { - if ( $a->cat_ID > $b->cat_ID ) +function _usort_terms_by_ID($a, $b) { + if ( $a->term_id > $b->term_id ) return 1; - elseif ( $a->cat_ID < $b->cat_ID ) + elseif ( $a->term_id < $b->term_id ) return -1; else return 0; @@ -98,7 +104,9 @@ function _get_the_category_usort_by_ID($a, $b) { function get_the_category_by_ID($cat_ID) { $cat_ID = (int) $cat_ID; $category = &get_category($cat_ID); - return $category->cat_name; + if ( is_wp_error( $category ) ) + return $category; + return $category->name; } function get_the_category_list($separator = '', $parents='') { @@ -116,19 +124,19 @@ function get_the_category_list($separator = '', $parents='') { $thelist .= "\n\t<li>"; switch ( strtolower($parents) ) { case 'multiple': - if ($category->category_parent) - $thelist .= get_category_parents($category->category_parent, TRUE); - $thelist .= '<a href="' . get_category_link($category->cat_ID) . '" title="' . sprintf(__("View all posts in %s"), $category->cat_name) . '" ' . $rel . '>' . $category->cat_name.'</a></li>'; + if ($category->parent) + $thelist .= get_category_parents($category->parent, TRUE); + $thelist .= '<a href="' . get_category_link($category->term_id) . '" title="' . sprintf(__("View all posts in %s"), $category->name) . '" ' . $rel . '>' . $category->name.'</a></li>'; break; case 'single': - $thelist .= '<a href="' . get_category_link($category->cat_ID) . '" title="' . sprintf(__("View all posts in %s"), $category->cat_name) . '" ' . $rel . '>'; - if ($category->category_parent) - $thelist .= get_category_parents($category->category_parent, FALSE); - $thelist .= $category->cat_name.'</a></li>'; + $thelist .= '<a href="' . get_category_link($category->term_id) . '" title="' . sprintf(__("View all posts in %s"), $category->name) . '" ' . $rel . '>'; + if ($category->parent) + $thelist .= get_category_parents($category->parent, FALSE); + $thelist .= $category->name.'</a></li>'; break; case '': default: - $thelist .= '<a href="' . get_category_link($category->cat_ID) . '" title="' . sprintf(__("View all posts in %s"), $category->cat_name) . '" ' . $rel . '>' . $category->cat_name.'</a></li>'; + $thelist .= '<a href="' . get_category_link($category->term_id) . '" title="' . sprintf(__("View all posts in %s"), $category->name) . '" ' . $rel . '>' . $category->cat_name.'</a></li>'; } } $thelist .= '</ul>'; @@ -139,19 +147,19 @@ function get_the_category_list($separator = '', $parents='') { $thelist .= $separator . ' '; switch ( strtolower($parents) ) { case 'multiple': - if ( $category->category_parent ) - $thelist .= get_category_parents($category->category_parent, TRUE); - $thelist .= '<a href="' . get_category_link($category->cat_ID) . '" title="' . sprintf(__("View all posts in %s"), $category->cat_name) . '" ' . $rel . '>' . $category->cat_name.'</a>'; + if ( $category->parent ) + $thelist .= get_category_parents($category->parent, TRUE); + $thelist .= '<a href="' . get_category_link($category->term_id) . '" title="' . sprintf(__("View all posts in %s"), $category->name) . '" ' . $rel . '>' . $category->cat_name.'</a>'; break; case 'single': - $thelist .= '<a href="' . get_category_link($category->cat_ID) . '" title="' . sprintf(__("View all posts in %s"), $category->cat_name) . '" ' . $rel . '>'; - if ( $category->category_parent ) - $thelist .= get_category_parents($category->category_parent, FALSE); + $thelist .= '<a href="' . get_category_link($category->term_id) . '" title="' . sprintf(__("View all posts in %s"), $category->name) . '" ' . $rel . '>'; + if ( $category->parent ) + $thelist .= get_category_parents($category->parent, FALSE); $thelist .= "$category->cat_name</a>"; break; case '': default: - $thelist .= '<a href="' . get_category_link($category->cat_ID) . '" title="' . sprintf(__("View all posts in %s"), $category->cat_name) . '" ' . $rel . '>' . $category->cat_name.'</a>'; + $thelist .= '<a href="' . get_category_link($category->term_id) . '" title="' . sprintf(__("View all posts in %s"), $category->name) . '" ' . $rel . '>' . $category->name.'</a>'; } ++$i; } @@ -159,10 +167,13 @@ function get_the_category_list($separator = '', $parents='') { return apply_filters('the_category', $thelist, $separator, $parents); } -function in_category($category) { // Check if the current post is in the given category - global $category_cache, $post, $blog_id; +function in_category( $category ) { // Check if the current post is in the given category + global $post, $blog_id; - if ( isset( $category_cache[$blog_id][$post->ID][$category] ) ) + $categories = get_object_term_cache($post->ID, 'category'); + if ( false === $categories ) + $categories = wp_get_object_terms($post->ID, 'category'); + if(array_key_exists($category, $categories)) return true; else return false; @@ -176,25 +187,26 @@ function category_description($category = 0) { global $cat; if ( !$category ) $category = $cat; - $category = & get_category($category); - return apply_filters('category_description', $category->category_description, $category->cat_ID); + + return get_term_field('description', $category, 'category'); } 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, EXTR_SKIP); + extract( $r ); $categories = get_categories($r); @@ -230,22 +242,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'), + 'echo' => 1 + ); + + $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, EXTR_SKIP); + } + + extract( $r ); $categories = get_categories($r); @@ -260,13 +278,13 @@ function wp_list_categories($args = '') { $output .= __("No categories"); } else { global $wp_query; - + if( !empty($show_option_all) ) - if ('list' == $style ) + 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(); @@ -281,7 +299,103 @@ function wp_list_categories($args = '') { if ( $title_li && 'list' == $style ) $output .= '</ul></li>'; - echo apply_filters('wp_list_categories', $output); + $output = apply_filters('wp_list_categories', $output); + + if ( $echo ) + echo $output; + else + return $output; +} + +function wp_tag_cloud( $args = '' ) { + $defaults = array( + 'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45, + 'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC', + 'exclude' => '', 'include' => '' + ); + $args = wp_parse_args( $args, $defaults ); + + $tags = get_tags( array_merge($args, array('orderby' => 'count', 'order' => 'DESC')) ); // Always query top tags + + if ( empty($tags) ) + return; + + $return = wp_generate_tag_cloud( $tags, $args ); // Here's where those top tags get sorted according to $args + if ( is_wp_error( $return ) ) + return false; + else + echo apply_filters( 'wp_tag_cloud', $return, $args ); +} + +// $tags = prefetched tag array ( get_tags() ) +// $args['format'] = 'flat' => whitespace separated, 'list' => UL, 'array' => array() +// $args['orderby'] = 'name', 'count' +function wp_generate_tag_cloud( $tags, $args = '' ) { + global $wp_rewrite; + $defaults = array( + 'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45, + 'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC' + ); + $args = wp_parse_args( $args, $defaults ); + extract($args); + + if ( !$tags ) + return; + $counts = $tag_links = array(); + foreach ( (array) $tags as $tag ) { + $counts[$tag->name] = $tag->count; + $tag_links[$tag->name] = get_tag_link( $tag->term_id ); + if ( is_wp_error( $tag_links[$tag->name] ) ) + return $tag_links[$tag->name]; + $tag_ids[$tag->name] = $tag->term_id; + } + + $min_count = min($counts); + $spread = max($counts) - $min_count; + if ( $spread <= 0 ) + $spread = 1; + $font_spread = $largest - $smallest; + if ( $font_spread <= 0 ) + $font_spread = 1; + $font_step = $font_spread / $spread; + + // SQL cannot save you; this is a second (potentially different) sort on a subset of data. + if ( 'name' == $orderby ) + uksort($counts, 'strnatcasecmp'); + else + asort($counts); + + if ( 'DESC' == $order ) + $counts = array_reverse( $counts, true ); + + $a = array(); + + $rel = ( is_object($wp_rewrite) && $wp_rewrite->using_permalinks() ) ? ' rel="tag"' : ''; + + foreach ( $counts as $tag => $count ) { + $tag_id = $tag_ids[$tag]; + $tag_link = clean_url($tag_links[$tag]); + $tag = str_replace(' ', ' ', wp_specialchars( $tag )); + $a[] = "<a href='$tag_link' class='tag-link-$tag_id' title='" . attribute_escape( sprintf( __('%d topics'), $count ) ) . "'$rel style='font-size: " . + ( $smallest + ( ( $count - $min_count ) * $font_step ) ) + . "$unit;'>$tag</a>"; + } + + switch ( $format ) : + case 'array' : + $return =& $a; + break; + case 'list' : + $return = "<ul class='wp-tag-cloud'>\n\t<li>"; + $return .= join("</li>\n\t<li>", $a); + $return .= "</li>\n</ul>\n"; + break; + default : + $return = join("\n", $a); + break; + endswitch; + + return apply_filters( 'wp_generate_tag_cloud', $return, $tags, $args ); } // @@ -300,4 +414,79 @@ function walk_category_dropdown_tree() { return call_user_func_array(array(&$walker, 'walk'), $args); } +// +// Tags +// + +function get_tag_link( $tag_id ) { + global $wp_rewrite; + $taglink = $wp_rewrite->get_tag_permastruct(); + + $tag = &get_term($tag_id, 'post_tag'); + if ( is_wp_error( $tag ) ) + return $tag; + $slug = $tag->slug; + + if ( empty($taglink) ) { + $file = get_option('home') . '/'; + $taglink = $file . '?tag=' . $slug; + } else { + $taglink = str_replace('%tag%', $slug, $taglink); + $taglink = get_option('home') . user_trailingslashit($taglink, 'category'); + } + return apply_filters('tag_link', $taglink, $tag_id); +} + +function get_the_tags( $id = 0 ) { + global $post; + + $id = (int) $id; + + if ( ! $id && ! in_the_loop() ) + return false; // in-the-loop function + + if ( !$id ) + $id = (int) $post->ID; + + $tags = get_object_term_cache($id, 'post_tag'); + if ( false === $tags ) + $tags = wp_get_object_terms($id, 'post_tag'); + + $tags = apply_filters( 'get_the_tags', $tags ); + if ( empty( $tags ) ) + return false; + return $tags; +} + +function get_the_tag_list( $before = '', $sep = '', $after = '' ) { + $tags = get_the_tags(); + + if ( empty( $tags ) ) + return false; + + $tag_list = $before; + foreach ( $tags as $tag ) { + $link = get_tag_link($tag->term_id); + if ( is_wp_error( $link ) ) + return $link; + $tag_links[] = '<a href="' . $link . '" rel="tag">' . $tag->name . '</a>'; + } + + $tag_links = join( $sep, $tag_links ); + $tag_links = apply_filters( 'the_tags', $tag_links ); + $tag_list .= $tag_links; + + $tag_list .= $after; + + return $tag_list; +} + +function the_tags( $before = 'Tags: ', $sep = ', ', $after = '' ) { + $return = get_the_tag_list($before, $sep, $after); + if ( is_wp_error( $return ) ) + return false; + else + echo $return; +} + ?> diff --git a/wp-includes/category.php b/wp-includes/category.php index fcfb60f..71e5be8 100644 --- a/wp-includes/category.php +++ b/wp-includes/category.php @@ -4,7 +4,7 @@ function get_all_category_ids() { global $wpdb; if ( ! $cat_ids = wp_cache_get('all_category_ids', 'category') ) { - $cat_ids = $wpdb->get_col("SELECT cat_ID FROM $wpdb->categories"); + $cat_ids = get_terms('category', 'fields=ids&get=all'); wp_cache_add('all_category_ids', $cat_ids, 'category'); } @@ -12,162 +12,30 @@ 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'] ) - $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, EXTR_SKIP); - - $key = md5( serialize( $r ) ); - if ( $cache = wp_cache_get( 'get_categories', 'category' ) ) - if ( isset( $cache[ $key ] ) ) - return apply_filters('get_categories', $cache[$key], $r); - - $where = 'cat_ID > 0'; - $inclusions = ''; - if ( !empty($include) ) { - $child_of = 0; //ignore child_of and exclude params if using include - $exclude = ''; - $incategories = preg_split('/[\s,]+/',$include); - if ( count($incategories) ) { - foreach ( $incategories as $incat ) { - if (empty($inclusions)) - $inclusions = ' AND ( cat_ID = ' . intval($incat) . ' '; - else - $inclusions .= ' OR cat_ID = ' . intval($incat) . ' '; - } - } - } - if (!empty($inclusions)) - $inclusions .= ')'; - $where .= $inclusions; - - $exclusions = ''; - if ( !empty($exclude) ) { - $excategories = preg_split('/[\s,]+/',$exclude); - if ( count($excategories) ) { - foreach ( $excategories as $excat ) { - if (empty($exclusions)) - $exclusions = ' AND ( cat_ID <> ' . intval($excat) . ' '; - else - $exclusions .= ' AND cat_ID <> ' . intval($excat) . ' '; - // TODO: Exclude children of excluded cats? Note: children are getting excluded - } - } - } - if (!empty($exclusions)) - $exclusions .= ')'; - $exclusions = apply_filters('list_cats_exclusions', $exclusions, $r ); - $where .= $exclusions; - - if ( $hide_empty && !$hierarchical ) { - if ( 'link' == $type ) - $where .= ' AND link_count > 0'; - else - $where .= ' AND category_count > 0'; - } - - if ( !empty($number) ) - $number = 'LIMIT ' . $number; - else - $number = ''; - - $categories = $wpdb->get_results("SELECT * FROM $wpdb->categories WHERE $where ORDER BY $orderby $order $number"); - - if ( empty($categories) ) - return array(); - - // TODO: Integrate this into the main query. - if ( $include_last_update_time ) { - $stamps = $wpdb->get_results("SELECT category_id, UNIX_TIMESTAMP( MAX(post_date) ) AS ts FROM $wpdb->posts, $wpdb->post2cat, $wpdb->categories - WHERE post_status = 'publish' AND post_id = ID AND $where GROUP BY category_id"); - global $cat_stamps; - foreach ($stamps as $stamp) - $cat_stamps[$stamp->category_id] = $stamp->ts; - function stamp_cat($cat) { - global $cat_stamps; - $cat->last_update_timestamp = $cat_stamps[$cat->cat_ID]; - return $cat; - } - $categories = array_map('stamp_cat', $categories); - unset($cat_stamps); - } - - if ( $child_of || $hierarchical ) { - $children = _get_category_hierarchy(); - if ( ! empty($children) ) - $categories = & _get_cat_children($child_of, $categories); - } + $defaults = array('type' => 'category'); + $args = wp_parse_args($args, $defaults); - // Update category counts to include children. - if ( $pad_counts ) - _pad_category_counts($type, $categories); - - // Make sure we show empty categories that have children. - if ( $hierarchical && $hide_empty ) { - foreach ( $categories as $k => $category ) { - if ( ! $category->{'link' == $type ? 'link_count' : 'category_count'} ) { - $children = _get_cat_children($category->cat_ID, $categories); - foreach ( $children as $child ) - if ( $child->{'link' == $type ? 'link_count' : 'category_count'} ) - continue 2; - - // It really is empty - unset($categories[$k]); - } - } - } - reset ( $categories ); + $taxonomy = 'category'; + if ( 'link' == $args['type'] ) + $taxonomy = 'link_category'; + $categories = get_terms($taxonomy, $args); - $cache[ $key ] = $categories; - wp_cache_add( 'get_categories', $cache, 'category' ); + foreach ( array_keys($categories) as $k ) + _make_cat_compat($categories[$k]); - $categories = apply_filters('get_categories', $categories, $r); return $categories; } // Retrieves category data given a category ID or category object. // Handles category caching. -function &get_category(&$category, $output = OBJECT) { - global $wpdb; +function &get_category($category, $output = OBJECT, $filter = 'raw') { + $category = get_term($category, 'category', $output, $filter); + if ( is_wp_error( $category ) ) + return $category; - if ( empty($category) ) - return null; + _make_cat_compat($category); - if ( is_object($category) ) { - 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_add($category, $_category, 'category'); - } - } - - $_category = apply_filters('get_category', $_category); - - if ( $output == OBJECT ) { - return $_category; - } elseif ( $output == ARRAY_A ) { - return get_object_vars($_category); - } elseif ( $output == ARRAY_N ) { - return array_values(get_object_vars($_category)); - } else { - return $_category; - } + return $category; } function get_category_by_path($category_path, $full_match = true, $output = OBJECT) { @@ -182,7 +50,7 @@ function get_category_by_path($category_path, $full_match = true, $output = OBJE foreach ( (array) $category_paths as $pathdir ) $full_path .= ( $pathdir != '' ? '/' : '' ) . sanitize_title($pathdir); - $categories = $wpdb->get_results("SELECT cat_ID, category_nicename, category_parent FROM $wpdb->categories WHERE category_nicename = '$leaf_path'"); + $categories = get_terms('category', "get=all&slug=$leaf_path"); if ( empty($categories) ) return NULL; @@ -190,29 +58,40 @@ function get_category_by_path($category_path, $full_match = true, $output = OBJE foreach ($categories as $category) { $path = '/' . $leaf_path; $curcategory = $category; - while ( ($curcategory->category_parent != 0) && ($curcategory->category_parent != $curcategory->cat_ID) ) { - $curcategory = $wpdb->get_row("SELECT cat_ID, category_nicename, category_parent FROM $wpdb->categories WHERE cat_ID = '$curcategory->category_parent'"); - $path = '/' . $curcategory->category_nicename . $path; + while ( ($curcategory->parent != 0) && ($curcategory->parent != $curcategory->term_id) ) { + $curcategory = get_term($curcategory->parent, 'category'); + if ( is_wp_error( $curcategory ) ) + return $curcategory; + $path = '/' . $curcategory->slug . $path; } if ( $path == $full_path ) - return get_category($category->cat_ID, $output); + return get_category($category->term_id, $output); } // If full matching is not required, return the first cat that matches the leaf. if ( ! $full_match ) - return get_category($categories[0]->cat_ID, $output); + return get_category($categories[0]->term_id, $output); return NULL; } +function get_category_by_slug( $slug ) { + $category = get_term_by('slug', $slug, 'category'); + if ( $category ) + _make_cat_compat($category); + + return $category; +} + // Get the ID of a category from its name function get_cat_ID($cat_name='General') { global $wpdb; - $cid = $wpdb->get_var("SELECT cat_ID FROM $wpdb->categories WHERE cat_name='$cat_name'"); - - return $cid?$cid:1; // default to cat 1 + $cat = get_term_by('name', $cat_name, 'category'); + if ($cat) + return $cat->term_id; + return 0; } // Deprecate @@ -224,108 +103,91 @@ function get_catname($cat_ID) { function get_cat_name($cat_id) { $cat_id = (int) $cat_id; $category = &get_category($cat_id); - return $category->cat_name; + return $category->name; } -function cat_is_ancestor_of($cat1, $cat2) { - if ( is_int($cat1) ) - $cat1 = & get_category($cat1); - if ( is_int($cat2) ) - $cat2 = & get_category($cat2); +function cat_is_ancestor_of($cat1, $cat2) { + if ( is_int($cat1) ) + $cat1 = & get_category($cat1); + if ( is_int($cat2) ) + $cat2 = & get_category($cat2); - if ( !$cat1->cat_ID || !$cat2->category_parent ) - return false; + if ( !$cat1->term_id || !$cat2->parent ) + return false; - if ( $cat2->category_parent == $cat1->cat_ID ) - return true; + if ( $cat2->parent == $cat1->term_id ) + return true; - return cat_is_ancestor_of($cat1, get_category($cat2->parent_category)); -} + return cat_is_ancestor_of($cat1, get_category($cat2->parent)); +} -// -// Private -// +function sanitize_category($category, $context = 'display') { + return sanitize_term($category, 'category', $context); +} -function &_get_cat_children($category_id, $categories) { - if ( empty($categories) ) - return array(); +function sanitize_category_field($field, $value, $cat_id, $context) { + return sanitize_term_field($field, $value, $cat_id, 'category', $context); +} - $category_list = array(); - $has_children = _get_category_hierarchy(); +// Tags - if ( ( 0 != $category_id ) && ! isset($has_children[$category_id]) ) - return array(); +function &get_tags($args = '') { + global $wpdb, $category_links; - foreach ( $categories as $category ) { - if ( $category->cat_ID == $category_id ) - continue; + $key = md5( serialize( $args ) ); + if ( $cache = wp_cache_get( 'get_tags', 'category' ) ) + if ( isset( $cache[ $key ] ) ) + return apply_filters('get_tags', $cache[$key], $args); - if ( $category->category_parent == $category_id ) { - $category_list[] = $category; - if ( !isset($has_children[$category->cat_ID]) ) - continue; + $tags = get_terms('post_tag', $args); - if ( $children = _get_cat_children($category->cat_ID, $categories) ) - $category_list = array_merge($category_list, $children); - } - } + if ( empty($tags) ) + return array(); - return $category_list; -} + $cache[ $key ] = $tags; + wp_cache_set( 'get_tags', $cache, 'category' ); -// Recalculates link or post counts by including items from child categories -// Assumes all relevant children are already in the $categories argument -function _pad_category_counts($type, &$categories) { - global $wpdb; + $tags = apply_filters('get_tags', $tags, $args); + return $tags; +} - // Set up some useful arrays - foreach ( $categories as $key => $cat ) { - $cats[$cat->cat_ID] = & $categories[$key]; - $cat_IDs[] = $cat->cat_ID; - } +function &get_tag($tag, $output = OBJECT, $filter = 'raw') { + return get_term($tag, 'post_tag', $output, $filter); +} - // Get the relevant post2cat or link2cat records and stick them in a lookup table - if ( $type == 'post' ) { - $results = $wpdb->get_results("SELECT post_id, category_id FROM $wpdb->post2cat LEFT JOIN $wpdb->posts ON post_id = ID WHERE category_id IN (".join(',', $cat_IDs).") AND post_type = 'post' AND post_status = 'publish'"); - foreach ( $results as $row ) - ++$cat_items[$row->category_id][$row->post_id]; - } else { - $results = $wpdb->get_results("SELECT $wpdb->link2cat.link_id, category_id FROM $wpdb->link2cat LEFT JOIN $wpdb->links USING (link_id) WHERE category_id IN (".join(',', $cat_IDs).") AND link_visible = 'Y'"); - foreach ( $results as $row ) - ++$cat_items[$row->category_id][$row->link_id]; - } +// +// Cache +// - // Touch every ancestor's lookup row for each post in each category - foreach ( $cat_IDs as $cat_ID ) { - $child = $cat_ID; - while ( $parent = $cats[$child]->category_parent ) { - if ( !empty($cat_items[$cat_ID]) ) - foreach ( $cat_items[$cat_ID] as $item_id => $touches ) - ++$cat_items[$parent][$item_id]; - $child = $parent; - } - } +function update_category_cache() { + return true; +} - // Transfer the touched cells - foreach ( (array) $cat_items as $id => $items ) - if ( isset($cats[$id]) ) - $cats[$id]->{'link' == $type ? 'link_count' : 'category_count'} = count($items); +function clean_category_cache($id) { + clean_term_cache($id, 'category'); } -function _get_category_hierarchy() { - $children = get_option('category_children'); - if ( is_array($children) ) - return $children; +// +// Private helpers +// - $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; +function _make_cat_compat( &$category) { + if ( is_object($category) ) { + $category->cat_ID = &$category->term_id; + $category->category_count = &$category->count; + $category->category_description = &$category->description; + $category->cat_name = &$category->name; + $category->category_nicename = &$category->slug; + $category->category_parent = &$category->parent; + } else if ( is_array($category) && isset($category['term_id']) ) { + $category['cat_ID'] = &$category['term_id']; + $category['category_count'] = &$category['count']; + $category['category_description'] = &$category['description']; + $category['cat_name'] = &$category['name']; + $category['category_nicename'] = &$category['slug']; + $category['category_parent'] = &$category['parent']; } - update_option('category_children', $children); - - return $children; } + ?> diff --git a/wp-includes/class-phpmailer.php b/wp-includes/class-phpmailer.php index 4c93bae..acacabb 100644 --- a/wp-includes/class-phpmailer.php +++ b/wp-includes/class-phpmailer.php @@ -96,7 +96,7 @@ class PHPMailer var $AltBody = ""; /** - * Sets word wrapping on the body of the message to a given number of + * Sets word wrapping on the body of the message to a given number of * characters. * @var int */ @@ -113,10 +113,10 @@ class PHPMailer * @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. + * 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 = ""; @@ -186,7 +186,7 @@ class PHPMailer var $Password = ""; /** - * Sets the SMTP server timeout in seconds. This function will not + * Sets the SMTP server timeout in seconds. This function will not * work with the win32 version. * @var int */ @@ -199,9 +199,9 @@ class PHPMailer 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(). + * 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; @@ -222,13 +222,13 @@ class PHPMailer var $error_count = 0; var $LE = "\n"; /**#@-*/ - + ///////////////////////////////////////////////// // VARIABLE METHODS ///////////////////////////////////////////////// /** - * Sets message type to HTML. + * Sets message type to HTML. * @param bool $bool * @return void */ @@ -264,7 +264,7 @@ class PHPMailer } /** - * Sets Mailer to send message using the qmail MTA. + * Sets Mailer to send message using the qmail MTA. * @return void */ function IsQmail() { @@ -278,7 +278,7 @@ class PHPMailer ///////////////////////////////////////////////// /** - * Adds a "To" address. + * Adds a "To" address. * @param string $address * @param string $name * @return void @@ -292,7 +292,7 @@ class PHPMailer /** * Adds a "Cc" address. Note: this function works * with the SMTP mailer on win32, not with the "mail" - * mailer. + * mailer. * @param string $address * @param string $name * @return void @@ -306,7 +306,7 @@ class PHPMailer /** * Adds a "Bcc" address. Note: this function works * with the SMTP mailer on win32, not with the "mail" - * mailer. + * mailer. * @param string $address * @param string $name * @return void @@ -318,7 +318,7 @@ class PHPMailer } /** - * Adds a "Reply-to" address. + * Adds a "Reply-to" address. * @param string $address * @param string $name * @return void @@ -337,7 +337,7 @@ class PHPMailer /** * 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. + * variable to view description of the error. * @return bool */ function Send() { @@ -382,9 +382,9 @@ class PHPMailer return $result; } - + /** - * Sends mail using the $Sendmail program. + * Sends mail using the $Sendmail program. * @access private * @return bool */ @@ -402,7 +402,7 @@ class PHPMailer fputs($mail, $header); fputs($mail, $body); - + $result = pclose($mail) >> 8 & 0xFF; if($result != 0) { @@ -414,7 +414,7 @@ class PHPMailer } /** - * Sends mail using the PHP mail() function. + * Sends mail using the PHP mail() function. * @access private * @return bool */ @@ -431,7 +431,7 @@ class PHPMailer $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, + $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, $header, $params); } else @@ -457,7 +457,7 @@ class PHPMailer * @return bool */ function SmtpSend($header, $body) { - include_once($this->PluginDir . "class.smtp.php"); + include_once($this->PluginDir . "class-smtp.php"); $error = ""; $bad_rcpt = array(); @@ -518,7 +518,7 @@ class PHPMailer } /** - * Initiates a connection to an SMTP server. Returns false if the + * Initiates a connection to an SMTP server. Returns false if the * operation failed. * @access private * @return bool @@ -529,7 +529,7 @@ class PHPMailer $this->smtp->do_debug = $this->SMTPDebug; $hosts = explode(";", $this->Host); $index = 0; - $connection = ($this->smtp->Connected()); + $connection = ($this->smtp->Connected()); // Retry while there is no connection while($index < count($hosts) && $connection == false) @@ -548,10 +548,10 @@ class PHPMailer $this->smtp->Hello($this->Helo); else $this->smtp->Hello($this->ServerHostname()); - + if($this->SMTPAuth) { - if(!$this->smtp->Authenticate($this->Username, + if(!$this->smtp->Authenticate($this->Username, $this->Password)) { $this->SetError($this->Lang("authenticate")); @@ -585,7 +585,7 @@ class PHPMailer } /** - * Sets the language for all class error messages. Returns false + * 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") @@ -604,7 +604,7 @@ class PHPMailer return false; } $this->language = $PHPMAILER_LANG; - + return true; } @@ -613,7 +613,7 @@ class PHPMailer ///////////////////////////////////////////////// /** - * Creates recipient headers. + * Creates recipient headers. * @access private * @return string */ @@ -629,9 +629,9 @@ class PHPMailer return $addr_str; } - + /** - * Formats an address correctly. + * Formats an address correctly. * @access private * @return string */ @@ -640,7 +640,7 @@ class PHPMailer $formatted = $addr[0]; else { - $formatted = $this->EncodeHeader($addr[1], 'phrase') . " <" . + $formatted = $this->EncodeHeader($addr[1], 'phrase') . " <" . $addr[0] . ">"; } @@ -650,7 +650,7 @@ class PHPMailer /** * Wraps message for use with mailers that do not * automatically perform wrapping and for quoted-printable. - * Original written by philippe. + * Original written by philippe. * @access private * @return string */ @@ -712,7 +712,7 @@ class PHPMailer else { $buf_o = $buf; - $buf .= ($e == 0) ? $word : (" " . $word); + $buf .= ($e == 0) ? $word : (" " . $word); if (strlen($buf) > $length and $buf_o != "") { @@ -726,7 +726,7 @@ class PHPMailer return $message; } - + /** * Set the body wrapping. * @access private @@ -735,7 +735,7 @@ class PHPMailer function SetWordWrap() { if($this->WordWrap < 1) return; - + switch($this->message_type) { case "alt": @@ -750,13 +750,13 @@ class PHPMailer } /** - * Assembles message header. + * Assembles message header. * @access private * @return string */ function CreateHeader() { $result = ""; - + // Set the boundaries $uniq_id = md5(uniqid(time())); $this->boundary[1] = "b1_" . $uniq_id; @@ -767,7 +767,7 @@ class PHPMailer $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") { @@ -782,7 +782,7 @@ class PHPMailer $from = array(); $from[0][0] = trim($this->From); $from[0][1] = $this->FromName; - $result .= $this->AddrAppend("From", $from); + $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)) @@ -797,17 +797,17 @@ class PHPMailer $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", + $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]), + $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1]))); } $result .= $this->HeaderLine("MIME-Version", "1.0"); @@ -824,8 +824,8 @@ class PHPMailer 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, + $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 @@ -859,16 +859,16 @@ class PHPMailer switch($this->message_type) { case "alt": - $result .= $this->GetBoundary($this->boundary[1], "", + $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], "", + $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": @@ -878,32 +878,32 @@ class PHPMailer $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, + "multipart/alternative", $this->LE, $this->boundary[2], $this->LE.$this->LE); - + // Create text body - $result .= $this->GetBoundary($this->boundary[2], "", + $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], "", + $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; } @@ -924,23 +924,23 @@ class PHPMailer if($encoding == "") { $encoding = $this->Encoding; } $result .= $this->TextLine("--" . $boundary); - $result .= sprintf("Content-Type: %s; charset = \"%s\"", + $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; + return $this->LE . "--" . $boundary . "--" . $this->LE; } - + /** * Sets the message type. * @access private @@ -992,7 +992,7 @@ class PHPMailer * @param string $type File extension (MIME) type. * @return bool */ - function AddAttachment($path, $name = "", $encoding = "base64", + function AddAttachment($path, $name = "", $encoding = "base64", $type = "application/octet-stream") { if(!@is_file($path)) { @@ -1043,7 +1043,7 @@ class PHPMailer $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); @@ -1051,7 +1051,7 @@ class PHPMailer if($disposition == "inline") $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); - $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", + $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $name, $this->LE.$this->LE); // Encode as string attachment @@ -1063,7 +1063,7 @@ class PHPMailer } else { - $mime[] = $this->EncodeFile($path, $encoding); + $mime[] = $this->EncodeFile($path, $encoding); if($this->IsError()) { return ""; } $mime[] = $this->LE.$this->LE; } @@ -1073,7 +1073,7 @@ class PHPMailer return join("", $mime); } - + /** * Encodes attachment in requested format. Returns an * empty string on failure. @@ -1129,13 +1129,13 @@ class PHPMailer } /** - * Encode a header string to best of Q, B, quoted or none. + * 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)) { @@ -1177,12 +1177,12 @@ class PHPMailer $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); $encoded = trim(str_replace("\n", $this->LE, $encoded)); - + return $encoded; } - + /** - * Encode string to quoted-printable. + * Encode string to quoted-printable. * @access private * @return string */ @@ -1205,7 +1205,7 @@ class PHPMailer } /** - * Encode string to q encoding. + * Encode string to q encoding. * @access private * @return string */ @@ -1226,7 +1226,7 @@ class PHPMailer "'='.sprintf('%02X', ord('\\1'))", $encoded); break; } - + // Replace every spaces to _ (more readable than =20) $encoded = str_replace(" ", "_", $encoded); @@ -1243,7 +1243,7 @@ class PHPMailer * @param string $type File extension (MIME) type. * @return void */ - function AddStringAttachment($string, $filename, $encoding = "base64", + function AddStringAttachment($string, $filename, $encoding = "base64", $type = "application/octet-stream") { // Append to $attachment array $cur = count($this->attachment); @@ -1256,23 +1256,23 @@ class PHPMailer $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 + * 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 + * @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. + * @param string $type File extension (MIME) type. * @return bool */ - function AddEmbeddedImage($path, $cid, $name = "", $encoding = "base64", + function AddEmbeddedImage($path, $cid, $name = "", $encoding = "base64", $type = "application/octet-stream") { - + if(!@is_file($path)) { $this->SetError($this->Lang("file_access") . $path); @@ -1293,10 +1293,10 @@ class PHPMailer $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 @@ -1312,7 +1312,7 @@ class PHPMailer break; } } - + return $result; } @@ -1397,7 +1397,7 @@ class PHPMailer } /** - * Returns the proper RFC 822 formatted date. + * Returns the proper RFC 822 formatted date. * @access private * @return string */ @@ -1410,10 +1410,10 @@ class PHPMailer return $result; } - + /** - * Returns the appropriate server variable. Should work with both - * PHP 4.1.0+ as well as older versions. Returns an empty string + * 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 @@ -1428,7 +1428,7 @@ class PHPMailer if(!isset($_SERVER["REMOTE_ADDR"])) $_SERVER = $HTTP_ENV_VARS; // must be Apache } - + if(isset($_SERVER[$varName])) return $_SERVER[$varName]; else @@ -1459,13 +1459,13 @@ class PHPMailer 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 @@ -1475,7 +1475,7 @@ class PHPMailer } /** - * Changes every end of line from CR or LF to CRLF. + * Changes every end of line from CR or LF to CRLF. * @access private * @return string */ @@ -1487,7 +1487,7 @@ class PHPMailer } /** - * Adds a custom header. + * Adds a custom header. * @return void */ function AddCustomHeader($custom_header) { diff --git a/wp-includes/class-pop3.php b/wp-includes/class-pop3.php index fccf329..38c6694 100644 --- a/wp-includes/class-pop3.php +++ b/wp-includes/class-pop3.php @@ -1,4 +1,4 @@ -<?php +<?php /** * mail_fetch/setup.php @@ -13,7 +13,7 @@ * * pop3 class * - * $Id: class-pop3.php 4945 2007-02-25 18:19:21Z ryan $ + * $Id: class-pop3.php 6044 2007-09-05 22:55:38Z ryan $ */ class POP3 { @@ -57,14 +57,14 @@ class POP3 { settype($timeout,"integer"); $this->TIMEOUT = $timeout; if (!ini_get('safe_mode')) - set_time_limit($timeout); + set_time_limit($timeout); } return true; } function update_timer () { if (!ini_get('safe_mode')) - set_time_limit($this->TIMEOUT); + set_time_limit($this->TIMEOUT); return true; } @@ -74,12 +74,12 @@ class POP3 { // If MAILSERVER is set, override $server with it's value - if (!isset($port) || !$port) {$port = 110;} + if (!isset($port) || !$port) {$port = 110;} if(!empty($this->MAILSERVER)) $server = $this->MAILSERVER; if(empty($server)){ - $this->ERROR = _("POP3 connect:") . ' ' . _("No server specified"); + $this->ERROR = "POP3 connect: " . _("No server specified"); unset($this->FP); return false; } @@ -87,7 +87,7 @@ class POP3 { $fp = @fsockopen("$server", $port, $errno, $errstr); if(!$fp) { - $this->ERROR = _("POP3 connect:") . ' ' . _("Error ") . "[$errno] [$errstr]"; + $this->ERROR = "POP3 connect: " . _("Error ") . "[$errno] [$errstr]"; unset($this->FP); return false; } @@ -99,7 +99,7 @@ class POP3 { if($this->DEBUG) error_log("POP3 SEND [connect: $server] GOT [$reply]",0); if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 connect:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 connect: " . _("Error ") . "[$reply]"; unset($this->FP); return false; } @@ -112,15 +112,15 @@ class POP3 { // Sends the USER command, returns true or false if( empty($user) ) { - $this->ERROR = _("POP3 user:") . ' ' . _("no login ID submitted"); + $this->ERROR = "POP3 user: " . _("no login ID submitted"); return false; } elseif(!isset($this->FP)) { - $this->ERROR = _("POP3 user:") . ' ' . _("connection not established"); + $this->ERROR = "POP3 user: " . _("connection not established"); return false; } else { $reply = $this->send_cmd("USER $user"); if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 user:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 user: " . _("Error ") . "[$reply]"; return false; } else return true; @@ -132,15 +132,15 @@ class POP3 { // returns false (undef) on Auth failure if(empty($pass)) { - $this->ERROR = _("POP3 pass:") . ' ' . _("No password submitted"); + $this->ERROR = "POP3 pass: " . _("No password submitted"); return false; } elseif(!isset($this->FP)) { - $this->ERROR = _("POP3 pass:") . ' ' . _("connection not established"); + $this->ERROR = "POP3 pass: " . _("connection not established"); return false; } else { $reply = $this->send_cmd("PASS $pass"); if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 pass:") . ' ' . _("Authentication failed ") . "[$reply]"; + $this->ERROR = "POP3 pass: " . _("Authentication failed") . " [$reply]"; $this->quit(); return false; } else { @@ -159,21 +159,21 @@ class POP3 { // (apop is optional per rfc1939) if(!isset($this->FP)) { - $this->ERROR = _("POP3 apop:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 apop: " . _("No connection to server"); return false; } elseif(!$this->ALLOWAPOP) { $retVal = $this->login($login,$pass); return $retVal; } elseif(empty($login)) { - $this->ERROR = _("POP3 apop:") . ' ' . _("No login ID submitted"); + $this->ERROR = "POP3 apop: " . _("No login ID submitted"); return false; } elseif(empty($pass)) { - $this->ERROR = _("POP3 apop:") . ' ' . _("No password submitted"); + $this->ERROR = "POP3 apop: " . _("No password submitted"); return false; } else { $banner = $this->BANNER; if( (!$banner) or (empty($banner)) ) { - $this->ERROR = _("POP3 apop:") . ' ' . _("No server banner") . ' - ' . _("abort"); + $this->ERROR = "POP3 apop: " . _("No server banner") . ' - ' . _("abort"); $retVal = $this->login($login,$pass); return $retVal; } else { @@ -183,7 +183,7 @@ class POP3 { $cmd = "APOP $login $APOPString"; $reply = $this->send_cmd($cmd); if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 apop:") . ' ' . _("apop authentication failed") . ' - ' . _("abort"); + $this->ERROR = "POP3 apop: " . _("apop authentication failed") . ' - ' . _("abort"); $retVal = $this->login($login,$pass); return $retVal; } else { @@ -202,7 +202,7 @@ class POP3 { // the number of messages.) if( !isset($this->FP) ) { - $this->ERROR = _("POP3 login:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 login: " . _("No connection to server"); return false; } else { $fp = $this->FP; @@ -227,7 +227,7 @@ class POP3 { // only the header information, and none of the body. if(!isset($this->FP)) { - $this->ERROR = _("POP3 top:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 top: " . _("No connection to server"); return false; } $this->update_timer(); @@ -243,7 +243,7 @@ class POP3 { } if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 top:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 top: " . _("Error ") . "[$reply]"; return false; } @@ -269,7 +269,7 @@ class POP3 { if(!isset($this->FP)) { - $this->ERROR = _("POP3 pop_list:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 pop_list: " . _("No connection to server"); return false; } $fp = $this->FP; @@ -297,7 +297,7 @@ class POP3 { } if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 pop_list:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]"; return false; } list($junk,$num,$size) = preg_split('/\s+/',$reply); @@ -308,7 +308,7 @@ class POP3 { if(!$this->is_ok($reply)) { $reply = $this->strip_clf($reply); - $this->ERROR = _("POP3 pop_list:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]"; return false; } $MsgArray = array(); @@ -320,7 +320,7 @@ class POP3 { $line = $this->strip_clf($line); if(ereg("^\.",$line)) { - $this->ERROR = _("POP3 pop_list:") . ' ' . _("Premature end of list"); + $this->ERROR = "POP3 pop_list: " . _("Premature end of list"); return false; } list($thisMsg,$msgSize) = preg_split('/\s+/',$line); @@ -343,7 +343,7 @@ class POP3 { if(!isset($this->FP)) { - $this->ERROR = _("POP3 get:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 get: " . _("No connection to server"); return false; } @@ -356,25 +356,21 @@ class POP3 { if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 get:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 get: " . _("Error ") . "[$reply]"; return false; } $count = 0; $MsgArray = array(); - $line = ""; + $line = fgets($fp,$buffer); while ( !ereg("^\.\r\n",$line)) { - $line = fgets($fp,$buffer); - if (preg_match("/^\s+/", $line) && $count > 0) { - $MsgArray[$count-1] .= $line; - continue; - } - if(empty($line)) { break; } - + if ( $line{0} == '.' ) { $line = substr($line,1); } $MsgArray[$count] = $line; $count++; + $line = fgets($fp,$buffer); + if(empty($line)) { break; } } return $MsgArray; } @@ -387,14 +383,14 @@ class POP3 { $last = -1; if(!isset($this->FP)) { - $this->ERROR = _("POP3 last:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 last: " . _("No connection to server"); return $last; } $reply = $this->send_cmd("STAT"); if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 last:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 last: " . _("Error ") . "[$reply]"; return $last; } @@ -417,7 +413,7 @@ class POP3 { if(!isset($this->FP)) { - $this->ERROR = _("POP3 reset:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 reset: " . _("No connection to server"); return false; } $reply = $this->send_cmd("RSET"); @@ -427,7 +423,7 @@ class POP3 { // response - if it ever does, something truely // wild is going on. - $this->ERROR = _("POP3 reset:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 reset: " . _("Error ") . "[$reply]"; @error_log("POP3 reset: ERROR [$reply]",0); } $this->quit(); @@ -451,13 +447,13 @@ class POP3 { if(!isset($this->FP)) { - $this->ERROR = _("POP3 send_cmd:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 send_cmd: " . _("No connection to server"); return false; } if(empty($cmd)) { - $this->ERROR = _("POP3 send_cmd:") . ' ' . _("Empty command string"); + $this->ERROR = "POP3 send_cmd: " . _("Empty command string"); return ""; } @@ -477,7 +473,7 @@ class POP3 { if(!isset($this->FP)) { - $this->ERROR = _("POP3 quit:") . ' ' . _("connection does not exist"); + $this->ERROR = "POP3 quit: " . _("connection does not exist"); return false; } $fp = $this->FP; @@ -514,7 +510,7 @@ class POP3 { // Array element 0 will contain the total number of msgs if(!isset($this->FP)) { - $this->ERROR = _("POP3 uidl:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 uidl: " . _("No connection to server"); return false; } @@ -526,7 +522,7 @@ class POP3 { $reply = $this->send_cmd($cmd); if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 uidl:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]"; return false; } list ($ok,$num,$myUidl) = preg_split('/\s+/',$reply); @@ -549,7 +545,7 @@ class POP3 { if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 uidl:") . ' ' . _("Error ") . "[$reply]"; + $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]"; return false; } @@ -582,18 +578,18 @@ class POP3 { if(!isset($this->FP)) { - $this->ERROR = _("POP3 delete:") . ' ' . _("No connection to server"); + $this->ERROR = "POP3 delete: " . _("No connection to server"); return false; } if(empty($msgNum)) { - $this->ERROR = _("POP3 delete:") . ' ' . _("No msg number submitted"); + $this->ERROR = "POP3 delete: " . _("No msg number submitted"); return false; } $reply = $this->send_cmd("DELE $msgNum"); if(!$this->is_ok($reply)) { - $this->ERROR = _("POP3 delete:") . ' ' . _("Command failed ") . "[$reply]"; + $this->ERROR = "POP3 delete: " . _("Command failed ") . "[$reply]"; return false; } return true; @@ -630,8 +626,8 @@ class POP3 { $length = strlen($server_text); for($count =0; $count < $length; $count++) { - $digit = substr($server_text, $count, 1); - if (!empty($digit)) { + $digit = substr($server_text,$count,1); + if(!empty($digit)) { if( (!$outside) && ($digit != '<') && ($digit != '>') ) { $banner .= $digit; @@ -651,5 +647,4 @@ class POP3 { } } // End class - ?> diff --git a/wp-includes/classes.php b/wp-includes/classes.php index dd05256..6e55c45 100644 --- a/wp-includes/classes.php +++ b/wp-includes/classes.php @@ -1,9 +1,9 @@ <?php class WP { - var $public_query_vars = array('m', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'debug', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'feed', 'author_name', 'static', 'pagename', 'page_id', 'error', 'comments_popup', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots'); + var $public_query_vars = array('m', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'debug', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'static', 'pagename', 'page_id', 'error', 'comments_popup', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots'); - var $private_query_vars = array('offset', 'posts_per_page', 'posts_per_archive_page', 'what_to_show', 'showposts', 'nopaging', 'post_type'); + var $private_query_vars = array('offset', 'posts_per_page', 'posts_per_archive_page', 'what_to_show', 'showposts', 'nopaging', 'post_type', 'post_status', 'category__in', 'category__not_in', 'category__and', 'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and', 'tag_id'); var $extra_query_vars = array(); var $query_vars; @@ -17,6 +17,10 @@ class WP { $this->public_query_vars[] = $qv; } + function set_query_var($key, $value) { + $this->query_vars[$key] = $value; + } + function parse_request($extra_query_vars = '') { global $wp_rewrite; @@ -176,9 +180,9 @@ class WP { status_header( 404 ); if ( !is_user_logged_in() ) nocache_headers(); - @header('Content-type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset')); + @header('Content-Type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset')); } else if ( empty($this->query_vars['feed']) ) { - @header('Content-type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset')); + @header('Content-Type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset')); } else { // We're showing a feed, so WP is indeed the only thing that last changed if ( $this->query_vars['withcomments'] @@ -507,10 +511,10 @@ class Walker_Page extends Walker { if ( $depth ) $indent = str_repeat("\t", $depth); extract($args, EXTR_SKIP); - $css_class = 'page_item'; + $css_class = 'page_item page-item-'.$page->ID; $_current_page = get_page( $current_page ); if ( $page->ID == $current_page ) - $css_class .= ' current_page_item'; + $css_class .= ' current_page_item '; elseif ( $_current_page && $page->ID == $_current_page->post_parent ) $css_class .= ' current_page_parent'; @@ -557,7 +561,7 @@ class Walker_PageDropdown extends Walker { class Walker_Category extends Walker { var $tree_type = 'category'; - var $db_fields = array ('parent' => 'category_parent', 'id' => 'cat_ID'); //TODO: decouple this + var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); //TODO: decouple this function start_lvl($output, $depth, $args) { if ( 'list' != $args['style'] ) @@ -580,13 +584,13 @@ class Walker_Category extends Walker { function start_el($output, $category, $depth, $args) { extract($args); - $cat_name = attribute_escape( $category->cat_name); + $cat_name = attribute_escape( $category->name); $cat_name = apply_filters( 'list_cats', $cat_name, $category ); - $link = '<a href="' . get_category_link( $category->cat_ID ) . '" '; - if ( $use_desc_for_title == 0 || empty($category->category_description) ) + $link = '<a href="' . get_category_link( $category->term_id ) . '" '; + if ( $use_desc_for_title == 0 || empty($category->description) ) $link .= 'title="' . sprintf(__( 'View all posts filed under %s' ), $cat_name) . '"'; else - $link .= 'title="' . attribute_escape( apply_filters( 'category_description', $category->category_description, $category )) . '"'; + $link .= 'title="' . attribute_escape( apply_filters( 'category_description', $category->description, $category )) . '"'; $link .= '>'; $link .= $cat_name . '</a>'; @@ -596,7 +600,7 @@ class Walker_Category extends Walker { if ( empty($feed_image) ) $link .= '('; - $link .= '<a href="' . get_category_rss_link( 0, $category->cat_ID, $category->category_nicename ) . '"'; + $link .= '<a href="' . get_category_rss_link( 0, $category->term_id, $category->slug ) . '"'; if ( empty($feed) ) $alt = ' alt="' . sprintf(__( 'Feed for all posts filed under %s' ), $cat_name ) . '"'; @@ -619,7 +623,7 @@ class Walker_Category extends Walker { } if ( isset($show_count) && $show_count ) - $link .= ' (' . intval($category->category_count) . ')'; + $link .= ' (' . intval($category->count) . ')'; if ( isset($show_date) && $show_date ) { $link .= ' ' . gmdate('Y-m-d', $category->last_update_timestamp); @@ -630,10 +634,12 @@ class Walker_Category extends Walker { if ( 'list' == $args['style'] ) { $output .= "\t<li"; - if ( $current_category && ($category->cat_ID == $current_category) ) - $output .= ' class="current-cat"'; - elseif ( $_current_category && ($category->cat_ID == $_current_category->category_parent) ) - $output .= ' class="current-cat-parent"'; + $class = 'cat-item cat-item-'.$category->term_id; + if ( $current_category && ($category->term_id == $current_category) ) + $class .= ' current-cat'; + elseif ( $_current_category && ($category->term_id == $_current_category->parent) ) + $class .= ' current-cat-parent'; + $output .= ' class="'.$class.'"'; $output .= ">$link\n"; } else { $output .= "\t$link<br />\n"; @@ -654,19 +660,19 @@ class Walker_Category extends Walker { class Walker_CategoryDropdown extends Walker { var $tree_type = 'category'; - var $db_fields = array ('parent' => 'category_parent', 'id' => 'cat_ID'); //TODO: decouple this + var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); //TODO: decouple this function start_el($output, $category, $depth, $args) { $pad = str_repeat(' ', $depth * 3); - $cat_name = apply_filters('list_cats', $category->cat_name, $category); - $output .= "\t<option value=\"".$category->cat_ID."\""; - if ( $category->cat_ID == $args['selected'] ) + $cat_name = apply_filters('list_cats', $category->name, $category); + $output .= "\t<option value=\"".$category->term_id."\""; + if ( $category->term_id == $args['selected'] ) $output .= ' selected="selected"'; $output .= '>'; $output .= $pad.$cat_name; if ( $args['show_count'] ) - $output .= ' ('. $category->category_count .')'; + $output .= ' ('. $category->count .')'; if ( $args['show_last_update'] ) { $format = 'Y-m-d'; $output .= ' ' . gmdate($format, $category->last_update_timestamp); @@ -687,16 +693,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()); + $defaults = array( + 'what' => 'object', 'action' => false, + 'id' => '0', 'old_id' => false, + 'data' => '', 'supplemental' => array() + ); - $r = array_merge($defaults, $r); - extract($r, EXTR_SKIP); + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); if ( is_wp_error($id) ) { $data = $id; @@ -731,7 +735,7 @@ class WP_Ajax_Response { } function send() { - header('Content-type: text/xml'); + header('Content-Type: text/xml'); echo "<?xml version='1.0' standalone='yes'?><wp_ajax>"; foreach ( $this->responses as $response ) echo $response; diff --git a/wp-includes/comment-template.php b/wp-includes/comment-template.php index 086c782..99fecfe 100644 --- a/wp-includes/comment-template.php +++ b/wp-includes/comment-template.php @@ -223,18 +223,17 @@ function comment_type($commenttxt = 'Comment', $trackbacktxt = 'Trackback', $pin function get_trackback_url() { global $id; - $tb_url = get_option('siteurl') . '/wp-trackback.php?p=' . $id; - - if ( '' != get_option('permalink_structure') ) + if ( '' != get_option('permalink_structure') ) { $tb_url = trailingslashit(get_permalink()) . user_trailingslashit('trackback', 'single_trackback'); - + } else { + $tb_url = get_option('siteurl') . '/wp-trackback.php?p=' . $id; + } return apply_filters('trackback_url', $tb_url); } -function trackback_url( $display = true ) { - if ( $display) - echo get_trackback_url(); - else - return get_trackback_url(); + +function trackback_url($deprecated = true) { // remove backwards compat in 2.4 + if ($deprecated) echo get_trackback_url(); + else return get_trackback_url(); } function trackback_rdf($timezone = 0) { @@ -250,7 +249,7 @@ function trackback_rdf($timezone = 0) { the_permalink(); echo '"'."\n"; echo ' dc:title="'.str_replace('--', '--', wptexturize(strip_tags(get_the_title()))).'"'."\n"; - echo ' trackback:ping="'.trackback_url(0).'"'." />\n"; + echo ' trackback:ping="'.get_trackback_url().'"'." />\n"; echo '</rdf:RDF>'; } } @@ -290,7 +289,7 @@ function comments_template( $file = '/comments.php' ) { // TODO: Use API instead of SELECTs. 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) ) { + } 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); @@ -301,6 +300,7 @@ function comments_template( $file = '/comments.php' ) { // keep $comments for legacy's sake (remember $table*? ;) ) $comments = $wp_query->comments = apply_filters( 'comments_array', $comments, $post->ID ); $wp_query->comment_count = count($wp_query->comments); + update_comment_cache($comments); define('COMMENTS_TEMPLATE', true); $include = apply_filters('comments_template', TEMPLATEPATH . $file ); @@ -363,7 +363,7 @@ function comments_popup_link($zero='No Comments', $one='1 Comment', $more='% Com if (!empty($CSSclass)) { echo ' class="'.$CSSclass.'"'; } - $title = attribute_escape(apply_filters('the_title', get_the_title())); + $title = attribute_escape(get_the_title()); echo ' title="' . sprintf( __('Comment on %s'), $title ) .'">'; comments_number($zero, $one, $more, $number); echo '</a>'; diff --git a/wp-includes/comment.php b/wp-includes/comment.php index 82a00ab..3fedd9b 100644 --- a/wp-includes/comment.php +++ b/wp-includes/comment.php @@ -71,25 +71,28 @@ function get_approved_comments($post_id) { // Retrieves comment data given a comment ID or comment object. // Handles comment caching. function &get_comment(&$comment, $output = OBJECT) { - global $comment_cache, $wpdb; - - if ( empty($comment) ) - return null; + global $wpdb; - if ( is_object($comment) ) { - if ( !isset($comment_cache[$comment->comment_ID]) ) - $comment_cache[$comment->comment_ID] = &$comment; - $_comment = & $comment_cache[$comment->comment_ID]; + if ( empty($comment) ) { + if ( isset($GLOBALS['comment']) ) + $_comment = & $GLOBALS['comment']; + else + $_comment = null; + } elseif ( is_object($comment) ) { + wp_cache_add($comment->comment_ID, $comment, 'comment'); + $_comment = $comment; } else { $comment = (int) $comment; - if ( !isset($comment_cache[$comment]) ) { + if ( isset($GLOBALS['comment']) && ($GLOBALS['comment']->comment_ID == $comment) ) { + $_comment = & $GLOBALS['comment']; + } elseif ( ! $_comment = wp_cache_get($comment, 'comment') ) { $_comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment' LIMIT 1"); - $comment_cache[$comment->comment_ID] = & $_comment; - } else { - $_comment = & $comment_cache[$comment]; + wp_cache_add($_comment->comment_ID, $_comment, 'comment'); } } + $_comment = apply_filters('get_comment', $_comment); + if ( $output == OBJECT ) { return $_comment; } elseif ( $output == ARRAY_A ) { @@ -135,13 +138,13 @@ function get_lastcommentmodified($timezone = 'server') { if ( !isset($cache_lastcommentmodified[$timezone]) ) { switch ( strtolower($timezone)) { case 'gmt': - $lastcommentmodified = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_date_gmt <= '$now' ORDER BY comment_date_gmt DESC LIMIT 1"); + $lastcommentmodified = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_date_gmt <= '$now' AND comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1"); break; case 'blog': - $lastcommentmodified = $wpdb->get_var("SELECT comment_date FROM $wpdb->comments WHERE comment_date_gmt <= '$now' ORDER BY comment_date_gmt DESC LIMIT 1"); + $lastcommentmodified = $wpdb->get_var("SELECT comment_date FROM $wpdb->comments WHERE comment_date_gmt <= '$now' AND comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1"); break; case 'server': - $lastcommentmodified = $wpdb->get_var("SELECT DATE_ADD(comment_date_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->comments WHERE comment_date_gmt <= '$now' ORDER BY comment_date_gmt DESC LIMIT 1"); + $lastcommentmodified = $wpdb->get_var("SELECT DATE_ADD(comment_date_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->comments WHERE comment_date_gmt <= '$now' AND comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1"); break; } $cache_lastcommentmodified[$timezone] = $lastcommentmodified; @@ -170,7 +173,6 @@ function sanitize_comment_cookies() { if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) ) { $comment_author_url = apply_filters('pre_comment_author_url', $_COOKIE['comment_author_url_'.COOKIEHASH]); $comment_author_url = stripslashes($comment_author_url); - $comment_author_url = clean_url($comment_author_url); $_COOKIE['comment_author_url_'.COOKIEHASH] = $comment_author_url; } } @@ -188,16 +190,7 @@ function wp_allow_comment($commentdata) { if ( $wpdb->get_var($dupe) ) wp_die( __('Duplicate comment detected; it looks as though you\'ve already said that!') ); - // Simple flood-protection - if ( $lasttime = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_author_IP = '$comment_author_IP' OR comment_author_email = '$comment_author_email' ORDER BY comment_date DESC LIMIT 1") ) { - $time_lastcomment = mysql2date('U', $lasttime); - $time_newcomment = mysql2date('U', $comment_date_gmt); - $flood_die = apply_filters('comment_flood_filter', false, $time_lastcomment, $time_newcomment); - if ( $flood_die ) { - do_action('comment_flood_trigger', $time_lastcomment, $time_newcomment); - wp_die( __('You are posting comments too quickly. Slow down.') ); - } - } + do_action( 'check_comment_flood', $comment_author_IP, $comment_author_email, $comment_date_gmt ); if ( $user_id ) { $userdata = get_userdata($user_id); @@ -222,6 +215,18 @@ function wp_allow_comment($commentdata) { return $approved; } +function check_comment_flood_db( $ip, $email, $date ) { + global $wpdb; + if ( $lasttime = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_author_IP = '$ip' OR comment_author_email = '$email' ORDER BY comment_date DESC LIMIT 1") ) { + $time_lastcomment = mysql2date('U', $lasttime); + $time_newcomment = mysql2date('U', $date); + $flood_die = apply_filters('comment_flood_filter', false, $time_lastcomment, $time_newcomment); + if ( $flood_die ) { + do_action('comment_flood_trigger', $time_lastcomment, $time_newcomment); + wp_die( __('You are posting comments too quickly. Slow down.') ); + } + } +} function wp_blacklist_check($author, $email, $url, $comment, $user_ip, $user_agent) { global $wpdb; @@ -281,6 +286,8 @@ function wp_delete_comment($comment_id) { if ( $post_id && $comment->comment_approved == 1 ) wp_update_comment_count($post_id); + clean_comment_cache($comment_id); + do_action('wp_set_comment_status', $comment_id, 'delete'); return true; } @@ -289,15 +296,19 @@ function wp_delete_comment($comment_id) { function wp_get_comment_status($comment_id) { global $wpdb; - $result = $wpdb->get_var("SELECT comment_approved FROM $wpdb->comments WHERE comment_ID='$comment_id' LIMIT 1"); + $comment = get_comment($comment_id); + if ( !$comment ) + return false; - if ( $result == NULL ) + $approved = $comment->comment_approved; + + if ( $approved == NULL ) return 'deleted'; - elseif ( $result == '1' ) + elseif ( $approved == '1' ) return 'approved'; - elseif ( $result == '0' ) + elseif ( $approved == '0' ) return 'unapproved'; - elseif ( $result == 'spam' ) + elseif ( $approved == 'spam' ) return 'spam'; else return false; @@ -434,9 +445,12 @@ function wp_set_comment_status($comment_id, $comment_status) { if ( !$wpdb->query($query) ) return false; + clean_comment_cache($comment_id); + do_action('wp_set_comment_status', $comment_id, $comment_status); $comment = get_comment($comment_id); wp_update_comment_count($comment->comment_post_ID); + return true; } @@ -475,6 +489,8 @@ function wp_update_comment($commentarr) { WHERE comment_ID = $comment_ID" ); $rval = $wpdb->rows_affected; + + clean_comment_cache($comment_ID); wp_update_comment_count($comment_post_ID); do_action('edit_comment', $comment_ID); return $rval; @@ -486,17 +502,21 @@ function wp_update_comment_count($post_id) { $post_id = (int) $post_id; if ( !$post_id ) return false; - $count = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = '$post_id' AND comment_approved = '1'"); - $wpdb->query("UPDATE $wpdb->posts SET comment_count = $count WHERE ID = '$post_id'"); - $comment_count_cache[$post_id] = $count; + if ( !$post = get_post($post_id) ) + return false; + + $old = (int) $post->comment_count; + $new = (int) $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = '$post_id' AND comment_approved = '1'"); + $wpdb->query("UPDATE $wpdb->posts SET comment_count = '$new' WHERE ID = '$post_id'"); + $comment_count_cache[$post_id] = $new; - $post = get_post($post_id); if ( 'page' == $post->post_type ) clean_page_cache( $post_id ); else clean_post_cache( $post_id ); - do_action('edit_post', $post_id); + do_action('wp_update_comment_count', $post_id, $new, $old); + do_action('edit_post', $post_id, $post); return true; } @@ -672,9 +692,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); @@ -690,10 +708,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 @@ -717,16 +731,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); @@ -736,15 +746,10 @@ function pingback($content, $post_ID) { // when set to true, this outputs debug messages by itself $client->debug = false; - if ( $client->query('pingback.ping', $pagelinkedfrom, $pagelinkedto ) ) + if ( $client->query('pingback.ping', $pagelinkedfrom, $pagelinkedto) || ( isset($client->error->code) && 48 == $client->error->code ) ) // Already registered 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); } @@ -781,16 +786,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 ); @@ -815,4 +810,17 @@ function weblog_ping($server = '', $path = '') { $client->query('weblogUpdates.ping', get_option('blogname'), $home); } +// +// Cache +// + +function clean_comment_cache($id) { + wp_cache_delete($id, 'comment'); +} + +function update_comment_cache($comments) { + foreach ( $comments as $comment ) + wp_cache_add($comment->comment_ID, $comment, 'comment'); +} + ?> diff --git a/wp-includes/compat.php b/wp-includes/compat.php index b346fdd..a4914b5 100644 --- a/wp-includes/compat.php +++ b/wp-includes/compat.php @@ -73,7 +73,7 @@ if (!defined('CASE_UPPER')) { * @link http://php.net/function.array_change_key_case * @author Stephan Schmidt <schst@php.net> * @author Aidan Lister <aidan@php.net> - * @version $Revision: 5187 $ + * @version $Revision: 6070 $ * @since PHP 4.2.0 * @require PHP 4.0.0 (user_error) */ @@ -98,18 +98,40 @@ if (!function_exists('array_change_key_case')) { } } -// From php.net -if(!function_exists('http_build_query')) { - function http_build_query( $formdata, $numeric_prefix = null, $key = null ) { - $res = array(); - foreach ((array)$formdata as $k=>$v) { - $tmp_key = urlencode(is_int($k) ? $numeric_prefix.$k : $k); - if ($key) $tmp_key = $key.'['.$tmp_key.']'; - $res[] = ( ( is_array($v) || is_object($v) ) ? http_build_query($v, null, $tmp_key) : $tmp_key."=".urlencode($v) ); - } - $separator = ini_get('arg_separator.output'); - return implode($separator, $res); - } +if (!function_exists('http_build_query')) { + function http_build_query($data, $prefix=null, $sep=null) { + return _http_build_query($data, $prefix, $sep); + } +} + +// from php.net (modified by Mark Jaquith to behave like the native PHP5 function) +function _http_build_query($data, $prefix=null, $sep=null, $key='', $urlencode=true) { + $ret = array(); + + foreach ( (array) $data as $k => $v ) { + if ( $urlencode) + $k = urlencode($k); + if ( is_int($k) && $prefix != null ) + $k = $prefix.$k; + if ( !empty($key) ) + $k = $key . '%5B' . $k . '%5D'; + if ( $v === NULL ) + continue; + elseif ( $v === FALSE ) + $v = '0'; + + if ( is_array($v) || is_object($v) ) + array_push($ret,_http_build_query($v, '', $sep, $k, $urlencode)); + elseif ( $urlencode ) + array_push($ret, $k.'='.urlencode($v)); + else + array_push($ret, $k.'='.$v); + } + + if ( NULL === $sep ) + $sep = ini_get('arg_separator.output'); + + return implode($sep, $ret); } if ( !function_exists('_') ) { diff --git a/wp-includes/cron.php b/wp-includes/cron.php index f81c6ad..1c17c76 100644 --- a/wp-includes/cron.php +++ b/wp-includes/cron.php @@ -83,18 +83,20 @@ function spawn_cron() { $cron_url = get_option( 'siteurl' ) . '/wp-cron.php';
$parts = parse_url( $cron_url );
-
+
if ($parts['scheme'] == 'https') {
// support for SSL was added in 4.3.0
if (version_compare(phpversion(), '4.3.0', '>=') && function_exists('openssl_open')) {
- $argyle = @fsockopen('ssl://' . $parts['host'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01);
+ $port = isset($parts['port']) ? $parts['port'] : 443;
+ $argyle = @fsockopen('ssl://' . $parts['host'], $port, $errno, $errstr, 0.01);
} else {
return false;
}
} else {
- $argyle = @ fsockopen( $parts['host'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01 );
+ $port = isset($parts['port']) ? $parts['port'] : 80;
+ $argyle = @ fsockopen( $parts['host'], $port, $errno, $errstr, 0.01 );
}
-
+
if ( $argyle )
fputs( $argyle,
"GET {$parts['path']}?check=" . wp_hash('187425') . " HTTP/1.0\r\n"
diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php index 1613b33..53060b1 100644 --- a/wp-includes/default-filters.php +++ b/wp-includes/default-filters.php @@ -1,135 +1,102 @@ <?php -// Some default filters -add_filter('bloginfo','wp_specialchars'); -add_filter('category_description', 'wptexturize'); -add_filter('list_cats', 'wptexturize'); -add_filter('comment_author', 'wptexturize'); -add_filter('comment_text', 'wptexturize'); -add_filter('single_post_title', 'wptexturize'); -add_filter('the_title', 'wptexturize'); -add_filter('the_content', 'wptexturize'); -add_filter('the_excerpt', 'wptexturize'); -add_filter('bloginfo', 'wptexturize'); - -// Comments, trackbacks, pingbacks -add_filter('pre_comment_author_name', 'strip_tags'); -add_filter('pre_comment_author_name', 'trim'); -add_filter('pre_comment_author_name', 'wp_specialchars', 30); - -add_filter('pre_comment_author_email', 'trim'); -add_filter('pre_comment_author_email', 'sanitize_email'); - -add_filter('pre_comment_author_url', 'strip_tags'); -add_filter('pre_comment_author_url', 'trim'); -add_filter('pre_comment_author_url', 'clean_url'); - -add_filter('pre_comment_content', 'wp_rel_nofollow', 15); -add_filter('pre_comment_content', 'balanceTags', 30); - -add_filter('pre_comment_author_name', 'wp_filter_kses'); -add_filter('pre_comment_author_email', 'wp_filter_kses'); -add_filter('pre_comment_author_url', 'wp_filter_kses'); - -add_action('comment_form', 'wp_comment_form_unfiltered_html_nonce'); - -// Default filters for these functions -add_filter('comment_author', 'wptexturize'); -add_filter('comment_author', 'convert_chars'); -add_filter('comment_author', 'wp_specialchars'); - -add_filter('comment_email', 'antispambot'); - -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', 9); -add_filter('comment_text', 'force_balance_tags', 25); -add_filter('comment_text', 'wpautop', 30); -add_filter('comment_text', 'convert_smilies', 20); - -add_filter('comment_excerpt', 'convert_chars'); - -// Categories -add_filter('pre_category_name', 'strip_tags'); -add_filter('pre_category_name', 'trim'); -add_filter('pre_category_name', 'wp_filter_kses'); -add_filter('pre_category_name', 'wp_specialchars', 30); -add_filter('pre_category_description', 'wp_filter_kses'); - -//Links -add_filter('pre_link_name', 'strip_tags'); -add_filter('pre_link_name', 'trim'); -add_filter('pre_link_name', 'wp_filter_kses'); -add_filter('pre_link_name', 'wp_specialchars', 30); -add_filter('pre_link_description', 'wp_filter_kses'); -add_filter('pre_link_notes', 'wp_filter_kses'); -add_filter('pre_link_url', 'strip_tags'); -add_filter('pre_link_url', 'trim'); -add_filter('pre_link_url', 'clean_url'); -add_filter('pre_link_image', 'strip_tags'); -add_filter('pre_link_image', 'trim'); -add_filter('pre_link_image', 'clean_url'); -add_filter('pre_link_rss', 'strip_tags'); -add_filter('pre_link_rss', 'trim'); -add_filter('pre_link_rss', 'clean_url'); -add_filter('pre_link_target', 'strip_tags'); -add_filter('pre_link_target', 'trim'); -add_filter('pre_link_target', 'wp_filter_kses'); -add_filter('pre_link_target', 'wp_specialchars', 30); -add_filter('pre_link_rel', 'strip_tags'); -add_filter('pre_link_rel', 'trim'); -add_filter('pre_link_rel', 'wp_filter_kses'); -add_filter('pre_link_rel', 'wp_specialchars', 30); - -// Users -add_filter('pre_user_display_name', 'strip_tags'); -add_filter('pre_user_display_name', 'trim'); -add_filter('pre_user_display_name', 'wp_filter_kses'); -add_filter('pre_user_display_name', 'wp_specialchars', 30); -add_filter('pre_user_first_name', 'strip_tags'); -add_filter('pre_user_first_name', 'trim'); -add_filter('pre_user_first_name', 'wp_filter_kses'); -add_filter('pre_user_first_name', 'wp_specialchars', 30); -add_filter('pre_user_last_name', 'strip_tags'); -add_filter('pre_user_last_name', 'trim'); -add_filter('pre_user_last_name', 'wp_filter_kses'); -add_filter('pre_user_last_name', 'wp_specialchars', 30); -add_filter('pre_user_nickname', 'strip_tags'); -add_filter('pre_user_nickname', 'trim'); -add_filter('pre_user_nickname', 'wp_filter_kses'); -add_filter('pre_user_nickname', 'wp_specialchars', 30); -add_filter('pre_user_description', 'trim'); -add_filter('pre_user_description', 'wp_filter_kses'); -add_filter('pre_user_url', 'strip_tags'); -add_filter('pre_user_url', 'trim'); -add_filter('pre_user_url', 'clean_url'); -add_filter('pre_user_email', 'trim'); -add_filter('pre_user_email', 'sanitize_email'); +// Strip, trim, kses, special chars for string saves +$filters = array('pre_term_name', 'pre_comment_author_name', 'pre_link_name', 'pre_link_target', + 'pre_link_rel', 'pre_user_display_name', 'pre_user_first_name', 'pre_user_last_name', + 'pre_user_nickname'); +foreach ( $filters as $filter ) { + add_filter($filter, 'strip_tags'); + add_filter($filter, 'trim'); + add_filter($filter, 'wp_filter_kses'); + add_filter($filter, 'wp_specialchars', 30); +} + +// Kses only for textarea saves +$filters = array('pre_term_description', 'pre_link_description', 'pre_link_notes', 'pre_user_description'); +foreach ( $filters as $filter ) { + add_filter($filter, 'wp_filter_kses'); +} + +// Email +$filters = array('pre_comment_author_email', 'pre_user_email'); +foreach ( $filters as $filter ) { + add_filter($filter, 'trim'); + add_filter($filter, 'sanitize_email'); + add_filter($filter, 'wp_filter_kses'); +} + +// URL +$filters = array('pre_comment_author_url', 'pre_user_url', 'pre_link_url', 'pre_link_image', + 'pre_link_rss', 'comment_url'); +foreach ( $filters as $filter ) { + add_filter($filter, 'strip_tags'); + add_filter($filter, 'trim'); + add_filter($filter, 'clean_url'); + add_filter($filter, 'wp_filter_kses'); +} + +// Slugs +$filters = array('pre_term_slug'); +foreach ( $filters as $filter ) { + add_filter($filter, 'sanitize_title'); +} // Places to balance tags on input -add_filter('content_save_pre', 'balanceTags', 50); -add_filter('excerpt_save_pre', 'balanceTags', 50); -add_filter('comment_save_pre', 'balanceTags', 50); - -// Misc. title, content, and excerpt filters +$filters = array('content_save_pre', 'excerpt_save_pre', 'comment_save_pre', 'pre_comment_content'); +foreach ( $filters as $filter ) { + add_filter( $filter, 'balanceTags', 50); +} + +// Format strings for display. +$filters = array('comment_author', 'term_name', 'link_name', 'link_description', + 'link_notes', 'bloginfo', 'wp_title'); +foreach ( $filters as $filter ) { + add_filter($filter, 'wptexturize'); + add_filter($filter, 'convert_chars'); + add_filter($filter, 'wp_specialchars'); +} + +// Format text area for display. +$filters = array('term_description'); +foreach ( $filters as $filter ) { + add_filter($filter, 'wptexturize'); + add_filter($filter, 'convert_chars'); + add_filter($filter, 'wpautop'); +} + +// Format for RSS +$filters = array('term_name_rss'); +foreach ( $filters as $filter ) { + add_filter($filter, 'convert_chars'); +} + +// Display filters +add_filter('the_title', 'wptexturize'); add_filter('the_title', 'convert_chars'); add_filter('the_title', 'trim'); +add_filter('the_content', 'wptexturize'); add_filter('the_content', 'convert_smilies'); add_filter('the_content', 'convert_chars'); add_filter('the_content', 'wpautop'); +add_filter('the_excerpt', 'wptexturize'); add_filter('the_excerpt', 'convert_smilies'); add_filter('the_excerpt', 'convert_chars'); add_filter('the_excerpt', 'wpautop'); add_filter('get_the_excerpt', 'wp_trim_excerpt'); -add_filter('sanitize_title', 'sanitize_title_with_dashes'); +add_filter('comment_text', 'wptexturize'); +add_filter('comment_text', 'convert_chars'); +add_filter('comment_text', 'make_clickable', 9); +add_filter('comment_text', 'force_balance_tags', 25); +add_filter('comment_text', 'convert_smilies', 20); +add_filter('comment_text', 'wpautop', 30); -add_filter('wp_title', 'wp_specialchars'); +add_filter('comment_excerpt', 'convert_chars'); + +add_filter('list_cats', 'wptexturize'); +add_filter('single_post_title', 'wptexturize'); // RSS filters add_filter('the_title_rss', 'strip_tags'); @@ -139,8 +106,8 @@ add_filter('the_content_rss', 'ent2ncr', 8); add_filter('the_excerpt_rss', 'convert_chars'); add_filter('the_excerpt_rss', 'ent2ncr', 8); add_filter('comment_author_rss', 'ent2ncr', 8); -add_filter('comment_text_rss', 'wp_specialchars'); add_filter('comment_text_rss', 'ent2ncr', 8); +add_filter('comment_text_rss', 'wp_specialchars'); add_filter('bloginfo_rss', 'ent2ncr', 8); add_filter('the_author', 'ent2ncr', 8); @@ -151,11 +118,12 @@ add_filter('option_home', '_config_wp_home'); add_filter('option_siteurl', '_config_wp_siteurl'); add_filter('mce_plugins', '_mce_load_rtl_plugin'); add_filter('mce_buttons', '_mce_add_direction_buttons'); - -// Redirect Old Slugs -add_action('template_redirect', 'wp_old_slug_redirect'); -add_action('edit_post', 'wp_check_for_changed_slugs'); -add_action('edit_form_advanced', 'wp_remember_old_slug'); +add_filter('pre_kses', 'wp_pre_kses_less_than'); +add_filter('sanitize_title', 'sanitize_title_with_dashes'); +add_action('check_comment_flood', 'check_comment_flood_db', 10, 3); +add_filter('comment_flood_filter', 'wp_throttle_comment_flood', 10, 3); +add_filter('pre_comment_content', 'wp_rel_nofollow', 15); +add_filter('comment_email', 'antispambot'); // Actions add_action('wp_head', 'rsd_link'); @@ -177,5 +145,15 @@ 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); +add_action('publish_post', '_publish_post_hook', 5, 1); +add_action('future_post', '_future_post_hook', 5, 2); +add_action('future_page', '_future_post_hook', 5, 2); +add_action('save_post', '_save_post_hook', 5, 2); +add_action('transition_post_status', '_transition_post_status', 5, 3); +add_action('comment_form', 'wp_comment_form_unfiltered_html_nonce'); +// Redirect Old Slugs +add_action('template_redirect', 'wp_old_slug_redirect'); +add_action('edit_post', 'wp_check_for_changed_slugs'); +add_action('edit_form_advanced', 'wp_remember_old_slug'); ?> diff --git a/wp-includes/deprecated.php b/wp-includes/deprecated.php index c93abe3..67ef9f9 100644 --- a/wp-includes/deprecated.php +++ b/wp-includes/deprecated.php @@ -56,7 +56,7 @@ function start_wp() { function the_category_ID($echo = true) { // Grab the first cat in the list. $categories = get_the_category(); - $cat = $categories[0]->cat_ID; + $cat = $categories[0]->term_id; if ( $echo ) echo $cat; @@ -217,12 +217,10 @@ function get_linksbyname($cat_name = "noname", $before = '', $after = '<br />', $limit = -1, $show_updated = 0) { global $wpdb; $cat_id = -1; - $results = $wpdb->get_results("SELECT cat_ID FROM $wpdb->categories WHERE cat_name='$cat_name'"); - if ($results) { - foreach ($results as $result) { - $cat_id = $result->cat_ID; - } - } + $cat = get_term_by('name', $cat_name, 'link_category'); + if ( $cat ) + $cat_id = $cat->term_id; + get_links($cat_id, $before, $after, $between, $show_images, $orderby, $show_description, $show_rating, $limit, $show_updated); } @@ -235,10 +233,10 @@ function get_linksbyname($cat_name = "noname", $before = '', $after = '<br />', function wp_get_linksbyname($category, $args = '') { global $wpdb; - $cat_id = $wpdb->get_var("SELECT cat_ID FROM $wpdb->categories WHERE cat_name='$category' LIMIT 1"); - - if (! $cat_id) - return; + $cat = get_term_by('name', $cat_name, 'link_category'); + if ( !$cat ) + return false; + $cat_id = $cat->term_id; $args = add_query_arg('category', $cat_id, $args); wp_get_links($args); @@ -263,17 +261,13 @@ function wp_get_linksbyname($category, $args = '') { ** echo '<li>'.$link->link_name.'</li>'; ** } **/ -// Deprecate in favor of get_linkz(). function get_linkobjectsbyname($cat_name = "noname" , $orderby = 'name', $limit = -1) { global $wpdb; $cat_id = -1; - //$results = $wpdb->get_results("SELECT cat_id FROM $wpdb->linkcategories WHERE cat_name='$cat_name'"); - // TODO: Fix me. - if ($results) { - foreach ($results as $result) { - $cat_id = $result->cat_id; - } - } + $cat = get_term_by('name', $cat_name, 'link_category'); + if ( $cat ) + $cat_id = $cat->term_id; + return get_linkobjects($cat_id, $orderby, $limit); } @@ -313,41 +307,17 @@ function get_linkobjectsbyname($cat_name = "noname" , $orderby = 'name', $limit ** link_notes **/ // Deprecate in favor of get_linkz(). -function get_linkobjects($category = -1, $orderby = 'name', $limit = -1) { +function get_linkobjects($category = 0, $orderby = 'name', $limit = 0) { global $wpdb; - $sql = "SELECT * FROM $wpdb->links WHERE link_visible = 'Y'"; - if ($category != -1) { - $sql .= " AND link_category = $category "; - } - if ($orderby == '') - $orderby = 'id'; - if (substr($orderby,0,1) == '_') { - $direction = ' DESC'; - $orderby = substr($orderby,1); - } - if (strcasecmp('rand',$orderby) == 0) { - $orderby = 'rand()'; - } else { - $orderby = " link_" . $orderby; - } - $sql .= ' ORDER BY ' . $orderby; - $sql .= $direction; - /* The next 2 lines implement LIMIT TO processing */ - if ($limit != -1) - $sql .= " LIMIT $limit"; - - $results = $wpdb->get_results($sql); - if ($results) { - foreach ($results as $result) { - $result->link_url = $result->link_url; - $result->link_name = $result->link_name; - $result->link_description = $result->link_description; - $result->link_notes = $result->link_notes; - $newresults[] = $result; - } + $links = get_bookmarks("category=$category&orderby=$orderby&limit=$limit"); + + $links_array = array(); + foreach ($links as $link) { + $links_array[] = $link; } - return $newresults; + + return $links_array; } /** function get_linksbyname_withrating() @@ -427,10 +397,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'])) @@ -512,4 +479,254 @@ function get_settings($option) { return get_option($option); } +// Use the_permalink(). +function permalink_link() { + the_permalink(); +} + +// Use the_permalink_rss() +function permalink_single_rss($file = '') { + the_permalink_rss(); +} + +/** function wp_get_links() + ** Gets the links associated with category n. + ** Parameters: + ** category (no default) - The category to use. + ** or: + ** a query string + **/ +function wp_get_links($args = '') { + global $wpdb; + + if ( strpos( $args, '=' ) === false ) { + $cat_id = $args; + $args = add_query_arg( 'category', $cat_id, $args ); + } + + $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, EXTR_SKIP ); + + return get_links($category, $before, $after, $between, $show_images, $orderby, $show_description, $show_rating, $limit, $show_updated, $echo); +} // end wp_get_links + +/** function get_links() + ** Gets the links associated with category n. + ** Parameters: + ** category (default -1) - The category to use. If no category supplied + ** uses all + ** before (default '') - the html to output before the link + ** after (default '<br />') - the html to output after the link + ** between (default ' ') - the html to output between the link/image + ** and its description. Not used if no image or show_images == true + ** show_images (default true) - whether to show images (if defined). + ** orderby (default 'id') - the order to output the links. E.g. 'id', 'name', + ** 'url', 'description', or 'rating'. Or maybe owner. If you start the + ** name with an underscore the order will be reversed. + ** You can also specify 'rand' as the order which will return links in a + ** random order. + ** show_description (default true) - whether to show the description if + ** show_images=false/not defined . + ** show_rating (default false) - show rating stars/chars + ** limit (default -1) - Limit to X entries. If not specified, all entries + ** are shown. + ** show_updated (default 0) - whether to show last updated timestamp + ** echo (default true) - whether to echo the results, or return them instead + */ +function get_links($category = -1, + $before = '', + $after = '<br />', + $between = ' ', + $show_images = true, + $orderby = 'name', + $show_description = true, + $show_rating = false, + $limit = -1, + $show_updated = 1, + $echo = true) { + + global $wpdb; + + $order = 'ASC'; + if ( substr($orderby, 0, 1) == '_' ) { + $order = 'DESC'; + $orderby = substr($orderby, 1); + } + + if ( $category == -1 ) //get_bookmarks uses '' to signify all categories + $category = ''; + + $results = get_bookmarks("category=$category&orderby=$orderby&order=$order&show_updated=$show_updated&limit=$limit"); + + if ( !$results ) + return; + + $output = ''; + + foreach ( (array) $results as $row ) { + if ( !isset($row->recently_updated) ) + $row->recently_updated = false; + $output .= $before; + if ( $show_updated && $row->recently_updated ) + $output .= get_option('links_recently_updated_prepend'); + $the_link = '#'; + if ( !empty($row->link_url) ) + $the_link = clean_url($row->link_url); + $rel = $row->link_rel; + if ( '' != $rel ) + $rel = ' rel="' . $rel . '"'; + + $desc = attribute_escape(sanitize_bookmark_field('link_description', $row->link_description, $row->link_id, 'display')); + $name = attribute_escape(sanitize_bookmark_field('link_name', $row->link_name, $row->link_id, 'display')); + $title = $desc; + + if ( $show_updated ) + if (substr($row->link_updated_f, 0, 2) != '00') + $title .= ' ('.__('Last updated') . ' ' . date(get_option('links_updated_date_format'), $row->link_updated_f + (get_option('gmt_offset') * 3600)) . ')'; + + if ( '' != $title ) + $title = ' title="' . $title . '"'; + + $alt = ' alt="' . $name . '"'; + + $target = $row->link_target; + if ( '' != $target ) + $target = ' target="' . $target . '"'; + + $output .= '<a href="' . $the_link . '"' . $rel . $title . $target. '>'; + + if ( $row->link_image != null && $show_images ) { + if ( strpos($row->link_image, 'http') !== false ) + $output .= "<img src=\"$row->link_image\" $alt $title />"; + else // If it's a relative path + $output .= "<img src=\"" . get_option('siteurl') . "$row->link_image\" $alt $title />"; + } else { + $output .= $name; + } + + $output .= '</a>'; + + if ( $show_updated && $row->recently_updated ) + $output .= get_option('links_recently_updated_append'); + + if ( $show_description && '' != $desc ) + $output .= $between . $desc; + + if ($show_rating) { + $output .= $between . get_linkrating($row); + } + + $output .= "$after\n"; + } // end while + + if ( !$echo ) + return $output; + echo $output; +} + +/* + * function get_links_list() + * + * added by Dougal + * + * Output a list of all links, listed by category, using the + * settings in $wpdb->linkcategories and output it as a nested + * HTML unordered list. + * + * Parameters: + * order (default 'name') - Sort link categories by 'name' or 'id' + * hide_if_empty (default true) - Supress listing empty link categories + */ +function get_links_list($order = 'name', $hide_if_empty = 'obsolete') { + $order = strtolower($order); + + // Handle link category sorting + $direction = 'ASC'; + if ( '_' == substr($order,0,1) ) { + $direction = 'DESC'; + $order = substr($order,1); + } + + if ( !isset($direction) ) + $direction = ''; + + $cats = get_categories("type=link&orderby=$order&order=$direction&hierarchical=0"); + + // Display each category + if ( $cats ) { + foreach ( (array) $cats as $cat ) { + // Handle each category. + + // Display the category name + echo ' <li id="linkcat-' . $cat->term_id . '" class="linkcat"><h2>' . apply_filters('link_category', $cat->name ) . "</h2>\n\t<ul>\n"; + // Call get_links() with all the appropriate params + get_links($cat->term_id, '<li>', "</li>", "\n", true, 'name', false); + + // Close the last category + echo "\n\t</ul>\n</li>\n"; + } + } +} + + +/** function links_popup_script() + ** This function contributed by Fullo -- http://sprite.csr.unibo.it/fullo/ + ** Show the link to the links popup and the number of links + ** Parameters: + ** text (default Links) - the text of the link + ** width (default 400) - the width of the popup window + ** height (default 400) - the height of the popup window + ** file (default linkspopup.php) - the page to open in the popup window + ** count (default true) - the number of links in the db + */ +function links_popup_script($text = 'Links', $width=400, $height=400, $file='links.all.php', $count = true) { + if ( $count ) + $counts = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->links"); + + $javascript = "<a href=\"#\" onclick=\"javascript:window.open('$file?popup=1', '_blank', 'width=$width,height=$height,scrollbars=yes,status=no'); return false\">"; + $javascript .= $text; + + if ( $count ) + $javascript .= " ($counts)"; + + $javascript .= "</a>\n\n"; + echo $javascript; +} + + +function get_linkrating($link) { + return sanitize_bookmark_field('link_rating', $link->link_rating, $link->link_id, 'display'); +} + +/** function get_linkcatname() + ** Gets the name of category n. + ** Parameters: id (default 0) - The category to get. If no category supplied + ** uses 0 + */ +function get_linkcatname($id = 0) { + $id = (int) $id; + + if ( empty($id) ) + return ''; + + $cats = wp_get_link_cats($id); + + if ( empty($cats) || ! is_array($cats) ) + return ''; + + $cat_id = (int) $cats[0]; // Take the first cat. + + $cat = get_category($cat_id); + return $cat->name; +} + ?> diff --git a/wp-includes/feed-atom-comments.php b/wp-includes/feed-atom-comments.php index 0cde6e7..ee9a73b 100644 --- a/wp-includes/feed-atom-comments.php +++ b/wp-includes/feed-atom-comments.php @@ -7,7 +7,7 @@ echo '<?xml version="1.0" encoding="' . get_option('blog_charset') . '" ?' . '>' xml:lang="<?php echo get_option('rss_language'); ?>" <?php do_action('atom_ns'); ?> > - <title type="text"><?php + <title type="text"><?php if ( is_singular() ) printf(__('Comments on: %s'), get_the_title_rss()); elseif ( is_search() ) @@ -33,7 +33,6 @@ if ( have_comments() ) : while ( have_comments() ) : the_comment(); <title><?php if ( !is_singular() ) { $title = get_the_title($comment_post->ID); - $title = apply_filters('the_title', $title); $title = apply_filters('the_title_rss', $title); printf(__('Comment on %1$s by %2$s'), $title, get_comment_author_rss()); } else { diff --git a/wp-includes/feed-atom.php b/wp-includes/feed-atom.php index 2eb7c2f..f80f48f 100644 --- a/wp-includes/feed-atom.php +++ b/wp-includes/feed-atom.php @@ -1,5 +1,5 @@ <?php -header('Content-type: application/atom+xml; charset=' . get_option('blog_charset'), true); +header('Content-Type: application/atom+xml; charset=' . get_option('blog_charset'), true); $more = 1; ?> @@ -26,17 +26,19 @@ $more = 1; <entry> <author> <name><?php the_author() ?></name> + <?php $author_url = get_the_author_url(); if ( !empty($author_url) ) : ?> <uri><?php the_author_url()?></uri> + <?php endif; ?> </author> <title type="<?php html_type_rss(); ?>"><![CDATA[<?php the_title_rss() ?>]]></title> - <link rel="alternate" type="text/html" href="<?php permalink_single_rss() ?>" /> + <link rel="alternate" type="text/html" href="<?php the_permalink_rss() ?>" /> <id><?php the_guid(); ?></id> - <updated><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></updated> + <updated><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></updated> <published><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></published> <?php the_category_rss('atom') ?> <summary type="<?php html_type_rss(); ?>"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary> <?php if ( !get_option('rss_use_excerpt') ) : ?> - <content type="<?php html_type_rss(); ?>" xml:base="<?php permalink_single_rss() ?>"><![CDATA[<?php the_content('', 0, '') ?>]]></content> + <content type="<?php html_type_rss(); ?>" xml:base="<?php the_permalink_rss() ?>"><![CDATA[<?php the_content('', 0, '') ?>]]></content> <?php endif; ?> <?php atom_enclosure(); ?> <?php do_action('atom_entry'); ?> diff --git a/wp-includes/feed-rdf.php b/wp-includes/feed-rdf.php index d1ac458..1f92b23 100644 --- a/wp-includes/feed-rdf.php +++ b/wp-includes/feed-rdf.php @@ -1,5 +1,5 @@ <?php -header('Content-type: application/rdf+xml; charset=' . get_option('blog_charset'), true); +header('Content-Type: application/rdf+xml; charset=' . get_option('blog_charset'), true); $more = 1; ?> @@ -27,15 +27,15 @@ $more = 1; <items> <rdf:Seq> <?php while (have_posts()): the_post(); ?> - <rdf:li rdf:resource="<?php permalink_single_rss() ?>"/> + <rdf:li rdf:resource="<?php the_permalink_rss() ?>"/> <?php endwhile; ?> </rdf:Seq> </items> </channel> <?php rewind_posts(); while (have_posts()): the_post(); ?> -<item rdf:about="<?php permalink_single_rss() ?>"> +<item rdf:about="<?php the_permalink_rss() ?>"> <title><?php the_title_rss() ?></title> - <link><?php permalink_single_rss() ?></link> + <link><?php the_permalink_rss() ?></link> <dc:date><?php echo mysql2date('Y-m-d\TH:i:s\Z', $post->post_date_gmt, false); ?></dc:date> <dc:creator><?php the_author() ?></dc:creator> <?php the_category_rss('rdf') ?> diff --git a/wp-includes/feed-rss.php b/wp-includes/feed-rss.php index 447dd59..469e4bc 100644 --- a/wp-includes/feed-rss.php +++ b/wp-includes/feed-rss.php @@ -1,5 +1,5 @@ <?php -header('Content-type: text/xml; charset=' . get_option('blog_charset'), true); +header('Content-Type: text/xml; charset=' . get_option('blog_charset'), true); $more = 1; ?> @@ -23,7 +23,7 @@ $more = 1; <?php } else { // use content ?> <description><?php the_content_rss('', 0, '', get_option('rss_excerpt_length')) ?></description> <?php } ?> - <link><?php permalink_single_rss() ?></link> + <link><?php the_permalink_rss() ?></link> <?php do_action('rss_item'); ?> </item> <?php endwhile; ?> diff --git a/wp-includes/feed-rss2-comments.php b/wp-includes/feed-rss2-comments.php index adb2930..7bd5ae2 100644 --- a/wp-includes/feed-rss2-comments.php +++ b/wp-includes/feed-rss2-comments.php @@ -1,10 +1,10 @@ <?php -header('Content-type: text/xml;charset=' . get_option('blog_charset'), true); +header('Content-Type: text/xml;charset=' . get_option('blog_charset'), true); -echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; +echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?> <!-- generator="wordpress/<?php echo $wp_version ?>" --> -<rss version="2.0" +<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" > @@ -17,12 +17,12 @@ echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; else printf(__('Comments for %s'), get_bloginfo_rss( 'name' ) . get_wp_title_rss()); ?></title> - <link><?php (is_single()) ? permalink_single_rss() : bloginfo_rss("url") ?></link> + <link><?php (is_single()) ? the_permalink_rss() : bloginfo_rss("url") ?></link> <description><?php bloginfo_rss("description") ?></description> <pubDate><?php echo gmdate('r'); ?></pubDate> <generator>http://wordpress.org/?v=<?php echo $wp_version ?></generator> - -<?php + <?php do_action('commentsrss2_head'); ?> +<?php if ( have_comments() ) : while ( have_comments() ) : the_comment(); $comment_post = get_post($comment->comment_post_ID); get_post_custom($comment_post->ID); @@ -31,7 +31,6 @@ if ( have_comments() ) : while ( have_comments() ) : the_comment(); <title><?php if ( !is_singular() ) { $title = get_the_title($comment_post->ID); - $title = apply_filters('the_title', $title); $title = apply_filters('the_title_rss', $title); printf(__('Comment on %1$s by %2$s'), $title, get_comment_author_rss()); } else { diff --git a/wp-includes/feed-rss2.php b/wp-includes/feed-rss2.php index 588a063..21d9b8e 100644 --- a/wp-includes/feed-rss2.php +++ b/wp-includes/feed-rss2.php @@ -1,5 +1,5 @@ <?php -header('Content-type: text/xml; charset=' . get_option('blog_charset'), true); +header('Content-Type: text/xml; charset=' . get_option('blog_charset'), true); $more = 1; ?> @@ -24,7 +24,7 @@ $more = 1; <?php while( have_posts()) : the_post(); ?> <item> <title><?php the_title_rss() ?></title> - <link><?php permalink_single_rss() ?></link> + <link><?php the_permalink_rss() ?></link> <comments><?php comments_link(); ?></comments> <pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_post_time('Y-m-d H:i:s', true), false); ?></pubDate> <dc:creator><?php the_author() ?></dc:creator> diff --git a/wp-includes/feed.php b/wp-includes/feed.php index 3474ef3..8f9219c 100644 --- a/wp-includes/feed.php +++ b/wp-includes/feed.php @@ -12,6 +12,8 @@ function bloginfo_rss($show = '') { function get_wp_title_rss($sep = '»') { $title = wp_title($sep, false); + if ( is_wp_error( $title ) ) + return $title->get_error_message(); $title = apply_filters('get_wp_title_rss', $title); return $title; } @@ -22,7 +24,6 @@ function wp_title_rss($sep = '»') { function get_the_title_rss() { $title = get_the_title(); - $title = apply_filters('the_title', $title); $title = apply_filters('the_title_rss', $title); return $title; } @@ -66,16 +67,15 @@ function the_content_rss($more_link_text='(more...)', $stripteaser=0, $more_file function the_excerpt_rss() { - $output = get_the_excerpt(true); + $output = get_the_excerpt(); echo apply_filters('the_excerpt_rss', $output); } +function the_permalink_rss() { + echo apply_filters('the_permalink_rss', get_permalink()); -function permalink_single_rss($file = '') { - echo get_permalink(); } - function comment_link() { echo get_comment_link(); } @@ -117,7 +117,7 @@ function get_author_rss_link($echo = false, $author_id, $author_nicename) { $link = get_option('home') . '?feed=rss2&author=' . $author_id; } else { $link = get_author_posts_url($author_id, $author_nicename); - $link = $link . user_trailingslashit('feed', 'feed'); + $link = trailingslashit($link) . user_trailingslashit('feed', 'feed'); } $link = apply_filters('author_feed_link', $link); @@ -135,7 +135,7 @@ function get_category_rss_link($echo = false, $cat_ID, $category_nicename) { $link = get_option('home') . '?feed=rss2&cat=' . $cat_ID; } else { $link = get_category_link($cat_ID); - $link = $link . user_trailingslashit('feed', 'feed'); + $link = trailingslashit($link) . user_trailingslashit('feed', 'feed'); } $link = apply_filters('category_feed_link', $link); @@ -148,17 +148,34 @@ function get_category_rss_link($echo = false, $cat_ID, $category_nicename) { function get_the_category_rss($type = 'rss') { $categories = get_the_category(); + $tags = get_the_tags(); $home = get_bloginfo_rss('home'); $the_list = ''; - foreach ( (array) $categories as $category ) { - $cat_name = convert_chars($category->cat_name); + $cat_names = array(); + + $filter = 'rss'; + if ( 'atom' == $type ) + $filter = 'raw'; + + if ( !empty($categories) ) foreach ( (array) $categories as $category ) { + $cat_names[] = sanitize_term_field('name', $category->name, $category->term_id, 'category', $filter); + } + + if ( !empty($tags) ) foreach ( (array) $tags as $tag ) { + $cat_names[] = sanitize_term_field('name', $tag->name, $tag->term_id, 'post_tag', $filter); + } + + $cat_names = array_unique($cat_names); + + foreach ( $cat_names as $cat_name ) { if ( 'rdf' == $type ) $the_list .= "\n\t\t<dc:subject><![CDATA[$cat_name]]></dc:subject>\n"; - if ( 'atom' == $type ) - $the_list .= sprintf( '<category scheme="%1$s" term="%2$s" />', attribute_escape( apply_filters( 'get_bloginfo_rss', get_bloginfo( 'url' ) ) ), attribute_escape( $category->cat_name ) ); + elseif ( 'atom' == $type ) + $the_list .= sprintf( '<category scheme="%1$s" term="%2$s" />', attribute_escape( apply_filters( 'get_bloginfo_rss', get_bloginfo( 'url' ) ) ), attribute_escape( $cat_name ) ); else $the_list .= "\n\t\t<category><![CDATA[$cat_name]]></category>\n"; } + return apply_filters('the_category_rss', $the_list, $type); } @@ -167,6 +184,32 @@ function the_category_rss($type = 'rss') { echo get_the_category_rss($type); } +function get_tag_feed_link($tag_id, $feed = 'rss2') { + $tag_id = (int) $tag_id; + + $tag = get_tag($tag_id); + + if ( empty($tag) || is_wp_error($tag) ) + return false; + + $permalink_structure = get_option('permalink_structure'); + + if ( '' == $permalink_structure ) { + $link = get_option('home') . "?feed=$feed&tag=" . $tag->slug; + } else { + $link = get_tag_link($tag->term_id); + if ( 'rss2' == $feed ) + $feed_link = 'feed'; + else + $feed_link = "feed/$feed"; + $link = $link . user_trailingslashit($feed_link, 'feed'); + } + + $link = apply_filters('tag_feed_link', $link, $feed); + + return $link; +} + function html_type_rss() { $type = get_bloginfo('html_type'); if (strpos($type, 'xhtml') !== false) diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php index cb8b372..a58aa88 100644 --- a/wp-includes/formatting.php +++ b/wp-includes/formatting.php @@ -17,7 +17,7 @@ function wptexturize($text) { $cockneyreplace = array("’tain’t","’twere","’twas","’tis","’twill","’til","’bout","’nuff","’round","’cause"); } - $static_characters = array_merge(array('---', ' -- ', '--', 'xn–', '...', '``', '\'s', '\'\'', ' (tm)'), $cockney); + $static_characters = array_merge(array('---', ' -- ', '--', 'xn–', '...', '``', '\'s', '\'\'', ' (tm)'), $cockney); $static_replacements = array_merge(array('—', ' — ', '–', 'xn--', '…', '“', '’s', '”', ' ™'), $cockneyreplace); $dynamic_characters = array('/\'(\d\d(?:’|\')?s)/', '/(\s|\A|")\'/', '/(\d+)"/', '/(\d+)\'/', '/(\S)\'([^\'\s])/', '/(\s|\A)"(?!\s)/', '/"(\s|\S|\Z)/', '/\'([\s.]|\Z)/', '/(\d+)x(\d+)/'); @@ -44,10 +44,18 @@ function wptexturize($text) { return $output; } -function clean_pre($text) { +// Accepts matches array from preg_replace_callback in wpautop() +// or a string +function clean_pre($matches) { + if ( is_array($matches) ) + $text = $matches[1] . $matches[2] . "</pre>"; + else + $text = $matches; + $text = str_replace('<br />', '', $text); $text = str_replace('<p>', "\n", $text); $text = str_replace('</p>', '', $text); + return $text; } @@ -78,7 +86,7 @@ function wpautop($pee, $br = 1) { $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee); $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee); if (strpos($pee, '<pre') !== false) - $pee = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " stripslashes('$1') . stripslashes(clean_pre('$2')) . '</pre>' ", $pee); + $pee = preg_replace_callback('!(<pre.*?>)(.*?)</pre>!is', 'clean_pre', $pee ); $pee = preg_replace( "|\n</p>$|", '</p>', $pee ); return $pee; @@ -131,7 +139,7 @@ function utf8_uri_encode( $utf8_string, $length = 0 ) { if ( $value < 128 ) { if ( $length && ( strlen($unicode) + 1 > $length ) ) - break; + break; $unicode .= chr($value); } else { if ( count( $values ) == 0 ) $num_octets = ( $value < 224 ) ? 2 : 3; @@ -413,8 +421,14 @@ function funky_javascript_fix($text) { return $text; } +function balanceTags( $text, $force = false ) { + if ( !$force && get_option('use_balanceTags') == 0 ) + return $text; + return force_balance_tags( $text ); +} + /* - balanceTags + force_balance_tags Balances Tags of string using a modified stack. @@ -433,12 +447,10 @@ function funky_javascript_fix($text) { Added Cleaning Hooks 1.0 First Version */ -function balanceTags($text, $force = false) { - - if ( !$force && get_option('use_balanceTags') == 0 ) - return $text; - +function force_balance_tags( $text ) { $tagstack = array(); $stacksize = 0; $tagqueue = ''; $newtext = ''; + $single_tags = array('br', 'hr', 'img', 'input'); //Known single-entity/self-closing tags + $nestable_tags = array('blockquote', 'div', 'span'); //Tags that can be immediately nested within themselves # WP bug fix for comments - in case you REALLY meant to type '< !--' $text = str_replace('< !--', '< !--', $text); @@ -489,11 +501,11 @@ function balanceTags($text, $force = false) { if((substr($regex[2],-1) == '/') || ($tag == '')) { } // ElseIf it's a known single-entity tag but it doesn't close itself, do so - elseif ($tag == 'br' || $tag == 'img' || $tag == 'hr' || $tag == 'input') { + elseif ( in_array($tag, $single_tags) ) { $regex[2] .= '/'; } else { // Push the tag onto the stack // If the top of the stack is the same as the tag we want to push, close previous tag - if (($stacksize > 0) && ($tag != 'div') && ($tagstack[$stacksize - 1] == $tag)) { + if (($stacksize > 0) && !in_array($tag, $nestable_tags) && ($tagstack[$stacksize - 1] == $tag)) { $tagqueue = '</' . array_pop ($tagstack) . '>'; $stacksize--; } @@ -534,10 +546,6 @@ function balanceTags($text, $force = false) { return $newtext; } -function force_balance_tags($text) { - return balanceTags($text, true); -} - function format_to_edit($content, $richedit = false) { $content = apply_filters('format_to_edit', $content); if (! $richedit ) @@ -636,24 +644,30 @@ function wp_rel_nofollow( $text ) { global $wpdb; // This is a pre save filter, so text is already escaped. $text = stripslashes($text); - $text = preg_replace('|<a (.+?)>|ie', "'<a ' . str_replace(' rel=\"nofollow\"','',stripslashes('$1')) . ' rel=\"nofollow\">'", $text); + $text = preg_replace_callback('|<a (.+?)>|i', 'wp_rel_nofollow_callback', $text); $text = $wpdb->escape($text); return $text; } +function wp_rel_nofollow_callback( $matches ) { + $text = $matches[1]; + $text = str_replace(array(' rel="nofollow"', " rel='nofollow'"), '', $text); + return "<a $text rel=\"nofollow\">"; +} + function convert_smilies($text) { global $wp_smiliessearch, $wp_smiliesreplace; $output = ''; if (get_option('use_smilies')) { // HTML loop taken from texturize function, could possible be consolidated $textarr = preg_split("/(<.*>)/U", $text, -1, PREG_SPLIT_DELIM_CAPTURE); // capture the tags as well as in between - $stop = count($textarr);// loop stuff - for ($i = 0; $i < $stop; $i++) { - $content = $textarr[$i]; - if ((strlen($content) > 0) && ('<' != $content{0})) { // If it's not a tag - $content = preg_replace($wp_smiliessearch, $wp_smiliesreplace, $content); - } - $output .= $content; + $stop = count($textarr);// loop stuff + for ($i = 0; $i < $stop; $i++) { + $content = $textarr[$i]; + if ((strlen($content) > 0) && ('<' != $content{0})) { // If it's not a tag + $content = preg_replace($wp_smiliessearch, $wp_smiliesreplace, $content); + } + $output .= $content; } } else { // return default text. @@ -1074,22 +1088,28 @@ function wp_richedit_pre($text) { } function clean_url( $url, $protocols = null ) { + $original_url = $url; + if ('' == $url) return $url; - $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%]|i', '', $url); + $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@]|i', '', $url); $strip = array('%0d', '%0a'); $url = str_replace($strip, '', $url); $url = str_replace(';//', '://', $url); - // Append http unless a relative link starting with / or a php file. - if ( strpos($url, '://') === false && + /* If the URL doesn't appear to contain a scheme, we + * presume it needs http:// appended (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) ) $url = 'http://' . $url; - + $url = preg_replace('/&([^#])(?![a-z]{2,8};)/', '&$1', $url); if ( !is_array($protocols) ) - $protocols = array('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet'); + $protocols = array('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet'); if ( wp_kses_bad_protocol( $url, $protocols ) != $url ) return ''; - return $url; + + return apply_filters('clean_url', $url, $original_url); } // Borrowed from the PHP Manual user notes. Convert entities, while @@ -1185,6 +1205,7 @@ function sanitize_option($option, $value) { // Remember to call stripslashes! $value = clean_url($value); break; default : + $value = apply_filters("sanitize_option_{$option}", $value, $option); break; } @@ -1198,4 +1219,15 @@ function wp_parse_str( $string, &$array ) { $array = apply_filters( 'wp_parse_str', $array ); } +// Convert lone less than signs. KSES already converts lone greater than signs. +function wp_pre_kses_less_than( $text ) { + return preg_replace_callback('%<[^>]*?((?=<)|>|$)%', 'wp_pre_kses_less_than_callback', $text); +} + +function wp_pre_kses_less_than_callback( $matches ) { + if ( false === strpos($matches[0], '>') ) + return wp_specialchars($matches[0]); + return $matches[0]; +} + ?> diff --git a/wp-includes/functions.php b/wp-includes/functions.php index 60a5730..43a2ba9 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -1,16 +1,14 @@ <?php -require_once(dirname(__FILE__).'/compat.php'); - function mysql2date($dateformatstring, $mysqlstring, $translate = true) { global $wp_locale; $m = $mysqlstring; if ( empty($m) ) { return false; } - $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 ) + $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 ) @@ -83,6 +81,30 @@ 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 size_format($bytes, $decimals = null) { + // technically the correct unit names for powers of 1024 are KiB, MiB etc + // see http://en.wikipedia.org/wiki/Byte + $quant = array( + 'TB' => pow(1024, 4), + 'GB' => pow(1024, 3), + 'MB' => pow(1024, 2), + 'kB' => pow(1024, 1), + 'B' => pow(1024, 0), + ); + + foreach ($quant as $unit => $mag) + if ( intval($bytes) >= $mag ) + return number_format_i18n($bytes / $mag, $decimals) . ' ' . $unit; +} + function get_weekstartend($mysqlstring, $start_of_week) { $my = substr($mysqlstring,0,4); $mm = substr($mysqlstring,8,2); @@ -108,56 +130,6 @@ function get_weekstartend($mysqlstring, $start_of_week) { return $week; } -function get_lastpostdate($timezone = 'server') { - global $cache_lastpostdate, $pagenow, $wpdb, $blog_id; - $add_seconds_blog = get_option('gmt_offset') * 3600; - $add_seconds_server = date('Z'); - if ( !isset($cache_lastpostdate[$blog_id][$timezone]) ) { - switch(strtolower($timezone)) { - case 'gmt': - $lastpostdate = $wpdb->get_var("SELECT post_date_gmt FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_date_gmt DESC LIMIT 1"); - break; - case 'blog': - $lastpostdate = $wpdb->get_var("SELECT post_date FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_date_gmt DESC LIMIT 1"); - break; - case 'server': - $lastpostdate = $wpdb->get_var("SELECT DATE_ADD(post_date_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_date_gmt DESC LIMIT 1"); - break; - } - $cache_lastpostdate[$blog_id][$timezone] = $lastpostdate; - } else { - $lastpostdate = $cache_lastpostdate[$blog_id][$timezone]; - } - return $lastpostdate; -} - -function get_lastpostmodified($timezone = 'server') { - global $cache_lastpostmodified, $pagenow, $wpdb, $blog_id; - $add_seconds_blog = get_option('gmt_offset') * 3600; - $add_seconds_server = date('Z'); - if ( !isset($cache_lastpostmodified[$blog_id][$timezone]) ) { - switch(strtolower($timezone)) { - case 'gmt': - $lastpostmodified = $wpdb->get_var("SELECT post_modified_gmt FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_modified_gmt DESC LIMIT 1"); - break; - case 'blog': - $lastpostmodified = $wpdb->get_var("SELECT post_modified FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_modified_gmt DESC LIMIT 1"); - break; - case 'server': - $lastpostmodified = $wpdb->get_var("SELECT DATE_ADD(post_modified_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_modified_gmt DESC LIMIT 1"); - break; - } - $lastpostdate = get_lastpostdate($timezone); - if ( $lastpostdate > $lastpostmodified ) { - $lastpostmodified = $lastpostdate; - } - $cache_lastpostmodified[$blog_id][$timezone] = $lastpostmodified; - } else { - $lastpostmodified = $cache_lastpostmodified[$blog_id][$timezone]; - } - return $lastpostmodified; -} - function maybe_unserialize($original) { if ( is_serialized($original) ) // don't attempt to unserialize data that wasn't serialized going in if ( false !== $gm = @ unserialize($original) ) @@ -208,9 +180,9 @@ function get_option($setting) { global $wpdb, $switched, $current_blog; // Allow plugins to short-circuit options. - $pre = apply_filters( 'pre_option_' . $setting, false ); - if ( $pre ) - return $pre; + $pre = apply_filters( 'pre_option_' . $setting, false ); + if ( false !== $pre ) + return $pre; if ( $switched != false || defined('WP_INSTALLING') != false ) { wp_cache_delete($setting, 'options'); @@ -252,8 +224,8 @@ function get_option($setting) { if ( 'home' == $setting && '' == $value ) return get_option('siteurl'); - if ( 'siteurl' == $setting || 'home' == $setting || 'category_base' == $setting ) - $value = preg_replace('|/+$|', '', $value); + if ( in_array($setting, array('siteurl', 'home', 'category_base', 'tag_base')) ) + $value = untrailingslashit($value); if (! unserialize($value) ) $value = stripslashes( $value ); @@ -319,6 +291,7 @@ function update_option($option_name, $newvalue) { wp_protect_special_option($option_name); $safe_option_name = $wpdb->escape($option_name); + $newvalue = sanitize_option($option_name, $newvalue); if ( is_string($newvalue) ) $newvalue = trim($newvalue); @@ -363,7 +336,7 @@ function update_option($option_name, $newvalue) { // thx Alex Stapleton, http://alex.vort-x.net/blog/ // expects $name to NOT be SQL-escaped -function add_option($name, $value = '', $description = '', $autoload = 'yes') { +function add_option($name, $value = '', $deprecated = '', $autoload = 'yes') { global $wpdb; wp_protect_special_option($name); @@ -395,8 +368,7 @@ function add_option($name, $value = '', $description = '', $autoload = 'yes') { $name = $wpdb->escape($name); $value = $wpdb->escape($value); - $description = $wpdb->escape($description); - $wpdb->query("INSERT INTO $wpdb->options (option_name, option_value, option_description, autoload) VALUES ('$name', '$value', '$description', '$autoload')"); + $wpdb->query("INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES ('$name', '$value', '$autoload')"); return; } @@ -433,10 +405,16 @@ function maybe_serialize($data) { } function gzip_compression() { - if ( !get_option('gzipcompression') ) return false; + if ( !get_option( 'gzipcompression' ) ) { + return false; + } - if ( extension_loaded('zlib') ) { - ob_start('ob_gzhandler'); + if ( ( ini_get( 'zlib.output_compression' ) == 'On' || ini_get( 'zlib.output_compression_level' ) > 0 ) || ini_get( 'output_handler' ) == 'ob_gzhandler' ) { + return false; + } + + if ( extension_loaded( 'zlib' ) ) { + ob_start( 'ob_gzhandler' ); } } @@ -518,7 +496,7 @@ function do_enclose( $content, $post_ID ) { global $wp_version, $wpdb; include_once (ABSPATH . WPINC . '/class-IXR.php'); - $log = debug_fopen(ABSPATH . '/enclosures.log', 'a'); + $log = debug_fopen(ABSPATH . 'enclosures.log', 'a'); $post_links = array(); debug_fwrite($log, 'BEGIN '.date('YmdHis', time())."\n"); @@ -610,162 +588,8 @@ function is_new_day() { } } -function update_post_cache(&$posts) { - global $post_cache, $blog_id; - - if ( !$posts ) - return; - - for ($i = 0; $i < count($posts); $i++) { - $post_cache[$blog_id][$posts[$i]->ID] = &$posts[$i]; - } -} - -function clean_post_cache($id) { - global $post_cache, $post_meta_cache, $category_cache, $blog_id; - - if ( isset( $post_cache[$blog_id][$id] ) ) - unset( $post_cache[$blog_id][$id] ); - - if ( isset ($post_meta_cache[$blog_id][$id] ) ) - unset( $post_meta_cache[$blog_id][$id] ); - - if ( isset( $category_cache[$blog_id][$id]) ) - unset ( $category_cache[$blog_id][$id] ); -} - -function update_page_cache(&$pages) { - global $page_cache, $blog_id; - - if ( !$pages ) - return; - - for ($i = 0; $i < count($pages); $i++) { - $page_cache[$blog_id][$pages[$i]->ID] = &$pages[$i]; - wp_cache_add($pages[$i]->ID, $pages[$i], 'pages'); - } -} - -function clean_page_cache($id) { - global $page_cache, $blog_id; - - if ( isset( $page_cache[$blog_id][$id] ) ) - unset( $page_cache[$blog_id][$id] ); - - wp_cache_delete($id, 'pages'); - wp_cache_delete( 'all_page_ids', 'pages' ); - wp_cache_delete( 'get_pages', 'page' ); -} - -function update_post_category_cache($post_ids) { - global $wpdb, $category_cache, $blog_id; - - if ( empty($post_ids) ) - return; - - if ( is_array($post_ids) ) - $post_id_list = implode(',', $post_ids); - - $post_id_array = (array) explode(',', $post_ids); - $count = count( $post_id_array); - for ( $i = 0; $i < $count; $i++ ) { - $post_id = (int) $post_id_array[ $i ]; - if ( isset( $category_cache[$blog_id][$post_id] ) ) { - unset( $post_id_array[ $i ] ); - continue; - } - } - if ( count( $post_id_array ) == 0 ) - return; - $post_id_list = join( ',', $post_id_array ); // with already cached stuff removed - - $dogs = $wpdb->get_results("SELECT post_id, category_id FROM $wpdb->post2cat WHERE post_id IN ($post_id_list)"); - - if ( empty($dogs) ) - return; - - foreach ($dogs as $catt) - $category_cache[$blog_id][$catt->post_id][$catt->category_id] = &get_category($catt->category_id); -} - -function update_post_caches(&$posts) { - global $post_cache, $category_cache, $post_meta_cache; - global $wpdb, $blog_id; - - // No point in doing all this work if we didn't match any posts. - if ( !$posts ) - return; - - // Get the categories for all the posts - for ($i = 0; $i < count($posts); $i++) { - $post_id_array[] = $posts[$i]->ID; - $post_cache[$blog_id][$posts[$i]->ID] = &$posts[$i]; - } - - $post_id_list = implode(',', $post_id_array); - - update_post_category_cache($post_id_list); - - update_postmeta_cache($post_id_list); -} - -function update_postmeta_cache($post_id_list = '') { - global $wpdb, $post_meta_cache, $blog_id; - - // We should validate this comma-separated list for the upcoming SQL query - $post_id_list = preg_replace('|[^0-9,]|', '', $post_id_list); - - if ( empty( $post_id_list ) ) - return false; - - // we're marking each post as having its meta cached (with no keys... empty array), to prevent posts with no meta keys from being queried again - // any posts that DO have keys will have this empty array overwritten with a proper array, down below - $post_id_array = (array) explode(',', $post_id_list); - $count = count( $post_id_array); - for ( $i = 0; $i < $count; $i++ ) { - $post_id = (int) $post_id_array[ $i ]; - if ( isset( $post_meta_cache[$blog_id][$post_id] ) ) { // If the meta is already cached - unset( $post_id_array[ $i ] ); - continue; - } - $post_meta_cache[$blog_id][$post_id] = array(); - } - if ( count( $post_id_array ) == 0 ) - return; - $post_id_list = join( ',', $post_id_array ); // with already cached stuff removeds - - // Get post-meta info - if ( $meta_list = $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM $wpdb->postmeta WHERE post_id IN($post_id_list) ORDER BY post_id, meta_key", ARRAY_A) ) { - // Change from flat structure to hierarchical: - if ( !isset($post_meta_cache) ) - $post_meta_cache[$blog_id] = array(); - - foreach ($meta_list as $metarow) { - $mpid = (int) $metarow['post_id']; - $mkey = $metarow['meta_key']; - $mval = $metarow['meta_value']; - - // Force subkeys to be array type: - if ( !isset($post_meta_cache[$blog_id][$mpid]) || !is_array($post_meta_cache[$blog_id][$mpid]) ) - $post_meta_cache[$blog_id][$mpid] = array(); - if ( !isset($post_meta_cache[$blog_id][$mpid]["$mkey"]) || !is_array($post_meta_cache[$blog_id][$mpid]["$mkey"]) ) - $post_meta_cache[$blog_id][$mpid]["$mkey"] = array(); - - // Add a value to the current pid/key: - $post_meta_cache[$blog_id][$mpid][$mkey][] = $mval; - } - } -} - -function update_category_cache() { - return true; -} - -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'); +function build_query($data) { + return _http_build_query($data, NULL, '&', '', false); } /* @@ -813,7 +637,7 @@ function add_query_arg() { $base = $parts[0] . '?'; $query = $parts[1]; } - } elseif (!empty($protocol) || strpos($uri, '/') !== false) { + } elseif (!empty($protocol) || strpos($uri, '=') === false ) { $base = $uri . '?'; $query = ''; } else { @@ -822,7 +646,7 @@ function add_query_arg() { } wp_parse_str($query, $qs); - $qs = urlencode_deep($qs); + $qs = urlencode_deep($qs); // this re-URL-encodes things that were already in the query string if ( is_array(func_get_arg(0)) ) { $kayvees = func_get_arg(0); $qs = array_merge($qs, $kayvees); @@ -830,17 +654,14 @@ function add_query_arg() { $qs[func_get_arg(0)] = func_get_arg(1); } - foreach($qs as $k => $v) { - if ( $v !== FALSE ) { - if ( $ret != '' ) - $ret .= '&'; - if ( empty($v) && !preg_match('|[?&]' . preg_quote($k, '|') . '=|', $query) ) - $ret .= $k; - else - $ret .= "$k=$v"; - } + foreach ( $qs as $k => $v ) { + if ( $v === false ) + unset($qs[$k]); } + + $ret = build_query($qs); $ret = trim($ret, '?'); + $ret = preg_replace('#=(&|$)#', '$1', $ret); $ret = $protocol . $base . $ret . $frag; $ret = rtrim($ret, '?'); return $ret; @@ -919,25 +740,78 @@ 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) ) { + $wp_header_to_desc = 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' + ); + } + + 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'; + $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 ( function_exists('apply_filters') ) + $status_header = apply_filters('status_header', $status_header, $header, $text, $protocol); if ( version_compare( phpversion(), '4.3.0', '>=' ) ) { return @header( $status_header, true, $header ); @@ -955,7 +829,7 @@ function nocache_headers() { function cache_javascript_headers() { $expiresOffset = 864000; // 10 days - header("Content-type: text/javascript; charset=" . get_bloginfo('charset')); + header("Content-Type: text/javascript; charset=" . get_bloginfo('charset')); header("Vary: Accept-Encoding"); // Handle proxies header("Expires: " . gmdate("D, d M Y H:i:s", time() + $expiresOffset) . " GMT"); } @@ -965,9 +839,8 @@ function get_num_queries() { return $wpdb->num_queries; } -function bool_from_yn($yn) { - if ($yn == 'Y') return 1; - return 0; +function bool_from_yn( $yn ) { + return ( strtolower( $yn ) == 'y' ); } function do_feed() { @@ -1011,7 +884,7 @@ function do_feed_atom($for_comments) { function do_robots() { global $current_blog; - header('Content-type: text/plain; charset=utf-8'); + header('Content-Type: text/plain; charset=utf-8'); do_action('do_robotstxt'); @@ -1035,6 +908,7 @@ function is_blog_installed() { } function wp_nonce_url($actionurl, $action = -1) { + $actionurl = str_replace('&', '&', $actionurl); return wp_specialchars(add_query_arg('_wpnonce', wp_create_nonce($action), $actionurl)); } @@ -1223,7 +1097,16 @@ function wp_check_filetype($filename, $mimes = null) { 'tar' => 'application/x-tar', 'zip' => 'application/zip', 'gz|gzip' => 'application/x-gzip', - 'exe' => 'application/x-msdownload' + 'exe' => 'application/x-msdownload', + // openoffice formats + 'odt' => 'application/vnd.oasis.opendocument.text', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odf' => 'application/vnd.oasis.opendocument.formula', + )); $type = false; @@ -1358,18 +1241,28 @@ function wp_die( $message, $title = '' ) { $message = "<p>$message</p>"; } - if (strpos($_SERVER['PHP_SELF'], 'wp-admin') !== false) + if ( defined('WP_SITEURL') && '' != WP_SITEURL ) + $admin_dir = WP_SITEURL.'/wp-admin/'; + elseif (function_exists('get_bloginfo') && '' != get_bloginfo('wpurl')) + $admin_dir = get_bloginfo('wpurl').'/wp-admin/'; + elseif (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 ( !function_exists('did_action') || !did_action('admin_head') ) : + if( !headers_sent() ){ + status_header(500); + nocache_headers(); + header('Content-Type: text/html; charset=utf-8'); + } + if ( empty($title) ){ + if( function_exists('__') ) + $title = __('WordPress › Error'); + else + $title = 'WordPress › Error'; + } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> @@ -1377,10 +1270,10 @@ function wp_die( $message, $title = '' ) { <head> <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 + <link rel="stylesheet" href="<?php echo $admin_dir; ?>css/install.css" type="text/css" /> +<?php if ( ( $wp_locale ) && ('rtl' == $wp_locale->text_direction) ) : ?> - <link rel="stylesheet" href="<?php echo $admin_dir; ?>install-rtl.css" type="text/css" /> + <link rel="stylesheet" href="<?php echo $admin_dir; ?>css/install-rtl.css" type="text/css" /> <?php endif; ?> </head> <body> @@ -1395,13 +1288,13 @@ if ( ( $wp_locale ) && ('rtl' == $wp_locale->text_direction) ) : ?> } function _config_wp_home($url = '') { - if ( defined( 'WP_HOME' ) ) + if ( defined( 'WP_HOME' ) ) return WP_HOME; else return $url; } function _config_wp_siteurl($url = '') { - if ( defined( 'WP_SITEURL' ) ) + if ( defined( 'WP_SITEURL' ) ) return WP_SITEURL; else return $url; } @@ -1500,7 +1393,9 @@ function smilies_init() { } function wp_parse_args( $args, $defaults = '' ) { - if ( is_array( $args ) ) + if ( is_object($args) ) + $r = get_object_vars($args); + else if ( is_array( $args ) ) $r =& $args; else wp_parse_str( $args, $r ); diff --git a/wp-includes/general-template.php b/wp-includes/general-template.php index 7c3c5f3..9af63b6 100644 --- a/wp-includes/general-template.php +++ b/wp-includes/general-template.php @@ -60,28 +60,16 @@ function wp_meta() { function bloginfo($show='') { - $info = get_bloginfo($show); - - // Don't filter URL's. - if (strpos($show, 'url') === false && - strpos($show, 'directory') === false && - strpos($show, 'home') === false) { - $info = apply_filters('bloginfo', $info, $show); - $info = convert_chars($info); - } else { - $info = apply_filters('bloginfo_url', $info, $show); - } - - echo $info; + echo get_bloginfo($show, 'display'); } /** - * Note: some of these values are DEPRECATED. Meaning they could be - * taken out at any time and shouldn't be relied upon. Options - * without "// DEPRECATED" are the preferred and recommended ways + * Note: some of these values are DEPRECATED. Meaning they could be + * taken out at any time and shouldn't be relied upon. Options + * without "// DEPRECATED" are the preferred and recommended ways * to get the information. */ -function get_bloginfo($show='') { +function get_bloginfo($show = '', $filter = 'raw') { switch($show) { case 'url' : @@ -153,6 +141,20 @@ function get_bloginfo($show='') { $output = get_option('blogname'); break; } + + $url = true; + if (strpos($show, 'url') === false && + strpos($show, 'directory') === false && + strpos($show, 'home') === false) + $url = false; + + if ( 'display' == $filter ) { + if ( $url ) + $output = apply_filters('bloginfo_url', $output, $show); + else + $output = apply_filters('bloginfo', $output, $show); + } + return $output; } @@ -161,6 +163,7 @@ function wp_title($sep = '»', $display = true) { global $wpdb, $wp_locale, $wp_query; $cat = get_query_var('cat'); + $tag = get_query_var('tag_id'); $p = get_query_var('p'); $name = get_query_var('name'); $category_name = get_query_var('category_name'); @@ -185,8 +188,17 @@ function wp_title($sep = '»', $display = true) { else $category_name = $category_name[count($category_name)-2]; // there was a trailling slash } - $title = $wpdb->get_var("SELECT cat_name FROM $wpdb->categories WHERE category_nicename = '$category_name'"); - $title = apply_filters('single_cat_title', $title); + $cat = get_term_by('slug', $category_name, 'category', OBJECT, 'display'); + if ( $cat ) + $title = apply_filters('single_cat_title', $cat->name); + } + + if ( !empty($tag) ) { + $tag = get_term($tag, 'post_tag', OBJECT, 'display'); + if ( is_wp_error( $tag ) ) + return $tag; + if ( ! empty($tag->name) ) + $title = apply_filters('single_tag_title', $tag->name); } // If there's an author @@ -265,6 +277,29 @@ function single_cat_title($prefix = '', $display = true ) { else return strip_tags($my_cat_name); } + } else if ( is_tag() ) { + return single_tag_title($prefix, $display); + } +} + + +function single_tag_title($prefix = '', $display = true ) { + if ( !is_tag() ) + return; + + $tag_id = intval( get_query_var('tag_id') ); + + if ( !empty($tag_id) ) { + $my_tag = &get_term($tag_id, 'post_tag', OBJECT, 'display'); + if ( is_wp_error( $my_tag ) ) + return false; + $my_tag_name = apply_filters('single_tag_title', $my_tag->name); + if ( !empty($my_tag_name) ) { + if ( $display ) + echo $prefix . $my_tag_name; + else + return $my_tag_name; + } } } @@ -313,16 +348,16 @@ function get_archives_link($url, $text, $format = 'html', $before = '', $after = function wp_get_archives($args = '') { - global $wp_locale, $wpdb; + global $wpdb, $wp_locale; - if ( is_array($args) ) - $r = &$args; - else - parse_str($args, $r); + $defaults = array( + 'type' => 'monthly', 'limit' => '', + 'format' => 'html', 'before' => '', + 'after' => '', 'show_post_count' => false + ); - $defaults = array('type' => 'monthly', 'limit' => '', 'format' => 'html', 'before' => '', 'after' => '', 'show_post_count' => false); - $r = array_merge($defaults, $r); - extract($r, EXTR_SKIP); + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); if ( '' == $type ) $type = 'monthly'; @@ -365,7 +400,7 @@ function wp_get_archives($args = '') { foreach ( $arcresults as $arcresult ) { $url = get_month_link($arcresult->year, $arcresult->month); $text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($arcresult->month), $arcresult->year); - if ( $show_post_count ) + if ( $show_post_count ) $after = ' ('.$arcresult->posts.')' . $afterafter; echo get_archives_link($url, $text, $format, $before, $after); } @@ -585,10 +620,10 @@ function get_calendar($initial = true) { ); if ( $ak_post_titles ) { foreach ( $ak_post_titles as $ak_post_title ) { - + $post_title = apply_filters( "the_title", $ak_post_title->post_title ); $post_title = str_replace('"', '"', wptexturize( $post_title )); - + if ( empty($ak_titles_for_day['day_'.$ak_post_title->dom]) ) $ak_titles_for_day['day_'.$ak_post_title->dom] = ''; if ( empty($ak_titles_for_day["$ak_post_title->dom"]) ) // first one @@ -635,7 +670,7 @@ function get_calendar($initial = true) { ob_end_clean(); echo $output; $cache[ $key ] = $output; - wp_cache_add( 'get_calendar', $cache, 'calendar' ); + wp_cache_set( 'get_calendar', $cache, 'calendar' ); } function delete_get_calendar_cache() { @@ -675,7 +710,7 @@ function the_date_xml() { function the_date($d='', $before='', $after='', $echo = true) { - global $id, $post, $day, $previousday, $newday; + global $id, $post, $day, $previousday; $the_date = ''; if ( $day != $previousday ) { $the_date .= $before; @@ -810,10 +845,10 @@ function rich_edit_exists() { function user_can_richedit() { global $wp_rich_edit, $pagenow; - + 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 ) || + 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'] ) ) && 'comment.php' != $pagenow ) { $wp_rich_edit = true; @@ -863,30 +898,6 @@ function the_editor($content, $id = 'content', $prev_id = 'title') { // <![CDATA[ if ( typeof tinyMCE != "undefined" && tinyMCE.configs.length > 0 ) document.getElementById("quicktags").style.display="none"; - - function edInsertContent(myField, myValue) { - //IE support - if (document.selection) { - myField.focus(); - sel = document.selection.createRange(); - sel.text = myValue; - myField.focus(); - } - //MOZILLA/NETSCAPE support - else if (myField.selectionStart || myField.selectionStart == "0") { - var startPos = myField.selectionStart; - var endPos = myField.selectionEnd; - myField.value = myField.value.substring(0, startPos) - + myValue - + myField.value.substring(endPos, myField.value.length); - myField.focus(); - myField.selectionStart = startPos + myValue.length; - myField.selectionEnd = startPos + myValue.length; - } else { - myField.value += myValue; - myField.focus(); - } - } // ]]> </script> <?php @@ -940,9 +951,12 @@ function the_editor($content, $id = 'content', $prev_id = 'title') { <?php } +function get_search_query() { + return apply_filters( 'get_search_query', stripslashes( get_query_var( 's' ) ) ); +} + function the_search_query() { - global $s; - echo attribute_escape(stripslashes($s)); + echo attribute_escape( apply_filters( 'the_search_query', get_search_query() ) ); } function language_attributes() { @@ -960,7 +974,7 @@ function language_attributes() { } function paginate_links( $args = '' ) { - $defaults = array( + $defaults = array( 'base' => '%_%', // http://example.com/all_posts.php%_% : %_% is replaced by format (below) 'format' => '?page=%#%', // ?page=%#% : %#% is replaced by the page number 'total' => 1, @@ -1038,4 +1052,23 @@ function paginate_links( $args = '' ) { endswitch; return $r; } + +function wp_admin_css_uri( $file = 'wp-admin' ) { + if ( defined('WP_INSTALLING') ) + { + $_file = add_query_arg( 'version', get_bloginfo( 'version' ), "./$file.css" ); + } else { + $_file = add_query_arg( 'version', get_bloginfo( 'version' ), get_option( 'siteurl' ) . "/wp-admin/$file.css" ); + } + return apply_filters( 'wp_admin_css_uri', $_file, $file ); +} + +function wp_admin_css( $file = 'wp-admin' ) { + echo apply_filters( 'wp_admin_css', "<link rel='stylesheet' href='" . wp_admin_css_uri( $file ) . "' type='text/css' />\n", $file ); + if ( 'rtl' == get_bloginfo( 'text_direction' ) ) { + $rtl = ( 'wp-admin' == $file ) ? 'rtl' : "$file-rtl"; + echo apply_filters( 'wp_admin_css', "<link rel='stylesheet' href='" . wp_admin_css_uri( $rtl ) . "' type='text/css' />\n", $rtl ); + } +} + ?> diff --git a/wp-includes/js/jquery/jquery.js b/wp-includes/js/jquery/jquery.js index c684bda..59201f3 100644 --- a/wp-includes/js/jquery/jquery.js +++ b/wp-includes/js/jquery/jquery.js @@ -1 +1,13 @@ -eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('7(1C 1w.6=="T"){1w.T=1w.T;B 6=u(a,c){7(1w==q)v 1p 6(a,c);a=a||17;7(6.1t(a))v 1p 6(17)[6.E.27?"27":"2O"](a);7(1C a=="23"){B m=/^[^<]*(<(.|\\s)+>)[^>]*$/.2Q(a);7(m)a=6.3k([m[1]]);J v 1p 6(c).2o(a)}v q.6r(a.1l==2y&&a||(a.3Y||a.I&&a!=1w&&!a.24&&a[0]!=T&&a[0].24)&&6.3M(a)||[a])};7(1C $!="T")6.2S$=$;B $=6;6.E=6.8p={3Y:"1.1.2",8q:u(){v q.I},I:0,2b:u(1T){v 1T==T?6.3M(q):q[1T]},2r:u(a){B L=6(a);L.6p=q;v L},6r:u(a){q.I=0;[].1g.14(q,a);v q},K:u(E,1E){v 6.K(q,E,1E)},2h:u(1c){B 4c=-1;q.K(u(i){7(q==1c)4c=i});v 4c},1I:u(1Y,O,C){B 1c=1Y;7(1Y.1l==3t)7(O==T)v q.I&&6[C||"1I"](q[0],1Y)||T;J{1c={};1c[1Y]=O}v q.K(u(2h){P(B H 1x 1c)6.1I(C?q.1q:q,H,6.H(q,1c[H],C,2h,H))})},1m:u(1Y,O){v q.1I(1Y,O,"30")},2L:u(e){7(1C e=="23")v q.3u().3r(17.8t(e));B t="";6.K(e||q,u(){6.K(q.2I,u(){7(q.24!=8)t+=q.24!=1?q.60:6.E.2L([q])})});v t},2K:u(){B a=6.3k(1A);v q.K(u(){B b=a[0].3l(U);q.11.2X(b,q);22(b.1b)b=b.1b;b.4C(q)})},3r:u(){v q.3j(1A,U,1,u(a){q.4C(a)})},5i:u(){v q.3j(1A,U,-1,u(a){q.2X(a,q.1b)})},5j:u(){v q.3j(1A,12,1,u(a){q.11.2X(a,q)})},5t:u(){v q.3j(1A,12,-1,u(a){q.11.2X(a,q.2e)})},4g:u(){v q.6p||6([])},2o:u(t){v q.2r(6.31(q,u(a){v 6.2o(t,a)}),t)},4Y:u(4N){v q.2r(6.31(q,u(a){B a=a.3l(4N!=T?4N:U);a.$1H=16;v a}))},1D:u(t){v q.2r(6.1t(t)&&6.2q(q,u(2z,2h){v t.14(2z,[2h])})||6.3z(t,q))},2g:u(t){v q.2r(t.1l==3t&&6.3z(t,q,U)||6.2q(q,u(a){v(t.1l==2y||t.3Y)?6.3y(a,t)<0:a!=t}))},1M:u(t){v q.2r(6.2k(q.2b(),t.1l==3t?6(t).2b():t.I!=T&&(!t.1f||t.1f=="8v")?t:[t]))},4l:u(1s){v 1s?6.1D(1s,q).r.I>0:12},1a:u(1a){v 1a==T?(q.I?q[0].O:16):q.1I("O",1a)},4U:u(1a){v 1a==T?(q.I?q[0].2t:16):q.3u().3r(1a)},3j:u(1E,1P,3Z,E){B 4Y=q.I>1;B a=6.3k(1E);7(3Z<0)a.8w();v q.K(u(){B 1c=q;7(1P&&6.1f(q,"1P")&&6.1f(a[0],"3m"))1c=q.5J("20")[0]||q.4C(17.6n("20"));6.K(a,u(){E.14(1c,[4Y?q.3l(U):q])})})}};6.1z=6.E.1z=u(){B 1O=1A[0],a=1;7(1A.I==1){1O=q;a=0}B H;22(H=1A[a++])P(B i 1x H)1O[i]=H[i];v 1O};6.1z({8x:u(){7(6.2S$)$=6.2S$;v 6},1t:u(E){v!!E&&1C E!="23"&&!E.1f&&1C E[0]=="T"&&/u/i.1n(E+"")},4B:u(D){v D.66&&D.5I&&!D.5I.64},1f:u(D,Y){v D.1f&&D.1f.3K()==Y.3K()},K:u(1c,E,1E){7(1c.I==T)P(B i 1x 1c)E.14(1c[i],1E||[i,1c[i]]);J P(B i=0,6q=1c.I;i<6q;i++)7(E.14(1c[i],1E||[i,1c[i]])===12)3O;v 1c},H:u(D,O,C,2h,H){7(6.1t(O))O=O.3n(D,[2h]);B 6s=/z-?2h|7P-?8A|1d|58|8B-?28/i;v O&&O.1l==3Q&&C=="30"&&!6s.1n(H)?O+"4S":O},19:{1M:u(D,c){6.K(c.3o(/\\s+/),u(i,Q){7(!6.19.2V(D.19,Q))D.19+=(D.19?" ":"")+Q})},2f:u(D,c){D.19=c?6.2q(D.19.3o(/\\s+/),u(Q){v!6.19.2V(c,Q)}).6t(" "):""},2V:u(t,c){t=t.19||t;c=c.1R(/([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:])/g,"\\\\$1");v t&&1p 4v("(^|\\\\s)"+c+"(\\\\s|$)").1n(t)}},4d:u(e,o,f){P(B i 1x o){e.1q["1N"+i]=e.1q[i];e.1q[i]=o[i]}f.14(e,[]);P(B i 1x o)e.1q[i]=e.1q["1N"+i]},1m:u(e,p){7(p=="28"||p=="3V"){B 1N={},46,3P,d=["7d","8C","8D","8E"];6.K(d,u(){1N["8F"+q]=0;1N["8G"+q+"8H"]=0});6.4d(e,1N,u(){7(6.1m(e,"1h")!="1Z"){46=e.8I;3P=e.8J}J{e=6(e.3l(U)).2o(":4j").5l("2Z").4g().1m({4n:"1G",45:"8K",1h:"2D",7I:"0",8M:"0"}).5z(e.11)[0];B 3d=6.1m(e.11,"45");7(3d==""||3d=="4b")e.11.1q.45="6x";46=e.6y;3P=e.6z;7(3d==""||3d=="4b")e.11.1q.45="4b";e.11.33(e)}});v p=="28"?46:3P}v 6.30(e,p)},30:u(D,H,53){B L;7(H=="1d"&&6.W.1j)v 6.1I(D.1q,"1d");7(H=="4h"||H=="2v")H=6.W.1j?"3T":"2v";7(!53&&D.1q[H])L=D.1q[H];J 7(17.44&&17.44.4W){7(H=="2v"||H=="3T")H="4h";H=H.1R(/([A-Z])/g,"-$1").4m();B Q=17.44.4W(D,16);7(Q)L=Q.55(H);J 7(H=="1h")L="1Z";J 6.4d(D,{1h:"2D"},u(){B c=17.44.4W(q,"");L=c&&c.55(H)||""})}J 7(D.51){B 56=H.1R(/\\-(\\w)/g,u(m,c){v c.3K()});L=D.51[H]||D.51[56]}v L},3k:u(a){B r=[];6.K(a,u(i,1r){7(!1r)v;7(1r.1l==3Q)1r=1r.6C();7(1C 1r=="23"){B s=6.35(1r),1V=17.6n("1V"),2i=[];B 2K=!s.18("<1u")&&[1,"<42>","</42>"]||(!s.18("<6D")||!s.18("<20")||!s.18("<6E"))&&[1,"<1P>","</1P>"]||!s.18("<3m")&&[2,"<1P><20>","</20></1P>"]||(!s.18("<6F")||!s.18("<6G"))&&[3,"<1P><20><3m>","</3m></20></1P>"]||[0,"",""];1V.2t=2K[1]+s+2K[2];22(2K[0]--)1V=1V.1b;7(6.W.1j){7(!s.18("<1P")&&s.18("<20")<0)2i=1V.1b&&1V.1b.2I;J 7(2K[1]=="<1P>"&&s.18("<20")<0)2i=1V.2I;P(B n=2i.I-1;n>=0;--n)7(6.1f(2i[n],"20")&&!2i[n].2I.I)2i[n].11.33(2i[n])}1r=[];P(B i=0,l=1V.2I.I;i<l;i++)1r.1g(1V.2I[i])}7(1r.I===0&&!6.1f(1r,"3w"))v;7(1r[0]==T||6.1f(1r,"3w"))r.1g(1r);J r=6.2k(r,1r)});v r},1I:u(D,Y,O){B 2j=6.4B(D)?{}:{"P":"6J","6L":"19","4h":6.W.1j?"3T":"2v",2v:6.W.1j?"3T":"2v",2t:"2t",19:"19",O:"O",2W:"2W",2Z:"2Z",89:"6N",2Y:"2Y"};7(Y=="1d"&&6.W.1j&&O!=T){D.58=1;v D.1D=D.1D.1R(/4i\\([^\\)]*\\)/6O,"")+(O==1?"":"4i(1d="+O*6g+")")}J 7(Y=="1d"&&6.W.1j)v D.1D?4T(D.1D.6P(/4i\\(1d=(.*)\\)/)[1])/6g:1;7(Y=="1d"&&6.W.3h&&O==1)O=0.6R;7(2j[Y]){7(O!=T)D[2j[Y]]=O;v D[2j[Y]]}J 7(O==T&&6.W.1j&&6.1f(D,"3w")&&(Y=="81"||Y=="80"))v D.6T(Y).60;J 7(D.66){7(O!=T)D.6V(Y,O);7(6.W.1j&&/5E|3e/.1n(Y)&&!6.4B(D))v D.36(Y,2);v D.36(Y)}J{Y=Y.1R(/-([a-z])/6W,u(z,b){v b.3K()});7(O!=T)D[Y]=O;v D[Y]}},35:u(t){v t.1R(/^\\s+|\\s+$/g,"")},3M:u(a){B r=[];7(a.1l!=2y)P(B i=0,2R=a.I;i<2R;i++)r.1g(a[i]);J r=a.3N(0);v r},3y:u(b,a){P(B i=0,2R=a.I;i<2R;i++)7(a[i]==b)v i;v-1},2k:u(2u,3H){B r=[].3N.3n(2u,0);P(B i=0,5b=3H.I;i<5b;i++)7(6.3y(3H[i],r)==-1)2u.1g(3H[i]);v 2u},2q:u(1U,E,4k){7(1C E=="23")E=1p 4w("a","i","v "+E);B 1i=[];P(B i=0,2z=1U.I;i<2z;i++)7(!4k&&E(1U[i],i)||4k&&!E(1U[i],i))1i.1g(1U[i]);v 1i},31:u(1U,E){7(1C E=="23")E=1p 4w("a","v "+E);B 1i=[],r=[];P(B i=0,2z=1U.I;i<2z;i++){B 1a=E(1U[i],i);7(1a!==16&&1a!=T){7(1a.1l!=2y)1a=[1a];1i=1i.6Z(1a)}}B r=1i.I?[1i[0]]:[];5f:P(B i=1,5e=1i.I;i<5e;i++){P(B j=0;j<i;j++)7(1i[i]==r[j])5F 5f;r.1g(1i[i])}v r}});1p u(){B b=7L.71.4m();6.W={2N:/5D/.1n(b),3f:/3f/.1n(b),1j:/1j/.1n(b)&&!/3f/.1n(b),3h:/3h/.1n(b)&&!/(72|5D)/.1n(b)};6.7H=!6.W.1j||17.74=="75"};6.K({5u:"a.11",4z:"6.4z(a)",76:"6.2a(a,2,\'2e\')",7D:"6.2a(a,2,\'5s\')",78:"6.2B(a.11.1b,a)",79:"6.2B(a.1b)"},u(i,n){6.E[i]=u(a){B L=6.31(q,n);7(a&&1C a=="23")L=6.3z(a,L);v q.2r(L)}});6.K({5z:"3r",7b:"5i",2X:"5j",7e:"5t"},u(i,n){6.E[i]=u(){B a=1A;v q.K(u(){P(B j=0,2R=a.I;j<2R;j++)6(a[j])[n](q)})}});6.K({5l:u(1Y){6.1I(q,1Y,"");q.7g(1Y)},7h:u(c){6.19.1M(q,c)},7i:u(c){6.19.2f(q,c)},7k:u(c){6.19[6.19.2V(q,c)?"2f":"1M"](q,c)},2f:u(a){7(!a||6.1D(a,[q]).r.I)q.11.33(q)},3u:u(){22(q.1b)q.33(q.1b)}},u(i,n){6.E[i]=u(){v q.K(n,1A)}});6.K(["5q","5n","5p","5v"],u(i,n){6.E[n]=u(1T,E){v q.1D(":"+n+"("+1T+")",E)}});6.K(["28","3V"],u(i,n){6.E[n]=u(h){v h==T?(q.I?6.1m(q[0],n):16):q.1m(n,h.1l==3t?h:h+"4S")}});6.1z({1s:{"":"m[2]==\'*\'||6.1f(a,m[2])","#":"a.36(\'2J\')==m[2]",":":{5n:"i<m[3]-0",5p:"i>m[3]-0",2a:"m[3]-0==i",5q:"m[3]-0==i",2u:"i==0",2T:"i==r.I-1",5R:"i%2==0",5S:"i%2","2a-3s":"6.2a(a.11.1b,m[3],\'2e\',a)==a","2u-3s":"6.2a(a.11.1b,1,\'2e\')==a","2T-3s":"6.2a(a.11.7n,1,\'5s\')==a","7p-3s":"6.2B(a.11.1b).I==1",5u:"a.1b",3u:"!a.1b",5v:"6.E.2L.14([a]).18(m[3])>=0",3i:\'a.C!="1G"&&6.1m(a,"1h")!="1Z"&&6.1m(a,"4n")!="1G"\',1G:\'a.C=="1G"||6.1m(a,"1h")=="1Z"||6.1m(a,"4n")=="1G"\',7v:"!a.2W",2W:"a.2W",2Z:"a.2Z",2Y:"a.2Y||6.1I(a,\'2Y\')",2L:"a.C==\'2L\'",4j:"a.C==\'4j\'",5x:"a.C==\'5x\'",4G:"a.C==\'4G\'",5y:"a.C==\'5y\'",4R:"a.C==\'4R\'",5A:"a.C==\'5A\'",5B:"a.C==\'5B\'",3x:\'a.C=="3x"||6.1f(a,"3x")\',5C:"/5C|42|7A|3x/i.1n(a.1f)"},".":"6.19.2V(a,m[2])","@":{"=":"z==m[4]","!=":"z!=m[4]","^=":"z&&!z.18(m[4])","$=":"z&&z.2U(z.I - m[4].I,m[4].I)==m[4]","*=":"z&&z.18(m[4])>=0","":"z",4u:u(m){v["",m[1],m[3],m[2],m[5]]},5P:"z=a[m[3]];7(!z||/5E|3e/.1n(m[3]))z=6.1I(a,m[3]);"},"[":"6.2o(m[2],a).I"},5M:[/^\\[ *(@)([a-2m-3C-]*) *([!*$^=]*) *(\'?"?)(.*?)\\4 *\\]/i,/^(\\[)\\s*(.*?(\\[.*?\\])?[^[]*?)\\s*\\]/,/^(:)([a-2m-3C-]*)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/i,/^([:.#]*)([a-2m-3C*-]*)/i],1Q:[/^(\\/?\\.\\.)/,"a.11",/^(>|\\/)/,"6.2B(a.1b)",/^(\\+)/,"6.2a(a,2,\'2e\')",/^(~)/,u(a){B s=6.2B(a.11.1b);v s.3N(6.3y(a,s)+1)}],3z:u(1s,1U,2g){B 1N,Q=[];22(1s&&1s!=1N){1N=1s;B f=6.1D(1s,1U,2g);1s=f.t.1R(/^\\s*,\\s*/,"");Q=2g?1U=f.r:6.2k(Q,f.r)}v Q},2o:u(t,1B){7(1C t!="23")v[t];7(1B&&!1B.24)1B=16;1B=1B||17;7(!t.18("//")){1B=1B.4H;t=t.2U(2,t.I)}J 7(!t.18("/")){1B=1B.4H;t=t.2U(1,t.I);7(t.18("/")>=1)t=t.2U(t.18("/"),t.I)}B L=[1B],2c=[],2T=16;22(t&&2T!=t){B r=[];2T=t;t=6.35(t).1R(/^\\/\\//i,"");B 3B=12;B 1J=/^[\\/>]\\s*([a-2m-9*-]+)/i;B m=1J.2Q(t);7(m){6.K(L,u(){P(B c=q.1b;c;c=c.2e)7(c.24==1&&(6.1f(c,m[1])||m[1]=="*"))r.1g(c)});L=r;t=t.1R(1J,"");7(t.18(" ")==0)5F;3B=U}J{P(B i=0;i<6.1Q.I;i+=2){B 1J=6.1Q[i];B m=1J.2Q(t);7(m){r=L=6.31(L,6.1t(6.1Q[i+1])?6.1Q[i+1]:u(a){v 40(6.1Q[i+1])});t=6.35(t.1R(1J,""));3B=U;3O}}}7(t&&!3B){7(!t.18(",")){7(L[0]==1B)L.4L();6.2k(2c,L);r=L=[1B];t=" "+t.2U(1,t.I)}J{B 34=/^([a-2m-3C-]+)(#)([a-2m-9\\\\*2S-]*)/i;B m=34.2Q(t);7(m){m=[0,m[2],m[3],m[1]]}J{34=/^([#.]?)([a-2m-9\\\\*2S-]*)/i;m=34.2Q(t)}7(m[1]=="#"&&L[L.I-1].4X){B 2l=L[L.I-1].4X(m[2]);7(6.W.1j&&2l&&2l.2J!=m[2])2l=6(\'[@2J="\'+m[2]+\'"]\',L[L.I-1])[0];L=r=2l&&(!m[3]||6.1f(2l,m[3]))?[2l]:[]}J{7(m[1]==".")B 4r=1p 4v("(^|\\\\s)"+m[2]+"(\\\\s|$)");6.K(L,u(){B 3E=m[1]!=""||m[0]==""?"*":m[2];7(6.1f(q,"7J")&&3E=="*")3E="3g";6.2k(r,m[1]!=""&&L.I!=1?6.4x(q,[],m[1],m[2],4r):q.5J(3E))});7(m[1]=="."&&L.I==1)r=6.2q(r,u(e){v 4r.1n(e.19)});7(m[1]=="#"&&L.I==1){B 5K=r;r=[];6.K(5K,u(){7(q.36("2J")==m[2]){r=[q];v 12}})}L=r}t=t.1R(34,"")}}7(t){B 1a=6.1D(t,r);L=r=1a.r;t=6.35(1a.t)}}7(L&&L[0]==1B)L.4L();6.2k(2c,L);v 2c},1D:u(t,r,2g){22(t&&/^[a-z[({<*:.#]/i.1n(t)){B p=6.5M,m;6.K(p,u(i,1J){m=1J.2Q(t);7(m){t=t.7M(m[0].I);7(6.1s[m[1]].4u)m=6.1s[m[1]].4u(m);v 12}});7(m[1]==":"&&m[2]=="2g")r=6.1D(m[3],r,U).r;J 7(m[1]=="."){B 1J=1p 4v("(^|\\\\s)"+m[2]+"(\\\\s|$)");r=6.2q(r,u(e){v 1J.1n(e.19||"")},2g)}J{B f=6.1s[m[1]];7(1C f!="23")f=6.1s[m[1]][m[2]];40("f = u(a,i){"+(6.1s[m[1]].5P||"")+"v "+f+"}");r=6.2q(r,f,2g)}}v{r:r,t:t}},4x:u(o,r,1Q,Y,1J){P(B s=o.1b;s;s=s.2e)7(s.24==1){B 1M=U;7(1Q==".")1M=s.19&&1J.1n(s.19);J 7(1Q=="#")1M=s.36("2J")==Y;7(1M)r.1g(s);7(1Q=="#"&&r.I)3O;7(s.1b)6.4x(s,r,1Q,Y,1J)}v r},4z:u(D){B 4A=[];B Q=D.11;22(Q&&Q!=17){4A.1g(Q);Q=Q.11}v 4A},2a:u(Q,1i,3Z,D){1i=1i||1;B 1T=0;P(;Q;Q=Q[3Z]){7(Q.24==1)1T++;7(1T==1i||1i=="5R"&&1T%2==0&&1T>1&&Q==D||1i=="5S"&&1T%2==1&&Q==D)v Q}},2B:u(n,D){B r=[];P(;n;n=n.2e){7(n.24==1&&(!D||n!=D))r.1g(n)}v r}});6.G={1M:u(S,C,1o,F){7(6.W.1j&&S.3L!=T)S=1w;7(F)1o.F=F;7(!1o.2A)1o.2A=q.2A++;7(!S.$1H)S.$1H={};B 38=S.$1H[C];7(!38){38=S.$1H[C]={};7(S["39"+C])38[0]=S["39"+C]}38[1o.2A]=1o;S["39"+C]=q.5Y;7(!q.1k[C])q.1k[C]=[];q.1k[C].1g(S)},2A:1,1k:{},2f:u(S,C,1o){7(S.$1H){B i,j,k;7(C&&C.C){1o=C.1o;C=C.C}7(C&&S.$1H[C])7(1o)5U S.$1H[C][1o.2A];J P(i 1x S.$1H[C])5U S.$1H[C][i];J P(j 1x S.$1H)q.2f(S,j);P(k 1x S.$1H[C])7(k){k=U;3O}7(!k)S["39"+C]=16}},1S:u(C,F,S){F=6.3M(F||[]);7(!S)6.K(q.1k[C]||[],u(){6.G.1S(C,F,q)});J{B 1o=S["39"+C],1a,E=6.1t(S[C]);7(1o){F.61(q.2j({C:C,1O:S}));7((1a=1o.14(S,F))!==12)q.4F=U}7(E&&1a!==12)S[C]();q.4F=12}},5Y:u(G){7(1C 6=="T"||6.G.4F)v;G=6.G.2j(G||1w.G||{});B 3R;B c=q.$1H[G.C];B 1E=[].3N.3n(1A,1);1E.61(G);P(B j 1x c){1E[0].1o=c[j];1E[0].F=c[j].F;7(c[j].14(q,1E)===12){G.2n();G.2H();3R=12}}7(6.W.1j)G.1O=G.2n=G.2H=G.1o=G.F=16;v 3R},2j:u(G){7(!G.1O&&G.63)G.1O=G.63;7(G.65==T&&G.67!=T){B e=17.4H,b=17.64;G.65=G.67+(e.68||b.68);G.7Y=G.7Z+(e.6c||b.6c)}7(6.W.2N&&G.1O.24==3){B 3a=G;G=6.1z({},3a);G.1O=3a.1O.11;G.2n=u(){v 3a.2n()};G.2H=u(){v 3a.2H()}}7(!G.2n)G.2n=u(){q.3R=12};7(!G.2H)G.2H=u(){q.82=U};v G}};6.E.1z({3U:u(C,F,E){v q.K(u(){6.G.1M(q,C,E||F,F)})},6u:u(C,F,E){v q.K(u(){6.G.1M(q,C,u(G){6(q).6f(G);v(E||F).14(q,1A)},F)})},6f:u(C,E){v q.K(u(){6.G.2f(q,C,E)})},1S:u(C,F){v q.K(u(){6.G.1S(C,F,q)})},3X:u(){B a=1A;v q.6j(u(e){q.4M=q.4M==0?1:0;e.2n();v a[q.4M].14(q,[e])||12})},83:u(f,g){u 4O(e){B p=(e.C=="41"?e.84:e.85)||e.86;22(p&&p!=q)2G{p=p.11}2w(e){p=q};7(p==q)v 12;v(e.C=="41"?f:g).14(q,[e])}v q.41(4O).6k(4O)},27:u(f){7(6.3W)f.14(17,[6]);J{6.3c.1g(u(){v f.14(q,[6])})}v q}});6.1z({3W:12,3c:[],27:u(){7(!6.3W){6.3W=U;7(6.3c){6.K(6.3c,u(){q.14(17)});6.3c=16}7(6.W.3h||6.W.3f)17.87("6o",6.27,12)}}});1p u(){6.K(("88,8a,2O,8b,8d,52,6j,8e,"+"8f,8g,8h,41,6k,8j,42,"+"4R,8k,8l,8m,2C").3o(","),u(i,o){6.E[o]=u(f){v f?q.3U(o,f):q.1S(o)}});7(6.W.3h||6.W.3f)17.8n("6o",6.27,12);J 7(6.W.1j){17.8o("<8r"+"8s 2J=62 8u=U "+"3e=//:><\\/2d>");B 2d=17.4X("62");7(2d)2d.37=u(){7(q.3D!="1X")v;q.11.33(q);6.27()};2d=16}J 7(6.W.2N)6.50=3L(u(){7(17.3D=="8y"||17.3D=="1X"){4p(6.50);6.50=16;6.27()}},10);6.G.1M(1w,"2O",6.27)};7(6.W.1j)6(1w).6u("52",u(){B 1k=6.G.1k;P(B C 1x 1k){B 4Z=1k[C],i=4Z.I;7(i&&C!=\'52\')6w 6.G.2f(4Z[i-1],C);22(--i)}});6.E.1z({6A:u(V,21,M){q.2O(V,21,M,1)},2O:u(V,21,M,1W){7(6.1t(V))v q.3U("2O",V);M=M||u(){};B C="5d";7(21)7(6.1t(21)){M=21;21=16}J{21=6.3g(21);C="5V"}B 4e=q;6.3v({V:V,C:C,F:21,1W:1W,1X:u(2P,15){7(15=="2M"||!1W&&15=="5L")4e.1I("2t",2P.3G).4V().K(M,[2P.3G,15,2P]);J M.14(4e,[2P.3G,15,2P])}});v q},6B:u(){v 6.3g(q)},4V:u(){v q.2o("2d").K(u(){7(q.3e)6.59(q.3e);J 6.4a(q.2L||q.6H||q.2t||"")}).4g()}});7(!1w.3p)3p=u(){v 1p 6I("6K.6M")};6.K("5m,5Q,5O,5W,5N,5H".3o(","),u(i,o){6.E[o]=u(f){v q.3U(o,f)}});6.1z({2b:u(V,F,M,C,1W){7(6.1t(F)){M=F;F=16}v 6.3v({V:V,F:F,2M:M,4t:C,1W:1W})},6Q:u(V,F,M,C){v 6.2b(V,F,M,C,1)},59:u(V,M){v 6.2b(V,16,M,"2d")},6S:u(V,F,M){v 6.2b(V,F,M,"6m")},6U:u(V,F,M,C){7(6.1t(F)){M=F;F={}}v 6.3v({C:"5V",V:V,F:F,2M:M,4t:C})},6X:u(29){6.3q.29=29},6Y:u(5c){6.1z(6.3q,5c)},3q:{1k:U,C:"5d",29:0,5r:"70/x-73-3w-77",5h:U,48:U,F:16},3S:{},3v:u(s){s=6.1z({},6.3q,s);7(s.F){7(s.5h&&1C s.F!="23")s.F=6.3g(s.F);7(s.C.4m()=="2b"){s.V+=((s.V.18("?")>-1)?"&":"?")+s.F;s.F=16}}7(s.1k&&!6.4E++)6.G.1S("5m");B 4y=12;B N=1p 3p();N.7j(s.C,s.V,s.48);7(s.F)N.3A("7l-7m",s.5r);7(s.1W)N.3A("7o-4K-7q",6.3S[s.V]||"7s, 7t 7w 7x 4o:4o:4o 7z");N.3A("X-7B-7C","3p");7(N.7E)N.3A("7F","7G");7(s.5G)s.5G(N);7(s.1k)6.G.1S("5H",[N,s]);B 37=u(4s){7(N&&(N.3D==4||4s=="29")){4y=U;7(3I){4p(3I);3I=16}B 15;2G{15=6.5Z(N)&&4s!="29"?s.1W&&6.69(N,s.V)?"5L":"2M":"2C";7(15!="2C"){B 3F;2G{3F=N.4P("6b-4K")}2w(e){}7(s.1W&&3F)6.3S[s.V]=3F;B F=6.6i(N,s.4t);7(s.2M)s.2M(F,15);7(s.1k)6.G.1S("5N",[N,s])}J 6.3J(s,N,15)}2w(e){15="2C";6.3J(s,N,15,e)}7(s.1k)6.G.1S("5O",[N,s]);7(s.1k&&!--6.4E)6.G.1S("5Q");7(s.1X)s.1X(N,15);7(s.48)N=16}};B 3I=3L(37,13);7(s.29>0)57(u(){7(N){N.7N();7(!4y)37("29")}},s.29);2G{N.7Q(s.F)}2w(e){6.3J(s,N,16,e)}7(!s.48)37();v N},3J:u(s,N,15,e){7(s.2C)s.2C(N,15,e);7(s.1k)6.G.1S("5W",[N,s,e])},4E:0,5Z:u(r){2G{v!r.15&&7V.7W=="4G:"||(r.15>=5X&&r.15<7X)||r.15==6d||6.W.2N&&r.15==T}2w(e){}v 12},69:u(N,V){2G{B 6e=N.4P("6b-4K");v N.15==6d||6e==6.3S[V]||6.W.2N&&N.15==T}2w(e){}v 12},6i:u(r,C){B 4Q=r.4P("8c-C");B F=!C&&4Q&&4Q.18("N")>=0;F=C=="N"||F?r.8i:r.3G;7(C=="2d")6.4a(F);7(C=="6m")40("F = "+F);7(C=="4U")6("<1V>").4U(F).4V();v F},3g:u(a){B s=[];7(a.1l==2y||a.3Y)6.K(a,u(){s.1g(2x(q.Y)+"="+2x(q.O))});J P(B j 1x a)7(a[j]&&a[j].1l==2y)6.K(a[j],u(){s.1g(2x(j)+"="+2x(q))});J s.1g(2x(j)+"="+2x(a[j]));v s.6t("&")},4a:u(F){7(1w.54)1w.54(F);J 7(6.W.2N)1w.57(F,0);J 40.3n(1w,F)}});6.E.1z({1L:u(R,M){B 1G=q.1D(":1G");R?1G.26({28:"1L",3V:"1L",1d:"1L"},R,M):1G.K(u(){q.1q.1h=q.2E?q.2E:"";7(6.1m(q,"1h")=="1Z")q.1q.1h="2D"});v q},1K:u(R,M){B 3i=q.1D(":3i");R?3i.26({28:"1K",3V:"1K",1d:"1K"},R,M):3i.K(u(){q.2E=q.2E||6.1m(q,"1h");7(q.2E=="1Z")q.2E="2D";q.1q.1h="1Z"});v q},5g:6.E.3X,3X:u(E,4I){B 1E=1A;v 6.1t(E)&&6.1t(4I)?q.5g(E,4I):q.K(u(){6(q)[6(q).4l(":1G")?"1L":"1K"].14(6(q),1E)})},7a:u(R,M){v q.26({28:"1L"},R,M)},7c:u(R,M){v q.26({28:"1K"},R,M)},7f:u(R,M){v q.K(u(){B 5k=6(q).4l(":1G")?"1L":"1K";6(q).26({28:5k},R,M)})},7r:u(R,M){v q.26({1d:"1L"},R,M)},7u:u(R,M){v q.26({1d:"1K"},R,M)},7y:u(R,43,M){v q.26({1d:43},R,M)},26:u(H,R,1v,M){v q.1F(u(){q.2F=6.1z({},H);B 1u=6.R(R,1v,M);P(B p 1x H){B e=1p 6.3b(q,1u,p);7(H[p].1l==3Q)e.2s(e.Q(),H[p]);J e[H[p]](H)}})},1F:u(C,E){7(!E){E=C;C="3b"}v q.K(u(){7(!q.1F)q.1F={};7(!q.1F[C])q.1F[C]=[];q.1F[C].1g(E);7(q.1F[C].I==1)E.14(q)})}});6.1z({R:u(R,1v,E){B 1u=R&&R.1l==7K?R:{1X:E||!E&&1v||6.1t(R)&&R,25:R,1v:E&&1v||1v&&1v.1l!=4w&&1v};1u.25=(1u.25&&1u.25.1l==3Q?1u.25:{7R:7S,7T:5X}[1u.25])||7U;1u.1N=1u.1X;1u.1X=u(){6.6a(q,"3b");7(6.1t(1u.1N))1u.1N.14(q)};v 1u},1v:{},1F:{},6a:u(D,C){C=C||"3b";7(D.1F&&D.1F[C]){D.1F[C].4L();B f=D.1F[C][0];7(f)f.14(D)}},3b:u(D,1e,H){B z=q;B y=D.1q;B 4D=6.1m(D,"1h");y.5T="1G";z.a=u(){7(1e.49)1e.49.14(D,[z.2p]);7(H=="1d")6.1I(y,"1d",z.2p);J 7(6l(z.2p))y[H]=6l(z.2p)+"4S";y.1h="2D"};z.6v=u(){v 4T(6.1m(D,H))};z.Q=u(){B r=4T(6.30(D,H));v r&&r>-8z?r:z.6v()};z.2s=u(4f,43){z.4J=(1p 5o()).5w();z.2p=4f;z.a();z.4q=3L(u(){z.49(4f,43)},13)};z.1L=u(){7(!D.1y)D.1y={};D.1y[H]=q.Q();1e.1L=U;z.2s(0,D.1y[H]);7(H!="1d")y[H]="5a"};z.1K=u(){7(!D.1y)D.1y={};D.1y[H]=q.Q();1e.1K=U;z.2s(D.1y[H],0)};z.3X=u(){7(!D.1y)D.1y={};D.1y[H]=q.Q();7(4D=="1Z"){1e.1L=U;7(H!="1d")y[H]="5a";z.2s(0,D.1y[H])}J{1e.1K=U;z.2s(D.1y[H],0)}};z.49=u(32,47){B t=(1p 5o()).5w();7(t>1e.25+z.4J){4p(z.4q);z.4q=16;z.2p=47;z.a();7(D.2F)D.2F[H]=U;B 2c=U;P(B i 1x D.2F)7(D.2F[i]!==U)2c=12;7(2c){y.5T="";y.1h=4D;7(6.1m(D,"1h")=="1Z")y.1h="2D";7(1e.1K)y.1h="1Z";7(1e.1K||1e.1L)P(B p 1x D.2F)7(p=="1d")6.1I(y,p,D.1y[p]);J y[p]=""}7(2c&&6.1t(1e.1X))1e.1X.14(D)}J{B n=t-q.4J;B p=n/1e.25;z.2p=1e.1v&&6.1v[1e.1v]?6.1v[1e.1v](p,n,32,(47-32),1e.25):((-6h.7O(p*6h.8L)/2)+0.5)*(47-32)+32;z.a()}}}})}',62,545,'||||||jQuery|if|||||||||||||||||||this||||function|return||||||var|type|elem|fn|data|event|prop|length|else|each|ret|callback|xml|value|for|cur|speed|element|undefined|true|url|browser||name|||parentNode|false||apply|status|null|document|indexOf|className|val|firstChild|obj|opacity|options|nodeName|push|display|result|msie|global|constructor|css|test|handler|new|style|arg|expr|isFunction|opt|easing|window|in|orig|extend|arguments|context|typeof|filter|args|queue|hidden|events|attr|re|hide|show|add|old|target|table|token|replace|trigger|num|elems|div|ifModified|complete|key|none|tbody|params|while|string|nodeType|duration|animate|ready|height|timeout|nth|get|done|script|nextSibling|remove|not|index|tb|fix|merge|oid|z0|preventDefault|find|now|grep|pushStack|custom|innerHTML|first|cssFloat|catch|encodeURIComponent|Array|el|guid|sibling|error|block|oldblock|curAnim|try|stopPropagation|childNodes|id|wrap|text|success|safari|load|res|exec|al|_|last|substr|has|disabled|insertBefore|selected|checked|curCSS|map|firstNum|removeChild|re2|trim|getAttribute|onreadystatechange|handlers|on|originalEvent|fx|readyList|parPos|src|opera|param|mozilla|visible|domManip|clean|cloneNode|tr|call|split|XMLHttpRequest|ajaxSettings|append|child|String|empty|ajax|form|button|inArray|multiFilter|setRequestHeader|foundToken|9_|readyState|tag|modRes|responseText|second|ival|handleError|toUpperCase|setInterval|makeArray|slice|break|oWidth|Number|returnValue|lastModified|styleFloat|bind|width|isReady|toggle|jquery|dir|eval|mouseover|select|to|defaultView|position|oHeight|lastNum|async|step|globalEval|static|pos|swap|self|from|end|float|alpha|radio|inv|is|toLowerCase|visibility|00|clearInterval|timer|rec|isTimeout|dataType|_resort|RegExp|Function|getAll|requestDone|parents|matched|isXMLDoc|appendChild|oldDisplay|active|triggered|file|documentElement|fn2|startTime|Modified|shift|lastToggle|deep|handleHover|getResponseHeader|ct|submit|px|parseFloat|html|evalScripts|getComputedStyle|getElementById|clone|els|safariTimer|currentStyle|unload|force|execScript|getPropertyValue|newProp|setTimeout|zoom|getScript|1px|sl|settings|GET|rl|check|_toggle|processData|prepend|before|state|removeAttr|ajaxStart|lt|Date|gt|eq|contentType|previousSibling|after|parent|contains|getTime|checkbox|password|appendTo|image|reset|input|webkit|href|continue|beforeSend|ajaxSend|ownerDocument|getElementsByTagName|tmp|notmodified|parse|ajaxSuccess|ajaxComplete|_prefix|ajaxStop|even|odd|overflow|delete|POST|ajaxError|200|handle|httpSuccess|nodeValue|unshift|__ie_init|srcElement|body|pageX|tagName|clientX|scrollLeft|httpNotModified|dequeue|Last|scrollTop|304|xmlRes|unbind|100|Math|httpData|click|mouseout|parseInt|json|createElement|DOMContentLoaded|prevObject|ol|setArray|exclude|join|one|max|do|relative|clientHeight|clientWidth|loadIfModified|serialize|toString|thead|tfoot|td|th|textContent|ActiveXObject|htmlFor|Microsoft|class|XMLHTTP|readOnly|gi|match|getIfModified|9999|getJSON|getAttributeNode|post|setAttribute|ig|ajaxTimeout|ajaxSetup|concat|application|userAgent|compatible|www|compatMode|CSS1Compat|next|urlencoded|siblings|children|slideDown|prependTo|slideUp|Top|insertAfter|slideToggle|removeAttribute|addClass|removeClass|open|toggleClass|Content|Type|lastChild|If|only|Since|fadeIn|Thu|01|fadeOut|enabled|Jan|1970|fadeTo|GMT|textarea|Requested|With|prev|overrideMimeType|Connection|close|boxModel|right|object|Object|navigator|substring|abort|cos|font|send|slow|600|fast|400|location|protocol|300|pageY|clientY|method|action|cancelBubble|hover|fromElement|toElement|relatedTarget|removeEventListener|blur|readonly|focus|resize|content|scroll|dblclick|mousedown|mouseup|mousemove|responseXML|change|keydown|keypress|keyup|addEventListener|write|prototype|size|scr|ipt|createTextNode|defer|FORM|reverse|noConflict|loaded|10000|weight|line|Bottom|Right|Left|padding|border|Width|offsetHeight|offsetWidth|absolute|PI|left'.split('|'),0,{}));jQuery.noConflict(); +/* + * jQuery 1.1.4 - New Wave Javascript + * + * Copyright (c) 2007 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2007-08-23 21:49:27 -0400 (Thu, 23 Aug 2007) $ + * $Rev: 2862 $ + */ +eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(9(){6(1f C!="Q")E v=C;E C=19.16=9(a,c){6(19==7||!7.4a)F 1s C(a,c);F 7.4a(a,c)};6(1f $!="Q")E B=$;19.$=C;E q=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;C.15=C.3v={4a:9(a,c){a=a||R;6(1f a=="1E"){E m=q.2d(a);6(m&&(m[1]||!c)){6(m[1])a=C.3c([m[1]]);G{E b=R.37(m[3]);6(b)6(b.2j!=m[3])F C().1F(a);G{7[0]=b;7.H=1;F 7}G a=[]}}G F 1s C(c).1F(a)}G 6(C.1g(a))F 1s C(R)[C.15.1L?"1L":"2f"](a);F 7.5J(a.1b==1K&&a||(a.3w||a.H&&a!=19&&!a.1t&&a[0]!=Q&&a[0].1t)&&C.2V(a)||[a])},3w:"1.1.4",7K:9(){F 7.H},H:0,21:9(a){F a==Q?C.2V(7):7[a]},1O:9(a){E b=C(a);b.5c=7;F b},5J:9(a){7.H=0;1K.3v.Y.T(7,a);F 7},J:9(a,b){F C.J(7,a,b)},45:9(a){E b=-1;7.J(9(i){6(7==a)b=i});F b},1j:9(f,d,e){E c=f;6(f.1b==3n)6(d==Q)F 7.H&&C[e||"1j"](7[0],f)||Q;G{c={};c[f]=d}F 7.J(9(a){I(E b 17 c)C.1j(e?7.S:7,b,C.4Q(7,c[b],e,a,b))})},1h:9(b,a){F 7.1j(b,a,"34")},2Q:9(e){6(1f e!="4P"&&e!=K)F 7.3K().3H(R.60(e));E t="";C.J(e||7,9(){C.J(7.2Z,9(){6(7.1t!=8)t+=7.1t!=1?7.5S:C.15.2Q([7])})});F t},82:9(){E a,2e=1a;F 7.J(9(){6(!a)a=C.3c(2e,7.2I);E b=a[0].3B(O);7.P.2p(b,7);20(b.1k)b=b.1k;b.4p(7)})},3H:9(){F 7.2J(1a,O,1,9(a){7.4p(a)})},5v:9(){F 7.2J(1a,O,-1,9(a){7.2p(a,7.1k)})},5u:9(){F 7.2J(1a,M,1,9(a){7.P.2p(a,7)})},5t:9(){F 7.2J(1a,M,-1,9(a){7.P.2p(a,7.2a)})},3L:9(){F 7.5c||C([])},1F:9(t){E b=C.3M(7,9(a){F C.1F(t,a)});F 7.1O(/[^+>] [^+>]/.1d(t)||t.U("..")>-1?C.4d(b):b)},7o:9(e){e=e!=Q?e:O;E d=7.1r(7.1F("*"));6(C.N.12){d.J(9(){7.2l$1i={};I(E a 17 7.$1i)7.2l$1i[a]=C.14({},7.$1i[a])}).49()}E r=7.1O(C.3M(7,9(a){F a.3B(e)}));6(C.N.12){d.J(9(){E c=7.2l$1i;I(E a 17 c)I(E b 17 c[a])C.1c.1r(7,a,c[a][b],c[a][b].V);7.2l$1i=K})}6(e){E f=r.1r(r.1F(\'*\')).1l(\'2b,39[@L=3i]\');d.1l(\'2b,39[@L=3i]\').J(9(i){6(7.3j)f[i].3j=7.3j;6(7.27)f[i].27=O})}F r},1l:9(t){F 7.1O(C.1g(t)&&C.2B(7,9(b,a){F t.T(b,[a])})||C.2R(t,7))},5l:9(t){F 7.1O(t.1b==3n&&C.2R(t,7,O)||C.2B(7,9(a){F(t.1b==1K||t.3w)?C.4K(a,t)<0:a!=t}))},1r:9(t){F 7.1O(C.29(7.21(),t.1b==3n?C(t).21():t.H!=Q&&(!t.W||t.W=="6s")?t:[t]))},3y:9(a){F a?C.2R(a,7).H>0:M},2G:9(a){F a==Q?(7.H?7[0].2A:K):7.1j("2A",a)},5W:9(a){F a==Q?(7.H?7[0].2W:K):7.3K().3H(a)},3S:9(){F 7.1O(1K.3v.3S.T(7,1a))},2J:9(f,d,g,e){E c=7.H>1,a;F 7.J(9(){6(!a){a=C.3c(f,7.2I);6(g<0)a.8E()}E b=7;6(d&&C.W(7,"1A")&&C.W(a[0],"3O"))b=7.4L("1w")[0]||7.4p(R.6a("1w"));C.J(a,9(){6(C.W(7,"33")){6(7.32)C.31({1G:7.32,2w:M,3G:"33"});G C.4E(7.2Q||7.5Z||7.2W||"")}G e.T(b,[c?7.3B(O):7])})})}};C.14=C.15.14=9(){E c=1a[0]||{},a=1,1M=1a.H,4D=M;6(c.1b==8d){4D=c;c=1a[1]||{}}6(1M==1){c=7;a=0}E b;I(;a<1M;a++)6((b=1a[a])!=K)I(E i 17 b){6(c==b[i])5X;6(4D&&1f b[i]==\'4P\'&&c[i])C.14(c[i],b[i]);G 6(b[i]!=Q)c[i]=b[i]}F c};C.14({8a:9(a){19.$=B;6(a)19.16=v;F C},1g:9(a){F!!a&&1f a!="1E"&&!a.W&&a.1b!=1K&&/9/i.1d(a+"")},3E:9(a){F a.3D&&!a.4z||a.4y&&a.2I&&!a.2I.4z},4E:9(a){a=C.2s(a);6(a){6(19.5N)19.5N(a);G 6(C.N.1H)19.4x(a,0);G 2T.2S(19,a)}},W:9(b,a){F b.W&&b.W.1I()==a.1I()},J:9(a,b,c){6(c){6(a.H==Q)I(E i 17 a)b.T(a[i],c);G I(E i=0,3A=a.H;i<3A;i++)6(b.T(a[i],c)===M)1J}G{6(a.H==Q)I(E i 17 a)b.2S(a[i],i,a[i]);G I(E i=0,3A=a.H,2G=a[0];i<3A&&b.2S(2G,i,2G)!==M;2G=a[++i]){}}F a},4Q:9(c,b,d,e,a){6(C.1g(b))b=b.2S(c,[e]);E f=/z-?45|7S-?7Q|1e|5y|7O-?1u/i;F b&&b.1b==3x&&d=="34"&&!f.1d(a)?b+"4t":b},18:{1r:9(b,c){C.J((c||"").2M(/\\s+/),9(i,a){6(!C.18.2N(b.18,a))b.18+=(b.18?" ":"")+a})},23:9(b,c){b.18=c!=Q?C.2B(b.18.2M(/\\s+/),9(a){F!C.18.2N(c,a)}).5w(" "):""},2N:9(t,c){F C.4K(c,(t.18||t).3s().2M(/\\s+/))>-1}},1V:9(e,o,f){I(E i 17 o){e.S["2U"+i]=e.S[i];e.S[i]=o[i]}f.T(e,[]);I(E i 17 o)e.S[i]=e.S["2U"+i]},1h:9(e,p){6(p=="1u"||p=="24"){E b={},3p,3o,d=["7J","7G","7F","7B"];C.J(d,9(){b["7A"+7]=0;b["7x"+7+"7u"]=0});C.1V(e,b,9(){6(C(e).3y(\':4N\')){3p=e.7t;3o=e.7q}G{e=C(e.3B(O)).1F(":4e").5d("27").3L().1h({3V:"1C",3k:"7n",11:"2m",7h:"0",7e:"0"}).57(e.P)[0];E a=C.1h(e.P,"3k")||"3g";6(a=="3g")e.P.S.3k="76";3p=e.74;3o=e.71;6(a=="3g")e.P.S.3k="3g";e.P.3e(e)}});F p=="1u"?3p:3o}F C.34(e,p)},34:9(h,d,g){E i,1R=[],1V=[];9 2E(a){6(!C.N.1H)F M;E b=R.2L.3b(a,K);F!b||b.44("2E")==""}6(d=="1e"&&C.N.12){i=C.1j(h.S,"1e");F i==""?"1":i}6(d.2k(/3a/i))d=x;6(!g&&h.S[d])i=h.S[d];G 6(R.2L&&R.2L.3b){6(d.2k(/3a/i))d="3a";d=d.1v(/([A-Z])/g,"-$1").2D();E e=R.2L.3b(h,K);6(e&&!2E(h))i=e.44(d);G{I(E a=h;a&&2E(a);a=a.P)1R.42(a);I(a=0;a<1R.H;a++)6(2E(1R[a])){1V[a]=1R[a].S.11;1R[a].S.11="2m"}i=d=="11"&&1V[1R.H-1]!=K?"1T":R.2L.3b(h,K).44(d)||"";I(a=0;a<1V.H;a++)6(1V[a]!=K)1R[a].S.11=1V[a]}6(d=="1e"&&i=="")i="1"}G 6(h.41){E f=d.1v(/\\-(\\w)/g,9(m,c){F c.1I()});i=h.41[d]||h.41[f]}F i},3c:9(a,c){E r=[];c=c||R;C.J(a,9(i,b){6(!b)F;6(b.1b==3x)b=b.3s();6(1f b=="1E"){E s=C.2s(b).2D(),1m=c.6a("1m"),1P=[];E a=!s.U("<1Z")&&[1,"<2b>","</2b>"]||!s.U("<6L")&&[1,"<4V>","</4V>"]||s.2k(/^<(6I|1w|6H|6F|6D)/)&&[1,"<1A>","</1A>"]||!s.U("<3O")&&[2,"<1A><1w>","</1w></1A>"]||(!s.U("<6A")||!s.U("<6y"))&&[3,"<1A><1w><3O>","</3O></1w></1A>"]||!s.U("<6x")&&[2,"<1A><1w></1w><4T>","</4T></1A>"]||C.N.12&&[1,"1m<1m>","</1m>"]||[0,"",""];1m.2W=a[1]+b+a[2];20(a[0]--)1m=1m.3Y;6(C.N.12){6(!s.U("<1A")&&s.U("<1w")<0)1P=1m.1k&&1m.1k.2Z;G 6(a[1]=="<1A>"&&s.U("<1w")<0)1P=1m.2Z;I(E n=1P.H-1;n>=0;--n)6(C.W(1P[n],"1w")&&!1P[n].2Z.H)1P[n].P.3e(1P[n]);6(/^\\s/.1d(b))1m.2p(c.60(b.2k(/^\\s*/)[0]),1m.1k)}b=C.2V(1m.2Z)}6(0===b.H&&(!C.W(b,"38")&&!C.W(b,"2b")))F;6(b[0]==Q||C.W(b,"38")||b.6u)r.Y(b);G r=C.29(r,b)});F r},1j:9(c,d,a){E e=C.3E(c)?{}:C.4q;6(d=="28"&&C.N.1H)c.P.3j;6(e[d]){6(a!=Q)c[e[d]]=a;F c[e[d]]}G 6(C.N.12&&d=="S")F C.1j(c.S,"6p",a);G 6(a==Q&&C.N.12&&C.W(c,"38")&&(d=="6n"||d=="6m"))F c.6k(d).5S;G 6(c.4y){6(a!=Q)c.6j(d,a);6(C.N.12&&/5R|32/.1d(d)&&!C.3E(c))F c.3F(d,2);F c.3F(d)}G{6(d=="1e"&&C.N.12){6(a!=Q){c.5y=1;c.1l=(c.1l||"").1v(/5T\\([^)]*\\)/,"")+(3m(a).3s()=="6d"?"":"5T(1e="+a*6c+")")}F c.1l?(3m(c.1l.2k(/1e=([^)]*)/)[1])/6c).3s():""}d=d.1v(/-([a-z])/8I,9(z,b){F b.1I()});6(a!=Q)c[d]=a;F c[d]}},2s:9(t){F(t||"").1v(/^\\s+|\\s+$/g,"")},2V:9(a){E r=[];6(1f a!="8H")I(E i=0,1M=a.H;i<1M;i++)r.Y(a[i]);G r=a.3S(0);F r},4K:9(b,a){I(E i=0,1M=a.H;i<1M;i++)6(a[i]==b)F i;F-1},29:9(a,b){6(C.N.12){I(E i=0;b[i];i++)6(b[i].1t!=8)a.Y(b[i])}G I(E i=0;b[i];i++)a.Y(b[i]);F a},4d:9(a){E r=[],4O=C.1q++;2g{I(E i=0,69=a.H;i<69;i++)6(4O!=a[i].1q){a[i].1q=4O;r.Y(a[i])}}2h(e){r=a}F r},1q:0,2B:9(b,a,c){6(1f a=="1E")a=2T("M||9(a,i){F "+a+"}");E d=[];I(E i=0,3P=b.H;i<3P;i++)6(!c&&a(b[i],i)||c&&!a(b[i],i))d.Y(b[i]);F d},3M:9(c,b){6(1f b=="1E")b=2T("M||9(a){F "+b+"}");E d=[];I(E i=0,3P=c.H;i<3P;i++){E a=b(c[i],i);6(a!==K&&a!=Q){6(a.1b!=1K)a=[a];d=d.8x(a)}}F d}});E u=8w.8u.2D();C.N={6b:(u.2k(/.+(?:8s|8q|8p|8o)[\\/: ]([\\d.]+)/)||[])[1],1H:/61/.1d(u),2t:/2t/.1d(u),12:/12/.1d(u)&&!/2t/.1d(u),3J:/3J/.1d(u)&&!/(8n|61)/.1d(u)};E x=C.N.12?"3I":"4G";C.14({8m:!C.N.12||R.8l=="8k",3I:C.N.12?"3I":"4G",4q:{"I":"8j","8i":"18","3a":x,4G:x,3I:x,2W:"2W",18:"18",2A:"2A",30:"30",27:"27",8h:"8g",28:"28",8f:"8e"}});C.J({5Y:"a.P",4C:"16.4C(a)",8c:"16.25(a,2,\'2a\')",8b:"16.25(a,2,\'4B\')",88:"16.4A(a.P.1k,a)",87:"16.4A(a.1k)"},9(i,n){C.15[i]=9(a){E b=C.3M(7,n);6(a&&1f a=="1E")b=C.2R(a,b);F 7.1O(C.4d(b))}});C.J({57:"3H",86:"5v",2p:"5u",85:"5t"},9(i,n){C.15[i]=9(){E a=1a;F 7.J(9(){I(E j=0,1M=a.H;j<1M;j++)C(a[j])[n](7)})}});C.J({5d:9(a){C.1j(7,a,"");7.84(a)},83:9(c){C.18.1r(7,c)},81:9(c){C.18.23(7,c)},80:9(c){C.18[C.18.2N(7,c)?"23":"1r"](7,c)},23:9(a){6(!a||C.1l(a,[7]).r.H)7.P.3e(7)},3K:9(){20(7.1k)7.3e(7.1k)}},9(i,n){C.15[i]=9(){F 7.J(n,1a)}});C.J(["5Q","5P","5M","5L"],9(i,n){C.15[n]=9(a,b){F 7.1l(":"+n+"("+a+")",b)}});C.J(["1u","24"],9(i,n){C.15[n]=9(h){F h==Q?(7.H?C.1h(7[0],n):K):7.1h(n,h.1b==3n?h:h+"4t")}});E A=C.N.1H&&5K(C.N.6b)<7Z?"(?:[\\\\w*2l-]|\\\\\\\\.)":"(?:[\\\\w\\7Y-\\7V*2l-]|\\\\\\\\.)",5I=1s 3C("^[/>]\\\\s*("+A+"+)"),5H=1s 3C("^("+A+"+)(#)("+A+"+)"),5G=1s 3C("^([#.]?)("+A+"*)");C.14({4w:{"":"m[2]==\'*\'||16.W(a,m[2])","#":"a.3F(\'2j\')==m[2]",":":{5P:"i<m[3]-0",5M:"i>m[3]-0",25:"m[3]-0==i",5Q:"m[3]-0==i",2H:"i==0",2P:"i==r.H-1",5E:"i%2==0",5D:"i%2","2H-3z":"a.P.4L(\'*\')[0]==a","2P-3z":"16.25(a.P.3Y,1,\'4B\')==a","7U-3z":"!16.25(a.P.3Y,2,\'4B\')",5Y:"a.1k",3K:"!a.1k",5L:"(a.5Z||a.7T||\'\').U(m[3])>=0",4N:\'"1C"!=a.L&&16.1h(a,"11")!="1T"&&16.1h(a,"3V")!="1C"\',1C:\'"1C"==a.L||16.1h(a,"11")=="1T"||16.1h(a,"3V")=="1C"\',7R:"!a.30",30:"a.30",27:"a.27",28:"a.28||16.1j(a,\'28\')",2Q:"\'2Q\'==a.L",4e:"\'4e\'==a.L",3i:"\'3i\'==a.L",4v:"\'4v\'==a.L",5C:"\'5C\'==a.L",4u:"\'4u\'==a.L",5B:"\'5B\'==a.L",5A:"\'5A\'==a.L",1X:\'"1X"==a.L||16.W(a,"1X")\',39:"/39|2b|7P|1X/i.1d(a.W)",2N:"16.1F(m[3],a).H"},"[":"16.1F(m[2],a).H"},5x:[/^\\[ *(@)([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(\\[)\\s*(.*?(\\[.*?\\])?[^[]*?)\\s*\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1s 3C("^([:.#]*)("+A+"+)")],2R:9(a,c,b){E d,1Y=[];20(a&&a!=d){d=a;E f=C.1l(a,c,b);a=f.t.1v(/^\\s*,\\s*/,"");1Y=b?c=f.r:C.29(1Y,f.r)}F 1Y},1F:9(t,l){6(1f t!="1E")F[t];6(l&&!l.1t)l=K;l=l||R;6(!t.U("//")){t=t.2K(2,t.H)}G 6(!t.U("/")&&!l.2I){l=l.3D;t=t.2K(1,t.H);6(t.U("/")>=1)t=t.2K(t.U("/"),t.H)}E d=[l],2q=[],2P;20(t&&2P!=t){E r=[];2P=t;t=C.2s(t).1v(/^\\/\\//,"");E k=M;E g=5I;E m=g.2d(t);6(m){E o=m[1].1I();I(E i=0;d[i];i++)I(E c=d[i].1k;c;c=c.2a)6(c.1t==1&&(o=="*"||c.W.1I()==o.1I()))r.Y(c);d=r;t=t.1v(g,"");6(t.U(" ")==0)5X;k=O}G{g=/^((\\/?\\.\\.)|([>\\/+~]))\\s*(\\w*)/i;6((m=g.2d(t))!=K){r=[];E o=m[4],1q=C.1q++;m=m[1];I(E j=0,2o=d.H;j<2o;j++)6(m.U("..")<0){E n=m=="~"||m=="+"?d[j].2a:d[j].1k;I(;n;n=n.2a)6(n.1t==1){6(m=="~"&&n.1q==1q)1J;6(!o||n.W.1I()==o.1I()){6(m=="~")n.1q=1q;r.Y(n)}6(m=="+")1J}}G r.Y(d[j].P);d=r;t=C.2s(t.1v(g,""));k=O}}6(t&&!k){6(!t.U(",")){6(l==d[0])d.4s();2q=C.29(2q,d);r=d=[l];t=" "+t.2K(1,t.H)}G{E h=5H;E m=h.2d(t);6(m){m=[0,m[2],m[3],m[1]]}G{h=5G;m=h.2d(t)}m[2]=m[2].1v(/\\\\/g,"");E f=d[d.H-1];6(m[1]=="#"&&f&&f.37&&!C.3E(f)){E p=f.37(m[2]);6((C.N.12||C.N.2t)&&p&&1f p.2j=="1E"&&p.2j!=m[2])p=C(\'[@2j="\'+m[2]+\'"]\',f)[0];d=r=p&&(!m[3]||C.W(p,m[3]))?[p]:[]}G{I(E i=0;d[i];i++){E a=m[1]!=""||m[0]==""?"*":m[2];6(a=="*"&&d[i].W.2D()=="4P")a="2O";r=C.29(r,d[i].4L(a))}6(m[1]==".")r=C.4r(r,m[2]);6(m[1]=="#"){E e=[];I(E i=0;r[i];i++)6(r[i].3F("2j")==m[2]){e=[r[i]];1J}r=e}d=r}t=t.1v(h,"")}}6(t){E b=C.1l(t,r);d=r=b.r;t=C.2s(b.t)}}6(t)d=[];6(d&&l==d[0])d.4s();2q=C.29(2q,d);F 2q},4r:9(r,m,a){m=" "+m+" ";E c=[];I(E i=0;r[i];i++){E b=(" "+r[i].18+" ").U(m)>=0;6(!a&&b||a&&!b)c.Y(r[i])}F c},1l:9(t,r,h){E d;20(t&&t!=d){d=t;E p=C.5x,m;I(E i=0;p[i];i++){m=p[i].2d(t);6(m){t=t.7N(m[0].H);m[2]=m[2].1v(/\\\\/g,"");1J}}6(!m)1J;6(m[1]==":"&&m[2]=="5l")r=C.1l(m[3],r,O).r;G 6(m[1]==".")r=C.4r(r,m[2],h);G 6(m[1]=="@"){E g=[],L=m[3];I(E i=0,2o=r.H;i<2o;i++){E a=r[i],z=a[C.4q[m[2]]||m[2]];6(z==K||/5R|32|28/.1d(m[2]))z=C.1j(a,m[2])||\'\';6((L==""&&!!z||L=="="&&z==m[5]||L=="!="&&z!=m[5]||L=="^="&&z&&!z.U(m[5])||L=="$="&&z.2K(z.H-m[5].H)==m[5]||(L=="*="||L=="~=")&&z.U(m[5])>=0)^h)g.Y(a)}r=g}G 6(m[1]==":"&&m[2]=="25-3z"){E e=C.1q++,g=[],1d=/(\\d*)n\\+?(\\d*)/.2d(m[3]=="5E"&&"2n"||m[3]=="5D"&&"2n+1"||!/\\D/.1d(m[3])&&"n+"+m[3]||m[3]),2H=(1d[1]||1)-0,d=1d[2]-0;I(E i=0,2o=r.H;i<2o;i++){E j=r[i],P=j.P;6(e!=P.1q){E c=1;I(E n=P.1k;n;n=n.2a)6(n.1t==1)n.4o=c++;P.1q=e}E b=M;6(2H==1){6(d==0||j.4o==d)b=O}G 6((j.4o+d)%2H==0)b=O;6(b^h)g.Y(j)}r=g}G{E f=C.4w[m[1]];6(1f f!="1E")f=C.4w[m[1]][m[2]];f=2T("M||9(a,i){F "+f+"}");r=C.2B(r,f,h)}}F{r:r,t:t}},4C:9(c){E b=[];E a=c.P;20(a&&a!=R){b.Y(a);a=a.P}F b},25:9(a,e,c,b){e=e||1;E d=0;I(;a;a=a[c])6(a.1t==1&&++d==e)1J;F a},4A:9(n,a){E r=[];I(;n;n=n.2a){6(n.1t==1&&(!a||n!=a))r.Y(n)}F r}});C.1c={1r:9(f,d,c,b){6(C.N.12&&f.3t!=Q)f=19;6(!c.22)c.22=7.22++;6(b!=Q){E e=c;c=9(){F e.T(7,1a)};c.V=b;c.22=e.22}6(!f.$1i)f.$1i={};6(!f.$1y)f.$1y=9(){E a;6(1f C=="Q"||C.1c.4n)F a;a=C.1c.1y.T(f,1a);F a};E g=f.$1i[d];6(!g){g=f.$1i[d]={};6(f.4m)f.4m(d,f.$1y,M);G f.7M("3r"+d,f.$1y)}g[c.22]=c;7.1D[d]=O},22:1,1D:{},23:9(c,b,a){E d=c.$1i,2c,45;6(d){6(b&&b.L){a=b.4l;b=b.L}6(!b){I(b 17 d)7.23(c,b)}G 6(d[b]){6(a)4k d[b][a.22];G I(a 17 c.$1i[b])4k d[b][a];I(2c 17 d[b])1J;6(!2c){6(c.4j)c.4j(b,c.$1y,M);G c.7L("3r"+b,c.$1y);2c=K;4k d[b]}}I(2c 17 d)1J;6(!2c)c.$1y=c.$1i=K}},1z:9(c,b,d){b=C.2V(b||[]);6(!d){6(7.1D[c])C("*").1r([19,R]).1z(c,b)}G{E a,2c,15=C.1g(d[c]||K);b.42(7.4i({L:c,1S:d}));6(C.1g(d.$1y))a=d.$1y.T(d,b);6(!15&&d["3r"+c]&&d["3r"+c].T(d,b)===M)a=M;6(15&&a!==M&&!(C.W(d,\'a\')&&c=="4h")){7.4n=O;d[c]()}7.4n=M}},1y:9(b){E a;b=C.1c.4i(b||19.1c||{});E c=7.$1i&&7.$1i[b.L],2e=1K.3v.3S.2S(1a,1);2e.42(b);I(E j 17 c){2e[0].4l=c[j];2e[0].V=c[j].V;6(c[j].T(7,2e)===M){b.2u();b.2X();a=M}}6(C.N.12)b.1S=b.2u=b.2X=b.4l=b.V=K;F a},4i:9(c){E a=c;c=C.14({},a);c.2u=9(){6(a.2u)a.2u();a.7I=M};c.2X=9(){6(a.2X)a.2X();a.7H=O};6(!c.1S&&c.5r)c.1S=c.5r;6(C.N.1H&&c.1S.1t==3)c.1S=a.1S.P;6(!c.4g&&c.4F)c.4g=c.4F==c.1S?c.7C:c.4F;6(c.5p==K&&c.66!=K){E e=R.3D,b=R.4z;c.5p=c.66+(e&&e.5o||b.5o||0);c.7z=c.7v+(e&&e.5m||b.5m||0)}6(!c.3Q&&(c.5k||c.5j))c.3Q=c.5k||c.5j;6(!c.5i&&c.5g)c.5i=c.5g;6(!c.3Q&&c.1X)c.3Q=(c.1X&1?1:(c.1X&2?3:(c.1X&4?2:0)));F c}};C.15.14({3l:9(c,a,b){F c=="5f"?7.5e(c,a,b):7.J(9(){C.1c.1r(7,c,b||a,b&&a)})},5e:9(d,b,c){F 7.J(9(){C.1c.1r(7,d,9(a){C(7).49(a);F(c||b).T(7,1a)},c&&b)})},49:9(a,b){F 7.J(9(){C.1c.23(7,a,b)})},1z:9(a,b){F 7.J(9(){C.1c.1z(a,b,7)})},1W:9(){E a=1a;F 7.4h(9(e){7.3T=0==7.3T?1:0;e.2u();F a[7.3T].T(7,[e])||M})},7p:9(f,g){9 3U(e){E p=e.4g;20(p&&p!=7)2g{p=p.P}2h(e){p=7};6(p==7)F M;F(e.L=="3W"?f:g).T(7,[e])}F 7.3W(3U).5b(3U)},1L:9(f){5a();6(C.36)f.T(R,[C]);G C.2C.Y(9(){F f.T(7,[C])});F 7}});C.14({36:M,2C:[],1L:9(){6(!C.36){C.36=O;6(C.2C){C.J(C.2C,9(){7.T(R)});C.2C=K}6(C.N.3J||C.N.2t)R.4j("59",C.1L,M);6(!19.7m.H)C(19).2f(9(){C("#4b").23()})}}});C.J(("7l,7k,2f,7j,7i,5f,4h,7g,"+"7f,7d,7c,3W,5b,7b,2b,"+"4u,7a,79,78,3f").2M(","),9(i,o){C.15[o]=9(f){F f?7.3l(o,f):7.1z(o)}});E w=M;9 5a(){6(w)F;w=O;6(C.N.3J||C.N.2t)R.4m("59",C.1L,M);G 6(C.N.12){R.75("<73"+"72 2j=4b 70=O "+"32=//:><\\/33>");E a=R.37("4b");6(a)a.6Z=9(){6(R.3d!="1x")F;C.1L()};a=K}G 6(C.N.1H)C.48=3t(9(){6(R.3d=="6Y"||R.3d=="1x"){47(C.48);C.48=K;C.1L()}},10);C.1c.1r(19,"2f",C.1L)}C.15.14({6X:9(c,b,a){7.2f(c,b,a,1)},2f:9(g,e,c,d){6(C.1g(g))F 7.3l("2f",g);c=c||9(){};E f="46";6(e)6(C.1g(e)){c=e;e=K}G{e=C.2O(e);f="55"}E h=7;C.31({1G:g,L:f,V:e,2F:d,1x:9(a,b){6(b=="1U"||!d&&b=="54")h.5W(a.43);4x(9(){h.J(c,[a.43,b,a])},13)}});F 7},6W:9(){F C.2O(7)},6V:9(){}});C.J("53,52,51,50,4Z,5h".2M(","),9(i,o){C.15[o]=9(f){F 7.3l(o,f)}});C.14({21:9(e,c,a,d,b){6(C.1g(c)){a=c;c=K}F C.31({L:"46",1G:e,V:c,1U:a,3G:d,2F:b})},6U:9(d,b,a,c){F C.21(d,b,a,c,1)},6T:9(b,a){F C.21(b,K,a,"33")},77:9(c,b,a){F C.21(c,b,a,"56")},6S:9(d,b,a,c){6(C.1g(b)){a=b;b={}}F C.31({L:"55",1G:d,V:b,1U:a,3G:c})},6R:9(a){C.3u.1Q=a},6Q:9(a){C.14(C.3u,a)},3u:{1D:O,L:"46",1Q:0,4Y:"6P/x-6O-38-6N",4X:O,2w:O,V:K},3h:{},31:9(s){s=C.14(O,s,C.14(O,{},C.3u,s));6(s.V){6(s.4X&&1f s.V!="1E")s.V=C.2O(s.V);6(s.L.2D()=="21"){s.1G+=(s.1G.U("?")>-1?"&":"?")+s.V;s.V=K}}6(s.1D&&!C.40++)C.1c.1z("53");E f=M;E h=19.4W?1s 4W("6M.6K"):1s 58();h.6J(s.L,s.1G,s.2w);6(s.V)h.4c("7r-7s",s.4Y);6(s.2F)h.4c("6G-3Z-6E",C.3h[s.1G]||"7w, 6C 7y 6B 4J:4J:4J 6z");h.4c("X-7D-7E","58");6(s.4U)s.4U(h);6(s.1D)C.1c.1z("5h",[h,s]);E g=9(d){6(!f&&h&&(h.3d==4||d=="1Q")){f=O;6(i){47(i);i=K}E c=d=="1Q"&&"1Q"||!C.5n(h)&&"3f"||s.2F&&C.5s(h,s.1G)&&"54"||"1U";6(c=="1U"){2g{E a=C.5q(h,s.3G)}2h(e){c="4I"}}6(c=="1U"){E b;2g{b=h.4f("4S-3Z")}2h(e){}6(s.2F&&b)C.3h[s.1G]=b;6(s.1U)s.1U(a,c);6(s.1D)C.1c.1z("4Z",[h,s])}G C.3X(s,h,c);6(s.1D)C.1c.1z("51",[h,s]);6(s.1D&&!--C.40)C.1c.1z("52");6(s.1x)s.1x(h,c);6(s.2w)h=K}};6(s.2w){E i=3t(g,13);6(s.1Q>0)4x(9(){6(h){h.6w();6(!f)g("1Q")}},s.1Q)}2g{h.6v(s.V)}2h(e){C.3X(s,h,K,e)}6(!s.2w)g();F h},3X:9(s,a,b,e){6(s.3f)s.3f(a,b,e);6(s.1D)C.1c.1z("50",[a,s,e])},40:0,5n:9(r){2g{F!r.26&&6t.6r=="4v:"||(r.26>=4R&&r.26<6q)||r.26==5z||C.N.1H&&r.26==Q}2h(e){}F M},5s:9(a,c){2g{E b=a.4f("4S-3Z");F a.26==5z||b==C.3h[c]||C.N.1H&&a.26==Q}2h(e){}F M},5q:9(r,a){E b=r.4f("6o-L");E c=a=="5F"||!a&&b&&b.U("5F")>=0;V=c?r.7W:r.43;6(c&&V.3D.4y=="4I")7X"4I";6(a=="33")C.4E(V);6(a=="56")V=2T("("+V+")");F V},2O:9(a){E s=[];6(a.1b==1K||a.3w)C.J(a,9(){s.Y(2y(7.6l)+"="+2y(7.2A))});G I(E j 17 a)6(a[j]&&a[j].1b==1K)C.J(a[j],9(){s.Y(2y(j)+"="+2y(7))});G s.Y(2y(j)+"="+2y(a[j]));F s.5w("&")}});C.15.14({1o:9(b,a){F b?7.1B({1u:"1o",24:"1o",1e:"1o"},b,a):7.1l(":1C").J(9(){7.S.11=7.2r?7.2r:"";6(C.1h(7,"11")=="1T")7.S.11="2m"}).3L()},1p:9(b,a){F b?7.1B({1u:"1p",24:"1p",1e:"1p"},b,a):7.1l(":4N").J(9(){7.2r=7.2r||C.1h(7,"11");6(7.2r=="1T")7.2r="2m";7.S.11="1T"}).3L()},5O:C.15.1W,1W:9(a,b){F C.1g(a)&&C.1g(b)?7.5O(a,b):a?7.1B({1u:"1W",24:"1W",1e:"1W"},a,b):7.J(9(){C(7)[C(7).3y(":1C")?"1o":"1p"]()})},6i:9(b,a){F 7.1B({1u:"1o"},b,a)},6h:9(b,a){F 7.1B({1u:"1p"},b,a)},6g:9(b,a){F 7.1B({1u:"1W"},b,a)},6f:9(b,a){F 7.1B({1e:"1o"},b,a)},89:9(b,a){F 7.1B({1e:"1p"},b,a)},6e:9(c,a,b){F 7.1B({1e:a},c,b)},1B:9(d,h,f,g){F 7.1n(9(){E c=C(7).3y(":1C"),1Z=C.5V(h,f,g),5U=7;I(E p 17 d){6(d[p]=="1p"&&c||d[p]=="1o"&&!c)F C.1g(1Z.1x)&&1Z.1x.T(7);6(p=="1u"||p=="24"){1Z.11=C.1h(7,"11");1Z.2z=7.S.2z}}6(1Z.2z!=K)7.S.2z="1C";7.2v=C.14({},d);C.J(d,9(a,b){E e=1s C.2Y(5U,1Z,a);6(b.1b==3x)e.3R(e.1Y()||0,b);G e[b=="1W"?c?"1o":"1p":b](d)});F O})},1n:9(a,b){6(!b){b=a;a="2Y"}F 7.J(9(){6(!7.1n)7.1n={};6(!7.1n[a])7.1n[a]=[];7.1n[a].Y(b);6(7.1n[a].H==1)b.T(7)})}});C.14({5V:9(b,a,c){E d=b&&b.1b==8G?b:{1x:c||!c&&a||C.1g(b)&&b,1N:b,35:c&&a||a&&a.1b!=8F&&a};d.1N=(d.1N&&d.1N.1b==3x?d.1N:{8D:8C,8B:4R}[d.1N])||8A;d.2U=d.1x;d.1x=9(){C.68(7,"2Y");6(C.1g(d.2U))d.2U.T(7)};F d},35:{62:9(p,n,b,a){F b+a*p},4H:9(p,n,b,a){F((-67.8z(p*67.8y)/2)+0.5)*a+b}},1n:{},68:9(b,a){a=a||"2Y";6(b.1n&&b.1n[a]){b.1n[a].4s();E f=b.1n[a][0];6(f)f.T(b)}},3N:[],2Y:9(f,e,g){E z=7;E y=f.S;z.a=9(){6(e.3q)e.3q.T(f,[z.2x]);6(g=="1e")C.1j(y,"1e",z.2x);G{y[g]=5K(z.2x)+"4t";6(g=="1u"||g=="24")y.11="2m"}};z.65=9(){F 3m(C.1h(f,g))};z.1Y=9(){E r=3m(C.34(f,g));F r&&r>-8v?r:z.65()};z.3R=9(c,b){z.4M=(1s 64()).63();z.2x=c;z.a();C.3N.Y(9(){F z.3q(c,b)});6(C.3N.H==1){E d=3t(9(){E a=C.3N;I(E i=0;i<a.H;i++)6(!a[i]())a.8t(i--,1);6(!a.H)47(d)},13)}};z.1o=9(){6(!f.2i)f.2i={};f.2i[g]=C.1j(f.S,g);e.1o=O;z.3R(0,7.1Y());6(g!="1e")y[g]="8r";C(f).1o()};z.1p=9(){6(!f.2i)f.2i={};f.2i[g]=C.1j(f.S,g);e.1p=O;z.3R(7.1Y(),0)};z.3q=9(a,c){E t=(1s 64()).63();6(t>e.1N+z.4M){z.2x=c;z.a();6(f.2v)f.2v[g]=O;E b=O;I(E i 17 f.2v)6(f.2v[i]!==O)b=M;6(b){6(e.11!=K){y.2z=e.2z;y.11=e.11;6(C.1h(f,"11")=="1T")y.11="2m"}6(e.1p)y.11="1T";6(e.1p||e.1o)I(E p 17 f.2v)C.1j(y,p,f.2i[p])}6(b&&C.1g(e.1x))e.1x.T(f);F M}G{E n=t-7.4M;E p=n/e.1N;z.2x=C.35[e.35||(C.35.4H?"4H":"62")](p,n,a,(c-a),e.1N);z.a()}F O}}})})();',62,541,'||||||if|this||function|||||||||||||||||||||||||||||||var|return|else|length|for|each|null|type|false|browser|true|parentNode|undefined|document|style|apply|indexOf|data|nodeName||push|||display|msie||extend|fn|jQuery|in|className|window|arguments|constructor|event|test|opacity|typeof|isFunction|css|events|attr|firstChild|filter|div|queue|show|hide|mergeNum|add|new|nodeType|height|replace|tbody|complete|handle|trigger|table|animate|hidden|global|string|find|url|safari|toUpperCase|break|Array|ready|al|duration|pushStack|tb|timeout|stack|target|none|success|swap|toggle|button|cur|opt|while|get|guid|remove|width|nth|status|checked|selected|merge|nextSibling|select|ret|exec|args|load|try|catch|orig|id|match|_|block||rl|insertBefore|done|oldblock|trim|opera|preventDefault|curAnim|async|now|encodeURIComponent|overflow|value|grep|readyList|toLowerCase|color|ifModified|val|first|ownerDocument|domManip|substr|defaultView|split|has|param|last|text|multiFilter|call|eval|old|makeArray|innerHTML|stopPropagation|fx|childNodes|disabled|ajax|src|script|curCSS|easing|isReady|getElementById|form|input|float|getComputedStyle|clean|readyState|removeChild|error|static|lastModified|checkbox|selectedIndex|position|bind|parseFloat|String|oWidth|oHeight|step|on|toString|setInterval|ajaxSettings|prototype|jquery|Number|is|child|ol|cloneNode|RegExp|documentElement|isXMLDoc|getAttribute|dataType|append|styleFloat|mozilla|empty|end|map|timers|tr|el|which|custom|slice|lastToggle|handleHover|visibility|mouseover|handleError|lastChild|Modified|active|currentStyle|unshift|responseText|getPropertyValue|index|GET|clearInterval|safariTimer|unbind|init|__ie_init|setRequestHeader|unique|radio|getResponseHeader|relatedTarget|click|fix|removeEventListener|delete|handler|addEventListener|triggered|nodeIndex|appendChild|props|classFilter|shift|px|submit|file|expr|setTimeout|tagName|body|sibling|previousSibling|parents|deep|globalEval|fromElement|cssFloat|swing|parsererror|00|inArray|getElementsByTagName|startTime|visible|num|object|prop|200|Last|colgroup|beforeSend|fieldset|ActiveXObject|processData|contentType|ajaxSuccess|ajaxError|ajaxComplete|ajaxStop|ajaxStart|notmodified|POST|json|appendTo|XMLHttpRequest|DOMContentLoaded|bindReady|mouseout|prevObject|removeAttr|one|unload|ctrlKey|ajaxSend|metaKey|keyCode|charCode|not|scrollTop|httpSuccess|scrollLeft|pageX|httpData|srcElement|httpNotModified|after|before|prepend|join|parse|zoom|304|reset|image|password|odd|even|xml|quickClass|quickID|quickChild|setArray|parseInt|contains|gt|execScript|_toggle|lt|eq|href|nodeValue|alpha|self|speed|html|continue|parent|textContent|createTextNode|webkit|linear|getTime|Date|max|clientX|Math|dequeue|fl|createElement|version|100|NaN|fadeTo|fadeIn|slideToggle|slideUp|slideDown|setAttribute|getAttributeNode|name|method|action|content|cssText|300|protocol|FORM|location|options|send|abort|col|th|GMT|td|1970|01|cap|Since|colg|If|tfoot|thead|open|XMLHTTP|leg|Microsoft|urlencoded|www|application|ajaxSetup|ajaxTimeout|post|getScript|getIfModified|evalScripts|serialize|loadIfModified|loaded|onreadystatechange|defer|clientWidth|ipt|scr|clientHeight|write|relative|getJSON|keyup|keypress|keydown|change|mousemove|mouseup|left|mousedown|dblclick|right|scroll|resize|focus|blur|frames|absolute|clone|hover|offsetWidth|Content|Type|offsetHeight|Width|clientY|Thu|border|Jan|pageY|padding|Left|toElement|Requested|With|Right|Bottom|cancelBubble|returnValue|Top|size|detachEvent|attachEvent|substring|line|textarea|weight|enabled|font|innerText|only|uFFFF|responseXML|throw|u0128|417|toggleClass|removeClass|wrap|addClass|removeAttribute|insertAfter|prependTo|children|siblings|fadeOut|noConflict|prev|next|Boolean|maxLength|maxlength|readOnly|readonly|class|htmlFor|CSS1Compat|compatMode|boxModel|compatible|ie|ra|it|1px|rv|splice|userAgent|10000|navigator|concat|PI|cos|400|fast|600|slow|reverse|Function|Object|array|ig'.split('|'),0,{})); +jQuery.noConflict(); + diff --git a/wp-includes/js/prototype.js b/wp-includes/js/prototype.js index 6253917..979f3b3 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.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.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[^>]*>([\\S\\s]*?)<\/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,63 @@ 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}'); + }, + + isJSON: function() { + var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) 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 +416,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 +440,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 +649,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 +722,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 +740,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 +774,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 +869,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 +1013,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 +1021,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 +1044,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 +1117,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 +1145,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 +1266,54 @@ 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, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)"); + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + var elementClassName = child.className; + if (elementClassName.length == 0) continue; + if (elementClassName == className || elementClassName.match(pattern)) + 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 +1399,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 +1435,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 +1477,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 +1552,7 @@ Element.Methods = { }, empty: function(element) { - return $(element).innerHTML.match(/^\s*$/); + return $(element).innerHTML.blank(); }, descendantOf: function(element, ancestor) { @@ -1361,55 +1571,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 +1676,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 +1748,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 +1876,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 +2049,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 +2631,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 +2679,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 +2700,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 +2765,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 +2958,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 +3023,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 +3034,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 +3048,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 +3162,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 +3258,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/scriptaculous/MIT-LICENSE b/wp-includes/js/scriptaculous/MIT-LICENSE index a67de52..5600377 100644 --- a/wp-includes/js/scriptaculous/MIT-LICENSE +++ b/wp-includes/js/scriptaculous/MIT-LICENSE @@ -1,4 +1,4 @@ -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 diff --git a/wp-includes/js/scriptaculous/builder.js b/wp-includes/js/scriptaculous/builder.js index 199afc1..5b4ce87 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_beta3, Fri May 25 17:19:41 +0200 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 @@ -88,10 +89,14 @@ var Builder = { var attrs = []; for(attribute in attributes) attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + - '="' + attributes[attribute].toString().escapeHTML() + '"'); + '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"'); 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..6783bd0 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_beta3, Fri May 25 17:19:41 +0200 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..8face00 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_beta3, Fri May 25 17:19:41 +0200 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,10 +633,17 @@ var Sortable = { delay: 0, hoverclass: null, ghosting: false, + quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, format: this.SERIALIZE_RULE, + + // these take arrays of elements or ids and can be + // used for better initialization performance + elements: false, + handles: false, + onChange: Prototype.emptyFunction, onUpdate: Prototype.emptyFunction }, arguments[1] || {}); @@ -628,6 +654,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, @@ -681,10 +708,9 @@ var Sortable = { options.droppables.push(element); } - (this.findElements(element, options) || []).each( function(e) { - // handles are per-draggable - var handle = options.handle ? - $(e).down('.'+options.handle,0) : e; + (options.elements || this.findElements(element, options) || []).each( function(e,i) { + var handle = options.handles ? $(options.handles[i]) : + (options.handle ? $(e).getElementsByClassName(options.handle)[0] : e); options.draggables.push( new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); Droppables.add(e, options_for_droppable); diff --git a/wp-includes/js/scriptaculous/effects.js b/wp-includes/js/scriptaculous/effects.js index 6b7e5c3..8e36b7a 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_beta3, Fri May 25 17:19:41 +0200 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/prototype.js b/wp-includes/js/scriptaculous/prototype.js index 6253917..979f3b3 100644 --- a/wp-includes/js/scriptaculous/prototype.js +++ b/wp-includes/js/scriptaculous/prototype.js @@ -1,19 +1,33 @@ -/* Prototype JavaScript framework, version 1.5.0 +/* Prototype JavaScript framework, version 1.5.1.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.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[^>]*>([\\S\\s]*?)<\/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,63 @@ 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}'); + }, + + isJSON: function() { + var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) 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 +416,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 +440,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 +649,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 +722,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 +740,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 +774,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 +869,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 +1013,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 +1021,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 +1044,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 +1117,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 +1145,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 +1266,54 @@ 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, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)"); + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + var elementClassName = child.className; + if (elementClassName.length == 0) continue; + if (elementClassName == className || elementClassName.match(pattern)) + 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 +1399,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 +1435,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 +1477,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 +1552,7 @@ Element.Methods = { }, empty: function(element) { - return $(element).innerHTML.match(/^\s*$/); + return $(element).innerHTML.blank(); }, descendantOf: function(element, ancestor) { @@ -1361,55 +1571,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 +1676,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 +1748,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 +1876,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 +2049,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 +2631,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 +2679,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 +2700,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 +2765,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 +2958,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 +3023,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 +3034,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 +3048,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 +3162,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 +3258,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/scriptaculous/scriptaculous.js b/wp-includes/js/scriptaculous/scriptaculous.js index 0844cef..e39c40e 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_beta3, Fri May 25 17:19:41 +0200 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,33 @@ // For details, see the script.aculo.us web site: http://script.aculo.us/ var Scriptaculous = { - Version: '1.7.0', + Version: '1.7.1_beta3', 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( + if ( includes ) + includes[1].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..ef0459b 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_beta3, Fri May 25 17:19:41 +0200 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..164c79a --- /dev/null +++ b/wp-includes/js/scriptaculous/sound.js @@ -0,0 +1,60 @@ +// script.aculo.us sound.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 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..45c3776 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_beta3, Fri May 25 17:19:41 +0200 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/ @@ -121,7 +121,7 @@ Test.Unit.Logger.prototype = { this.loglines = $('loglines'); }, _toHTML: function(txt) { - return txt.escapeHTML().replace(/\n/g,"<br/>"); + return txt.escapeHTML().replace(/\n/g,"<br />"); }, addLinksToResults: function(){ $$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log diff --git a/wp-includes/js/scriptaculous/wp-scriptaculous.js b/wp-includes/js/scriptaculous/wp-scriptaculous.js index 90e6167..e39c40e 100644 --- a/wp-includes/js/scriptaculous/wp-scriptaculous.js +++ b/wp-includes/js/scriptaculous/wp-scriptaculous.js @@ -1,4 +1,6 @@ -// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// script.aculo.us scriptaculous.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007 + +// 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 @@ -10,20 +12,37 @@ // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// For details, see the script.aculo.us web site: http://script.aculo.us/ var Scriptaculous = { - Version: '1.7.0', + Version: '1.7.1_beta3', 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(\?.*)?$/)) diff --git a/wp-includes/js/tinymce/license.html b/wp-includes/js/tinymce/license.html deleted file mode 100644 index c0c9c9a..0000000 --- a/wp-includes/js/tinymce/license.html +++ /dev/null @@ -1,465 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>TinyMCE License (LGPL)</title>
-<link href="css/screen.css" rel="stylesheet" type="text/css" />
-</head>
-<body>
-
-<div class="header">
- <h1>TinyMCE License (LGPL)</h1>
-</div>
-
-<div class="content">
-<p>
-Visit the <a href="faq.html">FAQ</a> for general answers surrounding TinyMCE. Or visit <a href="http://www.fsf.org" target="_blank">http://www.fsf.org</a> for more information about Open-Source licenses.
-</p>
-<pre>
- GNU LIBRARY GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL. It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it. You can use it for
-your libraries, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
- Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library. If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-.
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software. To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
- Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs. This
-license, the GNU Library General Public License, applies to certain
-designated libraries. This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
- The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it. Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program. However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
- Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries. We
-concluded that weaker conditions might promote sharing better.
-
- However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves. This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them. (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.) The hope is that this
-will lead to faster development of free libraries.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, while the latter only
-works together with the library.
-
- Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-.
- GNU LIBRARY GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License"). Each licensee is
-addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-.
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-.
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-.
- 6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- c) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- d) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-.
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-.
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-.
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-</pre>
-</div>
-
-<div class="footer">
- <div class="helpindexlink"><a href="index.html">Index</a></div>
- <div class="copyright">Copyright © 2005 Moxiecode Systems AB</div>
- <br style="clear: both" />
-</div>
-
-</body>
-</html>
diff --git a/wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin.js b/wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin.js index 8f844a7..537fa33 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 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 268 2007-04-28 15:52:59Z spocke $
*
* Moxiecode DHTML Windows script.
*
@@ -82,22 +82,28 @@ TinyMCE_Engine.prototype.openWindow = function(template, args) { // Center div in editor area
pos.absLeft += Math.round((elm.firstChild.clientWidth / 2) - (width / 2));
pos.absTop += Math.round((elm.firstChild.clientHeight / 2) - (height / 2));
-
- url += tinyMCE.settings['imp_version'] ? (url.indexOf('?')==-1?'?':'&') + 'ver=' + tinyMCE.settings['imp_version'] : ''; // WordPress cache buster
+
+ // WordPress cache buster
+ url += tinyMCE.settings['imp_version'] ? (url.indexOf('?')==-1?'?':'&') + 'ver=' + tinyMCE.settings['imp_version'] : '';
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.closeWindow = function(win) {
var gotit = false, n, w;
+
for (n in mcWindows.windows) {
w = mcWindows.windows[n];
- if (typeof(w) == 'function') continue;
+
+ if (typeof(w) == 'function')
+ continue;
+
if (win.name == w.id + '_iframe') {
w.close();
gotit = true;
}
}
+
if (!gotit)
this.orgCloseWindow(win);
@@ -392,7 +398,10 @@ TinyMCE_Windows.prototype.open = function(url, name, features) { html += '<html>';
html += '<head>';
html += '<title>Wrapper iframe</title>';
+
+ // WordPress: put the window buttons on the left as in Macs
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" />';
html += '</head>';
diff --git a/wp-includes/js/tinymce/plugins/spellchecker/editor_plugin.js b/wp-includes/js/tinymce/plugins/spellchecker/editor_plugin.js index 7760175..18b1101 100755 --- a/wp-includes/js/tinymce/plugins/spellchecker/editor_plugin.js +++ b/wp-includes/js/tinymce/plugins/spellchecker/editor_plugin.js @@ -1 +1,631 @@ -tinyMCE.importPluginLanguagePack('spellchecker','en,fr,sv,nn,nb');var TinyMCE_SpellCheckerPlugin={_contextMenu:new TinyMCE_Menu(),_menu:new TinyMCE_Menu(),_counter:0,_ajaxPage:'/tinyspell.php',getInfo:function(){return{longname:'Spellchecker PHP',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://tinymce.moxiecode.com/tinymce/docs/plugin_spellchecker.html',version:"1.0.3"};},handleEvent:function(e){var elm=tinyMCE.isMSIE?e.srcElement:e.target;var inst=tinyMCE.selectedInstance,args='';var self=TinyMCE_SpellCheckerPlugin;var cm=self._contextMenu;var p,p2,x,y,sx,sy,h,elm;if((e.type=="click"||e.type=="contextmenu")&&elm){do{if(tinyMCE.getAttrib(elm,'class')=="mceItemHiddenSpellWord"){inst.spellCheckerElm=elm;args+='id='+inst.editorId+"|"+(++self._counter);args+='&cmd=suggest&check='+encodeURIComponent(elm.innerHTML);args+='&lang='+escape(inst.spellCheckerLang);elm=inst.spellCheckerElm;p=tinyMCE.getAbsPosition(inst.iframeElement);p2=tinyMCE.getAbsPosition(elm);h=parseInt(elm.offsetHeight);sx=inst.getBody().scrollLeft;sy=inst.getBody().scrollTop;x=p.absLeft+p2.absLeft-sx;y=p.absTop+p2.absTop-sy+h;cm.clear();cm.addTitle(tinyMCE.getLang('lang_spellchecker_wait','',true));cm.show();cm.moveTo(x,y);inst.selection.selectNode(elm,false,false);self._sendAjax(self.baseURL+self._ajaxPage,self._ajaxResponse,'post',args);tinyMCE.cancelEvent(e);return false;}}while((elm=elm.parentNode));}return true;},initInstance:function(inst){var self=TinyMCE_SpellCheckerPlugin,m=self._menu,cm=self._contextMenu,e;tinyMCE.importCSS(inst.getDoc(),tinyMCE.baseURL+"/plugins/spellchecker/css/content.css");if(!tinyMCE.hasMenu('spellcheckercontextmenu')){tinyMCE.importCSS(document,tinyMCE.baseURL+"/plugins/spellchecker/css/spellchecker.css");cm.init({drop_menu:false});tinyMCE.addMenu('spellcheckercontextmenu',cm);}if(!tinyMCE.hasMenu('spellcheckermenu')){m.init({});tinyMCE.addMenu('spellcheckermenu',m);}inst.spellCheckerLang='en';self._buildSettingsMenu(inst,null);e=self._getBlockBoxLayer(inst).create('div','mceBlockBox',document.getElementById(inst.editorId+'_parent'));self._getMsgBoxLayer(inst).create('div','mceMsgBox',document.getElementById(inst.editorId+'_parent'));},_getMsgBoxLayer:function(inst){if(!inst.spellCheckerMsgBoxL)inst.spellCheckerMsgBoxL=new TinyMCE_Layer(inst.editorId+'_spellcheckerMsgBox',false);return inst.spellCheckerMsgBoxL;},_getBlockBoxLayer:function(inst){if(!inst.spellCheckerBoxL)inst.spellCheckerBoxL=new TinyMCE_Layer(inst.editorId+'_spellcheckerBlockBox',false);return inst.spellCheckerBoxL;},_buildSettingsMenu:function(inst,lang){var i,ar=tinyMCE.getParam('spellchecker_languages','+English=en').split(','),p;var self=TinyMCE_SpellCheckerPlugin,m=self._menu,c;m.clear();m.addTitle(tinyMCE.getLang('lang_spellchecker_langs','',true));for(i=0;i<ar.length;i++){if(ar[i]!=''){p=ar[i].split('=');c='mceMenuCheckItem';if(p[0].charAt(0)=='+'){p[0]=p[0].substring(1);if(lang==null){c='mceMenuSelectedItem';inst.spellCheckerLang=p[1];}}if(lang==p[1])c='mceMenuSelectedItem';m.add({text:p[0],js:"tinyMCE.execInstanceCommand('"+inst.editorId+"','mceSpellCheckerSetLang',false,'"+p[1]+"');",class_name:c});}}},setupContent:function(editor_id,body,doc){TinyMCE_SpellCheckerPlugin._removeWords(doc,null,true);},getControlHTML:function(cn){switch(cn){case"spellchecker":return TinyMCE_SpellCheckerPlugin._getMenuButtonHTML(cn,'lang_spellchecker_desc','{$pluginurl}/images/spellchecker.gif','lang_spellchecker_desc','mceSpellCheckerMenu','mceSpellCheck');}return"";},_getMenuButtonHTML:function(id,lang,img,mlang,mid,cmd,ui,val){var h='',m,x;cmd='tinyMCE.hideMenus();tinyMCE.execInstanceCommand(\'{$editor_id}\',\''+cmd+'\'';if(typeof(ui)!="undefined"&&ui!=null)cmd+=','+ui;if(typeof(val)!="undefined"&&val!=null)cmd+=",'"+val+"'";cmd+=');';if(tinyMCE.getParam('button_tile_map')&&(!tinyMCE.isMSIE||tinyMCE.isOpera)&&(m=tinyMCE.buttonMap[id])!=null&&(tinyMCE.getParam("language")=="en"||img.indexOf('$lang')==-1)){x=0-(m*20)==0?'0':0-(m*20);h+='<a id="{$editor_id}_'+id+'" href="javascript:'+cmd+'" onclick="'+cmd+'return false;" onmousedown="return false;" class="mceTiledButton mceButtonNormal" target="_self">';h+='<img src="{$themeurl}/images/spacer.gif" style="background-position: '+x+'px 0" title="{$'+lang+'}" />';h+='<img src="{$themeurl}/images/button_menu.gif" title="{$'+lang+'}" class="mceMenuButton" onclick="'+mcmd+'return false;" />';h+='</a>';}else{if(tinyMCE.isMSIE&&!tinyMCE.isOpera)h+='<span id="{$editor_id}_'+id+'" class="mceMenuButton" onmouseover="tinyMCE.plugins.spellchecker._menuButtonEvent(\'over\',this);" onmouseout="tinyMCE.plugins.spellchecker._menuButtonEvent(\'out\',this);">';else h+='<span id="{$editor_id}_'+id+'" 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>';h+='<a href="#" onclick="tinyMCE.plugins.spellchecker._toggleMenu(\'{$editor_id}\',\''+mid+'\');return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$'+lang+'}" class="mceMenuButton" />';h+='</a></span>';}return h;},_menuButtonEvent:function(e,o){var t=this;window.setTimeout(function(){t._menuButtonEvent2(e,o);},1);},_menuButtonEvent2:function(e,o){if(o.className=='mceMenuButtonFocus')return;if(e=='over')o.className=o.className+' mceMenuHover';else o.className=o.className.replace(/\s.*$/,'');},_toggleMenu:function(editor_id,id){var self=TinyMCE_SpellCheckerPlugin;var e=document.getElementById(editor_id+'_spellchecker');var inst=tinyMCE.getInstanceById(editor_id);if(self._menu.isVisible()){tinyMCE.hideMenus();return;}tinyMCE.lastMenuBtnClass=e.className.replace(/\s.*$/,'');tinyMCE.switchClass(editor_id+'_spellchecker','mceMenuButtonFocus');self._menu.moveRelativeTo(e,'bl');self._menu.moveBy(tinyMCE.isMSIE&&!tinyMCE.isOpera?0:1,-1);if(tinyMCE.isOpera)self._menu.moveBy(0,-2);self._onMenuEvent(inst,self._menu,'show');self._menu.show();tinyMCE.lastSelectedMenuBtn=editor_id+'_spellchecker';},_onMenuEvent:function(inst,m,n){TinyMCE_SpellCheckerPlugin._buildSettingsMenu(inst,inst.spellCheckerLang);},execCommand:function(editor_id,element,command,user_interface,value){var inst=tinyMCE.getInstanceById(editor_id),self=TinyMCE_SpellCheckerPlugin,args='',co,bb,mb,nl,i,e,mbs;switch(command){case"mceSpellCheck":if(!inst.spellcheckerOn){inst.spellCheckerBookmark=inst.selection.getBookmark();if(tinyMCE.isRealIE)tinyMCE.setInnerHTML(inst.getBody(),inst.getBody().innerHTML);args+='id='+inst.editorId+"|"+(++self._counter);args+='&cmd=spell&check='+encodeURIComponent(self._getWordList(inst.getBody())).replace(/\'/g,'%27');args+='&lang='+escape(inst.spellCheckerLang);co=document.getElementById(inst.editorId+'_parent').firstChild;bb=self._getBlockBoxLayer(inst);bb.moveRelativeTo(co,'tl');bb.resizeTo(co.offsetWidth,co.offsetHeight);bb.show();mb=self._getMsgBoxLayer(inst);e=mb.getElement();if(e.childNodes[0])e.removeChild(e.childNodes[0]);mbs=document.createElement("span");mbs.innerHTML='<span>'+tinyMCE.getLang('lang_spellchecker_swait','',true)+'</span>';e.appendChild(mbs);mb.show();mb.moveRelativeTo(co,'cc');if(tinyMCE.isMSIE&&!tinyMCE.isOpera){nl=co.getElementsByTagName('select');for(i=0;i<nl.length;i++)nl[i].disabled=true;}inst.spellcheckerOn=true;tinyMCE.switchClass(editor_id+'_spellchecker','mceMenuButtonSelected');self._sendAjax(self.baseURL+self._ajaxPage,self._ajaxResponse,'post',args);}else{self._removeWords(inst.getDoc());inst.spellcheckerOn=false;tinyMCE.switchClass(editor_id+'_spellchecker','mceMenuButton');}return true;case"mceSpellCheckReplace":if(inst.spellCheckerElm)tinyMCE.setOuterHTML(inst.spellCheckerElm,value);self._checkDone(inst);self._contextMenu.hide();self._menu.hide();return true;case"mceSpellCheckIgnore":if(inst.spellCheckerElm)self._removeWord(inst.spellCheckerElm);self._checkDone(inst);self._contextMenu.hide();self._menu.hide();return true;case"mceSpellCheckIgnoreAll":if(inst.spellCheckerElm)self._removeWords(inst.getDoc(),inst.spellCheckerElm.innerHTML);self._checkDone(inst);self._contextMenu.hide();self._menu.hide();return true;case"mceSpellCheckerSetLang":tinyMCE.hideMenus();inst.spellCheckerLang=value;self._removeWords(inst.getDoc());inst.spellcheckerOn=false;tinyMCE.switchClass(editor_id+'_spellchecker','mceMenuButton');return true;}return false;},cleanup:function(type,content,inst){switch(type){case"get_from_editor_dom":TinyMCE_SpellCheckerPlugin._removeWords(content,null,true);inst.spellcheckerOn=false;break;}return content;},_displayUI:function(inst){var self=TinyMCE_SpellCheckerPlugin;var bb=self._getBlockBoxLayer(inst);var mb=self._getMsgBoxLayer(inst);var nl,i;var co=document.getElementById(inst.editorId+'_parent').firstChild;if(tinyMCE.isMSIE&&!tinyMCE.isOpera){nl=co.getElementsByTagName('select');for(i=0;i<nl.length;i++)nl[i].disabled=false;}bb.hide();mb.hide();},_ajaxResponse:function(xml){var el=xml?xml.documentElement:null;var inst=tinyMCE.selectedInstance,self=TinyMCE_SpellCheckerPlugin;var cmd=el?el.getAttribute("cmd"):null,err,id=el?el.getAttribute("id"):null;if(id)inst=tinyMCE.getInstanceById(id.substring(0,id.indexOf('|')));self._displayUI(inst);if(cmd=="suggest"&&id!=inst.editorId+"|"+self._counter)return;if(!el){inst.spellcheckerOn=false;tinyMCE.switchClass(inst.editorId+'_spellchecker','mceMenuButton');alert("Could not execute AJAX call, server didn't return valid a XML.");return;}err=el.getAttribute("error");if(err=="true"){inst.spellcheckerOn=false;tinyMCE.switchClass(inst.editorId+'_spellchecker','mceMenuButton');alert(el.getAttribute("msg"));return;}switch(cmd){case"spell":if(xml.documentElement.firstChild){self._markWords(inst.getDoc(),inst.getBody(),decodeURIComponent(el.firstChild.nodeValue).split('+'));inst.selection.moveToBookmark(inst.spellCheckerBookmark);if(tinyMCE.getParam('spellchecker_report_misspellings',false))alert(tinyMCE.getLang('lang_spellchecker_mpell_found','',true,{words:self._countWords(inst)}));}else alert(tinyMCE.getLang('lang_spellchecker_no_mpell','',true));self._checkDone(inst);inst.useCSS=false;break;case"suggest":self._buildMenu(el.firstChild?decodeURIComponent(el.firstChild.nodeValue).split('+'):null,10);self._contextMenu.show();break;}},_getWordSeparators:function(){var i,re='',ch=tinyMCE.getParam('spellchecker_word_separator_chars','\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}\u201d\u201c');for(i=0;i<ch.length;i++)re+='\\'+ch.charAt(i);return re;},_getWordList:function(n){var i,x,s,nv='',nl=tinyMCE.getNodeTree(n,new Array(),3),wl=new Array();var re=TinyMCE_SpellCheckerPlugin._getWordSeparators();for(i=0;i<nl.length;i++){if(!new RegExp('/SCRIPT|STYLE/').test(nl[i].parentNode.nodeName))nv+=nl[i].nodeValue+" ";}nv=nv.replace(new RegExp('([0-9]|['+re+'])','g'),' ');nv=tinyMCE.trim(nv.replace(/(\s+)/g,' '));nl=nv.split(/\s+/);for(i=0;i<nl.length;i++){s=false;for(x=0;x<wl.length;x++){if(wl[x]==nl[i]){s=true;break;}}if(!s&&nl[i].length>0)wl[wl.length]=nl[i];}return wl.join(' ');},_removeWords:function(doc,word,cleanup){var i,c,nl=doc.getElementsByTagName("span");var self=TinyMCE_SpellCheckerPlugin;var inst=tinyMCE.selectedInstance,b=inst?inst.selection.getBookmark():null;word=typeof(word)=='undefined'?null:word;for(i=nl.length-1;i>=0;i--){c=tinyMCE.getAttrib(nl[i],'class');if((c=='mceItemHiddenSpellWord'||c=='mceItemHidden')&&(word==null||nl[i].innerHTML==word))self._removeWord(nl[i]);}if(b&&!cleanup)inst.selection.moveToBookmark(b);},_checkDone:function(inst){var self=TinyMCE_SpellCheckerPlugin;var w=self._countWords(inst);if(w==0){self._removeWords(inst.getDoc());inst.spellcheckerOn=false;tinyMCE.switchClass(inst.editorId+'_spellchecker','mceMenuButton');}},_countWords:function(inst){var i,w=0,nl=inst.getDoc().getElementsByTagName("span"),c;var self=TinyMCE_SpellCheckerPlugin;for(i=nl.length-1;i>=0;i--){c=tinyMCE.getAttrib(nl[i],'class');if(c=='mceItemHiddenSpellWord')w++;}return w;},_removeWord:function(e){if(e!=null)tinyMCE.setOuterHTML(e,e.innerHTML);},_markWords:function(doc,n,wl){var i,nv,nn,nl=tinyMCE.getNodeTree(n,new Array(),3);var r1,r2,r3,r4,r5,w='';var re=TinyMCE_SpellCheckerPlugin._getWordSeparators();for(i=0;i<wl.length;i++){if(wl[i].length>0)w+=wl[i]+((i==wl.length-1)?'':'|');}for(i=0;i<nl.length;i++){nv=nl[i].nodeValue;r1=new RegExp('(['+re+'])('+w+')(['+re+'])','g');r2=new RegExp('^('+w+')','g');r3=new RegExp('('+w+')(['+re+']?)$','g');r4=new RegExp('^('+w+')(['+re+']?)$','g');r5=new RegExp('('+w+')(['+re+'])','g');if(r1.test(nv)||r2.test(nv)||r3.test(nv)||r4.test(nv)){nv=tinyMCE.xmlEncode(nv);nv=nv.replace(r5,'<span class="mceItemHiddenSpellWord">$1</span>$2');nv=nv.replace(r3,'<span class="mceItemHiddenSpellWord">$1</span>$2');nn=doc.createElement('span');nn.className="mceItemHidden";nn.innerHTML=nv;nl[i].parentNode.replaceChild(nn,nl[i]);}}},_buildMenu:function(sg,max){var i,self=TinyMCE_SpellCheckerPlugin,cm=self._contextMenu;cm.clear();if(sg!=null){cm.addTitle(tinyMCE.getLang('lang_spellchecker_sug','',true));for(i=0;i<sg.length&&i<max;i++)cm.addItem(sg[i],'tinyMCE.execCommand("mceSpellCheckReplace",false,"'+sg[i]+'");');cm.addSeparator();}else cm.addTitle(tinyMCE.getLang('lang_spellchecker_no_sug','',true));cm.addItem(tinyMCE.getLang('lang_spellchecker_ignore_word','',true),'tinyMCE.execCommand(\'mceSpellCheckIgnore\');');cm.addItem(tinyMCE.getLang('lang_spellchecker_ignore_words','',true),'tinyMCE.execCommand(\'mceSpellCheckIgnoreAll\');');cm.update();},_getAjaxHTTP:function(){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){return new XMLHttpRequest();}}},_sendAjax:function(u,f,m,a){var x=TinyMCE_SpellCheckerPlugin._getAjaxHTTP();x.open(m,u,true);x.onreadystatechange=function(){if(x.readyState==4)f(x.responseXML);};if(m=='post')x.setRequestHeader('Content-type','application/x-www-form-urlencoded');x.send(a);}};tinyMCE.addPlugin('spellchecker',TinyMCE_SpellCheckerPlugin);
+/** + * $Id: editor_plugin_src.js 289 2007-05-28 09:12:16Z spocke $ + * + * @author Moxiecode + * @copyright Copyright © 2004-2006, Moxiecode Systems AB, All rights reserved. + */ + +tinyMCE.importPluginLanguagePack('spellchecker', 'en,fr,sv,nn,nb'); + +// Plucin static class +var TinyMCE_SpellCheckerPlugin = { + _contextMenu : new TinyMCE_Menu(), + _menu : new TinyMCE_Menu(), + _counter : 0, + _ajaxPage : '/tinyspell.php', + + getInfo : function() { + return { + longname : 'Spellchecker PHP', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker', + version : "1.0.5" + }; + }, + + handleEvent : function(e) { + var elm = tinyMCE.isMSIE ? e.srcElement : e.target; + var inst = tinyMCE.selectedInstance, args = ''; + var self = TinyMCE_SpellCheckerPlugin; + var cm = self._contextMenu; + var p, p2, x, y, sx, sy, h, elm; + + // Handle click on word + if ((e.type == "click" || e.type == "contextmenu") && elm) { + do { + if (tinyMCE.getAttrib(elm, 'class') == "mceItemHiddenSpellWord") { + inst.spellCheckerElm = elm; + + // Setup arguments + args += 'id=' + inst.editorId + "|" + (++self._counter); + args += '&cmd=suggest&check=' + encodeURIComponent(elm.innerHTML); + args += '&lang=' + escape(inst.spellCheckerLang); + + elm = inst.spellCheckerElm; + p = tinyMCE.getAbsPosition(inst.iframeElement); + p2 = tinyMCE.getAbsPosition(elm); + h = parseInt(elm.offsetHeight); + sx = inst.getBody().scrollLeft; + sy = inst.getBody().scrollTop; + x = p.absLeft + p2.absLeft - sx; + y = p.absTop + p2.absTop - sy + h; + + cm.clear(); + cm.addTitle(tinyMCE.getLang('lang_spellchecker_wait', '', true)); + cm.show(); + cm.moveTo(x, y); + + inst.selection.selectNode(elm, false, false); + + self._sendAjax(self.baseURL + self._ajaxPage, self._ajaxResponse, 'post', args); + + tinyMCE.cancelEvent(e); + return false; + } + } while ((elm = elm.parentNode)); + } + + return true; + }, + + initInstance : function(inst) { + var self = TinyMCE_SpellCheckerPlugin, m = self._menu, cm = self._contextMenu, e; + + tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/plugins/spellchecker/css/content.css"); + + if (!tinyMCE.hasMenu('spellcheckercontextmenu')) { + tinyMCE.importCSS(document, tinyMCE.baseURL + "/plugins/spellchecker/css/spellchecker.css"); + + cm.init({drop_menu : false}); + tinyMCE.addMenu('spellcheckercontextmenu', cm); + } + + if (!tinyMCE.hasMenu('spellcheckermenu')) { + m.init({}); + tinyMCE.addMenu('spellcheckermenu', m); + } + + inst.spellCheckerLang = 'en'; + self._buildSettingsMenu(inst, null); + + e = self._getBlockBoxLayer(inst).create('div', 'mceBlockBox', document.getElementById(inst.editorId + '_parent')); + self._getMsgBoxLayer(inst).create('div', 'mceMsgBox', document.getElementById(inst.editorId + '_parent')); + }, + + _getMsgBoxLayer : function(inst) { + if (!inst.spellCheckerMsgBoxL) + inst.spellCheckerMsgBoxL = new TinyMCE_Layer(inst.editorId + '_spellcheckerMsgBox', false); + + return inst.spellCheckerMsgBoxL; + }, + + _getBlockBoxLayer : function(inst) { + if (!inst.spellCheckerBoxL) + inst.spellCheckerBoxL = new TinyMCE_Layer(inst.editorId + '_spellcheckerBlockBox', false); + + return inst.spellCheckerBoxL; + }, + + _buildSettingsMenu : function(inst, lang) { + var i, ar = tinyMCE.getParam('spellchecker_languages', '+English=en').split(','), p; + var self = TinyMCE_SpellCheckerPlugin, m = self._menu, c; + + m.clear(); + m.addTitle(tinyMCE.getLang('lang_spellchecker_langs', '', true)); + + for (i=0; i<ar.length; i++) { + if (ar[i] != '') { + p = ar[i].split('='); + c = 'mceMenuCheckItem'; + + if (p[0].charAt(0) == '+') { + p[0] = p[0].substring(1); + + if (lang == null) { + c = 'mceMenuSelectedItem'; + inst.spellCheckerLang = p[1]; + } + } + + if (lang == p[1]) + c = 'mceMenuSelectedItem'; + + m.add({text : p[0], js : "tinyMCE.execInstanceCommand('" + inst.editorId + "','mceSpellCheckerSetLang',false,'" + p[1] + "');", class_name : c}); + } + } + }, + + setupContent : function(editor_id, body, doc) { + TinyMCE_SpellCheckerPlugin._removeWords(doc, null, true); + }, + + getControlHTML : function(cn) { + switch (cn) { + case "spellchecker": + return TinyMCE_SpellCheckerPlugin._getMenuButtonHTML(cn, 'lang_spellchecker_desc', '{$pluginurl}/images/spellchecker.gif', 'lang_spellchecker_desc', 'mceSpellCheckerMenu', 'mceSpellCheck'); + } + + return ""; + }, + + /** + * Returns the HTML code for a normal button control. + * + * @param {string} id Button control id, this will be the suffix for the element id, the prefix is the editor id. + * @param {string} lang Language variable key name to insert as the title/alt of the button image. + * @param {string} img Image URL to insert, {$themeurl} and {$pluginurl} will be replaced. + * @param {string} mlang Language variable key name to insert as the title/alt of the menu button image. + * @param {string} mid Menu by id to display when the menu button is pressed. + * @param {string} cmd Command to execute when the user clicks the button. + * @param {string} ui Optional user interface boolean for command. + * @param {string} val Optional value for command. + * @return HTML code for a normal button based in input information. + * @type string + */ + _getMenuButtonHTML : function(id, lang, img, mlang, mid, cmd, ui, val) { + var h = '', m, x; + + cmd = 'tinyMCE.hideMenus();tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\''; + + if (typeof(ui) != "undefined" && ui != null) + cmd += ',' + ui; + + if (typeof(val) != "undefined" && val != null) + cmd += ",'" + val + "'"; + + cmd += ');'; + + // Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled + if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isMSIE || tinyMCE.isOpera) && (m = tinyMCE.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) { + // Tiled button + x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20); + h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceTiledButton mceButtonNormal" target="_self">'; + h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" title="{$' + lang + '}" />'; + h += '<img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" onclick="' + mcmd + 'return false;" />'; + h += '</a>'; + } else { + if (tinyMCE.isMSIE && !tinyMCE.isOpera) + h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton" onmouseover="tinyMCE.plugins.spellchecker._menuButtonEvent(\'over\',this);" onmouseout="tinyMCE.plugins.spellchecker._menuButtonEvent(\'out\',this);">'; + else + h += '<span id="{$editor_id}_' + id + '" 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>'; + h += '<a href="#" onclick="tinyMCE.plugins.spellchecker._toggleMenu(\'{$editor_id}\',\'' + mid + '\');return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />'; + h += '</a></span>'; + } + + return h; + }, + + _menuButtonEvent : function(e, o) { + var t = this; + + // Give IE some time since it's buggy!! :( + window.setTimeout(function() { + t._menuButtonEvent2(e, o); + }, 1); + }, + + _menuButtonEvent2 : function(e, o) { + if (o.className == 'mceMenuButtonFocus') + return; + + if (e == 'over') + o.className = o.className + ' mceMenuHover'; + else + o.className = o.className.replace(/\s.*$/, ''); + }, + + _toggleMenu : function(editor_id, id) { + var self = TinyMCE_SpellCheckerPlugin; + var e = document.getElementById(editor_id + '_spellchecker'); + var inst = tinyMCE.getInstanceById(editor_id); + + if (self._menu.isVisible()) { + tinyMCE.hideMenus(); + return; + } + + tinyMCE.lastMenuBtnClass = e.className.replace(/\s.*$/, ''); + tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButtonFocus'); + + self._menu.moveRelativeTo(e, 'bl'); + self._menu.moveBy(tinyMCE.isMSIE && !tinyMCE.isOpera ? 0 : 1, -1); + + if (tinyMCE.isOpera) + self._menu.moveBy(0, -2); + + self._onMenuEvent(inst, self._menu, 'show'); + + self._menu.show(); + + tinyMCE.lastSelectedMenuBtn = editor_id + '_spellchecker'; + }, + + _onMenuEvent : function(inst, m, n) { + TinyMCE_SpellCheckerPlugin._buildSettingsMenu(inst, inst.spellCheckerLang); + }, + + execCommand : function(editor_id, element, command, user_interface, value) { + var inst = tinyMCE.getInstanceById(editor_id), self = TinyMCE_SpellCheckerPlugin, args = '', co, bb, mb, nl, i, e, mbs; + + // Handle commands + switch (command) { + case "mceSpellCheck": + if (!inst.spellcheckerOn) { + inst.spellCheckerBookmark = inst.selection.getBookmark(); + + // Fix for IE bug: #1610184 + if (tinyMCE.isRealIE) + tinyMCE.setInnerHTML(inst.getBody(), inst.getBody().innerHTML); + + // Setup arguments + args += 'id=' + inst.editorId + "|" + (++self._counter); + args += '&cmd=spell&check=' + encodeURIComponent(self._getWordList(inst.getBody())).replace(/\'/g, '%27'); + args += '&lang=' + escape(inst.spellCheckerLang); + + co = document.getElementById(inst.editorId + '_parent').firstChild; + bb = self._getBlockBoxLayer(inst); + bb.moveRelativeTo(co, 'tl'); + bb.resizeTo(co.offsetWidth, co.offsetHeight); + bb.show(); + + // Setup message box + mb = self._getMsgBoxLayer(inst); + e = mb.getElement(); + + if (e.childNodes[0]) + e.removeChild(e.childNodes[0]); + + mbs = document.createElement("span"); + mbs.innerHTML = '<span>' + tinyMCE.getLang('lang_spellchecker_swait', '', true) + '</span>'; + e.appendChild(mbs); + + mb.show(); + mb.moveRelativeTo(co, 'cc'); + + if (tinyMCE.isMSIE && !tinyMCE.isOpera) { + nl = co.getElementsByTagName('select'); + for (i=0; i<nl.length; i++) + nl[i].disabled = true; + } + + inst.spellcheckerOn = true; + tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButtonSelected'); + + self._sendAjax(self.baseURL + self._ajaxPage, self._ajaxResponse, 'post', args); + } else { + self._removeWords(inst.getDoc()); + inst.spellcheckerOn = false; + tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButton'); + } + + return true; + + case "mceSpellCheckReplace": + if (inst.spellCheckerElm) + tinyMCE.setOuterHTML(inst.spellCheckerElm, value); + + self._checkDone(inst); + self._contextMenu.hide(); + self._menu.hide(); + + return true; + + case "mceSpellCheckIgnore": + if (inst.spellCheckerElm) + self._removeWord(inst.spellCheckerElm); + + self._checkDone(inst); + self._contextMenu.hide(); + self._menu.hide(); + return true; + + case "mceSpellCheckIgnoreAll": + if (inst.spellCheckerElm) + self._removeWords(inst.getDoc(), inst.spellCheckerElm.innerHTML); + + self._checkDone(inst); + self._contextMenu.hide(); + self._menu.hide(); + return true; + + case "mceSpellCheckerSetLang": + tinyMCE.hideMenus(); + inst.spellCheckerLang = value; + self._removeWords(inst.getDoc()); + inst.spellcheckerOn = false; + tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButton'); + return true; + } + + // Pass to next handler in chain + return false; + }, + + cleanup : function(type, content, inst) { + switch (type) { + case "get_from_editor_dom": + TinyMCE_SpellCheckerPlugin._removeWords(content, null, true); + inst.spellcheckerOn = false; + break; + } + + return content; + }, + + // Private plugin specific methods + + _displayUI : function(inst) { + var self = TinyMCE_SpellCheckerPlugin; + var bb = self._getBlockBoxLayer(inst); + var mb = self._getMsgBoxLayer(inst); + var nl, i; + var co = document.getElementById(inst.editorId + '_parent').firstChild; + + if (tinyMCE.isMSIE && !tinyMCE.isOpera) { + nl = co.getElementsByTagName('select'); + for (i=0; i<nl.length; i++) + nl[i].disabled = false; + } + + bb.hide(); + + // Boom, crash in FF if focus isn't else were + // el.style.display='none' on a opacity element seems to crash it + mb.hide(); + }, + + _ajaxResponse : function(xml, text) { + var el = xml ? xml.documentElement : null; + var inst = tinyMCE.selectedInstance, self = TinyMCE_SpellCheckerPlugin; + var cmd = el ? el.getAttribute("cmd") : null, err, id = el ? el.getAttribute("id") : null; + + if (id) + inst = tinyMCE.getInstanceById(id.substring(0, id.indexOf('|'))); + + // Workaround for crash in Gecko + if (tinyMCE.isGecko) + window.focus(); + + self._displayUI(inst); + + // Restore the selection again + if (tinyMCE.isGecko) { + inst.getWin().focus(); + inst.selection.moveToBookmark(inst.spellCheckerBookmark); + } + + // Ignore suggestions for other ajax responses + if (cmd == "suggest" && id != inst.editorId + "|" + self._counter) + return; + + if (!el) { + text = '' + text; + + if (text.length > 500) + text = text.substring(500); + + inst.spellcheckerOn = false; + tinyMCE.switchClass(inst.editorId + '_spellchecker', 'mceMenuButton'); + alert("Could not execute AJAX call, server didn't return valid a XML.\nResponse: " + text); + return; + } + + err = el.getAttribute("error"); + + if (err == "true") { + inst.spellcheckerOn = false; + tinyMCE.switchClass(inst.editorId + '_spellchecker', 'mceMenuButton'); + alert(el.getAttribute("msg")); + return; + } + + switch (cmd) { + case "spell": + if (xml.documentElement.firstChild) { + self._markWords(inst.getDoc(), inst.getBody(), decodeURIComponent(el.firstChild.nodeValue).split('+')); + inst.selection.moveToBookmark(inst.spellCheckerBookmark); + + if(tinyMCE.getParam('spellchecker_report_misspellings', false)) + alert(tinyMCE.getLang('lang_spellchecker_mpell_found', '', true, {words : self._countWords(inst)})); + } else + alert(tinyMCE.getLang('lang_spellchecker_no_mpell', '', true)); + + self._checkDone(inst); + + // Odd stuff FF removed useCSS, disable state for it + inst.useCSS = false; + + break; + + case "suggest": + self._buildMenu(el.firstChild ? decodeURIComponent(el.firstChild.nodeValue).split('+') : null, 10); + self._contextMenu.show(); + break; + } + }, + + _getWordSeparators : function() { + var i, re = '', ch = tinyMCE.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c'); + + for (i=0; i<ch.length; i++) + re += '\\' + ch.charAt(i); + + return re; + }, + + _getWordList : function(n) { + var i, x, s, nv = '', nl = tinyMCE.getNodeTree(n, [], 3), wl = []; + var re = TinyMCE_SpellCheckerPlugin._getWordSeparators(); + + for (i=0; i<nl.length; i++) { + if (!new RegExp('/SCRIPT|STYLE/').test(nl[i].parentNode.nodeName)) + nv += nl[i].nodeValue + " "; + } + + nv = nv.replace(new RegExp('([0-9]|[' + re + '])', 'g'), ' '); + nv = tinyMCE.trim(nv.replace(/(\s+)/g, ' ')); + + nl = nv.split(/\s+/); + for (i=0; i<nl.length; i++) { + s = false; + for (x=0; x<wl.length; x++) { + if (wl[x] == nl[i]) { + s = true; + break; + } + } + + if (!s && nl[i].length > 0) + wl[wl.length] = nl[i]; + } + + return wl.join(' '); + }, + + _removeWords : function(doc, word, cleanup) { + var i, c, nl = doc.getElementsByTagName("span"); + var self = TinyMCE_SpellCheckerPlugin; + var inst = tinyMCE.selectedInstance, b = inst ? inst.selection.getBookmark() : null; + + word = typeof(word) == 'undefined' ? null : word; + + for (i=nl.length-1; i>=0; i--) { + c = tinyMCE.getAttrib(nl[i], 'class'); + + if ((c == 'mceItemHiddenSpellWord' || c == 'mceItemHidden') && (word == null || nl[i].innerHTML == word)) + self._removeWord(nl[i]); + } + + if (b && !cleanup) + inst.selection.moveToBookmark(b); + }, + + _checkDone : function(inst) { + var self = TinyMCE_SpellCheckerPlugin; + var w = self._countWords(inst); + + if (w == 0) { + self._removeWords(inst.getDoc()); + inst.spellcheckerOn = false; + tinyMCE.switchClass(inst.editorId + '_spellchecker', 'mceMenuButton'); + } + }, + + _countWords : function(inst) { + var i, w = 0, nl = inst.getDoc().getElementsByTagName("span"), c; + var self = TinyMCE_SpellCheckerPlugin; + + for (i=nl.length-1; i>=0; i--) { + c = tinyMCE.getAttrib(nl[i], 'class'); + + if (c == 'mceItemHiddenSpellWord') + w++; + } + + return w; + }, + + _removeWord : function(e) { + if (e != null) + tinyMCE.setOuterHTML(e, e.innerHTML); + }, + + _markWords : function(doc, n, wl) { + var i, nv, nn, nl = tinyMCE.getNodeTree(n, new Array(), 3); + var r1, r2, r3, r4, r5, w = ''; + var re = TinyMCE_SpellCheckerPlugin._getWordSeparators(); + + for (i=0; i<wl.length; i++) { + if (wl[i].length > 0) + w += wl[i] + ((i == wl.length-1) ? '' : '|'); + } + + for (i=0; i<nl.length; i++) { + nv = nl[i].nodeValue; + + r1 = new RegExp('([' + re + '])(' + w + ')([' + re + '])', 'g'); + r2 = new RegExp('^(' + w + ')', 'g'); + r3 = new RegExp('(' + w + ')([' + re + ']?)$', 'g'); + r4 = new RegExp('^(' + w + ')([' + re + ']?)$', 'g'); + r5 = new RegExp('(' + w + ')([' + re + '])', 'g'); + + if (r1.test(nv) || r2.test(nv) || r3.test(nv) || r4.test(nv)) { + nv = tinyMCE.xmlEncode(nv).replace(''', "'"); + nv = nv.replace(r5, '<span class="mceItemHiddenSpellWord">$1</span>$2'); + nv = nv.replace(r3, '<span class="mceItemHiddenSpellWord">$1</span>$2'); + + nn = doc.createElement('span'); + nn.className = "mceItemHidden"; + nn.innerHTML = nv; + + // Remove old text node + nl[i].parentNode.replaceChild(nn, nl[i]); + } + } + }, + + _buildMenu : function(sg, max) { + var i, self = TinyMCE_SpellCheckerPlugin, cm = self._contextMenu; + + cm.clear(); + + if (sg != null) { + cm.addTitle(tinyMCE.getLang('lang_spellchecker_sug', '', true)); + + for (i=0; i<sg.length && i<max; i++) + cm.addItem(sg[i], 'tinyMCE.execCommand("mceSpellCheckReplace",false,"' + sg[i] + '");'); + + cm.addSeparator(); + } else + cm.addTitle(tinyMCE.getLang('lang_spellchecker_no_sug', '', true)); + + cm.addItem(tinyMCE.getLang('lang_spellchecker_ignore_word', '', true), 'tinyMCE.execCommand(\'mceSpellCheckIgnore\');'); + cm.addItem(tinyMCE.getLang('lang_spellchecker_ignore_words', '', true), 'tinyMCE.execCommand(\'mceSpellCheckIgnoreAll\');'); + + cm.update(); + }, + + _getAjaxHTTP : function() { + try { + return new ActiveXObject('Msxml2.XMLHTTP') + } catch (e) { + try { + return new ActiveXObject('Microsoft.XMLHTTP') + } catch (e) { + return new XMLHttpRequest(); + } + } + }, + + /** + * Perform AJAX call. + * + * @param {string} u URL of AJAX service. + * @param {function} f Function to call when response arrives. + * @param {string} m Request method post or get. + * @param {Array} a Array with arguments to send. + */ + _sendAjax : function(u, f, m, a) { + var x = TinyMCE_SpellCheckerPlugin._getAjaxHTTP(); + + x.open(m, u, true); + + x.onreadystatechange = function() { + if (x.readyState == 4) + f(x.responseXML, x.responseText); + }; + + if (m == 'post') + x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + + x.send(a); + } +}; + +// Register plugin +tinyMCE.addPlugin('spellchecker', TinyMCE_SpellCheckerPlugin); + diff --git a/wp-includes/js/tinymce/plugins/spellchecker/tinyspell.php b/wp-includes/js/tinymce/plugins/spellchecker/tinyspell.php index 18345e6..6b977c6 100755 --- a/wp-includes/js/tinymce/plugins/spellchecker/tinyspell.php +++ b/wp-includes/js/tinymce/plugins/spellchecker/tinyspell.php @@ -33,14 +33,14 @@ // Get input parameters.
- $check = urldecode($_REQUEST['check']);
- $cmd = sanitize($_REQUEST['cmd']);
- $lang = sanitize($_REQUEST['lang'], "strict");
- $mode = sanitize($_REQUEST['mode'], "strict");
- $spelling = sanitize($_REQUEST['spelling'], "strict");
- $jargon = sanitize($_REQUEST['jargon'], "strict");
- $encoding = sanitize($_REQUEST['encoding'], "strict");
- $sg = sanitize($_REQUEST['sg'], "bool");
+ $check = urldecode(getRequestParam('check'));
+ $cmd = sanitize(getRequestParam('cmd'));
+ $lang = sanitize(getRequestParam('lang'), "strict");
+ $mode = sanitize(getRequestParam('mode'), "strict");
+ $spelling = sanitize(getRequestParam('spelling'), "strict");
+ $jargon = sanitize(getRequestParam('jargon'), "strict");
+ $encoding = sanitize(getRequestParam('encoding'), "strict");
+ $sg = sanitize(getRequestParam('sg'), "bool");
$words = array();
$validRequest = true;
@@ -83,6 +83,28 @@ return $str;
}
+ function getRequestParam($name, $default_value = false) {
+ if (!isset($_REQUEST[$name]))
+ return $default_value;
+
+ if (!isset($_GLOBALS['magic_quotes_gpc']))
+ $_GLOBALS['magic_quotes_gpc'] = ini_get("magic_quotes_gpc");
+
+ if (isset($_GLOBALS['magic_quotes_gpc'])) {
+ if (is_array($_REQUEST[$name])) {
+ $newarray = array();
+
+ foreach($_REQUEST[$name] as $name => $value)
+ $newarray[stripslashes($name)] = stripslashes($value);
+
+ return $newarray;
+ }
+ return stripslashes($_REQUEST[$name]);
+ }
+
+ return $_REQUEST[$name];
+ }
+
$result = array();
$tinyspell = new $spellCheckerConfig['class']($spellCheckerConfig, $lang, $mode, $spelling, $jargon, $encoding);
@@ -93,7 +115,7 @@ $words = preg_split("/ |\n/", $check, -1, PREG_SPLIT_NO_EMPTY);
$result = $tinyspell->checkWords($words);
break;
-
+
case "suggest":
$result = $tinyspell->getSuggestion($check);
break;
@@ -116,7 +138,7 @@ header('Content-type: text/xml; charset=utf-8');
$body = '<?xml version="1.0" encoding="utf-8" ?>';
$body .= "\n";
-
+
if (count($result) == 0)
$body .= '<res id="' . $id . '" cmd="'. $cmd .'" />';
else
diff --git a/wp-includes/js/tinymce/plugins/wordpress/langs/en.js b/wp-includes/js/tinymce/plugins/wordpress/langs/en.js index 04eba01..b431fb6 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';
}
@@ -11,7 +15,7 @@ else { tinyMCE.addToLang('',{
wordpress_more_button : 'Split post with More tag (' + metaKey + '+t)',
wordpress_page_button : 'Split post with Page tag',
-wordpress_adv_button : 'Show/Hide Advanced Toolbar (' + metaKey + '+b)',
+wordpress_adv_button : 'Show/Hide Advanced Toolbar (' + metaKey + '+v)',
wordpress_more_alt : 'More...',
wordpress_page_alt : '...page...',
help_button_title : 'Help (' + metaKey + '+h)',
@@ -31,4 +35,3 @@ numlist_desc : 'Ordered list (' + metaKey + '+o)', outdent_desc : 'Outdent (' + metaKey + '+w)',
indent_desc : 'Indent list/blockquote (' + metaKey + '+q)'
});
-
diff --git a/wp-includes/js/tinymce/themes/advanced/editor_template.js b/wp-includes/js/tinymce/themes/advanced/editor_template.js index b8e3685..be0e234 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 218 2007-02-13 11:08:01Z spocke $ + * $Id: editor_template_src.js 256 2007-04-24 09:03:20Z spocke $ * * @author Moxiecode * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved. @@ -140,10 +140,10 @@ var TinyMCE_AdvancedTheme = { case "|": case "separator": - return '<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" />'; + return '<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" alt="" />'; case "spacer": - return '<img src="{$themeurl}/images/separator.gif" width="2" height="15" border="0" class="mceSeparatorLine" style="vertical-align: middle" />'; + return '<img src="{$themeurl}/images/separator.gif" width="2" height="15" border="0" class="mceSeparatorLine" style="vertical-align: middle" alt="" />'; case "rowseparator": return '<br />'; @@ -1242,7 +1242,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"; @@ -1251,8 +1251,8 @@ 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.) +/* 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; @@ -1274,7 +1274,7 @@ var TinyMCE_AdvancedTheme = { inst.iframeElement.style.width = (iw + dx) + "px"; } } - + tableElm.style.height = h + "px"; // WordPress: see above // Remove pesky table controls @@ -1404,7 +1404,7 @@ var TinyMCE_AdvancedTheme = { h += '</tr></table>'; 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>'; + h += '<a href="javascript:void(0);" onclick="TinyMCE_AdvancedTheme._pickColor(\'' + id + '\',\'' + cm + '\');" class="mceMoreColors">' + tinyMCE.getLang('lang_more_colors') + '</a>'; return h; }, @@ -1424,78 +1424,20 @@ var TinyMCE_AdvancedTheme = { }, _insertImage : function(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout) { - tinyMCE.execCommand('mceBeginUndoLevel'); - - if (src == "") - return; - - if (!tinyMCE.imgElement && tinyMCE.isSafari) { - var html = ""; - - html += '<img src="' + src + '" alt="' + alt + '"'; - html += ' border="' + border + '" hspace="' + hspace + '"'; - html += ' vspace="' + vspace + '" width="' + width + '"'; - html += ' height="' + height + '" align="' + align + '" title="' + title + '" onmouseover="' + onmouseover + '" onmouseout="' + onmouseout + '" />'; - - tinyMCE.execCommand("mceInsertContent", false, html); - } else { - if (!tinyMCE.imgElement && tinyMCE.selectedInstance) { - if (tinyMCE.isSafari) - tinyMCE.execCommand("mceInsertContent", false, '<img src="' + tinyMCE.uniqueURL + '" />'); - else - tinyMCE.selectedInstance.contentDocument.execCommand("insertimage", false, tinyMCE.uniqueURL); - - tinyMCE.imgElement = tinyMCE.getElementByAttributeValue(tinyMCE.selectedInstance.contentDocument.body, "img", "src", tinyMCE.uniqueURL); - } - } - - if (tinyMCE.imgElement) { - var needsRepaint = false; - var msrc = src; - - src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, tinyMCE.imgElement);"); - - if (tinyMCE.getParam('convert_urls')) - msrc = src; - - if (onmouseover && onmouseover != "") - onmouseover = "this.src='" + eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseover, tinyMCE.imgElement);") + "';"; - - if (onmouseout && onmouseout != "") - onmouseout = "this.src='" + eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseout, tinyMCE.imgElement);") + "';"; - - // Use alt as title if it's undefined - if (typeof(title) == "undefined") - title = alt; - - if (width != tinyMCE.imgElement.getAttribute("width") || height != tinyMCE.imgElement.getAttribute("height") || align != tinyMCE.imgElement.getAttribute("align")) - needsRepaint = true; - - tinyMCE.setAttrib(tinyMCE.imgElement, 'src', src); - tinyMCE.setAttrib(tinyMCE.imgElement, 'mce_src', msrc); - tinyMCE.setAttrib(tinyMCE.imgElement, 'alt', alt); - tinyMCE.setAttrib(tinyMCE.imgElement, 'title', title); - tinyMCE.setAttrib(tinyMCE.imgElement, 'align', align); - tinyMCE.setAttrib(tinyMCE.imgElement, 'border', border, true); - tinyMCE.setAttrib(tinyMCE.imgElement, 'hspace', hspace, true); - tinyMCE.setAttrib(tinyMCE.imgElement, 'vspace', vspace, true); - tinyMCE.setAttrib(tinyMCE.imgElement, 'width', width, true); - tinyMCE.setAttrib(tinyMCE.imgElement, 'height', height, true); - tinyMCE.setAttrib(tinyMCE.imgElement, 'onmouseover', onmouseover); - tinyMCE.setAttrib(tinyMCE.imgElement, 'onmouseout', onmouseout); - - // Fix for bug #989846 - Image resize bug - if (width && width != "") - tinyMCE.imgElement.style.pixelWidth = width; - - if (height && height != "") - tinyMCE.imgElement.style.pixelHeight = height; - - if (needsRepaint) - tinyMCE.selectedInstance.repaint(); - } - - tinyMCE.execCommand('mceEndUndoLevel'); + tinyMCE.execCommand("mceInsertContent", false, tinyMCE.createTagHTML('img', { + src : tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src), // Force absolute + mce_src : src, + alt : alt, + border : border, + hspace : hspace, + vspace : vspace, + width : width, + height : height, + align : align, + title : title, + onmouseover : onmouseover, + onmouseout : onmouseout + })); }, _insertLink : function(href, target, title, onclick, style_class) { diff --git a/wp-includes/js/tinymce/themes/advanced/image.htm b/wp-includes/js/tinymce/themes/advanced/image.htm index 4826a8d..bcebfb1 100644 --- a/wp-includes/js/tinymce/themes/advanced/image.htm +++ b/wp-includes/js/tinymce/themes/advanced/image.htm @@ -7,6 +7,7 @@ <script language="javascript" type="text/javascript" src="jscripts/image.js"></script> <base target="_self" /> </head> +<!-- WordPress: extra onload stuff is WP --> <body id="image" onload="tinyMCEPopup.executeOnLoad('init();');document.body.style.display='';document.getElementById('src').focus();" style="display: none"> <form onsubmit="insertImage();return false;" action="#"> <div class="tabs"> @@ -22,7 +23,7 @@ <td nowrap="nowrap"><label for="src">{$lang_insert_image_src}</label></td> <td><table border="0" cellspacing="0" cellpadding="0"> <tr> - <td><input id="src" name="src" type="text" value="" style="width: 200px" onchange="getImageData();"></td> + <td><input id="src" name="src" type="text" value="" style="width: 200px" onchange="getImageData();" /></td> <td id="srcbrowsercontainer"> </td> </tr> </table></td> @@ -47,7 +48,7 @@ <!-- /Image list --> <tr> <td nowrap="nowrap"><label for="alt">{$lang_insert_image_alt}</label></td> - <td><input id="alt" name="alt" type="text" value="" style="width: 200px"></td> + <td><input id="alt" name="alt" type="text" value="" style="width: 200px" /></td> </tr> <tr> <td nowrap="nowrap"><label for="align">{$lang_insert_image_align}</label></td> @@ -66,27 +67,28 @@ </tr> <tr> <td nowrap="nowrap"><label for="width">{$lang_insert_image_dimensions}</label></td> - <td><input id="width" name="width" type="text" value="" size="4" maxlength="4"> + <td><input id="width" name="width" type="text" value="" size="3" maxlength="5" /> x - <input id="height" name="height" type="text" value="" size="4" maxlength="4"></td> + <input id="height" name="height" type="text" value="" size="3" maxlength="5" /></td> </tr> <tr> <td nowrap="nowrap"><label for="border">{$lang_insert_image_border}</label></td> - <td><input id="border" name="border" type="text" value="" size="4" maxlength="4"></td> + <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" /></td> </tr> <tr> <td nowrap="nowrap"><label for="vspace">{$lang_insert_image_vspace}</label></td> - <td><input id="vspace" name="vspace" type="text" value="" size="4" maxlength="4"></td> + <td><input id="vspace" name="vspace" type="text" value="" size="3" maxlength="3" /></td> </tr> <tr> <td nowrap="nowrap"><label for="hspace">{$lang_insert_image_hspace}</label></td> - <td><input id="hspace" name="hspace" type="text" value="" size="4" maxlength="4"></td> + <td><input id="hspace" name="hspace" type="text" value="" size="3" maxlength="3" /></td> </tr> </table> </div> </div> <div class="mceActionPanel"> + <!-- WordPress: buttons reversed! --> <div style="float: left"> <input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" /> </div> 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 78425e4..9236fd0 100644 --- a/wp-includes/js/tinymce/themes/advanced/jscripts/color_picker.js +++ b/wp-includes/js/tinymce/themes/advanced/jscripts/color_picker.js @@ -153,7 +153,7 @@ function generateWebColors() { for (i=0; i<colors.length; i++) { h += '<td bgcolor="' + colors[i] + '">' - + '<a href="javascript:selectColor();" onfocus="showColor(\'' + colors[i] + '\');" onmouseover="showColor(\'' + colors[i] + '\');">' + + '<a href="javascript:insertAction();" 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) h += '</tr><tr>'; @@ -173,22 +173,13 @@ function generateNamedColors() { for (n in named) { v = named[n]; - h += '<a href="javascript:selectColor();" onmouseover="showColor(\'' + n + '\',\'' + v + '\');" style="background-color: ' + n + '"><!-- IE --></a>' + h += '<a href="javascript:insertAction();" 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); } @@ -246,4 +237,4 @@ function changeFinalColor(color) { document.getElementById('color').value = color; } -window.focus();
\ No newline at end of file +window.focus(); diff --git a/wp-includes/js/tinymce/themes/advanced/jscripts/link.js b/wp-includes/js/tinymce/themes/advanced/jscripts/link.js index 9adac22..36df14e 100644 --- a/wp-includes/js/tinymce/themes/advanced/jscripts/link.js +++ b/wp-includes/js/tinymce/themes/advanced/jscripts/link.js @@ -24,10 +24,12 @@ function init() { if (option.value == tinyMCE.getWindowArg('target')) option.selected = true; } - + + // WordPress -- next 3 lines 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); @@ -52,6 +54,14 @@ function init() { } } +function checkPrefix(n) { + if (Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCE.getLang('lang_is_email'))) + n.value = 'mailto:' + n.value; + + if (/^\s*www./i.test(n.value) && confirm(tinyMCE.getLang('lang_is_external'))) + n.value = 'http://' + n.value; +} + function insertLink() { var href = document.forms[0].href.value; var target = document.forms[0].target.options[document.forms[0].target.selectedIndex].value; @@ -61,7 +71,7 @@ function insertLink() { // WordPress: Make anchors absolute; if (href.charAt(0) == '#') - href = tinyMCE.settings['document_base_url'] + href; + href = tinyMCE.settings.document_base_url + href; if (target == '_self') target = ''; diff --git a/wp-includes/js/tinymce/themes/advanced/langs/en.js b/wp-includes/js/tinymce/themes/advanced/langs/en.js index c658d6d..8409e58 100644 --- a/wp-includes/js/tinymce/themes/advanced/langs/en.js +++ b/wp-includes/js/tinymce/themes/advanced/langs/en.js @@ -82,10 +82,12 @@ 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',
+web_colors_tab : 'Palette',
+web_colors : 'Palette colors',
named_colors_tab : 'Named',
named_colors : 'Named colors',
color : 'Color:',
-color_name : 'Name:'
+color_name : 'Name:',
+is_email : 'The URL you entered seems to be an email address, do you want to add the required mailto: prefix?',
+is_external : 'The URL you entered seems to external link, do you want to add the required http:// prefix?'
});
diff --git a/wp-includes/js/tinymce/themes/advanced/link.htm b/wp-includes/js/tinymce/themes/advanced/link.htm index 98d2f17..54220b7 100644 --- a/wp-includes/js/tinymce/themes/advanced/link.htm +++ b/wp-includes/js/tinymce/themes/advanced/link.htm @@ -4,9 +4,11 @@ <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="../../utils/form_utils.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/validate.js"></script> <script language="javascript" type="text/javascript" src="jscripts/link.js"></script> <base target="_self" /> </head> +<!-- WordPress: onload after the init();'); --> <body id="link" onload="tinyMCEPopup.executeOnLoad('init();');document.body.style.display='';document.getElementById('href').focus();" style="display: none"> <form onsubmit="insertLink();return false;" action="#"> <div class="tabs"> @@ -23,7 +25,7 @@ <td nowrap="nowrap"><label for="href">{$lang_insert_link_url}</label></td> <td><table border="0" cellspacing="0" cellpadding="0"> <tr> - <td><input id="href" name="href" type="text" value="" style="width: 200px" /></td> + <td><input id="href" name="href" type="text" value="" style="width: 200px" onchange="checkPrefix(this);" /></td> <td id="hrefbrowsercontainer"> </td> </tr> </table></td> @@ -87,6 +89,7 @@ </div> <div class="mceActionPanel"> + <!-- WordPress: Buttons are reversed! --> <div style="float: left"> <input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" /> </div> diff --git a/wp-includes/js/tinymce/themes/advanced/source_editor.htm b/wp-includes/js/tinymce/themes/advanced/source_editor.htm index a3b82c9..bb3a79b 100644 --- a/wp-includes/js/tinymce/themes/advanced/source_editor.htm +++ b/wp-includes/js/tinymce/themes/advanced/source_editor.htm @@ -6,6 +6,7 @@ <script language="javascript" type="text/javascript" src="jscripts/source_editor.js"></script> <base target="_self" /> </head> +<!-- WordPress: extra onload stuff is WP! --> <body onload="tinyMCEPopup.executeOnLoad('onLoadInit();');document.body.style.display='';document.getElementById('htmlSource').focus();" onresize="resizeInputs();" style="display: none"> <form name="source" onsubmit="saveContent();" action="#"> <div style="float: left" class="title">{$lang_theme_code_title}</div> @@ -16,9 +17,10 @@ <br style="clear: both" /> - <textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,mono; font-size: 12px" dir="ltr" wrap="off"></textarea> + <textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,monospace; font-size: 12px" dir="ltr" wrap="off"></textarea> <div class="mceActionPanel"> + <!-- WordPress: reversed buttons! --> <div style="float: left"> <input type="button" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" id="cancel" /> </div> diff --git a/wp-includes/js/tinymce/tiny_mce.js b/wp-includes/js/tinymce/tiny_mce.js index e425a1e..0e83794 100644 --- a/wp-includes/js/tinymce/tiny_mce.js +++ b/wp-includes/js/tinymce/tiny_mce.js @@ -5,22 +5,23 @@ function TinyMCE_Engine() { var ua; this.majorVersion = "2"; - this.minorVersion = "1.0"; - this.releaseDate = "2007-02-13"; - - this.instances = new Array(); - this.switchClassCache = new Array(); - this.windowArgs = new Array(); - this.loadedFiles = new Array(); - this.pendingFiles = new Array(); + this.minorVersion = "1.1.1"; + this.releaseDate = "2007-05-14"; + + this.instances = []; + this.switchClassCache = []; + this.windowArgs = []; + this.loadedFiles = []; + this.pendingFiles = []; this.loadingIndex = 0; - this.configs = new Array(); + this.configs = []; this.currentConfig = 0; - this.eventHandlers = new Array(); - this.log = new Array(); + this.eventHandlers = []; + this.log = []; this.undoLevels = []; this.undoIndex = 0; this.typingUndoIndex = -1; + this.settings = []; // Browser check ua = navigator.userAgent; @@ -28,18 +29,18 @@ function TinyMCE_Engine() { this.isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1); this.isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1); this.isMSIE7 = this.isMSIE && (ua.indexOf('MSIE 7') != -1); - this.isGecko = ua.indexOf('Gecko') != -1; + this.isGecko = ua.indexOf('Gecko') != -1; // Will also be true on Safari this.isSafari = ua.indexOf('Safari') != -1; - this.isOpera = ua.indexOf('Opera') != -1; + this.isOpera = window['opera'] && opera.buildNumber ? true : false; this.isMac = ua.indexOf('Mac') != -1; this.isNS7 = ua.indexOf('Netscape/7') != -1; this.isNS71 = ua.indexOf('Netscape/7.1') != -1; this.dialogCounter = 0; - this.plugins = new Array(); - this.themes = new Array(); - this.menus = new Array(); - this.loadedPlugins = new Array(); - this.buttonMap = new Array(); + this.plugins = []; + this.themes = []; + this.menus = []; + this.loadedPlugins = []; + this.buttonMap = []; this.isLoaded = false; // Fake MSIE on Opera and if Opera fakes IE, Gecko or Safari cancel those @@ -58,7 +59,7 @@ function TinyMCE_Engine() { TinyMCE_Engine.prototype = { init : function(settings) { - var theme, nl, baseHREF = "", i; + var theme, nl, baseHREF = "", i, cssPath, entities, h, p, src, elements = [], head; // IE 5.0x is no longer supported since 5.5, 6.0 and 7.0 now exists. We can't support old browsers forever, sorry. if (this.isMSIE5_0) @@ -72,7 +73,17 @@ TinyMCE_Engine.prototype = { // Get script base path if (!tinyMCE.baseURL) { - var elements = document.getElementsByTagName('script'); + // Search through head + head = document.getElementsByTagName('head')[0]; + + if (head) { + for (i=0, nl = head.getElementsByTagName('script'); i<nl.length; i++) + elements.push(nl[i]); + } + + // Search through rest of document + for (i=0, nl = document.getElementsByTagName('script'); i<nl.length; i++) + elements.push(nl[i]); // If base element found, add that infront of baseURL nl = document.getElementsByTagName('base'); @@ -81,9 +92,9 @@ TinyMCE_Engine.prototype = { baseHREF = nl[i].href; } - for (var i=0; i<elements.length; i++) { + for (i=0; i<elements.length; i++) { if (elements[i].src && (elements[i].src.indexOf("tiny_mce.js") != -1 || elements[i].src.indexOf("tiny_mce_dev.js") != -1 || elements[i].src.indexOf("tiny_mce_src.js") != -1 || elements[i].src.indexOf("tiny_mce_gzip") != -1)) { - var src = elements[i].src; + src = elements[i].src; tinyMCE.srcMode = (src.indexOf('_src') != -1 || src.indexOf('_dev') != -1) ? '_src' : ''; tinyMCE.gzipMode = src.indexOf('_gzip') != -1; @@ -93,7 +104,7 @@ TinyMCE_Engine.prototype = { tinyMCE.srcMode = settings.exec_mode == "src" ? '_src' : ''; // Force it absolute if page has a base href - if (baseHREF != "" && src.indexOf('://') == -1) + if (baseHREF !== '' && src.indexOf('://') == -1) tinyMCE.baseURL = baseHREF + src; else tinyMCE.baseURL = src; @@ -121,7 +132,7 @@ TinyMCE_Engine.prototype = { this._def("theme", "advanced"); this._def("plugins", "", true); this._def("language", "en"); - this._def("docs_language", this.settings['language']); + this._def("docs_language", this.settings.language); this._def("elements", ""); this._def("textarea_trigger", "mce_editable"); this._def("editor_selector", ""); @@ -132,7 +143,6 @@ TinyMCE_Engine.prototype = { this._def("encoding", ""); this._def("urlconverter_callback", tinyMCE.getParam("urlconvertor_callback", "TinyMCE_Engine.prototype.convertURL")); this._def("save_callback", ""); - this._def("debug", false); this._def("force_br_newlines", false); this._def("force_p_newlines", true); this._def("add_form_submit_trigger", true); @@ -193,31 +203,33 @@ TinyMCE_Engine.prototype = { this._def("display_tab_class", ''); this._def("gecko_spellcheck", false); this._def("hide_selects_on_submit", true); + this._def("forced_root_block", false); + this._def("remove_trailing_nbsp", false); // Force strict loading mode to false on non Gecko browsers if (this.isMSIE && !this.isOpera) this.settings.strict_loading_mode = false; // Browser check IE - if (this.isMSIE && this.settings['browsers'].indexOf('msie') == -1) + if (this.isMSIE && this.settings.browsers.indexOf('msie') == -1) return; // Browser check Gecko - if (this.isGecko && this.settings['browsers'].indexOf('gecko') == -1) + if (this.isGecko && this.settings.browsers.indexOf('gecko') == -1) return; // Browser check Safari - if (this.isSafari && this.settings['browsers'].indexOf('safari') == -1) + if (this.isSafari && this.settings.browsers.indexOf('safari') == -1) return; // Browser check Opera - if (this.isOpera && this.settings['browsers'].indexOf('opera') == -1) + if (this.isOpera && this.settings.browsers.indexOf('opera') == -1) return; // If not super absolute make it so - baseHREF = tinyMCE.settings['document_base_url']; - var h = document.location.href; - var p = h.indexOf('://'); + baseHREF = tinyMCE.settings.document_base_url; + h = document.location.href; + p = h.indexOf('://'); if (p > 0 && document.location.protocol != "file:") { p = h.indexOf('/', p + 3); h = h.substring(0, p); @@ -225,66 +237,54 @@ TinyMCE_Engine.prototype = { if (baseHREF.indexOf('://') == -1) baseHREF = h + baseHREF; - tinyMCE.settings['document_base_url'] = baseHREF; - tinyMCE.settings['document_base_prefix'] = h; + tinyMCE.settings.document_base_url = baseHREF; + tinyMCE.settings.document_base_prefix = h; } // Trim away query part if (baseHREF.indexOf('?') != -1) baseHREF = baseHREF.substring(0, baseHREF.indexOf('?')); - this.settings['base_href'] = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/"; + this.settings.base_href = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/"; - theme = this.settings['theme']; + theme = this.settings.theme; this.inlineStrict = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment'; this.inlineTransitional = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment'; - 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.blockElms = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|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.posKeyCodes = [13,45,36,35,33,34,37,38,39,40]; 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'); + this.callbacks = ['onInit', 'getInfo', 'getEditorTemplate', 'setupContent', 'onChange', 'onPageLoad', 'handleNodeChange', 'initInstance', 'execCommand', 'getControlHTML', 'handleEvent', 'cleanup', 'removeInstance']; // Theme url - this.settings['theme_href'] = tinyMCE.baseURL + "/themes/" + theme; + this.settings.theme_href = tinyMCE.baseURL + "/themes/" + theme; if (!tinyMCE.isIE || tinyMCE.isOpera) - this.settings['force_br_newlines'] = false; + this.settings.force_br_newlines = false; if (tinyMCE.getParam("popups_css", false)) { - var cssPath = tinyMCE.getParam("popups_css", ""); + cssPath = tinyMCE.getParam("popups_css", ""); // Is relative if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/') - this.settings['popups_css'] = this.documentBasePath + "/" + cssPath; + this.settings.popups_css = this.documentBasePath + "/" + cssPath; else - this.settings['popups_css'] = cssPath; + this.settings.popups_css = cssPath; } else - this.settings['popups_css'] = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_popup.css"; + this.settings.popups_css = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_popup.css"; if (tinyMCE.getParam("editor_css", false)) { - var cssPath = tinyMCE.getParam("editor_css", ""); + cssPath = tinyMCE.getParam("editor_css", ""); // Is relative if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/') - this.settings['editor_css'] = this.documentBasePath + "/" + cssPath; + this.settings.editor_css = this.documentBasePath + "/" + cssPath; else - this.settings['editor_css'] = cssPath; + this.settings.editor_css = cssPath; } else { - if (this.settings.editor_css != '') - this.settings['editor_css'] = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_ui.css"; - } - - if (tinyMCE.settings['debug']) { - var msg = "Debug: \n"; - - msg += "baseURL: " + this.baseURL + "\n"; - msg += "documentBasePath: " + this.documentBasePath + "\n"; - msg += "content_css: " + this.settings['content_css'] + "\n"; - msg += "popups_css: " + this.settings['popups_css'] + "\n"; - msg += "editor_css: " + this.settings['editor_css'] + "\n"; - - alert(msg); + if (this.settings.editor_css !== '') + this.settings.editor_css = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_ui.css"; } // Only do this once @@ -304,14 +304,14 @@ TinyMCE_Engine.prototype = { } } - this.loadScript(tinyMCE.baseURL + '/themes/' + this.settings['theme'] + '/editor_template' + tinyMCE.srcMode + '.js'); - this.loadScript(tinyMCE.baseURL + '/langs/' + this.settings['language'] + '.js'); - this.loadCSS(this.settings['editor_css']); + this.loadScript(tinyMCE.baseURL + '/themes/' + this.settings.theme + '/editor_template' + tinyMCE.srcMode + '.js'); + this.loadScript(tinyMCE.baseURL + '/langs/' + this.settings.language + '.js'); + this.loadCSS(this.settings.editor_css); // Add plugins - var p = tinyMCE.getParam('plugins', '', true, ','); + p = tinyMCE.getParam('plugins', '', true, ','); if (p.length > 0) { - for (var i=0; i<p.length; i++) { + for (i=0; i<p.length; i++) { if (p[i].charAt(0) != '-') this.loadScript(tinyMCE.baseURL + '/plugins/' + p[i] + '/editor_plugin' + tinyMCE.srcMode + '.js'); } @@ -319,14 +319,14 @@ TinyMCE_Engine.prototype = { // Setup entities if (tinyMCE.getParam('entity_encoding') == 'named') { - settings['cleanup_entities'] = new Array(); - var entities = tinyMCE.getParam('entities', '', true, ','); - for (var i=0; i<entities.length; i+=2) - settings['cleanup_entities']['c' + entities[i]] = entities[i+1]; + settings.cleanup_entities = []; + entities = tinyMCE.getParam('entities', '', true, ','); + for (i=0; i<entities.length; i+=2) + settings.cleanup_entities['c' + entities[i]] = entities[i+1]; } // Save away this config - settings['index'] = this.configs.length; + settings.index = this.configs.length; this.configs[this.configs.length] = settings; // Start loading first one in chain @@ -337,23 +337,24 @@ TinyMCE_Engine.prototype = { try { document.execCommand('BackgroundImageCache', false, true); } catch (e) { + // Ignore } } // Setup XML encoding regexps - this.xmlEncodeAposRe = new RegExp('[<>&"\']', 'g'); this.xmlEncodeRe = new RegExp('[<>&"]', 'g'); -// this.xmlEncodeEnts = {'&':'&','"':'"',"'":''','<':'<','>':'>'}; }, _addUnloadEvents : function() { + var st = tinyMCE.settings.add_unload_trigger; + if (tinyMCE.isIE) { - if (tinyMCE.settings['add_unload_trigger']) { + if (st) { tinyMCE.addEvent(window, "unload", TinyMCE_Engine.prototype.unloadHandler); tinyMCE.addEvent(window.document, "beforeunload", TinyMCE_Engine.prototype.unloadHandler); } } else { - if (tinyMCE.settings['add_unload_trigger']) + if (st) tinyMCE.addEvent(window, "unload", function () {tinyMCE.triggerSave(true, true);}); } }, @@ -449,8 +450,7 @@ TinyMCE_Engine.prototype = { loadCSS : function(url) { var ar = url.replace(/\s+/, '').split(','); - var lflen = 0, csslen = 0; - var skip = false; + var lflen = 0, csslen = 0, skip = false; var x = 0, i = 0, nl, le; for (x = 0,csslen = ar.length; x<csslen; x++) { @@ -514,25 +514,28 @@ TinyMCE_Engine.prototype = { tinyMCE.settings = settings; - if (tinyMCE.settings['convert_on_click'] || (!elm.getAttribute('mce_noask') && confirm(tinyMCELang['lang_edit_confirm']))) + if (tinyMCE.settings.convert_on_click || (!elm.getAttribute('mce_noask') && confirm(tinyMCELang.lang_edit_confirm))) tinyMCE.addMCEControl(elm, elementId); elm.setAttribute('mce_noask', 'true'); }, updateContent : function(form_element_name) { + var formElement, n, inst, doc; + // Find MCE instance linked to given form element and copy it's value - var formElement = document.getElementById(form_element_name); - for (var n in tinyMCE.instances) { - var inst = tinyMCE.instances[n]; + formElement = document.getElementById(form_element_name); + for (n in tinyMCE.instances) { + inst = tinyMCE.instances[n]; + if (!tinyMCE.isInstance(inst)) continue; inst.switchSettings(); if (inst.formElement == formElement) { - var doc = inst.getDoc(); - + doc = inst.getDoc(); + tinyMCE._setHTML(doc, inst.formElement.value); if (!tinyMCE.isIE) @@ -681,7 +684,7 @@ TinyMCE_Engine.prototype = { }, execCommand : function(command, user_interface, value) { - var inst = tinyMCE.selectedInstance; + var inst = tinyMCE.selectedInstance, n, pe, te; // Default input user_interface = user_interface ? user_interface : false; @@ -721,7 +724,8 @@ TinyMCE_Engine.prototype = { return true; case 'mceFocus': - var inst = tinyMCE.getInstanceById(value); + inst = tinyMCE.getInstanceById(value); + if (inst) inst.getWin().focus(); return; @@ -732,7 +736,7 @@ TinyMCE_Engine.prototype = { return; case "mceAddFrameControl": - tinyMCE.addMCEControl(tinyMCE._getElementById(value['element'], value['document']), value['element'], value['document']); + tinyMCE.addMCEControl(tinyMCE._getElementById(value.element, value.document), value.element, value.document); return; case "mceRemoveControl": @@ -741,7 +745,7 @@ TinyMCE_Engine.prototype = { return; case "mceToggleEditor": - var inst = tinyMCE.getInstanceById(value), pe, te; + inst = tinyMCE.getInstanceById(value); if (inst) { pe = document.getElementById(inst.editorId + '_parent'); @@ -754,13 +758,23 @@ TinyMCE_Engine.prototype = { if (!inst.enabled) { pe.style.display = 'none'; - te.value = inst.getHTML(); + + if (te.nodeName == 'TEXTAREA' || te.nodeName == 'INPUT') + te.value = inst.getHTML(); + else + te.innerHTML = 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); + + if (te.nodeName == 'TEXTAREA' || te.nodeName == 'INPUT') + inst.setHTML(te.value); + else + inst.setHTML(te.innerHTML); + inst.useCSS = false; tinyMCE.dispatchCallback(inst, 'show_instance_callback', 'showInstance', inst); } @@ -771,13 +785,15 @@ TinyMCE_Engine.prototype = { case "mceResetDesignMode": // Resets the designmode state of the editors in Gecko - if (!tinyMCE.isIE) { - for (var n in tinyMCE.instances) { + if (tinyMCE.isGecko) { + for (n in tinyMCE.instances) { if (!tinyMCE.isInstance(tinyMCE.instances[n])) continue; try { + tinyMCE.instances[n].getDoc().designMode = "off"; tinyMCE.instances[n].getDoc().designMode = "on"; + tinyMCE.instances[n].useCSS = false; } catch (e) { // Ignore any errors } @@ -789,8 +805,8 @@ TinyMCE_Engine.prototype = { if (inst) { inst.execCommand(command, user_interface, value); - } else if (tinyMCE.settings['focus_alert']) - alert(tinyMCELang['lang_focus_alert']); + } else if (tinyMCE.settings.focus_alert) + alert(tinyMCELang.lang_focus_alert); }, _createIFrame : function(replace_element, doc, win) { @@ -805,8 +821,8 @@ TinyMCE_Engine.prototype = { iframe = doc.createElement("iframe"); - aw = "" + tinyMCE.settings['area_width']; - ah = "" + tinyMCE.settings['area_height']; + aw = "" + tinyMCE.settings.area_width; + ah = "" + tinyMCE.settings.area_height; if (aw.indexOf('%') == -1) { aw = parseInt(aw); @@ -834,12 +850,12 @@ TinyMCE_Engine.prototype = { iframe.setAttribute("allowtransparency", "true"); iframe.className = 'mceEditorIframe'; - if (tinyMCE.settings["auto_resize"]) + if (tinyMCE.settings.auto_resize) iframe.setAttribute("scrolling", "no"); // Must have a src element in MSIE HTTPs breaks aswell as absoute URLs if (tinyMCE.isRealIE) - iframe.setAttribute("src", this.settings['default_document']); + iframe.setAttribute("src", this.settings.default_document); iframe.style.width = aw; iframe.style.height = ah; @@ -861,10 +877,8 @@ TinyMCE_Engine.prototype = { }, setupContent : function(editor_id) { - var inst = tinyMCE.instances[editor_id], i; - var doc = inst.getDoc(); - var head = doc.getElementsByTagName('head').item(0); - var content = inst.startContent; + var inst = tinyMCE.instances[editor_id], i, doc = inst.getDoc(), head = doc.getElementsByTagName('head').item(0); + var content = inst.startContent, contentElement, body; // HTML values get XML encoded in strict mode if (tinyMCE.settings.strict_loading_mode) { @@ -886,14 +900,15 @@ TinyMCE_Engine.prototype = { return; } - if (!head) { + // Wait for it to load + if (!head || !doc.body) { window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 10); return; } // Import theme specific content CSS the user specific - tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/themes/" + inst.settings['theme'] + "/css/editor_content.css"); - tinyMCE.importCSS(inst.getDoc(), inst.settings['content_css']); + tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/themes/" + inst.settings.theme + "/css/editor_content.css"); + tinyMCE.importCSS(inst.getDoc(), inst.settings.content_css); tinyMCE.dispatchCallback(inst, 'init_instance_callback', 'initInstance', inst); // Setup keyboard shortcuts @@ -921,20 +936,20 @@ TinyMCE_Engine.prototype = { if (tinyMCE.getParam("convert_fonts_to_spans")) inst.getBody().setAttribute('id', 'mceSpanFonts'); - if (tinyMCE.settings['nowrap']) + if (tinyMCE.settings.nowrap) doc.body.style.whiteSpace = "nowrap"; - doc.body.dir = this.settings['directionality']; + doc.body.dir = this.settings.directionality; doc.editorId = editor_id; // Add on document element in Mozilla if (!tinyMCE.isIE) doc.documentElement.editorId = editor_id; - inst.setBaseHREF(tinyMCE.settings['base_href']); + inst.setBaseHREF(tinyMCE.settings.base_href); // Replace new line characters to BRs - if (tinyMCE.settings['convert_newlines_to_brs']) { + if (tinyMCE.settings.convert_newlines_to_brs) { content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi"); content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi"); content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi"); @@ -951,10 +966,10 @@ TinyMCE_Engine.prototype = { // Ugly!!! window.setInterval('try{tinyMCE.getCSSClasses(tinyMCE.instances["' + editor_id + '"].getDoc(), "' + editor_id + '");}catch(e){}', 500); - if (tinyMCE.settings["force_br_newlines"]) + if (tinyMCE.settings.force_br_newlines) doc.styleSheets[0].addRule("p", "margin: 0;"); - var body = inst.getBody(); + body = inst.getBody(); body.editorId = editor_id; } @@ -962,27 +977,27 @@ TinyMCE_Engine.prototype = { // Fix for bug #958637 if (!tinyMCE.isIE) { - var contentElement = inst.getDoc().createElement("body"); - var doc = inst.getDoc(); + contentElement = inst.getDoc().createElement("body"); + doc = inst.getDoc(); contentElement.innerHTML = content; - // Remove weridness! - if (tinyMCE.isGecko && tinyMCE.settings['remove_lt_gt']) - content = content.replace(new RegExp('<>', 'g'), ""); - - if (tinyMCE.settings['cleanup_on_startup']) + if (tinyMCE.settings.cleanup_on_startup) tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, doc, this.settings, contentElement)); else tinyMCE.setInnerHTML(inst.getBody(), content); tinyMCE.convertAllRelativeURLs(inst.getBody()); } else { - if (tinyMCE.settings['cleanup_on_startup']) { + if (tinyMCE.settings.cleanup_on_startup) { tinyMCE._setHTML(inst.getDoc(), content); // Produces permission denied error in MSIE 5.5 - eval('try {tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody()));} catch(e) {}'); + try { + tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody())); + } catch(e) { + // Ignore + } } else tinyMCE._setHTML(inst.getDoc(), content); } @@ -990,7 +1005,7 @@ TinyMCE_Engine.prototype = { // Fix for bug #957681 //inst.getDoc().designMode = inst.getDoc().designMode; - tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings['visual'], inst); + tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings.visual, inst); tinyMCE.dispatchCallback(inst, 'setupcontent_callback', 'setupContent', editor_id, inst.getBody(), inst.getDoc()); // Re-add design mode on mozilla @@ -1106,7 +1121,7 @@ TinyMCE_Engine.prototype = { }, handleEvent : function(e) { - var inst = tinyMCE.selectedInstance; + var inst = tinyMCE.selectedInstance, i, elm, keys; // Remove odd, error if (typeof(tinyMCE) == "undefined") @@ -1149,19 +1164,17 @@ TinyMCE_Engine.prototype = { } } - window.setTimeout("tinyMCE.selectedInstance.setBaseHREF(tinyMCE.settings['base_href']);tinyMCE._resetIframeHeight();", 1); + window.setTimeout("tinyMCE.selectedInstance.setBaseHREF(tinyMCE.settings.base_href);tinyMCE._resetIframeHeight();", 1); return; case "submit": - tinyMCE.removeTinyMCEFormElements(tinyMCE.isMSIE ? window.event.srcElement : e.target); - tinyMCE.triggerSave(); - tinyMCE.isNotDirty = true; + tinyMCE.formSubmit(tinyMCE.isMSIE ? window.event.srcElement : e.target); return; case "reset": var formObj = tinyMCE.isIE ? window.event.srcElement : e.target; - for (var i=0; i<document.forms.length; i++) { + for (i=0; i<document.forms.length; i++) { if (document.forms[i] == formObj) window.setTimeout('tinyMCE.resetForm(' + i + ');', 10); } @@ -1183,7 +1196,7 @@ TinyMCE_Engine.prototype = { tinyMCE.selectedInstance.switchSettings(); // Insert P element - if ((tinyMCE.isGecko || tinyMCE.isOpera || tinyMCE.isSafari) && tinyMCE.settings['force_p_newlines'] && e.keyCode == 13 && !e.shiftKey) { + if ((tinyMCE.isGecko || tinyMCE.isOpera || tinyMCE.isSafari) && tinyMCE.settings.force_p_newlines && e.keyCode == 13 && !e.shiftKey) { // Insert P element instead of BR if (TinyMCE_ForceParagraphs._insertPara(tinyMCE.selectedInstance, e)) { // Cancel event @@ -1193,7 +1206,7 @@ TinyMCE_Engine.prototype = { } // Handle backspace - if ((tinyMCE.isGecko && !tinyMCE.isSafari) && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) { + if ((tinyMCE.isGecko && !tinyMCE.isSafari) && tinyMCE.settings.force_p_newlines && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) { // Insert P element instead of BR if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) { // Cancel event @@ -1203,7 +1216,7 @@ TinyMCE_Engine.prototype = { } // Return key pressed - if (tinyMCE.isIE && tinyMCE.settings['force_br_newlines'] && e.keyCode == 13) { + if (tinyMCE.isIE && tinyMCE.settings.force_br_newlines && e.keyCode == 13) { if (e.target.editorId) tinyMCE.instances[e.target.editorId].select(); @@ -1238,7 +1251,6 @@ TinyMCE_Engine.prototype = { } return false; - break; case "keyup": case "keydown": @@ -1248,16 +1260,21 @@ TinyMCE_Engine.prototype = { if (inst && inst.handleShortcut(e)) return false; + inst._fixRootBlocks(); + + if (inst.settings.remove_trailing_nbsp) + inst._fixTrailingNbsp(); + if (e.target.editorId) tinyMCE.instances[e.target.editorId].select(); if (tinyMCE.selectedInstance) tinyMCE.selectedInstance.switchSettings(); - var inst = tinyMCE.selectedInstance; + inst = tinyMCE.selectedInstance; // Handle backspace - if (tinyMCE.isGecko && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) { + if (tinyMCE.isGecko && tinyMCE.settings.force_p_newlines && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) { // Insert P element instead of BR if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) { // Cancel event @@ -1269,14 +1286,14 @@ TinyMCE_Engine.prototype = { tinyMCE.selectedElement = null; tinyMCE.selectedNode = null; - var elm = tinyMCE.selectedInstance.getFocusElement(); + elm = tinyMCE.selectedInstance.getFocusElement(); tinyMCE.linkElement = tinyMCE.getParentElement(elm, "a"); tinyMCE.imgElement = tinyMCE.getParentElement(elm, "img"); tinyMCE.selectedElement = elm; // Update visualaids on tabs if (tinyMCE.isGecko && e.type == "keyup" && e.keyCode == 9) - tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings['visual'], tinyMCE.selectedInstance); + tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings.visual, tinyMCE.selectedInstance); // Fix empty elements on return/enter, check where enter occured if (tinyMCE.isIE && e.type == "keydown" && e.keyCode == 13) @@ -1284,7 +1301,7 @@ TinyMCE_Engine.prototype = { // Fix empty elements on return/enter if (tinyMCE.isIE && e.type == "keyup" && e.keyCode == 13) { - var elm = tinyMCE.enterKeyElement; + elm = tinyMCE.enterKeyElement; if (elm) { var re = new RegExp('^HR|IMG|BR$','g'); // Skip these var dre = new RegExp('^H[1-6]$','g'); // Add double on these @@ -1299,9 +1316,9 @@ TinyMCE_Engine.prototype = { } // Check if it's a position key - var keys = tinyMCE.posKeyCodes; + keys = tinyMCE.posKeyCodes; var posKey = false; - for (var i=0; i<keys.length; i++) { + for (i=0; i<keys.length; i++) { if (keys[i] == e.keyCode) { posKey = true; break; @@ -1309,10 +1326,10 @@ TinyMCE_Engine.prototype = { } // MSIE custom key handling - if (tinyMCE.isIE && tinyMCE.settings['custom_undo_redo']) { - var keys = new Array(8,46); // Backspace,Delete + if (tinyMCE.isIE && tinyMCE.settings.custom_undo_redo) { + keys = [8, 46]; // Backspace,Delete - for (var i=0; i<keys.length; i++) { + for (i=0; i<keys.length; i++) { if (keys[i] == e.keyCode) { if (e.type == "keyup") tinyMCE.triggerNodeChange(false); @@ -1369,7 +1386,7 @@ TinyMCE_Engine.prototype = { if (!tinyMCE.isInstance(tinyMCE.instances[instanceName])) continue; - var inst = tinyMCE.instances[instanceName]; + inst = tinyMCE.instances[instanceName]; // Reset design mode if lost (on everything just in case) inst.autoResetDesignMode(); @@ -1403,7 +1420,6 @@ TinyMCE_Engine.prototype = { tinyMCE.instances[e.target.editorId].select(); return false; - break; } }, @@ -1429,12 +1445,12 @@ TinyMCE_Engine.prototype = { // Tiled button x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20); h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceTiledButton mceButtonNormal" target="_self">'; - h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" title="{$' + lang + '}" />'; + h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" alt="{$'+lang+'}" title="{$' + lang + '}" />'; h += '</a>'; } else { // Normal button h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceButtonNormal" target="_self">'; - h += '<img src="' + img + '" title="{$' + lang + '}" />'; + h += '<img src="' + img + '" alt="{$'+lang+'}" title="{$' + lang + '}" />'; h += '</a>'; } @@ -1500,15 +1516,45 @@ TinyMCE_Engine.prototype = { this.buttonMap[a[i]] = i; }, + formSubmit : function(f, p) { + var n, inst, found = false; + + if (f.form) + f = f.form; + + // Is it a form that has a TinyMCE instance + for (n in tinyMCE.instances) { + inst = tinyMCE.instances[n]; + + if (!tinyMCE.isInstance(inst)) + continue; + + if (inst.formElement) { + if (f == inst.formElement.form) { + found = true; + inst.isNotDirty = true; + } + } + } + + // Is valid + if (found) { + tinyMCE.removeTinyMCEFormElements(f); + tinyMCE.triggerSave(); + } + + // Is it patched + if (f.mceOldSubmit && p) + f.mceOldSubmit(); + }, + submitPatch : function() { - tinyMCE.removeTinyMCEFormElements(this); - tinyMCE.triggerSave(); - tinyMCE.isNotDirty = true; - this.mceOldSubmit(); + tinyMCE.formSubmit(this, true); }, onLoad : function() { - var r; + var r, i, c, mode, trigger, elements, element, settings, elementId, elm; + var selector, deselector, elementRefAr, form; // Wait for everything to be loaded first if (tinyMCE.settings.strict_loading_mode && this.loadingIndex != -1) { @@ -1527,7 +1573,7 @@ TinyMCE_Engine.prototype = { // IE produces JS error if TinyMCE is placed in a frame // It seems to have something to do with the selection not beeing // correctly initialized in IE so this hack solves the problem - if (tinyMCE.isRealIE && document.body) { + if (tinyMCE.isRealIE && document.body && window.location.href != window.top.location.href) { r = document.body.createTextRange(); r.collapse(true); r.select(); @@ -1535,24 +1581,24 @@ TinyMCE_Engine.prototype = { tinyMCE.dispatchCallback(null, 'onpageload', 'onPageLoad'); - for (var c=0; c<tinyMCE.configs.length; c++) { + for (c=0; c<tinyMCE.configs.length; c++) { tinyMCE.settings = tinyMCE.configs[c]; - var selector = tinyMCE.getParam("editor_selector"); - var deselector = tinyMCE.getParam("editor_deselector"); - var elementRefAr = new Array(); + selector = tinyMCE.getParam("editor_selector"); + deselector = tinyMCE.getParam("editor_deselector"); + elementRefAr = []; // Add submit triggers - if (document.forms && tinyMCE.settings['add_form_submit_trigger'] && !tinyMCE.submitTriggers) { - for (var i=0; i<document.forms.length; i++) { - var form = document.forms[i]; + if (document.forms && tinyMCE.settings.add_form_submit_trigger && !tinyMCE.submitTriggers) { + for (i=0; i<document.forms.length; i++) { + form = document.forms[i]; tinyMCE.addEvent(form, "submit", TinyMCE_Engine.prototype.handleEvent); tinyMCE.addEvent(form, "reset", TinyMCE_Engine.prototype.handleEvent); tinyMCE.submitTriggers = true; // Do it only once // Patch the form.submit function - if (tinyMCE.settings['submit_patch']) { + if (tinyMCE.settings.submit_patch) { try { form.mceOldSubmit = form.submit; form.submit = TinyMCE_Engine.prototype.submitPatch; @@ -1564,14 +1610,14 @@ TinyMCE_Engine.prototype = { } // Add editor instances based on mode - var mode = tinyMCE.settings['mode']; + mode = tinyMCE.settings.mode; switch (mode) { case "exact": - var elements = tinyMCE.getParam('elements', '', true, ','); + elements = tinyMCE.getParam('elements', '', true, ','); - for (var i=0; i<elements.length; i++) { - var element = tinyMCE._getElementById(elements[i]); - var trigger = element ? element.getAttribute(tinyMCE.settings['textarea_trigger']) : ""; + for (i=0; i<elements.length; i++) { + element = tinyMCE._getElementById(elements[i]); + trigger = element ? element.getAttribute(tinyMCE.settings.textarea_trigger) : ""; if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(element, "class"))) continue; @@ -1579,31 +1625,29 @@ TinyMCE_Engine.prototype = { if (trigger == "false") continue; - if ((tinyMCE.settings['ask'] || tinyMCE.settings['convert_on_click']) && element) { + if ((tinyMCE.settings.ask || tinyMCE.settings.convert_on_click) && element) { elementRefAr[elementRefAr.length] = element; continue; } if (element) tinyMCE.addMCEControl(element, elements[i]); - else if (tinyMCE.settings['debug']) - alert("Error: Could not find element by id or name: " + elements[i]); } break; case "specific_textareas": case "textareas": - var nodeList = document.getElementsByTagName("textarea"); + elements = document.getElementsByTagName("textarea"); - for (var i=0; i<nodeList.length; i++) { - var elm = nodeList.item(i); - var trigger = elm.getAttribute(tinyMCE.settings['textarea_trigger']); + for (i=0; i<elements.length; i++) { + elm = elements.item(i); + trigger = elm.getAttribute(tinyMCE.settings.textarea_trigger); - if (selector != '' && !new RegExp('\\b' + selector + '\\b').test(tinyMCE.getAttrib(elm, "class"))) + if (selector !== '' && !new RegExp('\\b' + selector + '\\b').test(tinyMCE.getAttrib(elm, "class"))) continue; - if (selector != '') - trigger = selector != "" ? "true" : ""; + if (selector !== '') + trigger = selector !== '' ? "true" : ""; if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(elm, "class"))) continue; @@ -1614,14 +1658,14 @@ TinyMCE_Engine.prototype = { break; } - for (var i=0; i<elementRefAr.length; i++) { - var element = elementRefAr[i]; - var elementId = element.name ? element.name : element.id; + for (i=0; i<elementRefAr.length; i++) { + element = elementRefAr[i]; + elementId = element.name ? element.name : element.id; - if (tinyMCE.settings['ask'] || tinyMCE.settings['convert_on_click']) { + if (tinyMCE.settings.ask || tinyMCE.settings.convert_on_click) { // Focus breaks in Mozilla if (tinyMCE.isGecko) { - var settings = tinyMCE.settings; + settings = tinyMCE.settings; tinyMCE.addEvent(element, "focus", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);}); @@ -1629,7 +1673,7 @@ TinyMCE_Engine.prototype = { tinyMCE.addEvent(element, "click", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);}); // tinyMCE.addEvent(element, "mouseover", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);}); } else { - var settings = tinyMCE.settings; + settings = tinyMCE.settings; tinyMCE.addEvent(element, "focus", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); }); tinyMCE.addEvent(element, "click", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); }); @@ -1640,9 +1684,9 @@ TinyMCE_Engine.prototype = { } // Handle auto focus - if (tinyMCE.settings['auto_focus']) { + if (tinyMCE.settings.auto_focus) { window.setTimeout(function () { - var inst = tinyMCE.getInstanceById(tinyMCE.settings['auto_focus']); + var inst = tinyMCE.getInstanceById(tinyMCE.settings.auto_focus); inst.selection.selectNode(inst.getBody(), true, true); inst.contentWindow.focus(); }, 100); @@ -1657,7 +1701,7 @@ TinyMCE_Engine.prototype = { }, getParam : function(name, default_value, strip_whitespace, split_chr) { - var value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name]; + var i, outArray, value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name]; // Fix bool values if (value == "true" || value == "false") @@ -1668,10 +1712,10 @@ TinyMCE_Engine.prototype = { if (typeof(split_chr) != "undefined" && split_chr != null) { value = value.split(split_chr); - var outArray = new Array(); + outArray = []; - for (var i=0; i<value.length; i++) { - if (value[i] && value[i] != "") + for (i=0; i<value.length; i++) { + if (value[i] && value[i] !== '') outArray[outArray.length] = value[i]; } @@ -1700,21 +1744,20 @@ TinyMCE_Engine.prototype = { e.innerHTML = s; - return e.firstChild.nodeValue; + return !e.firstChild ? s : e.firstChild.nodeValue; }, addToLang : function(prefix, ar) { - for (var key in ar) { - if (typeof(ar[key]) == 'function') + var k; + + for (k in ar) { + if (typeof(ar[k]) == 'function') continue; - tinyMCELang[(key.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix != '' ? (prefix + "_") : '') + key] = ar[key]; + tinyMCELang[(k.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix !== '' ? (prefix + "_") : '') + k] = ar[k]; } this.loadNextScript(); - - // for (var key in ar) - // tinyMCELang[(key.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix != '' ? (prefix + "_") : '') + key] = "|" + ar[key] + "|"; }, triggerNodeChange : function(focus, setup_content) { @@ -1743,7 +1786,7 @@ TinyMCE_Engine.prototype = { if (tinyMCE.selectedElement) anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (st && st.length > 0); - if (tinyMCE.settings['custom_undo_redo']) { + if (tinyMCE.settings.custom_undo_redo) { undoIndex = inst.undoRedo.undoIndex; undoLevels = inst.undoRedo.undoLevels.length; } @@ -1756,15 +1799,15 @@ TinyMCE_Engine.prototype = { }, _customCleanup : function(inst, type, content) { - var pl, po, i; + var pl, po, i, customCleanup; // Call custom cleanup - var customCleanup = tinyMCE.settings['cleanup_callback']; - if (customCleanup != "" && eval("typeof(" + customCleanup + ")") != "undefined") - content = eval(customCleanup + "(type, content, inst);"); + customCleanup = tinyMCE.settings.cleanup_callback; + if (customCleanup != '') + content = tinyMCE.resolveDots(tinyMCE.settings.cleanup_callback, window)(type, content, inst); // Trigger theme cleanup - po = tinyMCE.themes[tinyMCE.settings['theme']]; + po = tinyMCE.themes[tinyMCE.settings.theme]; if (po && po.cleanup) content = po.cleanup(type, content, inst); @@ -1789,9 +1832,9 @@ TinyMCE_Engine.prototype = { importThemeLanguagePack : function(name) { if (typeof(name) == "undefined") - name = tinyMCE.settings['theme']; + name = tinyMCE.settings.theme; - tinyMCE.loadScript(tinyMCE.baseURL + '/themes/' + name + '/langs/' + tinyMCE.settings['language'] + '.js'); + tinyMCE.loadScript(tinyMCE.baseURL + '/themes/' + name + '/langs/' + tinyMCE.settings.language + '.js'); }, importPluginLanguagePack : function(name) { @@ -1800,16 +1843,16 @@ TinyMCE_Engine.prototype = { if (this.plugins[name]) b = this.plugins[name].baseURL; - tinyMCE.loadScript(b + '/langs/' + tinyMCE.settings['language'] + '.js'); + tinyMCE.loadScript(b + '/langs/' + tinyMCE.settings.language + '.js'); }, - applyTemplate : function(h, as) { + applyTemplate : function(h, ag) { return h.replace(new RegExp('\\{\\$([a-z0-9_]+)\\}', 'gi'), function(m, s) { if (s.indexOf('lang_') == 0 && tinyMCELang[s]) return tinyMCELang[s]; - if (as && as[s]) - return as[s]; + if (ag && ag[s]) + return ag[s]; if (tinyMCE.settings[s]) return tinyMCE.settings[s]; @@ -1826,20 +1869,20 @@ TinyMCE_Engine.prototype = { }, openWindow : function(template, args) { - var html, width, height, x, y, resizable, scrollbars, url; + var html, width, height, x, y, resizable, scrollbars, url, name, win, modal, features; args = !args ? {} : args; - args['mce_template_file'] = template['file']; - args['mce_width'] = template['width']; - args['mce_height'] = template['height']; + args.mce_template_file = template.file; + args.mce_width = template.width; + args.mce_height = template.height; tinyMCE.windowArgs = args; - html = template['html']; - if (!(width = parseInt(template['width']))) + html = template.html; + if (!(width = parseInt(template.width))) width = 320; - if (!(height = parseInt(template['height']))) + if (!(height = parseInt(template.height))) height = 200; // Add to height in M$ due to SP2 WHY DON'T YOU GUYS IMPLEMENT innerWidth of windows!! @@ -1851,16 +1894,16 @@ TinyMCE_Engine.prototype = { x = parseInt(screen.width / 2.0) - (width / 2.0); y = parseInt(screen.height / 2.0) - (height / 2.0); - resizable = (args && args['resizable']) ? args['resizable'] : "no"; - scrollbars = (args && args['scrollbars']) ? args['scrollbars'] : "no"; + resizable = (args && args.resizable) ? args.resizable : "no"; + scrollbars = (args && args.scrollbars) ? args.scrollbars : "no"; - if (template['file'].charAt(0) != '/' && template['file'].indexOf('://') == -1) - url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template['file']; + if (template.file.charAt(0) != '/' && template.file.indexOf('://') == -1) + url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template.file; else - url = template['file']; + url = template.file; // Replace all args as variables in URL - for (var name in args) { + for (name in args) { if (typeof(args[name]) == 'function') continue; @@ -1868,12 +1911,12 @@ TinyMCE_Engine.prototype = { } if (html) { - html = tinyMCE.replaceVar(html, "css", this.settings['popups_css']); + html = tinyMCE.replaceVar(html, "css", this.settings.popups_css); html = tinyMCE.applyTemplate(html, args); - var win = window.open("", "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=yes,minimizable=" + resizable + ",modal=yes,width=" + width + ",height=" + height + ",resizable=" + resizable); + win = window.open("", "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=yes,minimizable=" + resizable + ",modal=yes,width=" + width + ",height=" + height + ",resizable=" + resizable); if (win == null) { - alert(tinyMCELang['lang_popup_blocked']); + alert(tinyMCELang.lang_popup_blocked); return; } @@ -1882,34 +1925,35 @@ TinyMCE_Engine.prototype = { win.resizeTo(width, height); win.focus(); } else { - if ((tinyMCE.isRealIE) && resizable != 'yes' && tinyMCE.settings["dialog_type"] == "modal") { + if ((tinyMCE.isRealIE) && resizable != 'yes' && tinyMCE.settings.dialog_type == "modal") { height += 10; - var features = "resizable:" + resizable - + ";scroll:" - + scrollbars + ";status:yes;center:yes;help:no;dialogWidth:" - + width + "px;dialogHeight:" + height + "px;"; + features = "resizable:" + resizable + ";scroll:" + scrollbars + ";status:yes;center:yes;help:no;dialogWidth:" + width + "px;dialogHeight:" + height + "px;"; window.showModalDialog(url, window, features); } else { - var modal = (resizable == "yes") ? "no" : "yes"; + modal = (resizable == "yes") ? "no" : "yes"; if (tinyMCE.isGecko && tinyMCE.isMac) modal = "no"; - if (template['close_previous'] != "no") + if (template.close_previous != "no") try {tinyMCE.lastWindow.close();} catch (ex) {} - var win = window.open(url, "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=" + modal + ",minimizable=" + resizable + ",modal=" + modal + ",width=" + width + ",height=" + height + ",resizable=" + resizable); + win = window.open(url, "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=" + modal + ",minimizable=" + resizable + ",modal=" + modal + ",width=" + width + ",height=" + height + ",resizable=" + resizable); if (win == null) { - alert(tinyMCELang['lang_popup_blocked']); + alert(tinyMCELang.lang_popup_blocked); return; } - if (template['close_previous'] != "no") + if (template.close_previous != "no") tinyMCE.lastWindow = win; - eval('try { win.resizeTo(width, height); } catch(e) { }'); + try { + win.resizeTo(width, height); + } catch(e) { + // Ignore + } // Make it bigger if statusbar is forced if (tinyMCE.isGecko) { @@ -1927,19 +1971,19 @@ TinyMCE_Engine.prototype = { }, getVisualAidClass : function(class_name, state) { - var aidClass = tinyMCE.settings['visual_table_class']; + var i, classNames, ar, className, aidClass = tinyMCE.settings.visual_table_class; if (typeof(state) == "undefined") - state = tinyMCE.settings['visual']; + state = tinyMCE.settings.visual; // Split - var classNames = new Array(); - var ar = class_name.split(' '); - for (var i=0; i<ar.length; i++) { + classNames = []; + ar = class_name.split(' '); + for (i=0; i<ar.length; i++) { if (ar[i] == aidClass) ar[i] = ""; - if (ar[i] != "") + if (ar[i] !== '') classNames[classNames.length] = ar[i]; } @@ -1947,8 +1991,8 @@ TinyMCE_Engine.prototype = { classNames[classNames.length] = aidClass; // Glue - var className = ""; - for (var i=0; i<classNames.length; i++) { + className = ""; + for (i=0; i<classNames.length; i++) { if (i > 0) className += " "; @@ -1959,30 +2003,32 @@ TinyMCE_Engine.prototype = { }, handleVisualAid : function(el, deep, state, inst, skip_dispatch) { + var i, x, y, tableElement, anchorName, oldW, oldH, bo, cn; + if (!el) return; if (!skip_dispatch) tinyMCE.dispatchCallback(inst, 'handle_visual_aid_callback', 'handleVisualAid', el, deep, state, inst); - var tableElement = null; + tableElement = null; switch (el.nodeName) { case "TABLE": - var oldW = el.style.width; - var oldH = el.style.height; - var bo = tinyMCE.getAttrib(el, "border"); + oldW = el.style.width; + oldH = el.style.height; + bo = tinyMCE.getAttrib(el, "border"); - bo = bo == "" || bo == "0" ? true : false; + bo = bo == '' || bo == "0" ? true : false; tinyMCE.setAttrib(el, "class", tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el, "class"), state && bo)); el.style.width = oldW; el.style.height = oldH; - for (var y=0; y<el.rows.length; y++) { - for (var x=0; x<el.rows[y].cells.length; x++) { - var cn = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el.rows[y].cells[x], "class"), state && bo); + for (y=0; y<el.rows.length; y++) { + for (x=0; x<el.rows[y].cells.length; x++) { + cn = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el.rows[y].cells[x], "class"), state && bo); tinyMCE.setAttrib(el.rows[y].cells[x], "class", cn); } } @@ -1990,56 +2036,23 @@ TinyMCE_Engine.prototype = { break; case "A": - var anchorName = tinyMCE.getAttrib(el, "name"); + anchorName = tinyMCE.getAttrib(el, "name"); - if (anchorName != '' && state) { + if (anchorName !== '' && state) { el.title = anchorName; tinyMCE.addCSSClass(el, 'mceItemAnchor'); - } else if (anchorName != '' && !state) + } else if (anchorName !== '' && !state) el.className = ''; break; } if (deep && el.hasChildNodes()) { - for (var i=0; i<el.childNodes.length; i++) + for (i=0; i<el.childNodes.length; i++) tinyMCE.handleVisualAid(el.childNodes[i], deep, state, inst, true); } }, - /* - applyClassesToFonts : function(doc, size) { - var f = doc.getElementsByTagName("font"); - for (var i=0; i<f.length; i++) { - var s = tinyMCE.getAttrib(f[i], "size"); - - if (s != "") - tinyMCE.setAttrib(f[i], 'class', "mceItemFont" + s); - } - - if (typeof(size) != "undefined") { - var css = ""; - - for (var x=0; x<doc.styleSheets.length; x++) { - for (var i=0; i<doc.styleSheets[x].rules.length; i++) { - if (doc.styleSheets[x].rules[i].selectorText == '#mceSpanFonts .mceItemFont' + size) { - css = doc.styleSheets[x].rules[i].style.cssText; - break; - } - } - - if (css != "") - break; - } - - if (doc.styleSheets[0].rules[0].selectorText == "FONT") - doc.styleSheets[0].removeRule(0); - - doc.styleSheets[0].addRule("FONT", css, 0); - } - }, - */ - fixGeckoBaseHREFBug : function(m, e, h) { var xsrc, xhref; @@ -2059,9 +2072,9 @@ TinyMCE_Engine.prototype = { xsrc = tinyMCE.getAttrib(n, "mce_tsrc"); xhref = tinyMCE.getAttrib(n, "mce_thref"); - if (xsrc != "") { + if (xsrc !== '') { try { - n.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xsrc); + n.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, xsrc); } catch (e) { // Ignore, Firefox cast exception if local file wasn't found } @@ -2069,9 +2082,9 @@ TinyMCE_Engine.prototype = { n.removeAttribute("mce_tsrc"); } - if (xhref != "") { + if (xhref !== '') { try { - n.href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xhref); + n.href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, xhref); } catch (e) { // Ignore, Firefox cast exception if local file wasn't found } @@ -2098,6 +2111,8 @@ TinyMCE_Engine.prototype = { }, _setHTML : function(doc, html_content) { + var i, html, paras, node; + // Force closed anchors open //html_content = html_content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>'); @@ -2112,11 +2127,12 @@ TinyMCE_Engine.prototype = { } // Content duplication bug fix - if (tinyMCE.isIE && tinyMCE.settings['fix_content_duplication']) { + if (tinyMCE.isIE && tinyMCE.settings.fix_content_duplication) { // Remove P elements in P elements - var paras = doc.getElementsByTagName("P"); - for (var i=0; i<paras.length; i++) { - var node = paras[i]; + paras = doc.getElementsByTagName("P"); + for (i=0; i<paras.length; i++) { + node = paras[i]; + while ((node = node.parentNode) != null) { if (node.nodeName == "P") node.outerHTML = node.innerHTML; @@ -2124,25 +2140,7 @@ TinyMCE_Engine.prototype = { } // Content duplication bug fix (Seems to be word crap) - var html = doc.body.innerHTML; -/* - if (html.indexOf('="mso') != -1) { - for (var i=0; i<doc.body.all.length; i++) { - var el = doc.body.all[i]; - el.removeAttribute("className","",0); - el.removeAttribute("style","",0); - } - - html = doc.body.innerHTML; - html = tinyMCE.regexpReplace(html, "<o:p><\/o:p>", "<br />"); - html = tinyMCE.regexpReplace(html, "<o:p> <\/o:p>", ""); - html = tinyMCE.regexpReplace(html, "<st1:.*?>", ""); - html = tinyMCE.regexpReplace(html, "<p><\/p>", ""); - html = tinyMCE.regexpReplace(html, "<p><\/p>\r\n<p><\/p>", ""); - html = tinyMCE.regexpReplace(html, "<p> <\/p>", "<br />"); - html = tinyMCE.regexpReplace(html, "<p>\s*(<p>\s*)?", "<p>"); - html = tinyMCE.regexpReplace(html, "<\/p>\s*(<\/p>\s*)?", "</p>"); - }*/ + html = doc.body.innerHTML; // Always set the htmlText output tinyMCE.setInnerHTML(doc.body, html); @@ -2156,6 +2154,7 @@ TinyMCE_Engine.prototype = { getEditorId : function(form_element) { var inst = this.getInstanceById(form_element); + if (!inst) return null; @@ -2163,25 +2162,27 @@ TinyMCE_Engine.prototype = { }, getInstanceById : function(editor_id) { - var inst = this.instances[editor_id]; + var inst = this.instances[editor_id], n; + if (!inst) { - for (var n in tinyMCE.instances) { - var instance = tinyMCE.instances[n]; - if (!tinyMCE.isInstance(instance)) + for (n in tinyMCE.instances) { + inst = tinyMCE.instances[n]; + + if (!tinyMCE.isInstance(inst)) continue; - if (instance.formTargetElementId == editor_id) { - inst = instance; - break; - } + if (inst.formTargetElementId == editor_id) + return inst; } - } + } else + return inst; - return inst; + return null; }, queryInstanceCommandValue : function(editor_id, command) { var inst = tinyMCE.getInstanceById(editor_id); + if (inst) return inst.queryCommandValue(command); @@ -2190,6 +2191,7 @@ TinyMCE_Engine.prototype = { queryInstanceCommandState : function(editor_id, command) { var inst = tinyMCE.getInstanceById(editor_id); + if (inst) return inst.queryCommandState(command); @@ -2205,76 +2207,72 @@ TinyMCE_Engine.prototype = { }, getCSSClasses : function(editor_id, doc) { - var inst = tinyMCE.getInstanceById(editor_id); + var i, c, x, rule, styles, rules, csses, selectorText, inst = tinyMCE.getInstanceById(editor_id); + var cssClass, addClass, p; - // Is cached, use that - if (inst && inst.cssClasses.length > 0) - return inst.cssClasses; + if (!inst) + inst = tinyMCE.selectedInstance; - if (typeof(editor_id) == "undefined" && typeof(doc) == "undefined") { - var instance; + if (!inst) + return []; - for (var instanceName in tinyMCE.instances) { - instance = tinyMCE.instances[instanceName]; - if (!tinyMCE.isInstance(instance)) - continue; + if (!doc) + doc = inst.getDoc(); - break; - } + // Is cached, use that + if (inst && inst.cssClasses.length > 0) + return inst.cssClasses; - doc = instance.getDoc(); - } + if (!doc) + return; - if (typeof(doc) == "undefined") { - var instance = tinyMCE.getInstanceById(editor_id); - doc = instance.getDoc(); - } + styles = doc.styleSheets; - if (doc) { - var styles = doc.styleSheets; + if (styles && styles.length > 0) { + for (x=0; x<styles.length; x++) { + csses = null; - if (styles && styles.length > 0) { - for (var x=0; x<styles.length; x++) { - var csses = null; + try { + csses = tinyMCE.isIE ? doc.styleSheets(x).rules : styles[x].cssRules; + } catch(e) { + // Just ignore any errors I know this is ugly!! + } + + if (!csses) + return []; - // Just ignore any errors - eval("try {var csses = tinyMCE.isIE ? doc.styleSheets(" + x + ").rules : styles[" + x + "].cssRules;} catch(e) {}"); - if (!csses) - return new Array(); + for (i=0; i<csses.length; i++) { + selectorText = csses[i].selectorText; - for (var i=0; i<csses.length; i++) { - var selectorText = csses[i].selectorText; + // Can be multiple rules per selector + if (selectorText) { + rules = selectorText.split(','); + for (c=0; c<rules.length; c++) { + rule = rules[c]; - // Can be multiple rules per selector - if (selectorText) { - var rules = selectorText.split(','); - for (var c=0; c<rules.length; c++) { - var rule = rules[c]; + // Strip spaces between selectors + while (rule.indexOf(' ') == 0) + rule = rule.substring(1); - // Strip spaces between selectors - while (rule.indexOf(' ') == 0) - rule = rule.substring(1); + // Invalid rule + if (rule.indexOf(' ') != -1 || rule.indexOf(':') != -1 || rule.indexOf('mceItem') != -1) + continue; - // Invalid rule - if (rule.indexOf(' ') != -1 || rule.indexOf(':') != -1 || rule.indexOf('mceItem') != -1) - continue; + if (rule.indexOf(tinyMCE.settings.visual_table_class) != -1 || rule.indexOf('mceEditable') != -1 || rule.indexOf('mceNonEditable') != -1) + continue; - if (rule.indexOf(tinyMCE.settings['visual_table_class']) != -1 || rule.indexOf('mceEditable') != -1 || rule.indexOf('mceNonEditable') != -1) - continue; + // Is class rule + if (rule.indexOf('.') != -1) { + cssClass = rule.substring(rule.indexOf('.') + 1); + addClass = true; - // Is class rule - if (rule.indexOf('.') != -1) { - var cssClass = rule.substring(rule.indexOf('.') + 1); - var addClass = true; - - for (var p=0; p<inst.cssClasses.length && addClass; p++) { - if (inst.cssClasses[p] == cssClass) - addClass = false; - } - - if (addClass) - inst.cssClasses[inst.cssClasses.length] = cssClass; + for (p=0; p<inst.cssClasses.length && addClass; p++) { + if (inst.cssClasses[p] == cssClass) + addClass = false; } + + if (addClass) + inst.cssClasses[inst.cssClasses.length] = cssClass; } } } @@ -2286,13 +2284,16 @@ TinyMCE_Engine.prototype = { }, regexpReplace : function(in_str, reg_exp, replace_str, opts) { + var re; + if (in_str == null) return in_str; if (typeof(opts) == "undefined") opts = 'g'; - var re = new RegExp(reg_exp, opts); + re = new RegExp(reg_exp, opts); + return in_str.replace(re, replace_str); }, @@ -2316,7 +2317,7 @@ TinyMCE_Engine.prototype = { 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>'; @@ -2324,8 +2325,8 @@ TinyMCE_Engine.prototype = { } } - o = tinyMCE.themes[tinyMCE.settings['theme']]; - if (o.getControlHTML && (v = o.getControlHTML(c)) != '') { + o = tinyMCE.themes[tinyMCE.settings.theme]; + if (o.getControlHTML && (v = o.getControlHTML(c)) !== '') { if (rtl) return '<span dir="rtl">' + v + '</span>'; @@ -2361,7 +2362,7 @@ TinyMCE_Engine.prototype = { l = tinyMCE.getParam(p, ''); - if (l != '' && (v = tinyMCE.evalFunc(l, 3, a)) == s && m > 0) + if (l !== '' && (v = tinyMCE.evalFunc(l, 3, a)) == s && m > 0) return true; if (ins != null) { @@ -2384,8 +2385,20 @@ TinyMCE_Engine.prototype = { return false; }, - xmlEncode : function(s, skip_apos) { - return s ? ('' + s).replace(!skip_apos ? this.xmlEncodeAposRe : this.xmlEncodeRe, function (c, b) { + resolveDots : function(s, o) { + var i; + + if (typeof(s) == 'string') { + for (i=0, s=s.split('.'); i<s.length; i++) + o = o[s[i]]; + } else + o = s; + + return o; + }, + + xmlEncode : function(s) { + return s ? ('' + s).replace(this.xmlEncodeRe, function (c, b) { switch (c) { case '&': return '&'; @@ -2393,9 +2406,6 @@ TinyMCE_Engine.prototype = { case '"': return '"'; - case '\'': - return '''; // ' is not working in MSIE - case '<': return '<'; @@ -2407,8 +2417,15 @@ TinyMCE_Engine.prototype = { }) : s; }, + add : function(c, m) { + var n; + + for (n in m) + c.prototype[n] = m[n]; + }, + extend : function(p, np) { - var o = {}; + var o = {}, n; o.parent = p; @@ -2445,20 +2462,21 @@ var tinyMCELang = {}; /* file:jscripts/tiny_mce/classes/TinyMCE_Control.class.js */ function TinyMCE_Control(settings) { - var t, i, to, fu, p, x, fn, fu, pn, s = settings; + var t, i, tos, fu, p, x, fn, fu, pn, s = settings; this.undoRedoLevel = true; this.isTinyMCE_Control = true; // Default settings + this.enabled = true; this.settings = s; - this.settings['theme'] = tinyMCE.getParam("theme", "default"); - this.settings['width'] = tinyMCE.getParam("width", -1); - this.settings['height'] = tinyMCE.getParam("height", -1); + this.settings.theme = tinyMCE.getParam("theme", "default"); + this.settings.width = tinyMCE.getParam("width", -1); + this.settings.height = tinyMCE.getParam("height", -1); this.selection = new TinyMCE_Selection(this); this.undoRedo = new TinyMCE_UndoRedo(this); this.cleanup = new TinyMCE_Cleanup(); - this.shortcuts = new Array(); + this.shortcuts = []; this.hasMouseMoved = false; this.foreColor = this.backColor = "#999999"; this.data = {}; @@ -2479,21 +2497,21 @@ function TinyMCE_Control(settings) { }); // Wrap old theme - t = this.settings['theme']; + t = this.settings.theme; if (!tinyMCE.hasTheme(t)) { fn = tinyMCE.callbacks; - to = {}; + tos = {}; for (i=0; i<fn.length; i++) { if ((fu = window['TinyMCE_' + t + "_" + fn[i]])) - to[fn[i]] = fu; + tos[fn[i]] = fu; } - tinyMCE.addTheme(t, to); + tinyMCE.addTheme(t, tos); } // Wrap old plugins - this.plugins = new Array(); + this.plugins = []; p = tinyMCE.getParam('plugins', '', true, ','); if (p.length > 0) { for (i=0; i<p.length; i++) { @@ -2504,14 +2522,14 @@ function TinyMCE_Control(settings) { if (!tinyMCE.hasPlugin(pn)) { fn = tinyMCE.callbacks; - to = {}; + tos = {}; for (x=0; x<fn.length; x++) { if ((fu = window['TinyMCE_' + pn + "_" + fn[x]])) - to[fn[x]] = fu; + tos[fn[x]] = fu; } - tinyMCE.addPlugin(pn, to); + tinyMCE.addPlugin(pn, tos); } this.plugins[this.plugins.length] = pn; @@ -2573,9 +2591,9 @@ TinyMCE_Control.prototype = { }, switchSettings : function() { - if (tinyMCE.configs.length > 1 && tinyMCE.currentConfig != this.settings['index']) { + if (tinyMCE.configs.length > 1 && tinyMCE.currentConfig != this.settings.index) { tinyMCE.settings = this.settings; - tinyMCE.currentConfig = this.settings['index']; + tinyMCE.currentConfig = this.settings.index; } }, @@ -2709,10 +2727,12 @@ TinyMCE_Control.prototype = { isDirty : function() { // Is content modified and not in a submit procedure - return tinyMCE.trim(this.startContent) != tinyMCE.trim(this.getBody().innerHTML) && !tinyMCE.isNotDirty; + return tinyMCE.trim(this.startContent) != tinyMCE.trim(this.getBody().innerHTML) && !this.isNotDirty; }, _mergeElements : function(scmd, pa, ch, override) { + var st, stc, className, n; + if (scmd == "removeformat") { pa.className = ""; pa.style.cssText = ""; @@ -2721,22 +2741,22 @@ TinyMCE_Control.prototype = { return; } - var st = tinyMCE.parseStyle(tinyMCE.getAttrib(pa, "style")); - var stc = tinyMCE.parseStyle(tinyMCE.getAttrib(ch, "style")); - var className = tinyMCE.getAttrib(pa, "class"); + st = tinyMCE.parseStyle(tinyMCE.getAttrib(pa, "style")); + stc = tinyMCE.parseStyle(tinyMCE.getAttrib(ch, "style")); + className = tinyMCE.getAttrib(pa, "class"); // Removed class adding due to bug #1478272 className = tinyMCE.getAttrib(ch, "class"); if (override) { - for (var n in st) { + for (n in st) { if (typeof(st[n]) == 'function') continue; stc[n] = st[n]; } } else { - for (var n in stc) { + for (n in stc) { if (typeof(stc[n]) == 'function') continue; @@ -2752,6 +2772,55 @@ TinyMCE_Control.prototype = { ch.removeAttribute("style"); }, + _fixRootBlocks : function() { + var rb, b, ne, be, nx, bm; + + rb = tinyMCE.getParam('forced_root_block'); + if (!rb) + return; + + b = this.getBody(); + ne = b.firstChild; + + while (ne) { + nx = ne.nextSibling; + + // If text node or inline element wrap it in a block element + if (ne.nodeType == 3 || !tinyMCE.blockRegExp.test(ne.nodeName)) { + if (!bm) + bm = this.selection.getBookmark(); + + if (!be) { + be = this.getDoc().createElement(rb); + be.appendChild(ne.cloneNode(true)); + b.replaceChild(be, ne); + } else { + be.appendChild(ne.cloneNode(true)); + b.removeChild(ne); + } + } else + be = null; + + ne = nx; + } + + if (bm) + this.selection.moveToBookmark(bm); + }, + + _fixTrailingNbsp : function() { + var s = this.selection, e = s.getFocusElement(), bm, v; + + if (e && tinyMCE.blockRegExp.test(e.nodeName) && e.firstChild) { + v = e.firstChild.nodeValue; + + if (v && v.length > 1 && /(^\u00a0|\u00a0$)/.test(v)) { + e.firstChild.nodeValue = v.replace(/(^\u00a0|\u00a0$)/, ''); + s.selectNode(e.firstChild, true, false, false); // Select and collapse + } + } + }, + _setUseCSS : function(b) { var d = this.getDoc(); @@ -2766,7 +2835,7 @@ TinyMCE_Control.prototype = { }, execCommand : function(command, user_interface, value) { - var doc = this.getDoc(), win = this.getWin(), focusElm = this.getFocusElement(); + var i, x, z, align, img, div, doc = this.getDoc(), win = this.getWin(), focusElm = this.getFocusElement(); // Is not a undo specific command if (!new RegExp('mceStartTyping|mceEndTyping|mceBeginUndoLevel|mceEndUndoLevel|mceAddUndoLevel', 'gi').test(command)) @@ -2789,8 +2858,8 @@ TinyMCE_Control.prototype = { // Fix align on images if (focusElm && focusElm.nodeName == "IMG") { - var align = focusElm.getAttribute('align'); - var img = command == "JustifyCenter" ? focusElm.cloneNode(false) : focusElm; + align = focusElm.getAttribute('align'); + img = command == "JustifyCenter" ? focusElm.cloneNode(false) : focusElm; switch (command) { case "JustifyLeft": @@ -2800,7 +2869,7 @@ TinyMCE_Control.prototype = { img.setAttribute('align', 'left'); // Remove the div - var div = focusElm.parentNode; + div = focusElm.parentNode; if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode) div.parentNode.replaceChild(img, div); @@ -2813,14 +2882,14 @@ TinyMCE_Control.prototype = { img.removeAttribute('align'); // Is centered - var div = tinyMCE.getParentElement(focusElm, "div"); + div = tinyMCE.getParentElement(focusElm, "div"); if (div && div.style.textAlign == "center") { // Remove div if (div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode) div.parentNode.replaceChild(img, div); } else { // Add div - var div = this.getDoc().createElement("div"); + div = this.getDoc().createElement("div"); div.style.textAlign = 'center'; div.appendChild(img); focusElm.parentNode.replaceChild(div, focusElm); @@ -2838,7 +2907,7 @@ TinyMCE_Control.prototype = { img.setAttribute('align', 'right'); // Remove the div - var div = focusElm.parentNode; + div = focusElm.parentNode; if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode) div.parentNode.replaceChild(img, div); @@ -2849,7 +2918,7 @@ TinyMCE_Control.prototype = { } } - if (tinyMCE.settings['force_br_newlines']) { + if (tinyMCE.settings.force_br_newlines) { var alignValue = ""; if (doc.selection.type != "Control") { @@ -2871,7 +2940,7 @@ TinyMCE_Control.prototype = { break; } - if (alignValue != "") { + if (alignValue !== '') { var rng = doc.selection.createRange(); if ((divElm = tinyMCE.getParentElement(rng.parentElement(), "div")) != null) @@ -2925,7 +2994,7 @@ TinyMCE_Control.prototype = { break; case "FormatBlock": - if (value == null || value == "") { + if (value == null || value == '') { var elm = tinyMCE.getParentElement(this.getFocusElement(), "p,div,h1,h2,h3,h4,h5,h6,pre,address,blockquote,dt,dl,dd,samp"); if (elm) @@ -2970,7 +3039,7 @@ TinyMCE_Control.prototype = { case "mceSelectNodeDepth": var parentNode = this.getFocusElement(); - for (var i=0; parentNode; i++) { + for (i=0; parentNode; i++) { if (parentNode.nodeName.toLowerCase() == "body") break; @@ -2996,14 +3065,14 @@ TinyMCE_Control.prototype = { case "SetStyleInfo": var rng = this.getRng(); var sel = this.getSel(); - var scmd = value['command']; - var sname = value['name']; - var svalue = value['value'] == null ? '' : value['value']; + var scmd = value.command; + var sname = value.name; + var svalue = value.value == null ? '' : value.value; //var svalue = value['value'] == null ? '' : value['value']; - var wrapper = value['wrapper'] ? value['wrapper'] : "span"; + var wrapper = value.wrapper ? value.wrapper : "span"; var parentElm = null; var invalidRe = new RegExp("^BODY|HTML$", "g"); - var invalidParentsRe = tinyMCE.settings['merge_styles_invalid_parents'] != '' ? new RegExp(tinyMCE.settings['merge_styles_invalid_parents'], "gi") : null; + var invalidParentsRe = tinyMCE.settings.merge_styles_invalid_parents !== '' ? new RegExp(tinyMCE.settings.merge_styles_invalid_parents, "gi") : null; // Whole element selected check if (tinyMCE.isIE) { @@ -3022,7 +3091,7 @@ TinyMCE_Control.prototype = { } } else { var felm = this.getFocusElement(); - if (sel.isCollapsed || (new RegExp('td|tr|tbody|table', 'gi').test(felm.nodeName) && sel.anchorNode == felm.parentNode)) + if (sel.isCollapsed || (new RegExp('td|tr|tbody|table|img', 'gi').test(felm.nodeName) && sel.anchorNode == felm.parentNode)) parentElm = felm; } @@ -3040,8 +3109,8 @@ TinyMCE_Control.prototype = { } // Remove style/attribs from all children - var ch = tinyMCE.getNodeTree(parentElm, new Array(), 1); - for (var z=0; z<ch.length; z++) { + var ch = tinyMCE.getNodeTree(parentElm, [], 1); + for (z=0; z<ch.length; z++) { if (ch[z] == parentElm) continue; @@ -3062,7 +3131,7 @@ TinyMCE_Control.prototype = { var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#"); // Change them all - for (var x=0; x<elementArray.length; x++) { + for (x=0; x<elementArray.length; x++) { elm = elementArray[x]; if (elm) { var spanElm = doc.createElement(wrapper); @@ -3079,7 +3148,7 @@ TinyMCE_Control.prototype = { } if (elm.hasChildNodes()) { - for (var i=0; i<elm.childNodes.length; i++) + for (i=0; i<elm.childNodes.length; i++) spanElm.appendChild(elm.childNodes[i].cloneNode(true)); } @@ -3087,8 +3156,8 @@ TinyMCE_Control.prototype = { elm.parentNode.replaceChild(spanElm, elm); // Remove style/attribs from all children - var ch = tinyMCE.getNodeTree(spanElm, new Array(), 1); - for (var z=0; z<ch.length; z++) { + var ch = tinyMCE.getNodeTree(spanElm, [], 1); + for (z=0; z<ch.length; z++) { if (ch[z] == spanElm) continue; @@ -3109,7 +3178,7 @@ TinyMCE_Control.prototype = { // Cleaup wrappers var nodes = doc.getElementsByTagName(wrapper); - for (var i=nodes.length-1; i>=0; i--) { + for (i=nodes.length-1; i>=0; i--) { var elm = nodes[i]; var isNew = tinyMCE.getAttrib(elm, "mce_new") == "true"; @@ -3132,9 +3201,8 @@ TinyMCE_Control.prototype = { // Remove empty wrappers var nodes = doc.getElementsByTagName(wrapper); - for (var i=nodes.length-1; i>=0; i--) { - var elm = nodes[i]; - var isEmpty = true; + for (i=nodes.length-1; i>=0; i--) { + var elm = nodes[i], isEmpty = true; // Check if it has any attribs var tmp = doc.createElement("body"); @@ -3144,7 +3212,7 @@ TinyMCE_Control.prototype = { tmp.innerHTML = tmp.innerHTML.replace(new RegExp('style=""|class=""', 'gi'), ''); //tinyMCE.debug(tmp.innerHTML); if (new RegExp('<span>', 'gi').test(tmp.innerHTML)) { - for (var x=0; x<elm.childNodes.length; x++) { + for (x=0; x<elm.childNodes.length; x++) { if (elm.parentNode != null) elm.parentNode.insertBefore(elm.childNodes[x].cloneNode(true), elm); } @@ -3269,6 +3337,8 @@ TinyMCE_Control.prototype = { tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this); tinyMCE._setEventsEnabled(this.getBody(), false); + this._addBogusBR(); + return true; case "mceCleanup": @@ -3283,6 +3353,7 @@ TinyMCE_Control.prototype = { tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this); tinyMCE._setEventsEnabled(this.getBody(), false); + this._addBogusBR(); this.repaint(); this.selection.moveToBookmark(b); tinyMCE.triggerNodeChange(); @@ -3308,16 +3379,17 @@ TinyMCE_Control.prototype = { tinyMCE.execCommand('mceInsertContent', false, value); } + this._addBogusBR(); tinyMCE.triggerNodeChange(); break; case "mceSetAttribute": if (typeof(value) == 'object') { - var targetElms = (typeof(value['targets']) == "undefined") ? "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address" : value['targets']; + var targetElms = (typeof(value.targets) == "undefined") ? "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address" : value.targets; var targetNode = tinyMCE.getParentElement(this.getFocusElement(), targetElms); if (targetNode) { - targetNode.setAttribute(value['name'], value['value']); + targetNode.setAttribute(value.name, value.value); tinyMCE.triggerNodeChange(); } } @@ -3412,10 +3484,7 @@ TinyMCE_Control.prototype = { value = rng.createContextualFragment(value); } else { // Setup text node - var el = document.createElement("div"); - el.innerHTML = value; - value = el.firstChild.nodeValue; - value = doc.createTextNode(value); + value = doc.createTextNode(tinyMCE.entityDecode(value)); } // Insert plain text in Safari @@ -3485,7 +3554,7 @@ TinyMCE_Control.prototype = { break; case "mceStartTyping": - if (tinyMCE.settings['custom_undo_redo'] && this.undoRedo.typingUndoIndex == -1) { + if (tinyMCE.settings.custom_undo_redo && this.undoRedo.typingUndoIndex == -1) { this.undoRedo.typingUndoIndex = this.undoRedo.undoIndex; tinyMCE.typingUndoIndex = tinyMCE.undoIndex; this.execCommand('mceAddUndoLevel'); @@ -3493,7 +3562,7 @@ TinyMCE_Control.prototype = { break; case "mceEndTyping": - if (tinyMCE.settings['custom_undo_redo'] && this.undoRedo.typingUndoIndex != -1) { + if (tinyMCE.settings.custom_undo_redo && this.undoRedo.typingUndoIndex != -1) { this.execCommand('mceAddUndoLevel'); this.undoRedo.typingUndoIndex = -1; } @@ -3511,14 +3580,14 @@ TinyMCE_Control.prototype = { break; case "mceAddUndoLevel": - if (tinyMCE.settings['custom_undo_redo'] && this.undoRedoLevel) { + if (tinyMCE.settings.custom_undo_redo && this.undoRedoLevel) { if (this.undoRedo.add()) tinyMCE.triggerNodeChange(false); } break; case "Undo": - if (tinyMCE.settings['custom_undo_redo']) { + if (tinyMCE.settings.custom_undo_redo) { tinyMCE.execCommand("mceEndTyping"); this.undoRedo.undo(); tinyMCE.triggerNodeChange(); @@ -3527,7 +3596,7 @@ TinyMCE_Control.prototype = { break; case "Redo": - if (tinyMCE.settings['custom_undo_redo']) { + if (tinyMCE.settings.custom_undo_redo) { tinyMCE.execCommand("mceEndTyping"); this.undoRedo.redo(); tinyMCE.triggerNodeChange(); @@ -3613,96 +3682,105 @@ TinyMCE_Control.prototype = { return this.getDoc().queryCommandState(c); }, + _addBogusBR : function() { + var b = this.getBody(); + + if (tinyMCE.isGecko && !b.hasChildNodes()) + b.innerHTML = '<br _moz_editor_bogus_node="TRUE" />'; + }, + _onAdd : function(replace_element, form_element_name, target_document) { - var hc, th, to, editorTemplate; + var hc, th, tos, editorTemplate, targetDoc, deltaWidth, deltaHeight, html, rng, fragment; + var dynamicIFrame, tElm, doc, parentElm; - th = this.settings['theme']; - to = tinyMCE.themes[th]; + th = this.settings.theme; + tos = tinyMCE.themes[th]; - var targetDoc = target_document ? target_document : document; + targetDoc = target_document ? target_document : document; this.targetDoc = targetDoc; - tinyMCE.themeURL = tinyMCE.baseURL + "/themes/" + this.settings['theme']; - this.settings['themeurl'] = tinyMCE.themeURL; + tinyMCE.themeURL = tinyMCE.baseURL + "/themes/" + this.settings.theme; + this.settings.themeurl = tinyMCE.themeURL; if (!replace_element) { alert("Error: Could not find the target element."); return false; } - if (to.getEditorTemplate) - editorTemplate = to.getEditorTemplate(this.settings, this.editorId); + if (tos.getEditorTemplate) + editorTemplate = tos.getEditorTemplate(this.settings, this.editorId); - var deltaWidth = editorTemplate['delta_width'] ? editorTemplate['delta_width'] : 0; - var deltaHeight = editorTemplate['delta_height'] ? editorTemplate['delta_height'] : 0; - var html = '<span id="' + this.editorId + '_parent" class="mceEditorContainer">' + editorTemplate['html']; + deltaWidth = editorTemplate.delta_width ? editorTemplate.delta_width : 0; + deltaHeight = editorTemplate.delta_height ? editorTemplate.delta_height : 0; + html = '<span id="' + this.editorId + '_parent" class="mceEditorContainer">' + editorTemplate.html; html = tinyMCE.replaceVar(html, "editor_id", this.editorId); - this.settings['default_document'] = tinyMCE.baseURL + "/blank.htm"; - this.settings['old_width'] = this.settings['width']; - this.settings['old_height'] = this.settings['height']; + if (!this.settings.default_document) + this.settings.default_document = tinyMCE.baseURL + "/blank.htm"; + + this.settings.old_width = this.settings.width; + this.settings.old_height = this.settings.height; // Set default width, height - if (this.settings['width'] == -1) - this.settings['width'] = replace_element.offsetWidth; + if (this.settings.width == -1) + this.settings.width = replace_element.offsetWidth; - if (this.settings['height'] == -1) - this.settings['height'] = replace_element.offsetHeight; + if (this.settings.height == -1) + this.settings.height = replace_element.offsetHeight; // Try the style width - if (this.settings['width'] == 0) - this.settings['width'] = replace_element.style.width; + if (this.settings.width == 0) + this.settings.width = replace_element.style.width; // Try the style height - if (this.settings['height'] == 0) - this.settings['height'] = replace_element.style.height; + if (this.settings.height == 0) + this.settings.height = replace_element.style.height; // If no width/height then default to 320x240, better than nothing - if (this.settings['width'] == 0) - this.settings['width'] = 320; + if (this.settings.width == 0) + this.settings.width = 320; - if (this.settings['height'] == 0) - this.settings['height'] = 240; + if (this.settings.height == 0) + this.settings.height = 240; - this.settings['area_width'] = parseInt(this.settings['width']); - this.settings['area_height'] = parseInt(this.settings['height']); - this.settings['area_width'] += deltaWidth; - this.settings['area_height'] += deltaHeight; - - this.settings['width_style'] = "" + this.settings['width']; - this.settings['height_style'] = "" + this.settings['height']; + this.settings.area_width = parseInt(this.settings.width); + this.settings.area_height = parseInt(this.settings.height); + this.settings.area_width += deltaWidth; + this.settings.area_height += deltaHeight; + this.settings.width_style = "" + this.settings.width; + this.settings.height_style = "" + this.settings.height; // Special % handling - if (("" + this.settings['width']).indexOf('%') != -1) - this.settings['area_width'] = "100%"; + if (("" + this.settings.width).indexOf('%') != -1) + this.settings.area_width = "100%"; else - this.settings['width_style'] += 'px'; + this.settings.width_style += 'px'; - if (("" + this.settings['height']).indexOf('%') != -1) - this.settings['area_height'] = "100%"; + if (("" + this.settings.height).indexOf('%') != -1) + this.settings.area_height = "100%"; else - this.settings['height_style'] += 'px'; + this.settings.height_style += 'px'; if (("" + replace_element.style.width).indexOf('%') != -1) { - this.settings['width'] = replace_element.style.width; - this.settings['area_width'] = "100%"; - this.settings['width_style'] = "100%"; + this.settings.width = replace_element.style.width; + this.settings.area_width = "100%"; + this.settings.width_style = "100%"; } if (("" + replace_element.style.height).indexOf('%') != -1) { - this.settings['height'] = replace_element.style.height; - this.settings['area_height'] = "100%"; - this.settings['height_style'] = "100%"; + this.settings.height = replace_element.style.height; + this.settings.area_height = "100%"; + this.settings.height_style = "100%"; } html = tinyMCE.applyTemplate(html); - this.settings['width'] = this.settings['old_width']; - this.settings['height'] = this.settings['old_height']; + this.settings.width = this.settings.old_width; + this.settings.height = this.settings.old_height; - this.visualAid = this.settings['visual']; + this.visualAid = this.settings.visual; this.formTargetElementId = form_element_name; // Get replace_element contents @@ -3716,13 +3794,9 @@ TinyMCE_Control.prototype = { this.oldTargetElement = replace_element; // Debug mode - if (tinyMCE.settings['debug']) { - 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"; - } + 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"; html += '</span>'; @@ -3733,10 +3807,10 @@ TinyMCE_Control.prototype = { // Output HTML and set editable if (tinyMCE.isGecko) { - var rng = replace_element.ownerDocument.createRange(); + rng = replace_element.ownerDocument.createRange(); rng.setStartBefore(replace_element); - var fragment = rng.createContextualFragment(html); + fragment = rng.createContextualFragment(html); tinyMCE.insertAfter(fragment, replace_element); } else replace_element.insertAdjacentHTML("beforeBegin", html); @@ -3746,25 +3820,23 @@ TinyMCE_Control.prototype = { // Just hide the textarea element this.oldTargetElement = replace_element; - if (!tinyMCE.settings['debug']) { - this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline'); - this.oldTargetElement.style.display = "none"; - } + this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline'); + this.oldTargetElement.style.display = "none"; // Output HTML and set editable if (tinyMCE.isGecko) { - var rng = replace_element.ownerDocument.createRange(); + rng = replace_element.ownerDocument.createRange(); rng.setStartBefore(replace_element); - var fragment = rng.createContextualFragment(html); + fragment = rng.createContextualFragment(html); tinyMCE.insertAfter(fragment, replace_element); } else replace_element.insertAdjacentHTML("beforeBegin", html); } // Setup iframe - var dynamicIFrame = false; - var tElm = targetDoc.getElementById(this.editorId); + dynamicIFrame = false; + tElm = targetDoc.getElementById(this.editorId); if (!tinyMCE.isIE) { // Node case is preserved in XML strict mode @@ -3801,9 +3873,9 @@ TinyMCE_Control.prototype = { } // Setup base HTML - var doc = this.contentDocument; + doc = this.contentDocument; if (dynamicIFrame) { - var html = tinyMCE.getParam('doctype') + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + tinyMCE.settings['base_href'] + '" /><title>blank_page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body class="mceContentBody"></body></html>'; + html = tinyMCE.getParam('doctype') + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + tinyMCE.settings.base_href + '" /><title>blank_page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body class="mceContentBody"></body></html>'; try { if (!this.isHidden()) @@ -3824,7 +3896,7 @@ TinyMCE_Control.prototype = { window.setTimeout("tinyMCE.addEventHandlers(tinyMCE.instances[\"" + this.editorId + "\"]);", 1); // Setup element references - var parentElm = this.targetDoc.getElementById(this.editorId + '_parent'); + parentElm = this.targetDoc.getElementById(this.editorId + '_parent'); this.formElement = tinyMCE.isGecko ? parentElm.previousSibling : parentElm.nextSibling; tinyMCE.setupContent(this.editorId, true); @@ -3847,7 +3919,7 @@ TinyMCE_Control.prototype = { b.setAttribute('href', u); h.appendChild(b); } else { - if (u == "" || u == null) + if (u == '' || u == null) b.parentNode.removeChild(b); else b.setAttribute('href', u); @@ -3886,7 +3958,10 @@ TinyMCE_Control.prototype = { }, triggerSave : function(skip_cleanup, skip_callback) { - var e, nl = [], i, s; + var e, nl = [], i, s, content, htm; + + if (!this.enabled) + return; this.switchSettings(); s = tinyMCE.settings; @@ -3908,7 +3983,7 @@ TinyMCE_Control.prototype = { } while ((e = e.parentNode) != null) } - tinyMCE.settings['preformatted'] = false; + tinyMCE.settings.preformatted = false; // Default to false if (typeof(skip_cleanup) == "undefined") @@ -3921,17 +3996,17 @@ TinyMCE_Control.prototype = { tinyMCE._setHTML(this.getDoc(), this.getBody().innerHTML); // Remove visual aids when cleanup is disabled - if (this.settings['cleanup'] == false) { + if (this.settings.cleanup == false) { tinyMCE.handleVisualAid(this.getBody(), true, false, this); tinyMCE._setEventsEnabled(this.getBody(), true); } tinyMCE._customCleanup(this, "submit_content_dom", this.contentWindow.document.body); - var htm = skip_cleanup ? this.getBody().innerHTML : tinyMCE._cleanupHTML(this, this.getDoc(), this.settings, this.getBody(), tinyMCE.visualAid, true, true); + htm = skip_cleanup ? this.getBody().innerHTML : tinyMCE._cleanupHTML(this, this.getDoc(), this.settings, this.getBody(), tinyMCE.visualAid, true, true); htm = tinyMCE._customCleanup(this, "submit_content", htm); - if (!skip_callback && tinyMCE.settings['save_callback'] != "") - var content = eval(tinyMCE.settings['save_callback'] + "(this.formTargetElementId,htm,this.getBody());"); + if (!skip_callback && tinyMCE.settings.save_callback !== '') + content = tinyMCE.resolveDots(tinyMCE.settings.save_callback, window)(this.formTargetElementId,htm,this.getBody()); // Use callback content if available if ((typeof(content) != "undefined") && content != null) @@ -3963,444 +4038,441 @@ TinyMCE_Control.prototype = { /* file:jscripts/tiny_mce/classes/TinyMCE_Cleanup.class.js */ -TinyMCE_Engine.prototype.cleanupHTMLCode = function(s) { - s = s.replace(new RegExp('<p \\/>', 'gi'), '<p> </p>'); - s = s.replace(new RegExp('<p>\\s*<\\/p>', 'gi'), '<p> </p>'); - - // Fix close BR elements - s = s.replace(new RegExp('<br>\\s*<\\/br>', 'gi'), '<br />'); +tinyMCE.add(TinyMCE_Engine, { + cleanupHTMLCode : function(s) { + s = s.replace(new RegExp('<p \\/>', 'gi'), '<p> </p>'); + s = s.replace(new RegExp('<p>\\s*<\\/p>', 'gi'), '<p> </p>'); - // Open closed tags like <b/> to <b></b> - s = s.replace(new RegExp('<(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|b|font|em|strong|i|strike|u|span|a|ul|ol|li|blockquote)([a-z]*)([^\\\\|>]*)\\/>', 'gi'), '<$1$2$3></$1$2>'); + // Fix close BR elements + s = s.replace(new RegExp('<br>\\s*<\\/br>', 'gi'), '<br />'); - // Remove trailing space <b > to <b> - s = s.replace(new RegExp('\\s+></', 'gi'), '></'); + // Open closed tags like <b/> to <b></b> + s = s.replace(new RegExp('<(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|b|font|em|strong|i|strike|u|span|a|ul|ol|li|blockquote)([a-z]*)([^\\\\|>]*)\\/>', 'gi'), '<$1$2$3></$1$2>'); - // Close tags <img></img> to <img/> - s = s.replace(new RegExp('<(img|br|hr)([^>]*)><\\/(img|br|hr)>', 'gi'), '<$1$2 />'); + // Remove trailing space <b > to <b> + s = s.replace(new RegExp('\\s+></', 'gi'), '></'); - // Weird MSIE bug, <p><hr /></p> breaks runtime? - if (tinyMCE.isIE) - s = s.replace(new RegExp('<p><hr \\/><\\/p>', 'gi'), "<hr>"); + // Close tags <img></img> to <img/> + s = s.replace(new RegExp('<(img|br|hr)([^>]*)><\\/(img|br|hr)>', 'gi'), '<$1$2 />'); - // Weird tags will make IE error #bug: 1538495 - if (tinyMCE.isIE) - s = s.replace(/<!(\s*)\/>/g, ''); + // Weird MSIE bug, <p><hr /></p> breaks runtime? + if (tinyMCE.isIE) + s = s.replace(new RegExp('<p><hr \\/><\\/p>', 'gi'), "<hr>"); - // Convert relative anchors to absolute URLs ex: #something to file.htm#something - // Removed: Since local document anchors should never be forced absolute example edit.php?id=something - //if (tinyMCE.getParam('convert_urls')) - // s = s.replace(new RegExp('(href=\"{0,1})(\\s*#)', 'gi'), '$1' + tinyMCE.settings['document_base_url'] + "#"); + // Weird tags will make IE error #bug: 1538495 + if (tinyMCE.isIE) + s = s.replace(/<!(\s*)\/>/g, ''); - return s; -}; + // Convert relative anchors to absolute URLs ex: #something to file.htm#something + // Removed: Since local document anchors should never be forced absolute example edit.php?id=something + //if (tinyMCE.getParam('convert_urls')) + // s = s.replace(new RegExp('(href=\"{0,1})(\\s*#)', 'gi'), '$1' + tinyMCE.settings.document_base_url + "#"); -TinyMCE_Engine.prototype.parseStyle = function(str) { - var ar = new Array(); + return s; + }, - if (str == null) - return ar; + parseStyle : function(str) { + var ar = [], st, i, re, pa; - var st = str.split(';'); + if (str == null) + return ar; - tinyMCE.clearArray(ar); + st = str.split(';'); - for (var i=0; i<st.length; i++) { - if (st[i] == '') - continue; + tinyMCE.clearArray(ar); - var re = new RegExp('^\\s*([^:]*):\\s*(.*)\\s*$'); - var pa = st[i].replace(re, '$1||$2').split('||'); -//tinyMCE.debug(str, pa[0] + "=" + pa[1], st[i].replace(re, '$1||$2')); - if (pa.length == 2) - ar[pa[0].toLowerCase()] = pa[1]; - } + for (i=0; i<st.length; i++) { + if (st[i] == '') + continue; - return ar; -}; + re = new RegExp('^\\s*([^:]*):\\s*(.*)\\s*$'); + pa = st[i].replace(re, '$1||$2').split('||'); + //tinyMCE.debug(str, pa[0] + "=" + pa[1], st[i].replace(re, '$1||$2')); + if (pa.length == 2) + ar[pa[0].toLowerCase()] = pa[1]; + } -TinyMCE_Engine.prototype.compressStyle = function(ar, pr, sf, res) { - var box = new Array(); + return ar; + }, - box[0] = ar[pr + '-top' + sf]; - box[1] = ar[pr + '-left' + sf]; - box[2] = ar[pr + '-right' + sf]; - box[3] = ar[pr + '-bottom' + sf]; + compressStyle : function(ar, pr, sf, res) { + var box = [], i, a; - for (var i=0; i<box.length; i++) { - if (box[i] == null) - return; + box[0] = ar[pr + '-top' + sf]; + box[1] = ar[pr + '-left' + sf]; + box[2] = ar[pr + '-right' + sf]; + box[3] = ar[pr + '-bottom' + sf]; - for (var a=0; a<box.length; a++) { - if (box[a] != box[i]) + for (i=0; i<box.length; i++) { + if (box[i] == null) return; + + for (a=0; a<box.length; a++) { + if (box[a] != box[i]) + return; + } } - } - // They are all the same - ar[res] = box[0]; - ar[pr + '-top' + sf] = null; - ar[pr + '-left' + sf] = null; - ar[pr + '-right' + sf] = null; - ar[pr + '-bottom' + sf] = null; -}; + // They are all the same + ar[res] = box[0]; + ar[pr + '-top' + sf] = null; + ar[pr + '-left' + sf] = null; + ar[pr + '-right' + sf] = null; + ar[pr + '-bottom' + sf] = null; + }, -TinyMCE_Engine.prototype.serializeStyle = function(ar) { - var str = ""; + serializeStyle : function(ar) { + var str = "", key, val, m; - // Compress box - tinyMCE.compressStyle(ar, "border", "", "border"); - tinyMCE.compressStyle(ar, "border", "-width", "border-width"); - tinyMCE.compressStyle(ar, "border", "-color", "border-color"); - tinyMCE.compressStyle(ar, "border", "-style", "border-style"); - tinyMCE.compressStyle(ar, "padding", "", "padding"); - tinyMCE.compressStyle(ar, "margin", "", "margin"); + // Compress box + tinyMCE.compressStyle(ar, "border", "", "border"); + tinyMCE.compressStyle(ar, "border", "-width", "border-width"); + tinyMCE.compressStyle(ar, "border", "-color", "border-color"); + tinyMCE.compressStyle(ar, "border", "-style", "border-style"); + tinyMCE.compressStyle(ar, "padding", "", "padding"); + tinyMCE.compressStyle(ar, "margin", "", "margin"); - for (var key in ar) { - var val = ar[key]; + for (key in ar) { + val = ar[key]; - if (typeof(val) == 'function') - continue; + if (typeof(val) == 'function') + continue; - if (key.indexOf('mso-') == 0) - continue; + if (key.indexOf('mso-') == 0) + continue; - if (val != null && val != '') { - val = '' + val; // Force string + if (val != null && val !== '') { + val = '' + val; // Force string - // Fix style URL - val = val.replace(new RegExp("url\\(\\'?([^\\']*)\\'?\\)", 'gi'), "url('$1')"); + // Fix style URL + val = val.replace(new RegExp("url\\(\\'?([^\\']*)\\'?\\)", 'gi'), "url('$1')"); - // Convert URL - if (val.indexOf('url(') != -1 && tinyMCE.getParam('convert_urls')) { - var m = new RegExp("url\\('(.*?)'\\)").exec(val); + // Convert URL + if (val.indexOf('url(') != -1 && tinyMCE.getParam('convert_urls')) { + m = new RegExp("url\\('(.*?)'\\)").exec(val); - if (m.length > 1) - val = "url('" + eval(tinyMCE.getParam('urlconverter_callback') + "(m[1], null, true);") + "')"; - } + if (m.length > 1) + val = "url('" + eval(tinyMCE.getParam('urlconverter_callback') + "(m[1], null, true);") + "')"; + } - // Force HEX colors - if (tinyMCE.getParam("force_hex_style_colors")) - val = tinyMCE.convertRGBToHex(val, true); + // Force HEX colors + if (tinyMCE.getParam("force_hex_style_colors")) + val = tinyMCE.convertRGBToHex(val, true); - val = val.replace(/\"/g, '\''); + val = val.replace(/\"/g, '\''); - if (val != "url('')") - str += key.toLowerCase() + ": " + val + "; "; + if (val != "url('')") + str += key.toLowerCase() + ": " + val + "; "; + } } - } - if (new RegExp('; $').test(str)) - str = str.substring(0, str.length - 2); + if (new RegExp('; $').test(str)) + str = str.substring(0, str.length - 2); - return str; -}; + return str; + }, -TinyMCE_Engine.prototype.convertRGBToHex = function(s, k) { - if (s.toLowerCase().indexOf('rgb') != -1) { - var re = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi"); - var rgb = s.replace(re, "$1,$2,$3,$4,$5").split(','); - if (rgb.length == 5) { - r = parseInt(rgb[1]).toString(16); - g = parseInt(rgb[2]).toString(16); - b = parseInt(rgb[3]).toString(16); + convertRGBToHex : function(s, k) { + var re, rgb; - r = r.length == 1 ? '0' + r : r; - g = g.length == 1 ? '0' + g : g; - b = b.length == 1 ? '0' + b : b; + if (s.toLowerCase().indexOf('rgb') != -1) { + re = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi"); + rgb = s.replace(re, "$1,$2,$3,$4,$5").split(','); - s = "#" + r + g + b; + if (rgb.length == 5) { + r = parseInt(rgb[1]).toString(16); + g = parseInt(rgb[2]).toString(16); + b = parseInt(rgb[3]).toString(16); - if (k) - s = rgb[0] + s + rgb[4]; - } - } + r = r.length == 1 ? '0' + r : r; + g = g.length == 1 ? '0' + g : g; + b = b.length == 1 ? '0' + b : b; - return s; -}; + s = "#" + r + g + b; -TinyMCE_Engine.prototype.convertHexToRGB = function(s) { - if (s.indexOf('#') != -1) { - s = s.replace(new RegExp('[^0-9A-F]', 'gi'), ''); - return "rgb(" + parseInt(s.substring(0, 2), 16) + "," + parseInt(s.substring(2, 4), 16) + "," + parseInt(s.substring(4, 6), 16) + ")"; - } + if (k) + s = rgb[0] + s + rgb[4]; + } + } - return s; -}; + return s; + }, -TinyMCE_Engine.prototype.convertSpansToFonts = function(doc) { - var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(','); + convertHexToRGB : function(s) { + if (s.indexOf('#') != -1) { + s = s.replace(new RegExp('[^0-9A-F]', 'gi'), ''); + return "rgb(" + parseInt(s.substring(0, 2), 16) + "," + parseInt(s.substring(2, 4), 16) + "," + parseInt(s.substring(4, 6), 16) + ")"; + } - /*var h = doc.body.innerHTML; - h = h.replace(/<span/gi, '<font'); - h = h.replace(/<\/span/gi, '</font'); - tinyMCE.setInnerHTML(doc.body, h);*/ + return s; + }, - var s = tinyMCE.selectElements(doc, 'span,font'); - for (var i=0; i<s.length; i++) { - var size = tinyMCE.trim(s[i].style.fontSize).toLowerCase(); - var fSize = 0; + convertSpansToFonts : function(doc) { + var s, i, size, fSize, x, fFace, fColor, sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(','); - for (var x=0; x<sizes.length; x++) { - if (sizes[x] == size) { - fSize = x + 1; - break; + s = tinyMCE.selectElements(doc, 'span,font'); + for (i=0; i<s.length; i++) { + size = tinyMCE.trim(s[i].style.fontSize).toLowerCase(); + fSize = 0; + + for (x=0; x<sizes.length; x++) { + if (sizes[x] == size) { + fSize = x + 1; + break; + } } - } - if (fSize > 0) { - tinyMCE.setAttrib(s[i], 'size', fSize); - s[i].style.fontSize = ''; - } + if (fSize > 0) { + tinyMCE.setAttrib(s[i], 'size', fSize); + s[i].style.fontSize = ''; + } - var fFace = s[i].style.fontFamily; - if (fFace != null && fFace != "") { - tinyMCE.setAttrib(s[i], 'face', fFace); - s[i].style.fontFamily = ''; - } + fFace = s[i].style.fontFamily; + if (fFace != null && fFace !== '') { + tinyMCE.setAttrib(s[i], 'face', fFace); + s[i].style.fontFamily = ''; + } - var fColor = s[i].style.color; - if (fColor != null && fColor != "") { - tinyMCE.setAttrib(s[i], 'color', tinyMCE.convertRGBToHex(fColor)); - s[i].style.color = ''; + fColor = s[i].style.color; + if (fColor != null && fColor !== '') { + tinyMCE.setAttrib(s[i], 'color', tinyMCE.convertRGBToHex(fColor)); + s[i].style.color = ''; + } } - } -}; + }, -TinyMCE_Engine.prototype.convertFontsToSpans = function(doc) { - var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(','); + convertFontsToSpans : function(doc) { + var fsClasses, s, i, fSize, fFace, fColor, sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(','); -/* var h = doc.body.innerHTML; - h = h.replace(/<font/gi, '<span'); - h = h.replace(/<\/font/gi, '</span'); - tinyMCE.setInnerHTML(doc.body, h);*/ + fsClasses = tinyMCE.getParam('font_size_classes'); + if (fsClasses !== '') + fsClasses = fsClasses.replace(/\s+/, '').split(','); + else + fsClasses = null; - var fsClasses = tinyMCE.getParam('font_size_classes'); - if (fsClasses != '') - fsClasses = fsClasses.replace(/\s+/, '').split(','); - else - fsClasses = null; + s = tinyMCE.selectElements(doc, 'span,font'); + for (i=0; i<s.length; i++) { + fSize = tinyMCE.getAttrib(s[i], 'size'); + fFace = tinyMCE.getAttrib(s[i], 'face'); + fColor = tinyMCE.getAttrib(s[i], 'color'); - var s = tinyMCE.selectElements(doc, 'span,font'); - for (var i=0; i<s.length; i++) { - var fSize, fFace, fColor; + if (fSize !== '') { + fSize = parseInt(fSize); - fSize = tinyMCE.getAttrib(s[i], 'size'); - fFace = tinyMCE.getAttrib(s[i], 'face'); - fColor = tinyMCE.getAttrib(s[i], 'color'); + if (fSize > 0 && fSize < 8) { + if (fsClasses != null) + tinyMCE.setAttrib(s[i], 'class', fsClasses[fSize-1]); + else + s[i].style.fontSize = sizes[fSize-1]; + } - if (fSize != "") { - fSize = parseInt(fSize); + s[i].removeAttribute('size'); + } - if (fSize > 0 && fSize < 8) { - if (fsClasses != null) - tinyMCE.setAttrib(s[i], 'class', fsClasses[fSize-1]); - else - s[i].style.fontSize = sizes[fSize-1]; + if (fFace !== '') { + s[i].style.fontFamily = fFace; + s[i].removeAttribute('face'); } - s[i].removeAttribute('size'); + if (fColor !== '') { + s[i].style.color = fColor; + s[i].removeAttribute('color'); + } } + }, - if (fFace != "") { - s[i].style.fontFamily = fFace; - s[i].removeAttribute('face'); - } + cleanupAnchors : function(doc) { + var i, cn, x, an = doc.getElementsByTagName("a"); - if (fColor != "") { - s[i].style.color = fColor; - s[i].removeAttribute('color'); + // Loops backwards due to bug #1467987 + for (i=an.length-1; i>=0; i--) { + if (tinyMCE.getAttrib(an[i], "name") !== '' && tinyMCE.getAttrib(an[i], "href") == '') { + cn = an[i].childNodes; + + for (x=cn.length-1; x>=0; x--) + tinyMCE.insertAfter(cn[x], an[i]); + } } - } -}; + }, -TinyMCE_Engine.prototype.cleanupAnchors = function(doc) { - var i, cn, x, an = doc.getElementsByTagName("a"); + getContent : function(editor_id) { + if (typeof(editor_id) != "undefined") + tinyMCE.getInstanceById(editor_id).select(); - // Loops backwards due to bug #1467987 - for (i=an.length-1; i>=0; i--) { - if (tinyMCE.getAttrib(an[i], "name") != "" && tinyMCE.getAttrib(an[i], "href") == "") { - cn = an[i].childNodes; + if (tinyMCE.selectedInstance) + return tinyMCE.selectedInstance.getHTML(); - for (x=cn.length-1; x>=0; x--) - tinyMCE.insertAfter(cn[x], an[i]); - } - } -}; + return null; + }, -TinyMCE_Engine.prototype.getContent = function(editor_id) { - if (typeof(editor_id) != "undefined") - tinyMCE.getInstanceById(editor_id).select(); + _fixListElements : function(d) { + var nl, x, a = ['ol', 'ul'], i, n, p, r = new RegExp('^(OL|UL)$'), np; - if (tinyMCE.selectedInstance) - return tinyMCE.selectedInstance.getHTML(); + for (x=0; x<a.length; x++) { + nl = d.getElementsByTagName(a[x]); - return null; -}; + for (i=0; i<nl.length; i++) { + n = nl[i]; + p = n.parentNode; + + if (r.test(p.nodeName)) { + np = tinyMCE.prevNode(n, 'LI'); -TinyMCE_Engine.prototype._fixListElements = function(d) { - var nl, x, a = ['ol', 'ul'], i, n, p, r = new RegExp('^(OL|UL)$'), np; + if (!np) { + np = d.createElement('li'); + np.innerHTML = ' '; + np.appendChild(n); + p.insertBefore(np, p.firstChild); + } else + np.appendChild(n); + } + } + } + }, - for (x=0; x<a.length; x++) { - nl = d.getElementsByTagName(a[x]); + _fixTables : function(d) { + var nl, i, n, p, np, x, t; + nl = d.getElementsByTagName('table'); for (i=0; i<nl.length; i++) { n = nl[i]; - p = n.parentNode; - if (r.test(p.nodeName)) { - np = tinyMCE.prevNode(n, 'LI'); + if ((p = tinyMCE.getParentElement(n, 'p,h1,h2,h3,h4,h5,h6')) != null) { + np = p.cloneNode(false); + np.removeAttribute('id'); - if (!np) { - np = d.createElement('li'); - np.innerHTML = ' '; - np.appendChild(n); - p.insertBefore(np, p.firstChild); - } else + t = n; + + while ((n = n.nextSibling)) np.appendChild(n); + + tinyMCE.insertAfter(np, p); + tinyMCE.insertAfter(t, p); } } - } -}; + }, -TinyMCE_Engine.prototype._fixTables = function(d) { - var nl, i, n, p, np, x, t; + _cleanupHTML : function(inst, doc, config, elm, visual, on_save, on_submit, inn) { + var h, d, t1, t2, t3, t4, t5, c, s, nb; - nl = d.getElementsByTagName('table'); - for (i=0; i<nl.length; i++) { - n = nl[i]; + if (!tinyMCE.getParam('cleanup')) + return elm.innerHTML; - if ((p = tinyMCE.getParentElement(n, 'p,h1,h2,h3,h4,h5,h6')) != null) { - np = p.cloneNode(false); - np.removeAttribute('id'); + on_save = typeof(on_save) == 'undefined' ? false : on_save; - t = n; + c = inst.cleanup; + s = inst.settings; + d = c.settings.debug; - while ((n = n.nextSibling)) - np.appendChild(n); + if (d) + t1 = new Date().getTime(); - tinyMCE.insertAfter(np, p); - tinyMCE.insertAfter(t, p); - } - } -}; + inst._fixRootBlocks(); -TinyMCE_Engine.prototype._cleanupHTML = function(inst, doc, config, elm, visual, on_save, on_submit, inn) { - var h, d, t1, t2, t3, t4, t5, c, s, nb; - - if (!tinyMCE.getParam('cleanup')) - return elm.innerHTML; - - on_save = typeof(on_save) == 'undefined' ? false : on_save; - - c = inst.cleanup; - s = inst.settings; - d = c.settings.debug; - - if (d) - t1 = new Date().getTime(); - - if (tinyMCE.getParam("convert_fonts_to_spans")) - tinyMCE.convertFontsToSpans(doc); - - if (tinyMCE.getParam("fix_list_elements")) - tinyMCE._fixListElements(doc); - - if (tinyMCE.getParam("fix_table_elements")) - tinyMCE._fixTables(doc); - - // Call custom cleanup code - tinyMCE._customCleanup(inst, on_save ? "get_from_editor_dom" : "insert_to_editor_dom", doc.body); - - if (d) - t2 = new Date().getTime(); - - c.settings.on_save = on_save; - //for (var i=0; i<100; i++) - - c.idCount = 0; - c.serializationId++; - c.serializedNodes = new Array(); - c.sourceIndex = -1; - - if (s.cleanup_serializer == "xml") - h = c.serializeNodeAsXML(elm, inn); - else - h = c.serializeNodeAsHTML(elm, inn); - - if (d) - t3 = new Date().getTime(); - - // Post processing - nb = tinyMCE.getParam('entity_encoding') == 'numeric' ? ' ' : ' '; - h = h.replace(/<\/?(body|head|html)[^>]*>/gi, ''); - h = h.replace(new RegExp(' (rowspan="1"|colspan="1")', 'g'), ''); - h = h.replace(/<p><hr \/><\/p>/g, '<hr />'); - h = h.replace(/<p>( | )<\/p><hr \/><p>( | )<\/p>/g, '<hr />'); - h = h.replace(/<td>\s*<br \/>\s*<\/td>/g, '<td>' + nb + '</td>'); - h = h.replace(/<p>\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>'); - h = h.replace(/<br \/>$/, ''); // Remove last BR for Gecko - h = h.replace(/<br \/><\/p>/g, '</p>'); // Remove last BR in P tags for Gecko - h = h.replace(/<p>\s*( | )\s*<br \/>\s*( | )\s*<\/p>/g, '<p>' + nb + '</p>'); - h = h.replace(/<p>\s*( | )\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>'); - h = h.replace(/<p>\s*<br \/>\s* \s*<\/p>/g, '<p>' + nb + '</p>'); - h = h.replace(new RegExp('<a>(.*?)<\\/a>', 'g'), '$1'); - h = h.replace(/<p([^>]*)>\s*<\/p>/g, '<p$1>' + nb + '</p>'); - - // Clean body - if (/^\s*(<br \/>|<p> <\/p>|<p> <\/p>|<p><\/p>)\s*$/.test(h)) - h = ''; - - // If preformatted - if (s.preformatted) { - h = h.replace(/^<pre>/, ''); - h = h.replace(/<\/pre>$/, ''); - h = '<pre>' + h + '</pre>'; - } + if (tinyMCE.getParam("convert_fonts_to_spans")) + tinyMCE.convertFontsToSpans(doc); - // Gecko specific processing - if (tinyMCE.isGecko) { - h = h.replace(/<o:p _moz-userdefined="" \/>/g, ''); - h = h.replace(/<td([^>]*)>\s*<br \/>\s*<\/td>/g, '<td$1>' + nb + '</td>'); - } + if (tinyMCE.getParam("fix_list_elements")) + tinyMCE._fixListElements(doc); - if (s.force_br_newlines) - h = h.replace(/<p>( | )<\/p>/g, '<br />'); + if (tinyMCE.getParam("fix_table_elements")) + tinyMCE._fixTables(doc); - // Call custom cleanup code - h = tinyMCE._customCleanup(inst, on_save ? "get_from_editor" : "insert_to_editor", h); + // Call custom cleanup code + tinyMCE._customCleanup(inst, on_save ? "get_from_editor_dom" : "insert_to_editor_dom", doc.body); - // Remove internal classes - if (on_save) { - h = h.replace(new RegExp(' ?(mceItem[a-zA-Z0-9]*|' + s.visual_table_class + ')', 'g'), ''); - h = h.replace(new RegExp(' ?class=""', 'g'), ''); - } + if (d) + t2 = new Date().getTime(); - if (s.remove_linebreaks && !c.settings.indent) - h = h.replace(/\n|\r/g, ' '); + c.settings.on_save = on_save; - if (d) - t4 = new Date().getTime(); + c.idCount = 0; + c.serializationId = new Date().getTime().toString(32); // Unique ID needed for the content duplication bug + c.serializedNodes = []; + c.sourceIndex = -1; - if (on_save && c.settings.indent) - h = c.formatHTML(h); + if (s.cleanup_serializer == "xml") + h = c.serializeNodeAsXML(elm, inn); + else + h = c.serializeNodeAsHTML(elm, inn); + + if (d) + t3 = new Date().getTime(); + + // Post processing + nb = tinyMCE.getParam('entity_encoding') == 'numeric' ? ' ' : ' '; + h = h.replace(/<\/?(body|head|html)[^>]*>/gi, ''); + h = h.replace(new RegExp(' (rowspan="1"|colspan="1")', 'g'), ''); + h = h.replace(/<p><hr \/><\/p>/g, '<hr />'); + h = h.replace(/<p>( | )<\/p><hr \/><p>( | )<\/p>/g, '<hr />'); + h = h.replace(/<td>\s*<br \/>\s*<\/td>/g, '<td>' + nb + '</td>'); + h = h.replace(/<p>\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>'); + h = h.replace(/<br \/>$/, ''); // Remove last BR for Gecko + h = h.replace(/<br \/><\/p>/g, '</p>'); // Remove last BR in P tags for Gecko + h = h.replace(/<p>\s*( | )\s*<br \/>\s*( | )\s*<\/p>/g, '<p>' + nb + '</p>'); + h = h.replace(/<p>\s*( | )\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>'); + h = h.replace(/<p>\s*<br \/>\s* \s*<\/p>/g, '<p>' + nb + '</p>'); + h = h.replace(new RegExp('<a>(.*?)<\\/a>', 'g'), '$1'); + h = h.replace(/<p([^>]*)>\s*<\/p>/g, '<p$1>' + nb + '</p>'); + + // Clean body + if (/^\s*(<br \/>|<p> <\/p>|<p> <\/p>|<p><\/p>)\s*$/.test(h)) + h = ''; + + // If preformatted + if (s.preformatted) { + h = h.replace(/^<pre>/, ''); + h = h.replace(/<\/pre>$/, ''); + h = '<pre>' + h + '</pre>'; + } + + // Gecko specific processing + if (tinyMCE.isGecko) { + // Makes no sence but FF generates it!! + h = h.replace(/<br \/>\s*<\/li>/g, '</li>'); + h = h.replace(/ \s*<\/(dd|dt)>/g, '</$1>'); + h = h.replace(/<o:p _moz-userdefined="" \/>/g, ''); + h = h.replace(/<td([^>]*)>\s*<br \/>\s*<\/td>/g, '<td$1>' + nb + '</td>'); + } - // If encoding (not recommended option) - if (on_submit && (s.encoding == "xml" || s.encoding == "html")) - h = c.xmlEncode(h); + if (s.force_br_newlines) + h = h.replace(/<p>( | )<\/p>/g, '<br />'); - if (d) - t5 = new Date().getTime(); + // Call custom cleanup code + h = tinyMCE._customCleanup(inst, on_save ? "get_from_editor" : "insert_to_editor", h); - if (c.settings.debug) - tinyMCE.debug("Cleanup in ms: Pre=" + (t2-t1) + ", Serialize: " + (t3-t2) + ", Post: " + (t4-t3) + ", Format: " + (t5-t4) + ", Sum: " + (t5-t1) + "."); + // Remove internal classes + if (on_save) { + h = h.replace(new RegExp(' ?(mceItem[a-zA-Z0-9]*|' + s.visual_table_class + ')', 'g'), ''); + h = h.replace(new RegExp(' ?class=""', 'g'), ''); + } - return h; -}; + if (s.remove_linebreaks && !c.settings.indent) + h = h.replace(/\n|\r/g, ' '); + + if (d) + t4 = new Date().getTime(); + + if (on_save && c.settings.indent) + h = c.formatHTML(h); + + // If encoding (not recommended option) + if (on_submit && (s.encoding == "xml" || s.encoding == "html")) + h = c.xmlEncode(h); + + if (d) + t5 = new Date().getTime(); + + if (c.settings.debug) + tinyMCE.debug("Cleanup in ms: Pre=" + (t2-t1) + ", Serialize: " + (t3-t2) + ", Post: " + (t4-t3) + ", Format: " + (t5-t4) + ", Sum: " + (t5-t1) + "."); + + return h; + } +}); function TinyMCE_Cleanup() { this.isIE = (navigator.appName == "Microsoft Internet Explorer"); - this.rules = tinyMCE.clearArray(new Array()); + this.rules = tinyMCE.clearArray([]); // Default config this.settings = { @@ -4418,7 +4490,7 @@ function TinyMCE_Cleanup() { verify_html : false }; - this.vElements = tinyMCE.clearArray(new Array()); + this.vElements = tinyMCE.clearArray([]); this.vElementsRe = ''; this.closeElementsRe = /^(IMG|BR|HR|LINK|META|BASE|INPUT|AREA)$/; this.codeElementsRe = /^(SCRIPT|STYLE)$/; @@ -4448,7 +4520,7 @@ TinyMCE_Cleanup.prototype = { this.nlBeforeAfterRe = this._arrayToRe(s.newline_before_after_elements.split(','), 'gi', '<(\\/?)(', ')([^>]*)>'); this.serializedNodes = []; - if (s.invalid_elements != '') + if (s.invalid_elements !== '') this.iveRe = this._arrayToRe(s.invalid_elements.toUpperCase().split(','), 'g', '^(', ')$'); else this.iveRe = null; @@ -4469,19 +4541,17 @@ TinyMCE_Cleanup.prototype = { this.fillStr = s.entity_encoding == "named" ? " " : " "; this.idCount = 0; this.xmlEncodeRe = new RegExp('[\u007F-\uFFFF<>&"]', 'g'); - this.xmlEncodeAposRe = new RegExp('[\u007F-\uFFFF<>&"\']', 'g'); }, addRuleStr : function(s) { - var r = this.parseRuleStr(s); - var n; + var r = this.parseRuleStr(s), n; for (n in r) { if (r[n]) this.rules[n] = r[n]; } - this.vElements = tinyMCE.clearArray(new Array()); + this.vElements = tinyMCE.clearArray([]); for (n in this.rules) { if (this.rules[n]) @@ -4492,7 +4562,8 @@ TinyMCE_Cleanup.prototype = { }, isValid : function(n) { - this._setupRules(); // Will initialize cleanup rules + if (!this.rulesDone) + this._setupRules(); // Will initialize cleanup rules // Empty is true since it removes formatting if (!n) @@ -4548,9 +4619,9 @@ TinyMCE_Cleanup.prototype = { } r += ')$'; -//tinyMCE.debug(t + "=" + r); + if (this.childRules == null) - this.childRules = tinyMCE.clearArray(new Array()); + this.childRules = tinyMCE.clearArray([]); this.childRules[tn[y]] = new RegExp(r); @@ -4561,7 +4632,7 @@ TinyMCE_Cleanup.prototype = { }, parseRuleStr : function(s) { - var ta, p, r, a, i, x, px, t, tn, y, av, or = tinyMCE.clearArray(new Array()), dv; + var ta, p, r, a, i, x, px, t, tn, y, av, or = tinyMCE.clearArray([]), dv; if (s == null || s.length == 0) return or; @@ -4621,19 +4692,19 @@ TinyMCE_Cleanup.prototype = { if (av && av.length > 0) { if (av[0].charAt(0) == ':') { if (!r.forceAttribs) - r.forceAttribs = tinyMCE.clearArray(new Array()); + r.forceAttribs = tinyMCE.clearArray([]); r.forceAttribs[t.toLowerCase()] = av[0].substring(1); } else if (av[0].charAt(0) == '=') { if (!r.defaultAttribs) - r.defaultAttribs = tinyMCE.clearArray(new Array()); + r.defaultAttribs = tinyMCE.clearArray([]); dv = av[0].substring(1); - r.defaultAttribs[t.toLowerCase()] = dv == "" ? "mce_empty" : dv; + r.defaultAttribs[t.toLowerCase()] = dv == '' ? "mce_empty" : dv; } else if (av[0].charAt(0) == '<') { if (!r.validAttribValues) - r.validAttribValues = tinyMCE.clearArray(new Array()); + r.validAttribValues = tinyMCE.clearArray([]); r.validAttribValues[t.toLowerCase()] = this._arrayToRe(this.split('?', av[0].substring(1)), 'i'); } @@ -4656,7 +4727,7 @@ TinyMCE_Cleanup.prototype = { //tinyMCE.debug(r.tag, r.oTagName, r.vAttribsRe, r.vAttribsReWC); } else { r.vAttribsRe = ''; - r.vAttribs = tinyMCE.clearArray(new Array()); + r.vAttribs = tinyMCE.clearArray([]); r.vAttribsReIsWild = false; } @@ -4745,7 +4816,8 @@ TinyMCE_Cleanup.prototype = { serializeNodeAsHTML : function(n, inn) { var en, no, h = '', i, l, t, st, r, cn, va = false, f = false, at, hc, cr, nn; - this._setupRules(); // Will initialize cleanup rules + if (!this.rulesDone) + this._setupRules(); // Will initialize cleanup rules if (tinyMCE.isRealIE && this._isDuplicate(n)) return ''; @@ -4767,12 +4839,19 @@ TinyMCE_Cleanup.prototype = { if (st) break; - // MSIE sometimes produces <//tag> - if ((tinyMCE.isRealIE) && n.nodeName.indexOf('/') != -1) - break; - nn = n.nodeName; + if (tinyMCE.isRealIE) { + // MSIE sometimes produces <//tag> + if (n.nodeName.indexOf('/') != -1) + break; + + // MSIE has it's NS in a separate attrib + if (n.scopeName && n.scopeName != 'HTML') + nn = n.scopeName.toUpperCase() + ':' + nn.toUpperCase(); + } else if (tinyMCE.isOpera && nn.indexOf(':') > 0) + nn = nn.toUpperCase(); + // Convert fonts to spans if (this.settings.convert_fonts_to_spans) { // On get content FONT -> SPAN @@ -4959,25 +5038,26 @@ TinyMCE_Cleanup.prototype = { return o; }, - xmlEncode : function(s, skip_apos) { - var cl = this, re = !skip_apos ? this.xmlEncodeAposRe : this.xmlEncodeRe; + xmlEncode : function(s) { + var cl = this, re = this.xmlEncodeRe; - this._setupEntities(); // Will intialize lookup table + if (!this.entitiesDone) + this._setupEntities(); // Will intialize lookup table switch (this.settings.entity_encoding) { case "raw": - return tinyMCE.xmlEncode(s, skip_apos); + return tinyMCE.xmlEncode(s); case "named": - return s.replace(re, function (c, b) { - b = cl.entities[c.charCodeAt(0)]; + return s.replace(re, function (c) { + var b = cl.entities[c.charCodeAt(0)]; return b ? '&' + b + ';' : c; }); case "numeric": - return s.replace(re, function (c, b) { - return b ? '&#' + c.charCodeAt(0) + ';' : c; + return s.replace(re, function (c) { + return '&#' + c.charCodeAt(0) + ';'; }); } @@ -4985,11 +5065,10 @@ TinyMCE_Cleanup.prototype = { }, split : function(re, s) { - var c = s.split(re); - var i, l, o = new Array(); + var i, l, o = [], c = s.split(re); for (i=0, l=c.length; i<l; i++) { - if (c[i] != '') + if (c[i] !== '') o[i] = c[i]; } @@ -5038,6 +5117,10 @@ TinyMCE_Cleanup.prototype = { if (nn == "INPUT" && n == "maxlength" && v == "2147483647") v = ""; + + // Images + if (n == "width" || n == "height") + v = e.getAttribute(n, 2); } if (n == 'style' && v) { @@ -5047,10 +5130,10 @@ TinyMCE_Cleanup.prototype = { v = tinyMCE.serializeStyle(tinyMCE.parseStyle(v)); } - if (this.settings.on_save && n.indexOf('on') != -1 && this.settings.on_save && v && v != "") + if (this.settings.on_save && n.indexOf('on') != -1 && this.settings.on_save && v && v !== '') v = tinyMCE.cleanupEventStr(v); - return (v && v != "") ? '' + v : d; + return (v && v !== '') ? '' + v : d; }, _urlConverter : function(c, n, v) { @@ -5095,35 +5178,31 @@ TinyMCE_Cleanup.prototype = { var n, a, i, s = this.settings; // Setup entities - if (!this.entitiesDone) { - if (s.entity_encoding == "named") { - n = tinyMCE.clearArray(new Array()); - a = this.split(',', s.entities); - for (i=0; i<a.length; i+=2) - n[a[i]] = a[i+1]; - - this.entities = n; - } + if (s.entity_encoding == "named") { + n = tinyMCE.clearArray([]); + a = this.split(',', s.entities); + for (i=0; i<a.length; i+=2) + n[a[i]] = a[i+1]; - this.entitiesDone = true; + this.entities = n; } + + this.entitiesDone = true; }, _setupRules : function() { var s = this.settings; // Setup default rule - if (!this.rulesDone) { - this.addRuleStr(s.valid_elements); - this.addRuleStr(s.extended_valid_elements); - this.addChildRemoveRuleStr(s.valid_child_elements); + this.addRuleStr(s.valid_elements); + this.addRuleStr(s.extended_valid_elements); + this.addChildRemoveRuleStr(s.valid_child_elements); - this.rulesDone = true; - } + this.rulesDone = true; }, _isDuplicate : function(n) { - var i; + var i, l, sn; if (!this.settings.fix_content_duplication) return false; @@ -5135,13 +5214,15 @@ TinyMCE_Cleanup.prototype = { n.setAttribute('mce_serialized', this.serializationId); } else { + sn = this.serializedNodes; + // Search lookup table for text nodes and comments - for (i=0; i<this.serializedNodes.length; i++) { - if (this.serializedNodes[i] == n) + for (i=0, l = sn.length; i<l; i++) { + if (sn[i] == n) return true; } - this.serializedNodes[this.serializedNodes.length] = n; + sn.push(n); } return false; @@ -5151,1036 +5232,1055 @@ TinyMCE_Cleanup.prototype = { /* file:jscripts/tiny_mce/classes/TinyMCE_DOMUtils.class.js */ -TinyMCE_Engine.prototype.createTagHTML = function(tn, a, h) { - var o = '', f = tinyMCE.xmlEncode; +tinyMCE.add(TinyMCE_Engine, { + createTagHTML : function(tn, a, h) { + var o = '', f = tinyMCE.xmlEncode, n; - o = '<' + tn; + o = '<' + tn; - if (a) { - for (n in a) { - if (typeof(a[n]) != 'function' && a[n] != null) - o += ' ' + f(n) + '="' + f('' + a[n]) + '"'; + if (a) { + for (n in a) { + if (typeof(a[n]) != 'function' && a[n] != null) + o += ' ' + f(n) + '="' + f('' + a[n]) + '"'; + } } - } - o += !h ? ' />' : '>' + h + '</' + tn + '>'; + o += !h ? ' />' : '>' + h + '</' + tn + '>'; - return o; -}; + return o; + }, -TinyMCE_Engine.prototype.createTag = function(d, tn, a, h) { - var o = d.createElement(tn); + createTag : function(d, tn, a, h) { + var o = d.createElement(tn), n; - if (a) { - for (n in a) { - if (typeof(a[n]) != 'function' && a[n] != null) - tinyMCE.setAttrib(o, n, a[n]); + if (a) { + for (n in a) { + if (typeof(a[n]) != 'function' && a[n] != null) + tinyMCE.setAttrib(o, n, a[n]); + } } - } - - if (h) - o.innerHTML = h; - return o; -}; + if (h) + o.innerHTML = h; -TinyMCE_Engine.prototype.getElementByAttributeValue = function(n, e, a, v) { - return (n = this.getElementsByAttributeValue(n, e, a, v)).length == 0 ? null : n[0]; -}; + return o; + }, -TinyMCE_Engine.prototype.getElementsByAttributeValue = function(n, e, a, v) { - var i, nl = n.getElementsByTagName(e), o = new Array(); + getElementByAttributeValue : function(n, e, a, v) { + return (n = this.getElementsByAttributeValue(n, e, a, v)).length == 0 ? null : n[0]; + }, - for (i=0; i<nl.length; i++) { - if (tinyMCE.getAttrib(nl[i], a).indexOf(v) != -1) - o[o.length] = nl[i]; - } + getElementsByAttributeValue : function(n, e, a, v) { + var i, nl = n.getElementsByTagName(e), o = []; - return o; -}; + for (i=0; i<nl.length; i++) { + if (tinyMCE.getAttrib(nl[i], a).indexOf(v) != -1) + o[o.length] = nl[i]; + } -TinyMCE_Engine.prototype.isBlockElement = function(n) { - return n != null && n.nodeType == 1 && this.blockRegExp.test(n.nodeName); -}; + return o; + }, -TinyMCE_Engine.prototype.getParentBlockElement = function(n, r) { - return this.getParentNode(n, function(n) { - return tinyMCE.isBlockElement(n); - }, r); + isBlockElement : function(n) { + return n != null && n.nodeType == 1 && this.blockRegExp.test(n.nodeName); + }, - return null; -}; + getParentBlockElement : function(n, r) { + return this.getParentNode(n, function(n) { + return tinyMCE.isBlockElement(n); + }, r); -TinyMCE_Engine.prototype.insertAfter = function(n, r){ - if (r.nextSibling) - r.parentNode.insertBefore(n, r.nextSibling); - else - r.parentNode.appendChild(n); -}; + return null; + }, -TinyMCE_Engine.prototype.setInnerHTML = function(e, h) { - var i, nl, n; - - // Convert all strong/em to b/i in Gecko - if (tinyMCE.isGecko) { - 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>'); - } + insertAfter : function(n, r){ + if (r.nextSibling) + r.parentNode.insertBefore(n, r.nextSibling); + else + r.parentNode.appendChild(n); + }, - if (tinyMCE.isRealIE) { - // Since MSIE handles invalid HTML better that valid XHTML we - // need to make some things invalid. <hr /> gets converted to <hr>. - h = h.replace(/\s\/>/g, '>'); + setInnerHTML : function(e, h) { + var i, nl, n; - // Since MSIE auto generated emtpy P tags some times we must tell it to keep the real ones - h = h.replace(/<p([^>]*)>\u00A0?<\/p>/gi, '<p$1 mce_keep="true"> </p>'); // Keep empty paragraphs - h = h.replace(/<p([^>]*)>\s* \s*<\/p>/gi, '<p$1 mce_keep="true"> </p>'); // Keep empty paragraphs - h = h.replace(/<p([^>]*)>\s+<\/p>/gi, '<p$1 mce_keep="true"> </p>'); // Keep empty paragraphs + // Convert all strong/em to b/i in Gecko + if (tinyMCE.isGecko) { + 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>'); + } - // Remove first comment - e.innerHTML = tinyMCE.uniqueTag + h; - e.firstChild.removeNode(true); + if (tinyMCE.isRealIE) { + // Since MSIE handles invalid HTML better that valid XHTML we + // need to make some things invalid. <hr /> gets converted to <hr>. + h = h.replace(/\s\/>/g, '>'); + + // Since MSIE auto generated emtpy P tags some times we must tell it to keep the real ones + h = h.replace(/<p([^>]*)>\u00A0?<\/p>/gi, '<p$1 mce_keep="true"> </p>'); // Keep empty paragraphs + h = h.replace(/<p([^>]*)>\s* \s*<\/p>/gi, '<p$1 mce_keep="true"> </p>'); // Keep empty paragraphs + h = h.replace(/<p([^>]*)>\s+<\/p>/gi, '<p$1 mce_keep="true"> </p>'); // Keep empty paragraphs + + // Remove first comment + e.innerHTML = tinyMCE.uniqueTag + h; + e.firstChild.removeNode(true); + + // Remove weird auto generated empty paragraphs unless it's supposed to be there + nl = e.getElementsByTagName("p"); + for (i=nl.length-1; i>=0; i--) { + n = nl[i]; + + if (n.nodeName == 'P' && !n.hasChildNodes() && !n.mce_keep) + n.parentNode.removeChild(n); + } + } else { + h = this.fixGeckoBaseHREFBug(1, e, h); + e.innerHTML = h; + this.fixGeckoBaseHREFBug(2, e, h); + } + }, - // Remove weird auto generated empty paragraphs unless it's supposed to be there - nl = e.getElementsByTagName("p"); - for (i=nl.length-1; i>=0; i--) { - n = nl[i]; + getOuterHTML : function(e) { + var d; - if (n.nodeName == 'P' && !n.hasChildNodes() && !n.mce_keep) - n.parentNode.removeChild(n); - } - } else { - h = this.fixGeckoBaseHREFBug(1, e, h); - e.innerHTML = h; - this.fixGeckoBaseHREFBug(2, e, h); - } -}; + if (tinyMCE.isIE) + return e.outerHTML; -TinyMCE_Engine.prototype.getOuterHTML = function(e) { - if (tinyMCE.isIE) - return e.outerHTML; + d = e.ownerDocument.createElement("body"); + d.appendChild(e.cloneNode(true)); - var d = e.ownerDocument.createElement("body"); - d.appendChild(e.cloneNode(true)); - return d.innerHTML; -}; + return d.innerHTML; + }, -TinyMCE_Engine.prototype.setOuterHTML = function(e, h, d) { - var d = typeof(d) == "undefined" ? e.ownerDocument : d, i, nl, t; + setOuterHTML : function(e, h, d) { + var d = typeof(d) == "undefined" ? e.ownerDocument : d, i, nl, t; - if (tinyMCE.isIE && e.nodeType == 1) - e.outerHTML = h; - else { - t = d.createElement("body"); - t.innerHTML = h; + if (tinyMCE.isIE && e.nodeType == 1) + e.outerHTML = h; + else { + t = d.createElement("body"); + t.innerHTML = h; - for (i=0, nl=t.childNodes; i<nl.length; i++) - e.parentNode.insertBefore(nl[i].cloneNode(true), e); + for (i=0, nl=t.childNodes; i<nl.length; i++) + e.parentNode.insertBefore(nl[i].cloneNode(true), e); - e.parentNode.removeChild(e); - } -}; + e.parentNode.removeChild(e); + } + }, -TinyMCE_Engine.prototype._getElementById = function(id, d) { - var e, i, j, f; + _getElementById : function(id, d) { + var e, i, j, f; - if (typeof(d) == "undefined") - d = document; + if (typeof(d) == "undefined") + d = document; - e = d.getElementById(id); - if (!e) { - f = d.forms; + e = d.getElementById(id); + if (!e) { + f = d.forms; - for (i=0; i<f.length; i++) { - for (j=0; j<f[i].elements.length; j++) { - if (f[i].elements[j].name == id) { - e = f[i].elements[j]; - break; + for (i=0; i<f.length; i++) { + for (j=0; j<f[i].elements.length; j++) { + if (f[i].elements[j].name == id) { + e = f[i].elements[j]; + break; + } } } } - } - return e; -}; + return e; + }, -TinyMCE_Engine.prototype.getNodeTree = function(n, na, t, nn) { - return this.selectNodes(n, function(n) { - return (!t || n.nodeType == t) && (!nn || n.nodeName == nn); - }, na ? na : new Array()); -}; + getNodeTree : function(n, na, t, nn) { + return this.selectNodes(n, function(n) { + return (!t || n.nodeType == t) && (!nn || n.nodeName == nn); + }, na ? na : []); + }, -TinyMCE_Engine.prototype.getParentElement = function(n, na, f, r) { - var re = na ? new RegExp('^(' + na.toUpperCase().replace(/,/g, '|') + ')$') : 0, v; + getParentElement : function(n, na, f, r) { + var re = na ? new RegExp('^(' + na.toUpperCase().replace(/,/g, '|') + ')$') : 0, v; - // Compatiblity with old scripts where f param was a attribute string - if (f && typeof(f) == 'string') - return this.getParentElement(n, na, function(no) {return tinyMCE.getAttrib(no, f) != '';}); + // Compatiblity with old scripts where f param was a attribute string + if (f && typeof(f) == 'string') + return this.getParentElement(n, na, function(no) {return tinyMCE.getAttrib(no, f) !== '';}); - return this.getParentNode(n, function(n) { - return ((n.nodeType == 1 && !re) || (re && re.test(n.nodeName))) && (!f || f(n)); - }, r); -}; + return this.getParentNode(n, function(n) { + return ((n.nodeType == 1 && !re) || (re && re.test(n.nodeName))) && (!f || f(n)); + }, r); + }, -TinyMCE_Engine.prototype.getParentNode = function(n, f, r) { - while (n) { - if (n == r) - return null; + getParentNode : function(n, f, r) { + while (n) { + if (n == r) + return null; - if (f(n)) - return n; + if (f(n)) + return n; - n = n.parentNode; - } + n = n.parentNode; + } - return null; -}; + return null; + }, -TinyMCE_Engine.prototype.getAttrib = function(elm, name, dv) { - var v; + getAttrib : function(elm, name, dv) { + var v; - if (typeof(dv) == "undefined") - dv = ""; + if (typeof(dv) == "undefined") + dv = ""; - // Not a element - if (!elm || elm.nodeType != 1) - return dv; + // Not a element + if (!elm || elm.nodeType != 1) + return dv; - try { - v = elm.getAttribute(name, 0); - } catch (ex) { - // IE 7 may cast exception on invalid attributes - v = elm.getAttribute(name, 2); - } - - // Try className for class attrib - if (name == "class" && !v) - v = elm.className; + try { + v = elm.getAttribute(name, 0); + } catch (ex) { + // IE 7 may cast exception on invalid attributes + v = elm.getAttribute(name, 2); + } - // Workaround for a issue with Firefox 1.5rc2+ - if (tinyMCE.isGecko && name == "src" && elm.src != null && elm.src != "") - v = elm.src; + // Try className for class attrib + if (name == "class" && !v) + v = elm.className; - // Workaround for a issue with Firefox 1.5rc2+ - if (tinyMCE.isGecko && name == "href" && elm.href != null && elm.href != "") - v = elm.href; + // Workaround for a issue with Firefox 1.5rc2+ + if (tinyMCE.isGecko) { + if (name == "src" && elm.src != null && elm.src !== '') + v = elm.src; + + // Workaround for a issue with Firefox 1.5rc2+ + if (name == "href" && elm.href != null && elm.href !== '') + v = elm.href; + } else if (tinyMCE.isIE) { + switch (name) { + case "http-equiv": + v = elm.httpEquiv; + break; - if (name == "http-equiv" && tinyMCE.isIE) - v = elm.httpEquiv; + case "width": + case "height": + v = elm.getAttribute(name, 2); + break; + } + } - if (name == "style" && !tinyMCE.isOpera) - v = elm.style.cssText; + if (name == "style" && !tinyMCE.isOpera) + v = elm.style.cssText; - return (v && v != "") ? v : dv; -}; + return (v && v !== '') ? v : dv; + }, -TinyMCE_Engine.prototype.setAttrib = function(el, name, va, fix) { - if (typeof(va) == "number" && va != null) - va = "" + va; + setAttrib : function(el, name, va, fix) { + if (typeof(va) == "number" && va != null) + va = "" + va; - if (fix) { - if (va == null) - va = ""; + if (fix) { + if (va == null) + va = ""; - va = va.replace(/[^0-9%]/g, ''); - } + va = va.replace(/[^0-9%]/g, ''); + } - if (name == "style") - el.style.cssText = va; + if (name == "style") + el.style.cssText = va; - if (name == "class") - el.className = va; + if (name == "class") + el.className = va; - if (va != null && va != "" && va != -1) - el.setAttribute(name, va); - else - el.removeAttribute(name); -}; + if (va != null && va !== '' && va != -1) + el.setAttribute(name, va); + else + el.removeAttribute(name); + }, -TinyMCE_Engine.prototype.setStyleAttrib = function(e, n, v) { - e.style[n] = v; + setStyleAttrib : function(e, n, v) { + e.style[n] = v; - // Style attrib deleted in IE - if (tinyMCE.isIE && v == null || v == '') { - v = tinyMCE.serializeStyle(tinyMCE.parseStyle(e.style.cssText)); - e.style.cssText = v; - e.setAttribute("style", v); - } -}; + // Style attrib deleted in IE + if (tinyMCE.isIE && v == null || v == '') { + v = tinyMCE.serializeStyle(tinyMCE.parseStyle(e.style.cssText)); + e.style.cssText = v; + e.setAttribute("style", v); + } + }, -TinyMCE_Engine.prototype.switchClass = function(ei, c) { - var e; + switchClass : function(ei, c) { + var e; - if (tinyMCE.switchClassCache[ei]) - e = tinyMCE.switchClassCache[ei]; - else - e = tinyMCE.switchClassCache[ei] = document.getElementById(ei); + if (tinyMCE.switchClassCache[ei]) + e = tinyMCE.switchClassCache[ei]; + else + e = tinyMCE.switchClassCache[ei] = document.getElementById(ei); - if (e) { - // Keep tile mode - if (tinyMCE.settings.button_tile_map && e.className && e.className.indexOf('mceTiledButton') == 0) - c = 'mceTiledButton ' + c; + if (e) { + // Keep tile mode + if (tinyMCE.settings.button_tile_map && e.className && e.className.indexOf('mceTiledButton') == 0) + c = 'mceTiledButton ' + c; - e.className = c; - } -}; + e.className = c; + } + }, -TinyMCE_Engine.prototype.getAbsPosition = function(n, cn) { - var l = 0, t = 0; + getAbsPosition : function(n, cn) { + var l = 0, t = 0; - while (n && n != cn) { - l += n.offsetLeft; - t += n.offsetTop; - n = n.offsetParent; - } + while (n && n != cn) { + l += n.offsetLeft; + t += n.offsetTop; + n = n.offsetParent; + } - return {absLeft : l, absTop : t}; -}; + return {absLeft : l, absTop : t}; + }, -TinyMCE_Engine.prototype.prevNode = function(e, n) { - var a = n.split(','), i; + prevNode : function(e, n) { + var a = n.split(','), i; - while ((e = e.previousSibling) != null) { - for (i=0; i<a.length; i++) { - if (e.nodeName == a[i]) - return e; + while ((e = e.previousSibling) != null) { + for (i=0; i<a.length; i++) { + if (e.nodeName == a[i]) + return e; + } } - } - return null; -}; + return null; + }, -TinyMCE_Engine.prototype.nextNode = function(e, n) { - var a = n.split(','), i; + nextNode : function(e, n) { + var a = n.split(','), i; - while ((e = e.nextSibling) != null) { - for (i=0; i<a.length; i++) { - if (e.nodeName == a[i]) - return e; + while ((e = e.nextSibling) != null) { + for (i=0; i<a.length; i++) { + if (e.nodeName == a[i]) + return e; + } } - } - return null; -}; + return null; + }, -TinyMCE_Engine.prototype.selectElements = function(n, na, f) { - var i, a = [], nl, x; + selectElements : function(n, na, f) { + var i, a = [], nl, x; - for (x=0, na = na.split(','); x<na.length; x++) - for (i=0, nl = n.getElementsByTagName(na[x]); i<nl.length; i++) - (!f || f(nl[i])) && a.push(nl[i]); + for (x=0, na = na.split(','); x<na.length; x++) + for (i=0, nl = n.getElementsByTagName(na[x]); i<nl.length; i++) + (!f || f(nl[i])) && a.push(nl[i]); - return a; -}; + return a; + }, -TinyMCE_Engine.prototype.selectNodes = function(n, f, a) { - var i; + selectNodes : function(n, f, a) { + var i; - if (!a) - a = new Array(); + if (!a) + a = []; - if (f(n)) - a[a.length] = n; + if (f(n)) + a[a.length] = n; - if (n.hasChildNodes()) { - for (i=0; i<n.childNodes.length; i++) - tinyMCE.selectNodes(n.childNodes[i], f, a); - } + if (n.hasChildNodes()) { + for (i=0; i<n.childNodes.length; i++) + tinyMCE.selectNodes(n.childNodes[i], f, a); + } - return a; -}; + return a; + }, -TinyMCE_Engine.prototype.addCSSClass = function(e, c, b) { - var o = this.removeCSSClass(e, c); - return e.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c; -}; + addCSSClass : function(e, c, b) { + var o = this.removeCSSClass(e, c); + return e.className = b ? c + (o !== '' ? (' ' + o) : '') : (o !== '' ? (o + ' ') : '') + c; + }, -TinyMCE_Engine.prototype.removeCSSClass = function(e, c) { - c = e.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); - return e.className = c != ' ' ? c : ''; -}; + removeCSSClass : function(e, c) { + c = e.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); + return e.className = c != ' ' ? c : ''; + }, -TinyMCE_Engine.prototype.hasCSSClass = function(n, c) { - return new RegExp('\\b' + c + '\\b', 'g').test(n.className); -}; + hasCSSClass : function(n, c) { + return new RegExp('\\b' + c + '\\b', 'g').test(n.className); + }, -TinyMCE_Engine.prototype.renameElement = function(e, n, d) { - var ne, i, ar; + renameElement : function(e, n, d) { + var ne, i, ar; - d = typeof(d) == "undefined" ? tinyMCE.selectedInstance.getDoc() : d; + d = typeof(d) == "undefined" ? tinyMCE.selectedInstance.getDoc() : d; - if (e) { - ne = d.createElement(n); + if (e) { + ne = d.createElement(n); - ar = e.attributes; - for (i=ar.length-1; i>-1; i--) { - if (ar[i].specified && ar[i].nodeValue) - ne.setAttribute(ar[i].nodeName.toLowerCase(), ar[i].nodeValue); - } + ar = e.attributes; + for (i=ar.length-1; i>-1; i--) { + if (ar[i].specified && ar[i].nodeValue) + ne.setAttribute(ar[i].nodeName.toLowerCase(), ar[i].nodeValue); + } - ar = e.childNodes; - for (i=0; i<ar.length; i++) - ne.appendChild(ar[i].cloneNode(true)); + ar = e.childNodes; + for (i=0; i<ar.length; i++) + ne.appendChild(ar[i].cloneNode(true)); - e.parentNode.replaceChild(ne, e); - } -}; + e.parentNode.replaceChild(ne, e); + } + }, -TinyMCE_Engine.prototype.getViewPort = function(w) { - var d = w.document, m = d.compatMode == 'CSS1Compat', b = d.body, de = d.documentElement; + getViewPort : function(w) { + var d = w.document, m = d.compatMode == 'CSS1Compat', b = d.body, de = d.documentElement; - return { - left : w.pageXOffset || (m ? de.scrollLeft : b.scrollLeft), - top : w.pageYOffset || (m ? de.scrollTop : b.scrollTop), - width : w.innerWidth || (m ? de.clientWidth : b.clientWidth), - height : w.innerHeight || (m ? de.clientHeight : b.clientHeight) - }; -}; + return { + left : w.pageXOffset || (m ? de.scrollLeft : b.scrollLeft), + top : w.pageYOffset || (m ? de.scrollTop : b.scrollTop), + width : w.innerWidth || (m ? de.clientWidth : b.clientWidth), + height : w.innerHeight || (m ? de.clientHeight : b.clientHeight) + }; + }, -TinyMCE_Engine.prototype.getStyle = function(n, na, d) { - if (!n) - return false; + 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; + // 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(); - }); + // Camelcase it, if needed + na = na.replace(/-(\D)/g, function(a, b){ + return b.toUpperCase(); + }); - // IE & Opera - if (n.currentStyle) - return n.currentStyle[na]; + // IE & Opera + if (n.currentStyle) + return n.currentStyle[na]; - return false; -}; + return false; + } + + }); /* file:jscripts/tiny_mce/classes/TinyMCE_URL.class.js */ -TinyMCE_Engine.prototype.parseURL = function(url_str) { - var urlParts = new Array(); +tinyMCE.add(TinyMCE_Engine, { + parseURL : function(url_str) { + var urlParts = [], i, pos, lastPos, chr; - if (url_str) { - var pos, lastPos; + if (url_str) { + // Parse protocol part + pos = url_str.indexOf('://'); + if (pos != -1) { + urlParts.protocol = url_str.substring(0, pos); + lastPos = pos + 3; + } - // Parse protocol part - pos = url_str.indexOf('://'); - if (pos != -1) { - urlParts['protocol'] = url_str.substring(0, pos); - lastPos = pos + 3; - } + // Find port or path start + for (i=lastPos; i<url_str.length; i++) { + chr = url_str.charAt(i); - // Find port or path start - for (var i=lastPos; i<url_str.length; i++) { - var chr = url_str.charAt(i); + if (chr == ':') + break; - if (chr == ':') - break; + if (chr == '/') + break; + } + pos = i; - if (chr == '/') - break; - } - pos = i; + // Get host + urlParts.host = url_str.substring(lastPos, pos); - // Get host - urlParts['host'] = url_str.substring(lastPos, pos); + // Get port + urlParts.port = ""; + lastPos = pos; + if (url_str.charAt(pos) == ':') { + pos = url_str.indexOf('/', lastPos); + urlParts.port = url_str.substring(lastPos+1, pos); + } - // Get port - urlParts['port'] = ""; - lastPos = pos; - if (url_str.charAt(pos) == ':') { - pos = url_str.indexOf('/', lastPos); - urlParts['port'] = url_str.substring(lastPos+1, pos); - } + // Get path + lastPos = pos; + pos = url_str.indexOf('?', lastPos); - // Get path - lastPos = pos; - pos = url_str.indexOf('?', lastPos); + if (pos == -1) + pos = url_str.indexOf('#', lastPos); - if (pos == -1) - pos = url_str.indexOf('#', lastPos); + if (pos == -1) + pos = url_str.length; - if (pos == -1) - pos = url_str.length; + urlParts.path = url_str.substring(lastPos, pos); - urlParts['path'] = url_str.substring(lastPos, pos); + // Get query + lastPos = pos; + if (url_str.charAt(pos) == '?') { + pos = url_str.indexOf('#'); + pos = (pos == -1) ? url_str.length : pos; + urlParts.query = url_str.substring(lastPos+1, pos); + } - // Get query - lastPos = pos; - if (url_str.charAt(pos) == '?') { - pos = url_str.indexOf('#'); - pos = (pos == -1) ? url_str.length : pos; - urlParts['query'] = url_str.substring(lastPos+1, pos); + // Get anchor + lastPos = pos; + if (url_str.charAt(pos) == '#') { + pos = url_str.length; + urlParts.anchor = url_str.substring(lastPos+1, pos); + } } - // Get anchor - lastPos = pos; - if (url_str.charAt(pos) == '#') { - pos = url_str.length; - urlParts['anchor'] = url_str.substring(lastPos+1, pos); - } - } + return urlParts; + }, - return urlParts; -}; + serializeURL : function(up) { + var o = ""; + + if (up.protocol) + o += up.protocol + "://"; -TinyMCE_Engine.prototype.serializeURL = function(up) { - var o = ""; + if (up.host) + o += up.host; - if (up['protocol']) - o += up['protocol'] + "://"; + if (up.port) + o += ":" + up.port; - if (up['host']) - o += up['host']; + if (up.path) + o += up.path; - if (up['port']) - o += ":" + up['port']; + if (up.query) + o += "?" + up.query; - if (up['path']) - o += up['path']; + if (up.anchor) + o += "#" + up.anchor; - if (up['query']) - o += "?" + up['query']; + return o; + }, - if (up['anchor']) - o += "#" + up['anchor']; + convertAbsoluteURLToRelativeURL : function(base_url, url_to_relative) { + var baseURL = this.parseURL(base_url), targetURL = this.parseURL(url_to_relative); + var i, strTok1, strTok2, breakPoint = 0, outPath = "", forceSlash = false; + var fileName, pos; - return o; -}; + if (targetURL.path == '') + targetURL.path = "/"; + else + forceSlash = true; -TinyMCE_Engine.prototype.convertAbsoluteURLToRelativeURL = function(base_url, url_to_relative) { - var baseURL = this.parseURL(base_url); - var targetURL = this.parseURL(url_to_relative); - var strTok1; - var strTok2; - var breakPoint = 0; - var outPath = ""; - var forceSlash = false; - - if (targetURL.path == "") - targetURL.path = "/"; - else - forceSlash = true; - - // Crop away last path part - base_url = baseURL.path.substring(0, baseURL.path.lastIndexOf('/')); - strTok1 = base_url.split('/'); - strTok2 = targetURL.path.split('/'); - - if (strTok1.length >= strTok2.length) { - for (var i=0; i<strTok1.length; i++) { - if (i >= strTok2.length || strTok1[i] != strTok2[i]) { - breakPoint = i + 1; - break; + // Crop away last path part + base_url = baseURL.path.substring(0, baseURL.path.lastIndexOf('/')); + strTok1 = base_url.split('/'); + strTok2 = targetURL.path.split('/'); + + if (strTok1.length >= strTok2.length) { + for (i=0; i<strTok1.length; i++) { + if (i >= strTok2.length || strTok1[i] != strTok2[i]) { + breakPoint = i + 1; + break; + } } } - } - if (strTok1.length < strTok2.length) { - for (var i=0; i<strTok2.length; i++) { - if (i >= strTok1.length || strTok1[i] != strTok2[i]) { - breakPoint = i + 1; - break; + if (strTok1.length < strTok2.length) { + for (i=0; i<strTok2.length; i++) { + if (i >= strTok1.length || strTok1[i] != strTok2[i]) { + breakPoint = i + 1; + break; + } } } - } - if (breakPoint == 1) - return targetURL.path; + if (breakPoint == 1) + return targetURL.path; - for (var i=0; i<(strTok1.length-(breakPoint-1)); i++) - outPath += "../"; + for (i=0; i<(strTok1.length-(breakPoint-1)); i++) + outPath += "../"; - for (var i=breakPoint-1; i<strTok2.length; i++) { - if (i != (breakPoint-1)) - outPath += "/" + strTok2[i]; - else - outPath += strTok2[i]; - } + for (i=breakPoint-1; i<strTok2.length; i++) { + if (i != (breakPoint-1)) + outPath += "/" + strTok2[i]; + else + outPath += strTok2[i]; + } - targetURL.protocol = null; - targetURL.host = null; - targetURL.port = null; - targetURL.path = outPath == "" && forceSlash ? "/" : outPath; + targetURL.protocol = null; + targetURL.host = null; + targetURL.port = null; + targetURL.path = outPath == '' && forceSlash ? "/" : outPath; - // Remove document prefix from local anchors - var fileName = baseURL.path; - var pos; + // Remove document prefix from local anchors + fileName = baseURL.path; - if ((pos = fileName.lastIndexOf('/')) != -1) - fileName = fileName.substring(pos + 1); + if ((pos = fileName.lastIndexOf('/')) != -1) + fileName = fileName.substring(pos + 1); - // Is local anchor - if (fileName == targetURL.path && targetURL.anchor != "") - targetURL.path = ""; + // Is local anchor + if (fileName == targetURL.path && targetURL.anchor !== '') + targetURL.path = ""; - // If empty and not local anchor force filename or slash - if (targetURL.path == "" && !targetURL.anchor) - targetURL.path = fileName != "" ? fileName : "/"; + // If empty and not local anchor force filename or slash + if (targetURL.path == '' && !targetURL.anchor) + targetURL.path = fileName !== '' ? fileName : "/"; - return this.serializeURL(targetURL); -}; + return this.serializeURL(targetURL); + }, -TinyMCE_Engine.prototype.convertRelativeToAbsoluteURL = function(base_url, relative_url) { - var baseURL = this.parseURL(base_url), baseURLParts, relURLParts; - var relURL = this.parseURL(relative_url); + convertRelativeToAbsoluteURL : function(base_url, relative_url) { + var baseURL = this.parseURL(base_url), baseURLParts, relURLParts, newRelURLParts, numBack, relURL = this.parseURL(relative_url), i; + var len, absPath, start, end, newBaseURLParts; - if (relative_url == "" || relative_url.indexOf('://') != -1 || /^(mailto:|javascript:|#|\/)/.test(relative_url)) - return relative_url; + if (relative_url == '' || relative_url.indexOf('://') != -1 || /^(mailto:|javascript:|#|\/)/.test(relative_url)) + return relative_url; - // Split parts - baseURLParts = baseURL['path'].split('/'); - relURLParts = relURL['path'].split('/'); + // Split parts + baseURLParts = baseURL.path.split('/'); + relURLParts = relURL.path.split('/'); - // Remove empty chunks - var newBaseURLParts = new Array(); - for (var i=baseURLParts.length-1; i>=0; i--) { - if (baseURLParts[i].length == 0) - continue; + // Remove empty chunks + newBaseURLParts = []; + for (i=baseURLParts.length-1; i>=0; i--) { + if (baseURLParts[i].length == 0) + continue; - newBaseURLParts[newBaseURLParts.length] = baseURLParts[i]; - } - baseURLParts = newBaseURLParts.reverse(); + newBaseURLParts[newBaseURLParts.length] = baseURLParts[i]; + } + baseURLParts = newBaseURLParts.reverse(); - // Merge relURLParts chunks - var newRelURLParts = new Array(); - var numBack = 0; - for (var i=relURLParts.length-1; i>=0; i--) { - if (relURLParts[i].length == 0 || relURLParts[i] == ".") - continue; + // Merge relURLParts chunks + newRelURLParts = []; + numBack = 0; + for (i=relURLParts.length-1; i>=0; i--) { + if (relURLParts[i].length == 0 || relURLParts[i] == ".") + continue; - if (relURLParts[i] == '..') { - numBack++; - continue; - } + if (relURLParts[i] == '..') { + numBack++; + continue; + } - if (numBack > 0) { - numBack--; - continue; - } + if (numBack > 0) { + numBack--; + continue; + } - newRelURLParts[newRelURLParts.length] = relURLParts[i]; - } + newRelURLParts[newRelURLParts.length] = relURLParts[i]; + } - relURLParts = newRelURLParts.reverse(); + relURLParts = newRelURLParts.reverse(); - // Remove end from absolute path - var len = baseURLParts.length-numBack; - var absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/'); - var start = "", end = ""; + // Remove end from absolute path + len = baseURLParts.length-numBack; + absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/'); + start = ""; + end = ""; - // Build output URL - relURL.protocol = baseURL.protocol; - relURL.host = baseURL.host; - relURL.port = baseURL.port; + // Build output URL + relURL.protocol = baseURL.protocol; + relURL.host = baseURL.host; + relURL.port = baseURL.port; - // Re-add trailing slash if it's removed - if (relURL.path.charAt(relURL.path.length-1) == "/") - absPath += "/"; + // Re-add trailing slash if it's removed + if (relURL.path.charAt(relURL.path.length-1) == "/") + absPath += "/"; - relURL.path = absPath; + relURL.path = absPath; - return this.serializeURL(relURL); -}; + return this.serializeURL(relURL); + }, -TinyMCE_Engine.prototype.convertURL = function(url, node, on_save) { - var prot = document.location.protocol; - var host = document.location.hostname; - var port = document.location.port; + convertURL : function(url, node, on_save) { + var dl = document.location, start, portPart, urlParts, baseUrlParts, tmpUrlParts, curl; + var prot = dl.protocol, host = dl.hostname, port = dl.port; - // Pass through file protocol - if (prot == "file:") - return url; + // Pass through file protocol + if (prot == "file:") + return url; - // Something is wrong, remove weirdness - url = tinyMCE.regexpReplace(url, '(http|https):///', '/'); + // Something is wrong, remove weirdness + url = tinyMCE.regexpReplace(url, '(http|https):///', '/'); - // Mailto link or anchor (Pass through) - if (url.indexOf('mailto:') != -1 || url.indexOf('javascript:') != -1 || tinyMCE.regexpReplace(url,'[ \t\r\n\+]|%20','').charAt(0) == "#") - return url; + // Mailto link or anchor (Pass through) + if (url.indexOf('mailto:') != -1 || url.indexOf('javascript:') != -1 || /^[ \t\r\n\+]*[#\?]/.test(url)) + return url; - // Fix relative/Mozilla - if (!tinyMCE.isIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/') - return tinyMCE.settings['base_href'] + url; + // Fix relative/Mozilla + if (!tinyMCE.isIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/') + return tinyMCE.settings.base_href + url; - // Handle relative URLs - if (on_save && tinyMCE.getParam('relative_urls')) { - var curl = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url); - if (curl.charAt(0) == '/') - curl = tinyMCE.settings['document_base_prefix'] + curl; + // Handle relative URLs + if (on_save && tinyMCE.getParam('relative_urls')) { + curl = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, url); + if (curl.charAt(0) == '/') + curl = tinyMCE.settings.document_base_prefix + curl; - var urlParts = tinyMCE.parseURL(curl); - var tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings['document_base_url']); + urlParts = tinyMCE.parseURL(curl); + tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings.document_base_url); - // Force relative - if (urlParts['host'] == tmpUrlParts['host'] && (urlParts['port'] == tmpUrlParts['port'])) - return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings['document_base_url'], curl); - } + // Force relative + if (urlParts.host == tmpUrlParts.host && (urlParts.port == tmpUrlParts.port)) + return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings.document_base_url, curl); + } - // Handle absolute URLs - if (!tinyMCE.getParam('relative_urls')) { - var urlParts = tinyMCE.parseURL(url); - var baseUrlParts = tinyMCE.parseURL(tinyMCE.settings['base_href']); + // Handle absolute URLs + if (!tinyMCE.getParam('relative_urls')) { + urlParts = tinyMCE.parseURL(url); + baseUrlParts = tinyMCE.parseURL(tinyMCE.settings.base_href); - // Force absolute URLs from relative URLs - url = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url); + // Force absolute URLs from relative URLs + url = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, url); - // If anchor and path is the same page - if (urlParts['anchor'] && urlParts['path'] == baseUrlParts['path']) - return "#" + urlParts['anchor']; - } + // If anchor and path is the same page + if (urlParts.anchor && urlParts.path == baseUrlParts.path) + return "#" + urlParts.anchor; + } - // Remove current domain - if (tinyMCE.getParam('remove_script_host')) { - var start = "", portPart = ""; + // Remove current domain + if (tinyMCE.getParam('remove_script_host')) { + start = ""; + portPart = ""; - if (port != "") - portPart = ":" + port; + if (port !== '') + portPart = ":" + port; - start = prot + "//" + host + portPart + "/"; + start = prot + "//" + host + portPart + "/"; - if (url.indexOf(start) == 0) - url = url.substring(start.length-1); - } + if (url.indexOf(start) == 0) + url = url.substring(start.length-1); + } - return url; -}; + return url; + }, -TinyMCE_Engine.prototype.convertAllRelativeURLs = function(body) { - var i, elms, src, href, mhref, msrc; + convertAllRelativeURLs : function(body) { + var i, elms, src, href, mhref, msrc; - // Convert all image URL:s to absolute URL - elms = body.getElementsByTagName("img"); - for (i=0; i<elms.length; i++) { - src = tinyMCE.getAttrib(elms[i], 'src'); + // Convert all image URL:s to absolute URL + elms = body.getElementsByTagName("img"); + for (i=0; i<elms.length; i++) { + src = tinyMCE.getAttrib(elms[i], 'src'); - msrc = tinyMCE.getAttrib(elms[i], 'mce_src'); - if (msrc != "") - src = msrc; + msrc = tinyMCE.getAttrib(elms[i], 'mce_src'); + if (msrc !== '') + src = msrc; - if (src != "") { - src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src); - elms[i].setAttribute("src", src); + if (src !== '') { + src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, src); + elms[i].setAttribute("src", src); + } } - } - // Convert all link URL:s to absolute URL - elms = body.getElementsByTagName("a"); - for (i=0; i<elms.length; i++) { - href = tinyMCE.getAttrib(elms[i], 'href'); + // Convert all link URL:s to absolute URL + elms = body.getElementsByTagName("a"); + for (i=0; i<elms.length; i++) { + href = tinyMCE.getAttrib(elms[i], 'href'); - mhref = tinyMCE.getAttrib(elms[i], 'mce_href'); - if (mhref != "") - href = mhref; + mhref = tinyMCE.getAttrib(elms[i], 'mce_href'); + if (mhref !== '') + href = mhref; - if (href && href != "") { - href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], href); - elms[i].setAttribute("href", href); + if (href && href !== '') { + href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, href); + elms[i].setAttribute("href", href); + } } } -}; + + }); /* file:jscripts/tiny_mce/classes/TinyMCE_Array.class.js */ -TinyMCE_Engine.prototype.clearArray = function(a) { - var n; +tinyMCE.add(TinyMCE_Engine, { + clearArray : function(a) { + var n; - for (n in a) - a[n] = null; + for (n in a) + a[n] = null; - return a; -}; + return a; + }, -TinyMCE_Engine.prototype.explode = function(d, s) { - var ar = s.split(d), oar = new Array(), i; + explode : function(d, s) { + var ar = s.split(d), oar = [], i; - for (i = 0; i<ar.length; i++) { - if (ar[i] != "") - oar[oar.length] = ar[i]; - } + for (i = 0; i<ar.length; i++) { + if (ar[i] !== '') + oar[oar.length] = ar[i]; + } - return oar; -}; + return oar; + } +}); /* file:jscripts/tiny_mce/classes/TinyMCE_Event.class.js */ -TinyMCE_Engine.prototype._setEventsEnabled = function(node, state) { - var evs, x, y, elms, i, event; - var events = ['onfocus','onblur','onclick','ondblclick', - 'onmousedown','onmouseup','onmouseover','onmousemove', - 'onmouseout','onkeypress','onkeydown','onkeydown','onkeyup']; - - evs = tinyMCE.settings['event_elements'].split(','); - for (y=0; y<evs.length; y++){ - elms = node.getElementsByTagName(evs[y]); - for (i=0; i<elms.length; i++) { - event = ""; - - for (x=0; x<events.length; x++) { - if ((event = tinyMCE.getAttrib(elms[i], events[x])) != '') { - event = tinyMCE.cleanupEventStr("" + event); - - if (!state) - event = "return true;" + event; - else - event = event.replace(/^return true;/gi, ''); - - elms[i].removeAttribute(events[x]); - elms[i].setAttribute(events[x], event); +tinyMCE.add(TinyMCE_Engine, { + _setEventsEnabled : function(node, state) { + var evs, x, y, elms, i, event; + var events = ['onfocus','onblur','onclick','ondblclick', + 'onmousedown','onmouseup','onmouseover','onmousemove', + 'onmouseout','onkeypress','onkeydown','onkeydown','onkeyup']; + + evs = tinyMCE.settings.event_elements.split(','); + for (y=0; y<evs.length; y++){ + elms = node.getElementsByTagName(evs[y]); + for (i=0; i<elms.length; i++) { + event = ""; + + for (x=0; x<events.length; x++) { + if ((event = tinyMCE.getAttrib(elms[i], events[x])) !== '') { + event = tinyMCE.cleanupEventStr("" + event); + + if (!state) + event = "return true;" + event; + else + event = event.replace(/^return true;/gi, ''); + + elms[i].removeAttribute(events[x]); + elms[i].setAttribute(events[x], event); + } } } } - } -}; + }, -TinyMCE_Engine.prototype._eventPatch = function(editor_id) { - var n, inst, win, e; + _eventPatch : function(editor_id) { + var n, inst, win, e; - // Remove odd, error - if (typeof(tinyMCE) == "undefined") - return true; + // Remove odd, error + if (typeof(tinyMCE) == "undefined") + return true; - try { - // Try selected instance first - if (tinyMCE.selectedInstance) { - win = tinyMCE.selectedInstance.getWin(); + try { + // Try selected instance first + if (tinyMCE.selectedInstance) { + win = tinyMCE.selectedInstance.getWin(); - if (win && win.event) { - e = win.event; + if (win && win.event) { + e = win.event; - if (!e.target) - e.target = e.srcElement; + if (!e.target) + e.target = e.srcElement; - TinyMCE_Engine.prototype.handleEvent(e); - return; + TinyMCE_Engine.prototype.handleEvent(e); + return; + } } - } - // Search for it - for (n in tinyMCE.instances) { - inst = tinyMCE.instances[n]; + // Search for it + for (n in tinyMCE.instances) { + inst = tinyMCE.instances[n]; - if (!tinyMCE.isInstance(inst)) - continue; + if (!tinyMCE.isInstance(inst)) + continue; - inst.select(); - win = inst.getWin(); + inst.select(); + win = inst.getWin(); - if (win && win.event) { - e = win.event; + if (win && win.event) { + e = win.event; - if (!e.target) - e.target = e.srcElement; + if (!e.target) + e.target = e.srcElement; - TinyMCE_Engine.prototype.handleEvent(e); - return; + TinyMCE_Engine.prototype.handleEvent(e); + return; + } } + } catch (ex) { + // Ignore error if iframe is pointing to external URL } - } catch (ex) { - // Ignore error if iframe is pointing to external URL - } -}; + }, -TinyMCE_Engine.prototype.findEvent = function(e) { - var n, inst; + findEvent : function(e) { + var n, inst; - if (e) - return e; + if (e) + return e; - for (n in tinyMCE.instances) { - inst = tinyMCE.instances[n]; + for (n in tinyMCE.instances) { + inst = tinyMCE.instances[n]; - if (tinyMCE.isInstance(inst) && inst.getWin().event) - return inst.getWin().event; - } + if (tinyMCE.isInstance(inst) && inst.getWin().event) + return inst.getWin().event; + } - return null; -}; + return null; + }, -TinyMCE_Engine.prototype.unloadHandler = function() { - tinyMCE.triggerSave(true, true); -}; + unloadHandler : function() { + tinyMCE.triggerSave(true, true); + }, -TinyMCE_Engine.prototype.addEventHandlers = function(inst) { - this.setEventHandlers(inst, 1); -}; + addEventHandlers : function(inst) { + this.setEventHandlers(inst, 1); + }, -TinyMCE_Engine.prototype.setEventHandlers = function(inst, s) { - var doc = inst.getDoc(), ie, ot, i, f = s ? tinyMCE.addEvent : tinyMCE.removeEvent; + setEventHandlers : function(inst, s) { + var doc = inst.getDoc(), ie, ot, i, f = s ? tinyMCE.addEvent : tinyMCE.removeEvent; - ie = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'controlselect', 'dblclick']; - ot = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'focus', 'blur', 'dragdrop']; + ie = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'controlselect', 'dblclick']; + ot = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'focus', 'blur', 'dragdrop']; - inst.switchSettings(); + inst.switchSettings(); - if (tinyMCE.isIE) { - for (i=0; i<ie.length; i++) - f(doc, ie[i], TinyMCE_Engine.prototype._eventPatch); - } else { - for (i=0; i<ot.length; i++) - f(doc, ot[i], tinyMCE.handleEvent); + if (tinyMCE.isIE) { + for (i=0; i<ie.length; i++) + f(doc, ie[i], TinyMCE_Engine.prototype._eventPatch); + } else { + for (i=0; i<ot.length; i++) + f(doc, ot[i], tinyMCE.handleEvent); - // Force designmode - try { - doc.designMode = "On"; - } catch (e) { - // Ignore + // Force designmode + try { + doc.designMode = "On"; + } catch (e) { + // Ignore + } } - } -}; + }, -TinyMCE_Engine.prototype.onMouseMove = function() { - var inst, lh; + onMouseMove : function() { + var inst, lh; - // Fix for IE7 bug where it's not restoring hover on anchors correctly - if (tinyMCE.lastHover) { - lh = tinyMCE.lastHover; + // Fix for IE7 bug where it's not restoring hover on anchors correctly + if (tinyMCE.lastHover) { + lh = tinyMCE.lastHover; - // Call out on menus and refresh class on normal buttons - if (lh.className.indexOf('mceMenu') != -1) - tinyMCE._menuButtonEvent('out', lh); - else - lh.className = lh.className; + // Call out on menus and refresh class on normal buttons + if (lh.className.indexOf('mceMenu') != -1) + tinyMCE._menuButtonEvent('out', lh); + else + lh.className = lh.className; - tinyMCE.lastHover = null; - } + tinyMCE.lastHover = null; + } - if (!tinyMCE.hasMouseMoved) { - inst = tinyMCE.selectedInstance; + if (!tinyMCE.hasMouseMoved) { + inst = tinyMCE.selectedInstance; - // Workaround for bug #1437457 (Odd MSIE bug) - if (inst.isFocused) { - inst.undoBookmark = inst.selection.getBookmark(); - tinyMCE.hasMouseMoved = true; + // Workaround for bug #1437457 (Odd MSIE bug) + if (inst.isFocused) { + inst.undoBookmark = inst.selection.getBookmark(); + tinyMCE.hasMouseMoved = true; + } } - } -// tinyMCE.cancelEvent(inst.getWin().event); -// return false; -}; + // tinyMCE.cancelEvent(inst.getWin().event); + // return false; + }, -TinyMCE_Engine.prototype.cancelEvent = function(e) { - if (!e) - return false; + cancelEvent : function(e) { + if (!e) + return false; - if (tinyMCE.isIE) { - e.returnValue = false; - e.cancelBubble = true; - } else { - e.preventDefault(); - e.stopPropagation && e.stopPropagation(); - } + if (tinyMCE.isIE) { + e.returnValue = false; + e.cancelBubble = true; + } else { + e.preventDefault(); + e.stopPropagation && e.stopPropagation(); + } - return false; -}; + return false; + }, -TinyMCE_Engine.prototype.addEvent = function(o, n, h) { - // Add cleanup for all non unload events - if (n != 'unload') { - function clean() { - var ex; + addEvent : function(o, n, h) { + // Add cleanup for all non unload events + if (n != 'unload') { + function clean() { + var ex; - try { - tinyMCE.removeEvent(o, n, h); - tinyMCE.removeEvent(window, 'unload', clean); - o = n = h = null; - } catch (ex) { - // IE may produce access denied exception on unload + try { + tinyMCE.removeEvent(o, n, h); + tinyMCE.removeEvent(window, 'unload', clean); + o = n = h = null; + } catch (ex) { + // IE may produce access denied exception on unload + } } + + // Add memory cleaner + tinyMCE.addEvent(window, 'unload', clean); } - // Add memory cleaner - tinyMCE.addEvent(window, 'unload', clean); - } + if (o.attachEvent) + o.attachEvent("on" + n, h); + else + o.addEventListener(n, h, false); + }, - if (o.attachEvent) - o.attachEvent("on" + n, h); - else - o.addEventListener(n, h, false); -}; + removeEvent : function(o, n, h) { + if (o.detachEvent) + o.detachEvent("on" + n, h); + else + o.removeEventListener(n, h, false); + }, -TinyMCE_Engine.prototype.removeEvent = function(o, n, h) { - if (o.detachEvent) - o.detachEvent("on" + n, h); - else - o.removeEventListener(n, h, false); -}; + addSelectAccessibility : function(e, s, w) { + // Add event handlers + if (!s._isAccessible) { + s.onkeydown = tinyMCE.accessibleEventHandler; + s.onblur = tinyMCE.accessibleEventHandler; + s._isAccessible = true; + s._win = w; + } -TinyMCE_Engine.prototype.addSelectAccessibility = function(e, s, w) { - // Add event handlers - if (!s._isAccessible) { - s.onkeydown = tinyMCE.accessibleEventHandler; - s.onblur = tinyMCE.accessibleEventHandler; - s._isAccessible = true; - s._win = w; - } + return false; + }, - return false; -}; + accessibleEventHandler : function(e) { + var elm, win = this._win; -TinyMCE_Engine.prototype.accessibleEventHandler = function(e) { - var win = this._win; - e = tinyMCE.isIE ? win.event : e; - var elm = tinyMCE.isIE ? e.srcElement : e.target; + e = tinyMCE.isIE ? win.event : e; + elm = tinyMCE.isIE ? e.srcElement : e.target; - // Unpiggyback onchange on blur - if (e.type == "blur") { - if (elm.oldonchange) { - elm.onchange = elm.oldonchange; - elm.oldonchange = null; - } + // Unpiggyback onchange on blur + if (e.type == "blur") { + if (elm.oldonchange) { + elm.onchange = elm.oldonchange; + elm.oldonchange = null; + } - return true; - } + return true; + } - // Piggyback onchange - if (elm.nodeName == "SELECT" && !elm.oldonchange) { - elm.oldonchange = elm.onchange; - elm.onchange = null; - } + // Piggyback onchange + if (elm.nodeName == "SELECT" && !elm.oldonchange) { + elm.oldonchange = elm.onchange; + elm.onchange = null; + } - // Execute onchange and remove piggyback - if (e.keyCode == 13 || e.keyCode == 32) { - elm.onchange = elm.oldonchange; - elm.onchange(); - elm.oldonchange = null; + // Execute onchange and remove piggyback + if (e.keyCode == 13 || e.keyCode == 32) { + elm.onchange = elm.oldonchange; + elm.onchange(); + elm.oldonchange = null; - tinyMCE.cancelEvent(e); - return false; - } + tinyMCE.cancelEvent(e); + return false; + } - return true; -}; + return true; + }, -TinyMCE_Engine.prototype._resetIframeHeight = function() { - var ife; + _resetIframeHeight : function() { + var ife; - if (tinyMCE.isRealIE) { - ife = tinyMCE.selectedInstance.iframeElement; + if (tinyMCE.isRealIE) { + ife = tinyMCE.selectedInstance.iframeElement; -/* if (ife._oldWidth) { - ife.style.width = ife._oldWidth; - ife.width = ife._oldWidth; - }*/ + /* if (ife._oldWidth) { + ife.style.width = ife._oldWidth; + ife.width = ife._oldWidth; + }*/ - if (ife._oldHeight) { - ife.style.height = ife._oldHeight; - ife.height = ife._oldHeight; + if (ife._oldHeight) { + ife.style.height = ife._oldHeight; + ife.height = ife._oldHeight; + } } } -}; + + }); /* file:jscripts/tiny_mce/classes/TinyMCE_Selection.class.js */ @@ -6190,8 +6290,7 @@ function TinyMCE_Selection(inst) { TinyMCE_Selection.prototype = { getSelectedHTML : function() { - var inst = this.instance; - var e, r = this.getRng(), h; + var inst = this.instance, e, r = this.getRng(), h; if (!r) return null; @@ -6215,8 +6314,7 @@ TinyMCE_Selection.prototype = { }, getSelectedText : function() { - var inst = this.instance; - var d, r, s, t; + var inst = this.instance, d, r, s, t; if (tinyMCE.isIE) { d = inst.getDoc(); @@ -6239,19 +6337,17 @@ TinyMCE_Selection.prototype = { }, getBookmark : function(simple) { - var inst = this.instance; - var rng = this.getRng(); - var doc = inst.getDoc(), b = inst.getBody(); - var sp, le, s, e, nl, i, si, ei, w; + var inst = this.instance, rng = this.getRng(), doc = inst.getDoc(), b = inst.getBody(); var trng, sx, sy, xx = -999999999, vp = inst.getViewPort(); + var sp, le, s, e, nl, i, si, ei, w; sx = vp.left; sy = vp.top; - if (tinyMCE.isSafari || tinyMCE.isOpera || simple) + if (simple) return {rng : rng, scrollX : sx, scrollY : sy}; - if (tinyMCE.isIE) { + if (tinyMCE.isRealIE) { if (rng.item) { e = rng.item(0); @@ -6290,9 +6386,7 @@ TinyMCE_Selection.prototype = { scrollY : sy }; } - } - - if (tinyMCE.isGecko) { + } else { s = this.getSel(); e = this.getFocusElement(); @@ -6349,16 +6443,13 @@ TinyMCE_Selection.prototype = { }, moveToBookmark : function(bookmark) { - var inst = this.instance; - var rng, nl, i, ex, b = inst.getBody(), sd; - var doc = inst.getDoc(); - var win = inst.getWin(); - var sel = this.getSel(); + var inst = this.instance, rng, nl, i, ex, b = inst.getBody(), sd; + var doc = inst.getDoc(), win = inst.getWin(), sel = this.getSel(); if (!bookmark) return false; - if (tinyMCE.isSafari) { + if (tinyMCE.isSafari && bookmark.rng) { sel.setBaseAndExtent(bookmark.rng.startContainer, bookmark.rng.startOffset, bookmark.rng.endContainer, bookmark.rng.endOffset); return true; } @@ -6428,7 +6519,9 @@ TinyMCE_Selection.prototype = { rng.setEnd(sd.endNode, sd.endOffset); sel.removeAllRanges(); sel.addRange(rng); - win.focus(); + + if (!tinyMCE.isOpera) + win.focus(); } catch (ex) { // Ignore } @@ -6549,7 +6642,7 @@ TinyMCE_Selection.prototype = { if (select_text_node) { // Find first textnode in tree - nodes = tinyMCE.getNodeTree(node, new Array(), 3); + nodes = tinyMCE.getNodeTree(node, [], 3); if (nodes.length > 0) rng.selectNodeContents(nodes[0]); else @@ -6706,7 +6799,7 @@ TinyMCE_Selection.prototype = { function TinyMCE_UndoRedo(inst) { this.instance = inst; - this.undoLevels = new Array(); + this.undoLevels = []; this.undoIndex = 0; this.typingUndoIndex = -1; this.undoRedo = true; @@ -6732,10 +6825,13 @@ TinyMCE_UndoRedo.prototype = { if (this.undoLevels[this.undoIndex] && newHTML != this.undoLevels[this.undoIndex].content) { //tinyMCE.debug(newHTML, this.undoLevels[this.undoIndex].content); + // Is dirty again + inst.isNotDirty = false; + tinyMCE.dispatchCallback(inst, 'onchange_callback', 'onChange', inst); // Time to compress - customUndoLevels = tinyMCE.settings['custom_undo_redo_levels']; + customUndoLevels = tinyMCE.settings.custom_undo_redo_levels; if (customUndoLevels != -1 && this.undoLevels.length > customUndoLevels) { for (i=0; i<this.undoLevels.length-1; i++) this.undoLevels[i] = this.undoLevels[i+1]; @@ -6822,11 +6918,13 @@ var TinyMCE_ForceParagraphs = { var doc = inst.getDoc(), sel = inst.getSel(), body = inst.getBody(), win = inst.contentWindow, rng = sel.getRangeAt(0); var rootElm = doc.documentElement, blockName = "P", startNode, endNode, startBlock, endBlock; var rngBefore, rngAfter, direct, startNode, startOffset, endNode, endOffset, b = tinyMCE.isOpera ? inst.selection.getBookmark() : null; - var paraBefore, paraAfter, startChop, endChop, contents; + var paraBefore, paraAfter, startChop, endChop, contents, i; function isEmpty(para) { + var nodes; + function isEmptyHTML(html) { - return html.replace(new RegExp('[ \t\r\n]+', 'g'), '').toLowerCase() == ""; + return html.replace(new RegExp('[ \t\r\n]+', 'g'), '').toLowerCase() == ''; } // Check for images @@ -6842,8 +6940,8 @@ var TinyMCE_ForceParagraphs = { return false; // Check all textnodes - var nodes = tinyMCE.getNodeTree(para, new Array(), 3); - for (var i=0; i<nodes.length; i++) { + nodes = tinyMCE.getNodeTree(para, [], 3); + for (i=0; i<nodes.length; i++) { if (!isEmptyHTML(nodes[i].nodeValue)) return false; } @@ -6881,10 +6979,10 @@ var TinyMCE_ForceParagraphs = { endBlock = inst.getParentBlockElement(endNode); // If absolute force paragraph generation within - if (startBlock && new RegExp('absolute|relative|static', 'gi').test(startBlock.style.position)) + if (startBlock && (startBlock.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(startBlock.style.position))) startBlock = null; - if (endBlock && new RegExp('absolute|relative|static', 'gi').test(endBlock.style.position)) + if (endBlock && (endBlock.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(endBlock.style.position))) endBlock = null; // Use current block name @@ -6892,7 +6990,7 @@ var TinyMCE_ForceParagraphs = { blockName = startBlock.nodeName; // Use P instead - if (blockName == "TD" || blockName == "TABLE" || (blockName == "DIV" && new RegExp('left|right', 'gi').test(startBlock.style.cssFloat))) + if (/(TD|TABLE|TH|CAPTION)/.test(blockName) || (blockName == "DIV" && /left|right/gi.test(startBlock.style.cssFloat))) blockName = "P"; } @@ -7031,7 +7129,7 @@ var TinyMCE_ForceParagraphs = { if (contents.firstChild && contents.firstChild.nodeName == blockName) { /* var nodes = contents.firstChild.childNodes; - for (var i=0; i<nodes.length; i++) { + for (i=0; i<nodes.length; i++) { //tinyMCE.debug(nodes[i].nodeName); if (nodes[i].nodeName != "BODY") paraAfter.appendChild(nodes[i]); @@ -7126,13 +7224,9 @@ function TinyMCE_Layer(id, bm) { TinyMCE_Layer.prototype = { moveRelativeTo : function(re, p) { - var rep = this.getAbsPosition(re); - var w = parseInt(re.offsetWidth); - var h = parseInt(re.offsetHeight); - var e = this.getElement(); - var ew = parseInt(e.offsetWidth); - var eh = parseInt(e.offsetHeight); - var x, y; + var rep = this.getAbsPosition(re), e = this.getElement(), x, y; + var w = parseInt(re.offsetWidth), h = parseInt(re.offsetHeight); + var ew = parseInt(e.offsetWidth), eh = parseInt(e.offsetHeight); switch (p) { case "tl": @@ -7342,7 +7436,7 @@ function TinyMCE_Menu() { TinyMCE_Layer.call(this, id, true); this.id = id; - this.items = new Array(); + this.items = []; this.needsUpdate = true; }; @@ -7366,7 +7460,7 @@ TinyMCE_Menu.prototype = tinyMCE.extend(TinyMCE_Layer.prototype, { }, clear : function() { - this.items = new Array(); + this.items = []; }, addTitle : function(t) { @@ -7456,37 +7550,22 @@ TinyMCE_Menu.prototype = tinyMCE.extend(TinyMCE_Layer.prototype, { }); -/* file:jscripts/tiny_mce/classes/TinyMCE_Compatibility.class.js */ - -if (!Function.prototype.call) { - Function.prototype.call = function() { - var a = arguments, s = a[0], i, as = '', r, o; - - for (i=1; i<a.length; i++) - as += (i > 1 ? ',' : '') + 'a[' + i + ']'; - - o = s._fu; - s._fu = this; - r = eval('s._fu(' + as + ')'); - s._fu = o; - - return r; - }; -}; - /* file:jscripts/tiny_mce/classes/TinyMCE_Debug.class.js */ -TinyMCE_Engine.prototype.debug = function() { - var m = "", a, i, l = tinyMCE.log.length; +tinyMCE.add(TinyMCE_Engine, { + debug : function() { + var m = "", a, i, l = tinyMCE.log.length; + + for (i=0, a = this.debug.arguments; i<a.length; i++) { + m += a[i]; - for (i=0, a = this.debug.arguments; i<a.length; i++) { - m += a[i]; + if (i<a.length-1) + m += ', '; + } - if (i<a.length-1) - m += ', '; + if (l < 1000) + tinyMCE.log[l] = "[debug] " + m; } - if (l < 1000) - tinyMCE.log[l] = "[debug] " + m; -}; + }); diff --git a/wp-includes/js/tinymce/tiny_mce_config.php b/wp-includes/js/tinymce/tiny_mce_config.php index 5c2c1c8..22a194d 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,7 +48,7 @@ $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()); ?> diff --git a/wp-includes/js/tinymce/tiny_mce_popup.js b/wp-includes/js/tinymce/tiny_mce_popup.js index e6c91c3..acfca0a 100644 --- a/wp-includes/js/tinymce/tiny_mce_popup.js +++ b/wp-includes/js/tinymce/tiny_mce_popup.js @@ -31,7 +31,7 @@ TinyMCE_Popup.prototype = { init : function() { var win = window.opener ? window.opener : window.dialogArguments, c; - var inst; + var inst, re, title, divElm; if (!win) win = this.findWin(window); @@ -61,18 +61,18 @@ TinyMCE_Popup.prototype = { inst.selectionBookmark = inst.selection.getBookmark(true); // Setup dir - if (tinyMCELang['lang_dir']) - document.dir = tinyMCELang['lang_dir']; + if (tinyMCELang.lang_dir) + document.dir = tinyMCELang.lang_dir; // Setup title - var re = new RegExp('{|\\\$|}', 'g'); - var title = document.title.replace(re, ""); - if (typeof tinyMCELang[title] != "undefined") { - var divElm = document.createElement("div"); + re = new RegExp('{|\\\$|}', 'g'); + title = document.title.replace(re, ""); + if (typeof(tinyMCELang[title]) != "undefined") { + divElm = document.createElement("div"); divElm.innerHTML = tinyMCELang[title]; document.title = divElm.innerHTML; - if (tinyMCE.setWindowTitle != null) + if (typeof(tinyMCE.setWindowTitle) != 'undefined') tinyMCE.setWindowTitle(window, divElm.innerHTML); } @@ -98,7 +98,7 @@ TinyMCE_Popup.prototype = { if (tinyMCE.getWindowArg('mce_replacevariables', true)) body.innerHTML = tinyMCE.applyTemplate(body.innerHTML, tinyMCE.windowArgs); - dir = tinyMCE.selectedInstance.settings['directionality']; + dir = tinyMCE.selectedInstance.settings.directionality; if (dir == "rtl" && document.forms && document.forms.length > 0) { elms = document.forms[0].elements; for (i=0; i<elms.length; i++) { @@ -111,7 +111,7 @@ TinyMCE_Popup.prototype = { body.style.display = 'block'; // Execute real onload (Opera fix) - if (tinyMCEPopup.onLoadEval != "") + if (tinyMCEPopup.onLoadEval !== '') eval(tinyMCEPopup.onLoadEval); }, @@ -123,6 +123,8 @@ TinyMCE_Popup.prototype = { }, resizeToInnerSize : function() { + var i, doc, body, oldMargin, wrapper, iframe, nodes, dx, dy; + // Netscape 7.1 workaround if (this.isWindow && tinyMCE.isNS71) { window.resizeBy(0, 10); @@ -130,9 +132,8 @@ TinyMCE_Popup.prototype = { } if (this.isWindow) { - var doc = document; - var body = doc.body; - var oldMargin, wrapper, iframe, nodes, dx, dy; + doc = document; + body = doc.body; if (body.style.display == 'none') body.style.display = 'block'; @@ -149,7 +150,7 @@ TinyMCE_Popup.prototype = { // Wrap body elements nodes = doc.body.childNodes; - for (var i=nodes.length-1; i>=0; i--) { + for (i=nodes.length-1; i>=0; i--) { if (wrapper.hasChildNodes()) wrapper.insertBefore(nodes[i].cloneNode(true), wrapper.firstChild); else @@ -164,7 +165,7 @@ TinyMCE_Popup.prototype = { // Create iframe iframe = document.createElement("iframe"); iframe.id = "mcWinIframe"; - iframe.src = document.location.href.toLowerCase().indexOf('https') == -1 ? "about:blank" : tinyMCE.settings['default_document']; + iframe.src = document.location.href.toLowerCase().indexOf('https') == -1 ? "about:blank" : tinyMCE.settings.default_document; iframe.width = "100%"; iframe.height = "100%"; iframe.style.margin = '0'; @@ -191,6 +192,7 @@ TinyMCE_Popup.prototype = { resizeToContent : function() { var isMSIE = (navigator.appName == "Microsoft Internet Explorer"); var isOpera = (navigator.userAgent.indexOf("Opera") != -1); + var elm, width, height, x, y, dx, dy; if (isOpera) return; @@ -198,11 +200,11 @@ TinyMCE_Popup.prototype = { if (isMSIE) { try { window.resizeTo(10, 10); } catch (e) {} - var elm = document.body; - var width = elm.offsetWidth; - var height = elm.offsetHeight; - var dx = (elm.scrollWidth - width) + 4; - var dy = elm.scrollHeight - height; + elm = document.body; + width = elm.offsetWidth; + height = elm.offsetHeight; + dx = (elm.scrollWidth - width) + 4; + dy = elm.scrollHeight - height; try { window.resizeBy(dx, dy); } catch (e) {} } else { @@ -211,8 +213,8 @@ TinyMCE_Popup.prototype = { window.resizeBy(window.innerWidth * 2, window.innerHeight * 2); window.sizeToContent(); window.scrollTo(0, 0); - var x = parseInt(screen.width / 2.0) - (window.outerWidth / 2.0); - var y = parseInt(screen.height / 2.0) - (window.outerHeight / 2.0); + x = parseInt(screen.width / 2.0) - (window.outerWidth / 2.0); + y = parseInt(screen.height / 2.0) - (window.outerHeight / 2.0); window.moveTo(x, y); } } @@ -223,8 +225,10 @@ TinyMCE_Popup.prototype = { }, restoreSelection : function() { + var inst; + if (this.storeSelection) { - var inst = tinyMCE.selectedInstance; + inst = tinyMCE.selectedInstance; inst.getWin().focus(); @@ -272,9 +276,11 @@ TinyMCE_Popup.prototype = { }, importClass : function(c) { + var n; + window[c] = function() {}; - for (var n in window.opener[c].prototype) + for (n in window.opener[c].prototype) window[c].prototype[n] = window.opener[c].prototype[n]; window[c].constructor = window.opener[c].constructor; diff --git a/wp-includes/js/tinymce/wp-mce-help.php b/wp-includes/js/tinymce/wp-mce-help.php index 6d5f1e4..9bcdc5c 100644 --- a/wp-includes/js/tinymce/wp-mce-help.php +++ b/wp-includes/js/tinymce/wp-mce-help.php @@ -6,10 +6,7 @@ header('Content-Type: text/html; charset=' . get_bloginfo('charset')); <head> <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo get_option('blog_charset'); ?>" /> <title><?php _e('Rich Editor Help') ?></title> -<link rel="stylesheet" href="<?php echo get_option('siteurl') ?>/wp-admin/wp-admin.css?version=<?php bloginfo('version'); ?>" type="text/css" /> -<?php if ( ('rtl' == $wp_locale->text_direction) ) : ?> -<link rel="stylesheet" href="<?php echo get_option('siteurl') ?>/wp-admin/rtl.css?version=<?php bloginfo('version'); ?>" type="text/css" /> -<?php endif; ?> +<?php wp_admin_css(); ?> <style type="text/css"> #wphead { padding-top: 5px; @@ -93,7 +90,7 @@ header('Content-Type: text/html; charset=' . get_bloginfo('charset')); #keys .right { text-align: left; } td b { font-family: Tahoma, "Times New Roman", Times, serif } </style> -<?php endif; ?> +<?php endif; ?> <script type="text/javascript"> window.onkeydown = window.onkeypress = function (e) { e = e ? e : window.event; @@ -183,4 +180,3 @@ header('Content-Type: text/html; charset=' . get_bloginfo('charset')); </body> </html> - diff --git a/wp-includes/kses.php b/wp-includes/kses.php index 178071f..a6500e9 100644 --- a/wp-includes/kses.php +++ b/wp-includes/kses.php @@ -19,181 +19,181 @@ if (!defined('CUSTOM_TAGS')) // You can override this in your my-hacks.php file if (!CUSTOM_TAGS) { $allowedposttags = array( - 'address' => array(), + 'address' => array(), 'a' => array( - 'href' => array(), 'title' => array(), - 'rel' => array(), 'rev' => 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(), + ), + 'b' => array(), + 'big' => array(), 'blockquote' => array( - 'cite' => array(), 'xml:lang' => array(), + 'cite' => array(), 'xml:lang' => array(), 'lang' => array() - ), - 'br' => array(), + ), + 'br' => array(), 'button' => array( - 'disabled' => array(), 'name' => array(), + 'disabled' => array(), 'name' => array(), 'type' => array(), 'value' => array() - ), + ), 'caption' => array( 'align' => array() - ), - 'code' => array(), + ), + 'code' => array(), 'col' => array( - 'align' => array(), 'char' => array(), - 'charoff' => array(), 'span' => array(), + 'align' => array(), 'char' => array(), + 'charoff' => array(), 'span' => array(), 'valign' => array(), 'width' => array() - ), + ), 'del' => array( 'datetime' => array() - ), - 'dd' => array(), + ), + 'dd' => array(), 'div' => array( - 'align' => array(), 'xml:lang' => array(), + 'align' => array(), 'xml:lang' => array(), 'lang' => array() - ), - 'dl' => array(), - 'dt' => array(), - 'em' => array(), - 'fieldset' => array(), + ), + 'dl' => array(), + 'dt' => array(), + 'em' => array(), + 'fieldset' => array(), 'font' => array( - 'color' => array(), 'face' => array(), + 'color' => array(), 'face' => array(), 'size' => array() - ), + ), 'form' => array( - 'action' => array(), 'accept' => array(), - 'accept-charset' => array(), 'enctype' => array(), - 'method' => array(), 'name' => 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(), + 'align' => array(), 'noshade' => array(), 'size' => array(), 'width' => array() - ), - 'i' => array(), + ), + 'i' => array(), 'img' => array( - 'alt' => array(), 'align' => array(), - 'border' => array(), 'height' => array(), - 'hspace' => array(), 'longdesc' => array(), - 'vspace' => array(), 'src' => 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(), + ), + 'kbd' => array(), 'label' => array( 'for' => array() - ), + ), 'legend' => array( 'align' => array() - ), - 'li' => array(), + ), + 'li' => array(), 'p' => array( - 'align' => array(), 'xml:lang' => array(), + 'align' => array(), 'xml:lang' => array(), 'lang' => array() - ), + ), 'pre' => array( 'width' => array() - ), + ), 'q' => array( 'cite' => array() - ), - 's' => array(), - 'strike' => array(), - 'strong' => array(), - 'sub' => array(), - 'sup' => 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(), + 'align' => array(), 'bgcolor' => array(), + 'border' => array(), 'cellpadding' => array(), + 'cellspacing' => array(), 'rules' => array(), 'summary' => array(), 'width' => array() - ), + ), 'tbody' => array( - 'align' => array(), 'char' => 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(), + '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(), + 'cols' => array(), 'rows' => array(), + 'disabled' => array(), 'name' => array(), 'readonly' => array() - ), + ), 'tfoot' => array( - 'align' => array(), 'char' => 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(), + '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(), + 'align' => array(), 'char' => array(), 'charoff' => array(), 'valign' => array() - ), - 'title' => array(), + ), + 'title' => array(), 'tr' => array( - 'align' => array(), 'bgcolor' => array(), - 'char' => array(), 'charoff' => array(), + 'align' => array(), 'bgcolor' => array(), + 'char' => array(), 'charoff' => array(), 'valign' => array() - ), - 'tt' => array(), - 'u' => array(), - 'ul' => array(), - 'ol' => 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(), + ), + 'b' => array(), 'blockquote' => array( 'cite' => array() ), @@ -203,14 +203,14 @@ if (!CUSTOM_TAGS) { // 'dd' => array(), // 'dl' => array(), // 'dt' => array(), - 'em' => array(), + 'em' => array(), 'i' => array(), // 'ins' => array('datetime' => array(), 'cite' => array()), // 'li' => array(), // 'ol' => array(), // 'p' => array(), // 'q' => array(), - 'strike' => array(), + 'strike' => array(), 'strong' => array(), // 'sub' => array(), // 'sup' => array(), @@ -218,6 +218,7 @@ if (!CUSTOM_TAGS) { // '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 @@ -229,17 +230,17 @@ function wp_kses($string, $allowed_html, $allowed_protocols = array ('http', 'ht $string = wp_kses_no_null($string); $string = wp_kses_js_entities($string); $string = wp_kses_normalize_entities($string); - $string = wp_kses_hook($string); $allowed_html_fixed = wp_kses_array_lc($allowed_html); + $string = wp_kses_hook($string, $allowed_html_fixed, $allowed_protocols); // WP changed the order of these funcs and added args to wp_kses_hook return wp_kses_split($string, $allowed_html_fixed, $allowed_protocols); } # function wp_kses -function wp_kses_hook($string) +function wp_kses_hook($string, $allowed_html, $allowed_protocols) ############################################################################### # You add any kses hooks here. ############################################################################### { - $string = apply_filters('pre_kses', $string); + $string = apply_filters('pre_kses', $string, $allowed_html, $allowed_protocols); return $string; } # function wp_kses_hook @@ -285,21 +286,17 @@ function wp_kses_split2($string, $allowed_html, $allowed_protocols) } # Allow HTML comments - if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches)) { - wp_kses_reject(__('Seriously malformed HTML removed')); + if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches)) return ''; # It's seriously malformed - } $slash = trim($matches[1]); $elem = $matches[2]; $attrlist = $matches[3]; - if (!@isset($allowed_html[strtolower($elem)])) { - wp_kses_reject(sprintf(__('Removed <code><%1$s%2$s></code> tag'), $slash, $elem)); + if (!@isset($allowed_html[strtolower($elem)])) return ''; # They are using a not allowed HTML element - } if ($slash != '') return "<$slash$elem>"; @@ -308,43 +305,6 @@ function wp_kses_split2($string, $allowed_html, $allowed_protocols) return wp_kses_attr("$slash$elem", $attrlist, $allowed_html, $allowed_protocols); } # function wp_kses_split2 -$kses_messages = array(); -function wp_kses_reject($message) { - global $kses_messages; -return; // Disabled - if ( count($kses_messages) == 0 ) - add_action('save_post', 'wp_kses_save_message'); - - $kses_messages[] = $message; - - return ''; -} - -function wp_kses_save_message($id) { - global $kses_messages; - - foreach ( $kses_messages as $text ) - $message .= "$text\n"; - - $kses_messages[] = ""; - - update_option('kses_message', $message); -} - -function wp_kses_show_message() { - $message = get_option('kses_message'); - - if ( empty($message) ) - return; - - echo "<div class='updated fade'>\n"; - echo nl2br($message); - echo "</div>\n"; - - update_option('kses_message', ''); -} - - function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) ############################################################################### # This function removes all attributes, if none are allowed for this element. @@ -363,11 +323,8 @@ function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) # Are any attributes allowed at all for this element? - if (@ count($allowed_html[strtolower($element)]) == 0) { - if ( ! empty($attr) ) - wp_kses_reject(sprintf(__('All attributes removed from <%s> tag'), $element)); + if (@ count($allowed_html[strtolower($element)]) == 0) return "<$element$xhtml_slash>"; - } # Split it @@ -379,16 +336,12 @@ function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) $attr2 = ''; foreach ($attrarr as $arreach) { - if (!@ isset ($allowed_html[strtolower($element)][strtolower($arreach['name'])])) { - wp_kses_reject(sprintf(__('Attribute <code>%1$s</code> removed from <code><%2$s></code> tag'), $arreach['name'], $element)); + if (!@ isset ($allowed_html[strtolower($element)][strtolower($arreach['name'])])) continue; # the attribute is not allowed - } $current = $allowed_html[strtolower($element)][strtolower($arreach['name'])]; - if ($current == '') { - wp_kses_reject(sprintf(__('Attribute <code>%1$s</code> removed from <code><%2$s></code> tag'), $arreach['name'], $element)); + if ($current == '') continue; # the attribute is not allowed - } if (!is_array($current)) $attr2 .= ' '.$arreach['whole']; @@ -399,7 +352,6 @@ function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) $ok = true; foreach ($current as $currkey => $currval) if (!wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval)) { - wp_kses_reject(sprintf(__('Attribute <code>%1$s</code> removed from <code><%2$s></code> tag due to illegal value'), $arreach['name'], $element)); $ok = false; break; } @@ -765,8 +717,6 @@ function kses_init_filters() { add_filter('content_save_pre', 'wp_filter_post_kses'); add_filter('excerpt_save_pre', 'wp_filter_post_kses'); add_filter('content_filtered_save_pre', 'wp_filter_post_kses'); - add_filter('pre_comment_author', 'wp_filter_kses'); - add_action('admin_notices', 'wp_kses_show_message'); } function kses_remove_filters() { diff --git a/wp-includes/link-template.php b/wp-includes/link-template.php index 2a05f93..6a0677b 100644 --- a/wp-includes/link-template.php +++ b/wp-includes/link-template.php @@ -6,11 +6,6 @@ function the_permalink() { } -function permalink_link() { // For backwards compatibility - echo apply_filters('the_permalink', get_permalink()); -} - - /** * Conditionally adds a trailing slash if the permalink structure * has a trailing slash, strips the trailing slash if not @@ -64,6 +59,9 @@ function get_permalink($id = 0) { ); $post = &get_post($id); + + if ( empty($post->ID) ) return FALSE; + if ( $post->post_type == 'page' ) return get_page_link($post->ID); elseif ($post->post_type == 'attachment') @@ -71,16 +69,16 @@ function get_permalink($id = 0) { $permalink = get_option('permalink_structure'); - if ( '' != $permalink && 'draft' != $post->post_status ) { + if ( '' != $permalink && !in_array($post->post_status, array('draft', 'pending')) ) { $unixtime = strtotime($post->post_date); $category = ''; if (strpos($permalink, '%category%') !== false) { $cats = get_the_category($post->ID); if ( $cats ) - usort($cats, '_get_the_category_usort_by_ID'); // order by ID - $category = $cats[0]->category_nicename; - if ( $parent=$cats[0]->category_parent ) + usort($cats, '_usort_terms_by_ID'); // order by ID + $category = $cats[0]->slug; + if ( $parent=$cats[0]->parent ) $category = get_category_parents($parent, FALSE, '/', TRUE) . $category; } @@ -111,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); } @@ -169,7 +167,7 @@ function get_attachment_link($id = false) { else $parentlink = get_permalink( $object->post_parent ); if (strpos($parentlink, '?') === false) - $link = trim($parentlink, '/') . '/' . $object->post_name . '/'; + $link = trailingslashit($parentlink) . $object->post_name . '/'; } if (! $link ) { @@ -264,50 +262,95 @@ function get_post_comments_feed_link($post_id = '', $feed = 'rss2') { $post_id = (int) $id; if ( '' != get_option('permalink_structure') ) { - $url = trailingslashit( get_permalink() ) . 'feed'; + $url = trailingslashit( get_permalink($post_id) ) . 'feed'; if ( 'rss2' != $feed ) $url .= "/$feed"; $url = user_trailingslashit($url, 'single_feed'); } else { - $url = get_option('home') . "/?feed=$feed&p=$id"; + $type = get_post_field('post_type', $post_id); + if ( 'page' == $type ) + $url = get_option('home') . "/?feed=$feed&page_id=$post_id"; + else + $url = get_option('home') . "/?feed=$feed&p=$post_id"; } return apply_filters('post_comments_feed_link', $url); } -function edit_post_link($link = 'Edit This', $before = '', $after = '') { - global $post; +function get_edit_post_link( $id = 0 ) { + $post = &get_post( $id ); - if ( is_attachment() ) + 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'; + } - if( $post->post_type == 'page' ) { - if ( ! current_user_can('edit_page', $post->ID) ) + 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 ( $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) ) + 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 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; + } + + $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 $post, $comment; +function edit_comment_link( $link = 'Edit This', $before = '', $after = '' ) { + global $comment, $post; - if( $post->post_type == 'page' ){ - if ( ! current_user_can('edit_page', $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) ) + 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 @@ -315,18 +358,18 @@ function edit_comment_link($link = 'Edit This', $before = '', $after = '') { function get_previous_post($in_same_cat = false, $excluded_categories = '') { global $post, $wpdb; - if( !is_single() || is_attachment() ) + if( empty($post) || !is_single() || is_attachment() ) return null; $current_post_date = $post->post_date; $join = ''; if ( $in_same_cat ) { - $join = " INNER JOIN $wpdb->post2cat ON $wpdb->posts.ID= $wpdb->post2cat.post_id "; - $cat_array = get_the_category($post->ID); - $join .= ' AND (category_id = ' . intval($cat_array[0]->cat_ID); + $join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id "; + $cat_array = wp_get_object_terms($post->ID, 'category', 'fields=tt_ids'); + $join .= ' AND (tr.term_taxonomy_id = ' . intval($cat_array[0]); for ( $i = 1; $i < (count($cat_array)); $i++ ) { - $join .= ' OR category_id = ' . intval($cat_array[$i]->cat_ID); + $join .= ' OR tr.term_taxonomy_id = ' . intval($cat_array[$i]); } $join .= ')'; } @@ -334,36 +377,32 @@ function get_previous_post($in_same_cat = false, $excluded_categories = '') { $sql_exclude_cats = ''; if ( !empty($excluded_categories) ) { $blah = explode(' and ', $excluded_categories); - foreach ( $blah as $category ) { - $category = intval($category); - $sql_cat_ids = " OR pc.category_ID = '$category'"; - } - $posts_in_ex_cats = $wpdb->get_col("SELECT p.ID FROM $wpdb->posts p LEFT JOIN $wpdb->post2cat pc ON pc.post_id=p.ID WHERE 1 = 0 $sql_cat_ids GROUP BY p.ID"); - $posts_in_ex_cats_sql = 'AND ID NOT IN (' . implode($posts_in_ex_cats, ',') . ')'; + $posts_in_ex_cats = get_objects_in_term($blah, 'category'); + $posts_in_ex_cats_sql = 'AND p.ID NOT IN (' . implode($posts_in_ex_cats, ',') . ')'; } $join = apply_filters( 'get_previous_post_join', $join, $in_same_cat, $excluded_categories ); - $where = apply_filters( 'get_previous_post_where', "WHERE post_date < '$current_post_date' AND post_type = 'post' AND post_status = 'publish' $posts_in_ex_cats_sql", $in_same_cat, $excluded_categories ); - $sort = apply_filters( 'get_previous_post_sort', 'ORDER BY post_date DESC LIMIT 1' ); + $where = apply_filters( 'get_previous_post_where', "WHERE p.post_date < '$current_post_date' AND p.post_type = 'post' AND p.post_status = 'publish' $posts_in_ex_cats_sql", $in_same_cat, $excluded_categories ); + $sort = apply_filters( 'get_previous_post_sort', 'ORDER BY p.post_date DESC LIMIT 1' ); - return @$wpdb->get_row("SELECT ID, post_title FROM $wpdb->posts $join $where $sort"); + return @$wpdb->get_row("SELECT p.ID, p.post_title FROM $wpdb->posts AS p $join $where $sort"); } function get_next_post($in_same_cat = false, $excluded_categories = '') { global $post, $wpdb; - if( !is_single() || is_attachment() ) + if( empty($post) || !is_single() || is_attachment() ) return null; $current_post_date = $post->post_date; $join = ''; if ( $in_same_cat ) { - $join = " INNER JOIN $wpdb->post2cat ON $wpdb->posts.ID= $wpdb->post2cat.post_id "; - $cat_array = get_the_category($post->ID); - $join .= ' AND (category_id = ' . intval($cat_array[0]->cat_ID); + $join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id "; + $cat_array = wp_get_object_terms($post->ID, 'category', 'fields=tt_ids'); + $join .= ' AND (tr.term_taxonomy_id = ' . intval($cat_array[0]); for ( $i = 1; $i < (count($cat_array)); $i++ ) { - $join .= ' OR category_id = ' . intval($cat_array[$i]->cat_ID); + $join .= ' OR tr.term_taxonomy_id = ' . intval($cat_array[$i]); } $join .= ')'; } @@ -371,19 +410,15 @@ function get_next_post($in_same_cat = false, $excluded_categories = '') { $sql_exclude_cats = ''; if ( !empty($excluded_categories) ) { $blah = explode(' and ', $excluded_categories); - foreach ( $blah as $category ) { - $category = intval($category); - $sql_cat_ids = " OR pc.category_ID = '$category'"; - } - $posts_in_ex_cats = $wpdb->get_col("SELECT p.ID from $wpdb->posts p LEFT JOIN $wpdb->post2cat pc ON pc.post_id = p.ID WHERE 1 = 0 $sql_cat_ids GROUP BY p.ID"); - $posts_in_ex_cats_sql = 'AND ID NOT IN (' . implode($posts_in_ex_cats, ',') . ')'; + $posts_in_ex_cats = get_objects_in_term($blah, 'category'); + $posts_in_ex_cats_sql = 'AND p.ID NOT IN (' . implode($posts_in_ex_cats, ',') . ')'; } $join = apply_filters( 'get_next_post_join', $join, $in_same_cat, $excluded_categories ); - $where = apply_filters( 'get_next_post_where', "WHERE post_date > '$current_post_date' AND post_type = 'post' AND post_status = 'publish' $posts_in_ex_cats_sql AND ID != $post->ID", $in_same_cat, $excluded_categories ); - $sort = apply_filters( 'get_next_post_sort', 'ORDER BY post_date ASC LIMIT 1' ); + $where = apply_filters( 'get_next_post_where', "WHERE p.post_date > '$current_post_date' AND p.post_type = 'post' AND p.post_status = 'publish' $posts_in_ex_cats_sql AND p.ID != $post->ID", $in_same_cat, $excluded_categories ); + $sort = apply_filters( 'get_next_post_sort', 'ORDER BY p.post_date ASC LIMIT 1' ); - return @$wpdb->get_row("SELECT ID, post_title FROM $wpdb->posts $join $where $sort"); + return @$wpdb->get_row("SELECT p.ID, p.post_title FROM $wpdb->posts AS p $join $where $sort"); } @@ -397,7 +432,12 @@ function previous_post_link($format='« %link', $link='%title', $in_same_ca if ( !$post ) return; - $title = apply_filters('the_title', $post->post_title, $post); + $title = $post->post_title; + + if ( empty($post->post_title) ) + $title = __('Previous Post'); + + $title = apply_filters('the_title', $title, $post); $string = '<a href="'.get_permalink($post->ID).'">'; $link = str_replace('%title', $title, $link); $link = $pre . $string . $link . '</a>'; @@ -413,7 +453,12 @@ function next_post_link($format='%link »', $link='%title', $in_same_cat = if ( !$post ) return; - $title = apply_filters('the_title', $post->post_title, $post); + $title = $post->post_title; + + if ( empty($post->post_title) ) + $title = __('Next Post'); + + $title = apply_filters('the_title', $title, $post); $string = '<a href="'.get_permalink($post->ID).'">'; $link = str_replace('%title', $title, $link); $link = $string . $link . '</a>'; @@ -425,74 +470,53 @@ function next_post_link($format='%link »', $link='%title', $in_same_cat = function get_pagenum_link($pagenum = 1) { global $wp_rewrite; - $qstr = $_SERVER['REQUEST_URI']; + $pagenum = (int) $pagenum; - $page_querystring = "paged"; - $page_modstring = "page/"; - $page_modregex = "page/?"; - $permalink = 0; + $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 ( stripos( $qstr, $page_querystring ) !== false ) { - $replacement = "$page_querystring=$pagenum"; - $qstr = preg_replace("/".$page_querystring."[^\d]+\d+/", $replacement, $qstr); - // if we already have a mod_rewrite style page string - } 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() || is_admin() ) { + $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 ( stripos( $qstr, '?' ) !== false ) { - // so append the query string (using &, since we already have ?) - $qstr .= '&' . $page_querystring . '=' . $pagenum; - // otherwise, it could be rewritten, OR just the default index ... - } 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; + $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 = ''; } - } - $qstr = preg_replace('|^/+|', '', $qstr); - if ( $permalink ) - $qstr = user_trailingslashit($qstr, 'paged'); + $request = preg_replace( '|page/(.+)/?$|', '', $request); + $request = preg_replace( '|^index\.php|', '', $request); + $request = ltrim($request, '/'); - // 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 - } + $base = trailingslashit( get_bloginfo( 'url' ) ); + + if ( $wp_rewrite->using_index_permalinks() && ( $pagenum > 1 || '' != $request ) ) + $base .= 'index.php/'; - $qstr = preg_replace('/&([^#])(?![a-z]{1,8};)/', '&$1', trailingslashit( get_option('home') ) . $qstr ); + if ( $pagenum > 1 ) { + $request = ( ( !empty( $request ) ) ? trailingslashit( $request ) : $request ) . user_trailingslashit( 'page/' . $pagenum, 'paged' ); + } + + $result = $base . $request . $query_string; + } - 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..70f3b03 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 = _c('number_format_decimals|$decimals argument for http://php.net/number_format, default is 0'); + $this->number_format['decimals'] = ('number_format_decimals' == $trans) ? 0 : $trans; + + $trans = _c('number_format_decimal_point|$dec_point argument for http://php.net/number_format, default is .'); + $this->number_format['decimal_point'] = ('number_format_decimal_point' == $trans) ? '.' : $trans; + + $trans = _c('number_format_thousands_sep|$thousands_sep argument for http://php.net/number_format, default is ,'); + $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 3774f50..72a4be7 100644 --- a/wp-includes/pluggable.php +++ b/wp-includes/pluggable.php @@ -59,26 +59,33 @@ endif; if ( !function_exists('get_userdata') ) : function get_userdata( $user_id ) { - global $wpdb; + global $wpdb, $cache_userdata, $wpmuBaseTablePrefix; $user_id = (int) $user_id; if ( $user_id == 0 ) return false; $user = wp_cache_get($user_id, 'users'); - - if ( $user ) + $user_level = $wpmuBaseTablePrefix . $wpdb->blogid . '_user_level'; + if ( $user && is_site_admin( $user->user_login ) ) { + $user->$user_level = 10; + $user->user_level = 10; + $cap_key = $wpdb->prefix . 'capabilities'; + $user->{$cap_key} = array( 'administrator' => '1' ); return $user; + } elseif ( $user ) { + return $user; + } - if ( !$user = $wpdb->get_row("SELECT * FROM $wpdb->users WHERE ID = '$user_id' LIMIT 1") ) + if ( !$user = $wpdb->get_row("SELECT * FROM $wpdb->users WHERE ID = '$user_id'") ) return false; - $wpdb->hide_errors(); - $metavalues = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = '$user_id'"); - $wpdb->show_errors(); + $metavalues = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = '$user_id' /* pluggable get_userdata */"); if ($metavalues) { foreach ( $metavalues as $meta ) { - $value = maybe_unserialize($meta->meta_value); + @ $value = unserialize($meta->meta_value); + if ($value === FALSE) + $value = $meta->meta_value; $user->{$meta->meta_key} = $value; // We need to set user_level from meta, not row @@ -87,16 +94,15 @@ function get_userdata( $user_id ) { } // end foreach } //end if - // For backwards compat. - if ( isset($user->first_name) ) - $user->user_firstname = $user->first_name; - if ( isset($user->last_name) ) - $user->user_lastname = $user->last_name; - if ( isset($user->description) ) - $user->user_description = $user->description; + if( is_site_admin( $user->user_login ) == true ) { + $user->user_level = 10; + $cap_key = $wpdb->prefix . 'capabilities'; + $user->{$cap_key} = array( 'administrator' => '1' ); + } wp_cache_add($user_id, $user, 'users'); - wp_cache_add($user->user_login, $user_id, 'userlogins'); + wp_cache_add($user->user_login, $user, 'userlogins'); + return $user; } endif; @@ -115,111 +121,165 @@ function get_userdatabylogin($user_login) { if ( empty( $user_login ) ) return false; - $user_id = wp_cache_get($user_login, 'userlogins'); - $userdata = wp_cache_get($user_id, 'users'); + $userdata = wp_cache_get($user_login, 'userlogins'); if ( $userdata ) return $userdata; $user_login = $wpdb->escape($user_login); - if ( !$user = $wpdb->get_row("SELECT * FROM $wpdb->users WHERE user_login = '$user_login'") ) + if ( !$user_ID = $wpdb->get_var("SELECT ID FROM $wpdb->users WHERE user_login = '$user_login'") ) return false; - $wpdb->hide_errors(); - $metavalues = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = '$user->ID'"); - $wpdb->show_errors(); - - if ($metavalues) { - foreach ( $metavalues as $meta ) { - $value = maybe_unserialize($meta->meta_value); - $user->{$meta->meta_key} = $value; - - // We need to set user_level from meta, not row - if ( $wpdb->prefix . 'user_level' == $meta->meta_key ) - $user->user_level = $meta->meta_value; - } - } - - // For backwards compat. - if ( isset($user->first_name) ) - $user->user_firstname = $user->first_name; - if ( isset($user->last_name) ) - $user->user_lastname = $user->last_name; - if ( isset($user->description) ) - $user->user_description = $user->description; - + $user = get_userdata($user_ID); if( is_site_admin( $user_login ) == true ) { $user->user_level = 10; $cap_key = $wpdb->prefix . 'capabilities'; $user->{$cap_key} = array( 'administrator' => '1' ); } - - wp_cache_add($user->ID, $user, 'users'); - wp_cache_add($user->user_login, $user->ID, 'userlogins'); return $user; - } endif; if ( !function_exists( 'wp_mail' ) ) : -function wp_mail($to, $subject, $message, $headers = '') { +function wp_mail( $to, $subject, $message, $headers = '' ) { + // Compact the input, apply the filters, and extract them back out + extract( apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers' ) ) ); + global $phpmailer; - if ( !is_object( $phpmailer ) ) { - require_once(ABSPATH . WPINC . '/class-phpmailer.php'); - require_once(ABSPATH . WPINC . '/class-smtp.php'); + // (Re)create it, if it's gone missing + if ( !is_object( $phpmailer ) || !is_a( $phpmailer, 'PHPMailer' ) ) { + require_once ABSPATH . WPINC . '/class-phpmailer.php'; + require_once ABSPATH . WPINC . '/class-smtp.php'; $phpmailer = new PHPMailer(); } - $mail = compact('to', 'subject', 'message', 'headers'); - $mail = apply_filters('wp_mail', $mail); - extract($mail, EXTR_SKIP); - - if ( $headers == '' ) { - $headers = "MIME-Version: 1.0\n" . - "From: " . apply_filters('wp_mail_from', get_option('admin_email') ) . "\n" . - "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n"; + // Headers + if ( empty( $headers ) ) { + $headers = array(); + } elseif ( !is_array( $headers ) ) { + // Explode the headers out, so this function can take both + // string headers and an array of headers. + $tempheaders = (array) explode( "\n", $headers ); + $headers = array(); + + // If it's actually got contents + if ( !empty( $tempheaders ) ) { + // Iterate through the raw headers + foreach ( $tempheaders as $header ) { + if ( strpos($header, ':') === false ) + continue; + // Explode them out + list( $name, $content ) = explode( ':', trim( $header ), 2 ); + + // Cleanup crew + $name = trim( $name ); + $content = trim( $content ); + + // Mainly for legacy -- process a From: header if it's there + if ( 'from' == strtolower($name) ) { + if ( strpos($content, '<' ) !== false ) { + // So... making my life hard again? + $from_name = substr( $content, 0, strpos( $content, '<' ) - 1 ); + $from_name = str_replace( '"', '', $from_name ); + $from_name = trim( $from_name ); + + $from_email = substr( $content, strpos( $content, '<' ) + 1 ); + $from_email = str_replace( '>', '', $from_email ); + $from_email = trim( $from_email ); + } else { + $from_name = trim( $content ); + } + } elseif ( 'content-type' == strtolower($name) ) { + if ( strpos( $content,';' ) !== false ) { + list( $type, $charset ) = explode( ';', $content ); + $content_type = trim( $type ); + $charset = trim( str_replace( array( 'charset=', '"' ), '', $charset ) ); + } else { + $content_type = trim( $content ); + } + } else { + // Add it to our grand headers array + $headers[trim( $name )] = trim( $content ); + } + } + } } + // Empty out the values that may be set $phpmailer->ClearAddresses(); - $phpmailer->ClearCCs(); - $phpmailer->ClearBCCs(); - $phpmailer->ClearReplyTos(); $phpmailer->ClearAllRecipients(); + $phpmailer->ClearAttachments(); + $phpmailer->ClearBCCs(); + $phpmailer->ClearCCs(); $phpmailer->ClearCustomHeaders(); + $phpmailer->ClearReplyTos(); - $phpmailer->FromName = "WordPress"; - $phpmailer->AddAddress("$to", ""); + // From email and name + // If we don't have a name from the input headers + if ( !isset( $from_name ) ) { + $from_name = 'WordPress'; + } + + // If we don't have an email from the input headers + if ( !isset( $from_email ) ) { + // Get the site domain and get rid of www. + $sitename = strtolower( $_SERVER['SERVER_NAME'] ); + if ( substr( $sitename, 0, 4 ) == 'www.' ) { + $sitename = substr( $sitename, 4 ); + } + + $from_email = 'wordpress@' . $sitename; + } + + // Set the from name and email + $phpmailer->From = apply_filters( 'wp_mail_from', $from_email ); + $phpmailer->FromName = apply_filters( 'wp_mail_from_name', $from_name ); + + // Set destination address + $phpmailer->AddAddress( $to ); + + // Set mail's subject and body $phpmailer->Subject = $subject; - $phpmailer->Body = $message; - $phpmailer->IsHTML(false); - $phpmailer->IsMail(); // set mailer to use php mail() - - do_action_ref_array('phpmailer_init', array(&$phpmailer)); - - $mailheaders = (array) explode( "\n", $headers ); - foreach ( $mailheaders as $line ) { - $header = explode( ":", $line ); - switch ( trim( $header[0] ) ) { - case "From": - $from = trim( str_replace( '"', '', $header[1] ) ); - if ( strpos( $from, '<' ) ) { - $phpmailer->FromName = str_replace( '"', '', substr( $header[1], 0, strpos( $header[1], '<' ) - 1 ) ); - $from = trim( substr( $from, strpos( $from, '<' ) + 1 ) ); - $from = str_replace( '>', '', $from ); - } else { - $phpmailer->FromName = $from; - } - $phpmailer->From = trim( $from ); - break; - default: - if ( $line != '' && $header[0] != 'MIME-Version' && $header[0] != 'Content-Type' ) - $phpmailer->AddCustomHeader( $line ); - break; + $phpmailer->Body = $message; + + // Set to use PHP's mail() + $phpmailer->IsMail(); + + // Set Content-Type and charset + // If we don't have a content-type from the input headers + if ( !isset( $content_type ) ) { + $content_type = 'text/plain'; + } + + $content_type = apply_filters( 'wp_mail_content_type', $content_type ); + + // Set whether it's plaintext or not, depending on $content_type + if ( $content_type == 'text/html' ) { + $phpmailer->IsHTML( true ); + } else { + $phpmailer->IsHTML( false ); + } + + // If we don't have a charset from the input headers + if ( !isset( $charset ) ) { + $charset = get_bloginfo( 'charset' ); + } + + // Set the content-type and charset + $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset ); + + // Set custom headers + if ( !empty( $headers ) ) { + foreach ( $headers as $name => $content ) { + $phpmailer->AddCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) ); } } + do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) ); + + // Send! $result = @$phpmailer->Send(); return $result; @@ -228,7 +288,7 @@ endif; if ( !function_exists('wp_login') ) : function wp_login($username, $password, $already_md5 = false) { - global $wpdb, $error; + global $wpdb, $error, $current_user; $username = sanitize_user($username); @@ -240,19 +300,46 @@ function wp_login($username, $password, $already_md5 = false) { return false; } + if ($current_user->data->user_login == $username) + return true; + $login = get_userdatabylogin($username); - //$login = $wpdb->get_row("SELECT ID, user_login, user_pass FROM $wpdb->users WHERE user_login = '$username'"); if (!$login) { - $error = __('<strong>ERROR</strong>: Invalid username.'); + if( is_site_admin( $username ) ) { + unset( $login ); + $userdetails = get_userdatabylogin( $username ); + $login->user_login = $username; + $login->user_pass = $userdetails->user_pass; + } else { + $admins = get_admin_users_for_domain(); + reset( $admins ); + while( list( $key, $val ) = each( $admins ) ) { + if( $val[ 'user_login' ] == $username ) { + unset( $login ); + $login->user_login = $username; + $login->user_pass = $val[ 'user_pass' ]; + } + } + } + } + if (!$login) { + $error = __('<strong>Error</strong>: Wrong username.'); return false; } else { + if( is_site_admin( $username ) == false && ( $primary_blog = get_usermeta( $login->ID, "primary_blog" ) ) ) { + $details = get_blog_details( $primary_blog ); + if( is_object( $details ) && $details->archived == 1 || $details->spam == 1 || $details->deleted == 1 ) { + $error = __('<strong>Error</strong>: Blog suspended.'); + return false; + } + } // If the password is already_md5, it has been double hashed. // Otherwise, it is plain text. - if ( ($already_md5 && md5($login->user_pass) == $password) || ($login->user_login == $username && $login->user_pass == md5($password)) ) { + if ( ($already_md5 && $login->user_login == $username && md5($login->user_pass) == $password) || ($login->user_login == $username && $login->user_pass == md5($password)) ) { return true; } else { - $error = __('<strong>ERROR</strong>: Incorrect password.'); + $error = __('<strong>Error</strong>: Incorrect password.'); $pwd = ''; return false; } @@ -300,6 +387,12 @@ function check_admin_referer($action = -1) { if ( !function_exists('check_ajax_referer') ) : function check_ajax_referer() { + $current_name = ''; + if ( ( $current = wp_get_current_user() ) && $current->ID ) + $current_name = $current->data->user_login; + if ( !$current_name ) + die('-1'); + $cookie = explode('; ', urldecode(empty($_POST['cookie']) ? $_GET['cookie'] : $_POST['cookie'])); // AJAX scripts must pass cookie=document.cookie foreach ( $cookie as $tasty ) { if ( false !== strpos($tasty, USER_COOKIE) ) @@ -307,7 +400,8 @@ function check_ajax_referer() { if ( false !== strpos($tasty, PASS_COOKIE) ) $pass = substr(strstr($tasty, '='), 1); } - if ( !wp_login( $user, $pass, true ) ) + + if ( $current_name != $user || !wp_login( $user, $pass, true ) ) die('-1'); do_action('check_ajax_referer'); } @@ -322,8 +416,26 @@ function wp_redirect($location, $status = 302) { $location = apply_filters('wp_redirect', $location, $status); if ( !$location ) // allows the wp_redirect filter to cancel a redirect - return false; + return false; + + $location = wp_sanitize_redirect($location); + + if ( $is_IIS ) { + header("Refresh: 0;url=$location"); + } else { + if ( php_sapi_name() != 'cgi-fcgi' ) + status_header($status); // This causes problems on IIS and some FastCGI setups + header("Location: $location"); + } +} +endif; +if ( !function_exists('wp_sanitize_redirect') ) : +/** + * sanitizes a URL for use in a redirect + * @return string redirect-sanitized URL + **/ +function wp_sanitize_redirect($location) { $location = preg_replace('|[^a-z0-9-~+_.?#=&;,/:%]|i', '', $location); $location = wp_kses_no_null($location); @@ -339,14 +451,33 @@ function wp_redirect($location, $status = 302) { } } } + return $location; +} +endif; - if ( $is_IIS ) { - header("Refresh: 0;url=$location"); - } else { - if ( php_sapi_name() != 'cgi-fcgi' ) - status_header($status); // This causes problems on IIS and some FastCGI setups - header("Location: $location"); - } +if ( !function_exists('wp_safe_redirect') ) : +/** + * performs a safe (local) redirect, using wp_redirect() + * @return void + **/ +function wp_safe_redirect($location, $status = 302) { + + // Need to look at the URL the way it will end up in wp_redirect() + $location = wp_sanitize_redirect($location); + + // browsers will assume 'http' is your protocol, and will obey a redirect to a URL starting with '//' + if ( substr($location, 0, 2) == '//' ) + $location = 'http:' . $location; + + $lp = parse_url($location); + $wpp = parse_url(get_option('home')); + + $allowed_hosts = (array) apply_filters('allowed_redirect_hosts', array($wpp['host']), $lp['host']); + + if ( isset($lp['host']) && !in_array($lp['host'], $allowed_hosts) ) + $location = get_option('siteurl') . '/wp-admin/'; + + wp_redirect($location, $status); } endif; @@ -458,8 +589,7 @@ function wp_notify_postauthor($comment_id, $comment_type='') { $reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>"; } - $message_headers = "MIME-Version: 1.0\n" - . "$from\n" + $message_headers = "$from\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n"; if ( isset($reply_to) ) @@ -470,7 +600,7 @@ function wp_notify_postauthor($comment_id, $comment_type='') { $message_headers = apply_filters('comment_notification_headers', $message_headers, $comment_id); @wp_mail($user->user_email, $subject, $notify_message, $message_headers); - + return true; } endif; @@ -485,8 +615,8 @@ function wp_notify_moderator($comment_id) { global $wpdb; if( get_option( "moderation_notify" ) == 0 ) - return true; - + return true; + $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID='$comment_id' LIMIT 1"); $post = $wpdb->get_row("SELECT * FROM $wpdb->posts WHERE ID='$comment->comment_post_ID' LIMIT 1"); diff --git a/wp-includes/plugin.php b/wp-includes/plugin.php index 050c544..2c04c1c 100644 --- a/wp-includes/plugin.php +++ b/wp-includes/plugin.php @@ -2,12 +2,12 @@ /** * 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 + * 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. + * 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. @@ -19,14 +19,16 @@ function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) 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][_wp_filter_build_unique_id($tag, $function_to_add, $priority)] = array('function' => $function_to_add, 'accepted_args' => $accepted_args); + $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority); + $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $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 @@ -57,16 +59,16 @@ function apply_filters($tag, $string) { $string = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args'])); } - } while ( next($wp_filter[$tag]) ); + } while ( next($wp_filter[$tag]) !== false ); 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 + * + * 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. @@ -85,10 +87,10 @@ function merge_filters($tag) { } /** - * 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 + * 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. @@ -97,26 +99,28 @@ function merge_filters($tag) { * @return boolean Whether the function is removed. */ function remove_filter($tag, $function_to_remove, $priority = 10, $accepted_args = 1) { - global $wp_filter, $merged_filters; - - unset($GLOBALS['wp_filter'][$tag][$priority][_wp_filter_build_unique_id($tag, $function_to_remove, $priority)]); - unset( $merged_filters[ $tag ] ); + $function_to_remove = _wp_filter_build_unique_id($tag, $function_to_remove, $priority); - return true; + $r = isset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]); + + unset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]); + unset($GLOBALS['merged_filters'][$tag]); + + return $r; } /** * Hooks a function on to a specific action. - * - * Actions are the hooks that the WordPress core launches at specific points + * + * 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 + * 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. + * @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) { @@ -125,13 +129,13 @@ function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) /** * 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. + * @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; @@ -159,7 +163,7 @@ function do_action($tag, $arg = '') { if ( !is_null($the_['function']) ) call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); - } while ( next($wp_filter[$tag]) ); + } while ( next($wp_filter[$tag]) !== false ); } @@ -179,8 +183,8 @@ function did_action($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 + * + * 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> @@ -203,15 +207,15 @@ function do_action_ref_array($tag, $args) { if ( !is_null($the_['function']) ) call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); - } while ( next($wp_filter[$tag]) ); + } while ( next($wp_filter[$tag]) !== false ); } /** - * 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 + * 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. @@ -220,7 +224,7 @@ function do_action_ref_array($tag, $args) { * @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); } // @@ -229,7 +233,7 @@ function remove_action($tag, $function_to_remove, $priority = 10, $accepted_args /** * 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. @@ -243,14 +247,14 @@ function plugin_basename($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 + * 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. @@ -262,14 +266,14 @@ function register_activation_hook($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 + * 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. @@ -282,8 +286,9 @@ function register_deactivation_hook($file, $function) { function _wp_filter_build_unique_id($tag, $function, $priority = 10) { global $wp_filter; - + // If function then just skip all of the tests and not overwrite the following. + // Static Calling if( is_string($function) ) return $function; // Object Class Calling @@ -299,7 +304,6 @@ function _wp_filter_build_unique_id($tag, $function, $priority = 10) $obj_idx .= $function[0]->wp_filter_id; return $obj_idx; } - // Static Calling else if( is_string($function[0]) ) return $function[0].$function[1]; } diff --git a/wp-includes/post-template.php b/wp-includes/post-template.php index f294914..a956dc4 100644 --- a/wp-includes/post-template.php +++ b/wp-includes/post-template.php @@ -18,17 +18,39 @@ function get_the_ID() { function the_title($before = '', $after = '', $echo = true) { $title = get_the_title(); - if ( strlen($title) > 0 ) { - $title = apply_filters('the_title', $before . $title . $after, $before, $after); - if ( $echo ) - echo $title; - else - return $title; - } + + if ( strlen($title) == 0 ) + return; + + $title = $before . $title . $after; + + if ( $echo ) + echo $title; + else + return $title; } +function the_title_attribute( $args = '' ) { + $title = get_the_title(); + + if ( strlen($title) == 0 ) + return; + + $defaults = array('before' => '', 'after' => '', 'echo' => true); + $r = wp_parse_args($args, $defaults); + extract( $r, EXTR_SKIP ); + + + $title = $before . $title . $after; + $title = attribute_escape(strip_tags($title)); -function get_the_title($id = 0) { + if ( $echo ) + echo $title; + else + return $title; +} + +function get_the_title( $id = 0 ) { $post = &get_post($id); $title = $post->post_title; @@ -37,7 +59,7 @@ function get_the_title($id = 0) { else if ( 'private' == $post->post_status ) $title = sprintf(__('Private: %s'), $title); - return $title; + return apply_filters( 'the_title', $title ); } function the_guid( $id = 0 ) { @@ -115,7 +137,7 @@ function the_excerpt() { } -function get_the_excerpt($fakeit = true) { +function get_the_excerpt($deprecated = true) { global $id, $post; $output = ''; $output = $post->post_excerpt; @@ -129,21 +151,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 = '') { - global $post; + $defaults = array( + 'before' => '<p>' . __('Pages:'), 'after' => '</p>', + 'next_or_number' => 'number', 'nextpagelink' => __('Next page'), + 'previouspagelink' => __('Previous page'), 'pagelink' => '%', + 'more_file' => '', 'echo' => 1 + ); - 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, EXTR_SKIP); + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); - global $id, $page, $numpages, $multipage, $more, $pagenow; + global $post, $id, $page, $numpages, $multipage, $more, $pagenow; if ( $more_file != '' ) $file = $more_file; else @@ -160,7 +184,7 @@ function wp_link_pages($args = '') { if ( 1 == $i ) { $output .= '<a href="' . get_permalink() . '">'; } else { - if ( '' == get_option('permalink_structure') || 'draft' == $post->post_status ) + if ( '' == get_option('permalink_structure') || in_array($post->post_status, array('draft', 'pending')) ) $output .= '<a href="' . get_permalink() . '&page=' . $i . '">'; else $output .= '<a href="' . trailingslashit(get_permalink()) . user_trailingslashit($i, 'single_paged') . '">'; @@ -179,7 +203,7 @@ function wp_link_pages($args = '') { if ( 1 == $i ) { $output .= '<a href="' . get_permalink() . '">' . $previouspagelink . '</a>'; } else { - if ( '' == get_option('permalink_structure') || 'draft' == $post->post_status ) + if ( '' == get_option('permalink_structure') || in_array($post->post_status, array('draft', 'pending')) ) $output .= '<a href="' . get_permalink() . '&page=' . $i . '">' . $previouspagelink . '</a>'; else $output .= '<a href="' . trailingslashit(get_permalink()) . user_trailingslashit($i, 'single_paged') . '">' . $previouspagelink . '</a>'; @@ -190,7 +214,7 @@ function wp_link_pages($args = '') { if ( 1 == $i ) { $output .= '<a href="' . get_permalink() . '">' . $nextpagelink . '</a>'; } else { - if ( '' == get_option('permalink_structure') || 'draft' == $post->post_status ) + if ( '' == get_option('permalink_structure') || in_array($post->post_status, array('draft', 'pending')) ) $output .= '<a href="' . get_permalink() . '&page=' . $i . '">' . $nextpagelink . '</a>'; else $output .= '<a href="' . trailingslashit(get_permalink()) . user_trailingslashit($i, 'single_paged') . '">' . $nextpagelink . '</a>'; @@ -247,15 +271,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' => '' + ); - $defaults = array('depth' => 0, 'child_of' => 0, 'selected' => 0, 'echo' => 1, - 'name' => 'page_id', 'show_option_none' => ''); - $r = array_merge($defaults, $r); - extract($r, EXTR_SKIP); + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); $pages = get_pages($r); $output = ''; @@ -277,14 +300,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, EXTR_SKIP ); $output = ''; $current_page = 0; diff --git a/wp-includes/post.php b/wp-includes/post.php index db0472d..f23ba32 100644 --- a/wp-includes/post.php +++ b/wp-includes/post.php @@ -28,22 +28,24 @@ 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); + } + } 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 + ); - $defaults = array('numberposts' => -1, 'post_type' => '', 'post_status' => '', 'post_parent' => 0); - $r = array_merge($defaults, $r); + $r = wp_parse_args( $args, $defaults ); $children = get_posts( $r ); @@ -90,7 +92,7 @@ function get_extended($post) { // Retrieves post data given a post ID or post object. // Handles post caching. -function &get_post(&$post, $output = OBJECT) { +function &get_post(&$post, $output = OBJECT, $filter = 'raw') { global $post_cache, $wpdb, $blog_id; if ( empty($post) ) { @@ -122,6 +124,8 @@ function &get_post(&$post, $output = OBJECT) { if ( defined('WP_IMPORTING') ) unset($post_cache[$blog_id]); + $_post = sanitize_post($_post, $filter); + if ( $output == OBJECT ) { return $_post; } elseif ( $output == ARRAY_A ) { @@ -133,6 +137,22 @@ function &get_post(&$post, $output = OBJECT) { } } +function get_post_field( $field, $post, $context = 'display' ) { + $post = (int) $post; + $post = get_post( $post ); + + if ( is_wp_error($post) ) + return $post; + + if ( !is_object($post) ) + return ''; + + if ( !isset($post->$field) ) + return ''; + + return sanitize_post_field($field, $post->$field, $post->ID, $context); +} + // Takes a post ID, returns its mime type. function get_post_mime_type($ID = '') { $post = & get_post($ID); @@ -173,16 +193,18 @@ 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 = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); - $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, EXTR_SKIP); $numberposts = (int) $numberposts; $offset = (int) $offset; $category = (int) $category; @@ -226,13 +248,13 @@ function get_posts($args) { $exclusions .= ')'; $query = "SELECT DISTINCT * FROM $wpdb->posts "; - $query .= empty( $category ) ? '' : ", $wpdb->post2cat "; + $query .= empty( $category ) ? '' : ", $wpdb->term_relationships, $wpdb->term_taxonomy "; $query .= empty( $meta_key ) ? '' : ", $wpdb->postmeta "; $query .= " WHERE 1=1 "; $query .= empty( $post_type ) ? '' : "AND post_type = '$post_type' "; $query .= empty( $post_status ) ? '' : "AND post_status = '$post_status' "; $query .= "$exclusions $inclusions " ; - $query .= empty( $category ) ? '' : "AND ($wpdb->posts.ID = $wpdb->post2cat.post_id AND $wpdb->post2cat.category_id = " . $category. ") "; + $query .= empty( $category ) ? '' : "AND ($wpdb->posts.ID = $wpdb->term_relationships.object_id AND $wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id AND $wpdb->term_taxonomy.term_id = " . $category. ") "; $query .= empty( $post_parent ) ? '' : "AND $wpdb->posts.post_parent = '$post_parent' "; $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; @@ -363,6 +385,17 @@ function update_post_meta($post_id, $key, $value, $prev_value = '') { } +function delete_post_meta_by_key($post_meta_key) { + global $wpdb, $post_meta_cache, $blog_id; + $post_meta_key = $wpdb->escape($post_meta_key); + if ( $wpdb->query("DELETE FROM $wpdb->postmeta WHERE meta_key = '$post_meta_key'") ) { + unset($post_meta_cache[$blog_id]); // not worth doing the work to iterate through the cache + return true; + } + return false; +} + + function get_post_custom($post_id = 0) { global $id, $post_meta_cache, $wpdb, $blog_id; @@ -394,6 +427,81 @@ function get_post_custom_values( $key = '', $post_id = 0 ) { return $custom[$key]; } +function sanitize_post($post, $context = 'display') { + // TODO: Use array keys instead of hard coded list + $fields = array('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_content_filtered', 'post_title', 'post_excerpt', 'post_status', 'post_type', 'comment_status', 'ping_status', 'post_password', 'post_name', 'to_ping', 'pinged', 'post_date', 'post_date_gmt', 'post_parent', 'menu_order', 'post_mime_type', 'post_category'); + + $do_object = false; + if ( is_object($post) ) + $do_object = true; + + foreach ( $fields as $field ) { + if ( $do_object ) + $post->$field = sanitize_post_field($field, $post->$field, $post->ID, $context); + else + $post[$field] = sanitize_post_field($field, $post[$field], $post['ID'], $context); + } + + return $post; +} + +function sanitize_post_field($field, $value, $post_id, $context) { + $int_fields = array('ID', 'post_parent', 'menu_order'); + if ( in_array($field, $int_fields) ) + $value = (int) $value; + + if ( 'raw' == $context ) + return $value; + + $prefixed = false; + if ( false !== strpos($field, 'post_') ) { + $prefixed = true; + $field_no_prefix = str_replace('post_', '', $field); + } + + if ( 'edit' == $context ) { + $format_to_edit = array('post_content', 'post_excerpt', 'post_title', 'post_password'); + + if ( $prefixed ) { + $value = apply_filters("edit_$field", $value, $post_id); + // Old school + $value = apply_filters("${field_no_prefix}_edit_pre", $value, $post_id); + } else { + $value = apply_filters("edit_post_$field", $value, $post_id); + } + + if ( in_array($field, $format_to_edit) ) { + if ( 'post_content' == $field ) + $value = format_to_edit($value, user_can_richedit()); + else + $value = format_to_edit($value); + } else { + $value = attribute_escape($value); + } + } else if ( 'db' == $context ) { + if ( $prefixed ) { + $value = apply_filters("pre_$field", $value); + $value = apply_filters("${field_no_prefix}_save_pre", $value); + } else { + $value = apply_filters("pre_post_$field", $value); + $value = apply_filters("${field}_pre", $value); + } + } else { + // Use display filters by default. + if ( $prefixed ) + $value = apply_filters($field, $value, $post_id, $context); + else + $value = apply_filters("post_$field", $value, $post_id, $context); + } + + if ( 'attribute' == $context ) + $value = attribute_escape($value); + else if ( 'js' == $context ) + $value = js_escape($value); + + return $value; +} + function wp_delete_post($postid = 0) { global $wpdb, $wp_rewrite; $postid = (int) $postid; @@ -406,16 +514,8 @@ function wp_delete_post($postid = 0) { do_action('delete_post', $postid); - if ( 'publish' == $post->post_status && 'post' == $post->post_type ) { - $categories = wp_get_post_categories($post->ID); - if( is_array( $categories ) ) { - foreach ( $categories as $cat_id ) { - $wpdb->query("UPDATE $wpdb->categories SET category_count = category_count - 1 WHERE cat_ID = '$cat_id'"); - wp_cache_delete($cat_id, 'category'); - do_action('edit_category', $cat_id); - } - } - } + // TODO delete for pluggable post taxonomies too + wp_delete_object_term_relationships($postid, array('category', 'post_tag')); if ( 'page' == $post->post_type ) $wpdb->query("UPDATE $wpdb->posts SET post_parent = $post->post_parent WHERE post_parent = $postid AND post_type = 'page'"); @@ -426,8 +526,6 @@ function wp_delete_post($postid = 0) { $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_post_ID = $postid"); - $wpdb->query("DELETE FROM $wpdb->post2cat WHERE post_id = $postid"); - $wpdb->query("DELETE FROM $wpdb->postmeta WHERE post_id = $postid"); if ( 'page' == $post->post_type ) { @@ -436,18 +534,29 @@ function wp_delete_post($postid = 0) { } do_action('deleted_post', $postid); - + return $post; } -function wp_get_post_categories($post_id = 0) { +function wp_get_post_categories( $post_id = 0, $args = array() ) { + $post_id = (int) $post_id; + + $defaults = array('fields' => 'ids'); + $args = wp_parse_args( $args, $defaults ); + + $cats = wp_get_object_terms($post_id, 'category', $args); + return $cats; +} + +function wp_get_post_tags( $post_id = 0, $args = array() ) { $post_id = (int) $post_id; - $cats = &get_the_category($post_id); - $cat_ids = array(); - foreach ( $cats as $cat ) - $cat_ids[] = (int) $cat->cat_ID; - return array_unique($cat_ids); + $defaults = array('fields' => 'all'); + $args = wp_parse_args( $args, $defaults ); + + $tags = wp_get_object_terms($post_id, 'post_tag', $args); + + return $tags; } function wp_get_recent_posts($num = 10) { @@ -472,12 +581,14 @@ function wp_get_single_post($postid = 0, $mode = OBJECT) { $post = get_post($postid, $mode); - // Set categories + // Set categories and tags if($mode == OBJECT) { $post->post_category = wp_get_post_categories($postid); + $post->tags_input = wp_get_post_tags($postid, array('fields' => 'names')); } else { $post['post_category'] = wp_get_post_categories($postid); + $post['tags_input'] = wp_get_post_tags($postid, array('fields' => 'names')); } return $post; @@ -486,8 +597,12 @@ function wp_get_single_post($postid = 0, $mode = OBJECT) { function wp_insert_post($postarr = array()) { global $wpdb, $wp_rewrite, $allowedtags, $user_ID; - if ( is_object($postarr) ) - $postarr = get_object_vars($postarr); + $defaults = array('post_status' => 'draft', 'post_type' => 'post', 'post_author' => $user_ID, + 'ping_status' => get_option('default_ping_status'), 'post_parent' => 0, + 'menu_order' => 0, 'to_ping' => '', 'pinged' => '', 'post_password' => ''); + + $postarr = wp_parse_args($postarr, $defaults); + $postarr = sanitize_post($postarr, 'db'); // export array as variables extract($postarr, EXTR_SKIP); @@ -496,21 +611,9 @@ function wp_insert_post($postarr = array()) { $update = false; if ( !empty($ID) ) { $update = true; - $post = & get_post($ID); - $previous_status = $post->post_status; - } - - // Get the basics. - if ( empty($no_filter) ) { - $post_content = apply_filters('content_save_pre', $post_content); - $post_content_filtered = apply_filters('content_filtered_save_pre', $post_content_filtered); - $post_excerpt = apply_filters('excerpt_save_pre', $post_excerpt); - $post_title = apply_filters('title_save_pre', $post_title); - $post_category = apply_filters('category_save_pre', $post_category); - $post_status = apply_filters('status_save_pre', $post_status); - $post_name = apply_filters('name_save_pre', $post_name); - $comment_status = apply_filters('comment_status_pre', $comment_status); - $ping_status = apply_filters('ping_status_pre', $ping_status); + $previous_status = get_post_field('post_status', $ID); + } else { + $previous_status = 'new'; } if ( ('' == $post_content) && ('' == $post_title) && ('' == $post_excerpt) ) @@ -520,7 +623,6 @@ function wp_insert_post($postarr = array()) { if (0 == count($post_category) || !is_array($post_category)) { $post_category = array(get_option('default_category')); } - $post_cat = $post_category[0]; if ( empty($post_author) ) $post_author = $user_ID; @@ -544,15 +646,14 @@ function wp_insert_post($postarr = array()) { $post_name = sanitize_title($post_name); } - // If the post date is empty (due to having been new or a draft) and status is not 'draft', set date to now if (empty($post_date)) { - if ( 'draft' != $post_status ) + if ( !in_array($post_status, array('draft', 'pending')) ) $post_date = current_time('mysql'); } if (empty($post_date_gmt)) { - if ( 'draft' != $post_status ) + if ( !in_array($post_status, array('draft', 'pending')) ) $post_date_gmt = get_gmt_from_date($post_date); } @@ -570,8 +671,6 @@ function wp_insert_post($postarr = array()) { } if ( empty($ping_status) ) $ping_status = get_option('default_ping_status'); - if ( empty($post_pingback) ) - $post_pingback = get_option('default_pingback_flag'); if ( isset($to_ping) ) $to_ping = preg_replace('|\s+|', "\n", $to_ping); @@ -600,7 +699,7 @@ function wp_insert_post($postarr = array()) { if ($post_name_check || in_array($post_name, $wp_rewrite->feeds) ) { $suffix = 2; do { - $alt_post_name = $post_name . "-$suffix"; + $alt_post_name = substr($post_name, 0, 200-(strlen($suffix)+1)). "-$suffix"; $post_name_check = $wpdb->get_var("SELECT post_name FROM $wpdb->posts WHERE post_name = '$alt_post_name' AND post_type = '$post_type' AND ID != '$post_ID' AND post_parent = '$post_parent' LIMIT 1"); $suffix++; } while ($post_name_check); @@ -645,11 +744,11 @@ 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 ); + wp_set_post_tags( $post_ID, $tags_input ); if ( 'page' == $post_type ) { clean_page_cache($post_ID); - $wp_rewrite->flush_rules(); } else { clean_post_cache($post_ID); } @@ -658,55 +757,17 @@ function wp_insert_post($postarr = array()) { if ( ! $update ) $wpdb->query("UPDATE $wpdb->posts SET guid = '" . get_permalink($post_ID) . "' WHERE ID = '$post_ID'"); - if ( $update) { - if ($previous_status != 'publish' && $post_status == 'publish') { - // Reset GUID if transitioning to publish. - $wpdb->query("UPDATE $wpdb->posts SET guid = '" . get_permalink($post_ID) . "' WHERE ID = '$post_ID'"); - do_action('private_to_published', $post_ID); - } - - do_action('edit_post', $post_ID); - } - - if ($post_status == 'publish' && $post_type == 'post') { - do_action('publish_post', $post_ID); - if ( defined('XMLRPC_REQUEST') ) - do_action('xmlrpc_publish_post', $post_ID); - if ( defined('APP_REQUEST') ) - do_action('app_publish_post', $post_ID); - - if ( !defined('WP_IMPORTING') ) { - if ( $post_pingback ) - $result = $wpdb->query(" - INSERT INTO $wpdb->postmeta - (post_id,meta_key,meta_value) - VALUES ('$post_ID','_pingme','1') - "); - $result = $wpdb->query(" - INSERT INTO $wpdb->postmeta - (post_id,meta_key,meta_value) - VALUES ('$post_ID','_encloseme','1') - "); - wp_schedule_single_event(time(), 'do_pings'); - } - } else if ($post_type == 'page') { - if ( !empty($page_template) ) - if ( ! update_post_meta($post_ID, '_wp_page_template', $page_template)) - add_post_meta($post_ID, '_wp_page_template', $page_template, true); - - if ( $post_status == 'publish' ) - do_action('publish_page', $post_ID); - } + $post = get_post($post_ID); + if ( !empty($page_template) ) + $post->page_template = $page_template; - // Always clears the hook in case the post status bounced from future to draft. - wp_clear_scheduled_hook('publish_future_post', $post_ID); + wp_transition_post_status($post_status, $previous_status, $post); - // Schedule publication. - if ( 'future' == $post_status ) - wp_schedule_single_event(strtotime($post_date_gmt. ' GMT'), 'publish_future_post', array($post_ID)); + if ( $update) + do_action('edit_post', $post_ID, $post); - do_action('save_post', $post_ID); - do_action('wp_insert_post', $post_ID); + do_action('save_post', $post_ID, $post); + do_action('wp_insert_post', $post_ID, $post); return $post_ID; } @@ -731,7 +792,7 @@ function wp_update_post($postarr = array()) { $post_cats = $post['post_category']; // Drafts shouldn't be assigned a date unless explicitly done so by the user - if ( 'draft' == $post['post_status'] && empty($postarr['edit_date']) && empty($postarr['post_date']) && + if ( in_array($post['post_status'], array('draft', 'pending')) && empty($postarr['edit_date']) && empty($postarr['post_date']) && ('0000-00-00 00:00:00' == $post['post_date']) ) $clear_date = true; else @@ -752,6 +813,8 @@ function wp_update_post($postarr = array()) { } function wp_publish_post($post_id) { + global $wpdb; + $post = get_post($post_id); if ( empty($post) ) @@ -760,7 +823,34 @@ function wp_publish_post($post_id) { if ( 'publish' == $post->post_status ) return; - return wp_update_post(array('post_status' => 'publish', 'ID' => $post_id, 'no_filter' => true)); + $wpdb->query( "UPDATE $wpdb->posts SET post_status = 'publish' WHERE ID = '$post_id'" ); + + $old_status = $post->post_status; + $post->post_status = 'publish'; + wp_transition_post_status('publish', $old_status, $post); + + do_action('edit_post', $post_id, $post); + do_action('save_post', $post_id, $post); + do_action('wp_insert_post', $post_id, $post); +} + +function wp_add_post_tags($post_id = 0, $tags = '') { + return wp_set_post_tags($post_id, $tags, true); +} + +function wp_set_post_tags( $post_id = 0, $tags = '', $append = false ) { + /* $append - true = don't delete existing tags, just add on, false = replace the tags with the new tags */ + global $wpdb; + + $post_id = (int) $post_id; + + if ( !$post_id ) + return false; + + if ( empty($tags) ) + $tags = array(); + $tags = (is_array($tags)) ? $tags : explode( ',', $tags ); + wp_set_object_terms($post_id, $tags, 'post_tag', $append); } function wp_set_post_categories($post_ID = 0, $post_categories = array()) { @@ -770,56 +860,22 @@ function wp_set_post_categories($post_ID = 0, $post_categories = array()) { // If $post_categories isn't already an array, make it one: if (!is_array($post_categories) || 0 == count($post_categories) || empty($post_categories)) $post_categories = array(get_option('default_category')); + else if ( 1 == count($post_categories) && '' == $post_categories[0] ) + return true; + $post_categories = array_map('intval', $post_categories); $post_categories = array_unique($post_categories); - // First the old categories - $old_categories = $wpdb->get_col(" - SELECT category_id - FROM $wpdb->post2cat - WHERE post_id = '$post_ID'"); - - if (!$old_categories) { - $old_categories = array(); - } else { - $old_categories = array_unique($old_categories); - } - - // Delete any? - $delete_cats = array_diff($old_categories,$post_categories); - - if ($delete_cats) { - foreach ($delete_cats as $del) { - $wpdb->query(" - DELETE FROM $wpdb->post2cat - WHERE category_id = '$del' - AND post_id = '$post_ID' - "); - } - } - - // Add any? - $add_cats = array_diff($post_categories, $old_categories); - - if ($add_cats) { - foreach ($add_cats as $new_cat) { - $new_cat = (int) $new_cat; - if ( !empty($new_cat) ) - $wpdb->query(" - INSERT INTO $wpdb->post2cat (post_id, category_id) - VALUES ('$post_ID', '$new_cat')"); - } - } + return wp_set_object_terms($post_ID, $post_categories, 'category'); +} // wp_set_post_categories() - // Update category counts. - $all_affected_cats = array_unique(array_merge($post_categories, $old_categories)); - foreach ( $all_affected_cats as $cat_id ) { - $count = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->post2cat, $wpdb->posts WHERE $wpdb->posts.ID=$wpdb->post2cat.post_id AND post_status = 'publish' AND post_type = 'post' AND category_id = '$cat_id'"); - $wpdb->query("UPDATE $wpdb->categories SET category_count = '$count' WHERE cat_ID = '$cat_id'"); - clean_category_cache($cat_id); - do_action('edit_category', $cat_id); +function wp_transition_post_status($new_status, $old_status, $post) { + if ( $new_status != $old_status ) { + do_action('transition_post_status', $new_status, $old_status, $post); + do_action("${old_status}_to_$new_status", $post); } -} // wp_set_post_categories() + do_action("${new_status}_$post->post_type", $post->ID, $post); +} // // Trackback and ping functions @@ -920,7 +976,7 @@ function &get_page(&$page, $output = OBJECT) { global $wpdb, $blog_id; if ( empty($page) ) { - if ( isset($GLOBALS['page']) ) { + if ( isset( $GLOBALS['page'] ) && isset( $GLOBALS['page']->ID ) ) { $_page = & $GLOBALS['page']; wp_cache_add($_page->ID, $_page, 'pages'); } else { @@ -1059,15 +1115,16 @@ 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' => '' + ); - $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, EXTR_SKIP); + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); $key = md5( serialize( $r ) ); if ( $cache = wp_cache_get( 'get_pages', 'page' ) ) @@ -1076,7 +1133,7 @@ function &get_pages($args = '') { $inclusions = ''; if ( !empty($include) ) { - $child_of = 0; //ignore child_of, exclude, meta_key, and meta_value params if using include + $child_of = 0; //ignore child_of, exclude, meta_key, and meta_value params if using include $exclude = ''; $meta_key = ''; $meta_value = ''; @@ -1105,7 +1162,7 @@ function &get_pages($args = '') { } } } - if (!empty($exclusions)) + if (!empty($exclusions)) $exclusions .= ')'; $author_query = ''; @@ -1135,14 +1192,13 @@ function &get_pages($args = '') { } $query = "SELECT * FROM $wpdb->posts " ; - $query .= ( empty( $meta_key ) ? "" : ", $wpdb->postmeta " ) ; + $query .= ( empty( $meta_key ) ? "" : ", $wpdb->postmeta " ) ; $query .= " WHERE (post_type = 'page' AND post_status = 'publish') $exclusions $inclusions " ; $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 .= $author_query; $query .= " ORDER BY " . $sort_column . " " . $sort_order ; $pages = $wpdb->get_results($query); - $pages = apply_filters('get_pages', $pages, $r); if ( empty($pages) ) return array(); @@ -1156,6 +1212,8 @@ function &get_pages($args = '') { $cache[ $key ] = $pages; wp_cache_set( 'get_pages', $cache, 'page' ); + $pages = apply_filters('get_pages', $pages, $r); + return $pages; } @@ -1214,31 +1272,26 @@ function is_local_attachment($url) { return false; } -function wp_insert_attachment($object, $file = false, $post_parent = 0) { +function wp_insert_attachment($object, $file = false, $parent = 0) { global $wpdb, $user_ID; - if ( is_object($object) ) - $object = get_object_vars($object); + $defaults = array('post_status' => 'draft', 'post_type' => 'post', 'post_author' => $user_ID, + 'ping_status' => get_option('default_ping_status'), 'post_parent' => 0, + 'menu_order' => 0, 'to_ping' => '', 'pinged' => '', 'post_password' => ''); - // Export array as variables - extract($object, EXTR_SKIP); + $object = wp_parse_args($object, $defaults); + if ( !empty($parent) ) + $object['post_parent'] = $parent; - // Get the basics. - $post_content = apply_filters('content_save_pre', $post_content); - $post_content_filtered = apply_filters('content_filtered_save_pre', $post_content_filtered); - $post_excerpt = apply_filters('excerpt_save_pre', $post_excerpt); - $post_title = apply_filters('title_save_pre', $post_title); - $post_category = apply_filters('category_save_pre', $post_category); - $post_name = apply_filters('name_save_pre', $post_name); - $comment_status = apply_filters('comment_status_pre', $comment_status); - $ping_status = apply_filters('ping_status_pre', $ping_status); - $post_mime_type = apply_filters('post_mime_type_pre', $post_mime_type); + $object = sanitize_post($object, 'db'); + + // export array as variables + extract($object, EXTR_SKIP); // Make sure we set a valid category if (0 == count($post_category) || !is_array($post_category)) { $post_category = array(get_option('default_category')); } - $post_cat = $post_category[0]; if ( empty($post_author) ) $post_author = $user_ID; @@ -1272,9 +1325,9 @@ function wp_insert_attachment($object, $file = false, $post_parent = 0) { $post_name = $alt_post_name; } - if (empty($post_date)) + if ( empty($post_date) ) $post_date = current_time('mysql'); - if (empty($post_date_gmt)) + if ( empty($post_date_gmt) ) $post_date_gmt = current_time('mysql', 1); if ( empty($comment_status) ) { @@ -1285,8 +1338,6 @@ function wp_insert_attachment($object, $file = false, $post_parent = 0) { } if ( empty($ping_status) ) $ping_status = get_option('default_ping_status'); - if ( empty($post_pingback) ) - $post_pingback = get_option('default_pingback_flag'); if ( isset($to_ping) ) $to_ping = preg_replace('|\s+|', "\n", $to_ping); @@ -1306,11 +1357,6 @@ function wp_insert_attachment($object, $file = false, $post_parent = 0) { if ( !isset($post_password) ) $post_password = ''; - if ( isset($to_ping) ) - $to_ping = preg_replace('|\s+|', "\n", $to_ping); - else - $to_ping = ''; - if ( ! isset($pinged) ) $pinged = ''; @@ -1382,12 +1428,13 @@ function wp_delete_attachment($postid) { $meta = wp_get_attachment_metadata( $postid ); $file = get_attached_file( $postid ); + // TODO delete for pluggable post taxonomies too + wp_delete_object_term_relationships($postid, array('category', 'post_tag')); + $wpdb->query("DELETE FROM $wpdb->posts WHERE ID = '$postid'"); $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_post_ID = '$postid'"); - $wpdb->query("DELETE FROM $wpdb->post2cat WHERE post_id = '$postid'"); - $wpdb->query("DELETE FROM $wpdb->postmeta WHERE post_id = '$postid'"); if ( ! empty($meta['thumb']) ) { @@ -1566,7 +1613,7 @@ function wp_check_for_changed_slugs($post_id) { * 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. */ @@ -1606,4 +1653,237 @@ function get_private_posts_cap_sql($post_type) { return $sql; } +function get_lastpostdate($timezone = 'server') { + global $cache_lastpostdate, $pagenow, $wpdb, $blog_id; + $add_seconds_blog = get_option('gmt_offset') * 3600; + $add_seconds_server = date('Z'); + if ( !isset($cache_lastpostdate[$blog_id][$timezone]) ) { + switch(strtolower($timezone)) { + case 'gmt': + $lastpostdate = $wpdb->get_var("SELECT post_date_gmt FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_date_gmt DESC LIMIT 1"); + break; + case 'blog': + $lastpostdate = $wpdb->get_var("SELECT post_date FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_date_gmt DESC LIMIT 1"); + break; + case 'server': + $lastpostdate = $wpdb->get_var("SELECT DATE_ADD(post_date_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_date_gmt DESC LIMIT 1"); + break; + } + $cache_lastpostdate[$blog_id][$timezone] = $lastpostdate; + } else { + $lastpostdate = $cache_lastpostdate[$blog_id][$timezone]; + } + return apply_filters( 'get_lastpostdate', $lastpostdate ); +} + +function get_lastpostmodified($timezone = 'server') { + global $cache_lastpostmodified, $pagenow, $wpdb, $blog_id; + $add_seconds_blog = get_option('gmt_offset') * 3600; + $add_seconds_server = date('Z'); + if ( !isset($cache_lastpostmodified[$blog_id][$timezone]) ) { + switch(strtolower($timezone)) { + case 'gmt': + $lastpostmodified = $wpdb->get_var("SELECT post_modified_gmt FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_modified_gmt DESC LIMIT 1"); + break; + case 'blog': + $lastpostmodified = $wpdb->get_var("SELECT post_modified FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_modified_gmt DESC LIMIT 1"); + break; + case 'server': + $lastpostmodified = $wpdb->get_var("SELECT DATE_ADD(post_modified_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_modified_gmt DESC LIMIT 1"); + break; + } + $lastpostdate = get_lastpostdate($timezone); + if ( $lastpostdate > $lastpostmodified ) { + $lastpostmodified = $lastpostdate; + } + $cache_lastpostmodified[$blog_id][$timezone] = $lastpostmodified; + } else { + $lastpostmodified = $cache_lastpostmodified[$blog_id][$timezone]; + } + return apply_filters( 'get_lastpostmodified', $lastpostmodified ); +} + +// +// Cache +// + +function update_post_cache(&$posts) { + global $post_cache, $blog_id; + + if ( !$posts ) + return; + + for ($i = 0; $i < count($posts); $i++) { + $post_cache[$blog_id][$posts[$i]->ID] = &$posts[$i]; + } +} + +function clean_post_cache($id) { + global $post_cache, $post_meta_cache, $post_term_cache, $blog_id; + + if ( isset( $post_cache[$blog_id][$id] ) ) + unset( $post_cache[$blog_id][$id] ); + + if ( isset ($post_meta_cache[$blog_id][$id] ) ) + unset( $post_meta_cache[$blog_id][$id] ); + + clean_object_term_cache($id, 'post'); +} + +function update_page_cache(&$pages) { + global $page_cache, $blog_id; + + if ( !$pages ) + return; + + for ($i = 0; $i < count($pages); $i++) { + $page_cache[$blog_id][$pages[$i]->ID] = &$pages[$i]; + wp_cache_add($pages[$i]->ID, $pages[$i], 'pages'); + } +} + +function clean_page_cache($id) { + global $page_cache, $blog_id; + + if ( isset( $page_cache[$blog_id][$id] ) ) + unset( $page_cache[$blog_id][$id] ); + + wp_cache_delete($id, 'pages'); + wp_cache_delete( 'all_page_ids', 'pages' ); + wp_cache_delete( 'get_pages', 'page' ); +} + +function update_post_caches(&$posts) { + global $post_cache; + global $wpdb, $blog_id; + + // No point in doing all this work if we didn't match any posts. + if ( !$posts ) + return; + + // Get the categories for all the posts + for ($i = 0; $i < count($posts); $i++) { + $post_id_array[] = $posts[$i]->ID; + $post_cache[$blog_id][$posts[$i]->ID] = &$posts[$i]; + } + + $post_id_list = implode(',', $post_id_array); + + update_object_term_cache($post_id_list, 'post'); + + update_postmeta_cache($post_id_list); +} + +function update_postmeta_cache($post_id_list = '') { + global $wpdb, $post_meta_cache, $blog_id; + + // We should validate this comma-separated list for the upcoming SQL query + $post_id_list = preg_replace('|[^0-9,]|', '', $post_id_list); + + if ( empty( $post_id_list ) ) + return false; + + // we're marking each post as having its meta cached (with no keys... empty array), to prevent posts with no meta keys from being queried again + // any posts that DO have keys will have this empty array overwritten with a proper array, down below + $post_id_array = (array) explode(',', $post_id_list); + $count = count( $post_id_array); + for ( $i = 0; $i < $count; $i++ ) { + $post_id = (int) $post_id_array[ $i ]; + if ( isset( $post_meta_cache[$blog_id][$post_id] ) ) { // If the meta is already cached + unset( $post_id_array[ $i ] ); + continue; + } + $post_meta_cache[$blog_id][$post_id] = array(); + } + if ( count( $post_id_array ) == 0 ) + return; + $post_id_list = join( ',', $post_id_array ); // with already cached stuff removeds + + // Get post-meta info + if ( $meta_list = $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM $wpdb->postmeta WHERE post_id IN($post_id_list) ORDER BY post_id, meta_key", ARRAY_A) ) { + // Change from flat structure to hierarchical: + if ( !isset($post_meta_cache) ) + $post_meta_cache[$blog_id] = array(); + + foreach ($meta_list as $metarow) { + $mpid = (int) $metarow['post_id']; + $mkey = $metarow['meta_key']; + $mval = $metarow['meta_value']; + + // Force subkeys to be array type: + if ( !isset($post_meta_cache[$blog_id][$mpid]) || !is_array($post_meta_cache[$blog_id][$mpid]) ) + $post_meta_cache[$blog_id][$mpid] = array(); + if ( !isset($post_meta_cache[$blog_id][$mpid]["$mkey"]) || !is_array($post_meta_cache[$blog_id][$mpid]["$mkey"]) ) + $post_meta_cache[$blog_id][$mpid]["$mkey"] = array(); + + // Add a value to the current pid/key: + $post_meta_cache[$blog_id][$mpid][$mkey][] = $mval; + } + } +} + +// +// Hooks +// + +function _transition_post_status($new_status, $old_status, $post) { + global $wpdb; + + if ( $old_status != 'publish' && $new_status == 'publish' ) { + // Reset GUID if transitioning to publish. + $wpdb->query("UPDATE $wpdb->posts SET guid = '" . get_permalink($post->ID) . "' WHERE ID = '$post->ID'"); + do_action('private_to_published', $post->ID); // Deprecated, use private_to_publish + } + + // Always clears the hook in case the post status bounced from future to draft. + wp_clear_scheduled_hook('publish_future_post', $post->ID); +} + +function _future_post_hook($post_id, $post) { + // Schedule publication. + wp_clear_scheduled_hook( 'publish_future_post', $post->ID ); + wp_schedule_single_event(strtotime($post->post_date_gmt. ' GMT'), 'publish_future_post', array($post->ID)); +} + +function _publish_post_hook($post_id) { + global $wpdb; + + if ( defined('XMLRPC_REQUEST') ) + do_action('xmlrpc_publish_post', $post_id); + if ( defined('APP_REQUEST') ) + do_action('app_publish_post', $post_id); + + if ( defined('WP_IMPORTING') ) + return; + + $post = get_post($post_id); + + if ( get_option('default_pingback_flag') ) + $result = $wpdb->query(" + INSERT INTO $wpdb->postmeta + (post_id,meta_key,meta_value) + VALUES ('$post_id','_pingme','1') + "); + $result = $wpdb->query(" + INSERT INTO $wpdb->postmeta + (post_id,meta_key,meta_value) + VALUES ('$post_id','_encloseme','1') + "); + wp_schedule_single_event(time(), 'do_pings'); +} + +function _save_post_hook($post_id, $post) { + if ( $post->post_type == 'page' ) { + if ( !empty($post->page_template) ) + if ( ! update_post_meta($post_id, '_wp_page_template', $post->page_template)) + add_post_meta($post_id, '_wp_page_template', $post->page_template, true); + + clean_page_cache($post_id); + global $wp_rewrite; + $wp_rewrite->flush_rules(); + } else { + clean_post_cache($post_id); + } +} + ?> diff --git a/wp-includes/query.php b/wp-includes/query.php index 45b6316..49cff8b 100644 --- a/wp-includes/query.php +++ b/wp-includes/query.php @@ -34,7 +34,7 @@ function wp_reset_query() { function is_admin () {
global $wp_query;
- return ($wp_query->is_admin || (strpos($_SERVER['REQUEST_URI'], 'wp-admin/') !== false));
+ return ($wp_query->is_admin || (stripos($_SERVER['REQUEST_URI'], 'wp-admin/') !== false));
}
function is_archive () {
@@ -81,16 +81,30 @@ function is_category ($category = '') { $cat_obj = $wp_query->get_queried_object();
- if ( $category == $cat_obj->cat_ID )
+ if ( $category == $cat_obj->term_id )
return true;
- else if ( $category == $cat_obj->cat_name )
+ else if ( $category == $cat_obj->name )
return true;
- elseif ( $category == $cat_obj->category_nicename )
+ elseif ( $category == $cat_obj->slug )
return true;
return false;
}
+function is_tag( $slug = '' ) {
+ global $wp_query;
+ if ( !$wp_query->is_tag )
+ return false;
+
+ if ( empty( $slug ) )
+ return true;
+
+ $tag_obj = $wp_query->get_queried_object();
+ if ( $slug == $tag_obj->slug )
+ return true;
+ return false;
+}
+
function is_comments_popup () {
global $wp_query;
@@ -261,18 +275,18 @@ function the_post() { }
/*
- * Comments loop.
- */
+ * Comments loop.
+ */
-function have_comments() {
- global $wp_query;
- return $wp_query->have_comments();
-}
+function have_comments() {
+ global $wp_query;
+ return $wp_query->have_comments();
+}
-function the_comment() {
- global $wp_query;
- return $wp_query->the_comment();
-}
+function the_comment() {
+ global $wp_query;
+ return $wp_query->the_comment();
+}
/*
* WP_Query
@@ -310,6 +324,7 @@ class WP_Query { var $is_time = false;
var $is_author = false;
var $is_category = false;
+ var $is_tag = false;
var $is_search = false;
var $is_feed = false;
var $is_comment_feed = false;
@@ -334,6 +349,7 @@ class WP_Query { $this->is_time = false;
$this->is_author = false;
$this->is_category = false;
+ $this->is_tag = false;
$this->is_search = false;
$this->is_feed = false;
$this->is_comment_feed = false;
@@ -388,6 +404,8 @@ class WP_Query { , 'year'
, 'w'
, 'category_name'
+ , 'tag'
+ , 'tag_id'
, 'author_name'
, 'feed'
, 'tb'
@@ -401,6 +419,13 @@ class WP_Query { $array[$key] = '';
}
+ $array_keys = array('category__in', 'category__not_in', 'category__and',
+ 'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and');
+
+ foreach ( $array_keys as $key ) {
+ if ( !isset($array[$key]))
+ $array[$key] = array();
+ }
return $array;
}
@@ -428,9 +453,9 @@ class WP_Query { $qv['day'] = (int) $qv['day'];
$qv['w'] = (int) $qv['w'];
$qv['m'] = (int) $qv['m'];
- if ( '' != $qv['hour'] ) $qv['hour'] = (int) $qv['hour'];
- if ( '' != $qv['minute'] ) $qv['minute'] = (int) $qv['minute'];
- if ( '' != $qv['second'] ) $qv['second'] = (int) $qv['second'];
+ if ( '' !== $qv['hour'] ) $qv['hour'] = (int) $qv['hour'];
+ if ( '' !== $qv['minute'] ) $qv['minute'] = (int) $qv['minute'];
+ if ( '' !== $qv['second'] ) $qv['second'] = (int) $qv['second'];
// Compat. Map subpost to attachment.
if ( '' != $qv['subpost'] )
@@ -439,7 +464,7 @@ class WP_Query { $qv['attachment_id'] = $qv['subpost_id'];
$qv['attachment_id'] = (int) $qv['attachment_id'];
-
+
if ( ('' != $qv['attachment']) || !empty($qv['attachment_id']) ) {
$this->is_single = true;
$this->is_attachment = true;
@@ -447,7 +472,7 @@ class WP_Query { $this->is_single = true;
} elseif ( $qv['p'] ) {
$this->is_single = true;
- } elseif ( ('' != $qv['hour']) && ('' != $qv['minute']) &&('' != $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day']) ) {
+ } elseif ( ('' !== $qv['hour']) && ('' !== $qv['minute']) &&('' !== $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day']) ) {
// If year, month, day, hour, minute, and second are set, a single
// post is being queried.
$this->is_single = true;
@@ -459,17 +484,17 @@ class WP_Query { } else {
// Look for archive queries. Dates, categories, authors.
- if ( '' != $qv['second'] ) {
+ if ( '' !== $qv['second'] ) {
$this->is_time = true;
$this->is_date = true;
}
- if ( '' != $qv['minute'] ) {
+ if ( '' !== $qv['minute'] ) {
$this->is_time = true;
$this->is_date = true;
}
- if ( '' != $qv['hour'] ) {
+ if ( '' !== $qv['hour'] ) {
$this->is_time = true;
$this->is_date = true;
}
@@ -526,6 +551,67 @@ class WP_Query { $this->is_category = true;
}
+ if ( !is_array($qv['category__in']) || empty($qv['category__in']) ) {
+ $qv['category__in'] = array();
+ } else {
+ $qv['category__in'] = array_map('intval', $qv['category__in']);
+ $this->is_category = true;
+ }
+
+ if ( !is_array($qv['category___not_in']) || empty($qv['category__not_in']) ) {
+ $qv['category__not_in'] = array();
+ } else {
+ $qv['category__not_in'] = array_map('intval', $qv['category__not_in']);
+ }
+
+ if ( !is_array($qv['category__and']) || empty($qv['category__and']) ) {
+ $qv['category__and'] = array();
+ } else {
+ $qv['category__and'] = array_map('intval', $qv['category__and']);
+ $this->is_category = true;
+ }
+
+ if ( '' != $qv['tag'] )
+ $this->is_tag = true;
+
+ $qv['tag_id'] = (int) $qv['tag_id'];
+ if ( !empty($qv['tag_id']) )
+ $this->is_tag = true;
+
+ if ( !is_array($qv['tag__in']) || empty($qv['tag__in']) ) {
+ $qv['tag__in'] = array();
+ } else {
+ $qv['tag__in'] = array_map('intval', $qv['tag__in']);
+ $this->is_tag = true;
+ }
+
+ if ( !is_array($qv['tag___not_in']) || empty($qv['tag__not_in']) ) {
+ $qv['tag__not_in'] = array();
+ } else {
+ $qv['tag__not_in'] = array_map('intval', $qv['tag__not_in']);
+ }
+
+ if ( !is_array($qv['tag__and']) || empty($qv['tag__and']) ) {
+ $qv['tag__and'] = array();
+ } else {
+ $qv['tag__and'] = array_map('intval', $qv['tag__and']);
+ $this->is_category = true;
+ }
+
+ if ( !is_array($qv['tag_slug__in']) || empty($qv['tag_slug__in']) ) {
+ $qv['tag_slug__in'] = array();
+ } else {
+ $qv['tag_slug__in'] = array_map('sanitize_title', $qv['tag_slug__in']);
+ $this->is_tag = true;
+ }
+
+ if ( !is_array($qv['tag_slug__and']) || empty($qv['tag_slug__and']) ) {
+ $qv['tag_slug__and'] = array();
+ } else {
+ $qv['tag_slug__and'] = array_map('sanitize_title', $qv['tag_slug__and']);
+ $this->is_tag = true;
+ }
+
if ( empty($qv['author']) || ($qv['author'] == '0') ) {
$this->is_author = false;
} else {
@@ -536,7 +622,7 @@ class WP_Query { $this->is_author = true;
}
- if ( ($this->is_date || $this->is_author || $this->is_category) )
+ if ( ($this->is_date || $this->is_author || $this->is_category || $this->is_tag ) )
$this->is_archive = true;
}
@@ -723,13 +809,13 @@ class WP_Query { $where .= ' AND SECOND(post_date)=' . substr($q['m'], 12, 2);
}
- if ( '' != $q['hour'] )
+ if ( '' !== $q['hour'] )
$where .= " AND HOUR(post_date)='" . $q['hour'] . "'";
- if ( '' != $q['minute'] )
+ if ( '' !== $q['minute'] )
$where .= " AND MINUTE(post_date)='" . $q['minute'] . "'";
- if ( '' != $q['second'] )
+ if ( '' !== $q['second'] )
$where .= " AND SECOND(post_date)='" . $q['second'] . "'";
if ( $q['year'] )
@@ -809,7 +895,7 @@ class WP_Query { $search .= "{$searchand}((post_title LIKE '{$n}{$term}{$n}') OR (post_content LIKE '{$n}{$term}{$n}'))";
$searchand = ' AND ';
}
- $term = addslashes_gpc($q['s']);
+ $term = addslashes_gpc($q['s']);
if (!$q['sentence'] && count($q['search_terms']) > 1 && $q['search_terms'][0] != $q['s'] )
$search .= " OR (post_title LIKE '{$n}{$term}{$n}') OR (post_content LIKE '{$n}{$term}{$n}')";
@@ -826,38 +912,51 @@ class WP_Query { } else {
$q['cat'] = ''.urldecode($q['cat']).'';
$q['cat'] = addslashes_gpc($q['cat']);
- $join = " LEFT JOIN $wpdb->post2cat ON ($wpdb->posts.ID = $wpdb->post2cat.post_id) ";
$cat_array = preg_split('/[,\s]+/', $q['cat']);
- $in_cats = $out_cats = $out_posts = '';
foreach ( $cat_array as $cat ) {
$cat = intval($cat);
- $in = (strpos($cat, '-') !== false) ? false : true;
- $cat = trim($cat, '-');
- if ( $in )
- $in_cats .= "$cat, " . get_category_children($cat, '', ', ');
- else
- $out_cats .= "$cat, " . get_category_children($cat, '', ', ');
- }
- $in_cats = substr($in_cats, 0, -2);
- $out_cats = substr($out_cats, 0, -2);
- if ( strlen($in_cats) > 0 )
- $in_cats = " AND $wpdb->post2cat.category_id IN ($in_cats)";
- if ( strlen($out_cats) > 0 ) {
- $ids = $wpdb->get_col("SELECT post_id FROM $wpdb->post2cat WHERE $wpdb->post2cat.category_id IN ($out_cats)");
- if ( is_array($ids) && count($ids > 0) ) {
- foreach ( $ids as $id )
- $out_posts .= "$id, ";
- $out_posts = substr($out_posts, 0, -2);
+ $in = ($cat > 0);
+ $cat = abs($cat);
+ if ( $in ) {
+ $q['category__in'][] = $cat;
+ $q['category__in'] = array_merge($q['category__in'], get_term_children($cat, 'category'));
+ } else {
+ $q['category__not_in'][] = $cat;
+ $q['category__not_in'] = array_merge($q['category__not_in'], get_term_children($cat, 'category'));
}
- if ( strlen($out_posts) > 0 )
- $out_cats = " AND $wpdb->posts.ID NOT IN ($out_posts)";
- else
- $out_cats = '';
}
- $whichcat = $in_cats . $out_cats;
+ }
+
+ if ( !empty($q['category__in']) || !empty($q['category__not_in']) || !empty($q['category__and']) ) {
$groupby = "{$wpdb->posts}.ID";
}
+ if ( !empty($q['category__in']) ) {
+ $join = " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) ";
+ $whichcat .= " AND $wpdb->term_taxonomy.taxonomy = 'category' ";
+ $include_cats = "'" . implode("', '", $q['category__in']) . "'";
+ $whichcat .= " AND $wpdb->term_taxonomy.term_id IN ($include_cats) ";
+ }
+
+ if ( !empty($q['category__not_in']) ) {
+ $ids = get_objects_in_term($q['category__not_in'], 'category');
+ if ( is_wp_error( $ids ) )
+ return $ids;
+ if ( is_array($ids) && count($ids > 0) ) {
+ $out_posts = "'" . implode("', '", $ids) . "'";
+ $whichcat .= " AND $wpdb->posts.ID NOT IN ($out_posts)";
+ }
+ }
+
+ if ( !empty($q['category__and']) ) {
+ $count = 0;
+ foreach ( $q['category__and'] as $category_and ) {
+ $join .= " LEFT JOIN $wpdb->term_relationships AS tr$count ON ($wpdb->posts.ID = tr$count.object_id) LEFT JOIN $wpdb->term_taxonomy AS tt$count ON (tr$count.term_taxonomy_id = tt$count.term_taxonomy_id) ";
+ $whichcat .= " AND tt$count.term_id = '$category_and' ";
+ $count++;
+ }
+ }
+
// Category stuff for nice URLs
if ( '' != $q['category_name'] ) {
$reqcat = get_category_by_path($q['category_name']);
@@ -877,22 +976,104 @@ class WP_Query { $reqcat = get_category_by_path($q['category_name'], false);
if ( !empty($reqcat) )
- $reqcat = $reqcat->cat_ID;
+ $reqcat = $reqcat->term_id;
else
$reqcat = 0;
$q['cat'] = $reqcat;
- $tables = ", $wpdb->post2cat, $wpdb->categories";
- $join = " LEFT JOIN $wpdb->post2cat ON ($wpdb->posts.ID = $wpdb->post2cat.post_id) LEFT JOIN $wpdb->categories ON ($wpdb->post2cat.category_id = $wpdb->categories.cat_ID) ";
- $whichcat = " AND category_id IN ({$q['cat']}, ";
- $whichcat .= get_category_children($q['cat'], '', ', ');
- $whichcat = substr($whichcat, 0, -2);
- $whichcat .= ")";
+ $join = " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) ";
+ $whichcat = " AND $wpdb->term_taxonomy.taxonomy = 'category' ";
+ $in_cats = array($q['cat']);
+ $in_cats = array_merge($in_cats, get_term_children($q['cat'], 'category'));
+ $in_cats = "'" . implode("', '", $in_cats) . "'";
+ $whichcat .= "AND $wpdb->term_taxonomy.term_id IN ($in_cats)";
$groupby = "{$wpdb->posts}.ID";
}
+ // Tags
+ if ( '' != $q['tag'] ) {
+ if ( strpos($q['tag'], ',') !== false ) {
+ $tags = preg_split('/[,\s]+/', $q['tag']);
+ foreach ( (array) $tags as $tag ) {
+ $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
+ $q['tag_slug__in'][] = $tag;
+ }
+ } else if ( preg_match('/[+\s]+/', $q['tag']) ) {
+ $tags = preg_split('/[+\s]+/', $q['tag']);
+ foreach ( (array) $tags as $tag ) {
+ $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
+ $q['tag_slug__and'][] = $tag;
+ }
+ } else {
+ $q['tag'] = sanitize_term_field('slug', $q['tag'], 0, 'post_tag', 'db');
+ $reqtag = is_term( $q['tag'], 'post_tag' );
+ if ( !empty($reqtag) )
+ $reqtag = $reqtag['term_id'];
+ else
+ $reqtag = 0;
+ $q['tag_id'] = $reqtag;
+ $q['tag__in'][] = $reqtag;
+ }
+ }
+
+ if ( !empty($q['tag__in']) || !empty($q['tag__not_in']) || !empty($q['tag__and']) ||
+ !empty($q['tag_slug__in']) || !empty($q['tag_slug__and']) ) {
+ $groupby = "{$wpdb->posts}.ID";
+ }
+
+ if ( !empty($q['tag__in']) ) {
+ $join = " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) ";
+ $whichcat .= " AND $wpdb->term_taxonomy.taxonomy = 'post_tag' ";
+ $include_tags = "'" . implode("', '", $q['tag__in']) . "'";
+ $whichcat .= " AND $wpdb->term_taxonomy.term_id IN ($include_tags) ";
+ $reqtag = is_term( $q['tag__in'][0], 'post_tag' );
+ if ( !empty($reqtag) )
+ $q['tag_id'] = $reqtag['term_id'];
+ }
+
+ if ( !empty($q['tag_slug__in']) ) {
+ $join = " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) LEFT JOIN $wpdb->terms ON ($wpdb->term_taxonomy.term_id = $wpdb->terms.term_id) ";
+ $whichcat .= " AND $wpdb->term_taxonomy.taxonomy = 'post_tag' ";
+ $include_tags = "'" . implode("', '", $q['tag_slug__in']) . "'";
+ $whichcat .= " AND $wpdb->terms.slug IN ($include_tags) ";
+ $reqtag = is_term( $q['tag_slug__in'][0], 'post_tag' );
+ if ( !empty($reqtag) )
+ $q['tag_id'] = $reqtag['term_id'];
+ }
+
+ if ( !empty($q['tag__not_in']) ) {
+ $ids = get_objects_in_term($q['tag__not_in'], 'post_tag');
+ if ( is_array($ids) && count($ids > 0) ) {
+ $out_posts = "'" . implode("', '", $ids) . "'";
+ $whichcat .= " AND $wpdb->posts.ID NOT IN ($out_posts)";
+ }
+ }
+
+ if ( !empty($q['tag__and']) ) {
+ $count = 0;
+ foreach ( $q['tag__and'] as $tag_and ) {
+ $join .= " LEFT JOIN $wpdb->term_relationships AS tr$count ON ($wpdb->posts.ID = tr$count.object_id) LEFT JOIN $wpdb->term_taxonomy AS tt$count ON (tr$count.term_taxonomy_id = tt$count.term_taxonomy_id) ";
+ $whichcat .= " AND tt$count.term_id = '$tag_and' ";
+ $count++;
+ }
+ $reqtag = is_term( $q['tag__and'][0], 'post_tag' );
+ if ( !empty($reqtag) )
+ $q['tag_id'] = $reqtag['term_id'];
+ }
+
+ if ( !empty($q['tag_slug__and']) ) {
+ $count = 0;
+ foreach ( $q['tag_slug__and'] as $tag_and ) {
+ $join .= " LEFT JOIN $wpdb->term_relationships AS tr$count ON ($wpdb->posts.ID = tr$count.object_id) LEFT JOIN $wpdb->term_taxonomy AS tt$count ON (tr$count.term_taxonomy_id = tt$count.term_taxonomy_id) LEFT JOIN $wpdb->terms AS term$count ON (tt$count.term_id = term$count.term_id) ";
+ $whichcat .= " AND term$count.slug = '$tag_and' ";
+ $count++;
+ }
+ $reqtag = is_term( $q['tag_slug__and'][0], 'post_tag' );
+ if ( !empty($reqtag) )
+ $q['tag_id'] = $reqtag['term_id'];
+ }
// Author/user stuff
@@ -964,30 +1145,43 @@ class WP_Query { }
if ( $this->is_attachment ) {
- $where .= " AND (post_type = 'attachment')";
+ $where .= " AND post_type = 'attachment'";
} elseif ($this->is_page) {
- $where .= " AND (post_type = 'page')";
+ $where .= " AND post_type = 'page'";
} elseif ($this->is_single) {
- $where .= " AND (post_type = 'post')";
+ $where .= " AND post_type = 'post'";
} else {
- $where .= " AND (post_type = '$post_type' AND (post_status = 'publish'";
+ $where .= " AND post_type = '$post_type'";
+ }
+
+ if ( isset($q['post_status']) && '' != $q['post_status'] ) {
+ $q_status = explode(',', $q['post_status']);
+ $r_status = array();
+ if ( in_array( 'draft' , $q_status ) )
+ $r_status[] = "post_status = 'draft'";
+ if ( in_array( 'pending', $q_status ) )
+ $r_status[] = "post_status = 'pending'";
+ if ( in_array( 'future' , $q_status ) )
+ $r_status[] = "post_status = 'future'";
+ if ( in_array( 'inherit' , $q_status ) )
+ $r_status[] = "post_status = 'inherit'";
+ if ( in_array( 'private', $q_status ) )
+ $r_status[] = "post_status = 'private'";
+ if ( in_array( 'publish', $q_status ) )
+ $r_status[] = "post_status = 'publish'";
+ if ( !empty($r_status) )
+ $where .= " AND (" . join( ' OR ', $r_status ) . ")";
+ } elseif ( !$this->is_singular ) {
+ $where .= " AND (post_status = 'publish'";
if ( is_admin() )
- $where .= " OR post_status = 'future' OR post_status = 'draft'";
+ $where .= " OR post_status = 'future' OR post_status = 'draft' OR post_status = 'pending'";
if ( is_user_logged_in() ) {
- if ( 'post' == $post_type )
- $cap = 'read_private_posts';
- else
- $cap = 'read_private_pages';
-
- if ( current_user_can($cap) )
- $where .= " OR post_status = 'private'";
- else
- $where .= " OR post_author = $user_ID AND post_status = 'private'";
+ $where .= current_user_can( "read_private_{$post_type}s" ) ? " OR post_status = 'private'" : " OR post_author = $user_ID AND post_status = 'private'";
}
- $where .= '))';
+ $where .= ')';
}
// Apply filters on where and join prior to paging so that any
@@ -1047,12 +1241,18 @@ class WP_Query { // Apply post-paging filters on where and join. Only plugins that
// manipulate paging queries should use these hooks.
+
+ // Announce current selection parameters. For use by caching plugins.
+ do_action( 'posts_selection', $where . $groupby . $q['orderby'] . $limits . $join );
+
$where = apply_filters('posts_where_paged', $where);
$groupby = apply_filters('posts_groupby', $groupby);
if ( ! empty($groupby) )
$groupby = 'GROUP BY ' . $groupby;
$join = apply_filters('posts_join_paged', $join);
$orderby = apply_filters('posts_orderby', $q['orderby']);
+ if ( !empty( $orderby ) )
+ $orderby = 'ORDER BY ' . $orderby;
$distinct = apply_filters('posts_distinct', $distinct);
$fields = apply_filters('posts_fields', "$wpdb->posts.*");
$limits = apply_filters( 'post_limits', $limits );
@@ -1060,10 +1260,12 @@ class WP_Query { if ( !empty($limits) )
$found_rows = 'SQL_CALC_FOUND_ROWS';
- $request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby ORDER BY $orderby $limits";
+ $request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";
$this->request = apply_filters('posts_request', $request);
$this->posts = $wpdb->get_results($this->request);
+ // Raw results filter. Prior to status checks.
+ $this->posts = apply_filters('posts_results', $this->posts);
if ( $this->is_comment_feed && $this->is_singular ) {
$cjoin = apply_filters('comment_feed_join', '');
@@ -1089,7 +1291,7 @@ class WP_Query { // User must be logged in to view unpublished posts.
$this->posts = array();
} else {
- if ('draft' == $status) {
+ if (in_array($status, array('draft', 'pending')) ) {
// User must have edit permissions on the draft to preview.
if (! current_user_can('edit_post', $this->posts[0]->ID)) {
$this->posts = array();
@@ -1212,6 +1414,13 @@ class WP_Query { $category = &get_category($cat);
$this->queried_object = &$category;
$this->queried_object_id = (int) $cat;
+ } else if ($this->is_tag) {
+ $tag_id = $this->get('tag_id');
+ $tag = &get_term($tag_id, 'post_tag');
+ if ( is_wp_error( $tag ) )
+ return $tag;
+ $this->queried_object = &$tag;
+ $this->queried_object_id = (int) $tag_id;
} else if ($this->is_posts_page) {
$this->queried_object = & get_page(get_option('page_for_posts'));
$this->queried_object_id = (int) $this->queried_object->ID;
@@ -1288,7 +1497,7 @@ function wp_old_slug_redirect () { // Setup global post data.
function setup_postdata($post) {
- global $id, $postdata, $authordata, $day, $page, $pages, $multipage, $more, $numpages, $wp_query;
+ global $id, $postdata, $authordata, $day, $currentmonth, $page, $pages, $multipage, $more, $numpages, $wp_query;
global $pagenow;
$id = (int) $post->ID;
diff --git a/wp-includes/registration.php b/wp-includes/registration.php index cd387fd..c5b0fb1 100644 --- a/wp-includes/registration.php +++ b/wp-includes/registration.php @@ -1,34 +1,47 @@ <?php +/** + * Checks whether the given username exists. + * @param string $username Username. + * @return mixed The user's ID on success, and null on failure. + */ function username_exists( $username ) { - global $wpdb; - $username = sanitize_user( $username ); - $user = get_userdatabylogin($username); - if ( $user ) + if ( $user = get_userdatabylogin( sanitize_user( $username ) ) ) { return $user->ID; - - return null; + } else { + return null; + } } - +/** + * Checks whether the given email exists. + * @global object $wpdb WordPress database layer. + * @param string $email Email. + * @return mixed The user's ID on success, and false on failure. + */ function email_exists( $email ) { global $wpdb; - $email = addslashes( $email ); - return $wpdb->get_var("SELECT ID FROM $wpdb->users WHERE user_email = '$email'"); + $email = $wpdb->escape( $email ); + return $wpdb->get_var( "SELECT ID FROM $wpdb->users WHERE user_email = '$email'" ); } - +/** + * Checks whether an username is valid. + * @param string $username Username. + * @return bool A filtered boolean. + */ function validate_username( $username ) { - $name = sanitize_user($username, true); - $valid = true; - - if ( $name != $username ) - $valid = false; - - return apply_filters('validate_username', $valid, $username); + $sanitized = sanitize_user( $username, true ); + $valid = ( $sanitized == $username ); + return apply_filters( 'validate_username', $valid, $username ); } - +/** + * Insert an user into the database. + * @global object $wpdb WordPress database layer. + * @param array $userdata An array of user data. + * @return int The newly created user's ID. + */ function wp_insert_user($userdata) { global $wpdb; @@ -130,7 +143,12 @@ function wp_insert_user($userdata) { return $user_id; } - +/** + * Update an user in the database. + * @global object $wpdb WordPress database layer. + * @param array $userdata An array of user data. + * @return int The updated user's ID. + */ function wp_update_user($userdata) { global $wpdb; @@ -164,7 +182,15 @@ function wp_update_user($userdata) { return $user_id; } - +/** + * A simpler way of inserting an user into the database. + * See also: wp_insert_user(). + * @global object $wpdb WordPress database layer. + * @param string $username The user's username. + * @param string $password The user's password. + * @param string $email The user's email (optional). + * @return int The new user's ID. + */ function wp_create_user($username, $password, $email = '') { global $wpdb; @@ -176,7 +202,14 @@ function wp_create_user($username, $password, $email = '') { return wp_insert_user($userdata); } - +/** + * An alias of wp_create_user(). + * @param string $username The user's username. + * @param string $password The user's password. + * @param string $email The user's email (optional). + * @return int The new user's ID. + * @deprecated + */ function create_user($username, $password, $email) { return wp_create_user($username, $password, $email); } diff --git a/wp-includes/rewrite.php b/wp-includes/rewrite.php index 19d5224..bd5daf0 100644 --- a/wp-includes/rewrite.php +++ b/wp-includes/rewrite.php @@ -4,9 +4,9 @@ *******************************************************************************/ //Add a straight rewrite rule -function add_rewrite_rule($regex, $redirect) { +function add_rewrite_rule($regex, $redirect, $after = 'bottom') { global $wp_rewrite; - $wp_rewrite->add_rule($regex, $redirect); + $wp_rewrite->add_rule($regex, $redirect, $after); } //Add a new tag (like %postname%) @@ -46,11 +46,12 @@ 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_TAGS', 1024 ); +define('EP_AUTHORS', 2048); +define('EP_PAGES', 4096); //pseudo-places define('EP_NONE', 0 ); -define('EP_ALL', 4095); +define('EP_ALL', 8191); //and an endpoint, like /trackback/ function add_rewrite_endpoint($name, $places) { @@ -62,7 +63,7 @@ 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 @@ -161,7 +162,9 @@ class WP_Rewrite { var $permalink_structure; var $use_trailing_slashes; var $category_base; + var $tag_base; var $category_structure; + var $tag_structure; var $author_base = 'author'; var $author_structure; var $date_structure; @@ -177,8 +180,9 @@ class WP_Rewrite { var $index = 'index.php'; var $matches = ''; var $rules; - var $extra_rules; //those not generated by the class, see add_rewrite_rule() - var $non_wp_rules; //rules that don't redirect to WP's index.php + var $extra_rules = array(); //those not generated by the class, see add_rewrite_rule() + var $extra_rules_top = array(); //those not generated by the class, see add_rewrite_rule() + var $non_wp_rules = array(); //rules that don't redirect to WP's index.php var $endpoints; var $use_verbose_rules = false; var $rewritecode = @@ -192,6 +196,7 @@ class WP_Rewrite { '%postname%', '%post_id%', '%category%', + '%tag%', '%author%', '%pagename%', '%search%' @@ -208,6 +213,7 @@ class WP_Rewrite { '([^/]+)', '([0-9]+)', '(.+?)', + '(.+?)', '([^/]+)', '([^/]+)', '(.+)' @@ -224,6 +230,7 @@ class WP_Rewrite { 'name=', 'p=', 'category_name=', + 'tag=', 'author_name=', 'pagename=', 's=' @@ -389,6 +396,26 @@ class WP_Rewrite { return $this->category_structure; } + function get_tag_permastruct() { + if (isset($this->tag_structure)) { + return $this->tag_structure; + } + + if (empty($this->permalink_structure)) { + $this->tag_structure = ''; + return false; + } + + if (empty($this->tag_base)) + $this->tag_structure = $this->front . 'tag/'; + else + $this->tag_structure = $this->tag_base . '/'; + + $this->tag_structure .= '%tag%'; + + return $this->tag_structure; + } + function get_author_permastruct() { if (isset($this->author_structure)) { return $this->author_structure; @@ -745,6 +772,10 @@ class WP_Rewrite { $category_rewrite = $this->generate_rewrite_rules($this->get_category_permastruct(), EP_CATEGORIES); $category_rewrite = apply_filters('category_rewrite_rules', $category_rewrite); + // Tags + $tag_rewrite = $this->generate_rewrite_rules($this->get_tag_permastruct(), EP_TAGS); + $tag_rewrite = apply_filters('tag_rewrite_rules', $tag_rewrite); + // Authors $author_rewrite = $this->generate_rewrite_rules($this->get_author_permastruct(), EP_AUTHORS); $author_rewrite = apply_filters('author_rewrite_rules', $author_rewrite); @@ -754,7 +785,7 @@ class WP_Rewrite { $page_rewrite = apply_filters('page_rewrite_rules', $page_rewrite); // Put them together. - $this->rules = array_merge($robots_rewrite, $default_feeds, $page_rewrite, $root_rewrite, $comments_rewrite, $search_rewrite, $category_rewrite, $author_rewrite, $date_rewrite, $post_rewrite, $this->extra_rules); + $this->rules = array_merge($this->extra_rules_top, $robots_rewrite, $default_feeds, $page_rewrite, $root_rewrite, $comments_rewrite, $search_rewrite, $category_rewrite, $tag_rewrite, $author_rewrite, $date_rewrite, $post_rewrite, $this->extra_rules); do_action_ref_array('generate_rewrite_rules', array(&$this)); $this->rules = apply_filters('rewrite_rules_array', $this->rules); @@ -841,14 +872,18 @@ class WP_Rewrite { } //Add a straight rewrite rule - function add_rule($regex, $redirect) { + function add_rule($regex, $redirect, $after = 'bottom') { //get everything up to the first ? $index = (strpos($redirect, '?') == false ? strlen($redirect) : strpos($redirect, '?')); $front = substr($redirect, 0, $index); if ($front != $this->index) { //it doesn't redirect to WP's index.php $this->add_external_rule($regex, $redirect); } else { - $this->extra_rules[$regex] = $redirect; + if ( 'bottom' == $after) + $this->extra_rules = array_merge($this->extra_rules, array($regex => $redirect)); + else + $this->extra_rules_top = array_merge($this->extra_rules_top, array($regex => $redirect)); + //$this->extra_rules[$regex] = $redirect; } } @@ -880,7 +915,8 @@ 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' ); + $this->tag_base = get_option( 'tag_base' ); unset($this->category_structure); unset($this->author_structure); unset($this->date_structure); @@ -905,6 +941,13 @@ class WP_Rewrite { } } + function set_tag_base( $tag_base ) { + if ( $tag_base != $this->tag_base ) { + update_option( 'tag_base', $tag_base ); + $this->init(); + } + } + function WP_Rewrite() { $this->init(); } diff --git a/wp-includes/rss.php b/wp-includes/rss.php index 72b7bb1..8746767 100644 --- a/wp-includes/rss.php +++ b/wp-includes/rss.php @@ -1,4 +1,6 @@ <?php +do_action('load_feed_engine'); + /* * Project: MagpieRSS: a simple RSS integration tool * File: A compiled file for RSS syndication @@ -375,6 +377,7 @@ class MagpieRSS { } require_once( dirname(__FILE__) . '/class-snoopy.php'); +if ( !function_exists('fetch_rss') ) : function fetch_rss ($url) { // initialize constants init(); @@ -501,6 +504,7 @@ function fetch_rss ($url) { } // end if ( !MAGPIE_CACHE_ON ) { } // end fetch_rss() +endif; function _fetch_remote_file ($url, $headers = "" ) { // Snoopy is an HTTP client in PHP @@ -775,6 +779,7 @@ class RSSCache { } } +if ( !function_exists('parse_w3cdtf') ) : function parse_w3cdtf ( $date_str ) { # regex to match wc3dtf @@ -815,27 +820,35 @@ 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); - if ( $rss ) { - echo "<ul>"; - $rss->items = array_slice($rss->items, 0, $num_items); - foreach ($rss->items as $item ) { - echo "<li>\n"; - echo "<a href='$item[link]' title='$item[description]'>"; - echo htmlentities($item['title']); - echo "</a><br />\n"; - echo "</li>\n"; - } - echo "</ul>"; - } - else { - echo "an error has occured the feed is probably down, try again later."; +} +endif; + +if ( !function_exists('wp_rss') ) : +function wp_rss( $url, $num_items = -1 ) { + if ( $rss = fetch_rss( $url ) ) { + echo '<ul>'; + + if ( $num_items !== -1 ) { + $rss->items = array_slice( $rss->items, 0, $num_items ); + } + + foreach ( $rss->items as $item ) { + printf( + '<li><a href="%1$s" title="%2$s">%3$s</a></li>', + clean_url( $item['link'] ), + attribute_escape( strip_tags( $item['description'] ) ), + htmlentities( $item['title'] ) + ); + } + + echo '</ul>'; + } else { + _e( 'An error has occurred, which probably means the feed is down. Try again later.' ); } } +endif; +if ( !function_exists('get_rss') ) : function get_rss ($url, $num_items = 5) { // Like get posts, but for RSS $rss = fetch_rss($url); if ( $rss ) { @@ -851,4 +864,6 @@ function get_rss ($url, $num_items = 5) { // Like get posts, but for RSS return false; } } +endif; + ?> diff --git a/wp-includes/script-loader.php b/wp-includes/script-loader.php index 8ee90aa..2a7730c 100644 --- a/wp-includes/script-loader.php +++ b/wp-includes/script-loader.php @@ -2,6 +2,7 @@ class WP_Scripts { var $scripts = array(); var $queue = array(); + var $to_print = array(); var $printed = array(); var $args = array(); @@ -11,8 +12,11 @@ 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, '3958' ); $this->localize( 'quicktags', 'quicktagsL10n', array( 'quickLinks' => __('(Quick Links)'), @@ -25,11 +29,15 @@ class WP_Scripts { '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' ); + + $this->add( 'tiny_mce', '/wp-includes/js/tinymce/tiny_mce_gzip.php', false, '20070528' ); $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( 'wp_tiny_mce', $mce_config, array('tiny_mce'), '20070528' ); + + $this->add( 'prototype', '/wp-includes/js/prototype.js', false, '1.5.1.1'); + $this->add( 'autosave', '/wp-includes/js/autosave.js', array('prototype', 'sack'), '20070306'); $this->localize( 'autosave', 'autosaveL10n', array( 'autosaveInterval' => apply_filters('autosave_interval', '120'), @@ -38,6 +46,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', @@ -45,21 +54,28 @@ 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->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/scriptaculous.js', array('prototype'), '1.7.1-b3'); + $this->add( 'scriptaculous-builder', '/wp-includes/js/scriptaculous/builder.js', array('scriptaculous-root'), '1.7.1-b3'); + $this->add( 'scriptaculous-dragdrop', '/wp-includes/js/scriptaculous/dragdrop.js', array('scriptaculous-builder', 'scriptaculous-effects'), '1.7.1-b3'); + $this->add( 'scriptaculous-effects', '/wp-includes/js/scriptaculous/effects.js', array('scriptaculous-root'), '1.7.1-b3'); + $this->add( 'scriptaculous-slider', '/wp-includes/js/scriptaculous/slider.js', array('scriptaculous-effects'), '1.7.1-b3'); + $this->add( 'scriptaculous-sound', '/wp-includes/js/scriptaculous/sound.js', array( 'scriptaculous-root' ), '1.7.1-b3' ); + $this->add( 'scriptaculous-controls', '/wp-includes/js/scriptaculous/controls.js', array('scriptaculous-root'), '1.7.1-b3'); + $this->add( 'scriptaculous', '', array('scriptaculous-dragdrop', 'scriptaculous-slider', 'scriptaculous-controls'), '1.7.1-b3'); + $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.2'); + + $this->add( 'jquery', '/wp-includes/js/jquery/jquery.js', false, '1.1.4'); + $this->add( 'jquery-form', '/wp-includes/js/jquery/jquery.form.js', array('jquery'), '1.0.3'); $this->add( 'interface', '/wp-includes/js/jquery/interface.js', array('jquery'), '1.2'); + if ( is_admin() ) { global $pagenow; $man = false; @@ -78,7 +94,7 @@ class WP_Scripts { break; endswitch; if ( $man ) { - $this->add( 'dbx-admin-key', '/wp-admin/dbx-admin-key.js', array('dbx'), '20070417' ); + $this->add( 'dbx-admin-key', '/wp-admin/js/dbx-admin-key.js', array('dbx'), '20070417' ); $this->localize( 'dbx-admin-key', 'dbxL10n', array( 'manager' => $man, 'open' => __('open'), @@ -89,17 +105,22 @@ class WP_Scripts { 'toggleKey' => __(', or press the enter key to %toggle% it'), ) ); } - $this->add( 'ajaxcat', '/wp-admin/cat.js', array('listman'), '20070417' ); + $this->add( 'ajaxcat', '/wp-admin/js/cat.js', array('listman'), '20070724' ); $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'), '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' ); + $this->add( 'ajaxlinkcat', '/wp-admin/js/link-cat.js', array('listman'), '200700601' ); + $this->localize( 'ajaxlinkcat', 'linkcatL10n', array( + 'add' => attribute_escape(__('Add')), + 'how' => __('Separate multiple categories with commas.') + ) ); + $this->add( 'admin-categories', '/wp-admin/js/categories.js', array('listman'), '3684' ); + $this->add( 'admin-custom-fields', '/wp-admin/js/custom-fields.js', array('listman'), '3733' ); + $this->add( 'admin-comments', '/wp-admin/js/edit-comments.js', array('listman'), '20070327' ); + $this->add( 'admin-users', '/wp-admin/js/users.js', array('listman'), '4583' ); + $this->add( 'xfn', '/wp-admin/js/xfn.js', false, '3517' ); + $this->add( 'upload', '/wp-admin/js/upload.js', array('jquery'), '20070518' ); $this->localize( 'upload', 'uploadL10n', array( 'browseTitle' => attribute_escape(__('Browse your files')), 'back' => __('« Back'), @@ -134,27 +155,15 @@ class WP_Scripts { * @return array Scripts that have been printed */ function print_scripts( $handles = false ) { + global $wp_db_version; + // Print the queue if nothing is passed. If a string is passed, print that script. If an array is passed, print those scripts. $handles = false === $handles ? $this->queue : (array) $handles; - $handles = $this->all_deps( $handles ); - $this->_print_scripts( $handles ); - return $this->printed; - } + $this->all_deps( $handles ); - /** - * Internally used helper function for printing script tags - * - * @param array handles Hierarchical array of scripts to be printed - * @see WP_Scripts::all_deps() - */ - function _print_scripts( $handles ) { - global $wp_db_version; + $to_print = apply_filters( 'print_scripts_array', array_keys($this->to_print) ); - foreach( array_keys($handles) as $handle ) { - if ( !$handles[$handle] ) - return; - elseif ( is_array($handles[$handle]) ) - $this->_print_scripts( $handles[$handle] ); + foreach( $to_print as $handle ) { if ( !in_array($handle, $this->printed) && isset($this->scripts[$handle]) ) { if ( $this->scripts[$handle]->src ) { // Else it defines a group. $ver = $this->scripts[$handle]->ver ? $this->scripts[$handle]->ver : $wp_db_version; @@ -162,11 +171,11 @@ class WP_Scripts { $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"; @@ -175,6 +184,9 @@ class WP_Scripts { $this->printed[] = $handle; } } + + $this->to_print = array(); + return $this->printed; } function print_scripts_l10n( $handle ) { @@ -199,33 +211,43 @@ class WP_Scripts { /** * Determines dependencies of scripts * - * Recursively builds hierarchical array of script dependencies. Does NOT catch infinite loops. + * Recursively builds array of scripts to print taking dependencies into account. Does NOT catch infinite loops. * * @param mixed handles Accepts (string) script name or (array of strings) script names * @param bool recursion Used internally when function calls itself - * @return array Hierarchical array of dependencies */ function all_deps( $handles, $recursion = false ) { - if ( ! $handles = (array) $handles ) - return array(); - $return = array(); + if ( !$handles = (array) $handles ) + return false; + foreach ( $handles as $handle ) { $handle = explode('?', $handle); if ( isset($handle[1]) ) $this->args[$handle[0]] = $handle[1]; $handle = $handle[0]; - if ( is_null($return[$handle]) ) // Prime the return array with $handles - $return[$handle] = true; - if ( $this->scripts[$handle]->deps ) { - if ( false !== $return[$handle] && array_diff($this->scripts[$handle]->deps, array_keys($this->scripts)) ) - $return[$handle] = false; // Script required deps which don't exist + + if ( isset($this->to_print[$handle]) ) // Already grobbed it and its deps + continue; + + $keep_going = true; + if ( !isset($this->scripts[$handle]) ) + $keep_going = false; // Script doesn't exist + elseif ( $this->scripts[$handle]->deps && array_diff($this->scripts[$handle]->deps, array_keys($this->scripts)) ) + $keep_going = false; // Script requires deps which don't exist (not a necessary check. efficiency?) + elseif ( $this->scripts[$handle]->deps && !$this->all_deps( $this->scripts[$handle]->deps, true ) ) + $keep_going = false; // Script requires deps which don't exist + + if ( !$keep_going ) { // Either script or its deps don't exist. + if ( $recursion ) + return false; // Abort this branch. else - $return[$handle] = $this->all_deps( $this->scripts[$handle]->deps, true ); // Build the hierarchy - } - if ( $recursion && false === $return[$handle] ) - return false; // Cut the branch + continue; // We're at the top level. Move on to the next one. + } + + $this->to_print[$handle] = true; } - return $return; + + return true; } /** diff --git a/wp-includes/taxonomy.php b/wp-includes/taxonomy.php new file mode 100644 index 0000000..ea2f432 --- /dev/null +++ b/wp-includes/taxonomy.php @@ -0,0 +1,1410 @@ +<?php + +// +// Taxonomy Registration +// + +/** + * @global array $wp_taxonomies Fill me out please + */ +$wp_taxonomies = array(); +$wp_taxonomies['category'] = (object) array('name' => 'category', 'object_type' => 'post', 'hierarchical' => true, 'update_count_callback' => '_update_post_term_count'); +$wp_taxonomies['post_tag'] = (object) array('name' => 'post_tag', 'object_type' => 'post', 'hierarchical' => false, 'update_count_callback' => '_update_post_term_count'); +$wp_taxonomies['link_category'] = (object) array('name' => 'link_category', 'object_type' => 'link', 'hierarchical' => false); + +/** + * get_object_taxonomies() - Return all of the taxonomy names that are of $object_type + * + * It appears that this function can be used to find all of the names inside of + * $wp_taxonomies global variable. + * + * @example + * <?php $taxonomies = get_object_taxonomies('post'); ?> + * Should result in <pre>Array( + * 'category', + * 'post_tag' + * )</pre> + * + * @package Taxonomy + * @global array $wp_taxonomies + * @param string $object_type Name of the type of taxonomy object + * @return array The names of all within the object_type. + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function get_object_taxonomies($object_type) { + global $wp_taxonomies; + + $taxonomies = array(); + foreach ( $wp_taxonomies as $taxonomy ) { + if ( $object_type == $taxonomy->object_type ) + $taxonomies[] = $taxonomy->name; + } + + return $taxonomies; +} + +/** + * get_taxonomy() - Returns the "taxonomy" object of $taxonomy. + * + * The get_taxonomy function will first check that the parameter string given + * is a taxonomy object and if it is, it will return it. + * + * @package Taxonomy + * @global array $wp_taxonomies + * @param string $taxonomy Name of taxonomy object to return + * @return object|bool The Taxonomy Object or false if taxonomy doesn't exist + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function get_taxonomy( $taxonomy ) { + global $wp_taxonomies; + + if ( ! is_taxonomy($taxonomy) ) + return false; + + return $wp_taxonomies[$taxonomy]; +} + +/** + * is_taxonomy() - Checks that the taxonomy name exists + * + * @package Taxonomy + * @global array $wp_taxonomies + * @param string $taxonomy Name of taxonomy object + * @return bool Whether the taxonomy exists or not. + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function is_taxonomy( $taxonomy ) { + global $wp_taxonomies; + + return isset($wp_taxonomies[$taxonomy]); +} + +/** + * is_taxonomy_hierarchical() - Whether the taxonomy object is hierarchical + * + * Checks to make sure that the taxonomy is an object first. Then Gets the object, and finally + * returns the hierarchical value in the object. + * + * A false return value, might also mean that the taxonomy does not exist. + * + * @package Taxonomy + * @global array $wp_taxonomies + * @param string $taxonomy Name of taxonomy object + * @return bool Whether the taxonomy is hierarchical + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function is_taxonomy_hierarchical($taxonomy) { + if ( ! is_taxonomy($taxonomy) ) + return false; + + $taxonomy = get_taxonomy($taxonomy); + return $taxonomy->hierarchical; +} + +/** + * register_taxonomy() - Create or modify a taxonomy object. + * + * A simple function for creating or modifying a taxonomy object based on the parameters given. + * The function will accept an array (third optional parameter), along with strings for the + * taxonomy name and another string for the object type. + * + * The function keeps a default set, allowing for the $args to be optional but allow the other + * functions to still work. It is possible to overwrite the default set, which contains two + * keys: hierarchical and update_count_callback. + * + * hierarachical has some defined purpose at other parts of the API and is a boolean value. + * + * update_count_callback works much like a hook, in that it will be called (or something from + * somewhere). + * + * @package Taxonomy + * @global array $wp_taxonomies + * @param string $taxonomy Name of taxonomy object + * @param string $object_type Name of the object type for the taxonomy object. + * @param array|string $args See above description for the two keys values. + * @return null Nothing is returned, so expect error maybe or use is_taxonomy() to check. + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function register_taxonomy( $taxonomy, $object_type, $args = array() ) { + global $wp_taxonomies; + + $defaults = array('hierarchical' => false, 'update_count_callback' => ''); + $args = wp_parse_args($args, $defaults); + + $args['name'] = $taxonomy; + $args['object_type'] = $object_type; + $wp_taxonomies[$taxonomy] = (object) $args; +} + +// +// Term API +// + +/** + * get_objects_in_term() - Return object_ids of valid taxonomy and term + * + * The strings of $taxonomies must exist before this function will continue. On failure of finding + * a valid taxonomy, it will return an WP_Error class, kind of like Exceptions in PHP 5, except you + * can't catch them. Even so, you can still test for the WP_Error class and get the error message. + * + * The $terms aren't checked the same as $taxonomies, but still need to exist for $object_ids to + * be returned. + * + * It is possible to change the order that object_ids is returned by either using PHP sort family + * functions or using the database by using $args with either ASC or DESC array. The value should + * be in the key named 'order'. + * + * @package Taxonomy + * @subpackage Term + * @global object $wpdb Database Query + * @param string|array $terms String of term or array of string values of terms that will be used + * @param string|array $taxonomies String of taxonomy name or Array of string values of taxonomy names + * @param array|string $args Change the order of the object_ids, either ASC or DESC + * @return object WP_Error - A PHP 4 compatible Exception class prototype + * @return array Empty array if there are no $object_ids + * @return array Array of $object_ids + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function get_objects_in_term( $terms, $taxonomies, $args = array() ) { + global $wpdb; + + if ( !is_array( $terms) ) + $terms = array($terms); + + if ( !is_array($taxonomies) ) + $taxonomies = array($taxonomies); + + foreach ( $taxonomies as $taxonomy ) { + if ( ! is_taxonomy($taxonomy) ) + return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); + } + + $defaults = array('order' => 'ASC'); + $args = wp_parse_args( $args, $defaults ); + extract($args, EXTR_SKIP); + + $terms = array_map('intval', $terms); + + $taxonomies = "'" . implode("', '", $taxonomies) . "'"; + $terms = "'" . implode("', '", $terms) . "'"; + + $object_ids = $wpdb->get_col("SELECT tr.object_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tt.term_id IN ($terms) ORDER BY tr.object_id $order"); + + if ( ! $object_ids ) + return array(); + + return $object_ids; +} + +/** + * get_term() - + * + * + * + * @package Taxonomy + * @subpackage Term + * @global object $wpdb Database Query + * @param int|object $term + * @param string $taxonomy + * @param string $output Either OBJECT, ARRAY_A, or ARRAY_N + * @return mixed Term Row from database + * + * @internal + * This won't appear but just a note to say that this is all conjecture and parts or whole + * might be inaccurate or wrong. + */ +function &get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { + global $wpdb; + + if ( empty($term) ) + return null; + + if ( ! is_taxonomy($taxonomy) ) + return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); + + if ( is_object($term) ) { + wp_cache_add($term->term_id, $term, $taxonomy); + $_term = $term; + } else { + $term = (int) $term; + if ( ! $_term = wp_cache_get($term, $taxonomy) ) { + $_term = $wpdb->get_row("SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = '$taxonomy' AND t.term_id = '$term' LIMIT 1"); + wp_cache_add($term, $_term, $taxonomy); + } + } + + /** + * @internal + * Filter tag is basically: filter 'type' 'hook_name' 'description' + * + * Takes two parameters the term Object and the taxonomy name. Must return term object. + * @filter object get_term Used in @see get_term() as a catch-all filter for every $term + */ + $_term = apply_filters('get_term', $_term, $taxonomy); + /** + * @internal + * Filter tag is basically: filter 'type' 'hook_name' 'description' + * + * Takes two parameters the term Object and the taxonomy name. Must return term object. + * $taxonomy will be the taxonomy name, so for example, if 'category', it would be 'get_category' + * as the filter name. + * Useful for custom taxonomies or plugging into default taxonomies. + * @filter object get_$taxonomy Used in @see get_term() as specific filter for each $taxonomy. + */ + $_term = apply_filters("get_$taxonomy", $_term, $taxonomy); + $_term = sanitize_term($_term, $taxonomy, $filter); + + if ( $output == OBJECT ) { + return $_term; + } elseif ( $output == ARRAY_A ) { + return get_object_vars($_term); + } elseif ( $output == ARRAY_N ) { + return array_values(get_object_vars($_term)); + } else { + return $_term; + } +} + +/** + * get_term_by() - + * + * + * + * @package Taxonomy + * @subpackage Term + * @global object $wpdb Database Query + * @param string $field + * @param string $value + * @param string $taxonomy + * @param string $output Either OBJECT, ARRAY_A, or ARRAY_N + * @return mixed Term Row from database + * + * @internal + * This won't appear but just a note to say that this is all conjecture and parts or whole + * might be inaccurate or wrong. + */ +function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw') { + global $wpdb; + + if ( ! is_taxonomy($taxonomy) ) + return false; + + if ( 'slug' == $field ) { + $field = 't.slug'; + $value = sanitize_title($value); + if ( empty($value) ) + return false; + } else if ( 'name' == $field ) { + // Assume already escaped + $field = 't.name'; + } else { + $field = 't.term_id'; + $value = (int) $value; + } + + $term = $wpdb->get_row("SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = '$taxonomy' AND $field = '$value' LIMIT 1"); + if ( !$term ) + return false; + + wp_cache_add($term->term_id, $term, $taxonomy); + + $term = sanitize_term($term, $taxonomy, $filter); + + if ( $output == OBJECT ) { + return $term; + } elseif ( $output == ARRAY_A ) { + return get_object_vars($term); + } elseif ( $output == ARRAY_N ) { + return array_values(get_object_vars($term)); + } else { + return $term; + } +} + +/** + * get_term_children() - Merge all term children into a single array. + * + * This recursive function will merge all of the children of $term into + * the same array. + * + * Only useful for taxonomies which are hierarchical. + * + * @package Taxonomy + * @subpackage Term + * @global object $wpdb Database Query + * @param string $term Name of Term to get children + * @param string $taxonomy Taxonomy Name + * @return array List of Term Objects + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function get_term_children( $term, $taxonomy ) { + if ( ! is_taxonomy($taxonomy) ) + return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); + + $terms = _get_term_hierarchy($taxonomy); + + if ( ! isset($terms[$term]) ) + return array(); + + $children = $terms[$term]; + + foreach ( $terms[$term] as $child ) { + if ( isset($terms[$child]) ) + $children = array_merge($children, get_term_children($child, $taxonomy)); + } + + return $children; +} + +/** + * get_term_field() - Get sanitized Term field + * + * Does checks for $term, based on the $taxonomy. The function is for + * contextual reasons and for simplicity of usage. @see sanitize_term_field() for + * more information. + * + * @package Taxonomy + * @subpackage Term + * @param string $field Term field to fetch + * @param int $term Term ID + * @param string $taxonomy Taxonomy Name + * @param string $context ?? + * @return mixed @see sanitize_term_field() + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function get_term_field( $field, $term, $taxonomy, $context = 'display' ) { + $term = (int) $term; + $term = get_term( $term, $taxonomy ); + if ( is_wp_error($term) ) + return $term; + + if ( !is_object($term) ) + return ''; + + if ( !isset($term->$field) ) + return ''; + + return sanitize_term_field($field, $term->$field, $term->term_id, $taxonomy, $context); +} + +/** + * get_term_to_edit() - Sanitizes Term for editing + * + * Return value is @see sanitize_term() and usage is for sanitizing the term + * for editing. Function is for contextual and simplicity. + * + * @package Taxonomy + * @subpackage Term + * @param int|object $id Term ID or Object + * @param string $taxonomy Taxonomy Name + * @return mixed @see sanitize_term() + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function get_term_to_edit( $id, $taxonomy ) { + $term = get_term( $id, $taxonomy ); + + if ( is_wp_error($term) ) + return $term; + + if ( !is_object($term) ) + return ''; + + return sanitize_term($term, $taxonomy, 'edit'); +} + +/** + * get_terms() - + * + * + * + * @package Taxonomy + * @subpackage Term + * @param string|array Taxonomy name or list of Taxonomy names + * @param string|array $args ?? + * @return array List of Term Objects and their children. + * + * @internal + * This is all conjecture and might be partially or completely inaccurate. + */ +function &get_terms($taxonomies, $args = '') { + global $wpdb; + + $single_taxonomy = false; + if ( !is_array($taxonomies) ) { + $single_taxonomy = true; + $taxonomies = array($taxonomies); + } + + foreach ( $taxonomies as $taxonomy ) { + if ( ! is_taxonomy($taxonomy) ) + return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); + } + + $in_taxonomies = "'" . implode("', '", $taxonomies) . "'"; + + $defaults = array('orderby' => 'name', 'order' => 'ASC', + 'hide_empty' => true, 'exclude' => '', 'include' => '', + 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '', + 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '', + 'pad_counts' => false); + $args = wp_parse_args( $args, $defaults ); + $args['number'] = (int) $args['number']; + if ( !$single_taxonomy || !is_taxonomy_hierarchical($taxonomies[0]) || + '' != $args['parent'] ) { + $args['child_of'] = 0; + $args['hierarchical'] = false; + $args['pad_counts'] = false; + } + + if ( 'all' == $args['get'] ) { + $args['child_of'] = 0; + $args['hide_empty'] = 0; + $args['hierarchical'] = false; + $args['pad_counts'] = false; + } + extract($args, EXTR_SKIP); + + if ( $child_of ) { + $hierarchy = _get_term_hierarchy($taxonomies[0]); + if ( !isset($hierarchy[$child_of]) ) + return array(); + } + + if ( $parent ) { + $hierarchy = _get_term_hierarchy($taxonomies[0]); + if ( !isset($hierarchy[$parent]) ) + return array(); + } + + $key = md5( serialize( $args ) . serialize( $taxonomies ) ); + if ( $cache = wp_cache_get( 'get_terms', 'terms' ) ) { + if ( isset( $cache[ $key ] ) ) + return apply_filters('get_terms', $cache[$key], $taxonomies, $args); + } + + if ( 'count' == $orderby ) + $orderby = 'tt.count'; + else if ( 'name' == $orderby ) + $orderby = 't.name'; + else + $orderby = 't.term_id'; + + $where = ''; + $inclusions = ''; + if ( !empty($include) ) { + $exclude = ''; + $interms = preg_split('/[\s,]+/',$include); + if ( count($interms) ) { + foreach ( $interms as $interm ) { + if (empty($inclusions)) + $inclusions = ' AND ( t.term_id = ' . intval($interm) . ' '; + else + $inclusions .= ' OR t.term_id = ' . intval($interm) . ' '; + } + } + } + + if ( !empty($inclusions) ) + $inclusions .= ')'; + $where .= $inclusions; + + $exclusions = ''; + if ( !empty($exclude) ) { + $exterms = preg_split('/[\s,]+/',$exclude); + if ( count($exterms) ) { + foreach ( $exterms as $exterm ) { + if (empty($exclusions)) + $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; + else + $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; + } + } + } + + if ( !empty($exclusions) ) + $exclusions .= ')'; + $exclusions = apply_filters('list_terms_exclusions', $exclusions, $args ); + $where .= $exclusions; + + if ( !empty($slug) ) { + $slug = sanitize_title($slug); + $where .= " AND t.slug = '$slug'"; + } + + if ( !empty($name__like) ) + $where .= " AND t.name LIKE '{$name__like}%'"; + + if ( '' != $parent ) { + $parent = (int) $parent; + $where .= " AND tt.parent = '$parent'"; + } + + if ( $hide_empty && !$hierarchical ) + $where .= ' AND tt.count > 0'; + + if ( !empty($number) ) + $number = 'LIMIT ' . $number; + else + $number = ''; + + if ( 'all' == $fields ) + $select_this = 't.*, tt.*'; + else if ( 'ids' == $fields ) + $select_this = 't.term_id'; + else if ( 'names' == $fields ) + $select_this == 't.name'; + + $query = "SELECT $select_this FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy IN ($in_taxonomies) $where ORDER BY $orderby $order $number"; + + if ( 'all' == $fields ) { + $terms = $wpdb->get_results($query); + update_term_cache($terms); + } else if ( 'ids' == $fields ) { + $terms = $wpdb->get_col($query); + } + + if ( empty($terms) ) + return array(); + + if ( $child_of || $hierarchical ) { + $children = _get_term_hierarchy($taxonomies[0]); + if ( ! empty($children) ) + $terms = & _get_term_children($child_of, $terms, $taxonomies[0]); + } + + // Update term counts to include children. + if ( $pad_counts ) + _pad_term_counts($terms, $taxonomies[0]); + + // Make sure we show empty categories that have children. + if ( $hierarchical && $hide_empty ) { + foreach ( $terms as $k => $term ) { + if ( ! $term->count ) { + $children = _get_term_children($term->term_id, $terms, $taxonomies[0]); + foreach ( $children as $child ) + if ( $child->count ) + continue 2; + + // It really is empty + unset($terms[$k]); + } + } + } + reset ( $terms ); + + $cache[ $key ] = $terms; + wp_cache_set( 'get_terms', $cache, 'terms' ); + + $terms = apply_filters('get_terms', $terms, $taxonomies, $args); + return $terms; +} + +/** + * is_term() - Check if Term exists + * + * Returns the index of a defined term, or 0 (false) if the term doesn't exist. + * + * @global $wpdb Database Object + * @param int|string $term The term to check + * @param string $taxonomy The taxonomy name to use + * @return mixed Get the term id or Term Object, if exists. + */ +function is_term($term, $taxonomy = '') { + global $wpdb; + + if ( is_int($term) ) { + if ( 0 == $term ) + return 0; + $where = "t.term_id = '$term'"; + } else { + if ( ! $term = sanitize_title($term) ) + return 0; + $where = "t.slug = '$term'"; + } + + $term_id = $wpdb->get_var("SELECT term_id FROM $wpdb->terms as t WHERE $where"); + + if ( empty($taxonomy) || empty($term_id) ) + return $term_id; + + return $wpdb->get_row("SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE $where AND tt.taxonomy = '$taxonomy'", ARRAY_A); +} + +/** + * sanitize_term() - Sanitize Term all fields + * + * Relys on @see sanitize_term_field() to sanitize the term. The difference + * is that this function will sanitize <strong>all</strong> fields. The context + * is based on @see sanitize_term_field(). + * + * The $term is expected to be either an array or an object. + * + * @param array|object $term The term to check + * @param string $taxonomy The taxonomy name to use + * @param string $context Default is display + * @return array|object Term with all fields sanitized + */ +function sanitize_term($term, $taxonomy, $context = 'display') { + $fields = array('term_id', 'name', 'description', 'slug', 'count', 'parent', 'term_group'); + + $do_object = false; + if ( is_object($term) ) + $do_object = true; + + foreach ( $fields as $field ) { + if ( $do_object ) + $term->$field = sanitize_term_field($field, $term->$field, $term->term_id, $taxonomy, $context); + else + $term[$field] = sanitize_term_field($field, $term[$field], $term['term_id'], $taxonomy, $context); + } + + return $term; +} + +/** + * sanitize_term_field() - + * + * + * + * @global object $wpdb Database Object + * @param string $field Term field to sanitize + * @param string $value Search for this term value + * @param int $term_id Term ID + * @param string $taxonomy Taxonomy Name + * @param string $context Either edit, db, display, attribute, or js. + * @return mixed sanitized field + */ +function sanitize_term_field($field, $value, $term_id, $taxonomy, $context) { + if ( 'parent' == $field || 'term_id' == $field || 'count' == $field + || 'term_group' == $field ) + $value = (int) $value; + + if ( 'edit' == $context ) { + $value = apply_filters("edit_term_$field", $value, $term_id, $taxonomy); + $value = apply_filters("edit_${taxonomy}_$field", $value, $term_id); + if ( 'description' == $field ) + $value = format_to_edit($value); + else + $value = attribute_escape($value); + } else if ( 'db' == $context ) { + $value = apply_filters("pre_term_$field", $value, $taxonomy); + $value = apply_filters("pre_${taxonomy}_$field", $value); + // Back compat filters + if ( 'slug' == $field ) + $value = apply_filters('pre_category_nicename', $value); + + } else if ( 'rss' == $context ) { + $value = apply_filters("term_${field}_rss", $value, $taxonomy); + $value = apply_filters("${taxonomy}_$field_rss", $value); + } else { + // Use display filters by default. + $value = apply_filters("term_$field", $value, $term_id, $taxonomy, $context); + $value = apply_filters("${taxonomy}_$field", $value, $term_id, $context); + } + + if ( 'attribute' == $context ) + $value = attribute_escape($value); + else if ( 'js' == $context ) + $value = js_escape($value); + + return $value; +} + +/** + * wp_count_terms() - Count how many terms are in Taxonomy + * + * Default $args is 'ignore_empty' which can be @example 'ignore_empty=true' or + * @example array('ignore_empty' => true); See @see wp_parse_args() for more + * information on parsing $args. + * + * @global object $wpdb Database Object + * @param string $taxonomy Taxonomy name + * @param array|string $args Overwrite defaults + * @return int How many terms are in $taxonomy + */ +function wp_count_terms( $taxonomy, $args = array() ) { + global $wpdb; + + $defaults = array('ignore_empty' => false); + $args = wp_parse_args($args, $defaults); + extract($args, EXTR_SKIP); + + $where = ''; + if ( $ignore_empty ) + $where = 'AND count > 0'; + + return $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->term_taxonomy WHERE taxonomy = '$taxonomy' $where"); +} + +/** + * wp_delete_object_term_relationships() - + * + * + * + * @global object $wpdb Database Object + * @param int $object_id ?? + * @param string|array $taxonomy List of Taxonomy Names or single Taxonomy name. + */ +function wp_delete_object_term_relationships( $object_id, $taxonomies ) { + global $wpdb; + + $object_id = (int) $object_id; + + if ( !is_array($taxonomies) ) + $taxonomies = array($taxonomies); + + foreach ( $taxonomies as $taxonomy ) { + $terms = wp_get_object_terms($object_id, $taxonomy, 'fields=tt_ids'); + $in_terms = "'" . implode("', '", $terms) . "'"; + $wpdb->query("DELETE FROM $wpdb->term_relationships WHERE object_id = '$object_id' AND term_taxonomy_id IN ($in_terms)"); + wp_update_term_count($terms, $taxonomy); + } +} + +/** + * Removes a term from the database. + */ +function wp_delete_term( $term, $taxonomy, $args = array() ) { + global $wpdb; + + $term = (int) $term; + + if ( ! $ids = is_term($term, $taxonomy) ) + return false; + $tt_id = $ids['term_taxonomy_id']; + + $defaults = array(); + $args = wp_parse_args($args, $defaults); + extract($args, EXTR_SKIP); + + if ( isset($default) ) { + $default = (int) $default; + if ( ! is_term($default, $taxonomy) ) + unset($default); + } + + // Update children to point to new parent + if ( is_taxonomy_hierarchical($taxonomy) ) { + $term_obj = get_term($term, $taxonomy); + if ( is_wp_error( $term_obj ) ) + return $term_obj; + $parent = $term_obj->parent; + + $wpdb->query("UPDATE $wpdb->term_taxonomy SET parent = '$parent' WHERE parent = '$term_obj->term_id' AND taxonomy = '$taxonomy'"); + } + + $objects = $wpdb->get_col("SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = '$tt_id'"); + + foreach ( (array) $objects as $object ) { + $terms = wp_get_object_terms($object, $taxonomy, 'fields=ids'); + if ( 1 == count($terms) && isset($default) ) + $terms = array($default); + else + $terms = array_diff($terms, array($term)); + $terms = array_map('intval', $terms); + wp_set_object_terms($object, $terms, $taxonomy); + } + + $wpdb->query("DELETE FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = '$tt_id'"); + + // Delete the term if no taxonomies use it. + if ( !$wpdb->get_var("SELECT COUNT(*) FROM $wpdb->term_taxonomy WHERE term_id = '$term'") ) + $wpdb->query("DELETE FROM $wpdb->terms WHERE term_id = '$term'"); + + clean_term_cache($term, $taxonomy); + + do_action('delete_term', $term, $tt_id, $taxonomy); + do_action("delete_$taxonomy", $term, $tt_id); + + return true; +} + +/** + * Returns the terms associated with the given object(s), in the supplied taxonomies. + * @param int|array $object_id The id of the object(s)) to retrieve for. + * @param string|array $taxonomies The taxonomies to retrieve terms from. + * @return array The requested term data. + */ +function wp_get_object_terms($object_ids, $taxonomies, $args = array()) { + global $wpdb; + + if ( !is_array($taxonomies) ) + $taxonomies = array($taxonomies); + + foreach ( $taxonomies as $taxonomy ) { + if ( ! is_taxonomy($taxonomy) ) + return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); + } + + if ( !is_array($object_ids) ) + $object_ids = array($object_ids); + $object_ids = array_map('intval', $object_ids); + + $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all'); + $args = wp_parse_args( $args, $defaults ); + extract($args, EXTR_SKIP); + + if ( 'count' == $orderby ) + $orderby = 'tt.count'; + else if ( 'name' == $orderby ) + $orderby = 't.name'; + + $taxonomies = "'" . implode("', '", $taxonomies) . "'"; + $object_ids = implode(', ', $object_ids); + + if ( 'all' == $fields ) + $select_this = 't.*, tt.*'; + else if ( 'ids' == $fields ) + $select_this = 't.term_id'; + else if ( 'names' == $fields ) + $select_this = 't.name'; + else if ( 'all_with_object_id' == $fields ) + $select_this = 't.*, tt.*, tr.object_id'; + + $query = "SELECT $select_this FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tr.object_id IN ($object_ids) ORDER BY $orderby $order"; + + if ( 'all' == $fields || 'all_with_object_id' == $fields ) { + $terms = $wpdb->get_results($query); + update_term_cache($terms); + } else if ( 'ids' == $fields || 'names' == $fields ) { + $terms = $wpdb->get_col($query); + } else if ( 'tt_ids' == $fields ) { + $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ($object_ids) AND tt.taxonomy IN ($taxonomies) ORDER BY tr.term_taxonomy_id $order"); + } + + if ( ! $terms ) + return array(); + + return $terms; +} + +/** + * wp_insert_term() - Adds a new term to the database. Optionally marks it as an alias of an existing term. + * + * + * + * @global $wpdb Database Object + * @param int|string $term The term to add or update. + * @param string $taxonomy The taxonomy to which to add the term + * @param array|string $args Change the values of the inserted term + * @return array The Term ID and Term Taxonomy ID + */ +function wp_insert_term( $term, $taxonomy, $args = array() ) { + global $wpdb; + + if ( ! is_taxonomy($taxonomy) ) + return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); + + if ( is_int($term) && 0 == $term ) + return new WP_Error('invalid_term_id', __('Invalid term ID')); + + $defaults = array( 'alias_of' => '', 'description' => '', 'parent' => 0, 'slug' => ''); + $args = wp_parse_args($args, $defaults); + $args['name'] = $term; + $args['taxonomy'] = $taxonomy; + $args = sanitize_term($args, $taxonomy, 'db'); + extract($args, EXTR_SKIP); + + if ( empty($slug) ) + $slug = sanitize_title($name); + + $term_group = 0; + if ( $alias_of ) { + $alias = $wpdb->fetch_row("SELECT term_id, term_group FROM $wpdb->terms WHERE slug = '$alias_of'"); + if ( $alias->term_group ) { + // The alias we want is already in a group, so let's use that one. + $term_group = $alias->term_group; + } else { + // The alias isn't in a group, so let's create a new one and firstly add the alias term to it. + $term_group = $wpdb->get_var("SELECT MAX(term_group) FROM $wpdb->terms GROUP BY term_group") + 1; + $wpdb->query("UPDATE $wpdb->terms SET term_group = $term_group WHERE term_id = $alias->term_id"); + } + } + + if ( ! $term_id = is_term($slug) ) { + $maxterm = $wpdb->get_var( "SELECT max(term_id) FROM {$wpdb->terms}" ); + $term_id = mt_rand( $maxterm+100, $maxterm+4000 ); + $wpdb->query("INSERT INTO $wpdb->terms (term_id, name, slug, term_group) VALUES ('$term_id', '$name', '$slug', '$term_group')"); + } else if ( is_taxonomy_hierarchical($taxonomy) && !empty($parent) ) { + // If the taxonomy supports hierarchy and the term has a parent, make the slug unique + // by incorporating parent slugs. + $slug = wp_unique_term_slug($slug, (object) $args); + $maxterm = $wpdb->get_var( "SELECT max(term_id) FROM {$wpdb->terms}" ); + $term_id = mt_rand( $maxterm+100, $maxterm+4000 ); + $wpdb->query("INSERT INTO $wpdb->terms (term_id, name, slug, term_group) VALUES ('$term_id', '$name', '$slug', '$term_group')"); + } + + if ( empty($slug) ) { + $slug = sanitize_title($slug, $term_id); + $wpdb->query("UPDATE $wpdb->terms SET slug = '$slug' WHERE term_id = '$term_id'"); + } + + $tt_id = $wpdb->get_var("SELECT tt.term_taxonomy_id FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = '$taxonomy' AND t.term_id = $term_id"); + + if ( !empty($tt_id) ) { + $term_id = apply_filters('term_id_filter', $term_id, $tt_id); + return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id); + } + + $wpdb->query("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ('$term_id', '$taxonomy', '$description', '$parent', '0')"); + $tt_id = (int) $wpdb->insert_id; + + do_action("create_term", $term_id, $tt_id); + do_action("create_$taxonomy", $term_id, $tt_id); + + clean_term_cache($term_id, $taxonomy); + + $term_id = apply_filters('term_id_filter', $term_id, $tt_id); + + clean_term_cache($term_id, $taxonomy); // Clean again if ID changed + + do_action("created_term", $term_id, $tt_id); + do_action("created_$taxonomy", $term_id, $tt_id); + + return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id); +} + +/** + * wp_set_object_terms() - + * + * Relates an object (post, link etc) to a term and taxonomy type. Creates the term and taxonomy + * relationship if it doesn't already exist. Creates a term if it doesn't exist (using the slug). + * + * @global $wpdb Database Object + * @param int $object_id The object to relate to. + * @param array|int|string $term The slug or id of the term. + * @param array|string $taxonomy The context in which to relate the term to the object. + * @param bool $append If false will delete difference of terms. + */ +function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false) { + global $wpdb; + + $object_id = (int) $object_id; + + if ( ! is_taxonomy($taxonomy) ) + return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); + + if ( !is_array($terms) ) + $terms = array($terms); + + if ( ! $append ) + $old_terms = wp_get_object_terms($object_id, $taxonomy, 'fields=tt_ids'); + + $tt_ids = array(); + $term_ids = array(); + + foreach ($terms as $term) { + if ( !$id = is_term($term, $taxonomy) ) + $id = wp_insert_term($term, $taxonomy); + $term_ids[] = $id['term_id']; + $id = $id['term_taxonomy_id']; + $tt_ids[] = $id; + + if ( $wpdb->get_var("SELECT term_taxonomy_id FROM $wpdb->term_relationships WHERE object_id = '$object_id' AND term_taxonomy_id = '$id'") ) + continue; + $wpdb->query("INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id) VALUES ('$object_id', '$id')"); + } + + wp_update_term_count($tt_ids, $taxonomy); + + if ( ! $append ) { + $delete_terms = array_diff($old_terms, $tt_ids); + if ( $delete_terms ) { + $in_delete_terms = "'" . implode("', '", $delete_terms) . "'"; + $wpdb->query("DELETE FROM $wpdb->term_relationships WHERE object_id = '$object_id' AND term_taxonomy_id IN ($in_delete_terms)"); + wp_update_term_count($delete_terms, $taxonomy); + } + } + + return $tt_ids; +} + +function wp_unique_term_slug($slug, $term) { + global $wpdb; + + // If the taxonomy supports hierarchy and the term has a parent, make the slug unique + // by incorporating parent slugs. + if ( is_taxonomy_hierarchical($term->taxonomy) && !empty($term->parent) ) { + $the_parent = $term->parent; + while ( ! empty($the_parent) ) { + $parent_term = get_term($the_parent, $term->taxonomy); + if ( is_wp_error($parent_term) || empty($parent_term) ) + break; + $slug .= '-' . $parent_term->slug; + if ( empty($parent_term->parent) ) + break; + $the_parent = $parent_term->parent; + } + } + + // If we didn't get a unique slug, try appending a number to make it unique. + if ( $wpdb->get_var("SELECT slug FROM $wpdb->terms WHERE slug = '$slug'") ) { + $num = 2; + do { + $alt_slug = $slug . "-$num"; + $num++; + $slug_check = $wpdb->get_var("SELECT slug FROM $wpdb->terms WHERE slug = '$alt_slug'"); + } while ( $slug_check ); + $slug = $alt_slug; + } + + return $slug; +} + +function wp_update_term( $term, $taxonomy, $args = array() ) { + global $wpdb; + + if ( ! is_taxonomy($taxonomy) ) + return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); + + $term_id = (int) $term; + + // First, get all of the original args + $term = get_term ($term_id, $taxonomy, ARRAY_A); + + // Escape data pulled from DB. + $term = add_magic_quotes($term); + + // Merge old and new args with new args overwriting old ones. + $args = array_merge($term, $args); + + $defaults = array( 'alias_of' => '', 'description' => '', 'parent' => 0, 'slug' => ''); + $args = wp_parse_args($args, $defaults); + $args = sanitize_term($args, $taxonomy, 'db'); + extract($args, EXTR_SKIP); + + $empty_slug = false; + if ( empty($slug) ) { + $empty_slug = true; + $slug = sanitize_title($name); + } + + if ( $alias_of ) { + $alias = $wpdb->fetch_row("SELECT term_id, term_group FROM $wpdb->terms WHERE slug = '$alias_of'"); + if ( $alias->term_group ) { + // The alias we want is already in a group, so let's use that one. + $term_group = $alias->term_group; + } else { + // The alias isn't in a group, so let's create a new one and firstly add the alias term to it. + $term_group = $wpdb->get_var("SELECT MAX(term_group) FROM $wpdb->terms GROUP BY term_group") + 1; + $wpdb->query("UPDATE $wpdb->terms SET term_group = $term_group WHERE term_id = $alias->term_id"); + } + } + + // Check for duplicate slug + $id = $wpdb->get_var("SELECT term_id FROM $wpdb->terms WHERE slug = '$slug'"); + if ( $id && ($id != $term_id) ) { + // If an empty slug was passed, reset the slug to something unique. + // Otherwise, bail. + if ( $empty_slug ) + $slug = wp_unique_term_slug($slug, (object) $args); + else + return new WP_Error('duplicate_term_slug', sprintf(__('The slug "%s" is already in use by another term'), $slug)); + } + + $wpdb->query("UPDATE $wpdb->terms SET name = '$name', slug = '$slug', term_group = '$term_group' WHERE term_id = '$term_id'"); + + if ( empty($slug) ) { + $slug = sanitize_title($name, $term_id); + $wpdb->query("UPDATE $wpdb->terms SET slug = '$slug' WHERE term_id = '$term_id'"); + } + + $tt_id = $wpdb->get_var("SELECT tt.term_taxonomy_id FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = '$taxonomy' AND t.term_id = $term_id"); + + $wpdb->query("UPDATE $wpdb->term_taxonomy SET term_id = '$term_id', taxonomy = '$taxonomy', description = '$description', parent = '$parent' WHERE term_taxonomy_id = '$tt_id'"); + + do_action("edit_term", $term_id, $tt_id); + do_action("edit_$taxonomy", $term_id, $tt_id); + + clean_term_cache($term_id, $taxonomy); + + $term_id = apply_filters('term_id_filter', $term_id, $tt_id); + + clean_term_cache($term_id, $taxonomy); + + do_action("edited_term", $term_id, $tt_id); + do_action("edited_$taxonomy", $term_id, $tt_id); + + return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id); +} + +function wp_update_term_count( $terms, $taxonomy ) { + global $wpdb; + + if ( empty($terms) ) + return false; + + if ( !is_array($terms) ) + $terms = array($terms); + + $terms = array_map('intval', $terms); + + $taxonomy = get_taxonomy($taxonomy); + if ( !empty($taxonomy->update_count_callback) ) { + call_user_func($taxonomy->update_count_callback, $terms); + } else { + // Default count updater + foreach ($terms as $term) { + $count = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = '$term'"); + $wpdb->query("UPDATE $wpdb->term_taxonomy SET count = '$count' WHERE term_taxonomy_id = '$term'"); + } + + } + + clean_term_cache($terms); + + return true; +} + +// +// Cache +// + +function clean_object_term_cache($object_ids, $object_type) { + global $object_term_cache, $blog_id; + + if ( !is_array($object_ids) ) + $object_ids = array($object_ids); + + $taxonomies = get_object_taxonomies($object_type); + + foreach ( $object_ids as $id ) { + foreach ( $taxonomies as $taxonomy ) { + if ( isset($object_term_cache[$blog_id][$id][$taxonomy]) ) + unset($object_term_cache[$blog_id][$id][$taxonomy]); + } + } + + do_action('clean_object_term_cache', $object_ids, $object_type); +} + +function clean_term_cache($ids, $taxonomy = '') { + global $wpdb; + + if ( !is_array($ids) ) + $ids = array($ids); + + $taxonomies = array(); + // If no taxonomy, assume tt_ids. + if ( empty($taxonomy) ) { + $tt_ids = implode(', ', $ids); + $terms = $wpdb->get_results("SELECT term_id, taxonomy FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ($tt_ids)"); + foreach ( (array) $terms as $term ) { + $taxonomies[] = $term->taxonomy; + wp_cache_delete($term->term_id, $term->taxonomy); + } + $taxonomies = array_unique($taxonomies); + } else { + foreach ( $ids as $id ) { + wp_cache_delete($id, $taxonomy); + } + $taxonomies = array($taxonomy); + } + + foreach ( $taxonomies as $taxonomy ) { + wp_cache_delete('all_ids', $taxonomy); + wp_cache_delete("all_{$taxonomy}_ids", $taxonomy); + wp_cache_delete('get', $taxonomy); + delete_option("{$taxonomy}_children"); + } + + wp_cache_delete('get_terms', 'terms'); + + do_action('clean_term_cache', $ids, $taxonomy); +} + +function &get_object_term_cache($id, $taxonomy) { + global $object_term_cache, $blog_id; + + if ( isset($object_term_cache[$blog_id][$id][$taxonomy]) ) + return $object_term_cache[$blog_id][$id][$taxonomy]; + + if ( isset($object_term_cache[$blog_id][$id]) ) + return array(); + + return false; +} + +function update_object_term_cache($object_ids, $object_type) { + global $wpdb, $object_term_cache, $blog_id; + + if ( empty($object_ids) ) + return; + + if ( !is_array($object_ids) ) + $object_ids = explode(',', $object_ids); + + $count = count( $object_ids); + for ( $i = 0; $i < $count; $i++ ) { + $object_id = (int) $object_ids[ $i ]; + if ( isset( $object_term_cache[$blog_id][$object_id] ) ) { + unset( $object_ids[ $i ] ); + continue; + } + } + + if ( count( $object_ids ) == 0 ) + return; + + $terms = wp_get_object_terms($object_ids, get_object_taxonomies($object_type), 'fields=all_with_object_id'); + + if ( empty($terms) ) + return; + + foreach ( $terms as $term ) + $object_term_cache[$blog_id][$term->object_id][$term->taxonomy][$term->term_id] = $term; + + foreach ( $object_ids as $id ) { + if ( ! isset($object_term_cache[$blog_id][$id]) ) + $object_term_cache[$blog_id][$id] = array(); + } +} + +function update_term_cache($terms, $taxonomy = '') { + foreach ( $terms as $term ) { + $term_taxonomy = $taxonomy; + if ( empty($term_taxonomy) ) + $term_taxonomy = $term->taxonomy; + + wp_cache_add($term->term_id, $term, $term_taxonomy); + } +} + +// +// Private +// + +function _get_term_hierarchy($taxonomy) { + if ( !is_taxonomy_hierarchical($taxonomy) ) + return array(); + $children = get_option("{$taxonomy}_children"); + if ( is_array($children) ) + return $children; + + $children = array(); + $terms = get_terms($taxonomy, 'get=all'); + foreach ( $terms as $term ) { + if ( $term->parent > 0 ) + $children[$term->parent][] = $term->term_id; + } + update_option("{$taxonomy}_children", $children); + + return $children; +} + +function &_get_term_children($term_id, $terms, $taxonomy) { + if ( empty($terms) ) + return array(); + + $term_list = array(); + $has_children = _get_term_hierarchy($taxonomy); + + if ( ( 0 != $term_id ) && ! isset($has_children[$term_id]) ) + return array(); + + foreach ( $terms as $term ) { + $use_id = false; + if ( !is_object($term) ) { + $term = get_term($term, $taxonomy); + if ( is_wp_error( $term ) ) + return $term; + $use_id = true; + } + + if ( $term->term_id == $term_id ) + continue; + + if ( $term->parent == $term_id ) { + if ( $use_id ) + $term_list[] = $term->term_id; + else + $term_list[] = $term; + + if ( !isset($has_children[$term->term_id]) ) + continue; + + if ( $children = _get_term_children($term->term_id, $terms, $taxonomy) ) + $term_list = array_merge($term_list, $children); + } + } + + return $term_list; +} + +// Recalculates term counts by including items from child terms +// Assumes all relevant children are already in the $terms argument +function _pad_term_counts(&$terms, $taxonomy) { + global $wpdb; + + // This function only works for post categories. + if ( 'category' != $taxonomy ) + return; + + $term_hier = _get_term_hierarchy($taxonomy); + + if ( empty($term_hier) ) + return; + + $term_items = array(); + + foreach ( $terms as $key => $term ) { + $terms_by_id[$term->term_id] = & $terms[$key]; + $term_ids[$term->term_taxonomy_id] = $term->term_id; + } + + // Get the object and term ids and stick them in a lookup table + $results = $wpdb->get_results("SELECT object_id, term_taxonomy_id FROM $wpdb->term_relationships INNER JOIN $wpdb->posts ON object_id = ID WHERE term_taxonomy_id IN (".join(',', array_keys($term_ids)).") AND post_type = 'post' AND post_status = 'publish'"); + foreach ( $results as $row ) { + $id = $term_ids[$row->term_taxonomy_id]; + ++$term_items[$id][$row->object_id]; + } + + // Touch every ancestor's lookup row for each post in each term + foreach ( $term_ids as $term_id ) { + $child = $term_id; + while ( $parent = $terms_by_id[$child]->parent ) { + if ( !empty($term_items[$term_id]) ) + foreach ( $term_items[$term_id] as $item_id => $touches ) + ++$term_items[$parent][$item_id]; + $child = $parent; + } + } + + // Transfer the touched cells + foreach ( (array) $term_items as $id => $items ) + if ( isset($terms_by_id[$id]) ) + $terms_by_id[$id]->count = count($items); +} + +// +// Default callbacks +// + +function _update_post_term_count( $terms ) { + global $wpdb; + + foreach ( $terms as $term ) { + $count = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status = 'publish' AND post_type = 'post' AND term_taxonomy_id = '$term'"); + $wpdb->query("UPDATE $wpdb->term_taxonomy SET count = '$count' WHERE term_taxonomy_id = '$term'"); + } +} + +?> diff --git a/wp-includes/template-loader.php b/wp-includes/template-loader.php index 7b654b8..cc218e7 100644 --- a/wp-includes/template-loader.php +++ b/wp-includes/template-loader.php @@ -8,7 +8,7 @@ if ( defined('WP_USE_THEMES') && constant('WP_USE_THEMES') ) { do_feed(); return; } else if ( is_trackback() ) { - include(ABSPATH . '/wp-trackback.php'); + include(ABSPATH . 'wp-trackback.php'); return; } else if ( is_404() && $template = get_404_template() ) { include($template); @@ -35,6 +35,9 @@ if ( defined('WP_USE_THEMES') && constant('WP_USE_THEMES') ) { } else if ( is_category() && $template = get_category_template()) { include($template); return; + } else if ( is_tag() && $template = get_tag_template()) { + include($template); + return; } else if ( is_author() && $template = get_author_template() ) { include($template); return; @@ -65,7 +68,7 @@ if ( defined('WP_USE_THEMES') && constant('WP_USE_THEMES') ) { do_feed(); return; } else if ( is_trackback() ) { - include(ABSPATH . '/wp-trackback.php'); + include(ABSPATH . 'wp-trackback.php'); return; } } diff --git a/wp-includes/theme.php b/wp-includes/theme.php index f20ae68..3362c1d 100644 --- a/wp-includes/theme.php +++ b/wp-includes/theme.php @@ -56,35 +56,51 @@ 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 ); - preg_match( '|Theme URI:(.*)|i', $theme_data, $theme_uri ); - preg_match( '|Description:(.*)|i', $theme_data, $description ); - preg_match( '|Author:(.*)|i', $theme_data, $author_name ); - preg_match( '|Author URI:(.*)|i', $theme_data, $author_uri ); - preg_match( '|Template:(.*)|i', $theme_data, $template ); + $theme_data = str_replace ( '\r', '\n', $theme_data ); + preg_match( '|Theme Name:(.*)$|mi', $theme_data, $theme_name ); + preg_match( '|Theme URI:(.*)$|mi', $theme_data, $theme_uri ); + preg_match( '|Description:(.*)$|mi', $theme_data, $description ); + preg_match( '|Author:(.*)$|mi', $theme_data, $author_name ); + preg_match( '|Author URI:(.*)$|mi', $theme_data, $author_uri ); + preg_match( '|Template:(.*)$|mi', $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 = 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 ); - $name = $theme_name[1]; - $name = trim( $name ); - $theme = $name; - $theme_uri = trim( $theme_uri[1] ); - $template = trim( $template[1] ); + $author_uri = clean_url( trim( $author_uri[1] ) ); - if ( '' == $author_uri[1] ) { - $author = trim( $author_name[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, 'Status' => $status ); @@ -98,50 +114,55 @@ function get_themes() { $themes = array(); $wp_broken_themes = array(); - $theme_root = get_theme_root(); - $theme_loc = str_replace(ABSPATH, '', $theme_root); + $theme_loc = $theme_root = get_theme_root(); + if ( '/' != ABSPATH ) // don't want to replace all forward slashes, see Trac #4541 + $theme_loc = str_replace(ABSPATH, '', $theme_root); // Files in wp-content/themes directory and one subdir down - $themes_dir = @ dir($theme_root); + $themes_dir = @ opendir($theme_root); if ( !$themes_dir ) return false; - while ( ($theme_dir = $themes_dir->read()) !== false ) { + while ( ($theme_dir = readdir($themes_dir)) !== false ) { if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) { if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' ) continue; - $stylish_dir = @ dir($theme_root . '/' . $theme_dir); + $stylish_dir = @ opendir($theme_root . '/' . $theme_dir); $found_stylesheet = false; - while ( ($theme_file = $stylish_dir->read()) !== false ) { + while ( ($theme_file = readdir($stylish_dir)) !== false ) { if ( $theme_file == 'style.css' ) { $theme_files[] = $theme_dir . '/' . $theme_file; $found_stylesheet = true; break; } } + @closedir($stylish_dir); if ( !$found_stylesheet ) { // look for themes in that dir $subdir = "$theme_root/$theme_dir"; $subdir_name = $theme_dir; - $theme_subdir = @dir( $subdir ); - while ( ($theme_dir = $theme_subdir->read()) !== false ) { + $theme_subdir = @ opendir( $subdir ); + while ( ($theme_dir = readdir($theme_subdir)) !== false ) { if ( is_dir( $subdir . '/' . $theme_dir) && is_readable($subdir . '/' . $theme_dir) ) { if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' ) continue; - $stylish_dir = @ dir($subdir . '/' . $theme_dir); + $stylish_dir = @ opendir($subdir . '/' . $theme_dir); $found_stylesheet = false; - while ( ($theme_file = $stylish_dir->read()) !== false ) { + while ( ($theme_file = readdir($stylish_dir)) !== false ) { if ( $theme_file == 'style.css' ) { $theme_files[] = $subdir_name . '/' . $theme_dir . '/' . $theme_file; $found_stylesheet = true; break; } } + @closedir($stylish_dir); } } + @closedir($theme_subdir); $wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.')); } } } + @closedir($theme_dir); if ( !$themes_dir || !$theme_files ) return $themes; @@ -189,7 +210,7 @@ function get_themes() { if ( !file_exists("$theme_root/$template/index.php") ) { $parent_dir = dirname(dirname($theme_file)); if ( file_exists("$theme_root/$parent_dir/$template/index.php") ) { - $template = "$parent_dir/$template"; + $template = "$parent_dir/$template"; } else { $wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.')); continue; @@ -330,6 +351,17 @@ function get_category_template() { return apply_filters('category_template', $template); } +function get_tag_template() { + $template = ''; + if ( file_exists(TEMPLATEPATH . "/tag-" . get_query_var('tag') . '.php') ) + $template = TEMPLATEPATH . "/tag-" . get_query_var('tag') . '.php'; + elseif ( file_exists(TEMPLATEPATH . "/tag.php") ) + $template = TEMPLATEPATH . "/tag.php"; + + return apply_filters('tag_template', $template); +} + + function get_date_template() { return get_query_template('date'); } @@ -400,7 +432,7 @@ function get_comments_popup_template() { function load_template($_template_file) { global $posts, $post, $wp_did_header, $wp_did_template_redirect, $wp_query, - $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment; + $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID; if ( is_array($wp_query->query_vars) ) extract($wp_query->query_vars, EXTR_SKIP); diff --git a/wp-includes/update.php b/wp-includes/update.php new file mode 100644 index 0000000..657c667 --- /dev/null +++ b/wp-includes/update.php @@ -0,0 +1,54 @@ +<?php +/* +// A simple set of functions to check our version 1.0 update service + +function wp_version_check() { + if ( !function_exists('fsockopen') || strpos($_SERVER['PHP_SELF'], 'install.php') !== false || defined('WP_INSTALLING') ) + return; + + global $wp_version; + $php_version = phpversion(); + + $current = get_option( 'update_core' ); + $locale = get_locale(); + + if ( + isset( $current->last_checked ) && + 43200 > ( time() - $current->last_checked ) && + $current->version_checked == $wp_version + ) + return false; + + $new_option = ''; + $new_option->last_checked = time(); // this gets set whether we get a response or not, so if something is down or misconfigured it won't delay the page load for more than 3 seconds, twice a day + $new_option->version_checked = $wp_version; + + $http_request = "GET /core/version-check/1.0/?version=$wp_version&php=$php_version&locale=$locale HTTP/1.0\r\n"; + $http_request .= "Host: api.wordpress.org\r\n"; + $http_request .= 'Content-Type: application/x-www-form-urlencoded; charset=' . get_option('blog_charset') . "\r\n"; + $http_request .= 'User-Agent: WordPress/' . $wp_version . '; ' . get_bloginfo('url') . "\r\n"; + $http_request .= "\r\n"; + + $response = ''; + if ( false !== ( $fs = @fsockopen( 'api.wordpress.org', 80, $errno, $errstr, 3 ) ) && is_resource($fs) ) { + fwrite( $fs, $http_request ); + while ( !feof( $fs ) ) + $response .= fgets( $fs, 1160 ); // One TCP-IP packet + fclose( $fs ); + + $response = explode("\r\n\r\n", $response, 2); + $body = trim( $response[1] ); + $body = str_replace(array("\r\n", "\r"), "\n", $body); + + $returns = explode("\n", $body); + + $new_option->response = $returns[0]; + if ( isset( $returns[1] ) ) + $new_option->url = $returns[1]; + } + update_option( 'update_core', $new_option ); +} + +add_action( 'init', 'wp_version_check' ); +*/ +?> diff --git a/wp-includes/user.php b/wp-includes/user.php index f243fcc..1990a39 100644 --- a/wp-includes/user.php +++ b/wp-includes/user.php @@ -91,6 +91,9 @@ function get_usermeta( $user_id, $meta_key = '') { global $wpdb; $user_id = (int) $user_id; + if ( !$user_id ) + return false; + if ( !empty($meta_key) ) { $meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key); $metas = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = '$user_id' AND meta_key = '$meta_key'"); @@ -105,13 +108,8 @@ function get_usermeta( $user_id, $meta_key = '') { return ''; } - foreach ($metas as $index => $meta) { - @ $value = unserialize($meta->meta_value); - if ( $value === FALSE ) - $value = $meta->meta_value; - - $values[] = $value; - } + foreach ($metas as $meta) + $values[] = maybe_unserialize($meta->meta_value); if ( count($values) == 1 ) return $values[0]; @@ -179,4 +177,69 @@ function setup_userdata($user_id = '') { $user_identity = $user->display_name; } +function wp_dropdown_users( $args = '' ) { + global $wpdb; + $defaults = array( + 'show_option_all' => '', 'show_option_none' => '', + 'orderby' => 'display_name', 'order' => 'ASC', + 'include' => '', 'exclude' => '', + 'show' => 'display_name', 'echo' => 1, + 'selected' => 0, 'name' => 'user', 'class' => '' + ); + + $defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0; + + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); + + $query = "SELECT * FROM $wpdb->users"; + + $query_where = array(); + + if ( is_array($include) ) + $include = join(',', $include); + $include = preg_replace('/[^0-9,]/', '', $include); // (int) + if ( $include ) + $query_where[] = "ID IN ($include)"; + + if ( is_array($exclude) ) + $exclude = join(',', $exclude); + $exclude = preg_replace('/[^0-9,]/', '', $exclude); // (int) + if ( $exclude ) + $query_where[] = "ID NOT IN ($exclude)"; + + if ( $query_where ) + $query .= " WHERE " . join(' AND', $query_where); + + $query .= " ORDER BY $orderby $order"; + + $users = $wpdb->get_results( $query ); + + $output = ''; + if ( !empty($users) ) { + $output = "<select name='$name' id='$name' class='$class'>\n"; + + if ( $show_option_all ) + $output .= "\t<option value='0'>$show_option_all</option>\n"; + + if ( $show_option_none ) + $output .= "\t<option value='-1'>$show_option_none</option>\n"; + + foreach ( $users as $user ) { + $user->ID = (int) $user->ID; + $_selected = $user->ID == $selected ? " selected='selected'" : ''; + $output .= "\t<option value='$user->ID'$_selected>" . wp_specialchars($user->$show) . "</option>\n"; + } + + $output .= "</select>"; + } + + $output = apply_filters('wp_dropdown_users', $output); + + if ( $echo ) + echo $output; + + return $output; +} + ?> diff --git a/wp-includes/version.php b/wp-includes/version.php index 13c05a4..1a3d531 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -2,8 +2,8 @@ // This holds the version number in a separate file so we can bump it without cluttering the SVN -$wp_version = 'wordpress-mu-1.2.5'; -$wporg_version = 'wordpress-2.2.3'; -$wp_db_version = 5200; +$wp_version = 'wordpress-mu-1.3rc1'; +$wporg_version = 'wordpress-2.3'; +$wp_db_version = 6124; ?> diff --git a/wp-includes/widgets.php b/wp-includes/widgets.php index b2ec69e..7bd6fbd 100644 --- a/wp-includes/widgets.php +++ b/wp-includes/widgets.php @@ -59,7 +59,7 @@ function register_sidebar($args = array()) { function unregister_sidebar( $name ) { global $wp_registered_sidebars; - + if ( isset( $wp_registered_sidebars[$name] ) ) unset( $wp_registered_sidebars[$name] ); } @@ -210,7 +210,15 @@ function dynamic_sidebar($index = 1) { $params = array_merge(array($sidebar), (array) $wp_registered_widgets[$id]['params']); // Substitute HTML id and class attributes into before_widget - $params[0]['before_widget'] = sprintf($params[0]['before_widget'], $id, $wp_registered_widgets[$id]['classname']); + $classname_ = ''; + foreach ( (array) $wp_registered_widgets[$id]['classname'] as $cn ) { + if ( is_string($cn) ) + $classname_ .= '_' . $cn; + elseif ( is_object($cn) ) + $classname_ .= '_' . get_class($cn); + } + $classname_ = ltrim($classname_, '_'); + $params[0]['before_widget'] = sprintf($params[0]['before_widget'], $id, $classname_); if ( is_callable($callback) ) { call_user_func_array($callback, $params); @@ -329,17 +337,17 @@ function wp_get_widget_defaults() { function wp_widget_pages( $args ) { extract( $args ); $options = get_option( 'widget_pages' ); - + $title = empty( $options['title'] ) ? __( 'Pages' ) : $options['title']; $sortby = empty( $options['sortby'] ) ? 'menu_order' : $options['sortby']; $exclude = empty( $options['exclude'] ) ? '' : $options['exclude']; - + if ( $sortby == 'menu_order' ) { $sortby = 'menu_order, post_title'; } - + $out = wp_list_pages( array('title_li' => '', 'echo' => 0, 'sort_column' => $sortby, 'exclude' => $exclude) ); - + if ( !empty( $out ) ) { ?> <?php echo $before_widget; ?> @@ -356,15 +364,15 @@ function wp_widget_pages_control() { $options = $newoptions = get_option('widget_pages'); if ( $_POST['pages-submit'] ) { $newoptions['title'] = strip_tags(stripslashes($_POST['pages-title'])); - + $sortby = stripslashes( $_POST['pages-sortby'] ); - + if ( in_array( $sortby, array( 'post_title', 'menu_order', 'ID' ) ) ) { $newoptions['sortby'] = $sortby; } else { $newoptions['sortby'] = 'menu_order'; } - + $newoptions['exclude'] = strip_tags( stripslashes( $_POST['pages-exclude'] ) ); } if ( $options != $newoptions ) { @@ -375,7 +383,7 @@ function wp_widget_pages_control() { $exclude = attribute_escape( $options['exclude'] ); ?> <p><label for="pages-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="pages-title" name="pages-title" type="text" value="<?php echo $title; ?>" /></label></p> - <p><label for="pages-sortby"><?php _e( 'Sort by:' ); ?> + <p><label for="pages-sortby"><?php _e( 'Sort by:' ); ?> <select name="pages-sortby" id="pages-sortby"> <option value="post_title"<?php selected( $options['sortby'], 'post_title' ); ?>><?php _e('Page title'); ?></option> <option value="menu_order"<?php selected( $options['sortby'], 'menu_order' ); ?>><?php _e('Page order'); ?></option> @@ -388,18 +396,12 @@ function wp_widget_pages_control() { } function wp_widget_links($args) { - global $wp_db_version; extract($args, EXTR_SKIP); - if ( $wp_db_version < 3582 ) { - // This ONLY works with li/h2 sidebars. - get_links_list(); - } else { - wp_list_bookmarks(array( - 'title_before' => $before_title, 'title_after' => $after_title, - 'category_before' => $before_widget, 'category_after' => $after_widget, - 'show_images' => true, 'class' => 'linkcat widget' - )); - } + wp_list_bookmarks(array( + 'title_before' => $before_title, 'title_after' => $after_title, + 'category_before' => $before_widget, 'category_after' => $after_widget, + 'show_images' => true, 'class' => 'linkcat widget' + )); } function wp_widget_search($args) { @@ -423,14 +425,14 @@ function wp_widget_archives($args) { $d = $options['dropdown'] ? '1' : '0'; $title = empty($options['title']) ? __('Archives') : $options['title']; - echo $before_widget; + echo $before_widget; echo $before_title . $title . $after_title; - if($d) { + if($d) { ?> - <select name="archive-dropdown" onChange='document.location.href=this.options[this.selectedIndex].value;'> <option value=""><?php echo attribute_escape(__('Select Month')); ?></option> <?php wp_get_archives("type=monthly&format=option&show_post_count=$c"); ?> </select> -<?php - } else { + <select name="archive-dropdown" onchange='document.location.href=this.options[this.selectedIndex].value;'> <option value=""><?php echo attribute_escape(__('Select Month')); ?></option> <?php wp_get_archives("type=monthly&format=option&show_post_count=$c"); ?> </select> +<?php + } else { ?> <ul> <?php wp_get_archives("type=monthly&show_post_count=$c"); ?> @@ -438,7 +440,7 @@ function wp_widget_archives($args) { <?php } - echo $after_widget; + echo $after_widget; } function wp_widget_archives_control() { @@ -609,20 +611,22 @@ function wp_widget_text_register() { add_action('sidebar_admin_page', 'wp_widget_text_page'); } -function wp_widget_categories($args) { +function wp_widget_categories($args, $number = 1) { extract($args); $options = get_option('widget_categories'); - $c = $options['count'] ? '1' : '0'; - $h = $options['hierarchical'] ? '1' : '0'; - $d = $options['dropdown'] ? '1' : '0'; - $title = empty($options['title']) ? __('Categories') : $options['title']; + + $c = $options[$number]['count'] ? '1' : '0'; + $h = $options[$number]['hierarchical'] ? '1' : '0'; + $d = $options[$number]['dropdown'] ? '1' : '0'; + + $title = empty($options[$number]['title']) ? __('Categories') : $options[$number]['title']; echo $before_widget; - echo $before_title . $title . $after_title; + echo $before_title . $title . $after_title; $cat_args = "orderby=name&show_count={$c}&hierarchical={$h}"; - if($d) { + if ( $d ) { wp_dropdown_categories($cat_args . '&show_option_none= ' . __('Select Category')); ?> @@ -648,31 +652,157 @@ function wp_widget_categories($args) { echo $after_widget; } -function wp_widget_categories_control() { +function wp_widget_categories_control( $number ) { $options = $newoptions = get_option('widget_categories'); - if ( $_POST['categories-submit'] ) { - $newoptions['count'] = isset($_POST['categories-count']); - $newoptions['hierarchical'] = isset($_POST['categories-hierarchical']); - $newoptions['dropdown'] = isset($_POST['categories-dropdown']); - $newoptions['title'] = strip_tags(stripslashes($_POST['categories-title'])); + + if ( !is_array( $options ) ) { + $options = $newoptions = get_option( 'widget_categories' ); + } + + if ( $_POST['categories-submit-' . $number] ) { + $newoptions[$number]['count'] = isset($_POST['categories-count-' . $number]); + $newoptions[$number]['hierarchical'] = isset($_POST['categories-hierarchical-' . $number]); + $newoptions[$number]['dropdown'] = isset($_POST['categories-dropdown-' . $number]); + $newoptions[$number]['title'] = strip_tags(stripslashes($_POST['categories-title-' . $number])); } + if ( $options != $newoptions ) { $options = $newoptions; update_option('widget_categories', $options); } - $count = $options['count'] ? 'checked="checked"' : ''; - $hierarchical = $options['hierarchical'] ? 'checked="checked"' : ''; - $dropdown = $options['dropdown'] ? 'checked="checked"' : ''; - $title = attribute_escape($options['title']); + + $title = attribute_escape( $options[$number]['title'] ); +?> + <p><label for="categories-title-<?php echo $number; ?>"> + <?php _e( 'Title:' ); ?> <input style="width:300px" id="categories-title-<?php echo $number; ?>" name="categories-title-<?php echo $number; ?>" type="text" value="<?php echo $title; ?>" /> + </label></p> + + <p><label for="categories-dropdown-<?php echo $number; ?>"> + <input type="checkbox" class="checkbox" id="categories-dropdown-<?php echo $number; ?>" name="categories-dropdown-<?php echo $number; ?>"<?php echo $options[$number]['dropdown'] ? ' checked="checked"' : ''; ?> /> <?php _e( 'Show as dropdown' ); ?> + </label></p> + + <p><label for="categories-count-<?php echo $number; ?>"> + <input type="checkbox" class="checkbox" id="categories-count-<?php echo $number; ?>" name="categories-count-<?php echo $number; ?>"<?php echo $options[$number]['count'] ? ' checked="checked"' : ''; ?> /> <?php _e( 'Show post counts' ); ?> + </label></p> + + <p><label for="categories-hierarchical-<?php echo $number; ?>"> + <input type="checkbox" class="checkbox" id="categories-hierarchical-<?php echo $number; ?>" name="categories-hierarchical-<?php echo $number; ?>"<?php echo $options[$number]['hierarchical'] ? ' checked="checked"' : ''; ?> /> <?php _e( 'Show hierarchy' ); ?> + </label></p> + + <input type="hidden" id="categories-submit-<?php echo $number; ?>" name="categories-submit-<?php echo $number; ?>" value="1" /> +<?php +} + +function wp_widget_categories_setup() { + $options = $newoptions = get_option( 'widget_categories' ); + + if ( isset( $_POST['categories-number-submit'] ) ) { + $number = (int) $_POST['categories-number']; + + if ( $number > 9 ) { + $number = 9; + } elseif ( $number < 1 ) { + $number = 1; + } + + $newoptions['number'] = $number; + } + + if ( $newoptions != $options ) { + $options = $newoptions; + update_option( 'widget_categories', $options ); + wp_widget_categories_register( $options['number'] ); + } +} + +function wp_widget_categories_page() { + $options = get_option( 'widget_categories' ); ?> - <p><label for="categories-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="categories-title" name="categories-title" type="text" value="<?php echo $title; ?>" /></label></p> - <p style="text-align:right;margin-right:40px;"><label for="categories-count"><?php _e('Show post counts'); ?> <input class="checkbox" type="checkbox" <?php echo $count; ?> id="categories-count" name="categories-count" /></label></p> - <p style="text-align:right;margin-right:40px;"><label for="categories-hierarchical" style="text-align:right;"><?php _e('Show hierarchy'); ?> <input class="checkbox" type="checkbox" <?php echo $hierarchical; ?> id="categories-hierarchical" name="categories-hierarchical" /></label></p> - <p style="text-align:right;margin-right:40px;"><label for="categories-dropdown" style="text-align:right;"><?php _e('Display as a drop down'); ?> <input class="checkbox" type="checkbox" <?php echo $dropdown; ?> id="categories-dropdown" name="categories-dropdown" /></label></p> - <input type="hidden" id="categories-submit" name="categories-submit" value="1" /> + <div class="wrap"> + <form method="post"> + <h2><?php _e( 'Categories Widgets' ); ?></h2> + <p style="line-height: 30px;"><?php _e( 'How many categories widgets would you like?' ); ?> + <select id="categories-number" name="categories-number" value="<?php echo attribute_escape( $options['number'] ); ?>"> + <?php + for ( $i = 1; $i < 10; $i++ ) { + echo '<option value="' . $i . '"' . ( $i == $options['number'] ? ' selected="selected"' : '' ) . '>' . $i . "</option>\n"; + } + ?> + </select> + <span class="submit"> + <input type="submit" value="<?php echo attribute_escape( __( 'Save' ) ); ?>" id="categories-number-submit" name="categories-number-submit" /> + </span> + </p> + </form> + </div> <?php } +function wp_widget_categories_upgrade() { + $options = get_option( 'widget_categories' ); + + $newoptions = array( 'number' => 1, 1 => $options ); + + update_option( 'widget_categories', $newoptions ); + + $sidebars_widgets = get_option( 'sidebars_widgets' ); + if ( is_array( $sidebars_widgets ) ) { + foreach ( $sidebars_widgets as $sidebar => $widgets ) { + if ( is_array( $widgets ) ) { + foreach ( $widgets as $widget ) + $new_widgets[$sidebar][] = ( $widget == 'categories' ) ? 'categories-1' : $widget; + } else { + $new_widgets[$sidebar] = $widgets; + } + } + if ( $new_widgets != $sidebars_widgets ) + update_option( 'sidebars_widgets', $new_widgets ); + } + + if ( isset( $_POST['categories-submit'] ) ) { + $_POST['categories-submit-1'] = $_POST['categories-submit']; + $_POST['categories-count-1'] = $_POST['categories-count']; + $_POST['categories-hierarchical-1'] = $_POST['categories-hierarchical']; + $_POST['categories-dropdown-1'] = $_POST['categories-dropdown']; + $_POST['categories-title-1'] = $_POST['categories-title']; + foreach ( $_POST as $k => $v ) + if ( substr($k, -5) == 'order' ) + $_POST[$k] = str_replace('categories', 'categories-1', $v); + } + + return $newoptions; +} + +function wp_widget_categories_register() { + $options = get_option( 'widget_categories' ); + if ( !isset($options['number']) ) + $options = wp_widget_categories_upgrade(); + $number = (int) $options['number']; + + if ( $number > 9 ) { + $number = 9; + } elseif ( $number < 1 ) { + $number = 1; + } + + $dims = array( 'width' => 350, 'height' => 170 ); + $class = array( 'classname' => 'widget_catgories' ); + + for ( $i = 1; $i <= 9; $i++ ) { + $name = sprintf( __( 'Categories %d' ), $i ); + $id = 'categories-' . $i; + + $widget_callback = ( $i <= $number ) ? 'wp_widget_categories' : ''; + $control_callback = ( $i <= $number ) ? 'wp_widget_categories_control' : ''; + + wp_register_sidebar_widget( $id, $name, $widget_callback, $class, $i ); + wp_register_widget_control( $id, $name, $control_callback, $dims, $i ); + } + + add_action( 'sidebar_admin_setup', 'wp_widget_categories_setup' ); + add_action( 'sidebar_admin_page', 'wp_widget_categories_page' ); +} + function wp_widget_recent_entries($args) { if ( $output = wp_cache_get('widget_recent_entries') ) return print($output); @@ -688,7 +818,7 @@ function wp_widget_recent_entries($args) { else if ( $number > 15 ) $number = 15; - $r = new WP_Query("showposts=$number&what_to_show=posts&nopaging=0"); + $r = new WP_Query("showposts=$number&what_to_show=posts&nopaging=0&post_status=publish"); if ($r->have_posts()) : ?> <?php echo $before_widget; ?> @@ -709,7 +839,7 @@ function wp_flush_widget_recent_entries() { } add_action('save_post', 'wp_flush_widget_recent_entries'); -add_action('post_deleted', 'wp_flush_widget_recent_entries'); +add_action('deleted_post', 'wp_flush_widget_recent_entries'); function wp_widget_recent_entries_control() { $options = $newoptions = get_option('widget_recent_entries'); @@ -798,14 +928,14 @@ function wp_widget_recent_comments_register() { $class = array('classname' => 'widget_recent_comments'); wp_register_sidebar_widget('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments', $class); wp_register_widget_control('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments_control', $dims); - + if ( is_active_widget('wp_widget_recent_comments') ) add_action('wp_head', 'wp_widget_recent_comments_style'); } function wp_widget_rss($args, $number = 1) { require_once(ABSPATH . WPINC . '/rss.php'); - extract($args, EXTR_SKIP); + extract($args); $options = get_option('widget_rss'); if ( isset($options['error']) && $options['error'] ) return; @@ -838,10 +968,10 @@ function wp_widget_rss($args, $number = 1) { ?> <?php echo $before_widget; ?> <?php $title ? print($before_title . $title . $after_title) : null; ?> - <ul> <?php - if ( is_array( $rss->items ) ) { + if ( is_array( $rss->items ) && !empty( $rss->items ) ) { $rss->items = array_slice($rss->items, 0, $num_items); + echo '<ul>'; foreach ($rss->items as $item ) { while ( strstr($item['link'], 'http') != $item['link'] ) $item['link'] = substr($item['link'], 1); @@ -859,13 +989,12 @@ function wp_widget_rss($args, $number = 1) { } echo "<li><a class='rsswidget' href='$link' title='$desc'>$title</a>$summary</li>"; } + echo '</ul>'; } else { - echo '<li>' . __( 'An error has occurred; the feed is probably down. Try again later.' ) . '</li>'; + echo '<ul><li>' . __( 'An error has occurred; the feed is probably down. Try again later.' ) . '</li></ul>'; } -?> - </ul> - <?php echo $after_widget; ?> -<?php + + echo $after_widget; } function wp_widget_rss_control($number) { @@ -953,40 +1082,84 @@ function wp_widget_rss_register() { add_action('sidebar_admin_page', 'wp_widget_rss_page'); } +function wp_widget_tag_cloud($args) { + extract($args); + $options = get_option('widget_tag_cloud'); + $title = empty($options['title']) ? __('Tags') : $options['title']; + + echo $before_widget; + echo $before_title . $title . $after_title; + wp_tag_cloud(); + echo $after_widget; +} + +function wp_widget_tag_cloud_control() { + $options = $newoptions = get_option('widget_tag_cloud'); + + if ( $_POST['tag-cloud-submit'] ) { + $newoptions['title'] = strip_tags(stripslashes($_POST['tag-cloud-title'])); + } + + if ( $options != $newoptions ) { + $options = $newoptions; + update_option('widget_tag_cloud', $options); + } + + $title = attribute_escape( $options['title'] ); +?> + <p><label for="tag-cloud-title"> + <?php _e('Title:') ?> <input type="text" style="width:300px" id="tag-cloud-title" name="tag-cloud-title" value="<?php echo $title ?>" /></label> + </p> + <input type="hidden" name="tag-cloud-submit" id="tag-cloud-submit" value="1" /> +<?php +} + function wp_widgets_init() { - global $wp_register_widget_defaults; + if ( !is_blog_installed() ) + return; + + $GLOBALS['wp_register_widget_defaults'] = true; + + $dims90 = array( 'height' => 90, 'width' => 300 ); + $dims100 = array( 'height' => 100, 'width' => 300 ); + $dims150 = array( 'height' => 150, 'width' => 300 ); - $wp_register_widget_defaults = true; - $dims90 = array('height' => 90, 'width' => 300); - $dims100 = array('height' => 100, 'width' => 300); - $dims150 = array('height' => 150, 'width' => 300); $class = array('classname' => 'widget_pages'); wp_register_sidebar_widget('pages', __('Pages'), 'wp_widget_pages', $class); wp_register_widget_control('pages', __('Pages'), 'wp_widget_pages_control', $dims150); + $class['classname'] = 'widget_calendar'; wp_register_sidebar_widget('calendar', __('Calendar'), 'wp_widget_calendar', $class); wp_register_widget_control('calendar', __('Calendar'), 'wp_widget_calendar_control', $dims90); + $class['classname'] = 'widget_archives'; wp_register_sidebar_widget('archives', __('Archives'), 'wp_widget_archives', $class); wp_register_widget_control('archives', __('Archives'), 'wp_widget_archives_control', $dims100); + $class['classname'] = 'widget_links'; wp_register_sidebar_widget('links', __('Links'), 'wp_widget_links', $class); + $class['classname'] = 'widget_meta'; wp_register_sidebar_widget('meta', __('Meta'), 'wp_widget_meta', $class); wp_register_widget_control('meta', __('Meta'), 'wp_widget_meta_control', $dims90); + $class['classname'] = 'widget_search'; wp_register_sidebar_widget('search', __('Search'), 'wp_widget_search', $class); - $class['classname'] = 'widget_categories'; - wp_register_sidebar_widget('categories', __('Categories'), 'wp_widget_categories', $class); - wp_register_widget_control('categories', __('Categories'), 'wp_widget_categories_control', $dims150); + $class['classname'] = 'widget_recent_entries'; wp_register_sidebar_widget('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries', $class); wp_register_widget_control('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries_control', $dims90); + + $class['classname'] = 'widget_tag_cloud'; + wp_register_sidebar_widget('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud', $class); + wp_register_widget_control('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud_control', 'width=300&height=160'); + + wp_widget_categories_register(); wp_widget_text_register(); wp_widget_rss_register(); wp_widget_recent_comments_register(); - $wp_register_widget_defaults = false; + $GLOBALS['wp_register_widget_defaults'] = false; do_action('widgets_init'); } diff --git a/wp-includes/wp-db.php b/wp-includes/wp-db.php index d829cd5..a3fa04e 100644 --- a/wp-includes/wp-db.php +++ b/wp-includes/wp-db.php @@ -34,6 +34,10 @@ class wpdb { var $optiongroups; var $optiongroup_options; var $postmeta; + var $usermeta; + var $terms; + var $term_taxonomy; + var $term_relationships; var $charset; var $collate; @@ -81,7 +85,7 @@ class wpdb { } function __destruct() { - return true; + return true; } /** @@ -115,6 +119,29 @@ class wpdb { return mysql_real_escape_string( $string, $this->dbh ); } + /** + * Escapes content by reference for insertion into the database, for security + * @param string $s + */ + function escape_by_ref(&$s) { + $s = $this->escape($s); + } + + /** + * Prepares a SQL query for safe use, using sprintf() syntax + */ + function prepare($args=NULL) { + if ( NULL === $args ) + return; + $args = func_get_args(); + $query = array_shift($args); + $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it + $query = str_replace('"%s"', '%s', $query); // doublequote unquoting + $query = str_replace('%s', "'%s'", $query); // quote the strings + array_walk($args, array(&$this, 'escape_by_ref')); + return @vsprintf($query, $args); + } + // ================================================================== // Print SQL/DB error. @@ -323,7 +350,9 @@ class wpdb { $this->func_call = "\$db->get_row(\"$query\",$output,$y)"; if ( $query ) $this->query($query); - + else + return null; + if ( !isset($this->last_result[$y]) ) return null; @@ -348,6 +377,7 @@ class wpdb { if ( $query ) $this->query($query); + $new_array = array(); // Extract the column values for ( $i=0; $i < count($this->last_result); $i++ ) { $new_array[$i] = $this->get_var(null, $x, $i); @@ -366,6 +396,8 @@ class wpdb { if ( $query ) $this->query($query); + else + return null; // Send back array of objects. Each row is an object if ( $output == OBJECT ) { diff --git a/wp-includes/wpmu-functions.php b/wp-includes/wpmu-functions.php index c382ce5..a5126d6 100644 --- a/wp-includes/wpmu-functions.php +++ b/wp-includes/wpmu-functions.php @@ -176,18 +176,23 @@ function get_blog_details( $id, $all = true ) { return false; } - if( $all == true ) { - $wpdb->hide_errors(); - $details->blogname = get_blog_option($id, 'blogname'); - $details->siteurl = get_blog_option($id, 'siteurl'); - $details->post_count = get_blog_option($id, 'post_count'); - $wpdb->show_errors(); + if ( !$all ) { + wp_cache_add( $id, $details, 'blog-details' ); + return $details; + } - wp_cache_add( $id, serialize( $details ), 'blog-details' ); + $wpdb->hide_errors(); + $details->blogname = get_blog_option($id, 'blogname'); + $details->siteurl = get_blog_option($id, 'siteurl'); + $details->post_count = get_blog_option($id, 'post_count'); + $wpdb->show_errors(); - $key = md5( $details->domain . $details->path ); - wp_cache_add( $key, serialize( $details ), 'blog-lookup' ); - } + $details = apply_filters('blog_details', $details); + + wp_cache_set( $id, $details, 'blog-details' ); + + $key = md5( $details->domain . $details->path ); + wp_cache_set( $key, $details, 'blog-lookup' ); return $details; } @@ -195,7 +200,7 @@ function get_blog_details( $id, $all = true ) { function refresh_blog_details( $id ) { global $wpdb, $wpmuBaseTablePrefix; - $details = get_blog_details( $id ); + $details = get_blog_details( $id, false ); wp_cache_delete( $id , 'blog-details' ); $key = md5( $details->domain . $details->path ); @@ -267,7 +272,6 @@ function add_site_option( $key, $value ) { $safe_key = $wpdb->escape( $key ); $exists = $wpdb->get_row("SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = '$safe_key' AND site_id = '{$wpdb->siteid}'"); - if ( is_object( $exists ) ) {// If we already have it update_site_option( $key, $value ); return false; @@ -296,6 +300,7 @@ function update_site_option( $key, $value ) { if ( is_array($value) || is_object($value) ) $value = serialize($value); + $value = $wpdb->escape( $value ); $wpdb->query( "UPDATE $wpdb->sitemeta SET meta_value = '" . $wpdb->escape( $value ) . "' WHERE site_id='{$wpdb->siteid}' AND meta_key = '$safe_key'" ); wp_cache_delete( $wpdb->siteid . $key, 'site-options' ); @@ -390,11 +395,14 @@ function switch_to_blog( $new_blog ) { $tmpoldblogdetails[ 'links' ] = $wpdb->links; $tmpoldblogdetails[ 'link2cat' ] = $wpdb->link2cat; $tmpoldblogdetails[ 'linkcategories' ] = $wpdb->linkcategories; - $tmpoldblogdetails[ 'options' ] = $wpdb->options; + $tmpoldblogdetails[ 'options' ] = $wpdb->options; $tmpoldblogdetails[ 'postmeta' ] = $wpdb->postmeta; + $tmpoldblogdetails[ 'terms' ] = $wpdb->terms; + $tmpoldblogdetails[ 'term_taxonomy' ] = $wpdb->term_taxonomy; + $tmpoldblogdetails[ 'term_relationships' ] = $wpdb->term_relationships; $tmpoldblogdetails[ 'prefix' ] = $wpdb->prefix; - $tmpoldblogdetails[ 'table_prefix' ] = $table_prefix; - $tmpoldblogdetails[ 'blog_id' ] = $blog_id; + $tmpoldblogdetails[ 'table_prefix' ] = $table_prefix; + $tmpoldblogdetails[ 'blog_id' ] = $blog_id; // fix the new prefix. $table_prefix = $wpmuBaseTablePrefix . $new_blog . "_"; @@ -409,6 +417,9 @@ function switch_to_blog( $new_blog ) { $wpdb->linkcategories = $table_prefix . 'linkcategories'; $wpdb->options = $table_prefix . 'options'; $wpdb->postmeta = $table_prefix . 'postmeta'; + $wpdb->terms = $table_prefix . 'terms'; + $wpdb->term_taxonomy = $table_prefix . 'term_taxonomy'; + $wpdb->term_relationships = $table_prefix . 'term_relationships'; $blog_id = $new_blog; if( is_object( $wp_roles ) ) { @@ -447,6 +458,9 @@ function restore_current_blog() { $wpdb->linkcategories = $tmpoldblogdetails[ 'linkcategories' ]; $wpdb->options = $tmpoldblogdetails[ 'options' ]; $wpdb->postmeta = $tmpoldblogdetails[ 'postmeta' ]; + $wpdb->terms = $tmpoldblogdetails[ 'terms' ]; + $wpdb->term_taxonomy = $tmpoldblogdetails[ 'term_taxonomy' ]; + $wpdb->term_relationships = $tmpoldblogdetails[ 'term_relationships' ]; $wpdb->prefix = $tmpoldblogdetails[ 'prefix' ]; $table_prefix = $tmpoldblogdetails[ 'table_prefix' ]; $prev_blog_id = $blog_id; @@ -787,8 +801,6 @@ function create_empty_blog( $domain, $path, $weblog_title, $site_id = 1 ) { } function get_blog_permalink( $blog_id, $post_id ) { - global $wpdb, $cache_settings; - $key = "{$blog_id}-{$post_id}-blog_permalink"; $link = wp_cache_get( $key, 'site-options' ); if( $link == false ) { @@ -1014,7 +1026,7 @@ function wpmu_validate_blog_signup($blog_id, $blog_title, $user = '') { if( in_array( $blog_id, $illegal_names ) == true ) { $errors->add('blog_id', __("That name is not allowed")); } - if( strlen( $blog_id ) < 4 ) { + if( strlen( $blog_id ) < 4 && !is_site_admin() ) { $errors->add('blog_id', __("Blog name must be at least 4 characters")); } @@ -1264,6 +1276,33 @@ function wpmu_create_blog($domain, $path, $title, $user_id, $meta = '', $site_id return $blog_id; } +function newblog_notify_siteadmin( $blog_id, $user_id ) { + global $current_site; + if( get_site_option( 'registrationnotification' ) != 'yes' ) + return; + $email = get_site_option( 'admin_email' ); + if( is_email( $email ) == false ) + return false; + $msg = "New Blog: " . get_blog_option( $blog_id, "blogname" ) . "\nURL: " . get_blog_option( $blog_id, "siteurl" ) . "\nRemote IP: {$_SERVER[ 'REMOTE_ADDR' ]}\n\nDisable these notifications: http://{$current_site->domain}{$current_site->path}wp-admin/wpmu-options.php"; + $msg = apply_filters( 'newblog_notify_siteadmin', $msg ); + wp_mail( $email, "New Blog Registration: " . get_blog_option( $blog_id, "siteurl" ), $msg ); +} +add_action( "wpmu_new_blog", "newblog_notify_siteadmin", 10, 2 ); + +function newuser_notify_siteadmin( $user_id ) { + global $current_site; + if( get_site_option( 'registrationnotification' ) != 'yes' ) + return; + $email = get_site_option( 'admin_email' ); + if( is_email( $email ) == false ) + return false; + $user = new WP_User($user_id); + $msg = "New User: " . $user->user_login . "\nRemote IP: {$_SERVER[ 'REMOTE_ADDR' ]}\n\nDisable these notifications: http://{$current_site->domain}{$current_site->path}wp-admin/wpmu-options.php"; + $msg = apply_filters( 'newuser_notify_siteadmin', $msg ); + wp_mail( $email, "New User Registration: " . $user->user_login, $msg ); +} +add_action( "wpmu_new_user", "newuser_notify_siteadmin" ); + function domain_exists($domain, $path, $site_id = 1) { global $wpdb; return $wpdb->get_var("SELECT blog_id FROM $wpdb->blogs WHERE domain = '$domain' AND path = '$path' AND site_id = '$site_id'" ); @@ -1287,7 +1326,7 @@ function install_blog($blog_id, $blog_title = '') { global $wpdb, $table_prefix, $wp_roles; $wpdb->hide_errors(); - require_once( ABSPATH . 'wp-admin/upgrade-functions.php'); + require_once( ABSPATH . 'wp-admin/includes/upgrade.php'); $installed = $wpdb->get_results("SELECT * FROM $wpdb->posts"); if ($installed) die(__('<h1>Already Installed</h1><p>You appear to have already installed WordPress. To reinstall please clear your old database tables first.</p>') . '</body></html>'); @@ -1311,15 +1350,24 @@ function install_blog($blog_id, $blog_title = '') { $wpdb->query("UPDATE $wpdb->options SET option_value = '' WHERE option_name = 'admin_email'"); // Default category - $wpdb->query("INSERT INTO $wpdb->categories (cat_ID, cat_name, category_nicename, category_count, category_description) VALUES ('0', '".addslashes(__('Uncategorized'))."', '".sanitize_title(__('Uncategorized'))."', 1, '')"); - $blogroll_id = $wpdb->get_var( "SELECT cat_ID FROM {$wpdb->sitecategories} WHERE category_nicename = 'blogroll'" ); + $cat_name = $wpdb->escape(__('Uncategorized')); + $cat_slug = sanitize_title(__('Uncategorized')); + $wpdb->query("INSERT INTO $wpdb->terms (term_id, name, slug, term_group) VALUES ('1', '$cat_name', '$cat_slug', '0')"); + + $wpdb->query("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ('1', 'category', '', '0', '1')"); + + // Default link category + $cat_name = $wpdb->escape(__('Blogroll')); + $cat_slug = sanitize_title(__('Blogroll')); + $blogroll_id = $wpdb->get_var( "SELECT cat_ID FROM {$wpdb->sitecategories} WHERE category_nicename = '$cat_slug'" ); if( $blogroll_id == null ) { - $wpdb->query( "INSERT INTO " . $wpdb->sitecategories . " (cat_ID, cat_name, category_nicename, last_updated) VALUES (0, 'Blogroll', 'blogroll', NOW())" ); + $wpdb->query( "INSERT INTO " . $wpdb->sitecategories . " (cat_ID, cat_name, category_nicename, last_updated) VALUES (0, '$cat_name', '$cat_slug', NOW())" ); $blogroll_id = $wpdb->insert_id; } - $wpdb->query("INSERT INTO $wpdb->categories (cat_ID, cat_name, category_nicename, link_count, category_description) VALUES ('{$blogroll_id}', '".addslashes(__('Blogroll'))."', '".sanitize_title(__('Blogroll'))."', 2, '')"); - $wpdb->query("INSERT INTO $wpdb->link2cat (link_id, category_id) VALUES (1, $blogroll_id)"); - $wpdb->query("INSERT INTO $wpdb->link2cat (link_id, category_id) VALUES (2, $blogroll_id)"); + $wpdb->query("INSERT INTO $wpdb->terms (term_id, name, slug, term_group) VALUES ('$blogroll_id', '$cat_name', '$cat_slug', '0')"); + $wpdb->query("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ('$blogroll_id', 'link_category', '', '0', '2')"); + + update_option('default_link_category', $blogroll_id); // remove all perms $wpdb->query( "DELETE FROM ".$wpdb->usermeta." WHERE meta_key = '".$table_prefix."user_level'" ); @@ -1334,8 +1382,10 @@ function install_blog_defaults($blog_id, $user_id) { $wpdb->hide_errors(); // Default links - $wpdb->query("INSERT INTO $wpdb->links (link_url, link_name, link_image, link_target, link_category, link_description, link_visible, link_owner, link_rating, link_updated, link_rel, link_notes, link_rss) VALUES ('http://wordpress.com/', 'WordPress.com', '', '', 1, '', 'Y', '$user_id', 0, 0, '', '', 'http://wordpress.com/feed/')"); - $wpdb->query("INSERT INTO $wpdb->links (link_url, link_name, link_image, link_target, link_category, link_description, link_visible, link_owner, link_rating, link_updated, link_rel, link_notes, link_rss) VALUES ('http://wordpress.org/', 'WordPress.org', '', '', 1, '', 'Y', '$user_id', 0, 0, '', '', 'http://wordpress.org/development/feed/')"); + $wpdb->query("INSERT INTO $wpdb->links (link_url, link_name, link_category, link_owner, link_rss) VALUES ('http://wordpress.com/', 'WordPress.com', 1356, '$user_id', 'http://wordpress.com/feed/');"); + $wpdb->query("INSERT INTO $wpdb->links (link_url, link_name, link_category, link_owner, link_rss) VALUES ('http://wordpress.org/', 'WordPress.org', 1356, '$user_id', 'http://wordpress.org/development/feed/');"); + $wpdb->query( "INSERT INTO $wpdb->term_relationships (`object_id`, `term_taxonomy_id`) VALUES (1, 2)" ); + $wpdb->query( "INSERT INTO $wpdb->term_relationships (`object_id`, `term_taxonomy_id`) VALUES (2, 2)" ); // First post $now = date('Y-m-d H:i:s'); @@ -1348,13 +1398,12 @@ function install_blog_defaults($blog_id, $user_id) { $first_post = str_replace( "SITE_NAME", $current_site->site_name, $first_post ); $first_post = stripslashes( $first_post ); - $wpdb->query("INSERT INTO $wpdb->posts (post_author, post_date, post_date_gmt, post_content, post_title, post_category, post_excerpt, post_status, comment_status, ping_status, post_password, post_name, to_ping, pinged, post_modified, post_modified_gmt, post_content_filtered, post_parent, guid, menu_order, post_type, post_mime_type, comment_count) VALUES ('".$user_id."', '$now', '$now_gmt', '".addslashes($first_post)."', '".addslashes(__('Hello world!'))."', '0', '', 'publish', 'open', 'open', '', '".addslashes(__('hello-world'))."', to_ping, pinged, '$now', '$now_gmt', '', 0, '', 0, 'post', '', 1)"); - $wpdb->query( "INSERT INTO $wpdb->post2cat (`rel_id`, `post_id`, `category_id`) VALUES (1, 1, 1)" ); + $wpdb->query("INSERT INTO $wpdb->posts (post_author, post_date, post_date_gmt, post_content, post_title, post_category, post_name, post_modified, post_modified_gmt, comment_count) VALUES ('".$user_id."', '$now', '$now_gmt', '".addslashes($first_post)."', '".addslashes(__('Hello world!'))."', '0', '".addslashes(__('hello-world'))."', '$now', '$now_gmt', '1')"); + $wpdb->query( "INSERT INTO $wpdb->term_relationships (`object_id`, `term_taxonomy_id`) VALUES (1, 1)" ); update_option( "post_count", 1 ); // First page $wpdb->query("INSERT INTO $wpdb->posts (post_author, post_date, post_date_gmt, post_content, post_excerpt, post_title, post_category, post_name, post_modified, post_modified_gmt, post_status, post_type, to_ping, pinged, post_content_filtered) VALUES ('$user_id', '$now', '$now_gmt', '".$wpdb->escape(__('This is an example of a WordPress page, you could edit this to put information about yourself or your site so readers know where you are coming from. You can create as many pages like this one or sub-pages as you like and manage all of your content inside of WordPress.'))."', '', '".$wpdb->escape(__('About'))."', '0', '".$wpdb->escape(__('about'))."', '$now', '$now_gmt', 'publish', 'page', '', '', '')"); - $wpdb->query( "INSERT INTO $wpdb->post2cat (`rel_id`, `post_id`, `category_id`) VALUES (2, 2, 1)" ); // Flush rules to pick up the new page. $wp_rewrite->init(); $wp_rewrite->flush_rules(); @@ -1819,192 +1868,38 @@ add_action( 'admin_footer', 'add_switcher' ); /* Global Categories */ -function global_categories( $cat_ID ) { +function global_terms( $term_id, $tt_id ) { global $wpdb; - $cat_ID = intval( $cat_ID ); - $c = $wpdb->get_row( "SELECT * FROM $wpdb->categories WHERE cat_ID = '$cat_ID'" ); + $term_id = intval( $term_id ); + $c = $wpdb->get_row( "SELECT * FROM $wpdb->terms WHERE term_id = '$term_id'" ); - $global_category = $wpdb->get_row( "SELECT * FROM $wpdb->sitecategories WHERE category_nicename = '" . $wpdb->escape( $c->category_nicename ) . "'" ); + $global_id = $wpdb->get_var( "SELECT cat_ID FROM $wpdb->sitecategories WHERE category_nicename = '" . $wpdb->escape( $c->slug ) . "'" ); - if ( $global_category ) { - $global_id = $global_category->cat_ID; - } else { - $wpdb->query( "INSERT INTO $wpdb->sitecategories ( cat_name, category_nicename ) VALUES ( '" . $wpdb->escape( $c->cat_name ) . "', '" . $wpdb->escape( $c->category_nicename ) . "' )" ); + if ( $global_id == null ) { + $wpdb->query( "INSERT INTO $wpdb->sitecategories ( cat_name, category_nicename ) VALUES ( '" . $wpdb->escape( $c->name ) . "', '" . $wpdb->escape( $c->slug ) . "' )" ); $global_id = $wpdb->insert_id; } - $wpdb->query( "UPDATE $wpdb->categories SET cat_ID = '$global_id' WHERE cat_id = '$cat_ID'" ); - $wpdb->query( "UPDATE $wpdb->categories SET category_parent = '$global_id' WHERE category_parent = '$cat_ID'" ); - $wpdb->query( "UPDATE $wpdb->post2cat SET category_id = '$global_id' WHERE category_id = '$cat_ID'" ); - $wpdb->query( "UPDATE $wpdb->link2cat SET category_id = '$global_id' WHERE category_id = '$cat_ID'" ); - wp_cache_delete($cat_ID, 'category'); - wp_cache_delete($global_id, 'category'); - wp_cache_delete('all_category_ids', 'category'); - - do_action('update_cat_id', $global_id, $cat_ID); - - return $global_id; -} - -add_filter( 'cat_id_filter', 'global_categories' ); - -/* WordPress MU Default Filters */ -add_filter('the_title', 'wp_filter_kses'); - -/* Pluggable */ - -function wp_login($username, $password, $already_md5 = false) { - global $wpdb, $error, $current_user; - - $username = sanitize_user($username); - - if ( '' == $username ) - return false; - - if ( '' == $password ) { - $error = __('<strong>ERROR</strong>: The password field is empty.'); - return false; - } - - if ($current_user->data->user_login == $username) - return true; - - $login = get_userdatabylogin($username); - - if (!$login) { - if( is_site_admin( $username ) ) { - unset( $login ); - $userdetails = get_userdatabylogin( $username ); - $login->user_login = $username; - $login->user_pass = $userdetails->user_pass; - } else { - $admins = get_admin_users_for_domain(); - reset( $admins ); - while( list( $key, $val ) = each( $admins ) ) - { - if( $val[ 'user_login' ] == $username ) { - unset( $login ); - $login->user_login = $username; - $login->user_pass = $val[ 'user_pass' ]; - } - } - } - } - if (!$login) { - $error = __('<strong>Error</strong>: Wrong username.'); - return false; - } else { - if( is_site_admin( $username ) == false && ( $primary_blog = get_usermeta( $login->ID, "primary_blog" ) ) ) { - $details = get_blog_details( $primary_blog ); - if( is_object( $details ) && $details->archived == 1 || $details->spam == 1 || $details->deleted == 1 ) { - $error = __('<strong>Error</strong>: Blog suspended.'); - return false; - } - } - // If the password is already_md5, it has been double hashed. - // Otherwise, it is plain text. - if ( ($already_md5 && $login->user_login == $username && md5($login->user_pass) == $password) || ($login->user_login == $username && $login->user_pass == md5($password)) ) { - return true; - } else { - $error = __('<strong>Error</strong>: Incorrect password.'); - $pwd = ''; - return false; - } - } -} - -function get_userdata( $user_id ) { - global $wpdb, $cache_userdata, $wpmuBaseTablePrefix; - $user_id = (int) $user_id; - if ( $user_id == 0 ) - return false; - - $user = wp_cache_get($user_id, 'users'); - $user_level = $wpmuBaseTablePrefix . $wpdb->blogid . '_user_level'; - if ( $user && is_site_admin( $user->user_login ) ) { - $user->$user_level = 10; - $user->user_level = 10; - $cap_key = $wpdb->prefix . 'capabilities'; - $user->{$cap_key} = array( 'administrator' => '1' ); - return $user; - } elseif ( $user ) { - return $user; - } - - if ( !$user = $wpdb->get_row("SELECT * FROM $wpdb->users WHERE ID = '$user_id'") ) - return false; - - $metavalues = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = '$user_id' /* pluggable get_userdata */"); - - if ($metavalues) { - foreach ( $metavalues as $meta ) { - @ $value = unserialize($meta->meta_value); - if ($value === FALSE) - $value = $meta->meta_value; - $user->{$meta->meta_key} = $value; - - // We need to set user_level from meta, not row - if ( $wpdb->prefix . 'user_level' == $meta->meta_key ) - $user->user_level = $meta->meta_value; - } // end foreach - } //end if - - if( is_site_admin( $user->user_login ) == true ) { - $user->user_level = 10; - $cap_key = $wpdb->prefix . 'capabilities'; - $user->{$cap_key} = array( 'administrator' => '1' ); - } - - wp_cache_add($user_id, $user, 'users'); - wp_cache_add($user->user_login, $user, 'userlogins'); - - return $user; -} -function get_userdatabylogin($user_login) { - global $wpdb; - $user_login = sanitize_user( $user_login ); + if ( $global_id == $term_id ) + return $global_id; - if ( empty( $user_login ) ) - return false; - - $userdata = wp_cache_get($user_login, 'userlogins'); - if( $userdata && is_site_admin( $user_login ) == true ) { - $userdata->user_level = 10; - $cap_key = $wpdb->prefix . 'capabilities'; - $userdata->{$cap_key} = array( 'administrator' => '1' ); - return $userdata; - } elseif( $userdata ) - return $userdata; - - if ( !$user = $wpdb->get_row("SELECT * FROM $wpdb->users WHERE user_login = '$user_login'") ) - return false; + $wpdb->query( "UPDATE $wpdb->terms SET term_id = '$global_id' WHERE term_id = '$term_id'" ); + $wpdb->query( "UPDATE $wpdb->term_taxonomy SET term_id = '$global_id' WHERE term_id = '$term_id'" ); + $wpdb->query( "UPDATE $wpdb->term_taxonomy SET parent = '$global_id' WHERE parent = '$term_id'" ); - $metavalues = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = '$user->ID'"); + $wpdb->query( "UPDATE $wpdb->categories SET cat_ID = '$global_id' WHERE cat_ID = '$term_id'" ); + $wpdb->query( "UPDATE $wpdb->categories SET category_parent = '$global_id' WHERE category_parent = '$term_id'" ); - if ($metavalues) { - foreach ( $metavalues as $meta ) { - @ $value = unserialize($meta->meta_value); - if ($value === FALSE) - $value = $meta->meta_value; - $user->{$meta->meta_key} = $value; + clean_term_cache($global_id, 'category'); + clean_term_cache($global_id, 'post_tag'); - // We need to set user_level from meta, not row - if ( $wpdb->prefix . 'user_level' == $meta->meta_key ) - $user->user_level = $meta->meta_value; - } - } - if( is_site_admin( $user_login ) == true ) { - $user->user_level = 10; - $cap_key = $wpdb->prefix . 'capabilities'; - $user->{$cap_key} = array( 'administrator' => '1' ); - } + return $global_id; +} +add_filter( 'term_id_filter', 'global_terms', 10, 2 ); // taxonomy specific filter - wp_cache_add($user->ID, $user, 'users'); - wp_cache_add($user->user_login, $user, 'userlogins'); - - return $user; -} +/* WordPress MU Default Filters */ +add_filter('the_title', 'wp_filter_kses'); function choose_primary_blog() { global $current_user; @@ -2022,5 +1917,4 @@ function choose_primary_blog() { } } add_action( 'profile_personal_options', 'choose_primary_blog' ); - ?> |
