Wordpress 2.5.1
[autoinstalls/wordpress.git] / wp-admin / includes / class-wp-filesystem-ftpsockets.php
1 <?php
2 class WP_Filesystem_ftpsockets{
3         var $ftp = false;
4         var $timeout = 5;
5         var $errors;
6         var $options = array();
7
8         var $wp_base = '';
9         var $permission = null;
10
11         var $filetypes = array(
12                                                         'php'=>FTP_ASCII,
13                                                         'css'=>FTP_ASCII,
14                                                         'txt'=>FTP_ASCII,
15                                                         'js'=>FTP_ASCII,
16                                                         'html'=>FTP_ASCII,
17                                                         'htm'=>FTP_ASCII,
18                                                         'xml'=>FTP_ASCII,
19
20                                                         'jpg'=>FTP_BINARY,
21                                                         'png'=>FTP_BINARY,
22                                                         'gif'=>FTP_BINARY,
23                                                         'bmp'=>FTP_BINARY
24                                                         );
25
26         function WP_Filesystem_ftpsockets($opt='') {
27                 $this->errors = new WP_Error();
28
29                 //Check if possible to use ftp functions.
30                 if( ! @include_once ABSPATH . 'wp-admin/includes/class-ftp.php' )
31                                 return false;
32                 $this->ftp = new ftp();
33
34                 //Set defaults:
35                 if ( empty($opt['port']) )
36                         $this->options['port'] = 21;
37                 else
38                         $this->options['port'] = $opt['port'];
39
40                 if ( empty($opt['hostname']) )
41                         $this->errors->add('empty_hostname', __('FTP hostname is required'));
42                 else
43                         $this->options['hostname'] = $opt['hostname'];
44
45                 if ( isset($opt['base']) && ! empty($opt['base']) )
46                         $this->wp_base = $opt['base'];
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
60         function connect() {
61                 if ( ! $this->ftp )
62                         return false;
63
64                 //$this->ftp->Verbose = true;
65
66                 if ( ! $this->ftp->SetServer($this->options['hostname'], $this->options['port']) ) {
67                         $this->errors->add('connect', sprintf(__('Failed to connect to FTP Server %1$s:%2$s'), $this->options['hostname'], $this->options['port']));
68                         return false;
69                 }
70                 if ( ! $this->ftp->connect() ) {
71                         $this->errors->add('connect', sprintf(__('Failed to connect to FTP Server %1$s:%2$s'), $this->options['hostname'], $this->options['port']));
72                         return false;
73                 }
74
75                 if ( ! $this->ftp->login($this->options['username'], $this->options['password']) ) {
76                         $this->errors->add('auth', sprintf(__('Username/Password incorrect for %s'), $this->options['username']));
77                         return false;
78                 }
79
80                 $this->ftp->SetType(FTP_AUTOASCII);
81                 $this->ftp->Passive(true);
82                 return true;
83         }
84
85         function setDefaultPermissions($perm) {
86                 $this->permission = $perm;
87         }
88
89         function find_base_dir($base = '.',$echo = false, $loop = false) {
90                 //Sanitize the Windows path formats, This allows easier conparison and aligns it to FTP output.
91                 $abspath = str_replace('\\','/',ABSPATH); //windows: Straighten up the paths..
92                 if( strpos($abspath, ':') ){ //Windows, Strip out the driveletter
93                         if( preg_match("|.{1}\:(.+)|i", $abspath, $mat) )
94                                 $abspath = $mat[1];
95                 }
96         
97                 //Set up the base directory (Which unless specified, is the current one)
98                 if( empty( $base ) || '.' == $base ) $base = $this->cwd();
99                 $base = trailingslashit($base);
100
101                 //Can we see the Current directory as part of the ABSPATH?
102                 $location = strpos($abspath, $base);
103                 if( false !== $location ) {
104                         $newbase = path_join($base, substr($abspath, $location + strlen($base)));
105
106                         if( false !== $this->chdir($newbase) ){ //chdir sometimes returns null under certain circumstances, even when its changed correctly, FALSE will be returned if it doesnt change correctly.
107                                 if($echo) printf( __('Changing to %s') . '<br/>', $newbase );
108                                 //Check to see if it exists in that folder.
109                                 if( $this->exists($newbase . 'wp-settings.php') ){
110                                         if($echo) printf( __('Found %s'),  $newbase . 'wp-settings.php<br/>' );
111                                         return $newbase;
112                                 }       
113                         }
114                 }
115         
116                 //Ok, Couldnt do a magic location from that particular folder level
117                 
118                 //Get a list of the files in the current directory, See if we can locate where we are in the folder stucture.
119                 $files = $this->dirlist($base);
120                 
121                 $arrPath = explode('/', $abspath);
122                 foreach($arrPath as $key){
123                         //Working from /home/ to /user/ to /wordpress/ see if that file exists within the current folder, 
124                         // If its found, change into it and follow through looking for it. 
125                         // If it cant find WordPress down that route, it'll continue onto the next folder level, and see if that matches, and so on.
126                         // If it reaches the end, and still cant find it, it'll return false for the entire function.
127                         if( isset($files[ $key ]) ){
128                                 //Lets try that folder:
129                                 $folder = path_join($base, $key);
130                                 if($echo) printf( __('Changing to %s') . '<br/>', $folder );
131                                 $ret = $this->find_base_dir( $folder, $echo, $loop);
132                                 if( $ret )
133                                         return $ret;
134                         }
135                 }
136                 //Only check this as a last resort, to prevent locating the incorrect install. All above proceeedures will fail quickly if this is the right branch to take.
137                 if(isset( $files[ 'wp-settings.php' ]) ){
138                         if($echo) printf( __('Found %s'),  $base . 'wp-settings.php<br/>' );
139                         return $base;
140                 }
141                 if( $loop )
142                         return false;//Prevent tihs function looping again.
143                 //As an extra last resort, Change back to / if the folder wasnt found. This comes into effect when the CWD is /home/user/ but WP is at /var/www/.... mainly dedicated setups.
144                 return $this->find_base_dir('/', $echo, true); 
145         }
146
147         function get_base_dir($base = '.', $echo = false){
148                 if( defined('FTP_BASE') )
149                         $this->wp_base = FTP_BASE;
150                 if( empty($this->wp_base) )
151                         $this->wp_base = $this->find_base_dir($base, $echo);
152                 return $this->wp_base;
153         }
154
155         function get_contents($file,$type='',$resumepos=0){
156                 if( ! $this->exists($file) )
157                         return false;
158
159                 if( empty($type) ){
160                         $extension = substr(strrchr($file, "."), 1);
161                         $type = isset($this->filetypes[ $extension ]) ? $this->filetypes[ $extension ] : FTP_AUTOASCII;
162                 }
163                 $this->ftp->SetType($type);
164                 $temp = tmpfile();
165                 if ( ! $temp )
166                         return false;
167                 if ( ! $this->ftp->fget($temp, $file) ) {
168                         fclose($temp);
169                         return ''; //Blank document, File does exist, Its just blank.
170                 }
171                 fseek($temp, 0); //Skip back to the start of the file being written to
172                 $contents = '';
173                 while ( !feof($temp) )
174                         $contents .= fread($temp, 8192);
175                 fclose($temp);
176                 return $contents;
177         }
178
179         function get_contents_array($file){
180                 return explode("\n",$this->get_contents($file));
181         }
182
183         function put_contents($file,$contents,$type=''){
184                 if( empty($type) ){
185                         $extension = substr(strrchr($file, "."), 1);
186                         $type = isset($this->filetypes[ $extension ]) ? $this->filetypes[ $extension ] : FTP_ASCII;
187                 }
188                 $this->ftp->SetType($type);
189
190                 $temp = tmpfile();
191                 if ( ! $temp )
192                         return false;
193                 fwrite($temp,$contents);
194                 fseek($temp, 0); //Skip back to the start of the file being written to
195                 $ret = $this->ftp->fput($file, $temp);
196                 fclose($temp);
197                 return $ret;
198         }
199
200         function cwd(){
201                 $cwd = $this->ftp->pwd();
202                 if( $cwd )
203                         $cwd = trailingslashit($cwd);
204                 return $cwd;
205         }
206
207         function chdir($file){
208                 return $this->ftp->chdir($file);
209         }
210         
211         function chgrp($file,$group,$recursive=false){
212                 return false;
213         }
214
215         function chmod($file,$mode=false,$recursive=false){
216                 if( ! $mode )
217                         $mode = $this->permission;
218                 if( ! $mode )
219                         return false;
220                 //if( ! $this->exists($file) )
221                 //      return false;
222                 if( ! $recursive || ! $this->is_dir($file) ){
223                         return $this->ftp->chmod($file,$mode);
224                 }
225                 //Is a directory, and we want recursive
226                 $filelist = $this->dirlist($file);
227                 foreach($filelist as $filename){
228                         $this->chmod($file.'/'.$filename,$mode,$recursive);
229                 }
230                 return true;
231         }
232
233         function chown($file,$owner,$recursive=false){
234                 return false;
235         }
236
237         function owner($file){
238                 $dir = $this->dirlist($file);
239                 return $dir[$file]['owner'];
240         }
241
242         function getchmod($file){
243                 $dir = $this->dirlist($file);
244                 return $dir[$file]['permsn'];
245         }
246
247         function gethchmod($file){
248                 //From the PHP.net page for ...?
249                 $perms = $this->getchmod($file);
250                 if (($perms & 0xC000) == 0xC000) {
251                         // Socket
252                         $info = 's';
253                 } elseif (($perms & 0xA000) == 0xA000) {
254                         // Symbolic Link
255                         $info = 'l';
256                 } elseif (($perms & 0x8000) == 0x8000) {
257                         // Regular
258                         $info = '-';
259                 } elseif (($perms & 0x6000) == 0x6000) {
260                         // Block special
261                         $info = 'b';
262                 } elseif (($perms & 0x4000) == 0x4000) {
263                         // Directory
264                         $info = 'd';
265                 } elseif (($perms & 0x2000) == 0x2000) {
266                         // Character special
267                         $info = 'c';
268                 } elseif (($perms & 0x1000) == 0x1000) {
269                         // FIFO pipe
270                         $info = 'p';
271                 } else {
272                         // Unknown
273                         $info = 'u';
274                 }
275
276                 // Owner
277                 $info .= (($perms & 0x0100) ? 'r' : '-');
278                 $info .= (($perms & 0x0080) ? 'w' : '-');
279                 $info .= (($perms & 0x0040) ?
280                                         (($perms & 0x0800) ? 's' : 'x' ) :
281                                         (($perms & 0x0800) ? 'S' : '-'));
282
283                 // Group
284                 $info .= (($perms & 0x0020) ? 'r' : '-');
285                 $info .= (($perms & 0x0010) ? 'w' : '-');
286                 $info .= (($perms & 0x0008) ?
287                                         (($perms & 0x0400) ? 's' : 'x' ) :
288                                         (($perms & 0x0400) ? 'S' : '-'));
289
290                 // World
291                 $info .= (($perms & 0x0004) ? 'r' : '-');
292                 $info .= (($perms & 0x0002) ? 'w' : '-');
293                 $info .= (($perms & 0x0001) ?
294                                         (($perms & 0x0200) ? 't' : 'x' ) :
295                                         (($perms & 0x0200) ? 'T' : '-'));
296                 return $info;
297         }
298
299         function getnumchmodfromh($mode) {
300                 $realmode = "";
301                 $legal =  array("","w","r","x","-");
302                 $attarray = preg_split("//",$mode);
303                 for($i=0;$i<count($attarray);$i++){
304                    if($key = array_search($attarray[$i],$legal)){
305                            $realmode .= $legal[$key];
306                    }
307                 }
308                 $mode = str_pad($realmode,9,'-');
309                 $trans = array('-'=>'0','r'=>'4','w'=>'2','x'=>'1');
310                 $mode = strtr($mode,$trans);
311                 $newmode = '';
312                 $newmode .= $mode[0]+$mode[1]+$mode[2];
313                 $newmode .= $mode[3]+$mode[4]+$mode[5];
314                 $newmode .= $mode[6]+$mode[7]+$mode[8];
315                 return $newmode;
316         }
317
318         function group($file){
319                 $dir = $this->dirlist($file);
320                 return $dir[$file]['group'];
321         }
322
323         function copy($source,$destination,$overwrite=false){
324                 if( ! $overwrite && $this->exists($destination) )
325                         return false;
326
327                 $content = $this->get_contents($source);
328                 if ( false === $content )
329                         return false;
330
331                 return $this->put_contents($destination,$content);
332         }
333
334         function move($source,$destination,$overwrite=false){
335                 return $this->ftp->rename($source,$destination);
336         }
337
338         function delete($file,$recursive=false) {
339                 if ( $this->is_file($file) )
340                         return $this->ftp->delete($file);
341                 if ( !$recursive )
342                         return $this->ftp->rmdir($file);
343
344                 return $this->ftp->mdel($file);
345         }
346
347         function exists($file){
348                 return $this->ftp->is_exists($file);
349         }
350
351         function is_file($file){
352                 return $this->is_dir($file) ? false : true;
353         }
354
355         function is_dir($path){
356                 $cwd = $this->cwd();
357                 if ( $this->chdir($path) ) {
358                         $this->chdir($cwd);
359                         return true;
360                 }
361                 return false;
362         }
363
364         function is_readable($file){
365                 //Get dir list, Check if the file is writable by the current user??
366                 return true;
367         }
368
369         function is_writable($file){
370                 //Get dir list, Check if the file is writable by the current user??
371                 return true;
372         }
373
374         function atime($file){
375                 return false;
376         }
377
378         function mtime($file){
379                 return $this->ftp->mdtm($file);
380         }
381
382         function size($file){
383                 return $this->ftp->filesize($file);
384         }
385
386         function touch($file,$time=0,$atime=0){
387                 return false;
388         }
389
390         function mkdir($path,$chmod=false,$chown=false,$chgrp=false){
391                 if( ! $this->ftp->mkdir($path) )
392                         return false;
393                 if( $chmod )
394                         $this->chmod($path, $chmod);
395                 if( $chown )
396                         $this->chown($path, $chown);
397                 if( $chgrp )
398                         $this->chgrp($path, $chgrp);
399                 return true;
400         }
401
402         function rmdir($path,$recursive=false){
403                 if( ! $recursive )
404                         return $this->ftp->rmdir($path);
405
406                 return $this->ftp->mdel($path);
407         }
408
409         function dirlist($path='.',$incdot=false,$recursive=false){
410                 if( $this->is_file($path) ){
411                         $limitFile = basename($path);
412                         $path = dirname($path) . '/';
413                 } else {
414                         $limitFile = false;
415                 }
416
417                 $list = $this->ftp->dirlist($path);
418                 if( ! $list )
419                         return false;
420                 if( empty($list) )
421                         return array();
422
423                 $ret = array();
424                 foreach ( $list as $struc ) {
425
426                         if ( 'd' == $struc['type'] ) {
427                                 $struc['files'] = array();
428
429                                 if ( $incdot ){
430                                         //We're including the doted starts
431                                         if( '.' != $struc['name'] && '..' != $struc['name'] ){ //Ok, It isnt a special folder
432                                                 if ($recursive)
433                                                         $struc['files'] = $this->dirlist($path.'/'.$struc['name'],$incdot,$recursive);
434                                         }
435                                 } else { //No dots
436                                         if ($recursive)
437                                                 $struc['files'] = $this->dirlist($path.'/'.$struc['name'],$incdot,$recursive);
438                                 }
439                         }
440                         //File
441                         $ret[$struc['name']] = $struc;
442                 }
443                 return $ret;
444         }
445
446         function __destruct(){
447                 $this->ftp->quit();
448         }
449 }
450 ?>