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['googledrive'] = 'GoogleDrive'; |
||
4 | |||
5 | /** |
||
6 | * Simple elFinder driver for GoogleDrive |
||
7 | * google-api-php-client-2.x or above. |
||
8 | * |
||
9 | * @author Dmitry (dio) Levashov |
||
10 | * @author Cem (discofever) |
||
11 | **/ |
||
12 | class elFinderVolumeGoogleDrive extends elFinderVolumeDriver |
||
13 | { |
||
14 | /** |
||
15 | * MIME tyoe of directory. |
||
16 | * |
||
17 | * @var string |
||
18 | */ |
||
19 | const DIRMIME = 'application/vnd.google-apps.folder'; |
||
20 | |||
21 | /** |
||
22 | * Fetch fields for list. |
||
23 | * |
||
24 | * @var string |
||
25 | */ |
||
26 | const FETCHFIELDS_LIST = 'files(id,name,mimeType,modifiedTime,parents,permissions,size,imageMediaMetadata(height,width),thumbnailLink,webContentLink,webViewLink),nextPageToken'; |
||
27 | |||
28 | /** |
||
29 | * Fetch fields for get. |
||
30 | * |
||
31 | * @var string |
||
32 | */ |
||
33 | const FETCHFIELDS_GET = 'id,name,mimeType,modifiedTime,parents,permissions,size,imageMediaMetadata(height,width),thumbnailLink,webContentLink,webViewLink'; |
||
34 | |||
35 | /** |
||
36 | * Net mount key. |
||
37 | * |
||
38 | * @var string |
||
39 | **/ |
||
40 | public $netMountKey = ''; |
||
41 | /** |
||
42 | * Driver id |
||
43 | * Must be started from letter and contains [a-z0-9] |
||
44 | * Used as part of volume id. |
||
45 | * |
||
46 | * @var string |
||
47 | **/ |
||
48 | protected $driverId = 'gd'; |
||
49 | |||
50 | /** |
||
51 | * Google API client object. |
||
52 | * |
||
53 | * @var object |
||
54 | **/ |
||
55 | protected $client = null; |
||
56 | |||
57 | /** |
||
58 | * GoogleDrive service object. |
||
59 | * |
||
60 | * @var object |
||
61 | **/ |
||
62 | protected $service = null; |
||
63 | |||
64 | /** |
||
65 | * Cache of parents of each directories. |
||
66 | * |
||
67 | * @var array |
||
68 | */ |
||
69 | protected $parents = []; |
||
70 | |||
71 | /** |
||
72 | * Cache of chiled directories of each directories. |
||
73 | * |
||
74 | * @var array |
||
75 | */ |
||
76 | protected $directories = null; |
||
77 | |||
78 | /** |
||
79 | * Cache of itemID => name of each items. |
||
80 | * |
||
81 | * @var array |
||
82 | */ |
||
83 | protected $names = []; |
||
84 | |||
85 | /** |
||
86 | * Directory for tmp files |
||
87 | * If not set driver will try to use tmbDir as tmpDir. |
||
88 | * |
||
89 | * @var string |
||
90 | **/ |
||
91 | protected $tmp = ''; |
||
92 | |||
93 | /** |
||
94 | * Constructor |
||
95 | * Extend options with required fields. |
||
96 | * |
||
97 | * @author Dmitry (dio) Levashov |
||
98 | * @author Cem (DiscoFever) |
||
99 | **/ |
||
100 | public function __construct() |
||
101 | { |
||
102 | $opts = [ |
||
103 | 'client_id' => '', |
||
104 | 'client_secret' => '', |
||
105 | 'access_token' => [], |
||
106 | 'refresh_token' => '', |
||
107 | 'serviceAccountConfigFile' => '', |
||
108 | 'root' => 'My Drive', |
||
109 | 'gdAlias' => '%s@GDrive', |
||
110 | 'googleApiClient' => '', |
||
111 | 'path' => '/', |
||
112 | 'tmbPath' => '', |
||
113 | 'separator' => '/', |
||
114 | 'useGoogleTmb' => true, |
||
115 | 'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#', |
||
116 | 'rootCssClass' => 'elfinder-navbar-root-googledrive', |
||
117 | 'publishPermission' => [ |
||
118 | 'type' => 'anyone', |
||
119 | 'role' => 'reader', |
||
120 | 'withLink' => true, |
||
121 | ], |
||
122 | 'appsExportMap' => [ |
||
123 | 'application/vnd.google-apps.document' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', |
||
124 | 'application/vnd.google-apps.spreadsheet' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', |
||
125 | 'application/vnd.google-apps.drawing' => 'application/pdf', |
||
126 | 'application/vnd.google-apps.presentation' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', |
||
127 | 'application/vnd.google-apps.script' => 'application/vnd.google-apps.script+json', |
||
128 | 'default' => 'application/pdf', |
||
129 | ], |
||
130 | ]; |
||
131 | $this->options = array_merge($this->options, $opts); |
||
132 | $this->options['mimeDetect'] = 'internal'; |
||
133 | } |
||
134 | |||
135 | /*********************************************************************/ |
||
136 | /* EXTENDED FUNCTIONS */ |
||
137 | /*********************************************************************/ |
||
138 | |||
139 | /** |
||
140 | * Prepare |
||
141 | * Call from elFinder::netmout() before volume->mount(). |
||
142 | * |
||
143 | * @return array |
||
144 | * |
||
145 | * @author Naoki Sawada |
||
146 | * @author Raja Sharma updating for GoogleDrive |
||
147 | **/ |
||
148 | public function netmountPrepare($options) |
||
149 | { |
||
150 | if (empty($options['client_id']) && defined('ELFINDER_GOOGLEDRIVE_CLIENTID')) { |
||
151 | $options['client_id'] = ELFINDER_GOOGLEDRIVE_CLIENTID; |
||
152 | } |
||
153 | if (empty($options['client_secret']) && defined('ELFINDER_GOOGLEDRIVE_CLIENTSECRET')) { |
||
154 | $options['client_secret'] = ELFINDER_GOOGLEDRIVE_CLIENTSECRET; |
||
155 | } |
||
156 | if (empty($options['googleApiClient']) && defined('ELFINDER_GOOGLEDRIVE_GOOGLEAPICLIENT')) { |
||
157 | $options['googleApiClient'] = ELFINDER_GOOGLEDRIVE_GOOGLEAPICLIENT; |
||
158 | include_once $options['googleApiClient']; |
||
159 | } |
||
160 | |||
161 | if (! isset($options['pass'])) { |
||
162 | $options['pass'] = ''; |
||
163 | } |
||
164 | |||
165 | try { |
||
166 | $client = new \Google_Client(); |
||
167 | $client->setClientId($options['client_id']); |
||
168 | $client->setClientSecret($options['client_secret']); |
||
169 | |||
170 | View Code Duplication | if ($options['pass'] === 'reauth') { |
|
171 | $options['pass'] = ''; |
||
172 | $this->session->set('GoogleDriveAuthParams', [])->set('GoogleDriveTokens', []); |
||
173 | } elseif ($options['pass'] === 'googledrive') { |
||
174 | $options['pass'] = ''; |
||
175 | } |
||
176 | |||
177 | $options = array_merge($this->session->get('GoogleDriveAuthParams', []), $options); |
||
178 | |||
179 | View Code Duplication | if (! isset($options['access_token'])) { |
|
180 | $options['access_token'] = $this->session->get('GoogleDriveTokens', []); |
||
181 | $this->session->remove('GoogleDriveTokens'); |
||
182 | } |
||
183 | $aToken = $options['access_token']; |
||
184 | |||
185 | $rootObj = $service = null; |
||
186 | View Code Duplication | if ($aToken) { |
|
187 | try { |
||
188 | $client->setAccessToken($aToken); |
||
189 | if ($client->isAccessTokenExpired()) { |
||
190 | $aToken = array_merge($aToken, $client->fetchAccessTokenWithRefreshToken()); |
||
191 | $client->setAccessToken($aToken); |
||
192 | } |
||
193 | $service = new \Google_Service_Drive($client); |
||
194 | $rootObj = $service->files->get('root'); |
||
195 | |||
196 | $options['access_token'] = $aToken; |
||
197 | $this->session->set('GoogleDriveAuthParams', $options); |
||
198 | } catch (Exception $e) { |
||
199 | $aToken = []; |
||
200 | $options['access_token'] = []; |
||
201 | if ($options['user'] !== 'init') { |
||
202 | $this->session->set('GoogleDriveAuthParams', $options); |
||
203 | |||
204 | return ['exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE]; |
||
205 | } |
||
206 | } |
||
207 | } |
||
208 | |||
209 | if ($options['user'] === 'init') { |
||
210 | if (empty($options['url'])) { |
||
211 | $options['url'] = elFinder::getConnectorUrl(); |
||
212 | } |
||
213 | |||
214 | $callback = $options['url'] |
||
215 | .'?cmd=netmount&protocol=googledrive&host=1'; |
||
216 | $client->setRedirectUri($callback); |
||
217 | |||
218 | if (! $aToken && empty($_GET['code'])) { |
||
219 | $client->setScopes([Google_Service_Drive::DRIVE]); |
||
220 | if (! empty($options['offline'])) { |
||
221 | $client->setApprovalPrompt('force'); |
||
222 | $client->setAccessType('offline'); |
||
223 | } |
||
224 | $url = $client->createAuthUrl(); |
||
225 | |||
226 | $html = '<input id="elf-volumedriver-googledrive-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.'\')">'; |
||
227 | $html .= '<script> |
||
228 | $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "googledrive", mode: "makebtn"}); |
||
229 | </script>'; |
||
230 | View Code Duplication | if (empty($options['pass']) && $options['host'] !== '1') { |
|
231 | $options['pass'] = 'return'; |
||
232 | $this->session->set('GoogleDriveAuthParams', $options); |
||
233 | |||
234 | return ['exit' => true, 'body' => $html]; |
||
235 | } else { |
||
236 | $out = [ |
||
237 | 'node' => $options['id'], |
||
238 | 'json' => '{"protocol": "googledrive", "mode": "makebtn", "body" : "'.str_replace($html, '"', '\\"').'", "error" : "'.elFinder::ERROR_ACCESS_DENIED.'"}', |
||
239 | 'bind' => 'netmount', |
||
240 | ]; |
||
241 | |||
242 | return ['exit' => 'callback', 'out' => $out]; |
||
243 | } |
||
244 | } else { |
||
245 | View Code Duplication | if (! empty($_GET['code'])) { |
|
246 | $aToken = $client->fetchAccessTokenWithAuthCode($_GET['code']); |
||
247 | $options['access_token'] = $aToken; |
||
248 | $this->session->set('GoogleDriveTokens', $aToken)->set('GoogleDriveAuthParams', $options); |
||
249 | $out = [ |
||
250 | 'node' => $options['id'], |
||
251 | 'json' => '{"protocol": "googledrive", "mode": "done", "reset": 1}', |
||
252 | 'bind' => 'netmount', |
||
253 | ]; |
||
254 | |||
255 | return ['exit' => 'callback', 'out' => $out]; |
||
256 | } |
||
257 | $path = $options['path']; |
||
258 | if ($path === '/') { |
||
259 | $path = 'root'; |
||
260 | } |
||
261 | $folders = []; |
||
262 | View Code Duplication | foreach ($service->files->listFiles([ |
|
263 | 'pageSize' => 1000, |
||
264 | 'q' => sprintf('trashed = false and "%s" in parents and mimeType = "application/vnd.google-apps.folder"', $path), |
||
265 | ]) as $f) { |
||
266 | $folders[$f->getId()] = $f->getName(); |
||
267 | } |
||
268 | natcasesort($folders); |
||
269 | |||
270 | if ($options['pass'] === 'folders') { |
||
271 | return ['exit' => true, 'folders' => $folders]; |
||
272 | } |
||
273 | |||
274 | $folders = ['root' => $rootObj->getName()] + $folders; |
||
275 | $folders = json_encode($folders); |
||
276 | $expires = empty($aToken['refresh_token']) ? $aToken['created'] + $aToken['expires_in'] - 30 : 0; |
||
277 | $json = '{"protocol": "googledrive", "mode": "done", "folders": '.$folders.', "expires": '.$expires.'}'; |
||
278 | $options['pass'] = 'return'; |
||
279 | $html = 'Google.com'; |
||
280 | $html .= '<script> |
||
281 | $("#'.$options['id'].'").elfinder("instance").trigger("netmount", '.$json.'); |
||
282 | </script>'; |
||
283 | $this->session->set('GoogleDriveAuthParams', $options); |
||
284 | |||
285 | return ['exit' => true, 'body' => $html]; |
||
286 | } |
||
287 | } |
||
288 | } catch (Exception $e) { |
||
289 | $this->session->remove('GoogleDriveAuthParams')->remove('GoogleDriveTokens'); |
||
290 | View Code Duplication | if (empty($options['pass'])) { |
|
291 | return ['exit' => true, 'body' => '{msg:'.elFinder::ERROR_ACCESS_DENIED.'}'.' '.$e->getMessage()]; |
||
292 | } else { |
||
293 | return ['exit' => true, 'error' => [elFinder::ERROR_ACCESS_DENIED, $e->getMessage()]]; |
||
294 | } |
||
295 | } |
||
296 | |||
297 | if (! $aToken) { |
||
298 | return ['exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE]; |
||
299 | } |
||
300 | |||
301 | if ($options['path'] === '/') { |
||
302 | $options['path'] = 'root'; |
||
303 | } |
||
304 | |||
305 | try { |
||
306 | $file = $service->files->get($options['path']); |
||
307 | $options['alias'] = sprintf($this->options['gdAlias'], $file->getName()); |
||
308 | } catch (Google_Service_Exception $e) { |
||
0 ignored issues
–
show
|
|||
309 | $err = json_decode($e->getMessage(), true); |
||
310 | View Code Duplication | if (isset($err['error']) && $err['error']['code'] == 404) { |
|
311 | return ['exit' => true, 'error' => [elFinder::ERROR_TRGDIR_NOT_FOUND, $options['path']]]; |
||
312 | } else { |
||
313 | return ['exit' => true, 'error' => $e->getMessage()]; |
||
314 | } |
||
315 | } catch (Exception $e) { |
||
316 | return ['exit' => true, 'error' => $e->getMessage()]; |
||
317 | } |
||
318 | |||
319 | View Code Duplication | foreach (['host', 'user', 'pass', 'id', 'offline'] as $key) { |
|
320 | unset($options[$key]); |
||
321 | } |
||
322 | |||
323 | return $options; |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * process of on netunmount |
||
328 | * Drop `googledrive` & rm thumbs. |
||
329 | * |
||
330 | * @param array $options |
||
331 | * |
||
332 | * @return bool |
||
333 | */ |
||
334 | public function netunmount($netVolumes, $key) |
||
335 | { |
||
336 | if (! $this->options['useGoogleTmb']) { |
||
337 | if ($tmbs = glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->netMountKey.'*.png')) { |
||
338 | foreach ($tmbs as $file) { |
||
339 | unlink($file); |
||
340 | } |
||
341 | } |
||
342 | } |
||
343 | $this->session->remove($this->id.$this->netMountKey); |
||
344 | |||
345 | return true; |
||
346 | } |
||
347 | |||
348 | /*********************************************************************/ |
||
349 | /* FS API */ |
||
350 | /*********************************************************************/ |
||
351 | |||
352 | /** |
||
353 | * Close opened connection. |
||
354 | * |
||
355 | * @author Dmitry (dio) Levashov |
||
356 | **/ |
||
357 | public function umount() |
||
358 | { |
||
359 | } |
||
360 | |||
361 | /** |
||
362 | * Return content URL (for netmout volume driver) |
||
363 | * If file.url == 1 requests from JavaScript client with XHR. |
||
364 | * |
||
365 | * @param string $hash file hash |
||
366 | * @param array $options options array |
||
367 | * |
||
368 | * @return bool|string |
||
369 | * |
||
370 | * @author Naoki Sawada |
||
371 | */ |
||
372 | public function getContentUrl($hash, $options = []) |
||
373 | { |
||
374 | View Code Duplication | if (! empty($options['temporary'])) { |
|
375 | // try make temporary file |
||
376 | $url = parent::getContentUrl($hash, $options); |
||
377 | if ($url) { |
||
378 | return $url; |
||
379 | } |
||
380 | } |
||
381 | if (($file = $this->file($hash)) == false || ! $file['url'] || $file['url'] == 1) { |
||
382 | $path = $this->decode($hash); |
||
383 | |||
384 | if ($this->_gd_publish($path)) { |
||
385 | if ($raw = $this->_gd_getFile($path)) { |
||
386 | return $this->_gd_getLink($raw); |
||
387 | } |
||
388 | } |
||
389 | } |
||
390 | |||
391 | return false; |
||
392 | } |
||
393 | |||
394 | /** |
||
395 | * Return debug info for client. |
||
396 | * |
||
397 | * @return array |
||
398 | **/ |
||
399 | public function debug() |
||
400 | { |
||
401 | $res = parent::debug(); |
||
402 | View Code Duplication | if (empty($this->options['refresh_token']) && $this->options['access_token'] && isset($this->options['access_token']['refresh_token'])) { |
|
403 | $res['refresh_token'] = $this->options['access_token']['refresh_token']; |
||
404 | } |
||
405 | |||
406 | return $res; |
||
407 | } |
||
408 | |||
409 | /*********************************************************************/ |
||
410 | /* ORIGINAL FUNCTIONS */ |
||
411 | /*********************************************************************/ |
||
412 | |||
413 | /** |
||
414 | * Get Parent ID, Item ID, Parent Path as an array from path. |
||
415 | * |
||
416 | * @param string $path |
||
417 | * |
||
418 | * @return array |
||
419 | */ |
||
420 | protected function _gd_splitPath($path) |
||
421 | { |
||
422 | $path = trim($path, '/'); |
||
423 | $pid = ''; |
||
424 | if ($path === '') { |
||
425 | $id = 'root'; |
||
426 | $parent = ''; |
||
427 | } else { |
||
428 | $paths = explode('/', $path); |
||
429 | $id = array_pop($paths); |
||
430 | if ($paths) { |
||
431 | $parent = '/'.implode('/', $paths); |
||
432 | $pid = array_pop($paths); |
||
433 | } else { |
||
434 | $rootid = ($this->root === '/') ? 'root' : trim($this->root, '/'); |
||
435 | if ($id === $rootid) { |
||
436 | $parent = ''; |
||
437 | } else { |
||
438 | $parent = $this->root; |
||
439 | $pid = $rootid; |
||
440 | } |
||
441 | } |
||
442 | } |
||
443 | |||
444 | return [$pid, $id, $parent]; |
||
445 | } |
||
446 | |||
447 | /** |
||
448 | * Parse line from googledrive metadata output and return file stat (array). |
||
449 | * |
||
450 | * @param string $raw line from ftp_rawlist() output |
||
451 | * |
||
452 | * @return array |
||
453 | * |
||
454 | * @author Dmitry Levashov |
||
455 | **/ |
||
456 | protected function _gd_parseRaw($raw) |
||
457 | { |
||
458 | $stat = []; |
||
459 | |||
460 | $stat['iid'] = isset($raw['id']) ? $raw['id'] : 'root'; |
||
461 | $stat['name'] = isset($raw['name']) ? $raw['name'] : ''; |
||
462 | if (isset($raw['modifiedTime'])) { |
||
463 | $stat['ts'] = strtotime($raw['modifiedTime']); |
||
464 | } |
||
465 | |||
466 | if ($raw['mimeType'] === self::DIRMIME) { |
||
467 | $stat['mime'] = 'directory'; |
||
468 | $stat['size'] = 0; |
||
469 | } else { |
||
470 | $stat['mime'] = $raw['mimeType'] == 'image/bmp' ? 'image/x-ms-bmp' : $raw['mimeType']; |
||
471 | $stat['size'] = (int) $raw['size']; |
||
472 | if ($size = $raw->getImageMediaMetadata()) { |
||
0 ignored issues
–
show
|
|||
473 | $stat['width'] = $size['width']; |
||
474 | $stat['height'] = $size['height']; |
||
475 | } |
||
476 | |||
477 | $published = $this->_gd_isPublished($raw); |
||
478 | |||
479 | if ($this->options['useGoogleTmb']) { |
||
480 | if (isset($raw['thumbnailLink'])) { |
||
481 | if ($published) { |
||
482 | $stat['tmb'] = 'drive.google.com/thumbnail?authuser=0&sz=s'.$this->options['tmbSize'].'&id='.$raw['id']; |
||
483 | } else { |
||
484 | $stat['tmb'] = substr($raw['thumbnailLink'], 8); // remove "https://" |
||
485 | } |
||
486 | } else { |
||
487 | $stat['tmb'] = ''; |
||
488 | } |
||
489 | } |
||
490 | |||
491 | if ($published) { |
||
492 | $stat['url'] = $this->_gd_getLink($raw); |
||
493 | } elseif (! $this->disabledGetUrl) { |
||
494 | $stat['url'] = '1'; |
||
495 | } |
||
496 | } |
||
497 | |||
498 | return $stat; |
||
499 | } |
||
500 | |||
501 | /** |
||
502 | * Make cache of $parents, $names and $directories. |
||
503 | * |
||
504 | * @param string $usecache |
||
505 | */ |
||
506 | protected function _gd_getDirectoryData($usecache = true) |
||
507 | { |
||
508 | if ($usecache) { |
||
509 | $cache = $this->session->get($this->id.$this->netMountKey, []); |
||
510 | if ($cache) { |
||
511 | $this->parents = $cache['parents']; |
||
512 | $this->names = $cache['names']; |
||
513 | $this->directories = $cache['directories']; |
||
514 | |||
515 | return; |
||
516 | } |
||
517 | } |
||
518 | |||
519 | $root = ''; |
||
520 | if ($this->root === '/') { |
||
521 | // get root id |
||
522 | if ($res = $this->_gd_getFile('/', 'id')) { |
||
523 | $root = $res->getId(); |
||
524 | } |
||
525 | } |
||
526 | |||
527 | $data = []; |
||
528 | $opts = [ |
||
529 | 'fields' => 'files(id, name, parents)', |
||
530 | 'q' => sprintf('trashed=false and mimeType="%s"', self::DIRMIME), |
||
531 | ]; |
||
532 | $res = $this->_gd_query($opts); |
||
533 | foreach ($res as $raw) { |
||
534 | if ($parents = $raw->getParents()) { |
||
535 | $id = $raw->getId(); |
||
536 | $this->parents[$id] = $parents; |
||
537 | $this->names[$id] = $raw->getName(); |
||
538 | foreach ($parents as $p) { |
||
539 | if (isset($data[$p])) { |
||
540 | $data[$p][] = $id; |
||
541 | } else { |
||
542 | $data[$p] = [$id]; |
||
543 | } |
||
544 | } |
||
545 | } |
||
546 | } |
||
547 | if ($root && isset($data[$root])) { |
||
548 | $data['root'] = $data[$root]; |
||
549 | } |
||
550 | $this->directories = $data; |
||
551 | $this->session->set($this->id.$this->netMountKey, [ |
||
552 | 'parents' => $this->parents, |
||
553 | 'names' => $this->names, |
||
554 | 'directories' => $this->directories, |
||
555 | ]); |
||
556 | } |
||
557 | |||
558 | /** |
||
559 | * Get descendants directories. |
||
560 | * |
||
561 | * @param string $itemId |
||
562 | * |
||
563 | * @return array |
||
564 | */ |
||
565 | protected function _gd_getDirectories($itemId) |
||
566 | { |
||
567 | $ret = []; |
||
568 | if ($this->directories === null) { |
||
569 | $this->_gd_getDirectoryData(); |
||
570 | } |
||
571 | $data = $this->directories; |
||
572 | if (isset($data[$itemId])) { |
||
573 | $ret = $data[$itemId]; |
||
574 | foreach ($data[$itemId] as $cid) { |
||
575 | $ret = array_merge($ret, $this->_gd_getDirectories($cid)); |
||
576 | } |
||
577 | } |
||
578 | |||
579 | return $ret; |
||
580 | } |
||
581 | |||
582 | /** |
||
583 | * Get ID based path from item ID. |
||
584 | * |
||
585 | * @param string $path |
||
586 | */ |
||
587 | protected function _gd_getMountPaths($id) |
||
588 | { |
||
589 | $root = false; |
||
590 | if ($this->directories === null) { |
||
591 | $this->_gd_getDirectoryData(); |
||
592 | } |
||
593 | list($pid) = explode('/', $id, 2); |
||
594 | $path = $id; |
||
595 | if ('/'.$pid === $this->root) { |
||
596 | $root = true; |
||
597 | } elseif (! isset($this->parents[$pid])) { |
||
598 | $root = true; |
||
599 | $path = ltrim(substr($path, strlen($pid)), '/'); |
||
600 | } |
||
601 | $res = []; |
||
602 | if ($root) { |
||
603 | if ($this->root === '/' || strpos('/'.$path, $this->root) === 0) { |
||
604 | $res = [(strpos($path, '/') === false) ? '/' : ('/'.$path)]; |
||
605 | } |
||
606 | } else { |
||
607 | foreach ($this->parents[$pid] as $p) { |
||
608 | $_p = $p.'/'.$path; |
||
609 | $res = array_merge($res, $this->_gd_getMountPaths($_p)); |
||
610 | } |
||
611 | } |
||
612 | |||
613 | return $res; |
||
614 | } |
||
615 | |||
616 | /** |
||
617 | * Return is published. |
||
618 | * |
||
619 | * @param object $file |
||
620 | * |
||
621 | * @return bool |
||
622 | */ |
||
623 | protected function _gd_isPublished($file) |
||
624 | { |
||
625 | $res = false; |
||
626 | $pType = $this->options['publishPermission']['type']; |
||
627 | $pRole = $this->options['publishPermission']['role']; |
||
628 | if ($permissions = $file->getPermissions()) { |
||
629 | foreach ($permissions as $permission) { |
||
630 | if ($permission->type === $pType && $permission->role === $pRole) { |
||
631 | $res = true; |
||
632 | break; |
||
633 | } |
||
634 | } |
||
635 | } |
||
636 | |||
637 | return $res; |
||
638 | } |
||
639 | |||
640 | /** |
||
641 | * return item URL link. |
||
642 | * |
||
643 | * @param object $file |
||
644 | * |
||
645 | * @return string |
||
646 | */ |
||
647 | protected function _gd_getLink($file) |
||
648 | { |
||
649 | if ($url = $file->getWebContentLink()) { |
||
650 | return str_replace('export=download', 'export=media', $url); |
||
651 | } |
||
652 | if ($url = $file->getWebViewLink()) { |
||
653 | return $url; |
||
654 | } |
||
655 | |||
656 | return ''; |
||
657 | } |
||
658 | |||
659 | /** |
||
660 | * Get download url. |
||
661 | * |
||
662 | * @param Google_Service_Drive_DriveFile $file |
||
663 | * |
||
664 | * @return string|false |
||
665 | */ |
||
666 | protected function _gd_getDownloadUrl($file) |
||
667 | { |
||
668 | if (strpos($file->mimeType, 'application/vnd.google-apps') !== 0) { |
||
669 | return 'https://www.googleapis.com/drive/v3/files/'.$file->getId().'?alt=media'; |
||
670 | } else { |
||
671 | $mimeMap = $this->options['appsExportMap']; |
||
672 | if (isset($mimeMap[$file->getMimeType()])) { |
||
673 | $mime = $mimeMap[$file->getMimeType()]; |
||
674 | } else { |
||
675 | $mime = $mimeMap['default']; |
||
676 | } |
||
677 | $mime = rawurlencode($mime); |
||
678 | |||
679 | return 'https://www.googleapis.com/drive/v3/files/'.$file->getId().'/export?mimeType='.$mime; |
||
680 | } |
||
681 | |||
682 | return false; |
||
0 ignored issues
–
show
return false; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
683 | } |
||
684 | |||
685 | /** |
||
686 | * Get thumbnail from GoogleDrive.com. |
||
687 | * |
||
688 | * @param string $path |
||
689 | * @param string $size |
||
690 | * |
||
691 | * @return string | boolean |
||
692 | */ |
||
693 | protected function _gd_getThumbnail($path) |
||
694 | { |
||
695 | list(, $itemId) = $this->_gd_splitPath($path); |
||
696 | |||
697 | try { |
||
698 | $contents = $this->service->files->get($itemId, [ |
||
699 | 'alt' => 'media', |
||
700 | ]); |
||
701 | $contents = $contents->getBody()->detach(); |
||
702 | rewind($contents); |
||
703 | |||
704 | return $contents; |
||
705 | } catch (Exception $e) { |
||
706 | return false; |
||
707 | } |
||
708 | } |
||
709 | |||
710 | /** |
||
711 | * Publish permissions specified path item. |
||
712 | * |
||
713 | * @param string $path |
||
714 | * |
||
715 | * @return bool |
||
716 | */ |
||
717 | protected function _gd_publish($path) |
||
718 | { |
||
719 | if ($file = $this->_gd_getFile($path)) { |
||
720 | if ($this->_gd_isPublished($file)) { |
||
721 | return true; |
||
722 | } |
||
723 | try { |
||
724 | if ($this->service->permissions->create($file->getId(), new \Google_Service_Drive_Permission($this->options['publishPermission']))) { |
||
725 | return true; |
||
726 | } |
||
727 | } catch (Exception $e) { |
||
728 | return false; |
||
729 | } |
||
730 | } |
||
731 | |||
732 | return false; |
||
733 | } |
||
734 | |||
735 | /** |
||
736 | * unPublish permissions specified path. |
||
737 | * |
||
738 | * @param string $path |
||
739 | * |
||
740 | * @return bool |
||
741 | */ |
||
742 | protected function _gd_unPublish($path) |
||
743 | { |
||
744 | if ($file = $this->_gd_getFile($path)) { |
||
745 | if (! $this->_gd_isPublished($file)) { |
||
746 | return true; |
||
747 | } |
||
748 | $permissions = $file->getPermissions(); |
||
749 | $pType = $this->options['publishPermission']['type']; |
||
750 | $pRole = $this->options['publishPermission']['role']; |
||
751 | try { |
||
752 | foreach ($permissions as $permission) { |
||
753 | if ($permission->type === $pType && $permission->role === $pRole) { |
||
754 | $this->service->permissions->delete($file->getId(), $permission->getId()); |
||
755 | |||
756 | return true; |
||
757 | break; |
||
758 | } |
||
759 | } |
||
760 | } catch (Exception $e) { |
||
761 | return false; |
||
762 | } |
||
763 | } |
||
764 | |||
765 | return false; |
||
766 | } |
||
767 | |||
768 | /** |
||
769 | * Read file chunk. |
||
770 | * |
||
771 | * @param resource $handle |
||
772 | * @param int $chunkSize |
||
773 | * |
||
774 | * @return string |
||
775 | */ |
||
776 | protected function _gd_readFileChunk($handle, $chunkSize) |
||
777 | { |
||
778 | $byteCount = 0; |
||
779 | $giantChunk = ''; |
||
780 | while (! feof($handle)) { |
||
781 | // fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file |
||
782 | $chunk = fread($handle, 8192); |
||
783 | $byteCount += strlen($chunk); |
||
784 | $giantChunk .= $chunk; |
||
785 | if ($byteCount >= $chunkSize) { |
||
786 | return $giantChunk; |
||
787 | } |
||
788 | } |
||
789 | |||
790 | return $giantChunk; |
||
791 | } |
||
792 | |||
793 | /** |
||
794 | * Return fileinfo based on filename |
||
795 | * For item ID based path file system |
||
796 | * Please override if needed on each drivers. |
||
797 | * |
||
798 | * @param string $path file cache |
||
799 | * |
||
800 | * @return array |
||
801 | */ |
||
802 | protected function isNameExists($path) |
||
803 | { |
||
804 | list($parentId, $name) = $this->_gd_splitPath($path); |
||
805 | $opts = [ |
||
806 | 'q' => sprintf('trashed=false and "%s" in parents and name="%s"', $parentId, $name), |
||
807 | 'fields' => self::FETCHFIELDS_LIST, |
||
808 | ]; |
||
809 | $srcFile = $this->_gd_query($opts); |
||
810 | |||
811 | return empty($srcFile) ? false : $this->_gd_parseRaw($srcFile[0]); |
||
812 | } |
||
813 | |||
814 | /*********************************************************************/ |
||
815 | /* INIT AND CONFIGURE */ |
||
816 | /*********************************************************************/ |
||
817 | |||
818 | /** |
||
819 | * Prepare FTP connection |
||
820 | * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn. |
||
821 | * |
||
822 | * @return bool |
||
823 | * |
||
824 | * @author Dmitry (dio) Levashov |
||
825 | * @author Cem (DiscoFever) |
||
826 | **/ |
||
827 | protected function init() |
||
828 | { |
||
829 | $serviceAccountConfig = ''; |
||
830 | if (empty($this->options['serviceAccountConfigFile'])) { |
||
831 | if (empty($options['client_id'])) { |
||
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. ![]() |
|||
832 | if (defined('ELFINDER_GOOGLEDRIVE_CLIENTID') && ELFINDER_GOOGLEDRIVE_CLIENTID) { |
||
833 | $this->options['client_id'] = ELFINDER_GOOGLEDRIVE_CLIENTID; |
||
834 | } else { |
||
835 | return $this->setError('Required option "client_id" is undefined.'); |
||
836 | } |
||
837 | } |
||
838 | if (empty($options['client_secret'])) { |
||
839 | if (defined('ELFINDER_GOOGLEDRIVE_CLIENTSECRET') && ELFINDER_GOOGLEDRIVE_CLIENTSECRET) { |
||
840 | $this->options['client_secret'] = ELFINDER_GOOGLEDRIVE_CLIENTSECRET; |
||
841 | } else { |
||
842 | return $this->setError('Required option "client_secret" is undefined.'); |
||
843 | } |
||
844 | } |
||
845 | if (! $this->options['access_token'] && ! $this->options['refresh_token']) { |
||
846 | return $this->setError('Required option "access_token" or "refresh_token" is undefined.'); |
||
847 | } |
||
848 | } else { |
||
849 | if (! is_readable($this->options['serviceAccountConfigFile'])) { |
||
850 | return $this->setError('Option "serviceAccountConfigFile" file is not readable.'); |
||
851 | } |
||
852 | $serviceAccountConfig = $this->options['serviceAccountConfigFile']; |
||
853 | } |
||
854 | |||
855 | try { |
||
856 | if (! $serviceAccountConfig) { |
||
857 | $aTokenFile = ''; |
||
858 | if ($this->options['refresh_token']) { |
||
859 | // permanent mount |
||
860 | $aToken = $this->options['refresh_token']; |
||
861 | $this->options['access_token'] = ''; |
||
862 | $tmp = elFinder::getStaticVar('commonTempPath'); |
||
863 | if (! $tmp) { |
||
864 | $tmp = $this->getTempPath(); |
||
865 | } |
||
866 | if ($tmp) { |
||
867 | $aTokenFile = $tmp.DIRECTORY_SEPARATOR.md5($this->options['client_id'].$this->options['refresh_token']).'.gtoken'; |
||
868 | if (is_file($aTokenFile)) { |
||
869 | $this->options['access_token'] = json_decode(file_get_contents($aTokenFile), true); |
||
870 | } |
||
871 | } |
||
872 | } else { |
||
873 | // make net mount key for network mount |
||
874 | if (is_array($this->options['access_token'])) { |
||
875 | $aToken = ! empty($this->options['access_token']['refresh_token']) |
||
876 | ? $this->options['access_token']['refresh_token'] |
||
877 | : $this->options['access_token']['access_token']; |
||
878 | } else { |
||
879 | return $this->setError('Required option "access_token" is not Array or empty.'); |
||
880 | } |
||
881 | } |
||
882 | } |
||
883 | |||
884 | $errors = []; |
||
885 | if (! $this->service) { |
||
886 | if ($this->options['googleApiClient'] && ! class_exists('Google_Client')) { |
||
887 | include_once $this->options['googleApiClient']; |
||
888 | } |
||
889 | if (! class_exists('Google_Client')) { |
||
890 | return $this->setError('Class Google_Client not found.'); |
||
891 | } |
||
892 | |||
893 | $this->client = new \Google_Client(); |
||
894 | |||
895 | $client = $this->client; |
||
896 | |||
897 | if (! $serviceAccountConfig) { |
||
898 | if ($this->options['access_token']) { |
||
899 | $client->setAccessToken($this->options['access_token']); |
||
900 | } |
||
901 | if ($client->isAccessTokenExpired()) { |
||
902 | $client->setClientId($this->options['client_id']); |
||
903 | $client->setClientSecret($this->options['client_secret']); |
||
904 | $access_token = $client->fetchAccessTokenWithRefreshToken($this->options['refresh_token'] ?: null); |
||
905 | $client->setAccessToken($access_token); |
||
906 | if ($aTokenFile) { |
||
907 | file_put_contents($aTokenFile, json_encode($access_token)); |
||
0 ignored issues
–
show
The variable
$aTokenFile does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
908 | } else { |
||
909 | $access_token['refresh_token'] = $this->options['access_token']['refresh_token']; |
||
910 | } |
||
911 | View Code Duplication | if (! empty($this->options['netkey'])) { |
|
912 | elFinder::$instance->updateNetVolumeOption($this->options['netkey'], 'access_token', $access_token); |
||
913 | } |
||
914 | $this->options['access_token'] = $access_token; |
||
915 | } |
||
916 | } else { |
||
917 | $client->setAuthConfigFile($serviceAccountConfig); |
||
918 | $client->setScopes([Google_Service_Drive::DRIVE]); |
||
919 | $aToken = $client->getClientId(); |
||
920 | } |
||
921 | $this->service = new \Google_Service_Drive($client); |
||
922 | } |
||
923 | |||
924 | $this->netMountKey = md5($aToken.'-'.$this->options['path']); |
||
0 ignored issues
–
show
The variable
$aToken does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
925 | } catch (InvalidArgumentException $e) { |
||
926 | $errors[] = $e->getMessage(); |
||
0 ignored issues
–
show
The variable
$errors does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
927 | } catch (Google_Service_Exception $e) { |
||
0 ignored issues
–
show
The class
Google_Service_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?
Scrutinizer analyzes your It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis. ![]() |
|||
928 | $errors[] = $e->getMessage(); |
||
929 | } |
||
930 | |||
931 | if (! $this->service) { |
||
932 | $this->session->remove($this->id.$this->netMountKey); |
||
933 | if ($aTokenFile) { |
||
934 | unlink($aTokenFile); |
||
935 | } |
||
936 | $errors[] = 'Google Drive Service could not be loaded.'; |
||
937 | |||
938 | return $this->setError($errors); |
||
939 | } |
||
940 | |||
941 | // normalize root path |
||
942 | if ($this->options['path'] == 'root') { |
||
943 | $this->options['path'] = '/'; |
||
944 | } |
||
945 | $this->root = $this->options['path'] = $this->_normpath($this->options['path']); |
||
946 | |||
947 | $this->options['root'] == '' ? $this->options['root'] = $this->_gd_getNameByPath('root') : $this->options['root']; |
||
948 | |||
949 | View Code Duplication | if (empty($this->options['alias'])) { |
|
950 | $this->options['alias'] = ($this->options['path'] === '/') ? $this->options['root'] : sprintf($this->options['gdAlias'], $this->_gd_getNameByPath($this->options['path'])); |
||
951 | } |
||
952 | |||
953 | $this->rootName = $this->options['alias']; |
||
954 | |||
955 | if (! empty($this->options['tmpPath'])) { |
||
956 | if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) { |
||
957 | $this->tmp = $this->options['tmpPath']; |
||
958 | } |
||
959 | } |
||
960 | |||
961 | if (! $this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) { |
||
962 | $this->tmp = $tmp; |
||
963 | } |
||
964 | |||
965 | // This driver dose not support `syncChkAsTs` |
||
966 | $this->options['syncChkAsTs'] = false; |
||
967 | |||
968 | // 'lsPlSleep' minmum 10 sec |
||
969 | $this->options['lsPlSleep'] = max(10, $this->options['lsPlSleep']); |
||
970 | |||
971 | if ($this->options['useGoogleTmb']) { |
||
972 | $this->options['tmbURL'] = 'https://'; |
||
973 | } |
||
974 | |||
975 | return true; |
||
976 | } |
||
977 | |||
978 | /** |
||
979 | * Configure after successfull mount. |
||
980 | * |
||
981 | * @author Dmitry (dio) Levashov |
||
982 | **/ |
||
983 | View Code Duplication | protected function configure() |
|
984 | { |
||
985 | parent::configure(); |
||
986 | |||
987 | // fallback of $this->tmp |
||
988 | if (! $this->tmp && $this->tmbPathWritable) { |
||
989 | $this->tmp = $this->tmbPath; |
||
990 | } |
||
991 | |||
992 | $this->disabled[] = 'archive'; |
||
993 | $this->disabled[] = 'extract'; |
||
994 | |||
995 | if ($this->isMyReload()) { |
||
996 | $this->_gd_getDirectoryData(false); |
||
997 | } |
||
998 | } |
||
999 | |||
1000 | /** |
||
1001 | * Cache dir contents. |
||
1002 | * |
||
1003 | * @param string $path dir path |
||
1004 | * |
||
1005 | * @author Dmitry Levashov |
||
1006 | **/ |
||
1007 | protected function cacheDir($path) |
||
1008 | { |
||
1009 | $this->dirsCache[$path] = []; |
||
1010 | $hasDir = false; |
||
1011 | |||
1012 | list(, $pid) = $this->_gd_splitPath($path); |
||
1013 | |||
1014 | $opts = [ |
||
1015 | 'fields' => self::FETCHFIELDS_LIST, |
||
1016 | 'q' => sprintf('trashed=false and "%s" in parents', $pid), |
||
1017 | ]; |
||
1018 | |||
1019 | $res = $this->_gd_query($opts); |
||
1020 | |||
1021 | $mountPath = $this->_normpath($path.'/'); |
||
1022 | |||
1023 | if ($res) { |
||
1024 | foreach ($res as $raw) { |
||
1025 | if ($stat = $this->_gd_parseRaw($raw)) { |
||
1026 | $stat = $this->updateCache($mountPath.$raw->id, $stat); |
||
1027 | if (empty($stat['hidden']) && $path !== $mountPath.$raw->id) { |
||
1028 | if (! $hasDir && $stat['mime'] === 'directory') { |
||
1029 | $hasDir = true; |
||
1030 | } |
||
1031 | $this->dirsCache[$path][] = $mountPath.$raw->id; |
||
1032 | } |
||
1033 | } |
||
1034 | } |
||
1035 | } |
||
1036 | |||
1037 | if (isset($this->sessionCache['subdirs'])) { |
||
1038 | $this->sessionCache['subdirs'][$path] = $hasDir; |
||
1039 | } |
||
1040 | |||
1041 | return $this->dirsCache[$path]; |
||
1042 | } |
||
1043 | |||
1044 | /** |
||
1045 | * Recursive files search. |
||
1046 | * |
||
1047 | * @param string $path dir path |
||
1048 | * @param string $q search string |
||
1049 | * @param array $mimes |
||
1050 | * |
||
1051 | * @return array |
||
1052 | * |
||
1053 | * @author Naoki Sawada |
||
1054 | **/ |
||
1055 | protected function doSearch($path, $q, $mimes) |
||
1056 | { |
||
1057 | list(, $itemId) = $this->_gd_splitPath($path); |
||
1058 | |||
1059 | $path = $this->_normpath($path.'/'); |
||
1060 | $result = []; |
||
1061 | $query = ''; |
||
1062 | |||
1063 | if ($itemId !== 'root') { |
||
1064 | $dirs = array_merge([$itemId], $this->_gd_getDirectories($itemId)); |
||
1065 | $query = '(\''.implode('\' in parents or \'', $dirs).'\' in parents)'; |
||
1066 | } |
||
1067 | |||
1068 | $tmp = []; |
||
1069 | if (! $mimes) { |
||
1070 | foreach (explode(' ', $q) as $_v) { |
||
1071 | $tmp[] = 'fullText contains \''.str_replace('\'', '\\\'', $_v).'\''; |
||
1072 | } |
||
1073 | $query .= ($query ? ' and ' : '').implode(' and ', $tmp); |
||
1074 | } else { |
||
1075 | foreach ($mimes as $_v) { |
||
1076 | $tmp[] = 'mimeType contains \''.str_replace('\'', '\\\'', $_v).'\''; |
||
1077 | } |
||
1078 | $query .= ($query ? ' and ' : '').'('.implode(' or ', $tmp).')'; |
||
1079 | } |
||
1080 | |||
1081 | $opts = [ |
||
1082 | 'q' => sprintf('trashed=false and (%s)', $query), |
||
1083 | ]; |
||
1084 | |||
1085 | $res = $this->_gd_query($opts); |
||
1086 | |||
1087 | $timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0; |
||
1088 | foreach ($res as $raw) { |
||
1089 | if ($timeout && $timeout < time()) { |
||
1090 | $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->_path($path)); |
||
1091 | break; |
||
1092 | } |
||
1093 | if ($stat = $this->_gd_parseRaw($raw)) { |
||
1094 | if ($parents = $raw->getParents()) { |
||
1095 | foreach ($parents as $parent) { |
||
1096 | $paths = $this->_gd_getMountPaths($parent); |
||
1097 | foreach ($paths as $path) { |
||
1098 | $path = ($path === '') ? '/' : (rtrim($path, '/').'/'); |
||
1099 | if (! isset($this->cache[$path.$raw->id])) { |
||
1100 | $stat = $this->updateCache($path.$raw->id, $stat); |
||
1101 | } else { |
||
1102 | $stat = $this->cache[$path.$raw->id]; |
||
1103 | } |
||
1104 | if (empty($stat['hidden'])) { |
||
1105 | $stat['path'] = $this->_path($path).$stat['name']; |
||
1106 | $result[] = $stat; |
||
1107 | } |
||
1108 | } |
||
1109 | } |
||
1110 | } |
||
1111 | } |
||
1112 | } |
||
1113 | |||
1114 | return $result; |
||
1115 | } |
||
1116 | |||
1117 | /** |
||
1118 | * Copy file/recursive copy dir only in current volume. |
||
1119 | * Return new file path or false. |
||
1120 | * |
||
1121 | * @param string $src source path |
||
1122 | * @param string $dst destination dir path |
||
1123 | * @param string $name new file name (optionaly) |
||
1124 | * |
||
1125 | * @return string|false |
||
1126 | * |
||
1127 | * @author Dmitry (dio) Levashov |
||
1128 | * @author Naoki Sawada |
||
1129 | **/ |
||
1130 | protected function copy($src, $dst, $name) |
||
1131 | { |
||
1132 | $this->clearcache(); |
||
1133 | $res = $this->_gd_getFile($src); |
||
1134 | if ($res['mimeType'] == self::DIRMIME) { |
||
1135 | $newDir = $this->_mkdir($dst, $name); |
||
1136 | if ($newDir) { |
||
1137 | list(, $itemId) = $this->_gd_splitPath($newDir); |
||
1138 | list(, $srcId) = $this->_gd_splitPath($src); |
||
1139 | $path = $this->_joinPath($dst, $itemId); |
||
1140 | $opts = [ |
||
1141 | 'q' => sprintf('trashed=false and "%s" in parents', $srcId), |
||
1142 | ]; |
||
1143 | |||
1144 | $res = $this->_gd_query($opts); |
||
1145 | foreach ($res as $raw) { |
||
1146 | $raw['mimeType'] == self::DIRMIME ? $this->copy($src.'/'.$raw['id'], $path, $raw['name']) : $this->_copy($src.'/'.$raw['id'], $path, $raw['name']); |
||
1147 | } |
||
1148 | |||
1149 | return $this->_joinPath($dst, $itemId); |
||
1150 | } else { |
||
1151 | $this->setError(elFinder::ERROR_COPY, $this->_path($src)); |
||
1152 | } |
||
1153 | View Code Duplication | } else { |
|
1154 | $itemId = $this->_copy($src, $dst, $name); |
||
1155 | |||
1156 | return $itemId |
||
1157 | ? $this->_joinPath($dst, $itemId) |
||
1158 | : $this->setError(elFinder::ERROR_COPY, $this->_path($src)); |
||
1159 | } |
||
1160 | } |
||
1161 | |||
1162 | /** |
||
1163 | * Remove file/ recursive remove dir. |
||
1164 | * |
||
1165 | * @param string $path file path |
||
1166 | * @param bool $force try to remove even if file locked |
||
1167 | * |
||
1168 | * @return bool |
||
1169 | * |
||
1170 | * @author Dmitry (dio) Levashov |
||
1171 | * @author Naoki Sawada |
||
1172 | **/ |
||
1173 | View Code Duplication | protected function remove($path, $force = false, $recursive = false) |
|
1174 | { |
||
1175 | $stat = $this->stat($path); |
||
1176 | $stat['realpath'] = $path; |
||
1177 | $this->rmTmb($stat); |
||
1178 | $this->clearcache(); |
||
1179 | |||
1180 | if (empty($stat)) { |
||
1181 | return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND); |
||
1182 | } |
||
1183 | |||
1184 | if (! $force && ! empty($stat['locked'])) { |
||
1185 | return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path)); |
||
1186 | } |
||
1187 | |||
1188 | if ($stat['mime'] == 'directory') { |
||
1189 | if (! $recursive && ! $this->_rmdir($path)) { |
||
1190 | return $this->setError(elFinder::ERROR_RM, $this->_path($path)); |
||
1191 | } |
||
1192 | } else { |
||
1193 | if (! $recursive && ! $this->_unlink($path)) { |
||
1194 | return $this->setError(elFinder::ERROR_RM, $this->_path($path)); |
||
1195 | } |
||
1196 | } |
||
1197 | |||
1198 | $this->removed[] = $stat; |
||
1199 | |||
1200 | return true; |
||
1201 | } |
||
1202 | |||
1203 | /** |
||
1204 | * Create thumnbnail and return it's URL on success. |
||
1205 | * |
||
1206 | * @param string $path file path |
||
1207 | * @param string $mime file mime type |
||
1208 | * |
||
1209 | * @return string|false |
||
1210 | * |
||
1211 | * @author Dmitry (dio) Levashov |
||
1212 | * @author Naoki Sawada |
||
1213 | **/ |
||
1214 | View Code Duplication | protected function createTmb($path, $stat) |
|
1215 | { |
||
1216 | if (! $stat || ! $this->canCreateTmb($path, $stat)) { |
||
1217 | return false; |
||
1218 | } |
||
1219 | |||
1220 | $name = $this->tmbname($stat); |
||
1221 | $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name; |
||
1222 | |||
1223 | // copy image into tmbPath so some drivers does not store files on local fs |
||
1224 | if (! $data = $this->_gd_getThumbnail($path)) { |
||
1225 | return false; |
||
1226 | } |
||
1227 | if (! file_put_contents($tmb, $data)) { |
||
1228 | return false; |
||
1229 | } |
||
1230 | |||
1231 | $result = false; |
||
0 ignored issues
–
show
$result is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
1232 | |||
1233 | $tmbSize = $this->tmbSize; |
||
1234 | |||
1235 | if (($s = getimagesize($tmb)) == false) { |
||
1236 | return false; |
||
1237 | } |
||
1238 | |||
1239 | /* If image smaller or equal thumbnail size - just fitting to thumbnail square */ |
||
1240 | if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) { |
||
1241 | $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png'); |
||
1242 | } else { |
||
1243 | if ($this->options['tmbCrop']) { |
||
1244 | |||
1245 | /* Resize and crop if image bigger than thumbnail */ |
||
1246 | if (! (($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize)) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) { |
||
1247 | $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png'); |
||
0 ignored issues
–
show
$result is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
1248 | } |
||
1249 | |||
1250 | if (($s = getimagesize($tmb)) != false) { |
||
1251 | $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize) / 2) : 0; |
||
1252 | $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize) / 2) : 0; |
||
1253 | $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png'); |
||
0 ignored issues
–
show
$result is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
1254 | } |
||
1255 | } else { |
||
1256 | $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, 'png'); |
||
0 ignored issues
–
show
$result is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
1257 | } |
||
1258 | |||
1259 | $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png'); |
||
1260 | } |
||
1261 | |||
1262 | 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
![]() |
|||
1263 | unlink($tmb); |
||
1264 | |||
1265 | return false; |
||
1266 | } |
||
1267 | |||
1268 | return $name; |
||
1269 | } |
||
1270 | |||
1271 | /** |
||
1272 | * Return thumbnail file name for required file. |
||
1273 | * |
||
1274 | * @param array $stat file stat |
||
1275 | * |
||
1276 | * @return string |
||
1277 | * |
||
1278 | * @author Dmitry (dio) Levashov |
||
1279 | **/ |
||
1280 | protected function tmbname($stat) |
||
1281 | { |
||
1282 | return $this->netMountKey.$stat['iid'].$stat['ts'].'.png'; |
||
1283 | } |
||
1284 | |||
1285 | /*********************** paths/urls *************************/ |
||
1286 | |||
1287 | /** |
||
1288 | * Return parent directory path. |
||
1289 | * |
||
1290 | * @param string $path file path |
||
1291 | * |
||
1292 | * @return string |
||
1293 | * |
||
1294 | * @author Dmitry (dio) Levashov |
||
1295 | **/ |
||
1296 | protected function _dirname($path) |
||
1297 | { |
||
1298 | list(, , $parent) = $this->_gd_splitPath($path); |
||
1299 | |||
1300 | return $this->_normpath($parent); |
||
1301 | } |
||
1302 | |||
1303 | /** |
||
1304 | * Return file name. |
||
1305 | * |
||
1306 | * @param string $path file path |
||
1307 | * |
||
1308 | * @return string |
||
1309 | * |
||
1310 | * @author Dmitry (dio) Levashov |
||
1311 | **/ |
||
1312 | protected function _basename($path) |
||
1313 | { |
||
1314 | list(, $basename) = $this->_gd_splitPath($path); |
||
1315 | |||
1316 | return $basename; |
||
1317 | } |
||
1318 | |||
1319 | /** |
||
1320 | * Join dir name and file name and retur full path. |
||
1321 | * |
||
1322 | * @param string $dir |
||
1323 | * @param string $name |
||
1324 | * |
||
1325 | * @return string |
||
1326 | * |
||
1327 | * @author Dmitry (dio) Levashov |
||
1328 | **/ |
||
1329 | protected function _joinPath($dir, $name) |
||
1330 | { |
||
1331 | return $this->_normpath($dir.'/'.$name); |
||
1332 | } |
||
1333 | |||
1334 | /** |
||
1335 | * Return normalized path, this works the same as os.path.normpath() in Python. |
||
1336 | * |
||
1337 | * @param string $path path |
||
1338 | * |
||
1339 | * @return string |
||
1340 | * |
||
1341 | * @author Troex Nevelin |
||
1342 | **/ |
||
1343 | View Code Duplication | protected function _normpath($path) |
|
1344 | { |
||
1345 | if (DIRECTORY_SEPARATOR !== '/') { |
||
1346 | $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); |
||
1347 | } |
||
1348 | $path = '/'.ltrim($path, '/'); |
||
1349 | |||
1350 | return $path; |
||
1351 | } |
||
1352 | |||
1353 | /** |
||
1354 | * Return file path related to root dir. |
||
1355 | * |
||
1356 | * @param string $path file path |
||
1357 | * |
||
1358 | * @return string |
||
1359 | * |
||
1360 | * @author Dmitry (dio) Levashov |
||
1361 | **/ |
||
1362 | protected function _relpath($path) |
||
1363 | { |
||
1364 | return $path; |
||
1365 | } |
||
1366 | |||
1367 | /** |
||
1368 | * Convert path related to root dir into real path. |
||
1369 | * |
||
1370 | * @param string $path file path |
||
1371 | * |
||
1372 | * @return string |
||
1373 | * |
||
1374 | * @author Dmitry (dio) Levashov |
||
1375 | **/ |
||
1376 | protected function _abspath($path) |
||
1377 | { |
||
1378 | return $path; |
||
1379 | } |
||
1380 | |||
1381 | /** |
||
1382 | * Return fake path started from root dir. |
||
1383 | * |
||
1384 | * @param string $path file path |
||
1385 | * |
||
1386 | * @return string |
||
1387 | * |
||
1388 | * @author Dmitry (dio) Levashov |
||
1389 | **/ |
||
1390 | protected function _path($path) |
||
1391 | { |
||
1392 | if (! $this->names) { |
||
1393 | $this->_gd_getDirectoryData(); |
||
1394 | } |
||
1395 | $path = $this->_normpath(substr($path, strlen($this->root))); |
||
1396 | $names = []; |
||
1397 | $paths = explode('/', $path); |
||
1398 | foreach ($paths as $_p) { |
||
1399 | $names[] = isset($this->names[$_p]) ? $this->names[$_p] : $_p; |
||
1400 | } |
||
1401 | |||
1402 | return $this->rootName.implode('/', $names); |
||
1403 | } |
||
1404 | |||
1405 | /** |
||
1406 | * Return true if $path is children of $parent. |
||
1407 | * |
||
1408 | * @param string $path path to check |
||
1409 | * @param string $parent parent path |
||
1410 | * |
||
1411 | * @return bool |
||
1412 | * |
||
1413 | * @author Dmitry (dio) Levashov |
||
1414 | **/ |
||
1415 | protected function _inpath($path, $parent) |
||
1416 | { |
||
1417 | return $path == $parent || strpos($path, $parent.'/') === 0; |
||
1418 | } |
||
1419 | |||
1420 | /***************** file stat ********************/ |
||
1421 | |||
1422 | /** |
||
1423 | * Return stat for given path. |
||
1424 | * Stat contains following fields: |
||
1425 | * - (int) size file size in b. required |
||
1426 | * - (int) ts file modification time in unix time. required |
||
1427 | * - (string) mime mimetype. required for folders, others - optionally |
||
1428 | * - (bool) read read permissions. required |
||
1429 | * - (bool) write write permissions. required |
||
1430 | * - (bool) locked is object locked. optionally |
||
1431 | * - (bool) hidden is object hidden. optionally |
||
1432 | * - (string) alias for symlinks - link target path relative to root path. optionally |
||
1433 | * - (string) target for symlinks - link target path. optionally. |
||
1434 | * |
||
1435 | * If file does not exists - returns empty array or false. |
||
1436 | * |
||
1437 | * @param string $path file path |
||
1438 | * |
||
1439 | * @return array|false |
||
1440 | * |
||
1441 | * @author Dmitry (dio) Levashov |
||
1442 | **/ |
||
1443 | protected function _stat($path) |
||
1444 | { |
||
1445 | if ($raw = $this->_gd_getFile($path)) { |
||
1446 | return $this->_gd_parseRaw($raw); |
||
1447 | } |
||
1448 | |||
1449 | return false; |
||
1450 | } |
||
1451 | |||
1452 | /** |
||
1453 | * Return true if path is dir and has at least one childs directory. |
||
1454 | * |
||
1455 | * @param string $path dir path |
||
1456 | * |
||
1457 | * @return bool |
||
1458 | * |
||
1459 | * @author Dmitry (dio) Levashov |
||
1460 | **/ |
||
1461 | protected function _subdirs($path) |
||
1462 | { |
||
1463 | if ($this->directories === null) { |
||
1464 | $this->_gd_getDirectoryData(); |
||
1465 | } |
||
1466 | list(, $itemId) = $this->_gd_splitPath($path); |
||
1467 | |||
1468 | return isset($this->directories[$itemId]); |
||
1469 | } |
||
1470 | |||
1471 | /** |
||
1472 | * Return object width and height |
||
1473 | * Ususaly used for images, but can be realize for video etc... |
||
1474 | * |
||
1475 | * @param string $path file path |
||
1476 | * @param string $mime file mime type |
||
1477 | * |
||
1478 | * @return string |
||
1479 | * |
||
1480 | * @author Dmitry (dio) Levashov |
||
1481 | **/ |
||
1482 | protected function _dimensions($path, $mime) |
||
1483 | { |
||
1484 | if (strpos($mime, 'image') !== 0) { |
||
1485 | return ''; |
||
1486 | } |
||
1487 | $ret = ''; |
||
1488 | |||
1489 | View Code Duplication | if ($file = $this->_gd_getFile($path)) { |
|
1490 | if (isset($file['imageMediaMetadata'])) { |
||
1491 | return $file['imageMediaMetadata']['width'].'x'.$file['imageMediaMetadata']['height']; |
||
1492 | } |
||
1493 | } |
||
1494 | |||
1495 | return $ret; |
||
1496 | } |
||
1497 | |||
1498 | /******************** file/dir content *********************/ |
||
1499 | |||
1500 | /** |
||
1501 | * Return files list in directory. |
||
1502 | * |
||
1503 | * @param string $path dir path |
||
1504 | * |
||
1505 | * @return array |
||
1506 | * |
||
1507 | * @author Dmitry (dio) Levashov |
||
1508 | * @author Cem (DiscoFever) |
||
1509 | **/ |
||
1510 | protected function _scandir($path) |
||
1511 | { |
||
1512 | return isset($this->dirsCache[$path]) |
||
1513 | ? $this->dirsCache[$path] |
||
1514 | : $this->cacheDir($path); |
||
1515 | } |
||
1516 | |||
1517 | /** |
||
1518 | * Open file and return file pointer. |
||
1519 | * |
||
1520 | * @param string $path file path |
||
1521 | * @param bool $write open file for writing |
||
1522 | * |
||
1523 | * @return resource|false |
||
1524 | * |
||
1525 | * @author Dmitry (dio) Levashov |
||
1526 | **/ |
||
1527 | protected function _fopen($path, $mode = 'rb') |
||
1528 | { |
||
1529 | if ($mode === 'rb' || $mode === 'r') { |
||
1530 | if ($file = $this->_gd_getFile($path)) { |
||
1531 | if ($dlurl = $this->_gd_getDownloadUrl($file)) { |
||
1532 | $token = $this->client->getAccessToken(); |
||
1533 | if (! $token && $this->client->isUsingApplicationDefaultCredentials()) { |
||
1534 | $this->client->fetchAccessTokenWithAssertion(); |
||
1535 | $token = $this->client->getAccessToken(); |
||
1536 | } |
||
1537 | $access_token = ''; |
||
1538 | if (is_array($token)) { |
||
1539 | $access_token = $token['access_token']; |
||
1540 | } else { |
||
1541 | if ($token = json_decode($this->client->getAccessToken())) { |
||
1542 | $access_token = $token->access_token; |
||
1543 | } |
||
1544 | } |
||
1545 | if ($access_token) { |
||
1546 | $data = [ |
||
1547 | 'target' => $dlurl, |
||
1548 | 'headers' => ['Authorization: Bearer '.$access_token], |
||
1549 | ]; |
||
1550 | |||
1551 | return elFinder::getStreamByUrl($data); |
||
1552 | } |
||
1553 | } |
||
1554 | } |
||
1555 | } |
||
1556 | |||
1557 | return false; |
||
1558 | } |
||
1559 | |||
1560 | /** |
||
1561 | * Close opened file. |
||
1562 | * |
||
1563 | * @param resource $fp file pointer |
||
1564 | * |
||
1565 | * @return bool |
||
1566 | * |
||
1567 | * @author Dmitry (dio) Levashov |
||
1568 | **/ |
||
1569 | protected function _fclose($fp, $path = '') |
||
1570 | { |
||
1571 | fclose($fp); |
||
1572 | if ($path) { |
||
1573 | unlink($this->getTempFile($path)); |
||
1574 | } |
||
1575 | } |
||
1576 | |||
1577 | /******************** file/dir manipulations *************************/ |
||
1578 | |||
1579 | /** |
||
1580 | * Create dir and return created dir path or false on failed. |
||
1581 | * |
||
1582 | * @param string $path parent dir path |
||
1583 | * @param string $name new directory name |
||
1584 | * |
||
1585 | * @return string|bool |
||
1586 | * |
||
1587 | * @author Dmitry (dio) Levashov |
||
1588 | **/ |
||
1589 | protected function _mkdir($path, $name) |
||
1590 | { |
||
1591 | $path = $this->_joinPath($path, $name); |
||
1592 | list($parentId, , $parent) = $this->_gd_splitPath($path); |
||
1593 | |||
1594 | try { |
||
1595 | $file = new \Google_Service_Drive_DriveFile(); |
||
1596 | |||
1597 | $file->setName($name); |
||
1598 | $file->setMimeType(self::DIRMIME); |
||
1599 | $file->setParents([$parentId]); |
||
1600 | |||
1601 | //create the Folder in the Parent |
||
1602 | $obj = $this->service->files->create($file); |
||
1603 | |||
1604 | if ($obj instanceof Google_Service_Drive_DriveFile) { |
||
0 ignored issues
–
show
The class
Google_Service_Drive_DriveFile does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
1605 | $path = $this->_joinPath($parent, $obj['id']); |
||
1606 | $this->_gd_getDirectoryData(false); |
||
1607 | |||
1608 | return $path; |
||
1609 | } else { |
||
1610 | return false; |
||
1611 | } |
||
1612 | } catch (Exception $e) { |
||
1613 | return $this->setError('GoogleDrive error: '.$e->getMessage()); |
||
1614 | } |
||
1615 | } |
||
1616 | |||
1617 | /** |
||
1618 | * Create file and return it's path or false on failed. |
||
1619 | * |
||
1620 | * @param string $path parent dir path |
||
1621 | * @param string $name new file name |
||
1622 | * |
||
1623 | * @return string|bool |
||
1624 | * |
||
1625 | * @author Dmitry (dio) Levashov |
||
1626 | **/ |
||
1627 | protected function _mkfile($path, $name) |
||
1628 | { |
||
1629 | return $this->_save(tmpfile(), $path, $name, []); |
||
1630 | } |
||
1631 | |||
1632 | /** |
||
1633 | * Create symlink. FTP driver does not support symlinks. |
||
1634 | * |
||
1635 | * @param string $target link target |
||
1636 | * @param string $path symlink path |
||
1637 | * |
||
1638 | * @return bool |
||
1639 | * |
||
1640 | * @author Dmitry (dio) Levashov |
||
1641 | **/ |
||
1642 | protected function _symlink($target, $path, $name) |
||
1643 | { |
||
1644 | return false; |
||
1645 | } |
||
1646 | |||
1647 | /** |
||
1648 | * Copy file into another file. |
||
1649 | * |
||
1650 | * @param string $source source file path |
||
1651 | * @param string $targetDir target directory path |
||
1652 | * @param string $name new file name |
||
1653 | * |
||
1654 | * @return bool |
||
1655 | * |
||
1656 | * @author Dmitry (dio) Levashov |
||
1657 | **/ |
||
1658 | protected function _copy($source, $targetDir, $name) |
||
1659 | { |
||
1660 | $source = $this->_normpath($source); |
||
1661 | $targetDir = $this->_normpath($targetDir); |
||
1662 | |||
1663 | try { |
||
1664 | $file = new \Google_Service_Drive_DriveFile(); |
||
1665 | $file->setName($name); |
||
1666 | |||
1667 | //Set the Parent id |
||
1668 | list(, $parentId) = $this->_gd_splitPath($targetDir); |
||
1669 | $file->setParents([$parentId]); |
||
1670 | |||
1671 | list(, $srcId) = $this->_gd_splitPath($source); |
||
1672 | $file = $this->service->files->copy($srcId, $file, ['fields' => self::FETCHFIELDS_GET]); |
||
1673 | $itemId = $file->id; |
||
1674 | |||
1675 | return $itemId; |
||
1676 | } catch (Exception $e) { |
||
1677 | return $this->setError('GoogleDrive error: '.$e->getMessage()); |
||
1678 | } |
||
1679 | |||
1680 | return true; |
||
0 ignored issues
–
show
return true; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
1681 | } |
||
1682 | |||
1683 | /** |
||
1684 | * Move file into another parent dir. |
||
1685 | * Return new file path or false. |
||
1686 | * |
||
1687 | * @param string $source source file path |
||
1688 | * @param string $target target dir path |
||
1689 | * @param string $name file name |
||
1690 | * |
||
1691 | * @return string|bool |
||
1692 | * |
||
1693 | * @author Dmitry (dio) Levashov |
||
1694 | **/ |
||
1695 | protected function _move($source, $targetDir, $name) |
||
1696 | { |
||
1697 | list($removeParents, $itemId) = $this->_gd_splitPath($source); |
||
1698 | $target = $this->_normpath($targetDir.'/'.$itemId); |
||
1699 | try { |
||
1700 | //moving and renaming a file or directory |
||
1701 | $files = new \Google_Service_Drive_DriveFile(); |
||
1702 | $files->setName($name); |
||
1703 | |||
1704 | //Set new Parent and remove old parent |
||
1705 | list(, $addParents) = $this->_gd_splitPath($targetDir); |
||
1706 | $opts = ['addParents' => $addParents, 'removeParents' => $removeParents]; |
||
1707 | |||
1708 | $file = $this->service->files->update($itemId, $files, $opts); |
||
1709 | |||
1710 | if ($file->getMimeType() === self::DIRMIME) { |
||
1711 | $this->_gd_getDirectoryData(false); |
||
1712 | } |
||
1713 | } catch (Exception $e) { |
||
1714 | return $this->setError('GoogleDrive error: '.$e->getMessage()); |
||
1715 | } |
||
1716 | |||
1717 | return $target; |
||
1718 | } |
||
1719 | |||
1720 | /** |
||
1721 | * Remove file. |
||
1722 | * |
||
1723 | * @param string $path file path |
||
1724 | * |
||
1725 | * @return bool |
||
1726 | * |
||
1727 | * @author Dmitry (dio) Levashov |
||
1728 | **/ |
||
1729 | protected function _unlink($path) |
||
1730 | { |
||
1731 | try { |
||
1732 | $files = new \Google_Service_Drive_DriveFile(); |
||
1733 | $files->setTrashed(true); |
||
1734 | |||
1735 | list($pid, $itemId) = $this->_gd_splitPath($path); |
||
1736 | $opts = ['removeParents' => $pid]; |
||
1737 | $this->service->files->update($itemId, $files, $opts); |
||
1738 | } catch (Exception $e) { |
||
1739 | return $this->setError('GoogleDrive error: '.$e->getMessage()); |
||
1740 | } |
||
1741 | |||
1742 | return true; |
||
1743 | } |
||
1744 | |||
1745 | /** |
||
1746 | * Remove dir. |
||
1747 | * |
||
1748 | * @param string $path dir path |
||
1749 | * |
||
1750 | * @return bool |
||
1751 | * |
||
1752 | * @author Dmitry (dio) Levashov |
||
1753 | **/ |
||
1754 | protected function _rmdir($path) |
||
1755 | { |
||
1756 | $res = $this->_unlink($path); |
||
1757 | $res && $this->_gd_getDirectoryData(false); |
||
1758 | |||
1759 | return $res; |
||
1760 | } |
||
1761 | |||
1762 | /** |
||
1763 | * Create new file and write into it from file pointer. |
||
1764 | * Return new file path or false on error. |
||
1765 | * |
||
1766 | * @param resource $fp file pointer |
||
1767 | * @param string $dir target dir path |
||
1768 | * @param string $name file name |
||
1769 | * @param array $stat file stat (required by some virtual fs) |
||
1770 | * |
||
1771 | * @return bool|string |
||
1772 | * |
||
1773 | * @author Dmitry (dio) Levashov |
||
1774 | **/ |
||
1775 | protected function _save($fp, $path, $name, $stat) |
||
1776 | { |
||
1777 | if ($name !== '') { |
||
1778 | $path .= '/'.$name; |
||
1779 | } |
||
1780 | list($parentId, $itemId, $parent) = $this->_gd_splitPath($path); |
||
1781 | if ($name === '') { |
||
1782 | $stat['iid'] = $itemId; |
||
1783 | } |
||
1784 | |||
1785 | if (! $stat || empty($stat['iid'])) { |
||
1786 | $opts = [ |
||
1787 | 'q' => sprintf('trashed=false and "%s" in parents and name="%s"', $parentId, $name), |
||
1788 | 'fields' => self::FETCHFIELDS_LIST, |
||
1789 | ]; |
||
1790 | $srcFile = $this->_gd_query($opts); |
||
1791 | $srcFile = empty($srcFile) ? null : $srcFile[0]; |
||
1792 | } else { |
||
1793 | $srcFile = $this->_gd_getFile($path); |
||
1794 | } |
||
1795 | |||
1796 | try { |
||
1797 | $mode = 'update'; |
||
1798 | $mime = isset($stat['mime']) ? $stat['mime'] : ''; |
||
1799 | |||
1800 | $file = new Google_Service_Drive_DriveFile(); |
||
1801 | if ($srcFile) { |
||
1802 | $mime = $srcFile->getMimeType(); |
||
1803 | } else { |
||
1804 | $mode = 'insert'; |
||
1805 | $file->setName($name); |
||
1806 | $file->setParents([ |
||
1807 | $parentId, |
||
1808 | ]); |
||
1809 | } |
||
1810 | |||
1811 | if (! $mime) { |
||
1812 | $mime = self::mimetypeInternalDetect($name); |
||
1813 | } |
||
1814 | if ($mime === 'unknown') { |
||
1815 | $mime = 'application/octet-stream'; |
||
1816 | } |
||
1817 | $file->setMimeType($mime); |
||
1818 | |||
1819 | $size = 0; |
||
1820 | if (isset($stat['size'])) { |
||
1821 | $size = $stat['size']; |
||
1822 | } else { |
||
1823 | $fstat = fstat($fp); |
||
1824 | if (! empty($fstat['size'])) { |
||
1825 | $size = $fstat['size']; |
||
1826 | } |
||
1827 | } |
||
1828 | |||
1829 | // set chunk size (max: 100MB) |
||
1830 | $chunkSizeBytes = 100 * 1024 * 1024; |
||
1831 | if ($size > 0) { |
||
1832 | $memory = elFinder::getIniBytes('memory_limit'); |
||
1833 | if ($memory) { |
||
1834 | $chunkSizeBytes = min([$chunkSizeBytes, (intval($memory / 4 / 256) * 256)]); |
||
1835 | } |
||
1836 | } |
||
1837 | |||
1838 | if ($size > $chunkSizeBytes) { |
||
1839 | $client = $this->client; |
||
1840 | // Call the API with the media upload, defer so it doesn't immediately return. |
||
1841 | $client->setDefer(true); |
||
1842 | if ($mode === 'insert') { |
||
1843 | $request = $this->service->files->create($file, [ |
||
1844 | 'fields' => self::FETCHFIELDS_GET, |
||
1845 | ]); |
||
1846 | } else { |
||
1847 | $request = $this->service->files->update($srcFile->getId(), $file, [ |
||
1848 | 'fields' => self::FETCHFIELDS_GET, |
||
1849 | ]); |
||
1850 | } |
||
1851 | |||
1852 | // Create a media file upload to represent our upload process. |
||
1853 | $media = new Google_Http_MediaFileUpload($client, $request, $mime, null, true, $chunkSizeBytes); |
||
1854 | $media->setFileSize($size); |
||
1855 | // Upload the various chunks. $status will be false until the process is |
||
1856 | // complete. |
||
1857 | $status = false; |
||
1858 | while (! $status && ! feof($fp)) { |
||
1859 | elFinder::extendTimeLimit(); |
||
1860 | // read until you get $chunkSizeBytes from TESTFILE |
||
1861 | // fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file |
||
1862 | // An example of a read buffered file is when reading from a URL |
||
1863 | $chunk = $this->_gd_readFileChunk($fp, $chunkSizeBytes); |
||
1864 | $status = $media->nextChunk($chunk); |
||
1865 | } |
||
1866 | // The final value of $status will be the data from the API for the object |
||
1867 | // that has been uploaded. |
||
1868 | if ($status !== false) { |
||
1869 | $obj = $status; |
||
1870 | } |
||
1871 | |||
1872 | $client->setDefer(false); |
||
1873 | } else { |
||
1874 | $params = [ |
||
1875 | 'data' => stream_get_contents($fp), |
||
1876 | 'uploadType' => 'media', |
||
1877 | 'fields' => self::FETCHFIELDS_GET, |
||
1878 | ]; |
||
1879 | if ($mode === 'insert') { |
||
1880 | $obj = $this->service->files->create($file, $params); |
||
1881 | } else { |
||
1882 | $obj = $this->service->files->update($srcFile->getId(), $file, $params); |
||
1883 | } |
||
1884 | } |
||
1885 | if ($obj instanceof Google_Service_Drive_DriveFile) { |
||
0 ignored issues
–
show
The class
Google_Service_Drive_DriveFile does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
1886 | return $this->_joinPath($parent, $obj->getId()); |
||
0 ignored issues
–
show
The variable
$obj does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
1887 | } else { |
||
1888 | return false; |
||
1889 | } |
||
1890 | } catch (Exception $e) { |
||
1891 | return $this->setError('GoogleDrive error: '.$e->getMessage()); |
||
1892 | } |
||
1893 | } |
||
1894 | |||
1895 | /** |
||
1896 | * Get file contents. |
||
1897 | * |
||
1898 | * @param string $path file path |
||
1899 | * |
||
1900 | * @return string|false |
||
1901 | * |
||
1902 | * @author Dmitry (dio) Levashov |
||
1903 | **/ |
||
1904 | protected function _getContents($path) |
||
1905 | { |
||
1906 | $contents = ''; |
||
1907 | |||
1908 | try { |
||
1909 | list(, $itemId) = $this->_gd_splitPath($path); |
||
1910 | |||
1911 | $contents = $this->service->files->get($itemId, [ |
||
1912 | 'alt' => 'media', |
||
1913 | ]); |
||
1914 | $contents = (string) $contents->getBody(); |
||
1915 | } catch (Exception $e) { |
||
1916 | return $this->setError('GoogleDrive error: '.$e->getMessage()); |
||
1917 | } |
||
1918 | |||
1919 | return $contents; |
||
1920 | } |
||
1921 | |||
1922 | /** |
||
1923 | * Write a string to a file. |
||
1924 | * |
||
1925 | * @param string $path file path |
||
1926 | * @param string $content new file content |
||
1927 | * |
||
1928 | * @return bool |
||
1929 | * |
||
1930 | * @author Dmitry (dio) Levashov |
||
1931 | **/ |
||
1932 | View Code Duplication | protected function _filePutContents($path, $content) |
|
1933 | { |
||
1934 | $res = false; |
||
1935 | |||
1936 | if ($local = $this->getTempFile($path)) { |
||
1937 | if (file_put_contents($local, $content, LOCK_EX) !== false |
||
1938 | && ($fp = fopen($local, 'rb'))) { |
||
1939 | clearstatcache(); |
||
1940 | $res = $this->_save($fp, $path, '', []); |
||
1941 | fclose($fp); |
||
1942 | } |
||
1943 | file_exists($local) && unlink($local); |
||
1944 | } |
||
1945 | |||
1946 | return $res; |
||
1947 | } |
||
1948 | |||
1949 | /** |
||
1950 | * Detect available archivers. |
||
1951 | **/ |
||
1952 | protected function _checkArchivers() |
||
1953 | { |
||
1954 | // die('Not yet implemented. (_checkArchivers)'); |
||
1955 | return []; |
||
1956 | } |
||
1957 | |||
1958 | /** |
||
1959 | * chmod implementation. |
||
1960 | * |
||
1961 | * @return bool |
||
1962 | **/ |
||
1963 | protected function _chmod($path, $mode) |
||
1964 | { |
||
1965 | return false; |
||
1966 | } |
||
1967 | |||
1968 | /** |
||
1969 | * Unpack archive. |
||
1970 | * |
||
1971 | * @param string $path archive path |
||
1972 | * @param array $arc archiver command and arguments (same as in $this->archivers) |
||
1973 | * |
||
1974 | * @return true |
||
1975 | * |
||
1976 | * @author Dmitry (dio) Levashov |
||
1977 | * @author Alexey Sukhotin |
||
1978 | **/ |
||
1979 | protected function _unpack($path, $arc) |
||
1980 | { |
||
1981 | die('Not yet implemented. (_unpack)'); |
||
0 ignored issues
–
show
The method
_unpack() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an ![]() |
|||
1982 | //return false; |
||
1983 | } |
||
1984 | |||
1985 | /** |
||
1986 | * Recursive symlinks search. |
||
1987 | * |
||
1988 | * @param string $path file/dir path |
||
1989 | * |
||
1990 | * @return bool |
||
1991 | * |
||
1992 | * @author Dmitry (dio) Levashov |
||
1993 | **/ |
||
1994 | protected function _findSymlinks($path) |
||
1995 | { |
||
1996 | die('Not yet implemented. (_findSymlinks)'); |
||
0 ignored issues
–
show
The method
_findSymlinks() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an ![]() |
|||
1997 | } |
||
1998 | |||
1999 | /** |
||
2000 | * Extract files from archive. |
||
2001 | * |
||
2002 | * @param string $path archive path |
||
2003 | * @param array $arc archiver command and arguments (same as in $this->archivers) |
||
2004 | * |
||
2005 | * @return true |
||
2006 | * |
||
2007 | * @author Dmitry (dio) Levashov, |
||
2008 | * @author Alexey Sukhotin |
||
2009 | **/ |
||
2010 | protected function _extract($path, $arc) |
||
2011 | { |
||
2012 | die('Not yet implemented. (_extract)'); |
||
0 ignored issues
–
show
The method
_extract() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an ![]() |
|||
2013 | } |
||
2014 | |||
2015 | /** |
||
2016 | * Create archive and return its path. |
||
2017 | * |
||
2018 | * @param string $dir target dir |
||
2019 | * @param array $files files names list |
||
2020 | * @param string $name archive name |
||
2021 | * @param array $arc archiver options |
||
2022 | * |
||
2023 | * @return string|bool |
||
2024 | * |
||
2025 | * @author Dmitry (dio) Levashov, |
||
2026 | * @author Alexey Sukhotin |
||
2027 | **/ |
||
2028 | protected function _archive($dir, $files, $name, $arc) |
||
2029 | { |
||
2030 | die('Not yet implemented. (_archive)'); |
||
0 ignored issues
–
show
The method
_archive() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an ![]() |
|||
2031 | } |
||
2032 | |||
2033 | /** |
||
2034 | * Drive query and fetchAll. |
||
2035 | * |
||
2036 | * @param string $sql |
||
2037 | * |
||
2038 | * @return bool|array |
||
2039 | */ |
||
2040 | private function _gd_query($opts) |
||
2041 | { |
||
2042 | $result = []; |
||
2043 | $pageToken = null; |
||
2044 | $parameters = [ |
||
2045 | 'fields' => self::FETCHFIELDS_LIST, |
||
2046 | 'pageSize' => 1000, |
||
2047 | 'spaces' => 'drive', |
||
2048 | ]; |
||
2049 | |||
2050 | if (is_array($opts)) { |
||
2051 | $parameters = array_merge($parameters, $opts); |
||
2052 | } |
||
2053 | do { |
||
2054 | try { |
||
2055 | if ($pageToken) { |
||
2056 | $parameters['pageToken'] = $pageToken; |
||
2057 | } |
||
2058 | $files = $this->service->files->listFiles($parameters); |
||
2059 | |||
2060 | $result = array_merge($result, $files->getFiles()); |
||
2061 | $pageToken = $files->getNextPageToken(); |
||
2062 | } catch (Exception $e) { |
||
2063 | $pageToken = null; |
||
2064 | } |
||
2065 | } while ($pageToken); |
||
2066 | |||
2067 | return $result; |
||
2068 | } |
||
2069 | |||
2070 | /** |
||
2071 | * Get dat(googledrive metadata) from GoogleDrive. |
||
2072 | * |
||
2073 | * @param string $path |
||
2074 | * |
||
2075 | * @return array googledrive metadata |
||
2076 | */ |
||
2077 | private function _gd_getFile($path, $fields = '') |
||
2078 | { |
||
2079 | list(, $itemId) = $this->_gd_splitPath($path); |
||
2080 | if (! $fields) { |
||
2081 | $fields = self::FETCHFIELDS_GET; |
||
2082 | } |
||
2083 | try { |
||
2084 | $file = $this->service->files->get($itemId, ['fields' => $fields]); |
||
2085 | if ($file instanceof Google_Service_Drive_DriveFile) { |
||
0 ignored issues
–
show
The class
Google_Service_Drive_DriveFile does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
2086 | return $file; |
||
2087 | } else { |
||
2088 | return []; |
||
2089 | } |
||
2090 | } catch (Exception $e) { |
||
2091 | return []; |
||
2092 | } |
||
2093 | } |
||
2094 | |||
2095 | /** |
||
2096 | * Get dat(googledrive metadata) from GoogleDrive. |
||
2097 | * |
||
2098 | * @param string $path |
||
2099 | * |
||
2100 | * @return array googledrive metadata |
||
2101 | */ |
||
2102 | private function _gd_getNameByPath($path) |
||
2103 | { |
||
2104 | list(, $itemId) = $this->_gd_splitPath($path); |
||
2105 | if (! $this->names) { |
||
2106 | $this->_gd_getDirectoryData(); |
||
2107 | } |
||
2108 | |||
2109 | return isset($this->names[$itemId]) ? $this->names[$itemId] : ''; |
||
2110 | } |
||
2111 | } // END class |
||
2112 |
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.