Index: wp-app.php
===================================================================
--- wp-app.php	(revision 5535)
+++ wp-app.php	(working copy)
@@ -11,6 +11,7 @@
 
 require_once('wp-config.php');
 require_once('wp-includes/post-template.php');
+require_once('wp-includes/atomlib.php');
 
 // Attempt to automatically detect whether to use querystring
 // or PATH_INFO, based on our environment:
@@ -18,7 +19,7 @@
 
 // If using querystring, we need to put the path together manually:
 if ($use_querystring) {
-	$GLOBALS['use_querystring'] = $use_querystring;
+	GLOBALS['use_querystring'] = $use_querystring;
 	$action = $_GET['action'];
 	$eid = (int) $_GET['eid'];
 
@@ -28,7 +29,7 @@
 		$_SERVER['PATH_INFO'] .= "/$eid";
 	}
 } else {
-	$_SERVER['PATH_INFO'] = str_replace( '/wp-app.php', '', $_SERVER['REQUEST_URI'] );
+	$_SERVER['PATH_INFO'] = str_replace( '.*/wp-app.php', '', $_SERVER['REQUEST_URI'] );
 }
 
 $app_logging = 0;
@@ -36,7 +37,7 @@
 function log_app($label,$msg) {
 	global $app_logging;
 	if ($app_logging) {
-		$fp = fopen( 'app.log', 'a+');
+		$fp = fopen( 'wp-app.log', 'a+');
 		$date = gmdate( 'Y-m-d H:i:s' );
 		fwrite($fp, "\n\n$date - $label\n$msg\n");
 		fclose($fp);
@@ -57,216 +58,22 @@
 endif;
 
 function wa_posts_where_include_drafts_filter($where) {
-	$where = ereg_replace("post_author = ([0-9]+) AND post_status != 'draft'","post_author = \\1 AND post_status = 'draft'", $where);
-	return $where;
+    $where = ereg_replace("post_status = 'publish'","post_status = 'publish' OR post_status = 'future' OR post_status = 'draft'", $where);
+    return $where;
 }
 add_filter('posts_where', 'wa_posts_where_include_drafts_filter');
 
-class AtomEntry {
-	var $links = array();
-	var $categories = array();
-}
-
-class AtomParser {
-
-	var $ATOM_CONTENT_ELEMENTS = array('content','summary','title','subtitle','rights');
-	var $ATOM_SIMPLE_ELEMENTS = array('id','updated','published','draft');
-
-	var $depth = 0;
-	var $indent = 2;
-	var $in_content;
-	var $ns_contexts = array();
-	var $ns_decls = array();
-	var $is_xhtml = false;
-	var $skipped_div = false;
-
-	var $entry;
-
-	function AtomParser() {
-
-		$this->entry = new AtomEntry();
-		$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 parse() {
-
-		global $app_logging;
-		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");
-
-		$contents = "";
-
-		$fp = fopen("php://input", "r");
-		while(!feof($fp)) {
-			$line = fgets($fp, 4096);
-		 
-			if($app_logging) $contents .= $line;
-
-			if(!xml_parse($parser, $line)) {
-				log_app("xml_parse_error", "line: $line");
-				$this->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));
-				log_app("xml_parse_error", $this->error);
-				return false;
-			}
-		}
-		fclose($fp);
-
-		xml_parser_free($parser);
-
-		log_app("AtomParser->parse()",trim($contents));
-
-		return true;
-	}
-
-	function start_element($parser, $name, $attrs) {
-
-		$tag = array_pop(split(":", $name));
-
-		array_unshift($this->ns_contexts, $this->ns_decls);
-
-		$this->depth++;
-
-		#print str_repeat(" ", $this->depth * $this->indent) . "start_element('$name')" ."\n";
-		#print str_repeat(" ", $this->depth+1 * $this->indent) . print_r($this->ns_contexts,true) ."\n";
-
-		if(!empty($this->in_content)) {
-			$attrs_prefix = array();
-
-			// resolve prefixes for attributes
-			foreach($attrs as $key => $value) {
-				$attrs_prefix[$this->ns_to_prefix($key)] = $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;
-			}
-
-			$xmlns_str = join(' ', array_map($this->map_xmlns_func, array_keys($this->ns_contexts[0]), array_values($this->ns_contexts[0])));
-			if(strlen($xmlns_str) > 0) {
-				$xmlns_str = " " . $xmlns_str;
-			}
-
-			// handle self-closing tags (case: a new child found right-away, no text node)
-			if(count($this->in_content) == 2) {
-				array_push($this->in_content, ">");
-			}
-		 
-			array_push($this->in_content, "<". $this->ns_to_prefix($name) ."{$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'; 
-			array_push($this->in_content, array($tag,$this->depth));
-		} else if($tag == 'link') {
-			array_push($this->entry->links, $attrs);
-		} else if($tag == 'category') {
-			array_push($this->entry->categories, $attrs);
-		}
-
-		$this->ns_decls = array();
-	}
-
-	function end_element($parser, $name) {
-
-		$tag = array_pop(split(":", $name));
-
-		if(!empty($this->in_content)) {
-			if($this->in_content[0][0] == $tag && 
-			$this->in_content[0][1] == $this->depth) {
-				array_shift($this->in_content);
-				if($this->is_xhtml) {
-					$this->in_content = array_slice($this->in_content, 2, count($this->in_content)-3);
-				}
-				$this->entry->$tag = join('',$this->in_content);
-				$this->in_content = array();
-			} else {
-				$endtag = $this->ns_to_prefix($name);
-				if (strpos($this->in_content[count($this->in_content)-1], '<' . $endtag) !== false) {
-					array_push($this->in_content, "/>");
-				} else {
-					array_push($this->in_content, "</$endtag>");
-				}
-			}
-		}
-
-		array_shift($this->ns_contexts);
-
-		#print str_repeat(" ", $this->depth * $this->indent) . "end_element('$name')" ."\n";
-
-		$this->depth--;
-	}
-
-	function start_ns($parser, $prefix, $uri) {
-		#print str_repeat(" ", $this->depth * $this->indent) . "starting: " . $prefix . ":" . $uri . "\n";
-		array_push($this->ns_decls, array($prefix,$uri));
-	}
-
-	function end_ns($parser, $prefix) {
-		#print str_repeat(" ", $this->depth * $this->indent) . "ending: #" . $prefix . "#\n";
-	}
-
-	function cdata($parser, $data) {
-		#print str_repeat(" ", $this->depth * $this->indent) . "data: #" . $data . "#\n";
-		if(!empty($this->in_content)) {
-			// handle self-closing tags (case: text node found, need to close element started)
-			if (strpos($this->in_content[count($this->in_content)-1], '<') !== false) {
-				array_push($this->in_content, ">");
-			}
-			array_push($this->in_content, $this->xml_escape($data));
-		}
-	}
-
-	function _default($parser, $data) {
-		# when does this gets called?
-	}
-
-
-	function ns_to_prefix($qname) {
-		$components = split(":", $qname);
-		$name = array_pop($components);
-
-		if(!empty($components)) {
-			$ns = join(":",$components);
-			foreach($this->ns_contexts as $context) {
-				foreach($context as $mapping) {
-					if($mapping[1] == $ns && strlen($mapping[0]) > 0) {
-						return "$mapping[0]:$name";
-					}
-				}
-			}
-		} 
-		return $name;
-	}
-
-	function xml_escape($string)
-	{
-			 return str_replace(array('&','"',"'",'<','>'), 
-				array('&amp;','&quot;','&apos;','&lt;','&gt;'), 
-				$string );
-	}
-}
-
 class AtomServer {
 
 	var $ATOM_CONTENT_TYPE = 'application/atom+xml';
 	var $CATEGORIES_CONTENT_TYPE = 'application/atomcat+xml';
-	var $INTROSPECTION_CONTENT_TYPE = 'application/atomserv+xml';
+	var $INTROSPECTION_CONTENT_TYPE = 'application/atomsvc+xml';
 
 	var $ENTRIES_PATH = "posts";
 	var $CATEGORIES_PATH = "categories";
 	var $MEDIA_PATH = "attachments";
 	var $ENTRY_PATH = "post";
+	var $SERVICE_PATH = "service";
 	var $MEDIA_SINGLE_PATH = "attachment";
 
 	var $params = array();
@@ -284,25 +91,25 @@
 		$this->script_name = array_pop(explode('/',$_SERVER['SCRIPT_NAME']));
 
 		$this->selectors = array(
-			'@/service@' => 
+			'@/service$@' => 
 				array('GET' => 'get_service'),
-			'@/categories@' =>
+			'@/categories$@' =>
 				array('GET' => 'get_categories_xml'),
-			'@/post/(\d+)@' => 
+			'@/post/(\d+)$@' => 
 				array('GET' => 'get_post', 
 						'PUT' => 'put_post', 
 						'DELETE' => 'delete_post'),
-			'@/posts/?([^/]+)?@' => 
+			'@/posts/?(\d+)?$@' => 
 				array('GET' => 'get_posts', 
 						'POST' => 'create_post'),
-			'@/attachments/?(\d+)?@' => 
+			'@/attachments/?(\d+)?$@' => 
 				array('GET' => 'get_attachment', 
 						'POST' => 'create_attachment'),
-			'@/attachment/file/(\d+)@' => 
+			'@/attachment/file/(\d+)$@' => 
 				array('GET' => 'get_file', 
 						'PUT' => 'put_file', 
 						'DELETE' => 'delete_file'),
-			'@/attachment/(\d+)@' => 
+			'@/attachment/(\d+)$@' => 
 				array('GET' => 'get_attachment', 
 						'PUT' => 'put_attachment', 
 						'DELETE' => 'delete_attachment'),
@@ -324,27 +131,32 @@
 			$method = 'GET';
 		}
 
-		// lame. 
+		// redirect to /service in case no path is found. 
 		if(strlen($path) == 0 || $path == '/') {
-			$path = '/service';
+				$this->redirect($this->get_service_url());
 		}
-
-		// authenticate regardless of the operation and set the current
-		// user. each handler will decide if auth is required or not.
-		$this->authenticate();
-
+	
 		// dispatch
 		foreach($this->selectors as $regex => $funcs) {
 			if(preg_match($regex, $path, $matches)) {
-				if(isset($funcs[$method])) {
-					array_shift($matches);
-					call_user_func_array(array(&$this,$funcs[$method]), $matches);
-					exit();
-				} else {
-					// only allow what we have handlers for...
-					$this->not_allowed(array_keys($funcs));
-				}
+			if(isset($funcs[$method])) {
+
+						// authenticate regardless of the operation and set the current
+						// user. each handler will decide if auth is required or not.
+						$this->authenticate();                
+						$u = wp_get_current_user();
+						if(!isset($u) || $u->ID == 0) {
+						$this->auth_required('Credentials required.');
+						}
+
+						array_shift($matches);
+						call_user_func_array(array(&$this,$funcs[$method]), $matches);
+						exit();
+			} else {
+						// only allow what we have handlers for...
+						$this->not_allowed(array_keys($funcs));
 			}
+			}
 		}
 
 		// oops, nothing found
@@ -353,23 +165,24 @@
 
 	function get_service() {
 		log_app('function','get_service()');
-		$entries_url = $this->get_entries_url();
-		$categories_url = $this->get_categories_url(); 
-		$media_url = $this->get_attachments_url();
-		$accepted_content_types = join(',',$this->media_content_types);
+		$entries_url = attribute_escape($this->get_entries_url());
+		$categories_url = attribute_escape($this->get_categories_url()); 
+		$media_url = attribute_escape($this->get_attachments_url());
+		$accepted_content_types = attribute_escape(join(',',$this->media_content_types));
 		$introspection = <<<EOD
 <service xmlns="http://purl.org/atom/app#" xmlns:atom="http://www.w3.org/2005/Atom"> 
-	<workspace title="WordPress Workspace"> 
-	    <collection href="$entries_url" title="Posts"> 
-		<atom:title>WordPress Posts</atom:title> 
-		<accept>entry</accept> 
-		<categories href="$categories_url" /> 
-	    </collection> 
-	    <collection href="$media_url" title="Media"> 
-		<atom:title>WordPress Media</atom:title> 
-		<accept>$accepted_content_types</accept> 
-	    </collection> 
-	</workspace> 
+  <workspace> 
+    <atom:title>WordPress Workspace</atom:title>
+    <collection href="$entries_url"> 
+      <atom:title>WordPress Posts</atom:title> 
+      <accept>entry</accept> 
+      <categories href="$categories_url" /> 
+    </collection> 
+    <collection href="$media_url"> 
+      <atom:title>WordPress Media</atom:title> 
+      <accept>$accepted_content_types</accept> 
+    </collection> 
+  </workspace> 
 </service>
 
 EOD;
@@ -377,25 +190,27 @@
 		$this->output($introspection, $this->INTROSPECTION_CONTENT_TYPE); 
 	}
 
-function get_categories_xml() {
-	log_app('function','get_categories_xml()');
-	$home = get_bloginfo_rss('home');
+	function get_categories_xml() {
+	
+	    log_app('function','get_categories_xml()');
+	    $home = attribute_escape(get_bloginfo_rss('home'));
 
-	$categories = "";
-	$cats = get_categories("hierarchical=0&hide_empty=0");
-	foreach ((array) $cats as $cat) {
-		$categories .= "    <category term=\"" . attribute_escape($cat->cat_name) .  "\" />\n";
-	}
-        $output = <<<EOD
+	    $categories = "";
+	    $cats = get_categories("hierarchical=0&hide_empty=0");
+	    foreach ((array) $cats as $cat) {
+		    $categories .= "    <category term=\"" . attribute_escape($cat->cat_name) .  "\" />\n";
+	    }
+	    $output = <<<EOD
 <app:categories xmlns:app="http://purl.org/atom/app#"
 	xmlns="http://www.w3.org/2005/Atom"
 	fixed="yes" scheme="$home">
 	$categories
 </app:categories>
 EOD;
-	$this->output($output, $this->CATEGORIES_CONTENT_TYPE); 
-}
 
+	    $this->output($output, $this->CATEGORIES_CONTENT_TYPE); 
+	}
+
 	/*
 	 * Create Post (No arguments)
 	 */
@@ -408,7 +223,22 @@
 			$this->client_error();
 		}
 
-		$entry = $parser->entry;
+		$entry = array_pop($parser->feed->entries);
+		
+		log_app('Received entry:', print_r($entry,true));
+		
+		$catnames = array();
+		foreach($entry->categories as $cat)
+		array_push($catnames, $cat["term"]);
+		
+		$wp_cats = get_categories(array('hide_empty' => false));
+		
+		$post_categories = array();
+		
+		foreach($wp_cats as $cat) {
+		if(in_array($cat->cat_name, $catnames))
+			array_push($post_categories, $cat->cat_ID);
+		}
 
 		$publish = (isset($entry->draft) && trim($entry->draft) == 'yes') ? false : true;
 
@@ -420,13 +250,17 @@
 		$blog_ID = (int ) $blog_id;
 		$post_status = ($publish) ? 'publish' : 'draft';
 		$post_author = (int) $user->ID;
-		$post_title = $entry->title;
-		$post_content = $entry->content;
-		$post_excerpt = $entry->summary;
-		$post_date = current_time('mysql');
-		$post_date_gmt = current_time('mysql', 1);
+		$post_title = $entry->title[1];
+		$post_content = $entry->content[1];
+		$post_excerpt = $entry->summary[1];
+		$pubtimes = $this->get_publish_time($entry);
+		$post_date = $pubtimes[0]; 
+		$post_date_gmt = $pubtimes[1];
+		
+		if ( isset( $_SERVER['HTTP_SLUG'] ) )
+			$post_name = $_SERVER['HTTP_SLUG'];
 
-		$post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt');
+		$post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'post_name');
 
 		log_app('Inserting Post. Data:', print_r($post_data,true));
 
@@ -436,6 +270,12 @@
 			$this->internal_error('Sorry, your entry could not be posted. Something wrong happened.');
 		}
 
