PluginProbe ʕ •ᴥ•ʔ
File Manager Pro – Filester / 1.9
File Manager Pro – Filester v1.9
2.1.1 trunk 1.6.1 1.7.6 1.8 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9 2.0 2.0.1 2.0.2 2.1.0
filester / includes / File_manager / lib / php / elFinderVolumeMySQL.class.php
filester / includes / File_manager / lib / php Last commit date
.tmp 9 months ago editors 9 months ago libs 9 months ago plugins 9 months ago resources 9 months ago MySQLStorage.sql 9 months ago autoload.php 9 months ago elFinder.class.php 9 months ago elFinderConnector.class.php 9 months ago elFinderFlysystemGoogleDriveNetmount.php 9 months ago elFinderPlugin.php 9 months ago elFinderSession.php 9 months ago elFinderSessionInterface.php 9 months ago elFinderVolumeBox.class.php 9 months ago elFinderVolumeDriver.class.php 9 months ago elFinderVolumeDropbox.class.php 9 months ago elFinderVolumeDropbox2.class.php 9 months ago elFinderVolumeFTP.class.php 9 months ago elFinderVolumeGoogleDrive.class.php 9 months ago elFinderVolumeGroup.class.php 9 months ago elFinderVolumeLocalFileSystem.class.php 9 months ago elFinderVolumeMySQL.class.php 9 months ago elFinderVolumeOneDrive.class.php 9 months ago elFinderVolumeSFTPphpseclib.class.php 9 months ago elFinderVolumeTrash.class.php 9 months ago elFinderVolumeTrashMySQL.class.php 9 months ago mime.types 9 months 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