PluginProbe ʕ •ᴥ•ʔ
File Manager Pro – Filester / 1.8
File Manager Pro – Filester v1.8
2.1.1 trunk 1.6.1 1.7.6 1.8 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9 2.0 2.0.1 2.0.2 2.1.0
filester / includes / File_manager / lib / php / elFinderFlysystemGoogleDriveNetmount.php
filester / includes / File_manager / lib / php Last commit date
.tmp 2 years ago editors 2 years ago libs 2 years ago plugins 2 years ago resources 2 years ago MySQLStorage.sql 2 years ago autoload.php 2 years ago elFinder.class.php 2 years ago elFinderConnector.class.php 2 years ago elFinderFlysystemGoogleDriveNetmount.php 2 years ago elFinderPlugin.php 2 years ago elFinderSession.php 2 years ago elFinderSessionInterface.php 2 years ago elFinderVolumeBox.class.php 2 years ago elFinderVolumeDriver.class.php 2 years ago elFinderVolumeDropbox.class.php 2 years ago elFinderVolumeDropbox2.class.php 2 years ago elFinderVolumeFTP.class.php 2 years ago elFinderVolumeGoogleDrive.class.php 2 years ago elFinderVolumeGroup.class.php 2 years ago elFinderVolumeLocalFileSystem.class.php 2 years ago elFinderVolumeMySQL.class.php 2 years ago elFinderVolumeOneDrive.class.php 2 years ago elFinderVolumeSFTPphpseclib.class.php 2 years ago elFinderVolumeTrash.class.php 2 years ago elFinderVolumeTrashMySQL.class.php 2 years ago index.php 2 years ago mime.types 2 years ago
elFinderFlysystemGoogleDriveNetmount.php
381 lines
1 <?php
2
3 use League\Flysystem\Filesystem;
4 use League\Flysystem\Adapter\Local;
5 use League\Flysystem\Cached\CachedAdapter;
6 use League\Flysystem\Cached\Storage\Adapter as ACache;
7 use Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter;
8 use Hypweb\Flysystem\Cached\Extra\Hasdir;
9 use Hypweb\Flysystem\Cached\Extra\DisableEnsureParentDirectories;
10 use Hypweb\elFinderFlysystemDriverExt\Driver as ExtDriver;
11
12 elFinder::$netDrivers['googledrive'] = 'FlysystemGoogleDriveNetmount';
13
14 if (!class_exists('elFinderVolumeFlysystemGoogleDriveCache', false)) {
15 class elFinderVolumeFlysystemGoogleDriveCache extends ACache
16 {
17 use Hasdir;
18 use DisableEnsureParentDirectories;
19 }
20 }
21
22 class elFinderVolumeFlysystemGoogleDriveNetmount extends ExtDriver
23 {
24
25 public function __construct()
26 {
27 parent::__construct();
28
29 $opts = array(
30 'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
31 'rootCssClass' => 'elfinder-navbar-root-googledrive',
32 'gdAlias' => '%s@GDrive',
33 'gdCacheDir' => __DIR__ . '/.tmp',
34 'gdCachePrefix' => 'gd-',
35 'gdCacheExpire' => 600
36 );
37
38 $this->options = array_merge($this->options, $opts);
39 }
40
41 /**
42 * Prepare driver before mount volume.
43 * Return true if volume is ready.
44 *
45 * @return bool
46 **/
47 protected function init()
48 {
49 if (empty($this->options['icon'])) {
50 $this->options['icon'] = true;
51 }
52 if ($res = parent::init()) {
53 if ($this->options['icon'] === true) {
54 unset($this->options['icon']);
55 }
56 // enable command archive
57 $this->options['useRemoteArchive'] = true;
58 }
59 return $res;
60 }
61
62 /**
63 * Prepare
64 * Call from elFinder::netmout() before volume->mount()
65 *
66 * @param $options
67 *
68 * @return Array
69 * @author Naoki Sawada
70 */
71 public function netmountPrepare($options)
72 {
73 if (empty($options['client_id']) && defined('ELFINDER_GOOGLEDRIVE_CLIENTID')) {
74 $options['client_id'] = ELFINDER_GOOGLEDRIVE_CLIENTID;
75 }
76 if (empty($options['client_secret']) && defined('ELFINDER_GOOGLEDRIVE_CLIENTSECRET')) {
77 $options['client_secret'] = ELFINDER_GOOGLEDRIVE_CLIENTSECRET;
78 }
79
80 if (!isset($options['pass'])) {
81 $options['pass'] = '';
82 }
83
84 try {
85 $client = new \Google_Client();
86 $client->setClientId($options['client_id']);
87 $client->setClientSecret($options['client_secret']);
88
89 if ($options['pass'] === 'reauth') {
90 $options['pass'] = '';
91 $this->session->set('GoogleDriveAuthParams', [])->set('GoogleDriveTokens', []);
92 } else if ($options['pass'] === 'googledrive') {
93 $options['pass'] = '';
94 }
95
96 $options = array_merge($this->session->get('GoogleDriveAuthParams', []), $options);
97
98 if (!isset($options['access_token'])) {
99 $options['access_token'] = $this->session->get('GoogleDriveTokens', []);
100 $this->session->remove('GoogleDriveTokens');
101 }
102 $aToken = $options['access_token'];
103
104 $rootObj = $service = null;
105 if ($aToken) {
106 try {
107 $client->setAccessToken($aToken);
108 if ($client->isAccessTokenExpired()) {
109 $aToken = array_merge($aToken, $client->fetchAccessTokenWithRefreshToken());
110 $client->setAccessToken($aToken);
111 }
112 $service = new \Google_Service_Drive($client);
113 $rootObj = $service->files->get('root');
114
115 $options['access_token'] = $aToken;
116 $this->session->set('GoogleDriveAuthParams', $options);
117
118 } catch (Exception $e) {
119 $aToken = [];
120 $options['access_token'] = [];
121 if ($options['user'] !== 'init') {
122 $this->session->set('GoogleDriveAuthParams', $options);
123 return array('exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE);
124 }
125 }
126
127 }
128
129 $itpCare = isset($options['code']);
130 $code = $itpCare? $options['code'] : (isset($_GET['code'])? $_GET['code'] : '');
131 if ($code || $options['user'] === 'init') {
132 if (empty($options['url'])) {
133 $options['url'] = elFinder::getConnectorUrl();
134 }
135
136 if (isset($options['id'])) {
137 $callback = $options['url'] . (strpos($options['url'], '?') !== false? '&' : '?') . 'cmd=netmount&protocol=googledrive&host=' . ($options['id'] === 'elfinder'? '1' : $options['id']);
138 $client->setRedirectUri($callback);
139 }
140
141 if (!$aToken && empty($code)) {
142 $client->setScopes([Google_Service_Drive::DRIVE]);
143 if (!empty($options['offline'])) {
144 $client->setApprovalPrompt('force');
145 $client->setAccessType('offline');
146 }
147 $url = $client->createAuthUrl();
148
149 $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">';
150 $html .= '<script>
151 $("#' . $options['id'] . '").elfinder("instance").trigger("netmount", {protocol: "googledrive", mode: "makebtn", url: "' . $url . '"});
152 </script>';
153 if (empty($options['pass']) && $options['host'] !== '1') {
154 $options['pass'] = 'return';
155 $this->session->set('GoogleDriveAuthParams', $options);
156 return array('exit' => true, 'body' => $html);
157 } else {
158 $out = array(
159 'node' => $options['id'],
160 'json' => '{"protocol": "googledrive", "mode": "makebtn", "body" : "' . str_replace($html, '"', '\\"') . '", "error" : "' . elFinder::ERROR_ACCESS_DENIED . '"}',
161 'bind' => 'netmount'
162 );
163 return array('exit' => 'callback', 'out' => $out);
164 }
165 } else {
166 if ($code) {
167 if (!empty($options['id'])) {
168 $aToken = $client->fetchAccessTokenWithAuthCode($code);
169 $options['access_token'] = $aToken;
170 unset($options['code']);
171 $this->session->set('GoogleDriveTokens', $aToken)->set('GoogleDriveAuthParams', $options);
172 $out = array(
173 'node' => $options['id'],
174 'json' => '{"protocol": "googledrive", "mode": "done", "reset": 1}',
175 'bind' => 'netmount'
176 );
177 } else {
178 $nodeid = ($_GET['host'] === '1')? 'elfinder' : $_GET['host'];
179 $out = array(
180 'node' => $nodeid,
181 'json' => json_encode(array(
182 'protocol' => 'googledrive',
183 'host' => $nodeid,
184 'mode' => 'redirect',
185 'options' => array(
186 'id' => $nodeid,
187 'code'=> $code
188 )
189 )),
190 'bind' => 'netmount'
191 );
192 }
193 if (!$itpCare) {
194 return array('exit' => 'callback', 'out' => $out);
195 } else {
196 return array('exit' => true, 'body' => $out['json']);
197 }
198 }
199 $folders = [];
200 foreach ($service->files->listFiles([
201 'pageSize' => 1000,
202 'q' => 'trashed = false and mimeType = "application/vnd.google-apps.folder"'
203 ]) as $f) {
204 $folders[$f->getId()] = $f->getName();
205 }
206 natcasesort($folders);
207 $folders = ['root' => $rootObj->getName()] + $folders;
208 $folders = json_encode($folders);
209 $json = '{"protocol": "googledrive", "mode": "done", "folders": ' . $folders . '}';
210 $options['pass'] = 'return';
211 $html = 'Google.com';
212 $html .= '<script>
213 $("#' . $options['id'] . '").elfinder("instance").trigger("netmount", ' . $json . ');
214 </script>';
215 $this->session->set('GoogleDriveAuthParams', $options);
216 return array('exit' => true, 'body' => $html);
217 }
218 }
219 } catch (Exception $e) {
220 $this->session->remove('GoogleDriveAuthParams')->remove('GoogleDriveTokens');
221 if (empty($options['pass'])) {
222 return array('exit' => true, 'body' => '{msg:' . elFinder::ERROR_ACCESS_DENIED . '}' . ' ' . $e->getMessage());
223 } else {
224 return array('exit' => true, 'error' => [elFinder::ERROR_ACCESS_DENIED, $e->getMessage()]);
225 }
226 }
227
228 if (!$aToken) {
229 return array('exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE);
230 }
231
232 if ($options['path'] === '/') {
233 $options['path'] = 'root';
234 }
235
236 try {
237 $file = $service->files->get($options['path']);
238 $options['alias'] = sprintf($this->options['gdAlias'], $file->getName());
239 if (!empty($this->options['netkey'])) {
240 elFinder::$instance->updateNetVolumeOption($this->options['netkey'], 'alias', $this->options['alias']);
241 }
242 } catch (Google_Service_Exception $e) {
243 $err = json_decode($e->getMessage(), true);
244 if (isset($err['error']) && $err['error']['code'] == 404) {
245 return array('exit' => true, 'error' => [elFinder::ERROR_TRGDIR_NOT_FOUND, $options['path']]);
246 } else {
247 return array('exit' => true, 'error' => $e->getMessage());
248 }
249 } catch (Exception $e) {
250 return array('exit' => true, 'error' => $e->getMessage());
251 }
252
253 foreach (['host', 'user', 'pass', 'id', 'offline'] as $key) {
254 unset($options[$key]);
255 }
256
257 return $options;
258 }
259
260 /**
261 * process of on netunmount
262 * Drop table `dropbox` & rm thumbs
263 *
264 * @param $netVolumes
265 * @param $key
266 *
267 * @return bool
268 * @internal param array $options
269 */
270 public function netunmount($netVolumes, $key)
271 {
272 $cache = $this->options['gdCacheDir'] . DIRECTORY_SEPARATOR . $this->options['gdCachePrefix'] . $this->netMountKey;
273 if (file_exists($cache) && is_writeable($cache)) {
274 unlink($cache);
275 }
276 if ($tmbs = glob($this->tmbPath . DIRECTORY_SEPARATOR . $this->netMountKey . '*')) {
277 foreach ($tmbs as $file) {
278 unlink($file);
279 }
280 }
281 return true;
282 }
283
284 /**
285 * "Mount" volume.
286 * Return true if volume available for read or write,
287 * false - otherwise
288 *
289 * @param array $opts
290 *
291 * @return bool
292 * @author Naoki Sawada
293 */
294 public function mount(array $opts)
295 {
296 $creds = null;
297 if (isset($opts['access_token'])) {
298 $this->netMountKey = md5(join('-', array('googledrive', $opts['path'], (isset($opts['access_token']['refresh_token']) ? $opts['access_token']['refresh_token'] : $opts['access_token']['access_token']))));
299 }
300
301 $client = new \Google_Client();
302 $client->setClientId($opts['client_id']);
303 $client->setClientSecret($opts['client_secret']);
304
305 if (!empty($opts['access_token'])) {
306 $client->setAccessToken($opts['access_token']);
307 }
308 if ($this->needOnline && $client->isAccessTokenExpired()) {
309 try {
310 $creds = $client->fetchAccessTokenWithRefreshToken();
311 } catch (LogicException $e) {
312 $this->session->remove('GoogleDriveAuthParams');
313 throw $e;
314 }
315 }
316
317 $service = new \Google_Service_Drive($client);
318
319 // If path is not set, use the root
320 if (!isset($opts['path']) || $opts['path'] === '') {
321 $opts['path'] = 'root';
322 }
323
324 $googleDrive = new GoogleDriveAdapter($service, $opts['path'], ['useHasDir' => true]);
325
326 $opts['fscache'] = null;
327 if ($this->options['gdCacheDir'] && is_writeable($this->options['gdCacheDir'])) {
328 if ($this->options['gdCacheExpire']) {
329 $opts['fscache'] = new elFinderVolumeFlysystemGoogleDriveCache(new Local($this->options['gdCacheDir']), $this->options['gdCachePrefix'] . $this->netMountKey, $this->options['gdCacheExpire']);
330 }
331 }
332 if ($opts['fscache']) {
333 $filesystem = new Filesystem(new CachedAdapter($googleDrive, $opts['fscache']));
334 } else {
335 $filesystem = new Filesystem($googleDrive);
336 }
337
338 $opts['driver'] = 'FlysystemExt';
339 $opts['filesystem'] = $filesystem;
340 $opts['separator'] = '/';
341 $opts['checkSubfolders'] = true;
342 if (!isset($opts['alias'])) {
343 $opts['alias'] = 'GoogleDrive';
344 }
345
346 if ($res = parent::mount($opts)) {
347 // update access_token of session data
348 if ($creds) {
349 $netVolumes = $this->session->get('netvolume');
350 $netVolumes[$this->netMountKey]['access_token'] = array_merge($netVolumes[$this->netMountKey]['access_token'], $creds);
351 $this->session->set('netvolume', $netVolumes);
352 }
353 }
354
355 return $res;
356 }
357
358 /**
359 * @inheritdoc
360 */
361 protected function tmbname($stat)
362 {
363 return $this->netMountKey . substr(substr($stat['hash'], strlen($this->id)), -38) . $stat['ts'] . '.png';
364 }
365
366 /**
367 * Return debug info for client.
368 *
369 * @return array
370 **/
371 public function debug()
372 {
373 $res = parent::debug();
374 if (!empty($this->options['netkey']) && empty($this->options['refresh_token']) && $this->options['access_token'] && isset($this->options['access_token']['refresh_token'])) {
375 $res['refresh_token'] = $this->options['access_token']['refresh_token'];
376 }
377
378 return $res;
379 }
380 }
381