+		// getting warning here about unable to set headers
+		// because something in the cache is printing to the buffer
+		// could we clean up wp_set_post_categories or cache to not print
+		// this could affect our ability to send back the right headers
+		@wp_set_post_categories($postID, $post_categories);
+
 		$output = $this->get_entry($postID);
 
 		log_app('function',"create_post($postID)");
@@ -463,7 +303,7 @@
 			$this->bad_request();
 		}
 
-		$parsed = $parser->entry;
+		$parsed = array_pop($parser->feed->entries);
 
 		// check for not found
 		global $entry;
@@ -478,16 +318,21 @@
 
 		extract($entry);
 
-		$post_title = $parsed->title;
-		$post_content = $parsed->content;
-		$post_excerpt = $parsed->summary;
+		$post_title = $parsed->title[1];
+		$post_content = $parsed->content[1];
+		$post_excerpt = $parsed->summary[1];
+		$pubtimes = $this->get_publish_time($entry);
+		$post_date = $pubtimes[0]; 
+		$post_date_gmt = $pubtimes[1];      
 
 		// let's not go backwards and make something draft again.
 		if(!$publish && $post_status == 'draft') {
 			$post_status = ($publish) ? 'publish' : 'draft';
+		} elseif($publish) {
+			$post_status = 'publish';
 		}
 
