/var/www/vhosts/nabawater/vendor/codeception/base/src/Codeception/Module
Edit: /var/www/vhosts/nabawater/vendor/codeception/base/src/Codeception/Module/FTP.php (24003B)
'ftp',
'port' => 21,
'timeout' => 90,
'user' => 'anonymous',
'password' => '',
'key' => '',
'tmp' => 'tests/_data',
'passive' => false,
'cleanup' => true
];
/**
* Required configuration fields
*
* @var array
*/
protected $requiredFields = ['host'];
// ----------- SETUP METHODS BELOW HERE -------------------------//
/**
* Setup connection and login with config settings
*
* @param \Codeception\TestInterface $test
*/
public function _before(TestInterface $test)
{
// Login using config settings
$this->loginAs($this->config['user'], $this->config['password']);
}
/**
* Close the FTP connection & Clear up
*/
public function _after(TestInterface $test)
{
$this->_closeConnection();
// Clean up temp files
if ($this->config['cleanup']) {
if (file_exists($this->config['tmp'] . '/ftp_data_file.tmp')) {
unlink($this->config['tmp'] . '/ftp_data_file.tmp');
}
}
}
/**
* Change the logged in user mid-way through your test, this closes the
* current connection to the server and initialises and new connection.
*
* On initiation of this modules you are automatically logged into
* the server using the specified config options or defaulted
* to anonymous user if not provided.
*
* ``` php
* loginAs('user','password');
* ?>
* ```
*
* @param String $user
* @param String $password
*/
public function loginAs($user = 'anonymous', $password = '')
{
$this->_openConnection($user, $password); // Create new connection and login.
}
/**
* Enters a directory on the ftp system - FTP root directory is used by default
*
* @param $path
*/
public function amInPath($path)
{
$this->_changeDirectory($this->path = $this->absolutizePath($path) . ($path == '/' ? '' : DIRECTORY_SEPARATOR));
$this->debug('Moved to ' . $this->path);
}
/**
* Resolve path
*
* @param $path
* @return string
*/
protected function absolutizePath($path)
{
if (strpos($path, '/') === 0) {
return $path;
}
return $this->path . $path;
}
// ----------- SEARCH METHODS BELOW HERE ------------------------//
/**
* Checks if file exists in path on the remote FTP/SFTP system.
* DOES NOT OPEN the file when it's exists
*
* ``` php
* seeFileFound('UserModel.php','app/models');
* ?>
* ```
*
* @param $filename
* @param string $path
*/
public function seeFileFound($filename, $path = '')
{
$files = $this->grabFileList($path);
$this->debug("see file: {$filename}");
$this->assertContains($filename, $files, "file {$filename} not found in {$path}");
}
/**
* Checks if file exists in path on the remote FTP/SFTP system, using regular expression as filename.
* DOES NOT OPEN the file when it's exists
*
* ``` php
* seeFileFoundMatches('/^UserModel_([0-9]{6}).php$/','app/models');
* ?>
* ```
*
* @param $regex
* @param string $path
*/
public function seeFileFoundMatches($regex, $path = '')
{
foreach ($this->grabFileList($path) as $filename) {
preg_match($regex, $filename, $matches);
if (!empty($matches)) {
$this->debug("file '{$filename}' matches '{$regex}'");
return;
}
}
$this->fail("no file matches found for '{$regex}'");
}
/**
* Checks if file does not exist in path on the remote FTP/SFTP system
*
* @param $filename
* @param string $path
*/
public function dontSeeFileFound($filename, $path = '')
{
$files = $this->grabFileList($path);
$this->debug("don't see file: {$filename}");
$this->assertNotContains($filename, $files);
}
/**
* Checks if file does not exist in path on the remote FTP/SFTP system, using regular expression as filename.
* DOES NOT OPEN the file when it's exists
*
* @param $regex
* @param string $path
*/
public function dontSeeFileFoundMatches($regex, $path = '')
{
foreach ($this->grabFileList($path) as $filename) {
preg_match($regex, $filename, $matches);
if (!empty($matches)) {
$this->fail("file matches found for {$regex}");
}
}
$this->assertTrue(true);
$this->debug("no files match '{$regex}'");
}
// ----------- UTILITY METHODS BELOW HERE -------------------------//
/**
* Opens a file (downloads from the remote FTP/SFTP system to a tmp directory for processing)
* and stores it's content.
*
* Usage:
*
* ``` php
* openFile('composer.json');
* $I->seeInThisFile('codeception/codeception');
* ?>
* ```
*
* @param $filename
*/
public function openFile($filename)
{
$this->_openFile($this->absolutizePath($filename));
}
/**
* Saves contents to tmp file and uploads the FTP/SFTP system.
* Overwrites current file on server if exists.
*
* ``` php
* writeToFile('composer.json', 'some data here');
* ?>
* ```
*
* @param $filename
* @param $contents
*/
public function writeToFile($filename, $contents)
{
$this->_writeToFile($this->absolutizePath($filename), $contents);
}
/**
* Create a directory on the server
*
* ``` php
* makeDir('vendor');
* ?>
* ```
*
* @param $dirname
*/
public function makeDir($dirname)
{
$this->makeDirectory($this->absolutizePath($dirname));
}
/**
* Currently not supported in this module, overwrite inherited method
*
* @param $src
* @param $dst
*/
public function copyDir($src, $dst)
{
$this->fail('copyDir() currently unsupported by FTP module');
}
/**
* Rename/Move file on the FTP/SFTP server
*
* ``` php
* renameFile('composer.lock', 'composer_old.lock');
* ?>
* ```
*
* @param $filename
* @param $rename
*/
public function renameFile($filename, $rename)
{
$this->renameDirectory($this->absolutizePath($filename), $this->absolutizePath($rename));
}
/**
* Rename/Move directory on the FTP/SFTP server
*
* ``` php
* renameDir('vendor', 'vendor_old');
* ?>
* ```
*
* @param $dirname
* @param $rename
*/
public function renameDir($dirname, $rename)
{
$this->renameDirectory($this->absolutizePath($dirname), $this->absolutizePath($rename));
}
/**
* Deletes a file on the remote FTP/SFTP system
*
* ``` php
* deleteFile('composer.lock');
* ?>
* ```
*
* @param $filename
*/
public function deleteFile($filename)
{
$this->delete($this->absolutizePath($filename));
}
/**
* Deletes directory with all subdirectories on the remote FTP/SFTP server
*
* ``` php
* deleteDir('vendor');
* ?>
* ```
*
* @param $dirname
*/
public function deleteDir($dirname)
{
$this->delete($this->absolutizePath($dirname));
}
/**
* Erases directory contents on the FTP/SFTP server
*
* ``` php
* cleanDir('logs');
* ?>
* ```
*
* @param $dirname
*/
public function cleanDir($dirname)
{
$this->clearDirectory($this->absolutizePath($dirname));
}
// ----------- GRABBER METHODS BELOW HERE -----------------------//
/**
* Grabber method for returning file/folders listing in an array
*
* ```php
* grabFileList();
* $count = $I->grabFileList('TEST', false); // Include . .. .thumbs.db
* ?>
* ```
*
* @param string $path
* @param bool $ignore - suppress '.', '..' and '.thumbs.db'
* @return array
*/
public function grabFileList($path = '', $ignore = true)
{
$absolutize_path = $this->absolutizePath($path)
. ($path != '' && substr($path, -1) != '/' ? DIRECTORY_SEPARATOR : '');
$files = $this->_listFiles($absolutize_path);
$display_files = [];
if (is_array($files) && !empty($files)) {
$this->debug('File List:');
foreach ($files as &$file) {
if (strtolower($file) != '.' &&
strtolower($file) != '..' &&
strtolower($file) != 'thumbs.db'
) { // Ignore '.', '..' and 'thumbs.db'
// Replace full path from file listings if returned in listing
$file = str_replace(
$absolutize_path,
'',
$file
);
$display_files[] = $file;
$this->debug(' - ' . $file);
}
}
return $ignore ? $display_files : $files;
}
$this->debug("File List:
");
return [];
}
/**
* Grabber method for returning file/folders count in directory
*
* ```php
* grabFileCount();
* $count = $I->grabFileCount('TEST', false); // Include . .. .thumbs.db
* ?>
* ```
*
* @param string $path
* @param bool $ignore - suppress '.', '..' and '.thumbs.db'
* @return int
*/
public function grabFileCount($path = '', $ignore = true)
{
$count = count($this->grabFileList($path, $ignore));
$this->debug("File Count: {$count}");
return $count;
}
/**
* Grabber method to return file size
*
* ```php
* grabFileSize('test.txt');
* ?>
* ```
*
* @param $filename
* @return bool
*/
public function grabFileSize($filename)
{
$fileSize = $this->size($filename);
$this->debug("{$filename} has a file size of {$fileSize}");
return $fileSize;
}
/**
* Grabber method to return last modified timestamp
*
* ```php
* grabFileModified('test.txt');
* ?>
* ```
*
* @param $filename
* @return bool
*/
public function grabFileModified($filename)
{
$time = $this->modified($filename);
$this->debug("{$filename} was last modified at {$time}");
return $time;
}
/**
* Grabber method to return current working directory
*
* ```php
* grabDirectory();
* ?>
* ```
*
* @return string
*/
public function grabDirectory()
{
$pwd = $this->_directory();
$this->debug("PWD: {$pwd}");
return $pwd;
}
// ----------- SERVER CONNECTION METHODS BELOW HERE -------------//
/**
* Open a new FTP/SFTP connection and authenticate user.
*
* @param string $user
* @param string $password
*/
private function _openConnection($user = 'anonymous', $password = '')
{
$this->_closeConnection(); // Close connection if already open
if ($this->isSFTP()) {
$this->sftpConnect($user, $password);
} else {
$this->ftpConnect($user, $password);
}
$pwd = $this->grabDirectory();
$this->path = $pwd . ($pwd == '/' ? '' : DIRECTORY_SEPARATOR);
}
/**
* Close open FTP/SFTP connection
*/
private function _closeConnection()
{
if (!$this->ftp) {
return;
}
if (!$this->isSFTP()) {
ftp_close($this->ftp);
$this->ftp = null;
}
}
/**
* Get the file listing for FTP/SFTP connection
*
* @param String $path
* @return array
*/
private function _listFiles($path)
{
if ($this->isSFTP()) {
$files = @$this->ftp->nlist($path);
} else {
$files = @ftp_nlist($this->ftp, $path);
}
if ($files === false) {
$this->fail("couldn't list files");
}
return $files;
}
/**
* Get the current directory for the FTP/SFTP connection
*
* @return string
*/
private function _directory()
{
if ($this->isSFTP()) {
// == DIRECTORY_SEPARATOR ? '' : $pwd;
$pwd = @$this->ftp->pwd();
} else {
$pwd = @ftp_pwd($this->ftp);
}
if (!$pwd) {
$this->fail("couldn't get current directory");
}
}
/**
* Change the working directory on the FTP/SFTP server
*
* @param $path
*/
private function _changeDirectory($path)
{
if ($this->isSFTP()) {
$changed = @$this->ftp->chdir($path);
} else {
$changed = @ftp_chdir($this->ftp, $path);
}
if (!$changed) {
$this->fail("couldn't change directory {$path}");
}
}
/**
* Download remote file to local tmp directory and open contents.
*
* @param $filename
*/
private function _openFile($filename)
{
// Check local tmp directory
if (!is_dir($this->config['tmp']) || !is_writeable($this->config['tmp'])) {
$this->fail('tmp directory not found or is not writable');
}
// Download file to local tmp directory
$tmp_file = $this->config['tmp'] . "/ftp_data_file.tmp";
if ($this->isSFTP()) {
$downloaded = @$this->ftp->get($filename, $tmp_file);
} else {
$downloaded = @ftp_get($this->ftp, $tmp_file, $filename, FTP_BINARY);
}
if (!$downloaded) {
$this->fail('failed to download file to tmp directory');
}
// Open file content to variable
if ($this->file = file_get_contents($tmp_file)) {
$this->filepath = $filename;
} else {
$this->fail('failed to open tmp file');
}
}
/**
* Write data to local tmp file and upload to server
*
* @param $filename
* @param $contents
*/
private function _writeToFile($filename, $contents)
{
// Check local tmp directory
if (!is_dir($this->config['tmp']) || !is_writeable($this->config['tmp'])) {
$this->fail('tmp directory not found or is not writable');
}
// Build temp file
$tmp_file = $this->config['tmp'] . "/ftp_data_file.tmp";
file_put_contents($tmp_file, $contents);
// Update variables
$this->filepath = $tmp_file;
$this->file = $contents;
// Upload the file to server
if ($this->isSFTP()) {
$uploaded = @$this->ftp->put($filename, $tmp_file, NET_SFTP_LOCAL_FILE);
} else {
$uploaded = ftp_put($this->ftp, $filename, $tmp_file, FTP_BINARY);
}
if (!$uploaded) {
$this->fail('failed to upload file to server');
}
}
/**
* Make new directory on server
*
* @param $path
*/
private function makeDirectory($path)
{
if ($this->isSFTP()) {
$created = @$this->ftp->mkdir($path, true);
} else {
$created = @ftp_mkdir($this->ftp, $path);
}
if (!$created) {
$this->fail("couldn't make directory {$path}");
}
$this->debug("Make directory: {$path}");
}
/**
* Rename/Move directory/file on server
*
* @param $path
* @param $rename
*/
private function renameDirectory($path, $rename)
{
if ($this->isSFTP()) {
$renamed = @$this->ftp->rename($path, $rename);
} else {
$renamed = @ftp_rename($this->ftp, $path, $rename);
}
if (!$renamed) {
$this->fail("couldn't rename directory {$path} to {$rename}");
}
$this->debug("Renamed directory: {$path} to {$rename}");
}
/**
* Delete file on server
*
* @param $filename
*/
private function delete($filename, $isDir = false)
{
if ($this->isSFTP()) {
$deleted = @$this->ftp->delete($filename, $isDir);
} else {
$deleted = @$this->ftpDelete($filename);
}
if (!$deleted) {
$this->fail("couldn't delete {$filename}");
}
$this->debug("Deleted: {$filename}");
}
/**
* Function to recursively delete folder, used for PHP FTP build in client.
*
* @param $directory
* @return bool
*/
private function ftpDelete($directory)
{
// here we attempt to delete the file/directory
if (!(@ftp_rmdir($this->ftp, $directory) || @ftp_delete($this->ftp, $directory))) {
// if the attempt to delete fails, get the file listing
$filelist = @ftp_nlist($this->ftp, $directory);
// loop through the file list and recursively delete the FILE in the list
foreach ($filelist as $file) {
$this->ftpDelete($file);
}
// if the file list is empty, delete the DIRECTORY we passed
$this->ftpDelete($directory);
}
return true;
}
/**
* Clear directory on server of all content
*
* @param $path
*/
private function clearDirectory($path)
{
$this->debug("Clear directory: {$path}");
$this->delete($path);
$this->makeDirectory($path);
}
/**
* Return the size of a given file
*
* @param $filename
* @return bool
*/
private function size($filename)
{
if ($this->isSFTP()) {
$size = (int)@$this->ftp->size($filename);
} else {
$size = @ftp_size($this->ftp, $filename);
}
if ($size > 0) {
return $size;
}
$this->fail("couldn't get the file size for {$filename}");
}
/**
* Return the last modified time of a given file
*
* @param $filename
* @return bool
*/
private function modified($filename)
{
if ($this->isSFTP()) {
$info = @$this->ftp->lstat($filename);
if ($info) {
return $info['mtime'];
}
} else {
if ($time = @ftp_mdtm($this->ftp, $filename)) {
return $time;
}
}
$this->fail("couldn't get the file size for {$filename}");
}
/**
* @param $user
* @param $password
*/
protected function sftpConnect($user, $password)
{
if (class_exists('Net_SFTP')) {
$this->ftp = new \Net_SFTP($this->config['host'], $this->config['port'], $this->config['timeout']);
} elseif (class_exists('phpseclib\Net\SFTP')) {
$this->ftp = new \phpseclib\Net\SFTP($this->config['host'], $this->config['port'], $this->config['timeout']);
} else {
throw new ModuleException('phpseclib/phpseclib library is not installed');
}
if ($this->ftp === false) {
$this->ftp = null;
$this->fail('failed to connect to ftp server');
}
if (isset($this->config['key'])) {
$keyFile = file_get_contents($this->config['key']);
if (class_exists('Crypt_RSA')) {
$password = new \Crypt_RSA();
} elseif (class_exists('phpseclib\Crypt\RSA')) {
$password = new \phpseclib\Crypt\RSA();
} else {
throw new ModuleException('phpseclib/phpseclib library is not installed');
}
$password->loadKey($keyFile);
}
if (!$this->ftp->login($user, $password)) {
$this->fail('failed to authenticate user');
}
}
/**
* @param $user
* @param $password
*/
protected function ftpConnect($user, $password)
{
$this->ftp = ftp_connect($this->config['host'], $this->config['port'], $this->config['timeout']);
if ($this->ftp === false) {
$this->ftp = null;
$this->fail('failed to connect to ftp server');
}
// Login using given access details
if (!@ftp_login($this->ftp, $user, $password)) {
$this->fail('failed to authenticate user');
}
// Set passive mode option (ftp only option)
if (isset($this->config['passive'])) {
ftp_pasv($this->ftp, $this->config['passive']);
}
}
protected function isSFTP()
{
return strtolower($this->config['type']) == 'sftp';
}
}