/libs/Nette/Web/Ftp.php

https://code.google.com/ · PHP · 203 lines · 106 code · 40 blank · 57 comment · 14 complexity · 768a997c1ce4e71337c897bdc9daeb61 MD5 · raw file

  1. <?php
  2. /**
  3. * This file is part of the Nette Framework.
  4. *
  5. * Copyright (c) 2004, 2010 David Grudl (http://davidgrudl.com)
  6. *
  7. * This source file is subject to the "Nette license", and/or
  8. * GPL license. For more information please see http://nette.org
  9. */
  10. namespace Nette\Web;
  11. use Nette;
  12. /**
  13. * Access to a FTP server.
  14. *
  15. * <code>
  16. * $ftp = new Ftp;
  17. * $ftp->connect('ftp.example.com');
  18. * $ftp->login('anonymous', 'example@example.com');
  19. * $ftp->get('file.txt', 'README', Ftp::ASCII);
  20. * </code>
  21. *
  22. * @author David Grudl
  23. */
  24. class Ftp extends Nette\Object
  25. {
  26. /**#@+ FTP constant alias */
  27. const ASCII = FTP_ASCII;
  28. const TEXT = FTP_TEXT;
  29. const BINARY = FTP_BINARY;
  30. const IMAGE = FTP_IMAGE;
  31. const TIMEOUT_SEC = FTP_TIMEOUT_SEC;
  32. const AUTOSEEK = FTP_AUTOSEEK;
  33. const AUTORESUME = FTP_AUTORESUME;
  34. const FAILED = FTP_FAILED;
  35. const FINISHED = FTP_FINISHED;
  36. const MOREDATA = FTP_MOREDATA;
  37. /**#@-*/
  38. /** @var resource */
  39. private $resource;
  40. /** @var array */
  41. private $state;
  42. /**
  43. */
  44. public function __construct()
  45. {
  46. if (!extension_loaded('ftp')) {
  47. throw new \Exception("PHP extension FTP is not loaded.");
  48. }
  49. }
  50. /**
  51. * Magic method (do not call directly).
  52. * @param string method name
  53. * @param array arguments
  54. * @return mixed
  55. * @throws \MemberAccessException
  56. * @throws FtpException
  57. */
  58. public function __call($name, $args)
  59. {
  60. $name = strtolower($name);
  61. $silent = strncmp($name, 'try', 3) === 0;
  62. $func = $silent ? substr($name, 3) : $name;
  63. static $aliases = array(
  64. 'sslconnect' => 'ssl_connect',
  65. 'getoption' => 'get_option',
  66. 'setoption' => 'set_option',
  67. 'nbcontinue' => 'nb_continue',
  68. 'nbfget' => 'nb_fget',
  69. 'nbfput' => 'nb_fput',
  70. 'nbget' => 'nb_get',
  71. 'nbput' => 'nb_put',
  72. );
  73. $func = 'ftp_' . (isset($aliases[$func]) ? $aliases[$func] : $func);
  74. if (!function_exists($func)) {
  75. return parent::__call($name, $args);
  76. }
  77. Nette\Tools::tryError();
  78. if ($func === 'ftp_connect' || $func === 'ftp_ssl_connect') {
  79. $this->state = array($name => $args);
  80. $this->resource = call_user_func_array($func, $args);
  81. $res = NULL;
  82. } elseif (!is_resource($this->resource)) {
  83. Nette\Tools::catchError($msg);
  84. throw new FtpException("Not connected to FTP server. Call connect() or ssl_connect() first.");
  85. } else {
  86. if ($func === 'ftp_login' || $func === 'ftp_pasv') {
  87. $this->state[$name] = $args;
  88. }
  89. array_unshift($args, $this->resource);
  90. $res = call_user_func_array($func, $args);
  91. if ($func === 'ftp_chdir' || $func === 'ftp_cdup') {
  92. $this->state['chdir'] = array(ftp_pwd($this->resource));
  93. }
  94. }
  95. if (Nette\Tools::catchError($msg) && !$silent) {
  96. throw new FtpException($msg);
  97. }
  98. return $res;
  99. }
  100. /**
  101. * Reconnects to FTP server.
  102. * @return void
  103. */
  104. public function reconnect()
  105. {
  106. @ftp_close($this->resource); // intentionally @
  107. foreach ($this->state as $name => $args) {
  108. call_user_func_array(array($this, $name), $args);
  109. }
  110. }
  111. /**
  112. * Checks if file or directory exists.
  113. * @param string
  114. * @return bool
  115. */
  116. public function fileExists($file)
  117. {
  118. return is_array($this->nlist($file));
  119. }
  120. /**
  121. * Checks if directory exists.
  122. * @param string
  123. * @return bool
  124. */
  125. public function isDir($dir)
  126. {
  127. $current = $this->pwd();
  128. try {
  129. $this->chdir($dir);
  130. } catch (FtpException $e) {
  131. }
  132. $this->chdir($current);
  133. return empty($e);
  134. }
  135. /**
  136. * Recursive creates directories.
  137. * @param string
  138. * @return void
  139. */
  140. public function mkDirRecursive($dir)
  141. {
  142. $parts = explode('/', $dir);
  143. $path = '';
  144. while (!empty($parts)) {
  145. $path .= array_shift($parts);
  146. try {
  147. if ($path !== '') $this->mkdir($path);
  148. } catch (FtpException $e) {
  149. if (!$this->isDir($path)) {
  150. throw new FtpException("Cannot create directory '$path'.");
  151. }
  152. }
  153. $path .= '/';
  154. }
  155. }
  156. }
  157. /**
  158. * FTP server exception.
  159. *
  160. */
  161. class FtpException extends \Exception
  162. {
  163. }