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 | elFinder::$netDrivers['onedrive'] = 'OneDrive'; |
||
4 | |||
5 | /** |
||
6 | * Simple elFinder driver for OneDrive |
||
7 | * onedrive api v5.0. |
||
8 | * |
||
9 | * @author Dmitry (dio) Levashov |
||
10 | * @author Cem (discofever) |
||
11 | **/ |
||
12 | class elFinderVolumeOneDrive extends elFinderVolumeDriver |
||
13 | { |
||
14 | /** |
||
15 | * @var string The base URL for API requests |
||
16 | **/ |
||
17 | const API_URL = 'https://api.onedrive.com/v1.0/drive/items/'; |
||
18 | |||
19 | /** |
||
20 | * @var string The base URL for authorization requests |
||
21 | */ |
||
22 | const AUTH_URL = 'https://login.live.com/oauth20_authorize.srf'; |
||
23 | |||
24 | /** |
||
25 | * @var string The base URL for token requests |
||
26 | */ |
||
27 | const TOKEN_URL = 'https://login.live.com/oauth20_token.srf'; |
||
28 | |||
29 | /** |
||
30 | * Net mount key. |
||
31 | * |
||
32 | * @var string |
||
33 | **/ |
||
34 | public $netMountKey = ''; |
||
35 | /** |
||
36 | * Driver id |
||
37 | * Must be started from letter and contains [a-z0-9] |
||
38 | * Used as part of volume id. |
||
39 | * |
||
40 | * @var string |
||
41 | **/ |
||
42 | protected $driverId = 'od'; |
||
43 | |||
44 | /** |
||
45 | * OneDrive token object. |
||
46 | * |
||
47 | * @var object |
||
48 | **/ |
||
49 | protected $token = null; |
||
50 | |||
51 | /** |
||
52 | * Directory for tmp files |
||
53 | * If not set driver will try to use tmbDir as tmpDir. |
||
54 | * |
||
55 | * @var string |
||
56 | **/ |
||
57 | protected $tmp = ''; |
||
58 | |||
59 | /** |
||
60 | * Thumbnail prefix. |
||
61 | * |
||
62 | * @var string |
||
63 | **/ |
||
64 | protected $tmbPrefix = ''; |
||
65 | |||
66 | /** |
||
67 | * hasCache by folders. |
||
68 | * |
||
69 | * @var array |
||
70 | **/ |
||
71 | protected $HasdirsCache = []; |
||
72 | |||
73 | /** |
||
74 | * Query options of API call. |
||
75 | * |
||
76 | * @var array |
||
77 | */ |
||
78 | protected $queryOptions = []; |
||
79 | |||
80 | /** |
||
81 | * Constructor |
||
82 | * Extend options with required fields. |
||
83 | * |
||
84 | * @author Dmitry (dio) Levashov |
||
85 | * @author Cem (DiscoFever) |
||
86 | **/ |
||
87 | public function __construct() |
||
88 | { |
||
89 | $opts = [ |
||
90 | 'client_id' => '', |
||
91 | 'client_secret' => '', |
||
92 | 'accessToken' => '', |
||
93 | 'root' => 'OneDrive.com', |
||
94 | 'OneDriveApiClient' => '', |
||
95 | 'path' => '/', |
||
96 | 'separator' => '/', |
||
97 | 'tmbPath' => '', |
||
98 | 'tmbURL' => '', |
||
99 | 'tmpPath' => '', |
||
100 | 'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#', |
||
101 | 'rootCssClass' => 'elfinder-navbar-root-onedrive', |
||
102 | 'useApiThumbnail' => true, |
||
103 | ]; |
||
104 | $this->options = array_merge($this->options, $opts); |
||
105 | $this->options['mimeDetect'] = 'internal'; |
||
106 | } |
||
107 | |||
108 | /*********************************************************************/ |
||
109 | /* OVERRIDE FUNCTIONS */ |
||
110 | /*********************************************************************/ |
||
111 | |||
112 | /** |
||
113 | * Prepare |
||
114 | * Call from elFinder::netmout() before volume->mount(). |
||
115 | * |
||
116 | * @return array |
||
117 | * |
||
118 | * @author Naoki Sawada |
||
119 | * @author Raja Sharma updating for OneDrive |
||
120 | **/ |
||
121 | public function netmountPrepare($options) |
||
122 | { |
||
123 | if (empty($options['client_id']) && defined('ELFINDER_ONEDRIVE_CLIENTID')) { |
||
124 | $options['client_id'] = ELFINDER_ONEDRIVE_CLIENTID; |
||
125 | } |
||
126 | if (empty($options['client_secret']) && defined('ELFINDER_ONEDRIVE_CLIENTSECRET')) { |
||
127 | $options['client_secret'] = ELFINDER_ONEDRIVE_CLIENTSECRET; |
||
128 | } |
||
129 | |||
130 | View Code Duplication | if (isset($options['pass']) && $options['pass'] === 'reauth') { |
|
131 | $options['user'] = 'init'; |
||
132 | $options['pass'] = ''; |
||
133 | $this->session->remove('OneDriveTokens'); |
||
134 | } |
||
135 | |||
136 | View Code Duplication | if (isset($options['id'])) { |
|
137 | $this->session->set('nodeId', $options['id']); |
||
138 | } elseif ($_id = $this->session->get('nodeId')) { |
||
139 | $options['id'] = $_id; |
||
140 | $this->session->set('nodeId', $_id); |
||
141 | } |
||
142 | |||
143 | try { |
||
144 | View Code Duplication | if (empty($options['client_id']) || empty($options['client_secret'])) { |
|
145 | return ['exit' => true, 'body' => '{msg:errNetMountNoDriver}']; |
||
146 | } |
||
147 | |||
148 | View Code Duplication | if (isset($_GET['code'])) { |
|
149 | try { |
||
150 | // Obtain the token using the code received by the OneDrive API |
||
151 | $this->session->set('OneDriveTokens', |
||
152 | $this->_od_obtainAccessToken($options['client_id'], $options['client_secret'], $_GET['code'])); |
||
153 | |||
154 | $out = [ |
||
155 | 'node' => $options['id'], |
||
156 | 'json' => '{"protocol": "onedrive", "mode": "done", "reset": 1}', |
||
157 | 'bind' => 'netmount', |
||
158 | ]; |
||
159 | |||
160 | return ['exit' => 'callback', 'out' => $out]; |
||
161 | } catch (Exception $e) { |
||
162 | $out = [ |
||
163 | 'node' => $options['id'], |
||
164 | 'json' => json_encode(['error' => elFinder::ERROR_ACCESS_DENIED.' '.$e->getMessage()]), |
||
165 | ]; |
||
166 | |||
167 | return ['exit' => 'callback', 'out' => $out]; |
||
168 | } |
||
169 | } elseif (! empty($_GET['error'])) { |
||
170 | $out = [ |
||
171 | 'node' => $options['id'], |
||
172 | 'json' => json_encode(['error' => elFinder::ERROR_ACCESS_DENIED]), |
||
173 | ]; |
||
174 | |||
175 | return ['exit' => 'callback', 'out' => $out]; |
||
176 | } |
||
177 | |||
178 | if ($options['user'] === 'init') { |
||
179 | $this->token = $this->session->get('OneDriveTokens'); |
||
180 | |||
181 | View Code Duplication | if ($this->token) { |
|
182 | try { |
||
183 | $this->_od_refreshToken(); |
||
184 | } catch (Exception $e) { |
||
185 | $this->setError($e->getMessage()); |
||
186 | $this->token = null; |
||
187 | $this->session->remove('OneDriveTokens'); |
||
188 | } |
||
189 | } |
||
190 | |||
191 | if (empty($this->token)) { |
||
192 | $result = false; |
||
193 | } else { |
||
194 | $path = $options['path']; |
||
195 | if ($path === '/') { |
||
196 | $path = 'root'; |
||
197 | } |
||
198 | $result = $this->_od_query($path, false, false, [ |
||
199 | 'query' => [ |
||
200 | 'select' => 'id,name', |
||
201 | 'filter' => 'folder ne null', |
||
202 | ], |
||
203 | ]); |
||
204 | } |
||
205 | |||
206 | if ($result === false) { |
||
207 | $cdata = ''; |
||
208 | $innerKeys = ['cmd', 'host', 'options', 'pass', 'protocol', 'user']; |
||
209 | $this->ARGS = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET; |
||
210 | View Code Duplication | foreach ($this->ARGS as $k => $v) { |
|
211 | if (! in_array($k, $innerKeys)) { |
||
212 | $cdata .= '&'.$k.'='.rawurlencode($v); |
||
213 | } |
||
214 | } |
||
215 | if (empty($options['url'])) { |
||
216 | $options['url'] = elFinder::getConnectorUrl(); |
||
217 | } |
||
218 | $callback = $options['url'] |
||
219 | .'?cmd=netmount&protocol=onedrive&host=onedrive.com&user=init&pass=return&node='.$options['id'].$cdata; |
||
220 | |||
221 | try { |
||
222 | $this->session->set('OneDriveTokens', (object) ['token' => null]); |
||
223 | |||
224 | $offline = ''; |
||
225 | // Gets a log in URL with sufficient privileges from the OneDrive API |
||
226 | if (! empty($options['offline'])) { |
||
227 | $offline = ' wl.offline_access'; |
||
228 | } |
||
229 | |||
230 | $redirect_uri = $options['url'].'/netmount/onedrive/1'; |
||
231 | $url = self::AUTH_URL |
||
232 | .'?client_id='.urlencode($options['client_id']) |
||
233 | .'&scope='.urlencode('wl.skydrive_update'.$offline) |
||
234 | .'&response_type=code' |
||
235 | .'&redirect_uri='.urlencode($redirect_uri); |
||
236 | |||
237 | $url .= '&oauth_callback='.rawurlencode($callback); |
||
238 | } catch (Exception $e) { |
||
239 | return ['exit' => true, 'body' => '{msg:errAccess}']; |
||
240 | } |
||
241 | |||
242 | $html = '<input id="elf-volumedriver-onedrive-host-btn" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" value="{msg:btnApprove}" type="button" onclick="window.open(\''.$url.'\')">'; |
||
243 | $html .= '<script> |
||
244 | $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "onedrive", mode: "makebtn"}); |
||
245 | </script>'; |
||
246 | |||
247 | return ['exit' => true, 'body' => $html]; |
||
248 | View Code Duplication | } else { |
|
249 | $folders = []; |
||
250 | |||
251 | if ($result) { |
||
252 | foreach ($result as $res) { |
||
253 | $folders[$res->id] = $res->name; |
||
254 | } |
||
255 | natcasesort($folders); |
||
256 | } |
||
257 | |||
258 | if ($options['pass'] === 'folders') { |
||
259 | return ['exit' => true, 'folders' => $folders]; |
||
260 | } |
||
261 | |||
262 | $folders = ['root' => 'My OneDrive'] + $folders; |
||
263 | $folders = json_encode($folders); |
||
264 | |||
265 | $expires = empty($this->token->data->refresh_token) ? (int) $this->token->expires : 0; |
||
266 | $json = '{"protocol": "onedrive", "mode": "done", "folders": '.$folders.', "expires": '.$expires.'}'; |
||
267 | $html = 'OneDrive.com'; |
||
268 | $html .= '<script> |
||
269 | $("#'.$options['id'].'").elfinder("instance").trigger("netmount", '.$json.'); |
||
270 | </script>'; |
||
271 | |||
272 | return ['exit' => true, 'body' => $html]; |
||
273 | } |
||
274 | } |
||
275 | } catch (Exception $e) { |
||
276 | return ['exit' => true, 'body' => '{msg:errNetMountNoDriver}']; |
||
277 | } |
||
278 | |||
279 | View Code Duplication | if ($_aToken = $this->session->get('OneDriveTokens')) { |
|
280 | $options['accessToken'] = json_encode($_aToken); |
||
281 | } else { |
||
282 | $this->setError(elFinder::ERROR_NETMOUNT, $options['host'], implode(' ', $this->error())); |
||
283 | |||
284 | return ['exit' => true, 'error' => $this->error()]; |
||
285 | } |
||
286 | |||
287 | $this->session->remove('nodeId'); |
||
288 | unset($options['user'], $options['pass'], $options['id']); |
||
289 | |||
290 | return $options; |
||
291 | } |
||
292 | |||
293 | /** |
||
294 | * process of on netunmount |
||
295 | * Drop `onedrive` & rm thumbs. |
||
296 | * |
||
297 | * @param array $options |
||
0 ignored issues
–
show
|
|||
298 | * |
||
299 | * @return bool |
||
300 | */ |
||
301 | View Code Duplication | public function netunmount($netVolumes, $key) |
|
302 | { |
||
303 | if ($tmbs = glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->tmbPrefix.'*.png')) { |
||
304 | foreach ($tmbs as $file) { |
||
305 | unlink($file); |
||
306 | } |
||
307 | } |
||
308 | |||
309 | return true; |
||
310 | } |
||
311 | |||
312 | /*********************************************************************/ |
||
313 | /* FS API */ |
||
314 | /*********************************************************************/ |
||
315 | |||
316 | /** |
||
317 | * Close opened connection. |
||
318 | * |
||
319 | * @author Dmitry (dio) Levashov |
||
320 | **/ |
||
321 | public function umount() |
||
322 | { |
||
323 | } |
||
324 | |||
325 | /** |
||
326 | * Return content URL. |
||
327 | * |
||
328 | * @param string $hash file hash |
||
329 | * @param array $options options |
||
330 | * |
||
331 | * @return string |
||
332 | * |
||
333 | * @author Naoki Sawada |
||
334 | **/ |
||
335 | public function getContentUrl($hash, $options = []) |
||
336 | { |
||
337 | View Code Duplication | if (! empty($options['temporary'])) { |
|
338 | // try make temporary file |
||
339 | $url = parent::getContentUrl($hash, $options); |
||
340 | if ($url) { |
||
341 | return $url; |
||
342 | } |
||
343 | } |
||
344 | $res = ''; |
||
345 | if (($file = $this->file($hash)) == false || ! $file['url'] || $file['url'] == 1) { |
||
346 | $path = $this->decode($hash); |
||
347 | |||
348 | list(, $itemId) = $this->_od_splitPath($path); |
||
349 | try { |
||
350 | $url = self::API_URL.$itemId.'/action.createLink'; |
||
351 | $data = (object) [ |
||
352 | 'type' => 'embed', |
||
353 | 'scope' => 'anonymous', |
||
354 | ]; |
||
355 | $curl = $this->_od_prepareCurl($url); |
||
356 | curl_setopt_array($curl, [ |
||
357 | CURLOPT_POST => true, |
||
358 | CURLOPT_POSTFIELDS => json_encode($data), |
||
359 | ]); |
||
360 | |||
361 | $result = curl_exec($curl); |
||
362 | curl_close($curl); |
||
363 | if ($result) { |
||
364 | $result = json_decode($result); |
||
365 | if (isset($result->link)) { |
||
366 | list(, $res) = explode('?', $result->link->webUrl); |
||
367 | $res = 'https://onedrive.live.com/download.aspx?'.$res; |
||
368 | } |
||
369 | } |
||
370 | } catch (Exception $e) { |
||
371 | $res = ''; |
||
372 | } |
||
373 | } |
||
374 | |||
375 | return $res; |
||
376 | } |
||
377 | |||
378 | /*********************************************************************/ |
||
379 | /* ORIGINAL FUNCTIONS */ |
||
380 | /*********************************************************************/ |
||
381 | |||
382 | /** |
||
383 | * Obtains a new access token from OAuth. This token is valid for one hour. |
||
384 | * |
||
385 | * @param string $clientSecret The OneDrive client secret |
||
0 ignored issues
–
show
There is no parameter named
$clientSecret . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
386 | * @param string $code The code returned by OneDrive after |
||
387 | * successful log in |
||
388 | * @param string $redirectUri Must be the same as the redirect URI passed |
||
0 ignored issues
–
show
There is no parameter named
$redirectUri . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
389 | * to LoginUrl |
||
390 | * |
||
391 | * @throws \Exception Thrown if this Client instance's clientId is not set |
||
392 | * @throws \Exception Thrown if the redirect URI of this Client instance's |
||
393 | * state is not set |
||
394 | */ |
||
395 | protected function _od_obtainAccessToken($client_id, $client_secret, $code) |
||
396 | { |
||
397 | if (null === $client_id) { |
||
398 | return 'The client ID must be set to call obtainAccessToken()'; |
||
399 | } |
||
400 | |||
401 | if (null === $client_secret) { |
||
402 | return 'The client Secret must be set to call obtainAccessToken()'; |
||
403 | } |
||
404 | |||
405 | $url = self::TOKEN_URL; |
||
406 | |||
407 | $curl = curl_init(); |
||
408 | |||
409 | $fields = http_build_query( |
||
410 | [ |
||
411 | 'client_id' => $client_id, |
||
412 | 'redirect_uri' => elFinder::getConnectorUrl(), |
||
413 | 'client_secret' => $client_secret, |
||
414 | 'code' => $code, |
||
415 | 'grant_type' => 'authorization_code', |
||
416 | ] |
||
417 | ); |
||
418 | |||
419 | curl_setopt_array($curl, [ |
||
420 | // General options. |
||
421 | CURLOPT_RETURNTRANSFER => true, |
||
422 | CURLOPT_POST => true, |
||
423 | CURLOPT_POSTFIELDS => $fields, |
||
424 | |||
425 | CURLOPT_HTTPHEADER => [ |
||
426 | 'Content-Length: '.strlen($fields), |
||
427 | ], |
||
428 | |||
429 | CURLOPT_URL => $url, |
||
430 | ]); |
||
431 | |||
432 | $result = curl_exec($curl); |
||
433 | |||
434 | View Code Duplication | if (false === $result) { |
|
435 | if (curl_errno($curl)) { |
||
436 | throw new \Exception('curl_setopt_array() failed: ' |
||
437 | .curl_error($curl)); |
||
438 | } else { |
||
439 | throw new \Exception('curl_setopt_array(): empty response'); |
||
440 | } |
||
441 | } |
||
442 | curl_close($curl); |
||
443 | |||
444 | $decoded = json_decode($result); |
||
445 | |||
446 | if (null === $decoded) { |
||
447 | throw new \Exception('json_decode() failed'); |
||
448 | } |
||
449 | |||
450 | return (object) [ |
||
451 | 'expires' => time() + $decoded->expires_in - 30, |
||
452 | 'data' => $decoded, |
||
453 | ]; |
||
454 | } |
||
455 | |||
456 | /** |
||
457 | * Get token and auto refresh. |
||
458 | * |
||
459 | * @return true|Exception |
||
460 | */ |
||
461 | protected function _od_refreshToken() |
||
462 | { |
||
463 | if ($this->token->expires < time()) { |
||
464 | if (! $token = $this->session->get('OneDriveTokens')) { |
||
465 | $token = $this->token; |
||
466 | } |
||
467 | if (empty($token->data->refresh_token)) { |
||
468 | $this->session->remove('OneDriveTokens'); |
||
469 | throw new \Exception(elFinder::ERROR_REAUTH_REQUIRE); |
||
470 | } |
||
471 | |||
472 | if (! $this->options['client_id']) { |
||
473 | $this->options['client_id'] = ELFINDER_ONEDRIVE_CLIENTID; |
||
474 | } |
||
475 | |||
476 | if (! $this->options['client_secret']) { |
||
477 | $this->options['client_secret'] = ELFINDER_ONEDRIVE_CLIENTSECRET; |
||
478 | } |
||
479 | |||
480 | $url = self::TOKEN_URL; |
||
481 | |||
482 | $curl = curl_init(); |
||
483 | |||
484 | curl_setopt_array($curl, [ |
||
485 | // General options. |
||
486 | CURLOPT_RETURNTRANSFER => true, |
||
487 | CURLOPT_POST => true, // i am sending post data |
||
488 | CURLOPT_POSTFIELDS => 'client_id='.urlencode($this->options['client_id']) |
||
489 | .'&client_secret='.urlencode($this->options['client_secret']) |
||
490 | .'&grant_type=refresh_token' |
||
491 | .'&refresh_token='.urlencode($token->data->refresh_token), |
||
492 | |||
493 | CURLOPT_URL => $url, |
||
494 | ]); |
||
495 | |||
496 | $result = curl_exec($curl); |
||
497 | |||
498 | View Code Duplication | if (! $result) { |
|
499 | if (curl_errno($curl)) { |
||
500 | throw new \Exception('curl_setopt_array() failed: '.curl_error($curl)); |
||
501 | } else { |
||
502 | throw new \Exception('curl_setopt_array(): empty response'); |
||
503 | } |
||
504 | } |
||
505 | curl_close($curl); |
||
506 | |||
507 | $decoded = json_decode($result); |
||
508 | |||
509 | if (! $decoded) { |
||
510 | throw new \Exception('json_decode() failed'); |
||
511 | } |
||
512 | |||
513 | if (empty($decoded->access_token)) { |
||
514 | throw new \Exception(elFinder::ERROR_REAUTH_REQUIRE); |
||
515 | } |
||
516 | |||
517 | $token = (object) [ |
||
518 | 'expires' => time() + $decoded->expires_in - 30, |
||
519 | 'data' => $decoded, |
||
520 | ]; |
||
521 | |||
522 | $this->session->set('OneDriveTokens', $token); |
||
523 | $this->options['accessToken'] = json_encode($token); |
||
524 | $this->token = $token; |
||
525 | |||
526 | View Code Duplication | if (! empty($this->options['netkey'])) { |
|
527 | elFinder::$instance->updateNetVolumeOption($this->options['netkey'], 'accessToken', $this->options['accessToken']); |
||
528 | } |
||
529 | } |
||
530 | |||
531 | return true; |
||
532 | } |
||
533 | |||
534 | /** |
||
535 | * Get Parent ID, Item ID, Parent Path as an array from path. |
||
536 | * |
||
537 | * @param string $path |
||
538 | * |
||
539 | * @return array |
||
540 | */ |
||
541 | View Code Duplication | protected function _od_splitPath($path) |
|
542 | { |
||
543 | $path = trim($path, '/'); |
||
544 | $pid = ''; |
||
545 | if ($path === '') { |
||
546 | $id = 'root'; |
||
547 | $parent = ''; |
||
548 | } else { |
||
549 | $paths = explode('/', trim($path, '/')); |
||
550 | $id = array_pop($paths); |
||
551 | if ($paths) { |
||
0 ignored issues
–
show
The expression
$paths of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
552 | $parent = '/'.implode('/', $paths); |
||
553 | $pid = array_pop($paths); |
||
554 | } else { |
||
555 | $pid = 'root'; |
||
556 | $parent = '/'; |
||
557 | } |
||
558 | } |
||
559 | |||
560 | return [$pid, $id, $parent]; |
||
561 | } |
||
562 | |||
563 | /** |
||
564 | * Creates a base cURL object which is compatible with the OneDrive API. |
||
565 | * |
||
566 | * @return resource A compatible cURL object |
||
567 | */ |
||
568 | protected function _od_prepareCurl($url = null) |
||
569 | { |
||
570 | $curl = curl_init($url); |
||
571 | |||
572 | $defaultOptions = [ |
||
573 | // General options. |
||
574 | CURLOPT_RETURNTRANSFER => true, |
||
575 | CURLOPT_HTTPHEADER => [ |
||
576 | 'Content-Type: application/json', |
||
577 | 'Authorization: Bearer '.$this->token->data->access_token, |
||
578 | ], |
||
579 | ]; |
||
580 | |||
581 | curl_setopt_array($curl, $defaultOptions); |
||
582 | |||
583 | return $curl; |
||
584 | } |
||
585 | |||
586 | /** |
||
587 | * Creates a base cURL object which is compatible with the OneDrive API. |
||
588 | * |
||
589 | * @param string $path The path of the API call (eg. me/skydrive) |
||
590 | * |
||
591 | * @return resource A compatible cURL object |
||
592 | */ |
||
593 | protected function _od_createCurl($path, $contents = false) |
||
594 | { |
||
595 | elfinder::extendTimeLimit(); |
||
596 | $curl = $this->_od_prepareCurl($path); |
||
597 | |||
598 | if ($contents) { |
||
599 | $res = elFinder::curlExec($curl); |
||
600 | } else { |
||
601 | $result = json_decode(curl_exec($curl)); |
||
602 | curl_close($curl); |
||
603 | if (isset($result->value)) { |
||
604 | $res = $result->value; |
||
605 | unset($result->value); |
||
606 | $result = (array) $result; |
||
607 | if (! empty($result['@odata.nextLink'])) { |
||
608 | $nextRes = $this->_od_createCurl($result['@odata.nextLink'], false); |
||
609 | if (is_array($nextRes)) { |
||
610 | $res = array_merge($res, $nextRes); |
||
611 | } |
||
612 | } |
||
613 | } else { |
||
614 | $res = $result; |
||
615 | } |
||
616 | } |
||
617 | |||
618 | return $res; |
||
619 | } |
||
620 | |||
621 | /** |
||
622 | * Drive query and fetchAll. |
||
623 | * |
||
624 | * @param string $sql |
||
0 ignored issues
–
show
There is no parameter named
$sql . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
625 | * |
||
626 | * @return object|array |
||
627 | */ |
||
628 | protected function _od_query($itemId, $fetch_self = false, $recursive = false, $options = []) |
||
629 | { |
||
630 | $result = []; |
||
631 | |||
632 | if (null === $itemId) { |
||
633 | $itemId = 'root'; |
||
634 | } |
||
635 | |||
636 | if ($fetch_self == true) { |
||
637 | $path = $itemId; |
||
638 | } else { |
||
639 | $path = $itemId.'/children'; |
||
640 | } |
||
641 | |||
642 | if (isset($options['query'])) { |
||
643 | $path .= '?'.http_build_query($options['query']); |
||
644 | } |
||
645 | |||
646 | $url = self::API_URL.$path; |
||
647 | |||
648 | $res = $this->_od_createCurl($url); |
||
649 | if (! $fetch_self && $recursive && is_array($res)) { |
||
650 | foreach ($res as $file) { |
||
651 | $result[] = $file; |
||
652 | if (! empty($file->folder)) { |
||
653 | $result = array_merge($result, $this->_od_query($file->id, false, true, $options)); |
||
654 | } |
||
655 | } |
||
656 | } else { |
||
657 | $result = $res; |
||
658 | } |
||
659 | |||
660 | return isset($result->error) ? [] : $result; |
||
661 | } |
||
662 | |||
663 | /** |
||
664 | * Parse line from onedrive metadata output and return file stat (array). |
||
665 | * |
||
666 | * @param string $raw line from ftp_rawlist() output |
||
667 | * |
||
668 | * @return array |
||
669 | * |
||
670 | * @author Dmitry Levashov |
||
671 | **/ |
||
672 | protected function _od_parseRaw($raw) |
||
673 | { |
||
674 | $stat = []; |
||
675 | |||
676 | $folder = isset($raw->folder) ? $raw->folder : null; |
||
677 | |||
678 | $stat['rev'] = isset($raw->id) ? $raw->id : 'root'; |
||
679 | $stat['name'] = $raw->name; |
||
680 | if (isset($raw->lastModifiedDateTime)) { |
||
681 | $stat['ts'] = strtotime($raw->lastModifiedDateTime); |
||
682 | } |
||
683 | |||
684 | if ($folder) { |
||
685 | $stat['mime'] = 'directory'; |
||
686 | $stat['size'] = 0; |
||
687 | if (empty($folder->childCount)) { |
||
688 | $stat['dirs'] = 0; |
||
689 | } else { |
||
690 | $stat['dirs'] = -1; |
||
691 | } |
||
692 | } else { |
||
693 | if (isset($raw->file->mimeType)) { |
||
694 | $stat['mime'] = $raw->file->mimeType; |
||
695 | } |
||
696 | $stat['size'] = (int) $raw->size; |
||
697 | if (! $this->disabledGetUrl) { |
||
698 | $stat['url'] = '1'; |
||
699 | } |
||
700 | if (isset($raw->image) && $img = $raw->image) { |
||
701 | isset($img->width) ? $stat['width'] = $img->width : $stat['width'] = 0; |
||
702 | isset($img->height) ? $stat['height'] = $img->height : $stat['height'] = 0; |
||
703 | } |
||
704 | if (! empty($raw->thumbnails)) { |
||
705 | if ($raw->thumbnails[0]->small->url) { |
||
706 | $stat['tmb'] = substr($raw->thumbnails[0]->small->url, 8); // remove "https://" |
||
707 | } |
||
708 | } |
||
709 | } |
||
710 | |||
711 | return $stat; |
||
712 | } |
||
713 | |||
714 | /** |
||
715 | * Get raw data(onedrive metadata) from OneDrive. |
||
716 | * |
||
717 | * @param string $path |
||
718 | * |
||
719 | * @return array|object onedrive metadata |
||
720 | */ |
||
721 | protected function _od_getFileRaw($path) |
||
722 | { |
||
723 | list(, $itemId) = $this->_od_splitPath($path); |
||
724 | try { |
||
725 | $res = $this->_od_query($itemId, true, false, $this->queryOptions); |
||
726 | |||
727 | return $res; |
||
728 | } catch (Exception $e) { |
||
729 | return []; |
||
730 | } |
||
731 | } |
||
732 | |||
733 | /** |
||
734 | * Get thumbnail from OneDrive.com. |
||
735 | * |
||
736 | * @param string $path |
||
737 | * @param string $size |
||
0 ignored issues
–
show
There is no parameter named
$size . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
738 | * |
||
739 | * @return string | boolean |
||
740 | */ |
||
741 | View Code Duplication | protected function _od_getThumbnail($path) |
|
742 | { |
||
743 | list(, $itemId) = $this->_od_splitPath($path); |
||
744 | |||
745 | try { |
||
746 | $url = self::API_URL.$itemId.'/thumbnails/0/medium/content'; |
||
747 | |||
748 | return $this->_od_createCurl($url, $contents = true); |
||
749 | } catch (Exception $e) { |
||
750 | return false; |
||
751 | } |
||
752 | } |
||
753 | |||
754 | /*********************************************************************/ |
||
755 | /* INIT AND CONFIGURE */ |
||
756 | /*********************************************************************/ |
||
757 | |||
758 | /** |
||
759 | * Prepare FTP connection |
||
760 | * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn. |
||
761 | * |
||
762 | * @return bool |
||
763 | * |
||
764 | * @author Dmitry (dio) Levashov |
||
765 | * @author Cem (DiscoFever) |
||
766 | **/ |
||
767 | protected function init() |
||
768 | { |
||
769 | if (! $this->options['accessToken']) { |
||
770 | return $this->setError('Required option `accessToken` is undefined.'); |
||
771 | } |
||
772 | |||
773 | try { |
||
774 | $this->token = json_decode($this->options['accessToken']); |
||
775 | $this->_od_refreshToken(); |
||
776 | } catch (Exception $e) { |
||
777 | $this->token = null; |
||
778 | $this->session->remove('OneDriveTokens'); |
||
779 | |||
780 | return $this->setError($e->getMessage()); |
||
781 | } |
||
782 | |||
783 | View Code Duplication | if (empty($options['netkey'])) { |
|
0 ignored issues
–
show
The variable
$options seems to never exist, and therefore empty should always return true . Did you maybe rename this variable?
This check looks for calls to This is most likely caused by the renaming of a variable or the removal of a function/method parameter. ![]() |
|||
784 | // make net mount key |
||
785 | $_tokenKey = isset($this->token->data->refresh_token) ? $this->token->data->refresh_token : $this->token->data->access_token; |
||
786 | $this->netMountKey = md5(implode('-', ['box', $this->options['path'], $_tokenKey])); |
||
787 | } else { |
||
788 | $this->netMountKey = $options['netkey']; |
||
789 | } |
||
790 | |||
791 | // normalize root path |
||
792 | if ($this->options['path'] == 'root') { |
||
793 | $this->options['path'] = '/'; |
||
794 | } |
||
795 | |||
796 | $this->root = $this->options['path'] = $this->_normpath($this->options['path']); |
||
797 | |||
798 | $this->options['root'] == '' ? $this->options['root'] = 'OneDrive.com' : $this->options['root']; |
||
799 | |||
800 | View Code Duplication | if (empty($this->options['alias'])) { |
|
801 | $this->options['alias'] = ($this->options['path'] === '/') ? $this->options['root'] : |
||
802 | $this->_od_query(basename($this->options['path']), $fetch_self = true)->name.'@OneDrive'; |
||
803 | } |
||
804 | |||
805 | $this->rootName = $this->options['alias']; |
||
806 | |||
807 | $this->tmbPrefix = 'onedrive'.base_convert($this->netMountKey, 10, 32); |
||
808 | |||
809 | if (! empty($this->options['tmpPath'])) { |
||
810 | if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) { |
||
811 | $this->tmp = $this->options['tmpPath']; |
||
812 | } |
||
813 | } |
||
814 | |||
815 | if (! $this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) { |
||
816 | $this->tmp = $tmp; |
||
817 | } |
||
818 | |||
819 | // This driver dose not support `syncChkAsTs` |
||
820 | $this->options['syncChkAsTs'] = false; |
||
821 | |||
822 | // 'lsPlSleep' minmum 10 sec |
||
823 | $this->options['lsPlSleep'] = max(10, $this->options['lsPlSleep']); |
||
824 | |||
825 | $this->queryOptions = [ |
||
826 | 'query' => [ |
||
827 | 'select' => 'id,name,lastModifiedDateTime,file,folder,size,image', |
||
828 | ], |
||
829 | ]; |
||
830 | |||
831 | if ($this->options['useApiThumbnail']) { |
||
832 | $this->options['tmbURL'] = 'https://'; |
||
833 | $this->queryOptions['query']['expand'] = 'thumbnails(select=small)'; |
||
834 | } |
||
835 | |||
836 | return true; |
||
837 | } |
||
838 | |||
839 | /** |
||
840 | * Configure after successfull mount. |
||
841 | * |
||
842 | * @author Dmitry (dio) Levashov |
||
843 | **/ |
||
844 | protected function configure() |
||
845 | { |
||
846 | parent::configure(); |
||
847 | |||
848 | // fallback of $this->tmp |
||
849 | if (! $this->tmp && $this->tmbPathWritable) { |
||
850 | $this->tmp = $this->tmbPath; |
||
851 | } |
||
852 | |||
853 | $this->disabled[] = 'archive'; |
||
854 | $this->disabled[] = 'extract'; |
||
855 | } |
||
856 | |||
857 | protected function isNameExists($path) |
||
858 | { |
||
859 | list($pid, $name) = $this->_od_splitPath($path); |
||
860 | |||
861 | return (bool) $this->_od_query($pid.'/children/'.rawurlencode($name).'?select=id', true); |
||
862 | } |
||
863 | |||
864 | /** |
||
865 | * Cache dir contents. |
||
866 | * |
||
867 | * @param string $path dir path |
||
868 | * |
||
869 | * @author Dmitry Levashov |
||
870 | **/ |
||
871 | protected function cacheDir($path) |
||
872 | { |
||
873 | $this->dirsCache[$path] = []; |
||
874 | $hasDir = false; |
||
875 | |||
876 | list(, $itemId) = $this->_od_splitPath($path); |
||
877 | |||
878 | $res = $this->_od_query($itemId, false, false, $this->queryOptions); |
||
879 | |||
880 | if ($res) { |
||
881 | foreach ($res as $raw) { |
||
882 | if ($stat = $this->_od_parseRaw($raw)) { |
||
883 | $itemPath = $this->_joinPath($path, $raw->id); |
||
884 | $stat = $this->updateCache($itemPath, $stat); |
||
885 | if (empty($stat['hidden'])) { |
||
886 | if (! $hasDir && $stat['mime'] === 'directory') { |
||
887 | $hasDir = true; |
||
888 | } |
||
889 | $this->dirsCache[$path][] = $itemPath; |
||
890 | } |
||
891 | } |
||
892 | } |
||
893 | } |
||
894 | |||
895 | if (isset($this->sessionCache['subdirs'])) { |
||
896 | $this->sessionCache['subdirs'][$path] = $hasDir; |
||
897 | } |
||
898 | |||
899 | return $this->dirsCache[$path]; |
||
900 | } |
||
901 | |||
902 | /** |
||
903 | * Copy file/recursive copy dir only in current volume. |
||
904 | * Return new file path or false. |
||
905 | * |
||
906 | * @param string $src source path |
||
907 | * @param string $dst destination dir path |
||
908 | * @param string $name new file name (optionaly) |
||
909 | * |
||
910 | * @return string|false |
||
911 | * |
||
912 | * @author Dmitry (dio) Levashov |
||
913 | * @author Naoki Sawada |
||
914 | **/ |
||
915 | protected function copy($src, $dst, $name) |
||
916 | { |
||
917 | $itemId = ''; |
||
918 | View Code Duplication | if ($this->options['copyJoin']) { |
|
919 | $test = $this->joinPathCE($dst, $name); |
||
920 | if ($testStat = $this->isNameExists($test)) { |
||
921 | $this->remove($test); |
||
922 | } |
||
923 | } |
||
924 | |||
925 | $path = $this->_copy($src, $dst, $name); |
||
926 | |||
927 | return $path |
||
928 | ? $path |
||
929 | : $this->setError(elFinder::ERROR_COPY, $this->_path($src)); |
||
930 | } |
||
931 | |||
932 | /** |
||
933 | * Remove file/ recursive remove dir. |
||
934 | * |
||
935 | * @param string $path file path |
||
936 | * @param bool $force try to remove even if file locked |
||
937 | * |
||
938 | * @return bool |
||
939 | * |
||
940 | * @author Dmitry (dio) Levashov |
||
941 | * @author Naoki Sawada |
||
942 | **/ |
||
943 | View Code Duplication | protected function remove($path, $force = false) |
|
944 | { |
||
945 | $stat = $this->stat($path); |
||
946 | $stat['realpath'] = $path; |
||
947 | $this->rmTmb($stat); |
||
948 | $this->clearcache(); |
||
949 | |||
950 | if (empty($stat)) { |
||
951 | return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND); |
||
952 | } |
||
953 | |||
954 | if (! $force && ! empty($stat['locked'])) { |
||
955 | return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path)); |
||
956 | } |
||
957 | |||
958 | if ($stat['mime'] == 'directory') { |
||
959 | if (! $this->_rmdir($path)) { |
||
960 | return $this->setError(elFinder::ERROR_RM, $this->_path($path)); |
||
961 | } |
||
962 | } else { |
||
963 | if (! $this->_unlink($path)) { |
||
964 | return $this->setError(elFinder::ERROR_RM, $this->_path($path)); |
||
965 | } |
||
966 | } |
||
967 | |||
968 | $this->removed[] = $stat; |
||
969 | |||
970 | return true; |
||
971 | } |
||
972 | |||
973 | /** |
||
974 | * Create thumnbnail and return it's URL on success. |
||
975 | * |
||
976 | * @param string $path file path |
||
977 | * @param string $mime file mime type |
||
0 ignored issues
–
show
There is no parameter named
$mime . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
978 | * |
||
979 | * @return string|false |
||
980 | * |
||
981 | * @author Dmitry (dio) Levashov |
||
982 | * @author Naoki Sawada |
||
983 | **/ |
||
984 | View Code Duplication | protected function createTmb($path, $stat) |
|
985 | { |
||
986 | if (! $stat || ! $this->canCreateTmb($path, $stat)) { |
||
987 | return false; |
||
988 | } |
||
989 | |||
990 | $name = $this->tmbname($stat); |
||
991 | $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name; |
||
992 | |||
993 | // copy image into tmbPath so some drivers does not store files on local fs |
||
994 | if (! $data = $this->_od_getThumbnail($path)) { |
||
995 | return false; |
||
996 | } |
||
997 | if (! file_put_contents($tmb, $data)) { |
||
998 | return false; |
||
999 | } |
||
1000 | |||
1001 | $result = false; |
||
1002 | |||
1003 | $tmbSize = $this->tmbSize; |
||
1004 | |||
1005 | if (($s = getimagesize($tmb)) == false) { |
||
1006 | return false; |
||
1007 | } |
||
1008 | |||
1009 | /* If image smaller or equal thumbnail size - just fitting to thumbnail square */ |
||
1010 | if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) { |
||
1011 | $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png'); |
||
1012 | } else { |
||
1013 | if ($this->options['tmbCrop']) { |
||
1014 | |||
1015 | /* Resize and crop if image bigger than thumbnail */ |
||
1016 | if (! (($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize)) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) { |
||
1017 | $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png'); |
||
1018 | } |
||
1019 | |||
1020 | if (($s = getimagesize($tmb)) != false) { |
||
1021 | $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize) / 2) : 0; |
||
1022 | $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize) / 2) : 0; |
||
1023 | $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png'); |
||
1024 | } |
||
1025 | } else { |
||
1026 | $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, 'png'); |
||
1027 | } |
||
1028 | |||
1029 | $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png'); |
||
1030 | } |
||
1031 | |||
1032 | if (! $result) { |
||
0 ignored issues
–
show
The expression
$result of type false|string is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
1033 | unlink($tmb); |
||
1034 | |||
1035 | return false; |
||
1036 | } |
||
1037 | |||
1038 | return $name; |
||
1039 | } |
||
1040 | |||
1041 | /** |
||
1042 | * Return thumbnail file name for required file. |
||
1043 | * |
||
1044 | * @param array $stat file stat |
||
1045 | * |
||
1046 | * @return string |
||
1047 | * |
||
1048 | * @author Dmitry (dio) Levashov |
||
1049 | **/ |
||
1050 | protected function tmbname($stat) |
||
1051 | { |
||
1052 | return $this->tmbPrefix.$stat['rev'].$stat['ts'].'.png'; |
||
1053 | } |
||
1054 | |||
1055 | /*********************** paths/urls *************************/ |
||
1056 | |||
1057 | /** |
||
1058 | * Return parent directory path. |
||
1059 | * |
||
1060 | * @param string $path file path |
||
1061 | * |
||
1062 | * @return string |
||
1063 | * |
||
1064 | * @author Dmitry (dio) Levashov |
||
1065 | **/ |
||
1066 | protected function _dirname($path) |
||
1067 | { |
||
1068 | list(, , $dirname) = $this->_od_splitPath($path); |
||
1069 | |||
1070 | return $dirname; |
||
1071 | } |
||
1072 | |||
1073 | /** |
||
1074 | * Return file name. |
||
1075 | * |
||
1076 | * @param string $path file path |
||
1077 | * |
||
1078 | * @return string |
||
1079 | * |
||
1080 | * @author Dmitry (dio) Levashov |
||
1081 | **/ |
||
1082 | protected function _basename($path) |
||
1083 | { |
||
1084 | list(, $basename) = $this->_od_splitPath($path); |
||
1085 | |||
1086 | return $basename; |
||
1087 | } |
||
1088 | |||
1089 | /** |
||
1090 | * Join dir name and file name and retur full path. |
||
1091 | * |
||
1092 | * @param string $dir |
||
1093 | * @param string $name |
||
1094 | * |
||
1095 | * @return string |
||
1096 | * |
||
1097 | * @author Dmitry (dio) Levashov |
||
1098 | **/ |
||
1099 | protected function _joinPath($dir, $name) |
||
1100 | { |
||
1101 | if ($dir === 'root') { |
||
1102 | $dir = ''; |
||
1103 | } |
||
1104 | |||
1105 | return $this->_normpath($dir.'/'.$name); |
||
1106 | } |
||
1107 | |||
1108 | /** |
||
1109 | * Return normalized path, this works the same as os.path.normpath() in Python. |
||
1110 | * |
||
1111 | * @param string $path path |
||
1112 | * |
||
1113 | * @return string |
||
1114 | * |
||
1115 | * @author Troex Nevelin |
||
1116 | **/ |
||
1117 | View Code Duplication | protected function _normpath($path) |
|
1118 | { |
||
1119 | if (DIRECTORY_SEPARATOR !== '/') { |
||
1120 | $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); |
||
1121 | } |
||
1122 | $path = '/'.ltrim($path, '/'); |
||
1123 | |||
1124 | return $path; |
||
1125 | } |
||
1126 | |||
1127 | /** |
||
1128 | * Return file path related to root dir. |
||
1129 | * |
||
1130 | * @param string $path file path |
||
1131 | * |
||
1132 | * @return string |
||
1133 | * |
||
1134 | * @author Dmitry (dio) Levashov |
||
1135 | **/ |
||
1136 | protected function _relpath($path) |
||
1137 | { |
||
1138 | return $path; |
||
1139 | } |
||
1140 | |||
1141 | /** |
||
1142 | * Convert path related to root dir into real path. |
||
1143 | * |
||
1144 | * @param string $path file path |
||
1145 | * |
||
1146 | * @return string |
||
1147 | * |
||
1148 | * @author Dmitry (dio) Levashov |
||
1149 | **/ |
||
1150 | protected function _abspath($path) |
||
1151 | { |
||
1152 | return $path; |
||
1153 | } |
||
1154 | |||
1155 | /** |
||
1156 | * Return fake path started from root dir. |
||
1157 | * |
||
1158 | * @param string $path file path |
||
1159 | * |
||
1160 | * @return string |
||
1161 | * |
||
1162 | * @author Dmitry (dio) Levashov |
||
1163 | **/ |
||
1164 | protected function _path($path) |
||
1165 | { |
||
1166 | return $this->rootName.$this->_normpath(substr($path, strlen($this->root))); |
||
1167 | } |
||
1168 | |||
1169 | /** |
||
1170 | * Return true if $path is children of $parent. |
||
1171 | * |
||
1172 | * @param string $path path to check |
||
1173 | * @param string $parent parent path |
||
1174 | * |
||
1175 | * @return bool |
||
1176 | * |
||
1177 | * @author Dmitry (dio) Levashov |
||
1178 | **/ |
||
1179 | protected function _inpath($path, $parent) |
||
1180 | { |
||
1181 | return $path == $parent || strpos($path, $parent.'/') === 0; |
||
1182 | } |
||
1183 | |||
1184 | /***************** file stat ********************/ |
||
1185 | |||
1186 | /** |
||
1187 | * Return stat for given path. |
||
1188 | * Stat contains following fields: |
||
1189 | * - (int) size file size in b. required |
||
1190 | * - (int) ts file modification time in unix time. required |
||
1191 | * - (string) mime mimetype. required for folders, others - optionally |
||
1192 | * - (bool) read read permissions. required |
||
1193 | * - (bool) write write permissions. required |
||
1194 | * - (bool) locked is object locked. optionally |
||
1195 | * - (bool) hidden is object hidden. optionally |
||
1196 | * - (string) alias for symlinks - link target path relative to root path. optionally |
||
1197 | * - (string) target for symlinks - link target path. optionally. |
||
1198 | * |
||
1199 | * If file does not exists - returns empty array or false. |
||
1200 | * |
||
1201 | * @param string $path file path |
||
1202 | * |
||
1203 | * @return array|false |
||
1204 | * |
||
1205 | * @author Dmitry (dio) Levashov |
||
1206 | **/ |
||
1207 | protected function _stat($path) |
||
1208 | { |
||
1209 | if ($raw = $this->_od_getFileRaw($path)) { |
||
1210 | return $this->_od_parseRaw($raw); |
||
1211 | } |
||
1212 | |||
1213 | return false; |
||
1214 | } |
||
1215 | |||
1216 | /** |
||
1217 | * Return true if path is dir and has at least one childs directory. |
||
1218 | * |
||
1219 | * @param string $path dir path |
||
1220 | * |
||
1221 | * @return bool |
||
1222 | * |
||
1223 | * @author Dmitry (dio) Levashov |
||
1224 | **/ |
||
1225 | protected function _subdirs($path) |
||
1226 | { |
||
1227 | list(, $itemId) = $this->_od_splitPath($path); |
||
1228 | |||
1229 | return (bool) $this->_od_query($itemId, false, false, [ |
||
1230 | 'query' => [ |
||
1231 | 'top' => 1, |
||
1232 | 'select' => 'id', |
||
1233 | 'filter' => 'folder ne null', |
||
1234 | ], |
||
1235 | ]); |
||
1236 | } |
||
1237 | |||
1238 | /** |
||
1239 | * Return object width and height |
||
1240 | * Ususaly used for images, but can be realize for video etc... |
||
1241 | * |
||
1242 | * @param string $path file path |
||
1243 | * @param string $mime file mime type |
||
1244 | * |
||
1245 | * @return string |
||
1246 | * |
||
1247 | * @author Dmitry (dio) Levashov |
||
1248 | **/ |
||
1249 | protected function _dimensions($path, $mime) |
||
1250 | { |
||
1251 | if (strpos($mime, 'image') !== 0) { |
||
1252 | return ''; |
||
1253 | } |
||
1254 | |||
1255 | $cache = $this->_od_getFileRaw($path); |
||
1256 | |||
1257 | if ($cache && $img = $cache->image) { |
||
1258 | if (isset($img->width) && isset($img->height)) { |
||
1259 | return $img->width.'x'.$img->height; |
||
1260 | } |
||
1261 | } |
||
1262 | |||
1263 | $ret = ''; |
||
1264 | View Code Duplication | if ($work = $this->getWorkFile($path)) { |
|
1265 | if ($size = @getimagesize($work)) { |
||
1266 | $cache['width'] = $size[0]; |
||
1267 | $cache['height'] = $size[1]; |
||
1268 | $ret = $size[0].'x'.$size[1]; |
||
1269 | } |
||
1270 | } |
||
1271 | is_file($work) && @unlink($work); |
||
1272 | |||
1273 | return $ret; |
||
1274 | } |
||
1275 | |||
1276 | /******************** file/dir content *********************/ |
||
1277 | |||
1278 | /** |
||
1279 | * Return files list in directory. |
||
1280 | * |
||
1281 | * @param string $path dir path |
||
1282 | * |
||
1283 | * @return array |
||
1284 | * |
||
1285 | * @author Dmitry (dio) Levashov |
||
1286 | * @author Cem (DiscoFever) |
||
1287 | **/ |
||
1288 | protected function _scandir($path) |
||
1289 | { |
||
1290 | return isset($this->dirsCache[$path]) |
||
1291 | ? $this->dirsCache[$path] |
||
1292 | : $this->cacheDir($path); |
||
1293 | } |
||
1294 | |||
1295 | /** |
||
1296 | * Open file and return file pointer. |
||
1297 | * |
||
1298 | * @param string $path file path |
||
1299 | * @param bool $write open file for writing |
||
0 ignored issues
–
show
There is no parameter named
$write . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
1300 | * |
||
1301 | * @return resource|false |
||
1302 | * |
||
1303 | * @author Dmitry (dio) Levashov |
||
1304 | **/ |
||
1305 | View Code Duplication | protected function _fopen($path, $mode = 'rb') |
|
1306 | { |
||
1307 | if ($mode === 'rb' || $mode === 'r') { |
||
1308 | list(, $itemId) = $this->_od_splitPath($path); |
||
1309 | $data = [ |
||
1310 | 'target' => self::API_URL.$itemId.'/content', |
||
1311 | 'headers' => ['Authorization: Bearer '.$this->token->data->access_token], |
||
1312 | ]; |
||
1313 | |||
1314 | return elFinder::getStreamByUrl($data); |
||
1315 | } |
||
1316 | |||
1317 | return false; |
||
1318 | } |
||
1319 | |||
1320 | /** |
||
1321 | * Close opened file. |
||
1322 | * |
||
1323 | * @param resource $fp file pointer |
||
1324 | * |
||
1325 | * @return bool |
||
1326 | * |
||
1327 | * @author Dmitry (dio) Levashov |
||
1328 | **/ |
||
1329 | protected function _fclose($fp, $path = '') |
||
1330 | { |
||
1331 | fclose($fp); |
||
1332 | if ($path) { |
||
1333 | unlink($this->getTempFile($path)); |
||
1334 | } |
||
1335 | } |
||
1336 | |||
1337 | /******************** file/dir manipulations *************************/ |
||
1338 | |||
1339 | /** |
||
1340 | * Create dir and return created dir path or false on failed. |
||
1341 | * |
||
1342 | * @param string $path parent dir path |
||
1343 | * @param string $name new directory name |
||
1344 | * |
||
1345 | * @return string|bool |
||
1346 | * |
||
1347 | * @author Dmitry (dio) Levashov |
||
1348 | **/ |
||
1349 | protected function _mkdir($path, $name) |
||
1350 | { |
||
1351 | $namePath = $this->_joinPath($path, $name); |
||
1352 | list($parentId) = $this->_od_splitPath($namePath); |
||
1353 | |||
1354 | try { |
||
1355 | $properties = [ |
||
1356 | 'name' => (string) $name, |
||
1357 | 'folder' => (object) [], |
||
1358 | ]; |
||
1359 | |||
1360 | $data = (object) $properties; |
||
1361 | |||
1362 | $url = self::API_URL.$parentId.'/children'; |
||
1363 | |||
1364 | $curl = $this->_od_prepareCurl($url); |
||
1365 | |||
1366 | curl_setopt_array($curl, [ |
||
1367 | CURLOPT_POST => true, |
||
1368 | CURLOPT_POSTFIELDS => json_encode($data), |
||
1369 | ]); |
||
1370 | |||
1371 | //create the Folder in the Parent |
||
1372 | $result = curl_exec($curl); |
||
1373 | curl_close($curl); |
||
1374 | $folder = json_decode($result); |
||
1375 | |||
1376 | return $this->_joinPath($path, $folder->id); |
||
1377 | } catch (Exception $e) { |
||
1378 | return $this->setError('OneDrive error: '.$e->getMessage()); |
||
1379 | } |
||
1380 | } |
||
1381 | |||
1382 | /** |
||
1383 | * Create file and return it's path or false on failed. |
||
1384 | * |
||
1385 | * @param string $path parent dir path |
||
1386 | * @param string $name new file name |
||
1387 | * |
||
1388 | * @return string|bool |
||
1389 | * |
||
1390 | * @author Dmitry (dio) Levashov |
||
1391 | **/ |
||
1392 | protected function _mkfile($path, $name) |
||
1393 | { |
||
1394 | return $this->_save(tmpfile(), $path, $name, []); |
||
1395 | } |
||
1396 | |||
1397 | /** |
||
1398 | * Create symlink. FTP driver does not support symlinks. |
||
1399 | * |
||
1400 | * @param string $target link target |
||
1401 | * @param string $path symlink path |
||
1402 | * |
||
1403 | * @return bool |
||
1404 | * |
||
1405 | * @author Dmitry (dio) Levashov |
||
1406 | **/ |
||
1407 | protected function _symlink($target, $path, $name) |
||
1408 | { |
||
1409 | return false; |
||
1410 | } |
||
1411 | |||
1412 | /** |
||
1413 | * Copy file into another file. |
||
1414 | * |
||
1415 | * @param string $source source file path |
||
1416 | * @param string $targetDir target directory path |
||
1417 | * @param string $name new file name |
||
1418 | * |
||
1419 | * @return bool |
||
1420 | * |
||
1421 | * @author Dmitry (dio) Levashov |
||
1422 | **/ |
||
1423 | protected function _copy($source, $targetDir, $name) |
||
1424 | { |
||
1425 | $path = $this->_joinPath($targetDir, $name); |
||
1426 | |||
1427 | try { |
||
1428 | //Set the Parent id |
||
1429 | list(, $parentId) = $this->_od_splitPath($targetDir); |
||
1430 | list(, $itemId) = $this->_od_splitPath($source); |
||
1431 | |||
1432 | $url = self::API_URL.$itemId.'/action.copy'; |
||
1433 | |||
1434 | $properties = [ |
||
1435 | 'name' => (string) $name, |
||
1436 | ]; |
||
1437 | if ($parentId === 'root') { |
||
1438 | $properties['parentReference'] = (object) ['path' => '/drive/root:']; |
||
1439 | } else { |
||
1440 | $properties['parentReference'] = (object) ['id' => (string) $parentId]; |
||
1441 | } |
||
1442 | $data = (object) $properties; |
||
1443 | $curl = $this->_od_prepareCurl($url); |
||
1444 | curl_setopt_array($curl, [ |
||
1445 | CURLOPT_POST => true, |
||
1446 | CURLOPT_HEADER => true, |
||
1447 | CURLOPT_HTTPHEADER => [ |
||
1448 | 'Content-Type: application/json', |
||
1449 | 'Authorization: Bearer '.$this->token->data->access_token, |
||
1450 | 'Prefer: respond-async', |
||
1451 | ], |
||
1452 | CURLOPT_POSTFIELDS => json_encode($data), |
||
1453 | ]); |
||
1454 | $result = curl_exec($curl); |
||
1455 | curl_close($curl); |
||
1456 | |||
1457 | $res = false; |
||
1458 | if (preg_match('/Location: (.+)/', $result, $m)) { |
||
1459 | $monUrl = trim($m[1]); |
||
1460 | while (! $res) { |
||
1461 | usleep(200000); |
||
1462 | $curl = $this->_od_prepareCurl($monUrl); |
||
1463 | $state = json_decode(curl_exec($curl)); |
||
1464 | curl_close($curl); |
||
1465 | if (isset($state->status)) { |
||
1466 | if ($state->status === 'failed') { |
||
1467 | break; |
||
1468 | } else { |
||
1469 | continue; |
||
1470 | } |
||
1471 | } |
||
1472 | $res = $state; |
||
1473 | } |
||
1474 | } |
||
1475 | |||
1476 | View Code Duplication | if ($res && isset($res->id)) { |
|
1477 | if (isset($res->folder) && isset($this->sessionCache['subdirs'])) { |
||
1478 | $this->sessionCache['subdirs'][$targetDir] = true; |
||
1479 | } |
||
1480 | |||
1481 | return $this->_joinPath($targetDir, $res->id); |
||
1482 | } |
||
1483 | |||
1484 | return false; |
||
1485 | } catch (Exception $e) { |
||
1486 | return $this->setError('OneDrive error: '.$e->getMessage()); |
||
1487 | } |
||
1488 | |||
1489 | return true; |
||
1490 | } |
||
1491 | |||
1492 | /** |
||
1493 | * Move file into another parent dir. |
||
1494 | * Return new file path or false. |
||
1495 | * |
||
1496 | * @param string $source source file path |
||
1497 | * @param string $target target dir path |
||
1498 | * @param string $name file name |
||
1499 | * |
||
1500 | * @return string|bool |
||
1501 | * |
||
1502 | * @author Dmitry (dio) Levashov |
||
1503 | **/ |
||
1504 | protected function _move($source, $targetDir, $name) |
||
1505 | { |
||
1506 | try { |
||
1507 | list(, $targetParentId) = $this->_od_splitPath($targetDir); |
||
1508 | list($sourceParentId, $itemId, $srcParent) = $this->_od_splitPath($source); |
||
1509 | |||
1510 | $properties = [ |
||
1511 | 'name' => (string) $name, |
||
1512 | ]; |
||
1513 | if ($targetParentId !== $sourceParentId) { |
||
1514 | $properties['parentReference'] = (object) ['id' => (string) $targetParentId]; |
||
1515 | } |
||
1516 | |||
1517 | $url = self::API_URL.$itemId; |
||
1518 | $data = (object) $properties; |
||
1519 | |||
1520 | $curl = $this->_od_prepareCurl($url); |
||
1521 | |||
1522 | curl_setopt_array($curl, [ |
||
1523 | CURLOPT_CUSTOMREQUEST => 'PATCH', |
||
1524 | CURLOPT_POSTFIELDS => json_encode($data), |
||
1525 | ]); |
||
1526 | |||
1527 | $result = json_decode(curl_exec($curl)); |
||
1528 | curl_close($curl); |
||
1529 | View Code Duplication | if ($result && isset($result->id)) { |
|
1530 | return $targetDir.'/'.$result->id; |
||
1531 | } else { |
||
1532 | return false; |
||
1533 | } |
||
1534 | } catch (Exception $e) { |
||
1535 | return $this->setError('OneDrive error: '.$e->getMessage()); |
||
1536 | } |
||
1537 | |||
1538 | return false; |
||
1539 | } |
||
1540 | |||
1541 | /** |
||
1542 | * Remove file. |
||
1543 | * |
||
1544 | * @param string $path file path |
||
1545 | * |
||
1546 | * @return bool |
||
1547 | * |
||
1548 | * @author Dmitry (dio) Levashov |
||
1549 | **/ |
||
1550 | protected function _unlink($path) |
||
1551 | { |
||
1552 | $stat = $this->stat($path); |
||
1553 | try { |
||
1554 | list(, $itemId) = $this->_od_splitPath($path); |
||
1555 | |||
1556 | $url = self::API_URL.$itemId; |
||
1557 | |||
1558 | $curl = $this->_od_prepareCurl($url); |
||
1559 | curl_setopt_array($curl, [ |
||
1560 | CURLOPT_CUSTOMREQUEST => 'DELETE', |
||
1561 | ]); |
||
1562 | |||
1563 | //unlink or delete File or Folder in the Parent |
||
1564 | $result = curl_exec($curl); |
||
1565 | curl_close($curl); |
||
1566 | } catch (Exception $e) { |
||
1567 | return $this->setError('OneDrive error: '.$e->getMessage()); |
||
1568 | } |
||
1569 | |||
1570 | return true; |
||
1571 | } |
||
1572 | |||
1573 | /** |
||
1574 | * Remove dir. |
||
1575 | * |
||
1576 | * @param string $path dir path |
||
1577 | * |
||
1578 | * @return bool |
||
1579 | * |
||
1580 | * @author Dmitry (dio) Levashov |
||
1581 | **/ |
||
1582 | protected function _rmdir($path) |
||
1583 | { |
||
1584 | return $this->_unlink($path); |
||
1585 | } |
||
1586 | |||
1587 | /** |
||
1588 | * Create new file and write into it from file pointer. |
||
1589 | * Return new file path or false on error. |
||
1590 | * |
||
1591 | * @param resource $fp file pointer |
||
1592 | * @param string $dir target dir path |
||
0 ignored issues
–
show
There is no parameter named
$dir . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
1593 | * @param string $name file name |
||
1594 | * @param array $stat file stat (required by some virtual fs) |
||
1595 | * |
||
1596 | * @return bool|string |
||
1597 | * |
||
1598 | * @author Dmitry (dio) Levashov |
||
1599 | **/ |
||
1600 | protected function _save($fp, $path, $name, $stat) |
||
1601 | { |
||
1602 | $itemId = ''; |
||
1603 | View Code Duplication | if ($name === '') { |
|
1604 | list($parentId, $itemId, $parent) = $this->_od_splitPath($path); |
||
1605 | } else { |
||
1606 | if ($stat) { |
||
0 ignored issues
–
show
The expression
$stat of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
1607 | if (isset($stat['name'])) { |
||
1608 | $name = $stat['name']; |
||
1609 | } |
||
1610 | if (isset($stat['rev']) && strpos($stat['hash'], $this->id) === 0) { |
||
1611 | $itemId = $stat['rev']; |
||
1612 | } |
||
1613 | } |
||
1614 | list(, $parentId) = $this->_od_splitPath($path); |
||
1615 | $parent = $path; |
||
1616 | } |
||
1617 | |||
1618 | try { |
||
1619 | //Create or Update a file |
||
1620 | $params = ['overwrite' => 'true']; |
||
1621 | $query = http_build_query($params); |
||
1622 | |||
1623 | if ($itemId === '') { |
||
1624 | $url = self::API_URL.$parentId.'/children/'.rawurlencode($name).'/content?'.$query; |
||
1625 | } else { |
||
1626 | $url = self::API_URL.$itemId.'/content?'.$query; |
||
1627 | } |
||
1628 | $curl = $this->_od_prepareCurl(); |
||
1629 | $stats = fstat($fp); |
||
1630 | |||
1631 | $options = [ |
||
1632 | CURLOPT_URL => $url, |
||
1633 | CURLOPT_PUT => true, |
||
1634 | CURLOPT_INFILE => $fp, |
||
1635 | ]; |
||
1636 | // Size |
||
1637 | if ($stats[7]) { |
||
1638 | $options[CURLOPT_INFILESIZE] = $stats[7]; |
||
1639 | } |
||
1640 | |||
1641 | curl_setopt_array($curl, $options); |
||
1642 | |||
1643 | //create or update File in the Target |
||
1644 | $file = json_decode(curl_exec($curl)); |
||
1645 | curl_close($curl); |
||
1646 | |||
1647 | return $this->_joinPath($parent, $file->id); |
||
1648 | } catch (Exception $e) { |
||
1649 | return $this->setError('OneDrive error: '.$e->getMessage()); |
||
1650 | } |
||
1651 | } |
||
1652 | |||
1653 | /** |
||
1654 | * Get file contents. |
||
1655 | * |
||
1656 | * @param string $path file path |
||
1657 | * |
||
1658 | * @return string|false |
||
1659 | * |
||
1660 | * @author Dmitry (dio) Levashov |
||
1661 | **/ |
||
1662 | View Code Duplication | protected function _getContents($path) |
|
1663 | { |
||
1664 | $contents = ''; |
||
1665 | |||
1666 | try { |
||
1667 | list(, $itemId) = $this->_od_splitPath($path); |
||
1668 | $url = self::API_URL.$itemId.'/content'; |
||
1669 | $contents = $this->_od_createCurl($url, $contents = true); |
||
1670 | } catch (Exception $e) { |
||
1671 | return $this->setError('OneDrive error: '.$e->getMessage()); |
||
1672 | } |
||
1673 | |||
1674 | return $contents; |
||
1675 | } |
||
1676 | |||
1677 | /** |
||
1678 | * Write a string to a file. |
||
1679 | * |
||
1680 | * @param string $path file path |
||
1681 | * @param string $content new file content |
||
1682 | * |
||
1683 | * @return bool |
||
1684 | * |
||
1685 | * @author Dmitry (dio) Levashov |
||
1686 | **/ |
||
1687 | View Code Duplication | protected function _filePutContents($path, $content) |
|
1688 | { |
||
1689 | $res = false; |
||
1690 | |||
1691 | if ($local = $this->getTempFile($path)) { |
||
1692 | if (file_put_contents($local, $content, LOCK_EX) !== false |
||
1693 | && ($fp = fopen($local, 'rb'))) { |
||
1694 | clearstatcache(); |
||
1695 | $res = $this->_save($fp, $path, '', []); |
||
1696 | fclose($fp); |
||
1697 | } |
||
1698 | file_exists($local) && unlink($local); |
||
1699 | } |
||
1700 | |||
1701 | return $res; |
||
1702 | } |
||
1703 | |||
1704 | /** |
||
1705 | * Detect available archivers. |
||
1706 | **/ |
||
1707 | protected function _checkArchivers() |
||
1708 | { |
||
1709 | // die('Not yet implemented. (_checkArchivers)'); |
||
1710 | return []; |
||
1711 | } |
||
1712 | |||
1713 | /** |
||
1714 | * chmod implementation. |
||
1715 | * |
||
1716 | * @return bool |
||
1717 | **/ |
||
1718 | protected function _chmod($path, $mode) |
||
1719 | { |
||
1720 | return false; |
||
1721 | } |
||
1722 | |||
1723 | /** |
||
1724 | * Unpack archive. |
||
1725 | * |
||
1726 | * @param string $path archive path |
||
1727 | * @param array $arc archiver command and arguments (same as in $this->archivers) |
||
1728 | * |
||
1729 | * @return true |
||
1730 | * |
||
1731 | * @author Dmitry (dio) Levashov |
||
1732 | * @author Alexey Sukhotin |
||
1733 | **/ |
||
1734 | protected function _unpack($path, $arc) |
||
1735 | { |
||
1736 | die('Not yet implemented. (_unpack)'); |
||
1737 | //return false; |
||
1738 | } |
||
1739 | |||
1740 | /** |
||
1741 | * Recursive symlinks search. |
||
1742 | * |
||
1743 | * @param string $path file/dir path |
||
1744 | * |
||
1745 | * @return bool |
||
1746 | * |
||
1747 | * @author Dmitry (dio) Levashov |
||
1748 | **/ |
||
1749 | protected function _findSymlinks($path) |
||
1750 | { |
||
1751 | die('Not yet implemented. (_findSymlinks)'); |
||
1752 | } |
||
1753 | |||
1754 | /** |
||
1755 | * Extract files from archive. |
||
1756 | * |
||
1757 | * @param string $path archive path |
||
1758 | * @param array $arc archiver command and arguments (same as in $this->archivers) |
||
1759 | * |
||
1760 | * @return true |
||
1761 | * |
||
1762 | * @author Dmitry (dio) Levashov, |
||
1763 | * @author Alexey Sukhotin |
||
1764 | **/ |
||
1765 | protected function _extract($path, $arc) |
||
1766 | { |
||
1767 | die('Not yet implemented. (_extract)'); |
||
1768 | } |
||
1769 | |||
1770 | /** |
||
1771 | * Create archive and return its path. |
||
1772 | * |
||
1773 | * @param string $dir target dir |
||
1774 | * @param array $files files names list |
||
1775 | * @param string $name archive name |
||
1776 | * @param array $arc archiver options |
||
1777 | * |
||
1778 | * @return string|bool |
||
1779 | * |
||
1780 | * @author Dmitry (dio) Levashov, |
||
1781 | * @author Alexey Sukhotin |
||
1782 | **/ |
||
1783 | protected function _archive($dir, $files, $name, $arc) |
||
1784 | { |
||
1785 | die('Not yet implemented. (_archive)'); |
||
1786 | } |
||
1787 | } // END class |
||
1788 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.
Consider the following example. The parameter
$italy
is not defined by the methodfinale(...)
.The most likely cause is that the parameter was removed, but the annotation was not.