From 47e277d3be62b944e9517ea3687dfcf1354e6379 Mon Sep 17 00:00:00 2001
From: Jan-Hendrik Willms <tleilax+github@gmail.com>
Date: Fri, 31 Mar 2023 18:24:52 +0200
Subject: [PATCH] wip

---
 app/controllers/start.php                     |  11 +
 composer.json                                 |   6 +-
 composer.lock                                 | 588 ++++++++++++++----
 lib/classes/HttpFactory.php                   | 151 +++++
 .../Routes/Files/FileRefsContentShow.php      |   4 +-
 lib/classes/Siteinfo.php                      |   2 +-
 .../exportdocument/ExportPDF.class.php        |   6 +-
 .../librarysearch/LibrarySearch.class.php     |   8 +-
 lib/functions.php                             |  87 +++
 lib/models/OpenGraphURL.class.php             |  10 +-
 10 files changed, 732 insertions(+), 141 deletions(-)
 create mode 100644 lib/classes/HttpFactory.php

diff --git a/app/controllers/start.php b/app/controllers/start.php
index f47520297c1..b3bceaf41b5 100644
--- a/app/controllers/start.php
+++ b/app/controllers/start.php
@@ -43,6 +43,17 @@ class StartController extends AuthenticatedController
             WidgetHelper::setInitialPositions();
         }
 
+        dd(
+            url_get_headers('https://cataas.com/cat?json=true', true),
+            get_headers('https://cataas.com/cat?json=true', true)
+        );
+
+        $client = HttpFactory::get()->createHttpClient();
+        $response = $client->sendRequest(
+            $client->createRequest('GET', 'https://cataas.com/cat?json=true')
+        );
+        dd($response, $response->getBody()->getContents());
+
         $this->left = WidgetHelper::getUserWidgets($GLOBALS['user']->id, 0);
         $this->right = WidgetHelper::getUserWidgets($GLOBALS['user']->id, 1);
 
