%PDF- %PDF-
| Direktori : /home/tjamichg/cursos.tjamich.gob.mx/vendor/knplabs/gaufrette/src/Gaufrette/Adapter/ |
| Current File : /home/tjamichg/cursos.tjamich.gob.mx/vendor/knplabs/gaufrette/src/Gaufrette/Adapter/Ftp.php |
<?php
namespace Gaufrette\Adapter;
use Gaufrette\Adapter;
use Gaufrette\File;
use Gaufrette\Filesystem;
/**
* Ftp adapter.
*
* @author Antoine Hérault <antoine.herault@gmail.com>
*/
class Ftp implements Adapter, FileFactory, ListKeysAware, SizeCalculator
{
/** @var null|resource|\FTP\Connection */
protected $connection = null;
protected $directory;
protected $host;
protected $port;
protected $username;
protected $password;
protected $passive;
protected $create;
protected $mode;
protected $ssl;
protected $timeout;
protected $fileData = [];
protected $utf8;
/**
* @param string $directory The directory to use in the ftp server
* @param string $host The host of the ftp server
* @param array $options The options like port, username, password, passive, create, mode
*/
public function __construct($directory, $host, $options = [])
{
if (!extension_loaded('ftp')) {
throw new \RuntimeException('Unable to use Gaufrette\Adapter\Ftp as the FTP extension is not available.');
}
$this->directory = (string) $directory;
$this->host = $host;
$this->port = $options['port'] ?? 21;
$this->username = $options['username'] ?? null;
$this->password = $options['password'] ?? null;
$this->passive = $options['passive'] ?? false;
$this->create = $options['create'] ?? false;
$this->mode = $options['mode'] ?? FTP_BINARY;
$this->ssl = $options['ssl'] ?? false;
$this->timeout = $options['timeout'] ?? 90;
$this->utf8 = $options['utf8'] ?? false;
}
/**
* {@inheritdoc}
*/
public function read($key)
{
$this->ensureDirectoryExists($this->directory, $this->create);
$temp = fopen('php://temp', 'r+');
if (!ftp_fget($this->getConnection(), $temp, $this->computePath($key), $this->mode)) {
return false;
}
rewind($temp);
$contents = stream_get_contents($temp);
fclose($temp);
return $contents;
}
/**
* {@inheritdoc}
*/
public function write($key, $content)
{
$this->ensureDirectoryExists($this->directory, $this->create);
$path = $this->computePath($key);
$directory = \Gaufrette\Util\Path::dirname($path);
$this->ensureDirectoryExists($directory, true);
$temp = fopen('php://temp', 'r+');
$size = fwrite($temp, $content);
rewind($temp);
if (!ftp_fput($this->getConnection(), $path, $temp, $this->mode)) {
fclose($temp);
return false;
}
fclose($temp);
return $size;
}
/**
* {@inheritdoc}
*/
public function rename($sourceKey, $targetKey)
{
$this->ensureDirectoryExists($this->directory, $this->create);
$sourcePath = $this->computePath($sourceKey);
$targetPath = $this->computePath($targetKey);
$this->ensureDirectoryExists(\Gaufrette\Util\Path::dirname($targetPath), true);
return ftp_rename($this->getConnection(), $sourcePath, $targetPath);
}
/**
* {@inheritdoc}
*/
public function exists($key)
{
$this->ensureDirectoryExists($this->directory, $this->create);
$file = $this->computePath($key);
$lines = ftp_rawlist($this->getConnection(), '-al ' . \Gaufrette\Util\Path::dirname($file));
if (false === $lines) {
return false;
}
$pattern = '{(?<!->) ' . preg_quote(basename($file)) . '( -> |$)}m';
foreach ($lines as $line) {
if (preg_match($pattern, $line)) {
return true;
}
}
return false;
}
/**
* {@inheritdoc}
*/
public function keys()
{
$this->ensureDirectoryExists($this->directory, $this->create);
$keys = $this->fetchKeys();
return $keys['keys'];
}
/**
* {@inheritdoc}
*/
public function listKeys($prefix = '')
{
$this->ensureDirectoryExists($this->directory, $this->create);
preg_match('/(.*?)[^\/]*$/', $prefix, $match);
$directory = rtrim($match[1], '/');
$keys = $this->fetchKeys($directory, false);
if ($directory === $prefix) {
return $keys;
}
$filteredKeys = [];
foreach (['keys', 'dirs'] as $hash) {
$filteredKeys[$hash] = [];
foreach ($keys[$hash] as $key) {
if (0 === strpos($key, $prefix)) {
$filteredKeys[$hash][] = $key;
}
}
}
return $filteredKeys;
}
/**
* {@inheritdoc}
*/
public function mtime($key)
{
$this->ensureDirectoryExists($this->directory, $this->create);
$mtime = ftp_mdtm($this->getConnection(), $this->computePath($key));
// the server does not support this function
if (-1 === $mtime) {
throw new \RuntimeException('Server does not support ftp_mdtm function.');
}
return $mtime;
}
/**
* {@inheritdoc}
*/
public function delete($key)
{
$this->ensureDirectoryExists($this->directory, $this->create);
if ($this->isDirectory($key)) {
return ftp_rmdir($this->getConnection(), $this->computePath($key));
}
return ftp_delete($this->getConnection(), $this->computePath($key));
}
/**
* {@inheritdoc}
*/
public function isDirectory($key)
{
$this->ensureDirectoryExists($this->directory, $this->create);
return $this->isDir($this->computePath($key));
}
/**
* Lists files from the specified directory. If a pattern is
* specified, it only returns files matching it.
*
* @param string $directory The path of the directory to list from
*
* @return array An array of keys and dirs
*/
public function listDirectory($directory = '')
{
$this->ensureDirectoryExists($this->directory, $this->create);
$directory = preg_replace('/^[\/]*([^\/].*)$/', '/$1', $directory);
$items = $this->parseRawlist(
ftp_rawlist($this->getConnection(), '-al ' . $this->directory . $directory) ?: []
);
$fileData = $dirs = [];
foreach ($items as $itemData) {
if ('..' === $itemData['name'] || '.' === $itemData['name']) {
continue;
}
$item = [
'name' => $itemData['name'],
'path' => trim(($directory ? $directory . '/' : '') . $itemData['name'], '/'),
'time' => $itemData['time'],
'size' => $itemData['size'],
];
if ('-' === substr($itemData['perms'], 0, 1)) {
$fileData[$item['path']] = $item;
} elseif ('d' === substr($itemData['perms'], 0, 1)) {
$dirs[] = $item['path'];
}
}
$this->fileData = array_merge($fileData, $this->fileData);
return [
'keys' => array_keys($fileData),
'dirs' => $dirs,
];
}
/**
* {@inheritdoc}
*/
public function createFile($key, Filesystem $filesystem)
{
$this->ensureDirectoryExists($this->directory, $this->create);
$file = new File($key, $filesystem);
if (!array_key_exists($key, $this->fileData)) {
$dirname = \Gaufrette\Util\Path::dirname($key);
$directory = $dirname == '.' ? '' : $dirname;
$this->listDirectory($directory);
}
if (isset($this->fileData[$key])) {
$fileData = $this->fileData[$key];
$file->setName($fileData['name']);
$file->setSize($fileData['size']);
}
return $file;
}
/**
* @param string $key
*
* @return int
*
* @throws \RuntimeException
*/
public function size($key)
{
$this->ensureDirectoryExists($this->directory, $this->create);
if (-1 === $size = ftp_size($this->connection, $key)) {
throw new \RuntimeException(sprintf('Unable to fetch the size of "%s".', $key));
}
return $size;
}
/**
* Ensures the specified directory exists. If it does not, and the create
* parameter is set to TRUE, it tries to create it.
*
* @param string $directory
* @param bool $create Whether to create the directory if it does not
* exist
*
* @throws RuntimeException if the directory does not exist and could not
* be created
*/
protected function ensureDirectoryExists($directory, $create = false)
{
if (!$this->isDir($directory)) {
if (!$create) {
throw new \RuntimeException(sprintf('The directory \'%s\' does not exist.', $directory));
}
$this->createDirectory($directory);
}
}
/**
* Creates the specified directory and its parent directories.
*
* @param string $directory Directory to create
*
* @throws RuntimeException if the directory could not be created
*/
protected function createDirectory($directory)
{
// create parent directory if needed
$parent = \Gaufrette\Util\Path::dirname($directory);
if (!$this->isDir($parent)) {
$this->createDirectory($parent);
}
// create the specified directory
$created = ftp_mkdir($this->getConnection(), $directory);
if (false === $created) {
throw new \RuntimeException(sprintf('Could not create the \'%s\' directory.', $directory));
}
}
/**
* @param string $directory - full directory path
*
* @return bool
*/
private function isDir($directory)
{
if ('/' === $directory) {
return true;
}
if (!@ftp_chdir($this->getConnection(), $directory)) {
return false;
}
// change directory again to return in the base directory
ftp_chdir($this->getConnection(), $this->directory);
return true;
}
private function fetchKeys($directory = '', $onlyKeys = true)
{
$directory = preg_replace('/^[\/]*([^\/].*)$/', '/$1', $directory);
$lines = ftp_rawlist($this->getConnection(), '-alR ' . $this->directory . $directory);
if (false === $lines) {
return ['keys' => [], 'dirs' => []];
}
$regexDir = '/' . preg_quote($this->directory . $directory, '/') . '\/?(.+):$/u';
$regexItem = '/^(?:([d\-\d])\S+)\s+\S+(?:(?:\s+\S+){5})?\s+(\S+)\s+(.+?)$/';
$prevLine = null;
$directories = [];
$keys = ['keys' => [], 'dirs' => []];
foreach ((array) $lines as $line) {
if ('' === $prevLine && preg_match($regexDir, $line, $match)) {
$directory = $match[1];
unset($directories[$directory]);
if ($onlyKeys) {
$keys = [
'keys' => array_merge($keys['keys'], $keys['dirs']),
'dirs' => [],
];
}
} elseif (preg_match($regexItem, $line, $tokens)) {
$name = $tokens[3];
if ('.' === $name || '..' === $name) {
continue;
}
$path = ltrim($directory . '/' . $name, '/');
if ('d' === $tokens[1] || '<dir>' === $tokens[2]) {
$keys['dirs'][] = $path;
$directories[$path] = true;
} else {
$keys['keys'][] = $path;
}
}
$prevLine = $line;
}
if ($onlyKeys) {
$keys = [
'keys' => array_merge($keys['keys'], $keys['dirs']),
'dirs' => [],
];
}
foreach (array_keys($directories) as $directory) {
$keys = array_merge_recursive($keys, $this->fetchKeys($directory, $onlyKeys));
}
return $keys;
}
/**
* Parses the given raw list.
*
* @param array $rawlist
*
* @return array
*/
private function parseRawlist(array $rawlist)
{
$parsed = [];
foreach ($rawlist as $line) {
$infos = preg_split("/[\s]+/", $line, 9);
if ($this->isLinuxListing($infos)) {
$infos[7] = (strrpos($infos[7], ':') != 2) ? ($infos[7] . ' 00:00') : (date('Y') . ' ' . $infos[7]);
if ('total' !== $infos[0]) {
$parsed[] = [
'perms' => $infos[0],
'num' => $infos[1],
'size' => $infos[4],
'time' => strtotime($infos[5] . ' ' . $infos[6] . '. ' . $infos[7]),
'name' => $infos[8],
];
}
} elseif (count($infos) >= 4) {
$isDir = (boolean) ('<dir>' === $infos[2]);
$parsed[] = [
'perms' => $isDir ? 'd' : '-',
'num' => '',
'size' => $isDir ? '' : $infos[2],
'time' => strtotime($infos[0] . ' ' . $infos[1]),
'name' => $infos[3],
];
}
}
return $parsed;
}
/**
* Computes the path for the given key.
*
* @param string $key
*/
private function computePath($key)
{
return rtrim($this->directory, '/') . '/' . $key;
}
/**
* Indicates whether the adapter has an open ftp connection.
*
* @return bool
*/
private function isConnected()
{
if (class_exists('\FTP\Connection')) {
return $this->connection instanceof \FTP\Connection;
}
return is_resource($this->connection);
}
/**
* Returns an opened ftp connection resource. If the connection is not
* already opened, it open it before.
*
* @return resource|\FTP\Connection The ftp connection
*/
private function getConnection()
{
if (!$this->isConnected()) {
$this->connect();
}
return $this->connection;
}
/**
* Opens the adapter's ftp connection.
*
* @throws RuntimeException if could not connect
*/
private function connect()
{
if ($this->ssl && !function_exists('ftp_ssl_connect')) {
throw new \RuntimeException('This Server Has No SSL-FTP Available.');
}
// open ftp connection
if (!$this->ssl) {
$this->connection = ftp_connect($this->host, $this->port, $this->timeout);
} else {
$this->connection = ftp_ssl_connect($this->host, $this->port, $this->timeout);
}
if (!$this->connection) {
throw new \RuntimeException(sprintf('Could not connect to \'%s\' (port: %s).', $this->host, $this->port));
}
if (defined('FTP_USEPASVADDRESS')) {
ftp_set_option($this->connection, FTP_USEPASVADDRESS, false);
}
$username = $this->username ?: 'anonymous';
$password = $this->password ?: '';
// login ftp user
if (!@ftp_login($this->connection, $username, $password)) {
$this->close();
throw new \RuntimeException(sprintf('Could not login as %s.', $username));
}
// switch to passive mode if needed
if ($this->passive && !ftp_pasv($this->connection, true)) {
$this->close();
throw new \RuntimeException('Could not turn passive mode on.');
}
// enable utf8 mode if configured
if ($this->utf8 == true) {
ftp_raw($this->connection, 'OPTS UTF8 ON');
}
// ensure the adapter's directory exists
if ('/' !== $this->directory) {
try {
$this->ensureDirectoryExists($this->directory, $this->create);
} catch (\RuntimeException $e) {
$this->close();
throw $e;
}
// change the current directory for the adapter's directory
if (!ftp_chdir($this->connection, $this->directory)) {
$this->close();
throw new \RuntimeException(sprintf('Could not change current directory for the \'%s\' directory.', $this->directory));
}
}
}
/**
* Closes the adapter's ftp connection.
*/
public function close()
{
if ($this->isConnected()) {
ftp_close($this->connection);
}
}
private function isLinuxListing($info)
{
return count($info) >= 9;
}
}