PluginProbe ʕ •ᴥ•ʔ
Advanced File Manager – Ultimate File Manager for WordPress And Document Library Solution / trunk
Advanced File Manager – Ultimate File Manager for WordPress And Document Library Solution vtrunk
trunk 4.1.5 4.1.6 5.0 5.2.13 5.2.14 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.4.0 5.4.1 5.4.10 5.4.11 5.4.12 5.4.2 5.4.3 5.4.4 5.4.5 5.4.6 5.4.7 5.4.8
file-manager-advanced / application / library / php / elFinderConnector.class.php
file-manager-advanced / application / library / php Last commit date
.tmp 10 months ago editors 4 weeks ago libs 7 years ago plugins 3 years ago resources 7 years ago MySQLStorage.sql 1 year ago autoload.php 10 months ago connector.maximal.php-dist 1 year ago connector.minimal.php-dist 1 year ago elFinder.class.php 4 weeks ago elFinderConnector.class.php 4 weeks ago elFinderFlysystemGoogleDriveNetmount.php 5 years ago elFinderPlugin.php 7 years ago elFinderSession.php 4 years ago elFinderSessionInterface.php 7 years ago elFinderVolumeBox.class.php 5 years ago elFinderVolumeDriver.class.php 4 weeks ago elFinderVolumeDropbox.class.php 1 year ago elFinderVolumeDropbox2.class.php 4 weeks ago elFinderVolumeFTP.class.php 5 years ago elFinderVolumeGoogleDrive.class.php 5 years ago elFinderVolumeGroup.class.php 7 years ago elFinderVolumeLocalFileSystem.class.php 2 years ago elFinderVolumeMySQL.class.php 10 months ago elFinderVolumeOneDrive.class.php 4 weeks ago elFinderVolumeSFTPphpseclib.class.php 4 weeks ago elFinderVolumeTrash.class.php 7 years ago elFinderVolumeTrashMySQL.class.php 7 years ago mime.types 3 years ago
elFinderConnector.class.php
381 lines
1 <?php
2
3 /**
4 * Default elFinder connector
5 *
6 * @author Dmitry (dio) Levashov
7 **/
8 class elFinderConnector
9 {
10 /**
11 * elFinder instance
12 *
13 * @var elFinder
14 **/
15 protected $elFinder;
16
17 /**
18 * Options
19 *
20 * @var array
21 **/
22 protected $options = array();
23
24 /**
25 * Must be use output($data) $data['header']
26 *
27 * @var string
28 * @deprecated
29 **/
30 protected $header = '';
31
32 /**
33 * HTTP request method
34 *
35 * @var string
36 */
37 protected $reqMethod = '';
38
39 /**
40 * Content type of output JSON
41 *
42 * @var string
43 */
44 protected static $contentType = 'Content-Type: application/json; charset=utf-8';
45
46 /**
47 * Constructor
48 *
49 * @param $elFinder
50 * @param bool $debug
51 *
52 * @author Dmitry (dio) Levashov
53 */
54 public function __construct($elFinder, $debug = false)
55 {
56
57 $this->elFinder = $elFinder;
58 $this->reqMethod = strtoupper($_SERVER["REQUEST_METHOD"]);
59 if ($debug) {
60 self::$contentType = 'Content-Type: text/plain; charset=utf-8';
61 }
62 }
63
64 /**
65 * Execute elFinder command and output result
66 *
67 * @return void
68 * @throws Exception
69 * @author Dmitry (dio) Levashov
70 */
71 public function run()
72 {
73 $isPost = $this->reqMethod === 'POST';
74 $src = $isPost ? array_merge($_GET, $_POST) : $_GET;
75 $maxInputVars = (!$src || isset($src['targets'])) ? ini_get('max_input_vars') : null;
76 if ((!$src || $maxInputVars) && $rawPostData = file_get_contents('php://input')) {
77 // for max_input_vars and supports IE XDomainRequest()
78 $parts = explode('&', $rawPostData);
79 if (!$src || $maxInputVars < count($parts)) {
80 $src = array();
81 foreach ($parts as $part) {
82 list($key, $value) = array_pad(explode('=', $part), 2, '');
83 $key = rawurldecode($key);
84 if (preg_match('/^(.+?)\[([^\[\]]*)\]$/', $key, $m)) {
85 $key = $m[1];
86 $idx = $m[2];
87 if (!isset($src[$key])) {
88 $src[$key] = array();
89 }
90 if ($idx) {
91 $src[$key][$idx] = rawurldecode($value);
92 } else {
93 $src[$key][] = rawurldecode($value);
94 }
95 } else {
96 $src[$key] = rawurldecode($value);
97 }
98 }
99 $_POST = $this->input_filter($src);
100 $_REQUEST = $this->input_filter(array_merge_recursive($src, $_REQUEST));
101 }
102 }
103
104 if (isset($src['targets']) && $this->elFinder->maxTargets && count($src['targets']) > $this->elFinder->maxTargets) {
105 $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_MAX_TARGTES)));
106 }
107
108 $cmd = isset($src['cmd']) ? $src['cmd'] : '';
109 $args = array();
110
111 if (!function_exists('json_encode')) {
112 $error = $this->elFinder->error(elFinder::ERROR_CONF, elFinder::ERROR_CONF_NO_JSON);
113 $this->output(array('error' => '{"error":["' . implode('","', $error) . '"]}', 'raw' => true));
114 }
115
116 if (!$this->elFinder->loaded()) {
117 $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_CONF, elFinder::ERROR_CONF_NO_VOL), 'debug' => $this->elFinder->mountErrors));
118 }
119
120 // telepat_mode: on
121 if (!$cmd && $isPost) {
122 $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_UPLOAD, elFinder::ERROR_UPLOAD_TOTAL_SIZE), 'header' => 'Content-Type: text/html'));
123 }
124 // telepat_mode: off
125
126 if (!$this->elFinder->commandExists($cmd)) {
127 $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_UNKNOWN_CMD)));
128 }
129
130 // collect required arguments to exec command
131 $hasFiles = false;
132 foreach ($this->elFinder->commandArgsList($cmd) as $name => $req) {
133 if ($name === 'FILES') {
134 if (isset($_FILES)) {
135 $hasFiles = true;
136 } elseif ($req) {
137 $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_INV_PARAMS, $cmd)));
138 }
139 } else {
140 $arg = isset($src[$name]) ? $src[$name] : '';
141
142 if (!is_array($arg) && $req !== '') {
143 $arg = trim($arg);
144 }
145 if ($req && $arg === '') {
146 $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_INV_PARAMS, $cmd)));
147 }
148 $args[$name] = $arg;
149 }
150 }
151
152 $args['debug'] = isset($src['debug']) ? !!$src['debug'] : false;
153
154 $args = $this->input_filter($args);
155 if ($hasFiles) {
156 $args['FILES'] = $_FILES;
157 }
158
159 try {
160 $this->output($this->elFinder->exec($cmd, $args));
161 } catch (elFinderAbortException $e) {
162 // connection aborted
163 // unlock session data for multiple access
164 $this->elFinder->getSession()->close();
165 // HTTP response code
166 header('HTTP/1.0 204 No Content');
167 // clear output buffer
168 while (ob_get_level() && ob_end_clean()) {
169 }
170 exit();
171 }
172 }
173
174 /**
175 * Sets the header.
176 *
177 * @param array|string $value HTTP header(s)
178 */
179 public function setHeader($value)
180 {
181 $this->header = $value;
182 }
183
184 /**
185 * Output json
186 *
187 * @param array data to output
188 *
189 * @return void
190 * @throws elFinderAbortException
191 * @author Dmitry (dio) Levashov
192 */
193 protected function output(array $data)
194 {
195 // unlock session data for multiple access
196 $this->elFinder->getSession()->close();
197 // client disconnect should abort
198 ignore_user_abort(false);
199
200 if ($this->header) {
201 self::sendHeader($this->header);
202 }
203
204 if (isset($data['pointer'])) {
205 // set time limit to 0
206 elFinder::extendTimeLimit(0);
207
208 // send optional header
209 if (!empty($data['header'])) {
210 self::sendHeader($data['header']);
211 }
212
213 // clear output buffer
214 while (ob_get_level() && ob_end_clean()) {
215 }
216
217 $toEnd = true;
218 $fp = $data['pointer'];
219 $sendData = !($this->reqMethod === 'HEAD' || !empty($data['info']['xsendfile']));
220 $psize = null;
221 if (($this->reqMethod === 'GET' || !$sendData)
222 && (elFinder::isSeekableStream($fp) || elFinder::isSeekableUrl($fp))
223 && (array_search('Accept-Ranges: none', headers_list()) === false)) {
224 header('Accept-Ranges: bytes');
225 if (!empty($_SERVER['HTTP_RANGE'])) {
226 $size = $data['info']['size'];
227 $end = $size - 1;
228 if (preg_match('/bytes=(\d*)-(\d*)(,?)/i', $_SERVER['HTTP_RANGE'], $matches)) {
229 if (empty($matches[3])) {
230 if (empty($matches[1]) && $matches[1] !== '0') {
231 $start = $size - $matches[2];
232 } else {
233 $start = intval($matches[1]);
234 if (!empty($matches[2])) {
235 $end = intval($matches[2]);
236 if ($end >= $size) {
237 $end = $size - 1;
238 }
239 $toEnd = ($end == ($size - 1));
240 }
241 }
242 $psize = $end - $start + 1;
243
244 header('HTTP/1.1 206 Partial Content');
245 header('Content-Length: ' . $psize);
246 header('Content-Range: bytes ' . $start . '-' . $end . '/' . $size);
247
248 // Apache mod_xsendfile dose not support range request
249 if (isset($data['info']['xsendfile']) && strtolower($data['info']['xsendfile']) === 'x-sendfile') {
250 if (function_exists('header_remove')) {
251 header_remove($data['info']['xsendfile']);
252 } else {
253 header($data['info']['xsendfile'] . ':');
254 }
255 unset($data['info']['xsendfile']);
256 if ($this->reqMethod !== 'HEAD') {
257 $sendData = true;
258 }
259 }
260
261 $sendData && !elFinder::isSeekableUrl($fp) && fseek($fp, $start);
262 }
263 }
264 }
265 if ($sendData && is_null($psize)) {
266 elFinder::rewind($fp);
267 }
268 } else {
269 header('Accept-Ranges: none');
270 if (isset($data['info']) && !$data['info']['size']) {
271 if (function_exists('header_remove')) {
272 header_remove('Content-Length');
273 } else {
274 header('Content-Length:');
275 }
276 }
277 }
278
279 if ($sendData) {
280 if ($toEnd || elFinder::isSeekableUrl($fp)) {
281 // PHP < 5.6 has a bug of fpassthru
282 // see https://bugs.php.net/bug.php?id=66736
283 if (version_compare(PHP_VERSION, '5.6', '<')) {
284 file_put_contents('php://output', $fp);
285 } else {
286 fpassthru($fp);
287 }
288 } else {
289 $out = fopen('php://output', 'wb');
290 stream_copy_to_stream($fp, $out, $psize);
291 fclose($out);
292 }
293 }
294
295 if (!empty($data['volume'])) {
296 $data['volume']->close($fp, $data['info']['hash']);
297 } else {
298 fclose($fp);
299 }
300 exit();
301 } else {
302 self::outputJson($data);
303 exit(0);
304 }
305 }
306
307 /**
308 * Remove null & stripslashes applies on "magic_quotes_gpc"
309 *
310 * @param mixed $args
311 *
312 * @return mixed
313 * @author Naoki Sawada
314 */
315 protected function input_filter($args)
316 {
317 static $magic_quotes_gpc = NULL;
318
319 if ($magic_quotes_gpc === NULL)
320 $magic_quotes_gpc = (version_compare(PHP_VERSION, '5.4', '<') && get_magic_quotes_gpc());
321
322 if (is_array($args)) {
323 return array_map(array(& $this, 'input_filter'), $args);
324 }
325 $res = str_replace("\0", '', $args);
326 $magic_quotes_gpc && ($res = stripslashes($res));
327 return $res;
328 }
329
330 /**
331 * Send HTTP header
332 *
333 * @param string|array $header optional header
334 */
335 protected static function sendHeader($header = null)
336 {
337 if ($header) {
338 if (is_array($header)) {
339 foreach ($header as $h) {
340 header($h);
341 }
342 } else {
343 header($header);
344 }
345 }
346 }
347
348 /**
349 * Output JSON
350 *
351 * @param array $data
352 */
353 public static function outputJson($data)
354 {
355 // send header
356 $header = isset($data['header']) ? $data['header'] : self::$contentType;
357 self::sendHeader($header);
358
359 unset($data['header']);
360
361 if (!empty($data['raw']) && isset($data['error'])) {
362 $out = $data['error'];
363 } else {
364 if (isset($data['debug']) && isset($data['debug']['backendErrors'])) {
365 $data['debug']['backendErrors'] = array_merge($data['debug']['backendErrors'], elFinder::$phpErrors);
366 }
367 $out = json_encode($data);
368 }
369
370 // clear output buffer
371 while (ob_get_level() && ob_end_clean()) {
372 }
373
374 header('Content-Length: ' . strlen($out));
375
376 echo $out;
377
378 flush();
379 }
380 }// END class
381