diff -Naur wordpress-2.3.1/wp-admin/admin.php wordpress-2.3.3/wp-admin/admin.php
--- wordpress-2.3.1/wp-admin/admin.php	2007-09-13 20:36:31.000000000 +0000
+++ wordpress-2.3.3/wp-admin/admin.php	2007-12-21 01:28:48.000000000 +0000
@@ -1,4 +1,6 @@
 <?php
+define('WP_ADMIN', TRUE);
+
 if ( defined('ABSPATH') )
 	require_once( ABSPATH . 'wp-config.php');
 else
diff -Naur wordpress-2.3.1/wp-admin/includes/file.php wordpress-2.3.3/wp-admin/includes/file.php
--- wordpress-2.3.1/wp-admin/includes/file.php	2007-09-14 21:13:23.000000000 +0000
+++ wordpress-2.3.3/wp-admin/includes/file.php	2007-12-29 03:14:53.000000000 +0000
@@ -43,6 +43,9 @@
 }
 
 function validate_file( $file, $allowed_files = '' ) {
+	if ( false !== strpos( $file, '..' ))
+		return 1;
+
 	if ( false !== strpos( $file, './' ))
 		return 1;
 
diff -Naur wordpress-2.3.1/wp-admin/install-helper.php wordpress-2.3.3/wp-admin/install-helper.php
--- wordpress-2.3.1/wp-admin/install-helper.php	2006-11-19 07:56:05.000000000 +0000
+++ wordpress-2.3.3/wp-admin/install-helper.php	2008-02-02 17:45:44.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-require_once('../wp-config.php');
+require_once(dirname(dirname(__FILE__)).'/wp-config.php');
 $debug = 0;
 
 /**
@@ -149,4 +149,4 @@
 }
 echo "</pre>";
 */
-?>
\ No newline at end of file
+?>
diff -Naur wordpress-2.3.1/wp-admin/install.php wordpress-2.3.3/wp-admin/install.php
--- wordpress-2.3.1/wp-admin/install.php	2007-09-19 21:45:23.000000000 +0000
+++ wordpress-2.3.3/wp-admin/install.php	2007-12-22 17:45:59.000000000 +0000
@@ -13,6 +13,7 @@
 	$step = $_GET['step'];
 else
 	$step = 0;
+function display_header(){
 header( 'Content-Type: text/html; charset=utf-8' );
 ?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@@ -24,13 +25,17 @@
 </head>
 <body>
 <h1 id="logo"><img alt="WordPress" src="images/wordpress-logo.png" /></h1>
+
 <?php
+}//end function display_header();
+
 // Let's check to make sure WP isn't already installed.
-if ( is_blog_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>');
+if ( is_blog_installed() ) {display_header(); 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>');}
 
 switch($step) {
 	case 0:
 	case 1: // in case people are directly linking to this
+	  display_header();
 ?>
 <h1><?php _e('Welcome'); ?></h1>
 <p><?php printf(__('Welcome to the famous five minute WordPress installation process! You may want to browse the <a href="%s">ReadMe documentation</a> at your leisure.  Otherwise, just fill in the information below and you\'ll be on your way to using the most extendable and powerful personal publishing platform in the world.'), '../readme.html'); ?></p>
@@ -61,6 +66,10 @@
 <?php
 		break;
 	case 2:
+		if ( !empty($wpdb->error) )
+			wp_die($wpdb->error->get_error_message());
+
+		display_header();	
 		// Fill in the data we gathered
 		$weblog_title = stripslashes($_POST['weblog_title']);
 		$admin_email = stripslashes($_POST['admin_email']);
@@ -74,8 +83,9 @@
 			die(__('<strong>ERROR</strong>: that isn\'t a valid e-mail address.  E-mail addresses look like: <code>username@example.com</code>'));
 		}
 
-	$result = wp_install($weblog_title, 'admin', $admin_email, $public);
-	extract($result, EXTR_SKIP);
+		$wpdb->show_errors();
+		$result = wp_install($weblog_title, 'admin', $admin_email, $public);
+		extract($result, EXTR_SKIP);
 ?>
 
 <h1><?php _e('Success!'); ?></h1>
diff -Naur wordpress-2.3.1/wp-admin/setup-config.php wordpress-2.3.3/wp-admin/setup-config.php
--- wordpress-2.3.1/wp-admin/setup-config.php	2007-09-19 04:27:56.000000000 +0000
+++ wordpress-2.3.3/wp-admin/setup-config.php	2007-12-21 01:35:26.000000000 +0000
@@ -3,6 +3,7 @@
 
 require_once('../wp-includes/compat.php');
 require_once('../wp-includes/functions.php');
+require_once('../wp-includes/classes.php');
 
 if (!file_exists('../wp-config-sample.php'))
 	wp_die('Sorry, I need a wp-config-sample.php file to work from. Please re-upload this file from your WordPress installation.');
@@ -161,6 +162,9 @@
 
 	// We'll fail here if the values are no good.
 	require_once('../wp-includes/wp-db.php');
+	if ( !empty($wpdb->error) )
+		wp_die($wpdb->error->get_error_message());
+
 	$handle = fopen('../wp-config.php', 'w');
 
 	foreach ($configFile as $line_num => $line) {
diff -Naur wordpress-2.3.1/wp-app.php wordpress-2.3.3/wp-app.php
--- wordpress-2.3.1/wp-app.php	2007-09-18 16:32:22.000000000 +0000
+++ wordpress-2.3.3/wp-app.php	2007-12-28 00:47:45.000000000 +0000
@@ -159,6 +159,10 @@
 
 	function get_service() {
 		log_app('function','get_service()');
+
+		if( !current_user_can( 'edit_posts' ) ) 
+			$this->auth_required( __( 'Sorry, you do not have the right to access this blog.' ) );
+
 		$entries_url = attribute_escape($this->get_entries_url());
 		$categories_url = attribute_escape($this->get_categories_url());
 		$media_url = attribute_escape($this->get_attachments_url());
@@ -188,8 +192,11 @@
 	}
 
 	function get_categories_xml() {
-
 		log_app('function','get_categories_xml()');
+
+		if( !current_user_can( 'edit_posts' ) ) 
+			$this->auth_required( __( 'Sorry, you do not have the right to access this blog.' ) );
+
 		$home = attribute_escape(get_bloginfo_rss('home'));
 
 		$categories = "";
@@ -282,8 +289,11 @@
 	}
 
 	function get_post($postID) {
-
 		global $entry;
+
+		if( !current_user_can( 'edit_post', $postID ) )
+			$this->auth_required( __( 'Sorry, you do not have the right to access this post.' ) ); 
+
 		$this->set_current_entry($postID);
 		$output = $this->get_entry($postID);
 		log_app('function',"get_post($postID)");
@@ -372,8 +382,9 @@
 	}
 
 	function get_attachment($postID = NULL) {
+		if( !current_user_can( 'upload_files' ) )
+			$this->auth_required( __( 'Sorry, you do not have the right to file uploads on this blog.' ) );
 
-		global $entry;
 		if (!isset($postID)) {
 			$this->get_attachments();
 		} else {
@@ -494,6 +505,10 @@
 		}
 
 		$location = get_post_meta($entry['ID'], '_wp_attached_file', true);
+		$filetype = wp_check_filetype($location);
+
+		if(!isset($location) || 'attachment' != $entry['post_type'] || empty($filetype['ext']))
+			$this->internal_error(__('Error ocurred while accessing post metadata for file location.'));
 
 		// delete file
 		@unlink($location);
@@ -795,7 +810,6 @@
 	</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 } ?>
diff -Naur wordpress-2.3.1/wp-content/plugins/akismet/akismet.php wordpress-2.3.3/wp-content/plugins/akismet/akismet.php
--- wordpress-2.3.1/wp-content/plugins/akismet/akismet.php	2007-06-18 18:27:32.000000000 +0000
+++ wordpress-2.3.3/wp-content/plugins/akismet/akismet.php	2008-01-17 06:10:28.000000000 +0000
@@ -2,8 +2,8 @@
 /*
 Plugin Name: Akismet
 Plugin URI: http://akismet.com/
-Description: Akismet checks your comments against the Akismet web service to see if they look like spam or not. You need a <a href="http://wordpress.com/api-keys/">WordPress.com API key</a> to use it. You can review the spam it catches under "Comments." To show off your Akismet stats just put <code>&lt;?php akismet_counter(); ?></code> in your template.
-Version: 2.0.2
+Description: Akismet checks your comments against the Akismet web service to see if they look like spam or not. You need a <a href="http://wordpress.com/api-keys/">WordPress.com API key</a> to use it. You can review the spam it catches under "Comments." To show off your Akismet stats just put <code>&lt;?php akismet_counter(); ?></code> in your template. See also: <a href="http://wordpress.org/extend/plugins/stats/">WP Stats plugin</a>.
+Version: 2.1.3
 Author: Matt Mullenweg
 Author URI: http://photomatt.net/
 */
@@ -35,6 +35,7 @@
 function akismet_config_page() {
 	if ( function_exists('add_submenu_page') )
 		add_submenu_page('plugins.php', __('Akismet Configuration'), __('Akismet Configuration'), 'manage_options', 'akismet-key-config', 'akismet_conf');
+	
 }
 
 function akismet_conf() {
@@ -146,14 +147,10 @@
 if ( !get_option('wordpress_api_key') && !$wpcom_api_key && !isset($_POST['submit']) ) {
 	function akismet_warning() {
 		echo "
-		<div id='akismet-warning' class='updated fade-ff0000'><p><strong>".__('Akismet is not active.')."</strong> ".sprintf(__('You must <a href="%1$s">enter your WordPress.com API key</a> for it to work.'), "plugins.php?page=akismet-key-config")."</p></div>
-		<style type='text/css'>
-		#adminmenu { margin-bottom: 5em; }
-		#akismet-warning { position: absolute; top: 7em; }
-		</style>
+		<div id='akismet-warning' class='updated fade-ff0000'><p><strong>".__('Akismet is almost ready.')."</strong> ".sprintf(__('You must <a href="%1$s">enter your WordPress.com API key</a> for it to work.'), "plugins.php?page=akismet-key-config")."</p></div>
 		";
 	}
-	add_action('admin_footer', 'akismet_warning');
+	add_action('admin_notices', 'akismet_warning');
 	return;
 }
 
@@ -204,6 +201,8 @@
 		add_filter('pre_comment_approved', create_function('$a', 'return \'spam\';'));
 		update_option( 'akismet_spam_count', get_option('akismet_spam_count') + 1 );
 
+		do_action( 'akismet_spam_caught' );
+
 		$post = get_post( $comment['comment_post_ID'] );
 		$last_updated = strtotime( $post->post_modified_gmt );
 		$diff = time() - $last_updated;
@@ -325,17 +324,60 @@
 else
 	$link = 'edit.php';
 ?>
+<style type="text/css">
+.akismet-tabs {
+	list-style: none;
+	margin: 0;
+	padding: 0;
+	clear: both;
+	border-bottom: 1px solid #ccc;
+	height: 31px;
+	margin-bottom: 20px;
+	background: #ddd;
+	border-top: 1px solid #bdbdbd;
+}
+.akismet-tabs li {
+	float: left;
+	margin: 5px 0 0 20px;
+}
+.akismet-tabs a {
+	display: block;
+	padding: 4px .5em 3px;
+	border-bottom: none;
+	color: #036;
+}
+.akismet-tabs .active a {
+	background: #fff;
+	border: 1px solid #ccc;
+	border-bottom: none;
+	color: #000;
+	font-weight: bold;
+	padding-bottom: 4px;
+}
+#akismetsearch {
+	float: right;
+	margin-top: -.5em;
+}
+
+#akismetsearch p {
+	margin: 0;
+	padding: 0;
+}
+</style>
 <div class="wrap">
 <h2><?php _e('Caught Spam') ?></h2>
 <?php
-$count = get_option('akismet_spam_count');
+$count = get_option( 'akismet_spam_count' );
 if ( $count ) {
 ?>
 <p><?php printf(__('Akismet has caught <strong>%1$s spam</strong> for you since you first installed it.'), number_format($count) ); ?></p>
 <?php
 }
-$spam_count = akismet_spam_count();
-if (0 == $spam_count) {
+
+$gotspam = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = 'spam'" );
+
+
+if ( 0 == $gotspam ) {
 	echo '<p>'.__('You have no spam currently in the queue. Must be your lucky day. :)').'</p>';
 	echo '</div>';
 } else {
@@ -345,7 +387,7 @@
 <form method="post" action="<?php echo attribute_escape( add_query_arg( 'noheader', 'true' ) ); ?>">
 <?php akismet_nonce_field($akismet_nonce) ?>
 <input type="hidden" name="action" value="delete" />
-<?php printf(__('There are currently %1$s comments identified as spam.'), $spam_count); ?>&nbsp; &nbsp; <input type="submit" name="Submit" value="<?php _e('Delete all'); ?>" />
+<?php printf(__('There are currently %1$s comments identified as spam.'), $spam_count); ?>&nbsp; &nbsp; <input type="submit" class="button" name="Submit" value="<?php _e('Delete all'); ?>" />
 <input type="hidden" name="display_time" value="<?php echo current_time('mysql', 1); ?>" />
 </form>
 <?php } ?>
@@ -354,7 +396,6 @@
 <?php if ( isset( $_POST['s'] ) ) { ?>
 <h2><?php _e('Search'); ?></h2>
 <?php } else { ?>
-<h2><?php _e('Latest Spam'); ?></h2>
 <?php echo '<p>'.__('These are the latest comments identified as spam by Akismet. If you see any mistakes, simply mark the comment as "not spam" and Akismet will learn from the submission. If you wish to recover a comment from spam, simply select the comment, and click Not Spam. After 15 days we clean out the junk for you.').'</p>'; ?>
 <?php } ?>
 <?php
@@ -380,19 +421,47 @@
 	$start = ( $page - 1 ) * 50;
 	$end = $start + 50;
 
-	$comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' ORDER BY comment_date DESC LIMIT $start, $end");
-	$total = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = 'spam'" );
+	$where = '';
+	if ( isset( $_GET['ctype'] ) ) {
+		$type = preg_replace( '|[^a-z]|', '', $_GET['ctype'] );
+		if ( 'comments' == $type )
+			$type = '';
+		$where = " AND comment_type = '$type' "; 
+	}
+
+	$comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' $where ORDER BY comment_date DESC LIMIT $start, $end");
+	$total = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = 'spam' $where" );
+
+	$totals = $wpdb->get_results( "SELECT comment_type, COUNT(*) AS cc FROM $wpdb->comments WHERE comment_approved = 'spam' GROUP BY comment_type" );
+?>
+<ul class="akismet-tabs">
+<li <?php if ( !isset( $_GET['ctype'] ) ) echo ' class="active"'; ?>><a href="edit-comments.php?page=akismet-admin"><?php _e('All'); ?></a></li>
+<?php
+foreach ( $totals as $type ) {
+	if ( '' == $type->comment_type ) $type->comment_type = 'comments';
+	$show = ucwords( $type->comment_type );
+	$type->cc = number_format( $type->cc );
+	$extra = ( $_GET['ctype'] == $type->comment_type ) ? ' class="active"' : '';
+	echo "<li $extra><a href='edit-comments.php?page=akismet-admin&amp;ctype=$type->comment_type'>$show ($type->cc)</a></li>";
+}
+do_action( 'akismet_tabs' ); // so plugins can add more tabs easily
+?>	
+</ul>
+<?php
 }
 
 if ($comments) {
 ?>
-
+<form method="post" action="<?php echo attribute_escape("$link?page=akismet-admin"); ?>" id="akismetsearch">
+<p>  <input type="text" name="s" value="<?php if (isset($_POST['s'])) echo attribute_escape($_POST['s']); ?>" size="17" /> 
+  <input type="submit" class="button" name="submit" value="<?php echo attribute_escape(__('Search Spam &raquo;')) ?>"  />  </p>
+</form>
 <?php if ( $total > 50 ) {
 $total_pages = ceil( $total / 50 );
 $r = '';
 if ( 1 < $page ) {
 	$args['apage'] = ( 1 == $page - 1 ) ? '' : $page - 1;
-	$r .=  '<a class="prev" href="' . clean_url(add_query_arg( $args )) . '">&laquo; '. __('Previous Page') .'</a>' . "\n";
+	$r .=  '<a class="prev" href="' . clean_url(add_query_arg( $args )) . '">'. __('&laquo; Previous Page') .'</a>' . "\n";
 }
 if ( ( $total_pages = ceil( $total / 50 ) ) > 1 ) {
 	for ( $page_num = 1; $page_num <= $total_pages; $page_num++ ) :
@@ -413,17 +482,13 @@
 }
 if ( ( $page ) * 50 < $total || -1 == $total ) {
 	$args['apage'] = $page + 1;
-	$r .=  '<a class="next" href="' . clean_url(add_query_arg($args)) . '">'. __('Next Page') .' &raquo;</a>' . "\n";
+	$r .=  '<a class="next" href="' . clean_url(add_query_arg($args)) . '">'. __('Next Page &raquo;') .'</a>' . "\n";
 }
 echo "<p>$r</p>";
 ?>
 
 <?php } ?>
-<form method="post" action="<?php echo attribute_escape("$link?page=akismet-admin"); ?>" id="akismetsearch">
-<p>  <input type="text" name="s" value="<?php if (isset($_POST['s'])) echo attribute_escape($_POST['s']); ?>" size="17" /> 
-  <input type="submit" name="submit" value="<?php echo attribute_escape(__('Search')) ?>"  />  </p>
-</form>
-<form method="post" action="<?php echo attribute_escape( add_query_arg( 'noheader', 'true' ) ); ?>">
+<form style="clear: both;" method="post" action="<?php echo attribute_escape( add_query_arg( 'noheader', 'true' ) ); ?>">
 <?php akismet_nonce_field($akismet_nonce) ?>
 <input type="hidden" name="action" value="recover" />
 <ul id="spam-list" class="commentlist" style="list-style: none; margin: 0; padding: 0;">
@@ -463,7 +528,7 @@
 $r = '';
 if ( 1 < $page ) {
 	$args['apage'] = ( 1 == $page - 1 ) ? '' : $page - 1;
-	$r .=  '<a class="prev" href="' . clean_url(add_query_arg( $args )) . '">&laquo; '. __('Previous Page') .'</a>' . "\n";
+	$r .=  '<a class="prev" href="' . clean_url(add_query_arg( $args )) . '">'. __('&laquo; Previous Page') .'</a>' . "\n";
 }
 if ( ( $total_pages = ceil( $total / 50 ) ) > 1 ) {
 	for ( $page_num = 1; $page_num <= $total_pages; $page_num++ ) :
@@ -484,7 +549,7 @@
 }
 if ( ( $page ) * 50 < $total || -1 == $total ) {
 	$args['apage'] = $page + 1;
-	$r .=  '<a class="next" href="' . clean_url(add_query_arg($args)) . '">'. __('Next Page') .' &raquo;</a>' . "\n";
+	$r .=  '<a class="next" href="' . clean_url(add_query_arg($args)) . '">'. __('Next Page &raquo;') .'</a>' . "\n";
 }
 echo "<p>$r</p>";
 }
@@ -504,7 +569,7 @@
 <form method="post" action="<?php echo attribute_escape( add_query_arg( 'noheader', 'true' ) ); ?>">
 <?php akismet_nonce_field($akismet_nonce) ?>
 <p><input type="hidden" name="action" value="delete" />
-<?php printf(__('There are currently %1$s comments identified as spam.'), $spam_count); ?>&nbsp; &nbsp; <input type="submit" name="Submit" value="<?php echo attribute_escape(__('Delete all')); ?>" />
+<?php printf(__('There are currently %1$s comments identified as spam.'), $spam_count); ?>&nbsp; &nbsp; <input type="submit" name="Submit" class="button" value="<?php echo attribute_escape(__('Delete all')); ?>" />
 <input type="hidden" name="display_time" value="<?php echo current_time('mysql', 1); ?>" /></p>
 </form>
 <?php } ?>
diff -Naur wordpress-2.3.1/wp-includes/formatting.php wordpress-2.3.3/wp-includes/formatting.php
--- wordpress-2.3.1/wp-includes/formatting.php	2007-10-03 16:17:54.000000000 +0000
+++ wordpress-2.3.3/wp-includes/formatting.php	2007-12-21 06:12:56.000000000 +0000
@@ -622,18 +622,35 @@
 	return $emailNOSPAMaddy;
 }
 
+function _make_url_clickable_cb($matches) {
+	$url = $matches[2];
+	$url = clean_url($url);
+	if ( empty($url) )
+		return $matches[0];
+	return $matches[1] . "<a href=\"$url\" rel=\"nofollow\">$url</a>";
+}
+
+function _make_web_ftp_clickable_cb($matches) {
+	$dest = $matches[2];
+	$dest = 'http://' . $dest;
+	$dest = clean_url($dest);
+	if ( empty($dest) )
+		return $matches[0];
+
+	return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>";
+}
+
+function _make_email_clickable_cb($matches) {
+	$email = $matches[2] . '@' . $matches[3];
+	return $matches[1] . "<a href=\"mailto:$email\">$email</a>";
+}
+
 function make_clickable($ret) {
 	$ret = ' ' . $ret;
 	// in testing, using arrays here was found to be faster
-	$ret = preg_replace(
-		array(
-			'#([\s>])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is',
-			'#([\s>])((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*)#is',
-			'#([\s>])([a-z0-9\-_.]+)@([^,< \n\r]+)#i'),
-		array(
-			'$1<a href="$2" rel="nofollow">$2</a>',
-			'$1<a href="http://$2" rel="nofollow">$2</a>',
-			'$1<a href="mailto:$2@$3">$2@$3</a>'),$ret);
+	$ret = preg_replace_callback('#([\s>])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_url_clickable_cb', $ret);
+	$ret = preg_replace_callback('#([\s>])((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_web_ftp_clickable_cb', $ret);
+	$ret = preg_replace_callback('#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret);
 	// this one is not in an array because we need it to run last, for cleanup of accidental links within links
 	$ret = preg_replace("#(<a( [^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i", "$1$3</a>", $ret);
 	$ret = trim($ret);
diff -Naur wordpress-2.3.1/wp-includes/functions.php wordpress-2.3.3/wp-includes/functions.php
--- wordpress-2.3.1/wp-includes/functions.php	2007-10-12 21:46:32.000000000 +0000
+++ wordpress-2.3.3/wp-includes/functions.php	2007-12-21 02:57:21.000000000 +0000
@@ -198,10 +198,10 @@
 
 		if ( false === $value ) {
 			if ( defined('WP_INSTALLING') )
-				$wpdb->hide_errors();
+				$show = $wpdb->hide_errors();
 			$row = $wpdb->get_row("SELECT option_value FROM $wpdb->options WHERE option_name = '$setting' LIMIT 1");
 			if ( defined('WP_INSTALLING') )
-				$wpdb->show_errors();
+				$wpdb->show_errors($show);
 
 			if( is_object( $row) ) { // Has to be get_row instead of get_var because of funkiness with 0, false, null values
 				$value = $row->option_value;
@@ -236,11 +236,11 @@
 
 function get_alloptions() {
 	global $wpdb, $wp_queries;
-	$wpdb->hide_errors();
+	$show = $wpdb->hide_errors();
 	if ( !$options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'") ) {
 		$options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options");
 	}
-	$wpdb->show_errors();
+	$wpdb->show_errors($show);
 
 	foreach ($options as $option) {
 		// "When trying to design a foolproof system,
@@ -263,10 +263,10 @@
 	$alloptions = wp_cache_get('alloptions', 'options');
 
 	if ( !$alloptions ) {
-		$wpdb->hide_errors();
+		$show = $wpdb->hide_errors();
 		if ( !$alloptions_db = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'") )
 			$alloptions_db = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options");
-		$wpdb->show_errors();
+		$wpdb->show_errors($show);
 		$alloptions = array();
 		foreach ( (array) $alloptions_db as $o )
 			$alloptions[$o->option_name] = $o->option_value;
@@ -892,9 +892,9 @@
 
 function is_blog_installed() {
 	global $wpdb;
-	$wpdb->hide_errors();
+	$show = $wpdb->hide_errors();
 	$installed = $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'");
-	$wpdb->show_errors();
+	$wpdb->show_errors($show);
 
 	$install_status = !empty( $installed ) ? TRUE : FALSE;
 	return $install_status;
@@ -1419,4 +1419,36 @@
 	while ( @ob_end_flush() );
 }
 
+function dead_db() {
+	global $wpdb;
+
+	// Load custom DB error template, if present.
+	if ( file_exists( ABSPATH . 'wp-content/db-error.php' ) ) {
+		require_once( ABSPATH . 'wp-content/db-error.php' );
+		die();
+	}
+
+	// If installing or in the admin, provide the verbose message.
+	if ( defined('WP_INSTALLING') || defined('WP_ADMIN') )
+		wp_die($wpdb->error);
+
+	// Otherwise, be terse.
+	status_header( 500 );
+	nocache_headers();
+	header( 'Content-Type: text/html; charset=utf-8' );
+?>
+<!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" <?php if ( function_exists( 'language_attributes' ) ) language_attributes(); ?>>
+<head>
+	<title>Database Error</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+</head>
+<body>
+	<h1>Error establishing a database connection</h1>
+</body>
+</html>
+<?php
+	die();
+}
+
 ?>
diff -Naur wordpress-2.3.1/wp-includes/gettext.php wordpress-2.3.3/wp-includes/gettext.php
--- wordpress-2.3.1/wp-includes/gettext.php	2007-04-13 23:29:47.000000000 +0000
+++ wordpress-2.3.3/wp-includes/gettext.php	2008-02-02 17:49:37.000000000 +0000
@@ -114,7 +114,7 @@
 
 		$this->STREAM = $Reader;
 		$magic = $this->readint();
-		if ($magic == ($MAGIC1 & 0xFFFFFFFF) || $magic == ($MAGIC3 & 0xFFFFFFFF)) { // to make sure it works for 64-bit platforms
+		if ($magic == $MAGIC1 || $magic == $MAGIC3) { // to make sure it works for 64-bit platforms
 			$this->BYTEORDER = 0;
 		} elseif ($magic == ($MAGIC2 & 0xFFFFFFFF)) {
 			$this->BYTEORDER = 1;
diff -Naur wordpress-2.3.1/wp-includes/pluggable.php wordpress-2.3.3/wp-includes/pluggable.php
--- wordpress-2.3.1/wp-includes/pluggable.php	2007-10-17 20:19:01.000000000 +0000
+++ wordpress-2.3.3/wp-includes/pluggable.php	2008-02-02 17:44:27.000000000 +0000
@@ -72,9 +72,9 @@
 	if ( !$user = $wpdb->get_row("SELECT * FROM $wpdb->users WHERE ID = '$user_id' LIMIT 1") )
 		return false;
 
-	$wpdb->hide_errors();
+	$show = $wpdb->hide_errors();
 	$metavalues = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = '$user_id'");
-	$wpdb->show_errors();
+	$wpdb->show_errors($show);
 
 	if ($metavalues) {
 		foreach ( $metavalues as $meta ) {
@@ -225,7 +225,6 @@
 
 	// Set the from name and email
 	$phpmailer->From = apply_filters( 'wp_mail_from', $from_email );
-	$phpmailer->Sender = apply_filters( 'wp_mail_from', $from_email );
 	$phpmailer->FromName = apply_filters( 'wp_mail_from_name', $from_name );
 
 	// Set destination address
diff -Naur wordpress-2.3.1/wp-includes/post.php wordpress-2.3.3/wp-includes/post.php
--- wordpress-2.3.1/wp-includes/post.php	2007-10-08 22:26:19.000000000 +0000
+++ wordpress-2.3.3/wp-includes/post.php	2007-12-24 21:24:26.000000000 +0000
@@ -428,6 +428,10 @@
 }
 
 function sanitize_post($post, $context = 'display') {
+
+	if ( 'raw' == $context )
+		return $post;
+
 	// 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');
 
@@ -1139,6 +1143,7 @@
 		$exclude = '';
 		$meta_key = '';
 		$meta_value = '';
+		$hierarchical = false;
 		$incpages = preg_split('/[\s,]+/',$include);
 		if ( count($incpages) ) {
 			foreach ( $incpages as $incpage ) {
diff -Naur wordpress-2.3.1/wp-includes/query.php wordpress-2.3.3/wp-includes/query.php
--- wordpress-2.3.1/wp-includes/query.php	2007-10-15 20:14:56.000000000 +0000
+++ wordpress-2.3.3/wp-includes/query.php	2007-12-28 01:04:30.000000000 +0000
@@ -32,9 +32,9 @@
  */
 
 function is_admin () {
-	global $wp_query;
-
-	return ($wp_query->is_admin || (stripos($_SERVER['REQUEST_URI'], 'wp-admin/') !== false));
+	if ( defined('WP_ADMIN') ) 
+		return WP_ADMIN;
+	return false;
 }
 
 function is_archive () {
@@ -642,7 +642,7 @@
 		if ('' != $qv['preview'])
 			$this->is_preview = true;
 
-		if ( strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false )
+		if ( is_admin() )
 			$this->is_admin = true;
 
 		if ( false !== strpos($qv['feed'], 'comments-') ) {
diff -Naur wordpress-2.3.1/wp-includes/taxonomy.php wordpress-2.3.3/wp-includes/taxonomy.php
--- wordpress-2.3.1/wp-includes/taxonomy.php	2007-10-15 20:14:56.000000000 +0000
+++ wordpress-2.3.3/wp-includes/taxonomy.php	2007-11-07 06:28:46.000000000 +0000
@@ -663,6 +663,10 @@
  * @return array|object Term with all fields sanitized
  */
 function sanitize_term($term, $taxonomy, $context = 'display') {
+
+	if ( 'raw' == $context )
+		return $term;
+
 	$fields = array('term_id', 'name', 'description', 'slug', 'count', 'parent', 'term_group');
 
 	$do_object = false;
diff -Naur wordpress-2.3.1/wp-includes/version.php wordpress-2.3.3/wp-includes/version.php
--- wordpress-2.3.1/wp-includes/version.php	2007-10-26 16:08:17.000000000 +0000
+++ wordpress-2.3.3/wp-includes/version.php	2008-02-05 04:05:20.000000000 +0000
@@ -2,7 +2,7 @@
 
 // This holds the version number in a separate file so we can bump it without cluttering the SVN
 
-$wp_version = '2.3.1';
+$wp_version = '2.3.3';
 $wp_db_version = 6124;
 
 ?>
diff -Naur wordpress-2.3.1/wp-includes/wp-db.php wordpress-2.3.3/wp-includes/wp-db.php
--- wordpress-2.3.1/wp-includes/wp-db.php	2007-09-13 06:23:23.000000000 +0000
+++ wordpress-2.3.3/wp-includes/wp-db.php	2007-12-22 17:45:59.000000000 +0000
@@ -15,11 +15,12 @@
 
 class wpdb {
 
-	var $show_errors = true;
+	var $show_errors = false;
 	var $num_queries = 0;
 	var $last_query;
 	var $col_info;
 	var $queries;
+	var $ready = false;
 
 	// Our tables
 	var $posts;
@@ -56,6 +57,9 @@
 	function __construct($dbuser, $dbpassword, $dbname, $dbhost) {
 		register_shutdown_function(array(&$this, "__destruct"));
 
+		if ( defined('WP_DEBUG') and WP_DEBUG == true )
+			$this->show_errors();
+
 		if ( defined('DB_CHARSET') )
 			$this->charset = DB_CHARSET;
 
@@ -74,8 +78,11 @@
 </ul>
 <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>
 ");
+			return;
 		}
 
+		$this->ready = true;
+
 		if ( !empty($this->charset) && version_compare(mysql_get_server_info(), '4.1.0', '>=') )
  			$this->query("SET NAMES '$this->charset'");
 
@@ -92,14 +99,17 @@
 	 */
 	function select($db) {
 		if (!@mysql_select_db($db, $this->dbh)) {
+			$this->ready = false;
 			$this->bail("
 <h1>Can&#8217;t select database</h1>
 <p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>$db</code> database.</p>
 <ul>
 <li>Are you sure it exists?</li>
+<li>Does the user <code>".DB_USER."</code> have permission to use the <code>$db</code> database?</li>
 <li>On some systems the name of your database is prefixed with your username, so it would be like username_wordpress. Could that be the problem?</li>
 </ul>
 <p>If you don't know how to setup a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>");
+			return;
 		}
 	}
 
@@ -149,29 +159,36 @@
 		$EZSQL_ERROR[] =
 		array ('query' => $this->last_query, 'error_str' => $str);
 
-		$str = htmlspecialchars($str, ENT_QUOTES);
-		$query = htmlspecialchars($this->last_query, ENT_QUOTES);
+		$error_str = "WordPress database error $str for query $this->last_query";
+		error_log($error_str, 0);
+
 		// Is error output turned on or not..
-		if ( $this->show_errors ) {
-			// If there is an error then take note of it
-			print "<div id='error'>
-			<p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
-			<code>$query</code></p>
-			</div>";
-		} else {
+		if ( !$this->show_errors )
 			return false;
-		}
+
+		$str = htmlspecialchars($str, ENT_QUOTES);
+		$query = htmlspecialchars($this->last_query, ENT_QUOTES);
+
+		// If there is an error then take note of it
+		print "<div id='error'>
+		<p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
+		<code>$query</code></p>
+		</div>";
 	}
 
 	// ==================================================================
 	//	Turn error handling on or off..
 
-	function show_errors() {
-		$this->show_errors = true;
+	function show_errors( $show = true ) {
+		$errors = $this->show_errors;
+		$this->show_errors = $show;
+		return $errors;
 	}
 
 	function hide_errors() {
+		$show = $this->show_errors;
 		$this->show_errors = false;
+		return $show;
 	}
 
 	// ==================================================================
@@ -187,6 +204,9 @@
 	//	Basic Query	- see docs for more detail
 
 	function query($query) {
+		if ( ! $this->ready )
+			return false;
+
 		// filter the query, if filters are available
 		// NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
 		if ( function_exists('apply_filters') )
@@ -399,12 +419,17 @@
 	 * @param string $message
 	 */
 	function bail($message) { // Just wraps errors in a nice header and footer
-		if ( !$this->show_errors )
+		if ( !$this->show_errors ) {
+			if ( class_exists('WP_Error') )
+				$this->error = new WP_Error('500', $message);
+			else
+				$this->error = $message;
 			return false;
+		}
 		wp_die($message);
 	}
 }
 
 if ( ! isset($wpdb) )
 	$wpdb = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
-?>
\ No newline at end of file
+?>
diff -Naur wordpress-2.3.1/wp-mail.php wordpress-2.3.3/wp-mail.php
--- wordpress-2.3.1/wp-mail.php	2007-10-21 06:18:08.000000000 +0000
+++ wordpress-2.3.3/wp-mail.php	2007-12-29 19:38:47.000000000 +0000
@@ -12,7 +12,7 @@
 $pop3 = new POP3();
 
 if (!$pop3->connect(get_option('mailserver_url'), get_option('mailserver_port')))
-	wp_die($pop3->ERROR);
+	wp_die(wp_specialchars($pop3->ERROR));
 
 $count = $pop3->login(get_option('mailserver_login'), get_option('mailserver_pass'));
 if (0 == $count) wp_die(__('There doesn&#8217;t seem to be any new mail.'));
@@ -129,9 +129,6 @@
 	$content = explode($phone_delim, $content);
 	$content[1] ? $content = $content[1] : $content = $content[0];
 
-	echo "<p><b>Content-type:</b> $content_type, <b>Content-Transfer-Encoding:</b> $content_transfer_encoding, <b>boundary:</b> $boundary</p>\n";
-	echo "<p><b>Raw content:</b><br /><pre>".$content.'</pre></p>';
-
 	$content = trim($content);
 
 	$post_content = apply_filters('phone_content', $content);
@@ -161,12 +158,11 @@
 
 	do_action('publish_phone', $post_ID);
 
-	echo "\n<p><b>Author:</b> $post_author</p>";
-	echo "\n<p><b>Posted title:</b> $post_title<br />";
-	echo "\n<b>Posted content:</b><br /><pre>".$content.'</pre></p>';
+	echo "\n<p><b>Author:</b> " . wp_specialchars($post_author) . "</p>";
+	echo "\n<p><b>Posted title:</b> " . wp_specialchars($post_title) . "<br />";
 
 	if(!$pop3->delete($i)) {
-		echo '<p>Oops '.$pop3->ERROR.'</p></div>';
+		echo '<p>Oops '.wp_specialchars($pop3->ERROR).'</p></div>';
 		$pop3->reset();
 		exit;
 	} else {
diff -Naur wordpress-2.3.1/wp-settings.php wordpress-2.3.3/wp-settings.php
--- wordpress-2.3.1/wp-settings.php	2007-09-19 20:48:34.000000000 +0000
+++ wordpress-2.3.3/wp-settings.php	2007-12-21 02:57:21.000000000 +0000
@@ -122,6 +122,9 @@
 else
 	require_once (ABSPATH . WPINC . '/wp-db.php');
 
+if ( !empty($wpdb->error) )
+	dead_db();
+
 // $table_prefix is deprecated as of 2.1
 $wpdb->prefix = $table_prefix;
 
diff -Naur wordpress-2.3.1/xmlrpc.php wordpress-2.3.3/xmlrpc.php
--- wordpress-2.3.1/xmlrpc.php	2007-09-18 16:42:25.000000000 +0000
+++ wordpress-2.3.3/xmlrpc.php	2008-02-04 18:52:49.000000000 +0000
@@ -187,6 +187,12 @@
 			return($this->error);
 		}
 
+		set_current_user( 0, $username );
+		if( !current_user_can( 'edit_page', $page_id ) )
+			return new IXR_Error( 401, __( 'Sorry, you can not edit this page.' ) );
+
+		do_action('xmlrpc_call', 'wp.getPage');
+
 		// Lookup page info.
 		$page = get_page($page_id);
 
@@ -268,6 +274,12 @@
 			return($this->error);
 		}
 
+		set_current_user( 0, $username );
+		if( !current_user_can( 'edit_pages' ) )
+			return new IXR_Error( 401, __( 'Sorry, you can not edit pages.' ) );
+
+		do_action('xmlrpc_call', 'wp.getPages');
+
 		// Lookup info on pages.
 		$pages = get_pages();
 		$num_pages = count($pages);
@@ -426,6 +438,12 @@
 			return($this->error);
 		}
 
+		set_current_user( 0, $username );
+		if( !current_user_can( 'edit_pages' ) )
+			return new IXR_Error( 401, __( 'Sorry, you can not edit pages.' ) );
+
+		do_action('xmlrpc_call', 'wp.getPageList');
+
 		// Get list of pages ids and titles
 		$page_list = $wpdb->get_results("
 			SELECT ID page_id,
@@ -459,7 +477,6 @@
 	 * wp_getAuthors
 	 */
 	function wp_getAuthors($args) {
-		global $wpdb;
 
 		$this->escape($args);
 
@@ -471,7 +488,23 @@
 			return($this->error);
 		}
 
-		return(get_users_of_blog());
+		set_current_user(0, $username);
+		if(!current_user_can("edit_posts")) {
+			return(new IXR_Error(401, __("Sorry, you can not edit posts on this blog.")));
+        }
+
+		do_action('xmlrpc_call', 'wp.getAuthors');
+
+		$authors = array();
+		foreach( (array) get_users_of_blog() as $row ) {
+			$authors[] = array(
+				"user_id"       => $row->user_id,
+				"user_login"    => $row->user_login,
+				"display_name"  => $row->display_name
+			);
+		}
+
+		return($authors);
 	}
 
 	/**
@@ -493,7 +526,7 @@
 		// Set the user context and make sure they are
 		// allowed to add a category.
 		set_current_user(0, $username);
-		if(!current_user_can("manage_categories", $page_id)) {
+		if(!current_user_can("manage_categories")) {
 			return(new IXR_Error(401, __("Sorry, you do not have the right to add a category.")));
 		}
 
@@ -547,6 +580,12 @@
 			return($this->error);
 		}
 
+		set_current_user(0, $username);
+		if( !current_user_can( 'edit_posts' ) ) 
+			return new IXR_Error( 401, __( 'Sorry, you must be able to publish to this blog in order to view categories.' ) );
+
+		do_action('xmlrpc_call', 'wp.suggestCategories');
+
 		$args = array('get' => 'all', 'number' => $max_results, 'name__like' => $category);
 		$category_suggestions = get_categories($args);
 
@@ -597,13 +636,18 @@
 			return $this->error;
 		}
 
+		set_current_user( 0, $user_login );
+		if( !current_user_can( 'edit_posts' ) ) 
+			return new IXR_Error( 401, __( 'Sorry, you do not have access to user data on this blog.' ) );
+
+		do_action('xmlrpc_call', 'blogger.getUserInfo');
+
 		$user_data = get_userdatabylogin($user_login);
 
 		$struct = array(
 			'nickname'  => $user_data->nickname,
 			'userid'    => $user_data->ID,
 			'url'       => $user_data->user_url,
-			'email'     => $user_data->user_email,
 			'lastname'  => $user_data->last_name,
 			'firstname' => $user_data->first_name
 		);
@@ -625,7 +669,12 @@
 			return $this->error;
 		}
 
-		$user_data = get_userdatabylogin($user_login);
+		set_current_user( 0, $user_login );
+		if( !current_user_can( 'edit_post', $post_ID ) ) 
+			return new IXR_Error( 401, __( 'Sorry, you can not edit this post.' ) );
+
+		do_action('xmlrpc_call', 'blogger.getPost');
+
 		$post_data = wp_get_single_post($post_ID, ARRAY_A);
 
 		$categories = implode(',', wp_get_post_categories($post_ID));
@@ -663,12 +712,16 @@
 
 		$posts_list = wp_get_recent_posts($num_posts);
 
+		set_current_user( 0, $user_login );
+
 		if (!$posts_list) {
 			$this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.'));
 			return $this->error;
 		}
 
 		foreach ($posts_list as $entry) {
+			if( !current_user_can( 'edit_post', $entry['ID'] ) )
+				continue;
 
 			$post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']);
 			$categories = implode(',', wp_get_post_categories($entry['ID']));
@@ -922,19 +975,28 @@
 	  if (!$this->login_pass_ok($user_login, $user_pass)) {
 	    return $this->error;
 	  }
-
-      $cap = ($publish) ? 'publish_posts' : 'edit_posts';
 	  $user = set_current_user(0, $user_login);
-	  if ( !current_user_can($cap) )
-	    return new IXR_Error(401, __('Sorry, you are not allowed to post on this blog.'));
 
-		// The post_type defaults to post, but could also be page.
-		$post_type = "post";
-		if(
-			!empty($content_struct["post_type"])
-			&& ($content_struct["post_type"] == "page")
-		) {
-			$post_type = "page";
+		$cap = ( $publish ) ? 'publish_posts' : 'edit_posts';
+		$error_message = __( 'Sorry, you are not allowed to publish posts on this blog.' );
+		$post_type = 'post';
+		if( !empty( $content_struct['post_type'] ) ) {
+			if( $content_struct['post_type'] == 'page' ) {
+				$cap = ( $publish ) ? 'publish_pages' : 'edit_pages';
+				$error_message = __( 'Sorry, you are not allowed to publish pages on this blog.' );
+				$post_type = 'page';
+			}
+			elseif( $content_type['post_type'] == 'post' ) {
+				// This is the default, no changes needed
+			}
+			else {
+				// No other post_type values are allowed here
+				return new IXR_Error( 401, __( 'Invalid post type.' ) );
+			}
+		}
+
+		if( !current_user_can( $cap ) ) {
+			return new IXR_Error( 401, $error_message );
 		}
 
 		// Let WordPress generate the post_name (slug) unless
@@ -1134,21 +1196,29 @@
 	  if (!$this->login_pass_ok($user_login, $user_pass)) {
 	    return $this->error;
 	  }
-
 		$user = set_current_user(0, $user_login);
 
-		// The post_type defaults to post, but could also be page.
-		$post_type = "post";
-		if(
-			!empty($content_struct["post_type"])
-			&& ($content_struct["post_type"] == "page")
-		) {
-			$post_type = "page";
+		$cap = ( $publish ) ? 'publish_posts' : 'edit_posts';
+		$error_message = __( 'Sorry, you are not allowed to publish posts on this blog.' );
+		$post_type = 'post';
+		if( !empty( $content_struct['post_type'] ) ) {
+			if( $content_struct['post_type'] == 'page' ) {
+				$cap = ( $publish ) ? 'publish_pages' : 'edit_pages';
+				$error_message = __( 'Sorry, you are not allowed to publish pages on this blog.' );
+				$post_type = 'page';
+			}
+			elseif( $content_type['post_type'] == 'post' ) {
+				// This is the default, no changes needed
+			}
+			else {
+				// No other post_type values are allowed here
+				return new IXR_Error( 401, __( 'Invalid post type.' ) );
+			}
 		}
 
-	  // Edit page caps are checked in editPage.  Just check post here.
-	  if ( ( 'post' == $post_type ) && !current_user_can('edit_post', $post_ID) )
-	    return new IXR_Error(401, __('Sorry, you can not edit this post.'));
+		if( !current_user_can( $cap ) ) {
+			return new IXR_Error( 401, $error_message );
+		}
 
 	  $postdata = wp_get_single_post($post_ID, ARRAY_A);
 
@@ -1328,78 +1398,83 @@
 	/* metaweblog.getPost ...returns a post */
 	function mw_getPost($args) {
 
-	  global $wpdb;
+		global $wpdb;
 
 		$this->escape($args);
 
-	  $post_ID     = (int) $args[0];
-	  $user_login  = $args[1];
-	  $user_pass   = $args[2];
+		$post_ID     = (int) $args[0];
+		$user_login  = $args[1];
+		$user_pass   = $args[2];
 
-	  if (!$this->login_pass_ok($user_login, $user_pass)) {
-	    return $this->error;
-	  }
+		if (!$this->login_pass_ok($user_login, $user_pass)) {
+			return $this->error;
+		}
 
-	  $postdata = wp_get_single_post($post_ID, ARRAY_A);
+		set_current_user( 0, $user_login );
+		if( !current_user_can( 'edit_post', $post_ID ) )
+			return new IXR_Error( 401, __( 'Sorry, you can not edit this post.' ) );
 
-	  if ($postdata['post_date'] != '') {
+		do_action('xmlrpc_call', 'metaWeblog.getPost');
 
-	    $post_date = mysql2date('Ymd\TH:i:s', $postdata['post_date']);
-	    $post_date_gmt = mysql2date('Ymd\TH:i:s', $postdata['post_date_gmt']);
+		$postdata = wp_get_single_post($post_ID, ARRAY_A);
 
-	    $categories = array();
-	    $catids = wp_get_post_categories($post_ID);
-	    foreach($catids as $catid) {
-	      $categories[] = get_cat_name($catid);
-	    }
+		if ($postdata['post_date'] != '') {
+			$post_date = mysql2date('Ymd\TH:i:s', $postdata['post_date']);
+			$post_date_gmt = mysql2date('Ymd\TH:i:s', $postdata['post_date_gmt']);
 
-		$tagnames = array();
-		$tags = wp_get_post_tags( $post_ID );
-		if ( !empty( $tags ) ) {
-			foreach ( $tags as $tag ) {
-				$tagnames[] = $tag->name;
+			$categories = array();
+			$catids = wp_get_post_categories($post_ID);
+			foreach($catids as $catid) {
+				$categories[] = get_cat_name($catid);
 			}
-			$tagnames = implode( ', ', $tagnames );
-		} else {
-			$tagnames = '';
-		}
 
-	    $post = get_extended($postdata['post_content']);
-	    $link = post_permalink($postdata['ID']);
+			$tagnames = array();
+			$tags = wp_get_post_tags( $post_ID );
+			if ( !empty( $tags ) ) {
+				foreach ( $tags as $tag ) {
+					$tagnames[] = $tag->name;
+				}
+				$tagnames = implode( ', ', $tagnames );
+			} else {
+				$tagnames = '';
+			}
 
-		// Get the author info.
-		$author = get_userdata($postdata['post_author']);
+			$post = get_extended($postdata['post_content']);
+			$link = post_permalink($postdata['ID']);
 
-	    $allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0;
-	    $allow_pings = ('open' == $postdata['ping_status']) ? 1 : 0;
-
-	    $resp = array(
-	      'dateCreated' => new IXR_Date($post_date),
-	      'userid' => $postdata['post_author'],
-	      'postid' => $postdata['ID'],
-	      'description' => $post['main'],
-	      'title' => $postdata['post_title'],
-	      'link' => $link,
-	      'permaLink' => $link,
-// commented out because no other tool seems to use this
-//	      'content' => $entry['post_content'],
-	      'categories' => $categories,
-	      'mt_excerpt' => $postdata['post_excerpt'],
-	      'mt_text_more' => $post['extended'],
-	      'mt_allow_comments' => $allow_comments,
-	      'mt_allow_pings' => $allow_pings,
-		  'mt_keywords' => $tagnames,
-          'wp_slug' => $postdata['post_name'],
-          'wp_password' => $postdata['post_password'],
-          'wp_author_id' => $author->ID,
-          'wp_author_display_name'	=> $author->display_name,
-          'date_created_gmt' => new IXR_Date($post_date_gmt)
-	    );
+			// Get the author info.
+			$author = get_userdata($postdata['post_author']);
 
-	    return $resp;
-	  } else {
-	  	return new IXR_Error(404, __('Sorry, no such post.'));
-	  }
+			$allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0;
+			$allow_pings = ('open' == $postdata['ping_status']) ? 1 : 0;
+
+			$resp = array(
+	      		'dateCreated' => new IXR_Date($post_date),
+				'userid' => $postdata['post_author'],
+				'postid' => $postdata['ID'],
+				'description' => $post['main'],
+				'title' => $postdata['post_title'],
+				'link' => $link,
+				'permaLink' => $link,
+				// commented out because no other tool seems to use this
+				//	      'content' => $entry['post_content'],
+				'categories' => $categories,
+				'mt_excerpt' => $postdata['post_excerpt'],
+				'mt_text_more' => $post['extended'],
+				'mt_allow_comments' => $allow_comments,
+				'mt_allow_pings' => $allow_pings,
+				'mt_keywords' => $tagnames,
+				'wp_slug' => $postdata['post_name'],
+				'wp_password' => $postdata['post_password'],
+				'wp_author_id' => $author->ID,
+				'wp_author_display_name'	=> $author->display_name,
+				'date_created_gmt' => new IXR_Date($post_date_gmt)
+			);
+
+			return $resp;
+		} else {
+			return new IXR_Error(404, __('Sorry, no such post.'));
+		}
 	}
 
 
@@ -1424,7 +1499,11 @@
 			return $this->error;
 		}
 
+		set_current_user( 0, $user_login );
+
 		foreach ($posts_list as $entry) {
+			if( !current_user_can( 'edit_post', $entry['ID'] ) )
+				continue;
 
 			$post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']);
 			$post_date_gmt = mysql2date('Ymd\TH:i:s', $entry['post_date_gmt']);
@@ -1504,6 +1583,12 @@
 			return $this->error;
 		}
 
+		set_current_user( 0, $user_login );
+		if( !current_user_can( 'edit_posts' ) )
+			return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this blog in order to view categories.' ) );
+
+		do_action('xmlrpc_call', 'metaWeblog.getCategories');
+
 		$categories_struct = array();
 
 		if ( $cats = get_categories('get=all') ) {
@@ -1623,7 +1708,11 @@
 			return $this->error;
 		}
 
+		set_current_user( 0, $user_login );
+
 		foreach ($posts_list as $entry) {
+			if( !current_user_can( 'edit_post', $entry['ID'] ) ) 
+				continue;
 
 			$post_date = mysql2date('Ymd\TH:i:s', $entry['post_date']);
 			$post_date_gmt = mysql2date('Ymd\TH:i:s', $entry['post_date_gmt']);
@@ -1662,9 +1751,14 @@
 			return $this->error;
 		}
 
+		set_current_user( 0, $user_login );
+		if( !current_user_can( 'edit_posts' ) )
+			return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this blog in order to view categories.' ) );
+
+		do_action('xmlrpc_call', 'mt.getCategoryList');
+
 		$categories_struct = array();
 
-		// FIXME: can we avoid using direct SQL there?
 		if ( $cats = get_categories('hide_empty=0&hierarchical=0') ) {
 			foreach ($cats as $cat) {
 				$struct['categoryId'] = $cat->term_id;
@@ -1691,6 +1785,12 @@
 			return $this->error;
 		}
 
+		set_current_user( 0, $user_login );
+		if( !current_user_can( 'edit_post', $post_ID ) )
+			return new IXR_Error( 401, __( 'Sorry, you can not edit this post.' ) );
+
+		do_action('xmlrpc_call', 'mt.getPostCategories');
+
 		$categories = array();
 		$catids = wp_get_post_categories(intval($post_ID));
 		// first listed category will be the primary category
