drg_elfinder 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +8 -0
- data/app/assets/config/drg_elfinder_manifest.js +1 -0
- data/app/assets/javascripts/drg_elfinder.js +15 -0
- data/app/assets/javascripts/elfinder/Changelog +1283 -0
- data/app/assets/javascripts/elfinder/LICENSE.md +15 -0
- data/app/assets/javascripts/elfinder/README.md +216 -0
- data/app/assets/javascripts/elfinder/bower.json +28 -0
- data/app/assets/javascripts/elfinder/composer.json +39 -0
- data/app/assets/javascripts/elfinder/css/elfinder.full.css +5350 -0
- data/app/assets/javascripts/elfinder/css/elfinder.min.css +9 -0
- data/app/assets/javascripts/elfinder/css/theme.css +430 -0
- data/app/assets/javascripts/elfinder/elfinder.html +74 -0
- data/app/assets/javascripts/elfinder/elfinder.legacy.html +94 -0
- data/app/assets/javascripts/elfinder/img/arrows-active.png +0 -0
- data/app/assets/javascripts/elfinder/img/arrows-normal.png +0 -0
- data/app/assets/javascripts/elfinder/img/crop.gif +0 -0
- data/app/assets/javascripts/elfinder/img/dialogs.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_aceeditor.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_ckeditor.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_ckeditor5.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_codemirror.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_creativecloud.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_onlineconvert.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_pixlreditor.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_pixlrexpress.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_simplemde.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_tinymce.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_tuiimgedit.png +0 -0
- data/app/assets/javascripts/elfinder/img/edit_zohooffice.png +0 -0
- data/app/assets/javascripts/elfinder/img/editor-icons.png +0 -0
- data/app/assets/javascripts/elfinder/img/icons-big.png +0 -0
- data/app/assets/javascripts/elfinder/img/icons-big.svg +1 -0
- data/app/assets/javascripts/elfinder/img/icons-small.png +0 -0
- data/app/assets/javascripts/elfinder/img/logo.png +0 -0
- data/app/assets/javascripts/elfinder/img/progress.gif +0 -0
- data/app/assets/javascripts/elfinder/img/quicklook-bg.png +0 -0
- data/app/assets/javascripts/elfinder/img/quicklook-icons.png +0 -0
- data/app/assets/javascripts/elfinder/img/resize.png +0 -0
- data/app/assets/javascripts/elfinder/img/spinner-mini.gif +0 -0
- data/app/assets/javascripts/elfinder/img/toolbar.png +0 -0
- data/app/assets/javascripts/elfinder/img/trashmesh.png +0 -0
- data/app/assets/javascripts/elfinder/img/tui-icon-a.svg +235 -0
- data/app/assets/javascripts/elfinder/img/tui-icon-b.svg +224 -0
- data/app/assets/javascripts/elfinder/img/tui-icon-c.svg +224 -0
- data/app/assets/javascripts/elfinder/img/tui-icon-d.svg +224 -0
- data/app/assets/javascripts/elfinder/img/ui-icons_ffffff_256x240.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_box.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_box.svg +1 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_dropbox.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_dropbox.svg +1 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_ftp.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_ftp.svg +1 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_googledrive.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_googledrive.svg +1 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_local.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_local.svg +1 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_network.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_network.svg +1 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_onedrive.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_onedrive.svg +1 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_sql.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_sql.svg +1 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_trash.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_trash.svg +1 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_zip.png +0 -0
- data/app/assets/javascripts/elfinder/img/volume_icon_zip.svg +1 -0
- data/app/assets/javascripts/elfinder/js/elfinder.full.js +36019 -0
- data/app/assets/javascripts/elfinder/js/elfinder.min.js +25 -0
- data/app/assets/javascripts/elfinder/js/extras/editors.default.js +2643 -0
- data/app/assets/javascripts/elfinder/js/extras/editors.default.min.js +2 -0
- data/app/assets/javascripts/elfinder/js/extras/quicklook.googledocs.js +75 -0
- data/app/assets/javascripts/elfinder/js/extras/quicklook.googledocs.min.js +1 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.LANG.js +587 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.ar.js +580 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.bg.js +559 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.ca.js +375 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.cs.js +581 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.da.js +580 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.de.js +582 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.el.js +374 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.es.js +546 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.fa.js +580 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.fallback.js +11 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.fo.js +419 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.fr.js +578 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.fr_CA.js +580 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.he.js +375 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.hr.js +434 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.hu.js +580 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.id.js +498 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.it.js +552 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.ja.js +581 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.ko.js +582 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.nl.js +581 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.no.js +374 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.pl.js +580 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.pt_BR.js +580 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.ro.js +417 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.ru.js +582 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.si.js +537 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.sk.js +581 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.sl.js +374 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.sr.js +374 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.sv.js +375 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.tr.js +583 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.ug_CN.js +374 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.uk.js +580 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.vi.js +579 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.zh_CN.js +585 -0
- data/app/assets/javascripts/elfinder/js/i18n/elfinder.zh_TW.js +582 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/cs.html.js +10 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/de.html.js +15 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/en.html.js +10 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/es.html.js +10 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/ja.html.js +10 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/ko.html.js +10 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/pl.html.js +10 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/ru.html.js +10 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/sk.html.js +10 -0
- data/app/assets/javascripts/elfinder/js/i18n/help/tr.html.js +10 -0
- data/app/assets/javascripts/elfinder/js/proxy/elFinderSupportVer1.js +408 -0
- data/app/assets/javascripts/elfinder/js/worker/calcfilehash.js +20 -0
- data/app/assets/javascripts/elfinder/js/worker/quicklook.tiff.js +7 -0
- data/app/assets/javascripts/elfinder/js/worker/quicklook.unzip.js +55 -0
- data/app/assets/javascripts/elfinder/main.default.js +175 -0
- data/app/assets/javascripts/elfinder/package.json +13 -0
- data/app/assets/javascripts/elfinder/php/MySQLStorage.sql +47 -0
- data/app/assets/javascripts/elfinder/php/autoload.php +56 -0
- data/app/assets/javascripts/elfinder/php/connector.maximal.php-dist +449 -0
- data/app/assets/javascripts/elfinder/php/connector.minimal.php-dist +180 -0
- data/app/assets/javascripts/elfinder/php/editors/OnlineConvert/editor.php +113 -0
- data/app/assets/javascripts/elfinder/php/editors/ZipArchive/editor.php +12 -0
- data/app/assets/javascripts/elfinder/php/editors/ZohoOffice/editor.php +206 -0
- data/app/assets/javascripts/elfinder/php/editors/editor.php +79 -0
- data/app/assets/javascripts/elfinder/php/elFinder.class.php +5401 -0
- data/app/assets/javascripts/elfinder/php/elFinderConnector.class.php +380 -0
- data/app/assets/javascripts/elfinder/php/elFinderFlysystemGoogleDriveNetmount.php +380 -0
- data/app/assets/javascripts/elfinder/php/elFinderPlugin.php +113 -0
- data/app/assets/javascripts/elfinder/php/elFinderSession.php +335 -0
- data/app/assets/javascripts/elfinder/php/elFinderSessionInterface.php +57 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeBox.class.php +1972 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeDriver.class.php +7651 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeDropbox.class.php +1464 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeDropbox2.class.php +1516 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeFTP.class.php +1810 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeGoogleDrive.class.php +2163 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeGroup.class.php +315 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeLocalFileSystem.class.php +1477 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeMySQL.class.php +1022 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeOneDrive.class.php +2131 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeSFTPphpseclib.class.php +838 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeTrash.class.php +51 -0
- data/app/assets/javascripts/elfinder/php/elFinderVolumeTrashMySQL.class.php +51 -0
- data/app/assets/javascripts/elfinder/php/libs/GdBmp.php +473 -0
- data/app/assets/javascripts/elfinder/php/mime.types +781 -0
- data/app/assets/javascripts/elfinder/php/plugins/AutoResize/plugin.php +151 -0
- data/app/assets/javascripts/elfinder/php/plugins/AutoRotate/plugin.php +148 -0
- data/app/assets/javascripts/elfinder/php/plugins/Normalizer/plugin.php +204 -0
- data/app/assets/javascripts/elfinder/php/plugins/Sanitizer/plugin.php +157 -0
- data/app/assets/javascripts/elfinder/php/plugins/Watermark/logo.png +0 -0
- data/app/assets/javascripts/elfinder/php/plugins/Watermark/plugin.php +432 -0
- data/app/assets/javascripts/elfinder/php/plugins/WinRemoveTailDots/plugin.php +114 -0
- data/app/assets/javascripts/elfinder/php/resources/image.png +0 -0
- data/app/assets/javascripts/elfinder/php/resources/video.png +0 -0
- data/app/assets/javascripts/elfinder/sounds/rm.wav +0 -0
- data/app/controllers/dc_elfinder_controller.rb +63 -0
- data/app/models/drgcms_form_fields/elfinder.rb +85 -0
- data/changelog.md +0 -0
- data/lib/drg_elfinder/engine.rb +5 -0
- data/lib/drg_elfinder/version.rb +3 -0
- data/lib/drg_elfinder.rb +9 -0
- data/lib/el_finder/action.rb +19 -0
- data/lib/el_finder/base64.rb +24 -0
- data/lib/el_finder/connector.rb +625 -0
- data/lib/el_finder/image.rb +33 -0
- data/lib/el_finder/mime_type.rb +86 -0
- data/lib/el_finder/pathname.rb +185 -0
- data/lib/el_finder/version.rb +5 -0
- data/lib/el_finder.rb +8 -0
- data/lib/patches/patch_for_elfinder.rb +115 -0
- data/lib/tasks/drg_elfinder_tasks.rake +10 -0
- metadata +245 -0
|
@@ -0,0 +1,1477 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
// Implement similar functionality in PHP 5.2 or 5.3
|
|
4
|
+
// http://php.net/manual/class.recursivecallbackfilteriterator.php#110974
|
|
5
|
+
if (!class_exists('RecursiveCallbackFilterIterator', false)) {
|
|
6
|
+
class RecursiveCallbackFilterIterator extends RecursiveFilterIterator
|
|
7
|
+
{
|
|
8
|
+
private $callback;
|
|
9
|
+
|
|
10
|
+
public function __construct(RecursiveIterator $iterator, $callback)
|
|
11
|
+
{
|
|
12
|
+
$this->callback = $callback;
|
|
13
|
+
parent::__construct($iterator);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public function accept()
|
|
17
|
+
{
|
|
18
|
+
return call_user_func($this->callback, parent::current(), parent::key(), parent::getInnerIterator());
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public function getChildren()
|
|
22
|
+
{
|
|
23
|
+
return new self($this->getInnerIterator()->getChildren(), $this->callback);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* elFinder driver for local filesystem.
|
|
30
|
+
*
|
|
31
|
+
* @author Dmitry (dio) Levashov
|
|
32
|
+
* @author Troex Nevelin
|
|
33
|
+
**/
|
|
34
|
+
class elFinderVolumeLocalFileSystem extends elFinderVolumeDriver
|
|
35
|
+
{
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Driver id
|
|
39
|
+
* Must be started from letter and contains [a-z0-9]
|
|
40
|
+
* Used as part of volume id
|
|
41
|
+
*
|
|
42
|
+
* @var string
|
|
43
|
+
**/
|
|
44
|
+
protected $driverId = 'l';
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Required to count total archive files size
|
|
48
|
+
*
|
|
49
|
+
* @var int
|
|
50
|
+
**/
|
|
51
|
+
protected $archiveSize = 0;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Is checking stat owner
|
|
55
|
+
*
|
|
56
|
+
* @var boolean
|
|
57
|
+
*/
|
|
58
|
+
protected $statOwner = false;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Path to quarantine directory
|
|
62
|
+
*
|
|
63
|
+
* @var string
|
|
64
|
+
*/
|
|
65
|
+
private $quarantine;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Constructor
|
|
69
|
+
* Extend options with required fields
|
|
70
|
+
*
|
|
71
|
+
* @author Dmitry (dio) Levashov
|
|
72
|
+
*/
|
|
73
|
+
public function __construct()
|
|
74
|
+
{
|
|
75
|
+
$this->options['alias'] = ''; // alias to replace root dir name
|
|
76
|
+
$this->options['dirMode'] = 0755; // new dirs mode
|
|
77
|
+
$this->options['fileMode'] = 0644; // new files mode
|
|
78
|
+
$this->options['rootCssClass'] = 'elfinder-navbar-root-local';
|
|
79
|
+
$this->options['followSymLinks'] = true;
|
|
80
|
+
$this->options['detectDirIcon'] = ''; // file name that is detected as a folder icon e.g. '.diricon.png'
|
|
81
|
+
$this->options['keepTimestamp'] = array('copy', 'move'); // keep timestamp at inner filesystem allowed 'copy', 'move' and 'upload'
|
|
82
|
+
$this->options['substituteImg'] = true; // support substitute image with dim command
|
|
83
|
+
$this->options['statCorrector'] = null; // callable to correct stat data `function(&$stat, $path, $statOwner, $volumeDriveInstance){}`
|
|
84
|
+
if (DIRECTORY_SEPARATOR === '/') {
|
|
85
|
+
// Linux
|
|
86
|
+
$this->options['acceptedName'] = '/^[^\.\/\x00][^\/\x00]*$/';
|
|
87
|
+
} else {
|
|
88
|
+
// Windows
|
|
89
|
+
$this->options['acceptedName'] = '/^[^\.\/\x00\\\:*?"<>|][^\/\x00\\\:*?"<>|]*$/';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*********************************************************************/
|
|
94
|
+
/* INIT AND CONFIGURE */
|
|
95
|
+
/*********************************************************************/
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Prepare driver before mount volume.
|
|
99
|
+
* Return true if volume is ready.
|
|
100
|
+
*
|
|
101
|
+
* @return bool
|
|
102
|
+
**/
|
|
103
|
+
protected function init()
|
|
104
|
+
{
|
|
105
|
+
// Normalize directory separator for windows
|
|
106
|
+
if (DIRECTORY_SEPARATOR !== '/') {
|
|
107
|
+
foreach (array('path', 'tmbPath', 'tmpPath', 'quarantine') as $key) {
|
|
108
|
+
if (!empty($this->options[$key])) {
|
|
109
|
+
$this->options[$key] = str_replace('/', DIRECTORY_SEPARATOR, $this->options[$key]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// PHP >= 7.1 Supports UTF-8 path on Windows
|
|
113
|
+
if (version_compare(PHP_VERSION, '7.1', '>=')) {
|
|
114
|
+
$this->options['encoding'] = '';
|
|
115
|
+
$this->options['locale'] = '';
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!$cwd = getcwd()) {
|
|
119
|
+
return $this->setError('elFinder LocalVolumeDriver requires a result of getcwd().');
|
|
120
|
+
}
|
|
121
|
+
// detect systemRoot
|
|
122
|
+
if (!isset($this->options['systemRoot'])) {
|
|
123
|
+
if ($cwd[0] === DIRECTORY_SEPARATOR || $this->root[0] === DIRECTORY_SEPARATOR) {
|
|
124
|
+
$this->systemRoot = DIRECTORY_SEPARATOR;
|
|
125
|
+
} else if (preg_match('/^([a-zA-Z]:' . preg_quote(DIRECTORY_SEPARATOR, '/') . ')/', $this->root, $m)) {
|
|
126
|
+
$this->systemRoot = $m[1];
|
|
127
|
+
} else if (preg_match('/^([a-zA-Z]:' . preg_quote(DIRECTORY_SEPARATOR, '/') . ')/', $cwd, $m)) {
|
|
128
|
+
$this->systemRoot = $m[1];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
$this->root = $this->getFullPath($this->root, $cwd);
|
|
132
|
+
if (!empty($this->options['startPath'])) {
|
|
133
|
+
$this->options['startPath'] = $this->getFullPath($this->options['startPath'], $this->root);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (is_null($this->options['syncChkAsTs'])) {
|
|
137
|
+
$this->options['syncChkAsTs'] = true;
|
|
138
|
+
}
|
|
139
|
+
if (is_null($this->options['syncCheckFunc'])) {
|
|
140
|
+
$this->options['syncCheckFunc'] = array($this, 'localFileSystemInotify');
|
|
141
|
+
}
|
|
142
|
+
// check 'statCorrector'
|
|
143
|
+
if (empty($this->options['statCorrector']) || !is_callable($this->options['statCorrector'])) {
|
|
144
|
+
$this->options['statCorrector'] = null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Configure after successfull mount.
|
|
152
|
+
*
|
|
153
|
+
* @return void
|
|
154
|
+
* @throws elFinderAbortException
|
|
155
|
+
* @author Dmitry (dio) Levashov
|
|
156
|
+
*/
|
|
157
|
+
protected function configure()
|
|
158
|
+
{
|
|
159
|
+
$hiddens = array();
|
|
160
|
+
$root = $this->stat($this->root);
|
|
161
|
+
|
|
162
|
+
// check thumbnails path
|
|
163
|
+
if (!empty($this->options['tmbPath'])) {
|
|
164
|
+
if (strpos($this->options['tmbPath'], DIRECTORY_SEPARATOR) === false) {
|
|
165
|
+
$hiddens['tmb'] = $this->options['tmbPath'];
|
|
166
|
+
$this->options['tmbPath'] = $this->_abspath($this->options['tmbPath']);
|
|
167
|
+
} else {
|
|
168
|
+
$this->options['tmbPath'] = $this->_normpath($this->options['tmbPath']);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// check temp path
|
|
172
|
+
if (!empty($this->options['tmpPath'])) {
|
|
173
|
+
if (strpos($this->options['tmpPath'], DIRECTORY_SEPARATOR) === false) {
|
|
174
|
+
$hiddens['temp'] = $this->options['tmpPath'];
|
|
175
|
+
$this->options['tmpPath'] = $this->_abspath($this->options['tmpPath']);
|
|
176
|
+
} else {
|
|
177
|
+
$this->options['tmpPath'] = $this->_normpath($this->options['tmpPath']);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// check quarantine path
|
|
181
|
+
$_quarantine = '';
|
|
182
|
+
if (!empty($this->options['quarantine'])) {
|
|
183
|
+
if (strpos($this->options['quarantine'], DIRECTORY_SEPARATOR) === false) {
|
|
184
|
+
//$hiddens['quarantine'] = $this->options['quarantine'];
|
|
185
|
+
//$this->options['quarantine'] = $this->_abspath($this->options['quarantine']);
|
|
186
|
+
$_quarantine = $this->_abspath($this->options['quarantine']);
|
|
187
|
+
$this->options['quarantine'] = '';
|
|
188
|
+
} else {
|
|
189
|
+
$this->options['quarantine'] = $this->_normpath($this->options['quarantine']);
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
$_quarantine = $this->_abspath('.quarantine');
|
|
193
|
+
}
|
|
194
|
+
is_dir($_quarantine) && self::localRmdirRecursive($_quarantine);
|
|
195
|
+
|
|
196
|
+
parent::configure();
|
|
197
|
+
|
|
198
|
+
// check tmbPath
|
|
199
|
+
if (!$this->tmbPath && isset($hiddens['tmb'])) {
|
|
200
|
+
unset($hiddens['tmb']);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// if no thumbnails url - try detect it
|
|
204
|
+
if ($root['read'] && !$this->tmbURL && $this->URL) {
|
|
205
|
+
if (strpos($this->tmbPath, $this->root) === 0) {
|
|
206
|
+
$this->tmbURL = $this->URL . str_replace(DIRECTORY_SEPARATOR, '/', substr($this->tmbPath, strlen($this->root) + 1));
|
|
207
|
+
if (preg_match("|[^/?&=]$|", $this->tmbURL)) {
|
|
208
|
+
$this->tmbURL .= '/';
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// set $this->tmp by options['tmpPath']
|
|
214
|
+
$this->tmp = '';
|
|
215
|
+
if (!empty($this->options['tmpPath'])) {
|
|
216
|
+
if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'], $this->options['dirMode'], true)) && is_writable($this->options['tmpPath'])) {
|
|
217
|
+
$this->tmp = $this->options['tmpPath'];
|
|
218
|
+
} else {
|
|
219
|
+
if (isset($hiddens['temp'])) {
|
|
220
|
+
unset($hiddens['temp']);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (!$this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) {
|
|
225
|
+
$this->tmp = $tmp;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// check quarantine dir
|
|
229
|
+
$this->quarantine = '';
|
|
230
|
+
if (!empty($this->options['quarantine'])) {
|
|
231
|
+
if ((is_dir($this->options['quarantine']) || mkdir($this->options['quarantine'], $this->options['dirMode'], true)) && is_writable($this->options['quarantine'])) {
|
|
232
|
+
$this->quarantine = $this->options['quarantine'];
|
|
233
|
+
} else {
|
|
234
|
+
if (isset($hiddens['quarantine'])) {
|
|
235
|
+
unset($hiddens['quarantine']);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
} else if ($_path = elFinder::getCommonTempPath()) {
|
|
239
|
+
$this->quarantine = $_path;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (!$this->quarantine) {
|
|
243
|
+
if (!$this->tmp) {
|
|
244
|
+
$this->archivers['extract'] = array();
|
|
245
|
+
$this->disabled[] = 'extract';
|
|
246
|
+
} else {
|
|
247
|
+
$this->quarantine = $this->tmp;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if ($hiddens) {
|
|
252
|
+
foreach ($hiddens as $hidden) {
|
|
253
|
+
$this->attributes[] = array(
|
|
254
|
+
'pattern' => '~^' . preg_quote(DIRECTORY_SEPARATOR . $hidden, '~') . '$~',
|
|
255
|
+
'read' => false,
|
|
256
|
+
'write' => false,
|
|
257
|
+
'locked' => true,
|
|
258
|
+
'hidden' => true
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (!empty($this->options['keepTimestamp'])) {
|
|
264
|
+
$this->options['keepTimestamp'] = array_flip($this->options['keepTimestamp']);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
$this->statOwner = (!empty($this->options['statOwner']));
|
|
268
|
+
|
|
269
|
+
// enable WinRemoveTailDots plugin on Windows server
|
|
270
|
+
if (DIRECTORY_SEPARATOR !== '/') {
|
|
271
|
+
if (!isset($this->options['plugin'])) {
|
|
272
|
+
$this->options['plugin'] = array();
|
|
273
|
+
}
|
|
274
|
+
$this->options['plugin']['WinRemoveTailDots'] = array('enable' => true);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Long pooling sync checker
|
|
280
|
+
* This function require server command `inotifywait`
|
|
281
|
+
* If `inotifywait` need full path, Please add `define('ELFINER_INOTIFYWAIT_PATH', '/PATH_TO/inotifywait');` into connector.php
|
|
282
|
+
*
|
|
283
|
+
* @param string $path
|
|
284
|
+
* @param int $standby
|
|
285
|
+
* @param number $compare
|
|
286
|
+
*
|
|
287
|
+
* @return number|bool
|
|
288
|
+
* @throws elFinderAbortException
|
|
289
|
+
*/
|
|
290
|
+
public function localFileSystemInotify($path, $standby, $compare)
|
|
291
|
+
{
|
|
292
|
+
if (isset($this->sessionCache['localFileSystemInotify_disable'])) {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
$path = realpath($path);
|
|
296
|
+
$mtime = filemtime($path);
|
|
297
|
+
if (!$mtime) {
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
if ($mtime != $compare) {
|
|
301
|
+
return $mtime;
|
|
302
|
+
}
|
|
303
|
+
$inotifywait = defined('ELFINER_INOTIFYWAIT_PATH') ? ELFINER_INOTIFYWAIT_PATH : 'inotifywait';
|
|
304
|
+
$standby = max(1, intval($standby));
|
|
305
|
+
$cmd = $inotifywait . ' ' . escapeshellarg($path) . ' -t ' . $standby . ' -e moved_to,moved_from,move,close_write,delete,delete_self';
|
|
306
|
+
$this->procExec($cmd, $o, $r);
|
|
307
|
+
if ($r === 0) {
|
|
308
|
+
// changed
|
|
309
|
+
clearstatcache();
|
|
310
|
+
if (file_exists($path)) {
|
|
311
|
+
$mtime = filemtime($path); // error on busy?
|
|
312
|
+
return $mtime ? $mtime : time();
|
|
313
|
+
} else {
|
|
314
|
+
// target was removed
|
|
315
|
+
return 0;
|
|
316
|
+
}
|
|
317
|
+
} else if ($r === 2) {
|
|
318
|
+
// not changed (timeout)
|
|
319
|
+
return $compare;
|
|
320
|
+
}
|
|
321
|
+
// error
|
|
322
|
+
// cache to $_SESSION
|
|
323
|
+
$this->sessionCache['localFileSystemInotify_disable'] = true;
|
|
324
|
+
$this->session->set($this->id, $this->sessionCache);
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/*********************************************************************/
|
|
329
|
+
/* FS API */
|
|
330
|
+
/*********************************************************************/
|
|
331
|
+
|
|
332
|
+
/*********************** paths/urls *************************/
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Return parent directory path
|
|
336
|
+
*
|
|
337
|
+
* @param string $path file path
|
|
338
|
+
*
|
|
339
|
+
* @return string
|
|
340
|
+
* @author Dmitry (dio) Levashov
|
|
341
|
+
**/
|
|
342
|
+
protected function _dirname($path)
|
|
343
|
+
{
|
|
344
|
+
return dirname($path);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Return file name
|
|
349
|
+
*
|
|
350
|
+
* @param string $path file path
|
|
351
|
+
*
|
|
352
|
+
* @return string
|
|
353
|
+
* @author Dmitry (dio) Levashov
|
|
354
|
+
**/
|
|
355
|
+
protected function _basename($path)
|
|
356
|
+
{
|
|
357
|
+
return basename($path);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Join dir name and file name and retur full path
|
|
362
|
+
*
|
|
363
|
+
* @param string $dir
|
|
364
|
+
* @param string $name
|
|
365
|
+
*
|
|
366
|
+
* @return string
|
|
367
|
+
* @author Dmitry (dio) Levashov
|
|
368
|
+
**/
|
|
369
|
+
protected function _joinPath($dir, $name)
|
|
370
|
+
{
|
|
371
|
+
$dir = rtrim($dir, DIRECTORY_SEPARATOR);
|
|
372
|
+
$path = realpath($dir . DIRECTORY_SEPARATOR . $name);
|
|
373
|
+
// realpath() returns FALSE if the file does not exist
|
|
374
|
+
if ($path === false || strpos($path, $this->root) !== 0) {
|
|
375
|
+
if (DIRECTORY_SEPARATOR !== '/') {
|
|
376
|
+
$name = str_replace('/', DIRECTORY_SEPARATOR, $name);
|
|
377
|
+
}
|
|
378
|
+
// Directory traversal measures
|
|
379
|
+
if (strpos($name, '..' . DIRECTORY_SEPARATOR) !== false) {
|
|
380
|
+
$name = basename($name);
|
|
381
|
+
}
|
|
382
|
+
$path = $dir . DIRECTORY_SEPARATOR . $name;
|
|
383
|
+
}
|
|
384
|
+
return $path;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Return normalized path, this works the same as os.path.normpath() in Python
|
|
389
|
+
*
|
|
390
|
+
* @param string $path path
|
|
391
|
+
*
|
|
392
|
+
* @return string
|
|
393
|
+
* @author Troex Nevelin
|
|
394
|
+
**/
|
|
395
|
+
protected function _normpath($path)
|
|
396
|
+
{
|
|
397
|
+
if (empty($path)) {
|
|
398
|
+
return '.';
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
$changeSep = (DIRECTORY_SEPARATOR !== '/');
|
|
402
|
+
if ($changeSep) {
|
|
403
|
+
$drive = '';
|
|
404
|
+
if (preg_match('/^([a-zA-Z]:)(.*)/', $path, $m)) {
|
|
405
|
+
$drive = $m[1];
|
|
406
|
+
$path = $m[2] ? $m[2] : '/';
|
|
407
|
+
}
|
|
408
|
+
$path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (strpos($path, '/') === 0) {
|
|
412
|
+
$initial_slashes = true;
|
|
413
|
+
} else {
|
|
414
|
+
$initial_slashes = false;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (($initial_slashes)
|
|
418
|
+
&& (strpos($path, '//') === 0)
|
|
419
|
+
&& (strpos($path, '///') === false)) {
|
|
420
|
+
$initial_slashes = 2;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
$initial_slashes = (int)$initial_slashes;
|
|
424
|
+
|
|
425
|
+
$comps = explode('/', $path);
|
|
426
|
+
$new_comps = array();
|
|
427
|
+
foreach ($comps as $comp) {
|
|
428
|
+
if (in_array($comp, array('', '.'))) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (($comp != '..')
|
|
433
|
+
|| (!$initial_slashes && !$new_comps)
|
|
434
|
+
|| ($new_comps && (end($new_comps) == '..'))) {
|
|
435
|
+
array_push($new_comps, $comp);
|
|
436
|
+
} elseif ($new_comps) {
|
|
437
|
+
array_pop($new_comps);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
$comps = $new_comps;
|
|
441
|
+
$path = implode('/', $comps);
|
|
442
|
+
if ($initial_slashes) {
|
|
443
|
+
$path = str_repeat('/', $initial_slashes) . $path;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
if ($changeSep) {
|
|
447
|
+
$path = $drive . str_replace('/', DIRECTORY_SEPARATOR, $path);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
return $path ? $path : '.';
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Return file path related to root dir
|
|
455
|
+
*
|
|
456
|
+
* @param string $path file path
|
|
457
|
+
*
|
|
458
|
+
* @return string
|
|
459
|
+
* @author Dmitry (dio) Levashov
|
|
460
|
+
**/
|
|
461
|
+
protected function _relpath($path)
|
|
462
|
+
{
|
|
463
|
+
if ($path === $this->root) {
|
|
464
|
+
return '';
|
|
465
|
+
} else {
|
|
466
|
+
if (strpos($path, $this->root) === 0) {
|
|
467
|
+
return ltrim(substr($path, strlen($this->root)), DIRECTORY_SEPARATOR);
|
|
468
|
+
} else {
|
|
469
|
+
// for link
|
|
470
|
+
return $path;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Convert path related to root dir into real path
|
|
477
|
+
*
|
|
478
|
+
* @param string $path file path
|
|
479
|
+
*
|
|
480
|
+
* @return string
|
|
481
|
+
* @author Dmitry (dio) Levashov
|
|
482
|
+
**/
|
|
483
|
+
protected function _abspath($path)
|
|
484
|
+
{
|
|
485
|
+
if ($path === DIRECTORY_SEPARATOR) {
|
|
486
|
+
return $this->root;
|
|
487
|
+
} else {
|
|
488
|
+
$path = $this->_normpath($path);
|
|
489
|
+
if (strpos($path, $this->systemRoot) === 0) {
|
|
490
|
+
return $path;
|
|
491
|
+
} else if (DIRECTORY_SEPARATOR !== '/' && preg_match('/^[a-zA-Z]:' . preg_quote(DIRECTORY_SEPARATOR, '/') . '/', $path)) {
|
|
492
|
+
return $path;
|
|
493
|
+
} else {
|
|
494
|
+
return $this->_joinPath($this->root, $path);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Return fake path started from root dir
|
|
501
|
+
*
|
|
502
|
+
* @param string $path file path
|
|
503
|
+
*
|
|
504
|
+
* @return string
|
|
505
|
+
* @author Dmitry (dio) Levashov
|
|
506
|
+
**/
|
|
507
|
+
protected function _path($path)
|
|
508
|
+
{
|
|
509
|
+
return $this->rootName . ($path == $this->root ? '' : $this->separator . $this->_relpath($path));
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Return true if $path is children of $parent
|
|
514
|
+
*
|
|
515
|
+
* @param string $path path to check
|
|
516
|
+
* @param string $parent parent path
|
|
517
|
+
*
|
|
518
|
+
* @return bool
|
|
519
|
+
* @author Dmitry (dio) Levashov
|
|
520
|
+
**/
|
|
521
|
+
protected function _inpath($path, $parent)
|
|
522
|
+
{
|
|
523
|
+
$cwd = getcwd();
|
|
524
|
+
$real_path = $this->getFullPath($path, $cwd);
|
|
525
|
+
$real_parent = $this->getFullPath($parent, $cwd);
|
|
526
|
+
if ($real_path && $real_parent) {
|
|
527
|
+
return $real_path === $real_parent || strpos($real_path, rtrim($real_parent, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR) === 0;
|
|
528
|
+
}
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
/***************** file stat ********************/
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Return stat for given path.
|
|
538
|
+
* Stat contains following fields:
|
|
539
|
+
* - (int) size file size in b. required
|
|
540
|
+
* - (int) ts file modification time in unix time. required
|
|
541
|
+
* - (string) mime mimetype. required for folders, others - optionally
|
|
542
|
+
* - (bool) read read permissions. required
|
|
543
|
+
* - (bool) write write permissions. required
|
|
544
|
+
* - (bool) locked is object locked. optionally
|
|
545
|
+
* - (bool) hidden is object hidden. optionally
|
|
546
|
+
* - (string) alias for symlinks - link target path relative to root path. optionally
|
|
547
|
+
* - (string) target for symlinks - link target path. optionally
|
|
548
|
+
* If file does not exists - returns empty array or false.
|
|
549
|
+
*
|
|
550
|
+
* @param string $path file path
|
|
551
|
+
*
|
|
552
|
+
* @return array|false
|
|
553
|
+
* @author Dmitry (dio) Levashov
|
|
554
|
+
**/
|
|
555
|
+
protected function _stat($path)
|
|
556
|
+
{
|
|
557
|
+
$stat = array();
|
|
558
|
+
|
|
559
|
+
if (!file_exists($path) && !is_link($path)) {
|
|
560
|
+
return $stat;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
//Verifies the given path is the root or is inside the root. Prevents directory traveral.
|
|
564
|
+
if (!$this->_inpath($path, $this->root)) {
|
|
565
|
+
return $stat;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
$stat['isowner'] = false;
|
|
569
|
+
$linkreadable = false;
|
|
570
|
+
if ($path != $this->root && is_link($path)) {
|
|
571
|
+
if (!$this->options['followSymLinks']) {
|
|
572
|
+
return array();
|
|
573
|
+
}
|
|
574
|
+
if (!($target = $this->readlink($path))
|
|
575
|
+
|| $target == $path) {
|
|
576
|
+
if (is_null($target)) {
|
|
577
|
+
$stat = array();
|
|
578
|
+
return $stat;
|
|
579
|
+
} else {
|
|
580
|
+
$stat['mime'] = 'symlink-broken';
|
|
581
|
+
$target = readlink($path);
|
|
582
|
+
$lstat = lstat($path);
|
|
583
|
+
$ostat = $this->getOwnerStat($lstat['uid'], $lstat['gid']);
|
|
584
|
+
$linkreadable = !empty($ostat['isowner']);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
$stat['alias'] = $this->_path($target);
|
|
588
|
+
$stat['target'] = $target;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
$readable = is_readable($path);
|
|
592
|
+
|
|
593
|
+
if ($readable) {
|
|
594
|
+
$size = sprintf('%u', filesize($path));
|
|
595
|
+
$stat['ts'] = filemtime($path);
|
|
596
|
+
if ($this->statOwner) {
|
|
597
|
+
$fstat = stat($path);
|
|
598
|
+
$uid = $fstat['uid'];
|
|
599
|
+
$gid = $fstat['gid'];
|
|
600
|
+
$stat['perm'] = substr((string)decoct($fstat['mode']), -4);
|
|
601
|
+
$stat = array_merge($stat, $this->getOwnerStat($uid, $gid));
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
if (($dir = is_dir($path)) && $this->options['detectDirIcon']) {
|
|
606
|
+
$favicon = $path . DIRECTORY_SEPARATOR . $this->options['detectDirIcon'];
|
|
607
|
+
if ($this->URL && file_exists($favicon)) {
|
|
608
|
+
$stat['icon'] = $this->URL . str_replace(DIRECTORY_SEPARATOR, '/', substr($favicon, strlen($this->root) + 1));
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
if (!isset($stat['mime'])) {
|
|
613
|
+
$stat['mime'] = $dir ? 'directory' : $this->mimetype($path);
|
|
614
|
+
}
|
|
615
|
+
//logical rights first
|
|
616
|
+
$stat['read'] = ($linkreadable || $readable) ? null : false;
|
|
617
|
+
$stat['write'] = is_writable($path) ? null : false;
|
|
618
|
+
|
|
619
|
+
if (is_null($stat['read'])) {
|
|
620
|
+
if ($dir) {
|
|
621
|
+
$stat['size'] = 0;
|
|
622
|
+
} else if (isset($size)) {
|
|
623
|
+
$stat['size'] = $size;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if ($this->options['statCorrector']) {
|
|
628
|
+
call_user_func_array($this->options['statCorrector'], array(&$stat, $path, $this->statOwner, $this));
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return $stat;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Get stat `owner`, `group` and `isowner` by `uid` and `gid`
|
|
636
|
+
* Sub-fuction of _stat() and _scandir()
|
|
637
|
+
*
|
|
638
|
+
* @param integer $uid
|
|
639
|
+
* @param integer $gid
|
|
640
|
+
*
|
|
641
|
+
* @return array stat
|
|
642
|
+
*/
|
|
643
|
+
protected function getOwnerStat($uid, $gid)
|
|
644
|
+
{
|
|
645
|
+
static $names = null;
|
|
646
|
+
static $phpuid = null;
|
|
647
|
+
|
|
648
|
+
if (is_null($names)) {
|
|
649
|
+
$names = array('uid' => array(), 'gid' => array());
|
|
650
|
+
}
|
|
651
|
+
if (is_null($phpuid)) {
|
|
652
|
+
if (is_callable('posix_getuid')) {
|
|
653
|
+
$phpuid = posix_getuid();
|
|
654
|
+
} else {
|
|
655
|
+
$phpuid = 0;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
$stat = array();
|
|
660
|
+
|
|
661
|
+
if ($uid) {
|
|
662
|
+
$stat['isowner'] = ($phpuid == $uid);
|
|
663
|
+
if (isset($names['uid'][$uid])) {
|
|
664
|
+
$stat['owner'] = $names['uid'][$uid];
|
|
665
|
+
} else if (is_callable('posix_getpwuid')) {
|
|
666
|
+
$pwuid = posix_getpwuid($uid);
|
|
667
|
+
$stat['owner'] = $names['uid'][$uid] = $pwuid['name'];
|
|
668
|
+
} else {
|
|
669
|
+
$stat['owner'] = $names['uid'][$uid] = $uid;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if ($gid) {
|
|
673
|
+
if (isset($names['gid'][$gid])) {
|
|
674
|
+
$stat['group'] = $names['gid'][$gid];
|
|
675
|
+
} else if (is_callable('posix_getgrgid')) {
|
|
676
|
+
$grgid = posix_getgrgid($gid);
|
|
677
|
+
$stat['group'] = $names['gid'][$gid] = $grgid['name'];
|
|
678
|
+
} else {
|
|
679
|
+
$stat['group'] = $names['gid'][$gid] = $gid;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
return $stat;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Return true if path is dir and has at least one childs directory
|
|
688
|
+
*
|
|
689
|
+
* @param string $path dir path
|
|
690
|
+
*
|
|
691
|
+
* @return bool
|
|
692
|
+
* @author Dmitry (dio) Levashov
|
|
693
|
+
**/
|
|
694
|
+
protected function _subdirs($path)
|
|
695
|
+
{
|
|
696
|
+
|
|
697
|
+
$dirs = false;
|
|
698
|
+
if (is_dir($path) && is_readable($path)) {
|
|
699
|
+
if (class_exists('FilesystemIterator', false)) {
|
|
700
|
+
$dirItr = new ParentIterator(
|
|
701
|
+
new RecursiveDirectoryIterator($path,
|
|
702
|
+
FilesystemIterator::SKIP_DOTS |
|
|
703
|
+
FilesystemIterator::CURRENT_AS_SELF |
|
|
704
|
+
(defined('RecursiveDirectoryIterator::FOLLOW_SYMLINKS') ?
|
|
705
|
+
RecursiveDirectoryIterator::FOLLOW_SYMLINKS : 0)
|
|
706
|
+
)
|
|
707
|
+
);
|
|
708
|
+
$dirItr->rewind();
|
|
709
|
+
if ($dirItr->hasChildren()) {
|
|
710
|
+
$dirs = true;
|
|
711
|
+
$name = $dirItr->getSubPathName();
|
|
712
|
+
while ($dirItr->valid()) {
|
|
713
|
+
if (!$this->attr($path . DIRECTORY_SEPARATOR . $name, 'read', null, true)) {
|
|
714
|
+
$dirs = false;
|
|
715
|
+
$dirItr->next();
|
|
716
|
+
$name = $dirItr->getSubPathName();
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
$dirs = true;
|
|
720
|
+
break;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
} else {
|
|
724
|
+
$path = strtr($path, array('[' => '\\[', ']' => '\\]', '*' => '\\*', '?' => '\\?'));
|
|
725
|
+
return (bool)glob(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
return $dirs;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Return object width and height
|
|
733
|
+
* Usualy used for images, but can be realize for video etc...
|
|
734
|
+
*
|
|
735
|
+
* @param string $path file path
|
|
736
|
+
* @param string $mime file mime type
|
|
737
|
+
*
|
|
738
|
+
* @return string
|
|
739
|
+
* @author Dmitry (dio) Levashov
|
|
740
|
+
**/
|
|
741
|
+
protected function _dimensions($path, $mime)
|
|
742
|
+
{
|
|
743
|
+
clearstatcache();
|
|
744
|
+
return strpos($mime, 'image') === 0 && is_readable($path) && filesize($path) && ($s = getimagesize($path)) !== false
|
|
745
|
+
? $s[0] . 'x' . $s[1]
|
|
746
|
+
: false;
|
|
747
|
+
}
|
|
748
|
+
/******************** file/dir content *********************/
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Return symlink target file
|
|
752
|
+
*
|
|
753
|
+
* @param string $path link path
|
|
754
|
+
*
|
|
755
|
+
* @return string
|
|
756
|
+
* @author Dmitry (dio) Levashov
|
|
757
|
+
**/
|
|
758
|
+
protected function readlink($path)
|
|
759
|
+
{
|
|
760
|
+
if (!($target = readlink($path))) {
|
|
761
|
+
return null;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
if (strpos($target, $this->systemRoot) !== 0) {
|
|
765
|
+
$target = $this->_joinPath(dirname($path), $target);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
if (!file_exists($target)) {
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
return $target;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Return files list in directory.
|
|
777
|
+
*
|
|
778
|
+
* @param string $path dir path
|
|
779
|
+
*
|
|
780
|
+
* @return array
|
|
781
|
+
* @throws elFinderAbortException
|
|
782
|
+
* @author Dmitry (dio) Levashov
|
|
783
|
+
*/
|
|
784
|
+
protected function _scandir($path)
|
|
785
|
+
{
|
|
786
|
+
elFinder::checkAborted();
|
|
787
|
+
$files = array();
|
|
788
|
+
$cache = array();
|
|
789
|
+
$dirWritable = is_writable($path);
|
|
790
|
+
$dirItr = array();
|
|
791
|
+
$followSymLinks = $this->options['followSymLinks'];
|
|
792
|
+
try {
|
|
793
|
+
$dirItr = new DirectoryIterator($path);
|
|
794
|
+
} catch (UnexpectedValueException $e) {
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
foreach ($dirItr as $file) {
|
|
798
|
+
try {
|
|
799
|
+
if ($file->isDot()) {
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
$files[] = $fpath = $file->getPathname();
|
|
804
|
+
|
|
805
|
+
$br = false;
|
|
806
|
+
$stat = array();
|
|
807
|
+
|
|
808
|
+
$stat['isowner'] = false;
|
|
809
|
+
$linkreadable = false;
|
|
810
|
+
if ($file->isLink()) {
|
|
811
|
+
if (!$followSymLinks) {
|
|
812
|
+
continue;
|
|
813
|
+
}
|
|
814
|
+
if (!($target = $this->readlink($fpath))
|
|
815
|
+
|| $target == $fpath) {
|
|
816
|
+
if (is_null($target)) {
|
|
817
|
+
$stat = array();
|
|
818
|
+
$br = true;
|
|
819
|
+
} else {
|
|
820
|
+
$_path = $fpath;
|
|
821
|
+
$stat['mime'] = 'symlink-broken';
|
|
822
|
+
$target = readlink($_path);
|
|
823
|
+
$lstat = lstat($_path);
|
|
824
|
+
$ostat = $this->getOwnerStat($lstat['uid'], $lstat['gid']);
|
|
825
|
+
$linkreadable = !empty($ostat['isowner']);
|
|
826
|
+
$dir = false;
|
|
827
|
+
$stat['alias'] = $this->_path($target);
|
|
828
|
+
$stat['target'] = $target;
|
|
829
|
+
}
|
|
830
|
+
} else {
|
|
831
|
+
$dir = is_dir($target);
|
|
832
|
+
$stat['alias'] = $this->_path($target);
|
|
833
|
+
$stat['target'] = $target;
|
|
834
|
+
$stat['mime'] = $dir ? 'directory' : $this->mimetype($stat['alias']);
|
|
835
|
+
}
|
|
836
|
+
} else {
|
|
837
|
+
if (($dir = $file->isDir()) && $this->options['detectDirIcon']) {
|
|
838
|
+
$path = $file->getPathname();
|
|
839
|
+
$favicon = $path . DIRECTORY_SEPARATOR . $this->options['detectDirIcon'];
|
|
840
|
+
if ($this->URL && file_exists($favicon)) {
|
|
841
|
+
$stat['icon'] = $this->URL . str_replace(DIRECTORY_SEPARATOR, '/', substr($favicon, strlen($this->root) + 1));
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
$stat['mime'] = $dir ? 'directory' : $this->mimetype($fpath);
|
|
845
|
+
}
|
|
846
|
+
$size = sprintf('%u', $file->getSize());
|
|
847
|
+
$stat['ts'] = $file->getMTime();
|
|
848
|
+
if (!$br) {
|
|
849
|
+
if ($this->statOwner && !$linkreadable) {
|
|
850
|
+
$uid = $file->getOwner();
|
|
851
|
+
$gid = $file->getGroup();
|
|
852
|
+
$stat['perm'] = substr((string)decoct($file->getPerms()), -4);
|
|
853
|
+
$stat = array_merge($stat, $this->getOwnerStat($uid, $gid));
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
//logical rights first
|
|
857
|
+
$stat['read'] = ($linkreadable || $file->isReadable()) ? null : false;
|
|
858
|
+
$stat['write'] = $file->isWritable() ? null : false;
|
|
859
|
+
$stat['locked'] = $dirWritable ? null : true;
|
|
860
|
+
|
|
861
|
+
if (is_null($stat['read'])) {
|
|
862
|
+
$stat['size'] = $dir ? 0 : $size;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
if ($this->options['statCorrector']) {
|
|
866
|
+
call_user_func_array($this->options['statCorrector'], array(&$stat, $fpath, $this->statOwner, $this));
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
$cache[] = array($fpath, $stat);
|
|
871
|
+
} catch (RuntimeException $e) {
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
if ($cache) {
|
|
877
|
+
$cache = $this->convEncOut($cache, false);
|
|
878
|
+
foreach ($cache as $d) {
|
|
879
|
+
$this->updateCache($d[0], $d[1]);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
return $files;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
/**
|
|
887
|
+
* Open file and return file pointer
|
|
888
|
+
*
|
|
889
|
+
* @param string $path file path
|
|
890
|
+
* @param string $mode
|
|
891
|
+
*
|
|
892
|
+
* @return false|resource
|
|
893
|
+
* @internal param bool $write open file for writing
|
|
894
|
+
* @author Dmitry (dio) Levashov
|
|
895
|
+
*/
|
|
896
|
+
protected function _fopen($path, $mode = 'rb')
|
|
897
|
+
{
|
|
898
|
+
return fopen($path, $mode);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* Close opened file
|
|
903
|
+
*
|
|
904
|
+
* @param resource $fp file pointer
|
|
905
|
+
* @param string $path
|
|
906
|
+
*
|
|
907
|
+
* @return bool
|
|
908
|
+
* @author Dmitry (dio) Levashov
|
|
909
|
+
*/
|
|
910
|
+
protected function _fclose($fp, $path = '')
|
|
911
|
+
{
|
|
912
|
+
return (is_resource($fp) && fclose($fp));
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/******************** file/dir manipulations *************************/
|
|
916
|
+
|
|
917
|
+
/**
|
|
918
|
+
* Create dir and return created dir path or false on failed
|
|
919
|
+
*
|
|
920
|
+
* @param string $path parent dir path
|
|
921
|
+
* @param string $name new directory name
|
|
922
|
+
*
|
|
923
|
+
* @return string|bool
|
|
924
|
+
* @author Dmitry (dio) Levashov
|
|
925
|
+
**/
|
|
926
|
+
protected function _mkdir($path, $name)
|
|
927
|
+
{
|
|
928
|
+
$path = $this->_joinPath($path, $name);
|
|
929
|
+
|
|
930
|
+
if (mkdir($path)) {
|
|
931
|
+
chmod($path, $this->options['dirMode']);
|
|
932
|
+
return $path;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
return false;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* Create file and return it's path or false on failed
|
|
940
|
+
*
|
|
941
|
+
* @param string $path parent dir path
|
|
942
|
+
* @param string $name new file name
|
|
943
|
+
*
|
|
944
|
+
* @return string|bool
|
|
945
|
+
* @author Dmitry (dio) Levashov
|
|
946
|
+
**/
|
|
947
|
+
protected function _mkfile($path, $name)
|
|
948
|
+
{
|
|
949
|
+
$path = $this->_joinPath($path, $name);
|
|
950
|
+
|
|
951
|
+
if (($fp = fopen($path, 'w'))) {
|
|
952
|
+
fclose($fp);
|
|
953
|
+
chmod($path, $this->options['fileMode']);
|
|
954
|
+
return $path;
|
|
955
|
+
}
|
|
956
|
+
return false;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* Create symlink
|
|
961
|
+
*
|
|
962
|
+
* @param string $source file to link to
|
|
963
|
+
* @param string $targetDir folder to create link in
|
|
964
|
+
* @param string $name symlink name
|
|
965
|
+
*
|
|
966
|
+
* @return bool
|
|
967
|
+
* @author Dmitry (dio) Levashov
|
|
968
|
+
**/
|
|
969
|
+
protected function _symlink($source, $targetDir, $name)
|
|
970
|
+
{
|
|
971
|
+
return symlink($source, $this->_joinPath($targetDir, $name));
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/**
|
|
975
|
+
* Copy file into another file
|
|
976
|
+
*
|
|
977
|
+
* @param string $source source file path
|
|
978
|
+
* @param string $targetDir target directory path
|
|
979
|
+
* @param string $name new file name
|
|
980
|
+
*
|
|
981
|
+
* @return bool
|
|
982
|
+
* @author Dmitry (dio) Levashov
|
|
983
|
+
**/
|
|
984
|
+
protected function _copy($source, $targetDir, $name)
|
|
985
|
+
{
|
|
986
|
+
$mtime = filemtime($source);
|
|
987
|
+
$target = $this->_joinPath($targetDir, $name);
|
|
988
|
+
if ($ret = copy($source, $target)) {
|
|
989
|
+
isset($this->options['keepTimestamp']['copy']) && $mtime && touch($target, $mtime);
|
|
990
|
+
}
|
|
991
|
+
return $ret;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* Move file into another parent dir.
|
|
996
|
+
* Return new file path or false.
|
|
997
|
+
*
|
|
998
|
+
* @param string $source source file path
|
|
999
|
+
* @param $targetDir
|
|
1000
|
+
* @param string $name file name
|
|
1001
|
+
*
|
|
1002
|
+
* @return bool|string
|
|
1003
|
+
* @internal param string $target target dir path
|
|
1004
|
+
* @author Dmitry (dio) Levashov
|
|
1005
|
+
*/
|
|
1006
|
+
protected function _move($source, $targetDir, $name)
|
|
1007
|
+
{
|
|
1008
|
+
$mtime = filemtime($source);
|
|
1009
|
+
$target = $this->_joinPath($targetDir, $name);
|
|
1010
|
+
if ($ret = rename($source, $target) ? $target : false) {
|
|
1011
|
+
isset($this->options['keepTimestamp']['move']) && $mtime && touch($target, $mtime);
|
|
1012
|
+
}
|
|
1013
|
+
return $ret;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Remove file
|
|
1018
|
+
*
|
|
1019
|
+
* @param string $path file path
|
|
1020
|
+
*
|
|
1021
|
+
* @return bool
|
|
1022
|
+
* @author Dmitry (dio) Levashov
|
|
1023
|
+
**/
|
|
1024
|
+
protected function _unlink($path)
|
|
1025
|
+
{
|
|
1026
|
+
return is_file($path) && unlink($path);
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* Remove dir
|
|
1031
|
+
*
|
|
1032
|
+
* @param string $path dir path
|
|
1033
|
+
*
|
|
1034
|
+
* @return bool
|
|
1035
|
+
* @author Dmitry (dio) Levashov
|
|
1036
|
+
**/
|
|
1037
|
+
protected function _rmdir($path)
|
|
1038
|
+
{
|
|
1039
|
+
return rmdir($path);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/**
|
|
1043
|
+
* Create new file and write into it from file pointer.
|
|
1044
|
+
* Return new file path or false on error.
|
|
1045
|
+
*
|
|
1046
|
+
* @param resource $fp file pointer
|
|
1047
|
+
* @param string $dir target dir path
|
|
1048
|
+
* @param string $name file name
|
|
1049
|
+
* @param array $stat file stat (required by some virtual fs)
|
|
1050
|
+
*
|
|
1051
|
+
* @return bool|string
|
|
1052
|
+
* @author Dmitry (dio) Levashov
|
|
1053
|
+
**/
|
|
1054
|
+
protected function _save($fp, $dir, $name, $stat)
|
|
1055
|
+
{
|
|
1056
|
+
$path = $this->_joinPath($dir, $name);
|
|
1057
|
+
|
|
1058
|
+
$meta = stream_get_meta_data($fp);
|
|
1059
|
+
$uri = isset($meta['uri']) ? $meta['uri'] : '';
|
|
1060
|
+
if ($uri && !preg_match('#^[a-zA-Z0-9]+://#', $uri) && !is_link($uri)) {
|
|
1061
|
+
fclose($fp);
|
|
1062
|
+
$mtime = filemtime($uri);
|
|
1063
|
+
$isCmdPaste = ($this->ARGS['cmd'] === 'paste');
|
|
1064
|
+
$isCmdCopy = ($isCmdPaste && empty($this->ARGS['cut']));
|
|
1065
|
+
if (($isCmdCopy || !rename($uri, $path)) && !copy($uri, $path)) {
|
|
1066
|
+
return false;
|
|
1067
|
+
}
|
|
1068
|
+
// keep timestamp on upload
|
|
1069
|
+
if ($mtime && $this->ARGS['cmd'] === 'upload') {
|
|
1070
|
+
touch($path, isset($this->options['keepTimestamp']['upload']) ? $mtime : time());
|
|
1071
|
+
}
|
|
1072
|
+
} else {
|
|
1073
|
+
if (file_put_contents($path, $fp, LOCK_EX) === false) {
|
|
1074
|
+
return false;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
chmod($path, $this->options['fileMode']);
|
|
1079
|
+
return $path;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
/**
|
|
1083
|
+
* Get file contents
|
|
1084
|
+
*
|
|
1085
|
+
* @param string $path file path
|
|
1086
|
+
*
|
|
1087
|
+
* @return string|false
|
|
1088
|
+
* @author Dmitry (dio) Levashov
|
|
1089
|
+
**/
|
|
1090
|
+
protected function _getContents($path)
|
|
1091
|
+
{
|
|
1092
|
+
return file_get_contents($path);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/**
|
|
1096
|
+
* Write a string to a file
|
|
1097
|
+
*
|
|
1098
|
+
* @param string $path file path
|
|
1099
|
+
* @param string $content new file content
|
|
1100
|
+
*
|
|
1101
|
+
* @return bool
|
|
1102
|
+
* @author Dmitry (dio) Levashov
|
|
1103
|
+
**/
|
|
1104
|
+
protected function _filePutContents($path, $content)
|
|
1105
|
+
{
|
|
1106
|
+
return (file_put_contents($path, $content, LOCK_EX) !== false);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
/**
|
|
1110
|
+
* Detect available archivers
|
|
1111
|
+
*
|
|
1112
|
+
* @return void
|
|
1113
|
+
* @throws elFinderAbortException
|
|
1114
|
+
*/
|
|
1115
|
+
protected function _checkArchivers()
|
|
1116
|
+
{
|
|
1117
|
+
$this->archivers = $this->getArchivers();
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* chmod availability
|
|
1123
|
+
*
|
|
1124
|
+
* @param string $path
|
|
1125
|
+
* @param string $mode
|
|
1126
|
+
*
|
|
1127
|
+
* @return bool
|
|
1128
|
+
*/
|
|
1129
|
+
protected function _chmod($path, $mode)
|
|
1130
|
+
{
|
|
1131
|
+
$modeOct = is_string($mode) ? octdec($mode) : octdec(sprintf("%04o", $mode));
|
|
1132
|
+
return chmod($path, $modeOct);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/**
|
|
1136
|
+
* Recursive symlinks search
|
|
1137
|
+
*
|
|
1138
|
+
* @param string $path file/dir path
|
|
1139
|
+
*
|
|
1140
|
+
* @return bool
|
|
1141
|
+
* @throws Exception
|
|
1142
|
+
* @author Dmitry (dio) Levashov
|
|
1143
|
+
*/
|
|
1144
|
+
protected function _findSymlinks($path)
|
|
1145
|
+
{
|
|
1146
|
+
return self::localFindSymlinks($path);
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* Extract files from archive
|
|
1151
|
+
*
|
|
1152
|
+
* @param string $path archive path
|
|
1153
|
+
* @param array $arc archiver command and arguments (same as in $this->archivers)
|
|
1154
|
+
*
|
|
1155
|
+
* @return array|string|boolean
|
|
1156
|
+
* @throws elFinderAbortException
|
|
1157
|
+
* @author Dmitry (dio) Levashov,
|
|
1158
|
+
* @author Alexey Sukhotin
|
|
1159
|
+
*/
|
|
1160
|
+
protected function _extract($path, $arc)
|
|
1161
|
+
{
|
|
1162
|
+
|
|
1163
|
+
if ($this->quarantine) {
|
|
1164
|
+
|
|
1165
|
+
$dir = $this->quarantine . DIRECTORY_SEPARATOR . md5(basename($path) . mt_rand());
|
|
1166
|
+
$archive = (isset($arc['toSpec']) || $arc['cmd'] === 'phpfunction') ? '' : $dir . DIRECTORY_SEPARATOR . basename($path);
|
|
1167
|
+
|
|
1168
|
+
if (!mkdir($dir)) {
|
|
1169
|
+
return false;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
// insurance unexpected shutdown
|
|
1173
|
+
register_shutdown_function(array($this, 'rmdirRecursive'), realpath($dir));
|
|
1174
|
+
|
|
1175
|
+
chmod($dir, 0777);
|
|
1176
|
+
|
|
1177
|
+
// copy in quarantine
|
|
1178
|
+
if (!is_readable($path) || ($archive && !copy($path, $archive))) {
|
|
1179
|
+
return false;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
// extract in quarantine
|
|
1183
|
+
try {
|
|
1184
|
+
$this->unpackArchive($path, $arc, $archive ? true : $dir);
|
|
1185
|
+
} catch(Exception $e) {
|
|
1186
|
+
return $this->setError($e->getMessage());
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// get files list
|
|
1190
|
+
try {
|
|
1191
|
+
$ls = self::localScandir($dir);
|
|
1192
|
+
} catch (Exception $e) {
|
|
1193
|
+
return false;
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
// no files - extract error ?
|
|
1197
|
+
if (empty($ls)) {
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
$this->archiveSize = 0;
|
|
1202
|
+
|
|
1203
|
+
// find symlinks and check extracted items
|
|
1204
|
+
$checkRes = $this->checkExtractItems($dir);
|
|
1205
|
+
if ($checkRes['symlinks']) {
|
|
1206
|
+
self::localRmdirRecursive($dir);
|
|
1207
|
+
return $this->setError(array_merge($this->error, array(elFinder::ERROR_ARC_SYMLINKS)));
|
|
1208
|
+
}
|
|
1209
|
+
$this->archiveSize = $checkRes['totalSize'];
|
|
1210
|
+
if ($checkRes['rmNames']) {
|
|
1211
|
+
foreach ($checkRes['rmNames'] as $name) {
|
|
1212
|
+
$this->addError(elFinder::ERROR_SAVE, $name);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
// check max files size
|
|
1217
|
+
if ($this->options['maxArcFilesSize'] > 0 && $this->options['maxArcFilesSize'] < $this->archiveSize) {
|
|
1218
|
+
$this->delTree($dir);
|
|
1219
|
+
return $this->setError(elFinder::ERROR_ARC_MAXSIZE);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
$extractTo = $this->extractToNewdir; // 'auto', ture or false
|
|
1223
|
+
|
|
1224
|
+
// archive contains one item - extract in archive dir
|
|
1225
|
+
$name = '';
|
|
1226
|
+
$src = $dir . DIRECTORY_SEPARATOR . $ls[0];
|
|
1227
|
+
if (($extractTo === 'auto' || !$extractTo) && count($ls) === 1 && is_file($src)) {
|
|
1228
|
+
$name = $ls[0];
|
|
1229
|
+
} else if ($extractTo === 'auto' || $extractTo) {
|
|
1230
|
+
// for several files - create new directory
|
|
1231
|
+
// create unique name for directory
|
|
1232
|
+
$src = $dir;
|
|
1233
|
+
$splits = elFinder::splitFileExtention(basename($path));
|
|
1234
|
+
$name = $splits[0];
|
|
1235
|
+
$test = dirname($path) . DIRECTORY_SEPARATOR . $name;
|
|
1236
|
+
if (file_exists($test) || is_link($test)) {
|
|
1237
|
+
$name = $this->uniqueName(dirname($path), $name, '-', false);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
if ($name !== '') {
|
|
1242
|
+
$result = dirname($path) . DIRECTORY_SEPARATOR . $name;
|
|
1243
|
+
|
|
1244
|
+
if (!rename($src, $result)) {
|
|
1245
|
+
$this->delTree($dir);
|
|
1246
|
+
return false;
|
|
1247
|
+
}
|
|
1248
|
+
} else {
|
|
1249
|
+
$dstDir = dirname($path);
|
|
1250
|
+
$result = array();
|
|
1251
|
+
foreach ($ls as $name) {
|
|
1252
|
+
$target = $dstDir . DIRECTORY_SEPARATOR . $name;
|
|
1253
|
+
if (self::localMoveRecursive($dir . DIRECTORY_SEPARATOR . $name, $target, true, $this->options['copyJoin'])) {
|
|
1254
|
+
$result[] = $target;
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
if (!$result) {
|
|
1258
|
+
$this->delTree($dir);
|
|
1259
|
+
return false;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
is_dir($dir) && $this->delTree($dir);
|
|
1264
|
+
|
|
1265
|
+
return (is_array($result) || file_exists($result)) ? $result : false;
|
|
1266
|
+
}
|
|
1267
|
+
//TODO: Add return statement here
|
|
1268
|
+
return false;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
/**
|
|
1272
|
+
* Create archive and return its path
|
|
1273
|
+
*
|
|
1274
|
+
* @param string $dir target dir
|
|
1275
|
+
* @param array $files files names list
|
|
1276
|
+
* @param string $name archive name
|
|
1277
|
+
* @param array $arc archiver options
|
|
1278
|
+
*
|
|
1279
|
+
* @return string|bool
|
|
1280
|
+
* @throws elFinderAbortException
|
|
1281
|
+
* @author Dmitry (dio) Levashov,
|
|
1282
|
+
* @author Alexey Sukhotin
|
|
1283
|
+
*/
|
|
1284
|
+
protected function _archive($dir, $files, $name, $arc)
|
|
1285
|
+
{
|
|
1286
|
+
return $this->makeArchive($dir, $files, $name, $arc);
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
/******************** Over write functions *************************/
|
|
1290
|
+
|
|
1291
|
+
/**
|
|
1292
|
+
* File path of local server side work file path
|
|
1293
|
+
*
|
|
1294
|
+
* @param string $path
|
|
1295
|
+
*
|
|
1296
|
+
* @return string
|
|
1297
|
+
* @author Naoki Sawada
|
|
1298
|
+
*/
|
|
1299
|
+
protected function getWorkFile($path)
|
|
1300
|
+
{
|
|
1301
|
+
return $path;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
/**
|
|
1305
|
+
* Delete dirctory trees
|
|
1306
|
+
*
|
|
1307
|
+
* @param string $localpath path need convert encoding to server encoding
|
|
1308
|
+
*
|
|
1309
|
+
* @return boolean
|
|
1310
|
+
* @throws elFinderAbortException
|
|
1311
|
+
* @author Naoki Sawada
|
|
1312
|
+
*/
|
|
1313
|
+
protected function delTree($localpath)
|
|
1314
|
+
{
|
|
1315
|
+
return $this->rmdirRecursive($localpath);
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
/**
|
|
1319
|
+
* Return fileinfo based on filename
|
|
1320
|
+
* For item ID based path file system
|
|
1321
|
+
* Please override if needed on each drivers
|
|
1322
|
+
*
|
|
1323
|
+
* @param string $path file cache
|
|
1324
|
+
*
|
|
1325
|
+
* @return array|boolean false
|
|
1326
|
+
*/
|
|
1327
|
+
protected function isNameExists($path)
|
|
1328
|
+
{
|
|
1329
|
+
$exists = file_exists($this->convEncIn($path));
|
|
1330
|
+
// restore locale
|
|
1331
|
+
$this->convEncOut();
|
|
1332
|
+
return $exists ? $this->stat($path) : false;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
/******************** Over write (Optimized) functions *************************/
|
|
1336
|
+
|
|
1337
|
+
/**
|
|
1338
|
+
* Recursive files search
|
|
1339
|
+
*
|
|
1340
|
+
* @param string $path dir path
|
|
1341
|
+
* @param string $q search string
|
|
1342
|
+
* @param array $mimes
|
|
1343
|
+
*
|
|
1344
|
+
* @return array
|
|
1345
|
+
* @throws elFinderAbortException
|
|
1346
|
+
* @author Dmitry (dio) Levashov
|
|
1347
|
+
* @author Naoki Sawada
|
|
1348
|
+
*/
|
|
1349
|
+
protected function doSearch($path, $q, $mimes)
|
|
1350
|
+
{
|
|
1351
|
+
if (!empty($this->doSearchCurrentQuery['matchMethod']) || $this->encoding || !class_exists('FilesystemIterator', false)) {
|
|
1352
|
+
// has custom match method or non UTF-8, use elFinderVolumeDriver::doSearch()
|
|
1353
|
+
return parent::doSearch($path, $q, $mimes);
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
$result = array();
|
|
1357
|
+
|
|
1358
|
+
$timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0;
|
|
1359
|
+
if ($timeout && $timeout < time()) {
|
|
1360
|
+
$this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
|
|
1361
|
+
return $result;
|
|
1362
|
+
}
|
|
1363
|
+
elFinder::extendTimeLimit($this->options['searchTimeout'] + 30);
|
|
1364
|
+
|
|
1365
|
+
$match = array();
|
|
1366
|
+
try {
|
|
1367
|
+
$iterator = new RecursiveIteratorIterator(
|
|
1368
|
+
new RecursiveCallbackFilterIterator(
|
|
1369
|
+
new RecursiveDirectoryIterator($path,
|
|
1370
|
+
FilesystemIterator::KEY_AS_PATHNAME |
|
|
1371
|
+
FilesystemIterator::SKIP_DOTS |
|
|
1372
|
+
((defined('RecursiveDirectoryIterator::FOLLOW_SYMLINKS') && $this->options['followSymLinks']) ?
|
|
1373
|
+
RecursiveDirectoryIterator::FOLLOW_SYMLINKS : 0)
|
|
1374
|
+
),
|
|
1375
|
+
array($this, 'localFileSystemSearchIteratorFilter')
|
|
1376
|
+
),
|
|
1377
|
+
RecursiveIteratorIterator::SELF_FIRST,
|
|
1378
|
+
RecursiveIteratorIterator::CATCH_GET_CHILD
|
|
1379
|
+
);
|
|
1380
|
+
foreach ($iterator as $key => $node) {
|
|
1381
|
+
if ($timeout && ($this->error || $timeout < time())) {
|
|
1382
|
+
!$this->error && $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($node->getPath)));
|
|
1383
|
+
break;
|
|
1384
|
+
}
|
|
1385
|
+
if ($node->isDir()) {
|
|
1386
|
+
if ($this->stripos($node->getFilename(), $q) !== false) {
|
|
1387
|
+
$match[] = $key;
|
|
1388
|
+
}
|
|
1389
|
+
} else {
|
|
1390
|
+
$match[] = $key;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
} catch (Exception $e) {
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
if ($match) {
|
|
1397
|
+
foreach ($match as $p) {
|
|
1398
|
+
if ($timeout && ($this->error || $timeout < time())) {
|
|
1399
|
+
!$this->error && $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode(dirname($p))));
|
|
1400
|
+
break;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
$stat = $this->stat($p);
|
|
1404
|
+
|
|
1405
|
+
if (!$stat) { // invalid links
|
|
1406
|
+
continue;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
if (!empty($stat['hidden']) || !$this->mimeAccepted($stat['mime'], $mimes)) {
|
|
1410
|
+
continue;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
if ((!$mimes || $stat['mime'] !== 'directory')) {
|
|
1414
|
+
$stat['path'] = $this->path($stat['hash']);
|
|
1415
|
+
if ($this->URL && !isset($stat['url'])) {
|
|
1416
|
+
$_path = str_replace(DIRECTORY_SEPARATOR, '/', substr($p, strlen($this->root) + 1));
|
|
1417
|
+
$stat['url'] = $this->URL . str_replace('%2F', '/', rawurlencode($_path));
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
$result[] = $stat;
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
return $result;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
/******************** Original local functions ************************
|
|
1429
|
+
*
|
|
1430
|
+
* @param $file
|
|
1431
|
+
* @param $key
|
|
1432
|
+
* @param $iterator
|
|
1433
|
+
*
|
|
1434
|
+
* @return bool
|
|
1435
|
+
*/
|
|
1436
|
+
|
|
1437
|
+
public function localFileSystemSearchIteratorFilter($file, $key, $iterator)
|
|
1438
|
+
{
|
|
1439
|
+
/* @var FilesystemIterator $file */
|
|
1440
|
+
/* @var RecursiveDirectoryIterator $iterator */
|
|
1441
|
+
$name = $file->getFilename();
|
|
1442
|
+
if ($this->doSearchCurrentQuery['excludes']) {
|
|
1443
|
+
foreach ($this->doSearchCurrentQuery['excludes'] as $exclude) {
|
|
1444
|
+
if ($this->stripos($name, $exclude) !== false) {
|
|
1445
|
+
return false;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
if ($iterator->hasChildren()) {
|
|
1450
|
+
if ($this->options['searchExDirReg'] && preg_match($this->options['searchExDirReg'], $key)) {
|
|
1451
|
+
return false;
|
|
1452
|
+
}
|
|
1453
|
+
return (bool)$this->attr($key, 'read', null, true);
|
|
1454
|
+
}
|
|
1455
|
+
return ($this->stripos($name, $this->doSearchCurrentQuery['q']) === false) ? false : true;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
/**
|
|
1459
|
+
* Creates a symbolic link
|
|
1460
|
+
*
|
|
1461
|
+
* @param string $target The target
|
|
1462
|
+
* @param string $link The link
|
|
1463
|
+
*
|
|
1464
|
+
* @return boolean ( result of symlink() )
|
|
1465
|
+
*/
|
|
1466
|
+
protected function localFileSystemSymlink($target, $link)
|
|
1467
|
+
{
|
|
1468
|
+
$res = false;
|
|
1469
|
+
$errlev = error_reporting();
|
|
1470
|
+
error_reporting($errlev ^ E_WARNING);
|
|
1471
|
+
if ($res = symlink(realpath($target), $link)) {
|
|
1472
|
+
$res = is_readable($link);
|
|
1473
|
+
}
|
|
1474
|
+
error_reporting($errlev);
|
|
1475
|
+
return $res;
|
|
1476
|
+
}
|
|
1477
|
+
} // END class
|