From 322cbd7f00c923d92ddae6e9aada13e4ea37ff42 Mon Sep 17 00:00:00 2001
From: Ere Maijala <ere.maijala@helsinki.fi>
Date: Wed, 11 Dec 2019 23:16:16 +0200
Subject: [PATCH] Add filtering of invalid request parameters. (#1518)

---
 module/VuFind/config/module.config.php        |   5 +
 .../src/VuFind/Controller/AbstractBase.php    |  15 ++
 .../VuFind/Http/PhpEnvironment/Request.php    | 135 ++++++++++++++++++
 3 files changed, 155 insertions(+)
 create mode 100644 module/VuFind/src/VuFind/Http/PhpEnvironment/Request.php

diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index 04f5f89af4b..4e976ef563d 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -383,6 +383,7 @@ $config = [
             'VuFind\Hierarchy\TreeDataFormatter\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory',
             'VuFind\Hierarchy\TreeDataSource\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory',
             'VuFind\Hierarchy\TreeRenderer\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory',
+            'VuFind\Http\PhpEnvironment\Request' => 'Zend\ServiceManager\Factory\InvokableFactory',
             'VuFind\ILS\Connection' => 'VuFind\ILS\ConnectionFactory',
             'VuFind\ILS\Driver\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory',
             'VuFind\ILS\Logic\Holds' => 'VuFind\ILS\Logic\LogicFactory',
@@ -431,10 +432,14 @@ $config = [
             'Zend\Mvc\I18n\Translator' => 'VuFind\I18n\Translator\TranslatorFactory',
             'Zend\Session\SessionManager' => 'VuFind\Session\ManagerFactory',
         ],
+        'delegators' => [
+            'VuFind\Http\PhpEnvironment\Request' => [ \Zend\Mvc\Console\Service\ConsoleRequestDelegatorFactory::class ],
+        ],
         'initializers' => [
             'VuFind\ServiceManager\ServiceInitializer',
         ],
         'aliases' => [
+            'Request' => 'VuFind\Http\PhpEnvironment\Request',
             'VuFind\AccountCapabilities' => 'VuFind\Config\AccountCapabilities',
             'VuFind\AuthManager' => 'VuFind\Auth\Manager',
             'VuFind\AuthPluginManager' => 'VuFind\Auth\PluginManager',
diff --git a/module/VuFind/src/VuFind/Controller/AbstractBase.php b/module/VuFind/src/VuFind/Controller/AbstractBase.php
index 454af22f3ed..be564d5ab89 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractBase.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractBase.php
@@ -30,6 +30,7 @@ namespace VuFind\Controller;
 
 use VuFind\Exception\Auth as AuthException;
 use VuFind\Exception\ILS as ILSException;
+use VuFind\Http\PhpEnvironment\Request as HttpRequest;
 use Zend\Mvc\Controller\AbstractActionController;
 use Zend\Mvc\MvcEvent;
 use Zend\ServiceManager\ServiceLocatorInterface;
@@ -130,6 +131,20 @@ class AbstractBase extends AbstractActionController
         $this->accessPermission = empty($ap) ? false : $ap;
     }
 
+    /**
+     * Get request object
+     *
+     * @return HttpRequest
+     */
+    public function getRequest()
+    {
+        if (!$this->request) {
+            $this->request = new HttpRequest();
+        }
+
+        return $this->request;
+    }
+
     /**
      * Register the default events for this controller
      *
diff --git a/module/VuFind/src/VuFind/Http/PhpEnvironment/Request.php b/module/VuFind/src/VuFind/Http/PhpEnvironment/Request.php
new file mode 100644
index 00000000000..752ff1fcce1
--- /dev/null
+++ b/module/VuFind/src/VuFind/Http/PhpEnvironment/Request.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * HTTP Request class
+ *
+ * PHP version 7
+ *
+ * Copyright (C) The National Library of Finland 2019.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  HTTP
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\Http\PhpEnvironment;
+
+/**
+ * HTTP Request class
+ *
+ * @category VuFind
+ * @package  HTTP
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class Request extends \Zend\Http\PhpEnvironment\Request
+{
+    /**
+     * Return the parameter container responsible for query parameters or a single
+     * query parameter
+     *
+     * @param string|null $name    Parameter name to retrieve, or null to get the
+     * whole container.
+     * @param mixed|null  $default Default value to use when the parameter is
+     * missing.
+     *
+     * @return \Zend\Stdlib\ParametersInterface|mixed
+     */
+    public function getQuery($name = null, $default = null)
+    {
+        return $this->cleanup(parent::getQuery($name, $default));
+    }
+
+    /**
+     * Return the parameter container responsible for post parameters or a single
+     * post parameter.
+     *
+     * @param string|null $name    Parameter name to retrieve, or null to get the
+     * whole container.
+     * @param mixed|null  $default Default value to use when the parameter is
+     * missing.
+     *
+     * @return \Zend\Stdlib\ParametersInterface|mixed
+     */
+    public function getPost($name = null, $default = null)
+    {
+        return $this->cleanup(parent::getPost($name, $default));
+    }
+
+    /**
+     * Return the parameter container responsible for server parameters or a single
+     * parameter value.
+     *
+     * @param string|null $name    Parameter name to retrieve, or null to get the
+     * whole container.
+     * @param mixed|null  $default Default value to use when the parameter is
+     * missing.
+     *
+     * @see    http://www.faqs.org/rfcs/rfc3875.html
+     * @return \Zend\Stdlib\ParametersInterface|mixed
+     */
+    public function getServer($name = null, $default = null)
+    {
+        return $this->cleanup(parent::getServer($name, $default));
+    }
+
+    /**
+     * Clean up a parameter
+     *
+     * @param \Zend\Stdlib\ParametersInterface|mixed $param Parameter
+     *
+     * @return \Zend\Stdlib\ParametersInterface|mixed
+     */
+    protected function cleanup($param)
+    {
+        if (is_array($param) || $param instanceof \Zend\Stdlib\ParametersInterface) {
+            foreach ($param as $key => &$value) {
+                if (is_array($value)) {
+                    $value = $this->cleanup($value);
+                } elseif (!$this->isValid($key) || !$this->isValid($value)) {
+                    unset($param[$key]);
+                }
+            }
+            return $param;
+        }
+
+        if (is_string($param) && !$this->isValid($param)) {
+            return '';
+        }
+
+        return $param;
+    }
+
+    /**
+     * Check if a string is a valid parameter
+     *
+     * @param string $str String to check
+     *
+     * @return bool
+     */
+    protected function isValid($str)
+    {
+        // Check if the string is UTF-8
+        if (is_string($str) && $str !== '' && !preg_match('/^./su', $str)) {
+            return false;
+        }
+        if (strpos($str, "\x00") !== false) {
+            return false;
+        }
+        return true;
+    }
+}
-- 
GitLab