Xataface 2.0
Xataface Application Framework
install/ftp.class.php
Go to the documentation of this file.
00001 <?php
00002 
00003         define("FTP_TIMEOUT",90);
00004 
00005         // FTP Statuscodes
00006         define("FTP_COMMAND_OK",200);
00007         define("FTP_FILE_ACTION_OK",250);
00008         define("FTP_FILE_TRANSFER_OK",226);
00009         define("FTP_COMMAND_NOT_IMPLEMENTED",502);
00010         define("FTP_FILE_STATUS",213);
00011         define("FTP_NAME_SYSTEM_TYPE",215);
00012         define("FTP_PASSIVE_MODE",227);
00013         define("FTP_PATHNAME",257);
00014         define("FTP_SERVICE_READY",220);
00015         define("FTP_USER_LOGGED_IN",230);
00016         define("FTP_PASSWORD_NEEDED",331);
00017         define("FTP_USER_NOT_LOGGED_IN",530);
00018         
00019         if (!defined("FTP_ASCII")) define("FTP_ASCII",0);
00020         if (!defined("FTP_BINARY")) define("FTP_BINARY",1);
00021 
00022         class FTP {
00023 
00024                 var $passiveMode = TRUE;
00025                 var $lastLines = array();
00026                 var $lastLine = "";
00027                 var $controlSocket = NULL;
00028                 var $newResult = FALSE;
00029                 var $lastResult = -1;
00030                 var $pasvAddr = NULL; 
00031                 
00032                 var $error_no = NULL;
00033                 var $error_msg = NULL;
00034                 
00035                 function FTP() {
00036                 }
00037 
00038                 function connect($host, $port=21, $timeout=FTP_TIMEOUT) { //Opens an FTP connection
00039                         $this->_resetError();
00040 
00041                         $err_no = 0;
00042                         $err_msg = "";
00043                         $this->controlSocket = @fsockopen($host, $port, $err_no, $err_msg, $timeout) or $this->_setError(-1,"fsockopen failed"); 
00044                         if ($err_no<>0) $this->setError($err_no,$err_msg);
00045 
00046                         if ($this->_isError()) return false;
00047                         
00048                         @socket_set_timeout($this->controlSocket,$timeout) or $this->_setError(-1,"socket_set_timeout failed");
00049                         if ($this->_isError()) return false;
00050                         
00051                         $this->_waitForResult();
00052                         if ($this->_isError()) return false;
00053                         
00054                         return $this->getLastResult() == FTP_SERVICE_READY;
00055                 }
00056                 
00057                 function isConnected() {
00058                         return $this->controlSocket != NULL;
00059                 }
00060                 
00061                 function disconnect() {
00062                         if (!$this->isConnected()) return;
00063                         @fclose($this->controlSocket);
00064                 }
00065 
00066                 function close() { //Closes an FTP connection
00067                         $this->disconnect();
00068                 }
00069                 
00070                 function login($user, $pass) {  //Logs in to an FTP connection
00071                         $this->_resetError();
00072 
00073                         $this->_printCommand("USER $user");
00074                         if ($this->_isError()) return false;
00075 
00076                         $this->_waitForResult();
00077                         if ($this->_isError()) return false;
00078 
00079                         if ($this->getLastResult() == FTP_PASSWORD_NEEDED){
00080                                 $this->_printCommand("PASS $pass");
00081                                 if ($this->_isError()) return FALSE;
00082 
00083                                 $this->_waitForResult();
00084                                 if ($this->_isError()) return FALSE;
00085                         }
00086                         
00087                         $result = $this->getLastResult() == FTP_USER_LOGGED_IN;
00088                         return $result;
00089                 }
00090 
00091                 function cdup() { //Changes to the parent directory
00092                         $this->_resetError();
00093 
00094                         $this->_printCommand("CDUP");
00095                         $this->_waitForResult();
00096                         $lr = $this->getLastResult();
00097                         if ($this->_isError()) return FALSE;
00098                         return ($lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK);
00099                 }
00100                 
00101                 function cwd($path) {
00102                         $this->_resetError();
00103 
00104                         $this->_printCommand("CWD $path");
00105                         $this->_waitForResult();
00106                         $lr = $this->getLastResult();
00107                         if ($this->_isError()) return FALSE;
00108                         return ($lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK);
00109                 }
00110 
00111                 function cd($path) {
00112                         return $this->cwd($path);
00113                 }
00114 
00115                 function chdir($path) { //Changes directories on a FTP server
00116                         return $this->cwd($path);
00117                 }
00118 
00119                 function chmod($mode,$filename) { //Set permissions on a file via FTP
00120                         return $this->site("CHMOD $mode $filename");
00121                 }
00122 
00123                 function delete($filename) { //Deletes a file on the FTP server
00124                         $this->_resetError();
00125 
00126                         $this->_printCommand("DELE $filename");
00127                         $this->_waitForResult();
00128                         $lr = $this->getLastResult();
00129                         if ($this->_isError()) return FALSE;
00130                         return ($lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK);
00131                 }
00132 
00133                 function exec($cmd) { //Requests execution of a program on the FTP server
00134                         return $this->site("EXEC $cmd");
00135                 }
00136 
00137                 function fget($fp,$remote,$mode=FTP_BINARY,$resumepos=0) { //Downloads a file from the FTP server and saves to an open file
00138                         $this->_resetError();
00139                         
00140                         $type = "I";
00141                         if ($mode==FTP_ASCII) $type = "A";
00142                         
00143                         $this->_printCommand("TYPE $type");
00144                         $this->_waitForResult();
00145                         $lr = $this->getLastResult();
00146                         if ($this->_isError()) return FALSE;
00147                         
00148                         $result = $this->_download("RETR $remote");
00149                         if ($result) {
00150                                 fwrite($fp,$result);
00151                         }
00152                         return $result;
00153                 }
00154 
00155                 function fput($remote,$resource,$mode=FTP_BINARY,$startpos=0) { //Uploads from an open file to the FTP server
00156                         $this->_resetError();
00157                         
00158                         $type = "I";
00159                         if ($mode==FTP_ASCII) $type = "A";
00160                         
00161                         $this->_printCommand("TYPE $type");
00162                         $this->_waitForResult();
00163                         $lr = $this->getLastResult();
00164                         if ($this->_isError()) return FALSE;
00165                         
00166                         if ($startpos>0) fseek($resource,$startpos);
00167                         $result = $this->_uploadResource("STOR $remote",$resource);
00168                         return $result;
00169                 }
00170 
00171                 function get_option($option) { //Retrieves various runtime behaviours of the current FTP stream
00172                         $this->_resetError();
00173 
00174                         switch ($option) {
00175                                 case "FTP_TIMEOUT_SEC" : return FTP_TIMEOUT;
00176                                 case "PHP_FTP_OPT_AUTOSEEK" : return FALSE;
00177                         }
00178                         setError(-1,"Unknown option: $option");
00179                         return false;
00180                 }
00181 
00182                 function get($locale,$remote,$mode=FTP_BINARY,$resumepos=0) { //Downloads a file from the FTP server
00183                         if (!($fp = @fopen($locale,"wb"))) return FALSE;
00184                         $result = $this->fget($fp,$remote,$mode,$resumepos);
00185                         @fclose($fp);
00186                         if (!$result) @unlink($locale);
00187                         return $result;
00188                 }
00189                 function mdtm($name) { //Returns the last modified time of the given file
00190                         $this->_resetError();
00191 
00192                         $this->_printCommand("MDTM $name");
00193                         $this->_waitForResult();
00194                         $lr = $this->getLastResult();
00195                         if ($this->_isError()) return FALSE;
00196                         if ($lr!=FTP_FILE_STATUS) return FALSE;
00197                         $subject = trim(substr($this->lastLine,4));
00198                         $lucifer = array();
00199                         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)) return mktime($lucifer[4],$lucifer[5],$lucifer[6],$lucifer[2],$lucifer[3],$lucifer[1],0);
00200                         return FALSE;
00201                 }
00202 
00203                 function mkdir($name) { //Creates a directory
00204                         $this->_resetError();
00205 
00206                         $this->_printCommand("MKD $name");
00207                         $this->_waitForResult();
00208                         $lr = $this->getLastResult();
00209                         if ($this->_isError()) return FALSE;
00210                         return ($lr==FTP_PATHNAME || $lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK);
00211                 }
00212 
00213                 function nb_continue() { //Continues retrieving/sending a file (non-blocking)
00214                         $this->_resetError();
00215                         // todo
00216                 }
00217 
00218                 function nb_fget() { //Retrieves a file from the FTP server and writes it to an open file (non-blocking)
00219                         $this->_resetError();
00220                         // todo
00221                 }
00222 
00223                 function nb_fput() { //Stores a file from an open file to the FTP server (non-blocking)
00224                         $this->_resetError();
00225                         // todo
00226                 }
00227 
00228                 function nb_get() { //Retrieves a file from the FTP server and writes it to a local file (non-blocking)
00229                         $this->_resetError();
00230                         // todo
00231                 }
00232 
00233                 function nb_put() { //Stores a file on the FTP server (non-blocking)
00234                         $this->_resetError();
00235                         // todo
00236                 }
00237 
00238                 function nlist($remote_filespec="") { //Returns a list of files in the given directory
00239                         $this->_resetError();
00240                         $result = $this->_download(trim("NLST $remote_filespec"));
00241                         return ($result !== FALSE) ? explode("\n",str_replace("\r","",trim($result))) : $result;
00242                 }
00243                 
00244                 function pasv($pasv) { //Turns passive mode on or off
00245                         if (!$pasv) {
00246                                 $this->_setError("Active (PORT) mode is not supported");
00247                                 return false;
00248                         }
00249                         return true;
00250                 }
00251 
00252                 function put($remote,$local,$mode=FTP_BINARY,$startpos=0) { //Uploads a file to the FTP server
00253                         if (!($fp = @fopen($local,"rb"))) return FALSE;
00254                         $result = $this->fput($remote,$fp,$mode,$startpos);
00255                         @fclose($fp);
00256                         return $result;
00257                 }
00258 
00259                 function pwd() { //Returns the current directory name
00260                         $this->_resetError();
00261 
00262                         $this->_printCommand("PWD");
00263                         $this->_waitForResult();
00264                         $lr = $this->getLastResult();
00265                         if ($this->_isError()) return FALSE;
00266                         if ($lr!=FTP_PATHNAME) return FALSE;
00267                         $subject = trim(substr($this->lastLine,4));
00268                         $lucifer = array();
00269                         if (preg_match("/\"(.*)\"/",$subject,$lucifer)) return $lucifer[1];
00270                         return FALSE;
00271                 }
00272 
00273                 function quit() { //Alias of close
00274                         $this->close();
00275                 }
00276 
00277                 function raw($cmd) { //Sends an arbitrary command to an FTP server
00278                         $this->_resetError();
00279 
00280                         $this->_printCommand($cmd);
00281                         $this->_waitForResult();
00282                         $this->getLastResult();
00283                         return array($this->lastLine);
00284                 }
00285 
00286                 function rawlist($remote_filespec="") { //Returns a detailed list of files in the given directory
00287                         $this->_resetError();
00288                         $result = $this->_download(trim("LIST $remote_filespec"));
00289                         return ($result !== FALSE) ? explode("\n",str_replace("\r","",trim($result))) : $result;
00290                 }
00291                 
00292                 function ls($remote_filespec="") { //Returns a parsed rawlist in an assoc array
00293                         $a = $this->rawlist($remote_filespec);
00294                         if (!$a) return $a;
00295                         $systype = $this->systype();
00296                         $is_windows = stristr($systype,"WIN")!==FALSE;
00297                         $b = array();
00298                         while (list($i,$line) = each($a)) {
00299                                 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)) {
00300                                         $b[$i] = array();
00301                                         if ($lucifer[3]<70) { $lucifer[3]+=2000; } else { $lucifer[3]+=1900; } // 4digit year fix
00302                                         $b[$i]['isdir'] = ($lucifer[7]=="<DIR>");
00303                                         $b[$i]['size'] = $lucifer[7];
00304                                         $b[$i]['month'] = $lucifer[1];
00305                                         $b[$i]['day'] = $lucifer[2];
00306                                         $b[$i]['year'] = $lucifer[3];
00307                                         $b[$i]['hour'] = $lucifer[4];
00308                                         $b[$i]['minute'] = $lucifer[5];
00309                                         $b[$i]['time'] = @mktime($lucifer[4]+(strcasecmp($lucifer[6],"PM")==0?12:0),$lucifer[5],0,$lucifer[1],$lucifer[2],$lucifer[3]);
00310                                         $b[$i]['am/pm'] = $lucifer[6];
00311                                         $b[$i]['name'] = $lucifer[8];
00312                                 } else if (!$is_windows && $lucifer=preg_split("/[ ]/",$line,9,PREG_SPLIT_NO_EMPTY)) {
00313                                         echo $line."\n";
00314                                         $lcount=count($lucifer);
00315                                         if ($lcount<8) continue;
00316                                         $b[$i] = array();
00317                                         $b[$i]['isdir'] = $lucifer[0]{0} === "d";
00318                                         $b[$i]['islink'] = $lucifer[0]{0} === "l";
00319                                         $b[$i]['perms'] = $lucifer[0];
00320                                         $b[$i]['number'] = $lucifer[1];
00321                                         $b[$i]['owner'] = $lucifer[2];
00322                                         $b[$i]['group'] = $lucifer[3];
00323                                         $b[$i]['size'] = $lucifer[4];
00324                                         if ($lcount==8) {
00325                                                 sscanf($lucifer[5],"%d-%d-%d",$b[$i]['year'],$b[$i]['month'],$b[$i]['day']);
00326                                                 sscanf($lucifer[6],"%d:%d",$b[$i]['hour'],$b[$i]['minute']);
00327                                                 $b[$i]['time'] = @mktime($b[$i]['hour'],$b[$i]['minute'],0,$b[$i]['month'],$b[$i]['day'],$b[$i]['year']);
00328                                                 $b[$i]['name'] = $lucifer[7];
00329                                         } else {
00330                                                 $b[$i]['month'] = $lucifer[5];
00331                                                 $b[$i]['day'] = $lucifer[6];
00332                                                 if (preg_match("/([0-9]{2}):([0-9]{2})/",$lucifer[7],$l2)) {
00333                                                         $b[$i]['year'] = date("Y");
00334                                                         $b[$i]['hour'] = $l2[1];
00335                                                         $b[$i]['minute'] = $l2[2];
00336                                                 } else {
00337                                                         $b[$i]['year'] = $lucifer[7];
00338                                                         $b[$i]['hour'] = 0;
00339                                                         $b[$i]['minute'] = 0;
00340                                                 }
00341                                                 $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']));
00342                                                 $b[$i]['name'] = $lucifer[8];
00343                                         }
00344                                 }
00345                         }
00346                         return $b;
00347                 }
00348 
00349                 function rename($from,$to) { //Renames a file on the FTP server
00350                         $this->_resetError();
00351 
00352                         $this->_printCommand("RNFR $from");
00353                         $this->_waitForResult();
00354                         $lr = $this->getLastResult();
00355                         if ($this->_isError()) return FALSE;
00356                         $this->_printCommand("RNTO $to");
00357                         $this->_waitForResult();
00358                         $lr = $this->getLastResult();
00359                         if ($this->_isError()) return FALSE;
00360                         return ($lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK);
00361                 }
00362 
00363                 function rmdir($name) { //Removes a directory
00364                         $this->_resetError();
00365 
00366                         $this->_printCommand("RMD $name");
00367                         $this->_waitForResult();
00368                         $lr = $this->getLastResult();
00369                         if ($this->_isError()) return FALSE;
00370                         return ($lr==FTP_FILE_ACTION_OK || $lr==FTP_COMMAND_OK);
00371                 }
00372 
00373                 function set_option() { //Set miscellaneous runtime FTP options
00374                         $this->_resetError();
00375                         $this->_setError(-1,"set_option not supported");
00376                         return false;
00377                 }
00378 
00379                 function site($cmd) { //Sends a SITE command to the server
00380                         $this->_resetError();
00381 
00382                         $this->_printCommand("SITE $cmd");
00383                         $this->_waitForResult();
00384                         $lr = $this->getLastResult();
00385                         if ($this->_isError()) return FALSE;
00386                         return true;
00387                 }
00388 
00389                 function size($name) { //Returns the size of the given file
00390                         $this->_resetError();
00391 
00392                         $this->_printCommand("SIZE $name");
00393                         $this->_waitForResult();
00394                         $lr = $this->getLastResult();
00395                         if ($this->_isError()) return FALSE;
00396                         return $lr==FTP_FILE_STATUS ? trim(substr($this->lastLine,4)) : FALSE;
00397                 }
00398 
00399                 function ssl_connect() { //Opens an Secure SSL-FTP connection
00400                         $this->_resetError();
00401                         $this->_setError(-1,"ssl_connect not supported");
00402                         return false;
00403                 }
00404 
00405                 function systype() { // Returns the system type identifier of the remote FTP server
00406                         $this->_resetError();
00407 
00408                         $this->_printCommand("SYST");
00409                         $this->_waitForResult();
00410                         $lr = $this->getLastResult();
00411                         if ($this->_isError()) return FALSE;
00412                         return $lr==FTP_NAME_SYSTEM_TYPE ? trim(substr($this->lastLine,4)) : FALSE;
00413                 }
00414 
00415                 function getLastResult() {
00416                         $this->newResult = FALSE;
00417                         return $this->lastResult;
00418                 }
00419                 
00420                 /* private */
00421                 function _hasNewResult() {
00422                         return $this->newResult;
00423                 }
00424                 
00425                 /* private */
00426                 function _waitForResult() {
00427                         while(!$this->_hasNewResult() && $this->_readln()!==FALSE && !$this->_isError()) { /* noop  */ }
00428                 }
00429                 
00430                 /* private */
00431                 function _readln() {
00432                         $line = fgets($this->controlSocket);
00433                         if ($line === FALSE) {
00434                                 $this->_setError(-1,"fgets failed in _readln");
00435                                 return FALSE;
00436                         }
00437                         if (strlen($line)==0) return $line;
00438 
00439                         $lucifer = array();
00440                         if (preg_match("/^[0-9][0-9][0-9] /",$line,$lucifer)) {
00441                                 //its a resultline
00442                                 $this->lastResult = intval($lucifer[0]);
00443                                 $this->newResult = TRUE;
00444                                 if (substr($lucifer[0],0,1)=='5') {
00445                                         $this->_setError($this->lastResult,trim(substr($line,4)));
00446                                 }
00447                         }
00448         
00449                         $this->lastLine = trim($line);
00450                         $this->lastLines[] = "< ".trim($line);
00451                         return $line;
00452                 }
00453                 
00454                 /* private */
00455                 function _printCommand($line) {
00456                         $this->lastLines[] = "> ".$line;
00457                         fwrite($this->controlSocket,$line."\r\n");
00458                         fflush($this->controlSocket);
00459                 }
00460                 
00461                 /* private */
00462                 function _pasv() {
00463                         $this->_resetError();
00464                         $this->_printCommand("PASV");
00465                         $this->_waitForResult();
00466                         $lr = $this->getLastResult();
00467                         if ($this->_isError()) return FALSE;
00468                         if ($lr!=FTP_PASSIVE_MODE) return FALSE;
00469                         $subject = trim(substr($this->lastLine,4));
00470                         $lucifer = array();
00471                         if (preg_match("/\\((\d{1,3}),(\d{1,3}),(\d{1,3}),(\d{1,3}),(\d{1,3}),(\d{1,3})\\)/",$subject,$lucifer)) {
00472                                 $this->pasvAddr=$lucifer;
00473                                 
00474                                 $host = sprintf("%d.%d.%d.%d",$lucifer[1],$lucifer[2],$lucifer[3],$lucifer[4]);
00475                                 $port = $lucifer[5]*256 + $lucifer[6];
00476                                 
00477                                 $err_no=0;
00478                                 $err_msg="";
00479                                 $passiveConnection = fsockopen($host,$port,$err_no,$err_msg, FTP_TIMEOUT);
00480                                 if ($err_no!=0) {
00481                                         $this->_setError($err_no,$err_msg);
00482                                         return FALSE;
00483                                 }
00484 
00485                                 return $passiveConnection;
00486                         }
00487                         return FALSE;
00488                 }
00489                 
00490                 /* private */
00491                 function _download($cmd) {
00492                         if (!($passiveConnection = $this->_pasv())) return FALSE;
00493                         $this->_printCommand($cmd);
00494                         $this->_waitForResult();
00495                         $lr = $this->getLastResult();
00496                         if (!$this->_isError()) {
00497                                 $result = "";
00498                                 while (!feof($passiveConnection)) {
00499                                         $result .= fgets($passiveConnection);
00500                                 }
00501                                 fclose($passiveConnection);
00502                                 $this->_waitForResult();
00503                                 $lr = $this->getLastResult();
00504                                 return ($lr==FTP_FILE_TRANSFER_OK) || ($lr==FTP_FILE_ACTION_OK) || ($lr==FTP_COMMAND_OK) ? $result : FALSE;
00505                         } else {
00506                                 fclose($passiveConnection);
00507                                 return FALSE;
00508                         }
00509                 }
00510 
00511                 /* upload */
00512                 function _uploadResource($cmd,$resource) {
00513                         if (!($passiveConnection = $this->_pasv())) return FALSE;
00514                         $this->_printCommand($cmd);
00515                         $this->_waitForResult();
00516                         $lr = $this->getLastResult();
00517                         if (!$this->_isError()) {
00518                                 $result = "";
00519                                 while (!feof($resource)) {
00520                                         $buf = fread($resource,1024);
00521                                         fwrite($passiveConnection,$buf);
00522                                 }
00523                                 fclose($passiveConnection);
00524                                 $this->_waitForResult();
00525                                 $lr = $this->getLastResult();
00526                                 return ($lr==FTP_FILE_TRANSFER_OK) || ($lr==FTP_FILE_ACTION_OK) || ($lr==FTP_COMMAND_OK) ? $result : FALSE;
00527                         } else {
00528                                 fclose($passiveConnection);
00529                                 return FALSE;
00530                         }
00531                 }
00532                 
00533                 /* private */
00534                 function _resetError() {
00535                         $this->error_no = NULL;
00536                         $this->error_msg = NULL;
00537                 }
00538 
00539                 /* private */
00540                 function _setError($no,$msg) {
00541                         if (is_array($this->error_no)) {
00542                                 $this->error_no[] = $no;
00543                                 $this->error_msg[] = $msg;
00544                         } else if ($this->error_no!=NULL) {
00545                                 $this->error_no = array($this->error_no,$no);
00546                                 $this->error_msg = array($this->error_msg,$msg);
00547                         } else {
00548                                 $this->error_no = $no;
00549                                 $this->error_msg = $msg;
00550                         }
00551                 }
00552                 
00553                 /* private */
00554                 function _isError() {
00555                         return ($this->error_no != NULL) && ($this->error_no !== 0);
00556                 }
00557 
00558         }
00559 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations