1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
elFinder::$netDrivers['dropbox'] = 'Dropbox'; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Simple elFinder driver for FTP. |
7
|
|
|
* |
8
|
|
|
* @author Dmitry (dio) Levashov |
9
|
|
|
* @author Cem (discofever) |
10
|
|
|
**/ |
11
|
|
|
class elFinderVolumeDropbox extends elFinderVolumeDriver |
|
|
|
|
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* Driver id |
15
|
|
|
* Must be started from letter and contains [a-z0-9] |
16
|
|
|
* Used as part of volume id. |
17
|
|
|
* |
18
|
|
|
* @var string |
19
|
|
|
**/ |
20
|
|
|
protected $driverId = 'd'; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* OAuth object. |
24
|
|
|
* |
25
|
|
|
* @var oauth |
26
|
|
|
**/ |
27
|
|
|
protected $oauth = null; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Dropbox object. |
31
|
|
|
* |
32
|
|
|
* @var dropbox |
33
|
|
|
**/ |
34
|
|
|
protected $dropbox = null; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* Directory for meta data caches |
38
|
|
|
* If not set driver not cache meta data. |
39
|
|
|
* |
40
|
|
|
* @var string |
41
|
|
|
**/ |
42
|
|
|
protected $metaCache = ''; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Last API error message. |
46
|
|
|
* |
47
|
|
|
* @var string |
48
|
|
|
**/ |
49
|
|
|
protected $apiError = ''; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Directory for tmp files |
53
|
|
|
* If not set driver will try to use tmbDir as tmpDir. |
54
|
|
|
* |
55
|
|
|
* @var string |
56
|
|
|
**/ |
57
|
|
|
protected $tmp = ''; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Dropbox.com uid. |
61
|
|
|
* |
62
|
|
|
* @var string |
63
|
|
|
**/ |
64
|
|
|
protected $dropboxUid = ''; |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Dropbox download host, replaces 'www.dropbox.com' of shares URL. |
68
|
|
|
* |
69
|
|
|
* @var string |
70
|
|
|
*/ |
71
|
|
|
private $dropbox_dlhost = 'dl.dropboxusercontent.com'; |
72
|
|
|
|
73
|
|
|
private $dropbox_phpFound = false; |
74
|
|
|
|
75
|
|
|
private $DB_TableName = ''; |
76
|
|
|
|
77
|
|
|
private $tmbPrefix = ''; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Constructor |
81
|
|
|
* Extend options with required fields. |
82
|
|
|
* |
83
|
|
|
* @author Dmitry (dio) Levashov |
84
|
|
|
* @author Cem (DiscoFever) |
85
|
|
|
*/ |
86
|
|
|
public function __construct() |
87
|
|
|
{ |
88
|
|
|
|
89
|
|
|
// check with composer |
90
|
|
|
$this->dropbox_phpFound = class_exists('Dropbox_API'); |
91
|
|
|
|
92
|
|
|
if (! $this->dropbox_phpFound) { |
93
|
|
|
// check with pear |
94
|
|
|
if (include_once 'Dropbox/autoload.php') { |
95
|
|
|
$this->dropbox_phpFound = in_array('Dropbox_autoload', spl_autoload_functions()); |
96
|
|
|
} |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
$opts = [ |
100
|
|
|
'consumerKey' => '', |
101
|
|
|
'consumerSecret' => '', |
102
|
|
|
'accessToken' => '', |
103
|
|
|
'accessTokenSecret' => '', |
104
|
|
|
'dropboxUid' => '', |
105
|
|
|
'root' => 'dropbox', |
106
|
|
|
'path' => '/', |
107
|
|
|
'separator' => '/', |
108
|
|
|
'PDO_DSN' => '', // if empty use 'sqlite:(metaCachePath|tmbPath)/elFinder_dropbox_db_(hash:dropboxUid+consumerSecret)' |
|
|
|
|
109
|
|
|
'PDO_User' => '', |
110
|
|
|
'PDO_Pass' => '', |
111
|
|
|
'PDO_Options' => [], |
112
|
|
|
'PDO_DBName' => 'dropbox', |
113
|
|
|
'treeDeep' => 0, |
114
|
|
|
'tmbPath' => '', |
115
|
|
|
'tmbURL' => '', |
116
|
|
|
'tmpPath' => '', |
117
|
|
|
'getTmbSize' => 'large', // small: 32x32, medium or s: 64x64, large or m: 128x128, l: 640x480, xl: 1024x768 |
118
|
|
|
'metaCachePath' => '', |
119
|
|
|
'metaCacheTime' => '600', // 10m |
120
|
|
|
'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#', |
121
|
|
|
'rootCssClass' => 'elfinder-navbar-root-dropbox', |
122
|
|
|
]; |
123
|
|
|
$this->options = array_merge($this->options, $opts); |
124
|
|
|
$this->options['mimeDetect'] = 'internal'; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Prepare |
129
|
|
|
* Call from elFinder::netmout() before volume->mount(). |
130
|
|
|
* |
131
|
|
|
* @param $options |
132
|
|
|
* @return array |
133
|
|
|
* @author Naoki Sawada |
134
|
|
|
*/ |
135
|
|
|
public function netmountPrepare($options) |
|
|
|
|
136
|
|
|
{ |
137
|
|
|
if (empty($options['consumerKey']) && defined('ELFINDER_DROPBOX_CONSUMERKEY')) { |
138
|
|
|
$options['consumerKey'] = ELFINDER_DROPBOX_CONSUMERKEY; |
139
|
|
|
} |
140
|
|
|
if (empty($options['consumerSecret']) && defined('ELFINDER_DROPBOX_CONSUMERSECRET')) { |
141
|
|
|
$options['consumerSecret'] = ELFINDER_DROPBOX_CONSUMERSECRET; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
if ($options['user'] === 'init') { |
145
|
|
|
if (! $this->dropbox_phpFound || empty($options['consumerKey']) || empty($options['consumerSecret']) || ! class_exists('PDO', false)) { |
146
|
|
|
return ['exit' => true, 'body' => '{msg:errNetMountNoDriver}']; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) { |
150
|
|
|
$this->oauth = new Dropbox_OAuth_Curl($options['consumerKey'], $options['consumerSecret']); |
|
|
|
|
151
|
|
|
} else { |
152
|
|
|
if (class_exists('OAuth', false)) { |
153
|
|
|
$this->oauth = new Dropbox_OAuth_PHP($options['consumerKey'], $options['consumerSecret']); |
|
|
|
|
154
|
|
|
} else { |
155
|
|
|
if (! class_exists('HTTP_OAuth_Consumer')) { |
156
|
|
|
// We're going to try to load in manually |
157
|
|
|
include 'HTTP/OAuth/Consumer.php'; |
158
|
|
|
} |
159
|
|
|
if (class_exists('HTTP_OAuth_Consumer', false)) { |
160
|
|
|
$this->oauth = new Dropbox_OAuth_PEAR($options['consumerKey'], $options['consumerSecret']); |
|
|
|
|
161
|
|
|
} |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
if (! $this->oauth) { |
166
|
|
|
return ['exit' => true, 'body' => '{msg:errNetMountNoDriver}']; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
if ($options['pass'] === 'init') { |
170
|
|
|
$html = ''; |
171
|
|
|
if ($sessionToken = $this->session->get('DropboxTokens')) { |
172
|
|
|
// token check |
173
|
|
|
try { |
174
|
|
|
list(, $accessToken, $accessTokenSecret) = $sessionToken; |
175
|
|
|
$this->oauth->setToken($accessToken, $accessTokenSecret); |
176
|
|
|
$this->dropbox = new Dropbox_API($this->oauth, $this->options['root']); |
|
|
|
|
177
|
|
|
$this->dropbox->getAccountInfo(); |
178
|
|
|
$script = '<script> |
179
|
|
|
$("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "done"}); |
180
|
|
|
</script>'; |
181
|
|
|
$html = $script; |
182
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
183
|
|
|
$this->session->remove('DropboxTokens'); |
184
|
|
|
} |
185
|
|
|
} |
186
|
|
|
if (! $html) { |
187
|
|
|
// get customdata |
188
|
|
|
$cdata = ''; |
189
|
|
|
$innerKeys = ['cmd', 'host', 'options', 'pass', 'protocol', 'user']; |
190
|
|
|
$this->ARGS = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET; |
191
|
|
View Code Duplication |
foreach ($this->ARGS as $k => $v) { |
|
|
|
|
192
|
|
|
if (! in_array($k, $innerKeys)) { |
193
|
|
|
$cdata .= '&'.$k.'='.rawurlencode($v); |
194
|
|
|
} |
195
|
|
|
} |
196
|
|
|
if (strpos($options['url'], 'http') !== 0) { |
197
|
|
|
$options['url'] = elFinder::getConnectorUrl(); |
198
|
|
|
} |
199
|
|
|
$callback = $options['url'] |
200
|
|
|
.'?cmd=netmount&protocol=dropbox&host=dropbox.com&user=init&pass=return&node='.$options['id'].$cdata; |
201
|
|
|
|
202
|
|
|
try { |
203
|
|
|
$tokens = $this->oauth->getRequestToken(); |
204
|
|
|
$url = $this->oauth->getAuthorizeUrl(rawurlencode($callback)); |
205
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
206
|
|
|
return ['exit' => true, 'body' => '{msg:errAccess}']; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
$this->session->set('DropboxAuthTokens', $tokens); |
210
|
|
|
$html = '<input id="elf-volumedriver-dropbox-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.'\')">'; |
211
|
|
|
$html .= '<script> |
212
|
|
|
$("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "makebtn"}); |
213
|
|
|
</script>'; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
return ['exit' => true, 'body' => $html]; |
217
|
|
|
} else { |
218
|
|
|
$this->oauth->setToken($this->session->get('DropboxAuthTokens')); |
219
|
|
|
$this->session->remove('DropboxAuthTokens'); |
220
|
|
|
$tokens = $this->oauth->getAccessToken(); |
221
|
|
|
$this->session->set('DropboxTokens', [$_GET['uid'], $tokens['token'], $tokens['token_secret']]); |
222
|
|
|
|
223
|
|
|
$out = [ |
224
|
|
|
'node' => $_GET['node'], |
225
|
|
|
'json' => '{"protocol": "dropbox", "mode": "done"}', |
226
|
|
|
'bind' => 'netmount', |
227
|
|
|
]; |
228
|
|
|
|
229
|
|
|
return ['exit' => 'callback', 'out' => $out]; |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
if ($sessionToken = $this->session->get('DropboxTokens')) { |
233
|
|
|
list($options['dropboxUid'], $options['accessToken'], $options['accessTokenSecret']) = $sessionToken; |
234
|
|
|
} |
235
|
|
|
unset($options['user'], $options['pass']); |
236
|
|
|
|
237
|
|
|
return $options; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* process of on netunmount |
242
|
|
|
* Drop table `dropbox` & rm thumbs. |
243
|
|
|
* |
244
|
|
|
* @param $netVolumes |
245
|
|
|
* @param $key |
246
|
|
|
* @return bool |
247
|
|
|
* @internal param array $options |
248
|
|
|
*/ |
249
|
|
|
public function netunmount($netVolumes, $key) |
250
|
|
|
{ |
251
|
|
|
$count = 0; |
252
|
|
|
$dropboxUid = ''; |
253
|
|
|
if (isset($netVolumes[$key])) { |
254
|
|
|
$dropboxUid = $netVolumes[$key]['dropboxUid']; |
255
|
|
|
} |
256
|
|
|
foreach ($netVolumes as $volume) { |
257
|
|
|
if ($volume['host'] === 'dropbox' && $volume['dropboxUid'] === $dropboxUid) { |
258
|
|
|
$count++; |
259
|
|
|
} |
260
|
|
|
} |
261
|
|
|
if ($count === 1) { |
262
|
|
|
$this->DB->exec('drop table '.$this->DB_TableName); |
|
|
|
|
263
|
|
|
foreach (glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->tmbPrefix.'*.png') as $tmb) { |
264
|
|
|
unlink($tmb); |
265
|
|
|
} |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
return true; |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
/*********************************************************************/ |
272
|
|
|
/* FS API */ |
273
|
|
|
/*********************************************************************/ |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Close opened connection. |
277
|
|
|
* |
278
|
|
|
* @return void |
279
|
|
|
* @author Dmitry (dio) Levashov |
280
|
|
|
**/ |
281
|
|
|
public function umount() |
282
|
|
|
{ |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* Return content URL. |
287
|
|
|
* |
288
|
|
|
* @param string $hash file hash |
289
|
|
|
* @param array $options options |
290
|
|
|
* @return array |
291
|
|
|
* @author Naoki Sawada |
292
|
|
|
**/ |
293
|
|
|
public function getContentUrl($hash, $options = []) |
294
|
|
|
{ |
295
|
|
|
if (($file = $this->file($hash)) == false || ! $file['url'] || $file['url'] == 1) { |
296
|
|
|
$path = $this->decode($hash); |
297
|
|
|
$cache = $this->getDBdat($path); |
298
|
|
|
$url = ''; |
299
|
|
|
if (isset($cache['share']) && strpos($cache['share'], $this->dropbox_dlhost) !== false) { |
300
|
|
|
$res = $this->getHttpResponseHeader($cache['share']); |
301
|
|
|
if (preg_match("/^HTTP\/[01\.]+ ([0-9]{3})/", $res, $match)) { |
302
|
|
|
if ($match[1] < 400) { |
303
|
|
|
$url = $cache['share']; |
304
|
|
|
} |
305
|
|
|
} |
306
|
|
|
} |
307
|
|
|
if (! $url) { |
308
|
|
|
try { |
309
|
|
|
$res = $this->dropbox->share($path, null, false); |
310
|
|
|
$url = $res['url']; |
311
|
|
|
if (strpos($url, 'www.dropbox.com') === false) { |
312
|
|
|
$res = $this->getHttpResponseHeader($url); |
313
|
|
|
if (preg_match('/^location:\s*(http[^\s]+)/im', $res, $match)) { |
314
|
|
|
$url = $match[1]; |
315
|
|
|
} |
316
|
|
|
} |
317
|
|
|
list($url) = explode('?', $url); |
318
|
|
|
$url = str_replace('www.dropbox.com', $this->dropbox_dlhost, $url); |
319
|
|
|
if (! isset($cache['share']) || $cache['share'] !== $url) { |
320
|
|
|
$cache['share'] = $url; |
321
|
|
|
$this->updateDBdat($path, $cache); |
322
|
|
|
} |
323
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
324
|
|
|
return false; |
325
|
|
|
} |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
return $url; |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
return $file['url']; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/*********************************************************************/ |
335
|
|
|
/* INIT AND CONFIGURE */ |
336
|
|
|
/*********************************************************************/ |
337
|
|
|
|
338
|
|
|
/** |
339
|
|
|
* Prepare FTP connection |
340
|
|
|
* Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn. |
341
|
|
|
* |
342
|
|
|
* @return bool |
343
|
|
|
* @author Dmitry (dio) Levashov |
344
|
|
|
* @author Cem (DiscoFever) |
345
|
|
|
**/ |
346
|
|
|
protected function init() |
347
|
|
|
{ |
348
|
|
|
if (! class_exists('PDO', false)) { |
349
|
|
|
return $this->setError('PHP PDO class is require.'); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
if (! $this->options['consumerKey'] |
353
|
|
|
|| ! $this->options['consumerSecret'] |
354
|
|
|
|| ! $this->options['accessToken'] |
355
|
|
|
|| ! $this->options['accessTokenSecret']) { |
356
|
|
|
return $this->setError('Required options undefined.'); |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
if (empty($this->options['metaCachePath']) && defined('ELFINDER_DROPBOX_META_CACHE_PATH')) { |
360
|
|
|
$this->options['metaCachePath'] = ELFINDER_DROPBOX_META_CACHE_PATH; |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
// make net mount key |
364
|
|
|
$this->netMountKey = md5(implode('-', ['dropbox', $this->options['path']])); |
365
|
|
|
|
366
|
|
|
if (! $this->oauth) { |
367
|
|
|
if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) { |
368
|
|
|
$this->oauth = new Dropbox_OAuth_Curl($this->options['consumerKey'], $this->options['consumerSecret']); |
|
|
|
|
369
|
|
|
} else { |
370
|
|
|
if (class_exists('OAuth', false)) { |
371
|
|
|
$this->oauth = new Dropbox_OAuth_PHP($this->options['consumerKey'], $this->options['consumerSecret']); |
|
|
|
|
372
|
|
|
} else { |
373
|
|
|
if (! class_exists('HTTP_OAuth_Consumer')) { |
374
|
|
|
// We're going to try to load in manually |
375
|
|
|
include 'HTTP/OAuth/Consumer.php'; |
376
|
|
|
} |
377
|
|
|
if (class_exists('HTTP_OAuth_Consumer', false)) { |
378
|
|
|
$this->oauth = new Dropbox_OAuth_PEAR($this->options['consumerKey'], $this->options['consumerSecret']); |
|
|
|
|
379
|
|
|
} |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
if (! $this->oauth) { |
385
|
|
|
return $this->setError('OAuth extension not loaded.'); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
// normalize root path |
389
|
|
|
$this->root = $this->options['path'] = $this->_normpath($this->options['path']); |
390
|
|
|
|
391
|
|
View Code Duplication |
if (empty($this->options['alias'])) { |
|
|
|
|
392
|
|
|
$this->options['alias'] = ($this->options['path'] === '/') ? 'Dropbox.com' : 'Dropbox'.$this->options['path']; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
$this->rootName = $this->options['alias']; |
396
|
|
|
|
397
|
|
|
try { |
398
|
|
|
$this->oauth->setToken($this->options['accessToken'], $this->options['accessTokenSecret']); |
399
|
|
|
$this->dropbox = new Dropbox_API($this->oauth, $this->options['root']); |
|
|
|
|
400
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
401
|
|
|
$this->session->remove('DropboxTokens'); |
402
|
|
|
|
403
|
|
|
return $this->setError('Dropbox error: '.$e->getMessage()); |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
// user |
407
|
|
|
if (empty($this->options['dropboxUid'])) { |
408
|
|
|
try { |
409
|
|
|
$res = $this->dropbox->getAccountInfo(); |
410
|
|
|
$this->options['dropboxUid'] = $res['uid']; |
411
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
412
|
|
|
$this->session->remove('DropboxTokens'); |
413
|
|
|
|
414
|
|
|
return $this->setError('Dropbox error: '.$e->getMessage()); |
415
|
|
|
} |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
$this->dropboxUid = $this->options['dropboxUid']; |
419
|
|
|
$this->tmbPrefix = 'dropbox'.base_convert($this->dropboxUid, 10, 32); |
420
|
|
|
|
421
|
|
|
if (! empty($this->options['tmpPath'])) { |
422
|
|
|
if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) { |
423
|
|
|
$this->tmp = $this->options['tmpPath']; |
424
|
|
|
} |
425
|
|
|
} |
426
|
|
|
if (! $this->tmp && is_writable($this->options['tmbPath'])) { |
427
|
|
|
$this->tmp = $this->options['tmbPath']; |
428
|
|
|
} |
429
|
|
|
if (! $this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) { |
430
|
|
|
$this->tmp = $tmp; |
431
|
|
|
} |
432
|
|
|
|
433
|
|
View Code Duplication |
if (! empty($this->options['metaCachePath'])) { |
|
|
|
|
434
|
|
|
if ((is_dir($this->options['metaCachePath']) || mkdir($this->options['metaCachePath'])) && is_writable($this->options['metaCachePath'])) { |
435
|
|
|
$this->metaCache = $this->options['metaCachePath']; |
436
|
|
|
} |
437
|
|
|
} |
438
|
|
|
if (! $this->metaCache && $this->tmp) { |
439
|
|
|
$this->metaCache = $this->tmp; |
440
|
|
|
} |
441
|
|
|
|
442
|
|
|
if (! $this->metaCache) { |
443
|
|
|
return $this->setError('Cache dirctory (metaCachePath or tmp) is require.'); |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
// setup PDO |
447
|
|
|
if (! $this->options['PDO_DSN']) { |
448
|
|
|
$this->options['PDO_DSN'] = 'sqlite:'.$this->metaCache.DIRECTORY_SEPARATOR.'.elFinder_dropbox_db_'.md5($this->dropboxUid.$this->options['consumerSecret']); |
449
|
|
|
} |
450
|
|
|
// DataBase table name |
451
|
|
|
$this->DB_TableName = $this->options['PDO_DBName']; |
452
|
|
|
// DataBase check or make table |
453
|
|
|
try { |
454
|
|
|
$this->DB = new PDO($this->options['PDO_DSN'], $this->options['PDO_User'], $this->options['PDO_Pass'], $this->options['PDO_Options']); |
455
|
|
|
if (! $this->checkDB()) { |
456
|
|
|
return $this->setError('Can not make DB table'); |
457
|
|
|
} |
458
|
|
|
} catch (PDOException $e) { |
459
|
|
|
return $this->setError('PDO connection failed: '.$e->getMessage()); |
460
|
|
|
} |
461
|
|
|
|
462
|
|
|
$res = $this->deltaCheck($this->isMyReload()); |
463
|
|
|
if ($res !== true) { |
464
|
|
|
if (is_string($res)) { |
465
|
|
|
return $this->setError($res); |
466
|
|
|
} else { |
467
|
|
|
return $this->setError('Could not check API "delta"'); |
468
|
|
|
} |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
if (is_null($this->options['syncChkAsTs'])) { |
472
|
|
|
$this->options['syncChkAsTs'] = true; |
473
|
|
|
} |
474
|
|
View Code Duplication |
if ($this->options['syncChkAsTs']) { |
|
|
|
|
475
|
|
|
// 'tsPlSleep' minmum 5 sec |
476
|
|
|
$this->options['tsPlSleep'] = max(5, $this->options['tsPlSleep']); |
477
|
|
|
} else { |
478
|
|
|
// 'lsPlSleep' minmum 10 sec |
479
|
|
|
$this->options['lsPlSleep'] = max(10, $this->options['lsPlSleep']); |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
return true; |
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
/** |
486
|
|
|
* Configure after successful mount. |
487
|
|
|
* |
488
|
|
|
* @return string |
489
|
|
|
* @author Dmitry (dio) Levashov |
490
|
|
|
**/ |
491
|
|
|
protected function configure() |
492
|
|
|
{ |
493
|
|
|
parent::configure(); |
494
|
|
|
|
495
|
|
|
$this->disabled[] = 'archive'; |
496
|
|
|
$this->disabled[] = 'extract'; |
497
|
|
|
} |
498
|
|
|
|
499
|
|
|
/** |
500
|
|
|
* Get delta data and DB update. |
501
|
|
|
* |
502
|
|
|
* @param bool $refresh force refresh |
503
|
|
|
* @return true|string error message |
504
|
|
|
*/ |
505
|
|
|
protected function deltaCheck($refresh = true) |
|
|
|
|
506
|
|
|
{ |
507
|
|
|
$chk = false; |
508
|
|
|
if (! $refresh && $chk = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) { |
509
|
|
|
$chk = unserialize($chk[0]); |
510
|
|
|
} |
511
|
|
|
if ($chk && ($chk['mtime'] + $this->options['metaCacheTime']) > $_SERVER['REQUEST_TIME']) { |
512
|
|
|
return true; |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
try { |
516
|
|
|
$more = true; |
|
|
|
|
517
|
|
|
$this->DB->beginTransaction(); |
518
|
|
|
|
519
|
|
|
if ($res = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) { |
520
|
|
|
$res = unserialize($res[0]); |
521
|
|
|
$cursor = $res['cursor']; |
522
|
|
|
} else { |
523
|
|
|
$cursor = ''; |
524
|
|
|
} |
525
|
|
|
$delete = false; |
526
|
|
|
$reset = false; |
527
|
|
|
$ptimes = []; |
528
|
|
|
$now = time(); |
529
|
|
|
do { |
530
|
|
|
ini_set('max_execution_time', 120); |
531
|
|
|
$_info = $this->dropbox->delta($cursor); |
532
|
|
|
if (! empty($_info['reset'])) { |
533
|
|
|
$this->DB->exec('TRUNCATE table '.$this->DB_TableName); |
534
|
|
|
$this->DB->exec('insert into '.$this->DB_TableName.' values(\'\', \'\', \''.serialize(['cursor' => '', 'mtime' => 0]).'\', 0);'); |
535
|
|
|
$this->DB->exec('insert into '.$this->DB_TableName.' values(\'/\', \'\', \''.serialize([ |
536
|
|
|
'path' => '/', |
537
|
|
|
'is_dir' => 1, |
538
|
|
|
'mime_type' => '', |
539
|
|
|
'bytes' => 0, |
540
|
|
|
]).'\', 0);'); |
541
|
|
|
$reset = true; |
542
|
|
|
} |
543
|
|
|
$cursor = $_info['cursor']; |
544
|
|
|
|
545
|
|
|
foreach ($_info['entries'] as $entry) { |
546
|
|
|
$key = strtolower($entry[0]); |
547
|
|
|
$pkey = strtolower($this->_dirname($key)); |
548
|
|
|
|
549
|
|
|
$path = $this->DB->quote($pkey); |
550
|
|
|
$fname = $this->DB->quote(strtolower($this->_basename($key))); |
551
|
|
|
$where = 'where path='.$path.' and fname='.$fname; |
552
|
|
|
|
553
|
|
|
if (empty($entry[1])) { |
554
|
|
|
$ptimes[$pkey] = isset($ptimes[$pkey]) ? max([$now, $ptimes[$pkey]]) : $now; |
555
|
|
|
$this->DB->exec('delete from '.$this->DB_TableName.' '.$where); |
556
|
|
|
! $delete && $delete = true; |
557
|
|
|
continue; |
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
$_itemTime = strtotime(isset($entry[1]['client_mtime']) ? $entry[1]['client_mtime'] : $entry[1]['modified']); |
561
|
|
|
$ptimes[$pkey] = isset($ptimes[$pkey]) ? max([$_itemTime, $ptimes[$pkey]]) : $_itemTime; |
562
|
|
|
$sql = 'select path from '.$this->DB_TableName.' '.$where.' limit 1'; |
563
|
|
|
if (! $reset && $this->query($sql)) { |
564
|
|
|
$this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($entry[1])).', isdir='.($entry[1]['is_dir'] ? 1 : 0).' '.$where); |
565
|
|
|
} else { |
566
|
|
|
$this->DB->exec('insert into '.$this->DB_TableName.' values ('.$path.', '.$fname.', '.$this->DB->quote(serialize($entry[1])).', '.(int) $entry[1]['is_dir'].')'); |
567
|
|
|
} |
568
|
|
|
} |
569
|
|
|
} while (! empty($_info['has_more'])); |
570
|
|
|
|
571
|
|
|
// update time stamp of parent holder |
572
|
|
|
foreach ($ptimes as $_p => $_t) { |
573
|
|
|
if ($praw = $this->getDBdat($_p)) { |
574
|
|
|
$_update = false; |
575
|
|
View Code Duplication |
if (isset($praw['client_mtime']) && $_t > strtotime($praw['client_mtime'])) { |
|
|
|
|
576
|
|
|
$praw['client_mtime'] = date('r', $_t); |
577
|
|
|
$_update = true; |
578
|
|
|
} |
579
|
|
View Code Duplication |
if (isset($praw['modified']) && $_t > strtotime($praw['modified'])) { |
|
|
|
|
580
|
|
|
$praw['modified'] = date('r', $_t); |
581
|
|
|
$_update = true; |
582
|
|
|
} |
583
|
|
|
if ($_update) { |
584
|
|
|
$pwhere = 'where path='.$this->DB->quote(strtolower($this->_dirname($_p))).' and fname='.$this->DB->quote(strtolower($this->_basename($_p))); |
585
|
|
|
$this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($praw)).' '.$pwhere); |
586
|
|
|
} |
587
|
|
|
} |
588
|
|
|
} |
589
|
|
|
|
590
|
|
|
$this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize(['cursor' => $cursor, 'mtime' => $_SERVER['REQUEST_TIME']])).' where path=\'\' and fname=\'\''); |
591
|
|
|
if (! $this->DB->commit()) { |
592
|
|
|
$e = $this->DB->errorInfo(); |
593
|
|
|
|
594
|
|
|
return $e[2]; |
595
|
|
|
} |
596
|
|
|
if ($delete) { |
597
|
|
|
$this->DB->exec('vacuum'); |
598
|
|
|
} |
599
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
600
|
|
|
return $e->getMessage(); |
601
|
|
|
} |
602
|
|
|
|
603
|
|
|
return true; |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
/** |
607
|
|
|
* Parse line from dropbox metadata output and return file stat (array). |
608
|
|
|
* |
609
|
|
|
* @param string $raw line from ftp_rawlist() output |
610
|
|
|
* @return array |
611
|
|
|
* @author Dmitry Levashov |
612
|
|
|
**/ |
613
|
|
|
protected function parseRaw($raw) |
|
|
|
|
614
|
|
|
{ |
615
|
|
|
$stat = []; |
616
|
|
|
|
617
|
|
|
$stat['rev'] = isset($raw['rev']) ? $raw['rev'] : 'root'; |
618
|
|
|
$stat['name'] = $this->_basename($raw['path']); |
619
|
|
|
$stat['mime'] = $raw['is_dir'] ? 'directory' : $raw['mime_type']; |
620
|
|
|
$stat['size'] = $stat['mime'] == 'directory' ? 0 : $raw['bytes']; |
621
|
|
|
$stat['ts'] = isset($raw['client_mtime']) ? strtotime($raw['client_mtime']) : |
622
|
|
|
(isset($raw['modified']) ? strtotime($raw['modified']) : $_SERVER['REQUEST_TIME']); |
623
|
|
|
$stat['dirs'] = 0; |
624
|
|
|
if ($raw['is_dir']) { |
625
|
|
|
$stat['dirs'] = (int) (bool) $this->query('select path from '.$this->DB_TableName.' where isdir=1 and path='.$this->DB->quote(strtolower($raw['path']))); |
626
|
|
|
} |
627
|
|
|
|
628
|
|
|
if (! empty($raw['url'])) { |
629
|
|
|
$stat['url'] = $raw['url']; |
630
|
|
|
} elseif (! $this->disabledGetUrl) { |
631
|
|
|
$stat['url'] = '1'; |
632
|
|
|
} |
633
|
|
|
if (isset($raw['width'])) { |
634
|
|
|
$stat['width'] = $raw['width']; |
635
|
|
|
} |
636
|
|
|
if (isset($raw['height'])) { |
637
|
|
|
$stat['height'] = $raw['height']; |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
return $stat; |
641
|
|
|
} |
642
|
|
|
|
643
|
|
|
/** |
644
|
|
|
* Cache dir contents. |
645
|
|
|
* |
646
|
|
|
* @param string $path dir path |
647
|
|
|
* @return string |
648
|
|
|
* @author Dmitry Levashov |
649
|
|
|
**/ |
650
|
|
|
protected function cacheDir($path) |
651
|
|
|
{ |
652
|
|
|
$this->dirsCache[$path] = []; |
653
|
|
|
$hasDir = false; |
654
|
|
|
|
655
|
|
|
$res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower($path))); |
656
|
|
|
|
657
|
|
|
if ($res) { |
658
|
|
|
foreach ($res as $raw) { |
|
|
|
|
659
|
|
|
$raw = unserialize($raw); |
660
|
|
View Code Duplication |
if ($stat = $this->parseRaw($raw)) { |
|
|
|
|
661
|
|
|
$stat = $this->updateCache($raw['path'], $stat); |
662
|
|
|
if (empty($stat['hidden']) && $path !== $raw['path']) { |
663
|
|
|
if (! $hasDir && $stat['mime'] === 'directory') { |
664
|
|
|
$hasDir = true; |
665
|
|
|
} |
666
|
|
|
$this->dirsCache[$path][] = $raw['path']; |
667
|
|
|
} |
668
|
|
|
} |
669
|
|
|
} |
670
|
|
|
} |
671
|
|
|
|
672
|
|
|
if (isset($this->sessionCache['subdirs'])) { |
673
|
|
|
$this->sessionCache['subdirs'][$path] = $hasDir; |
674
|
|
|
} |
675
|
|
|
|
676
|
|
|
return $this->dirsCache[$path]; |
677
|
|
|
} |
678
|
|
|
|
679
|
|
|
/** |
680
|
|
|
* Recursive files search. |
681
|
|
|
* |
682
|
|
|
* @param string $path dir path |
683
|
|
|
* @param string $q search string |
684
|
|
|
* @param array $mimes |
685
|
|
|
* @return array |
686
|
|
|
* @author Naoki Sawada |
687
|
|
|
**/ |
688
|
|
|
protected function doSearch($path, $q, $mimes) |
689
|
|
|
{ |
690
|
|
|
$result = []; |
691
|
|
|
$sth = $this->DB->prepare('select dat from '.$this->DB_TableName.' WHERE path LIKE ? AND fname LIKE ?'); |
692
|
|
|
$sth->execute([(($path === '/') ? '' : strtolower($path)).'%', '%'.strtolower($q).'%']); |
693
|
|
|
$res = $sth->fetchAll(PDO::FETCH_COLUMN); |
694
|
|
|
$timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0; |
695
|
|
|
|
696
|
|
|
if ($res) { |
697
|
|
|
foreach ($res as $raw) { |
698
|
|
View Code Duplication |
if ($timeout && $timeout < time()) { |
|
|
|
|
699
|
|
|
$this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path))); |
700
|
|
|
break; |
701
|
|
|
} |
702
|
|
|
|
703
|
|
|
$raw = unserialize($raw); |
704
|
|
|
if ($stat = $this->parseRaw($raw)) { |
705
|
|
|
if (! isset($this->cache[$raw['path']])) { |
706
|
|
|
$stat = $this->updateCache($raw['path'], $stat); |
707
|
|
|
} |
708
|
|
|
if (! empty($stat['hidden']) || ($mimes && $stat['mime'] === 'directory') || ! $this->mimeAccepted($stat['mime'], $mimes)) { |
|
|
|
|
709
|
|
|
continue; |
710
|
|
|
} |
711
|
|
|
$stat = $this->stat($raw['path']); |
712
|
|
|
$stat['path'] = $this->path($stat['hash']); |
713
|
|
|
$result[] = $stat; |
714
|
|
|
} |
715
|
|
|
} |
716
|
|
|
} |
717
|
|
|
|
718
|
|
|
return $result; |
719
|
|
|
} |
720
|
|
|
|
721
|
|
|
/** |
722
|
|
|
* Copy file/recursive copy dir only in current volume. |
723
|
|
|
* Return new file path or false. |
724
|
|
|
* |
725
|
|
|
* @param string $src source path |
726
|
|
|
* @param string $dst destination dir path |
727
|
|
|
* @param string $name new file name (optionaly) |
728
|
|
|
* @return string|false |
729
|
|
|
* @author Dmitry (dio) Levashov |
730
|
|
|
* @author Naoki Sawada |
731
|
|
|
**/ |
732
|
|
|
protected function copy($src, $dst, $name) |
733
|
|
|
{ |
734
|
|
|
$this->clearcache(); |
735
|
|
|
|
736
|
|
|
return $this->_copy($src, $dst, $name) |
737
|
|
|
? $this->_joinPath($dst, $name) |
738
|
|
|
: $this->setError(elFinder::ERROR_COPY, $this->_path($src)); |
739
|
|
|
} |
740
|
|
|
|
741
|
|
|
/** |
742
|
|
|
* Remove file/ recursive remove dir. |
743
|
|
|
* |
744
|
|
|
* @param string $path file path |
745
|
|
|
* @param bool $force try to remove even if file locked |
746
|
|
|
* @param bool $recursive |
747
|
|
|
* @return bool |
748
|
|
|
* @author Dmitry (dio) Levashov |
749
|
|
|
* @author Naoki Sawada |
750
|
|
|
*/ |
751
|
|
View Code Duplication |
protected function remove($path, $force = false, $recursive = false) |
|
|
|
|
752
|
|
|
{ |
753
|
|
|
$stat = $this->stat($path); |
754
|
|
|
$stat['realpath'] = $path; |
755
|
|
|
$this->rmTmb($stat); |
|
|
|
|
756
|
|
|
$this->clearcache(); |
757
|
|
|
|
758
|
|
|
if (empty($stat)) { |
759
|
|
|
return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND); |
760
|
|
|
} |
761
|
|
|
|
762
|
|
|
if (! $force && ! empty($stat['locked'])) { |
763
|
|
|
return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path)); |
764
|
|
|
} |
765
|
|
|
|
766
|
|
|
if ($stat['mime'] == 'directory') { |
767
|
|
|
if (! $recursive && ! $this->_rmdir($path)) { |
768
|
|
|
return $this->setError(elFinder::ERROR_RM, $this->_path($path)); |
769
|
|
|
} |
770
|
|
|
} else { |
771
|
|
|
if (! $recursive && ! $this->_unlink($path)) { |
772
|
|
|
return $this->setError(elFinder::ERROR_RM, $this->_path($path)); |
773
|
|
|
} |
774
|
|
|
} |
775
|
|
|
|
776
|
|
|
$this->removed[] = $stat; |
777
|
|
|
|
778
|
|
|
return true; |
779
|
|
|
} |
780
|
|
|
|
781
|
|
|
/** |
782
|
|
|
* Create thumnbnail and return it's URL on success. |
783
|
|
|
* |
784
|
|
|
* @param string $path file path |
785
|
|
|
* @param $stat |
786
|
|
|
* @return false|string |
787
|
|
|
* @internal param string $mime file mime type |
788
|
|
|
* @author Dmitry (dio) Levashov |
789
|
|
|
* @author Naoki Sawada |
790
|
|
|
*/ |
791
|
|
View Code Duplication |
protected function createTmb($path, $stat) |
|
|
|
|
792
|
|
|
{ |
793
|
|
|
if (! $stat || ! $this->canCreateTmb($path, $stat)) { |
794
|
|
|
return false; |
795
|
|
|
} |
796
|
|
|
|
797
|
|
|
$name = $this->tmbname($stat); |
798
|
|
|
$tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name; |
799
|
|
|
|
800
|
|
|
// copy image into tmbPath so some drivers does not store files on local fs |
801
|
|
|
if (! $data = $this->getThumbnail($path, $this->options['getTmbSize'])) { |
802
|
|
|
return false; |
803
|
|
|
} |
804
|
|
|
if (! file_put_contents($tmb, $data)) { |
805
|
|
|
return false; |
806
|
|
|
} |
807
|
|
|
|
808
|
|
|
$result = false; |
|
|
|
|
809
|
|
|
|
810
|
|
|
$tmbSize = $this->tmbSize; |
811
|
|
|
|
812
|
|
|
if (($s = getimagesize($tmb)) == false) { |
813
|
|
|
return false; |
814
|
|
|
} |
815
|
|
|
|
816
|
|
|
/* If image smaller or equal thumbnail size - just fitting to thumbnail square */ |
817
|
|
|
if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) { |
818
|
|
|
$result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png'); |
819
|
|
|
} else { |
820
|
|
|
if ($this->options['tmbCrop']) { |
821
|
|
|
|
822
|
|
|
/* Resize and crop if image bigger than thumbnail */ |
823
|
|
|
if (! (($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize)) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) { |
824
|
|
|
$result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png'); |
|
|
|
|
825
|
|
|
} |
826
|
|
|
|
827
|
|
|
if (($s = getimagesize($tmb)) != false) { |
828
|
|
|
$x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize) / 2) : 0; |
829
|
|
|
$y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize) / 2) : 0; |
830
|
|
|
$result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png'); |
|
|
|
|
831
|
|
|
} |
832
|
|
|
} else { |
833
|
|
|
$result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, 'png'); |
|
|
|
|
834
|
|
|
} |
835
|
|
|
|
836
|
|
|
$result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png'); |
837
|
|
|
} |
838
|
|
|
|
839
|
|
|
if (! $result) { |
|
|
|
|
840
|
|
|
unlink($tmb); |
841
|
|
|
|
842
|
|
|
return false; |
843
|
|
|
} |
844
|
|
|
|
845
|
|
|
return $name; |
846
|
|
|
} |
847
|
|
|
|
848
|
|
|
/** |
849
|
|
|
* Return thumbnail file name for required file. |
850
|
|
|
* |
851
|
|
|
* @param array $stat file stat |
852
|
|
|
* @return string |
853
|
|
|
* @author Dmitry (dio) Levashov |
854
|
|
|
**/ |
855
|
|
|
protected function tmbname($stat) |
856
|
|
|
{ |
857
|
|
|
return $this->tmbPrefix.$stat['rev'].'.png'; |
858
|
|
|
} |
859
|
|
|
|
860
|
|
|
/** |
861
|
|
|
* Get thumbnail from dropbox.com. |
862
|
|
|
* @param string $path |
863
|
|
|
* @param string $size |
864
|
|
|
* @return string | boolean |
865
|
|
|
*/ |
866
|
|
|
protected function getThumbnail($path, $size = 'small') |
867
|
|
|
{ |
868
|
|
|
try { |
869
|
|
|
return $this->dropbox->getThumbnail($path, $size); |
870
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
871
|
|
|
return false; |
872
|
|
|
} |
873
|
|
|
} |
874
|
|
|
|
875
|
|
|
/*********************** paths/urls *************************/ |
876
|
|
|
|
877
|
|
|
/** |
878
|
|
|
* Return parent directory path. |
879
|
|
|
* |
880
|
|
|
* @param string $path file path |
881
|
|
|
* @return string |
882
|
|
|
* @author Dmitry (dio) Levashov |
883
|
|
|
**/ |
884
|
|
|
protected function _dirname($path) |
885
|
|
|
{ |
886
|
|
|
return $this->_normpath(substr($path, 0, strrpos($path, '/'))); |
887
|
|
|
} |
888
|
|
|
|
889
|
|
|
/** |
890
|
|
|
* Return file name. |
891
|
|
|
* |
892
|
|
|
* @param string $path file path |
893
|
|
|
* @return string |
894
|
|
|
* @author Dmitry (dio) Levashov |
895
|
|
|
**/ |
896
|
|
|
protected function _basename($path) |
897
|
|
|
{ |
898
|
|
|
return substr($path, strrpos($path, '/') + 1); |
899
|
|
|
} |
900
|
|
|
|
901
|
|
|
/** |
902
|
|
|
* Join dir name and file name and retur full path. |
903
|
|
|
* |
904
|
|
|
* @param string $dir |
905
|
|
|
* @param string $name |
906
|
|
|
* @return string |
907
|
|
|
* @author Dmitry (dio) Levashov |
908
|
|
|
**/ |
909
|
|
|
protected function _joinPath($dir, $name) |
910
|
|
|
{ |
911
|
|
|
return $this->_normpath($dir.'/'.$name); |
912
|
|
|
} |
913
|
|
|
|
914
|
|
|
/** |
915
|
|
|
* Return normalized path, this works the same as os.path.normpath() in Python. |
916
|
|
|
* |
917
|
|
|
* @param string $path path |
918
|
|
|
* @return string |
919
|
|
|
* @author Troex Nevelin |
920
|
|
|
**/ |
921
|
|
|
protected function _normpath($path) |
922
|
|
|
{ |
923
|
|
|
$path = '/'.ltrim($path, '/'); |
924
|
|
|
|
925
|
|
|
return $path; |
926
|
|
|
} |
927
|
|
|
|
928
|
|
|
/** |
929
|
|
|
* Return file path related to root dir. |
930
|
|
|
* |
931
|
|
|
* @param string $path file path |
932
|
|
|
* @return string |
933
|
|
|
* @author Dmitry (dio) Levashov |
934
|
|
|
**/ |
935
|
|
|
protected function _relpath($path) |
936
|
|
|
{ |
937
|
|
|
return $path; |
938
|
|
|
} |
939
|
|
|
|
940
|
|
|
/** |
941
|
|
|
* Convert path related to root dir into real path. |
942
|
|
|
* |
943
|
|
|
* @param string $path file path |
944
|
|
|
* @return string |
945
|
|
|
* @author Dmitry (dio) Levashov |
946
|
|
|
**/ |
947
|
|
|
protected function _abspath($path) |
948
|
|
|
{ |
949
|
|
|
return $path; |
950
|
|
|
} |
951
|
|
|
|
952
|
|
|
/** |
953
|
|
|
* Return fake path started from root dir. |
954
|
|
|
* |
955
|
|
|
* @param string $path file path |
956
|
|
|
* @return string |
957
|
|
|
* @author Dmitry (dio) Levashov |
958
|
|
|
**/ |
959
|
|
|
protected function _path($path) |
960
|
|
|
{ |
961
|
|
|
return $this->rootName.$this->_normpath(substr($path, strlen($this->root))); |
962
|
|
|
} |
963
|
|
|
|
964
|
|
|
/** |
965
|
|
|
* Return true if $path is children of $parent. |
966
|
|
|
* |
967
|
|
|
* @param string $path path to check |
968
|
|
|
* @param string $parent parent path |
969
|
|
|
* @return bool |
970
|
|
|
* @author Dmitry (dio) Levashov |
971
|
|
|
**/ |
972
|
|
|
protected function _inpath($path, $parent) |
973
|
|
|
{ |
974
|
|
|
return $path == $parent || strpos($path, $parent.'/') === 0; |
975
|
|
|
} |
976
|
|
|
|
977
|
|
|
/***************** file stat ********************/ |
978
|
|
|
|
979
|
|
|
/** |
980
|
|
|
* Return stat for given path. |
981
|
|
|
* Stat contains following fields: |
982
|
|
|
* - (int) size file size in b. required |
983
|
|
|
* - (int) ts file modification time in unix time. required |
984
|
|
|
* - (string) mime mimetype. required for folders, others - optionally |
985
|
|
|
* - (bool) read read permissions. required |
986
|
|
|
* - (bool) write write permissions. required |
987
|
|
|
* - (bool) locked is object locked. optionally |
988
|
|
|
* - (bool) hidden is object hidden. optionally |
989
|
|
|
* - (string) alias for symlinks - link target path relative to root path. optionally |
990
|
|
|
* - (string) target for symlinks - link target path. optionally. |
991
|
|
|
* |
992
|
|
|
* If file does not exists - returns empty array or false. |
993
|
|
|
* |
994
|
|
|
* @param string $path file path |
995
|
|
|
* @return array|false |
996
|
|
|
* @author Dmitry (dio) Levashov |
997
|
|
|
**/ |
998
|
|
|
protected function _stat($path) |
999
|
|
|
{ |
1000
|
|
|
//if (!empty($this->ARGS['reload']) && isset($this->ARGS['target']) && strpos($this->ARGS['target'], $this->id) === 0) { |
|
|
|
|
1001
|
|
|
if ($this->isMyReload()) { |
1002
|
|
|
$this->deltaCheck(); |
1003
|
|
|
} |
1004
|
|
|
if ($raw = $this->getDBdat($path)) { |
1005
|
|
|
return $this->parseRaw($raw); |
|
|
|
|
1006
|
|
|
} |
1007
|
|
|
|
1008
|
|
|
return false; |
1009
|
|
|
} |
1010
|
|
|
|
1011
|
|
|
/** |
1012
|
|
|
* Return true if path is dir and has at least one childs directory. |
1013
|
|
|
* |
1014
|
|
|
* @param string $path dir path |
1015
|
|
|
* @return bool |
1016
|
|
|
* @author Dmitry (dio) Levashov |
1017
|
|
|
**/ |
1018
|
|
|
protected function _subdirs($path) |
1019
|
|
|
{ |
1020
|
|
|
return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false; |
1021
|
|
|
} |
1022
|
|
|
|
1023
|
|
|
/** |
1024
|
|
|
* Return object width and height |
1025
|
|
|
* Ususaly used for images, but can be realize for video etc... |
1026
|
|
|
* |
1027
|
|
|
* @param string $path file path |
1028
|
|
|
* @param string $mime file mime type |
1029
|
|
|
* @return string |
1030
|
|
|
* @author Dmitry (dio) Levashov |
1031
|
|
|
**/ |
1032
|
|
|
protected function _dimensions($path, $mime) |
1033
|
|
|
{ |
1034
|
|
|
if (strpos($mime, 'image') !== 0) { |
1035
|
|
|
return ''; |
1036
|
|
|
} |
1037
|
|
|
$cache = $this->getDBdat($path); |
1038
|
|
View Code Duplication |
if (isset($cache['width']) && isset($cache['height'])) { |
|
|
|
|
1039
|
|
|
return $cache['width'].'x'.$cache['height']; |
1040
|
|
|
} |
1041
|
|
|
$ret = ''; |
1042
|
|
|
if ($work = $this->getWorkFile($path)) { |
1043
|
|
View Code Duplication |
if ($size = getimagesize($work)) { |
|
|
|
|
1044
|
|
|
$cache['width'] = $size[0]; |
1045
|
|
|
$cache['height'] = $size[1]; |
1046
|
|
|
$this->updateDBdat($path, $cache); |
1047
|
|
|
$ret = $size[0].'x'.$size[1]; |
1048
|
|
|
} |
1049
|
|
|
} |
1050
|
|
|
is_file($work) && unlink($work); |
1051
|
|
|
|
1052
|
|
|
return $ret; |
1053
|
|
|
} |
1054
|
|
|
|
1055
|
|
|
/******************** file/dir content *********************/ |
1056
|
|
|
|
1057
|
|
|
/** |
1058
|
|
|
* Return files list in directory. |
1059
|
|
|
* |
1060
|
|
|
* @param string $path dir path |
1061
|
|
|
* @return array |
1062
|
|
|
* @author Dmitry (dio) Levashov |
1063
|
|
|
* @author Cem (DiscoFever) |
1064
|
|
|
**/ |
1065
|
|
|
protected function _scandir($path) |
1066
|
|
|
{ |
1067
|
|
|
return isset($this->dirsCache[$path]) |
1068
|
|
|
? $this->dirsCache[$path] |
1069
|
|
|
: $this->cacheDir($path); |
1070
|
|
|
} |
1071
|
|
|
|
1072
|
|
|
/** |
1073
|
|
|
* Open file and return file pointer. |
1074
|
|
|
* |
1075
|
|
|
* @param string $path file path |
1076
|
|
|
* @param string $mode |
1077
|
|
|
* @return false|resource |
1078
|
|
|
* @internal param bool $write open file for writing |
1079
|
|
|
* @author Dmitry (dio) Levashov |
1080
|
|
|
*/ |
1081
|
|
|
protected function _fopen($path, $mode = 'rb') |
1082
|
|
|
{ |
1083
|
|
|
if (($mode == 'rb' || $mode == 'r')) { |
1084
|
|
|
try { |
1085
|
|
|
$res = $this->dropbox->media($path); |
1086
|
|
|
$url = parse_url($res['url']); |
1087
|
|
|
$fp = stream_socket_client('ssl://'.$url['host'].':443'); |
1088
|
|
|
fwrite($fp, "GET {$url['path']} HTTP/1.0\r\n"); |
1089
|
|
|
fwrite($fp, "Host: {$url['host']}\r\n"); |
1090
|
|
|
fwrite($fp, "\r\n"); |
1091
|
|
|
while (trim(fgets($fp)) !== '') { |
|
|
|
|
1092
|
|
|
} |
1093
|
|
|
|
1094
|
|
|
return $fp; |
1095
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
1096
|
|
|
return false; |
1097
|
|
|
} |
1098
|
|
|
} |
1099
|
|
|
|
1100
|
|
|
if ($this->tmp) { |
1101
|
|
|
$contents = $this->_getContents($path); |
1102
|
|
|
|
1103
|
|
|
if ($contents === false) { |
1104
|
|
|
return false; |
1105
|
|
|
} |
1106
|
|
|
|
1107
|
|
|
if ($local = $this->getTempFile($path)) { |
1108
|
|
|
if (file_put_contents($local, $contents, LOCK_EX) !== false) { |
1109
|
|
|
return fopen($local, $mode); |
1110
|
|
|
} |
1111
|
|
|
} |
1112
|
|
|
} |
1113
|
|
|
|
1114
|
|
|
return false; |
1115
|
|
|
} |
1116
|
|
|
|
1117
|
|
|
/** |
1118
|
|
|
* Close opened file. |
1119
|
|
|
* |
1120
|
|
|
* @param resource $fp file pointer |
1121
|
|
|
* @param string $path |
1122
|
|
|
* @return bool |
1123
|
|
|
* @author Dmitry (dio) Levashov |
1124
|
|
|
*/ |
1125
|
|
|
protected function _fclose($fp, $path = '') |
1126
|
|
|
{ |
1127
|
|
|
fclose($fp); |
1128
|
|
|
if ($path) { |
1129
|
|
|
unlink($this->getTempFile($path)); |
1130
|
|
|
} |
1131
|
|
|
} |
1132
|
|
|
|
1133
|
|
|
/******************** file/dir manipulations *************************/ |
1134
|
|
|
|
1135
|
|
|
/** |
1136
|
|
|
* Create dir and return created dir path or false on failed. |
1137
|
|
|
* |
1138
|
|
|
* @param string $path parent dir path |
1139
|
|
|
* @param string $name new directory name |
1140
|
|
|
* @return string|bool |
1141
|
|
|
* @author Dmitry (dio) Levashov |
1142
|
|
|
**/ |
1143
|
|
|
protected function _mkdir($path, $name) |
1144
|
|
|
{ |
1145
|
|
|
$path = $this->_normpath($path.'/'.$name); |
1146
|
|
|
try { |
1147
|
|
|
$this->dropbox->createFolder($path); |
1148
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
1149
|
|
|
$this->deltaCheck(); |
1150
|
|
|
if ($this->dir($this->encode($path))) { |
1151
|
|
|
return $path; |
1152
|
|
|
} |
1153
|
|
|
|
1154
|
|
|
return $this->setError('Dropbox error: '.$e->getMessage()); |
1155
|
|
|
} |
1156
|
|
|
$this->deltaCheck(); |
1157
|
|
|
|
1158
|
|
|
return $path; |
1159
|
|
|
} |
1160
|
|
|
|
1161
|
|
|
/** |
1162
|
|
|
* Create file and return it's path or false on failed. |
1163
|
|
|
* |
1164
|
|
|
* @param string $path parent dir path |
1165
|
|
|
* @param string $name new file name |
1166
|
|
|
* @return string|bool |
1167
|
|
|
* @author Dmitry (dio) Levashov |
1168
|
|
|
**/ |
1169
|
|
|
protected function _mkfile($path, $name) |
1170
|
|
|
{ |
1171
|
|
|
return $this->_filePutContents($path.'/'.$name, ''); |
1172
|
|
|
} |
1173
|
|
|
|
1174
|
|
|
/** |
1175
|
|
|
* Create symlink. FTP driver does not support symlinks. |
1176
|
|
|
* |
1177
|
|
|
* @param string $target link target |
1178
|
|
|
* @param string $path symlink path |
1179
|
|
|
* @param string $name |
1180
|
|
|
* @return bool |
1181
|
|
|
* @author Dmitry (dio) Levashov |
1182
|
|
|
*/ |
1183
|
|
|
protected function _symlink($target, $path, $name) |
1184
|
|
|
{ |
1185
|
|
|
return false; |
1186
|
|
|
} |
1187
|
|
|
|
1188
|
|
|
/** |
1189
|
|
|
* Copy file into another file. |
1190
|
|
|
* |
1191
|
|
|
* @param string $source source file path |
1192
|
|
|
* @param string $targetDir target directory path |
1193
|
|
|
* @param string $name new file name |
1194
|
|
|
* @return bool |
1195
|
|
|
* @author Dmitry (dio) Levashov |
1196
|
|
|
**/ |
1197
|
|
View Code Duplication |
protected function _copy($source, $targetDir, $name) |
|
|
|
|
1198
|
|
|
{ |
1199
|
|
|
$path = $this->_normpath($targetDir.'/'.$name); |
1200
|
|
|
try { |
1201
|
|
|
$this->dropbox->copy($source, $path); |
1202
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
1203
|
|
|
return $this->setError('Dropbox error: '.$e->getMessage()); |
1204
|
|
|
} |
1205
|
|
|
$this->deltaCheck(); |
1206
|
|
|
|
1207
|
|
|
return true; |
1208
|
|
|
} |
1209
|
|
|
|
1210
|
|
|
/** |
1211
|
|
|
* Move file into another parent dir. |
1212
|
|
|
* Return new file path or false. |
1213
|
|
|
* |
1214
|
|
|
* @param string $source source file path |
1215
|
|
|
* @param $targetDir |
1216
|
|
|
* @param string $name file name |
1217
|
|
|
* @return bool|string |
1218
|
|
|
* @internal param string $target target dir path |
1219
|
|
|
* @author Dmitry (dio) Levashov |
1220
|
|
|
*/ |
1221
|
|
View Code Duplication |
protected function _move($source, $targetDir, $name) |
|
|
|
|
1222
|
|
|
{ |
1223
|
|
|
$target = $this->_normpath($targetDir.'/'.$name); |
1224
|
|
|
try { |
1225
|
|
|
$this->dropbox->move($source, $target); |
1226
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
1227
|
|
|
return $this->setError('Dropbox error: '.$e->getMessage()); |
1228
|
|
|
} |
1229
|
|
|
$this->deltaCheck(); |
1230
|
|
|
|
1231
|
|
|
return $target; |
1232
|
|
|
} |
1233
|
|
|
|
1234
|
|
|
/** |
1235
|
|
|
* Remove file. |
1236
|
|
|
* |
1237
|
|
|
* @param string $path file path |
1238
|
|
|
* @return bool |
1239
|
|
|
* @author Dmitry (dio) Levashov |
1240
|
|
|
**/ |
1241
|
|
|
protected function _unlink($path) |
1242
|
|
|
{ |
1243
|
|
|
try { |
1244
|
|
|
$this->dropbox->delete($path); |
1245
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
1246
|
|
|
return $this->setError('Dropbox error: '.$e->getMessage()); |
1247
|
|
|
} |
1248
|
|
|
$this->deltaCheck(); |
1249
|
|
|
|
1250
|
|
|
return true; |
1251
|
|
|
} |
1252
|
|
|
|
1253
|
|
|
/** |
1254
|
|
|
* Remove dir. |
1255
|
|
|
* |
1256
|
|
|
* @param string $path dir path |
1257
|
|
|
* @return bool |
1258
|
|
|
* @author Dmitry (dio) Levashov |
1259
|
|
|
**/ |
1260
|
|
|
protected function _rmdir($path) |
1261
|
|
|
{ |
1262
|
|
|
return $this->_unlink($path); |
1263
|
|
|
} |
1264
|
|
|
|
1265
|
|
|
/** |
1266
|
|
|
* Create new file and write into it from file pointer. |
1267
|
|
|
* Return new file path or false on error. |
1268
|
|
|
* |
1269
|
|
|
* @param resource $fp file pointer |
1270
|
|
|
* @param string $path |
1271
|
|
|
* @param string $name file name |
1272
|
|
|
* @param array $stat file stat (required by some virtual fs) |
1273
|
|
|
* @return bool|string |
1274
|
|
|
* @internal param string $dir target dir path |
1275
|
|
|
* @author Dmitry (dio) Levashov |
1276
|
|
|
*/ |
1277
|
|
|
protected function _save($fp, $path, $name, $stat) |
1278
|
|
|
{ |
1279
|
|
|
if ($name) { |
1280
|
|
|
$path .= '/'.$name; |
1281
|
|
|
} |
1282
|
|
|
$path = $this->_normpath($path); |
1283
|
|
|
try { |
1284
|
|
|
$this->dropbox->putFile($path, $fp); |
1285
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
1286
|
|
|
return $this->setError('Dropbox error: '.$e->getMessage()); |
1287
|
|
|
} |
1288
|
|
|
$this->deltaCheck(); |
1289
|
|
|
if (is_array($stat)) { |
1290
|
|
|
$raw = $this->getDBdat($path); |
1291
|
|
|
if (isset($stat['width'])) { |
1292
|
|
|
$raw['width'] = $stat['width']; |
1293
|
|
|
} |
1294
|
|
|
if (isset($stat['height'])) { |
1295
|
|
|
$raw['height'] = $stat['height']; |
1296
|
|
|
} |
1297
|
|
|
$this->updateDBdat($path, $raw); |
1298
|
|
|
} |
1299
|
|
|
|
1300
|
|
|
return $path; |
1301
|
|
|
} |
1302
|
|
|
|
1303
|
|
|
/** |
1304
|
|
|
* Get file contents. |
1305
|
|
|
* |
1306
|
|
|
* @param string $path file path |
1307
|
|
|
* @return string|false |
1308
|
|
|
* @author Dmitry (dio) Levashov |
1309
|
|
|
**/ |
1310
|
|
|
protected function _getContents($path) |
1311
|
|
|
{ |
1312
|
|
|
$contents = ''; |
1313
|
|
|
try { |
1314
|
|
|
$contents = $this->dropbox->getFile($path); |
1315
|
|
|
} catch (Dropbox_Exception $e) { |
|
|
|
|
1316
|
|
|
return $this->setError('Dropbox error: '.$e->getMessage()); |
1317
|
|
|
} |
1318
|
|
|
|
1319
|
|
|
return $contents; |
1320
|
|
|
} |
1321
|
|
|
|
1322
|
|
|
/** |
1323
|
|
|
* Write a string to a file. |
1324
|
|
|
* |
1325
|
|
|
* @param string $path file path |
1326
|
|
|
* @param string $content new file content |
1327
|
|
|
* @return bool |
1328
|
|
|
* @author Dmitry (dio) Levashov |
1329
|
|
|
**/ |
1330
|
|
View Code Duplication |
protected function _filePutContents($path, $content) |
|
|
|
|
1331
|
|
|
{ |
1332
|
|
|
$res = false; |
1333
|
|
|
|
1334
|
|
|
if ($local = $this->getTempFile($path)) { |
1335
|
|
|
if (file_put_contents($local, $content, LOCK_EX) !== false |
1336
|
|
|
&& ($fp = fopen($local, 'rb'))) { |
1337
|
|
|
clearstatcache(); |
1338
|
|
|
$res = $this->_save($fp, $path, '', []); |
1339
|
|
|
fclose($fp); |
1340
|
|
|
} |
1341
|
|
|
file_exists($local) && unlink($local); |
1342
|
|
|
} |
1343
|
|
|
|
1344
|
|
|
return $res; |
1345
|
|
|
} |
1346
|
|
|
|
1347
|
|
|
/** |
1348
|
|
|
* Detect available archivers. |
1349
|
|
|
* |
1350
|
|
|
* @return array |
1351
|
|
|
**/ |
1352
|
|
|
protected function _checkArchivers() |
1353
|
|
|
{ |
1354
|
|
|
// die('Not yet implemented. (_checkArchivers)'); |
|
|
|
|
1355
|
|
|
return []; |
1356
|
|
|
} |
1357
|
|
|
|
1358
|
|
|
/** |
1359
|
|
|
* chmod implementation. |
1360
|
|
|
* |
1361
|
|
|
* @param string $path |
1362
|
|
|
* @param string $mode |
1363
|
|
|
* @return bool |
1364
|
|
|
*/ |
1365
|
|
|
protected function _chmod($path, $mode) |
1366
|
|
|
{ |
1367
|
|
|
return false; |
1368
|
|
|
} |
1369
|
|
|
|
1370
|
|
|
/** |
1371
|
|
|
* Unpack archive. |
1372
|
|
|
* |
1373
|
|
|
* @param string $path archive path |
1374
|
|
|
* @param array $arc archiver command and arguments (same as in $this->archivers) |
1375
|
|
|
* @return true |
1376
|
|
|
* @return void |
1377
|
|
|
* @author Dmitry (dio) Levashov |
1378
|
|
|
* @author Alexey Sukhotin |
1379
|
|
|
**/ |
1380
|
|
|
protected function _unpack($path, $arc) |
|
|
|
|
1381
|
|
|
{ |
1382
|
|
|
die('Not yet implemented. (_unpack)'); |
|
|
|
|
1383
|
|
|
} |
1384
|
|
|
|
1385
|
|
|
/** |
1386
|
|
|
* Recursive symlinks search. |
1387
|
|
|
* |
1388
|
|
|
* @param string $path file/dir path |
1389
|
|
|
* @return bool |
1390
|
|
|
* @author Dmitry (dio) Levashov |
1391
|
|
|
**/ |
1392
|
|
|
protected function _findSymlinks($path) |
|
|
|
|
1393
|
|
|
{ |
1394
|
|
|
die('Not yet implemented. (_findSymlinks)'); |
|
|
|
|
1395
|
|
|
} |
1396
|
|
|
|
1397
|
|
|
/** |
1398
|
|
|
* Extract files from archive. |
1399
|
|
|
* |
1400
|
|
|
* @param string $path archive path |
1401
|
|
|
* @param array $arc archiver command and arguments (same as in $this->archivers) |
1402
|
|
|
* @return true |
1403
|
|
|
* @author Dmitry (dio) Levashov, |
1404
|
|
|
* @author Alexey Sukhotin |
1405
|
|
|
**/ |
1406
|
|
|
protected function _extract($path, $arc) |
1407
|
|
|
{ |
1408
|
|
|
die('Not yet implemented. (_extract)'); |
|
|
|
|
1409
|
|
|
} |
1410
|
|
|
|
1411
|
|
|
/** |
1412
|
|
|
* Create archive and return its path. |
1413
|
|
|
* |
1414
|
|
|
* @param string $dir target dir |
1415
|
|
|
* @param array $files files names list |
1416
|
|
|
* @param string $name archive name |
1417
|
|
|
* @param array $arc archiver options |
1418
|
|
|
* @return string|bool |
1419
|
|
|
* @author Dmitry (dio) Levashov, |
1420
|
|
|
* @author Alexey Sukhotin |
1421
|
|
|
**/ |
1422
|
|
|
protected function _archive($dir, $files, $name, $arc) |
1423
|
|
|
{ |
1424
|
|
|
die('Not yet implemented. (_archive)'); |
|
|
|
|
1425
|
|
|
} |
1426
|
|
|
|
1427
|
|
|
/** |
1428
|
|
|
* Check DB for delta cache. |
1429
|
|
|
* |
1430
|
|
|
* @return bool |
1431
|
|
|
*/ |
1432
|
|
|
private function checkDB() |
|
|
|
|
1433
|
|
|
{ |
1434
|
|
|
$res = $this->query('SELECT * FROM sqlite_master WHERE type=\'table\' AND name=\''.$this->DB_TableName.'\''); |
1435
|
|
|
if ($res && isset($_REQUEST['init'])) { |
1436
|
|
|
// check is index(nameidx) UNIQUE? |
1437
|
|
|
$chk = $this->query('SELECT sql FROM sqlite_master WHERE type=\'index\' and name=\'nameidx\''); |
1438
|
|
|
if (! $chk || strpos(strtoupper($chk[0]), 'UNIQUE') === false) { |
1439
|
|
|
// remake |
1440
|
|
|
$this->DB->exec('DROP TABLE '.$this->DB_TableName); |
1441
|
|
|
$res = false; |
1442
|
|
|
} |
1443
|
|
|
} |
1444
|
|
|
if (! $res) { |
1445
|
|
|
try { |
1446
|
|
|
$this->DB->exec('CREATE TABLE '.$this->DB_TableName.'(path text, fname text, dat blob, isdir integer);'); |
1447
|
|
|
$this->DB->exec('CREATE UNIQUE INDEX nameidx ON '.$this->DB_TableName.'(path, fname)'); |
1448
|
|
|
$this->DB->exec('CREATE INDEX isdiridx ON '.$this->DB_TableName.'(isdir)'); |
1449
|
|
|
} catch (PDOException $e) { |
1450
|
|
|
return $this->setError($e->getMessage()); |
1451
|
|
|
} |
1452
|
|
|
} |
1453
|
|
|
|
1454
|
|
|
return true; |
1455
|
|
|
} |
1456
|
|
|
|
1457
|
|
|
/** |
1458
|
|
|
* DB query and fetchAll. |
1459
|
|
|
* |
1460
|
|
|
* @param string $sql |
1461
|
|
|
* @return bool|array |
1462
|
|
|
*/ |
1463
|
|
|
private function query($sql) |
1464
|
|
|
{ |
1465
|
|
|
if ($sth = $this->DB->query($sql)) { |
1466
|
|
|
$res = $sth->fetchAll(PDO::FETCH_COLUMN); |
1467
|
|
|
} else { |
1468
|
|
|
$res = false; |
1469
|
|
|
} |
1470
|
|
|
|
1471
|
|
|
return $res; |
1472
|
|
|
} |
1473
|
|
|
|
1474
|
|
|
/** |
1475
|
|
|
* Get dat(dropbox metadata) from DB. |
1476
|
|
|
* |
1477
|
|
|
* @param string $path |
1478
|
|
|
* @return array dropbox metadata |
1479
|
|
|
*/ |
1480
|
|
|
private function getDBdat($path) |
1481
|
|
|
{ |
1482
|
|
|
if ($res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower($this->_dirname($path))).' and fname='.$this->DB->quote(strtolower($this->_basename($path))).' limit 1')) { |
1483
|
|
|
return unserialize($res[0]); |
1484
|
|
|
} else { |
1485
|
|
|
return []; |
1486
|
|
|
} |
1487
|
|
|
} |
1488
|
|
|
|
1489
|
|
|
/** |
1490
|
|
|
* Update DB dat(dropbox metadata). |
1491
|
|
|
* |
1492
|
|
|
* @param string $path |
1493
|
|
|
* @param array $dat |
1494
|
|
|
* @return bool|array |
1495
|
|
|
*/ |
1496
|
|
|
private function updateDBdat($path, $dat) |
1497
|
|
|
{ |
1498
|
|
|
return $this->query('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($dat)) |
1499
|
|
|
.', isdir='.($dat['is_dir'] ? 1 : 0) |
1500
|
|
|
.' where path='.$this->DB->quote(strtolower($this->_dirname($path))).' and fname='.$this->DB->quote(strtolower($this->_basename($path)))); |
1501
|
|
|
} |
1502
|
|
|
|
1503
|
|
|
/** |
1504
|
|
|
* Get HTTP request response header string. |
1505
|
|
|
* |
1506
|
|
|
* @param string $url target URL |
1507
|
|
|
* @return string |
1508
|
|
|
* @author Naoki Sawada |
1509
|
|
|
*/ |
1510
|
|
|
private function getHttpResponseHeader($url) |
1511
|
|
|
{ |
1512
|
|
|
if (function_exists('curl_exec')) { |
1513
|
|
|
$c = curl_init(); |
1514
|
|
|
curl_setopt($c, CURLOPT_RETURNTRANSFER, true); |
1515
|
|
|
curl_setopt($c, CURLOPT_CUSTOMREQUEST, 'HEAD'); |
1516
|
|
|
curl_setopt($c, CURLOPT_HEADER, 1); |
1517
|
|
|
curl_setopt($c, CURLOPT_NOBODY, true); |
1518
|
|
|
curl_setopt($c, CURLOPT_URL, $url); |
1519
|
|
|
$res = curl_exec($c); |
1520
|
|
|
} else { |
1521
|
|
|
require_once 'HTTP/Request2.php'; |
1522
|
|
|
try { |
1523
|
|
|
$request2 = new HTTP_Request2(); |
1524
|
|
|
$request2->setConfig([ |
1525
|
|
|
'ssl_verify_peer' => false, |
1526
|
|
|
'ssl_verify_host' => false, |
1527
|
|
|
]); |
1528
|
|
|
$request2->setUrl($url); |
1529
|
|
|
$request2->setMethod(HTTP_Request2::METHOD_HEAD); |
1530
|
|
|
$result = $request2->send(); |
1531
|
|
|
$res = []; |
1532
|
|
|
$res[] = 'HTTP/'.$result->getVersion().' '.$result->getStatus().' '.$result->getReasonPhrase(); |
1533
|
|
|
foreach ($result->getHeader() as $key => $val) { |
1534
|
|
|
$res[] = $key.': '.$val; |
1535
|
|
|
} |
1536
|
|
|
$res = implode("\r\n", $res); |
1537
|
|
|
} catch (HTTP_Request2_Exception $e) { |
|
|
|
|
1538
|
|
|
$res = ''; |
1539
|
|
|
} catch (Exception $e) { |
1540
|
|
|
$res = ''; |
1541
|
|
|
} |
1542
|
|
|
} |
1543
|
|
|
|
1544
|
|
|
return $res; |
1545
|
|
|
} |
1546
|
|
|
} // END class |
1547
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.