diff --git a/wp-content/plugins/feedwordpress/diagnostics-page.php b/wp-content/plugins/feedwordpress/diagnostics-page.php
index 46c397502585c3bc6cb250cd9aa52462485d100e..66f0dc2979032db1bc4dbdb2e09789be582130f2 100644
--- a/wp-content/plugins/feedwordpress/diagnostics-page.php
+++ b/wp-content/plugins/feedwordpress/diagnostics-page.php
@@ -356,23 +356,36 @@ function clone_http_test_args_keyvalue_prototype () {
 	<td><a href="#http-test-args" onclick="return clone_http_test_args_keyvalue_prototype();">+ Add</a></td>
 	</tr>
 	</table>
+	</td>
+	</tr>
 
+	<tr>
+	<th>XPath:</th>
+	<td><div><input type="text" name="http_test_xpath" value="" placeholder="xpath-like query" /></div>
+	<div><p>Leave blank to test HTTP, fill in to test a query.</p></div>
+	</td>
+	</tr>
+	
 	<?php if (isset($page->test_html['http_test'])) : ?>
+	<tr>
+	<th scope="row">RESULTS:</th>
+	<td>
+	<div>URL: <code><?php print esc_html($page->test_html['url']); ?></code></div>
 	<div style="position: relative">
 	<div style="width: 100%; overflow: scroll; background-color: #eed">
 	<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -o-pre-wrap;"><?php print $page->test_html['http_test']; ?></pre>
 	</div>
 	</div>
-	<?php endif; ?>
 	</td>
 	</tr>
+	<?php endif; ?>
 </table>
 
 <?php
 	} /* FeedWordPressDiagnosticsPage::tests_box () */
 
