Skip to content

Commit

Permalink
Switch to less extensive escaping of HTML attributes (vufind-org#4009)
Browse files Browse the repository at this point in the history
The old extended style can still be enabled via configuration.
  • Loading branch information
EreMaijala authored Oct 15, 2024
1 parent 6648420 commit 79f75f4
Show file tree
Hide file tree
Showing 11 changed files with 328 additions and 29 deletions.
6 changes: 6 additions & 0 deletions config/vufind/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ allowSavedSearches = true
nonJavascriptSupportEnabled = false
; Generator value to display in an HTML header <meta> tag:
generator = "VuFind 10.1"
; The following setting can be set to true in case extended HTML attribute
; escaping is needed. Default is false. Extended escaping is slower and
; results in larger HTML responses than normal escaping, so this setting
; should normally be left disabled, but must be enabled if there are unquoted
; HTML attributes in local templates.
;extendedHtmlAttributeEscaping = false

; This section allows you to configure the mechanism used for storing user
; sessions. Available types: File, Memcache, Database, Redis.
Expand Down
10 changes: 7 additions & 3 deletions module/VuFind/config/module.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@
'VuFind\Db\Table\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory',
'VuFind\DigitalContent\OverdriveConnector' => 'VuFind\DigitalContent\OverdriveConnectorFactory',
'VuFind\DoiLinker\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory',
'VuFind\Escaper\Escaper' => 'VuFind\Escaper\EscaperFactory',
'VuFind\Export' => 'VuFind\ExportFactory',
'VuFind\Favorites\FavoritesService' => 'VuFind\Favorites\FavoritesServiceFactory',
'VuFind\Form\Form' => 'VuFind\Form\FormFactory',
Expand Down Expand Up @@ -542,8 +543,6 @@
'VuFind\ServiceManager\ServiceInitializer',
],
'aliases' => [
'League\CommonMark\MarkdownConverterInterface' => 'League\CommonMark\ConverterInterface',
'Request' => 'VuFind\Http\PhpEnvironment\Request',
'VuFind\AccountCapabilities' => 'VuFind\Config\AccountCapabilities',
'VuFind\AuthManager' => 'VuFind\Auth\Manager',
'VuFind\AuthPluginManager' => 'VuFind\Auth\PluginManager',
Expand Down Expand Up @@ -602,9 +601,14 @@
'VuFind\Tags' => 'VuFind\Tags\TagsService',
'VuFind\Translator' => 'Laminas\Mvc\I18n\Translator',
'VuFind\YamlReader' => 'VuFind\Config\YamlReader',
'Laminas\Validator\Csrf' => 'VuFind\Validator\SessionCsrf',
'VuFind\Validator\Csrf' => 'VuFind\Validator\SessionCsrf',
'VuFind\Validator\CsrfInterface' => 'VuFind\Validator\SessionCsrf',

// Overrides:
'Laminas\Escaper\Escaper' => 'VuFind\Escaper\Escaper',
'Laminas\Validator\Csrf' => 'VuFind\Validator\SessionCsrf',
'League\CommonMark\MarkdownConverterInterface' => 'League\CommonMark\ConverterInterface',
'Request' => 'VuFind\Http\PhpEnvironment\Request',
],
'shared' => [
'VuFind\Form\Form' => false,
Expand Down
66 changes: 66 additions & 0 deletions module/VuFind/src/VuFind/Escaper/Escaper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

/**
* Escaper with configurable HTML attribute handling.
*
* PHP version 8
*
* Copyright (C) The National Library of Finland 2024.
*
* 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 Escaper
* @author Ere Maijala <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/

namespace VuFind\Escaper;

/**
* Escaper with configurable HTML attribute handling.
*
* @category VuFind
* @package Escaper
* @author Ere Maijala <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/
class Escaper extends \Laminas\Escaper\Escaper
{
/**
* Constructor
*
* @param bool $extendedHtmlAttrEscaping Use Laminas' extended HTML attribute escaping?
*/
public function __construct(protected bool $extendedHtmlAttrEscaping = false)
{
parent::__construct();
}

/**
* Escape a string for the HTML Attribute context.
*
* @param string $string String to escape
*
* @return string
*/
public function escapeHtmlAttr(string $string)
{
return $this->extendedHtmlAttrEscaping
? parent::escapeHtmlAttr($string)
: parent::escapeHtml($string);
}
}
74 changes: 74 additions & 0 deletions module/VuFind/src/VuFind/Escaper/EscaperFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

