1: <?php
  2: 
  3:   4:   5:   6:   7:   8:   9:  10: 
 11: 
 12: namespace Nette\Web;
 13: 
 14: use Nette;
 15: 
 16: 
 17: 
 18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29: 
 30: class Ftp extends Nette\Object
 31: {
 32:     
 33:     const ASCII = FTP_ASCII;
 34:     const TEXT = FTP_TEXT;
 35:     const BINARY = FTP_BINARY;
 36:     const IMAGE = FTP_IMAGE;
 37:     const TIMEOUT_SEC = FTP_TIMEOUT_SEC;
 38:     const AUTOSEEK = FTP_AUTOSEEK;
 39:     const AUTORESUME = FTP_AUTORESUME;
 40:     const FAILED = FTP_FAILED;
 41:     const FINISHED = FTP_FINISHED;
 42:     const MOREDATA = FTP_MOREDATA;
 43:     
 44: 
 45:     
 46:     private $resource;
 47: 
 48:     
 49:     private $state;
 50: 
 51: 
 52: 
 53:      54: 
 55:     public function __construct()
 56:     {
 57:         if (!extension_loaded('ftp')) {
 58:             throw new \Exception("PHP extension FTP is not loaded.");
 59:         }
 60:     }
 61: 
 62: 
 63: 
 64:      65:  66:  67:  68:  69:  70:  71: 
 72:     public function __call($name, $args)
 73:     {
 74:         $name = strtolower($name);
 75:         $silent = strncmp($name, 'try', 3) === 0;
 76:         $func = $silent ? substr($name, 3) : $name;
 77:         static $aliases = array(
 78:             'sslconnect' => 'ssl_connect',
 79:             'getoption' => 'get_option',
 80:             'setoption' => 'set_option',
 81:             'nbcontinue' => 'nb_continue',
 82:             'nbfget' => 'nb_fget',
 83:             'nbfput' => 'nb_fput',
 84:             'nbget' => 'nb_get',
 85:             'nbput' => 'nb_put',
 86:         );
 87:         $func = 'ftp_' . (isset($aliases[$func]) ? $aliases[$func] : $func);
 88: 
 89:         if (!function_exists($func)) {
 90:             return parent::__call($name, $args);
 91:         }
 92: 
 93: 
 94:         Nette\Tools::tryError();
 95: 
 96:         if ($func === 'ftp_connect' || $func === 'ftp_ssl_connect') {
 97:             $this->state = array($name => $args);
 98:             $this->resource = call_user_func_array($func, $args);
 99:             $res = NULL;
100: 
101:         } elseif (!is_resource($this->resource)) {
102:             Nette\Tools::catchError($msg);
103:             throw new FtpException("Not connected to FTP server. Call connect() or ssl_connect() first.");
104: 
105:         } else {
106:             if ($func === 'ftp_login' || $func === 'ftp_pasv') {
107:                 $this->state[$name] = $args;
108:             }
109: 
110:             array_unshift($args, $this->resource);
111:             $res = call_user_func_array($func, $args);
112: 
113:             if ($func === 'ftp_chdir' || $func === 'ftp_cdup') {
114:                 $this->state['chdir'] = array(ftp_pwd($this->resource));
115:             }
116:         }
117: 
118:         if (Nette\Tools::catchError($msg) && !$silent) {
119:             throw new FtpException($msg);
120:         }
121: 
122:         return $res;
123:     }
124: 
125: 
126: 
127:     128: 129: 130: 
131:     public function reconnect()
132:     {
133:         @ftp_close($this->resource); 
134:         foreach ($this->state as $name => $args) {
135:             call_user_func_array(array($this, $name), $args);
136:         }
137:     }
138: 
139: 
140: 
141:     142: 143: 144: 145: 
146:     public function fileExists($file)
147:     {
148:         return is_array($this->nlist($file));
149:     }
150: 
151: 
152: 
153:     154: 155: 156: 157: 
158:     public function isDir($dir)
159:     {
160:         $current = $this->pwd();
161:         try {
162:             $this->chdir($dir);
163:         } catch (FtpException $e) {
164:         }
165:         $this->chdir($current);
166:         return empty($e);
167:     }
168: 
169: 
170: 
171:     172: 173: 174: 175: 
176:     public function mkDirRecursive($dir)
177:     {
178:         $parts = explode('/', $dir);
179:         $path = '';
180:         while (!empty($parts)) {
181:             $path .= array_shift($parts);
182:             try {
183:                 if ($path !== '') $this->mkdir($path);
184:             } catch (FtpException $e) {
185:                 if (!$this->isDir($path)) {
186:                     throw new FtpException("Cannot create directory '$path'.");
187:                 }
188:             }
189:             $path .= '/';
190:         }
191:     }
192: 
193: }
194: 
195: 
196: 
197: 198: 199: 200: 
201: class FtpException extends \Exception
202: {
203: }
204: