Index: wp-includes/template-functions-general.php
===================================================================
--- wp-includes/template-functions-general.php	(revision 3405)
+++ wp-includes/template-functions-general.php	(working copy)
@@ -82,6 +82,13 @@
 		case 'wpurl' :
 			$output = get_settings('siteurl');
 			break;
+		case 'atom_alternate_url':
+			$output = get_self_link(-1);
+            break;
+		case 'atom_self_url':
+		case 'self' :
+			$output = get_self_link();
+			break;
 		case 'description':
 			$output = get_settings('blogdescription');
 			break;
Index: wp-includes/template-functions-links.php
===================================================================
--- wp-includes/template-functions-links.php	(revision 3405)
+++ wp-includes/template-functions-links.php	(working copy)
@@ -175,11 +175,193 @@
 	}
 }
 
+function get_self_link($omit_feed = 0) {
+	// This function produce the "prettiest" link that returns this resource
+	// Set $omit_feed to:
+	//   -1 to force the link to not contain a feed
+	//    0 to leave the feed parameter alone
+	//    1 to force the link to contain a feed
+
+	global $wp_rewrite;
+	// NOTE: This could be refactored into 'get_self_link' and 'get_params_link'
+	//  the latter could take an array of arbitrary paramaters (like the one below)
+	$params = array(
+		's' => get_query_var('s'),
+		'pagename' => get_query_var('pagename'),
+		'author_name' => get_query_var('author_name'),
+		'author' => get_query_var('author'),
+		'category_name' => get_query_var('category_name'),
+		'cat' => get_query_var('cat'),
+		'year' => get_query_var('year'),
+		'monthnum' => get_query_var('monthnum'),
+		'day' => get_query_var('day'),
+		'hour' => get_query_var('hour'),
+		'minute' => get_query_var('minute'),
+		'second' => get_query_var('second'),
+		'name' => get_query_var('name'),
+		'p' => get_query_var('p') );
+	foreach ( $params as $key => $value ) {
+		if ( empty($value) )
+			 unset($params[$key]);
+		else
+			 $params[$key] = rawurlencode($value);
+	}
+	// feed is a special case because it can be safely combined with 
+	// various permalink types
+	$feed = rawurlencode(get_query_var('feed'));
+	switch ( $omit_feed ) {
+	case 1:
+		if ( empty($feed) )
+			$feed = 'feed';
+		break;
+	case -1:
+		$feed = '';
+		break;
+	case 0:
+	default:
+		// do nothing
+		break;
+	}
+
+	$link = '';
+	// search, date, category, author
+	if ( $wp_rewrite->using_permalinks() ) {
+		if ( 1 == count($params) ) {
+			if ( ! empty($params['s']) ) {
+				$link = str_replace('%search%', $params['s'], $wp_rewrite->get_search_permastruct());
+			} else if ( ! empty($params['category_name']) ) {
+				$link = str_replace('%category%', $params['category_name'], $wp_rewrite->get_category_permastruct());
+			} else if ( ! empty($params['author_name']) ) {
+				$link = str_replace('%author%', $params['author_name'], $wp_rewrite->get_author_permastruct());
+			} else if ( ! empty($params['pagename']) ) {
+				$link = str_replace('%pagename%', $params['pagename'], $wp_rewrite->get_page_permastruct());
+			}
+		} else if ( 2 == count($params) ) {
+			if ( ! empty($params['cat']) && ( $params['category_name'] == get_catname($params['cat']) ) ) {
+				$link = str_replace('%category%', $params['category_name'], $wp_rewrite->get_category_permastruct());
+			} else if ( ! empty($params['author']) && ( $params['author_name'] == get_author_name($params['author']) ) ) {
+				$link = str_replace('%author%', $params['author_name'], $wp_rewrite->get_author_permastruct());
+			}
+		} else {
+			$is_date = false;
+			// if exactly one date param is not empty
+			if ( ( 1 == count($params) ) && ( ! empty($params['year']) || ! empty($params['monthnum']) || ! empty($params['day']) ) ) {
+				$is_date = true;
+			// if exactly two date params are not empty
+			} else if ( ( 2 == count($params) ) && ( ( ! empty($params['year']) && ! empty($params['monthnum']) ) || ( ! empty($params['monthnum']) && ! empty($params['day']) ) ) ) {
+				$is_date = true;
+			// if all three date params are not empty
+			} else if ( ( 3 == count($params) ) && ( ! empty($params['year']) && ! empty($params['monthnum']) && ! empty($params['day']) ) ) {
+				$is_date = true;
+			}
+			if ( $is_date ) {
+				if( ! empty($params['monthnum']) )
+					$params['monthnum'] = zeroise($params['monthnum'], 2);
+
+				if( ! empty($params['day']) )
+					$params['day'] = zeroise($params['day'], 2);
+				
+				$link = $wp_rewrite->get_date_permastruct();
+				$link = str_replace('%year%', $params['year'], $link);
+				$link = str_replace('%monthnum%', $params['monthnum'], $link);
+				$link = str_replace('%day%', $params['day'], $link);
+				$link = preg_replace('#/+#', '/', $link);
+			} else {
+				$struct = get_settings('permalink_structure');
+				
+				// replacements for consistency
+				$struct = str_replace('%post_id%', '%p%', $struct);
+				$struct = str_replace('%postname%', '%name%', $struct);
+				$struct = str_replace('%category%', '%category_name%', $struct);
+				$struct = str_replace('%author%', '%author_name%', $struct);
+				
+				// Note: array assignment always copies
+				$params_copy = $params;
+				foreach ( $params_copy as $key => $value ) {
+					if ( false === strpos($struct, "%{$key}%") ) {
+						$struct = str_replace("%{$key}%", $value, $struct);
+						unset($params_copy[$key]);
+					}
+				}
+				// were all the parameters used?
+				if ( empty($params_copy) ) {
+					$link = $struct;
+					$tags = array(
+						'p',
+						'title',
+						'category_name',
+						'author_name',
+						'year',
+						'monthnum',
+						'day',
+						'hour',
+						'minute',
+						'second' );
+					// were all tags substituted for?
+					foreach ( $tags as $value ) {
+						if ( false !== strpos($struct, "%{$value}%") ) {
+							$link = '';
+							break;
+						}
+					}
+				}
+			}
+		}
+
+		// handle feed
+		if ( ! empty($feed) ) {
+			if ( 0 == count($params) ) {
+				if ( ( 1 === $feed ) || ( 'feed' == $feed ) )
+					$feed = '';
+				$link = str_replace('%feed%', $feed, $wp_rewrite->get_feed_permastruct());
+			} else if ( '' != $link ) {
+				$link = trailingslashit($link);
+				if ( 1 === $feed )
+					$link .= 'feed/';
+				else
+					$link = trailingslashit($link) . "feed/{$feed}/";
+			}
+		}
+	}
+
+	$home = trailingslashit(get_settings('home'));
+	if ( '' == $link ) {
+		foreach ( $params as $key => $value ) {
+			if ( ! empty($value) ) {
+				$link .= "&{$key}={$value}";
+			}
+		}
+		if ( ! empty($feed) )
+			$link .= "&feed={$feed}";
+
+		if ( empty($link) ) {
+			$link = $home;
+		} else {
+			$link = "{$home}?" . substr($link, 1);
+		}
+	} else {
+		$link = trailingslashit($link);
+		$link = preg_replace('#/+#', '/', $link);
+		if ( $link{0} == '/' )
+			$link = substr($link, 1);
+		
+		$link = $home . $link;
+	}
+	return $link;
+}
+
 function get_feed_link($feed='rss2') {
 	global $wp_rewrite;
 	$do_perma = 0;
 	$feed_url = get_settings('siteurl');
 	$comment_feed_url = $feed_url;
+	$cat = '';
+	if ( false !== strpos($feed, '_self') ) {
+		$feed = str_replace('_self', '', $feed);
+		$cat = intval( get_query_var('cat') );
+		if ( ( $cat == 0 ) || ( strtoupper($cat) == 'ALL' ) )
+			$cat = '';
+	}
 
 	$permalink = $wp_rewrite->get_feed_permastruct();
 	if ( '' != $permalink ) {
@@ -193,12 +375,14 @@
 
 		$permalink = str_replace('%feed%', $feed, $permalink);
 		$permalink = preg_replace('#/+#', '/', "/$permalink/");
-		$output =  get_settings('home') . $permalink;
+		$output = get_settings('home') . $permalink;
 	} else {
 		if ( false !== strpos($feed, 'comments_') )
 			$feed = str_replace('comments_', 'comments-', $feed);
+		if ( $cat )
+			$cat = "&cat={$cat}";
 
-		$output = get_settings('home') . "/?feed={$feed}";
+		$output = get_settings('home') . "/?feed={$feed}{$cat}";
 	}
 
 	return apply_filters('feed_link', $output, $feed);
@@ -318,7 +502,7 @@
 
 	$format = str_replace('%link', $link, $format);
 
-	echo $format;	    
+	echo $format;
 }
 
 function next_post_link($format='%link &raquo;', $link='%title', $in_same_cat = false, $excluded_categories = '') {
@@ -333,7 +517,7 @@
 	$link = $string . $link . '</a>';
 	$format = str_replace('%link', $link, $format);
 
-	echo $format;	    
+	echo $format;
 }
 
 
