90 } |
90 } |
91 |
91 |
92 if ( ! $this->link ) { |
92 if ( ! $this->link ) { |
93 $this->errors->add( |
93 $this->errors->add( |
94 'connect', |
94 'connect', |
95 /* translators: %s: hostname:port */ |
|
96 sprintf( |
95 sprintf( |
|
96 /* translators: %s: hostname:port */ |
97 __( 'Failed to connect to FTP Server %s' ), |
97 __( 'Failed to connect to FTP Server %s' ), |
98 $this->options['hostname'] . ':' . $this->options['port'] |
98 $this->options['hostname'] . ':' . $this->options['port'] |
99 ) |
99 ) |
100 ); |
100 ); |
|
101 |
101 return false; |
102 return false; |
102 } |
103 } |
103 |
104 |
104 if ( ! @ftp_login( $this->link, $this->options['username'], $this->options['password'] ) ) { |
105 if ( ! @ftp_login( $this->link, $this->options['username'], $this->options['password'] ) ) { |
105 $this->errors->add( |
106 $this->errors->add( |
106 'auth', |
107 'auth', |
107 /* translators: %s: username */ |
|
108 sprintf( |
108 sprintf( |
|
109 /* translators: %s: Username. */ |
109 __( 'Username/Password incorrect for %s' ), |
110 __( 'Username/Password incorrect for %s' ), |
110 $this->options['username'] |
111 $this->options['username'] |
111 ) |
112 ) |
112 ); |
113 ); |
113 return false; |
114 |
114 } |
115 return false; |
115 |
116 } |
116 // Set the Connection to use Passive FTP |
117 |
117 @ftp_pasv( $this->link, true ); |
118 // Set the connection to use Passive FTP. |
|
119 ftp_pasv( $this->link, true ); |
|
120 |
118 if ( @ftp_get_option( $this->link, FTP_TIMEOUT_SEC ) < FS_TIMEOUT ) { |
121 if ( @ftp_get_option( $this->link, FTP_TIMEOUT_SEC ) < FS_TIMEOUT ) { |
119 @ftp_set_option( $this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT ); |
122 @ftp_set_option( $this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT ); |
120 } |
123 } |
121 |
124 |
122 return true; |
125 return true; |
130 * @param string $file Name of the file to read. |
133 * @param string $file Name of the file to read. |
131 * @return string|false Read data on success, false if no temporary file could be opened, |
134 * @return string|false Read data on success, false if no temporary file could be opened, |
132 * or if the file couldn't be retrieved. |
135 * or if the file couldn't be retrieved. |
133 */ |
136 */ |
134 public function get_contents( $file ) { |
137 public function get_contents( $file ) { |
135 $tempfile = wp_tempnam( $file ); |
138 $tempfile = wp_tempnam( $file ); |
136 $temp = fopen( $tempfile, 'w+' ); |
139 $temphandle = fopen( $tempfile, 'w+' ); |
137 |
140 |
138 if ( ! $temp ) { |
141 if ( ! $temphandle ) { |
139 unlink( $tempfile ); |
142 unlink( $tempfile ); |
140 return false; |
143 return false; |
141 } |
144 } |
142 |
145 |
143 if ( ! @ftp_fget( $this->link, $temp, $file, FTP_BINARY ) ) { |
146 if ( ! ftp_fget( $this->link, $temphandle, $file, FTP_BINARY ) ) { |
144 fclose( $temp ); |
147 fclose( $temphandle ); |
145 unlink( $tempfile ); |
148 unlink( $tempfile ); |
146 return false; |
149 return false; |
147 } |
150 } |
148 |
151 |
149 fseek( $temp, 0 ); // Skip back to the start of the file being written to |
152 fseek( $temphandle, 0 ); // Skip back to the start of the file being written to. |
150 $contents = ''; |
153 $contents = ''; |
151 |
154 |
152 while ( ! feof( $temp ) ) { |
155 while ( ! feof( $temphandle ) ) { |
153 $contents .= fread( $temp, 8 * KB_IN_BYTES ); |
156 $contents .= fread( $temphandle, 8 * KB_IN_BYTES ); |
154 } |
157 } |
155 |
158 |
156 fclose( $temp ); |
159 fclose( $temphandle ); |
157 unlink( $tempfile ); |
160 unlink( $tempfile ); |
|
161 |
158 return $contents; |
162 return $contents; |
159 } |
163 } |
160 |
164 |
161 /** |
165 /** |
162 * Reads entire file into an array. |
166 * Reads entire file into an array. |
180 * @param int|false $mode Optional. The file permissions as octal number, usually 0644. |
184 * @param int|false $mode Optional. The file permissions as octal number, usually 0644. |
181 * Default false. |
185 * Default false. |
182 * @return bool True on success, false on failure. |
186 * @return bool True on success, false on failure. |
183 */ |
187 */ |
184 public function put_contents( $file, $contents, $mode = false ) { |
188 public function put_contents( $file, $contents, $mode = false ) { |
185 $tempfile = wp_tempnam( $file ); |
189 $tempfile = wp_tempnam( $file ); |
186 $temp = fopen( $tempfile, 'wb+' ); |
190 $temphandle = fopen( $tempfile, 'wb+' ); |
187 |
191 |
188 if ( ! $temp ) { |
192 if ( ! $temphandle ) { |
189 unlink( $tempfile ); |
193 unlink( $tempfile ); |
190 return false; |
194 return false; |
191 } |
195 } |
192 |
196 |
193 mbstring_binary_safe_encoding(); |
197 mbstring_binary_safe_encoding(); |
194 |
198 |
195 $data_length = strlen( $contents ); |
199 $data_length = strlen( $contents ); |
196 $bytes_written = fwrite( $temp, $contents ); |
200 $bytes_written = fwrite( $temphandle, $contents ); |
197 |
201 |
198 reset_mbstring_encoding(); |
202 reset_mbstring_encoding(); |
199 |
203 |
200 if ( $data_length !== $bytes_written ) { |
204 if ( $data_length !== $bytes_written ) { |
201 fclose( $temp ); |
205 fclose( $temphandle ); |
202 unlink( $tempfile ); |
206 unlink( $tempfile ); |
203 return false; |
207 return false; |
204 } |
208 } |
205 |
209 |
206 fseek( $temp, 0 ); // Skip back to the start of the file being written to |
210 fseek( $temphandle, 0 ); // Skip back to the start of the file being written to. |
207 |
211 |
208 $ret = @ftp_fput( $this->link, $file, $temp, FTP_BINARY ); |
212 $ret = ftp_fput( $this->link, $file, $temphandle, FTP_BINARY ); |
209 |
213 |
210 fclose( $temp ); |
214 fclose( $temphandle ); |
211 unlink( $tempfile ); |
215 unlink( $tempfile ); |
212 |
216 |
213 $this->chmod( $file, $mode ); |
217 $this->chmod( $file, $mode ); |
214 |
218 |
215 return $ret; |
219 return $ret; |
266 } |
272 } |
267 |
273 |
268 // chmod any sub-objects if recursive. |
274 // chmod any sub-objects if recursive. |
269 if ( $recursive && $this->is_dir( $file ) ) { |
275 if ( $recursive && $this->is_dir( $file ) ) { |
270 $filelist = $this->dirlist( $file ); |
276 $filelist = $this->dirlist( $file ); |
|
277 |
271 foreach ( (array) $filelist as $filename => $filemeta ) { |
278 foreach ( (array) $filelist as $filename => $filemeta ) { |
272 $this->chmod( $file . '/' . $filename, $mode, $recursive ); |
279 $this->chmod( $file . '/' . $filename, $mode, $recursive ); |
273 } |
280 } |
274 } |
281 } |
275 |
282 |
276 // chmod the file or directory |
283 // chmod the file or directory. |
277 if ( ! function_exists( 'ftp_chmod' ) ) { |
284 if ( ! function_exists( 'ftp_chmod' ) ) { |
278 return (bool) @ftp_site( $this->link, sprintf( 'CHMOD %o %s', $mode, $file ) ); |
285 return (bool) ftp_site( $this->link, sprintf( 'CHMOD %o %s', $mode, $file ) ); |
279 } |
286 } |
280 return (bool) @ftp_chmod( $this->link, $mode, $file ); |
287 |
|
288 return (bool) ftp_chmod( $this->link, $mode, $file ); |
281 } |
289 } |
282 |
290 |
283 /** |
291 /** |
284 * Gets the file owner. |
292 * Gets the file owner. |
285 * |
293 * |
362 * Deletes a file or directory. |
376 * Deletes a file or directory. |
363 * |
377 * |
364 * @since 2.5.0 |
378 * @since 2.5.0 |
365 * |
379 * |
366 * @param string $file Path to the file or directory. |
380 * @param string $file Path to the file or directory. |
367 * @param bool $recursive Optional. If set to true, changes file group recursively. |
381 * @param bool $recursive Optional. If set to true, deletes files and folders recursively. |
368 * Default false. |
382 * Default false. |
369 * @param string|false $type Type of resource. 'f' for file, 'd' for directory. |
383 * @param string|false $type Type of resource. 'f' for file, 'd' for directory. |
370 * Default false. |
384 * Default false. |
371 * @return bool True on success, false on failure. |
385 * @return bool True on success, false on failure. |
372 */ |
386 */ |
373 public function delete( $file, $recursive = false, $type = false ) { |
387 public function delete( $file, $recursive = false, $type = false ) { |
374 if ( empty( $file ) ) { |
388 if ( empty( $file ) ) { |
375 return false; |
389 return false; |
376 } |
390 } |
377 if ( 'f' == $type || $this->is_file( $file ) ) { |
391 |
378 return @ftp_delete( $this->link, $file ); |
392 if ( 'f' === $type || $this->is_file( $file ) ) { |
379 } |
393 return ftp_delete( $this->link, $file ); |
|
394 } |
|
395 |
380 if ( ! $recursive ) { |
396 if ( ! $recursive ) { |
381 return @ftp_rmdir( $this->link, $file ); |
397 return ftp_rmdir( $this->link, $file ); |
382 } |
398 } |
383 |
399 |
384 $filelist = $this->dirlist( trailingslashit( $file ) ); |
400 $filelist = $this->dirlist( trailingslashit( $file ) ); |
|
401 |
385 if ( ! empty( $filelist ) ) { |
402 if ( ! empty( $filelist ) ) { |
386 foreach ( $filelist as $delete_file ) { |
403 foreach ( $filelist as $delete_file ) { |
387 $this->delete( trailingslashit( $file ) . $delete_file['name'], $recursive, $delete_file['type'] ); |
404 $this->delete( trailingslashit( $file ) . $delete_file['name'], $recursive, $delete_file['type'] ); |
388 } |
405 } |
389 } |
406 } |
390 return @ftp_rmdir( $this->link, $file ); |
407 |
|
408 return ftp_rmdir( $this->link, $file ); |
391 } |
409 } |
392 |
410 |
393 /** |
411 /** |
394 * Checks if a file or directory exists. |
412 * Checks if a file or directory exists. |
395 * |
413 * |
556 public function rmdir( $path, $recursive = false ) { |
579 public function rmdir( $path, $recursive = false ) { |
557 return $this->delete( $path, $recursive ); |
580 return $this->delete( $path, $recursive ); |
558 } |
581 } |
559 |
582 |
560 /** |
583 /** |
561 * @staticvar bool $is_windows |
|
562 * @param string $line |
584 * @param string $line |
563 * @return array |
585 * @return array |
564 */ |
586 */ |
565 public function parselisting( $line ) { |
587 public function parselisting( $line ) { |
566 static $is_windows = null; |
588 static $is_windows = null; |
|
589 |
567 if ( is_null( $is_windows ) ) { |
590 if ( is_null( $is_windows ) ) { |
568 $is_windows = stripos( ftp_systype( $this->link ), 'win' ) !== false; |
591 $is_windows = stripos( ftp_systype( $this->link ), 'win' ) !== false; |
569 } |
592 } |
570 |
593 |
571 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 ) ) { |
594 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 ) ) { |
572 $b = array(); |
595 $b = array(); |
|
596 |
573 if ( $lucifer[3] < 70 ) { |
597 if ( $lucifer[3] < 70 ) { |
574 $lucifer[3] += 2000; |
598 $lucifer[3] += 2000; |
575 } else { |
599 } else { |
576 $lucifer[3] += 1900; // 4digit year fix |
600 $lucifer[3] += 1900; // 4-digit year fix. |
577 } |
601 } |
578 $b['isdir'] = ( $lucifer[7] == '<DIR>' ); |
602 |
|
603 $b['isdir'] = ( '<DIR>' === $lucifer[7] ); |
|
604 |
579 if ( $b['isdir'] ) { |
605 if ( $b['isdir'] ) { |
580 $b['type'] = 'd'; |
606 $b['type'] = 'd'; |
581 } else { |
607 } else { |
582 $b['type'] = 'f'; |
608 $b['type'] = 'f'; |
583 } |
609 } |
|
610 |
584 $b['size'] = $lucifer[7]; |
611 $b['size'] = $lucifer[7]; |
585 $b['month'] = $lucifer[1]; |
612 $b['month'] = $lucifer[1]; |
586 $b['day'] = $lucifer[2]; |
613 $b['day'] = $lucifer[2]; |
587 $b['year'] = $lucifer[3]; |
614 $b['year'] = $lucifer[3]; |
588 $b['hour'] = $lucifer[4]; |
615 $b['hour'] = $lucifer[4]; |
589 $b['minute'] = $lucifer[5]; |
616 $b['minute'] = $lucifer[5]; |
590 $b['time'] = @mktime( $lucifer[4] + ( strcasecmp( $lucifer[6], 'PM' ) == 0 ? 12 : 0 ), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3] ); |
617 $b['time'] = mktime( $lucifer[4] + ( strcasecmp( $lucifer[6], 'PM' ) == 0 ? 12 : 0 ), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3] ); |
591 $b['am/pm'] = $lucifer[6]; |
618 $b['am/pm'] = $lucifer[6]; |
592 $b['name'] = $lucifer[8]; |
619 $b['name'] = $lucifer[8]; |
593 } elseif ( ! $is_windows && $lucifer = preg_split( '/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY ) ) { |
620 } elseif ( ! $is_windows ) { |
594 //echo $line."\n"; |
621 $lucifer = preg_split( '/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY ); |
595 $lcount = count( $lucifer ); |
622 |
596 if ( $lcount < 8 ) { |
623 if ( $lucifer ) { |
597 return ''; |
624 // echo $line."\n"; |
598 } |
625 $lcount = count( $lucifer ); |
599 $b = array(); |
626 |
600 $b['isdir'] = $lucifer[0]{0} === 'd'; |
627 if ( $lcount < 8 ) { |
601 $b['islink'] = $lucifer[0]{0} === 'l'; |
628 return ''; |
602 if ( $b['isdir'] ) { |
629 } |
603 $b['type'] = 'd'; |
630 |
604 } elseif ( $b['islink'] ) { |
631 $b = array(); |
605 $b['type'] = 'l'; |
632 $b['isdir'] = 'd' === $lucifer[0][0]; |
606 } else { |
633 $b['islink'] = 'l' === $lucifer[0][0]; |
607 $b['type'] = 'f'; |
634 |
608 } |
635 if ( $b['isdir'] ) { |
609 $b['perms'] = $lucifer[0]; |
636 $b['type'] = 'd'; |
610 $b['permsn'] = $this->getnumchmodfromh( $b['perms'] ); |
637 } elseif ( $b['islink'] ) { |
611 $b['number'] = $lucifer[1]; |
638 $b['type'] = 'l'; |
612 $b['owner'] = $lucifer[2]; |
|
613 $b['group'] = $lucifer[3]; |
|
614 $b['size'] = $lucifer[4]; |
|
615 if ( $lcount == 8 ) { |
|
616 sscanf( $lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day'] ); |
|
617 sscanf( $lucifer[6], '%d:%d', $b['hour'], $b['minute'] ); |
|
618 $b['time'] = @mktime( $b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year'] ); |
|
619 $b['name'] = $lucifer[7]; |
|
620 } else { |
|
621 $b['month'] = $lucifer[5]; |
|
622 $b['day'] = $lucifer[6]; |
|
623 if ( preg_match( '/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2 ) ) { |
|
624 $b['year'] = date( 'Y' ); |
|
625 $b['hour'] = $l2[1]; |
|
626 $b['minute'] = $l2[2]; |
|
627 } else { |
639 } else { |
628 $b['year'] = $lucifer[7]; |
640 $b['type'] = 'f'; |
629 $b['hour'] = 0; |
|
630 $b['minute'] = 0; |
|
631 } |
641 } |
632 $b['time'] = strtotime( sprintf( '%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute'] ) ); |
642 |
633 $b['name'] = $lucifer[8]; |
643 $b['perms'] = $lucifer[0]; |
634 } |
644 $b['permsn'] = $this->getnumchmodfromh( $b['perms'] ); |
635 } |
645 $b['number'] = $lucifer[1]; |
636 |
646 $b['owner'] = $lucifer[2]; |
637 // Replace symlinks formatted as "source -> target" with just the source name |
647 $b['group'] = $lucifer[3]; |
|
648 $b['size'] = $lucifer[4]; |
|
649 |
|
650 if ( 8 == $lcount ) { |
|
651 sscanf( $lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day'] ); |
|
652 sscanf( $lucifer[6], '%d:%d', $b['hour'], $b['minute'] ); |
|
653 |
|
654 $b['time'] = mktime( $b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year'] ); |
|
655 $b['name'] = $lucifer[7]; |
|
656 } else { |
|
657 $b['month'] = $lucifer[5]; |
|
658 $b['day'] = $lucifer[6]; |
|
659 |
|
660 if ( preg_match( '/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2 ) ) { |
|
661 $b['year'] = gmdate( 'Y' ); |
|
662 $b['hour'] = $l2[1]; |
|
663 $b['minute'] = $l2[2]; |
|
664 } else { |
|
665 $b['year'] = $lucifer[7]; |
|
666 $b['hour'] = 0; |
|
667 $b['minute'] = 0; |
|
668 } |
|
669 |
|
670 $b['time'] = strtotime( sprintf( '%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute'] ) ); |
|
671 $b['name'] = $lucifer[8]; |
|
672 } |
|
673 } |
|
674 } |
|
675 |
|
676 // Replace symlinks formatted as "source -> target" with just the source name. |
638 if ( isset( $b['islink'] ) && $b['islink'] ) { |
677 if ( isset( $b['islink'] ) && $b['islink'] ) { |
639 $b['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] ); |
678 $b['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] ); |
640 } |
679 } |
641 |
680 |
642 return $b; |
681 return $b; |
673 $path = dirname( $path ) . '/'; |
712 $path = dirname( $path ) . '/'; |
674 } else { |
713 } else { |
675 $limit_file = false; |
714 $limit_file = false; |
676 } |
715 } |
677 |
716 |
678 $pwd = @ftp_pwd( $this->link ); |
717 $pwd = ftp_pwd( $this->link ); |
|
718 |
679 if ( ! @ftp_chdir( $this->link, $path ) ) { // Can't change to folder = folder doesn't exist. |
719 if ( ! @ftp_chdir( $this->link, $path ) ) { // Can't change to folder = folder doesn't exist. |
680 return false; |
720 return false; |
681 } |
721 } |
682 $list = @ftp_rawlist( $this->link, '-a', false ); |
722 |
|
723 $list = ftp_rawlist( $this->link, '-a', false ); |
|
724 |
683 @ftp_chdir( $this->link, $pwd ); |
725 @ftp_chdir( $this->link, $pwd ); |
684 |
726 |
685 if ( empty( $list ) ) { // Empty array = non-existent folder (real folder will show . at least). |
727 if ( empty( $list ) ) { // Empty array = non-existent folder (real folder will show . at least). |
686 return false; |
728 return false; |
687 } |
729 } |
688 |
730 |
689 $dirlist = array(); |
731 $dirlist = array(); |
|
732 |
690 foreach ( $list as $k => $v ) { |
733 foreach ( $list as $k => $v ) { |
691 $entry = $this->parselisting( $v ); |
734 $entry = $this->parselisting( $v ); |
|
735 |
692 if ( empty( $entry ) ) { |
736 if ( empty( $entry ) ) { |
693 continue; |
737 continue; |
694 } |
738 } |
695 |
739 |
696 if ( '.' == $entry['name'] || '..' == $entry['name'] ) { |
740 if ( '.' === $entry['name'] || '..' === $entry['name'] ) { |
697 continue; |
741 continue; |
698 } |
742 } |
699 |
743 |
700 if ( ! $include_hidden && '.' == $entry['name'][0] ) { |
744 if ( ! $include_hidden && '.' === $entry['name'][0] ) { |
701 continue; |
745 continue; |
702 } |
746 } |
703 |
747 |
704 if ( $limit_file && $entry['name'] != $limit_file ) { |
748 if ( $limit_file && $entry['name'] != $limit_file ) { |
705 continue; |
749 continue; |