PageRenderTime 54ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/public/wp-content/plugins/w3-total-cache/lib/W3/Cdn/Ftp.php

https://bitbucket.org/millien/illien.ch-wordpress
PHP | 383 lines | 223 code | 98 blank | 62 comment | 37 complexity | 41aae0d6bad14dbef3d6355193f76ca9 MD5 | raw file
  1. <?php
  2. /**
  3. * W3 CDN FTP Class
  4. */
  5. if (!defined('W3TC')) {
  6. die();
  7. }
  8. define('W3TC_CDN_FTP_CONNECT_TIMEOUT', 30);
  9. w3_require_once(W3TC_LIB_W3_DIR . '/Cdn/Base.php');
  10. /**
  11. * Class W3_Cdn_Ftp
  12. */
  13. class W3_Cdn_Ftp extends W3_Cdn_Base {
  14. /**
  15. * FTP resource
  16. *
  17. * @var resource
  18. */
  19. var $_ftp = null;
  20. /**
  21. * PHP5 Constructor
  22. *
  23. * @param array $config
  24. */
  25. function __construct($config = array()) {
  26. $config = array_merge(array(
  27. 'host' => '',
  28. 'user' => '',
  29. 'pass' => '',
  30. 'path' => '',
  31. 'pasv' => false,
  32. 'domain' => array(),
  33. ), $config);
  34. $host_port = explode(':', $config['host']);
  35. if (sizeof($host_port) == 2) {
  36. $config['host'] = $host_port[0];
  37. $config['port'] = $host_port[1];
  38. }
  39. parent::__construct($config);
  40. }
  41. /**
  42. * Connects to FTP server
  43. *
  44. * @param string $error
  45. * @return boolean
  46. */
  47. function _connect(&$error) {
  48. if (empty($this->_config['host'])) {
  49. $error = 'Empty host.';
  50. return false;
  51. }
  52. if (empty($this->_config['port'])) {
  53. $this->_config['port'] = 21;
  54. }
  55. $this->_set_error_handler();
  56. $this->_ftp = @ftp_connect($this->_config['host'], (int) $this->_config['port'], W3TC_CDN_FTP_CONNECT_TIMEOUT);
  57. if (!$this->_ftp) {
  58. $error = sprintf('Unable to connect to %s:%d (%s).', $this->_config['host'], $this->_config['port'], $this->_get_last_error());
  59. $this->_restore_error_handler();
  60. return false;
  61. }
  62. if (!@ftp_login($this->_ftp, $this->_config['user'], $this->_config['pass'])) {
  63. $error = sprintf('Incorrect login or password (%s).', $this->_get_last_error());
  64. $this->_restore_error_handler();
  65. $this->_disconnect();
  66. return false;
  67. }
  68. if (!@ftp_pasv($this->_ftp, $this->_config['pasv'])) {
  69. $error = sprintf('Unable to change mode to passive (%s).', $this->_get_last_error());
  70. $this->_restore_error_handler();
  71. $this->_disconnect();
  72. return false;
  73. }
  74. if (!empty($this->_config['path']) && !@ftp_chdir($this->_ftp, $this->_config['path'])) {
  75. $error = sprintf('Unable to change directory to: %s (%s).', $this->_config['path'], $this->_get_last_error());
  76. $this->_restore_error_handler();
  77. $this->_disconnect();
  78. return false;
  79. }
  80. $this->_restore_error_handler();
  81. return true;
  82. }
  83. /**
  84. * Disconnects from FTP server
  85. */
  86. function _disconnect() {
  87. @ftp_close($this->_ftp);
  88. }
  89. /**
  90. * Sends MDTM command
  91. *
  92. * @param string $remote_file
  93. * @param integer $mtime
  94. * @return boolean
  95. */
  96. function _mdtm($remote_file, $mtime) {
  97. $command = sprintf('MDTM %s %s', date('YmdHis', $mtime), $remote_file);
  98. return @ftp_raw($this->_ftp, $command);
  99. }
  100. /**
  101. * Uploads files to FTP
  102. *
  103. * @param array $files
  104. * @param array $results
  105. * @param boolean $force_rewrite
  106. * @return boolean
  107. */
  108. function upload($files, &$results, $force_rewrite = false) {
  109. $error = null;
  110. if (!$this->_connect($error)) {
  111. $results = $this->_get_results($files, W3TC_CDN_RESULT_HALT, $error);
  112. return false;
  113. }
  114. $this->_set_error_handler();
  115. $home = @ftp_pwd($this->_ftp);
  116. if ($home === false) {
  117. $results = $this->_get_results($files, W3TC_CDN_RESULT_HALT, sprintf('Unable to get current directory (%s).', $this->_get_last_error()));
  118. $this->_restore_error_handler();
  119. $this->_disconnect();
  120. return false;
  121. }
  122. foreach ($files as $file) {
  123. $local_path = $file['local_path'];
  124. $remote_path = $file['remote_path'];
  125. if (!file_exists($local_path)) {
  126. $results[] = $this->_get_result($local_path, $remote_path, W3TC_CDN_RESULT_ERROR, 'Source file not found.');
  127. continue;
  128. }
  129. @ftp_chdir($this->_ftp, $home);
  130. $remote_dir = dirname($remote_path);
  131. $remote_dirs = preg_split('~\\/+~', $remote_dir);
  132. foreach ($remote_dirs as $dir) {
  133. if (!@ftp_chdir($this->_ftp, $dir)) {
  134. if (!@ftp_mkdir($this->_ftp, $dir)) {
  135. $results[] = $this->_get_result($local_path, $remote_path, W3TC_CDN_RESULT_ERROR, sprintf('Unable to create directory (%s).', $this->_get_last_error()));
  136. continue 2;
  137. }
  138. if (!@ftp_chdir($this->_ftp, $dir)) {
  139. $results[] = $this->_get_result($local_path, $remote_path, W3TC_CDN_RESULT_ERROR, sprintf('Unable to change directory (%s).', $this->_get_last_error()));
  140. continue 2;
  141. }
  142. }
  143. }
  144. $remote_file = basename($remote_path);
  145. $mtime = @filemtime($local_path);
  146. if (!$force_rewrite) {
  147. $size = @filesize($local_path);
  148. $ftp_size = @ftp_size($this->_ftp, $remote_file);
  149. $ftp_mtime = @ftp_mdtm($this->_ftp, $remote_file);
  150. if ($size === $ftp_size && $mtime === $ftp_mtime) {
  151. $results[] = $this->_get_result($local_path, $remote_path, W3TC_CDN_RESULT_OK, 'File up-to-date.');
  152. continue;
  153. }
  154. }
  155. $result = @ftp_put($this->_ftp, $remote_file, $local_path, FTP_BINARY);
  156. if ($result) {
  157. $this->_mdtm($remote_file, $mtime);
  158. $results[] = $this->_get_result($local_path, $remote_path, W3TC_CDN_RESULT_OK, 'OK');
  159. } else {
  160. $results[] = $this->_get_result($local_path, $remote_path, W3TC_CDN_RESULT_ERROR, sprintf('Unable to upload file (%s).', $this->_get_last_error()));
  161. }
  162. }
  163. $this->_restore_error_handler();
  164. $this->_disconnect();
  165. return !$this->_is_error($results);
  166. }
  167. /**
  168. * Deletes files from FTP
  169. *
  170. * @param array $files
  171. * @param array $results
  172. * @return boolean
  173. */
  174. function delete($files, &$results) {
  175. $error = null;
  176. if (!$this->_connect($error)) {
  177. $results = $this->_get_results($files, W3TC_CDN_RESULT_HALT, $error);
  178. return false;
  179. }
  180. $this->_set_error_handler();
  181. foreach ($files as $file) {
  182. $local_path = $file['local_path'];
  183. $remote_path = $file['remote_path'];
  184. $result = @ftp_delete($this->_ftp, $remote_path);
  185. if ($result) {
  186. $results[] = $this->_get_result($local_path, $remote_path, W3TC_CDN_RESULT_OK, 'OK');
  187. } else {
  188. $results[] = $this->_get_result($local_path, $remote_path, W3TC_CDN_RESULT_ERROR, sprintf('Unable to delete file (%s).', $this->_get_last_error()));
  189. }
  190. while (true) {
  191. $remote_path = dirname($remote_path);
  192. if ($remote_path == '.' || !@ftp_rmdir($this->_ftp, $remote_path)) {
  193. break;
  194. }
  195. }
  196. }
  197. $this->_restore_error_handler();
  198. $this->_disconnect();
  199. return !$this->_is_error($results);
  200. }
  201. /**
  202. * Tests FTP server
  203. *
  204. * @param string $error
  205. * @return boolean
  206. */
  207. function test(&$error) {
  208. if (!parent::test($error)) {
  209. return false;
  210. }
  211. $rand = md5(time());
  212. $tmp_dir = 'test_dir_' . $rand;
  213. $tmp_file = 'test_file_' . $rand;
  214. $tmp_path = W3TC_CACHE_TMP_DIR . '/' . $tmp_file;
  215. if (!@file_put_contents($tmp_path, $rand)) {
  216. $error = sprintf('Unable to create file: %s.', $tmp_path);
  217. return false;
  218. }
  219. if (!$this->_connect($error)) {
  220. return false;
  221. }
  222. $this->_set_error_handler();
  223. if (!@ftp_mkdir($this->_ftp, $tmp_dir)) {
  224. $error = sprintf('Unable to make directory: %s (%s).', $tmp_dir, $this->_get_last_error());
  225. @unlink($tmp_path);
  226. $this->_restore_error_handler();
  227. $this->_disconnect();
  228. return false;
  229. }
  230. if (!@ftp_chdir($this->_ftp, $tmp_dir)) {
  231. $error = sprintf('Unable to change directory to: %s (%s).', $tmp_dir, $this->_get_last_error());
  232. @unlink($tmp_path);
  233. @ftp_rmdir($this->_ftp, $tmp_dir);
  234. $this->_restore_error_handler();
  235. $this->_disconnect();
  236. return false;
  237. }
  238. if (!@ftp_put($this->_ftp, $tmp_file, $tmp_path, FTP_BINARY)) {
  239. $error = sprintf('Unable to upload file: %s (%s).', $tmp_path, $this->_get_last_error());
  240. @unlink($tmp_path);
  241. @ftp_cdup($this->_ftp);
  242. @ftp_rmdir($this->_ftp, $tmp_dir);
  243. $this->_restore_error_handler();
  244. $this->_disconnect();
  245. return false;
  246. }
  247. @unlink($tmp_path);
  248. if (!@ftp_delete($this->_ftp, $tmp_file)) {
  249. $error = sprintf('Unable to delete file: %s (%s).', $tmp_path, $this->_get_last_error());
  250. @ftp_cdup($this->_ftp);
  251. @ftp_rmdir($this->_ftp, $tmp_dir);
  252. $this->_restore_error_handler();
  253. $this->_disconnect();
  254. return false;
  255. }
  256. @ftp_cdup($this->_ftp);
  257. if (!@ftp_rmdir($this->_ftp, $tmp_dir)) {
  258. $error = sprintf('Unable to remove directory: %s (%s).', $tmp_dir, $this->_get_last_error());
  259. $this->_restore_error_handler();
  260. $this->_disconnect();
  261. return false;
  262. }
  263. $this->_restore_error_handler();
  264. $this->_disconnect();
  265. return true;
  266. }
  267. /**
  268. * Returns array of CDN domains
  269. *
  270. * @return array
  271. */
  272. function get_domains() {
  273. if (!empty($this->_config['domain'])) {
  274. return (array) $this->_config['domain'];
  275. }
  276. return array();
  277. }
  278. /**
  279. * How and if headers should be set
  280. * @return string W3TC_CDN_HEADER_NONE, W3TC_CDN_HEADER_UPLOADABLE, W3TC_CDN_HEADER_MIRRORING
  281. */
  282. function headers_support() {
  283. return W3TC_CDN_HEADER_MIRRORING;
  284. }
  285. }