diff --git a/composer.json b/composer.json
index 6dd4252b1bf..bab6cd62bd8 100644
--- a/composer.json
+++ b/composer.json
@@ -18,7 +18,6 @@
     },
     "require": {
         "php": "^7.2",
-        "guzzlehttp/psr7": "^2.3",
         "neomerx/json-api": "4.0.1",
         "spomky-labs/otphp": "^10",
         "tuupola/cors-middleware": "^1.2.1",
@@ -59,7 +58,10 @@
         "symfony/polyfill-php73": "^1.27",
         "symfony/polyfill-php74": "^1.27",
         "symfony/polyfill-php80": "^1.27",
-        "symfony/polyfill-php81": "^1.27"
+        "symfony/polyfill-php81": "^1.27",
+        "symfony/http-client": "^5.4",
+        "nyholm/psr7": "^1.5",
+        "psr/http-client": "^1.0"
     },
     "replace": {
         "symfony/polyfill-php54": "*",
diff --git a/composer.lock b/composer.lock
index 93986c9d9e4..d4f250a09d8 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "d67f415c948520b9630c33c48bc3c668",
+    "content-hash": "d023a038b03872de5d6551ddba759780",
     "packages": [
         {
             "name": "algo26-matthias/idna-convert",
@@ -462,125 +462,6 @@
             "abandoned": "phpowermove/docblock",
             "time": "2017-07-01T18:10:54+00:00"
         },
-        {
-            "name": "guzzlehttp/psr7",
-            "version": "2.4.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/guzzle/psr7.git",
-                "reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/psr7/zipball/3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf",
-                "reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^7.2.5 || ^8.0",
-                "psr/http-factory": "^1.0",
-                "psr/http-message": "^1.0",
-                "ralouphie/getallheaders": "^3.0"
-            },
-            "provide": {
-                "psr/http-factory-implementation": "1.0",
-                "psr/http-message-implementation": "1.0"
-            },
-            "require-dev": {
-                "bamarni/composer-bin-plugin": "^1.8.1",
-                "http-interop/http-factory-tests": "^0.9",
-                "phpunit/phpunit": "^8.5.29 || ^9.5.23"
-            },
-            "suggest": {
-                "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
-            },
-            "type": "library",
-            "extra": {
-                "bamarni-bin": {
-                    "bin-links": true,
-                    "forward-command": false
-                },
-                "branch-alias": {
-                    "dev-master": "2.4-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "GuzzleHttp\\Psr7\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Graham Campbell",
-                    "email": "hello@gjcampbell.co.uk",
-                    "homepage": "https://github.com/GrahamCampbell"
-                },
-                {
-                    "name": "Michael Dowling",
-                    "email": "mtdowling@gmail.com",
-                    "homepage": "https://github.com/mtdowling"
-                },
-                {
-                    "name": "George Mponos",
-                    "email": "gmponos@gmail.com",
-                    "homepage": "https://github.com/gmponos"
-                },
-                {
-                    "name": "Tobias Nyholm",
-                    "email": "tobias.nyholm@gmail.com",
-                    "homepage": "https://github.com/Nyholm"
-                },
-                {
-                    "name": "Márk Sági-Kazár",
-                    "email": "mark.sagikazar@gmail.com",
-                    "homepage": "https://github.com/sagikazarmark"
-                },
-                {
-                    "name": "Tobias Schultze",
-                    "email": "webmaster@tubo-world.de",
-                    "homepage": "https://github.com/Tobion"
-                },
-                {
-                    "name": "Márk Sági-Kazár",
-                    "email": "mark.sagikazar@gmail.com",
-                    "homepage": "https://sagikazarmark.hu"
-                }
-            ],
-            "description": "PSR-7 message implementation that also provides common utility methods",
-            "keywords": [
-                "http",
-                "message",
-                "psr-7",
-                "request",
-                "response",
-                "stream",
-                "uri",
-                "url"
-            ],
-            "support": {
-                "issues": "https://github.com/guzzle/psr7/issues",
-                "source": "https://github.com/guzzle/psr7/tree/2.4.4"
-            },
-            "funding": [
-                {
-                    "url": "https://github.com/GrahamCampbell",
-                    "type": "github"
-                },
-                {
-                    "url": "https://github.com/Nyholm",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2023-03-09T13:19:02+00:00"
-        },
         {
             "name": "jakeasmith/http_build_url",
             "version": "1.0.1",
@@ -1494,6 +1375,83 @@
             },
             "time": "2018-02-13T20:26:39+00:00"
         },
+        {
+            "name": "nyholm/psr7",
+            "version": "1.5.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Nyholm/psr7.git",
+                "reference": "f734364e38a876a23be4d906a2a089e1315be18a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Nyholm/psr7/zipball/f734364e38a876a23be4d906a2a089e1315be18a",
+                "reference": "f734364e38a876a23be4d906a2a089e1315be18a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1",
+                "php-http/message-factory": "^1.0",
+                "psr/http-factory": "^1.0",
+                "psr/http-message": "^1.0"
+            },
+            "provide": {
+                "psr/http-factory-implementation": "1.0",
+                "psr/http-message-implementation": "1.0"
+            },
+            "require-dev": {
+                "http-interop/http-factory-tests": "^0.9",
+                "php-http/psr7-integration-tests": "^1.0",
+                "phpunit/phpunit": "^7.5 || 8.5 || 9.4",
+                "symfony/error-handler": "^4.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Nyholm\\Psr7\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com"
+                },
+                {
+                    "name": "Martijn van der Ven",
+                    "email": "martijn@vanderven.se"
+                }
+            ],
+            "description": "A fast PHP7 implementation of PSR-7",
+            "homepage": "https://tnyholm.se",
+            "keywords": [
+                "psr-17",
+                "psr-7"
+            ],
+            "support": {
+                "issues": "https://github.com/Nyholm/psr7/issues",
+                "source": "https://github.com/Nyholm/psr7/tree/1.5.1"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/Zegnat",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/nyholm",
+                    "type": "github"
+                }
+            ],
+            "time": "2022-06-22T07:13:36+00:00"
+        },
         {
             "name": "opis/closure",
             "version": "3.6.3",
@@ -2013,6 +1971,60 @@
             },
             "time": "2020-10-12T12:39:22+00:00"
         },
+        {
+            "name": "php-http/message-factory",
+            "version": "v1.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-http/message-factory.git",
+                "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1",
+                "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4",
+                "psr/http-message": "^1.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Http\\Message\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com"
+                }
+            ],
+            "description": "Factory interfaces for PSR-7 HTTP Message",
+            "homepage": "http://php-http.org",
+            "keywords": [
+                "factory",
+                "http",
+                "message",
+                "stream",
+                "uri"
+            ],
+            "support": {
+                "issues": "https://github.com/php-http/message-factory/issues",
+                "source": "https://github.com/php-http/message-factory/tree/master"
+            },
+            "time": "2015-12-19T14:08:53+00:00"
+        },
         {
             "name": "phpseclib/phpseclib",
             "version": "3.0.19",
@@ -2278,6 +2290,58 @@
             },
             "time": "2021-03-05T17:36:06+00:00"
         },
