From 10ccbbdf1d5c452224fde017d125e9edb2eeebde Mon Sep 17 00:00:00 2001 From: Anna van Brecht Date: Mon, 17 Jun 2024 10:25:35 +0200 Subject: [PATCH 1/5] Check response body size to not exceed 50mb before json_decoding --- src/Picqer/Carriers/SendCloud/Connection.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Picqer/Carriers/SendCloud/Connection.php b/src/Picqer/Carriers/SendCloud/Connection.php index 77a590a..ac76881 100644 --- a/src/Picqer/Carriers/SendCloud/Connection.php +++ b/src/Picqer/Carriers/SendCloud/Connection.php @@ -13,6 +13,7 @@ class Connection private $apiKey; private $apiSecret; private $partnerId; + private $maxResponseSizeInBytes; /** * Contains the HTTP client (Guzzle) @@ -26,11 +27,12 @@ class Connection */ protected $middleWares = []; - public function __construct(string $apiKey, string $apiSecret, ?string $partnerId = null) + public function __construct(string $apiKey, string $apiSecret, ?string $partnerId = null, ?int $maxResponseSizeInBytes = 50000000) { $this->apiKey = $apiKey; $this->apiSecret = $apiSecret; $this->partnerId = $partnerId; + $this->maxResponseSizeInBytes = $maxResponseSizeInBytes; } public function client(): Client @@ -171,6 +173,11 @@ public function parseResponse(ResponseInterface $response) $response->getBody()->rewind(); $responseBody = $response->getBody()->getContents(); + + if (strlen($responseBody) > $this->maxResponseSizeInBytes) { + throw new SendCloudApiException(sprintf('Response size exceeded maximum of %d bytes', $this->maxResponseSizeInBytes)); + } + $resultArray = json_decode($responseBody, true); if (! is_array($resultArray)) { From 6b2de7f2dbb8a6167c6aaea6890950d871abbd5e Mon Sep 17 00:00:00 2001 From: Anna van Brecht Date: Mon, 24 Jun 2024 12:44:06 +0200 Subject: [PATCH 2/5] Bump PHP version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c154739..8b6d503 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ } ], "require": { - "php": ">=7.2.0", + "php": ">=7.4.0", "guzzlehttp/guzzle": "~6.0|~7.0", "ext-json": "*" }, From 09232439696ad665ef53b8335d77c59391d895c1 Mon Sep 17 00:00:00 2001 From: Anna van Brecht Date: Mon, 24 Jun 2024 12:44:41 +0200 Subject: [PATCH 3/5] Refactor maximum response size setting and checking --- src/Picqer/Carriers/SendCloud/Connection.php | 100 +++++------------- .../MaximumResponseSizeException.php | 5 + 2 files changed, 29 insertions(+), 76 deletions(-) create mode 100644 src/Picqer/Carriers/SendCloud/MaximumResponseSizeException.php diff --git a/src/Picqer/Carriers/SendCloud/Connection.php b/src/Picqer/Carriers/SendCloud/Connection.php index ac76881..51dd8b3 100644 --- a/src/Picqer/Carriers/SendCloud/Connection.php +++ b/src/Picqer/Carriers/SendCloud/Connection.php @@ -9,30 +9,21 @@ class Connection { - private $apiUrl = 'https://panel.sendcloud.sc/api/v2/'; - private $apiKey; - private $apiSecret; - private $partnerId; - private $maxResponseSizeInBytes; + private string $apiUrl = 'https://panel.sendcloud.sc/api/v2/'; + private string $apiKey; + private string $apiSecret; + private ?string $partnerId; + private ?int $maxResponseSizeInBytes; - /** - * Contains the HTTP client (Guzzle) - * @var Client - */ - private $client; - - /** - * Array of inserted middleWares - * @var array - */ - protected $middleWares = []; + private Client $client; + protected array $middleWares = []; - public function __construct(string $apiKey, string $apiSecret, ?string $partnerId = null, ?int $maxResponseSizeInBytes = 50000000) + public function __construct(string $apiKey, string $apiSecret, ?string $partnerId = null) { $this->apiKey = $apiKey; $this->apiSecret = $apiSecret; $this->partnerId = $partnerId; - $this->maxResponseSizeInBytes = $maxResponseSizeInBytes; + $this->maxResponseSizeInBytes = null; } public function client(): Client @@ -65,7 +56,7 @@ public function client(): Client return $this->client; } - public function insertMiddleWare($middleWare) + public function insertMiddleWare($middleWare): void { $this->middleWares[] = $middleWare; } @@ -75,13 +66,6 @@ public function apiUrl(): string return $this->apiUrl; } - /** - * Perform a GET request - * @param string $url - * @param array $params - * @return array - * @throws SendCloudApiException - */ public function get($url, $params = []): array { try { @@ -96,14 +80,6 @@ public function get($url, $params = []): array } } - /** - * Perform a POST request - * @param string $url - * @param mixed $body - * @param array $query - * @return array - * @throws SendCloudApiException - */ public function post($url, $body, $query = []): array { try { @@ -118,14 +94,6 @@ public function post($url, $body, $query = []): array } } - /** - * Perform PUT request - * @param string $url - * @param mixed $body - * @param array $query - * @return array - * @throws SendCloudApiException - */ public function put($url, $body, $query = []): array { try { @@ -140,14 +108,7 @@ public function put($url, $body, $query = []): array } } - /** - * Perform DELETE request - * @param string $url - * @param array $query - * @return array - * @throws SendCloudApiException - */ - public function delete($url, $query = []) + public function delete($url, $query = []): array { try { $result = $this->client()->delete($url, ['query' => $query]); @@ -161,12 +122,7 @@ public function delete($url, $query = []) } } - /** - * @param ResponseInterface $response - * @return array Parsed JSON result - * @throws SendCloudApiException - */ - public function parseResponse(ResponseInterface $response) + public function parseResponse(ResponseInterface $response): array { try { // Rewind the response (middlewares might have read it already) @@ -174,8 +130,10 @@ public function parseResponse(ResponseInterface $response) $responseBody = $response->getBody()->getContents(); - if (strlen($responseBody) > $this->maxResponseSizeInBytes) { - throw new SendCloudApiException(sprintf('Response size exceeded maximum of %d bytes', $this->maxResponseSizeInBytes)); + if (! is_null($this->maxResponseSizeInBytes)) { + if (strlen($responseBody) > $this->maxResponseSizeInBytes) { + throw new MaximumResponseSizeException(sprintf('Response size exceeded maximum of %d bytes', $this->maxResponseSizeInBytes)); + } } $resultArray = json_decode($responseBody, true); @@ -203,39 +161,29 @@ public function parseResponse(ResponseInterface $response) } /** - * Returns the selected environment - * - * @return string * @deprecated */ - public function getEnvironment() + public function getEnvironment(): string { return 'live'; } /** - * Set the environment for the client - * - * @param string $environment - * @throws SendCloudApiException * @deprecated */ - public function setEnvironment($environment) + public function setEnvironment($environment): void { if ($environment === 'test') { throw new SendCloudApiException('SendCloud test environment is no longer available'); } } - /** - * Download a resource. - * - * @param string $url - * @param array $headers - * @return string - * @throws SendCloudApiException - */ - public function download($url, array $headers = ['Accept' => 'application/pdf']) + public function setMaxResponseSizeInBytes(?int $maxResponseSizeInBytes): void + { + $this->maxResponseSizeInBytes = $maxResponseSizeInBytes; + } + + public function download($url, array $headers = ['Accept' => 'application/pdf']): string { try { $result = $this->client()->get($url, ['headers' => $headers]); diff --git a/src/Picqer/Carriers/SendCloud/MaximumResponseSizeException.php b/src/Picqer/Carriers/SendCloud/MaximumResponseSizeException.php new file mode 100644 index 0000000..f4f44ab --- /dev/null +++ b/src/Picqer/Carriers/SendCloud/MaximumResponseSizeException.php @@ -0,0 +1,5 @@ + Date: Mon, 24 Jun 2024 12:45:22 +0200 Subject: [PATCH 4/5] Remove setting in constructor --- src/Picqer/Carriers/SendCloud/Connection.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Picqer/Carriers/SendCloud/Connection.php b/src/Picqer/Carriers/SendCloud/Connection.php index 51dd8b3..594c45f 100644 --- a/src/Picqer/Carriers/SendCloud/Connection.php +++ b/src/Picqer/Carriers/SendCloud/Connection.php @@ -23,7 +23,6 @@ public function __construct(string $apiKey, string $apiSecret, ?string $partnerI $this->apiKey = $apiKey; $this->apiSecret = $apiSecret; $this->partnerId = $partnerId; - $this->maxResponseSizeInBytes = null; } public function client(): Client From 269ce1013c15190b3efc6fb2d38840c76ad4e78d Mon Sep 17 00:00:00 2001 From: Anna van Brecht Date: Mon, 24 Jun 2024 14:04:12 +0200 Subject: [PATCH 5/5] Set defaults for variables and improved client check --- src/Picqer/Carriers/SendCloud/Connection.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Picqer/Carriers/SendCloud/Connection.php b/src/Picqer/Carriers/SendCloud/Connection.php index 594c45f..ca60fa4 100644 --- a/src/Picqer/Carriers/SendCloud/Connection.php +++ b/src/Picqer/Carriers/SendCloud/Connection.php @@ -12,10 +12,10 @@ class Connection private string $apiUrl = 'https://panel.sendcloud.sc/api/v2/'; private string $apiKey; private string $apiSecret; - private ?string $partnerId; - private ?int $maxResponseSizeInBytes; + private ?string $partnerId = null; + private ?int $maxResponseSizeInBytes = null; - private Client $client; + private ?Client $client = null; protected array $middleWares = []; public function __construct(string $apiKey, string $apiSecret, ?string $partnerId = null) @@ -27,7 +27,7 @@ public function __construct(string $apiKey, string $apiSecret, ?string $partnerI public function client(): Client { - if ($this->client) { + if ($this->client instanceof Client) { return $this->client; } @@ -182,6 +182,11 @@ public function setMaxResponseSizeInBytes(?int $maxResponseSizeInBytes): void $this->maxResponseSizeInBytes = $maxResponseSizeInBytes; } + public function getMaxResponseSizeInBytes(): ?int + { + return $this->maxResponseSizeInBytes; + } + public function download($url, array $headers = ['Accept' => 'application/pdf']): string { try {