From b2d2842fdadf4983900462fd2179b95bb9c7f6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Tue, 7 Jan 2020 20:53:19 +0100 Subject: [PATCH 01/10] Run test suite on PHP 7.4 --- .circleci/config.yml | 24 ++++++++++++++++-------- .github/workflows/ci.yml | 3 ++- .travis.yml | 3 +-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6d14f4aa76..329b41723c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,7 +36,7 @@ shared: &shared command: vendor/bin/security-checker security:check - run: name: Coding standards - command: if [[ $(php --version|grep "7\.3") ]]; then vendor/bin/phpcs -d memory_limit=512M -p -n vendor/bin/phpcs -d memory_limit=512M -p --standard=vendor/glpi-project/coding-standard/GlpiStandard/ --ignore=/vendor/,/plugins/,/files/,/lib/,/config/,/tests/config,/css/tiny_mce,/.git ./; else echo "No CS for this version"; fi + command: if [[ $(php --version|grep "7\.4") ]]; then vendor/bin/phpcs -d memory_limit=512M -p -n vendor/bin/phpcs -d memory_limit=512M -p --standard=vendor/glpi-project/coding-standard/GlpiStandard/ --ignore=/vendor/,/plugins/,/files/,/lib/,/config/,/tests/config,/css/tiny_mce,/.git ./; else echo "No CS for this version"; fi - run: name: Update DB command: | @@ -110,25 +110,25 @@ jobs: docker: - image: glpi/circleci-env-core:php_7.3_fpm-node - image: circleci/mariadb:10.3-ram - php_latest_test_suite: + php_7_4_test_suite: <<: *shared docker: - - image: glpi/circleci-env-core:php_latest_fpm-node - - image: circleci/mariadb:10.3-ram + - image: glpi/circleci-env-core:php_7.4_fpm-node + - image: circleci/mariadb:10.4-ram mysql_5_6_test_suite: <<: *shared docker: - - image: glpi/circleci-env-core:php_7.3_fpm-node + - image: glpi/circleci-env-core:php_7.4_fpm-node - image: circleci/mysql:5.6-ram mysql_5_7_test_suite: <<: *shared docker: - - image: glpi/circleci-env-core:php_7.3_fpm-node + - image: glpi/circleci-env-core:php_7.4_fpm-node - image: circleci/mysql:5.7-ram mysql_8_0_test_suite: <<: *shared docker: - - image: glpi/circleci-env-core:php_7.3_fpm-node + - image: glpi/circleci-env-core:php_7.4_fpm-node - image: circleci/mysql:8.0-ram command: [--default-authentication-plugin=mysql_native_password] # Fix "Authentication plugin 'caching_sha2_password' cannot be loaded" @@ -177,6 +177,14 @@ workflows: filters: tags: only: /.*/ # run also on tag creation + branches: + ignore: /.*/ # do not run on branch update + - php_7_4_test_suite: + requires: + - checkout + filters: + tags: + only: /.*/ # run also on tag creation - mysql_5_6_test_suite: requires: - checkout @@ -227,7 +235,7 @@ workflows: - php_7_3_test_suite: requires: - checkout - - php_latest_test_suite: + - php_7_4_test_suite: requires: - checkout - mysql_5_6_test_suite: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 020d909411..811315fb67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,7 +53,8 @@ jobs: #- "7.0" #- "7.1" #- "7.2" - - "7.3" + #- "7.3" + - "7.4" services: app: image: "glpi/githubactions-php:${{ matrix.php-version }}" diff --git a/.travis.yml b/.travis.yml index ce6b588b17..1d5491bab5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ matrix: - slapd hosts: - openldap - - php: 7.4snapshot + - php: 7.4 addons: apt: packages: @@ -83,7 +83,6 @@ matrix: - openldap allow_failures: - php: nightly - - php: 7.4snapshot cache: directories: From 30079c3c9ff790f35a3727ad4029944249d42d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Mon, 30 Sep 2019 16:01:15 +0200 Subject: [PATCH 02/10] Fix notice trigerred when ticket has no followup ==> Error E_NOTICE in /var/glpi/tests/functionnal/NotificationTargetTicket.php on line 115, generated by file /var/glpi/inc/notificationtargetticket.class.php on line 462: Trying to access array offset on value of type bool --- inc/notificationtargetticket.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inc/notificationtargetticket.class.php b/inc/notificationtargetticket.class.php index 115c601838..d39f4ade7b 100644 --- a/inc/notificationtargetticket.class.php +++ b/inc/notificationtargetticket.class.php @@ -452,9 +452,9 @@ function getDataForObject(CommonDBTM $item, array $options, $simple = false) { ]; $replysolved = getAllDatasFromTable('glpi_itilfollowups', $solution_restrict, false, ['date_mod DESC', 'id ASC']); $current = current($replysolved); - $data['##ticket.solution.approval.description##'] = $current['content']; - $data['##ticket.solution.approval.date##'] = Html::convDateTime($current['date']); - $data['##ticket.solution.approval.author##'] = Html::clean(getUserName($current['users_id'])); + $data['##ticket.solution.approval.description##'] = $current ? $current['content'] : ''; + $data['##ticket.solution.approval.date##'] = $current ? Html::convDateTime($current['date']) : ''; + $data['##ticket.solution.approval.author##'] = $current ? Html::clean(getUserName($current['users_id'])) : ''; //Validation infos $restrict = ['tickets_id' => $item->getField('id')]; From f2e9da2e979d5f7be8d0a68919e00346220e7170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Mon, 30 Sep 2019 16:00:48 +0200 Subject: [PATCH 03/10] Fix parsing of classes on Search::testSearchOptions() ==> Error E_NOTICE in /var/glpi/tests/functionnal/Search.php on line 558, generated by file /var/glpi/tests/functionnal/Search.php on line 95: file_get_contents(): read of 8192 bytes failed with errno=21 Is a directory --- tests/functionnal/Search.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functionnal/Search.php b/tests/functionnal/Search.php index 3b830d3bd3..6432c18fea 100644 --- a/tests/functionnal/Search.php +++ b/tests/functionnal/Search.php @@ -88,7 +88,7 @@ private function doSearch($itemtype, $params, array $forcedisplay = []) { private function getClasses($function = false, array $excludes = []) { $classes = []; foreach (new \DirectoryIterator('inc/') as $fileInfo) { - if ($fileInfo->isDot()) { + if (!$fileInfo->isFile()) { continue; } From c7920bcd3b19757bb824bb52733715ac2d3ea6cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Mon, 30 Sep 2019 15:22:02 +0200 Subject: [PATCH 04/10] Fix error handling in unit tests --- inc/toolbox.class.php | 16 +++------------- tests/bootstrap.php | 1 + 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/inc/toolbox.class.php b/inc/toolbox.class.php index 0df3d82045..0f12616723 100644 --- a/inc/toolbox.class.php +++ b/inc/toolbox.class.php @@ -713,26 +713,16 @@ static function setDebugMode($mode = null, $debug_sql = null, $debug_vars = null // If debug mode activated : display some information if ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE) { - // display_errors only need for for E_ERROR, E_PARSE, ... which cannot be catched // Recommended development settings ini_set('display_errors', 'On'); - error_reporting(E_ALL | E_STRICT); + error_reporting(E_ALL); set_error_handler(['Toolbox','userErrorHandlerDebug']); - - } else { + } else if (!defined('TU_USER')) { // Recommended production settings ini_set('display_errors', 'Off'); - if (defined('TU_USER')) { - //do not set error_reporting to a low level for unit tests - error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT); - } + error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT); set_error_handler(['Toolbox', 'userErrorHandlerNormal']); } - - if (defined('TU_USER')) { - //user default error handler from tests - set_error_handler(null); - } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 8308d0a750..6575169bf6 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -30,6 +30,7 @@ * --------------------------------------------------------------------- */ +ini_set('display_errors', 'On'); error_reporting(E_ALL); define('GLPI_CACHE_DIR', __DIR__ . '/files/_cache'); From dff20cd35417ba596247192dfb8f78964d1a62a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Mon, 30 Sep 2019 12:53:47 +0200 Subject: [PATCH 05/10] Fix Iterator mock in Migration::addConfig() test --- tests/units/Migration.php | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tests/units/Migration.php b/tests/units/Migration.php index 68a57b63ed..6b34b20980 100644 --- a/tests/units/Migration.php +++ b/tests/units/Migration.php @@ -152,14 +152,22 @@ function () { //test with one existing value => only new key should be inserted $this->queries = []; - $dbresult = [[ - 'id' => '42', - 'context' => 'core', - 'name' => 'one', - 'value' => 'setted value' - ]]; - $it = new \ArrayIterator($dbresult); - $this->calling($this->db)->request = $it; + $this->calling($this->db)->request = function ($table) { + // Call using 'glpi_configs' value for first parameter + // corresponds to the call made to retrieve exisintg values + // -> returns a value for config 'one' + if ('glpi_configs' === $table) { + $dbresult = [[ + 'id' => '42', + 'context' => 'core', + 'name' => 'one', + 'value' => 'setted value' + ]]; + return new \ArrayIterator($dbresult); + } + // Other calls corresponds to call made in Config::setConfigurationValues() + return new \ArrayIterator(); + }; $DB = $this->db; From b7e216e928853f2d9cadb5a3fbc4d5386ce137ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Tue, 7 Jan 2020 21:23:18 +0100 Subject: [PATCH 06/10] Update dependencies that fixed issues with PHP 7.4 --- composer.lock | 115 ++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 51 deletions(-) diff --git a/composer.lock b/composer.lock index b0552ded8b..cea7521baf 100644 --- a/composer.lock +++ b/composer.lock @@ -162,21 +162,24 @@ }, { "name": "michelf/php-markdown", - "version": "1.8.0", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/michelf/php-markdown.git", - "reference": "01ab082b355bf188d907b9929cd99b2923053495" + "reference": "c83178d49e372ca967d1a8c77ae4e051b3a3c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/michelf/php-markdown/zipball/01ab082b355bf188d907b9929cd99b2923053495", - "reference": "01ab082b355bf188d907b9929cd99b2923053495", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/c83178d49e372ca967d1a8c77ae4e051b3a3c75c", + "reference": "c83178d49e372ca967d1a8c77ae4e051b3a3c75c", "shasum": "" }, "require": { "php": ">=5.3.0" }, + "require-dev": { + "phpunit/phpunit": ">=4.3 <5.8" + }, "type": "library", "autoload": { "psr-4": { @@ -204,7 +207,7 @@ "keywords": [ "markdown" ], - "time": "2018-01-15T00:49:33+00:00" + "time": "2019-12-02T02:32:27+00:00" }, { "name": "monolog/monolog", @@ -642,16 +645,16 @@ }, { "name": "sabre/vobject", - "version": "4.2.0", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/sabre-io/vobject.git", - "reference": "bd500019764e434ff65872d426f523e7882a0739" + "reference": "6d7476fbd227ae285029c19ad518cd451336038c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/vobject/zipball/bd500019764e434ff65872d426f523e7882a0739", - "reference": "bd500019764e434ff65872d426f523e7882a0739", + "url": "https://api.github.com/repos/sabre-io/vobject/zipball/6d7476fbd227ae285029c19ad518cd451336038c", + "reference": "6d7476fbd227ae285029c19ad518cd451336038c", "shasum": "" }, "require": { @@ -734,7 +737,7 @@ "xCal", "xCard" ], - "time": "2019-02-19T13:05:37+00:00" + "time": "2019-12-18T19:29:43+00:00" }, { "name": "sabre/xml", @@ -853,16 +856,16 @@ }, { "name": "simplepie/simplepie", - "version": "1.5.2", + "version": "1.5.4", "source": { "type": "git", "url": "https://github.com/simplepie/simplepie.git", - "reference": "0e8fe72132dad765d25db4cabc69a91139af1263" + "reference": "f4c8246511a38fc9d99a59fb42f61eeeafb31663" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplepie/simplepie/zipball/0e8fe72132dad765d25db4cabc69a91139af1263", - "reference": "0e8fe72132dad765d25db4cabc69a91139af1263", + "url": "https://api.github.com/repos/simplepie/simplepie/zipball/f4c8246511a38fc9d99a59fb42f61eeeafb31663", + "reference": "f4c8246511a38fc9d99a59fb42f61eeeafb31663", "shasum": "" }, "require": { @@ -916,20 +919,20 @@ "feeds", "rss" ], - "time": "2018-08-02T05:43:58+00:00" + "time": "2019-11-23T07:05:15+00:00" }, { "name": "symfony/console", - "version": "v3.4.22", + "version": "v3.4.36", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "069bf3f0e8f871a2169a06e43d9f3f03f355e9be" + "reference": "1ee23b3b659b06c622f2bd2492a229e416eb4586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/069bf3f0e8f871a2169a06e43d9f3f03f355e9be", - "reference": "069bf3f0e8f871a2169a06e43d9f3f03f355e9be", + "url": "https://api.github.com/repos/symfony/console/zipball/1ee23b3b659b06c622f2bd2492a229e416eb4586", + "reference": "1ee23b3b659b06c622f2bd2492a229e416eb4586", "shasum": "" }, "require": { @@ -988,7 +991,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-01-25T10:42:12+00:00" + "time": "2019-12-01T10:04:45+00:00" }, { "name": "symfony/debug", @@ -1107,16 +1110,16 @@ }, { "name": "tecnickcom/tcpdf", - "version": "6.2.26", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/tecnickcom/TCPDF.git", - "reference": "367241059ca166e3a76490f4448c284e0a161f15" + "reference": "9fde7bb9b404b945e7ea88fb7eccd23d9a4e324b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/367241059ca166e3a76490f4448c284e0a161f15", - "reference": "367241059ca166e3a76490f4448c284e0a161f15", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/9fde7bb9b404b945e7ea88fb7eccd23d9a4e324b", + "reference": "9fde7bb9b404b945e7ea88fb7eccd23d9a4e324b", "shasum": "" }, "require": { @@ -1165,7 +1168,7 @@ "pdf417", "qrcode" ], - "time": "2018-10-16T17:24:05+00:00" + "time": "2019-09-20T09:35:01+00:00" }, { "name": "true/punycode", @@ -1294,6 +1297,7 @@ "psr-6", "zf" ], + "abandoned": "laminas/laminas-cache", "time": "2018-05-01T21:58:00+00:00" }, { @@ -1348,28 +1352,33 @@ "events", "zf2" ], + "abandoned": "laminas/laminas-eventmanager", "time": "2018-04-25T15:33:34+00:00" }, { "name": "zendframework/zend-i18n", - "version": "2.9.0", + "version": "2.10.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-i18n.git", - "reference": "6d69af5a04e1a4de7250043cb1322f077a0cdb7f" + "reference": "84038e6a1838b611dcc491b1c40321fa4c3a123c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-i18n/zipball/6d69af5a04e1a4de7250043cb1322f077a0cdb7f", - "reference": "6d69af5a04e1a4de7250043cb1322f077a0cdb7f", + "url": "https://api.github.com/repos/zendframework/zend-i18n/zipball/84038e6a1838b611dcc491b1c40321fa4c3a123c", + "reference": "84038e6a1838b611dcc491b1c40321fa4c3a123c", "shasum": "" }, "require": { + "ext-intl": "*", "php": "^5.6 || ^7.0", "zendframework/zend-stdlib": "^2.7 || ^3.0" }, + "conflict": { + "phpspec/prophecy": "<1.9.0" + }, "require-dev": { - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.16", "zendframework/zend-cache": "^2.6.1", "zendframework/zend-coding-standard": "~1.0.0", "zendframework/zend-config": "^2.6", @@ -1380,7 +1389,6 @@ "zendframework/zend-view": "^2.6.3" }, "suggest": { - "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP", "zendframework/zend-cache": "Zend\\Cache component", "zendframework/zend-config": "Zend\\Config component", "zendframework/zend-eventmanager": "You should install this package to use the events in the translator", @@ -1393,8 +1401,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.9.x-dev", - "dev-develop": "2.10.x-dev" + "dev-master": "2.10.x-dev", + "dev-develop": "2.11.x-dev" }, "zf": { "component": "Zend\\I18n", @@ -1416,7 +1424,8 @@ "i18n", "zf" ], - "time": "2018-05-16T16:39:13+00:00" + "abandoned": "laminas/laminas-i18n", + "time": "2019-12-12T14:08:22+00:00" }, { "name": "zendframework/zend-json", @@ -1466,6 +1475,7 @@ "json", "zf" ], + "abandoned": "laminas/laminas-json", "time": "2018-01-04T17:51:34+00:00" }, { @@ -1523,6 +1533,7 @@ "serializer", "zf" ], + "abandoned": "laminas/laminas-serializer", "time": "2018-05-14T18:45:18+00:00" }, { @@ -1591,6 +1602,7 @@ "servicemanager", "zf" ], + "abandoned": "laminas/laminas-servicemanager", "time": "2018-12-22T06:05:09+00:00" }, { @@ -1637,6 +1649,7 @@ "stdlib", "zf" ], + "abandoned": "laminas/laminas-stdlib", "time": "2018-08-28T21:34:05+00:00" } ], @@ -1647,12 +1660,12 @@ "source": { "type": "git", "url": "https://github.com/atoum/atoum.git", - "reference": "be412c0d5c01a4d9d64f7422a510b5a5a9611c9f" + "reference": "b6c93433a7b0b92b54c2bb9b0731d71ddc03b365" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/atoum/atoum/zipball/be412c0d5c01a4d9d64f7422a510b5a5a9611c9f", - "reference": "be412c0d5c01a4d9d64f7422a510b5a5a9611c9f", + "url": "https://api.github.com/repos/atoum/atoum/zipball/b6c93433a7b0b92b54c2bb9b0731d71ddc03b365", + "reference": "b6c93433a7b0b92b54c2bb9b0731d71ddc03b365", "shasum": "" }, "require": { @@ -1722,7 +1735,7 @@ "test", "unit testing" ], - "time": "2019-06-08T11:00:07+00:00" + "time": "2019-10-04T19:45:12+00:00" }, { "name": "atoum/telemetry-extension", @@ -2383,16 +2396,16 @@ }, { "name": "fzaninotto/faker", - "version": "v1.8.0", + "version": "v1.9.1", "source": { "type": "git", "url": "https://github.com/fzaninotto/Faker.git", - "reference": "f72816b43e74063c8b10357394b6bba8cb1c10de" + "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/f72816b43e74063c8b10357394b6bba8cb1c10de", - "reference": "f72816b43e74063c8b10357394b6bba8cb1c10de", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/fc10d778e4b84d5bd315dad194661e091d307c6f", + "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f", "shasum": "" }, "require": { @@ -2401,12 +2414,12 @@ "require-dev": { "ext-intl": "*", "phpunit/phpunit": "^4.8.35 || ^5.7", - "squizlabs/php_codesniffer": "^1.5" + "squizlabs/php_codesniffer": "^2.9.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8-dev" + "dev-master": "1.9-dev" } }, "autoload": { @@ -2429,7 +2442,7 @@ "faker", "fixtures" ], - "time": "2018-07-12T10:23:15+00:00" + "time": "2019-12-12T13:22:17+00:00" }, { "name": "glpi-project/coding-standard", @@ -2861,23 +2874,23 @@ }, { "name": "mikey179/vfsstream", - "version": "v1.6.5", + "version": "v1.6.8", "source": { "type": "git", "url": "https://github.com/bovigo/vfsStream.git", - "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145" + "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", - "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/231c73783ebb7dd9ec77916c10037eff5a2b6efe", + "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "~4.5" + "phpunit/phpunit": "^4.5|^5.0" }, "type": "library", "extra": { @@ -2903,7 +2916,7 @@ ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", - "time": "2017-08-01T08:02:14+00:00" + "time": "2019-10-30T15:31:00+00:00" }, { "name": "natxet/CssMin", From 4ff0c081d9d3388ac39e89c8531d4c1fd74472c6 Mon Sep 17 00:00:00 2001 From: Johan Cwiklinski Date: Thu, 21 Nov 2019 10:33:19 +0100 Subject: [PATCH 07/10] ldap_control_paged* are deprecated in PHP 7.4 (#6570) --- inc/authldap.class.php | 84 +++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 18 deletions(-) diff --git a/inc/authldap.class.php b/inc/authldap.class.php index ede72d82b1..10f58b0efb 100644 --- a/inc/authldap.class.php +++ b/inc/authldap.class.php @@ -1654,18 +1654,45 @@ static function searchForUsers($ds, $values, $filter, $attrs, &$limitexceeded, & $count = 0; //Store the number of results ldap_search do { + $filter = Toolbox::unclean_cross_side_scripting_deep(Toolbox::stripslashes_deep($filter)); if (self::isLdapPageSizeAvailable($config_ldap)) { - ldap_control_paged_result($ds, $config_ldap->fields['pagesize'], true, $cookie); + if (version_compare(PHP_VERSION, '7.3') < 0) { + //prior to PHP 7.3, use ldap_control_paged_result + ldap_control_paged_result($ds, $config_ldap->fields['pagesize'], true, $cookie); + $sr = @ldap_search($ds, $values['basedn'], $filter, $attrs); + } else { + //since PHP 7.3, send serverctrls to ldap_search + $controls = [ + [ + 'oid' =>LDAP_CONTROL_PAGEDRESULTS, + 'iscritical' => true, + 'value' => [ + 'size' => $config_ldap->fields['pagesize'], + 'cookie' => $cookie + ] + ] + ]; + $sr = @ldap_search($ds, $values['basedn'], $filter, $attrs, 0, -1, -1, LDAP_DEREF_NEVER, $controls); + ldap_parse_result($ds, $sr, $errcode, $matcheddn, $errmsg, $referrals, $controls); + if (isset($controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) { + $cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']; + } else { + $cookie = ''; + } + } + } else { + $sr = @ldap_search($ds, $values['basedn'], $filter, $attrs); } - $filter = Toolbox::unclean_cross_side_scripting_deep(Toolbox::stripslashes_deep($filter)); - $sr = @ldap_search($ds, $values['basedn'], $filter, $attrs); + if ($sr) { if (in_array(ldap_errno($ds), [4,11])) { // openldap return 4 for Size limit exceeded $limitexceeded = true; } + $info = self::get_entries_clean($ds, $sr); if (in_array(ldap_errno($ds), [4,11])) { + // openldap return 4 for Size limit exceeded $limitexceeded = true; } @@ -1718,7 +1745,7 @@ static function searchForUsers($ds, $values, $filter, $attrs, &$limitexceeded, & } else { return false; } - if (self::isLdapPageSizeAvailable($config_ldap)) { + if (self::isLdapPageSizeAvailable($config_ldap) && version_compare(PHP_VERSION, '7.3') < 0) { ldap_control_paged_result_response($ds, $sr, $cookie); } @@ -2208,25 +2235,48 @@ static function getGroupsFromLDAP($ldap_connection, $config_ldap, $filter, $cookie = ''; $count = 0; do { + $filter = Toolbox::unclean_cross_side_scripting_deep(Toolbox::stripslashes_deep($filter)); if (self::isLdapPageSizeAvailable($config_ldap)) { - ldap_control_paged_result($ldap_connection, $config_ldap->fields['pagesize'], - true, $cookie); + if (version_compare(PHP_VERSION, '7.3') < 0) { + //prior to PHP 7.3, use ldap_control_paged_result + ldap_control_paged_result($ldap_connection, $config_ldap->fields['pagesize'], true, $cookie); + $sr = @ldap_search($ldap_connection, $config_ldap->fields['basedn'], $filter, $attrs); + } else { + //since PHP 7.3, send serverctrls to ldap_search + $controls = [ + [ + 'oid' =>LDAP_CONTROL_PAGEDRESULTS, + 'iscritical' => true, + 'value' => [ + 'size' => $config_ldap->fields['pagesize'], + 'cookie' => $cookie + ] + ] + ]; + $sr = @ldap_search($ldap_connection, $config_ldap->fields['basedn'], $filter, $attrs, 0, -1, -1, LDAP_DEREF_NEVER, $controls); + ldap_parse_result($ldap_connection, $sr, $errcode, $matcheddn, $errmsg, $referrals, $controls); + if (isset($controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) { + $cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']; + } else { + $cookie = ''; + } + } + } else { + $sr = @ldap_search($ldap_connection, $config_ldap->fields['basedn'], $filter, $attrs); } - $filter = Toolbox::unclean_cross_side_scripting_deep($filter); - $sr = @ldap_search($ldap_connection, $config_ldap->fields['basedn'], $filter, - $attrs); - if ($sr) { if (in_array(ldap_errno($ldap_connection), [4,11])) { // openldap return 4 for Size limit exceeded $limitexceeded = true; } + $infos = self::get_entries_clean($ldap_connection, $sr); if (in_array(ldap_errno($ldap_connection), [4,11])) { // openldap return 4 for Size limit exceeded $limitexceeded = true; } + $count += $infos['count']; //If page results are enabled and the number of results is greater than the maximum allowed //warn user that limit is exceeded and stop search @@ -2286,7 +2336,7 @@ static function getGroupsFromLDAP($ldap_connection, $config_ldap, $filter, } } } - if (self::isLdapPageSizeAvailable($config_ldap)) { + if (self::isLdapPageSizeAvailable($config_ldap) && version_compare(PHP_VERSION, '7.3') < 0) { ldap_control_paged_result_response($ldap_connection, $sr, $cookie); } } while (($cookie !== null) && ($cookie != '')); @@ -3189,7 +3239,7 @@ static function showUserImportForm(AuthLDAP $authldap) { ""; Entity::dropdown(['value' => $_SESSION['ldap_import']['entities_id'], 'entity' => $_SESSION['glpiactiveentities'], - 'on_change' => 'submit()']); + 'on_change' => 'this.form.submit()']); echo ""; } else { //Only one entity is active, store it @@ -3666,16 +3716,14 @@ static function getAllReplicateForAMaster($master_id) { * * @since 0.84 * - * @param object $config_ldap LDAP configuration - * @param boolean $check_config_value Whether to check config values + * @param object $config_ldap LDAP configuration + * @param boolean $check_config_value Whether to check config values * * @return boolean true if maxPageSize can be used, false otherwise */ static function isLdapPageSizeAvailable($config_ldap, $check_config_value = true) { - return ((!$check_config_value - || ($check_config_value && $config_ldap->fields['can_support_pagesize'])) - && function_exists('ldap_control_paged_result') - && function_exists('ldap_control_paged_result_response')); + return (extension_loaded('ldap') && (!$check_config_value + || ($check_config_value && $config_ldap->fields['can_support_pagesize']))); } /** From efc9a72fa17d738def91444233475dda57c533cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Tue, 7 Jan 2020 21:41:39 +0100 Subject: [PATCH 08/10] Update blueimp-file-upload PHP handler --- .../server/php/UploadHandler.php | 126 +++++++++--------- 1 file changed, 66 insertions(+), 60 deletions(-) diff --git a/lib/jqueryplugins/jquery-file-upload/server/php/UploadHandler.php b/lib/jqueryplugins/jquery-file-upload/server/php/UploadHandler.php index 5215e4c0fe..62f65a51f4 100755 --- a/lib/jqueryplugins/jquery-file-upload/server/php/UploadHandler.php +++ b/lib/jqueryplugins/jquery-file-upload/server/php/UploadHandler.php @@ -16,7 +16,7 @@ class UploadHandler protected $options; // PHP File Upload error message codes: - // http://php.net/manual/en/features.file-upload.errors.php + // https://php.net/manual/en/features.file-upload.errors.php protected $error_messages = array( 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini', 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', @@ -43,9 +43,9 @@ class UploadHandler const IMAGETYPE_PNG = 3; protected $image_objects = array(); + protected $response = array(); public function __construct($options = null, $initialize = true, $error_messages = null) { - $this->response = array(); $this->options = array( 'script_url' => $this->get_full_url().'/'.$this->basename($this->get_server_var('SCRIPT_NAME')), 'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/files/', @@ -75,12 +75,12 @@ public function __construct($options = null, $initialize = true, $error_messages ), // By default, allow redirects to the referer protocol+host: 'redirect_allow_target' => '/^'.preg_quote( - parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_SCHEME) - .'://' - .parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_HOST) - .'/', // Trailing slash to not match subdomains by mistake - '/' // preg_quote delimiter param - ).'/', + parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_SCHEME) + .'://' + .parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_HOST) + .'/', // Trailing slash to not match subdomains by mistake + '/' // preg_quote delimiter param + ).'/', // Enable to provide file downloads via GET requests to the PHP script: // 1. Set to 1 to download files via readfile method through PHP // 2. Set to 2 to send a X-Sendfile header for lighttpd/Apache @@ -151,21 +151,21 @@ public function __construct($options = null, $initialize = true, $error_messages 'identify_bin' => 'identify', 'image_versions' => array( // The empty image version key defines options for the original image. - // Keep in mind: these image manipulations are inherited by all other image versions from this point onwards. + // Keep in mind: these image manipulations are inherited by all other image versions from this point onwards. // Also note that the property 'no_cache' is not inherited, since it's not a manipulation. '' => array( // Automatically rotate images based on EXIF meta data: 'auto_orient' => true ), // You can add arrays to generate different versions. - // The name of the key is the name of the version (example: 'medium'). + // The name of the key is the name of the version (example: 'medium'). // the array contains the options to apply. /* 'medium' => array( 'max_width' => 800, 'max_height' => 600 ), - */ + */ 'thumbnail' => array( // Uncomment the following to use a defined directory for the thumbnails // instead of a subdirectory based on the version identifier. @@ -223,13 +223,13 @@ protected function initialize() { protected function get_full_url() { $https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0 || !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && - strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0; + strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0; return ($https ? 'https://' : 'http://'). (!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : ''). (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME']. - ($https && $_SERVER['SERVER_PORT'] === 443 || - $_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))). + ($https && $_SERVER['SERVER_PORT'] === 443 || + $_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))). substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/')); } @@ -324,7 +324,7 @@ protected function get_file_size($file_path, $clear_stat_cache = false) { protected function is_valid_file_object($file_name) { $file_path = $this->get_upload_path($file_name); - if (is_file($file_path) && $file_name[0] !== '.') { + if (strlen($file_name) > 0 && $file_name[0] !== '.' && is_file($file_path)) { return true; } return false; @@ -377,7 +377,11 @@ protected function get_error_message($error) { public function get_config_bytes($val) { $val = trim($val); $last = strtolower($val[strlen($val)-1]); - $val = (int)$val; + if (is_numeric($val)) { + $val = (int)$val; + } else { + $val = (int)substr($val, 0, -1); + } switch ($last) { case 'g': $val *= 1024; @@ -414,7 +418,7 @@ protected function validate($uploaded_file, $file, $error, $index) { if ($this->options['max_file_size'] && ( $file_size > $this->options['max_file_size'] || $file->size > $this->options['max_file_size']) - ) { + ) { $file->error = $this->get_error_message('max_file_size'); return false; } @@ -424,9 +428,9 @@ protected function validate($uploaded_file, $file, $error, $index) { return false; } if (is_int($this->options['max_number_of_files']) && - ($this->count_file_objects() >= $this->options['max_number_of_files']) && - // Ignore additional chunks of existing files: - !is_file($this->get_upload_path($file->name))) { + ($this->count_file_objects() >= $this->options['max_number_of_files']) && + // Ignore additional chunks of existing files: + !is_file($this->get_upload_path($file->name))) { $file->error = $this->get_error_message('max_number_of_files'); return false; } @@ -451,7 +455,7 @@ function_exists('exif_read_data') && unset($tmp); } } - if (!empty($img_width)) { + if (!empty($img_width) && !empty($img_height)) { if ($max_width && $img_width > $max_width) { $file->error = $this->get_error_message('max_width'); return false; @@ -488,12 +492,12 @@ protected function upcount_name($name) { } protected function get_unique_filename($file_path, $name, $size, $type, $error, - $index, $content_range) { + $index, $content_range) { while(is_dir($this->get_upload_path($name))) { $name = $this->upcount_name($name); } // Keep an existing filename if this is part of a chunked upload: - $uploaded_bytes = $this->fix_integer_overflow((int)$content_range[1]); + $uploaded_bytes = $this->fix_integer_overflow((int)@$content_range[1]); while (is_file($this->get_upload_path($name))) { if ($uploaded_bytes === $this->get_file_size( $this->get_upload_path($name))) { @@ -505,10 +509,10 @@ protected function get_unique_filename($file_path, $name, $size, $type, $error, } protected function fix_file_extension($file_path, $name, $size, $type, $error, - $index, $content_range) { + $index, $content_range) { // Add missing file extension for known image types: if (strpos($name, '.') === false && - preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) { + preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) { $name .= '.'.$matches[1]; } if ($this->options['correct_image_extensions']) { @@ -538,7 +542,7 @@ protected function fix_file_extension($file_path, $name, $size, $type, $error, } protected function trim_file_name($file_path, $name, $size, $type, $error, - $index, $content_range) { + $index, $content_range) { // Remove path information and dots around the filename, to prevent uploading // into different directories or replacing hidden system files. // Also remove control characters and spaces (\x00..\x20) around the filename: @@ -561,7 +565,7 @@ protected function trim_file_name($file_path, $name, $size, $type, $error, } protected function get_file_name($file_path, $name, $size, $type, $error, - $index, $content_range) { + $index, $content_range) { $name = $this->trim_file_name($file_path, $name, $size, $type, $error, $index, $content_range); return $this->get_unique_filename( @@ -795,25 +799,26 @@ protected function gd_create_scaled_image($file_name, $version, $options) { // Handle transparency in GIF and PNG images: switch ($type) { case 'gif': - case 'png': imagecolortransparent($new_img, imagecolorallocate($new_img, 0, 0, 0)); + break; case 'png': + imagecolortransparent($new_img, imagecolorallocate($new_img, 0, 0, 0)); imagealphablending($new_img, false); imagesavealpha($new_img, true); break; } $success = imagecopyresampled( - $new_img, - $src_img, - $dst_x, - $dst_y, - 0, - 0, - $new_width, - $new_height, - $img_width, - $img_height - ) && $write_func($new_img, $new_file_path, $image_quality); + $new_img, + $src_img, + $dst_x, + $dst_y, + 0, + 0, + $new_width, + $new_height, + $img_width, + $img_height + ) && $write_func($new_img, $new_file_path, $image_quality); $this->gd_set_image_object($file_path, $new_img); return $success; } @@ -827,7 +832,12 @@ protected function imagick_get_image_object($file_path, $no_cache = false) { $image->setResourceLimit($type, $limit); } } - $image->readImage($file_path); + try { + $image->readImage($file_path); + } catch (ImagickException $e) { + error_log($e->getMessage()); + return null; + } $this->image_objects[$file_path] = $image; } return $this->image_objects[$file_path]; @@ -884,6 +894,7 @@ protected function imagick_create_scaled_image($file_name, $version, $options) { $file_path, !empty($options['crop']) || !empty($options['no_cache']) ); + if (is_null($image)) return false; if ($image->getImageFormat() === 'GIF') { // Handle animated GIFs: $images = $image->coalesceImages(); @@ -896,32 +907,28 @@ protected function imagick_create_scaled_image($file_name, $version, $options) { $image_oriented = false; if (!empty($options['auto_orient'])) { $image_oriented = $this->imagick_orient_image($image); - } - - $image_resize = false; + } + $image_resize = false; $new_width = $max_width = $img_width = $image->getImageWidth(); - $new_height = $max_height = $img_height = $image->getImageHeight(); - + $new_height = $max_height = $img_height = $image->getImageHeight(); // use isset(). User might be setting max_width = 0 (auto in regular resizing). Value 0 would be considered empty when you use empty() if (isset($options['max_width'])) { - $image_resize = true; - $new_width = $max_width = $options['max_width']; + $image_resize = true; + $new_width = $max_width = $options['max_width']; } if (isset($options['max_height'])) { $image_resize = true; $new_height = $max_height = $options['max_height']; } - $image_strip = (isset($options['strip']) ? $options['strip'] : false); - - if ( !$image_oriented && ($max_width >= $img_width) && ($max_height >= $img_height) && !$image_strip && empty($options["jpeg_quality"]) ) { + if ( !$image_oriented && ($max_width >= $img_width) && ($max_height >= $img_height) && !$image_strip && empty($options["jpeg_quality"]) ) { if ($file_path !== $new_file_path) { return copy($file_path, $new_file_path); } return true; } $crop = (isset($options['crop']) ? $options['crop'] : false); - + if ($crop) { $x = 0; $y = 0; @@ -1111,14 +1118,14 @@ protected function handle_image_file($file_path, $file) { } if (count($failed_versions)) { $file->error = $this->get_error_message('image_resize') - .' ('.implode($failed_versions, ', ').')'; + .' ('.implode(', ', $failed_versions).')'; } // Free memory: $this->destroy_image_object($file_path); } protected function handle_file_upload($uploaded_file, $name, $size, $type, $error, - $index = null, $content_range = null) { + $index = null, $content_range = null) { $file = new \stdClass(); $file->name = $this->get_file_name($uploaded_file, $name, $size, $type, $error, $index, $content_range); @@ -1319,8 +1326,7 @@ public function generate_response($content, $print_response = true) { $json = json_encode($content); $redirect = stripslashes($this->get_post_param('redirect')); if ($redirect && preg_match($this->options['redirect_allow_target'], $redirect)) { - $this->header('Location: '.sprintf($redirect, rawurlencode($json))); - return; + return $this->header('Location: '.sprintf($redirect, rawurlencode($json))); } $this->head(); if ($this->get_server_var('HTTP_CONTENT_RANGE')) { @@ -1388,7 +1394,7 @@ public function post($print_response = true) { $content_range_header = $this->get_server_var('HTTP_CONTENT_RANGE'); $content_range = $content_range_header ? preg_split('/[^0-9]+/', $content_range_header) : null; - $size = $content_range ? $content_range[3] : null; + $size = @$content_range[3]; $files = array(); if ($upload) { if (is_array($upload['tmp_name'])) { @@ -1411,11 +1417,11 @@ public function post($print_response = true) { $files[] = $this->handle_file_upload( isset($upload['tmp_name']) ? $upload['tmp_name'] : null, $file_name ? $file_name : (isset($upload['name']) ? - $upload['name'] : null), + $upload['name'] : null), $size ? $size : (isset($upload['size']) ? - $upload['size'] : $this->get_server_var('CONTENT_LENGTH')), + $upload['size'] : $this->get_server_var('CONTENT_LENGTH')), isset($upload['type']) ? - $upload['type'] : $this->get_server_var('CONTENT_TYPE'), + $upload['type'] : $this->get_server_var('CONTENT_TYPE'), isset($upload['error']) ? $upload['error'] : null, null, $content_range @@ -1434,7 +1440,7 @@ public function delete($print_response = true) { $response = array(); foreach ($file_names as $file_name) { $file_path = $this->get_upload_path($file_name); - $success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path); + $success = strlen($file_name) > 0 && $file_name[0] !== '.' && is_file($file_path) && unlink($file_path); if ($success) { foreach ($this->options['image_versions'] as $version => $options) { if (!empty($version)) { From 53627ec1e7e11e7a38bcdc1273ec9ddd6ab591b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Tue, 7 Jan 2020 21:47:38 +0100 Subject: [PATCH 09/10] Fix travis configuration --- .travis.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d5491bab5..02c470e615 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,15 @@ language: php sudo: required -dist: trusty -env: - - DB=mysql +services: + - mysql before_script: - phpenv config-rm xdebug.ini || true - ./tests/LDAP/ldap_run.sh - composer self-update - - sed -e '/"php":/d' -i composer.json - rm -f composer.lock + - composer config --unset platform - composer install --optimize-autoloader - mysql -u root -e 'create database glpitest;' - bin/console glpi:database:install --config-dir=./tests --no-interaction --db-name=glpitest --db-user=root @@ -20,10 +19,10 @@ script: - mysql -u root -e 'select version();' - composer testldap -#note: default maria version is 5.5 for all main php versions list exept nightly matrix: include: - php: 5.6 + dist: trusty addons: apt: packages: @@ -32,8 +31,8 @@ matrix: hosts: - openldap - php: 7.0 + dist: xenial addons: - mariadb: 10.2 apt: packages: - ldap-utils @@ -41,8 +40,8 @@ matrix: hosts: - openldap - php: 7.1 + dist: xenial addons: - mariadb: 10.1 apt: packages: - ldap-utils @@ -50,6 +49,7 @@ matrix: hosts: - openldap - php: 7.2 + dist: bionic addons: apt: packages: @@ -58,6 +58,7 @@ matrix: hosts: - openldap - php: 7.3 + dist: bionic addons: apt: packages: @@ -66,6 +67,7 @@ matrix: hosts: - openldap - php: 7.4 + dist: bionic addons: apt: packages: @@ -74,6 +76,7 @@ matrix: hosts: - openldap - php: nightly + dist: bionic addons: apt: packages: From 0cc11eef00dc1ff7f2fe6988ff1fb471479e9a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Thu, 3 Oct 2019 13:51:54 +0200 Subject: [PATCH 10/10] Fix 'Trying to access array offset on value of type bool' on LDAP sync --- inc/authldap.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inc/authldap.class.php b/inc/authldap.class.php index 10f58b0efb..245b6519ae 100644 --- a/inc/authldap.class.php +++ b/inc/authldap.class.php @@ -2490,12 +2490,13 @@ static function ldapImportUserByServerId(array $params, $action, $ldap_server, try { $infos = self::searchUserDn($ds, $attribs); - $login = self::getFieldValue($infos, $search_parameters['fields'][$search_parameters['method']]); if ($infos && $infos['dn']) { $user_dn = $infos['dn']; $user = new User(); + $login = self::getFieldValue($infos, $search_parameters['fields'][$search_parameters['method']]); + //Get information from LDAP if ($user->getFromLDAP($ds, $config_ldap->fields, $user_dn, addslashes($login), ($action == self::ACTION_IMPORT))) {