Index: wp-includes/kses.php
===================================================================
--- wp-includes/kses.php	(revision 21789)
+++ wp-includes/kses.php	(working copy)
@@ -51,50 +51,42 @@
 	$allowedposttags = array(
 		'address' => array(),
 		'a' => array(
-			'class' => true,
 			'href' => true,
-			'id' => true,
-			'title' => true,
 			'rel' => true,
 			'rev' => true,
 			'name' => true,
 			'target' => true,
 		),
-		'abbr' => array(
-			'class' => true,
-			'title' => true,
+		'abbr' => array(),
+		'acronym' => array(),
+		'area' => array(
+			'alt' => true,
+			'coords' => true,
+			'href' => true,
+			'nohref' => true,
+			'shape' => true,
+			'target' => true,
 		),
-		'acronym' => array(
-			'title' => true,
-		),
 		'article' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'aside' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'b' => array(),
 		'big' => array(),
 		'blockquote' => array(
-			'id' => true,
 			'cite' => true,
-			'class' => true,
 			'lang' => true,
 			'xml:lang' => true,
 		),
-		'br' => array (
-			'class' => true,
-		),
+		'br' => array (),
 		'button' => array(
 			'disabled' => true,
 			'name' => true,
@@ -103,24 +95,18 @@
 		),
 		'caption' => array(
 			'align' => true,
-			'class' => true,
 		),
 		'cite' => array (
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'title' => true,
 		),
-		'code' => array (
-			'style' => true,
-		),
+		'code' => array (),
 		'col' => array(
 			'align' => true,
 			'char' => true,
 			'charoff' => true,
 			'span' => true,
 			'dir' => true,
-			'style' => true,
 			'valign' => true,
 			'width' => true,
 		),
@@ -130,19 +116,15 @@
 		'dd' => array(),
 		'details' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
 			'open' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'div' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'dl' => array(),
@@ -151,18 +133,14 @@
 		'fieldset' => array(),
 		'figure' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'figcaption' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'font' => array(
@@ -172,10 +150,8 @@
 		),
 		'footer' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'form' => array(
@@ -189,82 +165,58 @@
 		),
 		'h1' => array(
 			'align' => true,
-			'class' => true,
-			'id'    => true,
-			'style' => true,
 		),
 		'h2' => array (
 			'align' => true,
-			'class' => true,
-			'id'    => true,
-			'style' => true,
 		),
 		'h3' => array (
 			'align' => true,
-			'class' => true,
-			'id'    => true,
-			'style' => true,
 		),
 		'h4' => array (
 			'align' => true,
-			'class' => true,
-			'id'    => true,
-			'style' => true,
 		),
 		'h5' => array (
 			'align' => true,
-			'class' => true,
-			'id'    => true,
-			'style' => true,
 		),
 		'h6' => array (
 			'align' => true,
-			'class' => true,
-			'id'    => true,
-			'style' => true,
 		),
 		'header' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'hgroup' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'hr' => array (
 			'align' => true,
-			'class' => true,
 			'noshade' => true,
 			'size' => true,
 			'width' => true,
 		),
-		'i' => array(),
+		'i' => array (),
 		'img' => array(
 			'alt' => true,
 			'align' => true,
 			'border' => true,
-			'class' => true,
 			'height' => true,
 			'hspace' => true,
 			'longdesc' => true,
 			'vspace' => true,
 			'src' => true,
-			'style' => true,
+			'usemap' => true,
 			'width' => true,
 		),
 		'ins' => array(
 			'datetime' => true,
 			'cite' => true,
 		),
-		'kbd' => array(),
+		'kbd' => array (),
 		'label' => array(
 			'for' => true,
 		),
@@ -273,31 +225,26 @@
 		),
 		'li' => array (
 			'align' => true,
-			'class' => true,
 		),
+		'map' => array(
+			'name' => true,
+		),
 		'menu' => array (
-			'class' => true,
-			'style' => true,
 			'type' => true,
 		),
 		'nav' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'p' => array(
-			'class' => true,
 			'align' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
 		'pre' => array(
-			'style' => true,
 			'width' => true,
 		),
 		'q' => array(
@@ -305,46 +252,36 @@
 		),
 		's' => array(),
 		'span' => array (
-			'class' => true,
 			'dir' => true,
 			'align' => true,
 			'lang' => true,
-			'style' => true,
-			'title' => true,
 			'xml:lang' => true,
 		),
 		'section' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
-		'small' => array(),
-		'strike' => array(),
-		'strong' => array(),
-		'sub' => array(),
+		'small' => array (),
+		'strike' => array (),
+		'strong' => array (),
+		'sub' => array (),
 		'summary' => array(
 			'align' => true,
-			'class' => true,
 			'dir' => true,
 			'lang' => true,
-			'style' => true,
 			'xml:lang' => true,
 		),
-		'sup' => array(),
+		'sup' => array (),
 		'table' => array(
 			'align' => true,
 			'bgcolor' => true,
 			'border' => true,
 			'cellpadding' => true,
 			'cellspacing' => true,
-			'class' => true,
 			'dir' => true,
-			'id' => true,
 			'rules' => true,
-			'style' => true,
 			'summary' => true,
 			'width' => true,
 		),
@@ -361,7 +298,6 @@
 			'bgcolor' => true,
 			'char' => true,
 			'charoff' => true,
-			'class' => true,
 			'colspan' => true,
 			'dir' => true,
 			'headers' => true,
@@ -369,7 +305,6 @@
 			'nowrap' => true,
 			'rowspan' => true,
 			'scope' => true,
-			'style' => true,
 			'valign' => true,
 			'width' => true,
 		),
@@ -383,7 +318,6 @@
 		'tfoot' => array(
 			'align' => true,
 			'char' => true,
-			'class' => true,
 			'charoff' => true,
 			'valign' => true,
 		),
@@ -394,7 +328,6 @@
 			'bgcolor' => true,
 			'char' => true,
 			'charoff' => true,
-			'class' => true,
 			'colspan' => true,
 			'headers' => true,
 			'height' => true,
@@ -408,7 +341,6 @@
 			'align' => true,
 			'char' => true,
 			'charoff' => true,
-			'class' => true,
 			'valign' => true,
 		),
 		'title' => array(),
