From f00b22469cc295ff8e40f24da80ffdae26cb1b7e Mon Sep 17 00:00:00 2001 From: Herafia Date: Wed, 20 May 2026 09:30:11 +0200 Subject: [PATCH 1/3] fix/ escape SQL values --- inc/commoninjectionlib.class.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index 1ee5679c..5b85fed3 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -1903,7 +1903,7 @@ private function dataAlreadyInDB($injectionClass, $itemtype) //If it's a computer device if ($item instanceof CommonDevice) { $sql .= " WHERE `designation` = '" . - $this->getValueByItemtypeAndName($itemtype, 'designation') . "'"; + $DB->escape($this->getValueByItemtypeAndName($itemtype, 'designation')) . "'"; } elseif ($item instanceof CommonDBRelation) { //Type is a relation : check it this relation still exists //Define the side of the relation to use @@ -1920,13 +1920,13 @@ private function dataAlreadyInDB($injectionClass, $itemtype) $destination_itemtype = $item::$itemtype_2; } $where .= " AND `$source_id`='" . - $this->getValueByItemtypeAndName($itemtype, $source_id) . "'"; + $DB->escape($this->getValueByItemtypeAndName($itemtype, $source_id)) . "'"; if ($item->isField('itemtype')) { $where .= " AND `$source_itemtype`='" . - $this->getValueByItemtypeAndName($itemtype, $source_itemtype) . "'"; + $DB->escape($this->getValueByItemtypeAndName($itemtype, $source_itemtype)) . "'"; } $where .= " AND `" . $destination_id . "`='" . - $this->getValueByItemtypeAndName($itemtype, $destination_id) . "'"; + $DB->escape($this->getValueByItemtypeAndName($itemtype, $destination_id)) . "'"; $sql .= " WHERE 1 " . $where; } else { //Type is not a relation @@ -1958,7 +1958,7 @@ private function dataAlreadyInDB($injectionClass, $itemtype) } else { //Type cannot be recursive $where_entity = " AND `entities_id` = '" . - $this->getValueByItemtypeAndName($itemtype, 'entities_id') . "'"; + $DB->escape($this->getValueByItemtypeAndName($itemtype, 'entities_id')) . "'"; } } else { //If no entity assignment for this itemtype $where_entity = ""; @@ -1972,25 +1972,25 @@ private function dataAlreadyInDB($injectionClass, $itemtype) $email = $DB->escape($this->getValueByItemtypeAndName($itemtype, $field)); $where .= " AND `id` IN (SELECT `users_id` FROM glpi_useremails WHERE `email` = '$email') "; } else { - $where .= " AND `" . $field . "`='" . (string) $this->getValueByItemtypeAndName($itemtype, $field) . "'"; + $where .= " AND `" . $field . "`='" . $DB->escape((string) $this->getValueByItemtypeAndName($itemtype, $field)) . "'"; } } } } else { //Table contains an itemtype field if ($injectionClass->isField('itemtype')) { - $where .= " AND `itemtype` = '" . $this->getValueByItemtypeAndName( + $where .= " AND `itemtype` = '" . $DB->escape($this->getValueByItemtypeAndName( $itemtype, 'itemtype', - ) . "'"; + )) . "'"; } //Table contains an items_id field if ($injectionClass->isField('items_id')) { - $where .= " AND `items_id` = '" . $this->getValueByItemtypeAndName( + $where .= " AND `items_id` = '" . $DB->escape($this->getValueByItemtypeAndName( $itemtype, 'items_id', - ) . "'"; + )) . "'"; } } From acde442433ea8cefe5e7bc4d794803d00739bf2a Mon Sep 17 00:00:00 2001 From: Herafia Date: Wed, 20 May 2026 09:34:35 +0200 Subject: [PATCH 2/3] CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90c89964..f0c8a57d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] + +### Fixed + +- fix escape SQL values + ## [2.15.6] - 2026-05-05 ### Fixed From e980f99e4482166472016a69a5fe3a474c13206a Mon Sep 17 00:00:00 2001 From: Herafia Date: Wed, 20 May 2026 14:43:54 +0200 Subject: [PATCH 3/3] refracto to glpi querybuilder --- inc/commoninjectionlib.class.php | 84 +++++++++++++++----------------- inc/model.class.php | 1 + 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index 5b85fed3..45ace748 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -27,6 +27,8 @@ * @link https://github.com/pluginsGLPI/datainjection * ------------------------------------------------------------------------- */ +use Glpi\DBAL\QueryExpression; +use Glpi\DBAL\QuerySubQuery; use Glpi\Exception\Http\HttpException; use Glpi\Features\AssignableItem; @@ -1865,7 +1867,6 @@ private function dataAlreadyInDB($injectionClass, $itemtype) /** @var DBmysql $DB */ global $DB; - $where = ""; $continue = true; $injectionClass->getOptions($this->primary_type); @@ -1893,17 +1894,15 @@ private function dataAlreadyInDB($injectionClass, $itemtype) if (!$continue) { $this->values[$itemtype]['id'] = self::ITEM_NOT_FOUND; } else { - $sql = "SELECT * - FROM `" . $injectionClass->getTable() . "`"; - if (!is_a($itemtype, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $itemtype . ' is not a valid class'); } - $item = new $itemtype(); + $item = new $itemtype(); + $where = []; + //If it's a computer device if ($item instanceof CommonDevice) { - $sql .= " WHERE `designation` = '" . - $DB->escape($this->getValueByItemtypeAndName($itemtype, 'designation')) . "'"; + $where['designation'] = $this->getValueByItemtypeAndName($itemtype, 'designation'); } elseif ($item instanceof CommonDBRelation) { //Type is a relation : check it this relation still exists //Define the side of the relation to use @@ -1919,49 +1918,41 @@ private function dataAlreadyInDB($injectionClass, $itemtype) $source_itemtype = $item::$itemtype_1; $destination_itemtype = $item::$itemtype_2; } - $where .= " AND `$source_id`='" . - $DB->escape($this->getValueByItemtypeAndName($itemtype, $source_id)) . "'"; + $where[$source_id] = $this->getValueByItemtypeAndName($itemtype, $source_id); + $where[$destination_id] = $this->getValueByItemtypeAndName($itemtype, $destination_id); if ($item->isField('itemtype')) { - $where .= " AND `$source_itemtype`='" . - $DB->escape($this->getValueByItemtypeAndName($itemtype, $source_itemtype)) . "'"; + $where[$source_itemtype] = $this->getValueByItemtypeAndName($itemtype, $source_itemtype); } - $where .= " AND `" . $destination_id . "`='" . - $DB->escape($this->getValueByItemtypeAndName($itemtype, $destination_id)) . "'"; - $sql .= " WHERE 1 " . $where; } else { //Type is not a relation //Type can be deleted if ($injectionClass->maybeDeleted()) { - $where .= " AND `is_deleted` = '0' "; + $where['is_deleted'] = 0; } //Type can be a template if ($injectionClass->maybeTemplate()) { - $where .= " AND `is_template` = '0' "; + $where['is_template'] = 0; } //Type can be assigned to an entity if ($injectionClass->isEntityAssign()) { //Type can be recursive if ($injectionClass->maybeRecursive()) { - $where_entity = getEntitiesRestrictRequest( - " AND", - $injectionClass->getTable(), - "entities_id", - $this->getValueByItemtypeAndName( - $itemtype, + $where = array_merge( + $where, + getEntitiesRestrictCriteria( + $injectionClass->getTable(), 'entities_id', + $this->getValueByItemtypeAndName($itemtype, 'entities_id'), + true, ), - true, ); } else { //Type cannot be recursive - $where_entity = " AND `entities_id` = '" . - $DB->escape($this->getValueByItemtypeAndName($itemtype, 'entities_id')) . "'"; + $where['entities_id'] = $this->getValueByItemtypeAndName($itemtype, 'entities_id'); } - } else { //If no entity assignment for this itemtype - $where_entity = ""; } //Add mandatory fields to the query only if it's the primary_type to be injected @@ -1969,44 +1960,49 @@ private function dataAlreadyInDB($injectionClass, $itemtype) foreach ($this->mandatory_fields[$itemtype] as $field => $is_mandatory) { if ($is_mandatory) { if ($item instanceof User && $field == "useremails_id") { - $email = $DB->escape($this->getValueByItemtypeAndName($itemtype, $field)); - $where .= " AND `id` IN (SELECT `users_id` FROM glpi_useremails WHERE `email` = '$email') "; + $where['id'] = new QuerySubQuery([ + 'SELECT' => 'users_id', + 'FROM' => 'glpi_useremails', + 'WHERE' => ['email' => $this->getValueByItemtypeAndName($itemtype, $field)], + ]); } else { - $where .= " AND `" . $field . "`='" . $DB->escape((string) $this->getValueByItemtypeAndName($itemtype, $field)) . "'"; + $where[$field] = $this->getValueByItemtypeAndName($itemtype, $field); } } } } else { //Table contains an itemtype field if ($injectionClass->isField('itemtype')) { - $where .= " AND `itemtype` = '" . $DB->escape($this->getValueByItemtypeAndName( - $itemtype, - 'itemtype', - )) . "'"; + $where['itemtype'] = $this->getValueByItemtypeAndName($itemtype, 'itemtype'); } //Table contains an items_id field if ($injectionClass->isField('items_id')) { - $where .= " AND `items_id` = '" . $DB->escape($this->getValueByItemtypeAndName( - $itemtype, - 'items_id', - )) . "'"; + $where['items_id'] = $this->getValueByItemtypeAndName($itemtype, 'items_id'); } } //Add additional parameters specific to this itemtype (or function checkPresent exists) if (method_exists($injectionClass, 'checkPresent')) { - $where .= $injectionClass->checkPresent($this->values, $options); + $extra = trim((string) $injectionClass->checkPresent($this->values, $options)); + $extra = trim(preg_replace('/^\s*AND\s+/i', '', $extra)); + if ($extra !== '') { + $where[] = new QueryExpression($extra); + } } - $sql .= " WHERE 1 " . $where_entity . " " . $where; } - $result = $DB->doQuery($sql); - if ($DB->numrows($result) > 0) { - $db_fields = $DB->fetchAssoc($result); + + $result = $DB->request([ + 'FROM' => $injectionClass->getTable(), + 'WHERE' => $where, + ]); + + if (count($result) > 0) { + $db_fields = $result->current(); foreach ($db_fields as $key => $value) { $this->setValueForItemtype($itemtype, $key, $value, true); } - $this->setValueForItemtype($itemtype, 'id', $DB->result($result, 0, 'id')); + $this->setValueForItemtype($itemtype, 'id', $db_fields['id']); } else { $this->setValueForItemtype($itemtype, 'id', self::ITEM_NOT_FOUND); } diff --git a/inc/model.class.php b/inc/model.class.php index 26af99be..29b03cf1 100644 --- a/inc/model.class.php +++ b/inc/model.class.php @@ -993,6 +993,7 @@ public function readUploadedFile($options = []) ), ]; } + unset($_FILES['filename']); } //If file has not the right extension, reject it and delete if