From 381d4a9a37763990863c61a43e5d02e4afb1aac8 Mon Sep 17 00:00:00 2001 From: Herafia Date: Tue, 21 Apr 2026 12:00:58 +0200 Subject: [PATCH 1/4] Fixes incorrect escaping of apostrophes and accents --- inc/backendcsv.class.php | 5 +---- inc/mapping.class.php | 2 +- inc/mappingcollection.class.php | 2 -- inc/model.class.php | 8 ++++---- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/inc/backendcsv.class.php b/inc/backendcsv.class.php index b694c07d..a2863be3 100644 --- a/inc/backendcsv.class.php +++ b/inc/backendcsv.class.php @@ -91,14 +91,11 @@ public function setHeaderPresent($present = true) **/ public static function parseLine($fic, $data, $encoding = 1) { - /** @var DBmysql $DB */ - global $DB; - $csv = []; $num = count($data); for ($c = 0; $c < $num; $c++) { - $tmp = trim($DB->escape($data[$c])); + $tmp = trim($data[$c]); switch ($encoding) { case PluginDatainjectionBackend::ENCODING_ISO8859_1: $csv[0][] = $tmp === '' || $tmp === '0' ? Toolbox::encodeInUtf8($tmp) : $tmp; diff --git a/inc/mapping.class.php b/inc/mapping.class.php index 99c44f19..98569189 100644 --- a/inc/mapping.class.php +++ b/inc/mapping.class.php @@ -129,7 +129,7 @@ public static function showFormMappings(PluginDatainjectionModel $model) foreach ($model->getMappings() as $mapping) { $mappings_id = $mapping->getID(); echo ""; - echo "" . $mapping->fields['name'] . ""; + echo "" . htmlescape($mapping->fields['name']) . ""; echo ""; $options = ['primary_type' => $model->fields['itemtype']]; PluginDatainjectionInjectionType::dropdownLinkedTypes($mapping, $options); diff --git a/inc/mappingcollection.class.php b/inc/mappingcollection.class.php index 4d03393f..e77d4270 100644 --- a/inc/mappingcollection.class.php +++ b/inc/mappingcollection.class.php @@ -58,8 +58,6 @@ public function load($models_id) $this->mappingCollection = []; foreach ($data = $DB->doQuery($sql) as $data) { - // Addslashes to conform to value return by PluginDatainjectionBackendcsv::parseLine - $data["name"] = addslashes($data["name"]); $mapping = new PluginDatainjectionMapping(); $mapping->fields = $data; $this->mappingCollection[] = $mapping; diff --git a/inc/model.class.php b/inc/model.class.php index efc89ae1..93fb9492 100644 --- a/inc/model.class.php +++ b/inc/model.class.php @@ -1180,11 +1180,11 @@ public function isFileCorrect() //If name of the mapping is not equal in the csv file header and in the DB $name_from_file = trim( mb_strtoupper( - stripslashes($header[$mapping->getRank()]), + $header[$mapping->getRank()], 'UTF-8', ), ); - $name_from_db = trim(mb_strtoupper(stripslashes($mapping->getName()), 'UTF-8')); + $name_from_db = trim(mb_strtoupper($mapping->getName(), 'UTF-8')); if ($name_from_db != $name_from_file) { if ($error['error_message'] == '') { @@ -1331,7 +1331,7 @@ public static function showPreviewMappings($models_id) echo ""; foreach ($mappings as $mapping) { - echo"" . stripslashes($mapping->getMappingName()) . ""; + echo"" . htmlescape($mapping->getMappingName()) . ""; } echo ""; unset($lines[0]); @@ -1340,7 +1340,7 @@ public static function showPreviewMappings($models_id) foreach ($lines as $line) { echo ""; foreach ($line[0] as $value) { - echo "" . $value . ""; + echo "" . htmlescape($value) . ""; } echo ""; } From 97deced51b1d70e5e1a9b022043e9711353e4198 Mon Sep 17 00:00:00 2001 From: Herafia Date: Tue, 21 Apr 2026 12:03:44 +0200 Subject: [PATCH 2/4] CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4370626e..47568a6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fix crash when injection model has no mandatory fields defined - Fix models created on parent entities can't be used on child entites +- Fix incorrect escaping of apostrophes and accents ## [2.15.4] - 2026-03-16 From cf3f6c2e79303ab8b7ffdd3c3eacaf9cb40d2ca3 Mon Sep 17 00:00:00 2001 From: Maximilian Neu Date: Tue, 21 Apr 2026 11:53:00 +0200 Subject: [PATCH 3/4] PR : Fix responsible group visibility after injection (#607) * Fix responsible group visibility after injection * Use normalized group value in payload --- CHANGELOG.md | 1 + inc/commoninjectionlib.class.php | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47568a6b..cf5ffdc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fix crash when injection model has no mandatory fields defined - Fix models created on parent entities can't be used on child entites +- Fix responsible group injection payload normalization so group remains visible in GLPI after import - Fix incorrect escaping of apostrophes and accents ## [2.15.4] - 2026-03-16 diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index 8980b4c1..991effa6 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -1688,16 +1688,26 @@ private function effectiveAddOrUpdate($injectionClass, $item, $values, $add = tr $toinject[$key] = $value; } - // handle new format for group type specification - // restricting to group_item relations only - if (($key === "groups_id_tech" || $key === "groups_id" || $key === "groups_id_normal") && $option['table'] == getTableForItemType(Group::class) && !empty($option) && isset($option['joinparams']['beforejoin']['table']) && $option['joinparams']['beforejoin']['table'] === getTableForItemType(Group_Item::class) && isset($option['joinparams']['beforejoin']['joinparams']['condition']['NEWTABLE.type'])) { - $group_type = $option['joinparams']['beforejoin']['joinparams']['condition']['NEWTABLE.type']; - // depending on the type, set the correct field (_groups_id_tech => array or _groups_id => array) - // and unset the old one (groups_id_tech => int or groups_id => int or groups_id_normal => int) - if ($group_type == Group_Item::GROUP_TYPE_TECH) { - $toinject["_groups_id_tech"] = [$value]; + // Normalize group assignment fields to GLPI relation payload keys. + // Some search options do not expose a stable joinparams shape, but GLPI + // still expects _groups_id/_groups_id_tech arrays when saving equipment groups. + if ( + in_array($key, ['groups_id_tech', 'groups_id', 'groups_id_normal'], true) + && !empty($option) + && isset($option['table']) + && $option['table'] === getTableForItemType(Group::class) + ) { + $normalized_value = $toinject[$key]; + $group_type = null; + if (isset($option['joinparams']['beforejoin']['joinparams']['condition']['NEWTABLE.type'])) { + $group_type = $option['joinparams']['beforejoin']['joinparams']['condition']['NEWTABLE.type']; + } + + // Keep explicit technical group semantics from key or metadata. + if ($key === 'groups_id_tech' || $group_type == Group_Item::GROUP_TYPE_TECH) { + $toinject['_groups_id_tech'] = [$normalized_value]; } else { - $toinject["_groups_id"] = [$value]; + $toinject['_groups_id'] = [$normalized_value]; } unset($toinject[$key]); } From 935db0f0eecc7f2d56ed6cc7ad0d519635dd3dac Mon Sep 17 00:00:00 2001 From: Herafia Date: Wed, 22 Apr 2026 14:04:27 +0200 Subject: [PATCH 4/4] twig --- inc/mapping.class.php | 68 ++++++++++++------------------ templates/mappings_form.html.twig | 70 +++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 42 deletions(-) create mode 100644 templates/mappings_form.html.twig diff --git a/inc/mapping.class.php b/inc/mapping.class.php index 98569189..98f059d1 100644 --- a/inc/mapping.class.php +++ b/inc/mapping.class.php @@ -28,6 +28,11 @@ * ------------------------------------------------------------------------- */ +use Glpi\Application\View\TemplateRenderer; + +use function Safe\ob_get_clean; +use function Safe\ob_start; + class PluginDatainjectionMapping extends CommonDBTM { public static $rightname = "plugin_datainjection_model"; @@ -93,60 +98,39 @@ public function getItemtype() **/ public static function showFormMappings(PluginDatainjectionModel $model) { - /** @var array $CFG_GLPI */ - global $CFG_GLPI; - $canedit = $model->can($model->fields['id'], UPDATE); - $lines = isset($_SESSION['datainjection']['lines']) ? unserialize($_SESSION['datainjection']['lines']) : []; - echo "
"; - - //Display link to the preview popup - if (isset($_SESSION['datainjection']['lines']) && !empty($lines)) { - $nblines = $_SESSION['datainjection']['nblines']; - echo ""; - echo ""; + $show_preview = isset($_SESSION['datainjection']['lines']) && !empty($lines); + $preview_url = ''; + if ($show_preview) { + $preview_url = plugin_datainjection_geturl() . "front/popup.php?popup=preview&models_id=" . $model->getID(); } - echo "
"; - $url = plugin_datainjection_geturl() . - "front/popup.php?popup=preview&models_id=" . - $model->getID(); - echo ""; - echo __s('See the file', 'datainjection') . ""; - echo "
"; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - $model->loadMappings(); + $mappings = []; foreach ($model->getMappings() as $mapping) { - $mappings_id = $mapping->getID(); - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - } + $dropdown_html = ob_get_clean(); - if ($canedit) { - echo ""; + $mappings[] = [ + 'id' => $mapping->getID(), + 'name' => $mapping->fields['name'], + 'dropdown_html' => $dropdown_html, + ]; } - echo "
" . __s('Header of the file', 'datainjection') . "" . __s('Tables', 'datainjection') . "" . _sn('Field', 'Fields', 2) . "" . __s('Link field', 'datainjection') . "
" . htmlescape($mapping->fields['name']) . ""; + ob_start(); $options = ['primary_type' => $model->fields['itemtype']]; PluginDatainjectionInjectionType::dropdownLinkedTypes($mapping, $options); - echo ""; - echo "
"; - echo ""; - echo ""; - echo "
"; - Html::closeForm(); + + TemplateRenderer::getInstance()->display('@datainjection/mappings_form.html.twig', [ + 'form_action' => Toolbox::getItemTypeFormURL(self::class), + 'show_preview' => $show_preview, + 'preview_url' => $preview_url, + 'mappings' => $mappings, + 'canedit' => $canedit, + 'model_id' => $model->fields['id'], + ]); } diff --git a/templates/mappings_form.html.twig b/templates/mappings_form.html.twig new file mode 100644 index 00000000..1063f0e0 --- /dev/null +++ b/templates/mappings_form.html.twig @@ -0,0 +1,70 @@ +{# + # ------------------------------------------------------------------------- + # DataInjection plugin for GLPI + # ------------------------------------------------------------------------- + # + # LICENSE + # + # This file is part of DataInjection. + # + # DataInjection 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. + # + # DataInjection 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 DataInjection. If not, see . + # ------------------------------------------------------------------------- + # @copyright Copyright (C) 2007-2023 by DataInjection plugin team. + # @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + # @link https://github.com/pluginsGLPI/datainjection + # ------------------------------------------------------------------------- + #} + + + + {% if show_preview %} + + + + +
+ + {{ __('See the file', 'datainjection') }} + +
+ {% endif %} + + + + + + + + + + {% for mapping in mappings %} + + + + + + + {% endfor %} + + {% if canedit %} + + + + {% endif %} +
{{ __('Header of the file', 'datainjection') }}{{ __('Tables', 'datainjection') }}{{ _n('Field', 'Fields', 2) }}{{ __('Link field', 'datainjection') }}
{{ mapping.name }}{{ mapping.dropdown_html|raw }}
+ + +
+ +