package.xml0000664000175000017500000002533312500046241012563 0ustar kguestkguest Net_FTP pear.php.net Net_FTP provides an OO interface to the PHP FTP functions plus some additions Net_FTP allows you to communicate with FTP servers in a more comfortable way than the native FTP functions of PHP do. The class implements everything natively supported by PHP and additionally features like recursive up- and downloading, dircreation and chmodding. It also implements an observer pattern to allow for example the view of a progress bar. Jorrit Schippers jorrit jschippers@php.net yes Tobias Schlitt toby toby@php.net no 2015-03-11 1.4.0 1.4.0 stable stable BSD License * Feature Request 20317: Switch to BSD License. * Fixed Bug 20096: Package doesn't install because of conflict. * Fixed Bug 20088: Missing file config.php. * Validate return of _lsFiles() and _lsDirs() during _rmDirRecursive(). * Handle failed ls() command during chmodRecursive(). * $_file_extensions is prepped with invalid data. 4.3.0 1.3.0 ftp 1.3.0 1.0.0 stable stable 2005-03-31 PHP License - Updated year. - Updated docblocks regarding the new standard. - Fixed whitespace issues. - Fixed bug 3362: bug in Net_FTP::_rm_file. - Added PEAR 1.4 compatible package2.xml (package.xml version 2.0). 1.3.1 1.0.0 stable stable 2005-04-07 PHP License * Fix bug #3778 "Notice of Uninitialized string offset in function _rm_dir_recursive" * Fix bug #4008 "_list_and_parse tries to determine OS on an empty list" * Fix bug #4009 "_determine_os_match doesn't take into account numbered users and groups" 1.3.2 1.0.0 stable stable 2006-02-11 PHP License * Fixed Bug #4102: Problem detecting os method ls(). * Fixed Bug #5337: _list_and_parse behavior with an empty remote directory. * Fixed Bug #4836: Off-by-one error in regex for Windows directory listings. * Fixed Bug #4749: ls() fails when connection is closed. * Fixed Bug #4969: Recursive rm ends in endless loop. * Fixed Bug #5895: Recursive chmod ends in endless loop. 1.3.3 1.0.0 stable stable 2007-12-06 PHP License * Fixed Bug #7146: Recursive mkdir() broken on Windows * Fixed Bug #7270: Recursive rmdir() broken * Fixed Bug #7527: ls fails if there are no files and a total line * Fixed Bug #8102: Loading file extension and checking extension gives binary for ascii files * Fixed Bug #9611: (, ? and ) break detection of the unix platform * Fixed Bug #10237: put() doesn't run ftp_alloc to allocate space * PEAR Coding Style Valid * Removed package.xml version 1.0 * Added some unit tests 1.3.4 1.0.0 stable stable 2007-12-10 PHP License * Fixed Bug #12639: _constructPath() prevents _checkDir() from working correctly 1.4.0a1 1.4.0 alpha stable 2007-12-23 PHP License * Fixed bug #6754: Add method to set directory list matcher explicitly * Fixed Bug #7102: Add ability to disable use of ftp_nb_put(), can sometimes be very slow * Improved detection of remote directories. It is slower than before, but does not rely on simply detecting if the given path ends with a slash. 1.4.0a2 1.4.0 alpha stable 2008-05-19 PHP License * Fixed Bug #13496: set bit not supported * Fixed Bug #13689: . in file owner or group name breaks _ls_match * Fixed Bug #13690: getRecursive does not work because of '.' and '..' directories * Fixed Bug #13114: Error check in $FTP->getRecursive(...) * Implemented Request #13104: connect() <> $this->handle in login() * Fixed Bug #13917: putRecursive always return PEAR::Error * Fixed Bug #13850: inclusion of Net/FTP.php in tests doesn't always work * Implemented Request #2271: New flag for _rm_dir_recursive to leave directory structure intact * Implemented Request #6806: Allow recursive up-/download with only adding newer files 1.4.0a3 1.4.0 alpha stable 2011-12-11 PHP License * Fixed Bug #13946: Test Failed : testPutRecursive * Fixed Bug #14513: Timestamp when using the LS function * Implemented Request #14773: setPassive possible before connecting * Use markTestSkipped, not fail() * Fatal error: Cannot redeclare ftp_connect() in ./Net_FTP/Net/FTP/Socket.php * remove error_reporting (for PEAR QA team) 1.4.0 1.4.0 stable stable 2015-03-11 BSD License * Feature Request 20317: Switch to BSD License. * Fixed Bug 20096: Package doesn't install because of conflict. * Validate return of _lsFiles() and _lsDirs() during _rmDirRecursive(). * Handle failed ls() command during chmodRecursive(). * $_file_extensions is prepped with invalid data. Net_FTP-1.4.0/example/extensions.ini0000664000175000017500000000221312500046241016666 0ustar kguestkguest; This file can determine file-extension and wether to transfer them in ; binary- or ascii-mode. The two different values for file-modes are: ; ; FTP_ASCII (which equals 0) ; FTP_BINARY (which equals 1) ; ; This file will be directly parsed by parse_ini_file(), so beware of making mistakes ; inside this file, or your application may crash, everytime you parse your file. ; ; You can have more than 1 file containing extension-settings, for different kinds of ; application, server or case. But beware, if you've parsed a file into your Net_FTP-object, ; and after that you parse another file, the old settings will be overwriten! ; ; ASCII-Extensions: [ASCII] asc = 0 ascx = 0 asp = 0 aspx = 0 bas = 0 bash = 0 bat = 0 c = 0 cfc = 0 cfm = 0 cgi = 0 class = 0 conf = 0 css = 0 h = 0 hhc = 0 hhk = 0 hpp = 0 hta = 0 htm = 0 html = 0 inc = 0 nfo = 0 ini = 0 inf = 0 jav = 0 java = 0 js = 0 jsp = 0 log = 0 nfo = 0 pas = 0 php = 0 php3 = 0 php4 = 0 phtml = 0 pl = 0 svg = 0 sh = 0 shtml = 0 tcl = 0 text = 0 txt = 0 vb = 0 vbs = 0 wml = 0 xhtm = 0 xhtml = 0 xml = 0 xsd = 0 xsl = 0 xsl = 0 xslt = 0 xul = 0 ; BINARY-Extensions [BINARY] jpg = 1 gif = 1 bmp = 1Net_FTP-1.4.0/example/index.php0000664000175000017500000001244212500046241015613 0ustar kguestkguest * @copyright 1997-2005 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version CVS: $Id$ * @link http://pear.php.net/package/Net_FTP * @since File available since Release 0.0.1 */ require_once 'Net/FTP.php'; require_once 'Var_Dump.php'; /** * Setting up test variables. The following variables have to be set * up, to suite the needs of your environment. */ $host = ''; $port = 21; $user = ''; $pass = ''; // The local base directory for FTP operations. $baseDir = './test/'; // The directory to upload to the FTP server for testing. $testUpDir = 'test_up/'; // The directory to download to for testing. $testDownDir = 'test_down/'; // The file for single file up- and download testing. $singleTestFile = 'test.zip'; // Initializing Var_Var_Dump::display if (isset($_SERVER)) { // Setup for displaying XHTML output. Var_Dump::displayInit(array( 'display_mode'=>'XHTML_Text' ), array( 'mode'=>'normal', 'offset'=>4 )); /** * Headline function for XHTML output * * @param string $text Text to put in header * * @return void */ function head($text) { echo '
'.$text.'
'; } } else { // Setup for displaying console output. Var_Dump::displayInit(array('display_mode'=>'Text')); /** * Headline function for XHTML output * * @param string $text Text to put in header * * @return void */ function head($text) { echo "\n--- ".$text." ---\n"; } } head("\$ftp = new Net_FTP();"); $ftp = new Net_FTP(); head("\$ftp->setHostname($host)"); Var_Dump::display($ftp->setHostname($host)); head("\$ftp->setPort($port)"); Var_Dump::display($ftp->setPort($port)); head("\$ftp->connect($host, $port)"); Var_Dump::display($ftp->connect()); head("\$ftp->setUsername($user)"); Var_Dump::display($ftp->setUsername($user)); head("\$ftp->setPassword(xxx)"); Var_Dump::display($ftp->setPassword($pass)); head("\$ftp->login($user, xxx)"); Var_Dump::display($ftp->login($user, $pass)); head("\$ftp->pwd()"); Var_Dump::display($ftp->pwd()); head("\$ftp->ls(null, NET_FTP_DIRS_FILES)"); Var_Dump::display($ftp->ls(null, NET_FTP_DIRS_FILES)); head("\$ftp->mkdir($baseDir)"); Var_Dump::display($ftp->mkdir($baseDir)); head("\$ftp->cd($baseDir)"); Var_Dump::display($ftp->cd($baseDir)); head("\$ftp->ls(null, NET_FTP_RAWLIST)"); Var_Dump::display($ftp->ls(null, NET_FTP_RAWLIST)); head("\$ftp->put($baseDir$singleTestFile, $singleTestFile)"); Var_Dump::display($ftp->put($baseDir.$singleTestFile, $singleTestFile)); head("\$ftp->ls(null, NET_FTP_FILES_ONLY)"); Var_Dump::display($ftp->ls(null, NET_FTP_FILES_ONLY)); head("\$ftp->put($baseDir$singleTestFile, $singleTestFile, true)"); Var_Dump::display($ftp->put($baseDir.$singleTestFile, $singleTestFile, true)); head("\$ftp->ls(null, NET_FTP_FILES_ONLY)"); Var_Dump::display($ftp->ls(null, NET_FTP_FILES_ONLY)); head("\$ftp->mdtm($singleTestFile, 'd.m.Y H:i:s')"); Var_Dump::display($ftp->mdtm($singleTestFile, 'd.m.Y')); head("\$ftp->size($singleTestFile)"); Var_Dump::display($ftp->size($singleTestFile)); head("\$ftp->get($singleTestFile, $baseDir$singleTestFile, true)"); Var_Dump::display($ftp->get($singleTestFile, $baseDir.$singleTestFile, true)); head("\$ftp->chmod($singleTestFile, 700)"); Var_Dump::display($ftp->chmod($singleTestFile, 700)); head("\$ftp->ls(null, NET_FTP_FILES_ONLY)"); Var_Dump::display($ftp->ls(null, NET_FTP_FILES_ONLY)); head("\$ftp->cd('../')"); Var_Dump::display($ftp->cd('../')); head("\$ftp->chmodRecursive($baseDir, 777)"); Var_Dump::display($ftp->chmodRecursive($baseDir, 777)); head("\$ftp->ls(null, NET_FTP_DIRS_ONLY)"); Var_Dump::display($ftp->ls(null, NET_FTP_DIRS_ONLY)); head("\$ftp->putRecursive($baseDir$testUpDir, $baseDir$testUpDir)"); Var_Dump::display($ftp->putRecursive($baseDir.$testUpDir, $baseDir.$testUpDir)); head("\$ftp->putRecursive($baseDir$testUpDir, $baseDir$testUpDir)"); Var_Dump::display($ftp->putRecursive($baseDir.$testUpDir, $baseDir.$testUpDir, true)); head("\$ftp->cd($baseDir:$testUpDir)"); Var_Dump::display($ftp->cd($baseDir.$testUpDir)); head("\$ftp->ls(null, NET_FTP_DIRS_FILES)"); Var_Dump::display($ftp->ls(null, NET_FTP_DIRS_FILES)); head("\$ftp->cd(../../)"); Var_Dump::display($ftp->cd('../../')); head("\$ftp->getRecursive($baseDir$testUpDir, $baseDir$testDownDir)"); Var_Dump::display($ftp->getRecursive($baseDir.$testUpDir, $baseDir.$testDownDir, true)); head("\$ftp->rm($baseDir, true)"); Var_Dump::display($ftp->rm($baseDir, true)); head("\$ftp->ls(null, NET_FTP_DIRS_ONLY)"); Var_Dump::display($ftp->ls(null, NET_FTP_DIRS_ONLY)); head("\$ftp->disconnect()"); Var_Dump::display($ftp->disconnect()); ?> Net_FTP-1.4.0/example/observer.php0000664000175000017500000001363412500046241016337 0ustar kguestkguest= PHP 4.3.0) * * PHP versions 4 and 5 * * LICENSE: This source file is subject to version 3.0 of the PHP license * that is available through the world-wide-web at the following URI: * http://www.php.net/license/3_0.txt. If you did not receive a copy of * the PHP License and are unable to obtain it through the web, please * send a note to license@php.net so we can mail you a copy immediately. * * @category Networking * @package FTP * @author Tobias Schlitt * @author Laurent Laville * @copyright 1997-2005 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version CVS: $Id$ * @link http://pear.php.net/package/Net_FTP * @link http://pear.php.net/package/HTML_Progress * @since File available since Release 1.3.0 */ require_once 'Net/FTP.php'; require_once 'Net/FTP/Observer.php'; require_once 'HTML/Progress.php'; /** * Initializing test variables (required!) */ $ftp = array( 'host' => '', 'port' => 21, 'user' => '', 'pass' => '' ); $dest = 'tmp'; // this directory must exists in your ftp server ! $overwrite = true; // overwrite all existing files on the ftp server $files = array( 'HTML_Progress-1.2.0.tgz', 'php4ever.png' // initializing contents (required!) file(s) must ); // exists file(s) to upload /** * 1. Defines the FTP/Progress Observer * * @category Networking * @package FTP * @author Tobias Schlitt * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version Release: 1.4.0 * @link http://pear.php.net/package/Net_FTP * @since 0.0.1 * @access public */ class Observer_ProgressUpload extends Net_FTP_Observer { var $progress; /** * Constructor for the upload observer * * @param HTML_Progress &$progress Progress bar * * @return void */ function Observer_ProgressUpload(&$progress) { /* Call the base class constructor. */ parent::Net_FTP_Observer(); /** Configure the observer: Be sure to have an indeterminate progress meter when @link http://www.php.net/manual/en/function.ftp-nb-put.php stores a file on the FTP server (non-blocking) */ $this->progress =& $progress; $this->progress->setIndeterminate(true); } /** * Notification method * * @param mixed $event Variable describing occured event * * @return void */ function notify($event) { $this->progress->display(); $this->progress->sleep(); if ($this->progress->getPercentComplete() == 1) { $this->progress->setValue(0); } else { $this->progress->incValue(); } } } // // 2. defines the progress meter // $meter = new HTML_Progress(); $ui = &$meter->getUI(); $ui->setProgressAttributes(array( 'background-color' => '#e0e0e0' )); $ui->setStringAttributes(array( 'color' => '#996', 'background-color' => '#CCCC99' )); $ui->setCellAttributes(array( 'active-color' => '#996' )); $meter->setAnimSpeed(200); $meter->setIncrement(10); $meter->setStringPainted(true); // get space for the string $meter->setString(""); // but don't paint it $meter->setIndeterminate(true); // progress meter start in indeterminate mode ?> FTP/Progress Observer example toHtml(); @set_time_limit(0); // unlimited time operation (removed 30s default restriction) $f = new Net_FTP(); // // 3. connect to the FTP server // $ret = $f->connect($ftp['host'], $ftp['port']); if (PEAR::isError($ret)) { die($ret->getMessage()); } printf('connected at %s
', $ftp['host']); // // 4. login to the FTP server as a well-known user // $ret = $f->login($ftp['user'], $ftp['pass']); if (PEAR::isError($ret)) { $f->disconnect(); die($ret->getMessage()); } printf('login as %s
', $ftp['user']); // // 5. changes directory to final destination for upload operation // $ret = $f->cd($dest); if (PEAR::isError($ret)) { $f->disconnect(); die($ret->getMessage()); } // // 6. attachs an instance of the FTP/Progress subclass observer // $observer = new Observer_ProgressUpload($meter); $ok = $f->attach($observer); if (!$ok) { die('cannot attach a FTP Observer'); } // // 7. moves files on the FTP server // foreach ($files as $file) { $ret = $f->put($file, basename($file), $overwrite); if (PEAR::isError($ret)) { if ($ret->getCode() == NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN && !$overwrite) { printf('%s
', $ret->getMessage()); continue; // it is just a warning when \$overwrite variable is false } die($ret->getMessage()); } printf('%s transfer completed
', basename($file)); } $f->detach($observer); // // 8. checks if files are really on the FTP server // $ret = $f->ls(null, NET_FTP_RAWLIST); if (PEAR::isError($ret)) { $f->disconnect(); die($ret->getMessage()); } print '
';
var_dump($ret);
print '
'; // // 9. says goodbye to the FTP server ! // $f->disconnect(); echo 'Done!'; ?> Net_FTP-1.4.0/example/socket.php0000664000175000017500000000617712500046241016004 0ustar kguestkguest

 * @copyright 1997-2005 The PHP Group
 * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/Net_FTP
 * @since     File available since Release 1.3.0
 */

