diff --git a/include/class_msg_dialog.inc b/include/class_msg_dialog.inc index 4da11d9e80d948d1b3a8c4b72ac512a5aee2ea3a..e6b0b6c287aca8420393a3ce9d3a77976fdddcda 100644 --- a/include/class_msg_dialog.inc +++ b/include/class_msg_dialog.inc @@ -133,7 +133,11 @@ class msg_dialog public static function displayChecks ($messages) { foreach ($messages as $error) { - static::display(_('Error'), $error, ERROR_DIALOG); + if ($error instanceof FusionDirectoryError) { + static::display(...$error->computeMsgDialogParameters()); + } else { + static::display(_('Error'), $error, ERROR_DIALOG); + } } } diff --git a/include/errors/class_FusionDirectoryError.inc b/include/errors/class_FusionDirectoryError.inc new file mode 100644 index 0000000000000000000000000000000000000000..4fcd6a58645358fa8f11ec4288a4adb5c09b4d5c --- /dev/null +++ b/include/errors/class_FusionDirectoryError.inc @@ -0,0 +1,33 @@ +<?php +/* + This code is part of FusionDirectory (http://www.fusiondirectory.org/) + Copyright (C) 2019-2020 FusionDirectory + + 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; either version 2 of the License, or + (at your option) any later version. + + 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 St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/*! \class FusionDirectoryError + \brief Parent class for all errors in FusionDirectory +*/ +class FusionDirectoryError extends Error +{ + protected $htmlMessage; + + public function __construct (string $htmlMessage = '', int $code = 0, Throwable $previous = NULL) + { + $this->htmlMessage = $htmlMessage; + parent::__construct(htmlunescape(strip_tags($htmlMessage)), $code, $previous); + } +} diff --git a/include/errors/class_SimplePluginCheckError.inc b/include/errors/class_SimplePluginCheckError.inc new file mode 100644 index 0000000000000000000000000000000000000000..35899f1b11367b778fd2814a38fc81e8df24159d --- /dev/null +++ b/include/errors/class_SimplePluginCheckError.inc @@ -0,0 +1,77 @@ +<?php +/* + This code is part of FusionDirectory (http://www.fusiondirectory.org/) + Copyright (C) 2019-2020 FusionDirectory + + 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; either version 2 of the License, or + (at your option) any later version. + + 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 St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/*! \class SimplePluginCheckError + \brief Error returned by check method of SimplePlugin +*/ +class SimplePluginCheckError extends FusionDirectoryError +{ + protected $tab; + protected $attribute; + + public function __construct (?object $origin, string $htmlMessage = '', int $code = 0, Throwable $previous = NULL) + { + if ($origin instanceof Attribute) { + $this->attribute = $origin; + $this->tab = $origin->getParent(); + } else { + $this->attribute = NULL; + if ($origin instanceof SimpleTab) { + $this->tab = $origin; + } else { + $this->tab = NULL; + } + } + + parent::__construct($htmlMessage, $code, $previous); + } + + public function computeMsgDialogParameters (): array + { + $html = ''; + + if (isset($this->tab)) { + $html .= htmlescape($this->tab->parent->getBaseObject()->dn.' > '); + $html .= htmlescape($this->tab->parent->by_name[get_class($this->tab)].' > '); + } + + if (isset($this->attribute)) { + $label = $this->attribute->getLabel(); + if (empty($label)) { + $html .= '<i>'.htmlescape($this->attribute->getLdapName()).'</i>'; + } else { + $html .= htmlescape($label); + } + $example = $this->attribute->getExample(); + } + + $html .= '<br/><br/>'; + + $html .= $this->htmlMessage; + + /* Stylize example */ + if (!empty($example)) { + $html .= '<br/><br/><i>'.sprintf(_('Example: %s'), htmlescape($example)).'</i> '; + } + + + return [_('Error'), $html, ERROR_DIALOG]; + } +} diff --git a/include/functions.inc b/include/functions.inc index 4a97774bf39783c67b11484cc269bed10903c587..a756a6ff828970afa5aa78cffc1d3fa6a6c9331e 100644 --- a/include/functions.inc +++ b/include/functions.inc @@ -1722,19 +1722,21 @@ function send_binary_content ($data, $name, $type = "application/octet-stream") exit(); } - -function reverse_html_entities ($str, $type = ENT_QUOTES, $charset = "UTF-8") +/*! + * \brief Escape string for HTML output + */ +function htmlescape (string $str): string { - if (is_string($str)) { - return htmlentities($str, $type, $charset); - } elseif (is_array($str)) { - foreach ($str as $name => $value) { - $str[$name] = reverse_html_entities($value, $type, $charset); - } - } - return $str; + return htmlentities($str, ENT_COMPAT | ENT_HTML5, 'UTF-8'); } +/*! + * \brief Unescape string for HTML output, reverse of htmlescape + */ +function htmlunescape (string $html): string +{ + return html_entity_decode($html, ENT_COMPAT | ENT_HTML5, 'UTF-8'); +} /*! * \brief Encode special string characters diff --git a/include/simpleplugin/attributes/class_IntAttribute.inc b/include/simpleplugin/attributes/class_IntAttribute.inc index 496c7cd105e27234251125d7bebb58b6975c9cd5..bcbfc7008d0223d3640ea347ad8805f5d365b59a 100644 --- a/include/simpleplugin/attributes/class_IntAttribute.inc +++ b/include/simpleplugin/attributes/class_IntAttribute.inc @@ -26,7 +26,6 @@ class IntAttribute extends Attribute protected $min; protected $max; protected $step = 1; - protected $example; /*! \brief The constructor of IntAttribute * @@ -44,14 +43,16 @@ class IntAttribute extends Attribute parent::__construct($label, $description, $ldapName, $required, $defaultValue, $acl); $this->min = ($min === FALSE ? FALSE : $this->inputValue($min)); $this->max = ($max === FALSE ? FALSE : $this->inputValue($max)); - $this->example = ''; - - if (($min !== FALSE) && ($max !== FALSE)) { - $this->example = sprintf(_('An integer between %d and %d'), $min, $max); - } elseif ($min !== FALSE) { - $this->example = sprintf(_('An integer larger than %d'), $min); - } elseif ($max !== FALSE) { - $this->example = sprintf(_('An integer smaller than %d'), $max); + } + + public function getExample (): ?string + { + if (($this->min !== FALSE) && ($this->max !== FALSE)) { + return sprintf(_('An integer between %d and %d'), $this->min, $this->max); + } elseif ($this->min !== FALSE) { + return sprintf(_('An integer larger than %d'), $this->min); + } elseif ($this->max !== FALSE) { + return sprintf(_('An integer smaller than %d'), $this->max); } } @@ -80,11 +81,13 @@ class IntAttribute extends Attribute return $error; } elseif ($this->value !== '') { if (!is_numeric($this->value)) { - return msgPool::invalid($this->getLabel(), $this->value, $this->example); + return new SimplePluginCheckError($this, sprintf(_('"%s" is not an number'), $this->getValue())); } - if ((($this->min !== FALSE) && ($this->value < $this->min)) - || (($this->max !== FALSE) && ($this->value > $this->max))) { - return msgPool::invalid($this->getLabel(), $this->value, $this->example); + if (($this->min !== FALSE) && ($this->value < $this->min)) { + return new SimplePluginCheckError($this, sprintf(_('%s is smaller than %s'), $this->getValue(), $this->min)); + } + if (($this->max !== FALSE) && ($this->value > $this->max)) { + return new SimplePluginCheckError($this, sprintf(_('%s is larger than %s'), $this->getValue(), $this->max)); } } } @@ -156,14 +159,16 @@ class FloatAttribute extends IntAttribute parent::__construct($label, $description, $ldapName, $required, $min, $max, $defaultValue, $acl); $this->step = 0.01; + } - $this->example = ''; - if (($min !== FALSE) && ($max !== FALSE)) { - $this->example = sprintf(_('A float between %f and %f'), $min, $max); - } elseif ($min !== FALSE) { - $this->example = sprintf(_('A float larger than %f'), $min); - } elseif ($max !== FALSE) { - $this->example = sprintf(_('A float smaller than %f'), $max); + public function getExample (): ?string + { + if (($this->min !== FALSE) && ($this->max !== FALSE)) { + return sprintf(_('A float between %f and %f'), $this->min, $this->max); + } elseif ($this->min !== FALSE) { + return sprintf(_('A float larger than %f'), $this->min); + } elseif ($this->max !== FALSE) { + return sprintf(_('A float smaller than %f'), $this->max); } } diff --git a/include/simpleplugin/attributes/class_StringAttribute.inc b/include/simpleplugin/attributes/class_StringAttribute.inc index 635de25fd1883260e8825fc09d686cd58437027c..857710e300af8fe58a7576f96854e83f3b1da432 100644 --- a/include/simpleplugin/attributes/class_StringAttribute.inc +++ b/include/simpleplugin/attributes/class_StringAttribute.inc @@ -53,6 +53,11 @@ class StringAttribute extends Attribute $this->example = $example; } + public function getExample (): ?string + { + return $this->example; + } + function setPattern ($pattern) { $this->pattern = $pattern; diff --git a/include/simpleplugin/class_Attribute.inc b/include/simpleplugin/class_Attribute.inc index 8c1e6878f4d740431b82c39b651992b453fc7a40..747f7beccfc9f8a2b363a0e3536cc8a1cc759977 100644 --- a/include/simpleplugin/class_Attribute.inc +++ b/include/simpleplugin/class_Attribute.inc @@ -121,6 +121,11 @@ class Attribute $this->manageAttributes($this->getValue()); } + function getParent(): ?simplePlugin + { + return $this->plugin; + } + function setIsSubAttribute (bool $bool) { $this->isSubAttribute = $bool; @@ -167,6 +172,11 @@ class Attribute return $this->inLdap; } + public function getExample (): ?string + { + return NULL; + } + function checkValue ($value) { /* Should throw InvalidValueException if needed */