-		$postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt');
+		$postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'post_date', 'post_date_gmt');
 
 		$result = wp_update_post($postdata);
 
@@ -605,7 +450,7 @@
 			$this->bad_request();
 		}
 
-		$parsed = $parser->entry;
+		$parsed = array_pop($parser->feed->entries);
 
 		// check for not found
 		global $entry;
@@ -725,14 +570,19 @@
 
 	function get_entries_url($page = NULL) {
 		global $use_querystring;
+		if($GLOBALS['post_type'] == 'attachment') {
+			$path = $this->MEDIA_PATH;
+		} else {
+			$path = $this->ENTRIES_PATH;
+		}
 		$url = get_bloginfo('url') . '/' . $this->script_name;
 		if ($use_querystring) {
-			$url .= '?action=/' . $this->ENTRIES_PATH;
+			$url .= '?action=/' . $path;
 			if(isset($page) && is_int($page)) {
 				$url .= "&amp;eid=$page";
 			}
 		} else {
-			$url .= '/' . $this->ENTRIES_PATH;
+			$url .= '/' . $path;
 			if(isset($page) && is_int($page)) {
 				$url .= "/$page";
 			}
@@ -759,7 +609,7 @@
 	function the_categories_url() {
 		$url = $this->get_categories_url();
 		echo $url;
-    }
+	}
 
 	function get_attachments_url($page = NULL) {
 		global $use_querystring;
@@ -783,6 +633,16 @@
 		echo $url;
 	}
 
+	function get_service_url() {
+		global $use_querystring;
+		$url = get_bloginfo('url') . '/' . $this->script_name;
+		if ($use_querystring) {
+			$url .= '?action=/' . $this->SERVICE_PATH;
+		} else {
+			$url .= '/' . $this->SERVICE_PATH;
+		}
+		return $url;
+	}
 
 	function get_entry_url($postID = NULL) {
 		global $use_querystring;
@@ -845,13 +705,6 @@
 		return;
 	}
 
-	function get_posts_count() {
-		global $wpdb;
-		log_app('function',"get_posts_count()");
-		return $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_date_gmt < '" . gmdate("Y-m-d H:i:s",time()) . "'");
-	}
-
-
 	function get_posts($page = 1, $post_type = 'post') {
 			log_app('function',"get_posts($page, '$post_type')");
 			$feed = $this->get_feed($page, $post_type);
@@ -859,9 +712,10 @@
 	}
 
 	function get_attachments($page = 1, $post_type = 'attachment') {
-			log_app('function',"get_attachments($page, '$post_type')");
-			$feed = $this->get_feed($page, $post_type);
-			$this->output($feed);
+	    log_app('function',"get_attachments($page, '$post_type')");
+	    $GLOBALS['post_type'] = $post_type;
+	    $feed = $this->get_feed($page, $post_type);
+	    $this->output($feed);
 	}
 
 	function get_feed($page = 1, $post_type = 'post') {
@@ -875,11 +729,9 @@
 		$page = (int) $page;
 
 		$count = get_option('posts_per_rss');
-		$query = "paged=$page&posts_per_page=$count&order=DESC";
-		if($post_type == 'attachment') {
-			$query .= "&post_type=$post_type";
-		}
-		query_posts($query);
+
+		wp('what_to_show=posts&posts_per_page=' . $count . '&offset=' . ($page-1));
+
 		$post = $GLOBALS['post'];
 		$posts = $GLOBALS['posts'];
 		$wp = $GLOBALS['wp'];
@@ -887,10 +739,10 @@
 		$wpdb = $GLOBALS['wpdb'];
 		$blog_id = (int) $GLOBALS['blog_id'];
 		$post_cache = $GLOBALS['post_cache'];
+		log_app('function',"query_posts(# " . print_r($wp_query, true) . "#)");
 
-
-		$total_count = $this->get_posts_count();
-		$last_page = (int) ceil($total_count / $count);
+		log_app('function',"total_count(# $wp_query->max_num_pages #)");
+		$last_page = $wp_query->max_num_pages;
 		$next_page = (($page + 1) > $last_page) ? NULL : $page + 1;
 		$prev_page = ($page - 1) < 1 ? NULL : $page - 1; 
 		$last_page = ((int)$last_page == 1 || (int)$last_page == 0) ? NULL : (int) $last_page;
@@ -914,32 +766,35 @@
 $post = $GLOBALS['post'];
 ?>
 <entry>
-		<id><?php the_guid($post->ID); ?></id>
-		<title type="html"><![CDATA[<?php the_title() ?>]]></title>
-		<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>
-		<app:control>
-			<app:draft><?php echo ($GLOBALS['post']->post_status == 'draft' ? 'yes' : 'no') ?></app:draft>
-		</app:control>
-		<author>
-			<name><?php the_author()?></name>
-			<email><?php the_author_email()?></email>
-	<?php if (get_the_author_url() && get_the_author_url() != 'http://') { ?>
-		 <uri><?php the_author_url()?></uri>
-	<?php } ?>
-		</author>
-	<?php if($GLOBALS['post']->post_status == 'attachment') { ?>
-		<link rel="edit" href="<?php $this->the_entry_url() ?>" />
-		<link rel="edit-media" href="<?php $this->the_media_url() ?>" />
-	<?php } else { ?>
-		<link href="<?php permalink_single_rss() ?>" />
-		<link rel="edit" href="<?php $this->the_entry_url() ?>" />
-	<?php } ?>
-	<?php foreach(get_the_category() as $category) { ?>
-	 <category scheme="<?php bloginfo_rss('home') ?>" term="<?php echo $category->cat_name?>" />
-	<?php } ?>   <summary type="html"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary>
-	<?php if ( strlen( $GLOBALS['post']->post_content ) ) : ?>
-	<content type="html"><![CDATA[<?php echo get_the_content('', 0, '') ?>]]></content>
+	<id><?php the_guid($post->ID); ?></id>
+	<title type="text"><![CDATA[<?php the_title() ?>]]></title>
+	<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>
+	    <app:edited><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></app:edited>
+	<app:control>
+	    <app:draft><?php echo ($GLOBALS['post']->post_status == 'draft' ? 'yes' : 'no') ?></app:draft>
+	</app:control>
+	<author>
+	    <name><?php the_author()?></name>
+	    <email><?php the_author_email()?></email>
+    <?php if (get_the_author_url() && get_the_author_url() != 'http://') { ?>
+	 <uri><?php the_author_url()?></uri>
+    <?php } ?>
+	</author>
+    <?php if($GLOBALS['post']->post_status == 'attachment') { ?>
+	<link rel="edit" href="<?php $this->the_entry_url() ?>" />
+	<link rel="edit-media" href="<?php $this->the_media_url() ?>" />
+    <?php } else { ?>
+	<link href="<?php permalink_single_rss() ?>" />
+	<?php   if (current_user_can('edit_post', $post->ID)) { ?>
+	<link rel="edit" href="<?php $this->the_entry_url() ?>" />
+	<?php   }?> 
+    <?php } ?>
+    <?php foreach(get_the_category() as $category) { ?>
+     <category scheme="<?php bloginfo_rss('home') ?>" term="<?php echo $category->cat_name?>" />
+    <?php } ?>   <summary type="html"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary>
+    <?php if ( strlen( $GLOBALS['post']->post_content ) ) : ?>
+    <content type="html"><![CDATA[<?php echo get_the_content('', 0, '') ?>]]></content>
 <?php endif; ?>
 	</entry>
 <?php
@@ -970,33 +825,34 @@
 		?>
 		<?php log_app('$post',print_r($GLOBALS['post'],true)); ?>
 <entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://purl.org/atom/app#" xml:lang="<?php echo get_option('rss_language'); ?>">
-	<id><?php the_guid($post->ID); ?></id>
-	<title type="html"><![CDATA[<?php the_title_rss() ?>]]></title>
+    <id><?php the_guid($post->ID); ?></id>
+    <title type="text"><![CDATA[<?php the_title_rss() ?>]]></title>
 
-	<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>
-	<app:control>
-		<app:draft><?php echo ($GLOBALS['post']->post_status == 'draft' ? 'yes' : 'no') ?></app:draft>
-	</app:control>
-	<author>
-		<name><?php the_author()?></name>
-		<email><?php the_author_email()?></email>
-		<uri><?php the_author_url()?></uri>
-	</author>
+    <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>
+    <app:edited><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></app:edited>
+    <app:control>
+	<app:draft><?php echo ($GLOBALS['post']->post_status == 'draft' ? 'yes' : 'no') ?></app:draft>
+    </app:control>
+    <author>
+	<name><?php the_author()?></name>
+	<email><?php the_author_email()?></email>
+	<uri><?php the_author_url()?></uri>
+    </author>
 <?php if($GLOBALS['post']->post_type == 'attachment') { ?>
-	<link rel="edit" href="<?php $this->the_entry_url() ?>" />
-	<link rel="edit-media" href="<?php $this->the_media_url() ?>" />
-	<content type="<?php echo $GLOBALS['post']->post_mime_type ?>" src="<?php the_guid(); ?>"/>
+    <link rel="edit" href="<?php $this->the_entry_url() ?>" />
+    <link rel="edit-media" href="<?php $this->the_media_url() ?>" />
+    <content type="<?php echo $GLOBALS['post']->post_mime_type ?>" src="<?php the_guid(); ?>"/>
 <?php } else { ?>
-	<link href="<?php permalink_single_rss() ?>" />
-	<link rel="edit" href="<?php $this->the_entry_url() ?>" />
+    <link href="<?php permalink_single_rss() ?>" />
+    <link rel="edit" href="<?php $this->the_entry_url() ?>" />
 <?php } ?>
 <?php foreach(get_the_category() as $category) { ?>
-	<category scheme="<?php bloginfo_rss('home') ?>" term="<?php echo $category->cat_name?>" />
-	<summary type="html"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary>
+    <category scheme="<?php bloginfo_rss('home') ?>" term="<?php echo $category->cat_name?>" />
+    <summary type="html"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary>
 <?php }
-	if ( strlen( $GLOBALS['post']->post_content ) ) : ?>
-	<content type="html"><![CDATA[<?php echo get_the_content('', 0, '') ?>]]></content>
+    if ( strlen( $GLOBALS['post']->post_content ) ) : ?>
+    <content type="html"><![CDATA[<?php echo get_the_content('', 0, '') ?>]]></content>
 <?php endif; ?>
 </entry>
 <?php
@@ -1071,8 +927,34 @@
 		exit;
 	}
 
+	function redirect($url) {
+
+		log_app('Status','302: Redirect');
+		$escaped_url = attribute_escape($url);
+		$content = <<<EOD
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<html>
+  <head>
+    <title>302 Found</title>
+  </head>
+<body>
+  <h1>Found</h1>
+  <p>The document has moved <a href="$escaped_url">here</a>.</p>
+  </body>
+</html>
+
+EOD;
+		header('HTTP/1.1 302 Moved');
+		header('Content-Type: text/html');
+		header('Location: ' . $url);
+		echo $content;
+		exit;
+
+	}
+
+
 	function client_error($msg = 'Client Error') {
-		log_app('Status','400: Client Errir');
+		log_app('Status','400: Client Error');
 		header('Content-Type: text/plain');
 		status_header('400');
 		exit;
@@ -1107,11 +989,23 @@
 		log_app('Status','401: Auth Required');
 		nocache_headers();
 		header('WWW-Authenticate: Basic realm="WordPress Atom Protocol"');
-		header('WWW-Authenticate: Form action="' . get_option('siteurl') . '/wp-login.php"', false); 
 		header("HTTP/1.1 401 $msg");
 		header('Status: ' . $msg);
-		header('Content-Type: plain/text');
-		echo $msg;
+		header('Content-Type: text/html');
+		$content = <<<EOD
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<html>
+  <head>
+    <title>401 Unauthorized</title>
+  </head>
+<body>
+    <h1>401 Unauthorized</h1>
+    <p>$msg</p>
+  </body>
+</html>
+
+EOD;
+		echo $content;
 		exit;
 	}
 
@@ -1251,7 +1145,30 @@
 		}
 	}
 
+	
+	function rfc3339_str2time($str) {
+	    
+	    $match = false;
+	    if(!preg_match("/(\d{4}-\d{2}-\d{2})T(\d{2}\:\d{2}\:\d{2})\.?\d{0,3}(Z|[+-]+\d{2}\:\d{2})/", $str, $match))
+			return false;
+	
+	    if($match[3] == 'Z')
+			$match[3] == '+0000';
+	
+	    return strtotime($match[1] . " " . $match[2] . " " . $match[3]);
+	}        
 
+	function get_publish_time($entry) {
+
+	    $pubtime = $this->rfc3339_str2time($entry->published);
+	    
+	    if(!$pubtime) {
+			return array(current_time('mysql'),current_time('mysql',1));
+	    } else {
+			return array(date("Y-m-d H:i:s", $pubtime), gmdate("Y-m-d H:i:s", $pubtime));
+	    }
+	}
+
 }
 
 $server = new AtomServer();

