Changeset 7126

Show
Ignore:
Timestamp:
03/01/08 21:20:23 (5 months ago)
Author:
ryan
Message:

Plugin updater updates. see #5586

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/wp-admin/includes/class-ftp.php

    r6919 r7126  
    11<?php 
    2     //http://phpclasses.dknss.com/browse/package/3174.html 
    3     define("FTP_TIMEOUT",10); 
    4  
    5     // FTP Statuscodes 
    6     define("FTP_COMMAND_OK",200); 
    7     define("FTP_FILE_ACTION_OK",250); 
    8     define("FTP_FILE_TRANSFER_OK",226); 
    9     define("FTP_COMMAND_NOT_IMPLEMENTED",502); 
    10     define("FTP_FILE_STATUS",213); 
    11     define("FTP_NAME_SYSTEM_TYPE",215); 
    12     define("FTP_PASSIVE_MODE",227); 
    13     define("FTP_PATHNAME",257); 
    14     define("FTP_SERVICE_READY",220); 
    15     define("FTP_USER_LOGGED_IN",230); 
    16     define("FTP_PASSWORD_NEEDED",331); 
    17     define("FTP_USER_NOT_LOGGED_IN",530); 
     2if(!defined('CRLF')) define('CRLF',"\r\n"); 
     3if(!defined("FTP_AUTOASCII")) define("FTP_AUTOASCII", -1); 
     4if(!defined("FTP_BINARY")) define("FTP_BINARY", 1); 
     5if(!defined("FTP_ASCII")) define("FTP_ASCII", 0); 
     6if(!defined('FTP_FORCE')) define('FTP_FORCE', TRUE); 
     7define('FTP_OS_Unix','u'); 
     8define('FTP_OS_Windows','w'); 
     9define('FTP_OS_Mac','m'); 
     10 
     11class ftp_base { 
     12    /* Public variables */ 
     13    var $LocalEcho; 
     14    var $Verbose; 
     15    var $OS_local; 
     16    var $OS_remote; 
    1817     
    19     if (!defined("FTP_ASCII")) define("FTP_ASCII",0); 
    20     if (!defined("FTP_BINARY")) define("FTP_BINARY",1); 
    21  
    22     class FTP { 
    23  
    24         var $passiveMode = TRUE; 
    25         var $lastLines = array(); 
    26         var $lastLine = ""; 
    27         var $controlSocket = NULL; 
    28         var $newResult = FALSE; 
    29         var $lastResult = -1; 
    30         var $pasvAddr = NULL;  
     18    /* Private variables */ 
     19    var $_lastaction; 
     20    var $_errors; 
     21    var $_type; 
     22    var $_umask; 
     23    var $_timeout; 
     24    var $_passive; 
     25    var $_host; 
     26    var $_fullhost; 
     27    var $_port; 
     28    var $_datahost; 
     29    var $_dataport; 
     30    var $_ftp_control_sock; 
     31    var $_ftp_data_sock; 
     32    var $_ftp_temp_sock; 
     33    var $_ftp_buff_size; 
     34    var $_login; 
     35    var $_password; 
     36    var $_connected; 
     37    var $_ready; 
     38    var $_code; 
     39    var $_message; 
     40    var $_can_restore; 
     41    var $_port_available; 
     42    var $_curtype; 
     43    var $_features; 
     44 
     45    var $_error_array; 
     46    var $AuthorizedTransferMode; 
     47    var $OS_FullName; 
     48    var $_eol_code; 
     49    var $AutoAsciiExt; 
     50 
     51    /* Constructor */ 
     52    function ftp_base($port_mode=FALSE) { 
     53        $this->__construct($port_mode); 
     54    } 
     55 
     56    function __construct($port_mode=FALSE, $verb=FALSE, $le=FALSE) { 
     57        $this->LocalEcho=$le; 
     58        $this->Verbose=$verb; 
     59        $this->_lastaction=NULL; 
     60        $this->_error_array=array(); 
     61        $this->_eol_code=array(FTP_OS_Unix=>"\n", FTP_OS_Mac=>"\r", FTP_OS_Windows=>"\r\n"); 
     62        $this->AuthorizedTransferMode=array(FTP_AUTOASCII, FTP_ASCII, FTP_BINARY); 
     63        $this->OS_FullName=array(FTP_OS_Unix => 'UNIX', FTP_OS_Windows => 'WINDOWS', FTP_OS_Mac => 'MACOS'); 
     64        $this->AutoAsciiExt=array("ASP","BAT","C","CPP","CSS","CSV","JS","H","HTM","HTML","SHTML","INI","LOG","PHP3","PHTML","PL","PERL","SH","SQL","TXT"); 
     65        $this->_port_available=($port_mode==TRUE); 
     66        $this->SendMSG("Staring FTP client class".($this->_port_available?"":" without PORT mode support")); 
     67        $this->_connected=FALSE; 
     68        $this->_ready=FALSE; 
     69        $this->_can_restore=FALSE; 
     70        $this->_code=0; 
     71        $this->_message=""; 
     72        $this->_ftp_buff_size=4096; 
     73        $this->_curtype=NULL; 
     74        $this->SetUmask(0022); 
     75        $this->SetType(FTP_AUTOASCII); 
     76        $this->SetTimeout(30); 
     77        $this->Passive(!$this->_port_available); 
     78        $this->_login="anonymous"; 
     79        $this->_password="anon@ftp.com"; 
     80        $this->_features=array(); 
     81        $this->OS_local=FTP_OS_Unix; 
     82        $this->OS_remote=FTP_OS_Unix; 
     83        $this->features=array(); 
     84        if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $this->OS_local=FTP_OS_Windows; 
     85        elseif(strtoupper(substr(PHP_OS, 0, 3)) === 'MAC') $this->OS_local=FTP_OS_Mac; 
     86    } 
     87 
     88// <!-- --------------------------------------------------------------------------------------- --> 
     89// <!--       Public functions                                                                  --> 
     90// <!-- --------------------------------------------------------------------------------------- --> 
     91 
     92    function parselisting($line) { 
     93        $is_windows = ($this->OS_remote == FTP_OS_Windows); 
     94        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)) { 
     95            $b = array(); 
     96            if ($lucifer[3]<70) { $lucifer[3]+=2000; } else { $lucifer[3]+=1900; } // 4digit year fix 
     97            $b['isdir'] = ($lucifer[7]=="<DIR>"); 
     98            if ( $b['isdir'] ) 
     99                $b['type'] = 'd'; 
     100            else 
     101                $b['type'] = 'f'; 
     102            $b['size'] = $lucifer[7]; 
     103            $b['month'] = $lucifer[1]; 
     104            $b['day'] = $lucifer[2]; 
     105            $b['year'] = $lucifer[3]; 
     106            $b['hour'] = $lucifer[4]; 
     107            $b['minute'] = $lucifer[5]; 
     108            $b['time'] = @mktime($lucifer[4]+(strcasecmp($lucifer[6],"PM")==0?12:0),$lucifer[5],0,$lucifer[1],$lucifer[2],$lucifer[3]); 
     109            $b['am/pm'] = $lucifer[6]; 
     110            $b['name'] = $lucifer[8]; 
     111        } else if (!$is_windows && $lucifer=preg_split("/[ ]/",$line,9,PREG_SPLIT_NO_EMPTY)) { 
     112            //echo $line."\n"; 
     113            $lcount=count($lucifer); 
     114            if ($lcount<8) return ''; 
     115            $b = array(); 
     116            $b['isdir'] = $lucifer[0]{0} === "d"; 
     117            $b['islink'] = $lucifer[0]{0} === "l"; 
     118            if ( $b['isdir'] ) 
     119                $b['type'] = 'd'; 
     120            elseif ( $b['islink'] ) 
     121                $b['type'] = 'l'; 
     122            else 
     123                $b['type'] = 'f'; 
     124            $b['perms'] = $lucifer[0]; 
     125            $b['number'] = $lucifer[1]; 
     126            $b['owner'] = $lucifer[2]; 
     127            $b['group'] = $lucifer[3]; 
     128            $b['size'] = $lucifer[4]; 
     129            if ($lcount==8) { 
     130                sscanf($lucifer[5],"%d-%d-%d",$b['year'],$b['month'],$b['day']); 
     131                sscanf($lucifer[6],"%d:%d",$b['hour'],$b['minute']); 
     132                $b['time'] = @mktime($b['hour'],$b['minute'],0,$b['month'],$b['day'],$b['year']); 
     133                $b['name'] = $lucifer[7]; 
     134            } else { 
     135                $b['month'] = $lucifer[5]; 
     136                $b['day'] = $lucifer[6]; 
     137                if (preg_match("/([0-9]{2}):([0-9]{2})/",$lucifer[7],$l2)) { 
     138                    $b['year'] = date("Y"); 
     139                    $b['hour'] = $l2[1]; 
     140                    $b['minute'] = $l2[2]; 
     141                } else { 
     142                    $b['year'] = $lucifer[7]; 
     143                    $b['hour'] = 0; 
     144                    $b['minute'] = 0; 
     145                } 
     146                $b['time'] = strtotime(sprintf("%d %s %d %02d:%02d",$b['day'],$b['month'],$b['year'],$b['hour'],$b['minute'])); 
     147                $b['name'] = $lucifer[8]; 
     148            } 
     149        } 
     150 
     151        return $b; 
     152    } 
     153 
     154    function SendMSG($message = "", $crlf=true) { 
     155        if ($this->Verbose) { 
     156            echo $message.($crlf?CRLF:""); 
     157            flush(); 
     158        } 
     159        return TRUE; 
     160    } 
     161 
     162    function SetType($mode=FTP_AUTOASCII) { 
     163        if(!in_array($mode, $this->AuthorizedTransferMode)) { 
     164            $this->SendMSG("Wrong type"); 
     165            return FALSE; 
     166        } 
     167        $this->_type=$mode; 
     168        $this->SendMSG("Transfer type: ".($this->_type==FTP_BINARY?"binary":($this->_type==FTP_ASCII?"ASCII":"auto ASCII") ) ); 
     169        return TRUE; 
     170    } 
     171 
     172    function _settype($mode=FTP_ASCII) { 
     173        if($this->_ready) { 
     174            if($mode==FTP_BINARY) { 
     175                if($this->_curtype!=FTP_BINARY) { 
     176                    if(!$this->_exec("TYPE I", "SetType")) return FALSE; 
     177                    $this->_curtype=FTP_BINARY; 
     178                } 
     179            } elseif($this->_curtype!=FTP_ASCII) { 
     180                if(!$this->_exec("TYPE A", "SetType")) return FALSE; 
     181                $this->_curtype=FTP_ASCII; 
     182            } 
     183        } else return FALSE; 
     184        return TRUE; 
     185    } 
     186 
     187    function Passive($pasv=NULL) { 
     188        if(is_null($pasv)) $this->_passive=!$this->_passive; 
     189        else $this->_passive=$pasv; 
     190        if(!$this->_port_available and !$this->_passive) { 
     191            $this->SendMSG("Only passive connections available!"); 
     192            $this->_passive=TRUE; 
     193            return FALSE; 
     194        } 
     195        $this->SendMSG("Passive mode ".($this->_passive?"on":"off")); 
     196        return TRUE; 
     197    } 
     198 
     199    function SetServer($host, $port=21, $reconnect=true) { 
     200        if(!is_long($port)) { 
     201            $this->verbose=true; 
     202            $this->SendMSG("Incorrect port syntax"); 
     203            return FALSE; 
     204        } else { 
     205            $ip=@gethostbyname($host); 
     206            $dns=@gethostbyaddr($host); 
     207            if(!$ip) $ip=$host; 
     208            if(!$dns) $dns=$host; 
     209            if(ip2long($ip) === -1) { 
     210                $this->SendMSG("Wrong host name/address \"".$host."\""); 
     211                return FALSE; 
     212            } 
     213            $this->_host=$ip; 
     214            $this->_fullhost=$dns; 
     215            $this->_port=$port; 
     216            $this->_dataport=$port-1; 
     217        } 
     218        $this->SendMSG("Host \"".$this->_fullhost."(".$this->_host."):".$this->_port."\""); 
     219        if($reconnect){ 
     220            if($this->_connected) { 
     221                $this->SendMSG("Reconnecting"); 
     222                if(!$this->quit(FTP_FORCE)) return FALSE; 
     223                if(!$this->connect()) return FALSE; 
     224            } 
     225        } 
     226        return TRUE; 
     227    } 
     228 
     229    function SetUmask($umask=0022) { 
     230        $this->_umask=$umask; 
     231        umask($this->_umask); 
     232        $this->SendMSG("UMASK 0".decoct($this->_umask)); 
     233        return TRUE; 
     234    } 
     235 
     236    function SetTimeout($timeout=30) { 
     237        $this->_timeout=$timeout; 
     238        $this->SendMSG("Timeout ".$this->_timeout); 
     239        if($this->_connected) 
     240            if(!$this->_settimeout($this->_ftp_control_sock)) return FALSE; 
     241        return TRUE; 
     242    } 
     243 
     244    function connect($server=NULL) { 
     245        if(!empty($server)) { 
     246            if(!$this->SetServer($server)) return false; 
     247        } 
     248        if($this->_ready) return true; 
     249        $this->SendMsg('Local OS : '.$this->OS_FullName[$this->OS_local]); 
     250        if(!($this->_ftp_control_sock = $this->_connect($this->_host, $this->_port))) { 
     251            $this->SendMSG("Error : Cannot connect to remote host \"".$this->_fullhost." :".$this->_port."\""); 
     252            return FALSE; 
     253        } 
     254        $this->SendMSG("Connected to remote host \"".$this->_fullhost.":".$this->_port."\". Waiting for greeting."); 
     255        do { 
     256            if(!$this->_readmsg()) return FALSE; 
     257            if(!$this->_checkCode()) return FALSE; 
     258            $this->_lastaction=time(); 
     259        } while($this->_code<200); 
     260        $this->_ready=true; 
     261        $syst=$this->systype(); 
     262        if(!$syst) $this->SendMSG("Can't detect remote OS"); 
     263        else { 
     264            if(preg_match("/win|dos|novell/i", $syst[0])) $this->OS_remote=FTP_OS_Windows; 
     265            elseif(preg_match("/os/i", $syst[0])) $this->OS_remote=FTP_OS_Mac; 
     266            elseif(preg_match("/(li|u)nix/i", $syst[0])) $this->OS_remote=FTP_OS_Unix; 
     267            else $this->OS_remote=FTP_OS_Mac; 
     268            $this->SendMSG("Remote OS: ".$this->OS_FullName[$this->OS_remote]); 
     269        } 
     270        if(!$this->features()) $this->SendMSG("Can't get features list. All supported - disabled"); 
     271        else $this->SendMSG("Supported features: ".implode(", ", array_keys($this->_features))); 
     272        return TRUE; 
     273    } 
     274 
     275    function quit($force=false) { 
     276        if($this->_ready) { 
     277            if(!$this->_exec("QUIT") and !$force) return FALSE; 
     278            if(!$this->_checkCode() and !$force) return FALSE; 
     279            $this->_ready=false; 
     280            $this->SendMSG("Session finished"); 
     281        } 
     282        $this->_quit(); 
     283        return TRUE; 
     284    } 
     285 
     286    function login($user=NULL, $pass=NULL) { 
     287        if(!is_null($user)) $this->_login=$user; 
     288        else $this->_login="anonymous"; 
     289        if(!is_null($pass)) $this->_password=$pass; 
     290        else $this->_password="anon@anon.com"; 
     291        if(!$this->_exec("USER ".$this->_login, "login")) return FALSE; 
     292        if(!$this->_checkCode()) return FALSE; 
     293        if($this->_code!=230) { 
     294            if(!$this->_exec((($this->_code==331)?"PASS ":"ACCT ").$this->_password, "login")) return FALSE; 
     295            if(!$this->_checkCode()) return FALSE; 
     296        } 
     297        $this->SendMSG("Authentication succeeded"); 
     298        if(empty($this->_features)) { 
     299            if(!$this->features()) $this->SendMSG("Can't get features list. All supported - disabled"); 
     300            else $this->SendMSG("Supported features: ".implode(", ", array_keys($this->_features))); 
     301        } 
     302        return TRUE; 
     303    } 
     304 
     305    function pwd() { 
     306        if(!$this->_exec("PWD", "pwd")) return FALSE; 
     307        if(!$this->_checkCode()) return FALSE; 
     308        return ereg_replace("^[0-9]{3} \"(.+)\" .+".CRLF, "\\1", $this->_message); 
     309    } 
     310 
     311    function cdup() { 
     312        if(!$this->_exec("CDUP", "cdup")) return FALSE; 
     313        if(!$this->_checkCode()) return FALSE; 
     314        return true; 
     315    } 
     316 
     317    function chdir($pathname) { 
     318        if(!$this->_exec("CWD ".$pathname, "chdir")) return FALSE; 
     319        if(!$this->_checkCode()) return FALSE; 
     320        return TRUE; 
     321    } 
     322 
     323    function rmdir($pathname) { 
     324        if(!$this->_exec("RMD ".$pathname, "rmdir")) return FALSE; 
     325        if(!$this->_checkCode()) return FALSE; 
     326        return TRUE; 
     327    } 
     328 
     329    function mkdir($pathname) { 
     330        if(!$this->_exec("MKD ".$pathname, "mkdir")) return FALSE; 
     331        if(!$this->_checkCode()) return FALSE; 
     332        return TRUE; 
     333    } 
     334 
     335    function rename($from, $to) { 
     336        if(!$this->_exec("RNFR ".$from, "rename")) return FALSE; 
     337        if(!$this->_checkCode()) return FALSE; 
     338        if($this->_code==350) { 
     339            if(!$this->_exec("RNTO ".$to, "rename")) return FALSE; 
     340            if(!$this->_checkCode()) return FALSE; 
     341        } else return FALSE; 
     342        return TRUE; 
     343    } 
     344 
     345    function filesize($pathname) { 
     346        if(!isset($this->_features["SIZE"])) { 
     347            $this->PushError("filesize", "not supported by server"); 
     348            return FALSE; 
     349        } 
     350        if(!$this->_exec("SIZE ".$pathname, "filesize")) return FALSE; 
     351        if(!$this->_checkCode()) return FALSE; 
     352        return ereg_replace("^[0-9]{3} ([0-9]+)".CRLF, "\\1", $this->_message); 
     353    } 
     354 
     355    function abort() { 
     356        if(!$this->_exec("ABOR", "abort")) return FALSE; 
     357        if(!$this->_checkCode()) { 
     358            if($this->_code!=426) return FALSE; 
     359            if(!$this->_readmsg("abort")) return FALSE; 
     360            if(!$this->_checkCode()) return FALSE; 
     361        } 
     362        return true; 
     363    } 
     364 
     365    function mdtm($pathname) { 
     366        if(!isset($this->_features["MDTM"])) { 
     367            $this->PushError("mdtm", "not supported by server"); 
     368            return FALSE; 
     369        } 
     370        if(!$this->_exec("MDTM ".$pathname, "mdtm")) return FALSE; 
     371        if(!$this->_checkCode()) return FALSE; 
     372        $mdtm = ereg_replace("^[0-9]{3} ([0-9]+)".CRLF, "\\1", $this->_message); 
     373        $date = sscanf($mdtm, "%4d%2d%2d%2d%2d%2d"); 
     374        $timestamp = mktime($date[3], $date[4], $date[5], $date[1], $date[2], $date[0]); 
     375        return $timestamp; 
     376    } 
     377 
     378    function systype() { 
     379        if(!$this->_exec("SYST", "systype")) return FALSE; 
     380        if(!$this->_checkCode()) return FALSE; 
     381        $DATA = explode(" ", $this->_message); 
     382        return array($DATA[1], $DATA[3]); 
     383    } 
     384 
     385    function delete($pathname) { 
     386        if(!$this->_exec("DELE ".$pathname, "delete")) return FALSE; 
     387        if(!$this->_checkCode()) return FALSE; 
     388        return TRUE; 
     389    } 
     390 
     391    function site($command, $fnction="site") { 
     392        if(!$this->_exec("SITE ".$command, $fnction)) return FALSE; 
     393        if(!$this->_checkCode()) return FALSE; 
     394        return TRUE; 
     395    } 
     396 
     397    function chmod($pathname, $mode) { 
     398        if(!$this->site( sprintf('CHMOD %o %s', $mode, $pathname), "chmod")) return FALSE; 
     399        return TRUE; 
     400    } 
     401 
     402    function restore($from) { 
     403        if(!isset($this->_features["REST"])) { 
     404            $this->PushError("restore", "not supported by server"); 
     405            return FALSE; 
     406        } 
     407        if($this->_curtype!=FTP_BINARY) { 
     408            $this->PushError("restore", "can't restore in ASCII mode"); 
     409            return FALSE; 
     410        } 
     411        if(!$this->_exec("REST ".$from, "resore")) return FALSE; 
     412        if(!$this->_checkCode()) return FALSE; 
     413        return TRUE; 
     414    } 
     415 
     416    function features() { 
     417        if(!$this->_exec("FEAT", "features")) return FALSE; 
     418        if(!$this->_checkCode()) return FALSE; 
     419        $f=preg_split("/[".CRLF."]+/", preg_replace("/[0-9]{3}[ -].*[".CRLF."]+/", "", $this->_message), -1, PREG_SPLIT_NO_EMPTY); 
     420        $this->_features=array(); 
     421        foreach($f as $k=>$v) { 
     422            $v=explode(" ", trim($v)); 
     423            $this->_features[array_shift($v)]=$v;; 
     424        } 
     425        return true; 
     426    } 
     427 
     428    function rawlist($pathname="", $arg="") { 
     429        return $this->_list(($arg?" ".$arg:"").($pathname?" ".$pathname:""), "LIST", "rawlist"); 
     430    } 
     431 
     432    function nlist($pathname="") { 
     433        return $this->_list(($arg?" ".$arg:"").($pathname?" ".$pathname:""), "NLST", "nlist"); 
     434    } 
     435 
     436    function is_exists($pathname) { 
     437        return $this->file_exists($pathname); 
     438    } 
     439 
     440    function file_exists($pathname) { 
     441        $exists=true; 
     442        if(!$this->_exec("RNFR ".$pathname, "rename")) $exists=FALSE; 
     443        else { 
     444            if(!$this->_checkCode()) $exists=FALSE; 
     445            $this->abort(); 
     446        } 
     447        if($exists) $this->SendMSG("Remote file ".$pathname." exists"); 
     448        else $this->SendMSG("Remote file ".$pathname." does not exist"); 
     449        return $exists; 
     450    } 
     451 
     452    function fget($fp, $remotefile,$rest=0) { 
     453        if($this->_can_restore and $rest!=0) fseek($fp, $rest); 
     454        $pi=pathinfo($remotefile); 
     455        if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII; 
     456        else $mode=FTP_BINARY; 
     457        if(!$this->_data_prepare($mode)) { 
     458            return FALSE; 
     459        } 
     460        if($this->_can_restore and $rest!=0) $this->restore($rest); 
     461        if(!$this->_exec("RETR ".$remotefile, "get")) { 
     462            $this->_data_close(); 
     463            return FALSE; 
     464        } 
     465        if(!$this->_checkCode()) { 
     466            $this->_data_close(); 
     467            return FALSE; 
     468        } 
     469        $out=$this->_data_read($mode, $fp); 
     470        $this->_data_close(); 
     471        if(!$this->_readmsg()) return FALSE; 
     472        if(!$this->_checkCode()) return FALSE; 
     473        return $out; 
     474    } 
     475 
     476    function get($remotefile, $localfile=NULL, $rest=0) { 
     477        if(is_null($localfile)) $localfile=$remotefile; 
     478        if (@file_exists($localfile)) $this->SendMSG("Warning : local file will be overwritten"); 
     479        $fp = @fopen($localfile, "w"); 
     480        if (!$fp) { 
     481            $this->PushError("get","can't open local file", "Cannot create \"".$localfile."\""); 
     482            return FALSE; 
     483        } 
     484        if($this->_can_restore and $rest!=0) fseek($fp, $rest); 
     485        $pi=pathinfo($remotefile); 
     486        if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII; 
     487        else $mode=FTP_BINARY; 
     488        if(!$this->_data_prepare($mode)) { 
     489            fclose($fp); 
     490            return FALSE; 
     491        } 
     492        if($this->_can_restore and $rest!=0) $this->restore($rest); 
     493        if(!$this->_exec("RETR ".$remotefile, "get")) { 
     494            $this->_data_close(); 
     495            fclose($fp); 
     496            return FALSE; 
     497        } 
     498        if(!$this->_checkCode()) { 
     499            $this->_data_close(); 
     500            fclose($fp); 
     501            return FALSE; 
     502        } 
     503        $out=$this->_data_read($mode, $fp); 
     504        fclose($fp); 
     505        $this->_data_close(); 
     506        if(!$this->_readmsg()) return FALSE; 
     507        if(!$this->_checkCode()) return FALSE; 
     508        return $out; 
     509    } 
     510 
     511    function fput($remotefile, $fp) { 
     512        if($this->_can_restore and $rest!=0) fseek($fp, $rest); 
     513        $pi=pathinfo($remotefile); 
     514        if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII; 
     515        else $mode=FTP_BINARY; 
     516        if(!$this->_data_prepare($mode)) { 
     517            return FALSE; 
     518        } 
     519        if($this->_can_restore and $rest!=0) $this->restore($rest); 
     520        if(!$this->_exec("STOR ".$remotefile, "put")) { 
     521            $this->_data_close(); 
     522            return FALSE; 
     523        } 
     524        if(!$this->_checkCode()) { 
     525            $this->_data_close(); 
     526            return FALSE; 
     527        } 
     528        $ret=$this->_data_write($mode, $fp); 
     529        $this->_data_close(); 
     530        if(!$this->_readmsg()) return FALSE; 
     531        if(!$this->_checkCode()) return FALSE; 
     532        return $ret; 
     533    } 
     534 
     535    function put($localfile, $remotefile=NULL, $rest=0) { 
     536        if(is_null($remotefile)) $remotefile=$localfile; 
     537        if (!file_exists($localfile)) { 
     538            $this->PushError("put","can't open local file", "No such file or directory \"".$localfile."\""); 
     539            return FALSE; 
     540        } 
     541        $fp = @fopen($localfile, "r"); 
     542 
     543        if (!$fp) { 
     544            $this->PushError("put","can't open local file", "Cannot read file \"".$localfile."\""); 
     545            return FALSE; 
     546        } 
     547        if($this->_can_restore and $rest!=0) fseek($fp, $rest); 
     548        $pi=pathinfo($localfile); 
     549        if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII; 
     550        else $mode=FTP_BINARY; 
     551        if(!$this->_data_prepare($mode)) { 
     552            fclose($fp); 
     553            return FALSE; 
     554        } 
     555        if($this->_can_restore and $rest!=0) $this->restore($rest); 
     556        if(!$this->_exec("STOR ".$remotefile, "put")) { 
     557            $this->_data_close(); 
     558            fclose($fp); 
     559            return FALSE; 
     560        } 
     561        if(!$this->_checkCode()) { 
     562            $this->_data_close(); 
     563            fclose($fp); 
     564            return FALSE; 
     565        } 
     566        $ret=$this->_data_write($mode, $fp); 
     567        fclose($fp); 
     568        $this->_data_close(); 
     569        if(!$this->_readmsg()) return FALSE; 
     570        if(!$this->_checkCode()) return FALSE; 
     571        return $ret; 
     572    } 
     573 
     574    function mput($local=".", $remote=NULL, $continious=false) { 
     575        $local=realpath($local); 
     576        if(!@file_exists($local)) { 
     577            $this->PushError("mput","can't open local folder", "Cannot stat folder \"".$local."\""); 
     578            return FALSE; 
     579        } 
     580        if(!is_dir($local)) return $this->put($local, $remote); 
     581        if(empty($remote)) $remote="."; 
     582        elseif(!$this->file_exists($remote) and !$this->mkdir($remote)) return FALSE; 
     583        if($handle = opendir($local)) { 
     584            $list=array(); 
     585            while (false !== ($file = readdir($handle))) { 
     586                if ($file != "." && $file != "..") $list[]=$file; 
     587            } 
     588            closedir($handle); 
     589        } else { 
     590            $this->PushError("mput","can't open local folder", "Cannot read folder \"".$local."\""); 
     591            return FALSE; 
     592        } 
     593        if(empty($list)) return TRUE; 
     594        $ret=true; 
     595        foreach($list as $el) { 
     596            if(is_dir($local."/".$el)) $t=$this->mput($local."/".$el, $remote."/".$el); 
     597            else $t=$this->put($local."/".$el, $remote."/".$el); 
     598            if(!$t) { 
     599                $ret=FALSE; 
     600                if(!$continious) break; 
     601            } 
     602        } 
     603        return $ret; 
    31604         
    32         var $error_no = NULL; 
    33         var $error_msg = NULL; 
    34          
    35         function FTP() { 
    36         } 
    37  
    38         function connect($host, $port=21, $timeout=FTP_TIMEOUT) { //Opens an FTP connection 
    39             $this->_resetError(); 
    40  
    41             $err_no = 0; 
    42             $err_msg = ""; 
    43             $this->controlSocket = @fsockopen($host, $port, $err_no, $err_msg, $timeout) or $this->_setError(-1,"fsockopen failed");  
    44             if ($err_no<>0) $this->setError($err_no,$err_msg); 
    45  
    46             if ($this->_isError()) return false; 
    47              
    48             @socket_set_timeout($this->controlSocket,$timeout) or $this->_setError(-1,"socket_set_timeout failed"); 
    49             if ($this->_isError()) return false; 
    50              
    51             $this->_waitForResult(); 
    52             if ($this->_isError()) return false; 
    53              
    54             return $this->getLastResult() == FTP_SERVICE_READY; 
    55         } 
    56          
    57         function isConnected() { 
    58             return $this->controlSocket != NULL; 
    59         } 
    60          
    61         function disconnect() { 
    62             if (!$this->isConnected()) return; 
    63             @fclose($this->controlSocket); 
    64         } 
    65  
    66         function close() { //Closes an FTP connection 
    67             $this->disconnect(); 
    68         } 
    69          
    70         function login($user, $pass) {  //Logs in to an FTP connection 
    71             $this->_resetError(); 
    72  
    73             $this->_printCommand("USER $user"); 
    74             if ($this->_isError()) return false; 
    75  
    76             $this->_waitForResult(); 
    77             if ($this->_isError()) return false; 
    78  
    79             if ($this->getLastResult() == FTP_PASSWORD_NEEDED){ 
    80                 $this->_printCommand("PASS $pass"); 
    81                 if ($this->_isError()) return FALSE; 
    82  
    83                 $this->_waitForResult(); 
    84                 if ($this->_isError()) return FALSE; 
    85             } 
    86              
    87             $result = $this->getLastResult() == FTP_USER_LOGGED_IN; 
    88             return $result; 
    89         } 
    90  
    91         function cdup() { //Changes to the parent directory 
    92             $this->_resetError(); 
    93  
    94             $this->_printCommand("CDUP"); 
    95             $this->_waitForResult(); 
    96             $lr = $this->getLastResult(); 
    97             if ($this->_isError()) return FALSE; 
    98             return ($lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK); 
    99         } 
    100          
    101         function cwd($path) { 
    102             $this->_resetError(); 
    103  
    104             $this->_printCommand("CWD $path"); 
    105             $this->_waitForResult(); 
    106             $lr = $this->getLastResult(); 
    107             if ($this->_isError()) return FALSE; 
    108             return ($lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK); 
    109         } 
    110  
    111         function cd($path) { 
    112             return $this->cwd($path); 
    113         } 
    114  
    115         function chdir($path) { //Changes directories on a FTP server 
    116             return $this->cwd($path); 
    117         } 
    118  
    119         function chmod($mode,$filename) { //Set permissions on a file via FTP 
    120             return $this->site("CHMOD $mode $filename"); 
    121         } 
    122  
    123         function delete($filename) { //Deletes a file on the FTP server 
    124             $this->_resetError(); 
    125  
    126             $this->_printCommand("DELE $filename"); 
    127             $this->_waitForResult(); 
    128             $lr = $this->getLastResult(); 
    129             if ($this->_isError()) return FALSE; 
    130             return ($lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK); 
    131         } 
    132  
    133         function exec($cmd) { //Requests execution of a program on the FTP server 
    134             return $this->site("EXEC $cmd"); 
    135         } 
    136  
    137         function fget($fp,$remote,$mode=FTP_BINARY,$resumepos=0) { //Downloads a file from the FTP server and saves to an open file 
    138             $this->_resetError(); 
    139              
    140             $type = "I"; 
    141             if ($mode==FTP_ASCII) $type = "A"; 
    142              
    143             $this->_printCommand("TYPE $type"); 
    144             $this->_waitForResult(); 
    145             $lr = $this->getLastResult(); 
    146             if ($this->_isError()) return FALSE; 
    147              
    148             $result = $this->_download("RETR $remote"); 
    149             if ($result) { 
    150                 fwrite($fp,$result); 
    151             } 
    152             return $result; 
    153         } 
    154  
    155         function fput($remote,$resource,$mode=FTP_BINARY,$startpos=0) { //Uploads from an open file to the FTP server 
    156             $this->_resetError(); 
    157              
    158             $type = "I"; 
    159             if ($mode==FTP_ASCII) $type = "A"; 
    160              
    161             $this->_printCommand("TYPE $type"); 
    162             $this->_waitForResult(); 
    163             $lr = $this->getLastResult(); 
    164             if ($this->_isError()) return FALSE; 
    165              
    166             if ($startpos>0) fseek($resource,$startpos); 
    167             $result = $this->_uploadResource("STOR $remote",$resource); 
    168             return $result; 
    169         } 
    170  
    171         function get_option($option) { //Retrieves various runtime behaviours of the current FTP stream 
    172             $this->_resetError(); 
    173  
    174             switch ($option) { 
    175                 case "FTP_TIMEOUT_SEC" : return FTP_TIMEOUT; 
    176                 case "PHP_FTP_OPT_AUTOSEEK" : return FALSE; 
    177             } 
    178             setError(-1,"Unknown option: $option"); 
     605    } 
     606 
     607    function mget($remote, $local=".", $continious=false) { 
     608        $list=$this->rawlist($remote, "-lA"); 
     609        if($list===false) { 
     610            $this->PushError("mget","can't read remote folder list", "Can't read remote folder \"".$remote."\" contents"); 
     611            return FALSE; 
     612        } 
     613        if(empty($list)) return true; 
     614        if(!@file_exists($local)) { 
     615            if(!@mkdir($local)) { 
     616                $this->PushError("mget","can't create local folder", "Cannot create folder \"".$local."\""); 
     617                return FALSE; 
     618            } 
     619        } 
     620        foreach($list as $k=>$v) { 
     621            $list[$k]=$this->parselisting($v); 
     622            if($list[$k]["name"]=="." or $list[$k]["name"]=="..") unset($list[$k]); 
     623        } 
     624        $ret=true; 
     625        foreach($list as $el) { 
     626            if($el["type"]=="d") { 
     627                if(!$this->mget($remote."/".$el["name"], $local."/".$el["name"], $continious)) { 
     628                    $this->PushError("mget", "can't copy folder", "Can't copy remote folder \"".$remote."/".$el["name"]."\" to local \"".$local."/".$el["name"]."\""); 
     629                    $ret=false; 
     630                    if(!$continious) break; 
     631                } 
     632            } else { 
     633                if(!$this->get($remote."/".$el["name"], $local."/".$el["name"])) { 
     634                    $this->PushError("mget", "can't copy file", "Can't copy remote file \"".$remote."/".$el["name"]."\" to local \"".$local."/".$el["name"]."\""); 
     635                    $ret=false; 
     636                    if(!$continious) break; 
     637                } 
     638            } 
     639            @chmod($local."/".$el["name"], $el["perms"]); 
     640            $t=strtotime($el["date"]); 
     641            if($t!==-1 and $t!==false) @touch($local."/".$el["name"], $t); 
     642        } 
     643        return $ret; 
     644    } 
     645 
     646    function mdel($remote, $continious=false) { 
     647        $list=$this->rawlist($remote, "-la"); 
     648        if($list===false) { 
     649            $this->PushError("mdel","can't read remote folder list", "Can't read remote folder \"".$remote."\" contents"); 
    179650            return false; 
    180651        } 
    181  
    182         function get($locale,$remote,$mode=FTP_BINARY,$resumepos=0) { //Downloads a file from the FTP server 
    183             if (!($fp = @fopen($locale,"wb"))) return FALSE; 
    184             $result = $this->fget($fp,$remote,$mode,$resumepos); 
    185             @fclose($fp); 
    186             if (!$result) @unlink($locale); 
    187             return $result; 
    188         } 
    189         function mdtm($name) { //Returns the last modified time of the given file 
    190             $this->_resetError(); 
    191  
    192             $this->_printCommand("MDTM $name"); 
    193             $this->_waitForResult(); 
    194             $lr = $this->getLastResult(); 
    195             if ($this->_isError()) return FALSE; 
    196             if ($lr!=FTP_FILE_STATUS) return FALSE; 
    197             $subject = trim(substr($this->lastLine,4)); 
    198             $lucifer = array(); 
    199             if (preg_match("/([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])/",$subject,$lucifer)) 
    200                 return mktime($lucifer[4],$lucifer[5],$lucifer[6],$lucifer[2],$lucifer[3],$lucifer[1],0); 
    201             return FALSE; 
    202         } 
    203  
    204         function mkdir($name) { //Creates a directory 
    205             $this->_resetError(); 
    206  
    207             $this->_printCommand("MKD $name"); 
    208             $this->_waitForResult(); 
    209             $lr = $this->getLastResult(); 
    210             if ($this->_isError()) return FALSE; 
    211             return ($lr==FTP_PATHNAME || $lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK); 
    212         } 
    213  
    214         function nb_continue() { //Continues retrieving/sending a file (non-blocking) 
    215             $this->_resetError(); 
    216             // todo 
    217         } 
    218  
    219         function nb_fget() { //Retrieves a file from the FTP server and writes it to an open file (non-blocking) 
    220             $this->_resetError(); 
    221             // todo 
    222         } 
    223  
    224         function nb_fput() { //Stores a file from an open file to the FTP server (non-blocking) 
    225             $this->_resetError(); 
    226             // todo 
    227         } 
    228  
    229         function nb_get() { //Retrieves a file from the FTP server and writes it to a local file (non-blocking) 
    230             $this->_resetError(); 
    231             // todo 
    232         } 
    233  
    234         function nb_put() { //Stores a file on the FTP server (non-blocking) 
    235             $this->_resetError(); 
    236             // todo 
    237         } 
    238  
    239         function nlist($remote_filespec="") { //Returns a list of files in the given directory 
    240             $this->_resetError(); 
    241             $result = $this->_download(trim("NLST $remote_filespec")); 
    242             return ($result !== FALSE) ? explode("\n",str_replace("\r","",trim($result))) : $result; 
    243         } 
    244          
    245         function pasv($pasv) { //Turns passive mode on or off 
    246             if (!$pasv) { 
    247                 $this->_setError("Active (PORT) mode is not supported"); 
    248                 return false; 
    249             } 
    250             return true; 
    251         } 
    252  
    253         function put($remote,$local,$mode=FTP_BINARY,$startpos=0) { //Uploads a file to the FTP server 
    254             if (!($fp = @fopen($local,"rb"))) return FALSE; 
    255             $result = $this->fput($remote,$fp,$mode,$startpos); 
    256             @fclose($fp); 
    257             return $result; 
    258         } 
    259  
    260         function pwd() { //Returns the current directory name 
    261             $this->_resetError(); 
    262  
    263             $this->_printCommand("PWD"); 
    264             $this->_waitForResult(); 
    265             $lr = $this->getLastResult(); 
    266             if ($this->_isError()) return FALSE; 
    267             if ($lr!=FTP_PATHNAME) return FALSE; 
    268             $subject = trim(substr($this->lastLine,4)); 
    269             $lucifer = array(); 
    270             if (preg_match("/\"(.*)\"/",$subject,$lucifer)) return $lucifer[1]; 
    271             return FALSE; 
    272         } 
    273  
    274         function quit() { //Alias of close 
    275             $this->close(); 
    276         } 
    277  
    278         function raw($cmd) { //Sends an arbitrary command to an FTP server 
    279             $this->_resetError(); 
    280  
    281             $this->_printCommand($cmd); 
    282             $this->_waitForResult(); 
    283             $this->getLastResult(); 
    284             return array($this->lastLine); 
    285         } 
    286  
    287         function rawlist($remote_filespec="") { //Returns a detailed list of files in the given directory 
    288             $this->_resetError(); 
    289             $result = $this->_download(trim("LIST $remote_filespec")); 
    290             return ($result !== FALSE) ? explode("\n",str_replace("\r","",trim($result))) : $result; 
    291         } 
    292          
    293         function ls($remote_filespec="") { //Returns a parsed rawlist in an assoc array 
    294             $a = $this->rawlist($remote_filespec); 
    295             if (!$a) return $a; 
    296             $systype = $this->systype(); 
    297             $is_windows = stristr($systype,"WIN")!==FALSE; 
    298             $b = array(); 
    299             while (list($i,$line) = each($a)) { 
    300                 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)) { 
    301                     $b[$i] = array(); 
    302                     if ($lucifer[3]<70) { $lucifer[3]+=2000; } else { $lucifer[3]+=1900; } // 4digit year fix 
    303                     $b[$i]['isdir'] = ($lucifer[7]=="<DIR>"); 
    304                     $b[$i]['size'] = $lucifer[7]; 
    305                     $b[$i]['month'] = $lucifer[1]; 
    306                     $b[$i]['day'] = $lucifer[2]; 
    307                     $b[$i]['year'] = $lucifer[3]; 
    308                     $b[$i]['hour'] = $lucifer[4]; 
    309                     $b[$i]['minute'] = $lucifer[5]; 
    310                     $b[$i]['time'] = @mktime($lucifer[4]+(strcasecmp($lucifer[6],"PM")==0?12:0),$lucifer[5],0,$lucifer[1],$lucifer[2],$lucifer[3]); 
    311                     $b[$i]['am/pm'] = $lucifer[6]; 
    312                     $b[$i]['name'] = $lucifer[8]; 
    313                 } else if (!$is_windows && $lucifer=preg_split("/[ ]/",$line,9,PREG_SPLIT_NO_EMPTY)) { 
    314                     echo $line."\n"; 
    315                     $lcount=count($lucifer); 
    316                     if ($lcount<8) continue; 
    317                     $b[$i] = array(); 
    318                     $b[$i]['isdir'] = $lucifer[0]{0} === "d"; 
    319                     $b[$i]['islink'] = $lucifer[0]{0} === "l"; 
    320                     $b[$i]['perms'] = $lucifer[0]; 
    321                     $b[$i]['number'] = $lucifer[1]; 
    322                     $b[$i]['owner'] = $lucifer[2]; 
    323                     $b[$i]['group'] = $lucifer[3]; 
    324                     $b[$i]['size'] = $lucifer[4]; 
    325                     if ($lcount==8) { 
    326                         sscanf($lucifer[5],"%d-%d-%d",$b[$i]['year'],$b[$i]['month'],$b[$i]['day']); 
    327                         sscanf($lucifer[6],"%d:%d",$b[$i]['hour'],$b[$i]['minute']); 
    328                         $b[$i]['time'] = @mktime($b[$i]['hour'],$b[$i]['minute'],0,$b[$i]['month'],$b[$i]['day'],$b[$i]['year']); 
    329                         $b[$i]['name'] = $lucifer[7]; 
    330                     } else { 
    331                         $b[$i]['month'] = $lucifer[5]; 
    332                         $b[$i]['day'] = $lucifer[6]; 
    333                         if (preg_match("/([0-9]{2}):([0-9]{2})/",$lucifer[7],$l2)) { 
    334                             $b[$i]['year'] = date("Y"); 
    335                             $b[$i]['hour'] = $l2[1]; 
    336                             $b[$i]['minute'] = $l2[2]; 
    337                         } else { 
    338                             $b[$i]['year'] = $lucifer[7]; 
    339                             $b[$i]['hour'] = 0; 
    340                             $b[$i]['minute'] = 0; 
    341                         } 
    342                         $b[$i]['time'] = strtotime(sprintf("%d %s %d %02d:%02d",$b[$i]['day'],$b[$i]['month'],$b[$i]['year'],$b[$i]['hour'],$b[$i]['minute'])); 
    343                         $b[$i]['name'] = $lucifer[8]; 
    344                     } 
     652     
     653        foreach($list as $k=>$v) { 
     654            $list[$k]=$this->parselisting($v); 
     655            if($list[$k]["name"]=="." or $list[$k]["name"]=="..") unset($list[$k]); 
     656        } 
     657        $ret=true; 
     658     
     659        foreach($list as $el) { 
     660            if ( empty($el) ) 
     661                continue; 
     662 
     663            if($el["type"]=="d") { 
     664                if(!$this->mdel($remote."/".$el["name"], $continious)) { 
     665        &n