123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- <?php
- abstract class FileTransfer {
- protected $username;
- protected $password;
- protected $hostname = 'localhost';
- protected $port;
-
- function __construct($jail) {
- $this->jail = $jail;
- }
-
- static function factory($jail, $settings) {
- throw new FileTransferException('FileTransfer::factory() static method not overridden by FileTransfer subclass.');
- }
-
- function __get($name) {
- if ($name == 'connection') {
- $this->connect();
- return $this->connection;
- }
- if ($name == 'chroot') {
- $this->setChroot();
- return $this->chroot;
- }
- }
-
- abstract protected function connect();
-
- public final function copyDirectory($source, $destination) {
- $source = $this->sanitizePath($source);
- $destination = $this->fixRemotePath($destination);
- $this->checkPath($destination);
- $this->copyDirectoryJailed($source, $destination);
- }
-
- public final function chmod($path, $mode, $recursive = FALSE) {
- if (!in_array('FileTransferChmodInterface', class_implements(get_class($this)))) {
- throw new FileTransferException('Unable to change file permissions');
- }
- $path = $this->sanitizePath($path);
- $path = $this->fixRemotePath($path);
- $this->checkPath($path);
- $this->chmodJailed($path, $mode, $recursive);
- }
-
- public final function createDirectory($directory) {
- $directory = $this->fixRemotePath($directory);
- $this->checkPath($directory);
- $this->createDirectoryJailed($directory);
- }
-
- public final function removeDirectory($directory) {
- $directory = $this->fixRemotePath($directory);
- $this->checkPath($directory);
- $this->removeDirectoryJailed($directory);
- }
-
- public final function copyFile($source, $destination) {
- $source = $this->sanitizePath($source);
- $destination = $this->fixRemotePath($destination);
- $this->checkPath($destination);
- $this->copyFileJailed($source, $destination);
- }
-
- public final function removeFile($destination) {
- $destination = $this->fixRemotePath($destination);
- $this->checkPath($destination);
- $this->removeFileJailed($destination);
- }
-
- protected final function checkPath($path) {
- $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));
- }
- }
-
- protected final function fixRemotePath($path, $strip_chroot = TRUE) {
- $path = $this->sanitizePath($path);
- $path = preg_replace('|^([a-z]{1}):|i', '', $path);
- if ($strip_chroot) {
- if ($this->chroot && strpos($path, $this->chroot) === 0) {
- $path = ($path == $this->chroot) ? '' : substr($path, strlen($this->chroot));
- }
- }
- return $path;
- }
-
- function sanitizePath($path) {
- $path = str_replace('\\', '/', $path);
- if (substr($path, -1) == '/') {
- $path = substr($path, 0, -1);
- }
- return $path;
- }
-
- protected function copyDirectoryJailed($source, $destination) {
- if ($this->isDirectory($destination)) {
- $destination = $destination . '/' . drupal_basename($source);
- }
- $this->createDirectory($destination);
- foreach (new RecursiveIteratorIterator(new SkipDotsRecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST) as $filename => $file) {
- $relative_path = substr($filename, strlen($source));
- if ($file->isDir()) {
- $this->createDirectory($destination . $relative_path);
- }
- else {
- $this->copyFile($file->getPathName(), $destination . $relative_path);
- }
- }
- }
-
- abstract protected function createDirectoryJailed($directory);
-
- abstract protected function removeDirectoryJailed($directory);
-
- abstract protected function copyFileJailed($source, $destination);
-
- abstract protected function removeFileJailed($destination);
-
- abstract public function isDirectory($path);
-
- abstract public function isFile($path);
-
- function findChroot() {
-
- $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 . '/' . drupal_basename(__FILE__))) {
-
- return substr($chroot, 0, -1);
- }
- $chroot .= array_shift($parts) . '/';
- }
- return FALSE;
- }
-
- function setChroot() {
- $this->chroot = $this->findChroot();
- $this->jail = $this->fixRemotePath($this->jail);
- }
-
- public function getSettingsForm() {
- $form['username'] = array(
- '#type' => 'textfield',
- '#title' => t('Username'),
- );
- $form['password'] = array(
- '#type' => 'password',
- '#title' => t('Password'),
- '#description' => t('Your password is not saved in the database and is only used to establish a connection.'),
- );
- $form['advanced'] = array(
- '#type' => 'fieldset',
- '#title' => t('Advanced settings'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- );
- $form['advanced']['hostname'] = array(
- '#type' => 'textfield',
- '#title' => t('Host'),
- '#default_value' => 'localhost',
- '#description' => t('The connection will be created between your web server and the machine hosting the web server files. In the vast majority of cases, this will be the same machine, and "localhost" is correct.'),
- );
- $form['advanced']['port'] = array(
- '#type' => 'textfield',
- '#title' => t('Port'),
- '#default_value' => NULL,
- );
- return $form;
- }
- }
- class FileTransferException extends Exception {
- public $arguments;
- function __construct($message, $code = 0, $arguments = array()) {
- parent::__construct($message, $code);
- $this->arguments = $arguments;
- }
- }
- interface FileTransferChmodInterface {
-
- function chmodJailed($path, $mode, $recursive);
- }
- class SkipDotsRecursiveDirectoryIterator extends RecursiveDirectoryIterator {
-
- function __construct($path) {
- parent::__construct($path);
- }
- function next() {
- parent::next();
- while ($this->isDot()) {
- parent::next();
- }
- }
- }
|