PageRenderTime 39ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/downloader/lib/Mage/Connect/Ftp.php

https://bitbucket.org/jokusafet/magento2
PHP | 533 lines | 400 code | 15 blank | 118 comment | 22 complexity | 59a7e71c20b2e7ff531163ab2087ed75 MD5 | raw file
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Connect
  23. * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Class to work with remote FTP server
  28. *
  29. * @category Mage
  30. * @package Mage_Connect
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Connect_Ftp
  34. {
  35. /**
  36. * Connection object
  37. *
  38. * @var resource
  39. */
  40. protected $_conn = false;
  41. /**
  42. * Check connected, throw exception if not
  43. *
  44. * @throws Exception
  45. * @return null
  46. */
  47. protected function checkConnected()
  48. {
  49. if(!$this->_conn) {
  50. throw new Exception(__CLASS__." - no connection established with server");
  51. }
  52. }
  53. /**
  54. * ftp_mkdir wrapper
  55. *
  56. * @param string $name
  57. * @return string
  58. */
  59. public function mdkir($name)
  60. {
  61. $this->checkConnected();
  62. return @ftp_mkdir($this->_conn, $name);
  63. }
  64. /**
  65. * Make dir recursive
  66. *
  67. * @param string $path
  68. * @param int $mode
  69. */
  70. public function mkdirRecursive($path, $mode = 0777)
  71. {
  72. $this->checkConnected();
  73. $dir = explode('/', $path);
  74. $path= "";
  75. $ret = true;
  76. for ($i=0; $i < count($dir); $i++) {
  77. $path .= "/" .$dir[$i];
  78. if(!@ftp_chdir($this->_conn, $path)) {
  79. @ftp_chdir($this->_conn,"/");
  80. if(!@ftp_mkdir($this->_conn,$path)) {
  81. $ret=false;
  82. break;
  83. } else {
  84. @ftp_chmod($this->_conn, $mode, $path);
  85. }
  86. }
  87. }
  88. return $ret;
  89. }
  90. /**
  91. * Try to login to server
  92. *
  93. * @param string $login
  94. * @param string $password
  95. * @throws Exception on invalid login credentials
  96. * @return boolean
  97. */
  98. public function login($login = "anonymous", $password = "test@gmail.com")
  99. {
  100. $this->checkConnected();
  101. $res = @ftp_login($this->_conn, $login, $password);
  102. if(!$res) {
  103. throw new Exception("Invalid login credentials");
  104. }
  105. return $res;
  106. }
  107. /**
  108. * Validate connection string
  109. *
  110. * @param string $string
  111. * @throws Exception
  112. * @return string
  113. */
  114. public function validateConnectionString($string)
  115. {
  116. if (empty($string)) {
  117. throw new Exception("Connection string is empty");
  118. }
  119. $data = @parse_url($string);
  120. if(false === $data) {
  121. throw new Exception("Connection string invalid: '{$string}'");
  122. }
  123. if($data['scheme'] != 'ftp') {
  124. throw new Exception("Support for scheme '{$data['scheme']}' unsupported");
  125. }
  126. return $data;
  127. }
  128. /**
  129. * Connect to server using connect string
  130. * Connection string: ftp://user:pass@server:port/path
  131. * user,pass,port,path are optional parts
  132. *
  133. * @param string $string
  134. * @param int $timeout
  135. * @return null
  136. */
  137. public function connect($string, $timeout = 90)
  138. {
  139. $params = $this->validateConnectionString($string);
  140. $port = isset($params['port']) ? intval($params['port']) : 21;
  141. $this->_conn = @ftp_connect($params['host'], $port, $timeout);
  142. if(!$this->_conn) {
  143. throw new Exception("Cannot connect to host: {$params['host']}");
  144. }
  145. ftp_pasv($this->_conn, true);
  146. if(isset($params['user']) && isset($params['pass'])) {
  147. $this->login($params['user'], $params['pass']);
  148. } else {
  149. $this->login();
  150. }
  151. if(isset($params['path'])) {
  152. if(!$this->chdir($params['path'])) {
  153. throw new Exception ("Cannot chdir after login to: {$params['path']}");
  154. }
  155. }
  156. }
  157. /**
  158. * ftp_fput wrapper
  159. *
  160. * @param string $remoteFile
  161. * @param resource $handle
  162. * @param int $mode FTP_BINARY | FTP_ASCII
  163. * @param int $startPos
  164. * @return boolean
  165. */
  166. public function fput($remoteFile, $handle, $mode = FTP_BINARY, $startPos = 0)
  167. {
  168. $this->checkConnected();
  169. return @ftp_fput($this->_conn, $remoteFile, $handle, $mode, $startPos);
  170. }
  171. /**
  172. * ftp_put wrapper
  173. *
  174. * @param string $remoteFile
  175. * @param string $localFile
  176. * @param int $mode FTP_BINARY | FTP_ASCII
  177. * @param int $startPos
  178. * @return boolean
  179. */
  180. public function put($remoteFile, $localFile, $mode = FTP_BINARY, $startPos = 0)
  181. {
  182. $this->checkConnected();
  183. return @ftp_put($this->_conn, $remoteFile, $localFile, $mode, $startPos);
  184. }
  185. /**
  186. * Get current working directory
  187. *
  188. * @return string
  189. */
  190. public function getcwd()
  191. {
  192. $d = $this->raw("pwd");
  193. $data = explode(" ", $d[0], 3);
  194. if(empty($data[1])) {
  195. return false;
  196. }
  197. if(intval($data[0]) != 257) {
  198. return false;
  199. }
  200. $out = trim($data[1], '"');
  201. if($out !== "/") {
  202. $out = rtrim($out, "/");
  203. }
  204. return $out;
  205. }
  206. /**
  207. * ftp_raw wrapper
  208. *
  209. * @param string $cmd
  210. * @return array
  211. */
  212. public function raw($cmd)
  213. {
  214. $this->checkConnected();
  215. return @ftp_raw($this->_conn, $cmd);
  216. }
  217. /**
  218. * Upload local file to remote server.
  219. * Can be used for relative and absoulte remote paths
  220. * Relative: use chdir before calling this
  221. *
  222. * @param string $remote
  223. * @param string $local
  224. * @param int $dirMode
  225. * @param int $fileMode
  226. * @return boolean
  227. */
  228. public function upload($remote, $local, $dirMode = 0777, $fileMode=0)
  229. {
  230. $this->checkConnected();
  231. if(!file_exists($local)) {
  232. throw new Exception("Local file doesn't exist: {$local}");
  233. }
  234. if(!is_readable($local)) {
  235. throw new Exception("Local file is not readable: {$local}");
  236. }
  237. if(is_dir($local)) {
  238. throw new Exception("Directory given instead of file: {$local}");
  239. }
  240. $globalPathMode = substr($remote, 0, 1) == "/";
  241. $dirname = dirname($remote);
  242. $cwd = $this->getcwd();
  243. if(false === $cwd) {
  244. throw new Exception("Server returns something awful on PWD command");
  245. }
  246. if(!$globalPathMode) {
  247. $dirname = $cwd."/".$dirname;
  248. $remote = $cwd."/".$remote;
  249. }
  250. $res = $this->mkdirRecursive($dirname, $dirMode);
  251. $this->chdir($cwd);
  252. if(!$res) {
  253. return false;
  254. }
  255. $res = $this->put($remote, $local);
  256. if(!$res) {
  257. return false;
  258. }
  259. if($fileMode){
  260. $res=$this->chmod($fileMode, $remote);
  261. }
  262. return (boolean)$res;
  263. }
  264. /**
  265. * Download remote file to local machine
  266. *
  267. * @param string $remote
  268. * @param string $local
  269. * @param int $ftpMode FTP_BINARY|FTP_ASCII
  270. * @return boolean
  271. */
  272. public function download($remote, $local, $ftpMode = FTP_BINARY)
  273. {
  274. $this->checkConnected();
  275. return $this->get($local, $remote, $ftpMode);
  276. }
  277. /**
  278. * ftp_pasv wrapper
  279. *
  280. * @param boolean $pasv
  281. * @return boolean
  282. */
  283. public function pasv($pasv)
  284. {
  285. $this->checkConnected();
  286. return @ftp_pasv($this->_conn, (boolean) $pasv);
  287. }
  288. /**
  289. * Close FTP connection
  290. *
  291. * @return null
  292. */
  293. public function close()
  294. {
  295. if($this->_conn) {
  296. @ftp_close($this->_conn);
  297. }
  298. }
  299. /**
  300. * ftp_chmod wrapper
  301. *
  302. * @param $mode
  303. * @param $remoteFile
  304. * @return boolean
  305. */
  306. public function chmod($mode, $remoteFile)
  307. {
  308. $this->checkConnected();
  309. return @ftp_chmod($this->_conn, $mode, $remoteFile);
  310. }
  311. /**
  312. * ftp_chdir wrapper
  313. *
  314. * @param string $dir
  315. * @return boolean
  316. */
  317. public function chdir($dir)
  318. {
  319. $this->checkConnected();
  320. return @ftp_chdir($this->_conn, $dir);
  321. }
  322. /**
  323. * ftp_cdup wrapper
  324. *
  325. * @return boolean
  326. */
  327. public function cdup()
  328. {
  329. $this->checkConnected();
  330. return @ftp_cdup($this->_conn);
  331. }
  332. /**
  333. * ftp_get wrapper
  334. *
  335. * @param string $localFile
  336. * @param string $remoteFile
  337. * @param int $fileMode FTP_BINARY | FTP_ASCII
  338. * @param int $resumeOffset
  339. * @return boolean
  340. */
  341. public function get($localFile, $remoteFile, $fileMode = FTP_BINARY, $resumeOffset = 0)
  342. {
  343. $remoteFile = $this->correctFilePath($remoteFile);
  344. $this->checkConnected();
  345. return @ftp_get($this->_conn, $localFile, $remoteFile, $fileMode, $resumeOffset);
  346. }
  347. /**
  348. * ftp_nlist wrapper
  349. *
  350. * @param string $dir
  351. * @return boolean
  352. */
  353. public function nlist($dir = "/")
  354. {
  355. $this->checkConnected();
  356. $dir = $this->correctFilePath($dir);
  357. return @ftp_nlist($this->_conn, $dir);
  358. }
  359. /**
  360. * ftp_rawlist wrapper
  361. *
  362. * @param string $dir
  363. * @param boolean $recursive
  364. * @return array
  365. */
  366. public function rawlist( $dir = "/", $recursive = false )
  367. {
  368. $this->checkConnected();
  369. $dir = $this->correctFilePath($dir);
  370. return @ftp_rawlist($this->_conn, $dir, $recursive);
  371. }
  372. /**
  373. * Convert byte count to float KB/MB format
  374. *
  375. * @param int $bytes
  376. * @return string
  377. */
  378. public static function byteconvert($bytes)
  379. {
  380. $symbol = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
  381. $exp = floor( log($bytes) / log(1024) );
  382. return sprintf( '%.2f ' . $symbol[ $exp ], ($bytes / pow(1024, floor($exp))) );
  383. }
  384. /**
  385. * Chmod string "-rwxrwxrwx" to "777" converter
  386. *
  387. * @param string $chmod
  388. * @return string
  389. */
  390. public static function chmodnum($chmod)
  391. {
  392. $trans = array('-' => '0', 'r' => '4', 'w' => '2', 'x' => '1');
  393. $chmod = substr(strtr($chmod, $trans), 1);
  394. $array = str_split($chmod, 3);
  395. return array_sum(str_split($array[0])) . array_sum(str_split($array[1])) . array_sum(str_split($array[2]));
  396. }
  397. /**
  398. * Checks file exists
  399. *
  400. * @param string $path
  401. * @param boolean $excludeIfIsDir
  402. * @return boolean
  403. */
  404. public function fileExists($path, $excludeIfIsDir = true)
  405. {
  406. $path = $this->correctFilePath($path);
  407. $globalPathMode = substr($path, 0, 1) == "/";
  408. $file = basename($path);
  409. $dir = $globalPathMode ? dirname($path) : $this->getcwd()."/".($path==basename($path)?'':$path);
  410. $data = $this->ls($dir);
  411. foreach($data as $row) {
  412. if($file == basename($row['name'])) {
  413. if($excludeIfIsDir && $row['dir']) {
  414. continue;
  415. }
  416. return true;
  417. }
  418. }
  419. return false;
  420. }
  421. /**
  422. * Get directory contents in PHP array
  423. *
  424. * @param string $dir
  425. * @param boolean $recursive
  426. * @return array
  427. */
  428. public function ls($dir = "/", $recursive = false)
  429. {
  430. $dir= $this->correctFilePath($dir);
  431. $rawfiles = (array) $this->rawlist($dir, $recursive);
  432. $structure = array();
  433. $arraypointer = &$structure;
  434. foreach ($rawfiles as $rawfile) {
  435. if ($rawfile[0] == '/') {
  436. $paths = array_slice(explode('/', str_replace(':', '', $rawfile)), 1);
  437. $arraypointer = &$structure;
  438. foreach ($paths as $path) {
  439. foreach ($arraypointer as $i => $file) {
  440. if ($file['name'] == $path) {
  441. $arraypointer = &$arraypointer[ $i ]['children'];
  442. break;
  443. }
  444. }
  445. }
  446. } elseif(!empty($rawfile)) {
  447. $info = preg_split("/[\s]+/", $rawfile, 9);
  448. $arraypointer[] = array(
  449. 'name' => $info[8],
  450. 'dir' => $info[0]{0} == 'd',
  451. 'size' => (int) $info[4],
  452. 'chmod' => self::chmodnum($info[0]),
  453. 'rawdata' => $info,
  454. 'raw' => $rawfile
  455. );
  456. }
  457. }
  458. return $structure;
  459. }
  460. /**
  461. * Correct file path
  462. *
  463. * @param $str
  464. * @return string
  465. */
  466. public function correctFilePath($str)
  467. {
  468. $str = str_replace("\\", "/", $str);
  469. $str = preg_replace("/^.\//", "", $str);
  470. return $str;
  471. }
  472. /**
  473. * Delete file
  474. *
  475. * @param string $file
  476. * @return boolean
  477. */
  478. public function delete($file)
  479. {
  480. $this->checkConnected();
  481. $file = $this->correctFilePath($file);
  482. return @ftp_delete($this->_conn, $file);
  483. }
  484. /**
  485. * Remove directory
  486. *
  487. * @param string $dir
  488. * @return boolean
  489. */
  490. public function rmdir($dir)
  491. {
  492. $this->checkConnected();
  493. $dir = $this->correctFilePath($dir);
  494. return @ftp_rmdir($this->_conn, $dir);
  495. }
  496. }