PageRenderTime 58ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

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

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