guzzle_file_cookie_jar_shim.php
Namespace
GuzzleHttp\CookieFile
-
core/
includes/ guzzle_file_cookie_jar_shim.php
View source
<?php
/**
* Provides a hardened replacement for \GuzzleHttp\Cookie\FileCookieJar.
*
* Upstream hardening landed for Guzzle 8.0 but is not included in Guzzle 7.
* The body of the class below is a verbatim backport of the hardened Guzzle
* 8.0 implementation.
*
* @see https://github.com/guzzle/guzzle/pull/3334
*
* @todo Remove when Drupal updates to Guzzle 8.
*/
namespace GuzzleHttp\Cookie;
use GuzzleHttp\Utils;
// phpcs:ignoreFile
// Only define the class if the real one has not already been loaded.
if (!class_exists(FileCookieJar::class, false)) {
/**
* Persists non-session cookies using a JSON formatted file
*/
class FileCookieJar extends CookieJar {
/**
* @var string filename
*/
private string $filename;
/**
* @var bool Control whether to persist session cookies or not.
*/
private bool $storeSessionCookies;
/**
* @var bool Whether to save the cookie jar on destruction.
*
* Disabled by __wakeup() to prevent FileCookieJar from being used as a
* PHP object injection file-write gadget when an application unserializes
* attacker-controlled data.
*/
private bool $autoSave = true;
/**
* Create a new FileCookieJar object
*
* @param string $cookieFile File to store the cookie data
* @param bool $storeSessionCookies Set to true to store session cookies
* in the cookie jar.
*
* @throws \RuntimeException if the file cannot be found or created
*/
public function __construct(string $cookieFile, bool $storeSessionCookies = false) {
parent::__construct();
$this->filename = $cookieFile;
$this->storeSessionCookies = $storeSessionCookies;
if (\file_exists($cookieFile)) {
$this->load($cookieFile);
}
}
/**
* Saves the file when shutting down
*/
public function __destruct() {
if ($this->autoSave) {
$this->save($this->filename);
}
}
/**
* Disable automatic persistence after unserialization.
*/
public function __wakeup() : void {
$this->autoSave = false;
}
/**
* Saves the cookies to a file.
*
* @param string $filename File to save
*
* @throws \RuntimeException if the file cannot be found or created
*/
public function save(string $filename) : void {
$json = [];
/** @var SetCookie $cookie */
foreach ($this as $cookie) {
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
$json[] = $cookie->toArray();
}
}
$jsonStr = Utils::jsonEncode($json, \JSON_HEX_TAG);
if (false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) {
throw new \RuntimeException("Unable to save file {$filename}");
}
}
/**
* Load cookies from a JSON formatted file.
*
* Old cookies are kept unless overwritten by newly loaded ones.
*
* @param string $filename Cookie file to load.
*
* @throws \RuntimeException if the file cannot be loaded.
*/
public function load(string $filename) : void {
$json = \file_get_contents($filename);
if (false === $json) {
throw new \RuntimeException("Unable to load file {$filename}");
}
if ($json === '') {
return;
}
$data = Utils::jsonDecode($json, true);
if (\is_array($data)) {
foreach ($data as $cookie) {
if (!\is_array($cookie)) {
throw new \RuntimeException("Invalid cookie file: {$filename}");
}
try {
$this->setCookie(new SetCookie($cookie));
} catch (\InvalidArgumentException $e) {
throw new \RuntimeException("Invalid cookie file: {$filename}", 0, $e);
}
}
}
elseif (\is_scalar($data) && !empty($data)) {
throw new \RuntimeException("Invalid cookie file: {$filename}");
}
}
}
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.