Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — dev-extbase-fluid (#770)
by
unknown
03:55
created

PageViewProxy::handleOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
/**
4
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
5
 *
6
 * This file is part of the Kitodo and TYPO3 projects.
7
 *
8
 * @license GNU General Public License version 3 or later.
9
 * For the full copyright and license information, please read the
10
 * LICENSE.txt file that was distributed with this source code.
11
 */
12
13
namespace Kitodo\Dlf\Plugin\Eid;
14
15
use Kitodo\Dlf\Common\Helper;
16
use Kitodo\Dlf\Common\StdOutStream;
17
use Psr\Http\Message\ResponseInterface;
18
use Psr\Http\Message\ServerRequestInterface;
19
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
20
use TYPO3\CMS\Core\Http\JsonResponse;
21
use TYPO3\CMS\Core\Http\RequestFactory;
22
use TYPO3\CMS\Core\Http\Response;
23
use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25
/**
26
 * eID image proxy for plugin 'Page View' of the 'dlf' extension
27
 *
28
 * Supported query parameters:
29
 * - `url` (mandatory): The URL to be proxied
30
 * - `uHash` (mandatory): HMAC of the URL
31
 *
32
 * @author Alexander Bigga <[email protected]>
33
 * @package TYPO3
34
 * @subpackage dlf
35
 * @access public
36
 */
37
class PageViewProxy
38
{
39
    /**
40
     * @var RequestFactory
41
     */
42
    protected $requestFactory;
43
44
    /**
45
     * @var mixed
46
     */
47
    protected $extConf;
48
49
    public function __construct()
50
    {
51
        $this->requestFactory = GeneralUtility::makeInstance(RequestFactory::class);
52
        $this->extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('dlf');
53
    }
54
55
    /**
56
     * Return a response that is derived from $response and contains CORS
57
     * headers to be sent to the client.
58
     *
59
     * @return ResponseInterface $response
60
     * @return ServerRequestInterface $request The incoming request.
61
     * @return ResponseInterface
62
     */
63
    protected function withCorsResponseHeaders(
64
        ResponseInterface $response,
65
        ServerRequestInterface $request
66
    ): ResponseInterface {
67
        $origin = (string) ($request->getHeaderLine('Origin') ?: '*');
68
69
        return $response
70
            ->withHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')
71
            ->withHeader('Access-Control-Allow-Origin', $origin)
72
            ->withHeader('Access-Control-Max-Age', '86400');
73
    }
74
75
    /**
76
     * Takes headers listed in $headerNames from $fromResponse, adds them to
77
     * $toResponse and returns the result.
78
     *
79
     * @param ResponseInterface $fromResponse
80
     * @param ResponseInterface $toResponse
81
     * @param array $headerNames
82
     * @return ResponseInterface
83
     */
84
    protected function copyHeaders(
85
        ResponseInterface $fromResponse,
86
        ResponseInterface $toResponse,
87
        array $headerNames
88
    ) {
89
        $result = $toResponse;
90
91
        foreach ($headerNames as $headerName) {
92
            $headerValues = $fromResponse->getHeader($headerName);
93
            $result = $result->withAddedHeader($headerName, $headerValues);
94
        }
95
96
        return $result;
97
    }
98
99
    /**
100
     * Handle an OPTIONS request.
101
     *
102
     * @param ServerRequestInterface $request
103
     * @return ResponseInterface
104
     */
105
    protected function handleOptions(ServerRequestInterface $request): ResponseInterface
106
    {
107
        // 204 No Content
108
        $response = GeneralUtility::makeInstance(Response::class)
109
            ->withStatus(204);
110
        return $this->withCorsResponseHeaders($response, $request);
111
    }
112
113
    /**
114
     * Handle a GET request.
115
     *
116
     * @param ServerRequestInterface $request
117
     * @return ResponseInterface
118
     */
119
    protected function handleGet(ServerRequestInterface $request): ResponseInterface
120
    {
121
        $queryParams = $request->getQueryParams();
122
123
        $url = (string) ($queryParams['url'] ?? '');
124
        if (!Helper::isValidHttpUrl($url)) {
125
            return new JsonResponse(['message' => 'Did not receive a valid URL.'], 400);
126
        }
127
128
        // get and verify the uHash
129
        $uHash = (string) ($queryParams['uHash'] ?? '');
130
        if (!hash_equals(GeneralUtility::hmac($url, 'PageViewProxy'), $uHash)) {
131
            return new JsonResponse(['message' => 'No valid uHash passed!'], 401);
132
        }
133
134
        try {
135
            $targetResponse = $this->requestFactory->request($url, 'GET', [
136
                'headers' => [
137
                    'User-Agent' => $this->extConf['useragent'] ?? 'Kitodo.Presentation Proxy',
138
                ],
139
140
                // For performance, don't download content up-front. Rather, we'll
141
                // download and upload simultaneously.
142
                // https://docs.guzzlephp.org/en/6.5/request-options.html#stream
143
                'stream' => true,
144
145
                // Don't throw exceptions when a non-success status code is
146
                // received. We handle these manually.
147
                'http_errors' => false,
148
            ]);
149
        } catch (\Exception $e) {
150
            return new JsonResponse(['message' => 'Could not fetch resource of given URL.'], 500);
151
        }
152
153
        $body = new StdOutStream($targetResponse->getBody());
154
155
        $clientResponse = GeneralUtility::makeInstance(Response::class)
156
            ->withStatus($targetResponse->getStatusCode())
157
            ->withBody($body);
158
159
        $clientResponse = $this->copyHeaders($targetResponse, $clientResponse, [
160
            'Content-Length',
161
            'Content-Type',
162
            'Last-Modified',
163
        ]);
164
165
        return $this->withCorsResponseHeaders($clientResponse, $request);
166
    }
167
168
    /**
169
     * The main method of the eID script
170
     *
171
     * @access public
172
     *
173
     * @param ServerRequestInterface $request
174
     * @return ResponseInterface
175
     */
176
    public function main(ServerRequestInterface $request)
177
    {
178
        switch ($request->getMethod()) {
179
            case 'OPTIONS':
180
                return $this->handleOptions($request);
181
182
            case 'GET':
183
                return $this->handleGet($request);
184
185
            default:
186
                // 405 Method Not Allowed
187
                return GeneralUtility::makeInstance(Response::class)
188
                    ->withStatus(405);
189
        }
190
    }
191
}
192