if (isset($_GET['native'])) {
    @dl('ftp.so');
}

// Configuration

// Login info
$host = 'localhost';
$user = 'pub';
$pass = 'public';

// Passive mode on/off
$pasv = false;

// List directory
$dir = 'episodes/';

// Upload files
$Uasci   = basename($_SERVER['PHP_SELF']);
$Ubinary = 'screenshot.jpg';

// End of configuration

$time = microtime(true);

/**
 * Function used by the test suit.
 * Spits out test results in readable way
 *
 * @param mixed $action action
 * @param mixed $result result
 * @param mixed $msg    message
 *
 * @return false
 */
function dump($action, $result, $msg = false)
{
    if (is_bool($result)) {
        $result = $result ? 'TRUE' : 'FALSE';
    }

    if (is_array($result)) {
        echo '' .$action. ':' ."\n";
        foreach ($result as $key => $value) {
            echo ' ' .$key. ': ' .$value. "\n";
        }
    } else {
        echo '' .$action. ':' ."\n";
        echo $result;
        if ($msg) {
            echo ' ( ' .$msg. ' )';
        }
        echo "\n";
    }

    echo '
';// . "\n"; flush(); } /** * Little test suit */ $stream = ftp_connect($host); if (is_resource($stream)) { dump('Logging in', $bool = ftp_login($stream, $user, $pass)); if ($bool) { dump('PWD', ftp_pwd($stream)); dump('Systype', ftp_systype($stream)); dump('CHDIR "'.$dir.'"', ftp_chdir($stream, $dir)); dump('PWD', ftp_pwd($stream)); dump('CDUP', ftp_cdup($stream)); dump('PASSIVE', ftp_pasv($stream, $pasv)); dump('RAWLIST "."', ftp_rawlist($stream, '.')); dump('CHMOD', ftp_chmod($stream, 0777, 'sfv3.php')); dump('ALLOCATE', ftp_alloc($stream, filesize($Ubinary), $msg), $msg); dump('UPLOAD ASCII', ftp_put($stream, $Uasci, $Uasci, FTP_ASCII), $Uasci); dump('UPLOAD BINARY', ftp_put($stream, $Ubinary, $Ubinary, FTP_BINARY), $Ubinary); dump('RAWLIST "."', ftp_rawlist($stream, '.')); dump('DELETE '.$Uasci, ftp_delete($stream, $Uasci)); dump('DELETE '.$Bbinary, ftp_delete($stream, $Ubinary)); dump('RAWLIST "."', ftp_rawlist($stream, '.')); } dump('QUIT', ftp_quit($stream)); } $end = microtime(true); echo $end-$time; ?>
Net_FTP-1.4.0/Net/FTP.php0000775000175000017500000025035312500046241014240 0ustar kguestkguest * @author Jorrit Schippers * @copyright 1997-2008 The PHP Group * @license BSD http://www.opensource.org/licenses/bsd-license.php * @version CVS: $Id$ * @link http://pear.php.net/package/Net_FTP * @since File available since Release 0.0.1 */ /** * Include PEAR.php to obtain the PEAR base class */ require_once 'PEAR.php'; /** * Option to let the ls() method return only files. * * @since 1.3 * @name NET_FTP_FILES_ONLY * @see Net_FTP::ls() */ define('NET_FTP_FILES_ONLY', 0, true); /** * Option to let the ls() method return only directories. * * @since 1.3 * @name NET_FTP_DIRS_ONLY * @see Net_FTP::ls() */ define('NET_FTP_DIRS_ONLY', 1, true); /** * Option to let the ls() method return directories and files (default). * * @since 1.3 * @name NET_FTP_DIRS_FILES * @see Net_FTP::ls() */ define('NET_FTP_DIRS_FILES', 2, true); /** * Option to let the ls() method return the raw directory listing from ftp_rawlist() * * @since 1.3 * @name NET_FTP_RAWLIST * @see Net_FTP::ls() */ define('NET_FTP_RAWLIST', 3, true); /** * Option to indicate that non-blocking features should not be used in * put(). This will also disable the listener functionality as a side effect. * * @since 1.4a1 * @name NET_FTP_BLOCKING * @see Net_FTP::put() */ define('NET_FTP_BLOCKING', 1, true); /** * Option to indicate that non-blocking features should be used if available in * put(). This will also enable the listener functionality. * * This is the default behaviour. * * @since 1.4a1 * @name NET_FTP_NONBLOCKING * @see Net_FTP::put() */ define('NET_FTP_NONBLOCKING', 2, true); /** * Error code to indicate a failed connection * This error code indicates, that the connection you tryed to set up * could not be established. Check your connection settings (host & port)! * * @since 1.3 * @name NET_FTP_ERR_CONNECT_FAILED * @see Net_FTP::connect() */ define('NET_FTP_ERR_CONNECT_FAILED', -1); /** * Error code to indicate a failed login * This error code indicates, that the login to the FTP server failed. Check * your user data (username & password). * * @since 1.3 * @name NET_FTP_ERR_LOGIN_FAILED * @see Net_FTP::login() */ define('NET_FTP_ERR_LOGIN_FAILED', -2); /** * Error code to indicate a failed directory change * The cd() method failed. Ensure that the directory you wanted to access exists. * * @since 1.3 * @name NET_FTP_ERR_DIRCHANGE_FAILED * @see Net_FTP::cd() */ define('NET_FTP_ERR_DIRCHANGE_FAILED', 2); // Compatibillity reasons! /** * Error code to indicate that Net_FTP could not determine the current path * The pwd() method failed and could not determine the path you currently reside * in on the FTP server. * * @since 1.3 * @name NET_FTP_ERR_DETERMINEPATH_FAILED * @see Net_FTP::pwd() */ define('NET_FTP_ERR_DETERMINEPATH_FAILED', 4); // Compatibillity reasons! /** * Error code to indicate that the creation of a directory failed * The directory you tryed to create could not be created. Check the * access rights on the parent directory! * * @since 1.3 * @name NET_FTP_ERR_CREATEDIR_FAILED * @see Net_FTP::mkdir() */ define('NET_FTP_ERR_CREATEDIR_FAILED', -4); /** * Error code to indicate that the EXEC execution failed. * The execution of a command using EXEC failed. Ensure, that your * FTP server supports the EXEC command. * * @since 1.3 * @name NET_FTP_ERR_EXEC_FAILED * @see Net_FTP::execute() */ define('NET_FTP_ERR_EXEC_FAILED', -5); /** * Error code to indicate that the SITE command failed. * The execution of a command using SITE failed. Ensure, that your * FTP server supports the SITE command. * * @since 1.3 * @name NET_FTP_ERR_SITE_FAILED * @see Net_FTP::site() */ define('NET_FTP_ERR_SITE_FAILED', -6); /** * Error code to indicate that the CHMOD command failed. * The execution of CHMOD failed. Ensure, that your * FTP server supports the CHMOD command and that you have the appropriate * access rights to use CHMOD. * * @since 1.3 * @name NET_FTP_ERR_CHMOD_FAILED * @see Net_FTP::chmod() */ define('NET_FTP_ERR_CHMOD_FAILED', -7); /** * Error code to indicate that a file rename failed * The renaming of a file on the server failed. Ensure that you have the * appropriate access rights to rename the file. * * @since 1.3 * @name NET_FTP_ERR_RENAME_FAILED * @see Net_FTP::rename() */ define('NET_FTP_ERR_RENAME_FAILED', -8); /** * Error code to indicate that the MDTM command failed * The MDTM command is not supported for directories. Ensure that you gave * a file path to the mdtm() method, not a directory path. * * @since 1.3 * @name NET_FTP_ERR_MDTMDIR_UNSUPPORTED * @see Net_FTP::mdtm() */ define('NET_FTP_ERR_MDTMDIR_UNSUPPORTED', -9); /** * Error code to indicate that the MDTM command failed * The MDTM command failed. Ensure that your server supports the MDTM command. * * @since 1.3 * @name NET_FTP_ERR_MDTM_FAILED * @see Net_FTP::mdtm() */ define('NET_FTP_ERR_MDTM_FAILED', -10); /** * Error code to indicate that a date returned by the server was misformated * A date string returned by your server seems to be missformated and could not be * parsed. Check that the server is configured correctly. If you're sure, please * send an email to the auhtor with a dumped output of * $ftp->ls('./', NET_FTP_RAWLIST); to get the date format supported. * * @since 1.3 * @name NET_FTP_ERR_DATEFORMAT_FAILED * @see Net_FTP::mdtm(), Net_FTP::ls() */ define('NET_FTP_ERR_DATEFORMAT_FAILED', -11); /** * Error code to indicate that the SIZE command failed * The determination of the filesize of a file failed. Ensure that your server * supports the SIZE command. * * @since 1.3 * @name NET_FTP_ERR_SIZE_FAILED * @see Net_FTP::size() */ define('NET_FTP_ERR_SIZE_FAILED', -12); /** * Error code to indicate that a local file could not be overwritten * You specified not to overwrite files. Therefore the local file has not been * overwriten. If you want to get the file overwriten, please set the option to * do so. * * @since 1.3 * @name NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN * @see Net_FTP::get(), Net_FTP::getRecursive() */ define('NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN', -13); /** * Error code to indicate that a local file could not be overwritten * Also you specified to overwrite the local file you want to download to, * it has not been possible to do so. Check that you have the appropriate access * rights on the local file to overwrite it. * * @since 1.3 * @name NET_FTP_ERR_OVERWRITELOCALFILE_FAILED * @see Net_FTP::get(), Net_FTP::getRecursive() */ define('NET_FTP_ERR_OVERWRITELOCALFILE_FAILED', -14); /** * Error code to indicate that the file you wanted to upload does not exist * The file you tried to upload does not exist. Ensure that it exists. * * @since 1.3 * @name NET_FTP_ERR_LOCALFILENOTEXIST * @see Net_FTP::put(), Net_FTP::putRecursive() */ define('NET_FTP_ERR_LOCALFILENOTEXIST', -15); /** * Error code to indicate that a remote file could not be overwritten * You specified not to overwrite files. Therefore the remote file has not been * overwriten. If you want to get the file overwriten, please set the option to * do so. * * @since 1.3 * @name NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN * @see Net_FTP::put(), Net_FTP::putRecursive() */ define('NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN', -16); /** * Error code to indicate that the upload of a file failed * The upload you tried failed. Ensure that you have appropriate access rights * to upload the desired file. * * @since 1.3 * @name NET_FTP_ERR_UPLOADFILE_FAILED * @see Net_FTP::put(), Net_FTP::putRecursive() */ define('NET_FTP_ERR_UPLOADFILE_FAILED', -17); /** * Error code to indicate that you specified an incorrect directory path * The remote path you specified seems not to be a directory. Ensure that * the path you specify is a directory and that the path string ends with * a /. * * @since 1.3 * @name NET_FTP_ERR_REMOTEPATHNODIR * @see Net_FTP::putRecursive(), Net_FTP::getRecursive() */ define('NET_FTP_ERR_REMOTEPATHNODIR', -18); /** * Error code to indicate that you specified an incorrect directory path * The local path you specified seems not to be a directory. Ensure that * the path you specify is a directory and that the path string ends with * a /. * * @since 1.3 * @name NET_FTP_ERR_LOCALPATHNODIR * @see Net_FTP::putRecursive(), Net_FTP::getRecursive() */ define('NET_FTP_ERR_LOCALPATHNODIR', -19); /** * Error code to indicate that a local directory failed to be created * You tried to create a local directory through getRecursive() method, * which has failed. Ensure that you have the appropriate access rights * to create it. * * @since 1.3 * @name NET_FTP_ERR_CREATELOCALDIR_FAILED * @see Net_FTP::getRecursive() */ define('NET_FTP_ERR_CREATELOCALDIR_FAILED', -20); /** * Error code to indicate that the provided hostname was incorrect * The hostname you provided was invalid. Ensure to provide either a * full qualified domain name or an IP address. * * @since 1.3 * @name NET_FTP_ERR_HOSTNAMENOSTRING * @see Net_FTP::setHostname() */ define('NET_FTP_ERR_HOSTNAMENOSTRING', -21); /** * Error code to indicate that the provided port was incorrect * The port number you provided was invalid. Ensure to provide either a * a numeric port number greater zero. * * @since 1.3 * @name NET_FTP_ERR_PORTLESSZERO * @see Net_FTP::setPort() */ define('NET_FTP_ERR_PORTLESSZERO', -22); /** * Error code to indicate that you provided an invalid mode constant * The mode constant you provided was invalid. You may only provide * FTP_ASCII or FTP_BINARY. * * @since 1.3 * @name NET_FTP_ERR_NOMODECONST * @see Net_FTP::setMode() */ define('NET_FTP_ERR_NOMODECONST', -23); /** * Error code to indicate that you provided an invalid timeout * The timeout you provided was invalid. You have to provide a timeout greater * or equal to zero. * * @since 1.3 * @name NET_FTP_ERR_TIMEOUTLESSZERO * @see Net_FTP::Net_FTP(), Net_FTP::setTimeout() */ define('NET_FTP_ERR_TIMEOUTLESSZERO', -24); /** * Error code to indicate that you provided an invalid timeout * An error occured while setting the timeout. Ensure that you provide a * valid integer for the timeount and that your PHP installation works * correctly. * * @since 1.3 * @name NET_FTP_ERR_SETTIMEOUT_FAILED * @see Net_FTP::Net_FTP(), Net_FTP::setTimeout() */ define('NET_FTP_ERR_SETTIMEOUT_FAILED', -25); /** * Error code to indicate that the provided extension file doesn't exist * The provided extension file does not exist. Ensure to provided an * existant extension file. * * @since 1.3 * @name NET_FTP_ERR_EXTFILENOTEXIST * @see Net_FTP::getExtensionsFile() */ define('NET_FTP_ERR_EXTFILENOTEXIST', -26); /** * Error code to indicate that the provided extension file is not readable * The provided extension file is not readable. Ensure to have sufficient * access rights for it. * * @since 1.3 * @name NET_FTP_ERR_EXTFILEREAD_FAILED * @see Net_FTP::getExtensionsFile() */ define('NET_FTP_ERR_EXTFILEREAD_FAILED', -27); /** * Error code to indicate that the deletion of a file failed * The specified file could not be deleted. Ensure to have sufficient * access rights to delete the file. * * @since 1.3 * @name NET_FTP_ERR_EXTFILEREAD_FAILED * @see Net_FTP::rm() */ define('NET_FTP_ERR_DELETEFILE_FAILED', -28); /** * Error code to indicate that the deletion of a directory faild * The specified file could not be deleted. Ensure to have sufficient * access rights to delete the file. * * @since 1.3 * @name NET_FTP_ERR_EXTFILEREAD_FAILED * @see Net_FTP::rm() */ define('NET_FTP_ERR_DELETEDIR_FAILED', -29); /** * Error code to indicate that the directory listing failed * PHP could not list the directory contents on the server. Ensure * that your server is configured appropriate. * * @since 1.3 * @name NET_FTP_ERR_RAWDIRLIST_FAILED * @see Net_FTP::ls() */ define('NET_FTP_ERR_RAWDIRLIST_FAILED', -30); /** * Error code to indicate that the directory listing failed * The directory listing format your server uses seems not to * be supported by Net_FTP. Please send the output of the * call ls('./', NET_FTP_RAWLIST); to the author of this * class to get it supported. * * @since 1.3 * @name NET_FTP_ERR_DIRLIST_UNSUPPORTED * @see Net_FTP::ls() */ define('NET_FTP_ERR_DIRLIST_UNSUPPORTED', -31); /** * Error code to indicate failed disconnecting * This error code indicates, that disconnection was not possible. * * @since 1.3 * @name NET_FTP_ERR_DISCONNECT_FAILED * @see Net_FTP::disconnect() */ define('NET_FTP_ERR_DISCONNECT_FAILED', -32); /** * Error code to indicate that the username you provided was invalid. * Check that you provided a non-empty string as the username. * * @since 1.3 * @name NET_FTP_ERR_USERNAMENOSTRING * @see Net_FTP::setUsername() */ define('NET_FTP_ERR_USERNAMENOSTRING', -33); /** * Error code to indicate that the username you provided was invalid. * Check that you provided a non-empty string as the username. * * @since 1.3 * @name NET_FTP_ERR_PASSWORDNOSTRING * @see Net_FTP::setPassword() */ define('NET_FTP_ERR_PASSWORDNOSTRING', -34); /** * Error code to indicate that the provided extension file is not loadable * The provided extension file is not loadable. Ensure to have a correct file * syntax. * * @since 1.3.3 * @name NET_FTP_ERR_EXTFILELOAD_FAILED * @see Net_FTP::getExtensionsFile() */ define('NET_FTP_ERR_EXTFILELOAD_FAILED', -35); /** * Error code to indicate that the directory listing pattern provided is not a * string. * * @since 1.4.0a1 * @name NET_FTP_ERR_ILLEGALPATTERN * @see Net_FTP::setDirMatcher() */ define('NET_FTP_ERR_ILLEGALPATTERN', -36); /** * Error code to indicate that the directory listing matcher map provided is not an * array. * * @since 1.4.0a1 * @name NET_FTP_ERR_ILLEGALMAP * @see Net_FTP::setDirMatcher() */ define('NET_FTP_ERR_ILLEGALMAP', -37); /** * Error code to indicate that the directory listing matcher map provided contains * wrong values (ie: it contains non-numerical values) * * @since 1.4.0a1 * @name NET_FTP_ERR_ILLEGALMAPVALUE * @see Net_FTP::setDirMatcher() */ define('NET_FTP_ERR_ILLEGALMAPVALUE', -38); /** * Error code indicating that bad options were supplied to the * put() method. * * @since 1.4a1 * @name NET_FTP_ERR_BADOPTIONS * @see Net_FTP::put() */ define('NET_FTP_ERR_BADOPTIONS', -39); /** * Error code indicating that SSL connection is not supported as either the * ftp module or OpenSSL support is not statically built into php. * * @since 1.4a2 * @name NET_FTP_ERR_NOSSL * @see Net_FTP::setSsl() */ define('NET_FTP_ERR_NOSSL', -40); /** * Class for comfortable FTP-communication * * This class provides comfortable communication with FTP-servers. You may do * everything enabled by the PHP-FTP-extension and further functionalities, like * recursive-deletion, -up- and -download. Another feature is to create directories * recursively. * * @category Networking * @package FTP * @author Tobias Schlitt * @author Jorrit Schippers * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version Release: 1.4.0 * @link http://pear.php.net/package/Net_FTP * @since 0.0.1 * @access public */ class Net_FTP extends PEAR { /** * The host to connect to * * @access private * @var string */ var $_hostname; /** * The port for ftp-connection (standard is 21) * * @access private * @var int */ var $_port = 21; /** * The username for login * * @access private * @var string */ var $_username; /** * The password for login * * @access private * @var string */ var $_password; /** * Determine whether to connect through secure SSL connection or not * * Is null when it hasn't been explicitly set * * @access private * @var bool */ var $_ssl; /** * Determine whether to use passive-mode (true) or active-mode (false) * * Is null when it hasn't been explicitly set * * @access private * @var bool */ var $_passv = null; /** * The standard mode for ftp-transfer * * @access private * @var int */ var $_mode = FTP_BINARY; /** * This holds the handle for the ftp-connection * * If null, the connection hasn't been setup yet. If false, the connection * attempt has failed. Else, it contains an ftp resource. * * @access private * @var resource */ var $_handle = null; /** * Contains the timeout for FTP operations * * @access private * @var int * @since 1.3 */ var $_timeout = 90; /** * Saves file-extensions for ascii- and binary-mode * * The array is built like this: 'php' => FTP_ASCII, 'png' => FTP_BINARY * * @access private * @var array */ var $_file_extensions = array(); /** * ls match * Matches the ls entries against a regex and maps the resulting array to * speaking names * * The values are set in the constructor because of line length constaints. * * Typical lines for the Windows format: * 07-05-07 08:40AM 4701 SomeFile.ext * 04-29-07 10:28PM SomeDir * * @access private * @var array * @since 1.3 */ var $_ls_match = null; /** * matcher * Stores the matcher for the current connection * * @access private * @var array * @since 1.3 */ var $_matcher = null; /** * Holds all Net_FTP_Observer objects * that wish to be notified of new messages. * * @var array * @access private * @since 1.3 */ var $_listeners = array(); /** * Is true when a login has been performed * and was successful * * @access private * @var boolean * @since 1.4 */ var $_loggedin = false; /** * This generates a new FTP-Object. The FTP-connection will not be established, * yet. * You can leave $host and $port blank, if you want. The $host will not be set * and the $port will be left at 21. You have to set the $host manualy before * trying to connect or with the connect() method. * * @param string $host (optional) The hostname * @param int $port (optional) The port * @param int $timeout (optional) Sets the standard timeout * * @access public * @return void * @see Net_FTP::setHostname(), Net_FTP::setPort(), Net_FTP::connect() */ function Net_FTP($host = null, $port = null, $timeout = 90) { $this->PEAR(); if (isset($host)) { $this->setHostname($host); } if (isset($port)) { $this->setPort($port); } $this->_timeout = $timeout; $this->_ls_match = array( 'unix' => array( 'pattern' => '/(?:(d)|.)([rwxts-]{9})\s+(\w+)\s+([\w\d-()?.]+)\s+'. '([\w\d-()?.]+)\s+(\w+)\s+(\S+\s+\S+\s+\S+)\s+(.+)/', 'map' => array( 'is_dir' => 1, 'rights' => 2, 'files_inside' => 3, 'user' => 4, 'group' => 5, 'size' => 6, 'date' => 7, 'name' => 8, ) ), 'windows' => array( 'pattern' => '/([0-9\-]+\s+[0-9:APM]+)\s+(()|\d+)\s+(.+)/', 'map' => array( 'date' => 1, 'size' => 2, 'is_dir' => 3, 'name' => 4, ) ) ); } /** * This function generates the FTP-connection. You can optionally define a * hostname and/or a port. If you do so, this data is stored inside the object. * * @param string $host (optional) The Hostname * @param int $port (optional) The Port * @param bool $ssl (optional) Whether to connect through secure SSL connection * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_CONNECT_FAILED */ function connect($host = null, $port = null, $ssl = null) { $this->_matcher = null; if (isset($host)) { $this->setHostname($host); } if (isset($port)) { $this->setPort($port); } if (isset($ssl) && is_bool($ssl) && $ssl) { $this->setSsl(); } if ($this->getSsl()) { $handle = @ftp_ssl_connect($this->getHostname(), $this->getPort(), $this->_timeout); } else { $handle = @ftp_connect($this->getHostname(), $this->getPort(), $this->_timeout); } if (!$handle) { $this->_handle = false; return $this->raiseError("Connection to host failed", NET_FTP_ERR_CONNECT_FAILED); } else { $this->_handle =& $handle; return true; } } /** * This function close the FTP-connection * * @access public * @return bool|PEAR_Error Returns true on success, PEAR_Error on failure */ function disconnect() { $res = @ftp_close($this->_handle); if (!$res) { return PEAR::raiseError('Disconnect failed.', NET_FTP_ERR_DISCONNECT_FAILED); } $this->_handle = null; return true; } /** * This logs you into the ftp-server. You are free to specify username and * password in this method. If you specify it, the values will be taken into * the corresponding attributes, if do not specify, the attributes are taken. * * If connect() has not been called yet, a connection will be setup * * @param string $username (optional) The username to use * @param string $password (optional) The password to use * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_LOGIN_FAILED */ function login($username = null, $password = null) { if ($this->_handle === null) { $res = $this->connect(); if (PEAR::isError($res)) { return $res; } } if (!isset($username)) { $username = $this->getUsername(); } else { $this->setUsername($username); } if (!isset($password)) { $password = $this->getPassword(); } else { $this->setPassword($password); } $res = @ftp_login($this->_handle, $username, $password); if (!$res) { return $this->raiseError("Unable to login", NET_FTP_ERR_LOGIN_FAILED); } else { $this->_loggedin = true; // distinguish between null and false, null means this setting wasn't // explicitly changed, so we only change it when setPassive or // setActive was called by the user if ($this->_passv === true) { $this->setPassive(); } elseif ($this->_passv === false) { $this->setActive(); } return true; } } /** * This changes the currently used directory. You can use either an absolute * directory-path (e.g. "/home/blah") or a relative one (e.g. "../test"). * * @param string $dir The directory to go to. * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_DIRCHANGE_FAILED */ function cd($dir) { $erg = @ftp_chdir($this->_handle, $dir); if (!$erg) { return $this->raiseError("Directory change failed", NET_FTP_ERR_DIRCHANGE_FAILED); } else { return true; } } /** * Show's you the actual path on the server * This function questions the ftp-handle for the actual selected path and * returns it. * * @access public * @return mixed The actual path or PEAR::Error * @see NET_FTP_ERR_DETERMINEPATH_FAILED */ function pwd() { $res = @ftp_pwd($this->_handle); if (!$res) { return $this->raiseError("Could not determine the actual path.", NET_FTP_ERR_DETERMINEPATH_FAILED); } else { return $res; } } /** * This works similar to the mkdir-command on your local machine. You can either * give it an absolute or relative path. The relative path will be completed * with the actual selected server-path. (see: pwd()) * * @param string $dir Absolute or relative dir-path * @param bool $recursive (optional) Create all needed directories * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_CREATEDIR_FAILED */ function mkdir($dir, $recursive = false) { $dir = $this->_constructPath($dir); $savedir = $this->pwd(); $this->pushErrorHandling(PEAR_ERROR_RETURN); $e = $this->cd($dir); $this->popErrorHandling(); if ($e === true) { $this->cd($savedir); return true; } $this->cd($savedir); if ($recursive === false) { $res = @ftp_mkdir($this->_handle, $dir); if (!$res) { return $this->raiseError("Creation of '$dir' failed", NET_FTP_ERR_CREATEDIR_FAILED); } else { return true; } } else { // do not look at the first character, as $dir is absolute, // it will always be a / if (strpos(substr($dir, 1), '/') === false) { return $this->mkdir($dir, false); } if (substr($dir, -1) == '/') { $dir = substr($dir, 0, -1); } $parent = substr($dir, 0, strrpos($dir, '/')); $res = $this->mkdir($parent, true); if ($res === true) { $res = $this->mkdir($dir, false); } if ($res !== true) { return $res; } return true; } } /** * This method tries executing a command on the ftp, using SITE EXEC. * * @param string $command The command to execute * * @access public * @return mixed The result of the command (if successfull), otherwise * PEAR::Error * @see NET_FTP_ERR_EXEC_FAILED */ function execute($command) { $res = @ftp_exec($this->_handle, $command); if (!$res) { return $this->raiseError("Execution of command '$command' failed.", NET_FTP_ERR_EXEC_FAILED); } else { return $res; } } /** * Execute a SITE command on the server * This method tries to execute a SITE command on the ftp server. * * @param string $command The command with parameters to execute * * @access public * @return mixed True if successful, otherwise PEAR::Error * @see NET_FTP_ERR_SITE_FAILED */ function site($command) { $res = @ftp_site($this->_handle, $command); if (!$res) { return $this->raiseError("Execution of SITE command '$command' failed.", NET_FTP_ERR_SITE_FAILED); } else { return $res; } } /** * This method will try to chmod the file specified on the server * Currently, you must give a number as the the permission argument (777 or * similar). The file can be either a relative or absolute path. * NOTE: Some servers do not support this feature. In that case, you will * get a PEAR error object returned. If successful, the method returns true * * @param mixed $target The file or array of files to set permissions for * @param integer $permissions The mode to set the file permissions to * * @access public * @return mixed True if successful, otherwise PEAR::Error * @see NET_FTP_ERR_CHMOD_FAILED */ function chmod($target, $permissions) { // If $target is an array: Loop through it. if (is_array($target)) { for ($i = 0; $i < count($target); $i++) { $res = $this->chmod($target[$i], $permissions); if (PEAR::isError($res)) { return $res; } // end if isError } // end for i < count($target) return true; } else { $res = $this->site("CHMOD " . $permissions . " " . $target); if (!$res) { return PEAR::raiseError("CHMOD " . $permissions . " " . $target . " failed", NET_FTP_ERR_CHMOD_FAILED); } else { return $res; } } // end if is_array } // end method chmod /** * This method will try to chmod a folder and all of its contents * on the server. The target argument must be a folder or an array of folders * and the permissions argument have to be an integer (i.e. 777). * The file can be either a relative or absolute path. * NOTE: Some servers do not support this feature. In that case, you * will get a PEAR error object returned. If successful, the method * returns true * * @param mixed $target The folder or array of folders to * set permissions for * @param integer $permissions The mode to set the folder * and file permissions to * * @access public * @return mixed True if successful, otherwise PEAR::Error * @see NET_FTP_ERR_CHMOD_FAILED, NET_FTP_ERR_DETERMINEPATH_FAILED, * NET_FTP_ERR_RAWDIRLIST_FAILED, NET_FTP_ERR_DIRLIST_UNSUPPORTED */ function chmodRecursive($target, $permissions) { static $dir_permissions; if (!isset($dir_permissions)) { // Making directory specific permissions $dir_permissions = $this->_makeDirPermissions($permissions); } // If $target is an array: Loop through it if (is_array($target)) { for ($i = 0; $i < count($target); $i++) { $res = $this->chmodRecursive($target[$i], $permissions); if (PEAR::isError($res)) { return $res; } // end if isError } // end for i < count($target) } else { $remote_path = $this->_constructPath($target); // Chmod the directory itself $result = $this->chmod($remote_path, $dir_permissions); if (PEAR::isError($result)) { return $result; } // If $remote_path last character is not a slash, add one if (substr($remote_path, strlen($remote_path)-1) != "/") { $remote_path .= "/"; } $dir_list = array(); $mode = NET_FTP_DIRS_ONLY; $dir_list = $this->ls($remote_path, $mode); foreach ($dir_list as $dir_entry) { if ($dir_entry['name'] == '.' || $dir_entry['name'] == '..') { continue; } $remote_path_new = $remote_path.$dir_entry["name"]."/"; // Chmod the directory we're about to enter $result = $this->chmod($remote_path_new, $dir_permissions); if (PEAR::isError($result)) { return $result; } $result = $this->chmodRecursive($remote_path_new, $permissions); if (PEAR::isError($result)) { return $result; } } // end foreach dir_list as dir_entry $file_list = array(); $mode = NET_FTP_FILES_ONLY; $file_list = $this->ls($remote_path, $mode); if (PEAR::isError($file_list)) { return $file_list; } foreach ($file_list as $file_entry) { $remote_file = $remote_path.$file_entry["name"]; $result = $this->chmod($remote_file, $permissions); if (PEAR::isError($result)) { return $result; } } // end foreach $file_list } // end if is_array return true; // No errors } // end method chmodRecursive /** * Rename or move a file or a directory from the ftp-server * * @param string $remote_from The remote file or directory original to rename or * move * @param string $remote_to The remote file or directory final to rename or * move * * @access public * @return bool $res True on success, otherwise PEAR::Error * @see NET_FTP_ERR_RENAME_FAILED */ function rename ($remote_from, $remote_to) { $res = @ftp_rename($this->_handle, $remote_from, $remote_to); if (!$res) { return $this->raiseError("Could not rename ".$remote_from." to ". $remote_to." !", NET_FTP_ERR_RENAME_FAILED); } return true; } /** * This will return logical permissions mask for directory. * if directory has to be readable it have also be executable * * @param string $permissions File permissions in digits for file (i.e. 666) * * @access private * @return string File permissions in digits for directory (i.e. 777) */ function _makeDirPermissions($permissions) { $permissions = (string)$permissions; // going through (user, group, world) for ($i = 0; $i < strlen($permissions); $i++) { // Read permission is set but execute not yet if ((int)$permissions{$i} & 4 and !((int)$permissions{$i} & 1)) { // Adding execute flag $permissions{$i} = (int)$permissions{$i} + 1; } } return (string)$permissions; } /** * This will return the last modification-time of a file. You can either give * this function a relative or an absolute path to the file to check. * NOTE: Some servers will not support this feature and the function works * only on files, not directories! When successful, * it will return the last modification-time as a unix-timestamp or, when * $format is specified, a preformated timestring. * * @param string $file The file to check * @param string $format (optional) The format to give the date back * if not set, it will return a Unix timestamp * * @access public * @return mixed Unix timestamp, a preformated date-string or PEAR::Error * @see NET_FTP_ERR_MDTMDIR_UNSUPPORTED, NET_FTP_ERR_MDTM_FAILED, * NET_FTP_ERR_DATEFORMAT_FAILED */ function mdtm($file, $format = null) { $file = $this->_constructPath($file); if ($this->_checkRemoteDir($file) !== false) { return $this->raiseError("Filename '$file' seems to be a directory.", NET_FTP_ERR_MDTMDIR_UNSUPPORTED); } $res = @ftp_mdtm($this->_handle, $file); if ($res == -1) { return $this->raiseError("Could not get last-modification-date of '". $file."'.", NET_FTP_ERR_MDTM_FAILED); } if (isset($format)) { $res = date($format, $res); if (!$res) { return $this->raiseError("Date-format failed on timestamp '".$res. "'.", NET_FTP_ERR_DATEFORMAT_FAILED); } } return $res; } /** * This will return the size of a given file in bytes. You can either give this * function a relative or an absolute file-path. NOTE: Some servers do not * support this feature! * * @param string $file The file to check * * @access public * @return mixed Size in bytes or PEAR::Error * @see NET_FTP_ERR_SIZE_FAILED */ function size($file) { $file = $this->_constructPath($file); $res = @ftp_size($this->_handle, $file); if ($res == -1) { return $this->raiseError("Could not determine filesize of '$file'.", NET_FTP_ERR_SIZE_FAILED); } else { return $res; } } /** * This method returns a directory-list of the current directory or given one. * To display the current selected directory, simply set the first parameter to * null * or leave it blank, if you do not want to use any other parameters. *

* There are 4 different modes of listing directories. Either to list only * the files (using NET_FTP_FILES_ONLY), to list only directories (using * NET_FTP_DIRS_ONLY) or to show both (using NET_FTP_DIRS_FILES, which is * default). *

* The 4th one is the NET_FTP_RAWLIST, which returns just the array created by * the ftp_rawlist()-function build into PHP. *

* The other function-modes will return an array containing the requested data. * The files and dirs are listed in human-sorted order, but if you select * NET_FTP_DIRS_FILES the directories will be added above the files, * but although both sorted. *

* All elements in the arrays are associative arrays themselves. They have the * following structure: *

* Dirs:
* ["name"] => string The name of the directory
* ["rights"] => string The rights of the directory (in style * "rwxr-xr-x")
* ["user"] => string The owner of the directory
* ["group"] => string The group-owner of the directory
* ["files_inside"]=> string The number of files/dirs inside the * directory excluding "." and ".."
* ["date"] => int The creation-date as Unix timestamp
* ["is_dir"] => bool true, cause this is a dir
*

* Files:
* ["name"] => string The name of the file
* ["size"] => int Size in bytes
* ["rights"] => string The rights of the file (in style * "rwxr-xr-x")
* ["user"] => string The owner of the file
* ["group"] => string The group-owner of the file
* ["date"] => int The creation-date as Unix timestamp
* ["is_dir"] => bool false, cause this is a file
* * @param string $dir (optional) The directory to list or null, when listing * the current directory. * @param int $mode (optional) The mode which types to list (files, * directories or both). * * @access public * @return mixed The directory list as described above or PEAR::Error on failure * @see NET_FTP_DIRS_FILES, NET_FTP_DIRS_ONLY, NET_FTP_FILES_ONLY, * NET_FTP_RAWLIST, NET_FTP_ERR_DETERMINEPATH_FAILED, * NET_FTP_ERR_RAWDIRLIST_FAILED, NET_FTP_ERR_DIRLIST_UNSUPPORTED */ function ls($dir = null, $mode = NET_FTP_DIRS_FILES) { if (!isset($dir)) { $dir = @ftp_pwd($this->_handle); if (!$dir) { return $this->raiseError("Could not retrieve current directory", NET_FTP_ERR_DETERMINEPATH_FAILED); } } if (($mode != NET_FTP_FILES_ONLY) && ($mode != NET_FTP_DIRS_ONLY) && ($mode != NET_FTP_RAWLIST)) { $mode = NET_FTP_DIRS_FILES; } switch ($mode) { case NET_FTP_DIRS_FILES: $res = $this->_lsBoth($dir); break; case NET_FTP_DIRS_ONLY: $res = $this->_lsDirs($dir); break; case NET_FTP_FILES_ONLY: $res = $this->_lsFiles($dir); break; case NET_FTP_RAWLIST: $res = @ftp_rawlist($this->_handle, $dir); break; } return $res; } /** * This method will delete the given file or directory ($path) from the server * (maybe recursive). * * Whether the given string is a file or directory is only determined by the * last sign inside the string ("/" or not). * * If you specify a directory, you can optionally specify $recursive as true, * to let the directory be deleted recursive (with all sub-directories and files * inherited). * * You can either give a absolute or relative path for the file / dir. If you * choose to use the relative path, it will be automatically completed with the * actual selected directory. * * @param string $path The absolute or relative path to the file/directory. * @param bool $recursive Recursively delete everything in $path * @param bool $filesonly When deleting recursively, only delete files so the * directory structure is preserved * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_DELETEFILE_FAILED, NET_FTP_ERR_DELETEDIR_FAILED, * NET_FTP_ERR_REMOTEPATHNODIR */ function rm($path, $recursive = false, $filesonly = false) { $path = $this->_constructPath($path); if ($this->_checkRemoteDir($path) === true) { if ($recursive) { return $this->_rmDirRecursive($path, $filesonly); } else { return $this->_rmDir($path); } } else { return $this->_rmFile($path); } } /** * This function will download a file from the ftp-server. You can either * specify an absolute path to the file (beginning with "/") or a relative one, * which will be completed with the actual directory you selected on the server. * You can specify the path to which the file will be downloaded on the local * machine, if the file should be overwritten if it exists (optionally, default * is no overwriting) and in which mode (FTP_ASCII or FTP_BINARY) the file * should be downloaded (if you do not specify this, the method tries to * determine it automatically from the mode-directory or uses the default-mode, * set by you). * If you give a relative path to the local-file, the script-path is used as * basepath. * * @param string $remote_file The absolute or relative path to the file to * download * @param string $local_file The local file to put the downloaded in * @param bool $overwrite (optional) Whether to overwrite existing file * @param int $mode (optional) Either FTP_ASCII or FTP_BINARY * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN, * NET_FTP_ERR_OVERWRITELOCALFILE_FAILED, * NET_FTP_ERR_OVERWRITELOCALFILE_FAILED */ function get($remote_file, $local_file, $overwrite = false, $mode = null) { if (!isset($mode)) { $mode = $this->checkFileExtension($remote_file); } $remote_file = $this->_constructPath($remote_file); if (@file_exists($local_file) && !$overwrite) { return $this->raiseError("Local file '".$local_file. "' exists and may not be overwriten.", NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN); } if (@file_exists($local_file) && !@is_writeable($local_file) && $overwrite) { return $this->raiseError("Local file '".$local_file. "' is not writeable. Can not overwrite.", NET_FTP_ERR_OVERWRITELOCALFILE_FAILED); } if (@function_exists('ftp_nb_get')) { $res = @ftp_nb_get($this->_handle, $local_file, $remote_file, $mode); while ($res == FTP_MOREDATA) { $this->_announce('nb_get'); $res = @ftp_nb_continue($this->_handle); } } else { $res = @ftp_get($this->_handle, $local_file, $remote_file, $mode); } if (!$res) { return $this->raiseError("File '".$remote_file. "' could not be downloaded to '$local_file'.", NET_FTP_ERR_OVERWRITELOCALFILE_FAILED); } else { return true; } } /** * This function will upload a file to the ftp-server. You can either specify a * absolute path to the remote-file (beginning with "/") or a relative one, * which will be completed with the actual directory you selected on the server. * You can specify the path from which the file will be uploaded on the local * maschine, if the file should be overwritten if it exists (optionally, default * is no overwriting) and in which mode (FTP_ASCII or FTP_BINARY) the file * should be downloaded (if you do not specify this, the method tries to * determine it automatically from the mode-directory or uses the default-mode, * set by you). * If you give a relative path to the local-file, the script-path is used as * basepath. * * @param string $local_file The local file to upload * @param string $remote_file The absolute or relative path to the file to * upload to * @param bool $overwrite (optional) Whether to overwrite existing file * @param int $mode (optional) Either FTP_ASCII or FTP_BINARY * @param int $options (optional) Flags describing the behaviour of this * function. Currently NET_FTP_BLOCKING and * NET_FTP_NONBLOCKING are supported, of which * NET_FTP_NONBLOCKING is the default. * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_LOCALFILENOTEXIST, * NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN, * NET_FTP_ERR_UPLOADFILE_FAILED, NET_FTP_NONBLOCKING, NET_FTP_BLOCKING */ function put($local_file, $remote_file, $overwrite = false, $mode = null, $options = 0) { if ($options & (NET_FTP_BLOCKING | NET_FTP_NONBLOCKING) === (NET_FTP_BLOCKING | NET_FTP_NONBLOCKING)) { return $this->raiseError('Bad options given: NET_FTP_NONBLOCKING and '. 'NET_FTP_BLOCKING can\'t both be set', NET_FTP_ERR_BADOPTIONS); } $usenb = ! ($options & (NET_FTP_BLOCKING == NET_FTP_BLOCKING)); if (!isset($mode)) { $mode = $this->checkFileExtension($local_file); } $remote_file = $this->_constructPath($remote_file); if (!@file_exists($local_file)) { return $this->raiseError("Local file '$local_file' does not exist.", NET_FTP_ERR_LOCALFILENOTEXIST); } if ((@ftp_size($this->_handle, $remote_file) != -1) && !$overwrite) { return $this->raiseError("Remote file '".$remote_file. "' exists and may not be overwriten.", NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN); } if (function_exists('ftp_alloc')) { ftp_alloc($this->_handle, filesize($local_file)); } if ($usenb && function_exists('ftp_nb_put')) { $res = @ftp_nb_put($this->_handle, $remote_file, $local_file, $mode); while ($res == FTP_MOREDATA) { $this->_announce('nb_put'); $res = @ftp_nb_continue($this->_handle); } } else { $res = @ftp_put($this->_handle, $remote_file, $local_file, $mode); } if (!$res) { return $this->raiseError("File '$local_file' could not be uploaded to '" .$remote_file."'.", NET_FTP_ERR_UPLOADFILE_FAILED); } else { return true; } } /** * This functionality allows you to transfer a whole directory-structure from * the remote-ftp to your local host. You have to give a remote-directory * (ending with '/') and the local directory (ending with '/') where to put the * files you download. * The remote path is automatically completed with the current-remote-dir, if * you give a relative path to this function. You can give a relative path for * the $local_path, too. Then the script-basedir will be used for comletion of * the path. * The parameter $overwrite will determine, whether to overwrite existing files * or not. Standard for this is false. Fourth you can explicitly set a mode for * all transfer actions done. If you do not set this, the method tries to * determine the transfer mode by checking your mode-directory for the file * extension. If the extension is not inside the mode-directory, it will get * your default mode. * * Since 1.4 no error will be returned when a file exists while $overwrite is * set to false. * * @param string $remote_path The path to download * @param string $local_path The path to download to * @param bool $overwrite (optional) Whether to overwrite existing files * (true) or not (false, standard). * @param int $mode (optional) The transfermode (either FTP_ASCII or * FTP_BINARY). * @param array $excluded_paths (optional) List of remote files or directories to * exclude from the transfer. All files and * directories must be stated as absolute paths. * Note: You must include a trailing slash on directory names. * * @access public * @return mixed True on succes, otherwise PEAR::Error * @see NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN, * NET_FTP_ERR_OVERWRITELOCALFILE_FAILED, NET_FTP_ERR_OVERWRITELOCALFILE_FAILED, * NET_FTP_ERR_REMOTEPATHNODIR, NET_FTP_ERR_LOCALPATHNODIR, * NET_FTP_ERR_CREATELOCALDIR_FAILED */ function getRecursive($remote_path, $local_path, $overwrite = false, $mode = null, $excluded_paths = array()) { $remote_path = $this->_constructPath($remote_path); if ($this->_checkRemoteDir($remote_path) !== true) { return $this->raiseError("Given remote-path '".$remote_path. "' seems not to be a directory.", NET_FTP_ERR_REMOTEPATHNODIR); } if (!@file_exists($local_path)) { $res = @mkdir($local_path); if (!$res) { return $this->raiseError("Could not create dir '$local_path'", NET_FTP_ERR_CREATELOCALDIR_FAILED); } } elseif (!@is_dir($local_path)) { return $this->raiseError("Given local-path '".$local_path. "' seems not to be a directory.", NET_FTP_ERR_LOCALPATHNODIR); } $dir_list = array(); $dir_list = $this->ls($remote_path, NET_FTP_DIRS_ONLY); if (PEAR::isError($dir_list)) { return $dir_list; } foreach ($dir_list as $dir_entry) { if ($dir_entry['name'] != '.' && $dir_entry['name'] != '..') { $remote_path_new = $remote_path.$dir_entry["name"]."/"; $local_path_new = $local_path.$dir_entry["name"]."/"; // Check whether the directory should be excluded if (!in_array($remote_path_new, $excluded_paths)) { $result = $this->getRecursive($remote_path_new, $local_path_new, $overwrite, $mode); if ($this->isError($result)) { return $result; } } } } $file_list = array(); $file_list = $this->ls($remote_path, NET_FTP_FILES_ONLY); if (PEAR::isError($file_list)) { return $file_list; } foreach ($file_list as $file_entry) { $remote_file = $remote_path.$file_entry["name"]; $local_file = $local_path.$file_entry["name"]; // Check whether the file should be excluded if (!in_array($remote_file, $excluded_paths)) { $result = $this->get($remote_file, $local_file, $overwrite, $mode); if ($this->isError($result) && $result->getCode() != NET_FTP_ERR_OVERWRITELOCALFILE_FORBIDDEN) { return $result; } } } return true; } /** * This functionality allows you to transfer a whole directory-structure from * your local host to the remote-ftp. You have to give a remote-directory * (ending with '/') and the local directory (ending with '/') where to put the * files you download. The remote path is automatically completed with the * current-remote-dir, if you give a relative path to this function. You can * give a relative path for the $local_path, too. Then the script-basedir will * be used for comletion of the path. * The parameter $overwrite will determine, whether to overwrite existing files * or not. * Standard for this is false. Fourth you can explicitly set a mode for all * transfer actions done. If you do not set this, the method tries to determine * the transfer mode by checking your mode-directory for the file-extension. If * the extension is not inside the mode-directory, it will get your default * mode. * * @param string $local_path The path to download to * @param string $remote_path The path to download * @param bool $overwrite (optional) Whether to overwrite existing files * (true) or not (false, standard). * @param int $mode (optional) The transfermode (either FTP_ASCII or * FTP_BINARY). * @param array $excluded_paths (optional) List of local files or directories to * exclude from the transfer. All files and * directories must be stated as absolute paths. * Note: You must include a trailing slash on * directory names. * * @access public * @return mixed True on succes, otherwise PEAR::Error * @see NET_FTP_ERR_LOCALFILENOTEXIST, * NET_FTP_ERR_OVERWRITEREMOTEFILE_FORBIDDEN, * NET_FTP_ERR_UPLOADFILE_FAILED, NET_FTP_ERR_LOCALPATHNODIR, * NET_FTP_ERR_REMOTEPATHNODIR */ function putRecursive($local_path, $remote_path, $overwrite = false, $mode = null, $excluded_paths = array()) { $remote_path = $this->_constructPath($remote_path); if (!file_exists($local_path) || !is_dir($local_path)) { return $this->raiseError("Given local-path '".$local_path. "' seems not to be a directory.", NET_FTP_ERR_LOCALPATHNODIR); } // try to create directory if it doesn't exist $old_path = $this->pwd(); if ($this->isError($this->cd($remote_path))) { $res = $this->mkdir($remote_path); if ($this->isError($res)) { return $res; } } $this->cd($old_path); if ($this->_checkRemoteDir($remote_path) !== true) { return $this->raiseError("Given remote-path '".$remote_path. "' seems not to be a directory.", NET_FTP_ERR_REMOTEPATHNODIR); } $dir_list = $this->_lsLocal($local_path); foreach ($dir_list["dirs"] as $dir_entry) { // local directories do not have arrays as entry $remote_path_new = $remote_path.$dir_entry."/"; $local_path_new = $local_path.$dir_entry."/"; // Check whether the directory should be excluded if (!in_array($local_path_new, $excluded_paths)) { $result = $this->putRecursive($local_path_new, $remote_path_new, $overwrite, $mode, $excluded_paths); if ($this->isError($result)) { return $result; } } } foreach ($dir_list["files"] as $file_entry) { $remote_file = $remote_path.$file_entry; $local_file = $local_path.$file_entry; // Check whether the file should be excluded if (!in_array($local_file, $excluded_paths)) { $result = $this->put($local_file, $remote_file, $overwrite, $mode); if ($this->isError($result)) { return $result; } } } return true; } /** * This checks, whether a file should be transfered in ascii- or binary-mode * by it's file-extension. If the file-extension is not set or * the extension is not inside one of the extension-dirs, the actual set * transfer-mode is returned. * * @param string $filename The filename to be checked * * @access public * @return int Either FTP_ASCII or FTP_BINARY */ function checkFileExtension($filename) { if (($pos = strrpos($filename, '.')) === false) { return $this->_mode; } else { $ext = substr($filename, $pos + 1); } if (isset($this->_file_extensions[$ext])) { return $this->_file_extensions[$ext]; } return $this->_mode; } /** * Set the hostname * * @param string $host The hostname to set * * @access public * @return bool True on success, otherwise PEAR::Error * @see NET_FTP_ERR_HOSTNAMENOSTRING */ function setHostname($host) { if (!is_string($host)) { return PEAR::raiseError("Hostname must be a string.", NET_FTP_ERR_HOSTNAMENOSTRING); } $this->_hostname = $host; return true; } /** * Set the Port * * @param int $port The port to set * * @access public * @return bool True on success, otherwise PEAR::Error * @see NET_FTP_ERR_PORTLESSZERO */ function setPort($port) { if (!is_int($port) || ($port < 0)) { PEAR::raiseError("Invalid port. Has to be integer >= 0", NET_FTP_ERR_PORTLESSZERO); } $this->_port = $port; return true; } /** * Set to connect through secure SSL connection * * @access public * @return bool True on success, otherwise PEAR::Error */ function setSsl() { if (!function_exists('ftp_ssl_connect')) { return PEAR::raiseError('SSL connection not supported. Function ftp_ssl_connect does not exist.', NET_FTP_ERR_NOSSL); } $this->_ssl = true; return true; } /** * Set the Username * * @param string $user The username to set * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_USERNAMENOSTRING */ function setUsername($user) { if (empty($user) || !is_string($user)) { return PEAR::raiseError('Username $user invalid.', NET_FTP_ERR_USERNAMENOSTRING); } $this->_username = $user; return true; } /** * Set the password * * @param string $password The password to set * * @access private * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_PASSWORDNOSTRING */ function setPassword($password) { if (empty($password) || !is_string($password)) { return PEAR::raiseError('Password xxx invalid.', NET_FTP_ERR_PASSWORDNOSTRING); } $this->_password = $password; return true; } /** * Set the transfer-mode. You can use the predefined constants * FTP_ASCII or FTP_BINARY. The mode will be stored for any further transfers. * * @param int $mode The mode to set * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_NOMODECONST */ function setMode($mode) { if (($mode == FTP_ASCII) || ($mode == FTP_BINARY)) { $this->_mode = $mode; return true; } else { return $this->raiseError('FTP-Mode has either to be FTP_ASCII or'. 'FTP_BINARY', NET_FTP_ERR_NOMODECONST); } } /** * Set the transfer-method to passive mode * * @access public * @return void */ function setPassive() { $this->_passv = true; if ($this->_handle != null && $this->_loggedin) { @ftp_pasv($this->_handle, true); } } /** * Set the transfer-method to active mode * * @access public * @return void */ function setActive() { $this->_passv = false; if ($this->_handle != null && $this->_loggedin) { @ftp_pasv($this->_handle, false); } } /** * Set the timeout for FTP operations * * Use this method to set a timeout for FTP operation. Timeout has to be an * integer. * * @param int $timeout the timeout to use * * @access public * @return bool True on success, otherwise PEAR::Error * @see NET_FTP_ERR_TIMEOUTLESSZERO, NET_FTP_ERR_SETTIMEOUT_FAILED */ function setTimeout ( $timeout = 0 ) { if (!is_int($timeout) || ($timeout < 0)) { return PEAR::raiseError('Timeout '.$timeout. ' is invalid, has to be an integer >= 0', NET_FTP_ERR_TIMEOUTLESSZERO); } $this->_timeout = $timeout; if (isset($this->_handle) && is_resource($this->_handle)) { $res = @ftp_set_option($this->_handle, FTP_TIMEOUT_SEC, $timeout); } else { $res = true; } if (!$res) { return PEAR::raiseError("Set timeout failed.", NET_FTP_ERR_SETTIMEOUT_FAILED); } return true; } /** * Adds an extension to a mode-directory * * The mode-directory saves file-extensions coresponding to filetypes * (ascii e.g.: 'php', 'txt', 'htm',...; binary e.g.: 'jpg', 'gif', 'exe',...). * The extensions have to be saved without the '.'. And * can be predefined in an external file (see: getExtensionsFile()). * * The array is build like this: 'php' => FTP_ASCII, 'png' => FTP_BINARY * * To change the mode of an extension, just add it again with the new mode! * * @param int $mode Either FTP_ASCII or FTP_BINARY * @param string $ext Extension * * @access public * @return void */ function addExtension($mode, $ext) { $this->_file_extensions[$ext] = $mode; } /** * This function removes an extension from the mode-directories * (described above). * * @param string $ext The extension to remove * * @access public * @return void */ function removeExtension($ext) { if (isset($this->_file_extensions[$ext])) { unset($this->_file_extensions[$ext]); } } /** * This get's both (ascii- and binary-mode-directories) from the given file. * Beware, if you read a file into the mode-directory, all former set values * will be unset! * * Example file contents: * [ASCII] * asc = 0 * txt = 0 * [BINARY] * bin = 1 * jpg = 1 * * @param string $filename The file to get from * * @access public * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_EXTFILENOTEXIST, NET_FTP_ERR_EXTFILEREAD_FAILED */ function getExtensionsFile($filename) { if (!file_exists($filename)) { return $this->raiseError("Extensions-file '$filename' does not exist", NET_FTP_ERR_EXTFILENOTEXIST); } if (!is_readable($filename)) { return $this->raiseError("Extensions-file '$filename' is not readable", NET_FTP_ERR_EXTFILEREAD_FAILED); } $exts = @parse_ini_file($filename, true); if (!is_array($exts)) { return $this->raiseError("Extensions-file '$filename' could not be". "loaded", NET_FTP_ERR_EXTFILELOAD_FAILED); } $this->_file_extensions = array(); if (isset($exts['ASCII'])) { foreach (array_keys($exts['ASCII']) as $ext) { $this->_file_extensions[$ext] = FTP_ASCII; } } if (isset($exts['BINARY'])) { foreach (array_keys($exts['BINARY']) as $ext) { $this->_file_extensions[$ext] = FTP_BINARY; } } return true; } /** * Returns the hostname * * @access public * @return string The hostname */ function getHostname() { return $this->_hostname; } /** * Returns the port * * @access public * @return int The port */ function getPort() { return $this->_port; } /** * Returns whether to connect through secure SSL connection * * @access public * @return bool True if with SSL, false if without SSL */ function getSsl() { return $this->_ssl; } /** * Returns the username * * @access public * @return string The username */ function getUsername() { return $this->_username; } /** * Returns the password * * @access public * @return string The password */ function getPassword() { return $this->_password; } /** * Returns the transfermode * * @access public * @return int The transfermode, either FTP_ASCII or FTP_BINARY. */ function getMode() { return $this->_mode; } /** * Returns, whether the connection is set to passive mode or not * * @access public * @return bool True if passive-, false if active-mode */ function isPassive() { return $this->_passv; } /** * Returns the mode set for a file-extension * * @param string $ext The extension you wanna ask for * * @return int Either FTP_ASCII, FTP_BINARY or NULL (if not set a mode for it) * @access public */ function getExtensionMode($ext) { return @$this->_file_extensions[$ext]; } /** * Get the currently set timeout. * Returns the actual timeout set. * * @access public * @return int The actual timeout */ function getTimeout() { return ftp_get_option($this->_handle, FTP_TIMEOUT_SEC); } /** * Adds a Net_FTP_Observer instance to the list of observers * that are listening for messages emitted by this Net_FTP instance. * * @param object &$observer The Net_FTP_Observer instance to attach * as a listener. * * @return boolean True if the observer is successfully attached. * @access public * @since 1.3 */ function attach(&$observer) { if (!is_a($observer, 'Net_FTP_Observer')) { return false; } $this->_listeners[$observer->getId()] = &$observer; return true; } /** * Removes a Net_FTP_Observer instance from the list of observers. * * @param object $observer The Net_FTP_Observer instance to detach * from the list of listeners. * * @return boolean True if the observer is successfully detached. * @access public * @since 1.3 */ function detach($observer) { if (!is_a($observer, 'Net_FTP_Observer') || !isset($this->_listeners[$observer->getId()])) { return false; } unset($this->_listeners[$observer->getId()]); return true; } /** * Sets the directory listing matcher * * Use this method to set the directory listing matcher to a specific pattern. * Indicate the pattern as a perl regular expression and give an array * containing as keys the fields selected in the regular expression and as * values the offset of the subpattern in the pattern. * * Example: * $pattern = '/(?:(d)|.)([rwxt-]+)\s+(\w+)\s+([\w\d-]+)\s+([\w\d-]+)\s+(\w+) * \s+(\S+\s+\S+\s+\S+)\s+(.+)/', * $matchmap = array( * 'is_dir' => 1, * 'rights' => 2, * 'files_inside' => 3, * 'user' => 4, * 'group' => 5, * 'size' => 6, * 'date' => 7, * 'name' => 8, * ) * * Make sure at least the is_dir and name keys are set. The is_dir key should * point to a subpattern that is empty for non-directories and non-empty * for directories. * * @param string $pattern The new matcher pattern to use * @param array $matchmap An mapping from key to subpattern offset * * @since 1.4.0a1 * @access public * @return bool|PEAR_Error True if matcher set successfully, PEAR_Error * otherwise * @see NET_FTP_ERR_ILLEGALPATTERN, * NET_FTP_ERR_ILLEGALMAP * NET_FTP_ERR_ILLEGALMAPVALUE */ function setDirMatcher($pattern, $matchmap) { if (!is_string($pattern)) { return $this->raiseError('The supplied pattern is not a string', NET_FTP_ERR_ILLEGALPATTERN); } if (!is_array($matchmap)) { return $this->raiseError('The supplied pattern is not an array', NET_FTP_ERR_ILLEGALMAP); } else { foreach ($matchmap AS $val) { if (!is_numeric($val)) { return $this->raiseError('The supplied pattern contains'. 'invalid value '.$val, NET_FTP_ERR_ILLEGALMAPVALUE); } } } $this->_matcher = array('pattern' => $pattern, 'map' => $matchmap); return true; } /** * Informs each registered observer instance that a new message has been * sent. * * @param mixed $event A hash describing the net event. * * @access private * @since 1.3 * @return void */ function _announce($event) { foreach ($this->_listeners as $listener) { $listener->notify($event); } } /** * Rebuild the path, if given relative * * This method will make a relative path absolute by prepending the current * remote directory in front of it. * * @param string $path The path to check and construct * * @access private * @return string The build path */ function _constructPath($path) { if ((substr($path, 0, 1) != '/') && (substr($path, 0, 2) != './')) { $actual_dir = @ftp_pwd($this->_handle); if (substr($actual_dir, -1) != '/') { $actual_dir .= '/'; } $path = $actual_dir.$path; } return $path; } /** * Checks whether the given path is a remote directory by trying to * chdir() into it (and back out) * * @param string $path Path to check * * @access private * @return mixed True if $path is a directory, otherwise false, PEAR_Error * when an error occurs in determining path type */ function _checkRemoteDir($path) { $pwd = $this->pwd(); if ($this->isError($pwd)) { return $pwd; } $res = $this->cd($path); $this->cd($pwd); return $this->isError($res, NET_FTP_ERR_DIRCHANGE_FAILED) === false; } /** * This will remove a file * * @param string $file The file to delete * * @access private * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_DELETEFILE_FAILED */ function _rmFile($file) { if (substr($file, 0, 1) != "/") { $actual_dir = @ftp_pwd($this->_handle); if (substr($actual_dir, (strlen($actual_dir) - 2), 1) != "/") { $actual_dir .= "/"; } $file = $actual_dir.$file; } $res = @ftp_delete($this->_handle, $file); if (!$res) { return $this->raiseError("Could not delete file '$file'.", NET_FTP_ERR_DELETEFILE_FAILED); } else { return true; } } /** * This will remove a dir * * @param string $dir The dir to delete * * @access private * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_REMOTEPATHNODIR, NET_FTP_ERR_DELETEDIR_FAILED */ function _rmDir($dir) { if (substr($dir, (strlen($dir) - 1), 1) != "/") { return $this->raiseError("Directory name '".$dir. "' is invalid, has to end with '/'", NET_FTP_ERR_REMOTEPATHNODIR); } $res = @ftp_rmdir($this->_handle, $dir); if (!$res) { return $this->raiseError("Could not delete directory '$dir'.", NET_FTP_ERR_DELETEDIR_FAILED); } else { return true; } } /** * This will remove a dir and all subdirs and -files * * @param string $dir The dir to delete recursively * @param bool $filesonly Only delete files so the directory structure is * preserved * * @access private * @return mixed True on success, otherwise PEAR::Error * @see NET_FTP_ERR_REMOTEPATHNODIR, NET_FTP_ERR_DELETEDIR_FAILED */ function _rmDirRecursive($dir, $filesonly = false) { if (substr($dir, (strlen($dir) - 1), 1) != "/") { return $this->raiseError("Directory name '".$dir. "' is invalid, has to end with '/'", NET_FTP_ERR_REMOTEPATHNODIR); } $file_list = $this->_lsFiles($dir); if (PEAR::isError($file_list)) { return $file_list; } foreach ($file_list as $file) { $file = $dir.$file["name"]; $res = $this->rm($file); if ($this->isError($res)) { return $res; } } $dir_list = $this->_lsDirs($dir); if (PEAR::isError($dir_list)) { return $dir_list; } foreach ($dir_list as $new_dir) { if ($new_dir["name"] == '.' || $new_dir["name"] == '..') { continue; } $new_dir = $dir.$new_dir["name"]."/"; $res = $this->_rmDirRecursive($new_dir, $filesonly); if ($this->isError($res)) { return $res; } } if (!$filesonly) { $res = $this->_rmDir($dir); } if (PEAR::isError($res)) { return $res; } else { return true; } } /** * Lists up files and directories * * @param string $dir The directory to list up * * @access private * @return array An array of dirs and files */ function _lsBoth($dir) { $list_splitted = $this->_listAndParse($dir); if (PEAR::isError($list_splitted)) { return $list_splitted; } if (!is_array($list_splitted["files"])) { $list_splitted["files"] = array(); } if (!is_array($list_splitted["dirs"])) { $list_splitted["dirs"] = array(); } $res = array(); @array_splice($res, 0, 0, $list_splitted["files"]); @array_splice($res, 0, 0, $list_splitted["dirs"]); return $res; } /** * Lists up directories * * @param string $dir The directory to list up * * @access private * @return array An array of dirs */ function _lsDirs($dir) { $list = $this->_listAndParse($dir); if (PEAR::isError($list)) { return $list; } return $list["dirs"]; } /** * Lists up files * * @param string $dir The directory to list up * * @access private * @return array An array of files */ function _lsFiles($dir) { $list = $this->_listAndParse($dir); if (PEAR::isError($list)) { return $list; } return $list["files"]; } /** * This lists up the directory-content and parses the items into well-formated * arrays. * The results of this array are sorted (dirs on top, sorted by name; * files below, sorted by name). * * @param string $dir The directory to parse * * @access private * @return array Lists of dirs and files * @see NET_FTP_ERR_RAWDIRLIST_FAILED */ function _listAndParse($dir) { $dirs_list = array(); $files_list = array(); $dir_list = @ftp_rawlist($this->_handle, $dir); if (!is_array($dir_list)) { return PEAR::raiseError('Could not get raw directory listing.', NET_FTP_ERR_RAWDIRLIST_FAILED); } foreach ($dir_list AS $k=>$v) { if (strncmp($v, 'total: ', 7) == 0 && preg_match('/total: \d+/', $v)) { unset($dir_list[$k]); break; // usually there is just one line like this } } // Handle empty directories if (count($dir_list) == 0) { return array('dirs' => $dirs_list, 'files' => $files_list); } // Exception for some FTP servers seem to return this wiered result instead // of an empty list if (count($dirs_list) == 1 && $dirs_list[0] == 'total 0') { return array('dirs' => array(), 'files' => $files_list); } if (!isset($this->_matcher) || PEAR::isError($this->_matcher)) { $this->_matcher = $this->_determineOSMatch($dir_list); if (PEAR::isError($this->_matcher)) { return $this->_matcher; } } foreach ($dir_list as $entry) { $m = array(); if (!preg_match($this->_matcher['pattern'], $entry, $m)) { continue; } $entry = array(); foreach ($this->_matcher['map'] as $key=>$val) { $entry[$key] = $m[$val]; } $entry['stamp'] = $this->_parseDate($entry['date']); if ($entry['is_dir']) { $dirs_list[] = $entry; } else { $files_list[] = $entry; } } @usort($dirs_list, array("Net_FTP", "_natSort")); @usort($files_list, array("Net_FTP", "_natSort")); $res["dirs"] = (is_array($dirs_list)) ? $dirs_list : array(); $res["files"] = (is_array($files_list)) ? $files_list : array(); return $res; } /** * Determine server OS * This determines the server OS and returns a valid regex to parse * ls() output. * * @param array &$dir_list The raw dir list to parse * * @access private * @return mixed An array of 'pattern' and 'map' on success, otherwise * PEAR::Error * @see NET_FTP_ERR_DIRLIST_UNSUPPORTED */ function _determineOSMatch(&$dir_list) { foreach ($dir_list as $entry) { foreach ($this->_ls_match as $match) { if (preg_match($match['pattern'], $entry)) { return $match; } } } $error = 'The list style of your server seems not to be supported. Please'. 'email a "$ftp->ls(NET_FTP_RAWLIST);" output plus info on the'. 'server to the maintainer of this package to get it supported!'. 'Thanks for your help!'; return PEAR::raiseError($error, NET_FTP_ERR_DIRLIST_UNSUPPORTED); } /** * Lists a local directory * * @param string $dir_path The dir to list * * @access private * @return array The list of dirs and files */ function _lsLocal($dir_path) { $dir = dir($dir_path); $dir_list = array(); $file_list = array(); while (false !== ($entry = $dir->read())) { if (($entry != '.') && ($entry != '..')) { if (is_dir($dir_path.$entry)) { $dir_list[] = $entry; } else { $file_list[] = $entry; } } } $dir->close(); $res['dirs'] = $dir_list; $res['files'] = $file_list; return $res; } /** * Function for use with usort(). * Compares the list-array-elements by name. * * @param string $item_1 first item to be compared * @param string $item_2 second item to be compared * * @access private * @return int < 0 if $item_1 is less than $item_2, 0 if equal and > 0 otherwise */ function _natSort($item_1, $item_2) { return strnatcmp($item_1['name'], $item_2['name']); } /** * Parse dates to timestamps * * @param string $date Date * * @access private * @return int Timestamp * @see NET_FTP_ERR_DATEFORMAT_FAILED */ function _parseDate($date) { // Sep 10 22:06 => Sep 10, 22:06 $res = array(); if (preg_match('/([A-Za-z]+)[ ]+([0-9]+)[ ]+([0-9]+):([0-9]+)/', $date, $res)) { $year = date('Y'); $month = $res[1]; $day = $res[2]; $hour = $res[3]; $minute = $res[4]; $date = "$month $day, $year $hour:$minute"; $tmpDate = strtotime($date); if ($tmpDate > time()) { $year--; $date = "$month $day, $year $hour:$minute"; } } elseif (preg_match('/^\d\d-\d\d-\d\d/', $date)) { // 09-10-04 => 09/10/04 $date = str_replace('-', '/', $date); } $res = strtotime($date); if (!$res) { return $this->raiseError('Dateconversion failed.', NET_FTP_ERR_DATEFORMAT_FAILED); } return $res; } } ?> Net_FTP-1.4.0/Net/FTP/Observer.php0000664000175000017500000000470612500046241016023 0ustar kguestkguest * @author Laurent Laville * @author Chuck Hagenbuch * @copyright 1997-2008 The PHP Group * @license BSD http://www.opensource.org/licenses/bsd-license.php * @version CVS: $Id$ * @link http://pear.php.net/package/Net_FTP * @since File available since Release 0.0.1 */ /** * This class implements the Observer part of a Subject-Observer * design pattern. It listens to the events sent by a Net_FTP instance. * This module had many influences from the Log_observer code. * * @category Networking * @package FTP * @author Laurent Laville * @author Chuck Hagenbuch * @author Tobias Schlitt * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version Release: 1.4.0 * @link http://pear.php.net/package/Net_FTP * @since 1.3.0.0 * @access public * * @example observer_upload.php An example of Net_FTP_Observer implementation. */ class Net_FTP_Observer { /** * Instance-specific unique identification number. * * @var integer * @since 1.3.0 * @access private */ var $_id; /** * Creates a new basic Net_FTP_Observer instance. * * @since 1.3.0 * @access public */ function Net_FTP_Observer() { $this->_id = md5(microtime()); } /** * Returns the listener's identifier * * @return string The listener's identifier * @since 1.3.0 * @access public */ function getId() { return $this->_id; } /** * This is a stub method to make sure that Net_FTP_Observer classes do * something when they are notified of a message. The default behavior * is to just do nothing. * You should override this method. * * @param mixed $event A hash describing the net event. * * @since 1.3.0 * @access public * @return void */ function notify($event) { return; } } ?> Net_FTP-1.4.0/Net/FTP/Socket.php0000664000175000017500000005255612500046241015472 0ustar kguestkguest * @copyright 1997-2008 The PHP Group * @license BSD http://www.opensource.org/licenses/bsd-license.php * @version CVS: $Id$ * @link http://pear.php.net/package/Net_FTP * @since File available since Release 0.0.1 */ /** * Default FTP extension constants */ define('FTP_ASCII', 0); define('FTP_TEXT', 0); define('FTP_BINARY', 1); define('FTP_IMAGE', 1); define('FTP_TIMEOUT_SEC', 0); /** * What needs to be done overall? * #1 Install the rest of these functions * #2 Document better * #3 Alot of other things I don't remember */ /* * !!! NOTE !!! * Most of the comment's are "not working", * meaning they are not all up-to-date * !!! NOTE !!! */ /** * &resource ftp_connect ( string host [, int port [, int timeout ] ] ); * * Opens an FTP connection and return resource or false on failure. * * FTP Success respons code: 220 * * @param string $host Host to connect to * @param int $port Optional, port to connect to * @param int $timeout Optional, seconds until function timeouts * * @todo The FTP extension has ftp_get_option() function which returns the * timeout variable. This function needs to be created and contain it as * static variable. * @todo The FTP extension has ftp_set_option() function which sets the * timeout variable. This function needs to be created and called here. * @access public * @return &resource */ if (!function_exists('ftp_connect')) { function &ftp_connect($host, $port = 21, $timeout = 90) { $false = false; // We are going to return refrence (E_STRICT) if (!is_string($host) || !is_integer($port) || !is_integer($timeout)) { return $false; } $iError = 0; $sError = ''; $control = @fsockopen($host, $port, $iError, $sError, $timeout); $GLOBALS['_NET_FTP']['timeout'] = $timeout; if (!is_resource($control)) { return $false; } stream_set_blocking($control, true); stream_set_timeout($control, $timeout); do { $content[] = fgets($control, 8129); $array = socket_get_status($control); } while ($array['unread_bytes'] > 0); if (substr($content[count($content)-1], 0, 3) == 220) { return $control; } return $false; } } /** * boolean ftp_login ( resource stream, string username, string password ); * * Logs in to an given FTP connection stream. * Returns TRUE on success or FALSE on failure. * * NOTE: * Username and password are *not* optional. Function will *not* * assume "anonymous" if username and/or password is empty * * FTP Success respons code: 230 * * @param resource &$control FTP resource to login to * @param string $username FTP Username to be used * @param string $password FTP Password to be used * * @access public * @return boolean */ if (!function_exists('ftp_login')) { function ftp_login(&$control, $username, $password) { if (!is_resource($control) || is_null($username)) { return false; } fputs($control, 'USER '.$username."\r\n"); $contents = array(); do { $contents[] = fgets($control, 8192); $array = socket_get_status($control); } while ($array['unread_bytes'] > 0); if (substr($contents[count($contents)-1], 0, 3) != 331) { return false; } fputs($control, 'PASS '.$password."\r\n"); $contents = array(); do { $contents[] = fgets($control, 8192); $array = socket_get_status($control); } while ($array['unread_bytes']); if (substr($contents[count($contents)-1], 0, 3) == 230) { return true; } trigger_error('ftp_login() [function.ftp-login'. ']: '.$contents[count($contents)-1], E_USER_WARNING); return false; } } /** * boolean ftp_quit ( resource stream ); * * Closes FTP connection. * Returns TRUE or FALSE on error. * * NOTE: The PHP function ftp_quit is *alias* to ftp_close, here it is * the *other-way-around* ( ftp_close() is alias to ftp_quit() ). * * NOTE: * resource is set to null since unset() can't unset the variable. * * @param resource &$control FTP resource * * @access public * @return boolean */ if (!function_exists('ftp_quit')) { function ftp_quit(&$control) { if (!is_resource($control)) { return false; } fputs($control, 'QUIT'."\r\n"); fclose($control); $control = null; return true; } } /** * Alias to ftp_quit() * * @param resource &$control FTP resource * * @see ftp_quit() * @access public * @return boolean */ if (!function_exists('ftp_close')) { function ftp_close(&$control) { return ftp_quit($control); } } /** * string ftp_pwd ( resource stream ); * * Gets the current directory name. * Returns the current directory. * * Needs data connection: NO * Success response code: 257 * * @param resource &$control FTP resource * * @access public * @return string */ if (!function_exists('ftp_pwd')) { function ftp_pwd(&$control) { if (!is_resource($control)) { return $control; } fputs($control, 'PWD'."\r\n"); $content = array(); do { $content[] = fgets($control, 8192); $array = socket_get_status($control); } while ($array['unread_bytes'] > 0); if (substr($cont = $content[count($content)-1], 0, 3) == 257) { $pos = strpos($cont, '"')+1; $pos2 = strrpos($cont, '"') - $pos; $path = substr($cont, $pos, $pos2); return $path; } return false; } } /** * boolean ftp_chdir ( resource stream, string directory ); * * Changes the current directory to the specified directory. * Returns TRUE on success or FALSE on failure. * * FTP success response code: 250 * Needs data connection: NO * * @param resource &$control FTP stream * @param string $pwd Directory name * * @access public * @return boolean */ if (!function_exists('ftp_chdir')) { function ftp_chdir(&$control, $pwd) { if (!is_resource($control) || !is_string($pwd)) { return false; } fputs($control, 'CWD '.$pwd."\r\n"); $content = array(); do { $content[] = fgets($control, 8192); $array = socket_get_status($control); } while ($array['unread_bytes'] > 0); if (substr($content[count($content)-1], 0, 3) == 250) { return true; } trigger_error('ftp_chdir() [function.ftp-chdir]: ' .$content[count($content)-1], E_USER_WARNING); return false; } } $_NET_FTP = array(); $_NET_FTP['USE_PASSIVE'] = false; $_NET_FTP['DATA'] = null; /** * boolean ftp_pasv ( resource stream, boolean passive ); * * Toggles passive mode ON/OFF. * Returns TRUE on success or FALSE on failure. * * Comment: * Although my lack of C knowlege I checked how the PHP FTP extension * do things here. Seems like they create the data connection and store * it in object for other functions to use. * This is now done here. * * FTP success response code: 227 * * @param stream &$control FTP stream * @param boolean $pasv True to switch to passive, false for active mode * * @access public * @return boolean */ if (!function_exists('ftp_pasv')) { function ftp_pasv(&$control, $pasv) { if (!is_resource($control) || !is_bool($pasv)) { return false; } // If data connection exists, destroy it if (isset($GLOBALS['_NET_FTP']['DATA'])) { fclose($GLOBALS['_NET_FTP']['DATA']); $GLOBALS['_NET_FTP']['DATA'] = null; do { fgets($control, 16); $array = socket_get_status($control); } while ($array['unread_bytes'] > 0); } // Are we suppost to create active or passive connection? if (!$pasv) { $GLOBALS['_NET_FTP']['USE_PASSIVE'] = false; // Pick random "low bit" $low = rand(39, 250); // Pick random "high bit" $high = rand(39, 250); // Lowest possible port would be; 10023 // Highest possible port would be; 64246 $port = ($low<<8)+$high; $ip = str_replace('.', ',', $_SERVER['SERVER_ADDR']); $s = $ip.','.$low.','.$high; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (is_resource($socket)) { if (socket_bind($socket, '0.0.0.0', $port)) { if (socket_listen($socket)) { $GLOBALS['_NET_FTP']['DATA'] = &$socket; fputs($control, 'PORT '.$s."\r\n"); $line = fgets($control, 512); if (substr($line, 0, 3) == 200) { return true; } } } } return false; } // Since we are here, we are suppost to create passive data connection. fputs($control, 'PASV' ."\r\n"); $content = array(); do { $content[] = fgets($control, 128); $array = socket_get_status($control); } while ($array['unread_bytes']); if (substr($cont = $content[count($content)-1], 0, 3) != 227) { return false; } $pos = strpos($cont, '(')+1; $pos2 = strrpos($cont, ')')-$pos; $string = substr($cont, $pos, $pos2); $array = explode(',', $string); // IP we are connecting to $ip = $array[0]. '.' .$array[1]. '.' .$array[2]. '.' .$array[3]; // Port ( 256*lowbit + highbit $port = ($array[4] << 8)+$array[5]; // Our data connection $iError = 0; $sError = ''; $data = fsockopen($ip, $port, $iError, $sError, $GLOBALS['_NET_FTP']['timeout']); if (is_resource($data)) { $GLOBALS['_NET_FTP']['USE_PASSIVE'] = true; $GLOBALS['_NET_FTP']['DATA'] = &$data; stream_set_blocking($data, true); stream_set_timeout($data, $GLOBALS['_NET_FTP']['timeout']); return true; } return false; } } /** * array ftp_rawlist ( resource stream, string directory [,bool recursive] ); * * Returns a detailed list of files in the given directory. * * Needs data connection: YES * * @param integer &$control FTP resource * @param string $pwd Path to retrieve * @param boolean $recursive Optional, retrieve recursive listing * * @todo Enable the recursive feature. * @access public * @return array */ if (!function_exists('ftp_rawlist')) { function ftp_rawlist(&$control, $pwd, $recursive = false) { if (!is_resource($control) || !is_string($pwd)) { return false; } if (!isset($GLOBALS['_NET_FTP']['DATA']) || !is_resource($GLOBALS['_NET_FTP']['DATA'])) { ftp_pasv($control, $GLOBALS['_NET_FTP']['USE_PASSIVE']); } fputs($control, 'LIST '.$pwd."\r\n"); $msg = fgets($control, 512); if (substr($msg, 0, 3) == 425) { return false; } $data = &$GLOBALS['_NET_FTP']['DATA']; if (!$GLOBALS['_NET_FTP']['USE_PASSIVE']) { $data = &socket_accept($data); } $content = array(); switch ($GLOBALS['_NET_FTP']['USE_PASSIVE']) { case true: while (true) { $string = rtrim(fgets($data, 1024)); if ($string=='') { break; } $content[] = $string; } fclose($data); break; case false: $string = socket_read($data, 1024, PHP_BINARY_READ); $content = explode("\n", $string); unset($content[count($content)-1]); socket_close($GLOBALS['_NET_FTP']['DATA']); socket_close($data); break; } $data = $GLOBALS['_NET_FTP']['DATA'] = null; fgets($control, 1024); return $content; } } /** * string ftp_systype ( resource stream ); * * Gets system type identifier of remote FTP server * Returns the remote system type * * @param resource &$control FTP resource * * @access public * @return string */ if (!function_exists('ftp_systype')) { function ftp_systype(&$control) { if (!is_resource($control)) { return false; } fputs($control, 'SYST'."\r\n"); $line = fgets($control, 256); if (substr($line, 0, 3) != 215) { return false; } $os = substr($line, 4, strpos($line, ' ', 4)-4); return $os; } } /** * boolean ftp_alloc ( resource stream, integer bytes [, string &message ] ); * * Allocates space for a file to be uploaded * Return TRUE on success or FALSE on failure * * NOTE; Many FTP servers do not support this command and/or don't need it. * * FTP success respons key: Belive it's 200 * Needs data connection: NO * * @param resource &$control FTP stream * @param integer $int Space to allocate * @param string &$msg Optional, textual representation of the servers response * will be returned by reference * * @access public * @return boolean */ if (!function_exists('ftp_alloc')) { function ftp_alloc(&$control, $int, &$msg = null) { if (!is_resource($control) || !is_integer($int)) { return false; } fputs($control, 'ALLO '.$int.' R '.$int."\r\n"); $msg = rtrim(fgets($control, 256)); $code = substr($msg, 0, 3); if ($code == 200 || $code == 202) { return true; } return false; } } /** * bool ftp_put ( resource stream, string remote_file, string local_file, * int mode [, int startpos ] ); * * Uploads a file to the FTP server * Returns TRUE on success or FALSE on failure. * * NOTE: * The transfer mode specified must be either FTP_ASCII or FTP_BINARY. * * @param resource &$control FTP stream * @param string $remote Remote file to write * @param string $local Local file to upload * @param integer $mode Upload mode, FTP_ASCI || FTP_BINARY * @param integer $pos Optional, start upload at position * * @access public * @return boolean */ if (!function_exists('ftp_put')) { function ftp_put(&$control, $remote, $local, $mode, $pos = 0) { if (!is_resource($control) || !is_readable($local) || !is_integer($mode) || !is_integer($pos)) { return false; } $types = array ( 0 => 'A', 1 => 'I' ); $windows = array ( 0 => 't', 1 => 'b' ); /** * TYPE values: * A ( ASCII ) * I ( BINARY ) * E ( EBCDIC ) * L ( BYTE ) */ if (!isset($GLOBALS['_NET_FTP']['DATA']) || !is_resource($GLOBALS['_NET_FTP']['DATA'])) { ftp_pasv($control, $GLOBALS['_NET_FTP']['USE_PASSIVE']); } // Establish data connection variable $data = &$GLOBALS['_NET_FTP']['DATA']; // Decide TYPE to use fputs($control, 'TYPE '.$types[$mode]."\r\n"); $line = fgets($control, 256); // "Type set to TYPE" if (substr($line, 0, 3) != 200) { return false; } fputs($control, 'STOR '.$remote."\r\n"); sleep(1); $line = fgets($control, 256); // "Opening TYPE mode data connect." if (substr($line, 0, 3) != 150) { return false; } // Creating resource to $local file $fp = fopen($local, 'r'. $windows[$mode]); if (!is_resource($fp)) { $fp = null; return false; } // Loop throu that file and echo it to the data socket $i = 0; switch ($GLOBALS['_NET_FTP']['USE_PASSIVE']) { case false: $data = &socket_accept($data); while (!feof($fp)) { $i += socket_write($data, fread($fp, 10240), 10240); } socket_close($data); break; case true: while (!feof($fp)) { $i += fputs($data, fread($fp, 10240), 10240); } fclose($data); break; } $data = null; do { $line = fgets($control, 256); } while (substr($line, 0, 4) != "226 "); return true; } } /** * Retrieve a remote file to a local file * Returns TRUE on success or FALSE on failure * * @param integer &$control Stream ID * @param string $local Local filename * @param string $remote Remote filename * @param integer $mode Transfer mode (FTP_ASCII or FTP_BINARY) * @param integer $resume Resume the file transfer or not * * @access public * @return boolean */ if (!function_exists('ftp_get')) { function ftp_get(&$control, $local, $remote, $mode, $resume = 0) { if (!is_resource($control) || !is_writable(dirname($local)) || !is_integer($mode) || !is_integer($resume)) { return false; } $types = array ( 0 => 'A', 1 => 'I' ); $windows = array ( 0 => 't', 1 => 'b' ); if (!isset($GLOBALS['_NET_FTP']['DATA']) || !is_resource($GLOBALS['_NET_FTP'][ 'DATA'])) { ftp_pasv($control, $GLOBALS['_NET_FTP']['USE_PASSIVE']); } fputs($control, 'TYPE '.$types[$mode]."\r\n"); $line = fgets($control, 256); if (substr($line, 0, 3) != 200) { return false; } $fp = fopen($local, 'w'.$windows[$mode]); if (!is_resource($fp)) { $fp = null; return false; } return true; } } /** * Changes to the parent directory * Returns TRUE on success or FALSE on failure * * @param integer &$control Stream ID * * @access public * @return boolean */ if (!function_exists('ftp_cdup')) { function ftp_cdup(&$control) { fputs($control, 'CDUP'."\r\n"); $line = fgets($control, 256); if (substr($line, 0, 3) != 250) { return false; } return true; } } /** * Set permissions on a file via FTP * Returns the new file permission on success or false on error * * NOTE: This command is *not* supported by the standard * NOTE: This command not ready! * * @param integer &$control Stream ID * @param integer $mode Octal value * @param string $file File to change permissions on * * @todo Figure out a way to chmod files via FTP * @access public * @return integer */ if (!function_exists('ftp_chmod')) { function ftp_chmod(&$control, $mode, $file) { if (!is_resource($control) || !is_integer($mode) || !is_string($file)) { return false; } // chmod not in the standard, proftpd doesn't recognize it // use SITE CHMOD? fputs($control, 'SITE CHMOD '.$mode. ' ' .$file."\r\n"); $line = fgets($control, 256); if (substr($line, 0, 3) == 200) { return $mode; } trigger_error('ftp_chmod() [function.ftp-chmod]: ' . rtrim($line), E_USER_WARNING); return false; } } /** * Deletes a file on the FTP server * Returns TRUE on success or FALSE on failure * * @param integer &$control Stream ID * @param string $path File to delete * * @access public * @return boolean */ if (!function_exists('ftp_delete')) { function ftp_delete(&$control, $path) { if (!is_resource($control) || !is_string($path)) { return false; } fputs($control, 'DELE '.$path."\r\n"); $line = fgets($control, 256); if (substr($line, 0, 3) == 250) { return true; } return false; } } /** * Requests execution of a program on the FTP server * NOTE; SITE EXEC is *not* supported by the standart * Returns TRUE on success or FALSE on error * * @param integer &$control Stream ID * @param string $cmd Command to send * * @access public * @todo Look a littlebit better into this * @return boolean */ if (!function_exists('ftp_exec')) { function ftp_exec(&$control, $cmd) { if (!is_resource($control) || !is_string($cmd)) { return false; } // Command not defined in the standart // proftpd doesn't recognize SITE EXEC (only help,chgrp,chmod and ratio) fputs($control, 'SITE EXEC '.$cmd."\r\n"); $line = fgets($control, 256); // php.net/ftp_exec uses respons code 200 to verify if command was sent // successfully or not, so we'll just do the same if (substr($line, 0, 3) == 200) { return true; } return false; } } ?> Net_FTP-1.4.0/tests/AllTests.php0000664000175000017500000000412512500046241015745 0ustar kguestkguest * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version CVS: $Id$ * @link http://pear.php.net/package/Net_FTP * @link http://www.phpunit.de PHPUnit * @since File available since Release 0.0.1 */ if (!defined('PHPUnit_MAIN_METHOD')) { define('PHPUnit_MAIN_METHOD', 'Net_FTP_AllTests::main'); } require_once 'PHPUnit/TextUI/TestRunner.php'; require_once 'Net_FTPTest.php'; /** * Unit test case for Net_FTP * * @category Networking * @package FTP * @author Jorrit Schippers * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version Release: 1.4.0 * @link http://pear.php.net/package/Net_FTP * @since Class available since Release 1.3.3 */ class Net_FTP_AllTests { /** * Main test suite run method * * @return void */ public static function main() { PHPUnit_TextUI_TestRunner::run(self::suite()); } /** * Main test suite method * * @return void */ public static function suite() { $suite = new PHPUnit_Framework_TestSuite('Net_FTP Tests'); $suite->addTestSuite('Net_FTPTest'); return $suite; } } if (PHPUnit_MAIN_METHOD == 'Net_FTP_AllTests::main') { Net_FTP_AllTests::main(); } ?> Net_FTP-1.4.0/tests/config.php.dist0000664000175000017500000000044612500046241016423 0ustar kguestkguestNet_FTP-1.4.0/tests/extensions.ini0000664000175000017500000000221312500046241016375 0ustar kguestkguest; This file can determine file-extension and wether to transfer them in ; binary- or ascii-mode. The two different values for file-modes are: ; ; FTP_ASCII (which equals 0) ; FTP_BINARY (which equals 1) ; ; This file will be directly parsed by parse_ini_file(), so beware of making mistakes ; inside this file, or your application may crash, everytime you parse your file. ; ; You can have more than 1 file containing extension-settings, for different kinds of ; application, server or case. But beware, if you've parsed a file into your Net_FTP-object, ; and after that you parse another file, the old settings will be overwriten! ; ; ASCII-Extensions: [ASCII] asc = 0 ascx = 0 asp = 0 aspx = 0 bas = 0 bash = 0 bat = 0 c = 0 cfc = 0 cfm = 0 cgi = 0 class = 0 conf = 0 css = 0 h = 0 hhc = 0 hhk = 0 hpp = 0 hta = 0 htm = 0 html = 0 inc = 0 nfo = 0 ini = 0 inf = 0 jav = 0 java = 0 js = 0 jsp = 0 log = 0 nfo = 0 pas = 0 php = 0 php3 = 0 php4 = 0 phtml = 0 pl = 0 svg = 0 sh = 0 shtml = 0 tcl = 0 text = 0 txt = 0 vb = 0 vbs = 0 wml = 0 xhtm = 0 xhtml = 0 xml = 0 xsd = 0 xsl = 0 xsl = 0 xslt = 0 xul = 0 ; BINARY-Extensions [BINARY] jpg = 1 gif = 1 bmp = 1Net_FTP-1.4.0/tests/Net_FTPTest.php0000664000175000017500000003444012500046241016314 0ustar kguestkguest * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version CVS: $Id$ * @link http://pear.php.net/package/Net_FTP * @link http://www.phpunit.de PHPUnit * @since File available since Release 1.3.3 */ if (!defined('PHPUnit_MAIN_METHOD')) { define('PHPUnit_MAIN_METHOD', 'Net_FTPTest::main'); } require_once 'System.php'; chdir(dirname(__FILE__)); if (substr(dirname(__FILE__), -6) == DIRECTORY_SEPARATOR.'tests') { include_once '../Net/FTP.php'; } else { include_once 'Net/FTP.php'; } /** * Unit test case for Net_FTP * * @category Networking * @package FTP * @author Jorrit Schippers * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version Release: 1.4.0 * @link http://pear.php.net/package/Net_FTP * @since Class available since Release 1.3.3 */ class Net_FTPTest extends PHPUnit_Framework_TestCase { protected $ftp; protected $ftpdir; /** * Runs the test methods of this class. * * @access public * @static * @return void */ public static function main() { include_once 'PHPUnit/TextUI/TestRunner.php'; $suite = new PHPUnit_Framework_TestSuite('Net_FTPTest'); PHPUnit_TextUI_TestRunner::run($suite); } /** * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. * * @access protected * @return void */ protected function setUp() { if (!file_exists('config.php')) { $this->markTestSkipped('config.php does not exist in '.getcwd()); } include_once 'config.php'; if (!defined('FTPHOST') || !defined('FTPPORT') || !defined('FTPUSER') || !defined('FTPPASSWORD')) { $this->markTestSkipped('Some required constants are not defined'); } $this->ftp = new Net_FTP(FTPHOST, FTPPORT, 30); $res = $this->ftp->login(FTPUSER, FTPPASSWORD); if (PEAR::isError($res)) { $this->markTestSkipped('Could not login to the FTP server'); } if (defined('FTPDIR') && '' !== FTPDIR) { $res = $this->ftp->cd(FTPDIR); if (PEAR::isError($res)) { $this->markTestSkipped('Could switch to directory '.FTPDIR); } } $res = $this->ftp->pwd(); if (PEAR::isError($res)) { $this->markTestSkipped('Could not get current directory'); } $this->ftpdir = $res; $res = $this->ftp->mkdir('test'); if (PEAR::isError($res)) { $this->markTestSkipped('Could not create a test directory'); } $res = $this->ftp->cd('test'); if (PEAR::isError($res)) { $this->markTestSkipped('Could not change to the test directory'); } } /** * Tears down the fixture, for example, closes a network connection. * This method is called after a test is executed. * * @access protected * @return void */ protected function tearDown() { if ($this->ftp != null) { $this->ftp->cd($this->ftpdir); $this->ftp->rm('test/', true); $this->ftp->disconnect(); $this->ftpdir = null; $this->ftp = null; } } /** * Tests functionality of Net_FTP::mkdir() * * @return void * @see Net_FTP::mkdir() */ public function testMkdir() { $this->ftp->mkdir('dir1', false); $this->ftp->mkdir('dir1/dir2/dir3/dir4', true); $this->assertTrue($this->ftp->cd('dir1/dir2/dir3/dir4')); } /** * Tests functionality of Net_FTP::mkdir() * * @return void * @see Net_FTP::mkdir() */ public function testRename() { $this->ftp->put('testfile.dat', 'testfile.dat', FTP_ASCII); $this->assertTrue($this->ftp->rename('testfile.dat', 'testfile2.dat')); } /** * Tests functionality of Net_FTP::rm() * * @return void * @see Net_FTP::rm() */ public function testRm() { $list1 = $this->ftp->ls(); $this->ftp->put('testfile.dat', 'testfile.dat', FTP_ASCII); $this->ftp->mkdir('dir1/dir2/dir3/dir4', true); $this->ftp->rm('dir1/', true); $this->ftp->rm('testfile.dat'); $list2 = $this->ftp->ls(); $this->assertEquals($list1, $list2, 'Directory listing before creation and'. ' after creation are not equal'); $this->ftp->mkdir('dir1'); $this->ftp->cd('dir1'); $this->ftp->mkdir('dir1'); $this->ftp->mkdir('dir2'); $this->ftp->mkdir('dir3'); $this->ftp->put('testfile.dat', 'testfile.dat', FTP_ASCII); $this->ftp->cd('..'); $this->ftp->rm('dir1/', true, true); $this->ftp->cd('dir1'); $list = $this->_getNames($this->ftp->ls()); $dirs = array('dir1', 'dir2', 'dir3'); sort($list); sort($dirs); $this->assertEquals($list, $dirs, 'The resulting directory listing is not '. 'correct'); } /** * Tests functionality of Net_FTP::putRecursive() * * @return void * @see Net_FTP::putRecursive() */ public function testPutRecursive() { $tmpdir = array(); $tmpfile = array(); $tmpdir[] = System::mktemp(array('-d', 'pearnetftptest')); $tmpdir[] = System::mktemp(array('-t', $tmpdir[0], '-d')); $tmpdir[] = System::mktemp(array('-t', $tmpdir[1], '-d')); $tmpfile[] = System::mktemp(array('-t', $tmpdir[0])); $tmpfile[] = System::mktemp(array('-t', $tmpdir[1])); $tmpfile[] = System::mktemp(array('-t', $tmpdir[2])); $local = $tmpdir[0].DIRECTORY_SEPARATOR; $remote = './'.$this->_getLastPart($tmpdir[0]).'/'; $ret = $this->ftp->putRecursive($local, $remote); $this->assertFalse(PEAR::isError($ret)); for ($i = 0; $i < 3; $i++) { $ret = $this->ftp->cd($this->_getLastPart($tmpdir[$i]).'/'); $this->assertFalse(PEAR::isError($ret)); $dirlist = $this->ftp->ls(); $this->assertFalse(PEAR::isError($dirlist)); $dirlist = $this->_getNames($dirlist); $dirlistok = array($this->_getLastPart($tmpfile[$i])); if ($i < 2) { $dirlistok[] = $this->_getLastPart($tmpdir[$i+1]); } sort($dirlist); sort($dirlistok); $this->assertEquals($dirlist, $dirlistok); } } /** * Tests functionality of Net_FTP::put() * * @return void * @see Net_FTP::put() */ public function testPut() { $res = $this->ftp->put('testfile.dat', 'testfile.dat', true, FTP_ASCII, NET_FTP_BLOCKING | NET_FTP_NONBLOCKING); $this->assertTrue(PEAR::isError($res), 'No error return while it should'); if (PEAR::isError($res)) { $this->assertEquals($res->getCode(), NET_FTP_ERR_BADOPTIONS, 'Bad error code returned'); } } /** * Tests functionality of Net_FTP::_makeDirPermissions() * * @return void * @see Net_FTP::_makeDirPermissions() */ public function testMakeDirPermissions() { $tests = array( '111' => '111', '110' => '110', '444' => '555', '412' => '512', '641' => '751', '666' => '777', '400' => '500', '040' => '050', '004' => '005', ); foreach ($tests AS $in => $out) { $this->assertEquals($this->ftp->_makeDirPermissions($in), $out); } } /** * Tests functionality of Net_FTP::size() * * @return void * @see Net_FTP::size() */ public function testSize() { // upload in binary to avoid addition/removal of characters $this->ftp->put('testfile.dat', 'testfile.dat', FTP_BINARY); $this->assertEquals($this->ftp->size('testfile.dat'), filesize('testfile.dat')); } /** * Tests functionality of Net_FTP::setMode(), Net_FTP::checkFileExtension(), * Net_FTP::addExtension() and Net_FTP::removeExtension() * * @return void * @see Net_FTP::checkFileExtension(), Net_FTP::addExtension(), * Net_FTP::removeExtension(), Net_FTP::setMode() */ public function testExtensions() { $this->ftp->setMode(FTP_ASCII); $this->ftp->addExtension(FTP_BINARY, 'tst'); $this->assertEquals($this->ftp->checkFileExtension('test.tst'), FTP_BINARY); $this->ftp->removeExtension('tst'); $this->assertEquals($this->ftp->checkFileExtension('test.tst'), FTP_ASCII); $this->ftp->setMode(FTP_BINARY); $this->assertEquals($this->ftp->checkFileExtension('test.tst'), FTP_BINARY); } /** * Tests functionality of Net_FTP::getExtensionsFile() * * @return void * @see Net_FTP::getExtensionsFile() */ public function testGetExtensionsFile() { $res = $this->ftp->getExtensionsFile('extensions.ini'); $this->assertFalse(PEAR::isError($res), 'Test extensions file could be'. 'loaded'); $this->ftp->setMode(FTP_BINARY); $this->assertEquals($this->ftp->checkFileExtension('test.asc'), FTP_ASCII); $this->ftp->setMode(FTP_ASCII); $this->assertEquals($this->ftp->checkFileExtension('test.gif'), FTP_BINARY); } /** * Tests functionality of Net_FTP::setDirMatcher() * * @since 1.4.0a1 * @return void */ public function testSetDirMatcher() { $pattern = '/(?:(d)|.)([rwxt-]+)\s+(\w+)\s+(\w+)\s+(\w+)\s(\w+\s+\d+\s+.+)'. '\s+(.+)/'; $map = array( 'is_dir' => 1, 'rights' => 2, 'user' => 3, 'group' => 4, 'size' => 5, 'date' => 6, 'name' => 7, ); $res = $this->ftp->setDirMatcher(false, false); $this->assertTrue(PEAR::isError($res) && $res->getCode() == NET_FTP_ERR_ILLEGALPATTERN, 'Result of setDirMatcher(boolean, boolean) should give a '. 'NET_FTP_ERR_ILLEGALPATTERN error'); $res = $this->ftp->setDirMatcher($pattern, false); $this->assertTrue(PEAR::isError($res) && $res->getCode() == NET_FTP_ERR_ILLEGALMAP, 'Result of setDirMatcher(string, boolean) should give a '. 'NET_FTP_ERR_ILLEGALMAP error'); $res = $this->ftp->setDirMatcher($pattern, array('a' => 'b')); $this->assertTrue(PEAR::isError($res) && $res->getCode() == NET_FTP_ERR_ILLEGALMAPVALUE, 'The items in a matcher map should only contain numeric values'); $res = $this->ftp->setDirMatcher($pattern, $map); $this->assertFalse(PEAR::isError($res), 'A valid pattern and map should return no error'); } /** * Tests changes made to fix bug #9611 * * @since 1.4.0a1 * @return void */ public function testCheckRemoteDir() { $res = $this->ftp->_checkRemoteDir('test'); $this->assertFalse($res, 'test should not be a directory'); $this->ftp->put('testfile.dat', 'test', FTP_BINARY); $res = $this->ftp->_checkRemoteDir('test'); $this->assertFalse($res, 'test should not be a directory'); $this->ftp->rm('test'); $this->ftp->mkdir('test'); $res = $this->ftp->_checkRemoteDir('test'); $this->assertTrue($res, 'test should be a directory'); } /** * Tests _determineOSMatch * * @return void * @see Net_FTP::_determineOSMatch() */ public function testDetermineOSMatch() { $dirlist = array( 'drwxrwsr-x 75 upload. (?). 3008 Oct 30 21:09 ftp1', ); $res = $this->ftp->_determineOSMatch($dirlist); $this->assertFalse(PEAR::isError($res), 'The directory listing should be recognized'); $this->assertEquals($res['pattern'], $this->ftp->_ls_match['unix']['pattern'], 'The input should be parsed by the unix pattern'); } /** * Return all name keys in the elements of an array, leaving out . and .. * * @param array $in Multidimensional array * * @return array Array containing name keys */ function _getNames($in) { $return = array(); foreach ($in as $v) { if ($v['name'] != '.' && $v['name'] != '..') { $return[] = $v['name']; } } return $return; } /** * Return the last element of a local path * * @param string $in Path * * @return array Last part of path */ function _getLastPart($in) { $start = strrpos($in, DIRECTORY_SEPARATOR) + 1; return substr($in, $start); } } // Call Net_FTPTest::main() if this source file is executed directly. if (PHPUnit_MAIN_METHOD == 'Net_FTPTest::main') { Net_FTPTest::main(); } ?> Net_FTP-1.4.0/tests/testfile.dat0000664000175000017500000000000012500046241015776 0ustar kguestkguestNet_FTP-1.4.0/CHANGELOG0000664000175000017500000001205212500046241013547 0ustar kguestkguest1.4.0a3 - 2008-??-?? * Fixed Bug #13946: Test Failed : testPutRecursive * Fixed Bug #14513: Timestamp when using the LS function * Implemented Request #14773: setPassive possible before connecting 1.4.0a2 - 2008-05-19 * Fixed Bug #13496: set bit not supported * Fixed Bug #13689: . in file owner or group name breaks _ls_match * Fixed Bug #13690: getRecursive does not work because of '.' and '..' directories * Fixed Bug #13114: Error check in $FTP->getRecursive(...) * Implemented Request #13104: connect() <> $this->handle in login() * Fixed Bug #13917: putRecursive always return PEAR::Error * Fixed Bug #13850: inclusion of Net/FTP.php in tests doesn't always work * Implemented Request #2271: New flag for _rm_dir_recursive to leave directory structure intact * Implemented Request #6806: Allow recursive up-/download with only adding newer files 1.4.0a1 - 2007-12-22 * Fixed bug #6754: Add method to set directory list matcher explicitly * Fixed Bug #7102: Add ability to disable use of ftp_nb_put(), can sometimes be very slow * Improved detection of remote directories. It is slower than before, but does not rely on simply detecting if the given path ends with a slash. 1.3.7 - 2008-05-19 * Fixed Bug #13917: putRecursive always return PEAR::Error * Fixed Bug #13850: inclusion of Net/FTP.php in tests doesn't always work 1.3.6 - 2008-05-06 * Fixed Bug #13496: set bit not supported * Fixed Bug #13689: . in file owner or group name breaks _ls_match * Fixed Bug #13690: getRecursive does not work because of '.' and '..' directories * Fixed Bug #13114: Error check in $FTP->getRecursive(...) 1.3.5 - 2008-01-13 * Fixed Bug #12840: Fix compliance with PHP 4 (broken since 1.3.3) 1.3.4 - 2007-12-10 * Fixed Bug #12639: _constructPath() prevents _checkDir() from working correctly 1.3.3 - 2007-12-06 * Fixed Bug #7146: Recursive mkdir() broken on Windows * Fixed Bug #7270: Recursive rmdir() broken * Fixed Bug #7527: ls fails if there are no files and a total line * Fixed Bug #8102: Loading file extension and checking extension gives binary for ascii files * Fixed Bug #9611: (, ? and ) break detection of the unix platform * Fixed Bug #10237: put() doesn't run ftp_alloc to allocate space * PEAR Coding Style Valid * Removed package.xml version 1.0 1.3.2 - 2006-02-11 * Fixed Bug #4102: Problem detecting os method ls(). * Fixed Bug #5337: _list_and_parse behavior with an empty remote directory. * Fixed Bug #4836: Off-by-one error in regex for Windows directory listings. * Fixed Bug #4749: ls() fails when connection is closed. * Fixed Bug #4969: Recursive rm ends in endless loop. * Fixed Bug #5895: Recursive chmod ends in endless loop 1.3.1 - 2005-04-07 * Fix bug #3778 "Notice of Uninitialized string offset in function _rm_dir_recursive" * Fix bug #4008 "_list_and_parse tries to determine OS on an empty list" * Fix bug #4009 "_determine_os_match doesn't take into account numbered users and groups" 1.3.0 - 2005-03-31 - Updated year. - Updated docblocks regarding the new standard. - Fixed whitespace issues. - Fixed bug 3362: bug in Net_FTP::_rm_file. - Added PEAR 1.4 compatible package2.xml (package.xml version 2.0). 1.3.0RC2 2005-01-04 * Added example for observer. * Fixed CS issues. * Fixed bug #2654: mkdir() should not fail if the directory already exists. * Fixed bug #2648: if ls() returns array(), net_FTP bails. * Fixed some unknown small bugs. 1.3.0RC1 2004-09-23 * Fixed bug #2268: getRecursive does not work because of '.' and '..' directories. 1.3.0beta4 2004-06-28 * Optimized OS determination. Thanks to Eric Quilantang. * Added ability to set timeout in constructor. * Added much more error handling. * Added real error codes with full documentation. * Fix bug #1176: Net_FTP::ls can return dates in the future. * Fix bug #1446: Bug in isPassive(). * Fix bug #1480 _list_and_parse() may throw warnings. * Fix bug #1445 Improvement of setTimeout() method + timout handling. * Renamed makeDirPermissions() to _makeDirPermissions(), since it's private (CS). * Fix './' syntax for pathes. 1.3.0beta3 2004-05-25 * Added "t" for permission regex (some servers mark speacial dirs). * Added better support for different ls formats (thanks for hint by George Kearns). 1.3.0beta2 2004-03-20 * Added patch by Ilja Polivanovas to enable correct directory permissions. * Added rename() functionality. Thanks to the unnamed coder from "Webmestre ESGI" . 1.3.0beta1 2004-03-14 * Fixed bug #336: ftp_login displays Warning. * Fixed bug #813: ftp_nb_put function abort when mode is null. * Fixed bug #240: mkdir() with $recursive===true doesn't support "single" directories. * Fixed bug #723: Timeout for connect cannot be set. * Fixed bug #918: getRecursive() corrupts binary file. * Fixed typos. 1.2 2003-09-29 Fixes some typos and bugs. 1.1 2003-07-22 Fix for FatalError on Line 834 (rmrecursive()). 1.0 2003-07-15 - Fixed different typos in code, comments and example. - Fixed recursive deletion trying to remove "." and ".." entries in the directorylist. - Fixed uploading above 4096 byte, when using ftp_nb_put() 0.9 2003-02-22 Unknown 0.5 2002-12-20 First release Net_FTP-1.4.0/README0000664000175000017500000000101312500046241013210 0ustar kguestkguestThis package is http://pear.php.net/package/Net_FTP and has been migrated from http://svn.php.net/repository/pear/packages/Net_FTP Please report all new issues via the PEAR bug tracker. If this package is marked as unmaintained and you have fixes, please submit your pull requests and start discussion on the pear-qa mailing list. To test, run either $ phpunit tests/ or $ pear run-tests -r To build, simply $ pear package To install from scratch $ pear install package.xml To upgrade $ pear upgrade -f package.xml