src/Access/FTP.php
<?php
// Copyright (c) 2016, Avan.Tech, et. al.
// Copyright (c) 2008, Luis Argerich, Garland Foster, Eduardo Polidor, et. al.
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
namespace TikiManager\Access;
use TikiManager\Application\Tiki\Versions\TikiRequirements;
use TikiManager\Libs\Host\FTP as FTPHost;
use TikiManager\Application\Instance;
class FTP extends Access implements Mountable
{
private $lastMount;
public function __construct(Instance $instance)
{
parent::__construct($instance, 'ftp');
$this->port = 21;
}
// TODO: change directory using FTP
public function openShell($workingDir = '')
{
$this->io->writeln("User: {$this->user}, Pass: {$this->password}");
passthru("ftp {$this->host} {$this->port}");
}
public function getHost()
{
return new FTPHost($this->host, $this->user, $this->password, $this->port);
}
public function firstConnect()
{
$conn = $this->getHost();
return $conn->connect();
}
public function getInterpreterPath(TikiRequirements $requirements = null)
{
$result = $this->runPHP(
dirname(__FILE__) . '/../../scripts/checkversion.php',
[$this->instance->webroot]
);
if (preg_match('/^[5-9]\./', $result)) {
return 'mod_php';
}
}
public function getSVNPath()
{
return 1;
}
public function getInterpreterVersion($interpreter)
{
return 99999;
}
public function getDistributionName($interpreter)
{
return 'Unknown';
}
public function createDirectory($path)
{
$ftp = $this->getHost();
return $ftp->createDirectory($path);
}
public function fileExists($filename)
{
if ($filename[0] != '/') {
$filename = $this->instance->getWebPath($filename);
}
$ftp = $this->getHost();
return $ftp->fileExists($filename);
}
public function fileGetContents($filename)
{
$ftp = $this->getHost();
return $ftp->getContent($filename);
}
public function fileModificationDate($filename)
{
}
public function runPHP($localFile, $args = [])
{
foreach ($args as & $potentialPath) {
if ($potentialPath[0] == '/') {
$potentialPath = $this->obtainRelativePathTo(
$potentialPath,
$this->instance->webroot
);
}
}
$host = $this->getHost();
$remoteName = 'trim_' . md5($localFile) . '.php';
$remoteFile = $this->instance->getWebPath($remoteName);
array_unshift($args, null);
$arg = http_build_query($args, '', '&');
$host->sendFile($localFile, $remoteFile);
$output = file_get_contents($this->instance->getWebUrl($remoteName) . '?' . $arg);
$host->removeFile($remoteFile);
return $output;
}
public function downloadFile($filename, $target = ''): string
{
if ($filename[0] != '/') {
$filename = $this->instance->getWebPath($filename);
}
$dot = strrpos($filename, '.');
$ext = substr($filename, $dot);
$local = tempnam($_ENV['TEMP_FOLDER'], 'trim');
$host = $this->getHost();
$host->receiveFile($filename, $local);
rename($local, $local . $ext);
chmod($local . $ext, 0644);
return $local . $ext;
}
public function uploadFile($filename, $remoteLocation)
{
$host = $this->getHost();
if ($remoteLocation[0] == '/') {
$host->sendFile($filename, $remoteLocation);
} else {
$host->sendFile($filename, $this->instance->getWebPath($remoteLocation));
}
}
public function moveFile($remoteSource, $remoteTarget)
{
if ($remoteSource[0] != '/') {
$remoteSource = $this->instance->getWebPath($remoteSource);
}
if ($remoteTarget[0] != '/') {
$remoteTarget = $this->instance->getWebPath($remoteTarget);
}
$host = $this->getHost();
$host->rename($remoteSource, $remoteTarget);
}
public function copyFile($remoteSource, $remoteTarget)
{
if ($remoteSource[0] != '/') {
$remoteSource = $this->instance->getWebPath($remoteSource);
}
if ($remoteTarget[0] != '/') {
$remoteTarget = $this->instance->getWebPath($remoteTarget);
}
$host = $this->getHost();
$host->copy($remoteSource, $remoteTarget);
}
public function deleteFile($filename)
{
if ($filename[0] != '/') {
$filename = $this->instance->getWebPath($filename);
}
$host = $this->getHost();
$host->removeFile($filename);
}
public function localizeFolder($remoteLocation, $localMirror)
{
if ($remoteLocation[0] != '/') {
$remoteLocation = $this->instance->getWebPath($remoteLocation);
}
$compress = in_array('zlib', $this->instance->getExtensions());
$name = md5(time()) . '.tar';
if ($compress) {
$name .= '.gz';
}
$remoteTar = $this->instance->getWebPath($name);
$this->runPHP(
dirname(__FILE__) . '/../../scripts/package_tar.php',
[$remoteTar, $remoteLocation]
);
$localized = $this->downloadFile($remoteTar);
$this->deleteFile($remoteTar);
$current = getcwd();
if (! file_exists($localMirror)) {
mkdir($localMirror);
}
chdir($localMirror);
$eLoc = escapeshellarg($localized);
if ($compress) {
passthru("tar -zxf $eLoc");
} else {
`tar -xf $eLoc`;
}
chdir($current);
}
public static function obtainRelativePathTo($targetFolder, $originFolder)
{
$parts = [];
while ((0 !== strpos($targetFolder, $originFolder))
&& $originFolder != '/' && $originFolder != '') {
$originFolder = dirname($originFolder);
$parts[] = '..';
}
$out = null;
if (strpos($targetFolder, $originFolder) === false) {
// Target is under the origin
$relative = substr($targetFolder, strlen($originFolder));
$out = ltrim(implode('/', $parts) . '/' . ltrim($relative, '/'), '/');
}
if (empty($out)) {
$out = '.';
}
return $out;
}
public function mount($target)
{
if ($this->lastMount) {
return false;
}
$ftp = $this->getHost();
$pwd = $ftp->getPWD();
$toRoot = preg_replace('/\w+/', '..', $pwd);
$this->lastMount = $target;
$remote = escapeshellarg("ftp://{$this->user}:{$this->password}@{$this->host}$toRoot");
$local = escapeshellarg($target);
$cmd = "curlftpfs $remote $local";
shell_exec($cmd);
return true;
}
public function umount()
{
if ($this->lastMount) {
$loc = escapeshellarg($this->lastMount);
`sudo umount $loc`;
$this->lastMount = null;
}
}
public function synchronize($source, $mirror, $keepFolderName = false)
{
$source = rtrim($source, '/') . ($keepFolderName ? '' : '/');
$mirror = rtrim($mirror, '/') . '/';
$source = escapeshellarg($source);
$target = escapeshellarg($mirror);
$tmp = escapeshellarg($_ENV['RSYNC_FOLDER']);
$cmd = 'rsync -rDu --no-p --no-g --size-only ' .
'--exclude .svn --exclude copyright.txt --exclude changelog.txt ' .
"--temp-dir=$tmp $source $target";
passthru($cmd);
}
public function copyLocalFolder($localFolder, $remoteFolder = '')
{
if ($remoteFolder[0] != '/') {
$remoteFolder = $this->instance->getWebPath($remoteFolder);
}
$compress = in_array('zlib', $this->instance->getExtensions());
$current = getcwd();
chdir($localFolder);
$temp = $_ENV['TEMP_FOLDER'];
$name = md5(time()) . '.tar';
`chmod 777 db`;
`tar --exclude=.svn -cf $temp/$name *`;
if ($compress) {
`gzip -5 $temp/$name`;
$name .= '.gz';
}
chdir($current);
$this->uploadFile("$temp/$name", $name);
unlink("$temp/$name");
$this->runPHP(
dirname(__FILE__) . '/../../scripts/extract_tar.php',
[$name, $remoteFolder]
);
$this->deleteFile($name);
}
public function isEmptyDir($path): bool
{
if ($path[0] != '/') {
$path = $this->instance->getWebPath($path);
}
$ftp = $this->getHost();
$dirContents = $ftp->listFiles($path);
return empty($dirContents);
}
}