PageRenderTime 52ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/elFinder/elFinderVolumeDropbox.class.php

https://github.com/ahmadazimi/laravel-elfinder
PHP | 1531 lines | 869 code | 167 blank | 495 comment | 201 complexity | 6c5c60fd3be72acc4daae884b40fdba9 MD5 | raw file
  1. <?php
  2. elFinder::$netDrivers['dropbox'] = 'Dropbox';
  3. /**
  4. * Simple elFinder driver for FTP
  5. *
  6. * @author Dmitry (dio) Levashov
  7. * @author Cem (discofever)
  8. **/
  9. class elFinderVolumeDropbox extends elFinderVolumeDriver {
  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 = 'd';
  18. /**
  19. * OAuth object
  20. *
  21. * @var oauth
  22. **/
  23. protected $oauth = null;
  24. /**
  25. * Dropbox object
  26. *
  27. * @var dropbox
  28. **/
  29. protected $dropbox = null;
  30. /**
  31. * Directory for meta data caches
  32. * If not set driver not cache meta data
  33. *
  34. * @var string
  35. **/
  36. protected $metaCache = '';
  37. /**
  38. * Last API error message
  39. *
  40. * @var string
  41. **/
  42. protected $apiError = '';
  43. /**
  44. * Directory for tmp files
  45. * If not set driver will try to use tmbDir as tmpDir
  46. *
  47. * @var string
  48. **/
  49. protected $tmp = '';
  50. /**
  51. * Net mount key
  52. *
  53. * @var string
  54. **/
  55. public $netMountKey = '';
  56. /**
  57. * Dropbox.com uid
  58. *
  59. * @var string
  60. **/
  61. protected $dropboxUid = '';
  62. private $dropbox_phpFound = false;
  63. private $DB_TableName = '';
  64. private $tmbPrefix = '';
  65. /**
  66. * Constructor
  67. * Extend options with required fields
  68. *
  69. * @return void
  70. * @author Dmitry (dio) Levashov
  71. * @author Cem (DiscoFever)
  72. **/
  73. public function __construct() {
  74. //ini_set('memory_limit', '128M');
  75. @ include_once 'Dropbox/autoload.php';
  76. $this->dropbox_phpFound = in_array('Dropbox_autoload', spl_autoload_functions());
  77. $opts = array(
  78. 'consumerKey' => '',
  79. 'consumerSecret' => '',
  80. 'accessToken' => '',
  81. 'accessTokenSecret' => '',
  82. 'dropboxUid' => '',
  83. 'root' => 'dropbox',
  84. 'path' => '/',
  85. 'PDO_DSN' => '', // if empty use 'sqlite:(metaCachePath|tmbPath)/elFinder_dropbox_db_(hash:dropboxUid+consumerSecret)'
  86. 'PDO_User' => '',
  87. 'PDO_Pass' => '',
  88. 'PDO_Options' => array(),
  89. 'PDO_DBName' => 'dropbox',
  90. 'treeDeep' => 0,
  91. 'tmbPath' => '../files/.tmb',
  92. 'tmbURL' => 'files/.tmb',
  93. 'tmpPath' => '',
  94. 'getTmbSize' => 'medium', // small: 32x32, medium or s: 64x64, large or m: 128x128, l: 640x480, xl: 1024x768
  95. 'metaCachePath' => '',
  96. 'metaCacheTime' => '600', // 10m
  97. 'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
  98. 'icon' => (defined('ELFINDER_IMG_PARENT_URL')? (rtrim(ELFINDER_IMG_PARENT_URL, '/').'/') : '').'img/volume_icon_dropbox.png'
  99. );
  100. $this->options = array_merge($this->options, $opts);
  101. $this->options['mimeDetect'] = 'internal';
  102. }
  103. /**
  104. * Prepare
  105. * Call from elFinder::netmout() before volume->mount()
  106. *
  107. * @return Array
  108. * @author Naoki Sawada
  109. **/
  110. public function netmountPrepare($options) {
  111. if (empty($options['consumerKey']) && defined('ELFINDER_DROPBOX_CONSUMERKEY')) $options['consumerKey'] = ELFINDER_DROPBOX_CONSUMERKEY;
  112. if (empty($options['consumerSecret']) && defined('ELFINDER_DROPBOX_CONSUMERSECRET')) $options['consumerSecret'] = ELFINDER_DROPBOX_CONSUMERSECRET;
  113. if ($options['user'] === 'init') {
  114. if (! $this->dropbox_phpFound || empty($options['consumerKey']) || empty($options['consumerSecret']) || !class_exists('PDO')) {
  115. return array('exit' => true, 'body' => '{msg:errNetMountNoDriver}');
  116. }
  117. if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) {
  118. $this->oauth = new Dropbox_OAuth_Curl($options['consumerKey'], $options['consumerSecret']);
  119. } else {
  120. if (class_exists('OAuth')) {
  121. $this->oauth = new Dropbox_OAuth_PHP($options['consumerKey'], $options['consumerSecret']);
  122. } else {
  123. if (! class_exists('HTTP_OAuth_Consumer')) {
  124. // We're going to try to load in manually
  125. include 'HTTP/OAuth/Consumer.php';
  126. }
  127. if (class_exists('HTTP_OAuth_Consumer')) {
  128. $this->oauth = new Dropbox_OAuth_PEAR($options['consumerKey'], $options['consumerSecret']);
  129. }
  130. }
  131. }
  132. if (! $this->oauth) {
  133. return array('exit' => true, 'body' => '{msg:errNetMountNoDriver}');
  134. }
  135. if ($options['pass'] === 'init') {
  136. $html = '';
  137. if (isset($_SESSION['elFinderDropboxTokens'])) {
  138. // token check
  139. try {
  140. list(, $accessToken, $accessTokenSecret) = $_SESSION['elFinderDropboxTokens'];
  141. $this->oauth->setToken($accessToken, $accessTokenSecret);
  142. $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
  143. $this->dropbox->getAccountInfo();
  144. $script = '<script>
  145. $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "done"});
  146. </script>';
  147. $html = $script;
  148. } catch (Dropbox_Exception $e) {
  149. unset($_SESSION['elFinderDropboxTokens']);
  150. }
  151. }
  152. if (! $html) {
  153. // get customdata
  154. $cdata = '';
  155. $innerKeys = array('cmd', 'host', 'options', 'pass', 'protocol', 'user');
  156. $post = (strtolower($_SERVER['REQUEST_METHOD']) === 'post')? $_POST : $_GET;
  157. foreach($post as $k => $v) {
  158. if (! in_array($k, $innerKeys)) {
  159. $cdata .= '&' . $k . '=' . rawurlencode($v);
  160. }
  161. }
  162. if (strpos($options['url'], 'http') !== 0 ) {
  163. $options['url'] = $this->getConnectorUrl();
  164. }
  165. $callback = $options['url']
  166. . '?cmd=netmount&protocol=dropbox&host=dropbox.com&user=init&pass=return&node='.$options['id'].$cdata;
  167. try {
  168. $tokens = $this->oauth->getRequestToken();
  169. $url= $this->oauth->getAuthorizeUrl(rawurlencode($callback));
  170. } catch (Dropbox_Exception $e) {
  171. return array('exit' => true, 'body' => '{msg:errAccess}');
  172. }
  173. $_SESSION['elFinderDropboxAuthTokens'] = $tokens;
  174. $html = '<input id="elf-volumedriver-dropbox-host-btn" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" value="{msg:btnApprove}" type="button" onclick="window.open(\''.$url.'\')">';
  175. $html .= '<script>
  176. $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "makebtn"});
  177. </script>';
  178. }
  179. return array('exit' => true, 'body' => $html);
  180. } else {
  181. $this->oauth->setToken($_SESSION['elFinderDropboxAuthTokens']);
  182. unset($_SESSION['elFinderDropboxAuthTokens']);
  183. $tokens = $this->oauth->getAccessToken();
  184. $_SESSION['elFinderDropboxTokens'] = array($_GET['uid'], $tokens['token'], $tokens['token_secret']);
  185. $out = array(
  186. 'node' => $_GET['node'],
  187. 'json' => '{"protocol": "dropbox", "mode": "done"}',
  188. 'bind' => 'netmount'
  189. );
  190. return array('exit' => 'callback', 'out' => $out);
  191. }
  192. }
  193. if (isset($_SESSION['elFinderDropboxTokens'])) {
  194. list($options['dropboxUid'], $options['accessToken'], $options['accessTokenSecret']) = $_SESSION['elFinderDropboxTokens'];
  195. }
  196. unset($options['user'], $options['pass']);
  197. return $options;
  198. }
  199. /**
  200. * process of on netunmount
  201. * Drop table `dropbox` & rm thumbs
  202. *
  203. * @param array $options
  204. * @return boolean
  205. */
  206. public function netunmount($netVolumes, $key) {
  207. $count = 0;
  208. $dropboxUid = '';
  209. if (isset($netVolumes[$key])) {
  210. $dropboxUid = $netVolumes[$key]['dropboxUid'];
  211. }
  212. foreach($netVolumes as $volume) {
  213. if (@$volume['host'] === 'dropbox' && @$volume['dropboxUid'] === $dropboxUid) {
  214. $count++;
  215. }
  216. }
  217. if ($count === 1) {
  218. $this->DB->exec('drop table '.$this->DB_TableName);
  219. foreach(glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->tmbPrefix.'*.png') as $tmb) {
  220. unlink($tmb);
  221. }
  222. }
  223. return true;
  224. }
  225. /**
  226. * Get script url
  227. *
  228. * @return string full URL
  229. * @author Naoki Sawada
  230. */
  231. private function getConnectorUrl() {
  232. $url = ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')? 'https://' : 'http://')
  233. . $_SERVER['SERVER_NAME'] // host
  234. . ($_SERVER['SERVER_PORT'] == 80 ? '' : ':' . $_SERVER['SERVER_PORT']) // port
  235. . $_SERVER['REQUEST_URI']; // path & query
  236. list($url) = explode('?', $url);
  237. return $url;
  238. }
  239. /*********************************************************************/
  240. /* INIT AND CONFIGURE */
  241. /*********************************************************************/
  242. /**
  243. * Prepare FTP connection
  244. * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn
  245. *
  246. * @return bool
  247. * @author Dmitry (dio) Levashov
  248. * @author Cem (DiscoFever)
  249. **/
  250. protected function init() {
  251. if (!class_exists('PDO')) {
  252. return $this->setError('PHP PDO class is require.');
  253. }
  254. if (!$this->options['consumerKey']
  255. || !$this->options['consumerSecret']
  256. || !$this->options['accessToken']
  257. || !$this->options['accessTokenSecret']) {
  258. return $this->setError('Required options undefined.');
  259. }
  260. if (empty($this->options['metaCachePath']) && defined('ELFINDER_DROPBOX_META_CACHE_PATH')) {
  261. $this->options['metaCachePath'] = ELFINDER_DROPBOX_META_CACHE_PATH;
  262. }
  263. // make net mount key
  264. $this->netMountKey = md5(join('-', array('dropbox', $this->options['path'])));
  265. if (! $this->oauth) {
  266. if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) {
  267. $this->oauth = new Dropbox_OAuth_Curl($this->options['consumerKey'], $this->options['consumerSecret']);
  268. } else {
  269. if (class_exists('OAuth')) {
  270. $this->oauth = new Dropbox_OAuth_PHP($this->options['consumerKey'], $this->options['consumerSecret']);
  271. } else {
  272. if (! class_exists('HTTP_OAuth_Consumer')) {
  273. // We're going to try to load in manually
  274. include 'HTTP/OAuth/Consumer.php';
  275. }
  276. if (class_exists('HTTP_OAuth_Consumer')) {
  277. $this->oauth = new Dropbox_OAuth_PEAR($this->options['consumerKey'], $this->options['consumerSecret']);
  278. }
  279. }
  280. }
  281. }
  282. if (! $this->oauth) {
  283. return $this->setError('OAuth extension not loaded.');
  284. }
  285. // normalize root path
  286. $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
  287. if (empty($this->options['alias'])) {
  288. $this->options['alias'] = ($this->options['path'] === '/')? 'Dropbox.com' : 'Dropbox'.$this->options['path'];
  289. }
  290. $this->rootName = $this->options['alias'];
  291. $this->options['separator'] = '/';
  292. try {
  293. $this->oauth->setToken($this->options['accessToken'], $this->options['accessTokenSecret']);
  294. $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
  295. } catch (Dropbox_Exception $e) {
  296. unset($_SESSION['elFinderDropboxTokens']);
  297. return $this->setError('Dropbox error: '.$e->getMessage());
  298. }
  299. // user
  300. if (empty($this->options['dropboxUid'])) {
  301. try {
  302. $res = $this->dropbox->getAccountInfo();
  303. $this->options['dropboxUid'] = $res['uid'];
  304. } catch (Dropbox_Exception $e) {
  305. unset($_SESSION['elFinderDropboxTokens']);
  306. return $this->setError('Dropbox error: '.$e->getMessage());
  307. }
  308. }
  309. $this->dropboxUid = $this->options['dropboxUid'];
  310. $this->tmbPrefix = 'dropbox'.base_convert($this->dropboxUid, 10, 32);
  311. if (!empty($this->options['tmpPath'])) {
  312. if ((is_dir($this->options['tmpPath']) || @mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
  313. $this->tmp = $this->options['tmpPath'];
  314. }
  315. }
  316. if (!$this->tmp && is_writable($this->options['tmbPath'])) {
  317. $this->tmp = $this->options['tmbPath'];
  318. }
  319. if (!empty($this->options['metaCachePath'])) {
  320. if ((is_dir($this->options['metaCachePath']) || @mkdir($this->options['metaCachePath'])) && is_writable($this->options['metaCachePath'])) {
  321. $this->metaCache = $this->options['metaCachePath'];
  322. }
  323. }
  324. if (!$this->metaCache && $this->tmp) {
  325. $this->metaCache = $this->tmp;
  326. }
  327. if (!$this->tmp) {
  328. $this->disabled[] = 'archive';
  329. $this->disabled[] = 'extract';
  330. }
  331. if (!$this->metaCache) {
  332. return $this->setError('Cache dirctory (metaCachePath or tmp) is require.');
  333. }
  334. // setup PDO
  335. if (! $this->options['PDO_DSN']) {
  336. $this->options['PDO_DSN'] = 'sqlite:'.$this->metaCache.DIRECTORY_SEPARATOR.'.elFinder_dropbox_db_'.md5($this->dropboxUid.$this->options['consumerSecret']);
  337. }
  338. // DataBase table name
  339. $this->DB_TableName = $this->options['PDO_DBName'];
  340. // DataBase check or make table
  341. try {
  342. $this->DB = new PDO($this->options['PDO_DSN'], $this->options['PDO_User'], $this->options['PDO_Pass'], $this->options['PDO_Options']);
  343. if (! $this->checkDB()) {
  344. return $this->setError('Can not make DB table');
  345. }
  346. } catch (PDOException $e) {
  347. return $this->setError('PDO connection failed: '.$e->getMessage());
  348. }
  349. $res = $this->deltaCheck(!empty($_REQUEST['init']));
  350. if ($res !== true) {
  351. if (is_string($res)) {
  352. return $this->setError($res);
  353. } else {
  354. return $this->setError('Could not check API "delta"');
  355. }
  356. }
  357. return true;
  358. }
  359. /**
  360. * Configure after successfull mount.
  361. *
  362. * @return void
  363. * @author Dmitry (dio) Levashov
  364. **/
  365. protected function configure() {
  366. parent::configure();
  367. if (!$this->tmp) {
  368. $this->disabled[] = 'archive';
  369. $this->disabled[] = 'extract';
  370. }
  371. }
  372. /**
  373. * Check DB for delta cache
  374. *
  375. * @return void
  376. */
  377. private function checkDB() {
  378. $res = $this->query('select * from sqlite_master where type=\'table\' and name=\'dropbox\'; ');
  379. if (! $res) {
  380. try {
  381. $this->DB->exec('create table '.$this->DB_TableName.'(path text, fname text, dat blob, isdir integer);');
  382. $this->DB->exec('create index nameidx on '.$this->DB_TableName.'(path, fname)');
  383. $this->DB->exec('create index isdiridx on '.$this->DB_TableName.'(isdir)');
  384. } catch (PDOException $e) {
  385. return $this->setError($e->getMessage());
  386. }
  387. }
  388. return true;
  389. }
  390. /**
  391. * DB query and fetchAll
  392. *
  393. * @param string $sql
  394. * @return boolean|array
  395. */
  396. private function query($sql) {
  397. if ($sth = $this->DB->query($sql)) {
  398. $res = $sth->fetchAll(PDO::FETCH_COLUMN);
  399. } else {
  400. $res = false;
  401. }
  402. return $res;
  403. }
  404. /**
  405. * Get dat(dropbox metadata) from DB
  406. *
  407. * @param string $path
  408. * @return array dropbox metadata
  409. */
  410. private function getDBdat($path) {
  411. if ($res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower(dirname($path))).' and fname='.$this->DB->quote(strtolower(basename($path))).' limit 1')) {
  412. return unserialize($res[0]);
  413. } else {
  414. return array();
  415. }
  416. }
  417. /**
  418. * Update DB dat(dropbox metadata)
  419. *
  420. * @param string $path
  421. * @param array $dat
  422. * @return bool|array
  423. */
  424. private function updateDBdat($path, $dat) {
  425. return $this->query('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($dat))
  426. . ', isdir=' . ($dat['is_dir']? 1 : 0)
  427. . ' where path='.$this->DB->quote(strtolower(dirname($path))).' and fname='.$this->DB->quote(strtolower(basename($path))));
  428. }
  429. /*********************************************************************/
  430. /* FS API */
  431. /*********************************************************************/
  432. /**
  433. * Close opened connection
  434. *
  435. * @return void
  436. * @author Dmitry (dio) Levashov
  437. **/
  438. public function umount() {
  439. }
  440. /**
  441. * Get local temp filename
  442. *
  443. * @return string | false
  444. * @author Naoki Sawada
  445. **/
  446. protected function getLocalName($path) {
  447. if ($this->tmp) {
  448. return $this->tmp.DIRECTORY_SEPARATOR.md5($this->dropboxUid.$path);
  449. }
  450. return false;
  451. }
  452. /**
  453. * Get delta data and DB update
  454. *
  455. * @param boolean $refresh force refresh
  456. * @return true|string error message
  457. */
  458. protected function deltaCheck($refresh = true) {
  459. $chk = false;
  460. if (! $refresh && $chk = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
  461. $chk = unserialize($chk[0]);
  462. }
  463. if ($chk && ($chk['mtime'] + $this->options['metaCacheTime']) > $_SERVER['REQUEST_TIME']) {
  464. return true;
  465. }
  466. try {
  467. $more = true;
  468. $this->DB->beginTransaction();
  469. if ($res = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
  470. $res = unserialize($res[0]);
  471. $cursor = $res['cursor'];
  472. } else {
  473. $cursor = '';
  474. }
  475. $delete = false;
  476. $reset = false;
  477. do {
  478. @ ini_set('max_execution_time', 120);
  479. $_info = $this->dropbox->delta($cursor);
  480. if (! empty($_info['reset'])) {
  481. $this->DB->exec('TRUNCATE table '.$this->DB_TableName);
  482. $this->DB->exec('insert into '.$this->DB_TableName.' values(\'\', \'\', \''.serialize(array('cursor' => '', 'mtime' => 0)).'\', 0);');
  483. $this->DB->exec('insert into '.$this->DB_TableName.' values(\'/\', \'\', \''.serialize(array(
  484. 'path' => '/',
  485. 'is_dir' => 1,
  486. 'mime_type' => '',
  487. 'bytes' => 0
  488. )).'\', 0);');
  489. $reset = true;
  490. }
  491. $cursor = $_info['cursor'];
  492. foreach($_info['entries'] as $entry) {
  493. $key = strtolower($entry[0]);
  494. $pkey = strtolower(dirname($key));
  495. $path = $this->DB->quote($pkey);
  496. $fname = $this->DB->quote(strtolower(basename($key)));
  497. $where = 'where path='.$path.' and fname='.$fname;
  498. if (empty($entry[1])) {
  499. $this->DB->exec('delete from '.$this->DB_TableName.' '.$where);
  500. ! $delete && $delete = true;
  501. continue;
  502. }
  503. $sql = 'select path from '.$this->DB_TableName.' '.$where.' limit 1';
  504. if (! $reset && $this->query($sql)) {
  505. $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($entry[1])).', isdir='.($entry[1]['is_dir']? 1 : 0).' ' .$where);
  506. } else {
  507. $this->DB->exec('insert into '.$this->DB_TableName.' values ('.$path.', '.$fname.', '.$this->DB->quote(serialize($entry[1])).', '.(int)$entry[1]['is_dir'].')');
  508. }
  509. }
  510. } while (! empty($_info['has_more']));
  511. $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize(array('cursor'=>$cursor, 'mtime'=>$_SERVER['REQUEST_TIME']))).' where path=\'\' and fname=\'\'');
  512. if (! $this->DB->commit()) {
  513. $e = $this->DB->errorInfo();
  514. return $e[2];
  515. }
  516. if ($delete) {
  517. $this->DB->exec('vacuum');
  518. }
  519. } catch(Dropbox_Exception $e) {
  520. return $e->getMessage();
  521. }
  522. return true;
  523. }
  524. /**
  525. * Parse line from dropbox metadata output and return file stat (array)
  526. *
  527. * @param string $raw line from ftp_rawlist() output
  528. * @return array
  529. * @author Dmitry Levashov
  530. **/
  531. protected function parseRaw($raw) {
  532. $stat = array();
  533. $stat['rev'] = isset($raw['rev'])? $raw['rev'] : 'root';
  534. $stat['name'] = basename($raw['path']);
  535. $stat['mime'] = $raw['is_dir']? 'directory' : $raw['mime_type'];
  536. $stat['size'] = $stat['mime'] == 'directory' ? 0 : $raw['bytes'];
  537. $stat['ts'] = isset($raw['client_mtime'])? strtotime($raw['client_mtime']) :
  538. (isset($raw['modified'])? strtotime($raw['modified']) : $_SERVER['REQUEST_TIME']);
  539. $stat['dirs'] = 0;
  540. if ($raw['is_dir']) {
  541. $stat['dirs'] = (int)(bool)$this->query('select path from '.$this->DB_TableName.' where isdir=1 and path='.$this->DB->quote(strtolower($raw['path'])));
  542. }
  543. if (!empty($raw['url'])) {
  544. $stat['url'] = $raw['url'];
  545. } else {
  546. $stat['url'] = '1';
  547. }
  548. if (isset($raw['width'])) $stat['width'] = $raw['width'];
  549. if (isset($raw['height'])) $stat['height'] = $raw['height'];
  550. return $stat;
  551. }
  552. /**
  553. * Cache dir contents
  554. *
  555. * @param string $path dir path
  556. * @return void
  557. * @author Dmitry Levashov
  558. **/
  559. protected function cacheDir($path) {
  560. $this->dirsCache[$path] = array();
  561. $res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower($path)));
  562. if ($res) {
  563. foreach($res as $raw) {
  564. $raw = unserialize($raw);
  565. if ($stat = $this->parseRaw($raw)) {
  566. $stat = $this->updateCache($raw['path'], $stat);
  567. if (empty($stat['hidden'])) {
  568. $this->dirsCache[$path][] = $raw['path'];
  569. }
  570. }
  571. }
  572. }
  573. return $this->dirsCache[$path];
  574. }
  575. /**
  576. * Recursive files search
  577. *
  578. * @param string $path dir path
  579. * @param string $q search string
  580. * @param array $mimes
  581. * @return array
  582. * @author Naoki Sawada
  583. **/
  584. protected function doSearch($path, $q, $mimes) {
  585. $result = array();
  586. $sth = $this->DB->prepare('select dat from '.$this->DB_TableName.' WHERE path LIKE ? AND fname LIKE ?');
  587. $sth->execute(array('%'.(($path === $this->root)? '' : strtolower($path)), '%'.strtolower($q).'%'));
  588. $res = $sth->fetchAll(PDO::FETCH_COLUMN);
  589. if ($res) {
  590. foreach($res as $raw) {
  591. $raw = unserialize($raw);
  592. if ($stat = $this->parseRaw($raw)) {
  593. if (!isset($this->cache[$raw['path']])) {
  594. $stat = $this->updateCache($raw['path'], $stat);
  595. }
  596. if ($stat['mime'] !== 'directory' || $this->mimeAccepted($stat['mime'], $mimes)) {
  597. $result[] = $this->stat($raw['path']);
  598. }
  599. }
  600. }
  601. }
  602. return $result;
  603. }
  604. /**
  605. * Copy file/recursive copy dir only in current volume.
  606. * Return new file path or false.
  607. *
  608. * @param string $src source path
  609. * @param string $dst destination dir path
  610. * @param string $name new file name (optionaly)
  611. * @return string|false
  612. * @author Dmitry (dio) Levashov
  613. * @author Naoki Sawada
  614. **/
  615. protected function copy($src, $dst, $name) {
  616. $this->clearcache();
  617. return $this->_copy($src, $dst, $name)
  618. ? $this->_joinPath($dst, $name)
  619. : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
  620. }
  621. /**
  622. * Remove file/ recursive remove dir
  623. *
  624. * @param string $path file path
  625. * @param bool $force try to remove even if file locked
  626. * @return bool
  627. * @author Dmitry (dio) Levashov
  628. * @author Naoki Sawada
  629. **/
  630. protected function remove($path, $force = false, $recursive = false) {
  631. $stat = $this->stat($path);
  632. $stat['realpath'] = $path;
  633. $this->rmTmb($stat);
  634. $this->clearcache();
  635. if (empty($stat)) {
  636. return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
  637. }
  638. if (!$force && !empty($stat['locked'])) {
  639. return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
  640. }
  641. if ($stat['mime'] == 'directory') {
  642. if (!$recursive && !$this->_rmdir($path)) {
  643. return $this->setError(elFinder::ERROR_RM, $this->_path($path));
  644. }
  645. } else {
  646. if (!$recursive && !$this->_unlink($path)) {
  647. return $this->setError(elFinder::ERROR_RM, $this->_path($path));
  648. }
  649. }
  650. $this->removed[] = $stat;
  651. return true;
  652. }
  653. /**
  654. * Resize image
  655. *
  656. * @param string $hash image file
  657. * @param int $width new width
  658. * @param int $height new height
  659. * @param int $x X start poistion for crop
  660. * @param int $y Y start poistion for crop
  661. * @param string $mode action how to mainpulate image
  662. * @return array|false
  663. * @author Dmitry (dio) Levashov
  664. * @author Alexey Sukhotin
  665. * @author nao-pon
  666. * @author Troex Nevelin
  667. **/
  668. public function resize($hash, $width, $height, $x, $y, $mode = 'resize', $bg = '', $degree = 0) {
  669. if ($this->commandDisabled('resize')) {
  670. return $this->setError(elFinder::ERROR_PERM_DENIED);
  671. }
  672. if (($file = $this->file($hash)) == false) {
  673. return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
  674. }
  675. if (!$file['write'] || !$file['read']) {
  676. return $this->setError(elFinder::ERROR_PERM_DENIED);
  677. }
  678. $path = $this->decode($hash);
  679. if (!$this->canResize($path, $file)) {
  680. return $this->setError(elFinder::ERROR_UNSUPPORT_TYPE);
  681. }
  682. $path4stat = $path;
  683. if (! $path = $this->getLocalName($path)) {
  684. return false;
  685. }
  686. if (! $contents = $this->_getContents($path4stat)) {
  687. return false;
  688. }
  689. if (! @ file_put_contents($path, $contents, LOCK_EX)) {
  690. return false;
  691. }
  692. switch($mode) {
  693. case 'propresize':
  694. $result = $this->imgResize($path, $width, $height, true, true);
  695. break;
  696. case 'crop':
  697. $result = $this->imgCrop($path, $width, $height, $x, $y);
  698. break;
  699. case 'fitsquare':
  700. $result = $this->imgSquareFit($path, $width, $height, 'center', 'middle', ($bg ? $bg : $this->options['tmbBgColor']));
  701. break;
  702. case 'rotate':
  703. $result = $this->imgRotate($path, $degree, ($bg ? $bg : $this->options['tmbBgColor']));
  704. break;
  705. default:
  706. $result = $this->imgResize($path, $width, $height, false, true);
  707. break;
  708. }
  709. $result && $size = getimagesize($path);
  710. if ($result) {
  711. clearstatcache();
  712. $size = getimagesize($path);
  713. if ($fp = @fopen($path, 'rb')) {
  714. $res = $this->_save($fp, $path4stat, '', array());
  715. @fclose($fp);
  716. file_exists($path) && @unlink($path);
  717. $this->rmTmb($file);
  718. $this->clearcache();
  719. if ($size) {
  720. $raw = $this->getDBdat($path4stat);
  721. $raw['width'] = $size[0];
  722. $raw['height'] = $size[1];
  723. $this->updateDBdat($path4stat, $raw);
  724. }
  725. return $this->stat($path4stat);
  726. }
  727. }
  728. is_file($path) && @unlink($path);
  729. return false;
  730. }
  731. /**
  732. * Create thumnbnail and return it's URL on success
  733. *
  734. * @param string $path file path
  735. * @param string $mime file mime type
  736. * @return string|false
  737. * @author Dmitry (dio) Levashov
  738. * @author Naoki Sawada
  739. **/
  740. protected function createTmb($path, $stat) {
  741. if (!$stat || !$this->canCreateTmb($path, $stat)) {
  742. return false;
  743. }
  744. $name = $this->tmbname($stat);
  745. $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
  746. // copy image into tmbPath so some drivers does not store files on local fs
  747. if (! $data = $this->getThumbnail($path, $this->options['getTmbSize'])) {
  748. return false;
  749. }
  750. if (! file_put_contents($tmb, $data)) {
  751. return false;
  752. }
  753. $result = false;
  754. $tmbSize = $this->tmbSize;
  755. if (($s = getimagesize($tmb)) == false) {
  756. return false;
  757. }
  758. /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
  759. if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
  760. $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
  761. } else {
  762. if ($this->options['tmbCrop']) {
  763. /* Resize and crop if image bigger than thumbnail */
  764. if (!(($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize) ) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
  765. $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png');
  766. }
  767. if (($s = getimagesize($tmb)) != false) {
  768. $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize)/2) : 0;
  769. $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize)/2) : 0;
  770. $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png');
  771. }
  772. } else {
  773. $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, $this->imgLib, 'png');
  774. $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
  775. }
  776. }
  777. if (!$result) {
  778. unlink($tmb);
  779. return false;
  780. }
  781. return $name;
  782. }
  783. /**
  784. * Return thumbnail file name for required file
  785. *
  786. * @param array $stat file stat
  787. * @return string
  788. * @author Dmitry (dio) Levashov
  789. **/
  790. protected function tmbname($stat) {
  791. return $this->tmbPrefix.$stat['rev'].'.png';
  792. }
  793. /**
  794. * Get thumbnail from dropbox.com
  795. * @param string $path
  796. * @param string $size
  797. * @return string | boolean
  798. */
  799. protected function getThumbnail($path, $size = 'small') {
  800. try {
  801. return $this->dropbox->getThumbnail($path, $size);
  802. } catch (Dropbox_Exception $e) {
  803. return false;
  804. }
  805. }
  806. /**
  807. * Return content URL
  808. *
  809. * @param string $hash file hash
  810. * @param array $options options
  811. * @return array
  812. * @author Naoki Sawada
  813. **/
  814. public function getContentUrl($hash, $options = array()) {
  815. if (($file = $this->file($hash)) == false || !$file['url'] || $file['url'] == 1) {
  816. $path = $this->decode($hash);
  817. $cache = $this->getDBdat($path);
  818. $url = '';
  819. if (isset($cache['share'])) {
  820. $res = $this->getHttpResponseHeader($cache['share']);
  821. if (preg_match("/^HTTP\/[01\.]+ ([0-9]{3})/", $res, $match)) {
  822. if (preg_match('/^location:\s*(http[^\s]+)/im', $res, $match)) {
  823. $url = $match[1];
  824. } else if ($match[1] >= 400) {
  825. $url = '';
  826. }
  827. } else {
  828. $url = '';
  829. }
  830. }
  831. if (! $url) {
  832. try {
  833. $res = $this->dropbox->share($path);
  834. $res = $this->getHttpResponseHeader($res['url']);
  835. if (preg_match('/^location:\s*(http[^\s]+)/im', $res, $match)) {
  836. $url = $match[1] . '?dl=1';
  837. }
  838. if ($url) {
  839. if (! isset($cache['share']) || $cache['share'] !== $url) {
  840. $cache['share'] = $url;
  841. $this->updateDBdat($path, $cache);
  842. }
  843. $res = $this->getHttpResponseHeader($url);
  844. if (preg_match('/^location:\s*(http[^\s?]+)/im', $res, $match)) {
  845. $url = $match[1];
  846. }
  847. }
  848. } catch (Dropbox_Exception $e) {
  849. return false;
  850. }
  851. }
  852. if ($url) {
  853. list($url) = explode('?', $url);
  854. }
  855. return $url;
  856. }
  857. return $file['url'];
  858. }
  859. /**
  860. * Get HTTP request response header string
  861. *
  862. * @param string $url target URL
  863. * @return string
  864. * @author Naoki Sawada
  865. */
  866. private function getHttpResponseHeader($url) {
  867. if (function_exists('curl_exec')) {
  868. $c = curl_init();
  869. curl_setopt( $c, CURLOPT_RETURNTRANSFER, true );
  870. curl_setopt( $c, CURLOPT_CUSTOMREQUEST, 'HEAD' );
  871. curl_setopt( $c, CURLOPT_HEADER, 1 );
  872. curl_setopt( $c, CURLOPT_NOBODY, true );
  873. curl_setopt( $c, CURLOPT_URL, $url );
  874. $res = curl_exec( $c );
  875. } else {
  876. require_once 'HTTP/Request2.php';
  877. try {
  878. $request2 = new HTTP_Request2();
  879. $request2->setConfig(array(
  880. 'ssl_verify_peer' => false,
  881. 'ssl_verify_host' => false
  882. ));
  883. $request2->setUrl($url);
  884. $request2->setMethod(HTTP_Request2::METHOD_HEAD);
  885. $result = $request2->send();
  886. $res = array();
  887. $res[] = 'HTTP/'.$result->getVersion().' '.$result->getStatus().' '.$result->getReasonPhrase();
  888. foreach($result->getHeader() as $key => $val) {
  889. $res[] = $key . ': ' . $val;
  890. }
  891. $res = join("\r\n", $res);
  892. } catch( HTTP_Request2_Exception $e ){
  893. $res = '';
  894. } catch (Exception $e){
  895. $res = '';
  896. }
  897. }
  898. return $res;
  899. }
  900. /*********************** paths/urls *************************/
  901. /**
  902. * Return parent directory path
  903. *
  904. * @param string $path file path
  905. * @return string
  906. * @author Dmitry (dio) Levashov
  907. **/
  908. protected function _dirname($path) {
  909. return dirname($path);
  910. }
  911. /**
  912. * Return file name
  913. *
  914. * @param string $path file path
  915. * @return string
  916. * @author Dmitry (dio) Levashov
  917. **/
  918. protected function _basename($path) {
  919. return basename($path);
  920. }
  921. /**
  922. * Join dir name and file name and retur full path
  923. *
  924. * @param string $dir
  925. * @param string $name
  926. * @return string
  927. * @author Dmitry (dio) Levashov
  928. **/
  929. protected function _joinPath($dir, $name) {
  930. return $this->_normpath($dir.'/'.$name);
  931. }
  932. /**
  933. * Return normalized path, this works the same as os.path.normpath() in Python
  934. *
  935. * @param string $path path
  936. * @return string
  937. * @author Troex Nevelin
  938. **/
  939. protected function _normpath($path) {
  940. $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
  941. $path = '/' . ltrim($path, '/');
  942. return $path;
  943. }
  944. /**
  945. * Return file path related to root dir
  946. *
  947. * @param string $path file path
  948. * @return string
  949. * @author Dmitry (dio) Levashov
  950. **/
  951. protected function _relpath($path) {
  952. return $path;
  953. }
  954. /**
  955. * Convert path related to root dir into real path
  956. *
  957. * @param string $path file path
  958. * @return string
  959. * @author Dmitry (dio) Levashov
  960. **/
  961. protected function _abspath($path) {
  962. return $path;
  963. }
  964. /**
  965. * Return fake path started from root dir
  966. *
  967. * @param string $path file path
  968. * @return string
  969. * @author Dmitry (dio) Levashov
  970. **/
  971. protected function _path($path) {
  972. return $path;
  973. }
  974. /**
  975. * Return true if $path is children of $parent
  976. *
  977. * @param string $path path to check
  978. * @param string $parent parent path
  979. * @return bool
  980. * @author Dmitry (dio) Levashov
  981. **/
  982. protected function _inpath($path, $parent) {
  983. return $path == $parent || strpos($path, $parent.'/') === 0;
  984. }
  985. /***************** file stat ********************/
  986. /**
  987. * Return stat for given path.
  988. * Stat contains following fields:
  989. * - (int) size file size in b. required
  990. * - (int) ts file modification time in unix time. required
  991. * - (string) mime mimetype. required for folders, others - optionally
  992. * - (bool) read read permissions. required
  993. * - (bool) write write permissions. required
  994. * - (bool) locked is object locked. optionally
  995. * - (bool) hidden is object hidden. optionally
  996. * - (string) alias for symlinks - link target path relative to root path. optionally
  997. * - (string) target for symlinks - link target path. optionally
  998. *
  999. * If file does not exists - returns empty array or false.
  1000. *
  1001. * @param string $path file path
  1002. * @return array|false
  1003. * @author Dmitry (dio) Levashov
  1004. **/
  1005. protected function _stat($path) {
  1006. if ($raw = $this->getDBdat($path)) {
  1007. return $this->parseRaw($raw);
  1008. }
  1009. return false;
  1010. }
  1011. /**
  1012. * Return true if path is dir and has at least one childs directory
  1013. *
  1014. * @param string $path dir path
  1015. * @return bool
  1016. * @author Dmitry (dio) Levashov
  1017. **/
  1018. protected function _subdirs($path) {
  1019. return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
  1020. }
  1021. /**
  1022. * Return object width and height
  1023. * Ususaly used for images, but can be realize for video etc...
  1024. *
  1025. * @param string $path file path
  1026. * @param string $mime file mime type
  1027. * @return string
  1028. * @author Dmitry (dio) Levashov
  1029. **/
  1030. protected function _dimensions($path, $mime) {
  1031. if (strpos($mime, 'image') !== 0) return '';
  1032. $cache = $this->getDBdat($path);
  1033. if (isset($cache['width']) && isset($cache['height'])) {
  1034. return $cache['width'].'x'.$cache['height'];
  1035. }
  1036. if ($local = $this->getLocalName($path)) {
  1037. if (file_put_contents($local, $this->dropbox->getFile($path), LOCK_EX)) {
  1038. if ($size = @getimagesize($local)) {
  1039. $cache['width'] = $size[0];
  1040. $cache['height'] = $size[1];
  1041. $this->updateDBdat($path, $cache);
  1042. unlink($local);
  1043. return $size[0].'x'.$size[1];
  1044. }
  1045. unlink($local);
  1046. }
  1047. }
  1048. return '';
  1049. }
  1050. /******************** file/dir content *********************/
  1051. /**
  1052. * Return files list in directory.
  1053. *
  1054. * @param string $path dir path
  1055. * @return array
  1056. * @author Dmitry (dio) Levashov
  1057. * @author Cem (DiscoFever)
  1058. **/
  1059. protected function _scandir($path) {
  1060. return isset($this->dirsCache[$path])
  1061. ? $this->dirsCache[$path]
  1062. : $this->cacheDir($path);
  1063. }
  1064. /**
  1065. * Open file and return file pointer
  1066. *
  1067. * @param string $path file path
  1068. * @param bool $write open file for writing
  1069. * @return resource|false
  1070. * @author Dmitry (dio) Levashov
  1071. **/
  1072. protected function _fopen($path, $mode='rb') {
  1073. if (($mode == 'rb' || $mode == 'r')) {
  1074. try {
  1075. $res = $this->dropbox->media($path);
  1076. $url = parse_url($res['url']);
  1077. $fp = stream_socket_client('ssl://'.$url['host'].':443');
  1078. fputs($fp, "GET {$url['path']} HTTP/1.0\r\n");
  1079. fputs($fp, "Host: {$url['host']}\r\n");
  1080. fputs($fp, "\r\n");
  1081. while(trim(fgets($fp)) !== ''){};
  1082. return $fp;
  1083. } catch (Dropbox_Exception $e) {
  1084. return false;
  1085. }
  1086. }
  1087. if ($this->tmp) {
  1088. $contents = $this->_getContents($path);
  1089. if ($contents === false) {
  1090. return false;
  1091. }
  1092. if ($local = $this->getLocalName($path)) {
  1093. if (file_put_contents($local, $contents, LOCK_EX) !== false) {
  1094. return @fopen($local, $mode);
  1095. }
  1096. }
  1097. }
  1098. return false;
  1099. }
  1100. /**
  1101. * Close opened file
  1102. *
  1103. * @param resource $fp file pointer
  1104. * @return bool
  1105. * @author Dmitry (dio) Levashov
  1106. **/
  1107. protected function _fclose($fp, $path='') {
  1108. @fclose($fp);
  1109. if ($path) {
  1110. @unlink($this->getLocalName($path));
  1111. }
  1112. }
  1113. /******************** file/dir manipulations *************************/
  1114. /**
  1115. * Create dir and return created dir path or false on failed
  1116. *
  1117. * @param string $path parent dir path
  1118. * @param string $name new directory name
  1119. * @return string|bool
  1120. * @author Dmitry (dio) Levashov
  1121. **/
  1122. protected function _mkdir($path, $name) {
  1123. $path = $this->_normpath($path.'/'.$name);
  1124. try {
  1125. $this->dropbox->createFolder($path);
  1126. } catch (Dropbox_Exception $e) {
  1127. $this->deltaCheck();
  1128. if ($this->dir($this->encode($path))) {
  1129. return $path;
  1130. }
  1131. return $this->setError('Dropbox error: '.$e->getMessage());
  1132. }
  1133. $this->deltaCheck();
  1134. return $path;
  1135. }
  1136. /**
  1137. * Create file and return it's path or false on failed
  1138. *
  1139. * @param string $path parent dir path
  1140. * @param string $name new file name
  1141. * @return string|bool
  1142. * @author Dmitry (dio) Levashov
  1143. **/
  1144. protected function _mkfile($path, $name) {
  1145. return $this->_filePutContents($path.'/'.$name, '');
  1146. }
  1147. /**
  1148. * Create symlink. FTP driver does not support symlinks.
  1149. *
  1150. * @param string $target link target
  1151. * @param string $path symlink path
  1152. * @return bool
  1153. * @author Dmitry (dio) Levashov
  1154. **/
  1155. protected function _symlink($target, $path, $name) {
  1156. return false;
  1157. }
  1158. /**
  1159. * Copy file into another file
  1160. *
  1161. * @param string $source source file path
  1162. * @param string $targetDir target directory path
  1163. * @param string $name new file name
  1164. * @return bool
  1165. * @author Dmitry (dio) Levashov
  1166. **/
  1167. protected function _copy($source, $targetDir, $name) {
  1168. $path = $this->_normpath($targetDir.'/'.$name);
  1169. try {
  1170. $this->dropbox->copy($source, $path);
  1171. } catch (Dropbox_Exception $e) {
  1172. return $this->setError('Dropbox error: '.$e->getMessage());
  1173. }
  1174. $this->deltaCheck();
  1175. return true;
  1176. }
  1177. /**
  1178. * Move file into another parent dir.
  1179. * Return new file path or false.
  1180. *
  1181. * @param string $source source file path
  1182. * @param string $target target dir path
  1183. * @param string $name file name
  1184. * @return string|bool
  1185. * @author Dmitry (dio) Levashov
  1186. **/
  1187. protected function _move($source, $targetDir, $name) {
  1188. $target = $this->_normpath($targetDir.'/'.$name);
  1189. try {
  1190. $this->dropbox->move($source, $target);
  1191. } catch (Dropbox_Exception $e) {
  1192. return $this->setError('Dropbox error: '.$e->getMessage());
  1193. }
  1194. $this->deltaCheck();
  1195. return $target;
  1196. }
  1197. /**
  1198. * Remove file
  1199. *
  1200. * @param string $path file path
  1201. * @return bool
  1202. * @author Dmitry (dio) Levashov
  1203. **/
  1204. protected function _unlink($path) {
  1205. try {
  1206. $this->dropbox->delete($path);
  1207. } catch (Dropbox_Exception $e) {
  1208. return $this->setError('Dropbox error: '.$e->getMessage());
  1209. }
  1210. $this->deltaCheck();
  1211. return true;
  1212. }
  1213. /**
  1214. * Remove dir
  1215. *
  1216. * @param string $path dir path
  1217. * @return bool
  1218. * @author Dmitry (dio) Levashov
  1219. **/
  1220. protected function _rmdir($path) {
  1221. return $this->_unlink($path);
  1222. }
  1223. /**
  1224. * Create new file and write into it from file pointer.
  1225. * Return new file path or false on error.
  1226. *
  1227. * @param resource $fp file pointer
  1228. * @param string $dir target dir path
  1229. * @param string $name file name
  1230. * @param array $stat file stat (required by some virtual fs)
  1231. * @return bool|string
  1232. * @author Dmitry (dio) Levashov
  1233. **/
  1234. protected function _save($fp, $path, $name, $stat) {
  1235. if ($name) $path .= '/'.$name;
  1236. $path = $this->_normpath($path);
  1237. try {
  1238. $this->dropbox->putFile($path, $fp);
  1239. } catch (Dropbox_Exception $e) {
  1240. return $this->setError('Dropbox error: '.$e->getMessage());
  1241. }
  1242. $this->deltaCheck();
  1243. return $path;
  1244. }
  1245. /**
  1246. * Get file contents
  1247. *
  1248. * @param string $path file path
  1249. * @return string|false
  1250. * @author Dmitry (dio) Levashov
  1251. **/
  1252. protected function _getContents($path) {
  1253. $contents = '';
  1254. try {
  1255. $contents = $this->dropbox->getFile($path);
  1256. } catch (Dropbox_Exception $e) {
  1257. return $this->setError('Dropbox error: '.$e->getMessage());
  1258. }
  1259. return $contents;
  1260. }
  1261. /**
  1262. * Write a string to a file
  1263. *
  1264. * @param string $path file path
  1265. * @param string $content new file content
  1266. * @return bool
  1267. * @author Dmitry (dio) Levashov
  1268. **/
  1269. protected function _filePutContents($path, $content) {
  1270. $res = false;
  1271. if ($local = $this->getLocalName($path)) {
  1272. $local .= '.txt';
  1273. if (@file_put_contents($local, $content, LOCK_EX) !== false
  1274. && ($fp = @fopen($local, 'rb'))) {
  1275. clearstatcache();
  1276. $res = $this->_save($fp, $path, '', array());
  1277. @fclose($fp);
  1278. }
  1279. file_exists($local) && @unlink($local);
  1280. }
  1281. return $res;
  1282. }
  1283. /**
  1284. * Detect available archivers
  1285. *
  1286. * @return void
  1287. **/
  1288. protected function _checkArchivers() {
  1289. // die('Not yet implemented. (_checkArchivers)');
  1290. return array();
  1291. }
  1292. /**
  1293. * Unpack archive
  1294. *
  1295. * @param string $path archive path
  1296. * @param array $arc archiver command and arguments (same as in $this->archivers)
  1297. * @return true
  1298. * @return void
  1299. * @author Dmitry (dio) Levashov
  1300. * @author Alexey Sukhotin
  1301. **/
  1302. protected function _unpack($path, $arc) {
  1303. die('Not yet implemented. (_unpack)');
  1304. return false;
  1305. }
  1306. /**
  1307. * Recursive symlinks search
  1308. *
  1309. * @param string $path file/dir path
  1310. * @return bool
  1311. * @author Dmitry (dio) Levashov
  1312. **/
  1313. protected function _findSymlinks($path) {
  1314. die('Not yet implemented. (_findSymlinks)');
  1315. if (is_link($path)) {
  1316. return true;
  1317. }
  1318. if (is_dir($path)) {
  1319. foreach (scandir($path) as $name) {
  1320. if ($name != '.' && $name != '..') {
  1321. $p = $path.DIRECTORY_SEPARATOR.$name;
  1322. if (is_link($p)) {
  1323. return true;
  1324. }
  1325. if (is_dir($p) && $this->_findSymlinks($p)) {
  1326. return true;
  1327. } elseif (is_file($p)) {
  1328. $this->archiveSize += filesize($p);
  1329. }
  1330. }
  1331. }
  1332. } else {
  1333. $this->archiveSize += filesize($path);
  1334. }
  1335. return false;
  1336. }
  1337. /**
  1338. * Extract files from archive
  1339. *
  1340. * @param string $path archive path
  1341. * @param array $arc archiver command and arguments (same as in $this->archivers)
  1342. * @return true
  1343. * @author Dmitry (dio) Levashov,
  1344. * @author Alexey Sukhotin
  1345. **/
  1346. protected function _extract($path, $arc) {
  1347. die('Not yet implemented. (_extract)');
  1348. }
  1349. /**
  1350. * Create archive and return its path
  1351. *
  1352. * @param string $dir target dir
  1353. * @param array $files files names list
  1354. * @param string $name archive name
  1355. * @param array $arc archiver options
  1356. * @return string|bool
  1357. * @author Dmitry (dio) Levashov,
  1358. * @author Alexey Sukhotin
  1359. **/
  1360. protected function _archive($dir, $files, $name, $arc) {
  1361. die('Not yet implemented. (_archive)');
  1362. return false;
  1363. }
  1364. } // END class