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) |
|
0 ignored issues
–
show
|
|||
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) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
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, |
||
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 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.