@@ -417,21 +349,15 @@
 			'bgcolor' => true,
 			'char' => true,
 			'charoff' => true,
-			'class' => true,
-			'style' => true,
 			'valign' => true,
 		),
-		'tt' => array(),
-		'u' => array(),
+		'tt' => array (),
+		'u' => array (),
 		'ul' => array (
-			'class' => true,
-			'style' => true,
 			'type' => true,
 		),
 		'ol' => array (
-			'class' => true,
 			'start' => true,
-			'style' => true,
 			'type' => true,
 		),
 		'var' => array(),
@@ -526,6 +452,11 @@
 		'sdot',    'lceil',  'rceil',   'lfloor', 'rfloor', 'lang',
 		'rang',    'loz',    'spades',  'clubs',  'hearts', 'diams',
 	);
+
+	$allowedposttags = array_map( '_wp_add_global_attributes', $allowedposttags );
+} else {
+	$allowedtags = wp_kses_array_lc( $allowedtags );
+	$allowedposttags = wp_kses_array_lc( $allowedposttags );
 }
 
 /**
@@ -554,12 +485,48 @@
 	$string = wp_kses_no_null($string);
 	$string = wp_kses_js_entities($string);
 	$string = wp_kses_normalize_entities($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);
+	$string = wp_kses_hook($string, $allowed_html, $allowed_protocols); // WP changed the order of these funcs and added args to wp_kses_hook
+	return wp_kses_split($string, $allowed_html, $allowed_protocols);
 }
 
 /**
+ * Return a list of allowed tags and attributes for a given context.
+ *
+ * @since 3.5.0
+ *
+ * @param string $context The context for which to retrieve tags. Allowed values are
+ *  post | strip | data | entities or the name of a field filter such as pre_user_description.
+ * @return array List of allowed tags and their allowed attributes.
+ */
+function wp_kses_allowed_html( $context = '' ) {
+	global $allowedposttags, $allowedtags, $allowedentitynames;
+
+	if ( is_array( $context ) )
+		return apply_filters( 'wp_kses_allowed_html', $context, 'explicit' );
+
+	switch ( $context ) {
+		case 'post':
+			return apply_filters( 'wp_kses_allowed_html', $allowedposttags, $context );
+			break;
+		case 'user_description':
+		case 'pre_user_description':
+			$tags = $allowedtags;
+			$tags['a']['rel'] = true;
+			return apply_filters( 'wp_kses_allowed_html', $tags, $context );
+			break;
+		case 'strip':
+			return apply_filters( 'wp_kses_allowed_html', array(), $context );
+			break;
+		case 'entities':
+			return apply_filters( 'wp_kses_allowed_html', $allowedentitynames, $context);
+			break;
+		case 'data':
+		default:
+			return apply_filters( 'wp_kses_allowed_html', $allowedtags, $context );
+	}
+}
+
+/**
  * You add any kses hooks here.
  *
  * There is currently only one kses WordPress hook and it is called here. All
@@ -572,7 +539,7 @@
  * @param array $allowed_protocols Allowed protocol in links
  * @return string Filtered content through 'pre_kses' hook
  */