+        {
+            "name": "psr/http-client",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/http-client.git",
+                "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
+                "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0 || ^8.0",
+                "psr/http-message": "^1.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Client\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for HTTP clients",
+            "homepage": "https://github.com/php-fig/http-client",
+            "keywords": [
+                "http",
+                "http-client",
+                "psr",
+                "psr-18"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/http-client/tree/master"
+            },
+            "time": "2020-06-29T06:28:15+00:00"
+        },
         {
             "name": "psr/http-factory",
             "version": "1.0.1",
@@ -3110,6 +3174,171 @@
             ],
             "time": "2022-01-02T09:53:40+00:00"
         },
+        {
+            "name": "symfony/http-client",
+            "version": "v5.4.21",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/http-client.git",
+                "reference": "6b88914a7f1bf144df15904f60a19be78a67a3b2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/http-client/zipball/6b88914a7f1bf144df15904f60a19be78a67a3b2",
+                "reference": "6b88914a7f1bf144df15904f60a19be78a67a3b2",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2.5",
+                "psr/log": "^1|^2|^3",
+                "symfony/deprecation-contracts": "^2.1|^3",
+                "symfony/http-client-contracts": "^2.4",
+                "symfony/polyfill-php73": "^1.11",
+                "symfony/polyfill-php80": "^1.16",
+                "symfony/service-contracts": "^1.0|^2|^3"
+            },
+            "provide": {
+                "php-http/async-client-implementation": "*",
+                "php-http/client-implementation": "*",
+                "psr/http-client-implementation": "1.0",
+                "symfony/http-client-implementation": "2.4"
+            },
+            "require-dev": {
+                "amphp/amp": "^2.5",
+                "amphp/http-client": "^4.2.1",
+                "amphp/http-tunnel": "^1.0",
+                "amphp/socket": "^1.1",
+                "guzzlehttp/promises": "^1.4",
+                "nyholm/psr7": "^1.0",
+                "php-http/httplug": "^1.0|^2.0",
+                "psr/http-client": "^1.0",
+                "symfony/dependency-injection": "^4.4|^5.0|^6.0",
+                "symfony/http-kernel": "^4.4.13|^5.1.5|^6.0",
+                "symfony/process": "^4.4|^5.0|^6.0",
+                "symfony/stopwatch": "^4.4|^5.0|^6.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\HttpClient\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/http-client/tree/v5.4.21"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2023-02-17T21:35:35+00:00"
+        },
+        {
+            "name": "symfony/http-client-contracts",
+            "version": "v2.5.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/http-client-contracts.git",
+                "reference": "ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70",
+                "reference": "ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2.5"
+            },
+            "suggest": {
+                "symfony/http-client-implementation": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "2.5-dev"
+                },
+                "thanks": {
+                    "name": "symfony/contracts",
+                    "url": "https://github.com/symfony/contracts"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Contracts\\HttpClient\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Generic abstractions related to HTTP clients",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "abstractions",
+                "contracts",
+                "decoupling",
+                "interfaces",
+                "interoperability",
+                "standards"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.2"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-04-12T15:48:08+00:00"
+        },
         {
             "name": "symfony/polyfill-ctype",
             "version": "v1.26.0",
@@ -4936,6 +5165,125 @@
             ],
             "time": "2022-03-03T08:28:38+00:00"
         },
