OSDN Git Service

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