This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace League\Flysystem\Azure; |
||
4 | |||
5 | use League\Flysystem\Adapter\AbstractAdapter; |
||
6 | use League\Flysystem\Adapter\Polyfill\NotSupportingVisibilityTrait; |
||
7 | use League\Flysystem\Config; |
||
8 | use League\Flysystem\Util; |
||
9 | use MicrosoftAzure\Storage\Blob\Internal\IBlob; |
||
10 | use MicrosoftAzure\Storage\Blob\Models\BlobPrefix; |
||
11 | use MicrosoftAzure\Storage\Blob\Models\BlobProperties; |
||
12 | use MicrosoftAzure\Storage\Blob\Models\CopyBlobResult; |
||
13 | use MicrosoftAzure\Storage\Blob\Models\CreateBlobOptions; |
||
14 | use MicrosoftAzure\Storage\Blob\Models\ListBlobsOptions; |
||
15 | use MicrosoftAzure\Storage\Blob\Models\ListBlobsResult; |
||
16 | use MicrosoftAzure\Storage\Common\ServiceException; |
||
17 | |||
18 | class AzureAdapter extends AbstractAdapter |
||
19 | { |
||
20 | use NotSupportingVisibilityTrait; |
||
21 | |||
22 | /** |
||
23 | * @var string |
||
24 | */ |
||
25 | protected $container; |
||
26 | |||
27 | /** |
||
28 | * @var IBlob |
||
29 | */ |
||
30 | protected $client; |
||
31 | |||
32 | /** |
||
33 | * @var string[] |
||
34 | */ |
||
35 | protected static $metaOptions = [ |
||
36 | 'CacheControl', |
||
37 | 'ContentType', |
||
38 | 'Metadata', |
||
39 | 'ContentLanguage', |
||
40 | 'ContentEncoding', |
||
41 | ]; |
||
42 | |||
43 | /** |
||
44 | * Constructor. |
||
45 | * |
||
46 | * @param IBlob $azureClient |
||
47 | * @param string $container |
||
48 | * @param string $prefix |
||
49 | */ |
||
50 | public function __construct(IBlob $azureClient, $container, $prefix = null) |
||
51 | { |
||
52 | $this->client = $azureClient; |
||
53 | $this->container = $container; |
||
54 | $this->setPathPrefix($prefix); |
||
55 | } |
||
56 | |||
57 | /** |
||
58 | * {@inheritdoc} |
||
59 | */ |
||
60 | public function write($path, $contents, Config $config) |
||
61 | { |
||
62 | return $this->upload($path, $contents, $config); |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * {@inheritdoc} |
||
67 | */ |
||
68 | public function writeStream($path, $resource, Config $config) |
||
69 | { |
||
70 | return $this->upload($path, $resource, $config); |
||
71 | } |
||
72 | |||
73 | /** |
||
74 | * {@inheritdoc} |
||
75 | */ |
||
76 | public function update($path, $contents, Config $config) |
||
77 | { |
||
78 | return $this->upload($path, $contents, $config); |
||
79 | } |
||
80 | |||
81 | /** |
||
82 | * {@inheritdoc} |
||
83 | */ |
||
84 | public function updateStream($path, $resource, Config $config) |
||
85 | { |
||
86 | return $this->upload($path, $resource, $config); |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * {@inheritdoc} |
||
91 | */ |
||
92 | public function rename($path, $newpath) |
||
93 | { |
||
94 | $this->copy($path, $newpath); |
||
95 | |||
96 | return $this->delete($path); |
||
97 | } |
||
98 | |||
99 | public function copy($path, $newpath) |
||
100 | { |
||
101 | $path = $this->applyPathPrefix($path); |
||
102 | $newpath = $this->applyPathPrefix($newpath); |
||
103 | |||
104 | $this->client->copyBlob($this->container, $newpath, $this->container, $path); |
||
105 | |||
106 | return true; |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * {@inheritdoc} |
||
111 | */ |
||
112 | public function delete($path) |
||
113 | { |
||
114 | $path = $this->applyPathPrefix($path); |
||
115 | |||
116 | $this->client->deleteBlob($this->container, $path); |
||
117 | |||
118 | return true; |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * {@inheritdoc} |
||
123 | */ |
||
124 | public function deleteDir($dirname) |
||
125 | { |
||
126 | $dirname = $this->applyPathPrefix($dirname); |
||
127 | |||
128 | $options = new ListBlobsOptions(); |
||
129 | $options->setPrefix($dirname . '/'); |
||
130 | |||
131 | /** @var ListBlobsResult $listResults */ |
||
132 | $listResults = $this->client->listBlobs($this->container, $options); |
||
133 | |||
134 | foreach ($listResults->getBlobs() as $blob) { |
||
135 | /** @var \MicrosoftAzure\Storage\Blob\Models\Blob $blob */ |
||
136 | $this->client->deleteBlob($this->container, $blob->getName()); |
||
137 | } |
||
138 | |||
139 | return true; |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * {@inheritdoc} |
||
144 | */ |
||
145 | public function createDir($dirname, Config $config) |
||
146 | { |
||
147 | $this->write(rtrim($dirname, '/') . '/', ' ', $config); |
||
148 | |||
149 | return ['path' => $dirname, 'type' => 'dir']; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * {@inheritdoc} |
||
154 | */ |
||
155 | public function has($path) |
||
156 | { |
||
157 | $path = $this->applyPathPrefix($path); |
||
158 | |||
159 | try { |
||
160 | $this->client->getBlobMetadata($this->container, $path); |
||
161 | } catch (ServiceException $e) { |
||
162 | if ($e->getCode() !== 404) { |
||
163 | throw $e; |
||
164 | } |
||
165 | |||
166 | return false; |
||
167 | } |
||
168 | |||
169 | return true; |
||
170 | } |
||
171 | |||
172 | /** |
||
173 | * {@inheritdoc} |
||
174 | */ |
||
175 | View Code Duplication | public function read($path) |
|
176 | { |
||
177 | $path = $this->applyPathPrefix($path); |
||
178 | |||
179 | /** @var \MicrosoftAzure\Storage\Blob\Models\GetBlobResult $blobResult */ |
||
180 | $blobResult = $this->client->getBlob($this->container, $path); |
||
181 | $properties = $blobResult->getProperties(); |
||
182 | $content = $this->streamContentsToString($blobResult->getContentStream()); |
||
183 | |||
184 | return $this->normalizeBlobProperties($path, $properties) + ['contents' => $content]; |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * {@inheritdoc} |
||
189 | */ |
||
190 | View Code Duplication | public function readStream($path) |
|
191 | { |
||
192 | $path = $this->applyPathPrefix($path); |
||
193 | |||
194 | /** @var \MicrosoftAzure\Storage\Blob\Models\GetBlobResult $blobResult */ |
||
195 | $blobResult = $this->client->getBlob($this->container, $path); |
||
196 | $properties = $blobResult->getProperties(); |
||
197 | |||
198 | return $this->normalizeBlobProperties($path, $properties) + ['stream' => $blobResult->getContentStream()]; |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * {@inheritdoc} |
||
203 | */ |
||
204 | public function listContents($directory = '', $recursive = false) |
||
205 | { |
||
206 | $directory = $this->applyPathPrefix($directory); |
||
207 | |||
208 | // Append trailing slash only for directory other than root (which after normalization is an empty string). |
||
209 | // Listing for / doesn't work properly otherwise. |
||
210 | if (strlen($directory)) { |
||
211 | $directory = rtrim($directory, '/') . '/'; |
||
212 | } |
||
213 | |||
214 | $options = new ListBlobsOptions(); |
||
215 | $options->setPrefix($directory); |
||
216 | |||
217 | if ( ! $recursive) { |
||
218 | $options->setDelimiter('/'); |
||
219 | } |
||
220 | |||
221 | /** @var ListBlobsResult $listResults */ |
||
222 | $listResults = $this->client->listBlobs($this->container, $options); |
||
223 | |||
224 | $contents = []; |
||
225 | |||
226 | foreach ($listResults->getBlobs() as $blob) { |
||
227 | $contents[] = $this->normalizeBlobProperties($blob->getName(), $blob->getProperties()); |
||
228 | } |
||
229 | |||
230 | if ( ! $recursive) { |
||
231 | $contents = array_merge( |
||
232 | $contents, |
||
233 | array_map([$this, 'normalizeBlobPrefix'], $listResults->getBlobPrefixes()) |
||
234 | ); |
||
235 | } |
||
236 | |||
237 | return Util::emulateDirectories($contents); |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * {@inheritdoc} |
||
242 | */ |
||
243 | public function getMetadata($path) |
||
244 | { |
||
245 | $path = $this->applyPathPrefix($path); |
||
246 | |||
247 | /** @var \MicrosoftAzure\Storage\Blob\Models\GetBlobPropertiesResult $result */ |
||
248 | $result = $this->client->getBlobProperties($this->container, $path); |
||
249 | |||
250 | return $this->normalizeBlobProperties($path, $result->getProperties()); |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * {@inheritdoc} |
||
255 | */ |
||
256 | public function getSize($path) |
||
257 | { |
||
258 | return $this->getMetadata($path); |
||
259 | } |
||
260 | |||
261 | /** |
||
262 | * {@inheritdoc} |
||
263 | */ |
||
264 | public function getMimetype($path) |
||
265 | { |
||
266 | return $this->getMetadata($path); |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * {@inheritdoc} |
||
271 | */ |
||
272 | public function getTimestamp($path) |
||
273 | { |
||
274 | return $this->getMetadata($path); |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * Builds the normalized output array. |
||
279 | * |
||
280 | * @param string $path |
||
281 | * @param int $timestamp |
||
282 | * @param mixed $content |
||
283 | * |
||
284 | * @return array |
||
285 | */ |
||
286 | protected function normalize($path, $timestamp, $content = null) |
||
287 | { |
||
288 | $data = [ |
||
289 | 'path' => $path, |
||
290 | 'timestamp' => (int) $timestamp, |
||
291 | 'dirname' => Util::dirname($path), |
||
292 | 'type' => 'file', |
||
293 | ]; |
||
294 | |||
295 | if (is_string($content)) { |
||
296 | $data['contents'] = $content; |
||
297 | } |
||
298 | |||
299 | return $data; |
||
300 | } |
||
301 | |||
302 | /** |
||
303 | * Builds the normalized output array from a Blob object. |
||
304 | * |
||
305 | * @param string $path |
||
306 | * @param BlobProperties $properties |
||
307 | * |
||
308 | * @return array |
||
309 | */ |
||
310 | protected function normalizeBlobProperties($path, BlobProperties $properties) |
||
311 | { |
||
312 | if (substr($path, -1) === '/') { |
||
313 | return ['type' => 'dir', 'path' => $this->removePathPrefix(rtrim($path, '/'))]; |
||
314 | } |
||
315 | |||
316 | $path = $this->removePathPrefix($path); |
||
317 | |||
318 | return [ |
||
319 | 'path' => $path, |
||
320 | 'timestamp' => (int) $properties->getLastModified()->format('U'), |
||
321 | 'dirname' => Util::dirname($path), |
||
322 | 'mimetype' => $properties->getContentType(), |
||
323 | 'size' => $properties->getContentLength(), |
||
324 | 'type' => 'file', |
||
325 | ]; |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * Builds the normalized output array from a BlobPrefix object. |
||
330 | * |
||
331 | * @param BlobPrefix $blobPrefix |
||
332 | * |
||
333 | * @return array |
||
334 | */ |
||
335 | protected function normalizeBlobPrefix(BlobPrefix $blobPrefix) |
||
336 | { |
||
337 | return ['type' => 'dir', 'path' => $this->removePathPrefix(rtrim($blobPrefix->getName(), '/'))]; |
||
338 | } |
||
339 | |||
340 | /** |
||
341 | * Retrieves content streamed by Azure into a string. |
||
342 | * |
||
343 | * @param resource $resource |
||
344 | * |
||
345 | * @return string |
||
346 | */ |
||
347 | protected function streamContentsToString($resource) |
||
348 | { |
||
349 | return stream_get_contents($resource); |
||
350 | } |
||
351 | |||
352 | /** |
||
353 | * Upload a file. |
||
354 | * |
||
355 | * @param string $path Path |
||
356 | * @param string|resource $contents Either a string or a stream. |
||
357 | * @param Config $config Config |
||
358 | * |
||
359 | * @return array |
||
360 | */ |
||
361 | protected function upload($path, $contents, Config $config) |
||
362 | { |
||
363 | $path = $this->applyPathPrefix($path); |
||
364 | |||
365 | /** @var CopyBlobResult $result */ |
||
366 | $result = $this->client->createBlockBlob( |
||
367 | $this->container, |
||
368 | $path, |
||
369 | $contents, |
||
0 ignored issues
–
show
|
|||
370 | $this->getOptionsFromConfig($config) |
||
371 | ); |
||
372 | |||
373 | return $this->normalize($path, $result->getLastModified()->format('U'), $contents); |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * Retrieve options from a Config instance. |
||
378 | * |
||
379 | * @param Config $config |
||
380 | * |
||
381 | * @return CreateBlobOptions |
||
382 | */ |
||
383 | protected function getOptionsFromConfig(Config $config) |
||
384 | { |
||
385 | $options = new CreateBlobOptions(); |
||
386 | |||
387 | foreach (static::$metaOptions as $option) { |
||
388 | if ( ! $config->has($option)) { |
||
389 | continue; |
||
390 | } |
||
391 | |||
392 | call_user_func([$options, "set$option"], $config->get($option)); |
||
393 | } |
||
394 | |||
395 | if ($mimetype = $config->get('mimetype')) { |
||
396 | $options->setContentType($mimetype); |
||
397 | } |
||
398 | |||
399 | return $options; |
||
400 | } |
||
401 | } |
||
402 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.