+        {
+            "name": "guzzlehttp/psr7",
+            "version": "2.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/psr7.git",
+                "reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/psr7/zipball/3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf",
+                "reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2.5 || ^8.0",
+                "psr/http-factory": "^1.0",
+                "psr/http-message": "^1.0",
+                "ralouphie/getallheaders": "^3.0"
+            },
+            "provide": {
+                "psr/http-factory-implementation": "1.0",
+                "psr/http-message-implementation": "1.0"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.1",
+                "http-interop/http-factory-tests": "^0.9",
+                "phpunit/phpunit": "^8.5.29 || ^9.5.23"
+            },
+            "suggest": {
+                "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                },
+                "branch-alias": {
+                    "dev-master": "2.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GuzzleHttp\\Psr7\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "George Mponos",
+                    "email": "gmponos@gmail.com",
+                    "homepage": "https://github.com/gmponos"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://github.com/sagikazarmark"
+                },
+                {
+                    "name": "Tobias Schultze",
+                    "email": "webmaster@tubo-world.de",
+                    "homepage": "https://github.com/Tobion"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://sagikazarmark.hu"
+                }
+            ],
+            "description": "PSR-7 message implementation that also provides common utility methods",
+            "keywords": [
+                "http",
+                "message",
+                "psr-7",
+                "request",
+                "response",
+                "stream",
+                "uri",
+                "url"
+            ],
+            "support": {
+                "issues": "https://github.com/guzzle/psr7/issues",
+                "source": "https://github.com/guzzle/psr7/tree/2.4.4"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/Nyholm",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2023-03-09T13:19:02+00:00"
+        },
         {
             "name": "myclabs/deep-copy",
             "version": "1.11.0",
diff --git a/lib/classes/HttpFactory.php b/lib/classes/HttpFactory.php
new file mode 100644
index 00000000000..469e4473e10
--- /dev/null
+++ b/lib/classes/HttpFactory.php
@@ -0,0 +1,151 @@
+<?php
+
+use Psr\Http\Client\ClientInterface;
+use Psr\Http\Message\RequestFactoryInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseFactoryInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestFactoryInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\StreamFactoryInterface;
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UploadedFileFactoryInterface;
+use Psr\Http\Message\UploadedFileInterface;
+use Psr\Http\Message\UriFactoryInterface;
+use Psr\Http\Message\UriInterface;
+
+use Slim\Psr7\Factory\RequestFactory;
+use Slim\Psr7\Factory\ResponseFactory;
+use Slim\Psr7\Factory\ServerRequestFactory;
+use Slim\Psr7\Factory\StreamFactory;
+use Slim\Psr7\Factory\UploadedFileFactory;
+use Slim\Psr7\Factory\UriFactory;
+use Symfony\Component\HttpClient\HttpClient as SymfonyHttpClient;
+use Symfony\Component\HttpClient\Psr18Client;
+
+final class HttpFactory implements
+    RequestFactoryInterface,
+    ResponseFactoryInterface,
+    ServerRequestFactoryInterface,
+    StreamFactoryInterface,
+    UploadedFileFactoryInterface,
+    UriFactoryInterface
+{
+    private static $instance = null;
+
+    public static function get(): HttpFactory
+    {
+        if (self::$instance === null) {
+            self::$instance = new self();
+        }
+        return self::$instance;
+    }
+
+
+    public function createRequest(string $method, $uri): RequestInterface
+    {
+        return $this->getRequestFactory()->createRequest($method, $uri);
+    }
+
+    public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface
+    {
+        $factory = $this->getResponseFactory();
+        return $factory->createResponse($code, $reasonPhrase);
+    }
+
+    public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface
+    {
+        return $this->getServerRequestFactory()->createServerRequest($method, $uri, $serverParams);
+    }
+
+    public function createStream(string $content = ''): StreamInterface
+    {
+        return $this->getStreamFactory()->createStream($content);
+    }
+
+    public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface
+    {
+        return $this->getStreamFactory()->createStreamFromFile($filename, $mode);
+    }
+
+    public function createStreamFromResource($resource): StreamInterface
+    {
+        return $this->getStreamFactory()->createStreamFromResource($resource);
+    }
+
+    public function createUploadedFile(
+        StreamInterface $stream,
+        int $size = null,
+        int $error = \UPLOAD_ERR_OK,
+        string $clientFilename = null,
+        string $clientMediaType = null
+    ): UploadedFileInterface {
+        $factory = $this->getUploadedFileFactory();
+        return $factory->createUploadedFile($stream, $size, $error, $clientFilename, $clientMediaType);
+    }
+
+    public function createUri(string $uri = ''): UriInterface
+    {
+        return $this->getUriFactory()->createUri($uri);
+    }
+
+    public function createHttpClient(): ClientInterface
+    {
+        $options = [];
+
+        // Respect proxy
+        $proxy = Config::get()->getValue('HTTP_PROXY');
+        if ($proxy) {
+            $options['proxy'] = "http://{$proxy}";
+
+            $ignore = Config::get()->getValue('HTTP_PROXY_IGNORE');
+            $ignore = trim($ignore);
+            if ($ignore) {
+                $options['no_proxy'] = $ignore;
+            }
+        }
+
+        $client = SymfonyHttpClient::create($options);
+        return new Psr18Client(
+            $client,
+            $this->getResponseFactory(),
+            $this->getStreamFactory()
+        );
+    }
+
+    private function getRequestFactory(): RequestFactory
+    {
+        return new RequestFactory(
+            $this->getStreamFactory(),
+            $this->getUriFactory()
+        );
+    }
+
+    private function getResponseFactory(): ResponseFactory
+    {
+        return new ResponseFactory();
+    }
+
+    private function getServerRequestFactory(): ServerRequestFactory
+    {
+        return new ServerRequestFactory(
+            $this->getStreamFactory(),
+            $this->getUriFactory()
+        );
+    }
+
+    private function getStreamFactory(): StreamFactory
+    {
+        return new StreamFactory();
+    }
+
+    private function getUploadedFileFactory(): UploadedFileFactory
+    {
+        return new Slim\Psr7\Factory\UploadedFileFactory();
+    }
+
+    private function getUriFactory(): UriFactory
+    {
+        return new UriFactory();
+    }
+}
diff --git a/lib/classes/JsonApi/Routes/Files/FileRefsContentShow.php b/lib/classes/JsonApi/Routes/Files/FileRefsContentShow.php
index e2d19c4a95b..f5f3e8c26e8 100644
--- a/lib/classes/JsonApi/Routes/Files/FileRefsContentShow.php
+++ b/lib/classes/JsonApi/Routes/Files/FileRefsContentShow.php
@@ -6,7 +6,6 @@ use JsonApi\Errors\AuthorizationFailedException;
 use JsonApi\Errors\InternalServerError;
 use JsonApi\Errors\RecordNotFoundException;
 use JsonApi\NonJsonApiController;
-use GuzzleHttp\Psr7;
 use Psr\Http\Message\ResponseInterface as Response;
 use Psr\Http\Message\ServerRequestInterface as Request;
 
@@ -114,7 +113,8 @@ class FileRefsContentShow extends NonJsonApiController
 
         $fileRef->incrementDownloadCounter();
 
-        $stream = Psr7\Utils::streamFor(fopen($pathFile, 'rb'));
+
+        $stream = \HttpFactory::get()->createStreamFromFile($pathFile, 'rb');
 
         return $response->withBody($stream);
     }
