Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/woo-product-filter/classes/controller.php
+++ b/woo-product-filter/classes/controller.php
@@ -1,4 +1,14 @@
<?php
+/**
+ * Product Filter by WBW - ControllerWpf Class
+ *
+ * @version 3.1.3
+ *
+ * @author woobewoo
+ */
+
+defined( 'ABSPATH' ) || exit;
+
abstract class ControllerWpf {
protected $_models = array();
protected $_views = array();
@@ -58,7 +68,7 @@
//if (importWpf($parentModule->getModDir() . 'models' . DS . $name . '.php')) {
$className = toeGetClassNameWpf($name . 'Model');
}
-
+
if ($className) {
$model = new $className();
$model->setCode( $this->getCode() );
@@ -77,7 +87,7 @@
//if (importWpf($parentModule->getModDir() . 'views' . DS . $name . '.php')) {
$className = toeGetClassNameWpf($name . 'View');
}
-
+
if ($className) {
$view = new $className();
$view->setCode( $this->getCode() );
@@ -94,7 +104,21 @@
$view->display();
}
}
+
+ /**
+ * Magic method: __call
+ *
+ * @version 3.1.3
+ *
+ * @param $name
+ * @param $arguments
+ */
public function __call( $name, $arguments ) {
+ $blockedMethods = array( 'delete', 'clear', 'removeGroup' );
+ if ( in_array( $name, $blockedMethods, true ) ) {
+ return false;
+ }
+
$model = $this->getModel();
if (method_exists($model, $name)) {
return $model->$name($arguments[0]);
@@ -216,7 +240,7 @@
if (!current_user_can('manage_options')) {
wp_die();
}
-
+
$res = new ResponseWpf();
if ($this->getModel()->removeGroup(ReqWpf::getVar('listIds', 'post'))) {
$res->addMessage(esc_html__('Done', 'woo-product-filter'));
--- a/woo-product-filter/classes/frame.php
+++ b/woo-product-filter/classes/frame.php
@@ -2,7 +2,7 @@
/**
* Product Filter by WBW - FrameWpf Class
*
- * @version 3.0.4
+ * @version 3.1.3
*
* @author woobewoo
*/
@@ -256,7 +256,7 @@
/**
* Check permissions for action in controller by $code and made corresponding action.
*
- * @version 3.0.4
+ * @version 3.1.3
*
* @param string $code Code of controller that need to be checked
* @param string $action Action that need to be checked
@@ -266,41 +266,43 @@
if ($this->havePermissions($code, $action)) {
return true;
} else {
- exit(esc_html__('You have no permissions to view this page', 'woo-product-filter'));
+ wp_send_json_error(
+ array( 'message' => esc_html__( 'You have no permissions to view this page', 'woo-product-filter' ) ),
+ 403
+ );
}
}
/**
* Check permissions for action in controller by $code.
*
+ * @version 3.1.3
+ *
* @param string $code Code of controller that need to be checked
* @param string $action Action that need to be checked
* @return bool true if ok, else - false
*/
public function havePermissions( $code, $action ) {
- $res = true;
+ $res = false;
$mod = $this->getModule($code);
$action = strtolower($action);
if ($mod) {
$permissions = $mod->getController()->getPermissions();
if (!empty($permissions)) { // Special permissions
if (isset($permissions[WPF_METHODS]) && !empty($permissions[WPF_METHODS])) {
- foreach ($permissions[WPF_METHODS] as $method => $permissions) { // Make case-insensitive
- $permissions[WPF_METHODS][strtolower($method)] = $permissions;
+ foreach ($permissions[WPF_METHODS] as $method => $permission) { // Make case-insensitive
+ $permissions[WPF_METHODS][strtolower($method)] = $permission;
}
if (array_key_exists($action, $permissions[WPF_METHODS])) { // Permission for this method exists
$currentUserPosition = self::_()->getModule('user')->getCurrentUserPosition();
if (
+ is_array($permissions[ WPF_METHODS ][ $action ] ) &&
(
- is_array($permissions[ WPF_METHODS ][ $action ] ) &&
- !in_array($currentUserPosition, $permissions[ WPF_METHODS ][ $action ])
- ) ||
- (
- !is_array($permissions[ WPF_METHODS ][ $action ]) &&
- $permissions[WPF_METHODS][$action] != $currentUserPosition
+ in_array($currentUserPosition, $permissions[ WPF_METHODS ][ $action ]) ||
+ $permissions[WPF_METHODS][$action] === $currentUserPosition
)
) {
- $res = false;
+ $res = true;
}
}
}
@@ -314,16 +316,16 @@
if (is_array($methods)) {
$lowerMethods = array_map('strtolower', $methods); // Make case-insensitive
if (in_array($action, $lowerMethods)) { // Permission for this method exists
- if ($currentUserPosition != $userlevel) {
- $res = false;
+ if ($currentUserPosition === $userlevel) {
+ $res = true;
}
break;
}
} else {
$lowerMethod = strtolower($methods); // Make case-insensitive
if ($lowerMethod == $action) { // Permission for this method exists
- if ($currentUserPosition != $userlevel) {
- $res = false;
+ if ($currentUserPosition === $userlevel) {
+ $res = true;
}
break;
}
@@ -406,14 +408,19 @@
/**
* _doExec.
+ *
+ * @version 3.1.3
*/
protected function _doExec() {
$mod = $this->getModule($this->_mod);
if ($mod && $this->checkPermissions($this->_mod, $this->_action)) {
switch (ReqWpf::getVar('reqType')) {
case 'ajax':
- add_action('wp_ajax_' . $this->_action, array($mod->getController(), $this->_action));
- add_action('wp_ajax_nopriv_' . $this->_action, array($mod->getController(), $this->_action));
+ add_action('wp_ajax_' . $this->_action, array($mod->getController(), $this->_action));
+ $noprivActions = array( 'filtersFrontend', 'getTaxonomyTerms' );
+ if ( in_array( $this->_action, $noprivActions ) ) {
+ add_action('wp_ajax_nopriv_' . $this->_action, array($mod->getController(), $this->_action));
+ }
break;
default:
$this->_res = $mod->exec($this->_action);
--- a/woo-product-filter/classes/modInstaller.php
+++ b/woo-product-filter/classes/modInstaller.php
@@ -1,16 +1,40 @@
<?php
+/**
+ * Product Filter by WBW - ModInstallerWpf Class
+ *
+ * Handles the installation, activation, deactivation, and management of modules for the plugin.
+ *
+ * @version 3.1.3
+ *
+ * @author woobewoo
+ */
+
+defined( 'ABSPATH' ) || exit;
+
class ModInstallerWpf {
+
+ /**
+ * _current.
+ */
private static $_current = array();
+
+ /**
+ * extPlugName.
+ */
private static $extPlugName = '';
+
/**
- * Install new ModuleWpf into plugin
+ * Install new ModuleWpf into plugin.
+ *
+ * @version 3.1.3
*
* @param string $module new ModuleWpf data (@see classes/tables/modules.php)
* @param string $path path to the main plugin file from what module is installed
* @return bool true - if install success, else - false
*/
public static function install( $module, $path ) {
- $exPlugDest = explode('plugins', $path);
+ $plugin_dir = basename( untrailingslashit( WP_PLUGIN_DIR ) );
+ $exPlugDest = explode( $plugin_dir, $path );
if (!empty($exPlugDest[1])) {
$module['ex_plug_dir'] = str_replace(DS, '', $exPlugDest[1]);
}
@@ -21,7 +45,7 @@
if (empty($module['ex_plug_dir'])) {
$filesMoved = self::moveFiles($module['code'], $path);
} else {
- $filesMoved = true; //Those modules doesn't need to move their files
+ $filesMoved = true; // Those modules doesn't need to move their files
}
if ($filesMoved) {
if (FrameWpf::_()->getTable('modules')->exists($module['code'], 'code')) {
@@ -45,6 +69,10 @@
}
return false;
}
+
+ /**
+ * _runModuleInstall.
+ */
protected static function _runModuleInstall( $module, $action = 'install' ) {
$moduleLocationDir = WPF_MODULES_DIR;
if (!empty($module['ex_plug_dir'])) {
@@ -52,7 +80,6 @@
}
if (is_dir($moduleLocationDir . $module['code'])) {
if (!class_exists($module['code'] . strFirstUpWpf(WPF_CODE))) {
- //importClassWpf($module['code'] . strFirstUpWpf(WPF_CODE), $moduleLocationDir . $module['code'] . DS . 'mod.php');
if (file_exists($moduleLocationDir . $module['code'] . DS . 'mod.php')) {
require $moduleLocationDir . $module['code'] . DS . 'mod.php';
}
@@ -64,8 +91,9 @@
}
}
}
+
/**
- * Check whether is or no module in given path
+ * Check whether is or no module in given path.
*
* @param string $path path to the module
* @return bool true if it is module, else - false
@@ -73,8 +101,9 @@
public static function isModule( $path ) {
return true;
}
+
/**
- * Move files to plugin modules directory
+ * Move files to plugin modules directory.
*
* @param string $code code for module
* @param string $path path from what module will be moved
@@ -93,13 +122,17 @@
}
return false;
}
+
+ /**
+ * _getPluginLocations.
+ */
private static function _getPluginLocations() {
$locations = array();
$plug = ReqWpf::getVar('plugin');
if ( ( empty( $plug ) || is_array($plug) ) && !empty(self::$extPlugName) ) {
$plug = self::$extPlugName;
}
-
+
if ( empty( $plug ) ) {
$plug = ReqWpf::getVar( 'checked' );
if ( isset( $plug[0] ) ) {
@@ -119,7 +152,7 @@
}
/**
- * Try to parse xml file with module data
+ * Try to parse xml file with module data.
*
* @param string $xmlPath
*
@@ -155,8 +188,9 @@
}
return $modDataArr;
}
+
/**
- * Check whether modules is installed or not, if not and must be activated - install it
+ * Check whether modules is installed or not, if not and must be activated - install it.
*
* @param array $codes array with modules data to store in database
* @param string $path path to plugin file where modules is stored (__FILE__ for example)
@@ -174,10 +208,10 @@
$modules = self::_getModulesFromXml($locations['xmlPath']);
foreach ($modules as $modDataArr) {
if (!empty($modDataArr)) {
- //If module Exists - just activate it, we can't check this using FrameWpf::moduleExists because this will not work for multy-site WP
+ // If module Exists - just activate it, we can't check this using FrameWpf::moduleExists because this will not work for multi-site WP
if (FrameWpf::_()->getTable('modules')->exists($modDataArr['code'], 'code')) {
self::activate($modDataArr);
- // if not - install it
+ // if not - install it
} else {
$m = '';
if (!self::install($modDataArr, $locations['plugDir'])) {
@@ -195,14 +229,16 @@
update_option(WPF_CODE . '_full_installed', 1);
return true;
}
+
/**
- * Public alias for _getCheckRegPlugs()
- * We will run this each time plugin start to check modules activation messages
+ * Public alias for _getCheckRegPlugs().
+ * We will run this each time plugin start to check modules activation messages.
*/
public static function checkActivationMessages() {
}
+
/**
- * Deactivate module after deactivating external plugin
+ * Deactivate module after deactivating external plugin.
*/
public static function deactivate( $exclude = array() ) {
$locations = self::_getPluginLocations();
@@ -212,7 +248,7 @@
}
foreach ($modules as $modDataArr) {
- if (FrameWpf::_()->moduleActive($modDataArr['code']) && !in_array($modDataArr['code'], $exclude)) { //If module is active - then deacivate it
+ if (FrameWpf::_()->moduleActive($modDataArr['code']) && !in_array($modDataArr['code'], $exclude)) { // If module is active - then deactivate it
if (FrameWpf::_()->getModule('options')->getModel('modules')->put(array(
'id' => FrameWpf::_()->getModule($modDataArr['code'])->getID(),
'active' => 0,
@@ -228,11 +264,15 @@
}
return true;
}
+
+ /**
+ * activate.
+ */
public static function activate( $modDataArr ) {
$locations = self::_getPluginLocations();
$modules = self::_getModulesFromXml($locations['xmlPath']);
foreach ($modules as $modDataArr) {
- if (!FrameWpf::_()->moduleActive($modDataArr['code'])) { //If module is not active - then acivate it
+ if (!FrameWpf::_()->moduleActive($modDataArr['code'])) { // If module is not active - then activate it
if (FrameWpf::_()->getModule('options')->getModel('modules')->put(array(
'code' => $modDataArr['code'],
'active' => 1,
@@ -247,9 +287,10 @@
}
}
}
- }
+ }
+
/**
- * Display all errors for module installer, must be used ONLY if You realy need it
+ * Display all errors for module installer, must be used ONLY if You really need it.
*/
public static function displayErrors( $exit = true ) {
$errors = ErrorsWpf::get(ErrorsWpf::MOD_INSTALL);
@@ -260,6 +301,10 @@
exit();
}
}
+
+ /**
+ * uninstall.
+ */
public static function uninstall() {
$isPro = false;
$locations = self::_getPluginLocations();
@@ -278,9 +323,17 @@
self::uninstallLicense();
}
}
+
+ /**
+ * uninstallLicense.
+ */
public static function uninstallLicense() {
FrameWpf::_()->getModule('options')->getModel()->save('license_save_name', '');
}
+
+ /**
+ * _uninstallTables.
+ */
protected static function _uninstallTables( $module ) {
if (is_dir(WPF_MODULES_DIR . $module['code'] . DS . 'tables')) {
$tableFiles = UtilsWpf::getFilesList(WPF_MODULES_DIR . $module['code'] . DS . 'tables');
@@ -294,8 +347,12 @@
}
}
}
+
+ /**
+ * _installTables.
+ */
public static function _installTables( $module, $action = 'install' ) {
- $modDir = empty($module['ex_plug_dir']) ? WPF_MODULES_DIR . $module['code'] . DS : UtilsWpf::getPluginDir($module['ex_plug_dir']) . $module['code'] . DS;
+ $modDir = empty($module['ex_plug_dir']) ? WPF_MODULES_DIR . $module['code'] . DS : UtilsWpf::getPluginDir($module['ex_plug_dir']) . $module['code'] . DS;
if (is_dir($modDir . 'tables')) {
$tableFiles = UtilsWpf::getFilesList($modDir . 'tables');
if (!empty($tableFiles)) {
--- a/woo-product-filter/config.php
+++ b/woo-product-filter/config.php
@@ -62,7 +62,7 @@
define('WPF_EOL', "n");
define('WPF_PLUGIN_INSTALLED', true);
-define('WPF_VERSION', '3.1.2');
+define('WPF_VERSION', '3.1.3');
define('WPF_PRO_REQUIRES', '2.0.0');
define('WPF_USER', 'user');
--- a/woo-product-filter/modules/meta/controller.php
+++ b/woo-product-filter/modules/meta/controller.php
@@ -1,8 +1,18 @@
<?php
+/**
+ * Product Filter by WBW - MetaControllerWpf Class
+ *
+ * @version 3.1.3
+ *
+ * @author woobewoo
+ */
+
+defined( 'ABSPATH' ) || exit;
+
class MetaControllerWpf extends ControllerWpf {
protected $_code = 'meta';
-
+
public function doMetaIndexingFree() {
return $this->doMetaIndexing(false);
}
@@ -46,4 +56,22 @@
}
return $res->ajaxExec();
}
+
+ /**
+ * getPermissions.
+ *
+ * @version 3.1.3
+ * @since 3.1.3
+ *
+ * @return array
+ */
+ public function getPermissions() {
+ return array(
+ WPF_USERLEVELS => array(
+ WPF_ADMIN => array(
+ 'doMetaIndexingFree', 'doMetaIndexing', 'doMetaOptimizing',
+ )
+ ),
+ );
+ }
}
--- a/woo-product-filter/modules/woofilters/controller.php
+++ b/woo-product-filter/modules/woofilters/controller.php
@@ -2,7 +2,7 @@
/**
* Product Filter by WBW - WoofiltersControllerWpf Class
*
- * @version 3.1.1
+ * @version 3.1.3
*
* @author woobewoo
*/
@@ -1151,4 +1151,39 @@
return $args;
}
+
+ /**
+ * getPermissions.
+ *
+ * @version 3.1.3
+ * @since 3.1.3
+ *
+ * @return array
+ */
+ public function getPermissions() {
+ return array(
+ WPF_METHODS => array(
+ 'getListForTbl' => array(
+ WPF_ADMIN
+ ),
+ 'save' => array(
+ WPF_ADMIN
+ ),
+ 'removeGroup' => array(
+ WPF_ADMIN
+ ),
+ 'deleteByID' => array(
+ WPF_ADMIN
+ ),
+ 'drawFilterAjax' => array(
+ WPF_ADMIN
+ ),
+ 'filtersFrontend' => array(
+ WPF_GUEST,
+ WPF_ADMIN,
+ WPF_LOGGED
+ ),
+ ),
+ );
+ }
}
--- a/woo-product-filter/modules/woofilters/mod.php
+++ b/woo-product-filter/modules/woofilters/mod.php
@@ -2,7 +2,7 @@
/**
* Product Filter by WBW - WoofiltersWpf Class
*
- * @version 3.0.2
+ * @version 3.1.3
*
* @author woobewoo
*/
@@ -4012,7 +4012,7 @@
/**
* Returns items in filter blocks.
*
- * @version 2.9.4
+ * @version 3.1.3
*
* @param $filterLoop
* @param $param
@@ -4066,7 +4066,9 @@
if ( ! empty( $taxonomyList ) ) {
$addSqls['main']['withCount'] = $param['withCount'];
$addSqls['main']['fields'] = ( $param['withCount'] ? '' : 'DISTINCT ' ) . 'tr.term_taxonomy_id, tt.term_id, tt.taxonomy, tt.parent' . ( $param['withCount'] ? ', COUNT(*) as cnt' : '' );
- $addSqls['main']['taxonomyList'] = implode( "', '", $taxonomyList );
+
+ $taxonomyListFormatter = implode( ',', array_fill( 0, count( $taxonomyList ), '%s' ) );
+ $addSqls['main']['taxonomyList'] = $wpdb->prepare( $taxonomyListFormatter, ...$taxonomyList );
if ( $byVariations ) {
$attrTaxonomyList = array();
@@ -4137,7 +4139,7 @@
$sql[ $key ] .= ' INNER JOIN ' . $wpdb->terms . ' ttt ON (ttt.term_id=tt.term_id) ' . $typeJoin;
}
- $sql[ $key ] .= ' WHERE tt.taxonomy IN ('' . $addSql['taxonomyList'] . '')';
+ $sql[ $key ] .= ' WHERE tt.taxonomy IN ( ' . $addSql['taxonomyList'] . ' )';
if ( $byVariations ) {
$sql[ $key ] .= ' AND (md_type.val_id!=' . $variableMetaId .
--- a/woo-product-filter/woo-product-filter.php
+++ b/woo-product-filter/woo-product-filter.php
@@ -3,14 +3,14 @@
* Plugin Name: Product Filter for WooCommerce by WBW
* Plugin URI: https://woobewoo.com/product/woocommerce-filter/
* Description: Filter products in your store in most efficient way
- * Version: 3.1.2
+ * Version: 3.1.3
* Author: woobewoo
* Author URI: https://woobewoo.com/
* Requires at least: 3.4.0
* Text Domain: woo-product-filter
* Domain Path: /languages
* WC requires at least: 3.4.1
- * WC tested up to: 10.5
+ * WC tested up to: 10.6
* Requires Plugins: woocommerce
**/