/**
* Escaper factory.
*
* PHP version 8
*
* Copyright (C) The National Library of Finland 2024.
*
* 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 Escaper
* @author Ere Maijala <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/

namespace VuFind\Escaper;

use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Psr\Container\ContainerExceptionInterface as ContainerException;
use Psr\Container\ContainerInterface;

/**
* Escaper helper factory.
*
* @category VuFind
* @package Escaper
* @author Ere Maijala <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/
class EscaperFactory implements FactoryInterface
{
/**
* Create an object
*
* @param ContainerInterface $container Service manager
* @param string $requestedName Service being created
* @param null|array $options Extra options (optional)
*
* @return object
*
* @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when
* creating a service.
* @throws ContainerException&\Throwable if any other error occurs
*/
public function __invoke(
ContainerInterface $container,
$requestedName,
array $options = null
) {
if (!empty($options)) {
throw new \Exception('Unexpected options sent to factory.');
}
$config = $container->get(\VuFind\Config\PluginManager::class)->get('config');
return new $requestedName((bool)($config->Site->extendedHtmlAttributeEscaping ?? false));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

/**
* EscapeHtmlAttr helper factory.
*
* PHP version 8
*
* Copyright (C) The National Library of Finland 2024.
*
* 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 View_Helpers
* @author Ere Maijala <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/

namespace VuFind\View\Helper\Root;

use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Psr\Container\ContainerExceptionInterface as ContainerException;
use Psr\Container\ContainerInterface;

/**
* EscapeHtmlAttr helper factory.
*
* @category VuFind
* @package View_Helpers
* @author Ere Maijala <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/
class EscapeHtmlAttrFactory implements FactoryInterface
{
/**
* Create an object
*
* @param ContainerInterface $container Service manager
* @param string $requestedName Service being created
* @param null|array $options Extra options (optional)
*
* @return object
*
* @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when
* creating a service.
* @throws ContainerException&\Throwable if any other error occurs
*/
public function __invoke(
ContainerInterface $container,
$requestedName,
array $options = null
) {
if (!empty($options)) {
throw new \Exception('Unexpected options sent to factory.');
}
return new $requestedName($container->get(\VuFind\Escaper\Escaper::class));
}
}
62 changes: 62 additions & 0 deletions module/VuFind/src/VuFind/View/Helper/Root/HelperInitializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/**
* View Helper Initializer
*
* PHP version 8
*
* Copyright (C) The National Library of Finland 2024.
*
* 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 View_Helpers
* @author Ere Maijala <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/

namespace VuFind\View\Helper\Root;

use Laminas\ServiceManager\Initializer\InitializerInterface;
use Laminas\View\Helper\Placeholder\Container\AbstractStandalone;
use Psr\Container\ContainerInterface;

/**
* View Helper Initializer
*
* @category VuFind
* @package View_Helpers
* @author Ere Maijala <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/
class HelperInitializer implements InitializerInterface
{
/**
* Given an instance and a Service Manager, initialize the instance.
*
* @param ContainerInterface $container Service manager
* @param object $instance Instance to initialize
*
* @return object
*/
public function __invoke(ContainerInterface $container, $instance)
{
if ($instance instanceof AbstractStandalone) {
$instance->setEscaper($container->get(\VuFind\Escaper\Escaper::class));
}
return $instance;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected function getViewWithHelpers()
{
$helpers = [
'escapehtml' => new \Laminas\View\Helper\EscapeHtml(),
'escapehtmlattr' => new \Laminas\View\Helper\EscapeHtmlAttr(),
'escapehtmlattr' => new \Laminas\View\Helper\EscapeHtmlAttr(new \VuFind\Escaper\Escaper()),
'htmlattributes' => new \Laminas\View\Helper\HtmlAttributes(),
'maketag' => new \VuFind\View\Helper\Root\MakeTag(),
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
namespace VuFindTest\View\Helper\Root;

use Laminas\View\Helper\EscapeHtmlAttr;
use Laminas\View\Helper\Layout;
use Laminas\View\Helper\ServerUrl;
use Laminas\View\Renderer\PhpRenderer;
use Symfony\Component\Yaml\Yaml;
Expand Down Expand Up @@ -213,7 +212,7 @@ public function __invoke($template = null)
};

$plugins = [
'escapeHtmlAttr' => new EscapeHtmlAttr(),
'escapeHtmlAttr' => new EscapeHtmlAttr(new \VuFind\Escaper\Escaper()),
'layout' => $layout,
'serverUrl' => $serverUrl,
'url' => $url,
Expand Down
Loading

0 comments on commit 79f75f4

Please sign in to comment.