diff --git a/lib/classes/Siteinfo.php b/lib/classes/Siteinfo.php
index b17d611074d..985a05db2c9 100644
--- a/lib/classes/Siteinfo.php
+++ b/lib/classes/Siteinfo.php
@@ -353,7 +353,7 @@ class SiteinfoMarkupEngine {
     function coregroup() {
         $cache = StudipCacheFactory::getCache();
         if (!($remotefile = $cache->read('coregroup'))) {
-            $remotefile = file_get_contents('https://develop.studip.de/studip/extern.php?module=Persons&config_id=8d1dafc3afca2bce6125d57d4119b631&range_id=4498a5bc62d7974d0a0ac3e97aca5296', false, get_default_http_stream_context('https://develop.studip.de'));
+            $remotefile = url_get_contents('https://develop.studip.de/studip/extern.php?module=Persons&config_id=8d1dafc3afca2bce6125d57d4119b631&range_id=4498a5bc62d7974d0a0ac3e97aca5296');
             $cache->write('coregroup', $remotefile);
         }
         return str_replace(['class="normal"', 'align="left"'], ['', ''], $remotefile);
diff --git a/lib/classes/exportdocument/ExportPDF.class.php b/lib/classes/exportdocument/ExportPDF.class.php
index cb2c87eacf4..d78e8284515 100644
--- a/lib/classes/exportdocument/ExportPDF.class.php
+++ b/lib/classes/exportdocument/ExportPDF.class.php
@@ -112,10 +112,10 @@ class ExportPDF extends TCPDF implements ExportDocument {
 
             // Fetch headers from url, handle possible redirects
             do {
-                $headers = get_headers($url, true, get_default_http_stream_context($url));
+                $headers = url_get_headers($url, true);
                 list(, $status) = explode(' ', $headers[0]);
 
-                $url = $headers['Location'] ?: $headers['location'] ?: $url;
+                $url = $headers['Location'] ?? $headers['location'] ?? $url;
             } while (in_array($status, [300, 301, 302, 303, 305, 307]));
 
             $status = $status ?: 404;
@@ -336,7 +336,7 @@ class ExportPDF extends TCPDF implements ExportDocument {
         }
 
         $src = 'src=""';
-        $file_content = @file_get_contents($convurl, false, get_default_http_stream_context($convurl));
+        $file_content = url_get_contents($convurl);
         if ($file_content) {
             $img_size = @getimagesizefromstring($file_content);
             if (is_array($img_size) && $img_size[0] > 0) {
diff --git a/lib/classes/librarysearch/LibrarySearch.class.php b/lib/classes/librarysearch/LibrarySearch.class.php
index 473eacfbdc5..d5d2f2b5094 100644
--- a/lib/classes/librarysearch/LibrarySearch.class.php
+++ b/lib/classes/librarysearch/LibrarySearch.class.php
@@ -114,13 +114,9 @@ abstract class LibrarySearch
         if (!$base_url) {
             return false;
         }
-        $full_url = $base_url;
-        if ($url_parameters) {
-            $full_url .= '?' . http_build_query($url_parameters);
-        }
 
-        $data = file_get_contents($full_url, false, get_default_http_stream_context($base_url));
-        return $data;
+        $url = URLHelper::getURL($base_url, $url_parameters);
+        return url_get_contents($url);
     }
 
 
diff --git a/lib/functions.php b/lib/functions.php
index 144b6f580ff..2a030b0e67a 100644
--- a/lib/functions.php
+++ b/lib/functions.php
@@ -1834,6 +1834,93 @@ function get_default_http_stream_context($url = '')
     return stream_context_get_default($opts);
 }
 
+/**
+ * @param string $uri
+ * @param array $options
+ * @return \Psr\Http\Message\ResponseInterface|false
+ */
+function fetch_url_response(string $uri, array $options = [])
+{
+    try {
+        // Get client
+        $client = HttpFactory::get()->createHttpClient();
+
+        // Create request
+        $request = $client->createRequest('GET', $uri);
+
+        if (isset($options['headers']) && is_array($options['headers'])) {
+            foreach ($options['headers'] as $key => $value) {
+                $request = $request->withHeader($key, $value);
+            }
+        }
+
+        // Return response
+        return $client->sendRequest($request);
+    } catch (\Psr\Http\Client\ClientExceptionInterface $e) {
+        return false;
+    }
+}
+
+/**
+ * @param string $uri
+ * @param array $options
+ * @return string|false
+ */
+function url_get_contents(string $uri, array $options = [])
+{
+    $response = fetch_url_response($uri, $options);
+    if ($response === false) {
+        return false;
+    }
+
+    return $response->getBody()->getContents();
+}
+
+/**
+ * @param string $uri
+ * @param bool $associative
+ * @param array $options
+ * @return array|false
+ */
+function url_get_headers(string $uri, bool $associative = false, array $options = [])
+{
+    $response = fetch_url_response($uri, $options);
+    if ($response === false) {
+        return false;
+    }
+
+    $headers = [];
+    foreach ($response->getHeaders() as $key => $value) {
+        $key = ucwords($key, '-');
+        if (count($value) === 1) {
+            $value = array_values($value)[0];
+        }
+
+        $headers[$key] = $value;
+    }
+
+    array_unshift(
+        $headers,
+        "HTTP/{$response->getProtocolVersion()} {$response->getStatusCode()} {$response->getReasonPhrase()}",
+    );
+
+    if ($associative) {
+        return $headers;
+    }
+
+    $result = [];
+    array_map(
+        function ($key, $value) use (&$result) {
+            foreach ((array) $value as $line) {
+                $result[] = $key ? "{$key}: {$line}" : $line;
+            }
+        },
+        array_keys($headers),
+        array_values($headers)
+    );
+    return $result;
+}
+
 /**
  * Encodes an uri just like encodeURI() in Javascript would do.
  *
diff --git a/lib/models/OpenGraphURL.class.php b/lib/models/OpenGraphURL.class.php
index 62eecc45145..8428ca8a28a 100644
--- a/lib/models/OpenGraphURL.class.php
+++ b/lib/models/OpenGraphURL.class.php
@@ -166,16 +166,12 @@ class OpenGraphURL extends SimpleORMap
                 $currentEncoding = 'UTF-8';
             }
 
-            $context = get_default_http_stream_context($this['url']);
-            stream_context_set_option($context, [
-                'http' => [
-                    'method' => 'GET',
-                    'header' => sprintf("User-Agent: Stud.IP v%s OpenGraph Parser\r\n", $GLOBALS['SOFTWARE_VERSION']),
+            $content = url_get_contents($this['url'], [
+                'headers' => [
+                    'User-Agent' => "Stud.IP v{$GLOBALS['SOFTWARE_VERSION']} OpenGraph Parser",
                 ],
             ]);
 
-            $content = @file_get_contents($this['url'], false, $context);
-
             if ($content === false) {
                 return;
             }
-- 
GitLab