-function wp_kses_hook($string, $allowed_html, $allowed_protocols) {
+function wp_kses_hook( $string, $allowed_html, $allowed_protocols ) {
 	$string = apply_filters('pre_kses', $string, $allowed_html, $allowed_protocols);
 	return $string;
 }
@@ -600,7 +567,7 @@
  * @param array $allowed_protocols Allowed protocols to keep
  * @return string Content with fixed HTML tags
  */
-function wp_kses_split($string, $allowed_html, $allowed_protocols) {
+function wp_kses_split( $string, $allowed_html, $allowed_protocols ) {
 	global $pass_allowed_html, $pass_allowed_protocols;
 	$pass_allowed_html = $allowed_html;
 	$pass_allowed_protocols = $allowed_protocols;
@@ -668,6 +635,9 @@
 	$elem = $matches[2];
 	$attrlist = $matches[3];
 
+	if ( ! is_array( $allowed_html ) )
+		$allowed_html = wp_kses_allowed_html( $allowed_html );
+
 	if ( ! isset($allowed_html[strtolower($elem)]) )
 		return '';
 	# They are using a not allowed HTML element
@@ -699,6 +669,9 @@
 function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) {
 	# Is there a closing XHTML slash at the end of the attributes?
 
+	if ( ! is_array( $allowed_html ) )
+		$allowed_html = wp_kses_allowed_html( $allowed_html );
+
 	$xhtml_slash = '';
 	if (preg_match('%\s*/\s*$%', $attr))
 		$xhtml_slash = ' /';
@@ -1286,9 +1259,8 @@
  * @param string $data Content to filter, expected to be escaped with slashes
  * @return string Filtered content
  */
-function wp_filter_kses($data) {
-	global $allowedtags;
-	return addslashes( wp_kses(stripslashes( $data ), $allowedtags) );
+function wp_filter_kses( $data ) {
+	return addslashes( wp_kses( stripslashes( $data ), current_filter() ) );
 }
 
 /**
@@ -1300,9 +1272,8 @@
  * @param string $data Content to filter, expected to not be escaped
  * @return string Filtered content
  */
-function wp_kses_data($data) {
-	global $allowedtags;
-	return wp_kses( $data , $allowedtags );
+function wp_kses_data( $data ) {
+	return wp_kses( $data , current_filter() );
 }
 
 /**
@@ -1312,14 +1283,12 @@
  * data from forms.
  *
  * @since 2.0.0
- * @uses $allowedposttags
  *
  * @param string $data Post content to filter, expected to be escaped with slashes
  * @return string Filtered post content with allowed HTML tags and attributes intact.
  */
 function wp_filter_post_kses($data) {
-	global $allowedposttags;
-	return addslashes ( wp_kses(stripslashes( $data ), $allowedposttags) );
+	return addslashes ( wp_kses( stripslashes( $data ), 'post' ) );
 }
 
 /**
@@ -1329,14 +1298,12 @@
  * data from forms.
  *
  * @since 2.9.0
- * @uses $allowedposttags
  *
  * @param string $data Post content to filter
  * @return string Filtered post content with allowed HTML tags and attributes intact.
  */
 function wp_kses_post($data) {
-	global $allowedposttags;
-	return wp_kses( $data , $allowedposttags );
+	return wp_kses( $data , 'post' );
 }
 
 /**
@@ -1347,8 +1314,8 @@
  * @param string $data Content to strip all HTML from
  * @return string Filtered content without any HTML
  */
-function wp_filter_nohtml_kses($data) {
-	return addslashes ( wp_kses(stripslashes( $data ), array()) );
+function wp_filter_nohtml_kses( $data ) {
+	return addslashes ( wp_kses( stripslashes( $data ), 'strip' ) );
 }
 
 /**
@@ -1484,3 +1451,29 @@
 
 	return $css;
 }
+
+/**
+ * Helper function to add global attributes to a tag in the allowed html list.
+ *
+ * @since 3.5.0
+ * @access private
+ *
+ * @param array $value An array of attributes.
+ * @return array The array of attributes with global attributes added.
+ */
+function _wp_add_global_attributes( $value ) {
+	$global_attributes = array(
+		'class' => true,
+		'id' => true,
+		'style' => true,
+		'title' => true,
+	);
+
+	if ( true === $value )
+		$value = array();
+
+	if ( is_array( $value ) )
+		return array_merge( $value, $global_attributes );
+
+	return $value;
+}
