diff options
author | Dries Buytaert <dries@buytaert.net> | 2009-08-28 07:51:55 +0000 |
---|---|---|
committer | Dries Buytaert <dries@buytaert.net> | 2009-08-28 07:51:55 +0000 |
commit | b8448cac634bdc6d1e4c618a83d8478033734b9f (patch) | |
tree | 446b1d8daaf0c2df8c2bd08e50ddb75fd91e149b /includes/filetransfer/filetransfer.inc | |
parent | 45da74801a093fe58017cd109bbb14ef0e9e4c21 (diff) | |
download | brdo-b8448cac634bdc6d1e4c618a83d8478033734b9f.tar.gz brdo-b8448cac634bdc6d1e4c618a83d8478033734b9f.tar.bz2 |
- Patch #528326 by JacobSingh, cwgordon7: clean-up and bug fixes for the FTP file transfer classes.
Diffstat (limited to 'includes/filetransfer/filetransfer.inc')
-rw-r--r-- | includes/filetransfer/filetransfer.inc | 127 |
1 files changed, 119 insertions, 8 deletions
diff --git a/includes/filetransfer/filetransfer.inc b/includes/filetransfer/filetransfer.inc index 2b1c18c7e..f0cf9d56a 100644 --- a/includes/filetransfer/filetransfer.inc +++ b/includes/filetransfer/filetransfer.inc @@ -20,11 +20,7 @@ abstract class FileTransfer { * The constructer for the UpdateConnection class. This method is also called * from the classes that extend this class and override this method. */ - function __construct($jail, $username, $password, $hostname, $port) { - $this->username = $username; - $this->password = $password; - $this->hostname = $hostname; - $this->port = $port; + function __construct($jail) { $this->jail = $jail; } @@ -41,6 +37,11 @@ abstract class FileTransfer { $this->connect(); return $this->connection; } + + if ($name == 'chroot') { + $this->setChroot(); + return $this->chroot; + } } /** @@ -57,17 +58,36 @@ abstract class FileTransfer { * The destination path. */ public final function copyDirectory($source, $destination) { + $source = $this->sanitizePath($source); + $destination = $this->fixRemotePath($destination); $this->checkPath($destination); $this->copyDirectoryJailed($source, $destination); } /** + * @see http://php.net/chmod + * + * @param string $path + * @param long $mode + * @param bool $recursive + */ + public final function chmod($path, $mode, $recursive = FALSE) { + $path = $this->sanitizePath($path); + $path = $this->fixRemotePath($path); + $this->checkPath($path); + $this->chmodJailed($path, $mode, $recursive); + } + + protected abstract function chmodJailed($path, $mode, $recursive); + + /** * Creates a directory. * * @param $directory * The directory to be created. */ public final function createDirectory($directory) { + $directory = $this->fixRemotePath($directory); $this->checkPath($directory); $this->createDirectoryJailed($directory); } @@ -79,6 +99,7 @@ abstract class FileTransfer { * The directory to be removed. */ public final function removeDirectory($directory) { + $directory = $this->fixRemotePath($directory); $this->checkPath($directory); $this->removeDirectoryJailed($directory); } @@ -92,6 +113,8 @@ abstract class FileTransfer { * The destination file. */ public final function copyFile($source, $destination) { + $source = $this->sanitizePath($source); + $destination = $this->fixRemotePath($destination); $this->checkPath($destination); $this->copyFileJailed($source, $destination); } @@ -103,6 +126,7 @@ abstract class FileTransfer { * The destination file to be removed. */ public final function removeFile($destination) { + $destination = $this->fixRemotePath($destination); $this->checkPath($destination); $this->removeFileJailed($destination); } @@ -114,12 +138,51 @@ abstract class FileTransfer { * A path to check against the jail. */ protected final function checkPath($path) { - if (drupal_realpath(substr($path, 0, strlen($this->jail))) !== $this->jail) { + $full_jail = $this->chroot . $this->jail; + $full_path = drupal_realpath(substr($this->chroot . $path, 0, strlen($full_jail))); + $full_path = $this->fixRemotePath($full_path, FALSE); + if ($full_jail !== $full_path) { throw new FileTransferException('@directory is outside of the @jail', NULL, array('@directory' => $path, '@jail' => $this->jail)); } } /** + * 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 + * + * @return string; + */ + protected final function fixRemotePath($path, $strip_chroot = TRUE) { + $path = $this->sanitizePath($path); + $path = preg_replace('|^([a-z]{1}):|i', '', $path); // Strip out windows driveletter if its there. + if ($strip_chroot) { + if ($this->chroot && strpos($path, $this->chroot) === 0) { + $path = ($path == $this->chroot) ? '' : substr($path, strlen($this->chroot)); + } + } + return $path; + } + + /** + * Changes backslahes to slashes, also removes a trailing slash. + * + * @param string $path + * @return string; + */ + function sanitizePath($path) { + $path = str_replace('\\', '/', $path); // Windows path sanitiation. + if (substr($path, -1) == '/') { + $path = substr($path, 0, -1); + } + return $path; + } + + /** * Copies a directory. * * We need a separate method to make the $destination is in the jail. @@ -178,7 +241,7 @@ abstract class FileTransfer { * The destination file to be removed. */ abstract protected function removeFileJailed($destination); - + /** * Checks if a particular path is a directory * @@ -188,6 +251,54 @@ abstract class FileTransfer { * @return boolean */ abstract public function isDirectory($path); + + /** + * Checks if a particular path is a file (not a directory). + * + * @param $path + * The path to check + * + * @return boolean + */ + abstract public function isFile($path); + + /** + * Gets the chroot property for this connection. It does this by moving up + * the tree until it finds itself. If successful, it will return a chroot. + * + * @return string chroot + */ + function findChroot() { + // If the file exists as is, there is no chroot. + $path = __FILE__; + $path = $this->fixRemotePath($path, FALSE); + if ($this->isFile($path)) { + return FALSE; + } + + $path = dirname(__FILE__); + $path = $this->fixRemotePath($path, FALSE); + $parts = explode('/', $path); + $chroot = ''; + while (count($parts)) { + $check = implode($parts, '/'); + if ($this->isFile($check . '/' . basename(__FILE__))) { + // Remove the trailing slash. + return substr($chroot,0,-1); + } + $chroot .= array_shift($parts) . '/'; + } + return FALSE; + } + + /** + * Sets the chroot and changes the jail to match the correct path scheme + * + */ + function setChroot() { + $this->chroot = $this->findChroot(); + $this->jail = $this->fixRemotePath($this->jail); + } } /** @@ -200,4 +311,4 @@ class FileTransferException extends Exception { parent::__construct($message, $code); $this->arguments = $arguments; } -} +}
\ No newline at end of file |