-	var $test_html;
-	static function do_http_test ($post) {
+	private $test_html;
+	public function do_http_test ($post) {
 		if (isset($post['http_test_url']) and isset($post['http_test_method'])) :
 			$url = $post['http_test_url'];
 
@@ -410,6 +423,7 @@ function clone_http_test_args_keyvalue_prototype () {
 				break;
 			endswitch;
 			
+			$this->test_html['url'] = $url;
 			$this->test_html['http_test'] = esc_html(MyPHP::val($out));
 		endif;
 	} /* FeedWordPressDiagnosticsPage::do_http_test () */
diff --git a/wp-content/plugins/feedwordpress/feedwordpress-elements.js b/wp-content/plugins/feedwordpress/feedwordpress-elements.js
index c3d799a767db6a9a631cb5613dbf27bab84015e0..b2665dbba4b6148acf3d52758ca748230f95ce39 100644
--- a/wp-content/plugins/feedwordpress/feedwordpress-elements.js
+++ b/wp-content/plugins/feedwordpress/feedwordpress-elements.js
@@ -629,7 +629,7 @@ function fwp_xpathtest_ok (response, result_id, destination) {
 	
 	if (response.results instanceof Array) {
 		for (var i = 0; i < response.results.length; i++) {
-			resultsHtml += '<li>result['+i.toString()+'] = <code>'+response.results[i]+'</code></li>';
+			resultsHtml += '<li>result['+(i+1).toString()+'] = <code>'+response.results[i]+'</code></li>';
 		}
 	} else {
 		resultsHtml += '<li>result = <code>' + response.results + '</code></li>';
diff --git a/wp-content/plugins/feedwordpress/feedwordpress.php b/wp-content/plugins/feedwordpress/feedwordpress.php
index a92f2f916a0cbca6d348a81d5fe75af4617b2f67..753ca5eee9893a6307d380e195166f01ac46473d 100644
--- a/wp-content/plugins/feedwordpress/feedwordpress.php
+++ b/wp-content/plugins/feedwordpress/feedwordpress.php
@@ -3,7 +3,7 @@
 Plugin Name: FeedWordPress
 Plugin URI: http://feedwordpress.radgeek.com/
 Description: simple and flexible Atom/RSS syndication for WordPress
-Version: 2015.0514
+Version: 2016.0420
 Author: Charles Johnson
 Author URI: http://radgeek.com/
 License: GPL
@@ -11,7 +11,7 @@ License: GPL
 
 /**
  * @package FeedWordPress
- * @version 2015.0514
+ * @version 2016.0420
  */
 
 # This uses code derived from:
@@ -32,7 +32,7 @@ License: GPL
 
 # -- Don't change these unless you know what you're doing...
 
-define ('FEEDWORDPRESS_VERSION', '2015.0514');
+define ('FEEDWORDPRESS_VERSION', '2016.0420');
 define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
 
 if (!defined('FEEDWORDPRESS_BLEG')) :
diff --git a/wp-content/plugins/feedwordpress/readme.txt b/wp-content/plugins/feedwordpress/readme.txt
index 2ea28d8ccff5e659bd25ed4ca1766b2b9513431a..fe6342b57ee5e2ec2286982da70c7b5fe0d10226 100644
--- a/wp-content/plugins/feedwordpress/readme.txt
+++ b/wp-content/plugins/feedwordpress/readme.txt
@@ -3,8 +3,8 @@ Contributors: Charles Johnson
 Donate link: http://feedwordpress.radgeek.com/
 Tags: syndication, aggregation, feed, atom, rss
 Requires at least: 3.0
-Tested up to: 4.2.2
-Stable tag: 2015.0514
+Tested up to: 4.5.2
+Stable tag: 2016.0420
 
 FeedWordPress syndicates content from feeds you choose into your WordPress weblog. 
 
@@ -20,7 +20,7 @@ appears as a series of special posts in your WordPress posts database. If you
 syndicate several feeds then you can use WordPress's posts database and
 templating engine as the back-end of an aggregation ("planet") website. It was
 developed, originally, because I needed a more flexible replacement for
-[Planet][] to use at [Feminist Blogs][].
+[Planet][] to use at Feminist Blogs, an aggregator site that I used to administer.
 
 [Planet]: http://www.planetplanet.org/
 [Feminist Blogs]: http://feministblogs.org/
@@ -94,6 +94,33 @@ outs, see the documentation at the [FeedWordPress project homepage][].
 
 == Changelog ==
 
+= 2016.0420 =
+
+*	WORDPRESS COMPATIBILITY: Tested with new versions of WordPress up to 4.5.
+
+*	FILTERS AND ADD-ONS: Allow filters and add-ons to filter terms and taxonomy
+	(categories, tags, custom taxonomies, etc.) more thoroughly and more
+	fine-grainedly using syndicated_post_terms_match, syndicated_post_terms_match_{taxonomy},
+	syndicated_post_terms_unfamiliar, syndicated_post_terms_mapping,
+	syndicated_item_feed_terms, and syndicated_item_preset_terms filters.
+
+*	FILTERS AND ADD-ONS: Globals $fwp_channel and $fwp_feedmeta REMOVED.
+	These global variables, originally introduced to allow filters access to
+	information about the source feed in `syndicated_item` filters were
+	deprecated 6+ years ago. If you have any filters or add-ons which still
+	depend on these global variables, you've been using obsolete techniques
+	and you should see about fixing them to access data	about the source feed
+	using the SyndicatedPost::link element instead. For documentation, see
+	the FeedWordPress documentation wiki at
+	<http://feedwordpress.radgeek.com/wiki/syndicatedpost> and
+	<http://feedwordpress.radgeek.com/wiki/syndicatedlink>.
+
+*	BUGFIX: Syndication > Diagnostics HTTP diagnostic test widget was broken due to
+	a dumb error on my part. Now fixed.
+	
+*	SMALL CODING CHANGES: Lots of small changes to code organization, incorporation
+	of some PHP 5.x coding conventions, etc.
+
 = 2015.0514 =
 
 *	IMPORTANT SECURITY UPDATE: This version includes two important fixes for
diff --git a/wp-content/plugins/feedwordpress/syndicatedpost.class.php b/wp-content/plugins/feedwordpress/syndicatedpost.class.php
index f8fba139c4749aa07db94bd3cb380c712aca2c6f..eb3bdbed0e6dfbe1a45a304940a0ed13ad696ce2 100644
--- a/wp-content/plugins/feedwordpress/syndicatedpost.class.php
+++ b/wp-content/plugins/feedwordpress/syndicatedpost.class.php
@@ -1,6 +1,7 @@
 <?php
 require_once(dirname(__FILE__).'/feedtime.class.php');
 require_once(dirname(__FILE__).'/syndicatedpostterm.class.php');
+require_once(dirname(__FILE__).'/syndicatedpostxpathquery.class.php');
 
 /**
  * class SyndicatedPost: FeedWordPress uses to manage the conversion of
@@ -42,7 +43,7 @@ class SyndicatedPost {
 	 * @param array $item The item syndicated from the feed.
 	 * @param SyndicatedLink $source The feed it was syndicated from.
 	 */
-	function SyndicatedPost ($item, &$source) {
+	function __construct ($item, &$source) {
 		global $wpdb;
 
 		if ( empty($item) && empty($source) )
@@ -86,21 +87,6 @@ class SyndicatedPost {
 		// Fucking SimplePie.
 		$this->xmlns['reverse']['rss'][] = '';
 
-		# These globals were originally an ugly kludge around a bug in
-		# apply_filters from WordPress 1.5. The bug was fixed in 1.5.1,
-		# and I sure hope at this point that nobody writing filters for
-		# FeedWordPress is still relying on them.
-		#
-		# Anyway, I hereby declare them DEPRECATED as of 8 February
-		# 2010. I'll probably remove the globals within 1-2 releases in
-		# the interests of code hygiene and memory usage. If you
-		# currently use them in your filters, I advise you switch off to
-		# accessing the public members SyndicatedPost::feed and
-		# SyndicatedPost::feedmeta.
-
-		global $fwp_channel, $fwp_feedmeta;
-		$fwp_channel = $this->feed; $fwp_feedmeta = $this->feedmeta;
-
 		// Trigger global syndicated_item filter.
 		$changed = apply_filters('syndicated_item', $this->item, $this);
 		$this->item = $changed;
@@ -265,93 +251,15 @@ class SyndicatedPost {
 			// Store a hash of the post content for checking whether something needs to be updated
 			$this->post['meta']['syndication_item_hash'] = $this->update_hash();
 
-			// Categories: start with default categories, if any.
-			$cats = array();
-			if ('no' != $this->link->setting('add/category', NULL, 'yes')) :
-				$fc = get_option("feedwordpress_syndication_cats");
-				if ($fc) :
-					$cats = array_merge($cats, explode("\n", $fc));
-				endif;
-			endif;
-
-			$fc = $this->link->setting('cats', NULL, array());
-			if (is_array($fc)) :
-				$cats = array_merge($cats, $fc);
-			endif;
-			$this->preset_terms['category'] = $cats;
-
-			// Now add categories from the post, if we have 'em
-			$cats = array();
-			$post_cats = $this->entry->get_categories();
-			if (is_array($post_cats)) : foreach ($post_cats as $cat) :
-				$cat_name = $cat->get_term();
-				if (!$cat_name) : $cat_name = $cat->get_label(); endif;
-
-				if ($this->link->setting('cat_split', NULL, NULL)) :
-					$pcre = "\007".$this->feedmeta['cat_split']."\007";
-					$cats = array_merge(
-						$cats,
-						preg_split(
-							$pcre,
-							$cat_name,
-							-1 /*=no limit*/,
-							PREG_SPLIT_NO_EMPTY
-						)
-					);
-				else :
-					$cats[] = $cat_name;
-				endif;
-			endforeach; endif;
-
-			$this->feed_terms['category'] = apply_filters('syndicated_item_categories', $cats, $this);
-
-			// Tags: start with default tags, if any
-			$tags = array();
-			if ('no' != $this->link->setting('add/post_tag', NULL, 'yes')) :
-				$ft = get_option("feedwordpress_syndication_tags", NULL);
-				$tags = (is_null($ft) ? array() : explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft));
-			endif;
-
-			$ft = $this->link->setting('tags', NULL, array());
-			if (is_array($ft)) :
-				$tags = array_merge($tags, $ft);
-			endif;
-			$this->preset_terms['post_tag'] = $tags;
-
-			// Scan post for /a[@rel='tag'] and use as tags if present
-			$tags = $this->inline_tags();
-			$this->feed_terms['post_tag'] = apply_filters('syndicated_item_tags', $tags, $this);
-
-			$taxonomies = $this->link->taxonomies();
-			$feedTerms = $this->link->setting('terms', NULL, array());
-			$globalTerms = get_option('feedwordpress_syndication_terms', array());
-
-			$specials = array('category' => 'cats', 'post_tag' => 'tags');
-			foreach ($taxonomies as $tax) :
-				if (!isset($specials[$tax])) :
-					$terms = array();
-
-					// See if we should get the globals
-					if ('no' != $this->link->setting("add/$tax", NULL, 'yes')) :
-						if (isset($globalTerms[$tax])) :
-							$terms = $globalTerms[$tax];
-						endif;
-					endif;
-
-					// Now merge in the locals
-					if (isset($feedTerms[$tax])) :
-						$terms = array_merge($terms, $feedTerms[$tax]);
-					endif;
-
-					// That's all, folks.
-					$this->preset_terms[$tax] = $terms;
-				endif;
-			endforeach;
+			// Categories, Tags, and other Terms: from settings assignments (global settings, subscription settings),
+			// and from feed assignments (item metadata, post content)
+			$this->preset_terms = apply_filters('syndicated_item_preset_terms', $this->get_terms_from_settings(), $this);
+			$this->feed_terms = apply_filters('syndicated_item_feed_terms', $this->get_terms_from_feeds(), $this);
 
 			$this->post['post_type'] = apply_filters('syndicated_post_type', $this->link->setting('syndicated post type', 'syndicated_post_type', 'post'), $this);
 		endif;
 		
-	} /* SyndicatedPost::SyndicatedPost() */
+	} /* SyndicatedPost::__construct() */
 
 	#####################################
 	#### EXTRACT DATA FROM FEED ITEM ####
@@ -383,97 +291,26 @@ class SyndicatedPost {
 	 * elements or attributes
 	 */
 	 function query ($path) {
-	 	$urlHash = array();
-
-	 	// Allow {url} notation for namespaces. URLs will contain : and /, so...
-	 	preg_match_all('/{([^}]+)}/', $path, $match, PREG_SET_ORDER);
-	 	foreach ($match as $ref) :
-	 	 	$urlHash[md5($ref[1])] = $ref[1];
-		endforeach;
-
-		foreach ($urlHash as $hash => $url) :
-			$path = str_replace('{'.$url.'}', '{#'.$hash.'}', $path);
-		endforeach;
-
-		$path = explode('/', $path);
-		foreach ($path as $index => $node) :
-			if (preg_match('/{#([^}]+)}/', $node, $ref)) :
-				if (isset($urlHash[$ref[1]])) :
-					$path[$index] = str_replace(
-						'{#'.$ref[1].'}',
-						'{'.$urlHash[$ref[1]].'}',
-						$node
-					);
-				endif;
-			endif;
-		endforeach;
-
-		// Start out with a get_item_tags query.
-		$node = '';
-		while (strlen($node)==0 and !is_null($node)) :
-			$node = array_shift($path);
-		endwhile;
+		$xq = new SyndicatedPostXPathQuery(array("path" => $path));
 
-		switch ($node) :
-		case 'feed' :
-		case 'channel' :
-			$node = array_shift($path);
-			$data = $this->get_feed_root_element();
-			$data = array_merge($data, $this->get_feed_channel_elements());
-			break;
-		case 'item' :
-			$node = array_shift($path);
-		default :
-			$data = array($this->entry->data);
-			$method = NULL;
-		endswitch;
-
-		while (!is_null($node)) :
-			if (strlen($node) > 0) :
-				$matches = array();
-
-				list($axis, $element) = $this->xpath_name_and_axis($node);
-
-				foreach ($data as $datum) :
-					if (!is_string($datum) and isset($datum[$axis])) :
-						foreach ($datum[$axis] as $ns => $elements) :
-							if (isset($elements[$element])) :
-								// Potential match.
-								// Check namespace.
-								if (is_string($elements[$element])) : // Attribute
-									$addenda = array($elements[$element]);
-									$contexts = array($datum);
-								else : // Element
-									$addenda = $elements[$element];
-									$contexts = $elements[$element];
-								endif;
-
-								foreach ($addenda as $index => $addendum) :
-									$context = $contexts[$index];
-
-									$namespaces = $this->xpath_possible_namespaces($node, $context);
-									if (in_array($ns, $namespaces)) :
-										$matches[] = $addendum;
-									endif;
-								endforeach;
-							endif;
-						endforeach;
-					endif;
-				endforeach;
+		$feedChannel = array_merge(
+			$this->get_feed_root_element(),
+			$this->get_feed_channel_elements()
+		);
 
-				$data = $matches;
-			endif;
-			$node = array_shift($path);
-		endwhile;
+		$matches = $xq->match(array(
+		"type" => $this->link->simplepie->get_type(),
+		"xmlns" => $this->xmlns,
+		"map" => array(
+			"/" => array($this->entry->data),
+			"item" => array($this->entry->data),
+			"feed" => $feedChannel,
+			"channel" => $feedChannel
+		),
+		"context" => $this->entry->data,
+		"parent" => $feedChannel,
+		));
 
-		$matches = array();
-		foreach ($data as $datum) :
-			if (is_string($datum)) :
-				$matches[] = $datum;
-			elseif (isset($datum['data'])) :
-				$matches[] = $datum['data'];
-			endif;
-		endforeach;
 		return $matches;
 	} /* SyndicatedPost::query() */
 
@@ -505,84 +342,6 @@ class SyndicatedPost {
 		return $matches;
 	} /* SyndicatedPost::get_feed_channel_elements() */
 
-	function xpath_default_namespace () {
-		// Get the default namespace.
-		$type = $this->link->simplepie->get_type();
-		if ($type & SIMPLEPIE_TYPE_ATOM_10) :
-			$defaultNS = SIMPLEPIE_NAMESPACE_ATOM_10;
-		elseif ($type & SIMPLEPIE_TYPE_ATOM_03) :
-			$defaultNS = SIMPLEPIE_NAMESPACE_ATOM_03;
-		elseif ($type & SIMPLEPIE_TYPE_RSS_090) :
-			$defaultNS = SIMPLEPIE_NAMESPACE_RSS_090;
-		elseif ($type & SIMPLEPIE_TYPE_RSS_10) :
-			$defaultNS = SIMPLEPIE_NAMESPACE_RSS_10;
-		elseif ($type & SIMPLEPIE_TYPE_RSS_20) :
-			$defaultNS = SIMPLEPIE_NAMESPACE_RSS_20;
-		else :
-			$defaultNS = SIMPLEPIE_NAMESPACE_RSS_20;
-		endif;
-		return $defaultNS;
-	} /* SyndicatedPost::xpath_default_namespace() */
-
-	function xpath_name_and_axis ($node) {
-		$ns = NULL; $element = NULL;
-
-		if (substr($node, 0, 1)=='@') :
-			$axis = 'attribs'; $node = substr($node, 1);
-		else :
-			$axis = 'child';
-		endif;
-
-		if (preg_match('/^{([^}]*)}(.*)$/', $node, $ref)) :
-			$element = $ref[2];
-		elseif (strpos($node, ':') !== FALSE) :
-			list($xmlns, $element) = explode(':', $node, 2);
-		else :
-			$element = $node;
-		endif;
-		return array($axis, $element);
-	} /* SyndicatedPost::xpath_local_name () */
-
-	function xpath_possible_namespaces ($node, $datum = array()) {
-		$ns = NULL; $element = NULL;
-
-		if (substr($node, 0, 1)=='@') :
-			$attr = '@'; $node = substr($node, 1);
-		else :
-			$attr = '';
-		endif;
-
-		if (preg_match('/^{([^}]*)}(.*)$/', $node, $ref)) :
-			$ns = array($ref[1]);
-		elseif (strpos($node, ':') !== FALSE) :
-			list($xmlns, $element) = explode(':', $node, 2);
-
-			if (isset($this->xmlns['reverse'][$xmlns])) :
-				$ns = $this->xmlns['reverse'][$xmlns];
-			else :
-				$ns = array($xmlns);
-			endif;
-
-			// Fucking SimplePie. For attributes in default xmlns.
-			$defaultNS = $this->xpath_default_namespace();
-			if (isset($this->xmlns['forward'][$defaultNS])
-			and ($xmlns==$this->xmlns['forward'][$defaultNS])) :
-				$ns[] = '';
-			endif;
-
-			if (isset($datum['xmlns'])) :
-				if (isset($datum['xmlns'][$xmlns])) :
-					$ns[] = $datum['xmlns'][$xmlns];
-				endif;
-			endif;
-		else :
-			// Often in SimplePie, the default namespace gets stored
-			// as an empty string rather than a URL.
-			$ns = array($this->xpath_default_namespace(), '');
-		endif;
-		return array_unique($ns);
-	} /* SyndicatedPost::xpath_possible_namespaces() */
-
 	function get_categories ($params = array()) {
 		return $this->entry->get_categories();
 	}
@@ -976,6 +735,119 @@ class SyndicatedPost {
 		return $author;
 	} /* SyndicatedPost::author() */
 
+	/**
+	 * SyndicatedPost::get_terms_from_settings(): Return an array of terms to associate with the incoming
+	 * post based on the Categories, Tags, and other terms associated with each new post by the user's
+	 * settings (global and feed-specific).
+	 *
+	 * @since 2016.0331
+	 * @return array of lists, each element has the taxonomy for a key ('category', 'post_tag', etc.),
+	 * 		and a list of term codes (either alphanumeric names, or ID numbers encoded in a format that
+	 * 		SyndicatedLink::category_ids() can understand) within that taxonomy
+	 *	 
+	 */
+	public function get_terms_from_settings () {
+		// Categories: start with default categories, if any.
+		$cats = array();
+		if ('no' != $this->link->setting('add/category', NULL, 'yes')) :
+			$fc = get_option("feedwordpress_syndication_cats");
+			if ($fc) :
+				$cats = array_merge($cats, explode("\n", $fc));
+			endif;
+		endif;
+
+		$fc = $this->link->setting('cats',NULL, array());
+		if (is_array($fc)) :
+			$cats = array_merge($cats, $fc);
+		endif;
+		$preset_terms['category'] = $cats;
+
+		// Tags: start with default tags, if any
+		$tags = array();
+		if ('no' != $this->link->setting('add/post_tag', NULL, 'yes')) :
+			$ft = get_option("feedwordpress_syndication_tags", NULL);
+			$tags = (is_null($ft) ? array() : explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft));
+		endif;
+
+		$ft = $this->link->setting('tags', NULL, array());
+		if (is_array($ft)) :
+			$tags = array_merge($tags, $ft);
+		endif;
+		$preset_terms['post_tag'] = $tags;
+
+		$taxonomies = $this->link->taxonomies();
+		$feedTerms = $this->link->setting('terms', NULL, array());
+		$globalTerms = get_option('feedwordpress_syndication_terms', array());
+		$specials = array('category' => 'cats', 'post_tag' => 'tags');
+
+		foreach ($taxonomies as $tax) :
+			// category and tag settings have already previously been handled
+			// but if this is from another taxonomy, then...
+			if (!isset($specials[$tax])) :
+				$terms = array();
+
+				// See if we should get the globals
+				if ('no' != $this->link->setting("add/$tax", NULL, 'yes')) :
+					if (isset($globalTerms[$tax])) :
+						$terms = $globalTerms[$tax];
+					endif;
+				endif;
+
+				// Now merge in the locals
+				if (isset($feedTerms[$tax])) :
+					$terms = array_merge($terms, $feedTerms[$tax]);
+				endif;
+
+				// That's all, folks.
+				$preset_terms[$tax] = $terms;
+			endif;
+		endforeach;
+		
+		return $preset_terms;
+	} /* SyndicatedPost::get_terms_from_settings () */
+		
+	/**
+	 * SyndicatedPost::get_terms_from_feeds(): Return an array of terms to associate with the incoming
+	 * post based on the contents of the subscribed feed (atom:category and rss:category elements, dc:subject
+	 * elements, tags embedded using microformats in the post content, etc.)
+	 *
+	 * @since 2016.0331
+	 * @return array of lists, each element has the taxonomy for a key ('category', 'post_tag', etc.),
+	 * 		and a list of alphanumeric term names
+	 */
+	public function get_terms_from_feeds () {	
+		// Now add categories from the post, if we have 'em
+		$cats = array();
+		$post_cats = $this->entry->get_categories();
+		if (is_array($post_cats)) : foreach ($post_cats as $cat) :
+			$cat_name = $cat->get_term();
+			if (!$cat_name) : $cat_name = $cat->get_label(); endif;
+
+			if ($this->link->setting('cat_split', NULL, NULL)) :
+				$pcre = "\007".$this->feedmeta['cat_split']."\007";
+				$cats = array_merge(
+					$cats,
+					preg_split(
+						$pcre,
+						$cat_name,
+						-1 /*=no limit*/,
+						PREG_SPLIT_NO_EMPTY
+					)
+				);
+			else :
+				$cats[] = $cat_name;
+			endif;
+		endforeach; endif;
+
+		$feed_terms['category'] = apply_filters('syndicated_item_categories', $cats, $this);
+
+		// Scan post for /a[@rel='tag'] and use as tags if present
+		$tags = $this->inline_tags();
+		$feed_terms['post_tag'] = apply_filters('syndicated_item_tags', $tags, $this);
+
+		return $feed_terms;
+	} /* SyndicatedPost::get_terms_from_feeds () */
+
 	/**
 	 * SyndicatedPost::inline_tags: Return a list of all the tags embedded
 	 * in post content using the a[@rel="tag"] microformat.
@@ -1568,13 +1440,17 @@ class SyndicatedPost {
 		// We have to check again in case post has been filtered during
 		// the author_id lookup
 		if ($this->has_fresh_content()) :
-			$consider = array(
-				'category' => array('abbr' => 'cats', 'domain' => array('category', 'post_tag')),
-				'post_tag' => array('abbr' => 'tags', 'domain' => array('post_tag')),
-			);
+			$mapping = apply_filters('syndicated_post_terms_mapping', array(
+				'category' => array('abbr' => 'cats', 'unfamiliar' => 'category', 'domain' => array('category', 'post_tag')),
+				'post_tag' => array('abbr' => 'tags', 'unfamiliar' => 'post_tag', 'domain' => array('post_tag')),
+			), $this);
 
 			$termSet = array(); $valid = null;
-			foreach ($consider as $what => $taxes) :
+			foreach ($this->feed_terms as $what => $anTerms) :
+				// Default to using the inclusive procedures (for cats) rather than exclusive (for inline tags)
+				$taxes = (isset($mapping[$what]) ? $mapping[$what] : $mapping['category']);
+				$unfamiliar = $taxes['unfamiliar'];
+				
 				if (!is_null($this->post)) : // Not filtered out yet
 					# -- Look up, or create, numeric ID for categories
 					$taxonomies = $this->link->setting("match/".$taxes['abbr'], 'match_'.$taxes['abbr'], $taxes['domain']);
@@ -1582,9 +1458,24 @@ class SyndicatedPost {
 					// Eliminate dummy variables
 					$taxonomies = array_filter($taxonomies, 'remove_dummy_zero');
 
+					// Allow FWP add-on filters to control the taxonomies we use to search for a term
+					$taxonomies = apply_filters("syndicated_post_terms_match", $taxonomies, $what, $this);
+					$taxonomies = apply_filters("syndicated_post_terms_match_${what}", $taxonomies, $this);
+
+					// Allow FWP add-on filters to control with greater precision what happens on unmatched
+					$unmatched = apply_filters("syndicated_post_terms_unfamiliar",
+						$this->link->setting(
+							"unfamiliar {$unfamiliar}",
+							"unfamiliar_{$unfamiliar}",
+							'create:'.$unfamiliar
+						),
+						$what,
+						$this
+					);
+
 					$terms = $this->category_ids (
-						$this->feed_terms[$what],
-						$this->link->setting("unfamiliar {$what}", "unfamiliar_{$what}", 'create:'.$what),
+						$anTerms,
+						$unmatched,
 						/*taxonomies=*/ $taxonomies,
 						array(
 						  'singleton' => false, // I don't like surprises
@@ -1727,6 +1618,8 @@ class SyndicatedPost {
 
 		$dbpost = $this->normalize_post(/*new=*/ true);
 
+		$ret = null;
+
 		if (!is_null($dbpost)) :
 			$dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
 
@@ -1791,28 +1684,34 @@ class SyndicatedPost {
 				$dbpost['ID'] = $this->_wp_id;
 			endif;
 			
-			// Now that we've made sure the original exists, insert
-			// this version here as a revision.
-			$revision_id = _wp_put_post_revision($dbpost, /*autosave=*/ false);
-
-			if (!$this->this_revision_needs_original_post()) :
+			// Sanity check: if the attempt to insert post
+			// returned an error, then feeding that error
+			// object in to _wp_put_post_revision() would
+			// cause a fatal error. Better to break out.
+			if (!is_wp_error($this->_wp_id)) :
+				// Now that we've made sure the original exists, insert
+				// this version here as a revision.
+				$revision_id = _wp_put_post_revision($dbpost, /*autosave=*/ false);
+
+				if (!$this->this_revision_needs_original_post()) :
 			
-				if ($this->this_revision_is_current()) :
+					if ($this->this_revision_is_current()) :
 
-					wp_restore_post_revision($revision_id);
+						wp_restore_post_revision($revision_id);
 
-				else :
+					else :
 
-					// If we do not activate this revision, then the
-					// add_rss_meta will not be called, which is
-					// more or less as it should be, but that means
-					// we have to actively record this revision's
-					// update hash from here.
-					$postId = $this->post['ID'];
-					$key = 'syndication_item_hash';
-					$hash = $this->update_hash();
-					FeedWordPress::diagnostic('syndicated_posts:meta_data', "Adding post meta-datum to post [$postId]: [$key] = ".FeedWordPress::val($hash, /*no newlines=*/ true));
-					add_post_meta(	$postId, $key, $hash, /*unique=*/ false );
+						// If we do not activate this revision, then the
+						// add_rss_meta will not be called, which is
+						// more or less as it should be, but that means
+						// we have to actively record this revision's
+						// update hash from here.
+						$postId = $this->post['ID'];
+						$key = 'syndication_item_hash';
+						$hash = $this->update_hash();
+						FeedWordPress::diagnostic('syndicated_posts:meta_data', "Adding post meta-datum to post [$postId]: [$key] = ".FeedWordPress::val($hash, /*no newlines=*/ true));
+						add_post_meta(	$postId, $key, $hash, /*unique=*/ false );
+					endif;
 				endif;
 			endif;
 
@@ -1837,7 +1736,10 @@ class SyndicatedPost {
 			endforeach;
 
 			$this->validate_post_id($dbpost, $update, array(__CLASS__, __FUNCTION__));
+			
+			$ret = $this->_wp_id;
 		endif;
+		return $ret;
 	} /* function SyndicatedPost::insert_post () */
 
 	function insert_new () {
@@ -1884,11 +1786,46 @@ class SyndicatedPost {
 		return $out;
 	}
 
+	public function db_sanitize_post_check_encoding ($out) {
+		// Check encoding recursively: every string field needs to be checked
+		// for character encoding issues. This is a bit problematic because we
+		// *should* be using DB_CHARSET, but DB_CHARSET sometimes has values
+		// that work for MySQL but not for PHP mb_check_encoding. So instead
+		// we must rely on WordPress setting blog_charset and hope that the user
+		// has got their database encoding set up to roughly match
+		$charset = get_option('blog_charset', 'utf8');
+		
+		foreach ($out as $key => $value) :
+			if (is_string($value)) :
+				
+				if (!function_exists('mb_check_encoding') or mb_check_encoding($value, $charset)) :
+					$out[$key] = $value;
+				else :
+					$fromCharset = mb_detect_encoding($value, mb_detect_order(), /*strict=*/ true);
+					$out[$key] = mb_convert_encoding($value, $charset, $fromCharset);
+				endif;
+				
+			elseif (is_array($value)) :
+				$out[$key] = $this->db_sanitize_post_check_encoding($value);
+
+			else :
+				$out[$key] = $value;
+			endif;
+			
+		endforeach;
+		
+		return $out;
+	} /* SyndicatedPost::db_sanitize_post_check_encoding () */
+	
 	function db_sanitize_post ($out) {
-		// < 3.6. Core API, including wp_insert_post(), will expect
-		// properly slashed data. If wp_slash() exists, then this is
-		// after the big change-over, and wp_insert_post() etc. will
-		// expect *un*-slashed data.
+		global $wp_db_version;
+		
+		$out = $this->db_sanitize_post_check_encoding($out);
+				
+		// < 3.6. Core API, including `wp_insert_post()`, expects
+		// properly slashed data. If `wp_slash()` exists, then
+		// this is after the big change-over in how data slashing
+		// was handled.
 		if (!function_exists('wp_slash')) :
 		
 			foreach ($out as $key => $value) :
@@ -1898,7 +1835,21 @@ class SyndicatedPost {
 					$out[$key] = $value;
 				endif;
 			endforeach;
-
+			
+		// For revisions [@23416,@23554), core API expects
+		// unslashed data. Cf. <https://core.trac.wordpress.org/browser/trunk/wp-includes/post.php?rev=23416>
+		// 	NOOP for those revisions.
+		
+		// In revisions @23554 to present, `wp_insert_post()`
+		// expects slashed data once again.
+		// Cf. <https://core.trac.wordpress.org/changeset/23554/trunk/wp-includes/post.php?contextall=1>
+		// But at least now we can use the wp_slash API function to do that.
+		// Hooray.
+		
+		elseif ($wp_db_version >= 23524) :
+		
+			$out = wp_slash($out);
+			
 		endif;
 
 		return $out;
@@ -2338,4 +2289,3 @@ EOM;
 	} /* SyndicatedPost::category_ids () */
 
 } /* class SyndicatedPost */
-
diff --git a/wp-content/plugins/feedwordpress/syndicatedpostterm.class.php b/wp-content/plugins/feedwordpress/syndicatedpostterm.class.php
index 01f61a95709a65f9dd7abc97f5b26039d805de7b..ff70a375967535a75231b026fe19855ba4c801e1 100644
--- a/wp-content/plugins/feedwordpress/syndicatedpostterm.class.php
+++ b/wp-content/plugins/feedwordpress/syndicatedpostterm.class.php
@@ -59,6 +59,9 @@ class SyndicatedPostTerm {
 	
 	protected function search () {
 		
+		// Initialize
+		$found = null;
+		
 		// Either this is a numbered term code, which supplies the ID
 		// and the taxonomy explicitly (e.g.: {category#2}; in which
 		// case we have set $this->tax to a unit array containing only
@@ -90,7 +93,7 @@ class SyndicatedPostTerm {
 			'CHECKED familiarity of term '
 			  .json_encode($this->term)
 			  .' across '.json_encode($this->tax)
-			  . ' with result: '.json_encode($record) 
+			  . ' with result: '.json_encode($found) 
 		);
 		
 		return $this->exists;
diff --git a/wp-content/plugins/feedwordpress/syndicatedpostxpathquery.class.php b/wp-content/plugins/feedwordpress/syndicatedpostxpathquery.class.php
new file mode 100644
index 0000000000000000000000000000000000000000..7219c61631751b70f56ff96e94a0755c4aa6e1fa
--- /dev/null
+++ b/wp-content/plugins/feedwordpress/syndicatedpostxpathquery.class.php
@@ -0,0 +1,462 @@
+<?php
+/**
+ * class SyndicatedPostXPathQuery: implements an XPath-like syntax used to query
+ * arbitrary elements within the syndicated item.
+ *
+ */
+class SyndicatedPostXPathQuery {
+	private $path;
+	private $parsedPath;
+	private $feed_type;
+	private $xmlns;
+	private $urlHash = array();
+	
+	/**
+	 * SyndicatedPostXPathQuery::__construct
+	 *
+	 * @param array $args
+	 * @uses wp_parse_args
+	 *
+	 */
+	public function __construct ($args = array()) {
+		if (is_string($args)) :
+			$args = array("path" => $args);
+		endif;
+		
+		$args = wp_parse_args($args, array(
+		"path" => "",
+		));
+
+		$this->setPath($args['path']);
+	} /* SyndicatedPostXPathQuery::__construct() */
+	
+	/**
+	 * SyndicatedPostXPathQuery::getPath
+	 *
+	 * @param array $args
+	 * @return mixed
+	 */
+	public function getPath ($args = array()) {
+			$args = wp_parse_args($args, array(
+				"parsed" => false,
+			));
+
+			return ($args['parsed'] ? $this->parsedPath : $this->path);
+	} /* SyndicatedPostXPathQuery::getPath () */
+	
+	/**
+	 * SyndicatedPostXPathQuery::setPath
+	 *
+	 * @param string $path
+	 */
+	public function setPath ($path) {
+		$this->urlHash = array();
+		
+		$this->path = $path;
+
+	 	// Allow {url} notation for namespaces. URLs will contain : and /, so...
+	 	preg_match_all('/{([^}]+)}/', $path, $match, PREG_SET_ORDER);
+	 	foreach ($match as $ref) :
+	 	 	$this->urlHash[md5($ref[1])] = $ref[1];
+		endforeach;
+
+		foreach ($this->urlHash as $hash => $url) :
+			$path = str_replace('{'.$url.'}', '{#'.$hash.'}', $path);
+		endforeach;
+
+		$path = $this->parsePath(/*cur=*/ $path, /*orig=*/ $path);
+		
+		$this->parsedPath = $path;
+
+	} /* SyndicatedPostXPathQuery::setPath() */
+	
+	/**
+	 * SyndicatedPostXPathQuery::snipSlug
+	 *
+	 * @return string
+	 */
+	protected function snipSlug ($path, $start, $n) {
+		$slug = substr($path, $start, ($n-$start));
+		if (strlen($slug) > 0) :
+			if (preg_match('/{#([^}]+)}/', $slug, $ref)) :
+				if (isset($this->urlHash[$ref[1]])) :
+					$slug = str_replace(
+						'{#'.$ref[1].'}',
+						'{'.$this->urlHash[$ref[1]].'}',
+						$slug
+					);
+				endif;
+			endif;
+		endif;
+		return $slug;
+	} /* SyndicatedPostXPathQuery::snipSlug () */
+	
+	/**
+	 * SyndicatedPostXPathQuery::parsePath ()
+	 *
+	 * @param mixed $path
+	 * @param mixed $rootPath
+	 * @return array|object
+	 */
+	public function parsePath ($path, $rootPath) {
+		if (is_array($path)) :
+			// This looks like it's already been parsed.
+			$pp = $path;
+		else :
+			$pp = array();
+			
+			// Okay let's parse this thing.
+			$n = 0; $start = 0; $state = 'slug';
+			while ($state != '$') :
+			switch ($state) :
+			case 'slash' :
+				$slug = $this->snipSlug($path, $start, $n);
+				if (strlen($slug) > 0) :
+					$pp[] = $slug;
+				endif;
+
+				$n++;
+				// don't include the slash in our next slug
+				$start = $n;
+				
+				$state = (($n < strlen($path)) ? 'slug' : '$');
+				
+				break;
+			case 'brackets' :
+
+				// first, snip off what we've consumed so far
+				$slug = $this->snipSlug($path, $start, $n);
+				if (strlen($slug) > 0) :
+					$pp[] = $slug;
+				endif;
+
+				// now, chase the ]
+				$depth = 1;
+				$n++; $start = $n;
+				
+				// find the end of the [square-bracketed] expression
+				while ($depth > 0 and $n != '') :
+					$tok = ((strlen($path) > $n) ? $path[$n] : '');
+					switch ($tok) :
+					case '' :
+						// ERROR STATE: syntax error
+						$depth = -1;
+						$state = 'syntax-error';
+						break;
+					case '[' :
+						$depth++;
+						break;
+					case ']' :
+						$depth--;
+						break;
+					default :
+						// NOOP
+					endswitch;
+					$n++;
+				endwhile;
+
+				if ($state != 'syntax-error') :
+					$bracketed = substr($path, $start, ($n-$start)-1);
+
+					// recursive parsing
+					$oFilter = new stdClass;
+					$oFilter->verb = 'has';
+					$oFilter->query = $this->parsePath($bracketed, $rootPath);
+					$pp[] = $oFilter;
+				
+					$start = $n;
+					
+					$state = 'slash-expected';
+				endif;
+				break;
+				
+			case 'slash-expected' :
+				$tok = ((strlen($path) > $n) ? $path[$n] : '');
+				if ($tok == '/' or $tok == '') :
+					$state = 'slash';
+				else :
+					$state = 'syntax-error';
+				endif;
+				break;
+			case 'syntax-error' :
+				$pp = new WP_Error('xpath', __("Syntax error", "feedwordpress"));
+				$state = '$';
+				break;
+			case 'slug' :
+			default :
+				$tok = ((strlen($path) > $n) ? $path[$n] : '');
+				switch ($tok) :
+				case '' :
+				case '/' :
+					$state = 'slash';
+					break;
+				case '[' :
+					$state = 'brackets';
+					break;
+				default :
+					$n++;
+				endswitch;
+			endswitch;
+			endwhile;
+		endif;
+		return $pp;
+	} /* SyndicatedPostXPathQuery::parsePath() */
+	
+	/**
+	 * SyndicatedPostXPathQuery::match
+	 *
+	 * @param string $path
+	 * @return array
+	 */
+	public function match ($r = array()) {
+		$path = $this->parsedPath;
+		
+		$r = wp_parse_args($r, array(
+		"type" => SIMPLEPIE_TYPE_ATOM_10,
+		"xmlns" => array(),
+		"map" => array(),
+		"context" => array(),
+		"parent" => array(),
+		"format" => "string",
+		));
+
+		$this->feed_type = $r['type'];
+		$this->xmlns = $r['xmlns'];
+		
+		// Start out with a get_item_tags query.
+		$node = '';
+		while (strlen($node)==0 and !is_null($node)) :
+			$node = array_shift($path);
+		endwhile;
+
+		if (is_string($node) and isset($r['map'][$node])) :
+			$data = $r['map'][$node];
+			$node = array_shift($path);
+		else :
+			$data = $r['map']['/'];
+		endif;
+
+		$matches = $data;
+		while (!is_null($node)) :
+			if (is_object($node) OR strlen($node) > 0) :
+				list($axis, $element) = $this->xpath_name_and_axis($node);
+				if ('self'==$axis) :
+					if (is_object($element) and property_exists($element, 'verb')) :
+
+						$subq = new self(array("path" => $element->query));
+						$result = $subq->match(array(
+							"type" => $r['type'],
+							"xmlns" => $r['xmlns'],
+							"map" => array(
+								"/" => $matches,
+							),
+							"context" => $matches,
+							"parent" => $r['parent'],
+							"format" => "object",
+						));
+						
+						// when format = 'object' we should get back
+						// a sparse array of arrays, with indices = indices
+						// from the input array, each element = an array of
+						// one or more matching elements
+	
+						if ($element->verb = 'has' and is_array($result)) :
+
+							$results = array();
+							foreach (array_keys($result) as $a) :
+								$results[$a] = $matches[$a];
+							endforeach;
+							
+							$matches = $results;
+							$data = $matches;
+						endif;
+												
+					elseif (is_numeric($node)) :
+
+						// according to W3C, sequence starts at position 1, not 0
+						// so subtract 1 to line up with PHP array starting at 0
+						$idx = intval($element) - 1;
+						if (isset($matches[$idx])) :
+							$data = array($idx => $matches[$idx]);
+						else :
+							$data = array();
+						endif;
+						
+						$matches = array($idx => $data);
+					endif;
+					
+				else :
+					$matches = array();
+
+					foreach ($data as $idx => $datum) :
+						if (!is_string($datum) and isset($datum[$axis])) :
+							foreach ($datum[$axis] as $ns => $elements) :
+								if (isset($elements[$element])) :
+									// Potential match.
+									// Check namespace.
+									if (is_string($elements[$element])) : // Attribute
+										$addenda = array($elements[$element]);
+										$contexts = array($datum);
+									
+									// Element
+									else :
+										$addenda = $elements[$element];
+										$contexts = $elements[$element];
+									endif;
+
+									foreach ($addenda as $index => $addendum) :
+										$context = $contexts[$index];
+
+										$namespaces = $this->xpath_possible_namespaces($node, $context);
+										if (in_array($ns, $namespaces)) :
+											$matches[] = $addendum;
+										endif;
+									endforeach;
+								endif;
+							endforeach;
+						endif;
+					endforeach;
+
+					$data = $matches;
+				endif;
+			endif;
+			$node = array_shift($path);
+		endwhile;
+
+		$matches = array();
+		foreach ($data as $idx => $datum) :
+			if ($r['format'] == 'string') :
+				if (is_string($datum)) :
+					$matches[] = $datum;
+				elseif (isset($datum['data'])) :
+					$matches[] = $datum['data'];
+				endif;
+			else :
+				$matches[$idx] = $datum;
+			endif;
+		endforeach;
+		
+		return $matches;
+	} /* SyndicatedPostXPathQuery::match() */
+	
+	public function xpath_default_namespace () {
+		// Get the default namespace.
+		$type = $this->feed_type;
+		if ($type & SIMPLEPIE_TYPE_ATOM_10) :
+			$defaultNS = SIMPLEPIE_NAMESPACE_ATOM_10;
+		elseif ($type & SIMPLEPIE_TYPE_ATOM_03) :
+			$defaultNS = SIMPLEPIE_NAMESPACE_ATOM_03;
+		elseif ($type & SIMPLEPIE_TYPE_RSS_090) :
+			$defaultNS = SIMPLEPIE_NAMESPACE_RSS_090;
+		elseif ($type & SIMPLEPIE_TYPE_RSS_10) :
+			$defaultNS = SIMPLEPIE_NAMESPACE_RSS_10;
+		elseif ($type & SIMPLEPIE_TYPE_RSS_20) :
+			$defaultNS = SIMPLEPIE_NAMESPACE_RSS_20;
+		else :
+			$defaultNS = SIMPLEPIE_NAMESPACE_RSS_20;
+		endif;
+		return $defaultNS;
+	} /* SyndicatedPostXPathQuery::xpath_default_namespace() */
+
+	public function xpath_name_and_axis ($node) {
+		$ns = NULL; $element = NULL;
+
+		$axis = 'child'; // "In effect, `child` is the default axis."
+		if (is_object($node) and property_exists($node, 'verb')):
+			if ('has'==$node->verb) :
+				$axis = 'self';
+			endif;
+		elseif (strpos($node, '::') !== false) :
+			list($axis, $node) = explode("::", $node, 2);
+			if ($axis=='attribute') :
+				$axis = 'attribs'; // map from W3C to SimplePie's idiosyncratic notation
+			endif;
+		elseif (substr($node, 0, 1)=='@') :
+			$axis = 'attribs'; $node = substr($node, 1);
+		elseif (is_numeric($node)) :
+			$axis = 'self';
+		elseif (substr($node, 0, 1)=='/') :
+			// FIXME: properly, we should check for // and if we have it,
+			// treat that as short for /descendent-or-self::node()/
+			$axis = 'child'; $node = substr($node, 1);
+		else :
+			// NOOP
+		endif;
+
+		if (is_string($node) and preg_match('/^{([^}]*)}(.*)$/', $node, $ref)) :
+			$element = $ref[2];
+		elseif (is_string($node) and strpos($node, ':') !== FALSE) :
+			list($xmlns, $element) = explode(':', $node, 2);
+		else :
+			$element = $node;
+		endif;
+		return array($axis, $element);
+	} /* SyndicatedPostXPathQuery::xpath_name_and_axis () */
+
+	public function xpath_possible_namespaces ($node, $datum = array()) {
+		$ns = NULL; $element = NULL;
+
+		if (substr($node, 0, 1)=='@') :
+			$attr = '@'; $node = substr($node, 1);
+		else :
+			$attr = '';
+		endif;
+
+		if (preg_match('/^{([^}]*)}(.*)$/', $node, $ref)) :
+			$ns = array($ref[1]);
+		elseif (strpos($node, ':') !== FALSE) :
+			list($xmlns, $element) = explode(':', $node, 2);
+
+			if (isset($this->xmlns['reverse'][$xmlns])) :
+				$ns = $this->xmlns['reverse'][$xmlns];
+			else :
+				$ns = array($xmlns);
+			endif;
+
+			// Fucking SimplePie. For attributes in default xmlns.
+			$defaultNS = $this->xpath_default_namespace();
+			if (isset($this->xmlns['forward'][$defaultNS])
+			and ($xmlns==$this->xmlns['forward'][$defaultNS])) :
+				$ns[] = '';
+			endif;
+
+			if (isset($datum['xmlns'])) :
+				if (isset($datum['xmlns'][$xmlns])) :
+					$ns[] = $datum['xmlns'][$xmlns];
+				endif;
+			endif;
+		else :
+			// Often in SimplePie, the default namespace gets stored
+			// as an empty string rather than a URL.
+			$ns = array($this->xpath_default_namespace(), '');
+		endif;
+		return array_unique($ns);
+	} /* SyndicatedPostXPathQuery::xpath_possible_namespaces() */
+
+} /* class SyndicatedPostXPathQuery */
+
+// When called directly, run through and perform some tests.
+if (basename($_SERVER['SCRIPT_FILENAME'])==basename(__FILE__)) :
+	# some day when I am a grown-up developer I might include
+	# some test cases in this here section
+	# we need to implement wp_parse_args(), __(), and class WP_Error ...
+	#function wp_parse_args ($r, $defaults) {
+	#	return array_merge($defaults, $r);
+	#}
+	#function __($text, $domain) {
+	#	return $text;
+	#}
+	#class WP_Error {
+	#	public function __construct ( $slug, $message ) {
+	#		/*DBG*/ echo $slug;
+	#		/*DBG*/ echo ": ";
+	#		/*DBG*/ echo $message;
+	#	}
+	#}
+	#
+	#header("Content-type: text/plain");
+	#
+	#$spxq = new SyndicatedPostXPathQuery(array("path" => $_REQUEST['p']));
+	#
+	#var_dump($spxq);
+endif;