diff --git a/.gitattributes b/.gitattributes index b265272a54..f26a230f4b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -21,3 +21,5 @@ phpunit.xml export-ignore .markdownlintignore export-ignore .markdownlint.yml export-ignore .markdownlintrc export-ignore +*.php.dist linguist-language=php +.phive diff --git a/.github/build/full.json b/.github/build/full.json index 01e660dbc2..1a7ffa5346 100644 --- a/.github/build/full.json +++ b/.github/build/full.json @@ -2,7 +2,7 @@ "modules": { "authorize": { "repository": "simplesamlphp/simplesamlphp-module-authorize", - "version": "~1.6.0" + "version": "~1.6.2" }, "consent": { "repository": "simplesamlphp/simplesamlphp-module-consent", @@ -10,31 +10,31 @@ }, "consentadmin": { "repository": "simplesamlphp/simplesamlphp-module-consentadmin", - "version": "~1.0.0" + "version": "~1.1.0" }, "discopower": { "repository": "simplesamlphp/simplesamlphp-module-discopower", - "version": "~1.4.0" + "version": "~1.4.1" }, "ldap": { "repository": "simplesamlphp/simplesamlphp-module-ldap", - "version": "~2.3.0" + "version": "~2.3.7" }, "metarefresh": { "repository": "simplesamlphp/simplesamlphp-module-metarefresh", - "version": "~1.2.0" + "version": "~1.2.4" }, "radius": { "repository": "simplesamlphp/simplesamlphp-module-radius", - "version": "~2.0.0" + "version": "~2.0.3" }, "statistics": { "repository": "simplesamlphp/simplesamlphp-module-statistics", - "version": "~1.2.0" + "version": "~1.2.2" }, "sqlauth": { "repository": "simplesamlphp/simplesamlphp-module-sqlauth", - "version": "~1.3.0" + "version": "~1.3.1" } } } diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index c5bf246974..51764f4b84 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -13,50 +13,69 @@ 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 - steps: - - uses: actions/checkout@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 + 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 - quality: - name: Quality control - runs-on: [ubuntu-latest] + 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 - id: setup-php # https://github.com/shivammathur/setup-php uses: shivammathur/setup-php@v2 with: - php-version: '8.3' - tools: composer, phpcs, psalm - extensions: mbstring, xml - coverage: none + 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" @@ -67,63 +86,60 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - - name: Validate composer.json and composer.lock - run: composer validate - - name: Install Composer dependencies run: composer install --no-progress --prefer-dist --optimize-autoloader - - name: PHP Code Sniffer - run: phpcs - - - name: Psalm - continue-on-error: true - run: | - psalm \ - -c psalm.xml \ - --show-info=true \ - --shepherd \ - --php-version=${{ steps.setup-php.outputs.php-version }} + - name: Run unit tests with coverage + if: ${{ matrix.php-versions == '8.1' }} + run: ./vendor/bin/phpunit - - name: Psalm (testsuite) - run: | - psalm \ - -c psalm-dev.xml \ - --show-info=true \ - --shepherd \ - --php-version=${{ steps.setup-php.outputs.php-version }} + - name: Run unit tests (no coverage) + if: ${{ matrix.php-versions != '8.1' }} + run: ./vendor/bin/phpunit --no-coverage - - name: Psalter - run: | - psalm --alter \ - --issues=UnnecessaryVarAnnotation \ - --dry-run \ - --php-version=${{ steps.setup-php.outputs.php-version }} + - name: Save coverage data + if: ${{ matrix.php-versions == '8.1' }} + uses: actions/upload-artifact@v4 + with: + name: coverage-data + path: ${{ github.workspace }}/build - - name: Check for unused translations - continue-on-error: true - run: composer translations:unused + 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'] - security: - name: Security checks - runs-on: [ubuntu-latest] steps: - name: Setup PHP, with composer and extensions # https://github.com/shivammathur/setup-php uses: shivammathur/setup-php@v2 with: - php-version: '8.1' - extensions: mbstring, xml + 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)" >> "$GITHUB_ENV" + run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$env:GITHUB_ENV" - name: Cache composer dependencies uses: actions/cache@v4 @@ -133,49 +149,30 @@ jobs: restore-keys: ${{ runner.os }}-composer- - name: Install Composer dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Security check for locked dependencies - run: composer audit - - - name: Update Composer dependencies - run: composer update --no-progress --prefer-dist --optimize-autoloader + run: composer install --no-progress --prefer-dist --optimize-autoloader --no-scripts - - name: Security check for updated dependencies - run: composer audit + - name: Run unit tests + run: ./vendor/bin/phpunit --no-coverage - 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'] + quality: + name: Quality control + needs: [unit-tests-linux] + runs-on: [ubuntu-latest] steps: - name: Setup PHP, with composer and extensions + id: setup-php # 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 + php-version: '8.4' + tools: composer, phpcs, psalm + extensions: mbstring, xml + 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 @@ -188,60 +185,65 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- + - name: Validate composer.json and composer.lock + run: composer validate + - 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: PHP Code Sniffer + run: phpcs - - name: Run unit tests (no coverage) - if: ${{ matrix.php-versions != '8.1' }} - run: ./vendor/bin/phpunit --no-coverage + - name: Psalm + continue-on-error: true + run: | + psalm \ + -c psalm.xml \ + --show-info=true \ + --shepherd \ + --php-version=${{ steps.setup-php.outputs.php-version }} - - name: Save coverage data - if: ${{ matrix.php-versions == '8.1' }} - uses: actions/upload-artifact@v4 - with: - name: coverage-data - path: ${{ github.workspace }}/build + - name: Psalm (testsuite) + continue-on-error: true + run: | + psalm \ + -c psalm-dev.xml \ + --show-info=true \ + --shepherd \ + --php-version=${{ steps.setup-php.outputs.php-version }} - 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'] + - name: Psalter + run: | + psalm --alter \ + --issues=UnnecessaryVarAnnotation \ + --dry-run \ + --php-version=${{ steps.setup-php.outputs.php-version }} + - name: Check for unused translations + continue-on-error: true + run: composer translations:unused + + security: + name: Security checks + needs: [unit-tests-linux] + runs-on: [ubuntu-latest] 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 + php-version: '8.1' + extensions: mbstring, 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" + run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$GITHUB_ENV" - name: Cache composer dependencies uses: actions/cache@v4 @@ -253,8 +255,14 @@ jobs: - name: Install Composer dependencies run: composer install --no-progress --prefer-dist --optimize-autoloader - - name: Run unit tests - run: ./vendor/bin/phpunit --no-coverage + - name: Security check for locked dependencies + run: composer audit + + - name: Update Composer dependencies + run: composer update --no-progress --prefer-dist --optimize-autoloader + + - name: Security check for updated dependencies + run: composer audit coverage: name: Code coverage diff --git a/COPYING b/COPYING index b83b1c411c..f1d41affca 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -Copyright 2007-2020 UNINETT AS, 2021-2023 SimpleSAMLphp +Copyright 2007-2020 UNINETT AS, 2021-2024 SimpleSAMLphp SimpleSAMLphp is licensed under the CC-GNU LGPL version 2.1. http://creativecommons.org/licenses/LGPL/2.1/ diff --git a/composer.json b/composer.json index 72c4683994..4f56ae4438 100644 --- a/composer.json +++ b/composer.json @@ -62,10 +62,10 @@ "phpmailer/phpmailer": "^6.8", "psr/log": "^3.0", "simplesamlphp/assert": "^1.1", - "simplesamlphp/composer-module-installer": "^1.3", - "simplesamlphp/saml2": "^4.6", + "simplesamlphp/composer-module-installer": "~1.3.6", + "simplesamlphp/saml2": "^4.19.2", "simplesamlphp/simplesamlphp-assets-base": "~2.3.0", - "simplesamlphp/xml-security": "^1.7", + "simplesamlphp/xml-security": "^1.13.9", "symfony/cache": "^6.4", "symfony/config": "^6.4", "symfony/console": "^6.4", @@ -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": { @@ -123,12 +123,12 @@ }, "extra": { "branch-alias": { - "dev-master": "2.4.0.x-dev" + "dev-master": "2.3.0.x-dev" } }, "scripts": { "translations:unused": "php bin/translations translations:unused", "translations:update:translatable": "php bin/translations translations:update:translatable" }, - "version": "v2.3.2" + "version": "v2.3.11" } diff --git a/composer.lock b/composer.lock index 7604f4c266..52337f256b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "282e14b6588f9aae2d41c3260e038b24", + "content-hash": "9c9942b0958f9f07ada6d99609c44b5d", "packages": [ { "name": "gettext/gettext", - "version": "v5.7.1", + "version": "v5.7.3", "source": { "type": "git", "url": "https://github.com/php-gettext/Gettext.git", - "reference": "a9f89e0cc9d9a67b422632b594b5f1afb16eccfc" + "reference": "95820f020e4f2f05e0bbaa5603e4c6ec3edc50f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/a9f89e0cc9d9a67b422632b594b5f1afb16eccfc", - "reference": "a9f89e0cc9d9a67b422632b594b5f1afb16eccfc", + "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/95820f020e4f2f05e0bbaa5603e4c6ec3edc50f1", + "reference": "95820f020e4f2f05e0bbaa5603e4c6ec3edc50f1", "shasum": "" }, "require": { @@ -62,7 +62,7 @@ "support": { "email": "oom@oscarotero.com", "issues": "https://github.com/php-gettext/Gettext/issues", - "source": "https://github.com/php-gettext/Gettext/tree/v5.7.1" + "source": "https://github.com/php-gettext/Gettext/tree/v5.7.3" }, "funding": [ { @@ -78,20 +78,20 @@ "type": "patreon" } ], - "time": "2024-07-24T22:05:18+00:00" + "time": "2024-12-01T10:18:08+00:00" }, { "name": "gettext/languages", - "version": "2.10.0", + "version": "2.12.2", "source": { "type": "git", "url": "https://github.com/php-gettext/Languages.git", - "reference": "4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab" + "reference": "079d6f4842cbcbf5673a70d8e93169a684e7aadd" }, "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/079d6f4842cbcbf5673a70d8e93169a684e7aadd", + "reference": "079d6f4842cbcbf5673a70d8e93169a684e7aadd", "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.2" }, "funding": [ { @@ -152,20 +153,20 @@ "type": "github" } ], - "time": "2022-10-18T15:00:10+00:00" + "time": "2026-02-23T14:05:50+00:00" }, { "name": "gettext/translator", - "version": "v1.2.0", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/php-gettext/Translator.git", - "reference": "a4fa5ed740f304a0ed7b3e169b2b554a195c7570" + "reference": "8ae0ac79053bcb732a6c584cd86f7a82ef183161" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-gettext/Translator/zipball/a4fa5ed740f304a0ed7b3e169b2b554a195c7570", - "reference": "a4fa5ed740f304a0ed7b3e169b2b554a195c7570", + "url": "https://api.github.com/repos/php-gettext/Translator/zipball/8ae0ac79053bcb732a6c584cd86f7a82ef183161", + "reference": "8ae0ac79053bcb732a6c584cd86f7a82ef183161", "shasum": "" }, "require": { @@ -210,7 +211,7 @@ "support": { "email": "oom@oscarotero.com", "issues": "https://github.com/php-gettext/Translator/issues", - "source": "https://github.com/php-gettext/Translator/tree/v1.2.0" + "source": "https://github.com/php-gettext/Translator/tree/v1.2.1" }, "funding": [ { @@ -226,44 +227,51 @@ "type": "patreon" } ], - "time": "2023-11-06T15:42:03+00:00" + "time": "2025-01-09T09:20:22+00:00" }, { - "name": "league/uri-interfaces", - "version": "7.4.1", + "name": "guzzlehttp/psr7", + "version": "2.10.1", "source": { "type": "git", - "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "8d43ef5c841032c87e2de015972c06f3865ef718" + "url": "https://github.com/guzzle/psr7.git", + "reference": "73ab136360b5dfd858006eae9795e8fe43c80361" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/8d43ef5c841032c87e2de015972c06f3865ef718", - "reference": "8d43ef5c841032c87e2de015972c06f3865ef718", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/73ab136360b5dfd858006eae9795e8fe43c80361", + "reference": "73ab136360b5dfd858006eae9795e8fe43c80361", "shasum": "" }, "require": { - "ext-filter": "*", - "php": "^8.1", - "psr/http-factory": "^1", - "psr/http-message": "^1.1 || ^2.0" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "1.1.0", + "jshttp/mime-db": "1.54.0.1", + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "suggest": { - "ext-bcmath": "to improve IPV4 host parsing", - "ext-gmp": "to improve IPV4 host parsing", - "ext-intl": "to handle IDN host with the best performance", - "php-64bit": "to improve IPV4 host parsing", - "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "7.x-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { "psr-4": { - "League\\Uri\\": "" + "GuzzleHttp\\Psr7\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -272,58 +280,84 @@ ], "authors": [ { - "name": "Ignace Nyamagana Butera", - "email": "nyamsprod@gmail.com", - "homepage": "https://nyamsprod.com" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], - "description": "Common interfaces and classes for URI representation and interaction", - "homepage": "https://uri.thephpleague.com", + "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ - "data-uri", - "file-uri", - "ftp", - "hostname", "http", - "https", - "parse_str", - "parse_url", + "message", "psr-7", - "query-string", - "querystring", - "rfc3986", - "rfc3987", - "rfc6570", + "request", + "response", + "stream", "uri", - "url", - "ws" + "url" ], "support": { - "docs": "https://uri.thephpleague.com", - "forum": "https://thephpleague.slack.com", - "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.4.1" + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.10.1" }, "funding": [ { - "url": "https://github.com/sponsors/nyamsprod", + "url": "https://github.com/GrahamCampbell", "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" } ], - "time": "2024-03-23T07:42:40+00:00" + "time": "2026-05-20T09:27:36+00:00" }, { "name": "phpmailer/phpmailer", - "version": "v6.9.1", + "version": "v6.12.0", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "039de174cd9c17a8389754d3b877a2ed22743e18" + "reference": "d1ac35d784bf9f5e61b424901d5a014967f15b12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/039de174cd9c17a8389754d3b877a2ed22743e18", - "reference": "039de174cd9c17a8389754d3b877a2ed22743e18", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/d1ac35d784bf9f5e61b424901d5a014967f15b12", + "reference": "d1ac35d784bf9f5e61b424901d5a014967f15b12", "shasum": "" }, "require": { @@ -383,7 +417,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.1" + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.12.0" }, "funding": [ { @@ -391,7 +425,7 @@ "type": "github" } ], - "time": "2023-11-25T22:23:28+00:00" + "time": "2025-10-15T16:49:08+00:00" }, { "name": "psr/cache", @@ -655,16 +689,16 @@ }, { "name": "psr/log", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "79dff0b268932c640297f5208d6298f71855c03e" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/79dff0b268932c640297f5208d6298f71855c03e", - "reference": "79dff0b268932c640297f5208d6298f71855c03e", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -699,22 +733,66 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.1" + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" }, - "time": "2024-08-21T13:31:24+00:00" + "time": "2019-03-08T08:55:37+00:00" }, { "name": "robrichards/xmlseclibs", - "version": "3.1.1", + "version": "3.1.5", "source": { "type": "git", "url": "https://github.com/robrichards/xmlseclibs.git", - "reference": "f8f19e58f26cdb42c54b214ff8a820760292f8df" + "reference": "03062be78178cbb5e8f605cd255dc32a14981f92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/f8f19e58f26cdb42c54b214ff8a820760292f8df", - "reference": "f8f19e58f26cdb42c54b214ff8a820760292f8df", + "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/03062be78178cbb5e8f605cd255dc32a14981f92", + "reference": "03062be78178cbb5e8f605cd255dc32a14981f92", "shasum": "" }, "require": { @@ -741,22 +819,22 @@ ], "support": { "issues": "https://github.com/robrichards/xmlseclibs/issues", - "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.1" + "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.5" }, - "time": "2020-09-05T13:00:25+00:00" + "time": "2026-03-13T10:31:56+00:00" }, { "name": "simplesamlphp/assert", - "version": "v1.3.0", + "version": "v1.8.4", "source": { "type": "git", "url": "https://github.com/simplesamlphp/assert.git", - "reference": "7b7ef2a68eb0e36e67915ebd802e1bb29483d7d9" + "reference": "7250fb858b025032590078fc4cc52a4c1b634dbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/assert/zipball/7b7ef2a68eb0e36e67915ebd802e1bb29483d7d9", - "reference": "7b7ef2a68eb0e36e67915ebd802e1bb29483d7d9", + "url": "https://api.github.com/repos/simplesamlphp/assert/zipball/7250fb858b025032590078fc4cc52a4c1b634dbb", + "reference": "7250fb858b025032590078fc4cc52a4c1b634dbb", "shasum": "" }, "require": { @@ -764,13 +842,13 @@ "ext-filter": "*", "ext-pcre": "*", "ext-spl": "*", - "league/uri-interfaces": "^7.4", + "guzzlehttp/psr7": "~2.7", "php": "^8.1", - "webmozart/assert": "^1.11" + "webmozart/assert": "~1.11.0" }, "require-dev": { "ext-intl": "*", - "simplesamlphp/simplesamlphp-test-framework": "^1.7" + "simplesamlphp/simplesamlphp-test-framework": "~1.9.2" }, "type": "library", "extra": { @@ -800,22 +878,22 @@ "description": "A wrapper around webmozart/assert to make it useful beyond checking method arguments", "support": { "issues": "https://github.com/simplesamlphp/assert/issues", - "source": "https://github.com/simplesamlphp/assert/tree/v1.3.0" + "source": "https://github.com/simplesamlphp/assert/tree/v1.8.4" }, - "time": "2024-07-26T11:30:06+00:00" + "time": "2026-03-18T11:27:23+00:00" }, { "name": "simplesamlphp/composer-module-installer", - "version": "v1.3.4", + "version": "v1.3.6", "source": { "type": "git", "url": "https://github.com/simplesamlphp/composer-module-installer.git", - "reference": "36508ed9580a30c4d5ab0bb3c25c00d0b5d42946" + "reference": "58ff5fcb1e060015ba254c993ae11594662ffd24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/composer-module-installer/zipball/36508ed9580a30c4d5ab0bb3c25c00d0b5d42946", - "reference": "36508ed9580a30c4d5ab0bb3c25c00d0b5d42946", + "url": "https://api.github.com/repos/simplesamlphp/composer-module-installer/zipball/58ff5fcb1e060015ba254c993ae11594662ffd24", + "reference": "58ff5fcb1e060015ba254c993ae11594662ffd24", "shasum": "" }, "require": { @@ -843,22 +921,64 @@ "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.3.4" + "source": "https://github.com/simplesamlphp/composer-module-installer/tree/v1.3.6" + }, + "time": "2025-03-19T20:38:37+00:00" + }, + { + "name": "simplesamlphp/composer-xmlprovider-installer", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/simplesamlphp/composer-xmlprovider-installer.git", + "reference": "3d882187b5b0b404c381a2e4d17498ca4b2785b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/simplesamlphp/composer-xmlprovider-installer/zipball/3d882187b5b0b404c381a2e4d17498ca4b2785b3", + "reference": "3d882187b5b0b404c381a2e4d17498ca4b2785b3", + "shasum": "" }, - "time": "2023-03-08T20:58:22+00:00" + "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.2" + }, + "time": "2025-06-28T18:54:25+00:00" }, { "name": "simplesamlphp/saml2", - "version": "v4.6.12", + "version": "v4.19.2", "source": { "type": "git", "url": "https://github.com/simplesamlphp/saml2.git", - "reference": "9545abd0d9d48388f2fa00469c5c1e0294f0303e" + "reference": "93df4bffc052939e74ec0c1208e66cbd7eb2a1b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/9545abd0d9d48388f2fa00469c5c1e0294f0303e", - "reference": "9545abd0d9d48388f2fa00469c5c1e0294f0303e", + "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/93df4bffc052939e74ec0c1208e66cbd7eb2a1b2", + "reference": "93df4bffc052939e74ec0c1208e66cbd7eb2a1b2", "shasum": "" }, "require": { @@ -867,9 +987,12 @@ "ext-zlib": "*", "php": ">=7.1 || ^8.0", "psr/log": "~1.1 || ^2.0 || ^3.0", - "robrichards/xmlseclibs": "^3.1.1", + "robrichards/xmlseclibs": "^3.1.5", "webmozart/assert": "^1.9" }, + "conflict": { + "robrichards/xmlseclibs": "3.1.2" + }, "require-dev": { "mockery/mockery": "^1.3", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", @@ -901,22 +1024,22 @@ "description": "SAML2 PHP library from SimpleSAMLphp", "support": { "issues": "https://github.com/simplesamlphp/saml2/issues", - "source": "https://github.com/simplesamlphp/saml2/tree/v4.6.12" + "source": "https://github.com/simplesamlphp/saml2/tree/v4.19.2" }, - "time": "2024-04-25T14:10:08+00:00" + "time": "2026-03-13T12:09:45+00:00" }, { "name": "simplesamlphp/simplesamlphp-assets-base", - "version": "v2.3.0", + "version": "v2.3.15", "source": { "type": "git", "url": "https://github.com/simplesamlphp/simplesamlphp-assets-base.git", - "reference": "c6396600f0929dde7b78de41e6841251a3467063" + "reference": "8238c8067fe87c14a2e16b53db938beb65a10d9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-assets-base/zipball/c6396600f0929dde7b78de41e6841251a3467063", - "reference": "c6396600f0929dde7b78de41e6841251a3467063", + "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-assets-base/zipball/8238c8067fe87c14a2e16b53db938beb65a10d9f", + "reference": "8238c8067fe87c14a2e16b53db938beb65a10d9f", "shasum": "" }, "require": { @@ -937,38 +1060,40 @@ "description": "Assets for the SimpleSAMLphp main repository", "support": { "issues": "https://github.com/simplesamlphp/simplesamlphp-assets-base/issues", - "source": "https://github.com/simplesamlphp/simplesamlphp-assets-base/tree/v2.3.0" + "source": "https://github.com/simplesamlphp/simplesamlphp-assets-base/tree/v2.3.15" }, - "time": "2024-09-06T16:21:56+00:00" + "time": "2026-03-04T16:52:18+00:00" }, { "name": "simplesamlphp/xml-common", - "version": "v1.17.2", + "version": "v1.25.1", "source": { "type": "git", "url": "https://github.com/simplesamlphp/xml-common.git", - "reference": "c76769ab4e8eb7153f31d083e7af7f06f9747ed7" + "reference": "999603aa521d91e17b562bb0b498513af80eb190" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/xml-common/zipball/c76769ab4e8eb7153f31d083e7af7f06f9747ed7", - "reference": "c76769ab4e8eb7153f31d083e7af7f06f9747ed7", + "url": "https://api.github.com/repos/simplesamlphp/xml-common/zipball/999603aa521d91e17b562bb0b498513af80eb190", + "reference": "999603aa521d91e17b562bb0b498513af80eb190", "shasum": "" }, "require": { "ext-date": "*", "ext-dom": "*", + "ext-filter": "*", "ext-libxml": "*", "ext-pcre": "*", "ext-spl": "*", - "ext-xmlreader": "*", "php": "^8.1", - "simplesamlphp/assert": "^1.2" + "simplesamlphp/assert": "~1.8.1", + "simplesamlphp/composer-xmlprovider-installer": "~1.0.2", + "symfony/finder": "~6.4.0" }, "require-dev": { - "simplesamlphp/simplesamlphp-test-framework": "^1.7" + "simplesamlphp/simplesamlphp-test-framework": "~1.9.2" }, - "type": "project", + "type": "simplesamlphp-xmlprovider", "autoload": { "psr-4": { "SimpleSAML\\XML\\": "src/" @@ -998,20 +1123,20 @@ "issues": "https://github.com/simplesamlphp/xml-common/issues", "source": "https://github.com/simplesamlphp/xml-common" }, - "time": "2024-09-03T19:35:21+00:00" + "time": "2025-06-29T13:05:44+00:00" }, { "name": "simplesamlphp/xml-security", - "version": "v1.8.7", + "version": "v1.13.9", "source": { "type": "git", "url": "https://github.com/simplesamlphp/xml-security.git", - "reference": "10071025f286b49edd7f30a12ab216515c170925" + "reference": "16a5cf4a107e1b607337ff5af5fb4051fcc23ba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/xml-security/zipball/10071025f286b49edd7f30a12ab216515c170925", - "reference": "10071025f286b49edd7f30a12ab216515c170925", + "url": "https://api.github.com/repos/simplesamlphp/xml-security/zipball/16a5cf4a107e1b607337ff5af5fb4051fcc23ba0", + "reference": "16a5cf4a107e1b607337ff5af5fb4051fcc23ba0", "shasum": "" }, "require": { @@ -1022,13 +1147,13 @@ "ext-pcre": "*", "ext-spl": "*", "php": "^8.1", - "simplesamlphp/assert": "^1.1", - "simplesamlphp/xml-common": "^1.15" + "simplesamlphp/assert": "~1.8.1", + "simplesamlphp/xml-common": "~1.25.0" }, "require-dev": { - "simplesamlphp/simplesamlphp-test-framework": "^1.5" + "simplesamlphp/simplesamlphp-test-framework": "~1.9.2" }, - "type": "library", + "type": "simplesamlphp-xmlprovider", "autoload": { "psr-4": { "SimpleSAML\\XMLSecurity\\": "src/" @@ -1060,22 +1185,22 @@ ], "support": { "issues": "https://github.com/simplesamlphp/xml-security/issues", - "source": "https://github.com/simplesamlphp/xml-security/tree/v1.8.7" + "source": "https://github.com/simplesamlphp/xml-security/tree/v1.13.9" }, - "time": "2024-09-03T18:57:31+00:00" + "time": "2026-03-13T15:41:00+00:00" }, { "name": "symfony/cache", - "version": "v6.4.11", + "version": "v6.4.40", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "36daef8fce88fe0b9a4f8cf4c342ced5c05616dc" + "reference": "8f9b022e63fa02bd984c06dc886039936ea17714" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/36daef8fce88fe0b9a4f8cf4c342ced5c05616dc", - "reference": "36daef8fce88fe0b9a4f8cf4c342ced5c05616dc", + "url": "https://api.github.com/repos/symfony/cache/zipball/8f9b022e63fa02bd984c06dc886039936ea17714", + "reference": "8f9b022e63fa02bd984c06dc886039936ea17714", "shasum": "" }, "require": { @@ -1142,7 +1267,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.11" + "source": "https://github.com/symfony/cache/tree/v6.4.40" }, "funding": [ { @@ -1153,25 +1278,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-05T07:40:31+00:00" + "time": "2026-05-19T20:33:22+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.5.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197" + "reference": "225e8a254166bd3442e370c6f50145465db63831" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/df6a1a44c890faded49a5fca33c2d5c5fd3c2197", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/225e8a254166bd3442e370c6f50145465db63831", + "reference": "225e8a254166bd3442e370c6f50145465db63831", "shasum": "" }, "require": { @@ -1180,12 +1309,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" } }, "autoload": { @@ -1218,7 +1347,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.7.0" }, "funding": [ { @@ -1229,25 +1358,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2026-05-05T15:33:14+00:00" }, { "name": "symfony/config", - "version": "v6.4.8", + "version": "v6.4.37", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "12e7e52515ce37191b193cf3365903c4f3951e35" + "reference": "ee615e8352db9c5f0b7b149154a3f654dc72042b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/12e7e52515ce37191b193cf3365903c4f3951e35", - "reference": "12e7e52515ce37191b193cf3365903c4f3951e35", + "url": "https://api.github.com/repos/symfony/config/zipball/ee615e8352db9c5f0b7b149154a3f654dc72042b", + "reference": "ee615e8352db9c5f0b7b149154a3f654dc72042b", "shasum": "" }, "require": { @@ -1293,7 +1426,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.8" + "source": "https://github.com/symfony/config/tree/v6.4.37" }, "funding": [ { @@ -1304,25 +1437,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2026-04-29T10:19:30+00:00" }, { "name": "symfony/console", - "version": "v6.4.11", + "version": "v6.4.39", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "42686880adaacdad1835ee8fc2a9ec5b7bd63998" + "reference": "c132f1215fe4aa45b70173cc00ce9a755dd31ec5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/42686880adaacdad1835ee8fc2a9ec5b7bd63998", - "reference": "42686880adaacdad1835ee8fc2a9ec5b7bd63998", + "url": "https://api.github.com/repos/symfony/console/zipball/c132f1215fe4aa45b70173cc00ce9a755dd31ec5", + "reference": "c132f1215fe4aa45b70173cc00ce9a755dd31ec5", "shasum": "" }, "require": { @@ -1387,7 +1524,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.11" + "source": "https://github.com/symfony/console/tree/v6.4.39" }, "funding": [ { @@ -1398,25 +1535,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-15T22:48:29+00:00" + "time": "2026-05-12T06:50:03+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.11", + "version": "v6.4.38", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "e93c8368dc9915c2fe12018ff22fcbbdd32c9a9e" + "reference": "f0990df92ee67721886a2a8b6e19a1bafbf3d7a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e93c8368dc9915c2fe12018ff22fcbbdd32c9a9e", - "reference": "e93c8368dc9915c2fe12018ff22fcbbdd32c9a9e", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f0990df92ee67721886a2a8b6e19a1bafbf3d7a4", + "reference": "f0990df92ee67721886a2a8b6e19a1bafbf3d7a4", "shasum": "" }, "require": { @@ -1424,7 +1565,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", @@ -1468,7 +1609,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.11" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.38" }, "funding": [ { @@ -1479,25 +1620,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-29T08:15:38+00:00" + "time": "2026-05-04T13:00:01+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b", + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b", "shasum": "" }, "require": { @@ -1505,12 +1650,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" } }, "autoload": { @@ -1535,7 +1680,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.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0" }, "funding": [ { @@ -1546,25 +1691,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2026-04-13T15:52:40+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.10", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "231f1b2ee80f72daa1972f7340297d67439224f0" + "reference": "2ea68f0e1835ad6a126f93bbc14cd236c10ab361" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/231f1b2ee80f72daa1972f7340297d67439224f0", - "reference": "231f1b2ee80f72daa1972f7340297d67439224f0", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/2ea68f0e1835ad6a126f93bbc14cd236c10ab361", + "reference": "2ea68f0e1835ad6a126f93bbc14cd236c10ab361", "shasum": "" }, "require": { @@ -1610,7 +1759,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.10" + "source": "https://github.com/symfony/error-handler/tree/v6.4.36" }, "funding": [ { @@ -1621,25 +1770,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2026-03-10T15:56:14+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.8", + "version": "v6.4.37", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b" + "reference": "2e3bf817ba9347341ab15926700fb6320367c0e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8d7507f02b06e06815e56bb39aa0128e3806208b", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2e3bf817ba9347341ab15926700fb6320367c0e1", + "reference": "2e3bf817ba9347341ab15926700fb6320367c0e1", "shasum": "" }, "require": { @@ -1690,7 +1843,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.8" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.37" }, "funding": [ { @@ -1701,25 +1854,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2026-04-13T14:11:12+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/ccba7060602b7fed0b03c85bf025257f76d9ef32", + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32", "shasum": "" }, "require": { @@ -1728,12 +1885,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" } }, "autoload": { @@ -1766,7 +1923,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.0" }, "funding": [ { @@ -1777,25 +1934,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2026-01-05T13:30:16+00:00" }, { "name": "symfony/filesystem", - "version": "v6.4.9", + "version": "v6.4.39", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b51ef8059159330b74a4d52f68e671033c0fe463" + "reference": "c507b077756b4e3e09adbbe7975fac81cd3722ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463", - "reference": "b51ef8059159330b74a4d52f68e671033c0fe463", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/c507b077756b4e3e09adbbe7975fac81cd3722ca", + "reference": "c507b077756b4e3e09adbbe7975fac81cd3722ca", "shasum": "" }, "require": { @@ -1832,7 +1993,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.9" + "source": "https://github.com/symfony/filesystem/tree/v6.4.39" }, "funding": [ { @@ -1843,25 +2004,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-06-28T09:49:33+00:00" + "time": "2026-05-07T13:11:42+00:00" }, { "name": "symfony/finder", - "version": "v6.4.11", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d7eb6daf8cd7e9ac4976e9576b32042ef7253453" + "reference": "9590e86be1d1c57bfbb16d0dd040345378c20896" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d7eb6daf8cd7e9ac4976e9576b32042ef7253453", - "reference": "d7eb6daf8cd7e9ac4976e9576b32042ef7253453", + "url": "https://api.github.com/repos/symfony/finder/zipball/9590e86be1d1c57bfbb16d0dd040345378c20896", + "reference": "9590e86be1d1c57bfbb16d0dd040345378c20896", "shasum": "" }, "require": { @@ -1896,7 +2061,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.11" + "source": "https://github.com/symfony/finder/tree/v6.4.34" }, "funding": [ { @@ -1907,25 +2072,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-13T14:27:37+00:00" + "time": "2026-01-28T15:16:37+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.4.10", + "version": "v6.4.39", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "6cbdb0cc3ddbb63499262cd3036882b08ee2690b" + "reference": "a9cd7d768b9658fb8e9fa505ade58e5211ed7049" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/6cbdb0cc3ddbb63499262cd3036882b08ee2690b", - "reference": "6cbdb0cc3ddbb63499262cd3036882b08ee2690b", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/a9cd7d768b9658fb8e9fa505ade58e5211ed7049", + "reference": "a9cd7d768b9658fb8e9fa505ade58e5211ed7049", "shasum": "" }, "require": { @@ -1934,7 +2103,7 @@ "php": ">=8.1", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/config": "^6.1|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4.12|^7.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.1|^7.0", "symfony/event-dispatcher": "^5.4|^6.0|^7.0", @@ -1961,9 +2130,10 @@ "symfony/lock": "<5.4", "symfony/mailer": "<5.4", "symfony/messenger": "<6.3", - "symfony/mime": "<6.4", + "symfony/mime": "<6.4.37|>=7.0,<7.4.9", "symfony/property-access": "<5.4", "symfony/property-info": "<5.4", + "symfony/runtime": "<5.4.45|>=6.0,<6.4.13|>=7.0,<7.1.6", "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/security-core": "<5.4", "symfony/security-csrf": "<5.4", @@ -1997,7 +2167,7 @@ "symfony/lock": "^5.4|^6.0|^7.0", "symfony/mailer": "^5.4|^6.0|^7.0", "symfony/messenger": "^6.3|^7.0", - "symfony/mime": "^6.4|^7.0", + "symfony/mime": "^6.4.37|^7.4.9", "symfony/notifier": "^5.4|^6.0|^7.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/process": "^5.4|^6.0|^7.0", @@ -2044,7 +2214,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.10" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.39" }, "funding": [ { @@ -2055,25 +2225,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-07-26T13:24:20+00:00" + "time": "2026-05-13T11:43:22+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.10", + "version": "v6.4.35", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "117f1f20a7ade7bcea28b861fb79160a21a1e37b" + "reference": "cffffd0a2c037117b742b4f8b379a22a2a33f6d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/117f1f20a7ade7bcea28b861fb79160a21a1e37b", - "reference": "117f1f20a7ade7bcea28b861fb79160a21a1e37b", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/cffffd0a2c037117b742b4f8b379a22a2a33f6d2", + "reference": "cffffd0a2c037117b742b4f8b379a22a2a33f6d2", "shasum": "" }, "require": { @@ -2083,12 +2257,12 @@ "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.3" + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.3|^7.0", + "symfony/cache": "^6.4.12|^7.1.5", "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", @@ -2121,7 +2295,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.10" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.35" }, "funding": [ { @@ -2132,25 +2306,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-07-26T12:36:27+00:00" + "time": "2026-03-06T11:15:58+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.11", + "version": "v6.4.40", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "1ba6b89d781cb47448155cc70dd2e0f1b0584c79" + "reference": "41dff5c3d03b3fa20947c552c5f6ba74ca43fa28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/1ba6b89d781cb47448155cc70dd2e0f1b0584c79", - "reference": "1ba6b89d781cb47448155cc70dd2e0f1b0584c79", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/41dff5c3d03b3fa20947c552c5f6ba74ca43fa28", + "reference": "41dff5c3d03b3fa20947c552c5f6ba74ca43fa28", "shasum": "" }, "require": { @@ -2191,7 +2369,7 @@ "symfony/config": "^6.1|^7.0", "symfony/console": "^5.4|^6.0|^7.0", "symfony/css-selector": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4.1|^7.0.1", "symfony/dom-crawler": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/finder": "^5.4|^6.0|^7.0", @@ -2235,7 +2413,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.11" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.40" }, "funding": [ { @@ -2246,25 +2424,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-30T16:57:20+00:00" + "time": "2026-05-20T08:55:59+00:00" }, { "name": "symfony/intl", - "version": "v6.4.8", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "50265cdcf5a44bec3fcf487b5d0015aece91d1eb" + "reference": "026d246f3d2f6136db43d17b4ccb14b34d8e779a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/50265cdcf5a44bec3fcf487b5d0015aece91d1eb", - "reference": "50265cdcf5a44bec3fcf487b5d0015aece91d1eb", + "url": "https://api.github.com/repos/symfony/intl/zipball/026d246f3d2f6136db43d17b4ccb14b34d8e779a", + "reference": "026d246f3d2f6136db43d17b4ccb14b34d8e779a", "shasum": "" }, "require": { @@ -2318,7 +2500,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.4.8" + "source": "https://github.com/symfony/intl/tree/v6.4.36" }, "funding": [ { @@ -2329,25 +2511,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2026-03-24T11:36:52+00:00" }, { "name": "symfony/password-hasher", - "version": "v6.4.8", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "90ebbe946e5d64a5fad9ac9427e335045cf2bd31" + "reference": "fbdfa5a2ca218ec8bb9029517426df2d780bdba9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/90ebbe946e5d64a5fad9ac9427e335045cf2bd31", - "reference": "90ebbe946e5d64a5fad9ac9427e335045cf2bd31", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/fbdfa5a2ca218ec8bb9029517426df2d780bdba9", + "reference": "fbdfa5a2ca218ec8bb9029517426df2d780bdba9", "shasum": "" }, "require": { @@ -2390,7 +2576,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v6.4.8" + "source": "https://github.com/symfony/password-hasher/tree/v6.4.32" }, "funding": [ { @@ -2401,29 +2587,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2026-01-01T21:24:53+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.30.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -2434,8 +2624,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2469,7 +2659,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" }, "funding": [ { @@ -2480,29 +2670,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.30.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" + "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/4864388bfbd3001ce88e234fab652acd91fdc57e", + "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -2510,8 +2704,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2547,7 +2741,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.37.0" }, "funding": [ { @@ -2558,29 +2752,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2026-04-26T13:13:48+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.30.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "e76343c631b453088e2260ac41dfebe21954de81" + "reference": "3510b63d07376b04e57e27e82607d468bb134f78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e76343c631b453088e2260ac41dfebe21954de81", - "reference": "e76343c631b453088e2260ac41dfebe21954de81", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/3510b63d07376b04e57e27e82607d468bb134f78", + "reference": "3510b63d07376b04e57e27e82607d468bb134f78", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance and support of other locales than \"en\"" @@ -2588,8 +2786,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2631,7 +2829,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.37.0" }, "funding": [ { @@ -2642,29 +2840,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2026-04-10T16:50:15+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.30.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -2672,8 +2874,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2712,7 +2914,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.37.0" }, "funding": [ { @@ -2723,29 +2925,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.30.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -2756,8 +2963,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2792,7 +2999,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.37.0" }, "funding": [ { @@ -2804,79 +3011,7 @@ "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-06-19T12:30:46+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.30.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/3fb075789fb91f9ad9af537c4012d523085bd5af", - "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.30.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/nicolas-grekas", "type": "github" }, { @@ -2884,30 +3019,30 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.30.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9" + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/3600c2cb22399e25bb226e4a135ce91eeb2a6149", + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2944,7 +3079,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.37.0" }, "funding": [ { @@ -2955,25 +3090,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-06-19T12:35:24+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/routing", - "version": "v6.4.11", + "version": "v6.4.40", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "8ee0c24c1bf61c263a26f1b9b6d19e83b1121f2a" + "reference": "0cd0d2fb05382c95dff6b33c51a7c96cbdbc136d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/8ee0c24c1bf61c263a26f1b9b6d19e83b1121f2a", - "reference": "8ee0c24c1bf61c263a26f1b9b6d19e83b1121f2a", + "url": "https://api.github.com/repos/symfony/routing/zipball/0cd0d2fb05382c95dff6b33c51a7c96cbdbc136d", + "reference": "0cd0d2fb05382c95dff6b33c51a7c96cbdbc136d", "shasum": "" }, "require": { @@ -3027,7 +3166,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.11" + "source": "https://github.com/symfony/routing/tree/v6.4.40" }, "funding": [ { @@ -3038,25 +3177,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-29T08:15:38+00:00" + "time": "2026-05-19T20:33:22+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d25d82433a80eba6aa0e6c24b61d7370d99e444a", + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a", "shasum": "" }, "require": { @@ -3069,12 +3212,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" } }, "autoload": { @@ -3110,7 +3253,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.7.0" }, "funding": [ { @@ -3121,25 +3264,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2026-03-28T09:44:51+00:00" }, { "name": "symfony/string", - "version": "v6.4.11", + "version": "v6.4.39", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "5bc3eb632cf9c8dbfd6529d89be9950d1518883b" + "reference": "62e3c927de664edadb5bef260987eb047a17a113" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/5bc3eb632cf9c8dbfd6529d89be9950d1518883b", - "reference": "5bc3eb632cf9c8dbfd6529d89be9950d1518883b", + "url": "https://api.github.com/repos/symfony/string/zipball/62e3c927de664edadb5bef260987eb047a17a113", + "reference": "62e3c927de664edadb5bef260987eb047a17a113", "shasum": "" }, "require": { @@ -3153,7 +3300,6 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", "symfony/http-client": "^5.4|^6.0|^7.0", "symfony/intl": "^6.2|^7.0", "symfony/translation-contracts": "^2.5|^3.0", @@ -3196,7 +3342,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.11" + "source": "https://github.com/symfony/string/tree/v6.4.39" }, "funding": [ { @@ -3207,25 +3353,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-12T09:55:28+00:00" + "time": "2026-05-12T11:44:19+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0ab302977a952b42fd51475c4ebac81f8da0a95d", + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d", "shasum": "" }, "require": { @@ -3233,12 +3383,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" } }, "autoload": { @@ -3274,7 +3424,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.7.0" }, "funding": [ { @@ -3285,25 +3435,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2026-01-05T13:30:16+00:00" }, { "name": "symfony/twig-bridge", - "version": "v6.4.11", + "version": "v6.4.40", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "2cf03a4012631b74d68f9e6c3e03798ac592cbe5" + "reference": "5a68963b44e9a7089415540908c61de976c1ae34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/2cf03a4012631b74d68f9e6c3e03798ac592cbe5", - "reference": "2cf03a4012631b74d68f9e6c3e03798ac592cbe5", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/5a68963b44e9a7089415540908c61de976c1ae34", + "reference": "5a68963b44e9a7089415540908c61de976c1ae34", "shasum": "" }, "require": { @@ -3316,10 +3470,10 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/console": "<5.4", - "symfony/form": "<6.3", + "symfony/form": "<6.4.32|>7,<7.3.10|>7.4,<7.4.4", "symfony/http-foundation": "<5.4", "symfony/http-kernel": "<6.4", - "symfony/mime": "<6.2", + "symfony/mime": "<6.4.37|>=7.0,<7.4.9", "symfony/serializer": "<6.4", "symfony/translation": "<5.4", "symfony/workflow": "<5.4" @@ -3334,12 +3488,12 @@ "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.32|~7.3.10|^7.4.4", "symfony/html-sanitizer": "^6.1|^7.0", "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/intl": "^5.4|^6.0|^7.0", - "symfony/mime": "^6.2|^7.0", + "symfony/mime": "^6.4.37|^7.4.9", "symfony/polyfill-intl-icu": "~1.0", "symfony/property-info": "^5.4|^6.0|^7.0", "symfony/routing": "^5.4|^6.0|^7.0", @@ -3383,7 +3537,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.11" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.40" }, "funding": [ { @@ -3394,25 +3548,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-29T08:15:38+00:00" + "time": "2026-05-11T09:54:00+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.11", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "ee14c8254a480913268b1e3b1cba8045ed122694" + "reference": "7c8ad9ce4faf6c8a99948e70ce02b601a0439782" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/ee14c8254a480913268b1e3b1cba8045ed122694", - "reference": "ee14c8254a480913268b1e3b1cba8045ed122694", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7c8ad9ce4faf6c8a99948e70ce02b601a0439782", + "reference": "7c8ad9ce4faf6c8a99948e70ce02b601a0439782", "shasum": "" }, "require": { @@ -3424,7 +3582,6 @@ "symfony/console": "<5.4" }, "require-dev": { - "ext-iconv": "*", "symfony/console": "^5.4|^6.0|^7.0", "symfony/error-handler": "^6.3|^7.0", "symfony/http-kernel": "^5.4|^6.0|^7.0", @@ -3468,7 +3625,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.11" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.36" }, "funding": [ { @@ -3479,25 +3636,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-30T16:03:21+00:00" + "time": "2026-03-30T15:36:00+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.9", + "version": "v6.4.37", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "f9a060622e0d93777b7f8687ec4860191e16802e" + "reference": "34f6957deffacabd1b1c579a312daa481e3e99ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f9a060622e0d93777b7f8687ec4860191e16802e", - "reference": "f9a060622e0d93777b7f8687ec4860191e16802e", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/34f6957deffacabd1b1c579a312daa481e3e99ca", + "reference": "34f6957deffacabd1b1c579a312daa481e3e99ca", "shasum": "" }, "require": { @@ -3545,7 +3706,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.9" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.37" }, "funding": [ { @@ -3556,25 +3717,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-06-24T15:53:56+00:00" + "time": "2026-04-14T12:12:40+00:00" }, { "name": "symfony/yaml", - "version": "v6.4.11", + "version": "v6.4.40", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "be37e7f13195e05ab84ca5269365591edd240335" + "reference": "68dcd1f1602dac9d9221e25729683e0ce8733f3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/be37e7f13195e05ab84ca5269365591edd240335", - "reference": "be37e7f13195e05ab84ca5269365591edd240335", + "url": "https://api.github.com/repos/symfony/yaml/zipball/68dcd1f1602dac9d9221e25729683e0ce8733f3b", + "reference": "68dcd1f1602dac9d9221e25729683e0ce8733f3b", "shasum": "" }, "require": { @@ -3617,7 +3782,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.11" + "source": "https://github.com/symfony/yaml/tree/v6.4.40" }, "funding": [ { @@ -3628,31 +3793,35 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-12T09:55:28+00:00" + "time": "2026-05-19T20:33:22+00:00" }, { "name": "twig/intl-extra", - "version": "v3.12.0", + "version": "v3.26.0", "source": { "type": "git", "url": "https://github.com/twigphp/intl-extra.git", - "reference": "61e1189333120a475d2b67b93664b8002668fc27" + "reference": "98f5ad5bff13230fcd2d834d9e79b50adf3ccda9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/61e1189333120a475d2b67b93664b8002668fc27", - "reference": "61e1189333120a475d2b67b93664b8002668fc27", + "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/98f5ad5bff13230fcd2d834d9e79b50adf3ccda9", + "reference": "98f5ad5bff13230fcd2d834d9e79b50adf3ccda9", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/intl": "^5.4|^6.4|^7.0", - "twig/twig": "^3.10" + "php": ">=8.1.0", + "symfony/intl": "^5.4|^6.4|^7.0|^8.0", + "twig/twig": "^3.13|^4.0" }, "require-dev": { "symfony/phpunit-bridge": "^6.4|^7.0" @@ -3685,7 +3854,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/intl-extra/tree/v3.12.0" + "source": "https://github.com/twigphp/intl-extra/tree/v3.26.0" }, "funding": [ { @@ -3697,30 +3866,31 @@ "type": "tidelift" } ], - "time": "2024-08-10T10:32:24+00:00" + "time": "2026-05-19T20:44:48+00:00" }, { "name": "twig/twig", - "version": "v3.14.0", + "version": "v3.26.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72" + "reference": "1fcae487b180d78e6351f4e0afa91f9eab96a2bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/126b2c97818dbff0cdf3fbfc881aedb3d40aae72", - "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/1fcae487b180d78e6351f4e0afa91f9eab96a2bc", + "reference": "1fcae487b180d78e6351f4e0afa91f9eab96a2bc", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php81": "^1.29" + "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { + "php-cs-fixer/shim": "^3.0@stable", + "phpstan/phpstan": "^2.0@stable", "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, @@ -3764,7 +3934,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.14.0" + "source": "https://github.com/twigphp/Twig/tree/v3.26.0" }, "funding": [ { @@ -3776,7 +3946,7 @@ "type": "tidelift" } ], - "time": "2024-09-09T17:55:12+00:00" + "time": "2026-05-20T07:31:59+00:00" }, { "name": "webmozart/assert", @@ -3840,29 +4010,29 @@ "packages-dev": [ { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" + "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd", + "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0 || ^2.0", + "composer-plugin-api": "^2.2", "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { - "composer/composer": "*", + "composer/composer": "^2.2", "ext-json": "*", "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", "yoast/phpunit-polyfills": "^1.0" }, "type": "composer-plugin", @@ -3881,9 +4051,9 @@ "authors": [ { "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" + "email": "opensource@frenck.dev", + "homepage": "https://frenck.dev", + "role": "Open source developer" }, { "name": "Contributors", @@ -3891,7 +4061,6 @@ } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", @@ -3912,9 +4081,28 @@ ], "support": { "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", "source": "https://github.com/PHPCSStandards/composer-installer" }, - "time": "2023-01-05T11:28:13+00:00" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2026-05-06T08:26:05+00:00" }, { "name": "gettext/php-scanner", @@ -4029,16 +4217,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -4077,7 +4265,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -4085,20 +4273,20 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nikic/php-parser", - "version": "v4.19.1", + "version": "v4.19.5", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b" + "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4e1b88d21c69391150ace211e9eaf05810858d0b", - "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", + "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", "shasum": "" }, "require": { @@ -4107,17 +4295,12 @@ }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "bin": [ "bin/php-parse" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, "autoload": { "psr-4": { "PhpParser\\": "lib/PhpParser" @@ -4139,9 +4322,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.5" }, - "time": "2024-03-17T08:10:35+00:00" + "time": "2025-12-06T11:45:25+00:00" }, { "name": "phar-io/manifest", @@ -4311,30 +4494,30 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.30.0", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f" + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/5ceb0e384997db59f38774bf79c2a6134252c08f", - "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^5.3.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", "symfony/process": "^5.2" }, "type": "library", @@ -4352,22 +4535,17 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.30.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" }, - "time": "2024-08-29T09:54:52+00:00" + "time": "2026-01-25T14:56:51+00:00" }, { "name": "phpstan/phpstan", - "version": "1.12.2", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "0ca1c7bb55fca8fe6448f16fff0f311ccec960a1" - }, + "version": "1.12.33", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0ca1c7bb55fca8fe6448f16fff0f311ccec960a1", - "reference": "0ca1c7bb55fca8fe6448f16fff0f311ccec960a1", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/37982d6fc7cbb746dda7773530cda557cdf119e1", + "reference": "37982d6fc7cbb746dda7773530cda557cdf119e1", "shasum": "" }, "require": { @@ -4412,32 +4590,32 @@ "type": "github" } ], - "time": "2024-09-05T16:09:28+00:00" + "time": "2026-02-28T20:30:03+00:00" }, { "name": "phpstan/phpstan-mockery", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-mockery.git", - "reference": "88ae85931768efd3aaf3cce4cb9cb54c4d157d03" + "reference": "98cac6e256b4ee60fdeb26a7dd81bb271b454e80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-mockery/zipball/88ae85931768efd3aaf3cce4cb9cb54c4d157d03", - "reference": "88ae85931768efd3aaf3cce4cb9cb54c4d157d03", + "url": "https://api.github.com/repos/phpstan/phpstan-mockery/zipball/98cac6e256b4ee60fdeb26a7dd81bb271b454e80", + "reference": "98cac6e256b4ee60fdeb26a7dd81bb271b454e80", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.10" + "phpstan/phpstan": "^1.12" }, "require-dev": { - "mockery/mockery": "^1.2.4", + "mockery/mockery": "^1.6.11", "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.4", + "phpstan/phpstan-strict-rules": "^1.6", "phpunit/phpunit": "^9.5" }, "type": "phpstan-extension", @@ -4460,9 +4638,9 @@ "description": "PHPStan Mockery extension", "support": { "issues": "https://github.com/phpstan/phpstan-mockery/issues", - "source": "https://github.com/phpstan/phpstan-mockery/tree/1.1.2" + "source": "https://github.com/phpstan/phpstan-mockery/tree/1.1.3" }, - "time": "2024-01-10T13:50:05+00:00" + "time": "2024-09-11T15:47:29+00:00" }, { "name": "phpunit/php-code-coverage", @@ -4787,16 +4965,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.32", + "version": "10.5.63", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f069f46840445d37a4e6f0de8c5879598f9c4327" + "reference": "33198268dad71e926626b618f3ec3966661e4d90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f069f46840445d37a4e6f0de8c5879598f9c4327", - "reference": "f069f46840445d37a4e6f0de8c5879598f9c4327", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33198268dad71e926626b618f3ec3966661e4d90", + "reference": "33198268dad71e926626b618f3ec3966661e4d90", "shasum": "" }, "require": { @@ -4806,7 +4984,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.1", @@ -4817,13 +4995,13 @@ "phpunit/php-timer": "^6.0.0", "sebastian/cli-parser": "^2.0.1", "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.2", + "sebastian/comparator": "^5.0.5", "sebastian/diff": "^5.1.1", "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.2", + "sebastian/exporter": "^5.1.4", "sebastian/global-state": "^6.0.2", "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.0", + "sebastian/recursion-context": "^5.0.1", "sebastian/type": "^4.0.0", "sebastian/version": "^4.0.1" }, @@ -4868,7 +5046,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.32" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.63" }, "funding": [ { @@ -4879,25 +5057,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": "2024-09-04T13:33:39+00:00" + "time": "2026-01-27T05:48:37+00:00" }, { "name": "predis/predis", - "version": "v2.2.2", + "version": "v2.4.1", "source": { "type": "git", "url": "https://github.com/predis/predis.git", - "reference": "b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1" + "reference": "07105e050622ed80bd60808367ced9e379f31530" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/predis/predis/zipball/b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1", - "reference": "b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1", + "url": "https://api.github.com/repos/predis/predis/zipball/07105e050622ed80bd60808367ced9e379f31530", + "reference": "07105e050622ed80bd60808367ced9e379f31530", "shasum": "" }, "require": { @@ -4906,7 +5092,8 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.3", "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^8.0 || ~9.4.4" + "phpunit/phpcov": "^6.0 || ^8.0", + "phpunit/phpunit": "^8.0 || ^9.4" }, "suggest": { "ext-relay": "Faster connection with in-memory caching (>=0.6.2)" @@ -4928,7 +5115,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", @@ -4937,7 +5124,7 @@ ], "support": { "issues": "https://github.com/predis/predis/issues", - "source": "https://github.com/predis/predis/tree/v2.2.2" + "source": "https://github.com/predis/predis/tree/v2.4.1" }, "funding": [ { @@ -4945,7 +5132,7 @@ "type": "github" } ], - "time": "2023-09-13T16:42:03+00:00" + "time": "2025-11-12T18:00:11+00:00" }, { "name": "sebastian/cli-parser", @@ -5117,16 +5304,16 @@ }, { "name": "sebastian/comparator", - "version": "5.0.2", + "version": "5.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53" + "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d", + "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d", "shasum": "" }, "require": { @@ -5137,7 +5324,7 @@ "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^10.4" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { @@ -5182,15 +5369,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2" + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.5" }, "funding": [ { "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/sebastian/comparator", + "type": "tidelift" } ], - "time": "2024-08-12T06:03:08+00:00" + "time": "2026-01-24T09:25:16+00:00" }, { "name": "sebastian/complexity", @@ -5383,16 +5582,16 @@ }, { "name": "sebastian/exporter", - "version": "5.1.2", + "version": "5.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + "reference": "0735b90f4da94969541dac1da743446e276defa6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", + "reference": "0735b90f4da94969541dac1da743446e276defa6", "shasum": "" }, "require": { @@ -5401,7 +5600,7 @@ "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { @@ -5449,15 +5648,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" }, "funding": [ { "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/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T07:17:12+00:00" + "time": "2025-09-24T06:09:11+00:00" }, { "name": "sebastian/global-state", @@ -5693,23 +5904,23 @@ }, { "name": "sebastian/recursion-context", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a", + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { @@ -5744,15 +5955,28 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.1" }, "funding": [ { "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/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2023-02-03T07:05:40+00:00" + "time": "2025-08-10T07:50:56+00:00" }, { "name": "sebastian/type", @@ -5865,16 +6089,16 @@ }, { "name": "simplesamlphp/saml2-legacy", - "version": "v4.6.12", + "version": "v4.19.2", "source": { "type": "git", "url": "https://github.com/simplesamlphp/saml2-legacy.git", - "reference": "ee0ac34f4396306f877c6cea07f28fb6879ed37c" + "reference": "93df4bffc052939e74ec0c1208e66cbd7eb2a1b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/saml2-legacy/zipball/ee0ac34f4396306f877c6cea07f28fb6879ed37c", - "reference": "ee0ac34f4396306f877c6cea07f28fb6879ed37c", + "url": "https://api.github.com/repos/simplesamlphp/saml2-legacy/zipball/93df4bffc052939e74ec0c1208e66cbd7eb2a1b2", + "reference": "93df4bffc052939e74ec0c1208e66cbd7eb2a1b2", "shasum": "" }, "require": { @@ -5883,9 +6107,12 @@ "ext-zlib": "*", "php": ">=7.1 || ^8.0", "psr/log": "~1.1 || ^2.0 || ^3.0", - "robrichards/xmlseclibs": "^3.1.1", + "robrichards/xmlseclibs": "^3.1.5", "webmozart/assert": "^1.9" }, + "conflict": { + "robrichards/xmlseclibs": "3.1.2" + }, "require-dev": { "mockery/mockery": "^1.3", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", @@ -5916,9 +6143,9 @@ ], "description": "SAML2 PHP library from SimpleSAMLphp", "support": { - "source": "https://github.com/simplesamlphp/saml2-legacy/tree/v4.6.12" + "source": "https://github.com/simplesamlphp/saml2-legacy/tree/v4.19.2" }, - "time": "2024-04-30T09:01:00+00:00" + "time": "2026-03-13T12:09:45+00:00" }, { "name": "simplesamlphp/simplesamlphp-module-adfs", @@ -5982,16 +6209,16 @@ }, { "name": "simplesamlphp/simplesamlphp-test-framework", - "version": "v1.7.10", + "version": "v1.9.3", "source": { "type": "git", "url": "https://github.com/simplesamlphp/simplesamlphp-test-framework.git", - "reference": "157dbad53f1fc10610b23e9457eec20d0e4ad5aa" + "reference": "8dd14bb338573710165e6c237ec36378fa18eadb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-test-framework/zipball/157dbad53f1fc10610b23e9457eec20d0e4ad5aa", - "reference": "157dbad53f1fc10610b23e9457eec20d0e4ad5aa", + "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-test-framework/zipball/8dd14bb338573710165e6c237ec36378fa18eadb", + "reference": "8dd14bb338573710165e6c237ec36378fa18eadb", "shasum": "" }, "require": { @@ -6006,7 +6233,7 @@ "symfony/phpunit-bridge": "^6.4 || ^7.0" }, "require-dev": { - "simplesamlphp/simplesamlphp": "^2" + "simplesamlphp/simplesamlphp": "^2.4" }, "type": "project", "autoload": { @@ -6032,36 +6259,36 @@ "issues": "https://github.com/simplesamlphp/simplesamlphp-test-framework/issues", "source": "https://github.com/simplesamlphp/simplesamlphp-test-framework" }, - "time": "2024-08-19T08:33:29+00:00" + "time": "2025-07-14T17:03:27+00:00" }, { "name": "slevomat/coding-standard", - "version": "8.15.0", + "version": "8.29.0", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "7d1d957421618a3803b593ec31ace470177d7817" + "reference": "81fce13c4ef4b53a03e5cfa6ce36afc191c1598e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7d1d957421618a3803b593ec31ace470177d7817", - "reference": "7d1d957421618a3803b593ec31ace470177d7817", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/81fce13c4ef4b53a03e5cfa6ce36afc191c1598e", + "reference": "81fce13c4ef4b53a03e5cfa6ce36afc191c1598e", "shasum": "" }, "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", - "php": "^7.2 || ^8.0", - "phpstan/phpdoc-parser": "^1.23.1", - "squizlabs/php_codesniffer": "^3.9.0" + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.2.1", + "php": "^7.4 || ^8.0", + "phpstan/phpdoc-parser": "^2.3.2", + "squizlabs/php_codesniffer": "^4.0.1" }, "require-dev": { - "phing/phing": "2.17.4", - "php-parallel-lint/php-parallel-lint": "1.3.2", - "phpstan/phpstan": "1.10.60", - "phpstan/phpstan-deprecation-rules": "1.1.4", - "phpstan/phpstan-phpunit": "1.3.16", - "phpstan/phpstan-strict-rules": "1.5.2", - "phpunit/phpunit": "8.5.21|9.6.8|10.5.11" + "phing/phing": "3.0.1|3.1.2", + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/phpstan": "2.1.54", + "phpstan/phpstan-deprecation-rules": "2.0.4", + "phpstan/phpstan-phpunit": "2.0.16", + "phpstan/phpstan-strict-rules": "2.0.11", + "phpunit/phpunit": "9.6.34|10.5.63|11.4.4|11.5.55|12.5.24" }, "type": "phpcodesniffer-standard", "extra": { @@ -6085,7 +6312,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.15.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.29.0" }, "funding": [ { @@ -6097,41 +6324,36 @@ "type": "tidelift" } ], - "time": "2024-03-09T15:20:58+00:00" + "time": "2026-05-07T05:48:08+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.10.2", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017" + "reference": "0525c73950de35ded110cffafb9892946d7771b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017", - "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0525c73950de35ded110cffafb9892946d7771b5", + "reference": "0525c73950de35ded110cffafb9892946d7771b5", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": ">=5.4.0" + "php": ">=7.2.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + "phpunit/phpunit": "^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31" }, "bin": [ "bin/phpcbf", "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -6150,7 +6372,7 @@ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.", "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", @@ -6175,34 +6397,34 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2024-07-21T23:26:44+00:00" + "time": "2025-11-10T16:43:36+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v7.1.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "e876eb90e32a8fc4c4911d458e09f88d65877d1c" + "reference": "140bbbe1cd1c21a084494ccddeee33f3c3381d7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/e876eb90e32a8fc4c4911d458e09f88d65877d1c", - "reference": "e876eb90e32a8fc4c4911d458e09f88d65877d1c", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/140bbbe1cd1c21a084494ccddeee33f3c3381d7d", + "reference": "140bbbe1cd1c21a084494ccddeee33f3c3381d7d", "shasum": "" }, "require": { - "php": ">=7.2.5" - }, - "conflict": { - "phpunit/phpunit": "<7.5|9.1.2" + "php": ">=8.1.0" }, "require-dev": { - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/error-handler": "^5.4|^6.4|^7.0", - "symfony/polyfill-php81": "^1.27" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4.3|^7.0.3|^8.0" }, "bin": [ "bin/simple-phpunit" @@ -6210,8 +6432,8 @@ "type": "symfony-bridge", "extra": { "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" + "url": "https://github.com/sebastianbergmann/phpunit", + "name": "phpunit/phpunit" } }, "autoload": { @@ -6242,8 +6464,11 @@ ], "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", + "keywords": [ + "testing" + ], "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v7.1.4" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.4.8" }, "funding": [ { @@ -6254,25 +6479,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-13T14:28:19+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/translation", - "version": "v6.4.10", + "version": "v6.4.38", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "94041203f8ac200ae9e7c6a18fa6137814ccecc9" + "reference": "afaa31b0c12d9a659eed1ea97f268a614cc1299c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/94041203f8ac200ae9e7c6a18fa6137814ccecc9", - "reference": "94041203f8ac200ae9e7c6a18fa6137814ccecc9", + "url": "https://api.github.com/repos/symfony/translation/zipball/afaa31b0c12d9a659eed1ea97f268a614cc1299c", + "reference": "afaa31b0c12d9a659eed1ea97f268a614cc1299c", "shasum": "" }, "require": { @@ -6338,7 +6567,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.10" + "source": "https://github.com/symfony/translation/tree/v6.4.38" }, "funding": [ { @@ -6349,25 +6578,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2026-05-06T08:55:54+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -6396,7 +6629,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -6404,12 +6637,12 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -6430,5 +6663,5 @@ "ext-curl": "*", "ext-pdo_sqlite": "*" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/config/config.php.dist b/config/config.php.dist index dd54dc9000..a01d3ce169 100644 --- a/config/config.php.dist +++ b/config/config.php.dist @@ -826,7 +826,7 @@ $config = [ 'language.available' => [ 'en', 'no', 'nn', 'se', 'da', 'de', 'sv', 'fi', 'es', 'ca', 'fr', 'it', 'nl', 'lb', 'cs', 'sk', 'sl', 'lt', 'hr', 'hu', 'pl', 'pt', 'pt_BR', 'tr', 'ja', 'zh', 'zh_TW', - 'ru', 'et', 'he', 'id', 'sr', 'lv', 'ro', 'eu', 'el', 'af', 'zu', 'xh', 'st', + 'ru', 'et', 'he', 'id', 'sr', 'lv', 'ro', 'eu', 'el', 'af', 'zu', 'xh', 'st' ], 'language.rtl' => ['ar', 'dv', 'fa', 'ur', 'he'], 'language.default' => 'en', diff --git a/docs/simplesamlphp-changelog.md b/docs/simplesamlphp-changelog.md index 9c3308a1a2..9b17589cb2 100644 --- a/docs/simplesamlphp-changelog.md +++ b/docs/simplesamlphp-changelog.md @@ -5,11 +5,125 @@ 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.3 +## Version 2.3.12 Released TBD +## Version 2.3.11 + +Released 2026-03-13 + +* Bump robrichards/xmlseclibs (CVE-2026-32313) +* Bump all other dependencies + +## Version 2.3.10 + +Released 2025-12-08 + +* store.redis.tls should apply to sentinels (#2557) +* Fix unhandled canonicalization failure (CVE-2025-66475) +* Bump dependencies + +## Version 2.3.9 + +Released 2025-10-05 + +* Fix auth state AuthnInstant (#2478) +* Allow "Secure" cookie attribute via HTTP on localhost (#2483) +* Fix override over errorURL +* Fix FontAwesome icon names (#2509) +* Prevent emulation of SQL prepare-statements +* Remove double directory separator; \SimpleSAML\Configuration::getBasedir always ends with one + +`authorize` + +* Remove reauthentication-button when reauthentication is disabled (simplesamlphp/simplesamlphp-module-authorize#24) (v1.6.2) + +## 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 + +* Fixed loading translations for themes where there is no explicit X-Domain set in the po file. +* Bumped vulnerable saml2-library to v4.17.0 + +## Version 2.3.6 + +Released 2025-02-17 + +* Fixed PHP 8.4 deprecation notices +* Fixed infinite recursion (#2367) +* Fixed "Undefined array key" warning in RequestedAuthnContextSelector if no RAC is present in the request +* Fixed an unintended BC-break in `simplesamlphp/assert` that caused composer dependency issues +* Updated several dependencies +* Started testing on PHP 8.4 + +`ldap` + +* Verify attribute value is a string before calling strlen (simplesamlphp/simplesamlphp-module-ldap#64) (v2.4.4) + +## Version 2.3.5 + +Released 2024-12-02 + +* Fix a regression that would cause the translations for modules to revert to English + +## Version 2.3.4 + +Released 2024-12-02 + +`Security` + +* A security bug was patched in the `saml2-library` that allowed for XXE during the parsing + of SAML2-messages (CVE-2024-52596) + +`Other fixes` + +* Attributes translations are now in the "attributes" domain (#2328). +* Add `index` directive to Nginx example configuration (#2329). +* Better error message when using legacy endpoints format (#2335). +* Some minor improvements to the changes in 2.3.3. + +## Version 2.3.3 + +Released 2024-11-16 + +* Fix `st`-language by updating the ICU-files (#2305) +* Fix docs and configuration examples regarding SSO-endpoints. + +`admin` + * Fix regression in metadata converter clipboard-button (#2253) +* Fix typo that caused the metadata file-upload to be hidden (#2271) + +`discopower` + +* Throw a meaningful exception when tags contain illegal characters (v1.4.1) + +`ldap` + +* Fix a missing negation that rendered multi-ldap broken (v2.3.7) ## Version 2.3.2 @@ -73,6 +187,48 @@ Released 2024-08-20 * Add username_regex option - run regular expression over username before querying the database (simplesamlphp/simplesamlphp-module-sqlauth#11) (v1.3.0) +## Version 2.2.6 + +Released 2025-08-20 + +* Fix auth state AuthnInstant (#2478) + +`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) + +## Version 2.2.5 + +Released 2025-03-11 + +* Fixed PHP 8.4 deprecation notices +* Fixed infinite recursion (#2367) +* Fixed "Undefined array key" warning in RequestedAuthnContextSelector if no RAC is present in the request +* Bumped vulnerable saml2-library to v4.17.0 + +## Version 2.2.4 + +Released 2024-12-02 + +`Security` + +* A security bug was patched in the `saml2-library` that allowed for XXE during the parsing + of SAML2-messages (CVE-2024-52596) + +`Other fixes` + +* Run ob_end_clean() on configuration file parsing error (#2219) +* Fix typo that caused the metadata file-upload to be hidden (#2271) + +`admin` + +* Fix metadata-viewer to output a valid PHP array + ## Version 2.2.3 Released 2024-08-20 diff --git a/docs/simplesamlphp-customauth.md b/docs/simplesamlphp-customauth.md index 72b336ebb1..a6de7a20de 100644 --- a/docs/simplesamlphp-customauth.md +++ b/docs/simplesamlphp-customauth.md @@ -352,6 +352,7 @@ class MyAuth extends \SimpleSAML\Module\core\Auth\UserPassBase /* Connect to the database. */ $db = new PDO($this->dsn, $this->username, $this->password, $this->options); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); /* Ensure that we are operating with UTF-8 encoding. * This command is for MySQL. Other databases may need different commands. diff --git a/docs/simplesamlphp-developer-information.md b/docs/simplesamlphp-developer-information.md index 1d4cd82724..31b22c344b 100644 --- a/docs/simplesamlphp-developer-information.md +++ b/docs/simplesamlphp-developer-information.md @@ -124,6 +124,10 @@ might like to make the pull request against the simplesamlphp-2.1 branch and leave it to the team to also apply it to master and other branches in the same way that code updates work. +Some docs offered under the `docs` directory on the web site come from modules. +For example the [saml module](https://simplesamlphp.org/docs/2.3/saml/sp.html) +file comes from the file `./modules/saml/docs/sp.md` in the git repository. + ### Documentation linting The CI system has some linting for markdown files in place. This uses @@ -149,3 +153,16 @@ cd ./node_modules/.bin You will probably want to make a script or alias to the above command and apply it before pushing documentation changes to github. + +## Making a release + +The release process is documented on the wiki +. + +## Dependbot + +The dependbot + runs on the master branch +and creates pull requests with recommended updates. + +The release branches are updated automatically as part of the release process. diff --git a/docs/simplesamlphp-idp.md b/docs/simplesamlphp-idp.md index 681598c4cd..9c7eb9d2e9 100644 --- a/docs/simplesamlphp-idp.md +++ b/docs/simplesamlphp-idp.md @@ -184,8 +184,18 @@ This is a minimal example of a `metadata/saml20-sp-remote.php` metadata file for 'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', - 'SingleLogoutService' => 'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', + 'AssertionConsumerService' => [ + [ + 'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + ], + ], + 'SingleLogoutService' => [ + [ + 'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + ], + ], ]; ``` diff --git a/docs/simplesamlphp-install-repo.md b/docs/simplesamlphp-install-repo.md index e003dec07e..2ce34275c3 100644 --- a/docs/simplesamlphp-install-repo.md +++ b/docs/simplesamlphp-install-repo.md @@ -6,7 +6,7 @@ These are some notes about running SimpleSAMLphp from the repository. Prerequisites ------------- -Review the [prerequisites](../simplesamlphp-install) from the main installation guide. +Review the [prerequisites](simplesamlphp-install) from the main installation guide. Installing from git ------------------- diff --git a/docs/simplesamlphp-install.md b/docs/simplesamlphp-install.md index 8d1530e615..3283f25319 100644 --- a/docs/simplesamlphp-install.md +++ b/docs/simplesamlphp-install.md @@ -181,6 +181,7 @@ look like this: server { listen 443 ssl; server_name idp.example.com; + index index.php; ssl_certificate /etc/pki/tls/certs/idp.example.com.crt; ssl_certificate_key /etc/pki/tls/private/idp.example.com.key; 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 4dc53b3e1f..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` @@ -182,7 +182,7 @@ $metadata['entity-id-2'] = [ `SingleLogoutService` : Endpoint URL for logout requests and responses. You should obtain this from the IdP. Users who log out from your service is redirected to this URL with the LogoutRequest using HTTP-REDIRECT. -: The value of this option is specified in one of several [endpoint formats](./simplesamlphp-metadata-endpoints). +: The value of this option is specified in the format shown in [endpoint format](./simplesamlphp-metadata-endpoints). `SingleLogoutServiceResponse` : Endpoint URL for logout responses. Overrides the `SingleLogoutService`-option for responses. @@ -190,7 +190,7 @@ $metadata['entity-id-2'] = [ `SingleSignOnService` : Endpoint URL for sign on. You should obtain this from the IdP. For SAML 2.0, SimpleSAMLphp will use the HTTP-Redirect binding when contacting this endpoint. -: The value of this option is specified in one of several [endpoint formats](./simplesamlphp-metadata-endpoints). +: The value of this option is specified in the format shown in [endpoint format](./simplesamlphp-metadata-endpoints). `SPNameQualifier` : This corresponds to the SPNameQualifier in the SAML 2.0 specification. It allows to give subjects a SP specific namespace. This option is rarely used, so if you don't need it, leave it out. When left out, SimpleSAMLphp assumes the entityID of your SP as the SPNameQualifier. diff --git a/docs/simplesamlphp-reference-sp-remote.md b/docs/simplesamlphp-reference-sp-remote.md index f504070769..d67f225c49 100644 --- a/docs/simplesamlphp-reference-sp-remote.md +++ b/docs/simplesamlphp-reference-sp-remote.md @@ -89,7 +89,7 @@ The following options can be set: This option is required - without it you will not be able to send responses back to the SP. -: The value of this option is specified in one of several [endpoint formats](./simplesamlphp-metadata-endpoints). +: The value of this option is specified the format detailed in [endpoint format](./simplesamlphp-metadata-endpoints). `attributeencodings` : What encoding should be used for the different attributes. This is @@ -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,10 +166,9 @@ 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` +* `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` +* `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent` +* `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` : The `transient` format will generate a new unique ID every time the SP logs in. @@ -241,7 +240,7 @@ The following options can be set: this SP. If the option isn't specified, this SP will not be logged out automatically when a single logout operation is initialized. -: The value of this option is specified in one of several [endpoint formats](./simplesamlphp-metadata-endpoints). +: The value of this option is specified in the format detailed in [endpoint format](./simplesamlphp-metadata-endpoints). `SingleLogoutServiceResponse` : The URL logout responses to this SP should be sent. If this option diff --git a/docs/simplesamlphp-sp-api.md b/docs/simplesamlphp-sp-api.md index 76d7fe76fc..dcb31860bd 100644 --- a/docs/simplesamlphp-sp-api.md +++ b/docs/simplesamlphp-sp-api.md @@ -29,8 +29,14 @@ The constructor initializes a \SimpleSAML\Auth\Simple object. `Parameters`: -It has a single parameter, which is the ID of the authentication source that should be used. -This authentication source must exist in `config/authsources.php`. +It has a single parameter, which is the ID of the authentication +source that should be used. This authentication source must exist in +`config/authsources.php` and be of type saml:SP. Note that +authentication methods such as `ldap:Ldap` and `sqlauth` are defined +in `config/authsources.php` but those are only to be used by an IdP. +A normal setup would have your application talking to an SP, that SP +talking with an IdP, and that IdP using an authentication method to +authenticate the user. `Example`: diff --git a/docs/simplesamlphp-sp.md b/docs/simplesamlphp-sp.md index d2fe697177..99b93e2256 100644 --- a/docs/simplesamlphp-sp.md +++ b/docs/simplesamlphp-sp.md @@ -90,9 +90,20 @@ metadata file: ```php 'https://example.org/simplesaml/saml2/idp/SSOService.php', - 'SingleLogoutService' => 'https://example.org/simplesaml/saml2/idp/SingleLogoutService.php', - 'certificate' => 'example.pem', + 'SingleSignOnService' => [ + [ + 'Location' => 'https://example.org/simplesaml/saml2/idp/SSOService.php', + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + ], + ], + 'SingleLogoutService' => [ + [ + 'Location' => 'https://example.org/simplesaml/saml2/idp/SingleLogoutService.php', + 'ResponseLocation' => 'https://sp.example.org/LogoutResponse', + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + ], + ], + 'certificate' => 'example.pem', ]; ``` diff --git a/docs/simplesamlphp-upgrade-notes-2.3.md b/docs/simplesamlphp-upgrade-notes-2.3.md index fc5e7d7800..fcf6068926 100644 --- a/docs/simplesamlphp-upgrade-notes-2.3.md +++ b/docs/simplesamlphp-upgrade-notes-2.3.md @@ -6,11 +6,6 @@ The following changes are relevant for installers and/or developers. - Session ID's are now hashed when stored in a database. This means all old sessions are effectively invalidated by this upgrade. We recommend clearing your session store as part of the upgrade-routine. -- Endpoints are now only accepted in array-style. The old string-style was deprecated for 9 yrs - already and was broken anyway. See [endpoints] - -[endpoints]: https://simplesamlphp.org/docs/stable/simplesamlphp-metadata-endpoints.html - ## Deprecations The following classes were marked `deprecated` and will be removed in a next major release. @@ -36,3 +31,8 @@ The use of plain-text admin-passwords has been deprecated. Generate a secure has - The language codes `pt-br` and `zh-tw` have been renamed to `pt_BR` and `zh_TW`. Please update your configuration to match the new names. + +- Endpoints in metadata (e.g. "SingleSignOnLocation" and "AssertionCosumerService") can no longer be simple strings and are now only accepted in array-style. The old string-style was deprecated for 9 yrs + already and was broken anyway. See [endpoints] for the current format. + +[endpoints]: https://simplesamlphp.org/docs/stable/simplesamlphp-metadata-endpoints.html diff --git a/extra/simplesamlphp.spec b/extra/simplesamlphp.spec index 297c4f0f8a..f7c7e8c62f 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.2 +%define version 2.3.11 %define release 1 %define license LGPL 2.1 %define group Networking/WWW diff --git a/metadata/saml20-sp-remote.php.dist b/metadata/saml20-sp-remote.php.dist index 7b11e4e3d5..55d7353504 100644 --- a/metadata/saml20-sp-remote.php.dist +++ b/metadata/saml20-sp-remote.php.dist @@ -10,8 +10,20 @@ * Example SimpleSAMLphp SAML 2.0 SP */ $metadata['https://saml2sp.example.org'] = [ - 'AssertionConsumerService' => 'https://saml2.example.org/module.php/saml/sp/saml2-acs.php/default-sp', - 'SingleLogoutService' => 'https://saml2sp.example.org/module.php/saml/sp/saml2-logout.php/default-sp', + 'AssertionConsumerService' => [ + [ + 'index' => 1, + 'isDefault' => true, + 'Location' => 'https://saml2.example.org/module.php/saml/sp/saml2-acs.php/default-sp', + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + ], + ], + 'SingleLogoutService' => [ + [ + 'Location' => 'https://saml2sp.example.org/module.php/saml/sp/saml2-logout.php/default-sp', + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + ], + ], ]; /* @@ -22,7 +34,14 @@ $metadata['https://saml2sp.example.org'] = [ * this user has the value of 'john'. */ $metadata['google.com'] = [ - 'AssertionConsumerService' => 'https://www.google.com/a/g.feide.no/acs', + 'AssertionConsumerService' => [ + [ + 'index' => 1, + 'isDefault' => true, + 'Location' => 'https://www.google.com/a/g.feide.no/acs', + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + ], + ], 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', 'authproc' => [ 1 => [ @@ -34,8 +53,17 @@ $metadata['google.com'] = [ 'simplesaml.attributes' => false, ]; + $metadata['https://legacy.example.edu'] = [ - 'AssertionConsumerService' => 'https://legacy.example.edu/saml/acs', + 'AssertionConsumerService' => [ + [ + 'index' => 1, + 'isDefault' => true, + 'Location' => 'https://legacy.example.edu/saml/acs', + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + ], + ], + /* * Currently, SimpleSAMLphp defaults to the SHA-256 hashing algorithm. * Uncomment the following option to use SHA-1 for signatures directed diff --git a/modules/admin/locales/st/LC_MESSAGES/admin.po b/modules/admin/locales/en_LS/LC_MESSAGES/admin.po similarity index 100% rename from modules/admin/locales/st/LC_MESSAGES/admin.po rename to modules/admin/locales/en_LS/LC_MESSAGES/admin.po diff --git a/modules/admin/src/Controller/Federation.php b/modules/admin/src/Controller/Federation.php index e693aedbce..4f062e276c 100644 --- a/modules/admin/src/Controller/Federation.php +++ b/modules/admin/src/Controller/Federation.php @@ -481,7 +481,7 @@ public function metadataConverter(Request $request): Template 'xmldata' => $xmldata, 'output' => $output, 'error' => $error, - 'upload' => boolval(ini_get('file_upload')), + 'upload' => boolval(ini_get('file_uploads')), ]; $this->menu->addOption('logout', $t->data['logouturl'], Translate::noop('Log out')); 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/admin/templates/federation.twig b/modules/admin/templates/federation.twig index 017a5f6b0f..dae9211d04 100644 --- a/modules/admin/templates/federation.twig +++ b/modules/admin/templates/federation.twig @@ -56,7 +56,7 @@ - + {{ set.url }} diff --git a/modules/core/locales/st/LC_MESSAGES/core.po b/modules/core/locales/en_LS/LC_MESSAGES/core.po similarity index 100% rename from modules/core/locales/st/LC_MESSAGES/core.po rename to modules/core/locales/en_LS/LC_MESSAGES/core.po 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/Auth/Source/RequestedAuthnContextSelector.php b/modules/core/src/Auth/Source/RequestedAuthnContextSelector.php index b0262fe04d..411e6868d8 100644 --- a/modules/core/src/Auth/Source/RequestedAuthnContextSelector.php +++ b/modules/core/src/Auth/Source/RequestedAuthnContextSelector.php @@ -106,7 +106,7 @@ public function __construct(array $info, array $config) */ protected function selectAuthSource(array &$state): string { - $requestedContexts = $state['saml:RequestedAuthnContext']; + $requestedContexts = $state['saml:RequestedAuthnContext'] ?? null; if ( $requestedContexts === null || !array_key_exists('AuthnContextClassRef', $requestedContexts) diff --git a/modules/core/src/Storage/SQLPermanentStorage.php b/modules/core/src/Storage/SQLPermanentStorage.php index 5ba08cffdb..552b91de34 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(); @@ -53,6 +53,8 @@ public function __construct(string $name, Configuration $config = null) $this->db = new PDO($dbfile); if ($this->db) { $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); + $this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + $q = @$this->db->query('SELECT key1 FROM data LIMIT 1'); if ($q === false) { $this->db->exec(' @@ -81,7 +83,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 +101,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 +127,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 +150,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 +175,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 +208,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 +236,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 +301,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/core/templates/logout-iframe.twig b/modules/core/templates/logout-iframe.twig index 1cd8b2d54c..5c96865c2f 100644 --- a/modules/core/templates/logout-iframe.twig +++ b/modules/core/templates/logout-iframe.twig @@ -37,11 +37,11 @@ {%- for key, sp in remaining_services %} {%- set timeout = 5 %} {%- set name = sp['metadata']|entityDisplayName %} - {%- set icon = 'circle-o-notch' %} + {%- set icon = 'circle-notch' %} {%- if sp['status'] == 'completed' %} - {%- set icon = 'check-circle' %} + {%- set icon = 'circle-check' %} {%- elseif sp['status'] == 'failed' %} - {%- set icon = 'exclamation-circle' %} + {%- set icon = 'circle-exclamation' %} {%- set failed = true %} {%- elseif (sp['status'] == 'onhold' or sp['status'] == 'inprogress') %} {%- set remaining = remaining + 1 %} 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/multiauth/docs/multiauth.md b/modules/multiauth/docs/multiauth.md index 045dd86b5c..4deb53dbe3 100644 --- a/modules/multiauth/docs/multiauth.md +++ b/modules/multiauth/docs/multiauth.md @@ -2,8 +2,18 @@ MultiAuth module ================ The MultiAuth module provides a method for users to choose between -a list of authentication sources. There is only one authentication -module: +a list of authentication sources. + +If you are looking to have your web application offer multiple +identity providers during login this is not the module you should be +using. For that case you should setup a single saml:SP authsource that +you can call from `\SimpleSAML\Auth\Simple`. If you have multiple +remote IdP's the discovery service will ask you which one to use. + +`multiauth` is meant to be used as a selector for different +authentication methods. + +There is only one authentication module: `multiauth:MultiAuth` : Authenticate the user against a list of authentication sources. diff --git a/modules/multiauth/locales/st/LC_MESSAGES/multiauth.po b/modules/multiauth/locales/en_LS/LC_MESSAGES/multiauth.po similarity index 100% rename from modules/multiauth/locales/st/LC_MESSAGES/multiauth.po rename to modules/multiauth/locales/en_LS/LC_MESSAGES/multiauth.po diff --git a/modules/saml/docs/sp.md b/modules/saml/docs/sp.md index 5295f7c307..3312455cbe 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` @@ -97,11 +97,13 @@ The following attributes are available: : Note that this option can be overridden for a specific IdP in saml20-idp-remote. `AssertionConsumerService` -: List of Assertion Consumer Services in the generated metadata. Specified in the array of - arrays format as seen in the [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). + +: List of Assertion Consumer Services in the generated metadata. + Specified in the format detailed in the + [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). `AssertionConsumerServiceIndex` : The Assertion Consumer Service Index to be used in the AuthnRequest in place of the Assertion @@ -151,7 +153,7 @@ The following attributes are available: `authproc` : Processing filters that should be run after SP authentication. - See the [authentication processing filter manual](simplesamlphp-authproc). + See the [authentication processing filter manual](../simplesamlphp-authproc). `certData` : Base64 encoded certificate data. Can be used instead of the `certificate` option. diff --git a/modules/saml/locales/st/LC_MESSAGES/saml.po b/modules/saml/locales/en_LS/LC_MESSAGES/saml.po similarity index 100% rename from modules/saml/locales/st/LC_MESSAGES/saml.po rename to modules/saml/locales/en_LS/LC_MESSAGES/saml.po diff --git a/modules/saml/src/Auth/Source/SP.php b/modules/saml/src/Auth/Source/SP.php index a512321114..0d1f61992b 100644 --- a/modules/saml/src/Auth/Source/SP.php +++ b/modules/saml/src/Auth/Source/SP.php @@ -580,8 +580,8 @@ private function startSSO2(Configuration $idpMetadata, array $state): void /* Only check for real info for Scoping element if we are going to send Scoping element */ if ($this->disable_scoping !== true && $idpMetadata->getOptionalBoolean('disable_scoping', false) !== true) { - if (isset($state['IDPList'])) { - $ar->setIDPList($state['IDPList']); + if (isset($state['saml:IDPList'])) { + $ar->setIDPList($state['saml:IDPList']); } elseif (!empty($this->metadata->getOptionalArray('IDPList', []))) { $ar->setIDPList($this->metadata->getArray('IDPList')); } elseif (!empty($idpMetadata->getOptionalArray('IDPList', []))) { 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..42ea3f369c 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) { @@ -962,6 +962,11 @@ public static function getHostedMetadata(string $entityid, MetaDataStorageHandle $metadata['RegistrationInfo'] = $config->getArray('RegistrationInfo'); } + // Override errorURL if set + if ($config->hasValue('errorURL')) { + $metadata['errorURL'] = $config->getString('errorURL'); + } + // configure signature options if ($config->hasValue('validate.authnrequest')) { $metadata['sign.authnrequest'] = $config->getBoolean('validate.authnrequest'); @@ -1409,7 +1414,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/phpcs.xml b/phpcs.xml index ec365ed6ac..9b5cdd9011 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -31,6 +31,7 @@ tests/src/SimpleSAML/Metadata/MetaDataStorageSourceTest.php tests/src/SimpleSAML/Metadata/SAMLParserTest.php + tests/src/SimpleSAML/Utils/HTTPTest.php tests/modules/saml/src/Controller/ServiceProviderTest.php diff --git a/psalm-dev.xml b/psalm-dev.xml index 372f075efb..21dece15f2 100644 --- a/psalm-dev.xml +++ b/psalm-dev.xml @@ -2,7 +2,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/psalm.xml b/psalm.xml index de26cb641f..1fa1b3660c 100644 --- a/psalm.xml +++ b/psalm.xml @@ -21,7 +21,7 @@ - + @@ -78,7 +78,6 @@ - diff --git a/src/SimpleSAML/Auth/ProcessingChain.php b/src/SimpleSAML/Auth/ProcessingChain.php index 4a51a1a153..02cab9e8b7 100644 --- a/src/SimpleSAML/Auth/ProcessingChain.php +++ b/src/SimpleSAML/Auth/ProcessingChain.php @@ -22,7 +22,6 @@ use function is_string; use function sprintf; use function str_replace; -use function var_export; /** * Class for implementing authentication processing chains for IdPs. @@ -90,7 +89,7 @@ public function __construct(array $idpMetadata, array $spMetadata, string $mode } Logger::debug('Filter config for ' . $idpMetadata['entityid'] . '->' . - $spMetadata['entityid'] . ': ' . str_replace("\n", '', var_export($this->filters, true))); + $spMetadata['entityid'] . ': ' . str_replace("\n", '', print_r($this->filters, true))); } 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/Auth/State.php b/src/SimpleSAML/Auth/State.php index 814b4394b6..55399563c3 100644 --- a/src/SimpleSAML/Auth/State.php +++ b/src/SimpleSAML/Auth/State.php @@ -126,7 +126,7 @@ public static function getPersistentAuthData(array $state): array 'Attributes', 'Expire', 'LogoutState', - 'AuthInstant', + 'AuthnInstant', 'RememberMe', 'saml:sp:NameID', ]; 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 951614479f..e55cb690e4 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.2'; + public const VERSION = '2.3.11'; /** * A default value which means that the given option is required. @@ -1207,9 +1207,14 @@ public function getEndpoints(string $endpointType): array return []; } - $eps = $this->configuration[$endpointType]; - Assert::isArray($eps, Error\CriticalConfigurationError::class); + if (!is_array($eps)) { + $filename = explode('/', $loc)[0]; + throw new Error\CriticalConfigurationError( + "Endpoint of type $endpointType is not an array in $loc.", + $filename, + ); + } $eps_count = count($eps); @@ -1313,7 +1318,7 @@ public function getEndpointPrioritizedByBinding( */ public function getDefaultEndpoint( string $endpointType, - array $bindings = null, + ?array $bindings = null, mixed $default = self::REQUIRED_OPTION, ): mixed { $endpoints = $this->getEndpoints($endpointType); diff --git a/src/SimpleSAML/Database.php b/src/SimpleSAML/Database.php index 4f51170d63..e6e46a2fc1 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,16 +159,17 @@ 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); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); return $db; } catch (PDOException $e) { 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/Error.php b/src/SimpleSAML/Error/Error.php index f10477cdf1..7bfbcdbe6d 100644 --- a/src/SimpleSAML/Error/Error.php +++ b/src/SimpleSAML/Error/Error.php @@ -79,9 +79,9 @@ class Error extends Exception */ public function __construct( string|array $errorCode, - Throwable $cause = null, + ?Throwable $cause = null, ?int $httpCode = null, - ErrorCodes $errorCodes = null, + ?ErrorCodes $errorCodes = null, ) { if (is_array($errorCode)) { $this->parameters = $errorCode; 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/Exception.php b/src/SimpleSAML/Error/Exception.php index 46510d8c6b..2cc756c240 100644 --- a/src/SimpleSAML/Error/Exception.php +++ b/src/SimpleSAML/Error/Exception.php @@ -46,7 +46,7 @@ class Exception extends \Exception * @param int $code Error code * @param \Throwable|null $cause The cause of this exception. */ - public function __construct(string $message, int $code = 0, Throwable $cause = null) + public function __construct(string $message, int $code = 0, ?Throwable $cause = null) { parent::__construct($message, $code); 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/Kernel.php b/src/SimpleSAML/Kernel.php index ab30f77cfb..bb001642b3 100644 --- a/src/SimpleSAML/Kernel.php +++ b/src/SimpleSAML/Kernel.php @@ -66,7 +66,7 @@ public function getCacheDir(): string return $cachePath; } - return $configuration->getBaseDir() . DIRECTORY_SEPARATOR . $cachePath; + return $configuration->getBaseDir() . $cachePath; } diff --git a/src/SimpleSAML/Locale/Language.php b/src/SimpleSAML/Locale/Language.php index 58cdc67e85..b4e2952571 100644 --- a/src/SimpleSAML/Locale/Language.php +++ b/src/SimpleSAML/Locale/Language.php @@ -175,7 +175,8 @@ private function getInstalledLanguages(): array if (array_intersect(['pt-br', 'zh-tw'], $configuredAvailableLanguages)) { Logger::warning( "Deprecated locales found in `language.available`. " - . "Please replace 'pt-br' with 'pt_BR' and 'zh-tw' with 'zh_TW'.", + . "Please replace 'pt-br' with 'pt_BR'," + . " and 'zh-tw' with 'zh_TW'.", ); if (($i = array_search('pt-br', $configuredAvailableLanguages)) !== false) { @@ -192,7 +193,8 @@ private function getInstalledLanguages(): array if (Locales::exists($code)) { $availableLanguages[] = $code; } else { - Logger::error("Language \"$code\" not installed. Check config."); + /* The configured language code can't be found in Symfony's list of known locales */ + Logger::error("Locale \"$code\" is not known to the translation system. Check language settings in your config."); } } diff --git a/src/SimpleSAML/Locale/Localization.php b/src/SimpleSAML/Locale/Localization.php index 4e1d62845a..f98318c082 100644 --- a/src/SimpleSAML/Locale/Localization.php +++ b/src/SimpleSAML/Locale/Localization.php @@ -126,7 +126,7 @@ public function getDomainLocaleDir(string $domain): string * @param string $localeDir Absolute path if the module is housed elsewhere * @param string $domain Translation domain within module; defaults to module name */ - public function addModuleDomain(string $module, string $localeDir = null, string $domain = null): void + public function addModuleDomain(string $module, ?string $localeDir = null, ?string $domain = null): void { if (!$localeDir) { $localeDir = $this->getDomainLocaleDir($module); @@ -261,6 +261,18 @@ private function loadGettextGettextFromPO( $file = new File($langPath . $domain . '.po', false); if ($file->getRealPath() !== false && $file->isReadable()) { $translations = (new PoLoader())->loadFile($file->getRealPath()); + 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( $arrayGenerator->generateArray($translations), 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/Module.php b/src/SimpleSAML/Module.php index 4e2e5a3408..32435e602a 100644 --- a/src/SimpleSAML/Module.php +++ b/src/SimpleSAML/Module.php @@ -162,7 +162,7 @@ public static function isModuleEnabled(string $module): bool * @throws Error\BadRequest In case the request URI is malformed. * @throws Error\NotFound In case the request URI is invalid or the resource it points to cannot be found. */ - public static function process(Request $request = null): Response + public static function process(?Request $request = null): Response { if ($request === null) { $request = Request::createFromGlobals(); diff --git a/src/SimpleSAML/Session.php b/src/SimpleSAML/Session.php index 51f6e4f16c..d504ba2112 100644 --- a/src/SimpleSAML/Session.php +++ b/src/SimpleSAML/Session.php @@ -327,7 +327,7 @@ public static function getSessionFromRequest(): Session * @return \SimpleSAML\Session|null The session that is stored in the session handler, * or null if the session wasn't found. */ - public static function getSession(string $sessionId = null): ?Session + public static function getSession(?string $sessionId = null): ?Session { $sh = SessionHandler::getSessionHandler(); @@ -570,7 +570,7 @@ public function getRememberMeExpire(): ?int * * @param int $lifetime Number of seconds after when remember me session cookies expire. */ - public function setRememberMeExpire(int $lifetime = null): void + public function setRememberMeExpire(?int $lifetime = null): void { if ($lifetime === null) { $lifetime = self::$config->getOptionalInteger('session.rememberme.lifetime', 14 * 86400); @@ -800,7 +800,7 @@ public function updateSessionCookies(array $params = []): void * @param string $authority The authentication source we are setting expire time for. * @param int $expire The number of seconds authentication source is valid. */ - public function setAuthorityExpire(string $authority, int $expire = null): void + public function setAuthorityExpire(string $authority, ?int $expire = null): void { $this->markDirty(); diff --git a/src/SimpleSAML/SessionHandler.php b/src/SimpleSAML/SessionHandler.php index 873cc34eb5..2974f1d58b 100644 --- a/src/SimpleSAML/SessionHandler.php +++ b/src/SimpleSAML/SessionHandler.php @@ -120,7 +120,7 @@ abstract public function hasSessionCookie(): bool; * * @throws \SimpleSAML\Error\CannotSetCookie If we can't set the cookie. */ - abstract public function setCookie(string $sessionName, ?string $sessionID, array $cookieParams = null): void; + abstract public function setCookie(string $sessionName, ?string $sessionID, ?array $cookieParams = null): void; /** @@ -164,7 +164,7 @@ public function getCookieParams(): array 'lifetime' => $config->getOptionalInteger('session.cookie.lifetime', 0), 'path' => $config->getOptionalString('session.cookie.path', '/'), 'domain' => $config->getOptionalString('session.cookie.domain', null), - 'secure' => $config->getOptionalBoolean('session.cookie.secure', $httpUtils->isHTTPS()), + 'secure' => $config->getOptionalBoolean('session.cookie.secure', $httpUtils->isSecureCookieAllowed()), 'samesite' => $config->getOptionalString('session.cookie.samesite', null), 'httponly' => true, ]; 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/SessionHandlerPHP.php b/src/SimpleSAML/SessionHandlerPHP.php index 7a8d86ba5b..d7e6e42ad5 100644 --- a/src/SimpleSAML/SessionHandlerPHP.php +++ b/src/SimpleSAML/SessionHandlerPHP.php @@ -190,8 +190,8 @@ public function getCookieSessionId(): ?string $session_cookie_params = session_get_cookie_params(); $httpUtils = new Utils\HTTP(); - if ($session_cookie_params['secure'] && !$httpUtils->isHTTPS()) { - throw new Error\Exception('Session start with secure cookie not allowed on http.'); + if ($session_cookie_params['secure'] && !$httpUtils->isSecureCookieAllowed()) { + throw new Error\Exception('Session start with secure cookie not allowed on http (except on localhost).'); } @session_start(); @@ -231,7 +231,7 @@ public function saveSession(Session $session): void * @throws \SimpleSAML\Error\Exception If it wasn't possible to disable session cookies or we are trying to load a * PHP session with a specific identifier and it doesn't match with the current session identifier. */ - public function loadSession(string $sessionId = null): ?Session + public function loadSession(?string $sessionId = null): ?Session { if ($sessionId !== session_id()) { throw new Error\Exception('Cannot load PHP session with a specific ID.'); @@ -315,16 +315,16 @@ public function getCookieParams(): array * * @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) { $cookieParams = session_get_cookie_params(); } $httpUtils = new Utils\HTTP(); - if ($cookieParams['secure'] && !$httpUtils->isHTTPS()) { + if ($cookieParams['secure'] && !$httpUtils->isSecureCookieAllowed()) { throw new Error\CannotSetCookie( - 'Setting secure cookie on plain HTTP is not allowed.', + 'Setting secure cookie on plain HTTP (except on localhost) is not allowed.', Error\CannotSetCookie::SECURE_COOKIE, ); } diff --git a/src/SimpleSAML/Store/RedisStore.php b/src/SimpleSAML/Store/RedisStore.php index 3560d65af8..41e3c2e71a 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.'); @@ -98,6 +98,7 @@ public function __construct(Client $redis = null) 'service' => $mastergroup, 'prefix' => $prefix, 'parameters' => [ + 'scheme' => $scheme, 'database' => $database, ] + (!empty($ssl) ? ['ssl' => $ssl] : []) diff --git a/src/SimpleSAML/Store/SQLStore.php b/src/SimpleSAML/Store/SQLStore.php index 7597139d42..21e37239f4 100644 --- a/src/SimpleSAML/Store/SQLStore.php +++ b/src/SimpleSAML/Store/SQLStore.php @@ -78,6 +78,7 @@ public function __construct() throw new Exception("Database error: " . $e->getMessage()); } $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $this->driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME); @@ -159,7 +160,7 @@ private function initTableVersionTable(): void */ $update = [ 'CREATE TABLE ' . $this->prefix . - '_tableVersion (_name VARCHAR(30) PRIMARY KEY NOT NULL, _version INTEGER NOT NULL)', + '_tableVersion_new (_name VARCHAR(30) PRIMARY KEY NOT NULL, _version INTEGER NOT NULL)', 'INSERT INTO ' . $this->prefix . '_tableVersion_new SELECT * FROM ' . $this->prefix . '_tableVersion', 'DROP TABLE ' . $this->prefix . '_tableVersion', 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/HTTP.php b/src/SimpleSAML/Utils/HTTP.php index 82ff4ea8d3..f6c7616ceb 100644 --- a/src/SimpleSAML/Utils/HTTP.php +++ b/src/SimpleSAML/Utils/HTTP.php @@ -366,7 +366,7 @@ public function checkSessionCookie(?string $retryURL = null): void * @throws Error\Exception If the URL is not allowed by configuration. * */ - public function checkURLAllowed(string $url, array $trustedSites = null): string + public function checkURLAllowed(string $url, ?array $trustedSites = null): string { if (empty($url)) { return ''; @@ -1005,7 +1005,7 @@ public function redirectUntrustedURL(string $url, array $parameters = []): void * are not strings. * */ - public function resolveURL(string $url, string $base = null): string + public function resolveURL(string $url, ?string $base = null): string { if ($base === null) { $base = $this->getBaseURL(); @@ -1080,7 +1080,7 @@ public function resolveURL(string $url, string $base = null): string * * */ - public function setCookie(string $name, ?string $value, array $params = null, bool $throw = true): void + public function setCookie(string $name, ?string $value, ?array $params = null, bool $throw = true): void { $default_params = [ 'lifetime' => 0, @@ -1099,15 +1099,15 @@ public function setCookie(string $name, ?string $value, array $params = null, bo $params = $default_params; } - // Do not set secure cookie if not on HTTPS - if ($params['secure'] && !$this->isHTTPS()) { + // Do not set secure cookie if not on HTTPS or localhost + if ($params['secure'] && !$this->isSecureCookieAllowed()) { if ($throw) { throw new Error\CannotSetCookie( - 'Setting secure cookie on plain HTTP is not allowed.', + 'Setting secure cookie on plain HTTP (except on localhost) is not allowed.', Error\CannotSetCookie::SECURE_COOKIE, ); } - Logger::warning('Error setting cookie: setting secure cookie on plain HTTP is not allowed.'); + Logger::warning('Error setting cookie: setting secure cookie on plain HTTP (except on localhost) is not allowed.'); return; } @@ -1164,6 +1164,17 @@ public function setCookie(string $name, ?string $value, array $params = null, bo } + /** + * Check if "Secure" attribute on cookies is supported + * + * @return boolean True "Secure" attribute can be set, false otherwise. + */ + public function isSecureCookieAllowed(): bool + { + return $this->isHTTPS() || in_array($this->getSelfHost(), ['localhost', '127.0.0.1', '::1'], true); + } + + /** * Submit a POST form to a specific destination. * 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 cabac093e3..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' . @@ -121,7 +123,7 @@ public function getTempDir(): string * @return string An absolute path referring to $path. * */ - public function resolvePath(string $path, string $base = null): string + public function resolvePath(string $path, ?string $base = null): string { if ($base === null) { $config = Configuration::getInstance(); diff --git a/src/SimpleSAML/Utils/Time.php b/src/SimpleSAML/Utils/Time.php index b64bd36a10..42d1b40aaf 100644 --- a/src/SimpleSAML/Utils/Time.php +++ b/src/SimpleSAML/Utils/Time.php @@ -10,10 +10,10 @@ namespace SimpleSAML\Utils; -use SimpleSAML\Assert\Assert; use SimpleSAML\Configuration; use SimpleSAML\Error; use SimpleSAML\Logger; +use SimpleSAML\XML\Assert\Assert; class Time { @@ -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/src/SimpleSAML/XHTML/Template.php b/src/SimpleSAML/XHTML/Template.php index 9316d33be6..882173c78a 100644 --- a/src/SimpleSAML/XHTML/Template.php +++ b/src/SimpleSAML/XHTML/Template.php @@ -179,7 +179,7 @@ class_exists($controller) * @param bool $tag * @return string */ - public function asset(string $asset, string $module = null, bool $tag = true): string + public function asset(string $asset, ?string $module = null, bool $tag = true): string { $baseDir = $this->configuration->getBaseDir(); $basePath = $this->configuration->getBasePath(); diff --git a/templates/base.twig b/templates/base.twig index 7c7b86829b..169dcccb9a 100644 --- a/templates/base.twig +++ b/templates/base.twig @@ -2,7 +2,8 @@ - + + {{ pagetitle }} 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/modules/saml/src/Auth/Source/SPTest.php b/tests/modules/saml/src/Auth/Source/SPTest.php index cea9cd825b..304477acd9 100644 --- a/tests/modules/saml/src/Auth/Source/SPTest.php +++ b/tests/modules/saml/src/Auth/Source/SPTest.php @@ -476,7 +476,7 @@ public function testMetadataHostedBasicConfig(): void public function testSPIdpListScoping(): void { $ar = $this->createAuthnRequest([ - 'IDPList' => ['https://scope.example.com'], + 'saml:IDPList' => ['https://scope.example.com'], ]); $this->assertContains( @@ -542,7 +542,7 @@ public function testSPIdpListScopingOrder( $info = ['AuthId' => 'default-sp']; $state = []; if (isset($stateIdpList)) { - $state['IDPList'] = $stateIdpList; + $state['saml:IDPList'] = $stateIdpList; } $config = ['entityID' => 'urn:x-simplesamlphp:example-sp']; diff --git a/tests/modules/saml/src/IdP/SAML2Test.php b/tests/modules/saml/src/IdP/SAML2Test.php index ffcbf59d97..9e51018cec 100644 --- a/tests/modules/saml/src/IdP/SAML2Test.php +++ b/tests/modules/saml/src/IdP/SAML2Test.php @@ -262,6 +262,20 @@ private function idpMetadataHandlerHelper(array $metadata, array $extraconfig = return SAML2::getHostedMetadata($metadata['entityid']); } + + /** + * Test that an override for the errorURL produced the expected output. + */ + public function testIdPGetHostedMetadataErrorUrlOverride(): void + { + $md = [ + 'errorURL' => 'https://simplesamlphp.org', + ]; + $hostedMd = $this->idpMetadataHandlerHelper($md); + $this->assertEquals('https://simplesamlphp.org', $hostedMd['errorURL']); + } + + /** * A minimally configured hosted IdP has all default fields with expected values. */ diff --git a/tests/src/SimpleSAML/Auth/StateTest.php b/tests/src/SimpleSAML/Auth/StateTest.php index dd7744e3b4..08a2293b50 100644 --- a/tests/src/SimpleSAML/Auth/StateTest.php +++ b/tests/src/SimpleSAML/Auth/StateTest.php @@ -24,7 +24,7 @@ public function testGetPersistentAuthData(): void 'Attributes' => [], 'Expire' => 1234, 'LogoutState' => 'logoutState', - 'AuthInstant' => 123456, + 'AuthnInstant' => 123456, 'RememberMe' => true, 'saml:sp:NameID' => 'nameID', ]; diff --git a/tests/src/SimpleSAML/ConfigurationTest.php b/tests/src/SimpleSAML/ConfigurationTest.php index 64986f52c4..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'); } @@ -960,7 +967,8 @@ public function testGetEndpoints(): void // define a set of exception messages to expect $msgs = [ - 'The configuration is invalid: Expected an array. Got: integer', + "The configuration ([ARRAY]['SingleSignOnService']:) is invalid: Endpoint of type " . + "SingleSignOnService is not an array in [ARRAY]['SingleSignOnService']:.", 'Expected a string or an array.', 'Missing Location.', 'Location must be a string.', 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" + } + } +]);