PageRenderTime 24ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/administrator/components/com_joomlapack/classes/engine/packer/directftp.php

https://github.com/Ratmir15/Joomla---formula-of-success
PHP | 331 lines | 190 code | 43 blank | 98 comment | 35 complexity | 847cbf789928a1b6d0a1d4989c1e6e80 MD5 | raw file
  1. <?php
  2. /**
  3. * @package JoomlaPack
  4. * @copyright Copyright (C) 2006-2009 JoomlaPack Developers. All rights reserved.
  5. * @version $Id$
  6. * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
  7. * @since 2.3
  8. *
  9. * JoomlaPack is free software. This version may have been modified pursuant
  10. * to the GNU General Public License, and as distributed it includes or
  11. * is derivative of works licensed under the GNU General Public License or
  12. * other free or open source software licenses.
  13. **/
  14. defined('_JEXEC') or die('Restricted access');
  15. jpimport('core.utility.tempfiles');
  16. /**
  17. * Direct Transfer Over FTP archiver class
  18. *
  19. * Transfers the files to a remote FTP server instead of putting them in
  20. * an archive
  21. * @author Nicholas K. Dionysopoulos
  22. *
  23. */
  24. class JoomlapackPackerDirectftp extends JoomlapackCUBEArchiver
  25. {
  26. /** @var resource FTP resource handle */
  27. var $_ftphandle;
  28. /** @var string FTP hostname */
  29. var $_host;
  30. /** @var string FTP port */
  31. var $_port;
  32. /** @var string FTP username */
  33. var $_user;
  34. /** @var string FTP password */
  35. var $_pass;
  36. /** @var bool Should we use FTP over SSL? */
  37. var $_usessl;
  38. /** @var bool Should we use passive FTP? */
  39. var $_passive;
  40. /** @var string FTP initial directory */
  41. var $_initdir;
  42. /** @var string Current remote directory, including the remote directory string */
  43. var $_currentdir;
  44. /** @var bool Could we connect to the server? */
  45. var $connect_ok = false;
  46. // ------------------------------------------------------------------------
  47. // Implementation of abstract methods
  48. // ------------------------------------------------------------------------
  49. /**
  50. * Initialises the archiver class, seeding the remote installation
  51. * from an existent installer's JPA archive.
  52. *
  53. * @param string $sourceJPAPath Absolute path to an installer's JPA archive
  54. * @param string $targetArchivePath Absolute path to the generated archive (ignored in this class)
  55. * @param array $options A named key array of options (optional)
  56. * @access public
  57. */
  58. function initialize( $sourceJPAPath, $targetArchivePath, $options = array() )
  59. {
  60. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, __CLASS__." :: new instance");
  61. $registry =& JoomlapackModelRegistry::getInstance();
  62. $this->_host = $registry->get('df_host','');
  63. $this->_port = $registry->get('df_port','21');
  64. $this->_user = $registry->get('df_user','');
  65. $this->_pass = $registry->get('df_pass','');
  66. $this->_initdir = $registry->get('df_initdir','');
  67. $this->_usessl = $registry->get('df_usessl', false);
  68. $this->_passive = $registry->get('df_passive', true);
  69. if(isset($options['host'])) $this->_host = $options['host'];
  70. if(isset($options['port'])) $this->_port = $options['port'];
  71. if(isset($options['user'])) $this->_user = $options['user'];
  72. if(isset($options['pass'])) $this->_pass = $options['pass'];
  73. if(isset($options['initdir'])) $this->_initdir = $options['initdir'];
  74. if(isset($options['usessl'])) $this->_usessl = $options['usessl'];
  75. if(isset($options['passive'])) $this->_passive = $options['passive'];
  76. $this->connect_ok = $this->_connectFTP();
  77. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, __CLASS__." :: Initializing with $sourceJPAPath");
  78. parent::initialize($sourceJPAPath, $targetArchivePath, $options);
  79. }
  80. function finalize()
  81. {
  82. // Really does nothing...
  83. }
  84. /**
  85. * The most basic file transaction: add a single entry (file or directory) to
  86. * the archive.
  87. *
  88. * @param bool $isVirtual If true, the next parameter contains file data instead of a file name
  89. * @param string $sourceNameOrData Absolute file name to read data from or the file data itself is $isVirtual is true
  90. * @param string $targetName The (relative) file name under which to store the file in the archive
  91. * @return True on success, false otherwise
  92. * @since 1.2.1
  93. * @access protected
  94. * @abstract
  95. */
  96. function _addFile( $isVirtual, &$sourceNameOrData, $targetName )
  97. {
  98. // Are we connected to a server?
  99. if(!is_resource($this->_ftphandle))
  100. {
  101. if(!$this->_connectFTP()) return false;
  102. }
  103. // See if it's a directory
  104. $isDir = $isVirtual ? false : is_dir($sourceNameOrData);
  105. if($isDir)
  106. {
  107. // Just try to create the remote directory
  108. return $this->_makeDirectory($targetName);
  109. }
  110. else
  111. {
  112. // We have a file we need to upload
  113. if($isVirtual)
  114. {
  115. // Create a temporary file, upload, rename it
  116. $tempFileName = JoomlapackCUBETempfiles::createRegisterTempFile();
  117. if(function_exists('file_put_contents'))
  118. {
  119. if(@file_put_contents($tempFileName, $sourceNameOrData) === false)
  120. {
  121. $this->setError('Could not upload virtual file '.$targetName);
  122. return false;
  123. }
  124. $res = $this->_upload($tempFileName, $targetName);
  125. JoomlapackCUBETempfiles::unregisterAndDeleteTempFile($tempFileName, true);
  126. return $res;
  127. }
  128. }
  129. else
  130. {
  131. // Upload a file
  132. return $this->_upload($sourceNameOrData, $targetName);
  133. }
  134. }
  135. }
  136. // ------------------------------------------------------------------------
  137. // Private class-specific methods
  138. // ------------------------------------------------------------------------
  139. /**
  140. * "Magic" function called just before serialization of the object. Disconnects
  141. * from the FTP server and allows PHP to serialize like normal.
  142. * @return array The variables to serialize
  143. */
  144. function __sleep()
  145. {
  146. if(is_resource($this->_ftphandle))
  147. {
  148. @ftp_close($this->_ftphandle);
  149. }
  150. $this->_ftphandle = null;
  151. $this->_currentdir = null;
  152. return array_keys(get_object_vars($this));
  153. }
  154. /**
  155. * Tries to connect to the remote FTP server and change into the initial directory
  156. * @return bool True is connection successful, false otherwise
  157. */
  158. function _connectFTP()
  159. {
  160. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, 'Connecting to remote FTP');
  161. // Connect to the FTP server
  162. if($this->_usessl)
  163. {
  164. if(function_exists('ftp_ssl_connect'))
  165. {
  166. $this->_ftphandle = @ftp_ssl_connect($this->_host, $this->_port);
  167. }
  168. else
  169. {
  170. $this->_ftphandle = false;
  171. }
  172. }
  173. else
  174. {
  175. $this->_ftphandle = @ftp_connect($this->_host, $this->_port);
  176. }
  177. if(!is_resource($this->_ftphandle))
  178. {
  179. $this->setError('Could not connect to remote FTP server');
  180. return false;
  181. }
  182. // Login
  183. if(!@ftp_login($this->_ftphandle, $this->_user, $this->_pass))
  184. {
  185. $this->setError('Invalid username/password for the remote FTP server');
  186. return false;
  187. }
  188. // Change to initial directory
  189. if(!@ftp_chdir($this->_ftphandle, $this->_initdir))
  190. {
  191. $this->setError('Invalid initial directory for the remote FTP server');
  192. return false;
  193. }
  194. $this->_currentdir = $this->_initdir;
  195. @ftp_pasv($this->_ftphandle, $this->_passive);
  196. return true;
  197. }
  198. /**
  199. * Changes to the requested directory in the remote server. You give only the
  200. * path relative to the initial directory and it does all the rest by itself,
  201. * including doing nothing if the remote directory is the one we want. If the
  202. * directory doesn't exist, it creates it.
  203. * @param $dir string The (realtive) remote directory
  204. * @return bool True if successful, false otherwise.
  205. */
  206. function _ftp_chdir($dir)
  207. {
  208. // Calculate "real" (absolute) FTP path
  209. $realdir = substr($this->_initdir, -1) == '/' ? substr($this->_initdir, 0, strlen($this->_initdir) - 1) : $this->_initdir;
  210. $realdir .= '/'.$dir;
  211. $realdir = substr($realdir, 0, 1) == '/' ? $realdir : '/'.$realdir;
  212. if($this->_currentdir == $realdir)
  213. {
  214. // Already there, do nothing
  215. return true;
  216. }
  217. $result = @ftp_chdir($this->_ftphandle, $realdir);
  218. if($result === false)
  219. {
  220. // The directory doesn't exist, let's try to create it...
  221. if(!$this->_makeDirectory($dir)) return false;
  222. // After creating it, change into it
  223. @ftp_chdir($this->_ftphandle, $realdir);
  224. }
  225. // Update the private "current remote directory" variable
  226. $this->_currentdir = $realdir;
  227. return true;
  228. }
  229. function _makeDirectory( $dir )
  230. {
  231. $alldirs = explode('/', $dir);
  232. $previousDir = substr($this->_initdir, -1) == '/' ? substr($this->_initdir, 0, strlen($this->_initdir) - 1) : $this->_initdir;
  233. $previousDir = substr($previousDir, 0, 1) == '/' ? $previousDir : '/'.$previousDir;
  234. foreach($alldirs as $curdir)
  235. {
  236. $check = $previousDir.'/'.$curdir;
  237. if(!@ftp_chdir($this->_ftphandle, $check) )
  238. {
  239. if(@ftp_mkdir($this->_ftphandle, $check) === false)
  240. {
  241. $this->setError('Could not create directory '.$check);
  242. return false;
  243. }
  244. @ftp_chmod($this->_ftphandle, 0755, $check);
  245. }
  246. $previousDir = $check;
  247. }
  248. return true;
  249. }
  250. /**
  251. * Uploads a file to the remote server
  252. * @param $sourceName string The absolute path to the source local file
  253. * @param $targetName string The relative path to the targer remote file
  254. * @return bool True if successful
  255. */
  256. function _upload($sourceName, $targetName)
  257. {
  258. // Try to change into the remote directory, possibly creating it if it doesn't exist
  259. $dir = dirname($targetName);
  260. if(!$this->_ftp_chdir($dir))
  261. {
  262. return false;
  263. }
  264. // Upload
  265. $realdir = substr($this->_initdir, -1) == '/' ? substr($this->_initdir, 0, strlen($this->_initdir) - 1) : $this->_initdir;
  266. $realdir .= '/'.$dir;
  267. $realdir = substr($realdir, 0, 1) == '/' ? $realdir : '/'.$realdir;
  268. $realname = $realdir.'/'.basename($targetName);
  269. $res = @ftp_put($this->_ftphandle, $realname, $sourceName, FTP_BINARY);
  270. if(!$res)
  271. {
  272. // If the file was unreadable, just skip it...
  273. if(is_readable($sourceName))
  274. {
  275. $this->setError('Uploading '.$targetName.' has failed.');
  276. return false;
  277. } else {
  278. $cube->addWarning( 'Uploading '.$targetName.' has failed because the file is unreadable.');
  279. return true;
  280. }
  281. }
  282. else
  283. {
  284. @ftp_chmod($this->_ftphandle, 0755, $realname);
  285. return true;
  286. }
  287. }
  288. }