diff --git a/.github/build/full.json b/.github/build/full.json index 7e93d7ebec..69743931de 100644 --- a/.github/build/full.json +++ b/.github/build/full.json @@ -22,7 +22,7 @@ }, "metarefresh": { "repository": "simplesamlphp/simplesamlphp-module-metarefresh", - "version": "~1.2.2" + "version": "~1.2.4" }, "radius": { "repository": "simplesamlphp/simplesamlphp-module-radius", diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 4a51a746c7..51764f4b84 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -13,32 +13,150 @@ on: # yamllint disable-line rule:truthy - '**.md' jobs: + phplinter: + name: 'PHP-Linter' + strategy: + fail-fast: false + matrix: + php-version: ['8.1', '8.2', '8.3', '8.4'] + + uses: simplesamlphp/simplesamlphp-test-framework/.github/workflows/reusable_phplinter.yml@v1.9.2 + with: + php-version: ${{ matrix.php-version }} + linter: - name: Linter - runs-on: ['ubuntu-latest'] + name: 'Linter' + strategy: + fail-fast: false + + uses: simplesamlphp/simplesamlphp-test-framework/.github/workflows/reusable_linter.yml@v1.9.2 + with: + enable_eslinter: true + enable_jsonlinter: true + enable_stylelinter: true + enable_yamllinter: true + + unit-tests-linux: + name: "Syntax and unit tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }}" + runs-on: ${{ matrix.operating-system }} + needs: [phplinter, linter] + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest] + php-versions: ['8.1', '8.2', '8.3', '8.4'] + + steps: + - name: Setup PHP, with composer and extensions + # https://github.com/shivammathur/setup-php + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: intl, mbstring, mysql, pdo, pdo_sqlite, soap, xml + tools: composer:v2 + ini-values: error_reporting=E_ALL + coverage: xdebug + + - name: Setup problem matchers for PHP + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + + - name: Setup problem matchers for PHPUnit + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Set git to use LF + run: | + git config --global core.autocrlf false + git config --global core.eol lf + + - uses: actions/checkout@v4 + + - name: Copy config.php.dist to config.php + run: cp config/config.php.dist config/config.php + + - name: Create SimpleSAMLphp cache directory + run: sudo mkdir -p /var/cache/simplesamlphp && sudo chmod 777 /var/cache/simplesamlphp + + - name: Get composer cache directory + run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$GITHUB_ENV" + + - name: Cache composer dependencies + uses: actions/cache@v4 + with: + path: $COMPOSER_CACHE + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Run unit tests with coverage + if: ${{ matrix.php-versions == '8.1' }} + run: ./vendor/bin/phpunit + + - name: Run unit tests (no coverage) + if: ${{ matrix.php-versions != '8.1' }} + run: ./vendor/bin/phpunit --no-coverage + + - name: Save coverage data + if: ${{ matrix.php-versions == '8.1' }} + uses: actions/upload-artifact@v4 + with: + name: coverage-data + path: ${{ github.workspace }}/build + + unit-tests-windows: + name: "Syntax and unit tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }}" + runs-on: ${{ matrix.operating-system }} + needs: [phplinter, linter] + strategy: + fail-fast: true + matrix: + operating-system: [windows-latest] + php-versions: ['8.1', '8.2', '8.3', '8.4'] steps: + - name: Setup PHP, with composer and extensions + # https://github.com/shivammathur/setup-php + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: intl, mbstring, mysql, pdo, pdo_sqlite, soap, xml + tools: composer:v2 + ini-values: error_reporting=E_ALL + coverage: none + + - name: Setup problem matchers for PHP + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + + - name: Setup problem matchers for PHPUnit + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Set git to use LF + run: | + git config --global core.autocrlf false + git config --global core.eol lf + - uses: actions/checkout@v4 + + - name: Get composer cache directory + run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$env:GITHUB_ENV" + + - name: Cache composer dependencies + uses: actions/cache@v4 with: - fetch-depth: 0 - - - name: Lint Code Base - uses: super-linter/super-linter/slim@v6 - env: - # To report GitHub Actions status checks - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - LOG_LEVEL: NOTICE - VALIDATE_ALL_CODEBASE: true - LINTER_RULES_PATH: 'tools/linters' - VALIDATE_CSS: true - VALIDATE_JAVASCRIPT_ES: true - VALIDATE_JSON: true - VALIDATE_PHP_BUILTIN: true - VALIDATE_YAML: true - VALIDATE_GITHUB_ACTIONS: true + path: $COMPOSER_CACHE + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader --no-scripts + + - name: Run unit tests + run: ./vendor/bin/phpunit --no-coverage quality: name: Quality control + needs: [unit-tests-linux] runs-on: [ubuntu-latest] steps: @@ -107,6 +225,7 @@ jobs: security: name: Security checks + needs: [unit-tests-linux] runs-on: [ubuntu-latest] steps: - name: Setup PHP, with composer and extensions @@ -145,118 +264,6 @@ jobs: - name: Security check for updated dependencies run: composer audit - unit-tests-linux: - name: "Syntax and unit tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }}" - runs-on: ${{ matrix.operating-system }} - needs: [linter, quality, security] - strategy: - fail-fast: false - matrix: - operating-system: [ubuntu-latest] - php-versions: ['8.1', '8.2', '8.3', '8.4'] - - steps: - - name: Setup PHP, with composer and extensions - # https://github.com/shivammathur/setup-php - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: intl, mbstring, mysql, pdo, pdo_sqlite, xml - tools: composer:v2 - ini-values: error_reporting=E_ALL - coverage: xdebug - - - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - - - name: Setup problem matchers for PHPUnit - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - name: Set git to use LF - run: | - git config --global core.autocrlf false - git config --global core.eol lf - - - uses: actions/checkout@v4 - - - name: Get composer cache directory - run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$GITHUB_ENV" - - - name: Cache composer dependencies - uses: actions/cache@v4 - with: - path: $COMPOSER_CACHE - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install Composer dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Run unit tests with coverage - if: ${{ matrix.php-versions == '8.1' }} - run: ./vendor/bin/phpunit - - - name: Run unit tests (no coverage) - if: ${{ matrix.php-versions != '8.1' }} - run: ./vendor/bin/phpunit --no-coverage - - - name: Save coverage data - if: ${{ matrix.php-versions == '8.1' }} - uses: actions/upload-artifact@v4 - with: - name: coverage-data - path: ${{ github.workspace }}/build - - unit-tests-windows: - name: "Syntax and unit tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }}" - runs-on: ${{ matrix.operating-system }} - needs: [linter, quality, security] - strategy: - fail-fast: true - matrix: - operating-system: [windows-latest] - php-versions: ['8.1', '8.2', '8.3', '8.4'] - - steps: - - name: Setup PHP, with composer and extensions - # https://github.com/shivammathur/setup-php - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: intl, mbstring, mysql, pdo, pdo_sqlite, xml - tools: composer:v2 - ini-values: error_reporting=E_ALL - coverage: none - - - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - - - name: Setup problem matchers for PHPUnit - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - name: Set git to use LF - run: | - git config --global core.autocrlf false - git config --global core.eol lf - - - uses: actions/checkout@v4 - - - name: Get composer cache directory - run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$env:GITHUB_ENV" - - - name: Cache composer dependencies - uses: actions/cache@v4 - with: - path: $COMPOSER_CACHE - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install Composer dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Run unit tests - run: ./vendor/bin/phpunit --no-coverage - coverage: name: Code coverage runs-on: [ubuntu-latest] diff --git a/composer.json b/composer.json index 6dc46fa974..dd6959df8f 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,7 @@ "phpmailer/phpmailer": "^6.8", "psr/log": "^3.0", "simplesamlphp/assert": "^1.1", - "simplesamlphp/composer-module-installer": "^1.3", + "simplesamlphp/composer-module-installer": "~1.3.6", "simplesamlphp/saml2": "^4.17", "simplesamlphp/simplesamlphp-assets-base": "~2.3.0", "simplesamlphp/xml-security": "^1.7", @@ -94,7 +94,7 @@ "mikey179/vfsstream": "~1.6", "predis/predis": "^2.2", "simplesamlphp/simplesamlphp-module-adfs": "^2.1", - "simplesamlphp/simplesamlphp-test-framework": "^1.5.4", + "simplesamlphp/simplesamlphp-test-framework": "^1.9.2", "symfony/translation": "^6.4" }, "suggest": { @@ -130,5 +130,5 @@ "translations:unused": "php bin/translations translations:unused", "translations:update:translatable": "php bin/translations translations:update:translatable" }, - "version": "v2.3.7" + "version": "v2.3.8" } diff --git a/composer.lock b/composer.lock index 63f8b18461..beff2e3f01 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7c92b994b47eaf7496d03fa4d1905169", + "content-hash": "d5a4c080ba45815db6d946b9838add1d", "packages": [ { "name": "gettext/gettext", @@ -82,16 +82,16 @@ }, { "name": "gettext/languages", - "version": "2.10.0", + "version": "2.12.1", "source": { "type": "git", "url": "https://github.com/php-gettext/Languages.git", - "reference": "4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab" + "reference": "0b0b0851c55168e1dfb14305735c64019732b5f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-gettext/Languages/zipball/4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab", - "reference": "4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab", + "url": "https://api.github.com/repos/php-gettext/Languages/zipball/0b0b0851c55168e1dfb14305735c64019732b5f1", + "reference": "0b0b0851c55168e1dfb14305735c64019732b5f1", "shasum": "" }, "require": { @@ -101,7 +101,8 @@ "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4" }, "bin": [ - "bin/export-plural-rules" + "bin/export-plural-rules", + "bin/import-cldr-data" ], "type": "library", "autoload": { @@ -140,7 +141,7 @@ ], "support": { "issues": "https://github.com/php-gettext/Languages/issues", - "source": "https://github.com/php-gettext/Languages/tree/2.10.0" + "source": "https://github.com/php-gettext/Languages/tree/2.12.1" }, "funding": [ { @@ -152,7 +153,7 @@ "type": "github" } ], - "time": "2022-10-18T15:00:10+00:00" + "time": "2025-03-19T11:14:02+00:00" }, { "name": "gettext/translator", @@ -230,16 +231,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.7.0", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", "shasum": "" }, "require": { @@ -326,7 +327,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.0" + "source": "https://github.com/guzzle/psr7/tree/2.7.1" }, "funding": [ { @@ -342,20 +343,20 @@ "type": "tidelift" } ], - "time": "2024-07-18T11:15:46+00:00" + "time": "2025-03-27T12:30:47+00:00" }, { "name": "phpmailer/phpmailer", - "version": "v6.9.3", + "version": "v6.10.0", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e" + "reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2f5c94fe7493efc213f643c23b1b1c249d40f47e", - "reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144", + "reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144", "shasum": "" }, "require": { @@ -415,7 +416,7 @@ "description": "PHPMailer is a full-featured email creation and transfer class for PHP", "support": { "issues": "https://github.com/PHPMailer/PHPMailer/issues", - "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.3" + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.10.0" }, "funding": [ { @@ -423,7 +424,7 @@ "type": "github" } ], - "time": "2024-11-24T18:04:13+00:00" + "time": "2025-04-24T15:19:31+00:00" }, { "name": "psr/cache", @@ -882,26 +883,26 @@ }, { "name": "simplesamlphp/composer-module-installer", - "version": "v1.4.0", + "version": "v1.3.6", "source": { "type": "git", "url": "https://github.com/simplesamlphp/composer-module-installer.git", - "reference": "edb2155d200e2a208816d06f42cfa78bfd9e7cf4" + "reference": "58ff5fcb1e060015ba254c993ae11594662ffd24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/composer-module-installer/zipball/edb2155d200e2a208816d06f42cfa78bfd9e7cf4", - "reference": "edb2155d200e2a208816d06f42cfa78bfd9e7cf4", + "url": "https://api.github.com/repos/simplesamlphp/composer-module-installer/zipball/58ff5fcb1e060015ba254c993ae11594662ffd24", + "reference": "58ff5fcb1e060015ba254c993ae11594662ffd24", "shasum": "" }, "require": { - "composer-plugin-api": "^2.6", - "php": "^8.1", - "simplesamlphp/assert": "^1.6" + "composer-plugin-api": "^1.1 || ^2.0", + "php": "^7.4 || ^8.0", + "simplesamlphp/assert": "^0.8.0 || ^1.0" }, "require-dev": { - "composer/composer": "^2.8.3", - "simplesamlphp/simplesamlphp-test-framework": "^1.8.0" + "composer/composer": "^2.4", + "simplesamlphp/simplesamlphp-test-framework": "^1.2.1" }, "type": "composer-plugin", "extra": { @@ -919,64 +920,22 @@ "description": "A Composer plugin that allows installing SimpleSAMLphp modules through Composer.", "support": { "issues": "https://github.com/simplesamlphp/composer-module-installer/issues", - "source": "https://github.com/simplesamlphp/composer-module-installer/tree/v1.4.0" - }, - "time": "2024-12-08T16:57:03+00:00" - }, - { - "name": "simplesamlphp/composer-xmlprovider-installer", - "version": "v1.0.1", - "source": { - "type": "git", - "url": "https://github.com/simplesamlphp/composer-xmlprovider-installer.git", - "reference": "ce09a877a1de9469f1a872f04703d75d6bafcdc6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/composer-xmlprovider-installer/zipball/ce09a877a1de9469f1a872f04703d75d6bafcdc6", - "reference": "ce09a877a1de9469f1a872f04703d75d6bafcdc6", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.0", - "php": "^8.1" - }, - "require-dev": { - "composer/composer": "^2.4", - "simplesamlphp/simplesamlphp-test-framework": "^1.5.4" - }, - "type": "composer-plugin", - "extra": { - "class": "SimpleSAML\\Composer\\XMLProvider\\XMLProviderInstallerPlugin" - }, - "autoload": { - "psr-4": { - "SimpleSAML\\Composer\\XMLProvider\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1-only" - ], - "description": "A composer plugin that will auto-generate a classmap with all classes that implement SerializableElementInterface.", - "support": { - "issues": "https://github.com/simplesamlphp/composer-xmlprovider-installer/issues", - "source": "https://github.com/simplesamlphp/composer-xmlprovider-installer/tree/v1.0.1" + "source": "https://github.com/simplesamlphp/composer-module-installer/tree/v1.3.6" }, - "time": "2024-09-15T22:34:50+00:00" + "time": "2025-03-19T20:38:37+00:00" }, { "name": "simplesamlphp/saml2", - "version": "v4.17.0", + "version": "v4.18.1", "source": { "type": "git", "url": "https://github.com/simplesamlphp/saml2.git", - "reference": "bdf16d1021363a0819c35806124a20e74a78c2c9" + "reference": "78b1c6735db8e2f78dcea9bcac0317ad2b200d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/bdf16d1021363a0819c35806124a20e74a78c2c9", - "reference": "bdf16d1021363a0819c35806124a20e74a78c2c9", + "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/78b1c6735db8e2f78dcea9bcac0317ad2b200d72", + "reference": "78b1c6735db8e2f78dcea9bcac0317ad2b200d72", "shasum": "" }, "require": { @@ -1022,9 +981,9 @@ "description": "SAML2 PHP library from SimpleSAMLphp", "support": { "issues": "https://github.com/simplesamlphp/saml2/issues", - "source": "https://github.com/simplesamlphp/saml2/tree/v4.17.0" + "source": "https://github.com/simplesamlphp/saml2/tree/v4.18.1" }, - "time": "2025-03-11T17:35:33+00:00" + "time": "2025-03-16T11:37:44+00:00" }, { "name": "simplesamlphp/simplesamlphp-assets-base", @@ -1064,16 +1023,16 @@ }, { "name": "simplesamlphp/xml-common", - "version": "v1.24.2", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/simplesamlphp/xml-common.git", - "reference": "0521d7fa82ded0be994cf42e0365a4ac53c95789" + "reference": "2250c05aa0062bba4baad9d2357e94f9aa10ffc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/xml-common/zipball/0521d7fa82ded0be994cf42e0365a4ac53c95789", - "reference": "0521d7fa82ded0be994cf42e0365a4ac53c95789", + "url": "https://api.github.com/repos/simplesamlphp/xml-common/zipball/2250c05aa0062bba4baad9d2357e94f9aa10ffc0", + "reference": "2250c05aa0062bba4baad9d2357e94f9aa10ffc0", "shasum": "" }, "require": { @@ -1084,12 +1043,11 @@ "ext-pcre": "*", "ext-spl": "*", "php": "^8.1", - "simplesamlphp/assert": "~1.8.0", - "simplesamlphp/composer-xmlprovider-installer": "~1.0.0", - "symfony/finder": "^6.4" + "simplesamlphp/assert": "~1.8.1", + "symfony/finder": "~6.4.0" }, "require-dev": { - "simplesamlphp/simplesamlphp-test-framework": "^1.7" + "simplesamlphp/simplesamlphp-test-framework": "~1.9.2" }, "type": "simplesamlphp-xmlprovider", "autoload": { @@ -1121,20 +1079,20 @@ "issues": "https://github.com/simplesamlphp/xml-common/issues", "source": "https://github.com/simplesamlphp/xml-common" }, - "time": "2025-01-12T10:33:16+00:00" + "time": "2025-06-02T21:40:38+00:00" }, { "name": "simplesamlphp/xml-security", - "version": "v1.13.0", + "version": "v1.13.2", "source": { "type": "git", "url": "https://github.com/simplesamlphp/xml-security.git", - "reference": "ae601fb4398b533a2ba48e2c44fd972e2f20b474" + "reference": "a7f2e09632da1179ecb9a021c3c2fbcbcd28071a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/xml-security/zipball/ae601fb4398b533a2ba48e2c44fd972e2f20b474", - "reference": "ae601fb4398b533a2ba48e2c44fd972e2f20b474", + "url": "https://api.github.com/repos/simplesamlphp/xml-security/zipball/a7f2e09632da1179ecb9a021c3c2fbcbcd28071a", + "reference": "a7f2e09632da1179ecb9a021c3c2fbcbcd28071a", "shasum": "" }, "require": { @@ -1145,11 +1103,11 @@ "ext-pcre": "*", "ext-spl": "*", "php": "^8.1", - "simplesamlphp/assert": "~1.8.0", - "simplesamlphp/xml-common": "~1.24.0" + "simplesamlphp/assert": "~1.8.1", + "simplesamlphp/xml-common": "~1.25.0" }, "require-dev": { - "simplesamlphp/simplesamlphp-test-framework": "~1.8.0" + "simplesamlphp/simplesamlphp-test-framework": "~1.9.2" }, "type": "simplesamlphp-xmlprovider", "autoload": { @@ -1183,22 +1141,22 @@ ], "support": { "issues": "https://github.com/simplesamlphp/xml-security/issues", - "source": "https://github.com/simplesamlphp/xml-security/tree/v1.13.0" + "source": "https://github.com/simplesamlphp/xml-security/tree/v1.13.2" }, - "time": "2025-01-08T22:58:06+00:00" + "time": "2025-06-04T21:49:04+00:00" }, { "name": "symfony/cache", - "version": "v6.4.19", + "version": "v6.4.21", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "342e87b15ac02e4b4f0924ddc368e75d5262aab3" + "reference": "d1abcf763a7414f2e572f676f22da7a06c8cd9ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/342e87b15ac02e4b4f0924ddc368e75d5262aab3", - "reference": "342e87b15ac02e4b4f0924ddc368e75d5262aab3", + "url": "https://api.github.com/repos/symfony/cache/zipball/d1abcf763a7414f2e572f676f22da7a06c8cd9ee", + "reference": "d1abcf763a7414f2e572f676f22da7a06c8cd9ee", "shasum": "" }, "require": { @@ -1265,7 +1223,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.19" + "source": "https://github.com/symfony/cache/tree/v6.4.21" }, "funding": [ { @@ -1281,20 +1239,20 @@ "type": "tidelift" } ], - "time": "2025-02-26T09:12:57+00:00" + "time": "2025-04-08T08:21:20+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b" + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", - "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/5d68a57d66910405e5c0b63d6f0af941e66fc868", + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868", "shasum": "" }, "require": { @@ -1308,7 +1266,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -1341,7 +1299,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/cache-contracts/tree/v3.6.0" }, "funding": [ { @@ -1357,20 +1315,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-03-13T15:25:07+00:00" }, { "name": "symfony/config", - "version": "v6.4.14", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "4e55e7e4ffddd343671ea972216d4509f46c22ef" + "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/4e55e7e4ffddd343671ea972216d4509f46c22ef", - "reference": "4e55e7e4ffddd343671ea972216d4509f46c22ef", + "url": "https://api.github.com/repos/symfony/config/zipball/af5917a3b1571f54689e56677a3f06440d2fe4c7", + "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7", "shasum": "" }, "require": { @@ -1416,7 +1374,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.4.14" + "source": "https://github.com/symfony/config/tree/v6.4.22" }, "funding": [ { @@ -1432,20 +1390,20 @@ "type": "tidelift" } ], - "time": "2024-11-04T11:33:53+00:00" + "time": "2025-05-14T06:00:01+00:00" }, { "name": "symfony/console", - "version": "v6.4.17", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "799445db3f15768ecc382ac5699e6da0520a0a04" + "reference": "7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/799445db3f15768ecc382ac5699e6da0520a0a04", - "reference": "799445db3f15768ecc382ac5699e6da0520a0a04", + "url": "https://api.github.com/repos/symfony/console/zipball/7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3", + "reference": "7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3", "shasum": "" }, "require": { @@ -1510,7 +1468,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.17" + "source": "https://github.com/symfony/console/tree/v6.4.22" }, "funding": [ { @@ -1526,20 +1484,20 @@ "type": "tidelift" } ], - "time": "2024-12-07T12:07:30+00:00" + "time": "2025-05-07T07:05:04+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.19", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "b343c3b2f1539fe41331657b37d5c96c1d1ea842" + "reference": "8cb11f833d1f5bfbb2df97dfc23c92b4d42c18d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b343c3b2f1539fe41331657b37d5c96c1d1ea842", - "reference": "b343c3b2f1539fe41331657b37d5c96c1d1ea842", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/8cb11f833d1f5bfbb2df97dfc23c92b4d42c18d9", + "reference": "8cb11f833d1f5bfbb2df97dfc23c92b4d42c18d9", "shasum": "" }, "require": { @@ -1547,7 +1505,7 @@ "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.2.10|^7.0" + "symfony/var-exporter": "^6.4.20|^7.2.5" }, "conflict": { "ext-psr": "<1.1|>=2", @@ -1591,7 +1549,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.19" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.22" }, "funding": [ { @@ -1607,20 +1565,20 @@ "type": "tidelift" } ], - "time": "2025-02-20T10:02:49+00:00" + "time": "2025-05-17T07:35:26+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -1633,7 +1591,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -1658,7 +1616,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -1674,20 +1632,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.19", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "3d4e55cd2b8f1979a65eba9ab749d6466c316f71" + "reference": "ce765a2d28b3cce61de1fb916e207767a73171d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/3d4e55cd2b8f1979a65eba9ab749d6466c316f71", - "reference": "3d4e55cd2b8f1979a65eba9ab749d6466c316f71", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/ce765a2d28b3cce61de1fb916e207767a73171d1", + "reference": "ce765a2d28b3cce61de1fb916e207767a73171d1", "shasum": "" }, "require": { @@ -1733,7 +1691,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.19" + "source": "https://github.com/symfony/error-handler/tree/v6.4.22" }, "funding": [ { @@ -1749,7 +1707,7 @@ "type": "tidelift" } ], - "time": "2025-02-02T20:16:33+00:00" + "time": "2025-05-28T12:00:15+00:00" }, { "name": "symfony/event-dispatcher", @@ -1833,16 +1791,16 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { @@ -1856,7 +1814,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -1889,7 +1847,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -1905,7 +1863,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/filesystem", @@ -2039,16 +1997,16 @@ }, { "name": "symfony/framework-bundle", - "version": "v6.4.19", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "078a6f11cb34d208d6efc74003d77f66a09fa3c2" + "reference": "b1de19b2083484d0ce945977f6c6484e9e493a2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/078a6f11cb34d208d6efc74003d77f66a09fa3c2", - "reference": "078a6f11cb34d208d6efc74003d77f66a09fa3c2", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/b1de19b2083484d0ce945977f6c6484e9e493a2e", + "reference": "b1de19b2083484d0ce945977f6c6484e9e493a2e", "shasum": "" }, "require": { @@ -2168,7 +2126,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.4.19" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.22" }, "funding": [ { @@ -2184,20 +2142,20 @@ "type": "tidelift" } ], - "time": "2025-02-26T07:27:07+00:00" + "time": "2025-05-14T07:14:36+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.18", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "d0492d6217e5ab48f51fca76f64cf8e78919d0db" + "reference": "6b7c97fe1ddac8df3cc9ba6410c8abc683e148ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d0492d6217e5ab48f51fca76f64cf8e78919d0db", - "reference": "d0492d6217e5ab48f51fca76f64cf8e78919d0db", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6b7c97fe1ddac8df3cc9ba6410c8abc683e148ae", + "reference": "6b7c97fe1ddac8df3cc9ba6410c8abc683e148ae", "shasum": "" }, "require": { @@ -2245,7 +2203,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.18" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.22" }, "funding": [ { @@ -2261,20 +2219,20 @@ "type": "tidelift" } ], - "time": "2025-01-09T15:48:56+00:00" + "time": "2025-05-11T15:36:20+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.19", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "88f2c9f7feff86bb7b9105c5151bc2c1404cd64c" + "reference": "15c105b839a7cfa1bc0989c091bfb6477f23b673" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/88f2c9f7feff86bb7b9105c5151bc2c1404cd64c", - "reference": "88f2c9f7feff86bb7b9105c5151bc2c1404cd64c", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/15c105b839a7cfa1bc0989c091bfb6477f23b673", + "reference": "15c105b839a7cfa1bc0989c091bfb6477f23b673", "shasum": "" }, "require": { @@ -2359,7 +2317,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.19" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.22" }, "funding": [ { @@ -2375,20 +2333,20 @@ "type": "tidelift" } ], - "time": "2025-02-26T10:51:37+00:00" + "time": "2025-05-29T07:23:40+00:00" }, { "name": "symfony/intl", - "version": "v6.4.15", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "b1d5e8d82615b60f229216edfee0b59e2ef66da6" + "reference": "aaecb52f18a6f95766a239ca0a6cc0df983d92cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/b1d5e8d82615b60f229216edfee0b59e2ef66da6", - "reference": "b1d5e8d82615b60f229216edfee0b59e2ef66da6", + "url": "https://api.github.com/repos/symfony/intl/zipball/aaecb52f18a6f95766a239ca0a6cc0df983d92cc", + "reference": "aaecb52f18a6f95766a239ca0a6cc0df983d92cc", "shasum": "" }, "require": { @@ -2442,7 +2400,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.4.15" + "source": "https://github.com/symfony/intl/tree/v6.4.22" }, "funding": [ { @@ -2458,7 +2416,7 @@ "type": "tidelift" } ], - "time": "2024-11-08T15:28:48+00:00" + "time": "2025-05-04T12:02:38+00:00" }, { "name": "symfony/password-hasher", @@ -2534,7 +2492,7 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -2593,7 +2551,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { @@ -2613,7 +2571,7 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -2671,7 +2629,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -2691,16 +2649,16 @@ }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78" + "reference": "763d2a91fea5681509ca01acbc1c5e450d127811" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78", - "reference": "d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/763d2a91fea5681509ca01acbc1c5e450d127811", + "reference": "763d2a91fea5681509ca01acbc1c5e450d127811", "shasum": "" }, "require": { @@ -2755,7 +2713,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.32.0" }, "funding": [ { @@ -2771,11 +2729,11 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-21T18:38:29+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -2836,7 +2794,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -2856,19 +2814,20 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -2916,7 +2875,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -2932,11 +2891,11 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", @@ -2992,7 +2951,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" }, "funding": [ { @@ -3012,16 +2971,16 @@ }, { "name": "symfony/routing", - "version": "v6.4.18", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "e9bfc94953019089acdfb9be51c1b9142c4afa68" + "reference": "1f5234e8457164a3a0038a4c0a4ba27876a9c670" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/e9bfc94953019089acdfb9be51c1b9142c4afa68", - "reference": "e9bfc94953019089acdfb9be51c1b9142c4afa68", + "url": "https://api.github.com/repos/symfony/routing/zipball/1f5234e8457164a3a0038a4c0a4ba27876a9c670", + "reference": "1f5234e8457164a3a0038a4c0a4ba27876a9c670", "shasum": "" }, "require": { @@ -3075,7 +3034,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.18" + "source": "https://github.com/symfony/routing/tree/v6.4.22" }, "funding": [ { @@ -3091,20 +3050,20 @@ "type": "tidelift" } ], - "time": "2025-01-09T08:51:02+00:00" + "time": "2025-04-27T16:08:38+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { @@ -3122,7 +3081,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -3158,7 +3117,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -3174,20 +3133,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "symfony/string", - "version": "v6.4.15", + "version": "v6.4.21", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f" + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", - "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", + "url": "https://api.github.com/repos/symfony/string/zipball/73e2c6966a5aef1d4892873ed5322245295370c6", + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6", "shasum": "" }, "require": { @@ -3244,7 +3203,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.15" + "source": "https://github.com/symfony/string/tree/v6.4.21" }, "funding": [ { @@ -3260,20 +3219,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:31:12+00:00" + "time": "2025-04-18T15:23:29+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", "shasum": "" }, "require": { @@ -3286,7 +3245,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -3322,7 +3281,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" }, "funding": [ { @@ -3338,20 +3297,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-27T08:32:26+00:00" }, { "name": "symfony/twig-bridge", - "version": "v6.4.19", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "d6aecb7196bf610e63ebb64f937c33878d5d03b1" + "reference": "04ab306a2f2c9dbd46f4363383812954f704af9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/d6aecb7196bf610e63ebb64f937c33878d5d03b1", - "reference": "d6aecb7196bf610e63ebb64f937c33878d5d03b1", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/04ab306a2f2c9dbd46f4363383812954f704af9d", + "reference": "04ab306a2f2c9dbd46f4363383812954f704af9d", "shasum": "" }, "require": { @@ -3382,7 +3341,7 @@ "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/form": "^6.4|^7.0", + "symfony/form": "^6.4.20|^7.2.5", "symfony/html-sanitizer": "^6.1|^7.0", "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^6.4|^7.0", @@ -3431,7 +3390,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.4.19" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.22" }, "funding": [ { @@ -3447,20 +3406,20 @@ "type": "tidelift" } ], - "time": "2025-02-14T09:54:06+00:00" + "time": "2025-05-16T08:23:44+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.18", + "version": "v6.4.21", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "4ad10cf8b020e77ba665305bb7804389884b4837" + "reference": "22560f80c0c5cd58cc0bcaf73455ffd81eb380d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/4ad10cf8b020e77ba665305bb7804389884b4837", - "reference": "4ad10cf8b020e77ba665305bb7804389884b4837", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/22560f80c0c5cd58cc0bcaf73455ffd81eb380d5", + "reference": "22560f80c0c5cd58cc0bcaf73455ffd81eb380d5", "shasum": "" }, "require": { @@ -3516,7 +3475,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.18" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.21" }, "funding": [ { @@ -3532,20 +3491,20 @@ "type": "tidelift" } ], - "time": "2025-01-17T11:26:11+00:00" + "time": "2025-04-09T07:34:50+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.19", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "be6e71b0c257884c1107313de5d247741cfea172" + "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/be6e71b0c257884c1107313de5d247741cfea172", - "reference": "be6e71b0c257884c1107313de5d247741cfea172", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f28cf841f5654955c9f88ceaf4b9dc29571988a9", + "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9", "shasum": "" }, "require": { @@ -3593,7 +3552,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.19" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.22" }, "funding": [ { @@ -3609,20 +3568,20 @@ "type": "tidelift" } ], - "time": "2025-02-13T09:33:32+00:00" + "time": "2025-05-14T13:00:13+00:00" }, { "name": "symfony/yaml", - "version": "v6.4.18", + "version": "v6.4.21", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5" + "reference": "f01987f45676778b474468aa266fe2eda1f2bc7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5", - "reference": "bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5", + "url": "https://api.github.com/repos/symfony/yaml/zipball/f01987f45676778b474468aa266fe2eda1f2bc7e", + "reference": "f01987f45676778b474468aa266fe2eda1f2bc7e", "shasum": "" }, "require": { @@ -3665,7 +3624,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.18" + "source": "https://github.com/symfony/yaml/tree/v6.4.21" }, "funding": [ { @@ -3681,11 +3640,11 @@ "type": "tidelift" } ], - "time": "2025-01-07T09:44:41+00:00" + "time": "2025-04-04T09:48:44+00:00" }, { "name": "twig/intl-extra", - "version": "v3.20.0", + "version": "v3.21.0", "source": { "type": "git", "url": "https://github.com/twigphp/intl-extra.git", @@ -3733,7 +3692,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/intl-extra/tree/v3.20.0" + "source": "https://github.com/twigphp/intl-extra/tree/v3.21.0" }, "funding": [ { @@ -3749,16 +3708,16 @@ }, { "name": "twig/twig", - "version": "v3.20.0", + "version": "v3.21.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "3468920399451a384bef53cf7996965f7cd40183" + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/3468920399451a384bef53cf7996965f7cd40183", - "reference": "3468920399451a384bef53cf7996965f7cd40183", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d", + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d", "shasum": "" }, "require": { @@ -3812,7 +3771,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.20.0" + "source": "https://github.com/twigphp/Twig/tree/v3.21.1" }, "funding": [ { @@ -3824,7 +3783,7 @@ "type": "tidelift" } ], - "time": "2025-02-13T08:34:43+00:00" + "time": "2025-05-03T07:21:55+00:00" }, { "name": "webmozart/assert", @@ -4077,16 +4036,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.0", + "version": "1.13.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414" + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", "shasum": "" }, "require": { @@ -4125,7 +4084,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" }, "funding": [ { @@ -4133,7 +4092,7 @@ "type": "tidelift" } ], - "time": "2025-02-12T12:17:51+00:00" + "time": "2025-04-29T12:36:36+00:00" }, { "name": "nikic/php-parser", @@ -4406,16 +4365,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.21", + "version": "1.12.27", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "14276fdef70575106a3392a4ed553c06a984df28" + "reference": "3a6e423c076ab39dfedc307e2ac627ef579db162" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/14276fdef70575106a3392a4ed553c06a984df28", - "reference": "14276fdef70575106a3392a4ed553c06a984df28", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3a6e423c076ab39dfedc307e2ac627ef579db162", + "reference": "3a6e423c076ab39dfedc307e2ac627ef579db162", "shasum": "" }, "require": { @@ -4460,7 +4419,7 @@ "type": "github" } ], - "time": "2025-03-09T09:24:50+00:00" + "time": "2025-05-21T20:51:45+00:00" }, { "name": "phpstan/phpstan-mockery", @@ -4835,16 +4794,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.45", + "version": "10.5.46", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "bd68a781d8e30348bc297449f5234b3458267ae8" + "reference": "8080be387a5be380dda48c6f41cee4a13aadab3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bd68a781d8e30348bc297449f5234b3458267ae8", - "reference": "bd68a781d8e30348bc297449f5234b3458267ae8", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8080be387a5be380dda48c6f41cee4a13aadab3d", + "reference": "8080be387a5be380dda48c6f41cee4a13aadab3d", "shasum": "" }, "require": { @@ -4854,7 +4813,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.1", + "myclabs/deep-copy": "^1.13.1", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.1", @@ -4916,7 +4875,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.45" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.46" }, "funding": [ { @@ -4927,25 +4886,33 @@ "url": "https://github.com/sebastianbergmann", "type": "github" }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, { "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2025-02-06T16:08:12+00:00" + "time": "2025-05-02T06:46:24+00:00" }, { "name": "predis/predis", - "version": "v2.3.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/predis/predis.git", - "reference": "bac46bfdb78cd6e9c7926c697012aae740cb9ec9" + "reference": "f49e13ee3a2a825631562aa0223ac922ec5d058b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/predis/predis/zipball/bac46bfdb78cd6e9c7926c697012aae740cb9ec9", - "reference": "bac46bfdb78cd6e9c7926c697012aae740cb9ec9", + "url": "https://api.github.com/repos/predis/predis/zipball/f49e13ee3a2a825631562aa0223ac922ec5d058b", + "reference": "f49e13ee3a2a825631562aa0223ac922ec5d058b", "shasum": "" }, "require": { @@ -4954,6 +4921,7 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.3", "phpstan/phpstan": "^1.9", + "phpunit/phpcov": "^6.0 || ^8.0", "phpunit/phpunit": "^8.0 || ^9.4" }, "suggest": { @@ -4976,7 +4944,7 @@ "role": "Maintainer" } ], - "description": "A flexible and feature-complete Redis client for PHP.", + "description": "A flexible and feature-complete Redis/Valkey client for PHP.", "homepage": "http://github.com/predis/predis", "keywords": [ "nosql", @@ -4985,7 +4953,7 @@ ], "support": { "issues": "https://github.com/predis/predis/issues", - "source": "https://github.com/predis/predis/tree/v2.3.0" + "source": "https://github.com/predis/predis/tree/v2.4.0" }, "funding": [ { @@ -4993,7 +4961,7 @@ "type": "github" } ], - "time": "2024-11-21T20:00:02+00:00" + "time": "2025-04-30T15:16:02+00:00" }, { "name": "sebastian/cli-parser", @@ -5913,16 +5881,16 @@ }, { "name": "simplesamlphp/saml2-legacy", - "version": "v4.17.0", + "version": "v4.18.1", "source": { "type": "git", "url": "https://github.com/simplesamlphp/saml2-legacy.git", - "reference": "78934f4d776281a2a78821ef6b6be0a2e0e07f78" + "reference": "9bbf43a5ace9c8e5107dad3a613b014b456ecd56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/saml2-legacy/zipball/78934f4d776281a2a78821ef6b6be0a2e0e07f78", - "reference": "78934f4d776281a2a78821ef6b6be0a2e0e07f78", + "url": "https://api.github.com/repos/simplesamlphp/saml2-legacy/zipball/9bbf43a5ace9c8e5107dad3a613b014b456ecd56", + "reference": "9bbf43a5ace9c8e5107dad3a613b014b456ecd56", "shasum": "" }, "require": { @@ -5967,9 +5935,9 @@ ], "description": "SAML2 PHP library from SimpleSAMLphp", "support": { - "source": "https://github.com/simplesamlphp/saml2-legacy/tree/v4.17.0" + "source": "https://github.com/simplesamlphp/saml2-legacy/tree/v4.18.1" }, - "time": "2025-03-11T17:48:43+00:00" + "time": "2025-03-16T11:50:02+00:00" }, { "name": "simplesamlphp/simplesamlphp-module-adfs", @@ -6033,16 +6001,16 @@ }, { "name": "simplesamlphp/simplesamlphp-test-framework", - "version": "1.8.2", + "version": "v1.9.2", "source": { "type": "git", "url": "https://github.com/simplesamlphp/simplesamlphp-test-framework.git", - "reference": "8a2c2c10ab010f67d74812bfa13e9ccd5b31eda0" + "reference": "b8506d7b59c658ff4bb9bdd301bf24d1635019d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-test-framework/zipball/8a2c2c10ab010f67d74812bfa13e9ccd5b31eda0", - "reference": "8a2c2c10ab010f67d74812bfa13e9ccd5b31eda0", + "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-test-framework/zipball/b8506d7b59c658ff4bb9bdd301bf24d1635019d1", + "reference": "b8506d7b59c658ff4bb9bdd301bf24d1635019d1", "shasum": "" }, "require": { @@ -6083,36 +6051,36 @@ "issues": "https://github.com/simplesamlphp/simplesamlphp-test-framework/issues", "source": "https://github.com/simplesamlphp/simplesamlphp-test-framework" }, - "time": "2025-03-10T20:07:41+00:00" + "time": "2025-04-07T20:08:55+00:00" }, { "name": "slevomat/coding-standard", - "version": "8.16.0", + "version": "8.19.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "7748a4282df19daf966fda1d8c60a8aec803c83a" + "reference": "458d665acd49009efebd7e0cb385d71ae9ac3220" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7748a4282df19daf966fda1d8c60a8aec803c83a", - "reference": "7748a4282df19daf966fda1d8c60a8aec803c83a", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/458d665acd49009efebd7e0cb385d71ae9ac3220", + "reference": "458d665acd49009efebd7e0cb385d71ae9ac3220", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", "php": "^7.4 || ^8.0", "phpstan/phpdoc-parser": "^2.1.0", - "squizlabs/php_codesniffer": "^3.11.3" + "squizlabs/php_codesniffer": "^3.13.0" }, "require-dev": { "phing/phing": "3.0.1", "php-parallel-lint/php-parallel-lint": "1.4.0", - "phpstan/phpstan": "2.1.6", - "phpstan/phpstan-deprecation-rules": "2.0.1", - "phpstan/phpstan-phpunit": "2.0.4", - "phpstan/phpstan-strict-rules": "2.0.3", - "phpunit/phpunit": "9.6.8|10.5.45|11.4.4|11.5.9|12.0.4" + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpstan/phpstan-phpunit": "2.0.6", + "phpstan/phpstan-strict-rules": "2.0.4", + "phpunit/phpunit": "9.6.8|10.5.45|11.4.4|11.5.21|12.1.3" }, "type": "phpcodesniffer-standard", "extra": { @@ -6136,7 +6104,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.16.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.19.1" }, "funding": [ { @@ -6148,20 +6116,20 @@ "type": "tidelift" } ], - "time": "2025-02-23T18:12:49+00:00" + "time": "2025-06-09T17:53:57+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.11.3", + "version": "3.13.1", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10" + "reference": "1b71b4dd7e7ef651ac749cea67e513c0c832f4bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10", - "reference": "ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/1b71b4dd7e7ef651ac749cea67e513c0c832f4bd", + "reference": "1b71b4dd7e7ef651ac749cea67e513c0c832f4bd", "shasum": "" }, "require": { @@ -6228,24 +6196,24 @@ "type": "open_collective" }, { - "url": "https://thanks.dev/phpcsstandards", + "url": "https://thanks.dev/u/gh/phpcsstandards", "type": "thanks_dev" } ], - "time": "2025-01-23T17:04:15+00:00" + "time": "2025-06-12T15:04:34+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "2bbde92ab25a0e2c88160857af7be9db5da0d145" + "reference": "2eabda563921f21cbce1d1e3247b3c36568905e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2bbde92ab25a0e2c88160857af7be9db5da0d145", - "reference": "2bbde92ab25a0e2c88160857af7be9db5da0d145", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2eabda563921f21cbce1d1e3247b3c36568905e6", + "reference": "2eabda563921f21cbce1d1e3247b3c36568905e6", "shasum": "" }, "require": { @@ -6298,7 +6266,7 @@ "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v7.2.0" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.3.0" }, "funding": [ { @@ -6314,20 +6282,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T16:15:23+00:00" + "time": "2025-05-23T07:26:30+00:00" }, { "name": "symfony/translation", - "version": "v6.4.19", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "3b9bf9f33997c064885a7bfc126c14b9daa0e00e" + "reference": "7e3b3b7146c6fab36ddff304a8041174bf6e17ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/3b9bf9f33997c064885a7bfc126c14b9daa0e00e", - "reference": "3b9bf9f33997c064885a7bfc126c14b9daa0e00e", + "url": "https://api.github.com/repos/symfony/translation/zipball/7e3b3b7146c6fab36ddff304a8041174bf6e17ad", + "reference": "7e3b3b7146c6fab36ddff304a8041174bf6e17ad", "shasum": "" }, "require": { @@ -6393,7 +6361,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.19" + "source": "https://github.com/symfony/translation/tree/v6.4.22" }, "funding": [ { @@ -6409,7 +6377,7 @@ "type": "tidelift" } ], - "time": "2025-02-13T10:18:43+00:00" + "time": "2025-05-29T07:06:44+00:00" }, { "name": "theseer/tokenizer", diff --git a/docs/simplesamlphp-changelog.md b/docs/simplesamlphp-changelog.md index 19348d6c8a..413f76fc69 100644 --- a/docs/simplesamlphp-changelog.md +++ b/docs/simplesamlphp-changelog.md @@ -5,10 +5,33 @@ This document lists the changes between versions of SimpleSAMLphp. See the [upgrade notes](https://simplesamlphp.org/docs/stable/simplesamlphp-upgrade-notes.html) for specific information about upgrading. -## Version 2.3.8 +## Version 2.3.9 Released TBD + +## Version 2.3.8 + +Released 2025-06-17 + +* Fixed a bug where metadata-endpoints with isDefault set would not yield the expected metadata (#2439) +* Downgrade simplesamlphp/composer-module-installer to 1.3.x to keep things working with older (OS-supplied) + versions of composer +* Fixed one more PHP 8.4 deprecation notice + +`cron` + +* Fixed a security-issue where cron-jobs could be executed using the default key, + even if a different one was set (#2453) + +`metarefresh` + +* Fixed parsing of large metadata files (v1.2.4) + +`negotiate` + +* Fixed logout state reference (v2.3.2) + ## Version 2.3.7 Released 2025-03-11 diff --git a/docs/simplesamlphp-metadata-endpoints.md b/docs/simplesamlphp-metadata-endpoints.md index bbe191c04d..6c685cf581 100644 --- a/docs/simplesamlphp-metadata-endpoints.md +++ b/docs/simplesamlphp-metadata-endpoints.md @@ -12,6 +12,8 @@ Endpoint | Indexed | Default binding `SingleLogoutService` | N | HTTP-Redirect `SingleSignOnService` | N | HTTP-Redirect +Note that `isDefault` is only available for indexed endpoints. + The various endpoints can be specified in the following format: 'AssertionConsumerService' => [ diff --git a/docs/simplesamlphp-nostate.md b/docs/simplesamlphp-nostate.md index c7315ac3a0..882d0ac4f5 100644 --- a/docs/simplesamlphp-nostate.md +++ b/docs/simplesamlphp-nostate.md @@ -36,7 +36,7 @@ The domain name the IdP sends the response to is configured in the metadata of the IdP. This means that it may not match up with the domain name the user accessed. For example we may have the following scenario: -1. The user accesses `https://www.example.org/`. A session is created for the user, and the session cookie is set for the current domain (www.example.org). +1. The user accesses `https://www.example.org/`. A session is created for the user, and the session cookie is set for the current domain (`www.example.org`). 1. The user needs to be authenticated. We therefore save some information about the current status in the state array, create a SAML 2.0 authentication request, and send it to the IdP. 1. The user logs in on the IdP. The IdP then sends a response to the SP at `example.org`. However, the metadata for the SP that is registered at the IdP uses `https://example.org/` (without `www`) as the domain the response should be sent to. The authentication response is therefore sent to that domain. 1. The SP (now at `https://example.org/`) tries to load the state information associated with the authentication response it received. But, because the domain name has changed, we do not receive the session cookie of the user. We are therefore unable to find the session of the user. When we attempt to load the state information from the session we are therefore unable to find it. diff --git a/docs/simplesamlphp-reference-idp-hosted.md b/docs/simplesamlphp-reference-idp-hosted.md index cfe494cfc5..1ed924c22d 100644 --- a/docs/simplesamlphp-reference-idp-hosted.md +++ b/docs/simplesamlphp-reference-idp-hosted.md @@ -194,7 +194,7 @@ The following SAML 2.0 options are available: : The RSA encryption algorithm with PKCS#1 v1.5 padding is blacklisted by default for security reasons. Any assertions encrypted with this algorithm will therefore fail to decrypt. You can override this limitation by defining an empty array in this option (or blacklisting any other algorithms not including that one). However, it is strongly - discouraged to do so. For your own safety, please include the string 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' if + discouraged to do so. For your own safety, please include the string `http://www.w3.org/2001/04/xmlenc#rsa-1_5` if you make use of this option. `https.certificate` diff --git a/docs/simplesamlphp-reference-idp-remote.md b/docs/simplesamlphp-reference-idp-remote.md index 91a714a432..daafdb0af7 100644 --- a/docs/simplesamlphp-reference-idp-remote.md +++ b/docs/simplesamlphp-reference-idp-remote.md @@ -74,7 +74,7 @@ $metadata['entity-id-2'] = [ : The RSA encryption algorithm with PKCS#1 v1.5 padding is blacklisted by default for security reasons. Any assertions encrypted with this algorithm will therefore fail to decrypt. You can override this limitation by defining an empty array in this option (or blacklisting any other algorithms not including that one). However, it is strongly - discouraged to do so. For your own safety, please include the string 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' if + discouraged to do so. For your own safety, please include the string `http://www.w3.org/2001/04/xmlenc#rsa-1_5` if you make use of this option. `hide.from.discovery` diff --git a/docs/simplesamlphp-reference-sp-remote.md b/docs/simplesamlphp-reference-sp-remote.md index 77e353f0e0..f032d20c30 100644 --- a/docs/simplesamlphp-reference-sp-remote.md +++ b/docs/simplesamlphp-reference-sp-remote.md @@ -153,7 +153,7 @@ The following options can be set: : The RSA encryption algorithm with PKCS#1 v1.5 padding is blacklisted by default for security reasons. Any assertions encrypted with this algorithm will therefore fail to decrypt. You can override this limitation by defining an empty array in this option (or blacklisting any other algorithms not including that one). However, it is strongly - discouraged to do so. For your own safety, please include the string 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' if + discouraged to do so. For your own safety, please include the string `http://www.w3.org/2001/04/xmlenc#rsa-1_5` if you make use of this option. `ForceAuthn` @@ -166,7 +166,7 @@ The following options can be set: : The three most commonly used values are: -: +: 1. `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` 2. `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent` 3. `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` diff --git a/extra/simplesamlphp.spec b/extra/simplesamlphp.spec index 4a21439e0a..69e010555b 100644 --- a/extra/simplesamlphp.spec +++ b/extra/simplesamlphp.spec @@ -1,6 +1,6 @@ %define name simplesamlphp %define summary SAML IDP/SP written in PHP -%define version 2.3.7 +%define version 2.3.8 %define release 1 %define license LGPL 2.1 %define group Networking/WWW diff --git a/modules/admin/src/Controller/Test.php b/modules/admin/src/Controller/Test.php index 745bd77b8a..7e45977bdf 100644 --- a/modules/admin/src/Controller/Test.php +++ b/modules/admin/src/Controller/Test.php @@ -101,7 +101,7 @@ public function setAuthState(Auth\State $authState): void * @param string|null $as * @return \SimpleSAML\XHTML\Template|\SimpleSAML\HTTP\RunnableResponse */ - public function main(Request $request, string $as = null): Response + public function main(Request $request, ?string $as = null): Response { $this->authUtils->requireAdmin(); if (is_null($as)) { diff --git a/modules/core/public/assets/js/loginuserpass.js b/modules/core/public/assets/js/loginuserpass.js index 6f83220cee..7a258b27dd 100644 --- a/modules/core/public/assets/js/loginuserpass.js +++ b/modules/core/public/assets/js/loginuserpass.js @@ -4,7 +4,7 @@ ready(function () { var replacement = document.createTextNode(button.getAttribute("data-default")); button.replaceChild(replacement, button.childNodes[0]); button.disabled = false; - } + }; var form = document.getElementById("f"); form.onsubmit = function () { @@ -12,6 +12,6 @@ ready(function () { var replacement = document.createTextNode(button.getAttribute("data-processing")); button.replaceChild(replacement, button.childNodes[0]); button.disabled = true; - } + }; }); diff --git a/modules/core/src/Auth/Process/Cardinality.php b/modules/core/src/Auth/Process/Cardinality.php index 160261d07e..e22686804e 100644 --- a/modules/core/src/Auth/Process/Cardinality.php +++ b/modules/core/src/Auth/Process/Cardinality.php @@ -33,10 +33,10 @@ class Cardinality extends Auth\ProcessingFilter * * @param array &$config Configuration information about this filter. * @param mixed $reserved For future use. - * @param \SimpleSAML\Utils\HTTP $httpUtils HTTP utility service (handles redirects). + * @param \SimpleSAML\Utils\HTTP|null $httpUtils HTTP utility service (handles redirects). * @throws \SimpleSAML\Error\Exception */ - public function __construct(array &$config, $reserved, Utils\HTTP $httpUtils = null) + public function __construct(array &$config, $reserved, ?Utils\HTTP $httpUtils = null) { parent::__construct($config, $reserved); diff --git a/modules/core/src/Auth/Process/CardinalitySingle.php b/modules/core/src/Auth/Process/CardinalitySingle.php index fd51fb79a9..c559e295a2 100644 --- a/modules/core/src/Auth/Process/CardinalitySingle.php +++ b/modules/core/src/Auth/Process/CardinalitySingle.php @@ -44,9 +44,9 @@ class CardinalitySingle extends Auth\ProcessingFilter * * @param array &$config Configuration information about this filter. * @param mixed $reserved For future use. - * @param \SimpleSAML\Utils\HTTP $httpUtils HTTP utility service (handles redirects). + * @param \SimpleSAML\Utils\HTTP|null $httpUtils HTTP utility service (handles redirects). */ - public function __construct(array &$config, $reserved, Utils\HTTP $httpUtils = null) + public function __construct(array &$config, $reserved, ?Utils\HTTP $httpUtils = null) { parent::__construct($config, $reserved); diff --git a/modules/core/src/Storage/SQLPermanentStorage.php b/modules/core/src/Storage/SQLPermanentStorage.php index 5ba08cffdb..61095c9baf 100644 --- a/modules/core/src/Storage/SQLPermanentStorage.php +++ b/modules/core/src/Storage/SQLPermanentStorage.php @@ -29,7 +29,7 @@ class SQLPermanentStorage * @param \SimpleSAML\Configuration|null $config * @throws \Exception */ - public function __construct(string $name, Configuration $config = null) + public function __construct(string $name, ?Configuration $config = null) { if (is_null($config)) { $config = Configuration::getInstance(); @@ -81,7 +81,7 @@ public function __construct(string $name, Configuration $config = null) * @param string $value * @param int|null $duration */ - public function set(string $type, string $key1, string $key2, string $value, int $duration = null): void + public function set(string $type, string $key1, string $key2, string $value, ?int $duration = null): void { if ($this->exists($type, $key1, $key2)) { $this->update($type, $key1, $key2, $value, $duration); @@ -99,7 +99,7 @@ public function set(string $type, string $key1, string $key2, string $value, int * @param int|null $duration * @return array */ - private function insert(string $type, string $key1, string $key2, string $value, int $duration = null): array + private function insert(string $type, string $key1, string $key2, string $value, ?int $duration = null): array { $expire = is_null($duration) ? null : (time() + $duration); @@ -125,7 +125,7 @@ private function insert(string $type, string $key1, string $key2, string $value, * @param int|null $duration * @return array */ - private function update(string $type, string $key1, string $key2, string $value, int $duration = null): array + private function update(string $type, string $key1, string $key2, string $value, ?int $duration = null): array { $expire = is_null($duration) ? null : (time() + $duration); @@ -148,7 +148,7 @@ private function update(string $type, string $key1, string $key2, string $value, * @param string|null $key2 * @return array|null */ - public function get(string $type = null, string $key1 = null, string $key2 = null): ?array + public function get(?string $type = null, ?string $key1 = null, ?string $key2 = null): ?array { $conditions = $this->getCondition($type, $key1, $key2); $query = 'SELECT * FROM data WHERE ' . $conditions; @@ -173,7 +173,7 @@ public function get(string $type = null, string $key1 = null, string $key2 = nul * @param string|null $key2 * @return string|null */ - public function getValue(string $type = null, string $key1 = null, string $key2 = null): ?string + public function getValue(?string $type = null, ?string $key1 = null, ?string $key2 = null): ?string { $res = $this->get($type, $key1, $key2); if ($res === null) { @@ -206,7 +206,7 @@ public function exists(string $type, string $key1, string $key2): bool * @param string|null $key2 * @return array|false */ - public function getList(string $type = null, string $key1 = null, string $key2 = null) + public function getList(?string $type = null, ?string $key1 = null, ?string $key2 = null) { $conditions = $this->getCondition($type, $key1, $key2); $query = 'SELECT * FROM data WHERE ' . $conditions; @@ -234,9 +234,9 @@ public function getList(string $type = null, string $key1 = null, string $key2 = * @return array|null */ public function getKeys( - string $type = null, - string $key1 = null, - string $key2 = null, + ?string $type = null, + ?string $key1 = null, + ?string $key2 = null, string $whichKey = 'type', ): ?array { if (!in_array($whichKey, ['key1', 'key2', 'type'], true)) { @@ -299,7 +299,7 @@ public function removeExpired(): int * @param string|null $key2 * @return string */ - private function getCondition(string $type = null, string $key1 = null, string $key2 = null): string + private function getCondition(?string $type = null, ?string $key1 = null, ?string $key2 = null): string { $conditions = []; if (!is_null($type)) { diff --git a/modules/cron/src/Controller/Cron.php b/modules/cron/src/Controller/Cron.php index e23ced10e6..fedcec84cf 100644 --- a/modules/cron/src/Controller/Cron.php +++ b/modules/cron/src/Controller/Cron.php @@ -5,6 +5,7 @@ namespace SimpleSAML\Module\cron\Controller; use PHPMailer\PHPMailer\Exception as PHPMailerException; +use SimpleSAML\Assert\Assert; use SimpleSAML\Configuration; use SimpleSAML\Error; use SimpleSAML\Logger; @@ -116,14 +117,26 @@ public function run(string $tag, string $key, string $output = 'xhtml'): Respons { $configKey = $this->cronconfig->getOptionalString('key', 'secret'); - if ($key === 'secret' || $key === 'RANDOM_KEY') { - // Possible malicious attempt to run cron tasks with default secret - Logger::warning("Cron: Possible malicious attempt to run cron tasks with default secret"); - } elseif ($configKey === 'secret' || $configKey === 'RANDOM_KEY') { - Logger::warning("Cron: no proper key has been configured."); - } elseif ($key !== $configKey) { - throw new Error\Exception('Cron: Wrong key provided. Cron will not run.'); - } + Assert::notInArray( + $key, + ['secret', 'RANDOM_KEY'], + 'Cron: Possible malicious attempt to run cron tasks with default secret', + Error\ConfigurationError::class, + ); + + Assert::notInArray( + $configKey, + ['secret', 'RANDOM_KEY'], + 'Cron: no proper key has been configured.', + Error\ConfigurationError::class, + ); + + Assert::same( + $key, + $configKey, + 'Cron: Wrong key %s provided. Cron will not run.', + Error\Exception::class, + ); $cron = new \SimpleSAML\Module\cron\Cron(); if (!$cron->isValidTag($tag)) { diff --git a/modules/cron/src/Cron.php b/modules/cron/src/Cron.php index b6f7b43f9a..0cffbc296c 100644 --- a/modules/cron/src/Cron.php +++ b/modules/cron/src/Cron.php @@ -26,7 +26,7 @@ class Cron * @param \SimpleSAML\Configuration $cronconfig The cron configuration to use. If not specified defaults * to `config/module_cron.php` */ - public function __construct(Configuration $cronconfig = null) + public function __construct(?Configuration $cronconfig = null) { if ($cronconfig == null) { $cronconfig = Configuration::getConfig('module_cron.php'); diff --git a/modules/saml/docs/sp.md b/modules/saml/docs/sp.md index 6025387439..de53d333ec 100644 --- a/modules/saml/docs/sp.md +++ b/modules/saml/docs/sp.md @@ -67,7 +67,7 @@ All these parameters override the equivalent option from the configuration. ## Authentication data Some SAML-specific attributes are available to the application after authentication. -To retrieve these attributes, the application can use the `getAuthData()`-function from the [SP API](./simplesamlphp-sp-api). +To retrieve these attributes, the application can use the `getAuthData()`-function from the [SP API](../simplesamlphp-sp-api). The following attributes are available: `saml:sp:IdP` @@ -100,7 +100,7 @@ The following attributes are available: : List of Assertion Consumer Services in the generated metadata. Specified in the format detailed in the - [Metadata endpoints](./simplesamlphp-metadata-endpoints) documentation. + [Metadata endpoints](../simplesamlphp-metadata-endpoints) documentation. Note that this list is taken at face value, so it's not useful to list anything here that the SP auth source does not actually support (unless the URLs point externally). diff --git a/modules/saml/src/Error.php b/modules/saml/src/Error.php index e026f14b9d..8bf5df581b 100644 --- a/modules/saml/src/Error.php +++ b/modules/saml/src/Error.php @@ -29,7 +29,7 @@ public function __construct( private string $status, private ?string $subStatus = null, private ?string $statusMessage = null, - Throwable $cause = null, + ?Throwable $cause = null, ) { $st = self::shortStatus($status); if ($subStatus !== null) { diff --git a/modules/saml/src/Error/NoAuthnContext.php b/modules/saml/src/Error/NoAuthnContext.php index d3c59fc46f..7b1a5fee04 100644 --- a/modules/saml/src/Error/NoAuthnContext.php +++ b/modules/saml/src/Error/NoAuthnContext.php @@ -23,7 +23,7 @@ class NoAuthnContext extends \SimpleSAML\Module\saml\Error * @param string|null $message A short message explaining why this error happened. * @param \Throwable|null $cause An exception that caused this error. */ - public function __construct(string $responsible, string $message = null, Throwable $cause = null) + public function __construct(string $responsible, ?string $message = null, ?Throwable $cause = null) { parent::__construct($responsible, Constants::STATUS_NO_AUTHN_CONTEXT, $message, $cause); } diff --git a/modules/saml/src/Error/NoAvailableIDP.php b/modules/saml/src/Error/NoAvailableIDP.php index 8bf5014687..e515cb1f70 100644 --- a/modules/saml/src/Error/NoAvailableIDP.php +++ b/modules/saml/src/Error/NoAvailableIDP.php @@ -23,7 +23,7 @@ class NoAvailableIDP extends \SimpleSAML\Module\saml\Error * @param string|null $message A short message explaining why this error happened. * @param \Throwable|null $cause An exception that caused this error. */ - public function __construct(string $responsible, string $message = null, Throwable $cause = null) + public function __construct(string $responsible, ?string $message = null, ?Throwable $cause = null) { parent::__construct($responsible, Constants::STATUS_NO_AVAILABLE_IDP, $message, $cause); } diff --git a/modules/saml/src/Error/NoPassive.php b/modules/saml/src/Error/NoPassive.php index eb99a140b5..bba588f1b6 100644 --- a/modules/saml/src/Error/NoPassive.php +++ b/modules/saml/src/Error/NoPassive.php @@ -23,7 +23,7 @@ class NoPassive extends \SimpleSAML\Module\saml\Error * @param string|null $message A short message explaining why this error happened. * @param \Throwable|null $cause An exception that caused this error. */ - public function __construct(string $responsible, string $message = null, Throwable $cause = null) + public function __construct(string $responsible, ?string $message = null, ?Throwable $cause = null) { parent::__construct($responsible, Constants::STATUS_NO_PASSIVE, $message, $cause); } diff --git a/modules/saml/src/Error/NoSupportedIDP.php b/modules/saml/src/Error/NoSupportedIDP.php index 8afee75611..41cd41ae92 100644 --- a/modules/saml/src/Error/NoSupportedIDP.php +++ b/modules/saml/src/Error/NoSupportedIDP.php @@ -23,7 +23,7 @@ class NoSupportedIDP extends \SimpleSAML\Module\saml\Error * @param string|null $message A short message explaining why this error happened. * @param \Throwable|null $cause An exception that caused this error. */ - public function __construct(string $responsible, string $message = null, Throwable $cause = null) + public function __construct(string $responsible, ?string $message = null, ?Throwable $cause = null) { parent::__construct($responsible, Constants::STATUS_NO_SUPPORTED_IDP, $message, $cause); } diff --git a/modules/saml/src/Error/ProxyCountExceeded.php b/modules/saml/src/Error/ProxyCountExceeded.php index 4a7a5d9b6c..984df91f9d 100644 --- a/modules/saml/src/Error/ProxyCountExceeded.php +++ b/modules/saml/src/Error/ProxyCountExceeded.php @@ -23,7 +23,7 @@ class ProxyCountExceeded extends \SimpleSAML\Module\saml\Error * @param string|null $message A short message explaining why this error happened. * @param \Throwable|null $cause An exception that caused this error. */ - public function __construct(string $responsible, string $message = null, Throwable $cause = null) + public function __construct(string $responsible, ?string $message = null, ?Throwable $cause = null) { parent::__construct($responsible, Constants::STATUS_PROXY_COUNT_EXCEEDED, $message, $cause); } diff --git a/modules/saml/src/IdP/SAML2.php b/modules/saml/src/IdP/SAML2.php index 9fc88c8d38..1695d89aaf 100644 --- a/modules/saml/src/IdP/SAML2.php +++ b/modules/saml/src/IdP/SAML2.php @@ -198,9 +198,9 @@ public static function handleAuthError(Error\Exception $exception, array $state) private static function getAssertionConsumerService( array $supportedBindings, Configuration $spMetadata, - string $AssertionConsumerServiceURL = null, - string $ProtocolBinding = null, - int $AssertionConsumerServiceIndex = null, + ?string $AssertionConsumerServiceURL = null, + ?string $ProtocolBinding = null, + ?int $AssertionConsumerServiceIndex = null, bool $authnRequestSigned = false, ): ?array { /* We want to pick the best matching endpoint in the case where for example @@ -533,9 +533,9 @@ public static function receiveAuthnRequest(IdP $idp): void * * @param \SimpleSAML\IdP $idp The IdP we are sending a logout request from. * @param array $association The association that should be terminated. - * @param string|null $relayState An id that should be carried across the logout. + * @param string|null $relayState An id that should be carried across the logout. */ - public static function sendLogoutRequest(IdP $idp, array $association, string $relayState = null): void + public static function sendLogoutRequest(IdP $idp, array $association, ?string $relayState = null): void { Logger::info('Sending SAML 2.0 LogoutRequest to: ' . var_export($association['saml:entityID'], true)); @@ -702,11 +702,11 @@ public static function receiveLogoutMessage(IdP $idp): void * * @param \SimpleSAML\IdP $idp The IdP we are sending a logout request from. * @param array $association The association that should be terminated. - * @param string|NULL $relayState An id that should be carried across the logout. + * @param string|NULL $relayState An id that should be carried across the logout. * * @return string The logout URL. */ - public static function getLogoutURL(IdP $idp, array $association, string $relayState = null): string + public static function getLogoutURL(IdP $idp, array $association, ?string $relayState = null): string { Logger::info('Sending SAML 2.0 LogoutRequest to: ' . var_export($association['saml:entityID'], true)); @@ -761,7 +761,7 @@ public static function getAssociationConfig(IdP $idp, array $association): Confi * Retrieve the metadata of a hosted SAML 2 IdP. * * @param string $entityid The entity ID of the hosted SAML 2 IdP whose metadata we want. - * @param MetaDataStorageHandler $handler Optionally the metadata storage to use, + * @param MetaDataStorageHandler|null $handler Optionally the metadata storage to use, * if omitted the configured handler will be used. * * @return array @@ -769,7 +769,7 @@ public static function getAssociationConfig(IdP $idp, array $association): Confi * @throws \SimpleSAML\Error\Exception * @throws \SimpleSAML\Error\MetadataNotFound */ - public static function getHostedMetadata(string $entityid, MetaDataStorageHandler $handler = null): array + public static function getHostedMetadata(string $entityid, ?MetaDataStorageHandler $handler = null): array { $globalConfig = Configuration::getInstance(); if ($handler === null) { @@ -1409,7 +1409,7 @@ private static function buildLogoutRequest( Configuration $idpMetadata, Configuration $spMetadata, array $association, - string $relayState = null, + ?string $relayState = null, ): LogoutRequest { $lr = Message::buildLogoutRequest($idpMetadata, $spMetadata); $lr->setRelayState($relayState); diff --git a/src/SimpleSAML/Auth/Simple.php b/src/SimpleSAML/Auth/Simple.php index d42c47e3d3..b6f69d3b2c 100644 --- a/src/SimpleSAML/Auth/Simple.php +++ b/src/SimpleSAML/Auth/Simple.php @@ -35,8 +35,8 @@ class Simple */ public function __construct( protected string $authSource, - Configuration $config = null, - Session $session = null, + ?Configuration $config = null, + ?Session $session = null, ) { if ($config === null) { $config = Configuration::getInstance(); diff --git a/src/SimpleSAML/Compat/SspContainer.php b/src/SimpleSAML/Compat/SspContainer.php index f098d275f8..2718ef2a72 100644 --- a/src/SimpleSAML/Compat/SspContainer.php +++ b/src/SimpleSAML/Compat/SspContainer.php @@ -96,7 +96,7 @@ public function getTempDir(): string * @param string $date * @param int|null $mode */ - public function writeFile(string $filename, string $data, int $mode = null): void + public function writeFile(string $filename, string $data, ?int $mode = null): void { $sysUtils = new Utils\System(); diff --git a/src/SimpleSAML/Configuration.php b/src/SimpleSAML/Configuration.php index 5047d71258..0158c319e8 100644 --- a/src/SimpleSAML/Configuration.php +++ b/src/SimpleSAML/Configuration.php @@ -41,7 +41,7 @@ class Configuration implements Utils\ClearableState /** * The release version of this package */ - public const VERSION = '2.3.7'; + public const VERSION = '2.3.8'; /** * A default value which means that the given option is required. diff --git a/src/SimpleSAML/Database.php b/src/SimpleSAML/Database.php index 4f51170d63..588b1b4eb9 100644 --- a/src/SimpleSAML/Database.php +++ b/src/SimpleSAML/Database.php @@ -57,11 +57,11 @@ class Database /** * Retrieves the current database instance. Will create a new one if there isn't an existing connection. * - * @param \SimpleSAML\Configuration $altConfig Optional: Instance of a \SimpleSAML\Configuration class + * @param \SimpleSAML\Configuration|null $altConfig Optional: Instance of a \SimpleSAML\Configuration class * * @return \SimpleSAML\Database The shared database connection. */ - public static function getInstance(Configuration $altConfig = null): Database + public static function getInstance(?Configuration $altConfig = null): Database { $config = ($altConfig) ? $altConfig : Configuration::getInstance(); $instanceId = self::generateInstanceId($config); @@ -159,12 +159,12 @@ private static function generateInstanceId(Configuration $config): string * @param string $dsn Database connection string * @param string|null $username SQL user * @param string|null $password SQL password - * @param array $options PDO options + * @param array $options PDO options * * @throws \Exception If an error happens while trying to connect to the database. * @return \PDO object */ - private function connect(string $dsn, string $username = null, string $password = null, array $options): PDO + private function connect(string $dsn, ?string $username = null, ?string $password = null, array $options = []): PDO { try { $db = new PDO($dsn, $username, $password, $options); diff --git a/src/SimpleSAML/Error/AuthSource.php b/src/SimpleSAML/Error/AuthSource.php index f2ab95b28d..4cd207bc81 100644 --- a/src/SimpleSAML/Error/AuthSource.php +++ b/src/SimpleSAML/Error/AuthSource.php @@ -25,7 +25,7 @@ class AuthSource extends Error public function __construct( private string $authsource, private string $reason, - Throwable $cause = null, + ?Throwable $cause = null, ) { $this->authsource = $authsource; $this->reason = $reason; diff --git a/src/SimpleSAML/Error/ConfigurationError.php b/src/SimpleSAML/Error/ConfigurationError.php index 7dc54582ed..b9bd562d3c 100644 --- a/src/SimpleSAML/Error/ConfigurationError.php +++ b/src/SimpleSAML/Error/ConfigurationError.php @@ -34,7 +34,7 @@ class ConfigurationError extends Error * @param string|null $file The configuration file that originated this error. * @param array|null $config The configuration array that led to this problem. */ - public function __construct(string $reason = null, string $file = null, array $config = null) + public function __construct(?string $reason = null, ?string $file = null, ?array $config = null) { $file_str = ''; $reason_str = '.'; diff --git a/src/SimpleSAML/Error/CriticalConfigurationError.php b/src/SimpleSAML/Error/CriticalConfigurationError.php index 09b0d6779c..ec1c3a0d04 100644 --- a/src/SimpleSAML/Error/CriticalConfigurationError.php +++ b/src/SimpleSAML/Error/CriticalConfigurationError.php @@ -49,7 +49,7 @@ class CriticalConfigurationError extends ConfigurationError * @param string|null $file The configuration file that originated this error. * @param array|null $config The configuration array that led to this problem. */ - public function __construct(string $reason = null, string $file = null, array $config = null) + public function __construct(?string $reason = null, ?string $file = null, ?array $config = null) { if ($config === null) { $config = self::$minimum_config; diff --git a/src/SimpleSAML/Error/ErrorHandler.php b/src/SimpleSAML/Error/ErrorHandler.php index ae9297b9fe..a889c7205f 100644 --- a/src/SimpleSAML/Error/ErrorHandler.php +++ b/src/SimpleSAML/Error/ErrorHandler.php @@ -46,7 +46,8 @@ public function customErrorHandler( E_USER_DEPRECATED => 'User Deprecated', E_NOTICE => 'Notice', E_USER_NOTICE => 'User Notice', - E_STRICT => 'Runtime Notice', + // E_STRICT (2048) has become deprecated in PHP 8.4 + 2048 => 'Runtime Notice', E_WARNING => 'Warning', E_USER_WARNING => 'User Warning', E_COMPILE_WARNING => 'Compile Warning', diff --git a/src/SimpleSAML/Error/UserAborted.php b/src/SimpleSAML/Error/UserAborted.php index e995e5dd01..5ffcb118aa 100644 --- a/src/SimpleSAML/Error/UserAborted.php +++ b/src/SimpleSAML/Error/UserAborted.php @@ -19,7 +19,7 @@ class UserAborted extends Error * * @param \Throwable|null $cause The exception that caused this error. */ - public function __construct(Throwable $cause = null) + public function __construct(?Throwable $cause = null) { parent::__construct(ErrorCodes::USERABORTED, $cause); } diff --git a/src/SimpleSAML/IdP.php b/src/SimpleSAML/IdP.php index 2270dff0ed..a587f997db 100644 --- a/src/SimpleSAML/IdP.php +++ b/src/SimpleSAML/IdP.php @@ -505,7 +505,7 @@ public function handleLogoutRequest(array &$state, ?string $assocId): void * @param string|null $relayState The RelayState from the start of the logout. * @param \SimpleSAML\Error\Exception|null $error The error that occurred during session termination (if any). */ - public function handleLogoutResponse(string $assocId, ?string $relayState, Error\Exception $error = null): void + public function handleLogoutResponse(string $assocId, ?string $relayState, ?Error\Exception $error = null): void { $index = strpos($assocId, ':'); Assert::integer($index); diff --git a/src/SimpleSAML/IdP/IFrameLogoutHandler.php b/src/SimpleSAML/IdP/IFrameLogoutHandler.php index 134fd8840a..75f9645e8e 100644 --- a/src/SimpleSAML/IdP/IFrameLogoutHandler.php +++ b/src/SimpleSAML/IdP/IFrameLogoutHandler.php @@ -85,7 +85,7 @@ public function startLogout(array &$state, ?string $assocId): void * @param string|null $relayState The RelayState from the start of the logout. * @param \SimpleSAML\Error\Exception|null $error The error that occurred during session termination (if any). */ - public function onResponse(string $assocId, ?string $relayState, Error\Exception $error = null): void + public function onResponse(string $assocId, ?string $relayState, ?Error\Exception $error = null): void { $this->idp->terminateAssociation($assocId); diff --git a/src/SimpleSAML/IdP/LogoutHandlerInterface.php b/src/SimpleSAML/IdP/LogoutHandlerInterface.php index 56e4098a14..148981d072 100644 --- a/src/SimpleSAML/IdP/LogoutHandlerInterface.php +++ b/src/SimpleSAML/IdP/LogoutHandlerInterface.php @@ -43,5 +43,5 @@ public function startLogout(array &$state, ?string $assocId): void; * @param string|null $relayState The RelayState from the start of the logout. * @param \SimpleSAML\Error\Exception|null $error The error that occurred during session termination (if any). */ - public function onResponse(string $assocId, ?string $relayState, Error\Exception $error = null): void; + public function onResponse(string $assocId, ?string $relayState, ?Error\Exception $error = null): void; } diff --git a/src/SimpleSAML/IdP/TraditionalLogoutHandler.php b/src/SimpleSAML/IdP/TraditionalLogoutHandler.php index 06e3e021cb..c86b3f9c07 100644 --- a/src/SimpleSAML/IdP/TraditionalLogoutHandler.php +++ b/src/SimpleSAML/IdP/TraditionalLogoutHandler.php @@ -93,7 +93,7 @@ public function startLogout(array &$state, /** @scrutinizer ignore-unused */?str * * @throws \SimpleSAML\Error\Exception If the RelayState was lost during logout. */ - public function onResponse(string $assocId, ?string $relayState, Error\Exception $error = null): void + public function onResponse(string $assocId, ?string $relayState, ?Error\Exception $error = null): void { if ($relayState === null) { throw new Error\Exception('RelayState lost during logout.'); diff --git a/src/SimpleSAML/Locale/Localization.php b/src/SimpleSAML/Locale/Localization.php index f9f3833e78..f98318c082 100644 --- a/src/SimpleSAML/Locale/Localization.php +++ b/src/SimpleSAML/Locale/Localization.php @@ -264,6 +264,14 @@ private function loadGettextGettextFromPO( if (empty($translations->getDomain())) { $translations->setDomain($domain); } + if ($domain != $translations->getDomain()) { + Logger::warning(sprintf( + "The translation file at %s has domain %s but is expected to have a domain %s", + $file->getPath(), + $translations->getDomain(), + $domain, + )); + } $arrayGenerator = new ArrayGenerator(); $this->translator->addTranslations( diff --git a/src/SimpleSAML/Locale/Translate.php b/src/SimpleSAML/Locale/Translate.php index 36716ba75a..a341639537 100644 --- a/src/SimpleSAML/Locale/Translate.php +++ b/src/SimpleSAML/Locale/Translate.php @@ -72,6 +72,16 @@ public static function addDefaultDomain(string $domain): void * * @param string|null $original The string before translation. * + * + * NOTE: This may be called from TwigTranslator::trans() + * which will pass the following arguments. + * The $id will match $original above but there are other arguments which may also be used in this method. + * + * @param string $id + * @param array $parameters + * @param string|null $domain + * @param string|null $locale + * * @return string The translated string. */ public static function translateSingularGettext(?string $original): string @@ -88,7 +98,7 @@ public static function translateSingularGettext(?string $original): string foreach (self::$defaultDomains as $d) { $text = TranslatorFunctions::getTranslator()->dgettext($d, $original); if ($text != $original) { - return $text; + break; } } diff --git a/src/SimpleSAML/Metadata/MetaDataStorageHandler.php b/src/SimpleSAML/Metadata/MetaDataStorageHandler.php index dbbe0405d3..92ff8d3ae9 100644 --- a/src/SimpleSAML/Metadata/MetaDataStorageHandler.php +++ b/src/SimpleSAML/Metadata/MetaDataStorageHandler.php @@ -81,13 +81,17 @@ protected function __construct() * * @param string $property The metadata property which should be auto-generated. * @param string $set The set we the property comes from. - * @param string $overrideHost Hostname to use in the URLs + * @param string|null $overrideHost Hostname to use in the URLs * * @return string|array The auto-generated metadata property. * @throws \Exception If the metadata cannot be generated automatically. */ - public function getGenerated(string $property, string $set, string $overrideHost = null): string|array - { + public function getGenerated( + string $property, + string $set, + ?string $overrideHost = null, + ?string $entityId = null, + ): string|array { // first we check if the user has overridden this property in the metadata try { $metadataSet = $this->getMetaDataCurrent($set); diff --git a/src/SimpleSAML/Metadata/SAMLBuilder.php b/src/SimpleSAML/Metadata/SAMLBuilder.php index 7e88b1978f..a1a90ba1b1 100644 --- a/src/SimpleSAML/Metadata/SAMLBuilder.php +++ b/src/SimpleSAML/Metadata/SAMLBuilder.php @@ -347,6 +347,11 @@ private static function createEndpoints(array $endpoints, bool $indexed): array foreach ($endpoints as &$ep) { if ($indexed) { $t = new IndexedEndpointType(); + + if (isset($ep['isDefault'])) { + $t->setIsDefault($ep['isDefault']); + } + if (!isset($ep['index'])) { // Find the maximum index $maxIndex = -1; diff --git a/src/SimpleSAML/Metadata/SAMLParser.php b/src/SimpleSAML/Metadata/SAMLParser.php index 9cccfcda1b..4b114f73c5 100644 --- a/src/SimpleSAML/Metadata/SAMLParser.php +++ b/src/SimpleSAML/Metadata/SAMLParser.php @@ -358,7 +358,7 @@ public static function parseDescriptorsString(string $string): array * be the entity id. * @throws \Exception if the document is empty or the root is an unexpected node. */ - public static function parseDescriptorsElement(DOMElement $element = null): array + public static function parseDescriptorsElement(?DOMElement $element = null): array { if ($element === null) { throw new Exception('Document was empty.'); diff --git a/src/SimpleSAML/SessionHandlerCookie.php b/src/SimpleSAML/SessionHandlerCookie.php index 2e6ac8a17a..eeb54239c9 100644 --- a/src/SimpleSAML/SessionHandlerCookie.php +++ b/src/SimpleSAML/SessionHandlerCookie.php @@ -152,7 +152,7 @@ public function hasSessionCookie(): bool * * @throws \SimpleSAML\Error\CannotSetCookie If we can't set the cookie. */ - public function setCookie(string $sessionName, ?string $sessionID, array $cookieParams = null): void + public function setCookie(string $sessionName, ?string $sessionID, ?array $cookieParams = null): void { if ($cookieParams !== null) { $params = array_merge($this->getCookieParams(), $cookieParams); diff --git a/src/SimpleSAML/Store/RedisStore.php b/src/SimpleSAML/Store/RedisStore.php index 3560d65af8..3dab9bfa54 100644 --- a/src/SimpleSAML/Store/RedisStore.php +++ b/src/SimpleSAML/Store/RedisStore.php @@ -28,7 +28,7 @@ class RedisStore implements StoreInterface * Initialize the Redis data store. * @param \Predis\Client|null $redis */ - public function __construct(Client $redis = null) + public function __construct(?Client $redis = null) { if (!class_exists(Client::class)) { throw new Error\CriticalConfigurationError('predis/predis is not available.'); diff --git a/src/SimpleSAML/Utils/Config/Metadata.php b/src/SimpleSAML/Utils/Config/Metadata.php index 2dd4074996..d2901c8a86 100644 --- a/src/SimpleSAML/Utils/Config/Metadata.php +++ b/src/SimpleSAML/Utils/Config/Metadata.php @@ -175,12 +175,12 @@ function ($t) { * Find the default endpoint in an endpoint array. * * @param array $endpoints An array with endpoints. - * @param array $bindings An array with acceptable bindings. Can be null if any binding is allowed. + * @param array|null $bindings An array with acceptable bindings. Can be null if any binding is allowed. * * @return array|NULL The default endpoint, or null if no acceptable endpoints are used. * */ - public static function getDefaultEndpoint(array $endpoints, array $bindings = null): ?array + public static function getDefaultEndpoint(array $endpoints, ?array $bindings = null): ?array { $firstNotFalse = null; $firstAllowed = null; @@ -246,7 +246,7 @@ public static function isHiddenFromDiscovery(array $metadata): bool /** * This method parses the different possible values of the NameIDPolicy metadata configuration. */ - public static function parseNameIdPolicy(array $nameIdPolicy = null): array + public static function parseNameIdPolicy(?array $nameIdPolicy = null): array { if ($nameIdPolicy === null) { // when NameIDPolicy is unset or set to null, default to transient diff --git a/src/SimpleSAML/Utils/Crypto.php b/src/SimpleSAML/Utils/Crypto.php index 715f81625b..67b47679ec 100644 --- a/src/SimpleSAML/Utils/Crypto.php +++ b/src/SimpleSAML/Utils/Crypto.php @@ -74,7 +74,7 @@ private function aesDecryptInternal(string $ciphertext, string $secret): string * Decrypt data using AES-256-CBC and the system-wide secret salt as key. * * @param string $ciphertext The HMAC of the encrypted data, the IV used and the encrypted data, concatenated. - * @param string $secret The secret to use to decrypt the data. + * @param string|null $secret The secret to use to decrypt the data. * If not provided, the secret salt from the configuration will be used * * @return string The decrypted data. @@ -83,7 +83,7 @@ private function aesDecryptInternal(string $ciphertext, string $secret): string * * @deprecated - Possibly use xml-security library */ - public function aesDecrypt(string $ciphertext, string $secret = null): string + public function aesDecrypt(string $ciphertext, ?string $secret = null): string { if ($secret === null) { $configUtils = new Config(); @@ -140,7 +140,7 @@ private function aesEncryptInternal(string $data, string $secret): string * Encrypt data using AES-256-CBC and the system-wide secret salt as key. * * @param string $data The data to encrypt. - * @param string $secret The secret to use to decrypt the data. + * @param string|null $secret The secret to use to decrypt the data. * If not provided, the secret salt from the configuration will be used * * @return string An HMAC of the encrypted data, the IV and the encrypted data, concatenated. @@ -149,7 +149,7 @@ private function aesEncryptInternal(string $data, string $secret): string * * @deprecated - Possibly use xml-security library */ - public function aesEncrypt(string $data, string $secret = null): string + public function aesEncrypt(string $data, ?string $secret = null): string { if ($secret === null) { $configUtils = new Config(); diff --git a/src/SimpleSAML/Utils/EMail.php b/src/SimpleSAML/Utils/EMail.php index caf5163e58..b141f0d725 100644 --- a/src/SimpleSAML/Utils/EMail.php +++ b/src/SimpleSAML/Utils/EMail.php @@ -34,8 +34,8 @@ class EMail * from the configuration is used. * * @param string $subject The subject of the e-mail - * @param string $from The from-address (both envelope and header) - * @param string $to The recipient + * @param string|null $from The from-address (both envelope and header) + * @param string|null $to The recipient * @param string $txt_template The template to use for plain text messages * @param string $html_template The template to use for html messages * @@ -43,8 +43,8 @@ class EMail */ public function __construct( string $subject, - string $from = null, - string $to = null, + ?string $from = null, + ?string $to = null, private string $txt_template = 'mailtxt.twig', private string $html_template = 'mailhtml.twig', ) { diff --git a/src/SimpleSAML/Utils/Net.php b/src/SimpleSAML/Utils/Net.php index 8bcd706436..a656425f6e 100644 --- a/src/SimpleSAML/Utils/Net.php +++ b/src/SimpleSAML/Utils/Net.php @@ -18,13 +18,13 @@ class Net * Check whether an IP address is part of a CIDR. * * @param string|array $cidr The network CIDR address. - * @param string $ip The IP address to check. Optional. Current remote address will be used if none specified. Do + * @param string|null $ip The IP address to check. Optional. Current remote address will be used if none specified. Do * not rely on default parameter if running behind load balancers. * * @return boolean True if the IP address belongs to the specified CIDR, false otherwise. * */ - public function ipCIDRcheck(string|array $cidr, string $ip = null): bool + public function ipCIDRcheck(string|array $cidr, ?string $ip = null): bool { if ($ip === null) { $ip = Request::createFromGlobals()->getClientIp() ?? '127.0.0.1'; diff --git a/src/SimpleSAML/Utils/System.php b/src/SimpleSAML/Utils/System.php index 0d90b8215f..6a3300910b 100644 --- a/src/SimpleSAML/Utils/System.php +++ b/src/SimpleSAML/Utils/System.php @@ -94,7 +94,9 @@ public function getTempDir(): string (is_array($error) ? $error['message'] : 'no error available'), ); } - } elseif (!is_writable($tempDir)) { + } + + if (!is_writable($tempDir)) { throw new Error\Exception( 'Temporary directory "' . $tempDir . '" cannot be written to by the current user' . diff --git a/src/SimpleSAML/Utils/Time.php b/src/SimpleSAML/Utils/Time.php index f09b93a75e..42d1b40aaf 100644 --- a/src/SimpleSAML/Utils/Time.php +++ b/src/SimpleSAML/Utils/Time.php @@ -28,11 +28,11 @@ class Time /** * This function generates a timestamp on the form used by the SAML protocols. * - * @param int $instant The time the timestamp should represent. Defaults to current time. + * @param int|null $instant The time the timestamp should represent. Defaults to current time. * * @return string The timestamp. */ - public function generateTimestamp(int $instant = null): string + public function generateTimestamp(?int $instant = null): string { if ($instant === null) { $instant = time(); @@ -82,14 +82,14 @@ public function initTimezone(): void * durations specified in the formats PYYYYMMDDThhmmss nor P[YYYY]-[MM]-[DD]T[hh]:[mm]:[ss]. * * @param string $duration The duration, as a string. - * @param int $timestamp The unix timestamp we should apply the duration to. Optional, default to the current + * @param int|null $timestamp The unix timestamp we should apply the duration to. Optional, default to the current * time. * * @return int The new timestamp, after the duration is applied. * @throws \InvalidArgumentException If $duration is not a valid ISO 8601 duration or if the input parameters do * not have the right data types. */ - public function parseDuration(string $duration, int $timestamp = null): int + public function parseDuration(string $duration, ?int $timestamp = null): int { Assert::validDuration($duration); diff --git a/src/SimpleSAML/Utils/XML.php b/src/SimpleSAML/Utils/XML.php index dc2645a660..967da6e090 100644 --- a/src/SimpleSAML/Utils/XML.php +++ b/src/SimpleSAML/Utils/XML.php @@ -345,7 +345,7 @@ public function isValid(string|DOMDocument $xml, string $schema) * @param array $context * @return string|null */ - function (string $public = null, string $system, /** @scrutinizer ignore-unused */ array $context) { + function (?string $public = null, string $system = '', /** @scrutinizer ignore-unused */ array $context = []) { if (filter_var($system, FILTER_VALIDATE_URL) === $system) { return null; } diff --git a/tests/modules/cron/src/Controller/CronTest.php b/tests/modules/cron/src/Controller/CronTest.php index 603ac7da46..6e0e878780 100644 --- a/tests/modules/cron/src/Controller/CronTest.php +++ b/tests/modules/cron/src/Controller/CronTest.php @@ -5,8 +5,10 @@ namespace SimpleSAML\Test\Module\cron\Controller; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use SimpleSAML\Configuration; +use SimpleSAML\Error; use SimpleSAML\Module\cron\Controller; use SimpleSAML\Session; use SimpleSAML\Utils; @@ -45,6 +47,7 @@ protected function setUp(): void '[ARRAY]', 'simplesaml', ); + Configuration::setPreLoadedConfig($this->config); $this->session = Session::getSessionFromRequest(); @@ -96,7 +99,7 @@ public function testInfo(): void /** */ - public function testRun(): void + public function testRunCorrectKey(): void { $_SERVER['REQUEST_URI'] = '/module.php/cron/run/daily/verysecret'; @@ -111,4 +114,79 @@ public function testRun(): void $this->assertCount(1, $response->data['summary']); $this->assertEquals('Cron did run tag [daily] at ' . $response->data['time'], $response->data['summary'][0]); } + + + /** + */ + public function testRunWrongKey(): void + { + $_SERVER['REQUEST_URI'] = '/module.php/cron/run/daily/nodice'; + + $c = new Controller\Cron($this->config, $this->session); + + $this->expectException(Error\Exception::class); + $this->expectExceptionMessage('Cron: Wrong key "nodice" provided. Cron will not run.'); + + $c->run('daily', 'nodice'); + } + + + /** + */ + #[DataProvider('provideDefaultSecret')] + public function testRunDefaultSecret(string $secret): void + { + $_SERVER['REQUEST_URI'] = '/module.php/cron/run/daily/' . $secret; + + $c = new Controller\Cron($this->config, $this->session); + + $this->expectException(Error\ConfigurationError::class); + $this->expectExceptionMessage('Cron: Possible malicious attempt to run cron tasks with default secret'); + + $c->run('daily', $secret); + } + + + /** + */ + #[DataProvider('provideDefaultSecret')] + public function testRunDefaultConfigSecret(string $configKey): void + { + Configuration::setPreLoadedConfig( + Configuration::loadFromArray( + [ + 'key' => $configKey, + 'allowed_tags' => ['daily'], + 'sendemail' => false, + ], + '[ARRAY]', + 'simplesaml', + ), + 'module_cron.php', + 'simplesaml', + ); + + $_SERVER['REQUEST_URI'] = '/module.php/cron/run/daily/verysecret'; + + $c = new Controller\Cron($this->config, $this->session); + + $this->expectException(Error\ConfigurationError::class); + $this->expectExceptionMessage('Cron: no proper key has been configured.'); + + $c->run('daily', 'verysecret'); + } + + + /** + * @return array + */ + public static function provideDefaultSecret(): array + { + return [ + // Config template + ['secret'], + // Documentation inside several modules + ['RANDOM_KEY'], + ]; + } } diff --git a/tests/src/SimpleSAML/ConfigurationTest.php b/tests/src/SimpleSAML/ConfigurationTest.php index 5d366620d6..d20c0c2eee 100644 --- a/tests/src/SimpleSAML/ConfigurationTest.php +++ b/tests/src/SimpleSAML/ConfigurationTest.php @@ -35,7 +35,11 @@ public function testLoadDefaultInstance(): void { $this->expectException(Error\CriticalConfigurationError::class); Configuration::loadFromArray(['key' => 'value'], '', 'dummy'); + + // Point to a directory that will have no Configuration file + putenv('SIMPLESAMLPHP_CONFIG_DIR=/'); Configuration::getInstance(); + putenv('SIMPLESAMLPHP_CONFIG_DIR'); } @@ -45,6 +49,8 @@ public function testLoadDefaultInstance(): void */ public function testCriticalConfigurationError(): void { + // Do not rely on the default directory. Target another directory. + putenv('SIMPLESAMLPHP_CONFIG_DIR=/'); try { Configuration::getInstance(); $this->fail('Exception expected'); @@ -57,6 +63,7 @@ public function testCriticalConfigurationError(): void */ $c = Configuration::getInstance(); $this->assertNotEmpty($c->toArray()); + putenv('SIMPLESAMLPHP_CONFIG_DIR'); } diff --git a/tests/src/SimpleSAML/SessionHandlerPHPTest.php b/tests/src/SimpleSAML/SessionHandlerPHPTest.php index 7f2b1b45a1..75ad24b730 100644 --- a/tests/src/SimpleSAML/SessionHandlerPHPTest.php +++ b/tests/src/SimpleSAML/SessionHandlerPHPTest.php @@ -5,6 +5,8 @@ namespace SimpleSAML\Test; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Depends; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\Attributes\RunInSeparateProcess; use SimpleSAML\{Configuration, SessionHandlerPHP}; @@ -50,6 +52,18 @@ protected function tearDown(): void } + /** + */ + #[DoesNotPerformAssertions] + #[RequiresPhpExtension('xdebug')] + public function testXdebugMode(): void + { + if (!in_array('develop', xdebug_info('mode'))) { + $this->markTestSkipped('xdebug.mode != develop'); + } + } + + /** */ public function testGetSessionHandler(): void @@ -62,7 +76,7 @@ public function testGetSessionHandler(): void /** */ - #[RequiresPhpExtension('xdebug')] + #[Depends('testXdebugMode')] #[RunInSeparateProcess] public function testSetCookie(): void { @@ -85,7 +99,7 @@ public function testSetCookie(): void /** */ - #[RequiresPhpExtension('xdebug')] + #[Depends('testXdebugMode')] #[RunInSeparateProcess] public function testSetCookieSameSiteNone(): void { @@ -105,7 +119,7 @@ public function testSetCookieSameSiteNone(): void /** */ - #[RequiresPhpExtension('xdebug')] + #[Depends('testXdebugMode')] #[RunInSeparateProcess] public function testSetCookieSameSiteLax(): void { @@ -125,7 +139,7 @@ public function testSetCookieSameSiteLax(): void /** */ - #[RequiresPhpExtension('xdebug')] + #[Depends('testXdebugMode')] #[RunInSeparateProcess] public function testSetCookieSameSiteStrict(): void { @@ -145,7 +159,7 @@ public function testSetCookieSameSiteStrict(): void /** */ - #[RequiresPhpExtension('xdebug')] + #[Depends('testXdebugMode')] #[RunInSeparateProcess] public function testRestorePrevious(): void { diff --git a/tests/src/SimpleSAML/Utils/HTTPTest.php b/tests/src/SimpleSAML/Utils/HTTPTest.php index e48b66210c..b20782889b 100644 --- a/tests/src/SimpleSAML/Utils/HTTPTest.php +++ b/tests/src/SimpleSAML/Utils/HTTPTest.php @@ -6,6 +6,8 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Depends; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\Attributes\RunInSeparateProcess; use SimpleSAML\{Configuration, Error, Utils}; @@ -446,7 +448,19 @@ public function testCheckURLAllowedWithRegexWithoutDelimiters(): void /** */ + #[DoesNotPerformAssertions] #[RequiresPhpExtension('xdebug')] + public function testXdebugMode(): void + { + if (!in_array('develop', xdebug_info('mode'))) { + $this->markTestSkipped('xdebug.mode != develop'); + } + } + + + /** + */ + #[Depends('testXdebugMode')] #[RunInSeparateProcess] public function testSetCookie(): void { @@ -528,7 +542,7 @@ public function testSetCookieInsecure(): void /** */ - #[RequiresPhpExtension('xdebug')] + #[Depends('testXdebugMode')] #[RunInSeparateProcess] public function testSetCookieSameSite(): void { diff --git a/tools/linters/.eslintrc.js b/tools/linters/.eslintrc.js deleted file mode 100644 index eeca409acb..0000000000 --- a/tools/linters/.eslintrc.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - ignorePatterns: ["!/tools/linters/.eslintrc.yml", "!/tools/linters/.stylelintrc.json"], - parserOptions: { - ecmaVersion: 2015, - sourceType: "module" - }, - overrides: [ - { - files: ["*.json"], - extends: ["plugin:jsonc/recommended-with-json"], - parser: "jsonc-eslint-parser", - } - ] -}; diff --git a/tools/linters/.stylelintrc.json b/tools/linters/.stylelintrc.json index 3296f8568c..a278b06e44 100644 --- a/tools/linters/.stylelintrc.json +++ b/tools/linters/.stylelintrc.json @@ -1,8 +1,4 @@ { - "extends": [ - "stylelint-config-standard-scss", - "stylelint-config-recommended-scss" - ], "overrides": [ { "files": ["*.scss", "**/*.scss"], diff --git a/tools/linters/eslint.config.js b/tools/linters/eslint.config.js new file mode 100644 index 0000000000..c1e1c39cac --- /dev/null +++ b/tools/linters/eslint.config.js @@ -0,0 +1,19 @@ +// eslint.config.js +const { defineConfig } = require("eslint/config"); + +module.exports = defineConfig([ + { + ignores: ["!/tools/linters/.eslint.config.js", "!/tools/linters/.stylelintrc.json"], + languageOptions: { + ecmaVersion: 2015, + sourceType: "module" + }, + files: [ + "**/*.js", + ], + rules: { + semi: "error", + "prefer-const": "error" + } + } +]);