Compare commits

...

3 Commits

Author SHA1 Message Date
Anne-Cath
d54e71f0f9 N°9248 - REST API - Updating a link creates an empty caselog on the linked object when there is no change 2026-02-27 11:21:32 +01:00
Lenaick
fc967c06ce N°8834 - Add compatibility with PHP 8.4 (#819)
* N°8834 - Add compatibility with PHP 8.4

* Rollback of scssphp/scssphp version upgrade due to compilation error
2026-02-26 10:36:32 +01:00
Eric Espie
d4821b7edc remove log level config 2026-02-26 10:19:34 +01:00
963 changed files with 12554 additions and 7437 deletions

View File

@@ -4,7 +4,7 @@
"type": "project", "type": "project",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"require": { "require": {
"php": ">=8.1.0 <8.4.0", "php": ">=8.1.0 <8.5.0",
"ext-ctype": "*", "ext-ctype": "*",
"ext-dom": "*", "ext-dom": "*",
"ext-gd": "*", "ext-gd": "*",
@@ -12,8 +12,7 @@
"ext-json": "*", "ext-json": "*",
"ext-mysqli": "*", "ext-mysqli": "*",
"ext-soap": "*", "ext-soap": "*",
"apereo/phpcas": "~1.6.0", "apereo/phpcas": "dev-master",
"firebase/php-jwt": "^6.4.0",
"guzzlehttp/guzzle": "^7.5.1", "guzzlehttp/guzzle": "^7.5.1",
"league/oauth2-google": "^4.0.1", "league/oauth2-google": "^4.0.1",
"nikic/php-parser": "^4.14.0", "nikic/php-parser": "^4.14.0",
@@ -40,6 +39,12 @@
"symfony/stopwatch": "~6.4.0", "symfony/stopwatch": "~6.4.0",
"symfony/web-profiler-bundle": "~6.4.0" "symfony/web-profiler-bundle": "~6.4.0"
}, },
"repositories": [
{
"type": "vcs",
"url": "https://github.com/EsupPortail/phpCAS"
}
],
"suggest": { "suggest": {
"ext-libsodium": "Required to use the AttributeEncryptedString.", "ext-libsodium": "Required to use the AttributeEncryptedString.",
"ext-openssl": "Can be used as a polyfill if libsodium is not installed", "ext-openssl": "Can be used as a polyfill if libsodium is not installed",

852
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -179,7 +179,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
assert($oLink instanceof $this->sClass); assert($oLink instanceof $this->sClass);
$iObjectId = $oLink->GetKey(); $iObjectId = $oLink->GetKey();
if (array_key_exists($iObjectId, $this->aPreserved)) { if (array_key_exists($iObjectId, $this->aPreserved) && !$oLink->Equals(MetaModel::GetObject(get_class($oLink), $iObjectId, true))) {
unset($this->aPreserved[$iObjectId]); unset($this->aPreserved[$iObjectId]);
$this->aModified[$iObjectId] = $oLink; $this->aModified[$iObjectId] = $oLink;
$this->bHasDelta = true; $this->bHasDelta = true;

View File

@@ -13,7 +13,7 @@ Api documentation can be found here:
https://apereo.github.io/phpCAS/api/ https://apereo.github.io/phpCAS/api/
[![Test](https://github.com/apereo/phpCAS/actions/workflows/test.yml/badge.svg)](https://github.com/apereo/phpCAS/actions/workflows/test.yml) [![Test](https://github.com/EsupPortail/phpCAS/actions/workflows/test.yml/badge.svg)](https://github.com/EsupPortail/phpCAS/actions/workflows/test.yml)
LICENSE LICENSE
------- -------

View File

@@ -57,7 +57,7 @@ if (!isset($_SERVER['REQUEST_URI']) && isset($_SERVER['SCRIPT_NAME']) && isset($
/** /**
* phpCAS version. accessible for the user by phpCAS::getVersion(). * phpCAS version. accessible for the user by phpCAS::getVersion().
*/ */
define('PHPCAS_VERSION', '1.6.1'); define('PHPCAS_VERSION', '1.6.1+');
/** /**
* @addtogroup public * @addtogroup public
@@ -303,7 +303,7 @@ class phpCAS
/** /**
* This variable is used to enable verbose mode * This variable is used to enable verbose mode
* This pevents debug info to be show to the user. Since it's a security * This prevents debug info to be show to the user. Since it's a security
* feature the default is false * feature the default is false
* *
* @hideinitializer * @hideinitializer
@@ -338,7 +338,7 @@ class phpCAS
* @param bool $changeSessionID Allow phpCAS to change the session_id * @param bool $changeSessionID Allow phpCAS to change the session_id
* (Single Sign Out/handleLogoutRequests * (Single Sign Out/handleLogoutRequests
* is based on that change) * is based on that change)
* @param \SessionHandlerInterface $sessionHandler the session handler * @param \SessionHandlerInterface|null $sessionHandler the session handler
* *
* @return void a newly created CAS_Client object * @return void a newly created CAS_Client object
* @note Only one of the phpCAS::client() and phpCAS::proxy functions should be * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
@@ -347,7 +347,7 @@ class phpCAS
*/ */
public static function client($server_version, $server_hostname, public static function client($server_version, $server_hostname,
$server_port, $server_uri, $service_base_url, $server_port, $server_uri, $service_base_url,
$changeSessionID = true, \SessionHandlerInterface $sessionHandler = null $changeSessionID = true, ?\SessionHandlerInterface $sessionHandler = null
) { ) {
phpCAS :: traceBegin(); phpCAS :: traceBegin();
if (is_object(self::$_PHPCAS_CLIENT)) { if (is_object(self::$_PHPCAS_CLIENT)) {
@@ -393,7 +393,7 @@ class phpCAS
* @param bool $changeSessionID Allow phpCAS to change the session_id * @param bool $changeSessionID Allow phpCAS to change the session_id
* (Single Sign Out/handleLogoutRequests * (Single Sign Out/handleLogoutRequests
* is based on that change) * is based on that change)
* @param \SessionHandlerInterface $sessionHandler the session handler * @param \SessionHandlerInterface|null $sessionHandler the session handler
* *
* @return void a newly created CAS_Client object * @return void a newly created CAS_Client object
* @note Only one of the phpCAS::client() and phpCAS::proxy functions should be * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
@@ -402,14 +402,14 @@ class phpCAS
*/ */
public static function proxy($server_version, $server_hostname, public static function proxy($server_version, $server_hostname,
$server_port, $server_uri, $service_base_url, $server_port, $server_uri, $service_base_url,
$changeSessionID = true, \SessionHandlerInterface $sessionHandler = null $changeSessionID = true, ?\SessionHandlerInterface $sessionHandler = null
) { ) {
phpCAS :: traceBegin(); phpCAS :: traceBegin();
if (is_object(self::$_PHPCAS_CLIENT)) { if (is_object(self::$_PHPCAS_CLIENT)) {
phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')'); phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')');
} }
// store where the initialzer is called from // store where the initializer is called from
$dbg = debug_backtrace(); $dbg = debug_backtrace();
self::$_PHPCAS_INIT_CALL = array ( self::$_PHPCAS_INIT_CALL = array (
'done' => true, 'done' => true,
@@ -560,7 +560,7 @@ class phpCAS
$indent_str .= '| '; $indent_str .= '| ';
} }
// allow for multiline output with proper identing. Usefull for // allow for multiline output with proper identing. Useful for
// dumping cas answers etc. // dumping cas answers etc.
$str2 = str_replace("\n", "\n" . self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str, $str); $str2 = str_replace("\n", "\n" . self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str, $str);
$str3 = self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2; $str3 = self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2;
@@ -568,7 +568,7 @@ class phpCAS
self::$_PHPCAS_DEBUG['logger']->info($str3); self::$_PHPCAS_DEBUG['logger']->info($str3);
} }
if (!empty(self::$_PHPCAS_DEBUG['filename'])) { if (!empty(self::$_PHPCAS_DEBUG['filename'])) {
// Check if file exists and modifiy file permissions to be only // Check if file exists and modify file permissions to be only
// readable by the webserver // readable by the webserver
if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) { if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) {
touch(self::$_PHPCAS_DEBUG['filename']); touch(self::$_PHPCAS_DEBUG['filename']);
@@ -1769,7 +1769,7 @@ class phpCAS
/** /**
* If you want your service to be proxied you have to enable it (default * If you want your service to be proxied you have to enable it (default
* disabled) and define an accepable list of proxies that are allowed to * disabled) and define an acceptable list of proxies that are allowed to
* proxy your service. * proxy your service.
* *
* Add each allowed proxy definition object. For the normal CAS_ProxyChain * Add each allowed proxy definition object. For the normal CAS_ProxyChain
@@ -1790,7 +1790,7 @@ class phpCAS
* 'http://client.example.com/' * 'http://client.example.com/'
* ))); * )));
* *
* For quick testing or in certain production screnarios you might want to * For quick testing or in certain production scenarios you might want to
* allow allow any other valid service to proxy your service. To do so, add * allow allow any other valid service to proxy your service. To do so, add
* the "Any" chain: * the "Any" chain:
* phpCAS::allowProxyChain(new CAS_ProxyChain_Any); * phpCAS::allowProxyChain(new CAS_ProxyChain_Any);
@@ -1897,7 +1897,7 @@ class phpCAS
} }
/** /**
* Checks of a proxy client aready exists * Checks of a proxy client already exists
* *
* @throws CAS_OutOfSequenceBeforeProxyException * @throws CAS_OutOfSequenceBeforeProxyException
* *

View File

@@ -788,7 +788,7 @@ class CAS_Client
'file' => $dbg[1]['file'], 'file' => $dbg[1]['file'],
'line' => $dbg[1]['line'], 'line' => $dbg[1]['line'],
'method' => $dbg[1]['class'] . '::' . $dbg[1]['function'], 'method' => $dbg[1]['class'] . '::' . $dbg[1]['function'],
'result' => (boolean)$auth 'result' => (bool)$auth
); );
} }
private $_authentication_caller; private $_authentication_caller;
@@ -926,7 +926,7 @@ class CAS_Client
* CAS_ServiceBaseUrl_Interface for custom * CAS_ServiceBaseUrl_Interface for custom
* behavior. Added in 1.6.0. Similar to * behavior. Added in 1.6.0. Similar to
* serverName config in other CAS clients. * serverName config in other CAS clients.
* @param \SessionHandlerInterface $sessionHandler the session handler * @param \SessionHandlerInterface|null $sessionHandler the session handler
* *
* @return self a newly created CAS_Client object * @return self a newly created CAS_Client object
*/ */
@@ -938,7 +938,7 @@ class CAS_Client
$server_uri, $server_uri,
$service_base_url, $service_base_url,
$changeSessionID = true, $changeSessionID = true,
\SessionHandlerInterface $sessionHandler = null ?\SessionHandlerInterface $sessionHandler = null
) { ) {
// Argument validation // Argument validation
if (gettype($server_version) != 'string') if (gettype($server_version) != 'string')
@@ -3166,7 +3166,7 @@ class CAS_Client
$proxiedService->setCasClient($this); $proxiedService->setCasClient($this);
} }
return $proxiedService; return $proxiedService;
case PHPCAS_PROXIED_SERVICE_IMAP; case PHPCAS_PROXIED_SERVICE_IMAP:
$proxiedService = new CAS_ProxiedService_Imap($this->_getUser()); $proxiedService = new CAS_ProxiedService_Imap($this->_getUser());
if ($proxiedService instanceof CAS_ProxiedService_Testable) { if ($proxiedService instanceof CAS_ProxiedService_Testable) {
$proxiedService->setCasClient($this); $proxiedService->setCasClient($this);

View File

@@ -316,7 +316,7 @@ class CAS_PGTStorage_Db extends CAS_PGTStorage_AbstractStorage
try { try {
$pdo->beginTransaction(); $pdo->beginTransaction();
$query = $pdo->query($this->createTableSQL()); $query = $pdo->query($this->createTableSql());
$query->closeCursor(); $query->closeCursor();
$pdo->commit(); $pdo->commit();

View File

@@ -127,6 +127,12 @@ class CAS_PGTStorage_File extends CAS_PGTStorage_AbstractStorage
if (!preg_match('`^[a-zA-Z]:`', $path)) { if (!preg_match('`^[a-zA-Z]:`', $path)) {
phpCAS::error('an absolute path is needed for PGT storage to file'); phpCAS::error('an absolute path is needed for PGT storage to file');
} }
// ensure that the directory separator on Windows is '/' for consistency with the rest of the phpcas code
$path = str_replace(DIRECTORY_SEPARATOR , '/', $path);
// store the path (with a trailing '/')
$path = preg_replace('|([^/])$|', '$1/', $path);
} else { } else {

View File

@@ -139,7 +139,12 @@ implements CAS_Request_MultiRequestInterface
$buf = curl_multi_getcontent($handles[$i]); $buf = curl_multi_getcontent($handles[$i]);
$request->_storeResponseBody($buf); $request->_storeResponseBody($buf);
curl_multi_remove_handle($multiHandle, $handles[$i]); curl_multi_remove_handle($multiHandle, $handles[$i]);
curl_close($handles[$i]); if (PHP_VERSION_ID < 80000) {
curl_close($handles[$i]);
} else {
// unreference it => it will be closed
unset($handles[$i]);
}
} }
curl_multi_close($multiHandle); curl_multi_close($multiHandle);

View File

@@ -86,7 +86,9 @@ implements CAS_Request_RequestInterface
} }
// close the CURL session // close the CURL session
curl_close($ch); if (PHP_VERSION_ID < 80000) {
curl_close($ch);
}
phpCAS::traceEnd($res); phpCAS::traceEnd($res);
return $res; return $res;

0
lib/bin/patch-type-declarations Normal file → Executable file
View File

View File

@@ -1,5 +0,0 @@
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/patch-type-declarations
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
php "%BIN_TARGET%" %*

0
lib/bin/php-parse Normal file → Executable file
View File

View File

@@ -1,5 +0,0 @@
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/php-parse
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
php "%BIN_TARGET%" %*

0
lib/bin/pscss Normal file → Executable file
View File

View File

@@ -1,5 +0,0 @@
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/pscss
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
php "%BIN_TARGET%" %*

0
lib/bin/var-dump-server Normal file → Executable file
View File

View File

@@ -1,5 +0,0 @@
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/var-dump-server
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
php "%BIN_TARGET%" %*

0
lib/bin/yaml-lint Normal file → Executable file
View File

View File

@@ -1,5 +0,0 @@
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/yaml-lint
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
php "%BIN_TARGET%" %*

View File

@@ -958,6 +958,7 @@ return array(
'PDF417' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/pdf417.php', 'PDF417' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/pdf417.php',
'PDFBulkExport' => $baseDir . '/core/pdfbulkexport.class.inc.php', 'PDFBulkExport' => $baseDir . '/core/pdfbulkexport.class.inc.php',
'PEAR' => $vendorDir . '/pear/pear-core-minimal/src/PEAR.php', 'PEAR' => $vendorDir . '/pear/pear-core-minimal/src/PEAR.php',
'PEAR_Error' => $vendorDir . '/pear/pear-core-minimal/src/PEAR.php',
'PEAR_ErrorStack' => $vendorDir . '/pear/pear-core-minimal/src/PEAR/ErrorStack.php', 'PEAR_ErrorStack' => $vendorDir . '/pear/pear-core-minimal/src/PEAR/ErrorStack.php',
'PEAR_Exception' => $vendorDir . '/pear/pear_exception/PEAR/Exception.php', 'PEAR_Exception' => $vendorDir . '/pear/pear_exception/PEAR/Exception.php',
'Pelago\\Emogrifier\\Caching\\SimpleStringCache' => $vendorDir . '/pelago/emogrifier/src/Caching/SimpleStringCache.php', 'Pelago\\Emogrifier\\Caching\\SimpleStringCache' => $vendorDir . '/pelago/emogrifier/src/Caching/SimpleStringCache.php',
@@ -1645,22 +1646,43 @@ return array(
'Symfony\\Component\\Cache\\Psr16Cache' => $vendorDir . '/symfony/cache/Psr16Cache.php', 'Symfony\\Component\\Cache\\Psr16Cache' => $vendorDir . '/symfony/cache/Psr16Cache.php',
'Symfony\\Component\\Cache\\ResettableInterface' => $vendorDir . '/symfony/cache/ResettableInterface.php', 'Symfony\\Component\\Cache\\ResettableInterface' => $vendorDir . '/symfony/cache/ResettableInterface.php',
'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => $vendorDir . '/symfony/cache/Traits/AbstractAdapterTrait.php', 'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => $vendorDir . '/symfony/cache/Traits/AbstractAdapterTrait.php',
'Symfony\\Component\\Cache\\Traits\\CachedValueInterface' => $vendorDir . '/symfony/cache/Traits/CachedValueInterface.php',
'Symfony\\Component\\Cache\\Traits\\ContractsTrait' => $vendorDir . '/symfony/cache/Traits/ContractsTrait.php', 'Symfony\\Component\\Cache\\Traits\\ContractsTrait' => $vendorDir . '/symfony/cache/Traits/ContractsTrait.php',
'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemCommonTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemCommonTrait.php',
'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemTrait.php',
'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => $vendorDir . '/symfony/cache/Traits/ProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => $vendorDir . '/symfony/cache/Traits/ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => $vendorDir . '/symfony/cache/Traits/Redis5Proxy.php', 'Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => $vendorDir . '/symfony/cache/Traits/Redis5Proxy.php',
'Symfony\\Component\\Cache\\Traits\\Redis61ProxyTrait' => $vendorDir . '/symfony/cache/Traits/Redis61ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Redis62ProxyTrait' => $vendorDir . '/symfony/cache/Traits/Redis62ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Redis63ProxyTrait' => $vendorDir . '/symfony/cache/Traits/Redis63ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => $vendorDir . '/symfony/cache/Traits/Redis6Proxy.php', 'Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => $vendorDir . '/symfony/cache/Traits/Redis6Proxy.php',
'Symfony\\Component\\Cache\\Traits\\Redis6ProxyTrait' => $vendorDir . '/symfony/cache/Traits/Redis6ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster5Proxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster5Proxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster61ProxyTrait' => $vendorDir . '/symfony/cache/Traits/RedisCluster61ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster62ProxyTrait' => $vendorDir . '/symfony/cache/Traits/RedisCluster62ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster63ProxyTrait' => $vendorDir . '/symfony/cache/Traits/RedisCluster63ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster6Proxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster6Proxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster6ProxyTrait' => $vendorDir . '/symfony/cache/Traits/RedisCluster6ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterNodeProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterNodeProxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterProxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisProxy' => $vendorDir . '/symfony/cache/Traits/RedisProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisProxy' => $vendorDir . '/symfony/cache/Traits/RedisProxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisTrait' => $vendorDir . '/symfony/cache/Traits/RedisTrait.php', 'Symfony\\Component\\Cache\\Traits\\RedisTrait' => $vendorDir . '/symfony/cache/Traits/RedisTrait.php',
'Symfony\\Component\\Cache\\Traits\\RelayProxy' => $vendorDir . '/symfony/cache/Traits/RelayProxy.php', 'Symfony\\Component\\Cache\\Traits\\RelayProxy' => $vendorDir . '/symfony/cache/Traits/RelayProxy.php',
'Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => $vendorDir . '/symfony/cache/Traits/RelayProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => $vendorDir . '/symfony/cache/Traits/RelayProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\BgsaveTrait' => $vendorDir . '/symfony/cache/Traits/Relay/BgsaveTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\CopyTrait' => $vendorDir . '/symfony/cache/Traits/Relay/CopyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\FtTrait' => $vendorDir . '/symfony/cache/Traits/Relay/FtTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\GeosearchTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GeosearchTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\GetWithMetaTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GetWithMetaTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\GetrangeTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GetrangeTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\HsetTrait' => $vendorDir . '/symfony/cache/Traits/Relay/HsetTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\IsTrackedTrait' => $vendorDir . '/symfony/cache/Traits/Relay/IsTrackedTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\MoveTrait' => $vendorDir . '/symfony/cache/Traits/Relay/MoveTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\NullableReturnTrait' => $vendorDir . '/symfony/cache/Traits/Relay/NullableReturnTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\PfcountTrait' => $vendorDir . '/symfony/cache/Traits/Relay/PfcountTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\Relay11Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay11Trait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\Relay121Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay121Trait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\Relay12Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay12Trait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\Relay20Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay20Trait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\SwapdbTrait' => $vendorDir . '/symfony/cache/Traits/Relay/SwapdbTrait.php',
'Symfony\\Component\\Config\\Builder\\ClassBuilder' => $vendorDir . '/symfony/config/Builder/ClassBuilder.php', 'Symfony\\Component\\Config\\Builder\\ClassBuilder' => $vendorDir . '/symfony/config/Builder/ClassBuilder.php',
'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGenerator.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGenerator.php',
'Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php',
@@ -1825,6 +1847,7 @@ return array(
'Symfony\\Component\\Console\\Helper\\TableRows' => $vendorDir . '/symfony/console/Helper/TableRows.php', 'Symfony\\Component\\Console\\Helper\\TableRows' => $vendorDir . '/symfony/console/Helper/TableRows.php',
'Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php', 'Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php',
'Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php', 'Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php',
'Symfony\\Component\\Console\\Helper\\TerminalInputHelper' => $vendorDir . '/symfony/console/Helper/TerminalInputHelper.php',
'Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php', 'Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php',
'Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php', 'Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php',
'Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php', 'Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php',
@@ -2699,7 +2722,6 @@ return array(
'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => $vendorDir . '/symfony/var-dumper/Cloner/Cursor.php', 'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => $vendorDir . '/symfony/var-dumper/Cloner/Cursor.php',
'Symfony\\Component\\VarDumper\\Cloner\\Data' => $vendorDir . '/symfony/var-dumper/Cloner/Data.php', 'Symfony\\Component\\VarDumper\\Cloner\\Data' => $vendorDir . '/symfony/var-dumper/Cloner/Data.php',
'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => $vendorDir . '/symfony/var-dumper/Cloner/DumperInterface.php', 'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => $vendorDir . '/symfony/var-dumper/Cloner/DumperInterface.php',
'Symfony\\Component\\VarDumper\\Cloner\\Internal\\NoDefault' => $vendorDir . '/symfony/var-dumper/Cloner/Internal/NoDefault.php',
'Symfony\\Component\\VarDumper\\Cloner\\Stub' => $vendorDir . '/symfony/var-dumper/Cloner/Stub.php', 'Symfony\\Component\\VarDumper\\Cloner\\Stub' => $vendorDir . '/symfony/var-dumper/Cloner/Stub.php',
'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => $vendorDir . '/symfony/var-dumper/Cloner/VarCloner.php', 'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => $vendorDir . '/symfony/var-dumper/Cloner/VarCloner.php',
'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php',
@@ -2854,6 +2876,7 @@ return array(
'Twig\\ExpressionParser\\InfixExpressionParserInterface' => $vendorDir . '/twig/twig/src/ExpressionParser/InfixExpressionParserInterface.php', 'Twig\\ExpressionParser\\InfixExpressionParserInterface' => $vendorDir . '/twig/twig/src/ExpressionParser/InfixExpressionParserInterface.php',
'Twig\\ExpressionParser\\Infix\\ArgumentsTrait' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/ArgumentsTrait.php', 'Twig\\ExpressionParser\\Infix\\ArgumentsTrait' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/ArgumentsTrait.php',
'Twig\\ExpressionParser\\Infix\\ArrowExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/ArrowExpressionParser.php', 'Twig\\ExpressionParser\\Infix\\ArrowExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/ArrowExpressionParser.php',
'Twig\\ExpressionParser\\Infix\\AssignmentExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/AssignmentExpressionParser.php',
'Twig\\ExpressionParser\\Infix\\BinaryOperatorExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/BinaryOperatorExpressionParser.php', 'Twig\\ExpressionParser\\Infix\\BinaryOperatorExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/BinaryOperatorExpressionParser.php',
'Twig\\ExpressionParser\\Infix\\ConditionalTernaryExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/ConditionalTernaryExpressionParser.php', 'Twig\\ExpressionParser\\Infix\\ConditionalTernaryExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/ConditionalTernaryExpressionParser.php',
'Twig\\ExpressionParser\\Infix\\DotExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/DotExpressionParser.php', 'Twig\\ExpressionParser\\Infix\\DotExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser/Infix/DotExpressionParser.php',
@@ -2939,10 +2962,15 @@ return array(
'Twig\\Node\\Expression\\Binary\\MulBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/MulBinary.php', 'Twig\\Node\\Expression\\Binary\\MulBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/MulBinary.php',
'Twig\\Node\\Expression\\Binary\\NotEqualBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php', 'Twig\\Node\\Expression\\Binary\\NotEqualBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php',
'Twig\\Node\\Expression\\Binary\\NotInBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/NotInBinary.php', 'Twig\\Node\\Expression\\Binary\\NotInBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/NotInBinary.php',
'Twig\\Node\\Expression\\Binary\\NotSameAsBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/NotSameAsBinary.php',
'Twig\\Node\\Expression\\Binary\\NullCoalesceBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/NullCoalesceBinary.php', 'Twig\\Node\\Expression\\Binary\\NullCoalesceBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/NullCoalesceBinary.php',
'Twig\\Node\\Expression\\Binary\\ObjectDestructuringSetBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php',
'Twig\\Node\\Expression\\Binary\\OrBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/OrBinary.php', 'Twig\\Node\\Expression\\Binary\\OrBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/OrBinary.php',
'Twig\\Node\\Expression\\Binary\\PowerBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/PowerBinary.php', 'Twig\\Node\\Expression\\Binary\\PowerBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/PowerBinary.php',
'Twig\\Node\\Expression\\Binary\\RangeBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/RangeBinary.php', 'Twig\\Node\\Expression\\Binary\\RangeBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/RangeBinary.php',
'Twig\\Node\\Expression\\Binary\\SameAsBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/SameAsBinary.php',
'Twig\\Node\\Expression\\Binary\\SequenceDestructuringSetBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/SequenceDestructuringSetBinary.php',
'Twig\\Node\\Expression\\Binary\\SetBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/SetBinary.php',
'Twig\\Node\\Expression\\Binary\\SpaceshipBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php', 'Twig\\Node\\Expression\\Binary\\SpaceshipBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php',
'Twig\\Node\\Expression\\Binary\\StartsWithBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php', 'Twig\\Node\\Expression\\Binary\\StartsWithBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php',
'Twig\\Node\\Expression\\Binary\\SubBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/SubBinary.php', 'Twig\\Node\\Expression\\Binary\\SubBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/SubBinary.php',
@@ -2951,6 +2979,7 @@ return array(
'Twig\\Node\\Expression\\CallExpression' => $vendorDir . '/twig/twig/src/Node/Expression/CallExpression.php', 'Twig\\Node\\Expression\\CallExpression' => $vendorDir . '/twig/twig/src/Node/Expression/CallExpression.php',
'Twig\\Node\\Expression\\ConditionalExpression' => $vendorDir . '/twig/twig/src/Node/Expression/ConditionalExpression.php', 'Twig\\Node\\Expression\\ConditionalExpression' => $vendorDir . '/twig/twig/src/Node/Expression/ConditionalExpression.php',
'Twig\\Node\\Expression\\ConstantExpression' => $vendorDir . '/twig/twig/src/Node/Expression/ConstantExpression.php', 'Twig\\Node\\Expression\\ConstantExpression' => $vendorDir . '/twig/twig/src/Node/Expression/ConstantExpression.php',
'Twig\\Node\\Expression\\EmptyExpression' => $vendorDir . '/twig/twig/src/Node/Expression/EmptyExpression.php',
'Twig\\Node\\Expression\\FilterExpression' => $vendorDir . '/twig/twig/src/Node/Expression/FilterExpression.php', 'Twig\\Node\\Expression\\FilterExpression' => $vendorDir . '/twig/twig/src/Node/Expression/FilterExpression.php',
'Twig\\Node\\Expression\\Filter\\DefaultFilter' => $vendorDir . '/twig/twig/src/Node/Expression/Filter/DefaultFilter.php', 'Twig\\Node\\Expression\\Filter\\DefaultFilter' => $vendorDir . '/twig/twig/src/Node/Expression/Filter/DefaultFilter.php',
'Twig\\Node\\Expression\\Filter\\RawFilter' => $vendorDir . '/twig/twig/src/Node/Expression/Filter/RawFilter.php', 'Twig\\Node\\Expression\\Filter\\RawFilter' => $vendorDir . '/twig/twig/src/Node/Expression/Filter/RawFilter.php',

View File

@@ -8,5 +8,4 @@ $baseDir = dirname($vendorDir);
return array( return array(
'Console' => array($vendorDir . '/pear/console_getopt'), 'Console' => array($vendorDir . '/pear/console_getopt'),
'Archive_Tar' => array($vendorDir . '/pear/archive_tar'), 'Archive_Tar' => array($vendorDir . '/pear/archive_tar'),
'' => array($vendorDir . '/pear/pear-core-minimal/src'),
); );

View File

@@ -360,10 +360,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
), ),
); );
public static $fallbackDirsPsr0 = array (
0 => __DIR__ . '/..' . '/pear/pear-core-minimal/src',
);
public static $classMap = array ( public static $classMap = array (
'AbstractApplicationObjectExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'AbstractApplicationObjectExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php',
'AbstractApplicationUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'AbstractApplicationUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php',
@@ -1317,6 +1313,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'PDF417' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/pdf417.php', 'PDF417' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/pdf417.php',
'PDFBulkExport' => __DIR__ . '/../..' . '/core/pdfbulkexport.class.inc.php', 'PDFBulkExport' => __DIR__ . '/../..' . '/core/pdfbulkexport.class.inc.php',
'PEAR' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR.php', 'PEAR' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR.php',
'PEAR_Error' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR.php',
'PEAR_ErrorStack' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR/ErrorStack.php', 'PEAR_ErrorStack' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR/ErrorStack.php',
'PEAR_Exception' => __DIR__ . '/..' . '/pear/pear_exception/PEAR/Exception.php', 'PEAR_Exception' => __DIR__ . '/..' . '/pear/pear_exception/PEAR/Exception.php',
'Pelago\\Emogrifier\\Caching\\SimpleStringCache' => __DIR__ . '/..' . '/pelago/emogrifier/src/Caching/SimpleStringCache.php', 'Pelago\\Emogrifier\\Caching\\SimpleStringCache' => __DIR__ . '/..' . '/pelago/emogrifier/src/Caching/SimpleStringCache.php',
@@ -2004,22 +2001,43 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Symfony\\Component\\Cache\\Psr16Cache' => __DIR__ . '/..' . '/symfony/cache/Psr16Cache.php', 'Symfony\\Component\\Cache\\Psr16Cache' => __DIR__ . '/..' . '/symfony/cache/Psr16Cache.php',
'Symfony\\Component\\Cache\\ResettableInterface' => __DIR__ . '/..' . '/symfony/cache/ResettableInterface.php', 'Symfony\\Component\\Cache\\ResettableInterface' => __DIR__ . '/..' . '/symfony/cache/ResettableInterface.php',
'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/AbstractAdapterTrait.php', 'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/AbstractAdapterTrait.php',
'Symfony\\Component\\Cache\\Traits\\CachedValueInterface' => __DIR__ . '/..' . '/symfony/cache/Traits/CachedValueInterface.php',
'Symfony\\Component\\Cache\\Traits\\ContractsTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ContractsTrait.php', 'Symfony\\Component\\Cache\\Traits\\ContractsTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ContractsTrait.php',
'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemCommonTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemCommonTrait.php',
'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemTrait.php',
'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis5Proxy.php', 'Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis5Proxy.php',
'Symfony\\Component\\Cache\\Traits\\Redis61ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis61ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Redis62ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis62ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Redis63ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis63ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis6Proxy.php', 'Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis6Proxy.php',
'Symfony\\Component\\Cache\\Traits\\Redis6ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis6ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster5Proxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster5Proxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster61ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster61ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster62ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster62ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster63ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster63ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster6Proxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster6Proxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisCluster6ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster6ProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterNodeProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterNodeProxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterProxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisProxy.php',
'Symfony\\Component\\Cache\\Traits\\RedisTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisTrait.php', 'Symfony\\Component\\Cache\\Traits\\RedisTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisTrait.php',
'Symfony\\Component\\Cache\\Traits\\RelayProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxy.php', 'Symfony\\Component\\Cache\\Traits\\RelayProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxy.php',
'Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\BgsaveTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/BgsaveTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\CopyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/CopyTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\FtTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/FtTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\GeosearchTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GeosearchTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\GetWithMetaTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GetWithMetaTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\GetrangeTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GetrangeTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\HsetTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/HsetTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\IsTrackedTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/IsTrackedTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\MoveTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/MoveTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\NullableReturnTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/NullableReturnTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\PfcountTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/PfcountTrait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\Relay11Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay11Trait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\Relay121Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay121Trait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\Relay12Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay12Trait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\Relay20Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay20Trait.php',
'Symfony\\Component\\Cache\\Traits\\Relay\\SwapdbTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/SwapdbTrait.php',
'Symfony\\Component\\Config\\Builder\\ClassBuilder' => __DIR__ . '/..' . '/symfony/config/Builder/ClassBuilder.php', 'Symfony\\Component\\Config\\Builder\\ClassBuilder' => __DIR__ . '/..' . '/symfony/config/Builder/ClassBuilder.php',
'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGenerator.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGenerator.php',
'Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php',
@@ -2184,6 +2202,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Symfony\\Component\\Console\\Helper\\TableRows' => __DIR__ . '/..' . '/symfony/console/Helper/TableRows.php', 'Symfony\\Component\\Console\\Helper\\TableRows' => __DIR__ . '/..' . '/symfony/console/Helper/TableRows.php',
'Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php', 'Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php',
'Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php', 'Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php',
'Symfony\\Component\\Console\\Helper\\TerminalInputHelper' => __DIR__ . '/..' . '/symfony/console/Helper/TerminalInputHelper.php',
'Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php', 'Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php',
'Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php', 'Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php',
'Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php', 'Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php',
@@ -3058,7 +3077,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Cursor.php', 'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Cursor.php',
'Symfony\\Component\\VarDumper\\Cloner\\Data' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Data.php', 'Symfony\\Component\\VarDumper\\Cloner\\Data' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Data.php',
'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/DumperInterface.php', 'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/DumperInterface.php',
'Symfony\\Component\\VarDumper\\Cloner\\Internal\\NoDefault' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Internal/NoDefault.php',
'Symfony\\Component\\VarDumper\\Cloner\\Stub' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Stub.php', 'Symfony\\Component\\VarDumper\\Cloner\\Stub' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Stub.php',
'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/VarCloner.php', 'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/VarCloner.php',
'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php',
@@ -3213,6 +3231,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Twig\\ExpressionParser\\InfixExpressionParserInterface' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/InfixExpressionParserInterface.php', 'Twig\\ExpressionParser\\InfixExpressionParserInterface' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/InfixExpressionParserInterface.php',
'Twig\\ExpressionParser\\Infix\\ArgumentsTrait' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/ArgumentsTrait.php', 'Twig\\ExpressionParser\\Infix\\ArgumentsTrait' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/ArgumentsTrait.php',
'Twig\\ExpressionParser\\Infix\\ArrowExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/ArrowExpressionParser.php', 'Twig\\ExpressionParser\\Infix\\ArrowExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/ArrowExpressionParser.php',
'Twig\\ExpressionParser\\Infix\\AssignmentExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/AssignmentExpressionParser.php',
'Twig\\ExpressionParser\\Infix\\BinaryOperatorExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/BinaryOperatorExpressionParser.php', 'Twig\\ExpressionParser\\Infix\\BinaryOperatorExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/BinaryOperatorExpressionParser.php',
'Twig\\ExpressionParser\\Infix\\ConditionalTernaryExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/ConditionalTernaryExpressionParser.php', 'Twig\\ExpressionParser\\Infix\\ConditionalTernaryExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/ConditionalTernaryExpressionParser.php',
'Twig\\ExpressionParser\\Infix\\DotExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/DotExpressionParser.php', 'Twig\\ExpressionParser\\Infix\\DotExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser/Infix/DotExpressionParser.php',
@@ -3298,10 +3317,15 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Twig\\Node\\Expression\\Binary\\MulBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/MulBinary.php', 'Twig\\Node\\Expression\\Binary\\MulBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/MulBinary.php',
'Twig\\Node\\Expression\\Binary\\NotEqualBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php', 'Twig\\Node\\Expression\\Binary\\NotEqualBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php',
'Twig\\Node\\Expression\\Binary\\NotInBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/NotInBinary.php', 'Twig\\Node\\Expression\\Binary\\NotInBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/NotInBinary.php',
'Twig\\Node\\Expression\\Binary\\NotSameAsBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/NotSameAsBinary.php',
'Twig\\Node\\Expression\\Binary\\NullCoalesceBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/NullCoalesceBinary.php', 'Twig\\Node\\Expression\\Binary\\NullCoalesceBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/NullCoalesceBinary.php',
'Twig\\Node\\Expression\\Binary\\ObjectDestructuringSetBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php',
'Twig\\Node\\Expression\\Binary\\OrBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/OrBinary.php', 'Twig\\Node\\Expression\\Binary\\OrBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/OrBinary.php',
'Twig\\Node\\Expression\\Binary\\PowerBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/PowerBinary.php', 'Twig\\Node\\Expression\\Binary\\PowerBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/PowerBinary.php',
'Twig\\Node\\Expression\\Binary\\RangeBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/RangeBinary.php', 'Twig\\Node\\Expression\\Binary\\RangeBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/RangeBinary.php',
'Twig\\Node\\Expression\\Binary\\SameAsBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/SameAsBinary.php',
'Twig\\Node\\Expression\\Binary\\SequenceDestructuringSetBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/SequenceDestructuringSetBinary.php',
'Twig\\Node\\Expression\\Binary\\SetBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/SetBinary.php',
'Twig\\Node\\Expression\\Binary\\SpaceshipBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php', 'Twig\\Node\\Expression\\Binary\\SpaceshipBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php',
'Twig\\Node\\Expression\\Binary\\StartsWithBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php', 'Twig\\Node\\Expression\\Binary\\StartsWithBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php',
'Twig\\Node\\Expression\\Binary\\SubBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/SubBinary.php', 'Twig\\Node\\Expression\\Binary\\SubBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/SubBinary.php',
@@ -3310,6 +3334,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Twig\\Node\\Expression\\CallExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/CallExpression.php', 'Twig\\Node\\Expression\\CallExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/CallExpression.php',
'Twig\\Node\\Expression\\ConditionalExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/ConditionalExpression.php', 'Twig\\Node\\Expression\\ConditionalExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/ConditionalExpression.php',
'Twig\\Node\\Expression\\ConstantExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/ConstantExpression.php', 'Twig\\Node\\Expression\\ConstantExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/ConstantExpression.php',
'Twig\\Node\\Expression\\EmptyExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/EmptyExpression.php',
'Twig\\Node\\Expression\\FilterExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/FilterExpression.php', 'Twig\\Node\\Expression\\FilterExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/FilterExpression.php',
'Twig\\Node\\Expression\\Filter\\DefaultFilter' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Filter/DefaultFilter.php', 'Twig\\Node\\Expression\\Filter\\DefaultFilter' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Filter/DefaultFilter.php',
'Twig\\Node\\Expression\\Filter\\RawFilter' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Filter/RawFilter.php', 'Twig\\Node\\Expression\\Filter\\RawFilter' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Filter/RawFilter.php',
@@ -3542,7 +3567,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
$loader->prefixLengthsPsr4 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$prefixesPsr0; $loader->prefixesPsr0 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$prefixesPsr0;
$loader->fallbackDirsPsr0 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$fallbackDirsPsr0;
$loader->classMap = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$classMap; $loader->classMap = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,9 @@
<?php return array( <?php return array(
'root' => array( 'root' => array(
'name' => 'combodo/itop', 'name' => 'combodo/itop',
'pretty_version' => 'dev-develop', 'pretty_version' => '1.0.0+no-version-set',
'version' => 'dev-develop', 'version' => '1.0.0.0',
'reference' => 'd5706fcbef58868cb8bd6ee6f3af133ca4fdab3e', 'reference' => null,
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@@ -11,18 +11,20 @@
), ),
'versions' => array( 'versions' => array(
'apereo/phpcas' => array( 'apereo/phpcas' => array(
'pretty_version' => '1.6.1', 'pretty_version' => 'dev-master',
'version' => '1.6.1.0', 'version' => 'dev-master',
'reference' => 'c129708154852656aabb13d8606cd5b12dbbabac', 'reference' => '57a7744146a963d8fa80192e0ab351051b711ff6',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../apereo/phpcas', 'install_path' => __DIR__ . '/../apereo/phpcas',
'aliases' => array(), 'aliases' => array(
0 => '1.3.x-dev',
),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'combodo/itop' => array( 'combodo/itop' => array(
'pretty_version' => 'dev-develop', 'pretty_version' => '1.0.0+no-version-set',
'version' => 'dev-develop', 'version' => '1.0.0.0',
'reference' => 'd5706fcbef58868cb8bd6ee6f3af133ca4fdab3e', 'reference' => null,
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@@ -47,77 +49,68 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'firebase/php-jwt' => array( 'firebase/php-jwt' => array(
'pretty_version' => 'v6.10.0', 'pretty_version' => 'v7.0.2',
'version' => '6.10.0.0', 'version' => '7.0.2.0',
'reference' => 'a49db6f0a5033aef5143295342f1c95521b075ff', 'reference' => '5645b43af647b6947daac1d0f659dd1fbe8d3b65',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../firebase/php-jwt', 'install_path' => __DIR__ . '/../firebase/php-jwt',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'guzzlehttp/guzzle' => array( 'guzzlehttp/guzzle' => array(
'pretty_version' => '7.8.1', 'pretty_version' => '7.10.0',
'version' => '7.8.1.0', 'version' => '7.10.0.0',
'reference' => '41042bc7ab002487b876a0683fc8dce04ddce104', 'reference' => 'b51ac707cfa420b7bfd4e4d5e510ba8008e822b4',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../guzzlehttp/guzzle', 'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'guzzlehttp/promises' => array( 'guzzlehttp/promises' => array(
'pretty_version' => '2.0.2', 'pretty_version' => '2.3.0',
'version' => '2.0.2.0', 'version' => '2.3.0.0',
'reference' => 'bbff78d96034045e58e13dedd6ad91b5d1253223', 'reference' => '481557b130ef3790cf82b713667b43030dc9c957',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../guzzlehttp/promises', 'install_path' => __DIR__ . '/../guzzlehttp/promises',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'guzzlehttp/psr7' => array( 'guzzlehttp/psr7' => array(
'pretty_version' => '2.6.2', 'pretty_version' => '2.8.0',
'version' => '2.6.2.0', 'version' => '2.8.0.0',
'reference' => '45b30f99ac27b5ca93cb4831afe16285f57b8221', 'reference' => '21dc724a0583619cd1652f673303492272778051',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../guzzlehttp/psr7', 'install_path' => __DIR__ . '/../guzzlehttp/psr7',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'league/oauth2-client' => array( 'league/oauth2-client' => array(
'pretty_version' => '2.7.0', 'pretty_version' => '2.9.0',
'version' => '2.7.0.0', 'version' => '2.9.0.0',
'reference' => '160d6274b03562ebeb55ed18399281d8118b76c8', 'reference' => '26e8c5da4f3d78cede7021e09b1330a0fc093d5e',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../league/oauth2-client', 'install_path' => __DIR__ . '/../league/oauth2-client',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'league/oauth2-google' => array( 'league/oauth2-google' => array(
'pretty_version' => '4.0.1', 'pretty_version' => '4.1.0',
'version' => '4.0.1.0', 'version' => '4.1.0.0',
'reference' => '1b01ba18ba31b29e88771e3e0979e5c91d4afe76', 'reference' => '8b9bb43740ac6d994aca881a35f7bacbe98c0ffb',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../league/oauth2-google', 'install_path' => __DIR__ . '/../league/oauth2-google',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'nikic/php-parser' => array( 'nikic/php-parser' => array(
'pretty_version' => 'v4.18.0', 'pretty_version' => 'v4.19.5',
'version' => '4.18.0.0', 'version' => '4.19.5.0',
'reference' => '1bcbb2179f97633e98bbbc87044ee2611c7d7999', 'reference' => '51bd93cc741b7fc3d63d20b6bdcd99fdaa359837',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../nikic/php-parser', 'install_path' => __DIR__ . '/../nikic/php-parser',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'paragonie/random_compat' => array(
'pretty_version' => 'v9.99.100',
'version' => '9.99.100.0',
'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
'type' => 'library',
'install_path' => __DIR__ . '/../paragonie/random_compat',
'aliases' => array(),
'dev_requirement' => false,
),
'pear/archive_tar' => array( 'pear/archive_tar' => array(
'pretty_version' => '1.4.14', 'pretty_version' => '1.4.14',
'version' => '1.4.14.0', 'version' => '1.4.14.0',
@@ -137,9 +130,9 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'pear/pear-core-minimal' => array( 'pear/pear-core-minimal' => array(
'pretty_version' => 'v1.10.11', 'pretty_version' => 'v1.10.18',
'version' => '1.10.11.0', 'version' => '1.10.18.0',
'reference' => '68d0d32ada737153b7e93b8d3c710ebe70ac867d', 'reference' => 'c7b55789d01de0ce090d289b73f1bbd6a2f113b1',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../pear/pear-core-minimal', 'install_path' => __DIR__ . '/../pear/pear-core-minimal',
'aliases' => array(), 'aliases' => array(),
@@ -155,9 +148,9 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'pelago/emogrifier' => array( 'pelago/emogrifier' => array(
'pretty_version' => 'v7.2.0', 'pretty_version' => 'v7.3.0',
'version' => '7.2.0.0', 'version' => '7.3.0.0',
'reference' => '727bdf7255b51798307f17dec52ff8a91f1c7de3', 'reference' => '6e00d9d8235e8cc8eec857e8dcd6cfeefdfd0cd6',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../pelago/emogrifier', 'install_path' => __DIR__ . '/../pelago/emogrifier',
'aliases' => array(), 'aliases' => array(),
@@ -224,9 +217,9 @@
), ),
), ),
'psr/http-factory' => array( 'psr/http-factory' => array(
'pretty_version' => '1.0.2', 'pretty_version' => '1.1.0',
'version' => '1.0.2.0', 'version' => '1.1.0.0',
'reference' => 'e616d01114759c4c489f93b099585439f795fe35', 'reference' => '2b4765fddfe3b508ac62f829e852b1501d3f6e8a',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../psr/http-factory', 'install_path' => __DIR__ . '/../psr/http-factory',
'aliases' => array(), 'aliases' => array(),
@@ -286,22 +279,22 @@
'rsky/pear-core-min' => array( 'rsky/pear-core-min' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v1.10.11', 0 => 'v1.10.18',
), ),
), ),
'sabberworm/php-css-parser' => array( 'sabberworm/php-css-parser' => array(
'pretty_version' => '8.4.0', 'pretty_version' => 'v8.9.0',
'version' => '8.4.0.0', 'version' => '8.9.0.0',
'reference' => 'e41d2140031d533348b2192a83f02d8dd8a71d30', 'reference' => 'd8e916507b88e389e26d4ab03c904a082aa66bb9',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../sabberworm/php-css-parser', 'install_path' => __DIR__ . '/../sabberworm/php-css-parser',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'scssphp/scssphp' => array( 'scssphp/scssphp' => array(
'pretty_version' => 'v1.12.1', 'pretty_version' => 'v1.13.0',
'version' => '1.12.1.0', 'version' => '1.13.0.0',
'reference' => '394ed1e960138710a60d035c1a85d43d0bf0faeb', 'reference' => '63d1157457e5554edf00b0c1fabab4c1511d2520',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../scssphp/scssphp', 'install_path' => __DIR__ . '/../scssphp/scssphp',
'aliases' => array(), 'aliases' => array(),
@@ -317,9 +310,9 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/cache' => array( 'symfony/cache' => array(
'pretty_version' => 'v6.4.12', 'pretty_version' => 'v6.4.33',
'version' => '6.4.12.0', 'version' => '6.4.33.0',
'reference' => 'a463451b7f6ac4a47b98dbfc78ec2d3560c759d8', 'reference' => '5b088fa41eb9568748dc255c45e4054c387ba73b',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/cache', 'install_path' => __DIR__ . '/../symfony/cache',
'aliases' => array(), 'aliases' => array(),
@@ -341,45 +334,45 @@
), ),
), ),
'symfony/config' => array( 'symfony/config' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.32',
'version' => '6.4.0.0', 'version' => '6.4.32.0',
'reference' => '5d33e0fb707d603330e0edfd4691803a1253572e', 'reference' => 'd445badf0ad2c2a492e38c0378c39997a56ef97b',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/config', 'install_path' => __DIR__ . '/../symfony/config',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/console' => array( 'symfony/console' => array(
'pretty_version' => 'v6.4.2', 'pretty_version' => 'v6.4.32',
'version' => '6.4.2.0', 'version' => '6.4.32.0',
'reference' => '0254811a143e6bc6c8deea08b589a7e68a37f625', 'reference' => '0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/console', 'install_path' => __DIR__ . '/../symfony/console',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/css-selector' => array( 'symfony/css-selector' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.24',
'version' => '6.4.0.0', 'version' => '6.4.24.0',
'reference' => 'd036c6c0d0b09e24a14a35f8292146a658f986e4', 'reference' => '9b784413143701aa3c94ac1869a159a9e53e8761',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/css-selector', 'install_path' => __DIR__ . '/../symfony/css-selector',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/debug-bundle' => array( 'symfony/debug-bundle' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.27',
'version' => '6.4.0.0', 'version' => '6.4.27.0',
'reference' => '1e07027423d1d37125b60a50997ada26a9d9d202', 'reference' => '21a61c55192d558a6b81cdb12e8c010fc9474fe0',
'type' => 'symfony-bundle', 'type' => 'symfony-bundle',
'install_path' => __DIR__ . '/../symfony/debug-bundle', 'install_path' => __DIR__ . '/../symfony/debug-bundle',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'symfony/dependency-injection' => array( 'symfony/dependency-injection' => array(
'pretty_version' => 'v6.4.2', 'pretty_version' => 'v6.4.32',
'version' => '6.4.2.0', 'version' => '6.4.32.0',
'reference' => '226ea431b1eda6f0d9f5a4b278757171960bb195', 'reference' => 'b17882e933c4c606620247b6708ab53aa3b88753',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/dependency-injection', 'install_path' => __DIR__ . '/../symfony/dependency-injection',
'aliases' => array(), 'aliases' => array(),
@@ -395,27 +388,27 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/dotenv' => array( 'symfony/dotenv' => array(
'pretty_version' => 'v6.4.2', 'pretty_version' => 'v6.4.30',
'version' => '6.4.2.0', 'version' => '6.4.30.0',
'reference' => '835f8d2d1022934ac038519de40b88158798c96f', 'reference' => '924edbc9631b75302def0258ed1697948b17baf6',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/dotenv', 'install_path' => __DIR__ . '/../symfony/dotenv',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/error-handler' => array( 'symfony/error-handler' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.32',
'version' => '6.4.0.0', 'version' => '6.4.32.0',
'reference' => 'c873490a1c97b3a0a4838afc36ff36c112d02788', 'reference' => '8c18400784fcb014dc73c8d5601a9576af7f8ad4',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/error-handler', 'install_path' => __DIR__ . '/../symfony/error-handler',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/event-dispatcher' => array( 'symfony/event-dispatcher' => array(
'pretty_version' => 'v6.4.25', 'pretty_version' => 'v6.4.32',
'version' => '6.4.25.0', 'version' => '6.4.32.0',
'reference' => 'b0cf3162020603587363f0551cd3be43958611ff', 'reference' => '99d7e101826e6610606b9433248f80c1997cd20b',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'install_path' => __DIR__ . '/../symfony/event-dispatcher',
'aliases' => array(), 'aliases' => array(),
@@ -437,81 +430,81 @@
), ),
), ),
'symfony/filesystem' => array( 'symfony/filesystem' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.30',
'version' => '6.4.0.0', 'version' => '6.4.30.0',
'reference' => '952a8cb588c3bc6ce76f6023000fb932f16a6e59', 'reference' => '441c6b69f7222aadae7cbf5df588496d5ee37789',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/filesystem', 'install_path' => __DIR__ . '/../symfony/filesystem',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/finder' => array( 'symfony/finder' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.33',
'version' => '6.4.0.0', 'version' => '6.4.33.0',
'reference' => '11d736e97f116ac375a81f96e662911a34cd50ce', 'reference' => '24965ca011dac87431729640feef8bcf7b5523e0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/finder', 'install_path' => __DIR__ . '/../symfony/finder',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/framework-bundle' => array( 'symfony/framework-bundle' => array(
'pretty_version' => 'v6.4.2', 'pretty_version' => 'v6.4.33',
'version' => '6.4.2.0', 'version' => '6.4.33.0',
'reference' => 'c26a221e0462027d1f9d4a802ed63f8ab07a43d0', 'reference' => '9ef2d0b63b9e855ba351e770a603d89699115801',
'type' => 'symfony-bundle', 'type' => 'symfony-bundle',
'install_path' => __DIR__ . '/../symfony/framework-bundle', 'install_path' => __DIR__ . '/../symfony/framework-bundle',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/http-foundation' => array( 'symfony/http-foundation' => array(
'pretty_version' => 'v6.4.29', 'pretty_version' => 'v6.4.33',
'version' => '6.4.29.0', 'version' => '6.4.33.0',
'reference' => 'b03d11e015552a315714c127d8d1e0f9e970ec88', 'reference' => 'f1a490cc9d595ba7ebe684220e625d1e472ad278',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/http-foundation', 'install_path' => __DIR__ . '/../symfony/http-foundation',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/http-kernel' => array( 'symfony/http-kernel' => array(
'pretty_version' => 'v6.4.2', 'pretty_version' => 'v6.4.33',
'version' => '6.4.2.0', 'version' => '6.4.33.0',
'reference' => '13e8387320b5942d0dc408440c888e2d526efef4', 'reference' => '73fa5c999d7f741ca544a97d3c791cc97890ae4d',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/http-kernel', 'install_path' => __DIR__ . '/../symfony/http-kernel',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/mailer' => array( 'symfony/mailer' => array(
'pretty_version' => 'v6.4.25', 'pretty_version' => 'v6.4.31',
'version' => '6.4.25.0', 'version' => '6.4.31.0',
'reference' => '628b43b45a3e6b15c8a633fb22df547ed9b492a2', 'reference' => '8835f93333474780fda1b987cae37e33c3e026ca',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/mailer', 'install_path' => __DIR__ . '/../symfony/mailer',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/mime' => array( 'symfony/mime' => array(
'pretty_version' => 'v6.4.24', 'pretty_version' => 'v6.4.32',
'version' => '6.4.24.0', 'version' => '6.4.32.0',
'reference' => '664d5e844a2de5e11c8255d0aef6bc15a9660ac7', 'reference' => '7409686879ca36c09fc970a5fa8ff6e93504dba4',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/mime', 'install_path' => __DIR__ . '/../symfony/mime',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/polyfill-ctype' => array( 'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.28.0', 'pretty_version' => 'v1.33.0',
'version' => '1.28.0.0', 'version' => '1.33.0.0',
'reference' => 'ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb', 'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/polyfill-intl-grapheme' => array( 'symfony/polyfill-intl-grapheme' => array(
'pretty_version' => 'v1.28.0', 'pretty_version' => 'v1.33.0',
'version' => '1.28.0.0', 'version' => '1.33.0.0',
'reference' => '875e90aeea2777b6f135677f618529449334a612', 'reference' => '380872130d3a5dd3ace2f4010d95125fde5d5c70',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme',
'aliases' => array(), 'aliases' => array(),
@@ -554,18 +547,18 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/routing' => array( 'symfony/routing' => array(
'pretty_version' => 'v6.4.2', 'pretty_version' => 'v6.4.32',
'version' => '6.4.2.0', 'version' => '6.4.32.0',
'reference' => '98eab13a07fddc85766f1756129c69f207ffbc21', 'reference' => '0dc6253e864e71b486e8ba4970a56ab849106ebe',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/routing', 'install_path' => __DIR__ . '/../symfony/routing',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/runtime' => array( 'symfony/runtime' => array(
'pretty_version' => 'v6.4.24', 'pretty_version' => 'v6.4.30',
'version' => '6.4.24.0', 'version' => '6.4.30.0',
'reference' => 'c1cc6721646f546627236c57f835272806087337', 'reference' => 'fb3149ee85d3b639dd3e49ea9dda05656f0537e3',
'type' => 'composer-plugin', 'type' => 'composer-plugin',
'install_path' => __DIR__ . '/../symfony/runtime', 'install_path' => __DIR__ . '/../symfony/runtime',
'aliases' => array(), 'aliases' => array(),
@@ -587,54 +580,54 @@
), ),
), ),
'symfony/stopwatch' => array( 'symfony/stopwatch' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.24',
'version' => '6.4.0.0', 'version' => '6.4.24.0',
'reference' => 'fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2', 'reference' => 'b67e94e06a05d9572c2fa354483b3e13e3cb1898',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/stopwatch', 'install_path' => __DIR__ . '/../symfony/stopwatch',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'symfony/string' => array( 'symfony/string' => array(
'pretty_version' => 'v6.4.2', 'pretty_version' => 'v6.4.30',
'version' => '6.4.2.0', 'version' => '6.4.30.0',
'reference' => '7cb80bc10bfcdf6b5492741c0b9357dac66940bc', 'reference' => '50590a057841fa6bf69d12eceffce3465b9e32cb',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/string', 'install_path' => __DIR__ . '/../symfony/string',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/translation-contracts' => array( 'symfony/translation-contracts' => array(
'pretty_version' => 'v3.4.0', 'pretty_version' => 'v3.6.1',
'version' => '3.4.0.0', 'version' => '3.6.1.0',
'reference' => 'dee0c6e5b4c07ce851b462530088e64b255ac9c5', 'reference' => '65a8bc82080447fae78373aa10f8d13b38338977',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation-contracts', 'install_path' => __DIR__ . '/../symfony/translation-contracts',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/twig-bridge' => array( 'symfony/twig-bridge' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.32',
'version' => '6.4.0.0', 'version' => '6.4.32.0',
'reference' => '142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf', 'reference' => '1dcf980dd4f79885b986befdeb1c1bc0d6aedfc8',
'type' => 'symfony-bridge', 'type' => 'symfony-bridge',
'install_path' => __DIR__ . '/../symfony/twig-bridge', 'install_path' => __DIR__ . '/../symfony/twig-bridge',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/twig-bundle' => array( 'symfony/twig-bundle' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.32',
'version' => '6.4.0.0', 'version' => '6.4.32.0',
'reference' => '35d84393e598dfb774e6a2bf49e5229a8a6dbe4c', 'reference' => 'a5c8dcc11a5bf9c96320da20070d2e158a4e0b30',
'type' => 'symfony-bundle', 'type' => 'symfony-bundle',
'install_path' => __DIR__ . '/../symfony/twig-bundle', 'install_path' => __DIR__ . '/../symfony/twig-bundle',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/var-dumper' => array( 'symfony/var-dumper' => array(
'pretty_version' => 'v6.4.2', 'pretty_version' => 'v6.4.32',
'version' => '6.4.2.0', 'version' => '6.4.32.0',
'reference' => '68d6573ec98715ddcae5a0a85bee3c1c27a4c33f', 'reference' => '131fc9915e0343052af5ed5040401b481ca192aa',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/var-dumper', 'install_path' => __DIR__ . '/../symfony/var-dumper',
'aliases' => array(), 'aliases' => array(),
@@ -650,45 +643,45 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/web-profiler-bundle' => array( 'symfony/web-profiler-bundle' => array(
'pretty_version' => 'v6.4.2', 'pretty_version' => 'v6.4.32',
'version' => '6.4.2.0', 'version' => '6.4.32.0',
'reference' => '38462d16856740ec0d1ba2cb902eebf09100dde2', 'reference' => '011f59e3f3d20f60d11b4e78b8dc63504f56e145',
'type' => 'symfony-bundle', 'type' => 'symfony-bundle',
'install_path' => __DIR__ . '/../symfony/web-profiler-bundle', 'install_path' => __DIR__ . '/../symfony/web-profiler-bundle',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'symfony/yaml' => array( 'symfony/yaml' => array(
'pretty_version' => 'v6.4.0', 'pretty_version' => 'v6.4.30',
'version' => '6.4.0.0', 'version' => '6.4.30.0',
'reference' => '4f9237a1bb42455d609e6687d2613dde5b41a587', 'reference' => '8207ae83da19ee3748d6d4f567b4d9a7c656e331',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/yaml', 'install_path' => __DIR__ . '/../symfony/yaml',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'tecnickcom/tcpdf' => array( 'tecnickcom/tcpdf' => array(
'pretty_version' => '6.10.0', 'pretty_version' => '6.10.1',
'version' => '6.10.0.0', 'version' => '6.10.1.0',
'reference' => 'ca5b6de294512145db96bcbc94e61696599c391d', 'reference' => '7a2701251e5d52fc3d508fd71704683eb54f5939',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../tecnickcom/tcpdf', 'install_path' => __DIR__ . '/../tecnickcom/tcpdf',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'thenetworg/oauth2-azure' => array( 'thenetworg/oauth2-azure' => array(
'pretty_version' => 'v2.2.2', 'pretty_version' => 'v2.2.4',
'version' => '2.2.2.0', 'version' => '2.2.4.0',
'reference' => 'be204a5135f016470a9c33e82ab48785bbc11af2', 'reference' => 'a897d60b6b127daa2f27b1b4e62e7af40829d02f',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../thenetworg/oauth2-azure', 'install_path' => __DIR__ . '/../thenetworg/oauth2-azure',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'twig/twig' => array( 'twig/twig' => array(
'pretty_version' => 'v3.21.1', 'pretty_version' => 'v3.23.0',
'version' => '3.21.1.0', 'version' => '3.23.0.0',
'reference' => '285123877d4dd97dd7c11842ac5fb7e86e60d81d', 'reference' => 'a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../twig/twig', 'install_path' => __DIR__ . '/../twig/twig',
'aliases' => array(), 'aliases' => array(),

View File

@@ -1,5 +1,64 @@
# Changelog # Changelog
## [7.0.2](https://github.com/firebase/php-jwt/compare/v7.0.1...v7.0.2) (2025-12-16)
### Bug Fixes
* add key length validation for ec keys ([#615](https://github.com/firebase/php-jwt/issues/615)) ([7044f9a](https://github.com/firebase/php-jwt/commit/7044f9ae7e7d175d28cca71714feb236f1c0e252))
## [7.0.0](https://github.com/firebase/php-jwt/compare/v6.11.1...v7.0.0) (2025-12-15)
### ⚠️ ⚠️ ⚠️ Security Fixes ⚠️ ⚠️ ⚠️
* add key size validation ([#613](https://github.com/firebase/php-jwt/issues/613)) ([6b80341](https://github.com/firebase/php-jwt/commit/6b80341bf57838ea2d011487917337901cd71576))
**NOTE**: This fix will cause keys with a size below the minimally allowed size to break.
### Features
* add SensitiveParameter attribute to security-critical parameters ([#603](https://github.com/firebase/php-jwt/issues/603)) ([4dbfac0](https://github.com/firebase/php-jwt/commit/4dbfac0260eeb0e9e643063c99998e3219cc539b))
* store timestamp in `ExpiredException` ([#604](https://github.com/firebase/php-jwt/issues/604)) ([f174826](https://github.com/firebase/php-jwt/commit/f1748260d218a856b6a0c23715ac7fae1d7ca95b))
### Bug Fixes
* validate iat and nbf on payload ([#568](https://github.com/firebase/php-jwt/issues/568)) ([953b2c8](https://github.com/firebase/php-jwt/commit/953b2c88bb445b7e3bb82a5141928f13d7343afd))
## [6.11.1](https://github.com/firebase/php-jwt/compare/v6.11.0...v6.11.1) (2025-04-09)
### Bug Fixes
* update error text for consistency ([#528](https://github.com/firebase/php-jwt/issues/528)) ([c11113a](https://github.com/firebase/php-jwt/commit/c11113afa13265e016a669e75494b9203b8a7775))
## [6.11.0](https://github.com/firebase/php-jwt/compare/v6.10.2...v6.11.0) (2025-01-23)
### Features
* support octet typed JWK ([#587](https://github.com/firebase/php-jwt/issues/587)) ([7cb8a26](https://github.com/firebase/php-jwt/commit/7cb8a265fa81edf2fa6ef8098f5bc5ae573c33ad))
### Bug Fixes
* refactor constructor Key to use PHP 8.0 syntax ([#577](https://github.com/firebase/php-jwt/issues/577)) ([29fa2ce](https://github.com/firebase/php-jwt/commit/29fa2ce9e0582cd397711eec1e80c05ce20fabca))
## [6.10.2](https://github.com/firebase/php-jwt/compare/v6.10.1...v6.10.2) (2024-11-24)
### Bug Fixes
* Mitigate PHP8.4 deprecation warnings ([#570](https://github.com/firebase/php-jwt/issues/570)) ([76808fa](https://github.com/firebase/php-jwt/commit/76808fa227f3811aa5cdb3bf81233714b799a5b5))
* support php 8.4 ([#583](https://github.com/firebase/php-jwt/issues/583)) ([e3d68b0](https://github.com/firebase/php-jwt/commit/e3d68b044421339443c74199edd020e03fb1887e))
## [6.10.1](https://github.com/firebase/php-jwt/compare/v6.10.0...v6.10.1) (2024-05-18)
### Bug Fixes
* ensure ratelimit expiry is set every time ([#556](https://github.com/firebase/php-jwt/issues/556)) ([09cb208](https://github.com/firebase/php-jwt/commit/09cb2081c2c3bc0f61e2f2a5fbea5741f7498648))
* ratelimit cache expiration ([#550](https://github.com/firebase/php-jwt/issues/550)) ([dda7250](https://github.com/firebase/php-jwt/commit/dda725033585ece30ff8cae8937320d7e9f18bae))
## [6.10.0](https://github.com/firebase/php-jwt/compare/v6.9.0...v6.10.0) (2023-11-28) ## [6.10.0](https://github.com/firebase/php-jwt/compare/v6.9.0...v6.10.0) (2023-11-28)

View File

@@ -17,7 +17,7 @@ composer require firebase/php-jwt
``` ```
Optionally, install the `paragonie/sodium_compat` package from composer if your Optionally, install the `paragonie/sodium_compat` package from composer if your
php is < 7.2 or does not have libsodium installed: php env does not have libsodium installed:
```bash ```bash
composer require paragonie/sodium_compat composer require paragonie/sodium_compat
@@ -48,7 +48,8 @@ $decoded = JWT::decode($jwt, new Key($key, 'HS256'));
print_r($decoded); print_r($decoded);
// Pass a stdClass in as the third parameter to get the decoded header values // Pass a stdClass in as the third parameter to get the decoded header values
$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers = new stdClass()); $headers = new stdClass();
$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers);
print_r($headers); print_r($headers);
/* /*
@@ -185,7 +186,7 @@ $passphrase = '[YOUR_PASSPHRASE]';
// Can be generated with "ssh-keygen -t rsa -m pem" // Can be generated with "ssh-keygen -t rsa -m pem"
$privateKeyFile = '/path/to/key-with-passphrase.pem'; $privateKeyFile = '/path/to/key-with-passphrase.pem';
// Create a private key of type "resource" /** @var OpenSSLAsymmetricKey $privateKey */
$privateKey = openssl_pkey_get_private( $privateKey = openssl_pkey_get_private(
file_get_contents($privateKeyFile), file_get_contents($privateKeyFile),
$passphrase $passphrase
@@ -290,7 +291,7 @@ $jwks = ['keys' => []];
// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key // JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
// objects. Pass this as the second parameter to JWT::decode. // objects. Pass this as the second parameter to JWT::decode.
JWT::decode($payload, JWK::parseKeySet($jwks)); JWT::decode($jwt, JWK::parseKeySet($jwks));
``` ```
Using Cached Key Sets Using Cached Key Sets
@@ -349,7 +350,7 @@ use InvalidArgumentException;
use UnexpectedValueException; use UnexpectedValueException;
try { try {
$decoded = JWT::decode($payload, $keys); $decoded = JWT::decode($jwt, $keys);
} catch (InvalidArgumentException $e) { } catch (InvalidArgumentException $e) {
// provided key/key-array is empty or malformed. // provided key/key-array is empty or malformed.
} catch (DomainException $e) { } catch (DomainException $e) {
@@ -379,7 +380,7 @@ like this:
use Firebase\JWT\JWT; use Firebase\JWT\JWT;
use UnexpectedValueException; use UnexpectedValueException;
try { try {
$decoded = JWT::decode($payload, $keys); $decoded = JWT::decode($jwt, $keys);
} catch (LogicException $e) { } catch (LogicException $e) {
// errors having to do with environmental setup or malformed JWT Keys // errors having to do with environmental setup or malformed JWT Keys
} catch (UnexpectedValueException $e) { } catch (UnexpectedValueException $e) {
@@ -394,7 +395,7 @@ instead, you can do the following:
```php ```php
// return type is stdClass // return type is stdClass
$decoded = JWT::decode($payload, $keys); $decoded = JWT::decode($jwt, $keys);
// cast to array // cast to array
$decoded = json_decode(json_encode($decoded), true); $decoded = json_decode(json_encode($decoded), true);

View File

@@ -20,7 +20,7 @@
], ],
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"require": { "require": {
"php": "^7.4||^8.0" "php": "^8.0"
}, },
"suggest": { "suggest": {
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present", "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
@@ -32,10 +32,10 @@
} }
}, },
"require-dev": { "require-dev": {
"guzzlehttp/guzzle": "^6.5||^7.4", "guzzlehttp/guzzle": "^7.4",
"phpspec/prophecy-phpunit": "^2.0", "phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.5",
"psr/cache": "^1.0||^2.0", "psr/cache": "^2.0||^3.0",
"psr/http-client": "^1.0", "psr/http-client": "^1.0",
"psr/http-factory": "^1.0" "psr/http-factory": "^1.0"
} }

View File

@@ -80,9 +80,9 @@ class CachedKeySet implements ArrayAccess
ClientInterface $httpClient, ClientInterface $httpClient,
RequestFactoryInterface $httpFactory, RequestFactoryInterface $httpFactory,
CacheItemPoolInterface $cache, CacheItemPoolInterface $cache,
int $expiresAfter = null, ?int $expiresAfter = null,
bool $rateLimit = false, bool $rateLimit = false,
string $defaultAlg = null ?string $defaultAlg = null
) { ) {
$this->jwksUri = $jwksUri; $this->jwksUri = $jwksUri;
$this->httpClient = $httpClient; $this->httpClient = $httpClient;
@@ -180,7 +180,7 @@ class CachedKeySet implements ArrayAccess
$jwksResponse = $this->httpClient->sendRequest($request); $jwksResponse = $this->httpClient->sendRequest($request);
if ($jwksResponse->getStatusCode() !== 200) { if ($jwksResponse->getStatusCode() !== 200) {
throw new UnexpectedValueException( throw new UnexpectedValueException(
sprintf('HTTP Error: %d %s for URI "%s"', \sprintf('HTTP Error: %d %s for URI "%s"',
$jwksResponse->getStatusCode(), $jwksResponse->getStatusCode(),
$jwksResponse->getReasonPhrase(), $jwksResponse->getReasonPhrase(),
$this->jwksUri, $this->jwksUri,
@@ -212,15 +212,21 @@ class CachedKeySet implements ArrayAccess
} }
$cacheItem = $this->cache->getItem($this->rateLimitCacheKey); $cacheItem = $this->cache->getItem($this->rateLimitCacheKey);
if (!$cacheItem->isHit()) {
$cacheItem->expiresAfter(1); // # of calls are cached each minute $cacheItemData = [];
if ($cacheItem->isHit() && \is_array($data = $cacheItem->get())) {
$cacheItemData = $data;
} }
$callsPerMinute = (int) $cacheItem->get(); $callsPerMinute = $cacheItemData['callsPerMinute'] ?? 0;
$expiry = $cacheItemData['expiry'] ?? new \DateTime('+60 seconds', new \DateTimeZone('UTC'));
if (++$callsPerMinute > $this->maxCallsPerMinute) { if (++$callsPerMinute > $this->maxCallsPerMinute) {
return true; return true;
} }
$cacheItem->set($callsPerMinute);
$cacheItem->set(['expiry' => $expiry, 'callsPerMinute' => $callsPerMinute]);
$cacheItem->expiresAt($expiry);
$this->cache->save($cacheItem); $this->cache->save($cacheItem);
return false; return false;
} }

View File

@@ -6,6 +6,8 @@ class ExpiredException extends \UnexpectedValueException implements JWTException
{ {
private object $payload; private object $payload;
private ?int $timestamp = null;
public function setPayload(object $payload): void public function setPayload(object $payload): void
{ {
$this->payload = $payload; $this->payload = $payload;
@@ -15,4 +17,14 @@ class ExpiredException extends \UnexpectedValueException implements JWTException
{ {
return $this->payload; return $this->payload;
} }
public function setTimestamp(int $timestamp): void
{
$this->timestamp = $timestamp;
}
public function getTimestamp(): ?int
{
return $this->timestamp;
}
} }

View File

@@ -52,7 +52,7 @@ class JWK
* *
* @uses parseKey * @uses parseKey
*/ */
public static function parseKeySet(array $jwks, string $defaultAlg = null): array public static function parseKeySet(#[\SensitiveParameter] array $jwks, ?string $defaultAlg = null): array
{ {
$keys = []; $keys = [];
@@ -93,7 +93,7 @@ class JWK
* *
* @uses createPemFromModulusAndExponent * @uses createPemFromModulusAndExponent
*/ */
public static function parseKey(array $jwk, string $defaultAlg = null): ?Key public static function parseKey(#[\SensitiveParameter] array $jwk, ?string $defaultAlg = null): ?Key
{ {
if (empty($jwk)) { if (empty($jwk)) {
throw new InvalidArgumentException('JWK must not be empty'); throw new InvalidArgumentException('JWK must not be empty');
@@ -172,6 +172,12 @@ class JWK
// This library works internally with EdDSA keys (Ed25519) encoded in standard base64. // This library works internally with EdDSA keys (Ed25519) encoded in standard base64.
$publicKey = JWT::convertBase64urlToBase64($jwk['x']); $publicKey = JWT::convertBase64urlToBase64($jwk['x']);
return new Key($publicKey, $jwk['alg']); return new Key($publicKey, $jwk['alg']);
case 'oct':
if (!isset($jwk['k'])) {
throw new UnexpectedValueException('k not set');
}
return new Key(JWT::urlsafeB64Decode($jwk['k']), $jwk['alg']);
default: default:
break; break;
} }
@@ -212,7 +218,7 @@ class JWK
) )
); );
return sprintf( return \sprintf(
"-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n", "-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n",
wordwrap(base64_encode($pem), 64, "\n", true) wordwrap(base64_encode($pem), 64, "\n", true)
); );

View File

@@ -31,6 +31,8 @@ class JWT
private const ASN1_SEQUENCE = 0x10; private const ASN1_SEQUENCE = 0x10;
private const ASN1_BIT_STRING = 0x03; private const ASN1_BIT_STRING = 0x03;
private const RSA_KEY_MIN_LENGTH=2048;
/** /**
* When checking nbf, iat or expiration times, * When checking nbf, iat or expiration times,
* we want to provide some extra leeway time to * we want to provide some extra leeway time to
@@ -95,8 +97,8 @@ class JWT
*/ */
public static function decode( public static function decode(
string $jwt, string $jwt,
$keyOrKeyArray, #[\SensitiveParameter] $keyOrKeyArray,
stdClass &$headers = null ?stdClass &$headers = null
): stdClass { ): stdClass {
// Validate JWT // Validate JWT
$timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp; $timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp;
@@ -127,6 +129,16 @@ class JWT
if (!$payload instanceof stdClass) { if (!$payload instanceof stdClass) {
throw new UnexpectedValueException('Payload must be a JSON object'); throw new UnexpectedValueException('Payload must be a JSON object');
} }
if (isset($payload->iat) && !\is_numeric($payload->iat)) {
throw new UnexpectedValueException('Payload iat must be a number');
}
if (isset($payload->nbf) && !\is_numeric($payload->nbf)) {
throw new UnexpectedValueException('Payload nbf must be a number');
}
if (isset($payload->exp) && !\is_numeric($payload->exp)) {
throw new UnexpectedValueException('Payload exp must be a number');
}
$sig = static::urlsafeB64Decode($cryptob64); $sig = static::urlsafeB64Decode($cryptob64);
if (empty($header->alg)) { if (empty($header->alg)) {
throw new UnexpectedValueException('Empty algorithm'); throw new UnexpectedValueException('Empty algorithm');
@@ -154,7 +166,7 @@ class JWT
// token can actually be used. If it's not yet that time, abort. // token can actually be used. If it's not yet that time, abort.
if (isset($payload->nbf) && floor($payload->nbf) > ($timestamp + static::$leeway)) { if (isset($payload->nbf) && floor($payload->nbf) > ($timestamp + static::$leeway)) {
$ex = new BeforeValidException( $ex = new BeforeValidException(
'Cannot handle token with nbf prior to ' . \date(DateTime::ISO8601, (int) $payload->nbf) 'Cannot handle token with nbf prior to ' . \date(DateTime::ATOM, (int) floor($payload->nbf))
); );
$ex->setPayload($payload); $ex->setPayload($payload);
throw $ex; throw $ex;
@@ -165,7 +177,7 @@ class JWT
// correctly used the nbf claim). // correctly used the nbf claim).
if (!isset($payload->nbf) && isset($payload->iat) && floor($payload->iat) > ($timestamp + static::$leeway)) { if (!isset($payload->nbf) && isset($payload->iat) && floor($payload->iat) > ($timestamp + static::$leeway)) {
$ex = new BeforeValidException( $ex = new BeforeValidException(
'Cannot handle token with iat prior to ' . \date(DateTime::ISO8601, (int) $payload->iat) 'Cannot handle token with iat prior to ' . \date(DateTime::ATOM, (int) floor($payload->iat))
); );
$ex->setPayload($payload); $ex->setPayload($payload);
throw $ex; throw $ex;
@@ -175,6 +187,7 @@ class JWT
if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) { if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) {
$ex = new ExpiredException('Expired token'); $ex = new ExpiredException('Expired token');
$ex->setPayload($payload); $ex->setPayload($payload);
$ex->setTimestamp($timestamp);
throw $ex; throw $ex;
} }
@@ -185,7 +198,7 @@ class JWT
* Converts and signs a PHP array into a JWT string. * Converts and signs a PHP array into a JWT string.
* *
* @param array<mixed> $payload PHP array * @param array<mixed> $payload PHP array
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key. * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
* @param string $alg Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256', * @param string $alg Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256',
* 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512' * 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
* @param string $keyId * @param string $keyId
@@ -198,13 +211,13 @@ class JWT
*/ */
public static function encode( public static function encode(
array $payload, array $payload,
$key, #[\SensitiveParameter] $key,
string $alg, string $alg,
string $keyId = null, ?string $keyId = null,
array $head = null ?array $head = null
): string { ): string {
$header = ['typ' => 'JWT']; $header = ['typ' => 'JWT'];
if (isset($head) && \is_array($head)) { if (isset($head)) {
$header = \array_merge($header, $head); $header = \array_merge($header, $head);
} }
$header['alg'] = $alg; $header['alg'] = $alg;
@@ -226,7 +239,7 @@ class JWT
* Sign a string with a given key and algorithm. * Sign a string with a given key and algorithm.
* *
* @param string $msg The message to sign * @param string $msg The message to sign
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key. * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
* @param string $alg Supported algorithms are 'EdDSA', 'ES384', 'ES256', 'ES256K', 'HS256', * @param string $alg Supported algorithms are 'EdDSA', 'ES384', 'ES256', 'ES256K', 'HS256',
* 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512' * 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
* *
@@ -236,7 +249,7 @@ class JWT
*/ */
public static function sign( public static function sign(
string $msg, string $msg,
$key, #[\SensitiveParameter] $key,
string $alg string $alg
): string { ): string {
if (empty(static::$supported_algs[$alg])) { if (empty(static::$supported_algs[$alg])) {
@@ -248,10 +261,19 @@ class JWT
if (!\is_string($key)) { if (!\is_string($key)) {
throw new InvalidArgumentException('key must be a string when using hmac'); throw new InvalidArgumentException('key must be a string when using hmac');
} }
self::validateHmacKeyLength($key, $algorithm);
return \hash_hmac($algorithm, $msg, $key, true); return \hash_hmac($algorithm, $msg, $key, true);
case 'openssl': case 'openssl':
$signature = ''; $signature = '';
$success = \openssl_sign($msg, $signature, $key, $algorithm); // @phpstan-ignore-line if (!$key = openssl_pkey_get_private($key)) {
throw new DomainException('OpenSSL unable to validate key');
}
if (str_starts_with($alg, 'RS')) {
self::validateRsaKeyLength($key);
} elseif (str_starts_with($alg, 'ES')) {
self::validateEcKeyLength($key, $alg);
}
$success = \openssl_sign($msg, $signature, $key, $algorithm);
if (!$success) { if (!$success) {
throw new DomainException('OpenSSL unable to sign data'); throw new DomainException('OpenSSL unable to sign data');
} }
@@ -290,7 +312,7 @@ class JWT
* *
* @param string $msg The original message (header and body) * @param string $msg The original message (header and body)
* @param string $signature The original signature * @param string $signature The original signature
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial For Ed*, ES*, HS*, a string key works. for RS*, must be an instance of OpenSSLAsymmetricKey * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial For Ed*, ES*, HS*, a string key works. for RS*, must be an instance of OpenSSLAsymmetricKey
* @param string $alg The algorithm * @param string $alg The algorithm
* *
* @return bool * @return bool
@@ -300,7 +322,7 @@ class JWT
private static function verify( private static function verify(
string $msg, string $msg,
string $signature, string $signature,
$keyMaterial, #[\SensitiveParameter] $keyMaterial,
string $alg string $alg
): bool { ): bool {
if (empty(static::$supported_algs[$alg])) { if (empty(static::$supported_algs[$alg])) {
@@ -310,7 +332,15 @@ class JWT
list($function, $algorithm) = static::$supported_algs[$alg]; list($function, $algorithm) = static::$supported_algs[$alg];
switch ($function) { switch ($function) {
case 'openssl': case 'openssl':
$success = \openssl_verify($msg, $signature, $keyMaterial, $algorithm); // @phpstan-ignore-line if (!$key = openssl_pkey_get_public($keyMaterial)) {
throw new DomainException('OpenSSL unable to validate key');
}
if (str_starts_with($alg, 'RS')) {
self::validateRsaKeyLength($key);
} elseif (str_starts_with($alg, 'ES')) {
self::validateEcKeyLength($key, $alg);
}
$success = \openssl_verify($msg, $signature, $keyMaterial, $algorithm);
if ($success === 1) { if ($success === 1) {
return true; return true;
} }
@@ -347,6 +377,7 @@ class JWT
if (!\is_string($keyMaterial)) { if (!\is_string($keyMaterial)) {
throw new InvalidArgumentException('key must be a string when using hmac'); throw new InvalidArgumentException('key must be a string when using hmac');
} }
self::validateHmacKeyLength($keyMaterial, $algorithm);
$hash = \hash_hmac($algorithm, $msg, $keyMaterial, true); $hash = \hash_hmac($algorithm, $msg, $keyMaterial, true);
return self::constantTimeEquals($hash, $signature); return self::constantTimeEquals($hash, $signature);
} }
@@ -384,12 +415,7 @@ class JWT
*/ */
public static function jsonEncode(array $input): string public static function jsonEncode(array $input): string
{ {
if (PHP_VERSION_ID >= 50400) { $json = \json_encode($input, \JSON_UNESCAPED_SLASHES);
$json = \json_encode($input, \JSON_UNESCAPED_SLASHES);
} else {
// PHP 5.3 only
$json = \json_encode($input);
}
if ($errno = \json_last_error()) { if ($errno = \json_last_error()) {
self::handleJsonError($errno); self::handleJsonError($errno);
} elseif ($json === 'null') { } elseif ($json === 'null') {
@@ -459,7 +485,7 @@ class JWT
* @return Key * @return Key
*/ */
private static function getKey( private static function getKey(
$keyOrKeyArray, #[\SensitiveParameter] $keyOrKeyArray,
?string $kid ?string $kid
): Key { ): Key {
if ($keyOrKeyArray instanceof Key) { if ($keyOrKeyArray instanceof Key) {
@@ -666,4 +692,57 @@ class JWT
return [$pos, $data]; return [$pos, $data];
} }
/**
* Validate HMAC key length
*
* @param string $key HMAC key material
* @param string $algorithm The algorithm
*
* @throws DomainException Provided key is too short
*/
private static function validateHmacKeyLength(string $key, string $algorithm): void
{
$keyLength = \strlen($key) * 8;
$minKeyLength = (int) \str_replace('SHA', '', $algorithm);
if ($keyLength < $minKeyLength) {
throw new DomainException('Provided key is too short');
}
}
/**
* Validate RSA key length
*
* @param OpenSSLAsymmetricKey $key RSA key material
* @throws DomainException Provided key is too short
*/
private static function validateRsaKeyLength(#[\SensitiveParameter] OpenSSLAsymmetricKey $key): void
{
if (!$keyDetails = openssl_pkey_get_details($key)) {
throw new DomainException('Unable to validate key');
}
if ($keyDetails['bits'] < self::RSA_KEY_MIN_LENGTH) {
throw new DomainException('Provided key is too short');
}
}
/**
* Validate RSA key length
*
* @param OpenSSLAsymmetricKey $key RSA key material
* @param string $algorithm The algorithm
* @throws DomainException Provided key is too short
*/
private static function validateEcKeyLength(
#[\SensitiveParameter] OpenSSLAsymmetricKey $key,
string $algorithm
): void {
if (!$keyDetails = openssl_pkey_get_details($key)) {
throw new DomainException('Unable to validate key');
}
$minKeyLength = (int) \str_replace('ES', '', $algorithm);
if ($keyDetails['bits'] < $minKeyLength) {
throw new DomainException('Provided key is too short');
}
}
} }

View File

@@ -9,26 +9,20 @@ use TypeError;
class Key class Key
{ {
/** @var string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate */
private $keyMaterial;
/** @var string */
private $algorithm;
/** /**
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial
* @param string $algorithm * @param string $algorithm
*/ */
public function __construct( public function __construct(
$keyMaterial, #[\SensitiveParameter] private $keyMaterial,
string $algorithm private string $algorithm
) { ) {
if ( if (
!\is_string($keyMaterial) !\is_string($keyMaterial)
&& !$keyMaterial instanceof OpenSSLAsymmetricKey && !$keyMaterial instanceof OpenSSLAsymmetricKey
&& !$keyMaterial instanceof OpenSSLCertificate && !$keyMaterial instanceof OpenSSLCertificate
&& !\is_resource($keyMaterial)
) { ) {
throw new TypeError('Key material must be a string, resource, or OpenSSLAsymmetricKey'); throw new TypeError('Key material must be a string, OpenSSLCertificate, or OpenSSLAsymmetricKey');
} }
if (empty($keyMaterial)) { if (empty($keyMaterial)) {
@@ -38,10 +32,6 @@ class Key
if (empty($algorithm)) { if (empty($algorithm)) {
throw new InvalidArgumentException('Algorithm must not be empty'); throw new InvalidArgumentException('Algorithm must not be empty');
} }
// TODO: Remove in PHP 8.0 in favor of class constructor property promotion
$this->keyMaterial = $keyMaterial;
$this->algorithm = $algorithm;
} }
/** /**
@@ -55,7 +45,7 @@ class Key
} }
/** /**
* @return string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate * @return string|OpenSSLAsymmetricKey|OpenSSLCertificate
*/ */
public function getKeyMaterial() public function getKeyMaterial()
{ {

View File

@@ -2,6 +2,56 @@
Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version. Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version.
## 7.10.0 - 2025-08-23
### Added
- Support for PHP 8.5
### Changed
- Adjusted `guzzlehttp/promises` version constraint to `^2.3`
- Adjusted `guzzlehttp/psr7` version constraint to `^2.8`
## 7.9.3 - 2025-03-27
### Changed
- Remove explicit content-length header for GET requests
- Improve compatibility with bad servers for boolean cookie values
## 7.9.2 - 2024-07-24
### Fixed
- Adjusted handler selection to use cURL if its version is 7.21.2 or higher, rather than 7.34.0
## 7.9.1 - 2024-07-19
### Fixed
- Fix TLS 1.3 check for HTTP/2 requests
## 7.9.0 - 2024-07-18
### Changed
- Improve protocol version checks to provide feedback around unsupported protocols
- Only select the cURL handler by default if 7.34.0 or higher is linked
- Improved `CurlMultiHandler` to avoid busy wait if possible
- Dropped support for EOL `guzzlehttp/psr7` v1
- Improved URI user info redaction in errors
## 7.8.2 - 2024-07-18
### Added
- Support for PHP 8.4
## 7.8.1 - 2023-12-03 ## 7.8.1 - 2023-12-03

View File

@@ -62,11 +62,11 @@ composer require guzzlehttp/guzzle
| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version | | Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version |
|---------|---------------------|---------------------|--------------|---------------------|---------------------|-------|--------------| |---------|---------------------|---------------------|--------------|---------------------|---------------------|-------|--------------|
| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 | | 3.x | EOL (2016-10-31) | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 |
| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 | | 4.x | EOL (2016-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 |
| 5.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 | | 5.x | EOL (2019-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 |
| 6.x | Security fixes only | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >=5.5,<8.0 | | 6.x | EOL (2023-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >=5.5,<8.0 |
| 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >=7.2.5,<8.4 | | 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >=7.2.5,<8.5 |
[guzzle-3-repo]: https://github.com/guzzle/guzzle3 [guzzle-3-repo]: https://github.com/guzzle/guzzle3
[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x [guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x

View File

@@ -50,11 +50,39 @@
"homepage": "https://github.com/Tobion" "homepage": "https://github.com/Tobion"
} }
], ],
"repositories": [
{
"type": "package",
"package": {
"name": "guzzle/client-integration-tests",
"version": "v3.0.2",
"dist": {
"url": "https://codeload.github.com/guzzle/client-integration-tests/zip/2c025848417c1135031fdf9c728ee53d0a7ceaee",
"type": "zip"
},
"require": {
"php": "^7.2.5 || ^8.0",
"phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.11",
"php-http/message": "^1.0 || ^2.0",
"guzzlehttp/psr7": "^1.7 || ^2.0",
"th3n3rd/cartesian-product": "^0.3"
},
"autoload": {
"psr-4": {
"Http\\Client\\Tests\\": "src/"
}
},
"bin": [
"bin/http_test_server"
]
}
}
],
"require": { "require": {
"php": "^7.2.5 || ^8.0", "php": "^7.2.5 || ^8.0",
"ext-json": "*", "ext-json": "*",
"guzzlehttp/promises": "^1.5.3 || ^2.0.1", "guzzlehttp/promises": "^2.3",
"guzzlehttp/psr7": "^1.9.1 || ^2.5.1", "guzzlehttp/psr7": "^2.8",
"psr/http-client": "^1.0", "psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0" "symfony/deprecation-contracts": "^2.2 || ^3.0"
}, },
@@ -64,9 +92,9 @@
"require-dev": { "require-dev": {
"ext-curl": "*", "ext-curl": "*",
"bamarni/composer-bin-plugin": "^1.8.2", "bamarni/composer-bin-plugin": "^1.8.2",
"php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", "guzzle/client-integration-tests": "3.0.2",
"php-http/message-factory": "^1.1", "php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.36 || ^9.6.15", "phpunit/phpunit": "^8.5.39 || ^9.6.20",
"psr/log": "^1.1 || ^2.0 || ^3.0" "psr/log": "^1.1 || ^2.0 || ^3.0"
}, },
"suggest": { "suggest": {

View File

@@ -11,7 +11,7 @@ final class BodySummarizer implements BodySummarizerInterface
*/ */
private $truncateAt; private $truncateAt;
public function __construct(int $truncateAt = null) public function __construct(?int $truncateAt = null)
{ {
$this->truncateAt = $truncateAt; $this->truncateAt = $truncateAt;
} }
@@ -22,7 +22,7 @@ final class BodySummarizer implements BodySummarizerInterface
public function summarize(MessageInterface $message): ?string public function summarize(MessageInterface $message): ?string
{ {
return $this->truncateAt === null return $this->truncateAt === null
? \GuzzleHttp\Psr7\Message::bodySummary($message) ? Psr7\Message::bodySummary($message)
: \GuzzleHttp\Psr7\Message::bodySummary($message, $this->truncateAt); : Psr7\Message::bodySummary($message, $this->truncateAt);
} }
} }

View File

@@ -52,7 +52,7 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
* *
* @param array $config Client configuration settings. * @param array $config Client configuration settings.
* *
* @see \GuzzleHttp\RequestOptions for a list of available request options. * @see RequestOptions for a list of available request options.
*/ */
public function __construct(array $config = []) public function __construct(array $config = [])
{ {
@@ -202,7 +202,7 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
* *
* @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0. * @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0.
*/ */
public function getConfig(string $option = null) public function getConfig(?string $option = null)
{ {
return $option === null return $option === null
? $this->config ? $this->config

View File

@@ -80,5 +80,5 @@ interface ClientInterface
* *
* @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0. * @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0.
*/ */
public function getConfig(string $option = null); public function getConfig(?string $option = null);
} }

View File

@@ -103,7 +103,7 @@ class CookieJar implements CookieJarInterface
}, $this->getIterator()->getArrayCopy()); }, $this->getIterator()->getArrayCopy());
} }
public function clear(string $domain = null, string $path = null, string $name = null): void public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void
{ {
if (!$domain) { if (!$domain) {
$this->cookies = []; $this->cookies = [];

View File

@@ -62,7 +62,7 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
* @param string|null $path Clears cookies matching a domain and path * @param string|null $path Clears cookies matching a domain and path
* @param string|null $name Clears cookies matching a domain, path, and name * @param string|null $name Clears cookies matching a domain, path, and name
*/ */
public function clear(string $domain = null, string $path = null, string $name = null): void; public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void;
/** /**
* Discard all sessions cookies. * Discard all sessions cookies.

View File

@@ -62,6 +62,10 @@ class SetCookie
if (is_numeric($value)) { if (is_numeric($value)) {
$data[$search] = (int) $value; $data[$search] = (int) $value;
} }
} elseif ($search === 'Secure' || $search === 'Discard' || $search === 'HttpOnly') {
if ($value) {
$data[$search] = true;
}
} else { } else {
$data[$search] = $value; $data[$search] = $value;
} }

View File

@@ -14,7 +14,7 @@ class BadResponseException extends RequestException
string $message, string $message,
RequestInterface $request, RequestInterface $request,
ResponseInterface $response, ResponseInterface $response,
\Throwable $previous = null, ?\Throwable $previous = null,
array $handlerContext = [] array $handlerContext = []
) { ) {
parent::__construct($message, $request, $response, $previous, $handlerContext); parent::__construct($message, $request, $response, $previous, $handlerContext);

View File

@@ -25,7 +25,7 @@ class ConnectException extends TransferException implements NetworkExceptionInte
public function __construct( public function __construct(
string $message, string $message,
RequestInterface $request, RequestInterface $request,
\Throwable $previous = null, ?\Throwable $previous = null,
array $handlerContext = [] array $handlerContext = []
) { ) {
parent::__construct($message, 0, $previous); parent::__construct($message, 0, $previous);

View File

@@ -7,7 +7,6 @@ use GuzzleHttp\BodySummarizerInterface;
use Psr\Http\Client\RequestExceptionInterface; use Psr\Http\Client\RequestExceptionInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
/** /**
* HTTP Request exception * HTTP Request exception
@@ -32,8 +31,8 @@ class RequestException extends TransferException implements RequestExceptionInte
public function __construct( public function __construct(
string $message, string $message,
RequestInterface $request, RequestInterface $request,
ResponseInterface $response = null, ?ResponseInterface $response = null,
\Throwable $previous = null, ?\Throwable $previous = null,
array $handlerContext = [] array $handlerContext = []
) { ) {
// Set the code of the exception if the response is set and not future. // Set the code of the exception if the response is set and not future.
@@ -63,10 +62,10 @@ class RequestException extends TransferException implements RequestExceptionInte
*/ */
public static function create( public static function create(
RequestInterface $request, RequestInterface $request,
ResponseInterface $response = null, ?ResponseInterface $response = null,
\Throwable $previous = null, ?\Throwable $previous = null,
array $handlerContext = [], array $handlerContext = [],
BodySummarizerInterface $bodySummarizer = null ?BodySummarizerInterface $bodySummarizer = null
): self { ): self {
if (!$response) { if (!$response) {
return new self( return new self(
@@ -90,8 +89,7 @@ class RequestException extends TransferException implements RequestExceptionInte
$className = __CLASS__; $className = __CLASS__;
} }
$uri = $request->getUri(); $uri = \GuzzleHttp\Psr7\Utils::redactUserInfo($request->getUri());
$uri = static::obfuscateUri($uri);
// Client Error: `GET /` resulted in a `404 Not Found` response: // Client Error: `GET /` resulted in a `404 Not Found` response:
// <html> ... (truncated) // <html> ... (truncated)
@@ -113,20 +111,6 @@ class RequestException extends TransferException implements RequestExceptionInte
return new $className($message, $request, $response, $previous, $handlerContext); return new $className($message, $request, $response, $previous, $handlerContext);
} }
/**
* Obfuscates URI if there is a username and a password present
*/
private static function obfuscateUri(UriInterface $uri): UriInterface
{
$userInfo = $uri->getUserInfo();
if (false !== ($pos = \strpos($userInfo, ':'))) {
return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***');
}
return $uri;
}
/** /**
* Get the request that caused the exception * Get the request that caused the exception
*/ */

View File

@@ -11,6 +11,7 @@ use GuzzleHttp\Psr7\LazyOpenStream;
use GuzzleHttp\TransferStats; use GuzzleHttp\TransferStats;
use GuzzleHttp\Utils; use GuzzleHttp\Utils;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\UriInterface;
/** /**
* Creates curl resources from a request * Creates curl resources from a request
@@ -46,6 +47,16 @@ class CurlFactory implements CurlFactoryInterface
public function create(RequestInterface $request, array $options): EasyHandle public function create(RequestInterface $request, array $options): EasyHandle
{ {
$protocolVersion = $request->getProtocolVersion();
if ('2' === $protocolVersion || '2.0' === $protocolVersion) {
if (!self::supportsHttp2()) {
throw new ConnectException('HTTP/2 is supported by the cURL handler, however libcurl is built without HTTP/2 support.', $request);
}
} elseif ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) {
throw new ConnectException(sprintf('HTTP/%s is not supported by the cURL handler.', $protocolVersion), $request);
}
if (isset($options['curl']['body_as_string'])) { if (isset($options['curl']['body_as_string'])) {
$options['_body_as_string'] = $options['curl']['body_as_string']; $options['_body_as_string'] = $options['curl']['body_as_string'];
unset($options['curl']['body_as_string']); unset($options['curl']['body_as_string']);
@@ -72,13 +83,51 @@ class CurlFactory implements CurlFactoryInterface
return $easy; return $easy;
} }
private static function supportsHttp2(): bool
{
static $supportsHttp2 = null;
if (null === $supportsHttp2) {
$supportsHttp2 = self::supportsTls12()
&& defined('CURL_VERSION_HTTP2')
&& (\CURL_VERSION_HTTP2 & \curl_version()['features']);
}
return $supportsHttp2;
}
private static function supportsTls12(): bool
{
static $supportsTls12 = null;
if (null === $supportsTls12) {
$supportsTls12 = \CURL_SSLVERSION_TLSv1_2 & \curl_version()['features'];
}
return $supportsTls12;
}
private static function supportsTls13(): bool
{
static $supportsTls13 = null;
if (null === $supportsTls13) {
$supportsTls13 = defined('CURL_SSLVERSION_TLSv1_3')
&& (\CURL_SSLVERSION_TLSv1_3 & \curl_version()['features']);
}
return $supportsTls13;
}
public function release(EasyHandle $easy): void public function release(EasyHandle $easy): void
{ {
$resource = $easy->handle; $resource = $easy->handle;
unset($easy->handle); unset($easy->handle);
if (\count($this->handles) >= $this->maxHandles) { if (\count($this->handles) >= $this->maxHandles) {
\curl_close($resource); if (PHP_VERSION_ID < 80000) {
\curl_close($resource);
}
} else { } else {
// Remove all callback functions as they can hold onto references // Remove all callback functions as they can hold onto references
// and are not cleaned up by curl_reset. Using curl_setopt_array // and are not cleaned up by curl_reset. Using curl_setopt_array
@@ -147,7 +196,7 @@ class CurlFactory implements CurlFactoryInterface
'error' => \curl_error($easy->handle), 'error' => \curl_error($easy->handle),
'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME), 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME),
] + \curl_getinfo($easy->handle); ] + \curl_getinfo($easy->handle);
$ctx[self::CURL_VERSION_STR] = \curl_version()['version']; $ctx[self::CURL_VERSION_STR] = self::getCurlVersion();
$factory->release($easy); $factory->release($easy);
// Retry when nothing is present or when curl failed to rewind. // Retry when nothing is present or when curl failed to rewind.
@@ -158,6 +207,17 @@ class CurlFactory implements CurlFactoryInterface
return self::createRejection($easy, $ctx); return self::createRejection($easy, $ctx);
} }
private static function getCurlVersion(): string
{
static $curlVersion = null;
if (null === $curlVersion) {
$curlVersion = \curl_version()['version'];
}
return $curlVersion;
}
private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface
{ {
static $connectionErrors = [ static $connectionErrors = [
@@ -194,15 +254,22 @@ class CurlFactory implements CurlFactoryInterface
); );
} }
$uri = $easy->request->getUri();
$sanitizedError = self::sanitizeCurlError($ctx['error'] ?? '', $uri);
$message = \sprintf( $message = \sprintf(
'cURL error %s: %s (%s)', 'cURL error %s: %s (%s)',
$ctx['errno'], $ctx['errno'],
$ctx['error'], $sanitizedError,
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html' 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
); );
$uriString = (string) $easy->request->getUri();
if ($uriString !== '' && false === \strpos($ctx['error'], $uriString)) { if ('' !== $sanitizedError) {
$message .= \sprintf(' for %s', $uriString); $redactedUriString = \GuzzleHttp\Psr7\Utils::redactUserInfo($uri)->__toString();
if ($redactedUriString !== '' && false === \strpos($sanitizedError, $redactedUriString)) {
$message .= \sprintf(' for %s', $redactedUriString);
}
} }
// Create a connection exception if it was a specific error code. // Create a connection exception if it was a specific error code.
@@ -213,6 +280,24 @@ class CurlFactory implements CurlFactoryInterface
return P\Create::rejectionFor($error); return P\Create::rejectionFor($error);
} }
private static function sanitizeCurlError(string $error, UriInterface $uri): string
{
if ('' === $error) {
return $error;
}
$baseUri = $uri->withQuery('')->withFragment('');
$baseUriString = $baseUri->__toString();
if ('' === $baseUriString) {
return $error;
}
$redactedUriString = \GuzzleHttp\Psr7\Utils::redactUserInfo($baseUri)->__toString();
return str_replace($baseUriString, $redactedUriString, $error);
}
/** /**
* @return array<int|string, mixed> * @return array<int|string, mixed>
*/ */
@@ -232,10 +317,11 @@ class CurlFactory implements CurlFactoryInterface
} }
$version = $easy->request->getProtocolVersion(); $version = $easy->request->getProtocolVersion();
if ($version == 1.1) {
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1; if ('2' === $version || '2.0' === $version) {
} elseif ($version == 2.0) {
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0; $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
} elseif ('1.1' === $version) {
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
} else { } else {
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0; $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
} }
@@ -390,8 +476,10 @@ class CurlFactory implements CurlFactoryInterface
// The empty string enables all available decoders and implicitly // The empty string enables all available decoders and implicitly
// sets a matching 'Accept-Encoding' header. // sets a matching 'Accept-Encoding' header.
$conf[\CURLOPT_ENCODING] = ''; $conf[\CURLOPT_ENCODING] = '';
// But as the user did not specify any acceptable encodings we need // But as the user did not specify any encoding preference,
// to overwrite this implicit header with an empty one. // let's leave it up to server by preventing curl from sending
// the header, which will be interpreted as 'Accept-Encoding: *'.
// https://www.rfc-editor.org/rfc/rfc9110#field.accept-encoding
$conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; $conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
} }
} }
@@ -455,23 +543,35 @@ class CurlFactory implements CurlFactoryInterface
} }
if (isset($options['crypto_method'])) { if (isset($options['crypto_method'])) {
if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) { $protocolVersion = $easy->request->getProtocolVersion();
if (!defined('CURL_SSLVERSION_TLSv1_0')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL'); // If HTTP/2, upgrade TLS 1.0 and 1.1 to 1.2
if ('2' === $protocolVersion || '2.0' === $protocolVersion) {
if (
\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']
|| \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']
|| \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']
) {
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
} elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
if (!self::supportsTls13()) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
} else {
throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
} }
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) {
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0; $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0;
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) { } elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) {
if (!defined('CURL_SSLVERSION_TLSv1_1')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1; $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1;
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) { } elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
if (!defined('CURL_SSLVERSION_TLSv1_2')) { if (!self::supportsTls12()) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL'); throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL');
} }
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2; $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
} elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) { } elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
if (!defined('CURL_SSLVERSION_TLSv1_3')) { if (!self::supportsTls13()) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL'); throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
} }
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3; $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
@@ -631,7 +731,10 @@ class CurlFactory implements CurlFactoryInterface
public function __destruct() public function __destruct()
{ {
foreach ($this->handles as $id => $handle) { foreach ($this->handles as $id => $handle) {
\curl_close($handle); if (PHP_VERSION_ID < 80000) {
\curl_close($handle);
}
unset($this->handles[$id]); unset($this->handles[$id]);
} }
} }

View File

@@ -2,6 +2,7 @@
namespace GuzzleHttp\Handler; namespace GuzzleHttp\Handler;
use Closure;
use GuzzleHttp\Promise as P; use GuzzleHttp\Promise as P;
use GuzzleHttp\Promise\Promise; use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Promise\PromiseInterface;
@@ -159,6 +160,9 @@ class CurlMultiHandler
} }
} }
// Run curl_multi_exec in the queue to enable other async tasks to run
P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue']));
// Step through the task queue which may add additional requests. // Step through the task queue which may add additional requests.
P\Utils::queue()->run(); P\Utils::queue()->run();
@@ -169,11 +173,24 @@ class CurlMultiHandler
} }
while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) { while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
// Prevent busy looping for slow HTTP requests.
\curl_multi_select($this->_mh, $this->selectTimeout);
} }
$this->processMessages(); $this->processMessages();
} }
/**
* Runs \curl_multi_exec() inside the event loop, to prevent busy looping
*/
private function tickInQueue(): void
{
if (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
\curl_multi_select($this->_mh, 0);
P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue']));
}
}
/** /**
* Runs until all outstanding connections have completed. * Runs until all outstanding connections have completed.
*/ */
@@ -223,7 +240,10 @@ class CurlMultiHandler
$handle = $this->handles[$id]['easy']->handle; $handle = $this->handles[$id]['easy']->handle;
unset($this->delays[$id], $this->handles[$id]); unset($this->delays[$id], $this->handles[$id]);
\curl_multi_remove_handle($this->_mh, $handle); \curl_multi_remove_handle($this->_mh, $handle);
\curl_close($handle);
if (PHP_VERSION_ID < 80000) {
\curl_close($handle);
}
return true; return true;
} }

View File

@@ -52,21 +52,21 @@ class MockHandler implements \Countable
* @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
* @param callable|null $onRejected Callback to invoke when the return value is rejected. * @param callable|null $onRejected Callback to invoke when the return value is rejected.
*/ */
public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null): HandlerStack public static function createWithMiddleware(?array $queue = null, ?callable $onFulfilled = null, ?callable $onRejected = null): HandlerStack
{ {
return HandlerStack::create(new self($queue, $onFulfilled, $onRejected)); return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
} }
/** /**
* The passed in value must be an array of * The passed in value must be an array of
* {@see \Psr\Http\Message\ResponseInterface} objects, Exceptions, * {@see ResponseInterface} objects, Exceptions,
* callables, or Promises. * callables, or Promises.
* *
* @param array<int, mixed>|null $queue The parameters to be passed to the append function, as an indexed array. * @param array<int, mixed>|null $queue The parameters to be passed to the append function, as an indexed array.
* @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
* @param callable|null $onRejected Callback to invoke when the return value is rejected. * @param callable|null $onRejected Callback to invoke when the return value is rejected.
*/ */
public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null) public function __construct(?array $queue = null, ?callable $onFulfilled = null, ?callable $onRejected = null)
{ {
$this->onFulfilled = $onFulfilled; $this->onFulfilled = $onFulfilled;
$this->onRejected = $onRejected; $this->onRejected = $onRejected;
@@ -200,7 +200,7 @@ class MockHandler implements \Countable
private function invokeStats( private function invokeStats(
RequestInterface $request, RequestInterface $request,
array $options, array $options,
ResponseInterface $response = null, ?ResponseInterface $response = null,
$reason = null $reason = null
): void { ): void {
if (isset($options['on_stats'])) { if (isset($options['on_stats'])) {

View File

@@ -17,10 +17,10 @@ class Proxy
* Sends synchronous requests to a specific handler while sending all other * Sends synchronous requests to a specific handler while sending all other
* requests to another handler. * requests to another handler.
* *
* @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for normal responses * @param callable(RequestInterface, array): PromiseInterface $default Handler used for normal responses
* @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $sync Handler used for synchronous responses. * @param callable(RequestInterface, array): PromiseInterface $sync Handler used for synchronous responses.
* *
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. * @return callable(RequestInterface, array): PromiseInterface Returns the composed handler.
*/ */
public static function wrapSync(callable $default, callable $sync): callable public static function wrapSync(callable $default, callable $sync): callable
{ {
@@ -37,10 +37,10 @@ class Proxy
* performance benefits of curl while still supporting true streaming * performance benefits of curl while still supporting true streaming
* through the StreamHandler. * through the StreamHandler.
* *
* @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for non-streaming responses * @param callable(RequestInterface, array): PromiseInterface $default Handler used for non-streaming responses
* @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $streaming Handler used for streaming responses * @param callable(RequestInterface, array): PromiseInterface $streaming Handler used for streaming responses
* *
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. * @return callable(RequestInterface, array): PromiseInterface Returns the composed handler.
*/ */
public static function wrapStreaming(callable $default, callable $streaming): callable public static function wrapStreaming(callable $default, callable $streaming): callable
{ {

View File

@@ -40,6 +40,12 @@ class StreamHandler
\usleep($options['delay'] * 1000); \usleep($options['delay'] * 1000);
} }
$protocolVersion = $request->getProtocolVersion();
if ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) {
throw new ConnectException(sprintf('HTTP/%s is not supported by the stream handler.', $protocolVersion), $request);
}
$startTime = isset($options['on_stats']) ? Utils::currentTime() : null; $startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
try { try {
@@ -47,8 +53,14 @@ class StreamHandler
$request = $request->withoutHeader('Expect'); $request = $request->withoutHeader('Expect');
// Append a content-length header if body size is zero to match // Append a content-length header if body size is zero to match
// cURL's behavior. // the behavior of `CurlHandler`
if (0 === $request->getBody()->getSize()) { if (
(
0 === \strcasecmp('PUT', $request->getMethod())
|| 0 === \strcasecmp('POST', $request->getMethod())
)
&& 0 === $request->getBody()->getSize()
) {
$request = $request->withHeader('Content-Length', '0'); $request = $request->withHeader('Content-Length', '0');
} }
@@ -83,8 +95,8 @@ class StreamHandler
array $options, array $options,
RequestInterface $request, RequestInterface $request,
?float $startTime, ?float $startTime,
ResponseInterface $response = null, ?ResponseInterface $response = null,
\Throwable $error = null ?\Throwable $error = null
): void { ): void {
if (isset($options['on_stats'])) { if (isset($options['on_stats'])) {
$stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []); $stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []);
@@ -273,7 +285,7 @@ class StreamHandler
// HTTP/1.1 streams using the PHP stream wrapper require a // HTTP/1.1 streams using the PHP stream wrapper require a
// Connection: close header // Connection: close header
if ($request->getProtocolVersion() == '1.1' if ($request->getProtocolVersion() === '1.1'
&& !$request->hasHeader('Connection') && !$request->hasHeader('Connection')
) { ) {
$request = $request->withHeader('Connection', 'close'); $request = $request->withHeader('Connection', 'close');
@@ -321,8 +333,15 @@ class StreamHandler
); );
return $this->createResource( return $this->createResource(
function () use ($uri, &$http_response_header, $contextResource, $context, $options, $request) { function () use ($uri, $contextResource, $context, $options, $request) {
$resource = @\fopen((string) $uri, 'r', false, $contextResource); $resource = @\fopen((string) $uri, 'r', false, $contextResource);
// See https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_http_response_header_predefined_variable
if (function_exists('http_get_last_response_headers')) {
/** @var array|null */
$http_response_header = \http_get_last_response_headers();
}
$this->lastHeaders = $http_response_header ?? []; $this->lastHeaders = $http_response_header ?? [];
if (false === $resource) { if (false === $resource) {

View File

@@ -44,7 +44,7 @@ class HandlerStack
* handler is provided, the best handler for your * handler is provided, the best handler for your
* system will be utilized. * system will be utilized.
*/ */
public static function create(callable $handler = null): self public static function create(?callable $handler = null): self
{ {
$stack = new self($handler ?: Utils::chooseHandler()); $stack = new self($handler ?: Utils::chooseHandler());
$stack->push(Middleware::httpErrors(), 'http_errors'); $stack->push(Middleware::httpErrors(), 'http_errors');
@@ -58,7 +58,7 @@ class HandlerStack
/** /**
* @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler. * @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler.
*/ */
public function __construct(callable $handler = null) public function __construct(?callable $handler = null)
{ {
$this->handler = $handler; $this->handler = $handler;
} }
@@ -131,7 +131,7 @@ class HandlerStack
* @param callable(callable): callable $middleware Middleware function * @param callable(callable): callable $middleware Middleware function
* @param string $name Name to register for this middleware. * @param string $name Name to register for this middleware.
*/ */
public function unshift(callable $middleware, string $name = null): void public function unshift(callable $middleware, ?string $name = null): void
{ {
\array_unshift($this->stack, [$middleware, $name]); \array_unshift($this->stack, [$middleware, $name]);
$this->cached = null; $this->cached = null;

View File

@@ -68,7 +68,7 @@ class MessageFormatter implements MessageFormatterInterface
* @param ResponseInterface|null $response Response that was received * @param ResponseInterface|null $response Response that was received
* @param \Throwable|null $error Exception that was received * @param \Throwable|null $error Exception that was received
*/ */
public function format(RequestInterface $request, ResponseInterface $response = null, \Throwable $error = null): string public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string
{ {
$cache = []; $cache = [];

View File

@@ -14,5 +14,5 @@ interface MessageFormatterInterface
* @param ResponseInterface|null $response Response that was received * @param ResponseInterface|null $response Response that was received
* @param \Throwable|null $error Exception that was received * @param \Throwable|null $error Exception that was received
*/ */
public function format(RequestInterface $request, ResponseInterface $response = null, \Throwable $error = null): string; public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string;
} }

View File

@@ -55,7 +55,7 @@ final class Middleware
* *
* @return callable(callable): callable Returns a function that accepts the next handler. * @return callable(callable): callable Returns a function that accepts the next handler.
*/ */
public static function httpErrors(BodySummarizerInterface $bodySummarizer = null): callable public static function httpErrors(?BodySummarizerInterface $bodySummarizer = null): callable
{ {
return static function (callable $handler) use ($bodySummarizer): callable { return static function (callable $handler) use ($bodySummarizer): callable {
return static function ($request, array $options) use ($handler, $bodySummarizer) { return static function ($request, array $options) use ($handler, $bodySummarizer) {
@@ -132,7 +132,7 @@ final class Middleware
* *
* @return callable Returns a function that accepts the next handler. * @return callable Returns a function that accepts the next handler.
*/ */
public static function tap(callable $before = null, callable $after = null): callable public static function tap(?callable $before = null, ?callable $after = null): callable
{ {
return static function (callable $handler) use ($before, $after): callable { return static function (callable $handler) use ($before, $after): callable {
return static function (RequestInterface $request, array $options) use ($handler, $before, $after) { return static function (RequestInterface $request, array $options) use ($handler, $before, $after) {
@@ -176,7 +176,7 @@ final class Middleware
* *
* @return callable Returns a function that accepts the next handler. * @return callable Returns a function that accepts the next handler.
*/ */
public static function retry(callable $decider, callable $delay = null): callable public static function retry(callable $decider, ?callable $delay = null): callable
{ {
return static function (callable $handler) use ($decider, $delay): RetryMiddleware { return static function (callable $handler) use ($decider, $delay): RetryMiddleware {
return new RetryMiddleware($decider, $handler, $delay); return new RetryMiddleware($decider, $handler, $delay);
@@ -187,12 +187,12 @@ final class Middleware
* Middleware that logs requests, responses, and errors using a message * Middleware that logs requests, responses, and errors using a message
* formatter. * formatter.
* *
* @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests.
*
* @param LoggerInterface $logger Logs messages. * @param LoggerInterface $logger Logs messages.
* @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings. * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings.
* @param string $logLevel Level at which to log requests. * @param string $logLevel Level at which to log requests.
* *
* @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests.
*
* @return callable Returns a function that accepts the next handler. * @return callable Returns a function that accepts the next handler.
*/ */
public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info'): callable public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info'): callable

View File

@@ -86,7 +86,7 @@ class Pool implements PromisorInterface
* @param ClientInterface $client Client used to send the requests * @param ClientInterface $client Client used to send the requests
* @param array|\Iterator $requests Requests to send concurrently. * @param array|\Iterator $requests Requests to send concurrently.
* @param array $options Passes through the options available in * @param array $options Passes through the options available in
* {@see \GuzzleHttp\Pool::__construct} * {@see Pool::__construct}
* *
* @return array Returns an array containing the response or an exception * @return array Returns an array containing the response or an exception
* in the same order that the requests were sent. * in the same order that the requests were sent.

View File

@@ -76,8 +76,8 @@ class PrepareBodyMiddleware
$expect = $options['expect'] ?? null; $expect = $options['expect'] ?? null;
// Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0 // Return if disabled or using HTTP/1.0
if ($expect === false || $request->getProtocolVersion() < 1.1) { if ($expect === false || $request->getProtocolVersion() === '1.0') {
return; return;
} }

View File

@@ -61,7 +61,7 @@ final class RequestOptions
* Specifies whether or not cookies are used in a request or what cookie * Specifies whether or not cookies are used in a request or what cookie
* jar to use or what cookies to send. This option only works if your * jar to use or what cookies to send. This option only works if your
* handler has the `cookie` middleware. Valid values are `false` and * handler has the `cookie` middleware. Valid values are `false` and
* an instance of {@see \GuzzleHttp\Cookie\CookieJarInterface}. * an instance of {@see Cookie\CookieJarInterface}.
*/ */
public const COOKIES = 'cookies'; public const COOKIES = 'cookies';

View File

@@ -40,7 +40,7 @@ class RetryMiddleware
* and returns the number of * and returns the number of
* milliseconds to delay. * milliseconds to delay.
*/ */
public function __construct(callable $decider, callable $nextHandler, callable $delay = null) public function __construct(callable $decider, callable $nextHandler, ?callable $delay = null)
{ {
$this->decider = $decider; $this->decider = $decider;
$this->nextHandler = $nextHandler; $this->nextHandler = $nextHandler;
@@ -110,7 +110,7 @@ class RetryMiddleware
}; };
} }
private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null): PromiseInterface private function doRetry(RequestInterface $request, array $options, ?ResponseInterface $response = null): PromiseInterface
{ {
$options['delay'] = ($this->delay)(++$options['retries'], $response, $request); $options['delay'] = ($this->delay)(++$options['retries'], $response, $request);

View File

@@ -46,8 +46,8 @@ final class TransferStats
*/ */
public function __construct( public function __construct(
RequestInterface $request, RequestInterface $request,
ResponseInterface $response = null, ?ResponseInterface $response = null,
float $transferTime = null, ?float $transferTime = null,
$handlerErrorData = null, $handlerErrorData = null,
array $handlerStats = [] array $handlerStats = []
) { ) {

View File

@@ -71,7 +71,7 @@ final class Utils
return \STDOUT; return \STDOUT;
} }
return \GuzzleHttp\Psr7\Utils::tryFopen('php://output', 'w'); return Psr7\Utils::tryFopen('php://output', 'w');
} }
/** /**
@@ -79,7 +79,7 @@ final class Utils
* *
* The returned handler is not wrapped by any default middlewares. * The returned handler is not wrapped by any default middlewares.
* *
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system. * @return callable(\Psr\Http\Message\RequestInterface, array): Promise\PromiseInterface Returns the best handler for the given system.
* *
* @throws \RuntimeException if no viable Handler is available. * @throws \RuntimeException if no viable Handler is available.
*/ */
@@ -87,7 +87,7 @@ final class Utils
{ {
$handler = null; $handler = null;
if (\defined('CURLOPT_CUSTOMREQUEST')) { if (\defined('CURLOPT_CUSTOMREQUEST') && \function_exists('curl_version') && version_compare(curl_version()['version'], '7.21.2') >= 0) {
if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) { if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) {
$handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler()); $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
} elseif (\function_exists('curl_exec')) { } elseif (\function_exists('curl_exec')) {

View File

@@ -50,7 +50,7 @@ function debug_resource($value = null)
* *
* The returned handler is not wrapped by any default middlewares. * The returned handler is not wrapped by any default middlewares.
* *
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system. * @return callable(\Psr\Http\Message\RequestInterface, array): Promise\PromiseInterface Returns the best handler for the given system.
* *
* @throws \RuntimeException if no viable Handler is available. * @throws \RuntimeException if no viable Handler is available.
* *

View File

@@ -1,6 +1,41 @@
# CHANGELOG # CHANGELOG
## 2.3.0 - 2025-08-22
### Added
- PHP 8.5 support
## 2.2.0 - 2025-03-27
### Fixed
- Revert "Allow an empty EachPromise to be resolved by running the queue"
## 2.1.0 - 2025-03-27
### Added
- Allow an empty EachPromise to be resolved by running the queue
## 2.0.4 - 2024-10-17
### Fixed
- Once settled, don't allow further rejection of additional promises
## 2.0.3 - 2024-07-18
### Changed
- PHP 8.4 support
## 2.0.2 - 2023-12-03 ## 2.0.2 - 2023-12-03
### Changed ### Changed

View File

@@ -38,10 +38,10 @@ composer require guzzlehttp/promises
## Version Guidance ## Version Guidance
| Version | Status | PHP Version | | Version | Status | PHP Version |
|---------|------------------------|--------------| |---------|---------------------|--------------|
| 1.x | Bug and security fixes | >=5.5,<8.3 | | 1.x | Security fixes only | >=5.5,<8.3 |
| 2.x | Latest | >=7.2.5,<8.4 | | 2.x | Latest | >=7.2.5,<8.6 |
## Quick Start ## Quick Start

View File

@@ -30,7 +30,7 @@
}, },
"require-dev": { "require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2", "bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.36 || ^9.6.15" "phpunit/phpunit": "^8.5.44 || ^9.6.25"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@@ -84,8 +84,8 @@ final class Coroutine implements PromiseInterface
} }
public function then( public function then(
callable $onFulfilled = null, ?callable $onFulfilled = null,
callable $onRejected = null ?callable $onRejected = null
): PromiseInterface { ): PromiseInterface {
return $this->result->then($onFulfilled, $onRejected); return $this->result->then($onFulfilled, $onRejected);
} }

View File

@@ -23,8 +23,8 @@ final class Each
*/ */
public static function of( public static function of(
$iterable, $iterable,
callable $onFulfilled = null, ?callable $onFulfilled = null,
callable $onRejected = null ?callable $onRejected = null
): PromiseInterface { ): PromiseInterface {
return (new EachPromise($iterable, [ return (new EachPromise($iterable, [
'fulfilled' => $onFulfilled, 'fulfilled' => $onFulfilled,
@@ -46,8 +46,8 @@ final class Each
public static function ofLimit( public static function ofLimit(
$iterable, $iterable,
$concurrency, $concurrency,
callable $onFulfilled = null, ?callable $onFulfilled = null,
callable $onRejected = null ?callable $onRejected = null
): PromiseInterface { ): PromiseInterface {
return (new EachPromise($iterable, [ return (new EachPromise($iterable, [
'fulfilled' => $onFulfilled, 'fulfilled' => $onFulfilled,
@@ -67,7 +67,7 @@ final class Each
public static function ofLimitAll( public static function ofLimitAll(
$iterable, $iterable,
$concurrency, $concurrency,
callable $onFulfilled = null ?callable $onFulfilled = null
): PromiseInterface { ): PromiseInterface {
return self::ofLimit( return self::ofLimit(
$iterable, $iterable,

View File

@@ -31,8 +31,8 @@ class FulfilledPromise implements PromiseInterface
} }
public function then( public function then(
callable $onFulfilled = null, ?callable $onFulfilled = null,
callable $onRejected = null ?callable $onRejected = null
): PromiseInterface { ): PromiseInterface {
// Return itself if there is no onFulfilled function. // Return itself if there is no onFulfilled function.
if (!$onFulfilled) { if (!$onFulfilled) {

View File

@@ -25,16 +25,16 @@ class Promise implements PromiseInterface
* @param callable $cancelFn Fn that when invoked cancels the promise. * @param callable $cancelFn Fn that when invoked cancels the promise.
*/ */
public function __construct( public function __construct(
callable $waitFn = null, ?callable $waitFn = null,
callable $cancelFn = null ?callable $cancelFn = null
) { ) {
$this->waitFn = $waitFn; $this->waitFn = $waitFn;
$this->cancelFn = $cancelFn; $this->cancelFn = $cancelFn;
} }
public function then( public function then(
callable $onFulfilled = null, ?callable $onFulfilled = null,
callable $onRejected = null ?callable $onRejected = null
): PromiseInterface { ): PromiseInterface {
if ($this->state === self::PENDING) { if ($this->state === self::PENDING) {
$p = new Promise(null, [$this, 'cancel']); $p = new Promise(null, [$this, 'cancel']);

View File

@@ -27,8 +27,8 @@ interface PromiseInterface
* @param callable $onRejected Invoked when the promise is rejected. * @param callable $onRejected Invoked when the promise is rejected.
*/ */
public function then( public function then(
callable $onFulfilled = null, ?callable $onFulfilled = null,
callable $onRejected = null ?callable $onRejected = null
): PromiseInterface; ): PromiseInterface;
/** /**

View File

@@ -31,8 +31,8 @@ class RejectedPromise implements PromiseInterface
} }
public function then( public function then(
callable $onFulfilled = null, ?callable $onFulfilled = null,
callable $onRejected = null ?callable $onRejected = null
): PromiseInterface { ): PromiseInterface {
// If there's no onRejected callback then just return self. // If there's no onRejected callback then just return self.
if (!$onRejected) { if (!$onRejected) {

View File

@@ -18,7 +18,7 @@ class RejectionException extends \RuntimeException
* @param mixed $reason Rejection reason. * @param mixed $reason Rejection reason.
* @param string|null $description Optional description. * @param string|null $description Optional description.
*/ */
public function __construct($reason, string $description = null) public function __construct($reason, ?string $description = null)
{ {
$this->reason = $reason; $this->reason = $reason;

View File

@@ -21,7 +21,7 @@ final class Utils
* *
* @param TaskQueueInterface|null $assign Optionally specify a new queue instance. * @param TaskQueueInterface|null $assign Optionally specify a new queue instance.
*/ */
public static function queue(TaskQueueInterface $assign = null): TaskQueueInterface public static function queue(?TaskQueueInterface $assign = null): TaskQueueInterface
{ {
static $queue; static $queue;
@@ -144,7 +144,9 @@ final class Utils
$results[$idx] = $value; $results[$idx] = $value;
}, },
function ($reason, $idx, Promise $aggregate): void { function ($reason, $idx, Promise $aggregate): void {
$aggregate->reject($reason); if (Is::pending($aggregate)) {
$aggregate->reject($reason);
}
} }
)->then(function () use (&$results) { )->then(function () use (&$results) {
ksort($results); ksort($results);

View File

@@ -5,6 +5,43 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 2.8.0 - 2025-08-23
### Added
- Allow empty lists as header values
### Changed
- PHP 8.5 support
## 2.7.1 - 2025-03-27
### Fixed
- Fixed uppercase IPv6 addresses in URI
### Changed
- Improve uploaded file error message
## 2.7.0 - 2024-07-18
### Added
- Add `Utils::redactUserInfo()` method
- Add ability to encode bools as ints in `Query::build`
## 2.6.3 - 2024-07-18
### Fixed
- Make `StreamWrapper::stream_stat()` return `false` if inner stream's size is `null`
### Changed
- PHP 8.4 support
## 2.6.2 - 2023-12-03 ## 2.6.2 - 2023-12-03
### Fixed ### Fixed

View File

@@ -24,8 +24,8 @@ composer require guzzlehttp/psr7
| Version | Status | PHP Version | | Version | Status | PHP Version |
|---------|---------------------|--------------| |---------|---------------------|--------------|
| 1.x | Security fixes only | >=5.4,<8.1 | | 1.x | EOL (2024-06-30) | >=5.4,<8.2 |
| 2.x | Latest | >=7.2.5,<8.4 | | 2.x | Latest | >=7.2.5,<8.6 |
## AppendStream ## AppendStream
@@ -436,7 +436,7 @@ will be parsed into `['foo[a]' => '1', 'foo[b]' => '2'])`.
## `GuzzleHttp\Psr7\Query::build` ## `GuzzleHttp\Psr7\Query::build`
`public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986): string` `public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986, bool $treatBoolsAsInts = true): string`
Build a query string from an array of key value pairs. Build a query string from an array of key value pairs.
@@ -498,11 +498,18 @@ a message.
## `GuzzleHttp\Psr7\Utils::readLine` ## `GuzzleHttp\Psr7\Utils::readLine`
`public static function readLine(StreamInterface $stream, int $maxLength = null): string` `public static function readLine(StreamInterface $stream, ?int $maxLength = null): string`
Read a line from the stream up to the maximum allowed buffer length. Read a line from the stream up to the maximum allowed buffer length.
## `GuzzleHttp\Psr7\Utils::redactUserInfo`
`public static function redactUserInfo(UriInterface $uri): UriInterface`
Redact the password in the user info part of a URI.
## `GuzzleHttp\Psr7\Utils::streamFor` ## `GuzzleHttp\Psr7\Utils::streamFor`
`public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource = '', array $options = []): StreamInterface` `public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource = '', array $options = []): StreamInterface`
@@ -674,7 +681,7 @@ termed a relative-path reference.
### `GuzzleHttp\Psr7\Uri::isSameDocumentReference` ### `GuzzleHttp\Psr7\Uri::isSameDocumentReference`
`public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool` `public static function isSameDocumentReference(UriInterface $uri, ?UriInterface $base = null): bool`
Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its
fragment component, identical to the base URI. When no base URI is given, only an empty URI reference fragment component, identical to the base URI. When no base URI is given, only an empty URI reference

View File

@@ -61,8 +61,8 @@
}, },
"require-dev": { "require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2", "bamarni/composer-bin-plugin": "^1.8.2",
"http-interop/http-factory-tests": "^0.9", "http-interop/http-factory-tests": "0.9.0",
"phpunit/phpunit": "^8.5.36 || ^9.6.15" "phpunit/phpunit": "^8.5.44 || ^9.6.25"
}, },
"suggest": { "suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"

View File

@@ -33,7 +33,7 @@ final class CachingStream implements StreamInterface
*/ */
public function __construct( public function __construct(
StreamInterface $stream, StreamInterface $stream,
StreamInterface $target = null ?StreamInterface $target = null
) { ) {
$this->remoteStream = $stream; $this->remoteStream = $stream;
$this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+')); $this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+'));

View File

@@ -27,10 +27,10 @@ final class HttpFactory implements RequestFactoryInterface, ResponseFactoryInter
{ {
public function createUploadedFile( public function createUploadedFile(
StreamInterface $stream, StreamInterface $stream,
int $size = null, ?int $size = null,
int $error = \UPLOAD_ERR_OK, int $error = \UPLOAD_ERR_OK,
string $clientFilename = null, ?string $clientFilename = null,
string $clientMediaType = null ?string $clientMediaType = null
): UploadedFileInterface { ): UploadedFileInterface {
if ($size === null) { if ($size === null) {
$size = $stream->getSize(); $size = $stream->getSize();

View File

@@ -174,10 +174,6 @@ trait MessageTrait
return $this->trimAndValidateHeaderValues([$value]); return $this->trimAndValidateHeaderValues([$value]);
} }
if (count($value) === 0) {
throw new \InvalidArgumentException('Header value can not be an empty array.');
}
return $this->trimAndValidateHeaderValues($value); return $this->trimAndValidateHeaderValues($value);
} }

View File

@@ -32,7 +32,7 @@ final class MultipartStream implements StreamInterface
* *
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public function __construct(array $elements = [], string $boundary = null) public function __construct(array $elements = [], ?string $boundary = null)
{ {
$this->boundary = $boundary ?: bin2hex(random_bytes(20)); $this->boundary = $boundary ?: bin2hex(random_bytes(20));
$this->stream = $this->createStream($elements); $this->stream = $this->createStream($elements);

View File

@@ -63,12 +63,15 @@ final class Query
* string. This function does not modify the provided keys when an array is * string. This function does not modify the provided keys when an array is
* encountered (like `http_build_query()` would). * encountered (like `http_build_query()` would).
* *
* @param array $params Query string parameters. * @param array $params Query string parameters.
* @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986 * @param int|false $encoding Set to false to not encode,
* to encode using RFC3986, or PHP_QUERY_RFC1738 * PHP_QUERY_RFC3986 to encode using
* to encode using RFC1738. * RFC3986, or PHP_QUERY_RFC1738 to
* encode using RFC1738.
* @param bool $treatBoolsAsInts Set to true to encode as 0/1, and
* false as false/true.
*/ */
public static function build(array $params, $encoding = PHP_QUERY_RFC3986): string public static function build(array $params, $encoding = PHP_QUERY_RFC3986, bool $treatBoolsAsInts = true): string
{ {
if (!$params) { if (!$params) {
return ''; return '';
@@ -86,12 +89,14 @@ final class Query
throw new \InvalidArgumentException('Invalid type'); throw new \InvalidArgumentException('Invalid type');
} }
$castBool = $treatBoolsAsInts ? static function ($v) { return (int) $v; } : static function ($v) { return $v ? 'true' : 'false'; };
$qs = ''; $qs = '';
foreach ($params as $k => $v) { foreach ($params as $k => $v) {
$k = $encoder((string) $k); $k = $encoder((string) $k);
if (!is_array($v)) { if (!is_array($v)) {
$qs .= $k; $qs .= $k;
$v = is_bool($v) ? (int) $v : $v; $v = is_bool($v) ? $castBool($v) : $v;
if ($v !== null) { if ($v !== null) {
$qs .= '='.$encoder((string) $v); $qs .= '='.$encoder((string) $v);
} }
@@ -99,7 +104,7 @@ final class Query
} else { } else {
foreach ($v as $vv) { foreach ($v as $vv) {
$qs .= $k; $qs .= $k;
$vv = is_bool($vv) ? (int) $vv : $vv; $vv = is_bool($vv) ? $castBool($vv) : $vv;
if ($vv !== null) { if ($vv !== null) {
$qs .= '='.$encoder((string) $vv); $qs .= '='.$encoder((string) $vv);
} }

View File

@@ -96,7 +96,7 @@ class Response implements ResponseInterface
array $headers = [], array $headers = [],
$body = null, $body = null,
string $version = '1.1', string $version = '1.1',
string $reason = null ?string $reason = null
) { ) {
$this->assertStatusCodeRange($status); $this->assertStatusCodeRange($status);

View File

@@ -69,7 +69,7 @@ final class StreamWrapper
} }
} }
public function stream_open(string $path, string $mode, int $options, string &$opened_path = null): bool public function stream_open(string $path, string $mode, int $options, ?string &$opened_path = null): bool
{ {
$options = stream_context_get_options($this->context); $options = stream_context_get_options($this->context);
@@ -136,10 +136,14 @@ final class StreamWrapper
* ctime: int, * ctime: int,
* blksize: int, * blksize: int,
* blocks: int * blocks: int
* } * }|false
*/ */
public function stream_stat(): array public function stream_stat()
{ {
if ($this->stream->getSize() === null) {
return false;
}
static $modeMap = [ static $modeMap = [
'r' => 33060, 'r' => 33060,
'rb' => 33060, 'rb' => 33060,

View File

@@ -11,15 +11,15 @@ use RuntimeException;
class UploadedFile implements UploadedFileInterface class UploadedFile implements UploadedFileInterface
{ {
private const ERRORS = [ private const ERROR_MAP = [
UPLOAD_ERR_OK, UPLOAD_ERR_OK => 'UPLOAD_ERR_OK',
UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_INI_SIZE => 'UPLOAD_ERR_INI_SIZE',
UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_FORM_SIZE => 'UPLOAD_ERR_FORM_SIZE',
UPLOAD_ERR_PARTIAL, UPLOAD_ERR_PARTIAL => 'UPLOAD_ERR_PARTIAL',
UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_FILE => 'UPLOAD_ERR_NO_FILE',
UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_NO_TMP_DIR => 'UPLOAD_ERR_NO_TMP_DIR',
UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_CANT_WRITE => 'UPLOAD_ERR_CANT_WRITE',
UPLOAD_ERR_EXTENSION, UPLOAD_ERR_EXTENSION => 'UPLOAD_ERR_EXTENSION',
]; ];
/** /**
@@ -64,8 +64,8 @@ class UploadedFile implements UploadedFileInterface
$streamOrFile, $streamOrFile,
?int $size, ?int $size,
int $errorStatus, int $errorStatus,
string $clientFilename = null, ?string $clientFilename = null,
string $clientMediaType = null ?string $clientMediaType = null
) { ) {
$this->setError($errorStatus); $this->setError($errorStatus);
$this->size = $size; $this->size = $size;
@@ -104,7 +104,7 @@ class UploadedFile implements UploadedFileInterface
*/ */
private function setError(int $error): void private function setError(int $error): void
{ {
if (false === in_array($error, UploadedFile::ERRORS, true)) { if (!isset(UploadedFile::ERROR_MAP[$error])) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'Invalid error status for UploadedFile' 'Invalid error status for UploadedFile'
); );
@@ -137,7 +137,7 @@ class UploadedFile implements UploadedFileInterface
private function validateActive(): void private function validateActive(): void
{ {
if (false === $this->isOk()) { if (false === $this->isOk()) {
throw new RuntimeException('Cannot retrieve stream due to upload error'); throw new RuntimeException(\sprintf('Cannot retrieve stream due to upload error (%s)', self::ERROR_MAP[$this->error]));
} }
if ($this->isMoved()) { if ($this->isMoved()) {

View File

@@ -107,7 +107,7 @@ class Uri implements UriInterface, \JsonSerializable
{ {
// If IPv6 // If IPv6
$prefix = ''; $prefix = '';
if (preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)) { if (preg_match('%^(.*://\[[0-9:a-fA-F]+\])(.*?)$%', $url, $matches)) {
/** @var array{0:string, 1:string, 2:string} $matches */ /** @var array{0:string, 1:string, 2:string} $matches */
$prefix = $matches[1]; $prefix = $matches[1];
$url = $matches[2]; $url = $matches[2];
@@ -279,7 +279,7 @@ class Uri implements UriInterface, \JsonSerializable
* *
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.4 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.4
*/ */
public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool public static function isSameDocumentReference(UriInterface $uri, ?UriInterface $base = null): bool
{ {
if ($base !== null) { if ($base !== null) {
$uri = UriResolver::resolve($base, $uri); $uri = UriResolver::resolve($base, $uri);

View File

@@ -231,7 +231,7 @@ final class Utils
* @param StreamInterface $stream Stream to read from * @param StreamInterface $stream Stream to read from
* @param int|null $maxLength Maximum buffer length * @param int|null $maxLength Maximum buffer length
*/ */
public static function readLine(StreamInterface $stream, int $maxLength = null): string public static function readLine(StreamInterface $stream, ?int $maxLength = null): string
{ {
$buffer = ''; $buffer = '';
$size = 0; $size = 0;
@@ -250,6 +250,20 @@ final class Utils
return $buffer; return $buffer;
} }
/**
* Redact the password in the user info part of a URI.
*/
public static function redactUserInfo(UriInterface $uri): UriInterface
{
$userInfo = $uri->getUserInfo();
if (false !== ($pos = \strpos($userInfo, ':'))) {
return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***');
}
return $uri;
}
/** /**
* Create a new stream based on the input type. * Create a new stream based on the input type.
* *
@@ -383,7 +397,7 @@ final class Utils
restore_error_handler(); restore_error_handler();
if ($ex) { if ($ex) {
/** @var $ex \RuntimeException */ /** @var \RuntimeException $ex */
throw $ex; throw $ex;
} }
@@ -430,7 +444,7 @@ final class Utils
restore_error_handler(); restore_error_handler();
if ($ex) { if ($ex) {
/** @var $ex \RuntimeException */ /** @var \RuntimeException $ex */
throw $ex; throw $ex;
} }

View File

@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2013-2020 Alex Bilbie <hello@alexbilbie.com> Copyright (c) 2013-2023 Alex Bilbie <hello@alexbilbie.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -24,14 +24,16 @@ This package is compliant with [PSR-1][], [PSR-2][], [PSR-4][], and [PSR-7][]. I
We support the following versions of PHP: We support the following versions of PHP:
* PHP 8.5
* PHP 8.4
* PHP 8.3
* PHP 8.2
* PHP 8.1 * PHP 8.1
* PHP 8.0 * PHP 8.0
* PHP 7.4 * PHP 7.4
* PHP 7.3 * PHP 7.3
* PHP 7.2 * PHP 7.2
* PHP 7.1 * PHP 7.1
* PHP 7.0
* PHP 5.6
## Provider Clients ## Provider Clients

View File

@@ -6,15 +6,15 @@
"sort-packages": true "sort-packages": true
}, },
"require": { "require": {
"php": "^5.6 || ^7.0 || ^8.0", "php": "^7.1 || >=8.0.0 <8.6.0",
"guzzlehttp/guzzle": "^6.0 || ^7.0", "ext-json": "*",
"paragonie/random_compat": "^1 || ^2 || ^9.99" "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5"
}, },
"require-dev": { "require-dev": {
"mockery/mockery": "^1.3.5", "mockery/mockery": "^1.3.5",
"php-parallel-lint/php-parallel-lint": "^1.3.1", "php-parallel-lint/php-parallel-lint": "^1.4",
"phpunit/phpunit": "^5.7 || ^6.0 || ^9.5", "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11",
"squizlabs/php_codesniffer": "^2.3 || ^3.0" "squizlabs/php_codesniffer": "^3.11"
}, },
"keywords": [ "keywords": [
"oauth", "oauth",
@@ -49,10 +49,5 @@
"psr-4": { "psr-4": {
"League\\OAuth2\\Client\\Test\\": "test/src/" "League\\OAuth2\\Client\\Test\\": "test/src/"
} }
},
"extra": {
"branch-alias": {
"dev-2.x": "2.0.x-dev"
}
} }
} }

View File

@@ -17,6 +17,7 @@ namespace League\OAuth2\Client\Provider;
use GuzzleHttp\Client as HttpClient; use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\ClientInterface as HttpClientInterface; use GuzzleHttp\ClientInterface as HttpClientInterface;
use GuzzleHttp\Exception\BadResponseException; use GuzzleHttp\Exception\BadResponseException;
use GuzzleHttp\Exception\GuzzleException;
use InvalidArgumentException; use InvalidArgumentException;
use League\OAuth2\Client\Grant\AbstractGrant; use League\OAuth2\Client\Grant\AbstractGrant;
use League\OAuth2\Client\Grant\GrantFactory; use League\OAuth2\Client\Grant\GrantFactory;
@@ -405,6 +406,7 @@ abstract class AbstractProvider
* *
* @param array $options * @param array $options
* @return array Authorization parameters * @return array Authorization parameters
* @throws InvalidArgumentException
*/ */
protected function getAuthorizationParameters(array $options) protected function getAuthorizationParameters(array $options)
{ {
@@ -476,6 +478,7 @@ abstract class AbstractProvider
* *
* @param array $options * @param array $options
* @return string Authorization URL * @return string Authorization URL
* @throws InvalidArgumentException
*/ */
public function getAuthorizationUrl(array $options = []) public function getAuthorizationUrl(array $options = [])
{ {
@@ -492,10 +495,11 @@ abstract class AbstractProvider
* @param array $options * @param array $options
* @param callable|null $redirectHandler * @param callable|null $redirectHandler
* @return mixed * @return mixed
* @throws InvalidArgumentException
*/ */
public function authorize( public function authorize(
array $options = [], array $options = [],
callable $redirectHandler = null ?callable $redirectHandler = null
) { ) {
$url = $this->getAuthorizationUrl($options); $url = $this->getAuthorizationUrl($options);
if ($redirectHandler) { if ($redirectHandler) {
@@ -613,13 +617,20 @@ abstract class AbstractProvider
* *
* @param mixed $grant * @param mixed $grant
* @param array<string, mixed> $options * @param array<string, mixed> $options
* @throws IdentityProviderException
* @return AccessTokenInterface * @return AccessTokenInterface
* @throws IdentityProviderException
* @throws UnexpectedValueException
* @throws GuzzleException
*/ */
public function getAccessToken($grant, array $options = []) public function getAccessToken($grant, array $options = [])
{ {
$grant = $this->verifyGrant($grant); $grant = $this->verifyGrant($grant);
if (isset($options['scope']) && is_array($options['scope'])) {
$separator = $this->getScopeSeparator();
$options['scope'] = implode($separator, $options['scope']);
}
$params = [ $params = [
'client_id' => $this->clientId, 'client_id' => $this->clientId,
'client_secret' => $this->clientSecret, 'client_secret' => $this->clientSecret,
@@ -700,6 +711,7 @@ abstract class AbstractProvider
* *
* @param RequestInterface $request * @param RequestInterface $request
* @return ResponseInterface * @return ResponseInterface
* @throws GuzzleException
*/ */
public function getResponse(RequestInterface $request) public function getResponse(RequestInterface $request)
{ {
@@ -710,8 +722,10 @@ abstract class AbstractProvider
* Sends a request and returns the parsed response. * Sends a request and returns the parsed response.
* *
* @param RequestInterface $request * @param RequestInterface $request
* @throws IdentityProviderException
* @return mixed * @return mixed
* @throws IdentityProviderException
* @throws UnexpectedValueException
* @throws GuzzleException
*/ */
public function getParsedResponse(RequestInterface $request) public function getParsedResponse(RequestInterface $request)
{ {
@@ -757,7 +771,7 @@ abstract class AbstractProvider
*/ */
protected function getContentType(ResponseInterface $response) protected function getContentType(ResponseInterface $response)
{ {
return join(';', (array) $response->getHeader('content-type')); return implode(';', $response->getHeader('content-type'));
} }
/** /**
@@ -815,7 +829,7 @@ abstract class AbstractProvider
* Custom mapping of expiration, etc should be done here. Always call the * Custom mapping of expiration, etc should be done here. Always call the
* parent method when overloading this method. * parent method when overloading this method.
* *
* @param mixed $result * @param array<string, mixed> $result
* @return array * @return array
*/ */
protected function prepareAccessTokenResponse(array $result) protected function prepareAccessTokenResponse(array $result)
@@ -859,6 +873,9 @@ abstract class AbstractProvider
* *
* @param AccessToken $token * @param AccessToken $token
* @return ResourceOwnerInterface * @return ResourceOwnerInterface
* @throws IdentityProviderException
* @throws UnexpectedValueException
* @throws GuzzleException
*/ */
public function getResourceOwner(AccessToken $token) public function getResourceOwner(AccessToken $token)
{ {
@@ -872,6 +889,9 @@ abstract class AbstractProvider
* *
* @param AccessToken $token * @param AccessToken $token
* @return mixed * @return mixed
* @throws IdentityProviderException
* @throws UnexpectedValueException
* @throws GuzzleException
*/ */
protected function fetchResourceOwnerDetails(AccessToken $token) protected function fetchResourceOwnerDetails(AccessToken $token)
{ {

View File

@@ -22,7 +22,7 @@ use RuntimeException;
* *
* @link http://tools.ietf.org/html/rfc6749#section-1.4 Access Token (RFC 6749, §1.4) * @link http://tools.ietf.org/html/rfc6749#section-1.4 Access Token (RFC 6749, §1.4)
*/ */
class AccessToken implements AccessTokenInterface, ResourceOwnerAccessTokenInterface class AccessToken implements AccessTokenInterface, ResourceOwnerAccessTokenInterface, SettableRefreshTokenInterface
{ {
/** /**
* @var string * @var string
@@ -118,7 +118,7 @@ class AccessToken implements AccessTokenInterface, ResourceOwnerAccessTokenInter
} elseif (!empty($options['expires'])) { } elseif (!empty($options['expires'])) {
// Some providers supply the seconds until expiration rather than // Some providers supply the seconds until expiration rather than
// the exact timestamp. Take a best guess at which we received. // the exact timestamp. Take a best guess at which we received.
$expires = $options['expires']; $expires = (int) $options['expires'];
if (!$this->isExpirationTimestamp($expires)) { if (!$this->isExpirationTimestamp($expires)) {
$expires += $this->getTimeNow(); $expires += $this->getTimeNow();
@@ -169,6 +169,14 @@ class AccessToken implements AccessTokenInterface, ResourceOwnerAccessTokenInter
return $this->refreshToken; return $this->refreshToken;
} }
/**
* @inheritdoc
*/
public function setRefreshToken($refreshToken)
{
$this->refreshToken = $refreshToken;
}
/** /**
* @inheritdoc * @inheritdoc
*/ */
@@ -196,7 +204,7 @@ class AccessToken implements AccessTokenInterface, ResourceOwnerAccessTokenInter
throw new RuntimeException('"expires" is not set on the token'); throw new RuntimeException('"expires" is not set on the token');
} }
return $expires < time(); return $expires < $this->getTimeNow();
} }
/** /**

View File

@@ -1,5 +1,12 @@
OAuth 2.0 Google Provider Changelog OAuth 2.0 Google Provider Changelog
## 4.1.0 - 2025-12-15
### Added
- Added getEmailVerified(), isEmailTrustworthy() to user definition, #132 by @dt-thomas-durand
## 4.0.1 - 2022-03-17 ## 4.0.1 - 2022-03-17
### Changed ### Changed

View File

@@ -1,6 +1,6 @@
# Google Provider for OAuth 2.0 Client # Google Provider for OAuth 2.0 Client
[![Build Status](https://img.shields.io/github/workflow/status/thephpleague/oauth2-google/test/main)](https://github.com/thephpleague/oauth2-google/actions/workflows/test.yaml) [![Build Status](https://img.shields.io/github/actions/workflow/status/thephpleague/oauth2-google/ci.yml?branch=main)](https://github.com/thephpleague/oauth2-google/actions/workflows/ci.yml)
[![Code Coverage](https://img.shields.io/codecov/c/gh/thephpleague/oauth2-google)](https://app.codecov.io/gh/thephpleague/oauth2-google) [![Code Coverage](https://img.shields.io/codecov/c/gh/thephpleague/oauth2-google)](https://app.codecov.io/gh/thephpleague/oauth2-google)
[![License](https://img.shields.io/packagist/l/league/oauth2-google)](https://github.com/thephpleague/oauth2-google/blob/main/LICENSE) [![License](https://img.shields.io/packagist/l/league/oauth2-google)](https://github.com/thephpleague/oauth2-google/blob/main/LICENSE)
[![Latest Stable Version](https://img.shields.io/packagist/v/league/oauth2-google)](https://packagist.org/packages/league/oauth2-google) [![Latest Stable Version](https://img.shields.io/packagist/v/league/oauth2-google)](https://packagist.org/packages/league/oauth2-google)
@@ -22,6 +22,8 @@ The following versions of PHP are supported.
* PHP 7.4 * PHP 7.4
* PHP 8.0 * PHP 8.0
* PHP 8.1 * PHP 8.1
* PHP 8.2
* PHP 8.3
This package uses [OpenID Connect][openid-connect] to authenticate users with This package uses [OpenID Connect][openid-connect] to authenticate users with
Google accounts. Google accounts.

View File

@@ -72,6 +72,36 @@ class GoogleUser implements ResourceOwnerInterface
return $this->getResponseValue('email'); return $this->getResponseValue('email');
} }
/**
* Get email_verified attribute.
*
* @return bool|null
*/
public function getEmailVerified(): ?bool
{
return $this->getResponseValue('email_verified');
}
/**
* Returns whether the email is trustable enough to be used for authentication purpose.
*
* @see https://developers.google.com/identity/gsi/web/guides/verify-google-id-token
*/
public function isEmailTrustworthy(): bool
{
$email = $this->getEmail();
if (! $email) {
return false;
}
if ('@gmail.com' === substr($email, -10)) {
return true;
}
if ($this->getHostedDomain() && $this->getEmailVerified()) {
return true;
}
return false;
}
/** /**
* Get hosted domain. * Get hosted domain.
* *

View File

@@ -6,7 +6,7 @@ PHP Parser
This is a PHP 5.2 to PHP 8.2 parser written in PHP. Its purpose is to simplify static code analysis and This is a PHP 5.2 to PHP 8.2 parser written in PHP. Its purpose is to simplify static code analysis and
manipulation. manipulation.
[**Documentation for version 4.x**][doc_4_x] (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 8.2). [**Documentation for version 4.x**][doc_4_x] (stable; for running on PHP >= 7.1; for parsing PHP 5.2 to PHP 8.2).
[Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2). [Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2).

View File

@@ -13,18 +13,13 @@
} }
], ],
"require": { "require": {
"php": ">=7.0", "php": ">=7.1",
"ext-tokenizer": "*" "ext-tokenizer": "*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0", "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"ircmaxell/php-yacc": "^0.0.7" "ircmaxell/php-yacc": "^0.0.7"
}, },
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"PhpParser\\": "lib/PhpParser" "PhpParser\\": "lib/PhpParser"

View File

@@ -26,7 +26,7 @@ class ClassConst implements PhpParser\Builder
* Creates a class constant builder * Creates a class constant builder
* *
* @param string|Identifier $name Name * @param string|Identifier $name Name
* @param Node\Expr|bool|null|int|float|string|array $value Value * @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value Value
*/ */
public function __construct($name, $value) { public function __construct($name, $value) {
$this->constants = [new Const_($name, BuilderHelpers::normalizeValue($value))]; $this->constants = [new Const_($name, BuilderHelpers::normalizeValue($value))];
@@ -36,7 +36,7 @@ class ClassConst implements PhpParser\Builder
* Add another constant to const group * Add another constant to const group
* *
* @param string|Identifier $name Name * @param string|Identifier $name Name
* @param Node\Expr|bool|null|int|float|string|array $value Value * @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value Value
* *
* @return $this The builder instance (for fluid interface) * @return $this The builder instance (for fluid interface)
*/ */

View File

@@ -213,7 +213,7 @@ class BuilderFactory
/** /**
* Creates node a for a literal value. * Creates node a for a literal value.
* *
* @param Expr|bool|null|int|float|string|array $value $value * @param Expr|bool|null|int|float|string|array|\UnitEnum $value $value
* *
* @return Expr * @return Expr
*/ */

View File

@@ -6,6 +6,7 @@ use PhpParser\Node\ComplexType;
use PhpParser\Node\Expr; use PhpParser\Node\Expr;
use PhpParser\Node\Identifier; use PhpParser\Node\Identifier;
use PhpParser\Node\Name; use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\NullableType; use PhpParser\Node\NullableType;
use PhpParser\Node\Scalar; use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt; use PhpParser\Node\Stmt;
@@ -215,7 +216,7 @@ final class BuilderHelpers
* Normalizes a value: Converts nulls, booleans, integers, * Normalizes a value: Converts nulls, booleans, integers,
* floats, strings and arrays into their respective nodes * floats, strings and arrays into their respective nodes
* *
* @param Node\Expr|bool|null|int|float|string|array $value The value to normalize * @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value The value to normalize
* *
* @return Expr The normalized value * @return Expr The normalized value
*/ */
@@ -269,6 +270,10 @@ final class BuilderHelpers
return new Expr\Array_($items); return new Expr\Array_($items);
} }
if ($value instanceof \UnitEnum) {
return new Expr\ClassConstFetch(new FullyQualified(\get_class($value)), new Identifier($value->name));
}
throw new \LogicException('Invalid value'); throw new \LogicException('Invalid value');
} }

View File

@@ -37,7 +37,7 @@ class ConstExprEvaluator
* *
* @param callable|null $fallbackEvaluator To call if subexpression cannot be evaluated * @param callable|null $fallbackEvaluator To call if subexpression cannot be evaluated
*/ */
public function __construct(callable $fallbackEvaluator = null) { public function __construct(?callable $fallbackEvaluator = null) {
$this->fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) { $this->fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) {
throw new ConstExprEvaluationException( throw new ConstExprEvaluationException(
"Expression of type {$expr->getType()} cannot be evaluated" "Expression of type {$expr->getType()} cannot be evaluated"

View File

@@ -31,7 +31,7 @@ class PrintableNewAnonClassNode extends Expr
public $stmts; public $stmts;
public function __construct( public function __construct(
array $attrGroups, int $flags, array $args, Node\Name $extends = null, array $implements, array $attrGroups, int $flags, array $args, ?Node\Name $extends, array $implements,
array $stmts, array $attributes array $stmts, array $attributes
) { ) {
parent::__construct($attributes); parent::__construct($attributes);

Some files were not shown because too many files have changed in this diff Show More