Index: wp-includes/feed-functions.php
===================================================================
--- wp-includes/feed-functions.php	(revision 3405)
+++ wp-includes/feed-functions.php	(working copy)
@@ -105,7 +105,7 @@
 				 $link = get_author_link(0, $author_id, $author_nicename);
 				 $link = $link . "feed/";
        }
-			 
+
 			 $link = apply_filters('author_feed_link', $link);
 
        if ($echo) echo $link;
@@ -148,7 +148,7 @@
 
 	$custom_fields = get_post_custom();
 	if( is_array( $custom_fields ) ) {
-		while( list( $key, $val ) = each( $custom_fields ) ) { 
+		while( list( $key, $val ) = each( $custom_fields ) ) {
 			if( $key == 'enclosure' ) {
 				if (is_array($val)) {
 					foreach($val as $enc) {
@@ -161,4 +161,23 @@
 	}
 }
 
+
+function atom_enclosure() {
+	global $id, $post;
+	if (!empty($post->post_password) && ($_COOKIE['wp-postpass_'.COOKIEHASH] != $post->post_password)) return;
+
+	$custom_fields = get_post_custom();
+	if( is_array( $custom_fields ) ) {
+	while( list( $key, $val ) = each( $custom_fields ) ) {
+			if( $key == 'enclosure' ) {
+				if (is_array($val)) {
+					foreach($val as $enc) {
+						$enclosure = split( "\n", $enc );
+						print "<link rel=\"enclosure\" href=\"".trim( htmlspecialchars($enclosure[ 0 ]) )."\" length=\"".trim( $enclosure[ 1 ] )."\" type=\"".trim( $enclosure[ 2 ] )."\"/>\n";
+					}
+				}
+			}
+		}
+	}
+}
 ?>
\ No newline at end of file
Index: wp-content/themes/classic/header.php
===================================================================
--- wp-content/themes/classic/header.php	(revision 3405)
+++ wp-content/themes/classic/header.php	(working copy)
@@ -14,7 +14,7 @@
 
 	<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="<?php bloginfo('rss2_url'); ?>" />
 	<link rel="alternate" type="text/xml" title="RSS .92" href="<?php bloginfo('rss_url'); ?>" />
-	<link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="<?php bloginfo('atom_url'); ?>" />
+	<link rel="alternate" type="application/atom+xml" title="Atom 1.0" href="<?php bloginfo('atom_url'); ?>" />
 	
 	<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />
     <?php wp_get_archives('type=monthly&format=link'); ?>
Index: wp-content/themes/default/header.php
===================================================================
--- wp-content/themes/default/header.php	(revision 3405)
+++ wp-content/themes/default/header.php	(working copy)
@@ -9,6 +9,7 @@
 <meta name="generator" content="WordPress <?php bloginfo('version'); ?>" /> <!-- leave this for stats -->
 
 <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />
+<link rel="alternate" type="application/atom+xml" title="<?php bloginfo('name'); ?> Atom Feed" href="<?php bloginfo('atom_url'); ?>" />
 <link rel="alternate" type="application/rss+xml" title="<?php bloginfo('name'); ?> RSS Feed" href="<?php bloginfo('rss2_url'); ?>" />
 <link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />
 
Index: wp-atom.php
===================================================================
--- wp-atom.php	(revision 3405)
+++ wp-atom.php	(working copy)
@@ -1,45 +1,59 @@
 <?php
+// Atom 1.0 feed generator for WordPress
+// Distributed under the terms of the GNU General Public License v2
 
-if (empty($wp)) {
-	require_once('wp-config.php');
-	wp('feed=atom');
+if (empty($feed)) {
+	$blog = 1;
+	$feed = 'atom';
+	$doing_rss = 1;
+	require('wp-blog-header.php');
 }
 
 header('Content-type: application/atom+xml; charset=' . get_settings('blog_charset'), true);
 $more = 1;
-
 ?>
-<?php echo '<?xml version="1.0" encoding="'.get_settings('blog_charset').'"?'.'>'; ?>
-<feed version="0.3"
-  xmlns="http://purl.org/atom/ns#"
-  xmlns:dc="http://purl.org/dc/elements/1.1/"
-  xml:lang="<?php echo get_option('rss_language'); ?>"
-  <?php do_action('atom_ns'); ?>
-  >
-	<title><?php bloginfo_rss('name') ?></title>
-	<link rel="alternate" type="text/html" href="<?php bloginfo_rss('home') ?>" />
-	<tagline><?php bloginfo_rss("description") ?></tagline>
-	<modified><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></modified>
-	<copyright>Copyright <?php echo mysql2date('Y', get_lastpostdate('blog'), 0); ?></copyright>
-	<generator url="http://wordpress.org/" version="<?php bloginfo_rss('version'); ?>">WordPress</generator>
+<?php echo '<?xml version="1.0" encoding="'.get_settings('blog_charset').'"?'.'>'."\n"; ?>
+<feed xmlns="http://www.w3.org/2005/Atom"
+      xml:lang="<?php echo get_option('rss_language'); ?>"
+      <?php do_action('atom_ns'); ?>>
+	<title><?php bloginfo_rss('name'); ?></title>
+	<subtitle><?php bloginfo_rss('description'); ?></subtitle>
+	<id><?php bloginfo('url'); ?>/</id>
+	<link rel="self" type="application/atom+xml" href="<?php bloginfo_rss('atom_self_url'); ?>"/>
+	<link rel="alternate" type="<?php bloginfo('html_type'); ?>" href="<?php bloginfo_rss('atom_alternate_url'); ?>"/>
+	<updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></updated>
+	<rights>Copyright <?php echo mysql2date('Y', get_lastpostdate('blog'), 0); ?></rights>
+	<generator uri="http://wordpress.org/" version="<?php bloginfo_rss('version'); ?>">WordPress</generator>
 	<?php do_action('atom_head'); ?>
 	<?php $items_count = 0; if ($posts) { foreach ($posts as $post) { start_wp(); ?>
 	<entry>
 	  	<author>
-			<name><?php the_author() ?></name>
+			<name><?php the_author(); ?></name>
 		</author>
-		<title type="text/html" mode="escaped"><![CDATA[<?php the_title_rss() ?>]]></title>
-		<link rel="alternate" type="text/html" href="<?php permalink_single_rss() ?>" />
-		<id><?php the_guid(); ?></id>
-		<modified><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></modified>
-		<issued><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></issued>
-		<?php the_category_rss('rdf') ?> 
-		<summary type="text/plain" mode="escaped"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary>
+		<title type="html"><![CDATA[ <?php the_title_rss(); ?> ]]></title>
+		<link rel="alternate" type="<?php bloginfo('html_type'); ?>" href="<?php permalink_single_rss(); ?>"/>
+		<id><?php permalink_single_rss(); ?></id>
+		<published><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></published>
+		<updated><?php echo mysql2date('Y-m-d\TH:i:s\Z',$post->post_modified_gmt); ?></updated>
+<?php
+	$categories_path = get_category_link(0);
+	$categories = get_the_category();
+	foreach ($categories as $cat) { ?>
+		<category scheme="<?php echo $categories_path; ?>"
+		          term="<?php $foo = "/" . str_replace('/','\/',$categories_path) . "/";
+							echo preg_replace($foo,'',get_category_link($cat->cat_ID)); ?>"
+		          label="<?php echo $cat->cat_name; ?>"/>
+<?php } ?>
+		<summary type="html">
+			<![CDATA[ <?php the_excerpt_rss(); ?> ]]>
+		</summary>
 <?php if ( !get_settings('rss_use_excerpt') ) : ?>
-		<content type="<?php bloginfo('html_type'); ?>" mode="escaped" xml:base="<?php permalink_single_rss() ?>"><![CDATA[<?php the_content('', 0, '') ?>]]></content>
+		<content type="html">
+			<![CDATA[ <?php the_content('', 0, '') ?> ]]>
+		</content>
+		<?php atom_enclosure(); ?>
+		<?php do_action('atom_entry'); ?>
 <?php endif; ?>
-<?php rss_enclosure(); ?>
-<?php do_action('atom_entry'); ?>
 	</entry>
 	<?php $items_count++; if (($items_count == get_settings('posts_per_rss')) && empty($m)) { break; } } } ?>
-</feed>
+</feed>
\ No newline at end of file
