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 / elFinderVolumeMySQL.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
elFinderVolumeMySQL.class.php
1043 lines
1 <?php
2
3 /**
4 * Simple elFinder driver for MySQL.
5 *
6 * @author Dmitry (dio) Levashov
7 **/
8 class elFinderVolumeMySQL extends elFinderVolumeDriver
9 {
10
11 /**
12 * Driver id
13 * Must be started from letter and contains [a-z0-9]
14 * Used as part of volume id
15 *
16 * @var string
17 **/
18 protected $driverId = 'm';
19
20 /**
21 * Database object
22 *
23 * @var mysqli
24 **/
25 protected $db = null;
26
27 /**
28 * Tables to store files
29 *
30 * @var string
31 **/
32 protected $tbf = '';
33
34 /**
35 * Directory for tmp files
36 * If not set driver will try to use tmbDir as tmpDir
37 *
38 * @var string
39 **/
40 protected $tmpPath = '';
41
42 /**
43 * Numbers of sql requests (for debug)
44 *
45 * @var int
46 **/
47 protected $sqlCnt = 0;
48
49 /**
50 * Last db error message
51 *
52 * @var string
53 **/
54 protected $dbError = '';
55
56 /**
57 * This root has parent id
58 *
59 * @var boolean
60 */
61 protected $rootHasParent = false;
62
63 /**
64 * Constructor
65 * Extend options with required fields
66 *
67 * @author Dmitry (dio) Levashov
68 */
69 public function __construct()
70 {
71 $opts = array(
72 'host' => 'localhost',
73 'user' => '',
74 'pass' => '',
75 'db' => '',
76 'port' => null,
77 'socket' => null,
78 'files_table' => 'elfinder_file',
79 'tmbPath' => '',
80 'tmpPath' => '',
81 'rootCssClass' => 'elfinder-navbar-root-sql',
82 'noSessionCache' => array('hasdirs'),
83 'isLocalhost' => false
84 );
85 $this->options = array_merge($this->options, $opts);
86 $this->options['mimeDetect'] = 'internal';
87 }
88
89 /*********************************************************************/
90 /* INIT AND CONFIGURE */
91 /*********************************************************************/
92
93 /**
94 * Prepare driver before mount volume.
95 * Connect to db, check required tables and fetch root path
96 *
97 * @return bool
98 * @author Dmitry (dio) Levashov
99 **/
100 protected function init()
101 {
102
103 if (!($this->options['host'] || $this->options['socket'])
104 || !$this->options['user']
105 || !$this->options['pass']
106 || !$this->options['db']
107 || !$this->options['path']
108 || !$this->options['files_table']) {
109 return $this->setError('Required options "host", "socket", "user", "pass", "db", "path" or "files_table" are undefined.');
110 }
111
112 $err = null;
113 if ($this->db = @new mysqli($this->options['host'], $this->options['user'], $this->options['pass'], $this->options['db'], $this->options['port'], $this->options['socket'])) {
114 if ($this->db && $this->db->connect_error) {
115 $err = $this->db->connect_error;
116 }
117 } else {
118 $err = mysqli_connect_error();
119 }
120 if ($err) {
121 return $this->setError(array('Unable to connect to MySQL server.', $err));
122 }
123
124 if (!$this->needOnline && empty($this->ARGS['init'])) {
125 $this->db->close();
126 $this->db = null;
127 return true;
128 }
129
130 $this->db->set_charset('utf8');
131
132 if ($res = $this->db->query('SHOW TABLES')) {
133 while ($row = $res->fetch_array()) {
134 if ($row[0] == $this->options['files_table']) {
135 $this->tbf = $this->options['files_table'];
136 break;
137 }
138 }
139 }
140
141 if (!$this->tbf) {
142 return $this->setError('The specified database table cannot be found.');
143 }
144
145 $this->updateCache($this->options['path'], $this->_stat($this->options['path']));
146
147 // enable command archive
148 $this->options['useRemoteArchive'] = true;
149
150 // check isLocalhost
151 $this->isLocalhost = $this->options['isLocalhost'] || $this->options['host'] === 'localhost' || $this->options['host'] === '127.0.0.1' || $this->options['host'] === '::1';
152
153 return true;
154 }
155
156
157 /**
158 * Set tmp path
159 *
160 * @return void
161 * @throws elFinderAbortException
162 * @author Dmitry (dio) Levashov
163 */
164 protected function configure()
165 {
166 parent::configure();
167
168 if (($tmp = $this->options['tmpPath'])) {
169 if (!file_exists($tmp)) {
170 if (mkdir($tmp)) {
171 chmod($tmp, $this->options['tmbPathMode']);
172 }
173 }
174
175 $this->tmpPath = is_dir($tmp) && is_writable($tmp) ? $tmp : false;
176 }
177 if (!$this->tmpPath && ($tmp = elFinder::getStaticVar('commonTempPath'))) {
178 $this->tmpPath = $tmp;
179 }
180
181 // fallback of $this->tmp
182 if (!$this->tmpPath && $this->tmbPathWritable) {
183 $this->tmpPath = $this->tmbPath;
184 }
185
186 $this->mimeDetect = 'internal';
187 }
188
189 /**
190 * Close connection
191 *
192 * @return void
193 * @author Dmitry (dio) Levashov
194 **/
195 public function umount()
196 {
197 $this->db && $this->db->close();
198 }
199
200 /**
201 * Return debug info for client
202 *
203 * @return array
204 * @author Dmitry (dio) Levashov
205 **/
206 public function debug()
207 {
208 $debug = parent::debug();
209 $debug['sqlCount'] = $this->sqlCnt;
210 if ($this->dbError) {
211 $debug['dbError'] = $this->dbError;
212 }
213 return $debug;
214 }
215
216 /**
217 * Perform sql query and return result.
218 * Increase sqlCnt and save error if occured
219 *
220 * @param string $sql query
221 *
222 * @return bool|mysqli_result
223 * @author Dmitry (dio) Levashov
224 */
225 protected function query($sql)
226 {
227 $this->sqlCnt++;
228 $res = $this->db->query($sql);
229 if (!$res) {
230 $this->dbError = $this->db->error;
231 }
232 return $res;
233 }
234
235 /**
236 * Perform sql prepared statement and return result.
237 * Increase sqlCnt and save error if occurred.
238 *
239 * @param mysqli_stmt $stmt
240 * @return bool
241 */
242 protected function execute($stmt)
243 {
244 $this->sqlCnt++;
245 $res = $stmt->execute();
246 if (!$res) {
247 $this->dbError = $this->db->error;
248 }
249 return $res;
250 }
251
252 /**
253 * Create empty object with required mimetype
254 *
255 * @param string $path parent dir path
256 * @param string $name object name
257 * @param string $mime mime type
258 *
259 * @return bool
260 * @author Dmitry (dio) Levashov
261 **/
262 protected function make($path, $name, $mime)
263 {
264 $sql = 'INSERT INTO %s (`parent_id`, `name`, `size`, `mtime`, `mime`, `content`, `read`, `write`, `locked`, `hidden`, `width`, `height`) VALUES (\'%s\', \'%s\', 0, %d, \'%s\', \'\', \'%d\', \'%d\', \'%d\', \'%d\', 0, 0)';
265 $sql = sprintf($sql, $this->tbf, $path, $this->db->real_escape_string($name), time(), $mime, $this->defaults['read'], $this->defaults['write'], $this->defaults['locked'], $this->defaults['hidden']);
266 // echo $sql;
267 return $this->query($sql) && $this->db->affected_rows > 0;
268 }
269
270 /*********************************************************************/
271 /* FS API */
272 /*********************************************************************/
273
274 /**
275 * Cache dir contents
276 *
277 * @param string $path dir path
278 *
279 * @return string
280 * @author Dmitry Levashov
281 **/
282 protected function cacheDir($path)
283 {
284 $this->dirsCache[$path] = array();
285
286 $sql = 'SELECT f.id, f.parent_id, f.name, f.size, f.mtime AS ts, f.mime, f.read, f.write, f.locked, f.hidden, f.width, f.height, IF(ch.id, 1, 0) AS dirs
287 FROM ' . $this->tbf . ' AS f
288 LEFT JOIN ' . $this->tbf . ' AS ch ON ch.parent_id=f.id AND ch.mime=\'directory\'
289 WHERE f.parent_id=\'' . $path . '\'
290 GROUP BY f.id, ch.id';
291
292 $res = $this->query($sql);
293 if ($res) {
294 while ($row = $res->fetch_assoc()) {
295 $id = $row['id'];
296 if ($row['parent_id'] && $id != $this->root) {
297 $row['phash'] = $this->encode($row['parent_id']);
298 }
299
300 if ($row['mime'] == 'directory') {
301 unset($row['width']);
302 unset($row['height']);
303 $row['size'] = 0;
304 } else {
305 unset($row['dirs']);
306 }
307
308 unset($row['id']);
309 unset($row['parent_id']);
310
311
312 if (($stat = $this->updateCache($id, $row)) && empty($stat['hidden'])) {
313 $this->dirsCache[$path][] = $id;
314 }
315 }
316 }
317
318 return $this->dirsCache[$path];
319 }
320
321 /**
322 * Return array of parents paths (ids)
323 *
324 * @param int $path file path (id)
325 *
326 * @return array
327 * @author Dmitry (dio) Levashov
328 **/
329 protected function getParents($path)
330 {
331 $parents = array();
332
333 while ($path) {
334 if ($file = $this->stat($path)) {
335 array_unshift($parents, $path);
336 $path = isset($file['phash']) ? $this->decode($file['phash']) : false;
337 }
338 }
339
340 if (count($parents)) {
341 array_pop($parents);
342 }
343 return $parents;
344 }
345
346 /**
347 * Return correct file path for LOAD_FILE method
348 *
349 * @param string $path file path (id)
350 *
351 * @return string
352 * @author Troex Nevelin
353 **/
354 protected function loadFilePath($path)
355 {
356 $realPath = realpath($path);
357 if (DIRECTORY_SEPARATOR == '\\') { // windows
358 $realPath = str_replace('\\', '\\\\', $realPath);
359 }
360 return $this->db->real_escape_string($realPath);
361 }
362
363 /**
364 * Recursive files search
365 *
366 * @param string $path dir path
367 * @param string $q search string
368 * @param array $mimes
369 *
370 * @return array
371 * @throws elFinderAbortException
372 * @author Dmitry (dio) Levashov
373 */
374 protected function doSearch($path, $q, $mimes)
375 {
376 if (!empty($this->doSearchCurrentQuery['matchMethod'])) {
377 // has custom match method use elFinderVolumeDriver::doSearch()
378 return parent::doSearch($path, $q, $mimes);
379 }
380
381 $dirs = array();
382 $timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0;
383
384 if ($path != $this->root || $this->rootHasParent) {
385 $dirs = $inpath = array(intval($path));
386 while ($inpath) {
387 $in = '(' . join(',', $inpath) . ')';
388 $inpath = array();
389 $sql = 'SELECT f.id FROM %s AS f WHERE f.parent_id IN ' . $in . ' AND `mime` = \'directory\'';
390 $sql = sprintf($sql, $this->tbf);
391 if ($res = $this->query($sql)) {
392 $_dir = array();
393 while ($dat = $res->fetch_assoc()) {
394 $inpath[] = $dat['id'];
395 }
396 $dirs = array_merge($dirs, $inpath);
397 }
398 }
399 }
400
401 $result = array();
402
403 if ($mimes) {
404 $whrs = array();
405 foreach ($mimes as $mime) {
406 if (strpos($mime, '/') === false) {
407 $whrs[] = sprintf('f.mime LIKE \'%s/%%\'', $this->db->real_escape_string($mime));
408 } else {
409 $whrs[] = sprintf('f.mime = \'%s\'', $this->db->real_escape_string($mime));
410 }
411 }
412 $whr = join(' OR ', $whrs);
413 } else {
414 $whr = sprintf('f.name LIKE \'%%%s%%\'', $this->db->real_escape_string($q));
415 }
416 if ($dirs) {
417 $whr = '(' . $whr . ') AND (`parent_id` IN (' . join(',', $dirs) . '))';
418 }
419
420 $sql = 'SELECT f.id, f.parent_id, f.name, f.size, f.mtime AS ts, f.mime, f.read, f.write, f.locked, f.hidden, f.width, f.height, 0 AS dirs
421 FROM %s AS f
422 WHERE %s';
423
424 $sql = sprintf($sql, $this->tbf, $whr);
425
426 if (($res = $this->query($sql))) {
427 while ($row = $res->fetch_assoc()) {
428 if ($timeout && $timeout < time()) {
429 $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
430 break;
431 }
432
433 if (!$this->mimeAccepted($row['mime'], $mimes)) {
434 continue;
435 }
436 $id = $row['id'];
437 if ($id == $this->root) {
438 continue;
439 }
440 if ($row['parent_id'] && $id != $this->root) {
441 $row['phash'] = $this->encode($row['parent_id']);
442 }
443 $row['path'] = $this->_path($id);
444
445 if ($row['mime'] == 'directory') {
446 unset($row['width']);
447 unset($row['height']);
448 } else {
449 unset($row['dirs']);
450 }
451
452 unset($row['id']);
453 unset($row['parent_id']);
454
455 if (($stat = $this->updateCache($id, $row)) && empty($stat['hidden'])) {
456 $result[] = $stat;
457 }
458 }
459 }
460 return $result;
461 }
462
463
464 /*********************** paths/urls *************************/
465
466 /**
467 * Return parent directory path
468 *
469 * @param string $path file path
470 *
471 * @return string
472 * @author Dmitry (dio) Levashov
473 **/
474 protected function _dirname($path)
475 {
476 return ($stat = $this->stat($path)) ? (!empty($stat['phash']) ? $this->decode($stat['phash']) : $this->root) : false;
477 }
478
479 /**
480 * Return file name
481 *
482 * @param string $path file path
483 *
484 * @return string
485 * @author Dmitry (dio) Levashov
486 **/
487 protected function _basename($path)
488 {
489 return (($stat = $this->stat($path)) && isset($stat['name'])) ? $stat['name'] : false;
490 }
491
492 /**
493 * Join dir name and file name and return full path
494 *
495 * @param string $dir
496 * @param string $name
497 *
498 * @return string
499 * @author Dmitry (dio) Levashov
500 **/
501 protected function _joinPath($dir, $name)
502 {
503 $sql = 'SELECT id FROM ' . $this->tbf . ' WHERE parent_id=\'' . $dir . '\' AND name=\'' . $this->db->real_escape_string($name) . '\'';
504
505 if (($res = $this->query($sql)) && ($r = $res->fetch_assoc())) {
506 $this->updateCache($r['id'], $this->_stat($r['id']));
507 return $r['id'];
508 }
509 return -1;
510 }
511
512 /**
513 * Return normalized path, this works the same as os.path.normpath() in Python
514 *
515 * @param string $path path
516 *
517 * @return string
518 * @author Troex Nevelin
519 **/
520 protected function _normpath($path)
521 {
522 return $path;
523 }
524
525 /**
526 * Return file path related to root dir
527 *
528 * @param string $path file path
529 *
530 * @return string
531 * @author Dmitry (dio) Levashov
532 **/
533 protected function _relpath($path)
534 {
535 return $path;
536 }
537
538 /**
539 * Convert path related to root dir into real path
540 *
541 * @param string $path file path
542 *
543 * @return string
544 * @author Dmitry (dio) Levashov
545 **/
546 protected function _abspath($path)
547 {
548 return $path;
549 }
550
551 /**
552 * Return fake path started from root dir
553 *
554 * @param string $path file path
555 *
556 * @return string
557 * @author Dmitry (dio) Levashov
558 **/
559 protected function _path($path)
560 {
561 if (($file = $this->stat($path)) == false) {
562 return '';
563 }
564
565 $parentsIds = $this->getParents($path);
566 $path = '';
567 foreach ($parentsIds as $id) {
568 $dir = $this->stat($id);
569 $path .= $dir['name'] . $this->separator;
570 }
571 return $path . $file['name'];
572 }
573
574 /**
575 * Return true if $path is children of $parent
576 *
577 * @param string $path path to check
578 * @param string $parent parent path
579 *
580 * @return bool
581 * @author Dmitry (dio) Levashov
582 **/
583 protected function _inpath($path, $parent)
584 {
585 return $path == $parent
586 ? true
587 : in_array($parent, $this->getParents($path));
588 }
589
590 /***************** file stat ********************/
591 /**
592 * Return stat for given path.
593 * Stat contains following fields:
594 * - (int) size file size in b. required
595 * - (int) ts file modification time in unix time. required
596 * - (string) mime mimetype. required for folders, others - optionally
597 * - (bool) read read permissions. required
598 * - (bool) write write permissions. required
599 * - (bool) locked is object locked. optionally
600 * - (bool) hidden is object hidden. optionally
601 * - (string) alias for symlinks - link target path relative to root path. optionally
602 * - (string) target for symlinks - link target path. optionally
603 * If file does not exists - returns empty array or false.
604 *
605 * @param string $path file path
606 *
607 * @return array|false
608 * @author Dmitry (dio) Levashov
609 **/
610 protected function _stat($path)
611 {
612 $sql = 'SELECT f.id, f.parent_id, f.name, f.size, f.mtime AS ts, f.mime, f.read, f.write, f.locked, f.hidden, f.width, f.height, IF(ch.id, 1, 0) AS dirs
613 FROM ' . $this->tbf . ' AS f
614 LEFT JOIN ' . $this->tbf . ' AS ch ON ch.parent_id=f.id AND ch.mime=\'directory\'
615 WHERE f.id=\'' . $path . '\'
616 GROUP BY f.id, ch.id';
617
618 $res = $this->query($sql);
619
620 if ($res) {
621 $stat = $res->fetch_assoc();
622 if ($stat['id'] == $this->root) {
623 $this->rootHasParent = true;
624 $stat['parent_id'] = '';
625 }
626 if ($stat['parent_id']) {
627 $stat['phash'] = $this->encode($stat['parent_id']);
628 }
629 if ($stat['mime'] == 'directory') {
630 unset($stat['width']);
631 unset($stat['height']);
632 $stat['size'] = 0;
633 } else {
634 if (!$stat['mime']) {
635 unset($stat['mime']);
636 }
637 unset($stat['dirs']);
638 }
639 unset($stat['id']);
640 unset($stat['parent_id']);
641 return $stat;
642
643 }
644 return array();
645 }
646
647 /**
648 * Return true if path is dir and has at least one childs directory
649 *
650 * @param string $path dir path
651 *
652 * @return bool
653 * @author Dmitry (dio) Levashov
654 **/
655 protected function _subdirs($path)
656 {
657 return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
658 }
659
660 /**
661 * Return object width and height
662 * Usualy used for images, but can be realize for video etc...
663 *
664 * @param string $path file path
665 * @param string $mime file mime type
666 *
667 * @return string
668 * @author Dmitry (dio) Levashov
669 **/
670 protected function _dimensions($path, $mime)
671 {
672 return ($stat = $this->stat($path)) && isset($stat['width']) && isset($stat['height']) ? $stat['width'] . 'x' . $stat['height'] : '';
673 }
674
675 /******************** file/dir content *********************/
676
677 /**
678 * Return files list in directory.
679 *
680 * @param string $path dir path
681 *
682 * @return array
683 * @author Dmitry (dio) Levashov
684 **/
685 protected function _scandir($path)
686 {
687 return isset($this->dirsCache[$path])
688 ? $this->dirsCache[$path]
689 : $this->cacheDir($path);
690 }
691
692 /**
693 * Open file and return file pointer
694 *
695 * @param string $path file path
696 * @param string $mode open file mode (ignored in this driver)
697 *
698 * @return resource|false
699 * @author Dmitry (dio) Levashov
700 **/
701 protected function _fopen($path, $mode = 'rb')
702 {
703 $fp = $this->tmpPath
704 ? fopen($this->getTempFile($path), 'w+')
705 : $this->tmpfile();
706
707
708 if ($fp) {
709 if (($res = $this->query('SELECT content FROM ' . $this->tbf . ' WHERE id=\'' . $path . '\''))
710 && ($r = $res->fetch_assoc())) {
711 fwrite($fp, $r['content']);
712 rewind($fp);
713 return $fp;
714 } else {
715 $this->_fclose($fp, $path);
716 }
717 }
718
719 return false;
720 }
721
722 /**
723 * Close opened file
724 *
725 * @param resource $fp file pointer
726 * @param string $path
727 *
728 * @return void
729 * @author Dmitry (dio) Levashov
730 */
731 protected function _fclose($fp, $path = '')
732 {
733 is_resource($fp) && fclose($fp);
734 if ($path) {
735 $file = $this->getTempFile($path);
736 is_file($file) && unlink($file);
737 }
738 }
739
740 /******************** file/dir manipulations *************************/
741
742 /**
743 * Create dir and return created dir path or false on failed
744 *
745 * @param string $path parent dir path
746 * @param string $name new directory name
747 *
748 * @return string|bool
749 * @author Dmitry (dio) Levashov
750 **/
751 protected function _mkdir($path, $name)
752 {
753 return $this->make($path, $name, 'directory') ? $this->_joinPath($path, $name) : false;
754 }
755
756 /**
757 * Create file and return it's path or false on failed
758 *
759 * @param string $path parent dir path
760 * @param string $name new file name
761 *
762 * @return string|bool
763 * @author Dmitry (dio) Levashov
764 **/
765 protected function _mkfile($path, $name)
766 {
767 return $this->make($path, $name, '') ? $this->_joinPath($path, $name) : false;
768 }
769
770 /**
771 * Create symlink. FTP driver does not support symlinks.
772 *
773 * @param string $target link target
774 * @param string $path symlink path
775 * @param string $name
776 *
777 * @return bool
778 * @author Dmitry (dio) Levashov
779 */
780 protected function _symlink($target, $path, $name)
781 {
782 return false;
783 }
784
785 /**
786 * Copy file into another file
787 *
788 * @param string $source source file path
789 * @param string $targetDir target directory path
790 * @param string $name new file name
791 *
792 * @return bool
793 * @author Dmitry (dio) Levashov
794 **/
795 protected function _copy($source, $targetDir, $name)
796 {
797 $this->clearcache();
798 $id = $this->_joinPath($targetDir, $name);
799
800 $sql = $id > 0
801 ? sprintf('REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height, `read`, `write`, `locked`, `hidden`) (SELECT %d, %d, name, content, size, mtime, mime, width, height, `read`, `write`, `locked`, `hidden` FROM %s WHERE id=%d)', $this->tbf, $id, $this->_dirname($id), $this->tbf, $source)
802 : sprintf('INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height, `read`, `write`, `locked`, `hidden`) SELECT %d, \'%s\', content, size, %d, mime, width, height, `read`, `write`, `locked`, `hidden` FROM %s WHERE id=%d', $this->tbf, $targetDir, $this->db->real_escape_string($name), time(), $this->tbf, $source);
803
804 return $this->query($sql);
805 }
806
807 /**
808 * Move file into another parent dir.
809 * Return new file path or false.
810 *
811 * @param string $source source file path
812 * @param $targetDir
813 * @param string $name file name
814 *
815 * @return bool|string
816 * @internal param string $target target dir path
817 * @author Dmitry (dio) Levashov
818 */
819 protected function _move($source, $targetDir, $name)
820 {
821 $sql = 'UPDATE %s SET parent_id=%d, name=\'%s\' WHERE id=%d LIMIT 1';
822 $sql = sprintf($sql, $this->tbf, $targetDir, $this->db->real_escape_string($name), $source);
823 return $this->query($sql) && $this->db->affected_rows > 0 ? $source : false;
824 }
825
826 /**
827 * Remove file
828 *
829 * @param string $path file path
830 *
831 * @return bool
832 * @author Dmitry (dio) Levashov
833 **/
834 protected function _unlink($path)
835 {
836 return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime!=\'directory\' LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
837 }
838
839 /**
840 * Remove dir
841 *
842 * @param string $path dir path
843 *
844 * @return bool
845 * @author Dmitry (dio) Levashov
846 **/
847 protected function _rmdir($path)
848 {
849 return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime=\'directory\' LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
850 }
851
852 /**
853 * undocumented function
854 *
855 * @param $path
856 * @param $fp
857 *
858 * @author Dmitry Levashov
859 */
860 protected function _setContent($path, $fp)
861 {
862 elFinder::rewind($fp);
863 $fstat = fstat($fp);
864 $size = $fstat['size'];
865
866
867 }
868
869 /**
870 * Create new file and write into it from file pointer.
871 * Return new file path or false on error.
872 *
873 * @param resource $fp file pointer
874 * @param string $dir target dir path
875 * @param string $name file name
876 * @param array $stat file stat (required by some virtual fs)
877 *
878 * @return bool|string
879 * @author Dmitry (dio) Levashov
880 **/
881 protected function _save($fp, $dir, $name, $stat)
882 {
883 $this->clearcache();
884
885 $mime = !empty($stat['mime']) ? $stat['mime'] : $this->mimetype($name, true);
886 $w = !empty($stat['width']) ? $stat['width'] : 0;
887 $h = !empty($stat['height']) ? $stat['height'] : 0;
888 $ts = !empty($stat['ts']) ? $stat['ts'] : time();
889
890 $id = $this->_joinPath($dir, $name);
891 if (!isset($stat['size'])) {
892 $stat = fstat($fp);
893 $size = $stat['size'];
894 } else {
895 $size = $stat['size'];
896 }
897
898 if ($this->isLocalhost && ($tmpfile = tempnam($this->tmpPath, $this->id))) {
899 if (($trgfp = fopen($tmpfile, 'wb')) == false) {
900 unlink($tmpfile);
901 } else {
902 elFinder::rewind($fp);
903 stream_copy_to_stream($fp, $trgfp);
904 fclose($trgfp);
905 chmod($tmpfile, 0644);
906
907 $sql = $id > 0
908 ? 'REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height) VALUES (' . $id . ', ?, ?, LOAD_FILE(?), ?, ?, ?, ?, ?)'
909 : 'INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height) VALUES (?, ?, LOAD_FILE(?), ?, ?, ?, ?, ?)';
910 $stmt = $this->db->prepare(sprintf($sql, $this->tbf));
911 $path = $this->loadFilePath($tmpfile);
912 $stmt->bind_param("issiisii", $dir, $name, $path, $size, $ts, $mime, $w, $h);
913
914 $res = $this->execute($stmt);
915 unlink($tmpfile);
916
917 if ($res) {
918 return $id > 0 ? $id : $this->db->insert_id;
919 }
920 }
921 }
922
923
924 $content = '';
925 elFinder::rewind($fp);
926 while (!feof($fp)) {
927 $content .= fread($fp, 8192);
928 }
929
930 $sql = $id > 0
931 ? 'REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height) VALUES (' . $id . ', ?, ?, ?, ?, ?, ?, ?, ?)'
932 : 'INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height) VALUES (?, ?, ?, ?, ?, ?, ?, ?)';
933 $stmt = $this->db->prepare(sprintf($sql, $this->tbf));
934 $stmt->bind_param("issiisii", $dir, $name, $content, $size, $ts, $mime, $w, $h);
935
936 unset($content);
937
938 if ($this->execute($stmt)) {
939 return $id > 0 ? $id : $this->db->insert_id;
940 }
941
942 return false;
943 }
944
945 /**
946 * Get file contents
947 *
948 * @param string $path file path
949 *
950 * @return string|false
951 * @author Dmitry (dio) Levashov
952 **/
953 protected function _getContents($path)
954 {
955 return ($res = $this->query(sprintf('SELECT content FROM %s WHERE id=%d', $this->tbf, $path))) && ($r = $res->fetch_assoc()) ? $r['content'] : false;
956 }
957
958 /**
959 * Write a string to a file
960 *
961 * @param string $path file path
962 * @param string $content new file content
963 *
964 * @return bool
965 * @author Dmitry (dio) Levashov
966 **/
967 protected function _filePutContents($path, $content)
968 {
969 return $this->query(sprintf('UPDATE %s SET content=\'%s\', size=%d, mtime=%d WHERE id=%d LIMIT 1', $this->tbf, $this->db->real_escape_string($content), strlen($content), time(), $path));
970 }
971
972 /**
973 * Detect available archivers
974 *
975 * @return void
976 **/
977 protected function _checkArchivers()
978 {
979 return;
980 }
981
982 /**
983 * chmod implementation
984 *
985 * @param string $path
986 * @param string $mode
987 *
988 * @return bool
989 */
990 protected function _chmod($path, $mode)
991 {
992 return false;
993 }
994
995 /**
996 * Unpack archive
997 *
998 * @param string $path archive path
999 * @param array $arc archiver command and arguments (same as in $this->archivers)
1000 *
1001 * @return void
1002 * @author Dmitry (dio) Levashov
1003 * @author Alexey Sukhotin
1004 **/
1005 protected function _unpack($path, $arc)
1006 {
1007 return;
1008 }
1009
1010 /**
1011 * Extract files from archive
1012 *
1013 * @param string $path archive path
1014 * @param array $arc archiver command and arguments (same as in $this->archivers)
1015 *
1016 * @return true
1017 * @author Dmitry (dio) Levashov,
1018 * @author Alexey Sukhotin
1019 **/
1020 protected function _extract($path, $arc)
1021 {
1022 return false;
1023 }
1024
1025 /**
1026 * Create archive and return its path
1027 *
1028 * @param string $dir target dir
1029 * @param array $files files names list
1030 * @param string $name archive name
1031 * @param array $arc archiver options
1032 *
1033 * @return string|bool
1034 * @author Dmitry (dio) Levashov,
1035 * @author Alexey Sukhotin
1036 **/
1037 protected function _archive($dir, $files, $name, $arc)
1038 {
1039 return false;
1040 }
1041
1042 } // END class
1043