Commit 837430ff authored by catch's avatar catch

Issue #1323124 by amateescu, aspilicious, Berdir: Convert file transfer system...

Issue #1323124 by amateescu, aspilicious, Berdir: Convert file transfer system to PSR-0. Commit ALL THE files.
parent e89ce282
......@@ -320,10 +320,6 @@ function authorize_get_filetransfer($backend, $settings = array()) {
$filetransfer = FALSE;
if (!empty($_SESSION['authorize_filetransfer_info'][$backend])) {
$backend_info = $_SESSION['authorize_filetransfer_info'][$backend];
if (!empty($backend_info['file'])) {
$file = $backend_info['file path'] . '/' . $backend_info['file'];
require_once $file;
}
if (class_exists($backend_info['class'])) {
$filetransfer = $backend_info['class']::factory(DRUPAL_ROOT, $settings);
}
......
......@@ -7535,28 +7535,14 @@ function drupal_get_updaters() {
* @return
* The Drupal FileTransfer class registry.
*
* @see FileTransfer
* @see Drupal\Core\FileTransfer\FileTransfer
* @see hook_filetransfer_info()
* @see hook_filetransfer_info_alter()
*/
function drupal_get_filetransfer_info() {
$info = &drupal_static(__FUNCTION__);
if (!isset($info)) {
// Since we have to manually set the 'file path' default for each
// module separately, we can't use module_invoke_all().
$info = array();
foreach (module_implements('filetransfer_info') as $module) {
$function = $module . '_filetransfer_info';
$result = $function();
if (isset($result) && is_array($result)) {
foreach ($result as &$values) {
if (empty($values['file path'])) {
$values['file path'] = drupal_get_path('module', $module);
}
}
$info = array_merge_recursive($info, $result);
}
}
$info = module_invoke_all('filetransfer_info');
drupal_alter('filetransfer_info', $info);
uasort($info, 'drupal_sort_weight');
}
......
<?php
/**
* @file
* Definition of Drupal\Core\FileTransfer\ChmodInterface.
*/
namespace Drupal\Core\FileTransfer;
/**
* Defines an interface to chmod files.
*/
interface ChmodInterface {
/**
* Changes the permissions of the file / directory specified in $path
*
* @param string $path
* Path to change permissions of.
* @param int $mode
* See the $mode argument from http://php.net/chmod.
* @param bool $recursive
* Pass TRUE to recursively chmod the entire directory specified in $path.
*
* @see http://php.net/chmod
*/
function chmodJailed($path, $mode, $recursive);
}
<?php
/**
* @file
* Definition of Drupal\Core\FileTransfer\FTP.
*/
namespace Drupal\Core\FileTransfer;
/**
* Defines the base class for FTP implementations.
*/
abstract class FTP extends FileTransfer {
/**
* Overrides Drupal\Core\FileTransfer\FileTransfer::__construct().
*/
public function __construct($jail, $username, $password, $hostname, $port) {
$this->username = $username;
$this->password = $password;
$this->hostname = $hostname;
$this->port = $port;
parent::__construct($jail);
}
/**
* Overrides Drupal\Core\FileTransfer\FileTransfer::factory().
*/
static function factory($jail, $settings) {
$username = empty($settings['username']) ? '' : $settings['username'];
$password = empty($settings['password']) ? '' : $settings['password'];
$hostname = empty($settings['advanced']['hostname']) ? 'localhost' : $settings['advanced']['hostname'];
$port = empty($settings['advanced']['port']) ? 21 : $settings['advanced']['port'];
if (function_exists('ftp_connect')) {
$class = 'Drupal\Core\FileTransfer\FTPExtension';
}
else {
throw new FileTransferException('No FTP backend available.');
}
return new $class($jail, $username, $password, $hostname, $port);
}
/**
* Overrides Drupal\Core\FileTransfer\FileTransfer::getSettingsForm().
*/
public function getSettingsForm() {
$form = parent::getSettingsForm();
$form['advanced']['port']['#default_value'] = 21;
return $form;
}
}
<?php
/**
* Base class for FTP implementations.
* @file
* Definition of Drupal\Core\FileTransfer\FTPExtension.
*/
abstract class FileTransferFTP extends FileTransfer {
public function __construct($jail, $username, $password, $hostname, $port) {
$this->username = $username;
$this->password = $password;
$this->hostname = $hostname;
$this->port = $port;
parent::__construct($jail);
}
/**
* Return an object which can implement the FTP protocol.
*
* @param string $jail
* @param array $settings
* @return FileTransferFTP
* The appropriate FileTransferFTP subclass based on the available
* options. If the FTP PHP extension is available, use it.
*/
static function factory($jail, $settings) {
$username = empty($settings['username']) ? '' : $settings['username'];
$password = empty($settings['password']) ? '' : $settings['password'];
$hostname = empty($settings['advanced']['hostname']) ? 'localhost' : $settings['advanced']['hostname'];
$port = empty($settings['advanced']['port']) ? 21 : $settings['advanced']['port'];
namespace Drupal\Core\FileTransfer;
if (function_exists('ftp_connect')) {
$class = 'FileTransferFTPExtension';
}
else {
throw new FileTransferException('No FTP backend available.');
}
return new $class($jail, $username, $password, $hostname, $port);
}
/**
* Defines a file transfer class using the PHP FTP extension.
*/
class FTPExtension extends FTP implements ChmodInterface {
/**
* Returns the form to configure the FileTransfer class for FTP.
* Implements Drupal\Core\FileTransfer\FileTransfer::connect().
*/
public function getSettingsForm() {
$form = parent::getSettingsForm();
$form['advanced']['port']['#default_value'] = 21;
return $form;
}
}
class FileTransferFTPExtension extends FileTransferFTP implements FileTransferChmodInterface {
public function connect() {
$this->connection = ftp_connect($this->hostname, $this->port);
......@@ -61,18 +26,27 @@ public function connect() {
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::copyFileJailed().
*/
protected function copyFileJailed($source, $destination) {
if (!@ftp_put($this->connection, $destination, $source, FTP_BINARY)) {
throw new FileTransferException("Cannot move @source to @destination", NULL, array("@source" => $source, "@destination" => $destination));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::createDirectoryJailed().
*/
protected function createDirectoryJailed($directory) {
if (!ftp_mkdir($this->connection, $directory)) {
throw new FileTransferException("Cannot create directory @directory", NULL, array("@directory" => $directory));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::removeDirectoryJailed().
*/
protected function removeDirectoryJailed($directory) {
$pwd = ftp_pwd($this->connection);
if (!ftp_chdir($this->connection, $directory)) {
......@@ -100,12 +74,18 @@ protected function removeDirectoryJailed($directory) {
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::removeFileJailed().
*/
protected function removeFileJailed($destination) {
if (!ftp_delete($this->connection, $destination)) {
throw new FileTransferException("Unable to remove to file @file", NULL, array('@file' => $destination));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::isDirectory().
*/
public function isDirectory($path) {
$result = FALSE;
$curr = ftp_pwd($this->connection);
......@@ -116,10 +96,16 @@ public function isDirectory($path) {
return $result;
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::isFile().
*/
public function isFile($path) {
return ftp_size($this->connection, $path) != -1;
}
/**
* Implements Drupal\Core\FileTransfer\ChmodInterface::chmodJailed().
*/
function chmodJailed($path, $mode, $recursive) {
if (!ftp_chmod($this->connection, $mode, $path)) {
throw new FileTransferException("Unable to set permissions on %file", NULL, array ('%file' => $path));
......@@ -136,9 +122,3 @@ function chmodJailed($path, $mode, $recursive) {
}
}
}
if (!function_exists('ftp_chmod')) {
function ftp_chmod($ftp_stream, $mode, $filename) {
return ftp_site($ftp_stream, sprintf('CHMOD %o %s', $mode, $filename));
}
}
<?php
/**
* @file
* Definition of Drupal\Core\FileTransfer\FileTransferException.
*/
namespace Drupal\Core\FileTransfer;
use RuntimeException;
/**
* FileTransferException class.
*/
class FileTransferException extends RuntimeException {
/**
* Arguments to be used in this exception.
*
* @var array
*/
public $arguments;
/**
* Constructs a FileTransferException object.
*
* @param string $message
* Exception message.
* @param int $code
* Exception code.
* @param array $arguments
* Arguments to be used in this exception.
*/
function __construct($message, $code = 0, $arguments = array()) {
parent::__construct($message, $code);
$this->arguments = $arguments;
}
}
<?php
/**
* The local connection class for copying files as the httpd user.
* @file
* Definition of Drupal\Core\FileTransfer\Local.
*/
class FileTransferLocal extends FileTransfer implements FileTransferChmodInterface {
namespace Drupal\Core\FileTransfer;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
/**
* Defines the local connection class for copying files as the httpd user.
*/
class Local extends FileTransfer implements ChmodInterface {
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::connect().
*/
function connect() {
// No-op
}
/**
* Overrides Drupal\Core\FileTransfer\FileTransfer::factory().
*/
static function factory($jail, $settings) {
return new FileTransferLocal($jail);
return new Local($jail);
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::copyFileJailed().
*/
protected function copyFileJailed($source, $destination) {
if (@!copy($source, $destination)) {
throw new FileTransferException('Cannot copy %source to %destination.', NULL, array('%source' => $source, '%destination' => $destination));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::createDirectoryJailed().
*/
protected function createDirectoryJailed($directory) {
if (!is_dir($directory) && @!mkdir($directory, 0777, TRUE)) {
throw new FileTransferException('Cannot create directory %directory.', NULL, array('%directory' => $directory));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::removeDirectoryJailed().
*/
protected function removeDirectoryJailed($directory) {
if (!is_dir($directory)) {
// Programmer error assertion, not something we expect users to see.
throw new FileTransferException('removeDirectoryJailed() called with a path (%directory) that is not a directory.', NULL, array('%directory' => $directory));
}
foreach (new RecursiveIteratorIterator(new SkipDotsRecursiveDirectoryIterator($directory), RecursiveIteratorIterator::CHILD_FIRST) as $filename => $file) {
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $filename => $file) {
if ($file->isDir()) {
if (@!drupal_rmdir($filename)) {
throw new FileTransferException('Cannot remove directory %directory.', NULL, array('%directory' => $filename));
......@@ -47,23 +72,35 @@ protected function removeDirectoryJailed($directory) {
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::removeFileJailed().
*/
protected function removeFileJailed($file) {
if (@!drupal_unlink($file)) {
throw new FileTransferException('Cannot remove file %file.', NULL, array('%file' => $file));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::isDirectory().
*/
public function isDirectory($path) {
return is_dir($path);
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::isFile().
*/
public function isFile($path) {
return is_file($path);
}
/**
* Implements Drupal\Core\FileTransfer\ChmodInterface::chmodJailed().
*/
public function chmodJailed($path, $mode, $recursive) {
if ($recursive && is_dir($path)) {
foreach (new RecursiveIteratorIterator(new SkipDotsRecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST) as $filename => $file) {
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST) as $filename => $file) {
if (@!chmod($filename, $mode)) {
throw new FileTransferException('Cannot chmod %path.', NULL, array('%path' => $filename));
}
......
<?php
/**
* @file
* Definition of Drupal\Core\FileTransfer\SSH.
*/
namespace Drupal\Core\FileTransfer;
/**
* The SSH connection class for the update module.
*/
class FileTransferSSH extends FileTransfer implements FileTransferChmodInterface {
class SSH extends FileTransfer implements ChmodInterface {
/**
* Overrides Drupal\Core\FileTransfer\FileTransfer::__construct().
*/
function __construct($jail, $username, $password, $hostname = "localhost", $port = 22) {
$this->username = $username;
$this->password = $password;
......@@ -13,6 +23,9 @@ function __construct($jail, $username, $password, $hostname = "localhost", $port
parent::__construct($jail);
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::connect().
*/
function connect() {
$this->connection = @ssh2_connect($this->hostname, $this->port);
if (!$this->connection) {
......@@ -23,38 +36,56 @@ function connect() {
}
}
/**
* Overrides Drupal\Core\FileTransfer\FileTransfer::factory().
*/
static function factory($jail, $settings) {
$username = empty($settings['username']) ? '' : $settings['username'];
$password = empty($settings['password']) ? '' : $settings['password'];
$hostname = empty($settings['advanced']['hostname']) ? 'localhost' : $settings['advanced']['hostname'];
$port = empty($settings['advanced']['port']) ? 22 : $settings['advanced']['port'];
return new FileTransferSSH($jail, $username, $password, $hostname, $port);
return new SSH($jail, $username, $password, $hostname, $port);
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::copyFileJailed().
*/
protected function copyFileJailed($source, $destination) {
if (!@ssh2_scp_send($this->connection, $source, $destination)) {
throw new FileTransferException('Cannot copy @source_file to @destination_file.', NULL, array('@source' => $source, '@destination' => $destination));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::copyDirectoryJailed().
*/
protected function copyDirectoryJailed($source, $destination) {
if (@!ssh2_exec($this->connection, 'cp -Rp ' . escapeshellarg($source) . ' ' . escapeshellarg($destination))) {
throw new FileTransferException('Cannot copy directory @directory.', NULL, array('@directory' => $source));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::createDirectoryJailed().
*/
protected function createDirectoryJailed($directory) {
if (@!ssh2_exec($this->connection, 'mkdir ' . escapeshellarg($directory))) {
throw new FileTransferException('Cannot create directory @directory.', NULL, array('@directory' => $directory));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::removeDirectoryJailed().
*/
protected function removeDirectoryJailed($directory) {
if (@!ssh2_exec($this->connection, 'rm -Rf ' . escapeshellarg($directory))) {
throw new FileTransferException('Cannot remove @directory.', NULL, array('@directory' => $directory));
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::removeFileJailed().
*/
protected function removeFileJailed($destination) {
if (!@ssh2_exec($this->connection, 'rm ' . escapeshellarg($destination))) {
throw new FileTransferException('Cannot remove @directory.', NULL, array('@directory' => $destination));
......@@ -62,7 +93,10 @@ protected function removeFileJailed($destination) {
}
/**
* WARNING: This is untested. It is not currently used, but should do the trick.
* Implements Drupal\Core\FileTransfer\FileTransfer::isDirectory().
*
* WARNING: This is untested. It is not currently used, but should do the
* trick.
*/
public function isDirectory($path) {
$directory = escapeshellarg($path);
......@@ -77,6 +111,9 @@ public function isDirectory($path) {
}
}
/**
* Implements Drupal\Core\FileTransfer\FileTransfer::isFile().
*/
public function isFile($path) {
$file = escapeshellarg($path);
$cmd = "[ -f {$file} ] && echo 'yes'";
......@@ -90,6 +127,9 @@ public function isFile($path) {
}
}
/**
* Implements Drupal\Core\FileTransfer\ChmodInterface::chmodJailed().
*/
function chmodJailed($path, $mode, $recursive) {
$cmd = sprintf("chmod %s%o %s", $recursive ? '-R ' : '', $mode, escapeshellarg($path));
if (@!ssh2_exec($this->connection, $cmd)) {
......@@ -98,7 +138,7 @@ function chmodJailed($path, $mode, $recursive) {
}
/**
* Returns the form to configure the FileTransfer class for SSH.
* Overrides Drupal\Core\FileTransfer\FileTransfer::getSettingsForm().
*/
public function getSettingsForm() {
$form = parent::getSettingsForm();
......
......@@ -7,6 +7,8 @@
namespace Drupal\Core\Updater;
use Drupal\Core\FileTransfer\FileTransferException;
/**
* Defines the base class for Updaters used in Drupal.
*/
......
<?php
use Drupal\Core\FileTransfer\FileTransfer;
use Drupal\Core\FileTransfer\FileTransferException;
class FileTranferTest extends DrupalWebTestCase {
protected $hostname = 'localhost';
......
......@@ -4171,7 +4171,7 @@ function hook_menu_site_status_alter(&$menu_site_status, $path) {
* - 'weight': Optional. Integer weight used for sorting connection types on
* the authorize.php form.
*
* @see FileTransfer
* @see Drupal\Core\FileTransfer\FileTransfer
* @see authorize.php
* @see hook_filetransfer_info_alter()
* @see drupal_get_filetransfer_info()
......@@ -4179,8 +4179,7 @@ function hook_menu_site_status_alter(&$menu_site_status, $path) {
function hook_filetransfer_info() {
$info['sftp'] = array(
'title' => t('SFTP (Secure FTP)'),
'file' => 'sftp.filetransfer.inc',
'class' => 'FileTransferSFTP',
'class' => 'Drupal\Core\FileTransfer\SFTP',
'weight' => 10,
);
return $info;
......
......@@ -1770,7 +1770,7 @@ function _system_themes_access($theme) {
* as a Batch API processing page, if the operation requires a batch.
*
* @see authorize.php
* @see FileTransfer
* @see Drupal\Core\FileTransfer\FileTransfer
* @see hook_filetransfer_info()
*/
......@@ -1893,9 +1893,7 @@ function system_filetransfer_info() {
if (function_exists('ftp_connect')) {
$backends['ftp'] = array(
'title' => t('FTP'),
'class' => 'FileTransferFTP',
'file' => 'ftp.inc',
'file path' => 'core/includes/filetransfer',
'class' => 'Drupal\Core\FileTransfer\FTP',
'weight' => 0,
);
}
......@@ -1905,9 +1903,7 @@ function system_filetransfer_info() {
if (function_exists('ssh2_connect')) {
$backends['ssh'] = array(
'title' => t('SSH'),
'class' => 'FileTransferSSH',
'file' => 'ssh.inc',
'file path' => 'core/includes/filetransfer',
'class' => 'Drupal\Core\FileTransfer\SSH',
'weight' => 20,
);
}
......
......@@ -36,6 +36,7 @@
*/
use Drupal\Core\Updater\Updater;
use Drupal\Core\FileTransfer\Local;
/**
* @defgroup update_manager_update Update manager: update
......@@ -435,11 +436,11 @@ function update_manager_update_ready_form_submit($form, &$form_state) {
// If the owner of the last directory we extracted is the same as the
// owner of our configuration directory (e.g. sites/default) where we're
// trying to install the code, there's no need to prompt for FTP/SSH
// credentials. Instead, we instantiate a FileTransferLocal and invoke
// update_authorize_run_update() directly.
// credentials. Instead, we instantiate a Drupal\Core\FileTransfer\Local and
// invoke update_authorize_run_update() directly.
if (fileowner($project_real_location) == fileowner(conf_path())) {
module_load_include('inc', 'update', 'update.authorize');
$filetransfer = new FileTransferLocal(DRUPAL_ROOT);
$filetransfer = new Local(DRUPAL_ROOT);
update_authorize_run_update($filetransfer, $updates);
}
// Otherwise, go through the regular workflow to prompt for FTP/SSH
......@@ -704,11 +705,11 @@ function update_manager_install_form_submit($form, &$form_state) {
// If the owner of the directory we extracted is the same as the
// owner of our configuration directory (e.g. sites/default) where we're
// trying to install the code, there's no need to prompt for FTP/SSH
// credentials. Instead, we instantiate a FileTransferLocal and invoke
// update_authorize_run_install() directly.
// credentials. Instead, we instantiate a Drupal\Core\FileTransfer\Local and
// invoke update_authorize_run_install() directly.
if (fileowner($project_real_location) == fileowner(conf_path())) {
module_load_include('inc', 'update', 'update.authorize');
$filetransfer = new FileTransferLocal(DRUPAL_ROOT);
$filetransfer = new Local(DRUPAL_ROOT);
call_user_func_array('update_authorize_run_install', array_merge(array($filetransfer), $arguments));
}
// Otherwise, go through the regular workflow to prompt for FTP/SSH
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment