author | ymh <ymh.work@gmail.com> |
Mon, 14 Oct 2019 17:39:30 +0200 | |
changeset 7 | cf61fcea0001 |
parent 5 | 5e2f62d02dcd |
child 9 | 177826044cd9 |
permissions | -rw-r--r-- |
0 | 1 |
<?php |
2 |
/** |
|
3 |
* WordPress FTP Filesystem. |
|
4 |
* |
|
5 |
* @package WordPress |
|
6 |
* @subpackage Filesystem |
|
7 |
*/ |
|
8 |
||
9 |
/** |
|
10 |
* WordPress Filesystem Class for implementing FTP. |
|
11 |
* |
|
5 | 12 |
* @since 2.5.0 |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
13 |
* |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
14 |
* @see WP_Filesystem_Base |
0 | 15 |
*/ |
16 |
class WP_Filesystem_FTPext extends WP_Filesystem_Base { |
|
5 | 17 |
public $link; |
0 | 18 |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
19 |
/** |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
20 |
* |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
21 |
* @param array $opt |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
22 |
*/ |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
23 |
public function __construct( $opt = '' ) { |
0 | 24 |
$this->method = 'ftpext'; |
25 |
$this->errors = new WP_Error(); |
|
26 |
||
27 |
// Check if possible to use ftp functions. |
|
28 |
if ( ! extension_loaded('ftp') ) { |
|
29 |
$this->errors->add('no_ftp_ext', __('The ftp PHP extension is not available')); |
|
5 | 30 |
return; |
0 | 31 |
} |
32 |
||
33 |
// This Class uses the timeout on a per-connection basis, Others use it on a per-action basis. |
|
34 |
||
35 |
if ( ! defined('FS_TIMEOUT') ) |
|
36 |
define('FS_TIMEOUT', 240); |
|
37 |
||
38 |
if ( empty($opt['port']) ) |
|
39 |
$this->options['port'] = 21; |
|
40 |
else |
|
41 |
$this->options['port'] = $opt['port']; |
|
42 |
||
43 |
if ( empty($opt['hostname']) ) |
|
44 |
$this->errors->add('empty_hostname', __('FTP hostname is required')); |
|
45 |
else |
|
46 |
$this->options['hostname'] = $opt['hostname']; |
|
47 |
||
48 |
// Check if the options provided are OK. |
|
49 |
if ( empty($opt['username']) ) |
|
50 |
$this->errors->add('empty_username', __('FTP username is required')); |
|
51 |
else |
|
52 |
$this->options['username'] = $opt['username']; |
|
53 |
||
54 |
if ( empty($opt['password']) ) |
|
55 |
$this->errors->add('empty_password', __('FTP password is required')); |
|
56 |
else |
|
57 |
$this->options['password'] = $opt['password']; |
|
58 |
||
59 |
$this->options['ssl'] = false; |
|
60 |
if ( isset($opt['connection_type']) && 'ftps' == $opt['connection_type'] ) |
|
61 |
$this->options['ssl'] = true; |
|
62 |
} |
|
63 |
||
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
64 |
/** |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
65 |
* |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
66 |
* @return bool |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
67 |
*/ |
5 | 68 |
public function connect() { |
0 | 69 |
if ( isset($this->options['ssl']) && $this->options['ssl'] && function_exists('ftp_ssl_connect') ) |
70 |
$this->link = @ftp_ssl_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT); |
|
71 |
else |
|
72 |
$this->link = @ftp_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT); |
|
73 |
||
74 |
if ( ! $this->link ) { |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
75 |
$this->errors->add( 'connect', |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
76 |
/* translators: %s: hostname:port */ |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
77 |
sprintf( __( 'Failed to connect to FTP Server %s' ), |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
78 |
$this->options['hostname'] . ':' . $this->options['port'] |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
79 |
) |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
80 |
); |
0 | 81 |
return false; |
82 |
} |
|
83 |
||
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
84 |
if ( ! @ftp_login( $this->link,$this->options['username'], $this->options['password'] ) ) { |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
85 |
$this->errors->add( 'auth', |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
86 |
/* translators: %s: username */ |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
87 |
sprintf( __( 'Username/Password incorrect for %s' ), |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
88 |
$this->options['username'] |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
89 |
) |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
90 |
); |
0 | 91 |
return false; |
92 |
} |
|
93 |
||
94 |
// Set the Connection to use Passive FTP |
|
95 |
@ftp_pasv( $this->link, true ); |
|
96 |
if ( @ftp_get_option($this->link, FTP_TIMEOUT_SEC) < FS_TIMEOUT ) |
|
97 |
@ftp_set_option($this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT); |
|
98 |
||
99 |
return true; |
|
100 |
} |
|
101 |
||
5 | 102 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
103 |
* Retrieves the file contents. |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
104 |
* |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
105 |
* @since 2.5.0 |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
106 |
* |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
107 |
* @param string $file Filename. |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
108 |
* @return string|false File contents on success, false if no temp file could be opened, |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
109 |
* or if the file couldn't be retrieved. |
5 | 110 |
*/ |
111 |
public function get_contents( $file ) { |
|
0 | 112 |
$tempfile = wp_tempnam($file); |
113 |
$temp = fopen($tempfile, 'w+'); |
|
114 |
||
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
115 |
if ( ! $temp ) { |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
116 |
unlink( $tempfile ); |
0 | 117 |
return false; |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
118 |
} |
0 | 119 |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
120 |
if ( ! @ftp_fget( $this->link, $temp, $file, FTP_BINARY ) ) { |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
121 |
fclose( $temp ); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
122 |
unlink( $tempfile ); |
0 | 123 |
return false; |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
124 |
} |
0 | 125 |
|
126 |
fseek( $temp, 0 ); // Skip back to the start of the file being written to |
|
127 |
$contents = ''; |
|
128 |
||
129 |
while ( ! feof($temp) ) |
|
130 |
$contents .= fread($temp, 8192); |
|
131 |
||
132 |
fclose($temp); |
|
133 |
unlink($tempfile); |
|
134 |
return $contents; |
|
135 |
} |
|
136 |
||
5 | 137 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
138 |
* |
5 | 139 |
* @param string $file |
140 |
* @return array |
|
141 |
*/ |
|
142 |
public function get_contents_array($file) { |
|
0 | 143 |
return explode("\n", $this->get_contents($file)); |
144 |
} |
|
145 |
||
5 | 146 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
147 |
* |
5 | 148 |
* @param string $file |
149 |
* @param string $contents |
|
150 |
* @param bool|int $mode |
|
151 |
* @return bool |
|
152 |
*/ |
|
153 |
public function put_contents($file, $contents, $mode = false ) { |
|
0 | 154 |
$tempfile = wp_tempnam($file); |
155 |
$temp = fopen( $tempfile, 'wb+' ); |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
156 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
157 |
if ( ! $temp ) { |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
158 |
unlink( $tempfile ); |
0 | 159 |
return false; |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
160 |
} |
0 | 161 |
|
162 |
mbstring_binary_safe_encoding(); |
|
163 |
||
164 |
$data_length = strlen( $contents ); |
|
165 |
$bytes_written = fwrite( $temp, $contents ); |
|
166 |
||
167 |
reset_mbstring_encoding(); |
|
168 |
||
169 |
if ( $data_length !== $bytes_written ) { |
|
170 |
fclose( $temp ); |
|
171 |
unlink( $tempfile ); |
|
172 |
return false; |
|
173 |
} |
|
174 |
||
175 |
fseek( $temp, 0 ); // Skip back to the start of the file being written to |
|
176 |
||
177 |
$ret = @ftp_fput( $this->link, $file, $temp, FTP_BINARY ); |
|
178 |
||
179 |
fclose($temp); |
|
180 |
unlink($tempfile); |
|
181 |
||
182 |
$this->chmod($file, $mode); |
|
183 |
||
184 |
return $ret; |
|
185 |
} |
|
186 |
||
5 | 187 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
188 |
* |
5 | 189 |
* @return string |
190 |
*/ |
|
191 |
public function cwd() { |
|
0 | 192 |
$cwd = @ftp_pwd($this->link); |
193 |
if ( $cwd ) |
|
194 |
$cwd = trailingslashit($cwd); |
|
195 |
return $cwd; |
|
196 |
} |
|
197 |
||
5 | 198 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
199 |
* |
5 | 200 |
* @param string $dir |
201 |
* @return bool |
|
202 |
*/ |
|
203 |
public function chdir($dir) { |
|
0 | 204 |
return @ftp_chdir($this->link, $dir); |
205 |
} |
|
206 |
||
5 | 207 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
208 |
* |
5 | 209 |
* @param string $file |
210 |
* @param int $mode |
|
211 |
* @param bool $recursive |
|
212 |
* @return bool |
|
213 |
*/ |
|
214 |
public function chmod($file, $mode = false, $recursive = false) { |
|
0 | 215 |
if ( ! $mode ) { |
216 |
if ( $this->is_file($file) ) |
|
217 |
$mode = FS_CHMOD_FILE; |
|
218 |
elseif ( $this->is_dir($file) ) |
|
219 |
$mode = FS_CHMOD_DIR; |
|
220 |
else |
|
221 |
return false; |
|
222 |
} |
|
223 |
||
224 |
// chmod any sub-objects if recursive. |
|
225 |
if ( $recursive && $this->is_dir($file) ) { |
|
226 |
$filelist = $this->dirlist($file); |
|
227 |
foreach ( (array)$filelist as $filename => $filemeta ) |
|
228 |
$this->chmod($file . '/' . $filename, $mode, $recursive); |
|
229 |
} |
|
230 |
||
231 |
// chmod the file or directory |
|
232 |
if ( ! function_exists('ftp_chmod') ) |
|
233 |
return (bool)@ftp_site($this->link, sprintf('CHMOD %o %s', $mode, $file)); |
|
234 |
return (bool)@ftp_chmod($this->link, $mode, $file); |
|
235 |
} |
|
236 |
||
5 | 237 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
238 |
* |
5 | 239 |
* @param string $file |
240 |
* @return string |
|
241 |
*/ |
|
242 |
public function owner($file) { |
|
0 | 243 |
$dir = $this->dirlist($file); |
244 |
return $dir[$file]['owner']; |
|
245 |
} |
|
5 | 246 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
247 |
* |
5 | 248 |
* @param string $file |
249 |
* @return string |
|
250 |
*/ |
|
251 |
public function getchmod($file) { |
|
0 | 252 |
$dir = $this->dirlist($file); |
253 |
return $dir[$file]['permsn']; |
|
254 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
255 |
|
5 | 256 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
257 |
* |
5 | 258 |
* @param string $file |
259 |
* @return string |
|
260 |
*/ |
|
261 |
public function group($file) { |
|
0 | 262 |
$dir = $this->dirlist($file); |
263 |
return $dir[$file]['group']; |
|
264 |
} |
|
265 |
||
5 | 266 |
/** |
267 |
* |
|
268 |
* @param string $source |
|
269 |
* @param string $destination |
|
270 |
* @param bool $overwrite |
|
271 |
* @param string|bool $mode |
|
272 |
* @return bool |
|
273 |
*/ |
|
274 |
public function copy($source, $destination, $overwrite = false, $mode = false) { |
|
0 | 275 |
if ( ! $overwrite && $this->exists($destination) ) |
276 |
return false; |
|
277 |
$content = $this->get_contents($source); |
|
278 |
if ( false === $content ) |
|
279 |
return false; |
|
280 |
return $this->put_contents($destination, $content, $mode); |
|
281 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
282 |
|
5 | 283 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
284 |
* |
5 | 285 |
* @param string $source |
286 |
* @param string $destination |
|
287 |
* @param bool $overwrite |
|
288 |
* @return bool |
|
289 |
*/ |
|
290 |
public function move($source, $destination, $overwrite = false) { |
|
0 | 291 |
return ftp_rename($this->link, $source, $destination); |
292 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
293 |
|
5 | 294 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
295 |
* |
5 | 296 |
* @param string $file |
297 |
* @param bool $recursive |
|
298 |
* @param string $type |
|
299 |
* @return bool |
|
300 |
*/ |
|
301 |
public function delete($file, $recursive = false, $type = false) { |
|
0 | 302 |
if ( empty($file) ) |
303 |
return false; |
|
304 |
if ( 'f' == $type || $this->is_file($file) ) |
|
305 |
return @ftp_delete($this->link, $file); |
|
306 |
if ( !$recursive ) |
|
307 |
return @ftp_rmdir($this->link, $file); |
|
308 |
||
309 |
$filelist = $this->dirlist( trailingslashit($file) ); |
|
310 |
if ( !empty($filelist) ) |
|
311 |
foreach ( $filelist as $delete_file ) |
|
312 |
$this->delete( trailingslashit($file) . $delete_file['name'], $recursive, $delete_file['type'] ); |
|
313 |
return @ftp_rmdir($this->link, $file); |
|
314 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
315 |
|
5 | 316 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
317 |
* |
5 | 318 |
* @param string $file |
319 |
* @return bool |
|
320 |
*/ |
|
321 |
public function exists($file) { |
|
322 |
$list = @ftp_nlist($this->link, $file); |
|
0 | 323 |
|
5 | 324 |
if ( empty( $list ) && $this->is_dir( $file ) ) { |
325 |
return true; // File is an empty directory. |
|
326 |
} |
|
327 |
||
0 | 328 |
return !empty($list); //empty list = no file, so invert. |
329 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
330 |
|
5 | 331 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
332 |
* |
5 | 333 |
* @param string $file |
334 |
* @return bool |
|
335 |
*/ |
|
336 |
public function is_file($file) { |
|
0 | 337 |
return $this->exists($file) && !$this->is_dir($file); |
338 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
339 |
|
5 | 340 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
341 |
* |
5 | 342 |
* @param string $path |
343 |
* @return bool |
|
344 |
*/ |
|
345 |
public function is_dir($path) { |
|
0 | 346 |
$cwd = $this->cwd(); |
347 |
$result = @ftp_chdir($this->link, trailingslashit($path) ); |
|
348 |
if ( $result && $path == $this->cwd() || $this->cwd() != $cwd ) { |
|
349 |
@ftp_chdir($this->link, $cwd); |
|
350 |
return true; |
|
351 |
} |
|
352 |
return false; |
|
353 |
} |
|
354 |
||
5 | 355 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
356 |
* |
5 | 357 |
* @param string $file |
358 |
* @return bool |
|
359 |
*/ |
|
360 |
public function is_readable($file) { |
|
361 |
return true; |
|
362 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
363 |
|
5 | 364 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
365 |
* |
5 | 366 |
* @param string $file |
367 |
* @return bool |
|
368 |
*/ |
|
369 |
public function is_writable($file) { |
|
0 | 370 |
return true; |
371 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
372 |
|
5 | 373 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
374 |
* |
5 | 375 |
* @param string $file |
376 |
* @return bool |
|
377 |
*/ |
|
378 |
public function atime($file) { |
|
379 |
return false; |
|
0 | 380 |
} |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
381 |
|
5 | 382 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
383 |
* |
5 | 384 |
* @param string $file |
385 |
* @return int |
|
386 |
*/ |
|
387 |
public function mtime($file) { |
|
388 |
return ftp_mdtm($this->link, $file); |
|
389 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
390 |
|
5 | 391 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
392 |
* |
5 | 393 |
* @param string $file |
394 |
* @return int |
|
395 |
*/ |
|
396 |
public function size($file) { |
|
397 |
return ftp_size($this->link, $file); |
|
398 |
} |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
399 |
|
5 | 400 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
401 |
* |
5 | 402 |
* @param string $file |
403 |
* @return bool |
|
404 |
*/ |
|
405 |
public function touch($file, $time = 0, $atime = 0) { |
|
0 | 406 |
return false; |
407 |
} |
|
408 |
||
5 | 409 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
410 |
* |
5 | 411 |
* @param string $path |
412 |
* @param mixed $chmod |
|
413 |
* @param mixed $chown |
|
414 |
* @param mixed $chgrp |
|
415 |
* @return bool |
|
416 |
*/ |
|
417 |
public function mkdir($path, $chmod = false, $chown = false, $chgrp = false) { |
|
0 | 418 |
$path = untrailingslashit($path); |
419 |
if ( empty($path) ) |
|
420 |
return false; |
|
421 |
||
422 |
if ( !@ftp_mkdir($this->link, $path) ) |
|
423 |
return false; |
|
424 |
$this->chmod($path, $chmod); |
|
425 |
return true; |
|
426 |
} |
|
427 |
||
5 | 428 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
429 |
* |
5 | 430 |
* @param string $path |
431 |
* @param bool $recursive |
|
432 |
* @return bool |
|
433 |
*/ |
|
434 |
public function rmdir($path, $recursive = false) { |
|
0 | 435 |
return $this->delete($path, $recursive); |
436 |
} |
|
437 |
||
5 | 438 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
439 |
* |
5 | 440 |
* @staticvar bool $is_windows |
441 |
* @param string $line |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
442 |
* @return array |
5 | 443 |
*/ |
444 |
public function parselisting($line) { |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
445 |
static $is_windows = null; |
0 | 446 |
if ( is_null($is_windows) ) |
447 |
$is_windows = stripos( ftp_systype($this->link), 'win') !== false; |
|
448 |
||
449 |
if ( $is_windows && preg_match('/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)/', $line, $lucifer) ) { |
|
450 |
$b = array(); |
|
451 |
if ( $lucifer[3] < 70 ) |
|
452 |
$lucifer[3] +=2000; |
|
453 |
else |
|
454 |
$lucifer[3] += 1900; // 4digit year fix |
|
455 |
$b['isdir'] = ( $lucifer[7] == '<DIR>'); |
|
456 |
if ( $b['isdir'] ) |
|
457 |
$b['type'] = 'd'; |
|
458 |
else |
|
459 |
$b['type'] = 'f'; |
|
460 |
$b['size'] = $lucifer[7]; |
|
461 |
$b['month'] = $lucifer[1]; |
|
462 |
$b['day'] = $lucifer[2]; |
|
463 |
$b['year'] = $lucifer[3]; |
|
464 |
$b['hour'] = $lucifer[4]; |
|
465 |
$b['minute'] = $lucifer[5]; |
|
466 |
$b['time'] = @mktime($lucifer[4] + (strcasecmp($lucifer[6], "PM") == 0 ? 12 : 0), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3]); |
|
467 |
$b['am/pm'] = $lucifer[6]; |
|
468 |
$b['name'] = $lucifer[8]; |
|
469 |
} elseif ( !$is_windows && $lucifer = preg_split('/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY)) { |
|
470 |
//echo $line."\n"; |
|
471 |
$lcount = count($lucifer); |
|
472 |
if ( $lcount < 8 ) |
|
473 |
return ''; |
|
474 |
$b = array(); |
|
475 |
$b['isdir'] = $lucifer[0]{0} === 'd'; |
|
476 |
$b['islink'] = $lucifer[0]{0} === 'l'; |
|
477 |
if ( $b['isdir'] ) |
|
478 |
$b['type'] = 'd'; |
|
479 |
elseif ( $b['islink'] ) |
|
480 |
$b['type'] = 'l'; |
|
481 |
else |
|
482 |
$b['type'] = 'f'; |
|
483 |
$b['perms'] = $lucifer[0]; |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
484 |
$b['permsn'] = $this->getnumchmodfromh( $b['perms'] ); |
0 | 485 |
$b['number'] = $lucifer[1]; |
486 |
$b['owner'] = $lucifer[2]; |
|
487 |
$b['group'] = $lucifer[3]; |
|
488 |
$b['size'] = $lucifer[4]; |
|
489 |
if ( $lcount == 8 ) { |
|
490 |
sscanf($lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day']); |
|
491 |
sscanf($lucifer[6], '%d:%d', $b['hour'], $b['minute']); |
|
492 |
$b['time'] = @mktime($b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year']); |
|
493 |
$b['name'] = $lucifer[7]; |
|
494 |
} else { |
|
495 |
$b['month'] = $lucifer[5]; |
|
496 |
$b['day'] = $lucifer[6]; |
|
497 |
if ( preg_match('/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2) ) { |
|
498 |
$b['year'] = date("Y"); |
|
499 |
$b['hour'] = $l2[1]; |
|
500 |
$b['minute'] = $l2[2]; |
|
501 |
} else { |
|
502 |
$b['year'] = $lucifer[7]; |
|
503 |
$b['hour'] = 0; |
|
504 |
$b['minute'] = 0; |
|
505 |
} |
|
506 |
$b['time'] = strtotime( sprintf('%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute']) ); |
|
507 |
$b['name'] = $lucifer[8]; |
|
508 |
} |
|
509 |
} |
|
510 |
||
511 |
// Replace symlinks formatted as "source -> target" with just the source name |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
512 |
if ( isset( $b['islink'] ) && $b['islink'] ) { |
0 | 513 |
$b['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] ); |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
514 |
} |
0 | 515 |
|
516 |
return $b; |
|
517 |
} |
|
518 |
||
5 | 519 |
/** |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
520 |
* |
5 | 521 |
* @param string $path |
522 |
* @param bool $include_hidden |
|
523 |
* @param bool $recursive |
|
524 |
* @return bool|array |
|
525 |
*/ |
|
526 |
public function dirlist($path = '.', $include_hidden = true, $recursive = false) { |
|
0 | 527 |
if ( $this->is_file($path) ) { |
528 |
$limit_file = basename($path); |
|
529 |
$path = dirname($path) . '/'; |
|
530 |
} else { |
|
531 |
$limit_file = false; |
|
532 |
} |
|
533 |
||
534 |
$pwd = @ftp_pwd($this->link); |
|
535 |
if ( ! @ftp_chdir($this->link, $path) ) // Cant change to folder = folder doesn't exist |
|
536 |
return false; |
|
537 |
$list = @ftp_rawlist($this->link, '-a', false); |
|
538 |
@ftp_chdir($this->link, $pwd); |
|
539 |
||
540 |
if ( empty($list) ) // Empty array = non-existent folder (real folder will show . at least) |
|
541 |
return false; |
|
542 |
||
543 |
$dirlist = array(); |
|
544 |
foreach ( $list as $k => $v ) { |
|
545 |
$entry = $this->parselisting($v); |
|
546 |
if ( empty($entry) ) |
|
547 |
continue; |
|
548 |
||
549 |
if ( '.' == $entry['name'] || '..' == $entry['name'] ) |
|
550 |
continue; |
|
551 |
||
552 |
if ( ! $include_hidden && '.' == $entry['name'][0] ) |
|
553 |
continue; |
|
554 |
||
555 |
if ( $limit_file && $entry['name'] != $limit_file) |
|
556 |
continue; |
|
557 |
||
558 |
$dirlist[ $entry['name'] ] = $entry; |
|
559 |
} |
|
560 |
||
561 |
$ret = array(); |
|
562 |
foreach ( (array)$dirlist as $struc ) { |
|
563 |
if ( 'd' == $struc['type'] ) { |
|
564 |
if ( $recursive ) |
|
565 |
$struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive); |
|
566 |
else |
|
567 |
$struc['files'] = array(); |
|
568 |
} |
|
569 |
||
570 |
$ret[ $struc['name'] ] = $struc; |
|
571 |
} |
|
572 |
return $ret; |
|
573 |
} |
|
574 |
||
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
575 |
/** |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
576 |
*/ |
5 | 577 |
public function __destruct() { |
0 | 578 |
if ( $this->link ) |
579 |
ftp_close($this->link); |
|
580 |
} |
|
581 |
} |