diff --git a/core/lib/Drupal/Core/FileTransfer/ChmodInterface.php b/core/lib/Drupal/Core/FileTransfer/ChmodInterface.php index baabbc5..d9035f7 100644 --- a/core/lib/Drupal/Core/FileTransfer/ChmodInterface.php +++ b/core/lib/Drupal/Core/FileTransfer/ChmodInterface.php @@ -8,7 +8,7 @@ namespace Drupal\Core\FileTransfer; /** - * A FileTransfer Class implementing this interface can be used to chmod files. + * Defines an interface to chmod files. */ interface ChmodInterface { @@ -17,10 +17,12 @@ interface ChmodInterface { * * @param string $path * Path to change permissions of. - * @param long $mode - * @see http://php.net/chmod - * @param boolean $recursive + * @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); } diff --git a/core/lib/Drupal/Core/FileTransfer/FTP.php b/core/lib/Drupal/Core/FileTransfer/FTP.php index 34998f1..342660a 100644 --- a/core/lib/Drupal/Core/FileTransfer/FTP.php +++ b/core/lib/Drupal/Core/FileTransfer/FTP.php @@ -8,10 +8,13 @@ namespace Drupal\Core\FileTransfer; /** - * Base class for FTP implementations. + * 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; @@ -21,14 +24,7 @@ abstract class FTP extends FileTransfer { } /** - * Return an object which can implement the FTP protocol. - * - * @param string $jail - * @param array $settings - * - * @return FTP - * The appropriate FTP subclass based on the available - * options. If the FTP PHP extension is available, use it. + * Overrides Drupal\Core\FileTransfer\FileTransfer::factory(). */ static function factory($jail, $settings) { $username = empty($settings['username']) ? '' : $settings['username']; @@ -47,7 +43,7 @@ abstract class FTP extends FileTransfer { } /** - * Returns the form to configure the FileTransfer class for FTP. + * Overrides Drupal\Core\FileTransfer\FileTransfer::getSettingsForm(). */ public function getSettingsForm() { $form = parent::getSettingsForm(); diff --git a/core/lib/Drupal/Core/FileTransfer/FTPExtension.php b/core/lib/Drupal/Core/FileTransfer/FTPExtension.php index e746a84..39465ba 100644 --- a/core/lib/Drupal/Core/FileTransfer/FTPExtension.php +++ b/core/lib/Drupal/Core/FileTransfer/FTPExtension.php @@ -7,8 +7,14 @@ namespace Drupal\Core\FileTransfer; +/** + * Defines a file transfer class using the PHP FTP extension. + */ class FTPExtension extends FTP implements ChmodInterface { + /** + * Implements Drupal\Core\FileTransfer\FileTransfer::connect(). + */ public function connect() { $this->connection = ftp_connect($this->hostname, $this->port); @@ -20,18 +26,27 @@ class FTPExtension extends FTP implements ChmodInterface { } } + /** + * 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)) { @@ -59,12 +74,18 @@ class FTPExtension extends FTP implements ChmodInterface { } } + /** + * 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); @@ -75,10 +96,16 @@ class FTPExtension extends FTP implements ChmodInterface { 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)); diff --git a/core/lib/Drupal/Core/FileTransfer/FileTransfer.php b/core/lib/Drupal/Core/FileTransfer/FileTransfer.php index 54417d0..46ba9b0 100644 --- a/core/lib/Drupal/Core/FileTransfer/FileTransfer.php +++ b/core/lib/Drupal/Core/FileTransfer/FileTransfer.php @@ -20,21 +20,55 @@ use RecursiveDirectoryIterator; * safety, all methods operate only inside a "jail", by default the Drupal root. */ abstract class FileTransfer { + + /** + * The username for this file transfer. + * + * @var string + */ protected $username; + + /** + * The password for this file transfer. + * + * @var string + */ protected $password; + + /** + * The hostname for this file transfer. + * + * @var string + */ protected $hostname = 'localhost'; + + /** + * The port for this file transfer. + * + * @var int + */ protected $port; /** - * The constructor for the UpdateConnection class. This method is also called - * from the classes that extend this class and override this method. + * Constructs a Drupal\Core\FileTransfer\FileTransfer object. + * + * This method is also called from the classes that extend this class and + * override this method. + * + * @param $jail + * The full path where all file operations performed by this object will + * be restricted to. This prevents the FileTransfer classes from being + * able to touch other parts of the filesystem. */ function __construct($jail) { $this->jail = $jail; } /** + * Defines a factory method for this class. + * * Classes that extend this class must override the factory() static method. + * They should return a new instance of the appropriate FileTransfer subclass. * * @param string $jail * The full path where all file operations performed by this object will @@ -44,19 +78,28 @@ abstract class FileTransfer { * An array of connection settings for the FileTransfer subclass. If the * getSettingsForm() method uses any nested settings, the same structure * will be assumed here. + * * @return object * New instance of the appropriate FileTransfer subclass. + * + * @throws Drupal\Core\FileTransfer\FileTransferException */ static function factory($jail, $settings) { throw new FileTransferException('FileTransfer::factory() static method not overridden by FileTransfer subclass.'); } /** - * Implementation of the magic __get() method. + * Implements the magic __get() method. + * + * If the connection isn't set to anything, this will call the connect() + * method and return the result; afterwards, the connection will be returned + * directly without using this method. * - * If the connection isn't set to anything, this will call the connect() method - * and set it to and return the result; afterwards, the connection will be - * returned directly without using this method. + * @param string $name + * The name of the variable to return. + * + * @return string|bool + * The variable specified in $name. */ function __get($name) { if ($name == 'connection') { @@ -78,9 +121,9 @@ abstract class FileTransfer { /** * Copies a directory. * - * @param $source + * @param string $source * The source path. - * @param $destination + * @param string $destination * The destination path. */ public final function copyDirectory($source, $destination) { @@ -91,11 +134,18 @@ abstract class FileTransfer { } /** - * @see http://php.net/chmod + * Changes the permissions of the specified $path (file or directory). * * @param string $path - * @param long $mode + * The file / directory to change the 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. + * + * @throws Drupal\Core\FileTransfer\FileTransferException + * + * @see http://php.net/chmod */ public final function chmod($path, $mode, $recursive = FALSE) { if (!in_array('Drupal\Core\FileTransfer\ChmodInterface', class_implements(get_class($this)))) { @@ -110,7 +160,7 @@ abstract class FileTransfer { /** * Creates a directory. * - * @param $directory + * @param string $directory * The directory to be created. */ public final function createDirectory($directory) { @@ -122,7 +172,7 @@ abstract class FileTransfer { /** * Removes a directory. * - * @param $directory + * @param string $directory * The directory to be removed. */ public final function removeDirectory($directory) { @@ -134,9 +184,9 @@ abstract class FileTransfer { /** * Copies a file. * - * @param $source + * @param string $source * The source file. - * @param $destination + * @param string $destination * The destination file. */ public final function copyFile($source, $destination) { @@ -149,7 +199,7 @@ abstract class FileTransfer { /** * Removes a file. * - * @param $destination + * @param string $destination * The destination file to be removed. */ public final function removeFile($destination) { @@ -161,8 +211,10 @@ abstract class FileTransfer { /** * Checks that the path is inside the jail and throws an exception if not. * - * @param $path + * @param string $path * A path to check against the jail. + * + * @throws Drupal\Core\FileTransfer\FileTransferException */ protected final function checkPath($path) { $full_jail = $this->chroot . $this->jail; @@ -175,14 +227,18 @@ abstract class FileTransfer { /** * Returns a modified path suitable for passing to the server. - * If a path is a windows path, makes it POSIX compliant by removing the drive letter. - * If $this->chroot has a value, it is stripped from the path to allow for - * chroot'd filetransfer systems. * - * @param $path - * @param $strip_chroot + * If a path is a windows path, makes it POSIX compliant by removing the drive + * letter. If $this->chroot has a value, it is stripped from the path to allow + * for chroot'd filetransfer systems. + * + * @param string $path + * The path to modify. + * @param bool $strip_chroot + * Whether to remove the path in $this->chroot. * * @return string + * The modified path. */ protected final function fixRemotePath($path, $strip_chroot = TRUE) { $path = $this->sanitizePath($path); @@ -199,7 +255,10 @@ abstract class FileTransfer { * Changes backslashes to slashes, also removes a trailing slash. * * @param string $path + * The path to modify. + * * @return string + * The modified path. */ function sanitizePath($path) { $path = str_replace('\\', '/', $path); // Windows path sanitization. @@ -212,11 +271,11 @@ abstract class FileTransfer { /** * Copies a directory. * - * We need a separate method to make the $destination is in the jail. + * We need a separate method to make sure the $destination is in the jail. * - * @param $source + * @param string $source * The source path. - * @param $destination + * @param string $destination * The destination path. */ protected function copyDirectoryJailed($source, $destination) { @@ -238,7 +297,7 @@ abstract class FileTransfer { /** * Creates a directory. * - * @param $directory + * @param string $directory * The directory to be created. */ abstract protected function createDirectoryJailed($directory); @@ -246,7 +305,7 @@ abstract class FileTransfer { /** * Removes a directory. * - * @param $directory + * @param string $directory * The directory to be removed. */ abstract protected function removeDirectoryJailed($directory); @@ -254,9 +313,9 @@ abstract class FileTransfer { /** * Copies a file. * - * @param $source + * @param string $source * The source file. - * @param $destination + * @param string $destination * The destination file. */ abstract protected function copyFileJailed($source, $destination); @@ -264,39 +323,40 @@ abstract class FileTransfer { /** * Removes a file. * - * @param $destination + * @param string $destination * The destination file to be removed. */ abstract protected function removeFileJailed($destination); /** - * Checks if a particular path is a directory + * Checks if a particular path is a directory. * - * @param $path + * @param string $path * The path to check * - * @return boolean + * @return bool + * TRUE if the specified path is a directory, FALSE otherwise. */ abstract public function isDirectory($path); /** * Checks if a particular path is a file (not a directory). * - * @param $path - * The path to check + * @param string $path + * The path to check. * - * @return boolean + * @return bool + * TRUE if the specified path is a file, FALSE otherwise. */ abstract public function isFile($path); /** * Returns the chroot property for this connection. * - * It does this by moving up the tree until it finds itself. If successful, - * it will return the chroot, otherwise FALSE. + * It does this by moving up the tree until it finds itself * - * @return - * The chroot path for this connection or FALSE. + * @return string|bool + * If successful, the chroot path for this connection, otherwise FALSE. */ function findChroot() { // If the file exists as is, there is no chroot. @@ -322,8 +382,7 @@ abstract class FileTransfer { } /** - * Sets the chroot and changes the jail to match the correct path scheme - * + * Sets the chroot and changes the jail to match the correct path scheme. */ function setChroot() { $this->chroot = $this->findChroot(); @@ -335,6 +394,9 @@ abstract class FileTransfer { * * Implementing classes can either extend this form with fields collecting the * specific information they need, or override it entirely. + * + * @return array + * An array that contains a Form API definition. */ public function getSettingsForm() { $form['username'] = array( diff --git a/core/lib/Drupal/Core/FileTransfer/FileTransferException.php b/core/lib/Drupal/Core/FileTransfer/FileTransferException.php index 0179d91..bc32af8 100644 --- a/core/lib/Drupal/Core/FileTransfer/FileTransferException.php +++ b/core/lib/Drupal/Core/FileTransfer/FileTransferException.php @@ -13,8 +13,24 @@ 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; diff --git a/core/lib/Drupal/Core/FileTransfer/Local.php b/core/lib/Drupal/Core/FileTransfer/Local.php index 6d534ed..92ddcd9 100644 --- a/core/lib/Drupal/Core/FileTransfer/Local.php +++ b/core/lib/Drupal/Core/FileTransfer/Local.php @@ -11,30 +11,45 @@ use RecursiveIteratorIterator; use RecursiveDirectoryIterator; /** - * The local connection class for copying files as the httpd user. + * 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 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. @@ -57,20 +72,32 @@ class Local extends FileTransfer implements ChmodInterface { } } + /** + * 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 RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST) as $filename => $file) { diff --git a/core/lib/Drupal/Core/FileTransfer/SSH.php b/core/lib/Drupal/Core/FileTransfer/SSH.php index 19f68c4..c1bf991 100644 --- a/core/lib/Drupal/Core/FileTransfer/SSH.php +++ b/core/lib/Drupal/Core/FileTransfer/SSH.php @@ -12,6 +12,9 @@ namespace Drupal\Core\FileTransfer; */ 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; @@ -20,6 +23,9 @@ class SSH extends FileTransfer implements ChmodInterface { parent::__construct($jail); } + /** + * Implements Drupal\Core\FileTransfer\FileTransfer::connect(). + */ function connect() { $this->connection = @ssh2_connect($this->hostname, $this->port); if (!$this->connection) { @@ -30,6 +36,9 @@ class SSH extends FileTransfer implements ChmodInterface { } } + /** + * Overrides Drupal\Core\FileTransfer\FileTransfer::factory(). + */ static function factory($jail, $settings) { $username = empty($settings['username']) ? '' : $settings['username']; $password = empty($settings['password']) ? '' : $settings['password']; @@ -38,30 +47,45 @@ class SSH extends FileTransfer implements ChmodInterface { 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)); @@ -69,7 +93,10 @@ class SSH extends FileTransfer implements ChmodInterface { } /** - * 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); @@ -84,6 +111,9 @@ class SSH extends FileTransfer implements ChmodInterface { } } + /** + * Implements Drupal\Core\FileTransfer\FileTransfer::isFile(). + */ public function isFile($path) { $file = escapeshellarg($path); $cmd = "[ -f {$file} ] && echo 'yes'"; @@ -97,6 +127,9 @@ class SSH extends FileTransfer implements ChmodInterface { } } + /** + * 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)) { @@ -105,7 +138,7 @@ class SSH extends FileTransfer implements ChmodInterface { } /** - * Returns the form to configure the FileTransfer class for SSH. + * Overrides Drupal\Core\FileTransfer\FileTransfer::getSettingsForm(). */ public function getSettingsForm() { $form = parent::getSettingsForm();