PageRenderTime 64ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/elfinder/php/elFinderVolumeMySQL.php

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