From 2356221abaa5d9ea2eb86174e91b0d43913f413c Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Tue, 24 Aug 2021 14:17:42 +0200
Subject: [PATCH] Fixup HTTP headers for httpClient requests

---
 src/Core/Search.php                    |  2 +-
 src/Model/GServer.php                  |  3 +--
 src/Model/Storage/ExternalResource.php |  2 +-
 src/Module/Proxy.php                   |  2 +-
 src/Network/HTTPClient.php             |  2 +-
 src/Network/Probe.php                  |  6 +++---
 src/Protocol/DFRN.php                  |  2 +-
 src/Protocol/Diaspora.php              |  2 +-
 src/Protocol/OStatus.php               |  4 ++--
 src/Protocol/Salmon.php                | 12 ++++++------
 src/Util/HTTPSignature.php             | 25 ++++++++++++++-----------
 src/Worker/PubSubPublish.php           |  7 ++++---
 12 files changed, 36 insertions(+), 33 deletions(-)

diff --git a/src/Core/Search.php b/src/Core/Search.php
index a3588b3bd..efe8331b8 100644
--- a/src/Core/Search.php
+++ b/src/Core/Search.php
@@ -227,7 +227,7 @@ class Search
 			$return = Contact::searchByName($search, $mode);
 		} else {
 			$p = $page > 1 ? 'p=' . $page : '';
-			$curlResult = DI::httpRequest()->get(self::getGlobalDirectory() . '/search/people?' . $p . '&q=' . urlencode($search), ['accept_content' => 'application/json']);
+			$curlResult = DI::httpRequest()->get(self::getGlobalDirectory() . '/search/people?' . $p . '&q=' . urlencode($search), ['accept_content' => ['application/json']]);
 			if ($curlResult->isSuccess()) {
 				$searchResult = json_decode($curlResult->getBody(), true);
 				if (!empty($searchResult['profiles'])) {
diff --git a/src/Model/GServer.php b/src/Model/GServer.php
index eb99b1bbc..15bf727e5 100644
--- a/src/Model/GServer.php
+++ b/src/Model/GServer.php
@@ -1728,8 +1728,7 @@ class GServer
 
 		if (!empty($accesstoken)) {
 			$api = 'https://instances.social/api/1.0/instances/list?count=0';
-			$header = ['Authorization: Bearer '.$accesstoken];
-			$curlResult = DI::httpRequest()->get($api, ['header' => $header]);
+			$curlResult = DI::httpRequest()->get($api, ['header' => ['Authorization' => ['Bearer ' . $accesstoken]]]);
 
 			if ($curlResult->isSuccess()) {
 				$servers = json_decode($curlResult->getBody(), true);
diff --git a/src/Model/Storage/ExternalResource.php b/src/Model/Storage/ExternalResource.php
index 918bcf8ac..413050c30 100644
--- a/src/Model/Storage/ExternalResource.php
+++ b/src/Model/Storage/ExternalResource.php
@@ -50,7 +50,7 @@ class ExternalResource implements IStorage
 		}
 
 		try {
-			$fetchResult = HTTPSignature::fetchRaw($data->url, $data->uid, ['accept_content' => '']);
+			$fetchResult = HTTPSignature::fetchRaw($data->url, $data->uid, ['accept_content' => []]);
 		} catch (Exception $exception) {
 			throw new ReferenceStorageException(sprintf('External resource failed to get %s', $reference), $exception->getCode(), $exception);
 		}
diff --git a/src/Module/Proxy.php b/src/Module/Proxy.php
index 04fe00db1..cd11d9e3a 100644
--- a/src/Module/Proxy.php
+++ b/src/Module/Proxy.php
@@ -75,7 +75,7 @@ class Proxy extends BaseModule
 		$request['url'] = str_replace(' ', '+', $request['url']);
 
 		// Fetch the content with the local user
-		$fetchResult = HTTPSignature::fetchRaw($request['url'], local_user(), ['accept_content' => '', 'timeout' => 10]);
+		$fetchResult = HTTPSignature::fetchRaw($request['url'], local_user(), ['accept_content' => [], 'timeout' => 10]);
 		$img_str = $fetchResult->getBody();
 
 		if (!$fetchResult->isSuccess() || empty($img_str)) {
diff --git a/src/Network/HTTPClient.php b/src/Network/HTTPClient.php
index d2ea596f1..cd1d9e46b 100644
--- a/src/Network/HTTPClient.php
+++ b/src/Network/HTTPClient.php
@@ -103,7 +103,7 @@ class HTTPClient implements IHTTPClient
 		$header = [];
 
 		if (!empty($opts['accept_content'])) {
-			array_push($header, 'Accept: ' . $opts['accept_content']);
+			$header['Accept'] = $opts['accept_content'];
 		}
 
 		if (!empty($opts['header'])) {
diff --git a/src/Network/Probe.php b/src/Network/Probe.php
index 4cacfedf4..bdc12aadc 100644
--- a/src/Network/Probe.php
+++ b/src/Network/Probe.php
@@ -170,7 +170,7 @@ class Probe
 		Logger::info('Probing', ['host' => $host, 'ssl_url' => $ssl_url, 'url' => $url, 'callstack' => System::callstack(20)]);
 		$xrd = null;
 
-		$curlResult = DI::httpRequest()->get($ssl_url, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
+		$curlResult = DI::httpRequest()->get($ssl_url, ['timeout' => $xrd_timeout, 'accept_content' => ['application/xrd+xml']]);
 		$ssl_connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0);
 		if ($curlResult->isSuccess()) {
 			$xml = $curlResult->getBody();
@@ -187,7 +187,7 @@ class Probe
 		}
 
 		if (!is_object($xrd) && !empty($url)) {
-			$curlResult = DI::httpRequest()->get($url, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
+			$curlResult = DI::httpRequest()->get($url, ['timeout' => $xrd_timeout, 'accept_content' => ['application/xrd+xml']]);
 			$connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0);
 			if ($curlResult->isTimeout()) {
 				Logger::info('Probing timeout', ['url' => $url]);
@@ -940,7 +940,7 @@ class Probe
 	{
 		$xrd_timeout = DI::config()->get('system', 'xrd_timeout', 20);
 
-		$curlResult = DI::httpRequest()->get($url, ['timeout' => $xrd_timeout, 'accept_content' => $type]);
+		$curlResult = DI::httpRequest()->get($url, ['timeout' => $xrd_timeout, 'accept_content' => [$type]]);
 		if ($curlResult->isTimeout()) {
 			self::$istimeout = true;
 			return [];
diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index cd63291ee..141bce542 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -976,7 +976,7 @@ class DFRN
 
 		$content_type = ($public_batch ? "application/magic-envelope+xml" : "application/json");
 
-		$postResult = DI::httpRequest()->post($dest_url, $envelope, ["Content-Type: " . $content_type]);
+		$postResult = DI::httpRequest()->post($dest_url, $envelope, ['Content-Type' => $content_type]);
 		$xml = $postResult->getBody();
 
 		$curl_stat = $postResult->getReturnCode();
diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php
index b38e0506b..32c0ce042 100644
--- a/src/Protocol/Diaspora.php
+++ b/src/Protocol/Diaspora.php
@@ -3022,7 +3022,7 @@ class Diaspora
 		if (!intval(DI::config()->get("system", "diaspora_test"))) {
 			$content_type = (($public_batch) ? "application/magic-envelope+xml" : "application/json");
 
-			$postResult = DI::httpRequest()->post($dest_url . "/", $envelope, ["Content-Type: " . $content_type]);
+			$postResult = DI::httpRequest()->post($dest_url . "/", $envelope, ['Content-Type' => $content_type]);
 			$return_code = $postResult->getReturnCode();
 		} else {
 			Logger::log("test_mode");
diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php
index 215c08fa0..5a0135f9c 100644
--- a/src/Protocol/OStatus.php
+++ b/src/Protocol/OStatus.php
@@ -727,7 +727,7 @@ class OStatus
 
 		self::$conv_list[$conversation] = true;
 
-		$curlResult = DI::httpRequest()->get($conversation, ['accept_content' => 'application/atom+xml, text/html']);
+		$curlResult = DI::httpRequest()->get($conversation, ['accept_content' => ['application/atom+xml', 'text/html']]);
 
 		if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
 			return;
@@ -921,7 +921,7 @@ class OStatus
 		}
 
 		$stored = false;
-		$curlResult = DI::httpRequest()->get($related, ['accept_content' => 'application/atom+xml, text/html']);
+		$curlResult = DI::httpRequest()->get($related, ['accept_content' => ['application/atom+xml', 'text/html']]);
 
 		if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
 			return;
diff --git a/src/Protocol/Salmon.php b/src/Protocol/Salmon.php
index 53367f6d0..8d17f9678 100644
--- a/src/Protocol/Salmon.php
+++ b/src/Protocol/Salmon.php
@@ -156,8 +156,8 @@ class Salmon
 
 		// slap them
 		$postResult = DI::httpRequest()->post($url, $salmon, [
-			'Content-type: application/magic-envelope+xml',
-			'Content-length: ' . strlen($salmon)
+			'Content-type' => 'application/magic-envelope+xml',
+			'Content-length' => strlen($salmon),
 		]);
 
 		$return_code = $postResult->getReturnCode();
@@ -181,8 +181,8 @@ class Salmon
 
 			// slap them
 			$postResult = DI::httpRequest()->post($url, $salmon, [
-				'Content-type: application/magic-envelope+xml',
-				'Content-length: ' . strlen($salmon)
+				'Content-type' => 'application/magic-envelope+xml',
+				'Content-length' => strlen($salmon),
 			]);
 			$return_code = $postResult->getReturnCode();
 		}
@@ -204,8 +204,8 @@ class Salmon
 
 			// slap them
 			$postResult = DI::httpRequest()->post($url, $salmon, [
-				'Content-type: application/magic-envelope+xml',
-				'Content-length: ' . strlen($salmon)]);
+				'Content-type' => 'application/magic-envelope+xml',
+				'Content-length' => strlen($salmon)]);
 			$return_code = $postResult->getReturnCode();
 		}
 
diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php
index e2de810a6..cf3e1294f 100644
--- a/src/Util/HTTPSignature.php
+++ b/src/Util/HTTPSignature.php
@@ -29,6 +29,7 @@ use Friendica\Model\APContact;
 use Friendica\Model\Contact;
 use Friendica\Model\User;
 use Friendica\Network\CurlResult;
+use Friendica\Network\IHTTPResult;
 
 /**
  * Implements HTTP Signatures per draft-cavage-http-signatures-07.
@@ -290,15 +291,20 @@ class HTTPSignature
 		$content_length = strlen($content);
 		$date = DateTimeFormat::utcNow(DateTimeFormat::HTTP);
 
-		$headers = ['Date: ' . $date, 'Content-Length: ' . $content_length, 'Digest: ' . $digest, 'Host: ' . $host];
+		$headers = [
+			'Date' => $date,
+			'Content-Length' => $content_length,
+			'Digest' => $digest,
+			'Host' => $host
+		];
 
 		$signed_data = "(request-target): post " . $path . "\ndate: ". $date . "\ncontent-length: " . $content_length . "\ndigest: " . $digest . "\nhost: " . $host;
 
 		$signature = base64_encode(Crypto::rsaSign($signed_data, $owner['uprvkey'], 'sha256'));
 
-		$headers[] = 'Signature: keyId="' . $owner['url'] . '#main-key' . '",algorithm="rsa-sha256",headers="(request-target) date content-length digest host",signature="' . $signature . '"';
+		$headers['Signature'] = 'keyId="' . $owner['url'] . '#main-key' . '",algorithm="rsa-sha256",headers="(request-target) date content-length digest host",signature="' . $signature . '"';
 
-		$headers[] = 'Content-Type: application/activity+json';
+		$headers['Content-Type'] = 'application/activity+json';
 
 		$postResult = DI::httpRequest()->post($target, $content, $headers);
 		$return_code = $postResult->getReturnCode();
@@ -409,10 +415,10 @@ class HTTPSignature
 	 *                         'nobody' => only return the header
 	 *                         'cookiejar' => path to cookie jar file
 	 *
-	 * @return CurlResult CurlResult
+	 * @return IHTTPResult CurlResult
 	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
 	 */
-	public static function fetchRaw($request, $uid = 0, $opts = ['accept_content' => 'application/activity+json, application/ld+json'])
+	public static function fetchRaw($request, $uid = 0, $opts = ['accept_content' => ['application/activity+json', 'application/ld+json']])
 	{
 		$header = [];
 
@@ -434,17 +440,14 @@ class HTTPSignature
 			$path = parse_url($request, PHP_URL_PATH);
 			$date = DateTimeFormat::utcNow(DateTimeFormat::HTTP);
 
-			$header = ['Date: ' . $date, 'Host: ' . $host];
+			$header['Date'] = $date;
+			$header['Host'] = $host;
 
 			$signed_data = "(request-target): get " . $path . "\ndate: ". $date . "\nhost: " . $host;
 
 			$signature = base64_encode(Crypto::rsaSign($signed_data, $owner['uprvkey'], 'sha256'));
 
-			$header[] = 'Signature: keyId="' . $owner['url'] . '#main-key' . '",algorithm="rsa-sha256",headers="(request-target) date host",signature="' . $signature . '"';
-		}
-
-		if (!empty($opts['accept_content'])) {
-			$header[] = 'Accept: ' . $opts['accept_content'];
+			$header['Signature'] = 'keyId="' . $owner['url'] . '#main-key' . '",algorithm="rsa-sha256",headers="(request-target) date host",signature="' . $signature . '"';
 		}
 
 		$curl_opts = $opts;
diff --git a/src/Worker/PubSubPublish.php b/src/Worker/PubSubPublish.php
index a5381c18d..a3e2ee4ad 100644
--- a/src/Worker/PubSubPublish.php
+++ b/src/Worker/PubSubPublish.php
@@ -59,11 +59,12 @@ class PubSubPublish
 
 		$hmac_sig = hash_hmac("sha1", $params, $subscriber['secret']);
 
-		$headers = ["Content-type: application/atom+xml",
-				sprintf("Link: <%s>;rel=hub,<%s>;rel=self",
+		$headers = [
+			'Content-type' => 'application/atom+xml',
+			'Link' => sprintf("<%s>;rel=hub,<%s>;rel=self",
 					DI::baseUrl() . '/pubsubhubbub/' . $subscriber['nickname'],
 					$subscriber['topic']),
-				"X-Hub-Signature: sha1=" . $hmac_sig];
+			'X-Hub-Signature' => 'sha1=' . $hmac_sig];
 
 		Logger::log('POST ' . print_r($headers, true) . "\n" . $params, Logger::DATA);