<?php /** * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; under version 2 * of the License (non-upgradable). * * 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. * * Copyright (c) 2008-2010 (original work) Deutsche Institut für Internationale Pädagogische Forschung (under the project TAO-TRANSFER); * 2009-2012 (update and modification) Public Research Centre Henri Tudor (under the project TAO-SUSTAIN & TAO-DEV); * 2013-2017 (update and modification) Open Assessment Technologies SA (under the project TAO-PRODUCT); * */ use oat\oatbox\service\ServiceManager; use oat\tao\model\service\ApplicationService; /** * Utility class focusing on display methods. * * @author Bertrand Chevrier, <bertrand.chevrier@tudor.lu> * @package tao */ class tao_helpers_Display { private static $replacement = '_'; /** * Enables you to cut a long string and end it with [...] and add an hover * to display the complete string on mouse over. * * @author Bertrand Chevrier, <bertrand.chevrier@tudor.lu> * @param string input The string input. * @param int maxLength (optional, default = 75) The maximum length for the result string. * @return string The cut string, enclosed in a <span> html tag. This tag received the 'cutted' CSS class. */ public static function textCutter($input, int $maxLength = 75): string { $encoding = self::getEncoding(); if (mb_strlen($input, $encoding) <= $maxLength) { return $input; } return "<span title='$input' class='cutted' style='cursor:pointer;'>" . mb_substr($input, 0, $maxLength, $encoding) . '[...]</span>'; } /** * Clean a text with a joker character to replace any characters that is not alphanumeric. * * @author Bertrand Chevrier, <bertrand.chevrier@tudor.lu> * @param string input The string input. * @param string joker (optional, default = '_') A joker character that will be the alphanumeric placeholder. * @param int maxLength (optional, default = -1) output maximum length * @return string The result string. */ public static function textCleaner($input, string $joker = '_', int $maxLength = -1): string { $encoding = self::getEncoding(); if ($maxLength > -1) { $input = mb_substr($input, 0, $maxLength, $encoding); } $replacingPattern = strpos($encoding, 'UTF') === 0 ? '/[^\p{L}0-9-_]+/u' : '/[^a-z0-9-_]+/ui'; $patternMaps = [ '/\s+/u' => [self::class, 'replaceWithUnderscore'], $replacingPattern => [self::class, 'replace'], ]; self::$replacement = $joker; return preg_replace_callback_array($patternMaps, $input); } /** * Display clean and more secure text into an HTML page. The implementation * of this method is done with htmlentities.This method is Unicode safe. * * @author Bertrand Chevrier, <bertrand.chevrier@tudor.lu> * @param string input The input string. * @return string The htmlized string. */ public static function htmlize($input): string { return htmlentities($input, ENT_COMPAT, self::getEncoding()); } /** * Convert special characters to HTML entities */ public static function htmlEscape($string): string { return htmlspecialchars($string); } /** * Encode the value of an html attribute * * @param string $string * @return string */ public static function encodeAttrValue($string): string { return htmlspecialchars($string, ENT_QUOTES, 'UTF-8'); } /** * Sanitize all parts that could be used in XSS (script, style, hijacked links, etc.) * and update some attributes to use a safe behavior. * * @see http://htmlpurifier.org/live/configdoc/plain.html * * @param string $input the input HTML * @return string the sanitized HTML */ public static function sanitizeXssHtml($input): string { $config = HTMLPurifier_Config::createDefault(); //we don't use HTMLPurifier cache //because it writes serialized files inside it's own folder //so this won't work in a multi server env $config->set('Cache.DefinitionImpl', null); //allow target=_blank on links $config->set('Attr.AllowedFrameTargets', ['_blank']); $purifier = new HTMLPurifier($config); return $purifier->purify($input); } /** @noinspection PhpUnusedPrivateMethodInspection */ private static function replace(array $matches): string { return '*' === self::$replacement ? self::replaceWithRandom($matches) : self::replaceWith($matches, self::$replacement); } /** @noinspection PhpUnusedPrivateMethodInspection */ private static function replaceWithUnderscore(array $matches): string { return self::replaceWith($matches, '_'); } private static function replaceWithRandom(array $matches): string { $result = []; $length = mb_strlen(reset($matches), self::getEncoding()); for ($i = 0; $i < $length; $i++) { /** @noinspection RandomApiMigrationInspection */ $result[] = chr(mt_rand(97, 122)); } return implode('', $result); } private static function replaceWith(array $matches, string $replacement): string { return str_repeat($replacement, mb_strlen(reset($matches), self::getEncoding())); } private static function getEncoding(): string { static $encoding; if (null === $encoding) { try { $encoding = self::getApplicationService()->getDefaultEncoding(); } catch (common_Exception $exception) { $encoding = mb_internal_encoding(); } } return $encoding; } private static function getApplicationService(): ApplicationService { /** @noinspection PhpIncompatibleReturnTypeInspection */ return ServiceManager::getServiceManager()->get(ApplicationService::SERVICE_ID); } }