Completed
Pull Request — master (#184)
by
unknown
04:28
created

Request::setRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 3
cp 0
crap 2
rs 10
1
<?php
2
3
namespace TusPhp;
4
5
use TusPhp\Tus\Server;
6
use Symfony\Component\HttpFoundation\Request as HttpRequest;
7
8
class Request
9
{
10
    /** @var HttpRequest */
11
    protected $request;
12
13
    /**
14
     * Request constructor.
15
     */
16 1
    public function __construct()
17
    {
18 1
        if (null === $this->request) {
19 1
            $this->request = HttpRequest::createFromGlobals();
20
        }
21 1
    }
22
23
    /**
24
     * Set the request
25
     *
26
     * @param \Symfony\Component\HttpFoundation\Request $request
27
     * @return \TusPhp\Request
28
     */
29
    public function setRequest(HttpRequest $request): self
30
    {
31
        $this->request = $request;
32
33
        return $this;
34
    }
35
36
    /**
37
     * Get http method from current request.
38
     *
39
     * @return string
40
     */
41 1
    public function method() : string
42
    {
43 1
        return $this->request->getMethod();
44
    }
45
46
    /**
47
     * Get the current path info for the request.
48
     *
49
     * @return string
50
     */
51 1
    public function path() : string
52
    {
53 1
        return $this->request->getPathInfo();
54
    }
55
56
    /**
57
     * Get upload key from url.
58
     *
59
     * @return string
60
     */
61 1
    public function key() : string
62
    {
63 1
        return basename($this->path());
64
    }
65
66
    /**
67
     * Supported http requests.
68
     *
69
     * @return array
70
     */
71 1
    public function allowedHttpVerbs() : array
72
    {
73
        return [
74 1
            HttpRequest::METHOD_GET,
75 1
            HttpRequest::METHOD_POST,
76 1
            HttpRequest::METHOD_PATCH,
77 1
            HttpRequest::METHOD_DELETE,
78 1
            HttpRequest::METHOD_HEAD,
79 1
            HttpRequest::METHOD_OPTIONS,
80
        ];
81
    }
82
83
    /**
84
     * Retrieve a header from the request.
85
     *
86
     * @param string               $key
87
     * @param string|string[]|null $default
88
     *
89
     * @return string|null
90
     */
91 1
    public function header(string $key, $default = null)
92
    {
93 1
        return $this->request->headers->get($key, $default);
0 ignored issues
show
Bug introduced by
It seems like $default can also be of type string[]; however, parameter $default of Symfony\Component\HttpFoundation\HeaderBag::get() does only seem to accept null|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

93
        return $this->request->headers->get($key, /** @scrutinizer ignore-type */ $default);
Loading history...
94
    }
95
96
    /**
97
     * Get the root URL for the request.
98
     *
99
     * @return string
100
     */
101 1
    public function url() : string
102
    {
103 1
        return rtrim($this->request->getUriForPath('/'), '/');
104
    }
105
106
    /**
107
     * Extract metadata from header.
108
     *
109
     * @param string $key
110
     * @param string $value
111
     *
112
     * @return array
113
     */
114 2
    public function extractFromHeader(string $key, string $value) : array
115
    {
116 2
        $meta = $this->header($key);
117
118 2
        if (false !== strpos($meta, $value)) {
119 2
            $meta = trim(str_replace($value, '', $meta));
120
121 2
            return explode(' ', $meta) ?? [];
122
        }
123
124 1
        return [];
125
    }
126
127
    /**
128
     * Extract base64 encoded filename from header.
129
     *
130
     * @return string
131
     */
132 3
    public function extractFileName() : string
133
    {
134 3
        $name = $this->extractMeta('name') ?: $this->extractMeta('filename');
135
136 3
        if ( ! $this->isValidFilename($name)) {
137 1
            return '';
138
        }
139
140 2
        return $name;
141
    }
142
143
    /**
144
     * Extracts the meta data from the request header.
145
     *
146
     * @param string $requestedKey
147
     *
148
     * @return string
149
     */
150 4
    public function extractMeta(string $requestedKey) : string
151
    {
152 4
        $uploadMetaData = $this->request->headers->get('Upload-Metadata');
153
154 4
        if (empty($uploadMetaData)) {
155 1
            return '';
156
        }
157
158 3
        $uploadMetaDataChunks = explode(',', $uploadMetaData);
159
160 3
        foreach ($uploadMetaDataChunks as $chunk) {
161 3
            list($key, $value) = explode(' ', $chunk);
162
163 3
            if ($key === $requestedKey) {
164 3
                return base64_decode($value);
165
            }
166
        }
167
168 1
        return '';
169
    }
170
171
    /**
172
     * Extracts all meta data from the request header.
173
     *
174
     * @return string[]
175
     */
176
    public function extractAllMeta() : array
177
    {
178
        $uploadMetaData = $this->request->headers->get('Upload-Metadata');
179
180
        if (empty($uploadMetaData)) {
181
            return [];
182
        }
183
184
        $uploadMetaDataChunks = explode(',', $uploadMetaData);
185
186
        $result = [];
187
        foreach ($uploadMetaDataChunks as $chunk) {
188
            list($key, $value) = explode(' ', $chunk);
189
190
            $result[$key] = base64_decode($value);
191
        }
192
193
        return $result;
194
    }
195
196
    /**
197
     * Extract partials from header.
198
     *
199
     * @return array
200
     */
201 1
    public function extractPartials() : array
202
    {
203 1
        return $this->extractFromHeader('Upload-Concat', Server::UPLOAD_TYPE_FINAL . ';');
204
    }
205
206
    /**
207
     * Check if this is a partial upload request.
208
     *
209
     * @return bool
210
     */
211 1
    public function isPartial() : bool
212
    {
213 1
        return Server::UPLOAD_TYPE_PARTIAL === $this->header('Upload-Concat');
214
    }
215
216
    /**
217
     * Check if this is a final concatenation request.
218
     *
219
     * @return bool
220
     */
221 1
    public function isFinal() : bool
222
    {
223 1
        return false !== strpos($this->header('Upload-Concat'), Server::UPLOAD_TYPE_FINAL . ';');
224
    }
225
226
    /**
227
     * Get request.
228
     *
229
     * @return HttpRequest
230
     */
231 1
    public function getRequest() : HttpRequest
232
    {
233 1
        return $this->request;
234
    }
235
236
    /**
237
     * Validate file name.
238
     *
239
     * @param string $filename
240
     *
241
     * @return bool
242
     */
243 2
    protected function isValidFilename(string $filename) : bool
244
    {
245 2
        $forbidden = ['../', '"', "'", '&', '/', '\\', '?', '#', ':'];
246
247 2
        foreach ($forbidden as $char) {
248 2
            if (false !== strpos($filename, $char)) {
249 1
                return false;
250
            }
251
        }
252
253 1
        return true;
254
    }
255
}
256