From 50e5362b99bcbc323a94a35281d3bf57b5246f87 Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Sat, 25 Jul 2015 18:33:30 +0100
Subject: [PATCH] [auto] Plugin: feedwordpress 2015.0514

---
 wp-content/plugins/feedwordpress/admin-ui.php |  4 +-
 .../plugins/feedwordpress/feedwordpress.php   | 14 ++--
 .../feedwordpresssyndicationpage.class.php    | 70 ++++++++++++++++---
 wp-content/plugins/feedwordpress/readme.txt   | 50 ++++++++++---
 .../feedwordpress/syndicatedlink.class.php    | 15 +++-
 .../feedwordpress/syndicatedpost.class.php    | 14 +++-
 6 files changed, 136 insertions(+), 31 deletions(-)

diff --git a/wp-content/plugins/feedwordpress/admin-ui.php b/wp-content/plugins/feedwordpress/admin-ui.php
index f0c4ef397..bc3029fa6 100644
--- a/wp-content/plugins/feedwordpress/admin-ui.php
+++ b/wp-content/plugins/feedwordpress/admin-ui.php
@@ -59,11 +59,13 @@ class FeedWordPressAdminPage {
 		add_action('feedwordpress_check_feed', 'update_feeds_mention');
 		add_action('feedwordpress_check_feed_complete', 'update_feeds_finish', 10, 3);
 
+		$link = $this->link;
+		
 		print '<div class="updated">';
 		print "<ul>";
 		$uri = $this->link->uri();
 		$displayUrl = $uri;
-		
+
 		// check for effects of an effective-url filter
 		$effectiveUrl = $link->uri(array('fetch' => true));
 		if ($uri != $effectiveUrl) : $displayUrl .= ' | ' . $effectiveUrl; endif;
diff --git a/wp-content/plugins/feedwordpress/feedwordpress.php b/wp-content/plugins/feedwordpress/feedwordpress.php
index 98c2feb4a..a92f2f916 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: 2014.0805
+Version: 2015.0514
 Author: Charles Johnson
 Author URI: http://radgeek.com/
 License: GPL
@@ -11,7 +11,7 @@ License: GPL
 
 /**
  * @package FeedWordPress
- * @version 2014.0805
+ * @version 2015.0514
  */
 
 # 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', '2014.0805');
+define ('FEEDWORDPRESS_VERSION', '2015.0514');
 define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
 
 if (!defined('FEEDWORDPRESS_BLEG')) :
@@ -1284,7 +1284,7 @@ class FeedWordPress {
 					$sendback .= ( ! empty( $post_type ) ) ? '?post_type=' . $post_type : '';
 				endif;
 			else :
-				$sendback = remove_query_arg( array('trashed', 'untrashed', 'deleted', 'zapped', 'unzapped', 'ids'), $sendback );
+				$sendback = esc_url( remove_query_arg( array('trashed', 'untrashed', 'deleted', 'zapped', 'unzapped', 'ids'), $sendback ) );
 			endif;
 
 			// Make sure we have a post corresponding to this ID.
@@ -1324,7 +1324,7 @@ class FeedWordPress {
 				add_post_meta($post_id, '_feedwordpress_zapped_blank_me', 1, /*unique=*/ true);
 				add_post_meta($post_id, '_feedwordpress_zapped_blank_old_status', $old_status, /*unique=*/ true);
 				
-				wp_redirect( add_query_arg( array('zapped' => 1, 'ids' => $post_id), $sendback ) );
+				wp_redirect( esc_url_raw( add_query_arg( array('zapped' => 1, 'ids' => $post_id), $sendback ) ) );
 
 			else :
 				$old_status = get_post_meta($post_id, '_feedwordpress_zapped_blank_old_status', /*single=*/ true);
@@ -1336,7 +1336,7 @@ class FeedWordPress {
 				delete_post_meta($post_id, '_feedwordpress_zapped_blank_me');
 				delete_post_meta($post_id, '_feedwordpress_zapped_blank_old_status');
 
-				wp_redirect( add_query_arg( array('unzapped' => 1, 'ids' => $post_id), $sendback ) );
+				wp_redirect( esc_url_raw( add_query_arg( array('unzapped' => 1, 'ids' => $post_id), $sendback ) ) );
 
 			endif;
 				
@@ -1642,7 +1642,7 @@ class FeedWordPress {
 	} /* FeedWordPress::redirect_retired () */
 
 	public function row_actions ($actions, $post) {
-		if (is_syndicated($post->ID)) :
+		if (is_syndicated($post->ID) && current_user_can('edit_post', $post->ID)) :
 			$link = get_delete_post_link($post->ID, '', true);
 			$eraseLink = MyPHP::url($link, array("fwp_post_delete" => "nuke"));
 
diff --git a/wp-content/plugins/feedwordpress/feedwordpresssyndicationpage.class.php b/wp-content/plugins/feedwordpress/feedwordpresssyndicationpage.class.php
index f4afb1345..70409e263 100644
--- a/wp-content/plugins/feedwordpress/feedwordpresssyndicationpage.class.php
+++ b/wp-content/plugins/feedwordpress/feedwordpresssyndicationpage.class.php
@@ -70,6 +70,47 @@ class FeedWordPressSyndicationPage extends FeedWordPressAdminPage {
 		return ($this->visibility_toggle() == 'N');
 	}
 
+	/**
+	 * sanitize_ids: Protect id numbers from untrusted sources (POST array etc.)
+	 * from possibility of SQLi attacks. Runs everything through an intval filter
+	 * and then for good measure through esc_sql()
+	 *
+	 * @param array $link_ids An array of one or more putative link IDs
+	 * @return array 
+	 */
+	public function sanitize_ids_sql ($link_ids) {
+		$link_ids = array_map(
+			'esc_sql',
+			array_map(
+				'intval',
+				$link_ids
+			)
+		);
+		return $link_ids;
+	} /* FeedWordPressSyndicationPage::sanitize_ids_sql () */
+
+	/**
+	 * requested_link_ids_sql ()
+	 *
+	 * @return string An SQL list literal containing the link IDs, sanitized
+	 * 		and escaped for direct use in MySQL queries.
+	 *
+	 * @uses sanitize_ids_sql()
+	 */
+	public function requested_link_ids_sql () {
+		// Multiple link IDs passed in link_ids[]=... . . .
+		$link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
+		
+		// Or single in link_id=...
+		if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
+
+		// Filter for safe use in MySQL queries.
+		$link_ids = $this->sanitize_ids_sql($link_ids);
+		
+		// Convert to MySQL list literal.
+		return "('".implode("', '", $link_ids)."')";	
+	} /* FeedWordPressSyndicationPage::requested_link_ids_sql () */
+	
 	function updates_requested () {
 		global $wpdb;
 
@@ -84,9 +125,14 @@ class FeedWordPressSyndicationPage extends FeedWordPressAdminPage {
 		if ($fwp_update_invoke != 'get') :
 			if (is_array(MyPHP::post('link_ids'))
 			and (MyPHP::post('action')==FWP_UPDATE_CHECKED)) :
+				// Get single link ID or multiple link IDs from REQUEST parameters
+				// if available. Sanitize values for MySQL.
+				$link_list = $this->requested_link_ids_sql();
+				
+				// $link_list has previously been sanitized for html by self::requested_link_ids_sql
 				$targets = $wpdb->get_results("
 				SELECT * FROM $wpdb->links
-				WHERE link_id IN (".implode(",",$_POST['link_ids']).")
+				WHERE link_id IN ${link_list}
 				");
 				if (is_array($targets)) :
 					foreach ($targets as $target) :
@@ -738,10 +784,11 @@ regular donation</a>) using an existing PayPal account or any major credit card.
 		if (MyPHP::post('submit')==FWP_CANCEL_BUTTON) :
 			return true; // Continue without further ado.
 		endif;
-		
-		$link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
-		if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
-	
+
+		// Get single link ID or multiple link IDs from REQUEST parameters
+		// if available. Sanitize values for MySQL.		
+		$link_list = $this->requested_link_ids_sql();
+
 		if (MyPHP::post('confirm')=='Delete'):
 			if ( is_array(MyPHP::post('link_action')) ) :
 				$actions = MyPHP::post('link_action');
@@ -835,9 +882,10 @@ regular donation</a>) using an existing PayPal account or any major credit card.
 	
 			return true; // Continue on to Syndicated Sites listing
 		else :
+			// $link_list has previously been sanitized for html by self::requested_link_ids_sql
 			$targets = $wpdb->get_results("
 				SELECT * FROM $wpdb->links
-				WHERE link_id IN (".implode(",",$link_ids).")
+				WHERE link_id IN ${link_list}
 				");
 	?>
 	<form action="<?php print $this->form_action(); ?>" method="post">
@@ -907,9 +955,10 @@ regular donation</a>) using an existing PayPal account or any major credit card.
 		// If this is a POST, validate source and user credentials
 		FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_feeds', /*capability=*/ 'manage_links');
 	
-		$link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
-		if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
-	
+		// Get single link ID or multiple link IDs from REQUEST parameters
+		// if available. Sanitize values for MySQL.
+		$link_list = $this->requested_link_ids_sql();
+
 		if (MyPHP::post('confirm')=='Undelete'):
 			if ( is_array(MyPHP::post('link_action')) ) :
 				$actions = MyPHP::post('link_action');
@@ -956,9 +1005,10 @@ regular donation</a>) using an existing PayPal account or any major credit card.
 	
 			return true; // Continue on to Syndicated Sites listing
 		else :
+			// $link_list has previously been sanitized for html by self::requested_link_ids_sql
 			$targets = $wpdb->get_results("
 				SELECT * FROM $wpdb->links
-				WHERE link_id IN (".implode(",",$link_ids).")
+				WHERE link_id IN ${link_list}
 				");
 	?>
 	<form action="<?php print $this->form_action(); ?>" method="post">
diff --git a/wp-content/plugins/feedwordpress/readme.txt b/wp-content/plugins/feedwordpress/readme.txt
index 6dc09b3e0..2ea28d8cc 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: 3.9.1
-Stable tag: 2014.0805
+Tested up to: 4.2.2
+Stable tag: 2015.0514
 
 FeedWordPress syndicates content from feeds you choose into your WordPress weblog. 
 
@@ -26,12 +26,12 @@ developed, originally, because I needed a more flexible replacement for
 [Feminist Blogs]: http://feministblogs.org/
 
 FeedWordPress is designed with flexibility, ease of use, and ease of
-configuration in mind. You'll need a working installation of WordPress or
-WordPress MU (version [3.0] or later), and also FTP or SFTP access to your web
-host. The ability to create cron jobs on your web host is helpful but not
-required. You *don't* need to tweak any plain-text configuration files and you
-*don't* need shell access to your web host to make it work. (Although, I should
-point out, web hosts that *don't* offer shell access are *bad web hosts*.)
+configuration in mind. You'll need a working installation of WordPress (version
+[3.0] or later), and also FTP or SFTP access to your web host. The ability to
+create cron jobs on your web host is helpful but not required. You *don't* need
+to tweak any plain-text configuration files and you *don't* need shell access
+to your web host to make it work. (Although, I should point out, web hosts that
+*don't* offer shell access are *bad web hosts*.)
 
   [WordPress]: http://wordpress.org/
   [WordPress MU]: http://mu.wordpress.org/
@@ -94,8 +94,40 @@ outs, see the documentation at the [FeedWordPress project homepage][].
 
 == Changelog ==
 
-= 2014.0805 =
+= 2015.0514 =
+
+*	IMPORTANT SECURITY UPDATE: This version includes two important fixes for
+	potential security vulnerabilities reported to me through support channels.
+	
+	The first is a common problem across several plugins due to an ambiguity in
+	the WordPress documentation and a change in	the behavior of WordPress's
+	built-in add_query_arg() and remove_query_arg() functions
+	which could, under certain low-probability conditions, allow for potential
+	XSS attack vectors. This fixes issue # 39
+	reported at <https://github.com/radgeek/feedwordpress/issues/39>
+	Thanks to github.com/quassy
+	
+	The second is a security vulnerability fixes a security vulnerability that
+	was reported to me privately (thanks to Adrián M. F.) which, under other
+	low-probability conditions, could allow for SQL insertion attacks by
+	a malicious user with access to login credentials, which would compromise
+	data security.
+
+	It is *IMPORTANT* and worth your while to upgrade FeedWordPress as soon as
+	possible in order to eliminate these vulnerabilities. If you have any
+	questions or if there is something blocking you from making the upgrade
+	which you need my help with, don't hesitate to get in touch.
+
+*	ADMIN UI BUGFIX: "Update Now" button in feeds setting pages should now work
+	once again instead of causing a PHP fatal error. See
+	<https://github.com/radgeek/feedwordpress/issues/46>
+	
+*	SEVERAL OTHER SMALL BUG FIXES. See <https://github.com/radgeek/feedwordpress/issues/32>
+	<https://github.com/radgeek/feedwordpress/issues/30>
+	<https://github.com/radgeek/feedwordpress/issues/29>
+	etc.
 
+= 2014.0805 =
 
 *	FILTERS AND ADD-ONS: A number of new hooks for filters and add-ons to
 	further customize the behavior of FWP have been added.
diff --git a/wp-content/plugins/feedwordpress/syndicatedlink.class.php b/wp-content/plugins/feedwordpress/syndicatedlink.class.php
index b34de0c4b..f1d35a9ec 100644
--- a/wp-content/plugins/feedwordpress/syndicatedlink.class.php
+++ b/wp-content/plugins/feedwordpress/syndicatedlink.class.php
@@ -130,9 +130,9 @@ class SyndicatedLink {
 
 		$url = $this->uri(array('add_params' => true, 'fetch' => true));
 		FeedWordPress::diagnostic('updated_feeds', 'Polling feed ['.$url.']');
-
+	
 		$this->fetch();
-
+	
 		$new_count = NULL;
 
 		$resume = ('yes'==$this->setting('update/unfinished'));
@@ -178,6 +178,7 @@ class SyndicatedLink {
 			$this->save_settings(/*reload=*/ true);
 
 		elseif (is_object($this->simplepie)) :
+
 			// Success; clear out error setting, if any.
 			$this->update_setting('update/error', NULL);
 
@@ -285,7 +286,9 @@ class SyndicatedLink {
 							break;
 						endif;
 					endif;
+
 					unset($post);
+					
 				endforeach;
 			endif;
 
@@ -720,8 +723,13 @@ class SyndicatedLink {
 		'fetch' => false,
 		));
 
+		// Initialize $qp (= array for added query parameters, if any)
+		$qp = array();
+		
 		$link_rss = (is_object($this->link) ? $this->link->link_rss : NULL); 
-
+		
+		// $link_rss stores the URI for the subscription as stored in the feed's record.
+		// $uri stores the effective URI of the request including any/all added query parameters 
 		$uri = $link_rss;
 		if (!is_null($uri) and strlen($uri) > 0 and $params['add_params']) :
 			$qp = maybe_unserialize($this->setting('query parameters', array()));
@@ -729,6 +737,7 @@ class SyndicatedLink {
 			// For high-tech HTTP feed request kung fu
 			$qp = apply_filters('syndicated_feed_parameters', $qp, $uri, $this);
 
+			// $qp is an array of key-value pairs stored as arrays of format [$key, $value]
 			$q = array();
 			if (is_array($qp) and count($qp) > 0) :
 				foreach ($qp as $pair) :
diff --git a/wp-content/plugins/feedwordpress/syndicatedpost.class.php b/wp-content/plugins/feedwordpress/syndicatedpost.class.php
index e713b76fb..f8fba139c 100644
--- a/wp-content/plugins/feedwordpress/syndicatedpost.class.php
+++ b/wp-content/plugins/feedwordpress/syndicatedpost.class.php
@@ -117,6 +117,7 @@ class SyndicatedPost {
 		if (is_null($this->item)) :
 			$this->post = NULL;
 		else :
+
 			# Note that nothing is run through esc_sql() here.
 			# That's deliberate. The escaping is done at the point
 			# of insertion, not here, to avoid double-escaping and
@@ -127,6 +128,7 @@ class SyndicatedPost {
 				$this->entry->get_title(), $this
 			);
 
+
 			$this->named['author'] = apply_filters(
 				'syndicated_item_author',
 				$this->author(), $this
@@ -134,7 +136,7 @@ class SyndicatedPost {
 			// This just gives us an alphanumeric name for the author.
 			// We look up (or create) the numeric ID for the author
 			// in SyndicatedPost::add().
-			
+
 			$this->post['post_content'] = apply_filters(
 				'syndicated_item_content',
 				$this->content(), $this
@@ -348,6 +350,7 @@ class SyndicatedPost {
 
 			$this->post['post_type'] = apply_filters('syndicated_post_type', $this->link->setting('syndicated post type', 'syndicated_post_type', 'post'), $this);
 		endif;
+		
 	} /* SyndicatedPost::SyndicatedPost() */
 
 	#####################################
@@ -589,6 +592,7 @@ class SyndicatedPost {
 	} /* SyndicatedPost::title () */
 	
 	function content ($params = array()) {
+
 		$params = wp_parse_args($params, array(
 		"full only" => false, 
 		));
@@ -635,6 +639,7 @@ class SyndicatedPost {
 			endif;
 			
 		endif;
+		
 		return $content;
 	} /* SyndicatedPost::content() */
 
@@ -1213,6 +1218,7 @@ class SyndicatedPost {
 	function resolve_single_relative_uri ($refs) {
 		$tag = FeedWordPressHTML::attributeMatch($refs);
 		$url = SimplePie_Misc::absolutize_url($tag['value'], $this->_base);
+
 		return $tag['prefix'] . $url . $tag['suffix'];
 	} /* function SyndicatedPost::resolve_single_relative_uri() */
 
@@ -1233,11 +1239,17 @@ class SyndicatedPost {
 			foreach ($obj->uri_attrs as $pair) :
 				list($tag, $attr) = $pair;
 				$pattern = FeedWordPressHTML::attributeRegex($tag, $attr);
+
+				// FIXME: Encountered issue while testing an extremely long (= 88827 characters) item
+				// Relying on preg_replace_callback() here can cause a PHP seg fault on my development
+				// server. preg_match_all() causes a similar problem. Apparently this is a PCRE issue
+				// Cf. discussion of similar issue <https://bugs.php.net/bug.php?id=65009>
 				$content = preg_replace_callback (
 					$pattern,
 					array($obj, 'resolve_single_relative_uri'),
 					$content
 				);
+
 			endforeach;
 		endif;
 
-- 
GitLab