PluginProbe ʕ •ᴥ•ʔ
File Manager Pro – Filester / 1.8
File Manager Pro – Filester v1.8
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 2 years ago editors 2 years ago libs 2 years ago plugins 2 years ago resources 2 years ago MySQLStorage.sql 2 years ago autoload.php 2 years ago elFinder.class.php 2 years ago elFinderConnector.class.php 2 years ago elFinderFlysystemGoogleDriveNetmount.php 2 years ago elFinderPlugin.php 2 years ago elFinderSession.php 2 years ago elFinderSessionInterface.php 2 years ago elFinderVolumeBox.class.php 2 years ago elFinderVolumeDriver.class.php 2 years ago elFinderVolumeDropbox.class.php 2 years ago elFinderVolumeDropbox2.class.php 2 years ago elFinderVolumeFTP.class.php 2 years ago elFinderVolumeGoogleDrive.class.php 2 years ago elFinderVolumeGroup.class.php 2 years ago elFinderVolumeLocalFileSystem.class.php 2 years ago elFinderVolumeMySQL.class.php 2 years ago elFinderVolumeOneDrive.class.php 2 years ago elFinderVolumeSFTPphpseclib.class.php 2 years ago elFinderVolumeTrash.class.php 2 years ago elFinderVolumeTrashMySQL.class.php 2 years ago index.php 2 years ago mime.types 2 years ago
elFinderVolumeMySQL.class.php
1023 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 * Create empty object with required mimetype
237 *
238 * @param string $path parent dir path
239 * @param string $name object name
240 * @param string $mime mime type
241 *
242 * @return bool
243 * @author Dmitry (dio) Levashov
244 **/
245 protected function make($path, $name, $mime)
246 {
247 $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)';
248 $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']);
249 // echo $sql;
250 return $this->query($sql) && $this->db->affected_rows > 0;
251 }
252
253 /*********************************************************************/
254 /* FS API */
255 /*********************************************************************/
256
257 /**
258 * Cache dir contents
259 *
260 * @param string $path dir path
261 *
262 * @return string
263 * @author Dmitry Levashov
264 **/
265 protected function cacheDir($path)
266 {
267 $this->dirsCache[$path] = array();
268
269 $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
270 FROM ' . $this->tbf . ' AS f
271 LEFT JOIN ' . $this->tbf . ' AS ch ON ch.parent_id=f.id AND ch.mime=\'directory\'
272 WHERE f.parent_id=\'' . $path . '\'
273 GROUP BY f.id, ch.id';
274
275 $res = $this->query($sql);
276 if ($res) {
277 while ($row = $res->fetch_assoc()) {
278 $id = $row['id'];
279 if ($row['parent_id'] && $id != $this->root) {
280 $row['phash'] = $this->encode($row['parent_id']);
281 }
282
283 if ($row['mime'] == 'directory') {
284 unset($row['width']);
285 unset($row['height']);
286 $row['size'] = 0;
287 } else {
288 unset($row['dirs']);
289 }
290
291 unset($row['id']);
292 unset($row['parent_id']);
293
294
295 if (($stat = $this->updateCache($id, $row)) && empty($stat['hidden'])) {
296 $this->dirsCache[$path][] = $id;
297 }
298 }
299 }
300
301 return $this->dirsCache[$path];
302 }
303
304 /**
305 * Return array of parents paths (ids)
306 *
307 * @param int $path file path (id)
308 *
309 * @return array
310 * @author Dmitry (dio) Levashov
311 **/
312 protected function getParents($path)
313 {
314 $parents = array();
315
316 while ($path) {
317 if ($file = $this->stat($path)) {
318 array_unshift($parents, $path);
319 $path = isset($file['phash']) ? $this->decode($file['phash']) : false;
320 }
321 }
322
323 if (count($parents)) {
324 array_pop($parents);
325 }
326 return $parents;
327 }
328
329 /**
330 * Return correct file path for LOAD_FILE method
331 *
332 * @param string $path file path (id)
333 *
334 * @return string
335 * @author Troex Nevelin
336 **/
337 protected function loadFilePath($path)
338 {
339 $realPath = realpath($path);
340 if (DIRECTORY_SEPARATOR == '\\') { // windows
341 $realPath = str_replace('\\', '\\\\', $realPath);
342 }
343 return $this->db->real_escape_string($realPath);
344 }
345
346 /**
347 * Recursive files search
348 *
349 * @param string $path dir path
350 * @param string $q search string
351 * @param array $mimes
352 *
353 * @return array
354 * @throws elFinderAbortException
355 * @author Dmitry (dio) Levashov
356 */
357 protected function doSearch($path, $q, $mimes)
358 {
359 if (!empty($this->doSearchCurrentQuery['matchMethod'])) {
360 // has custom match method use elFinderVolumeDriver::doSearch()
361 return parent::doSearch($path, $q, $mimes);
362 }
363
364 $dirs = array();
365 $timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0;
366
367 if ($path != $this->root || $this->rootHasParent) {
368 $dirs = $inpath = array(intval($path));
369 while ($inpath) {
370 $in = '(' . join(',', $inpath) . ')';
371 $inpath = array();
372 $sql = 'SELECT f.id FROM %s AS f WHERE f.parent_id IN ' . $in . ' AND `mime` = \'directory\'';
373 $sql = sprintf($sql, $this->tbf);
374 if ($res = $this->query($sql)) {
375 $_dir = array();
376 while ($dat = $res->fetch_assoc()) {
377 $inpath[] = $dat['id'];
378 }
379 $dirs = array_merge($dirs, $inpath);
380 }
381 }
382 }
383
384 $result = array();
385
386 if ($mimes) {
387 $whrs = array();
388 foreach ($mimes as $mime) {
389 if (strpos($mime, '/') === false) {
390 $whrs[] = sprintf('f.mime LIKE \'%s/%%\'', $this->db->real_escape_string($mime));
391 } else {
392 $whrs[] = sprintf('f.mime = \'%s\'', $this->db->real_escape_string($mime));
393 }
394 }
395 $whr = join(' OR ', $whrs);
396 } else {
397 $whr = sprintf('f.name LIKE \'%%%s%%\'', $this->db->real_escape_string($q));
398 }
399 if ($dirs) {
400 $whr = '(' . $whr . ') AND (`parent_id` IN (' . join(',', $dirs) . '))';
401 }
402
403 $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
404 FROM %s AS f
405 WHERE %s';
406
407 $sql = sprintf($sql, $this->tbf, $whr);
408
409 if (($res = $this->query($sql))) {
410 while ($row = $res->fetch_assoc()) {
411 if ($timeout && $timeout < time()) {
412 $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
413 break;
414 }
415
416 if (!$this->mimeAccepted($row['mime'], $mimes)) {
417 continue;
418 }
419 $id = $row['id'];
420 if ($id == $this->root) {
421 continue;
422 }
423 if ($row['parent_id'] && $id != $this->root) {
424 $row['phash'] = $this->encode($row['parent_id']);
425 }
426 $row['path'] = $this->_path($id);
427
428 if ($row['mime'] == 'directory') {
429 unset($row['width']);
430 unset($row['height']);
431 } else {
432 unset($row['dirs']);
433 }
434
435 unset($row['id']);
436 unset($row['parent_id']);
437
438 if (($stat = $this->updateCache($id, $row)) && empty($stat['hidden'])) {
439 $result[] = $stat;
440 }
441 }
442 }
443 return $result;
444 }
445
446
447 /*********************** paths/urls *************************/
448
449 /**
450 * Return parent directory path
451 *
452 * @param string $path file path
453 *
454 * @return string
455 * @author Dmitry (dio) Levashov
456 **/
457 protected function _dirname($path)
458 {
459 return ($stat = $this->stat($path)) ? (!empty($stat['phash']) ? $this->decode($stat['phash']) : $this->root) : false;
460 }
461
462 /**
463 * Return file name
464 *
465 * @param string $path file path
466 *
467 * @return string
468 * @author Dmitry (dio) Levashov
469 **/
470 protected function _basename($path)
471 {
472 return (($stat = $this->stat($path)) && isset($stat['name'])) ? $stat['name'] : false;
473 }
474
475 /**
476 * Join dir name and file name and return full path
477 *
478 * @param string $dir
479 * @param string $name
480 *
481 * @return string
482 * @author Dmitry (dio) Levashov
483 **/
484 protected function _joinPath($dir, $name)
485 {
486 $sql = 'SELECT id FROM ' . $this->tbf . ' WHERE parent_id=\'' . $dir . '\' AND name=\'' . $this->db->real_escape_string($name) . '\'';
487
488 if (($res = $this->query($sql)) && ($r = $res->fetch_assoc())) {
489 $this->updateCache($r['id'], $this->_stat($r['id']));
490 return $r['id'];
491 }
492 return -1;
493 }
494
495 /**
496 * Return normalized path, this works the same as os.path.normpath() in Python
497 *
498 * @param string $path path
499 *
500 * @return string
501 * @author Troex Nevelin
502 **/
503 protected function _normpath($path)
504 {
505 return $path;
506 }
507
508 /**
509 * Return file path related to root dir
510 *
511 * @param string $path file path
512 *
513 * @return string
514 * @author Dmitry (dio) Levashov
515 **/
516 protected function _relpath($path)
517 {
518 return $path;
519 }
520
521 /**
522 * Convert path related to root dir into real path
523 *
524 * @param string $path file path
525 *
526 * @return string
527 * @author Dmitry (dio) Levashov
528 **/
529 protected function _abspath($path)
530 {
531 return $path;
532 }
533
534 /**
535 * Return fake path started from root dir
536 *
537 * @param string $path file path
538 *
539 * @return string
540 * @author Dmitry (dio) Levashov
541 **/
542 protected function _path($path)
543 {
544 if (($file = $this->stat($path)) == false) {
545 return '';
546 }
547
548 $parentsIds = $this->getParents($path);
549 $path = '';
550 foreach ($parentsIds as $id) {
551 $dir = $this->stat($id);
552 $path .= $dir['name'] . $this->separator;
553 }
554 return $path . $file['name'];
555 }
556
557 /**
558 * Return true if $path is children of $parent
559 *
560 * @param string $path path to check
561 * @param string $parent parent path
562 *
563 * @return bool
564 * @author Dmitry (dio) Levashov
565 **/
566 protected function _inpath($path, $parent)
567 {
568 return $path == $parent
569 ? true
570 : in_array($parent, $this->getParents($path));
571 }
572
573 /***************** file stat ********************/
574 /**
575 * Return stat for given path.
576 * Stat contains following fields:
577 * - (int) size file size in b. required
578 * - (int) ts file modification time in unix time. required
579 * - (string) mime mimetype. required for folders, others - optionally
580 * - (bool) read read permissions. required
581 * - (bool) write write permissions. required
582 * - (bool) locked is object locked. optionally
583 * - (bool) hidden is object hidden. optionally
584 * - (string) alias for symlinks - link target path relative to root path. optionally
585 * - (string) target for symlinks - link target path. optionally
586 * If file does not exists - returns empty array or false.
587 *
588 * @param string $path file path
589 *
590 * @return array|false
591 * @author Dmitry (dio) Levashov
592 **/
593 protected function _stat($path)
594 {
595 $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
596 FROM ' . $this->tbf . ' AS f
597 LEFT JOIN ' . $this->tbf . ' AS ch ON ch.parent_id=f.id AND ch.mime=\'directory\'
598 WHERE f.id=\'' . $path . '\'
599 GROUP BY f.id, ch.id';
600
601 $res = $this->query($sql);
602
603 if ($res) {
604 $stat = $res->fetch_assoc();
605 if ($stat['id'] == $this->root) {
606 $this->rootHasParent = true;
607 $stat['parent_id'] = '';
608 }
609 if ($stat['parent_id']) {
610 $stat['phash'] = $this->encode($stat['parent_id']);
611 }
612 if ($stat['mime'] == 'directory') {
613 unset($stat['width']);
614 unset($stat['height']);
615 $stat['size'] = 0;
616 } else {
617 if (!$stat['mime']) {
618 unset($stat['mime']);
619 }
620 unset($stat['dirs']);
621 }
622 unset($stat['id']);
623 unset($stat['parent_id']);
624 return $stat;
625
626 }
627 return array();
628 }
629
630 /**
631 * Return true if path is dir and has at least one childs directory
632 *
633 * @param string $path dir path
634 *
635 * @return bool
636 * @author Dmitry (dio) Levashov
637 **/
638 protected function _subdirs($path)
639 {
640 return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
641 }
642
643 /**
644 * Return object width and height
645 * Usualy used for images, but can be realize for video etc...
646 *
647 * @param string $path file path
648 * @param string $mime file mime type
649 *
650 * @return string
651 * @author Dmitry (dio) Levashov
652 **/
653 protected function _dimensions($path, $mime)
654 {
655 return ($stat = $this->stat($path)) && isset($stat['width']) && isset($stat['height']) ? $stat['width'] . 'x' . $stat['height'] : '';
656 }
657
658 /******************** file/dir content *********************/
659
660 /**
661 * Return files list in directory.
662 *
663 * @param string $path dir path
664 *
665 * @return array
666 * @author Dmitry (dio) Levashov
667 **/
668 protected function _scandir($path)
669 {
670 return isset($this->dirsCache[$path])
671 ? $this->dirsCache[$path]
672 : $this->cacheDir($path);
673 }
674
675 /**
676 * Open file and return file pointer
677 *
678 * @param string $path file path
679 * @param string $mode open file mode (ignored in this driver)
680 *
681 * @return resource|false
682 * @author Dmitry (dio) Levashov
683 **/
684 protected function _fopen($path, $mode = 'rb')
685 {
686 $fp = $this->tmpPath
687 ? fopen($this->getTempFile($path), 'w+')
688 : $this->tmpfile();
689
690
691 if ($fp) {
692 if (($res = $this->query('SELECT content FROM ' . $this->tbf . ' WHERE id=\'' . $path . '\''))
693 && ($r = $res->fetch_assoc())) {
694 fwrite($fp, $r['content']);
695 rewind($fp);
696 return $fp;
697 } else {
698 $this->_fclose($fp, $path);
699 }
700 }
701
702 return false;
703 }
704
705 /**
706 * Close opened file
707 *
708 * @param resource $fp file pointer
709 * @param string $path
710 *
711 * @return void
712 * @author Dmitry (dio) Levashov
713 */
714 protected function _fclose($fp, $path = '')
715 {
716 is_resource($fp) && fclose($fp);
717 if ($path) {
718 $file = $this->getTempFile($path);
719 is_file($file) && unlink($file);
720 }
721 }
722
723 /******************** file/dir manipulations *************************/
724
725 /**
726 * Create dir and return created dir path or false on failed
727 *
728 * @param string $path parent dir path
729 * @param string $name new directory name
730 *
731 * @return string|bool
732 * @author Dmitry (dio) Levashov
733 **/
734 protected function _mkdir($path, $name)
735 {
736 return $this->make($path, $name, 'directory') ? $this->_joinPath($path, $name) : false;
737 }
738
739 /**
740 * Create file and return it's path or false on failed
741 *
742 * @param string $path parent dir path
743 * @param string $name new file name
744 *
745 * @return string|bool
746 * @author Dmitry (dio) Levashov
747 **/
748 protected function _mkfile($path, $name)
749 {
750 return $this->make($path, $name, '') ? $this->_joinPath($path, $name) : false;
751 }
752
753 /**
754 * Create symlink. FTP driver does not support symlinks.
755 *
756 * @param string $target link target
757 * @param string $path symlink path
758 * @param string $name
759 *
760 * @return bool
761 * @author Dmitry (dio) Levashov
762 */
763 protected function _symlink($target, $path, $name)
764 {
765 return false;
766 }
767
768 /**
769 * Copy file into another file
770 *
771 * @param string $source source file path
772 * @param string $targetDir target directory path
773 * @param string $name new file name
774 *
775 * @return bool
776 * @author Dmitry (dio) Levashov
777 **/
778 protected function _copy($source, $targetDir, $name)
779 {
780 $this->clearcache();
781 $id = $this->_joinPath($targetDir, $name);
782
783 $sql = $id > 0
784 ? 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)
785 : 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);
786
787 return $this->query($sql);
788 }
789
790 /**
791 * Move file into another parent dir.
792 * Return new file path or false.
793 *
794 * @param string $source source file path
795 * @param $targetDir
796 * @param string $name file name
797 *
798 * @return bool|string
799 * @internal param string $target target dir path
800 * @author Dmitry (dio) Levashov
801 */
802 protected function _move($source, $targetDir, $name)
803 {
804 $sql = 'UPDATE %s SET parent_id=%d, name=\'%s\' WHERE id=%d LIMIT 1';
805 $sql = sprintf($sql, $this->tbf, $targetDir, $this->db->real_escape_string($name), $source);
806 return $this->query($sql) && $this->db->affected_rows > 0 ? $source : false;
807 }
808
809 /**
810 * Remove file
811 *
812 * @param string $path file path
813 *
814 * @return bool
815 * @author Dmitry (dio) Levashov
816 **/
817 protected function _unlink($path)
818 {
819 return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime!=\'directory\' LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
820 }
821
822 /**
823 * Remove dir
824 *
825 * @param string $path dir path
826 *
827 * @return bool
828 * @author Dmitry (dio) Levashov
829 **/
830 protected function _rmdir($path)
831 {
832 return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime=\'directory\' LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
833 }
834
835 /**
836 * undocumented function
837 *
838 * @param $path
839 * @param $fp
840 *
841 * @author Dmitry Levashov
842 */
843 protected function _setContent($path, $fp)
844 {
845 elFinder::rewind($fp);
846 $fstat = fstat($fp);
847 $size = $fstat['size'];
848
849
850 }
851
852 /**
853 * Create new file and write into it from file pointer.
854 * Return new file path or false on error.
855 *
856 * @param resource $fp file pointer
857 * @param string $dir target dir path
858 * @param string $name file name
859 * @param array $stat file stat (required by some virtual fs)
860 *
861 * @return bool|string
862 * @author Dmitry (dio) Levashov
863 **/
864 protected function _save($fp, $dir, $name, $stat)
865 {
866 $this->clearcache();
867
868 $mime = !empty($stat['mime']) ? $stat['mime'] : $this->mimetype($name, true);
869 $w = !empty($stat['width']) ? $stat['width'] : 0;
870 $h = !empty($stat['height']) ? $stat['height'] : 0;
871 $ts = !empty($stat['ts']) ? $stat['ts'] : time();
872
873 $id = $this->_joinPath($dir, $name);
874 if (!isset($stat['size'])) {
875 $stat = fstat($fp);
876 $size = $stat['size'];
877 } else {
878 $size = $stat['size'];
879 }
880
881 if ($this->isLocalhost && ($tmpfile = tempnam($this->tmpPath, $this->id))) {
882 if (($trgfp = fopen($tmpfile, 'wb')) == false) {
883 unlink($tmpfile);
884 } else {
885 elFinder::rewind($fp);
886 stream_copy_to_stream($fp, $trgfp);
887 fclose($trgfp);
888 chmod($tmpfile, 0644);
889
890 $sql = $id > 0
891 ? 'REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height) VALUES (' . $id . ', %d, \'%s\', LOAD_FILE(\'%s\'), %d, %d, \'%s\', %d, %d)'
892 : 'INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height) VALUES (%d, \'%s\', LOAD_FILE(\'%s\'), %d, %d, \'%s\', %d, %d)';
893 $sql = sprintf($sql, $this->tbf, $dir, $this->db->real_escape_string($name), $this->loadFilePath($tmpfile), $size, $ts, $mime, $w, $h);
894
895 $res = $this->query($sql);
896 unlink($tmpfile);
897
898 if ($res) {
899 return $id > 0 ? $id : $this->db->insert_id;
900 }
901 }
902 }
903
904
905 $content = '';
906 elFinder::rewind($fp);
907 while (!feof($fp)) {
908 $content .= fread($fp, 8192);
909 }
910
911 $sql = $id > 0
912 ? 'REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height) VALUES (' . $id . ', %d, \'%s\', \'%s\', %d, %d, \'%s\', %d, %d)'
913 : 'INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height) VALUES (%d, \'%s\', \'%s\', %d, %d, \'%s\', %d, %d)';
914 $sql = sprintf($sql, $this->tbf, $dir, $this->db->real_escape_string($name), $this->db->real_escape_string($content), $size, $ts, $mime, $w, $h);
915
916 unset($content);
917
918 if ($this->query($sql)) {
919 return $id > 0 ? $id : $this->db->insert_id;
920 }
921
922 return false;
923 }
924
925 /**
926 * Get file contents
927 *
928 * @param string $path file path
929 *
930 * @return string|false
931 * @author Dmitry (dio) Levashov
932 **/
933 protected function _getContents($path)
934 {
935 return ($res = $this->query(sprintf('SELECT content FROM %s WHERE id=%d', $this->tbf, $path))) && ($r = $res->fetch_assoc()) ? $r['content'] : false;
936 }
937
938 /**
939 * Write a string to a file
940 *
941 * @param string $path file path
942 * @param string $content new file content
943 *
944 * @return bool
945 * @author Dmitry (dio) Levashov
946 **/
947 protected function _filePutContents($path, $content)
948 {
949 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));
950 }
951
952 /**
953 * Detect available archivers
954 *
955 * @return void
956 **/
957 protected function _checkArchivers()
958 {
959 return;
960 }
961
962 /**
963 * chmod implementation
964 *
965 * @param string $path
966 * @param string $mode
967 *
968 * @return bool
969 */
970 protected function _chmod($path, $mode)
971 {
972 return false;
973 }
974
975 /**
976 * Unpack archive
977 *
978 * @param string $path archive path
979 * @param array $arc archiver command and arguments (same as in $this->archivers)
980 *
981 * @return void
982 * @author Dmitry (dio) Levashov
983 * @author Alexey Sukhotin
984 **/
985 protected function _unpack($path, $arc)
986 {
987 return;
988 }
989
990 /**
991 * Extract files from archive
992 *
993 * @param string $path archive path
994 * @param array $arc archiver command and arguments (same as in $this->archivers)
995 *
996 * @return true
997 * @author Dmitry (dio) Levashov,
998 * @author Alexey Sukhotin
999 **/
1000 protected function _extract($path, $arc)
1001 {
1002 return false;
1003 }
1004
1005 /**
1006 * Create archive and return its path
1007 *
1008 * @param string $dir target dir
1009 * @param array $files files names list
1010 * @param string $name archive name
1011 * @param array $arc archiver options
1012 *
1013 * @return string|bool
1014 * @author Dmitry (dio) Levashov,
1015 * @author Alexey Sukhotin
1016 **/
1017 protected function _archive($dir, $files, $name, $arc)
1018 {
1019 return false;
1020 }
1021
1022 } // END class
1023