Skip to content

Commit

Permalink
Correctly handle URL separator for code to work both on IIS and Apache
Browse files Browse the repository at this point in the history
  • Loading branch information
nkharchenko committed Jan 17, 2014
1 parent 47cf306 commit 1a8f873
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 48 deletions.
4 changes: 0 additions & 4 deletions php/elFinderVolumeDriver.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,6 @@ abstract class elFinderVolumeDriver {
'treeDeep' => 1,
// root url, not set to disable sending URL to client (replacement for old "fileURL" option)
'URL' => '',
// directory separator. required by client to show paths correctly
'separator' => DIRECTORY_SEPARATOR,
// library to crypt/uncrypt files names (not implemented)
'cryptLib' => '',
// how to detect files mimetypes. (auto/internal/finfo/mime_content_type)
Expand Down Expand Up @@ -583,7 +581,6 @@ public function mount(array $opts) {
$this->options = array_merge($this->options, $opts);
$this->id = $this->driverId.(!empty($this->options['id']) ? $this->options['id'] : elFinder::$volumesCnt++).'_';
$this->root = $this->_normpath($this->options['path']);
$this->separator = isset($this->options['separator']) ? $this->options['separator'] : DIRECTORY_SEPARATOR;

// default file attribute
$this->defaults = array(
Expand Down Expand Up @@ -875,7 +872,6 @@ public function options($hash) {
'url' => $this->URL,
'tmbUrl' => $this->tmbURL,
'disabled' => $this->disabled,
'separator' => $this->separator,
'copyOverwrite' => intval($this->options['copyOverwrite']),
'archivers' => array(
// 'create' => array_keys($this->archivers['create']),
Expand Down
100 changes: 59 additions & 41 deletions php/elFinderVolumeFTP.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ class elFinderVolumeFTP extends elFinderVolumeDriver {
**/
protected $tmp = '';

/**
* FTP URL separator
*
* @var string
**/
const URL_SEPARATOR = '/';

/**
* Constructor
* Extend options with required fields
Expand All @@ -77,7 +84,7 @@ public function __construct() {
'pass' => '',
'port' => 21,
'mode' => 'passive',
'path' => '/',
'path' => self::URL_SEPARATOR,
'timeout' => 20,
'owner' => true,
'tmbPath' => '',
Expand Down Expand Up @@ -130,7 +137,6 @@ protected function init() {
}

$this->rootName = $this->options['alias'];
$this->options['separator'] = '/';

return $this->connect();

Expand Down Expand Up @@ -259,8 +265,8 @@ protected function parseRaw($raw) {
if (preg_match('|(.+)\-\>(.+)|', $name, $m)) {
$name = trim($m[1]);
$target = trim($m[2]);
if (substr($target, 0, 1) != '/') {
$target = $this->root.'/'.$target;
if (substr($target, 0, 1) != self::URL_SEPARATOR) {
$target = $this->_joinPath($this->root, $target);
}
$target = $this->_normpath($target);
$stat['name'] = $name;
Expand Down Expand Up @@ -341,7 +347,7 @@ protected function cacheDir($path) {
}
foreach (ftp_rawlist($this->connect, $path) as $raw) {
if (($stat = $this->parseRaw($raw))) {
$p = $path.'/'.$stat['name'];
$p = $this->_joinPath($path, $stat['name']);
$stat = $this->updateCache($p, $stat);
if (empty($stat['hidden'])) {
// $files[] = $stat;
Expand Down Expand Up @@ -372,7 +378,12 @@ protected function ftpMode($path) {
* @author Dmitry (dio) Levashov
**/
protected function _dirname($path) {
return dirname($path);
$name = dirname($path);
// on Win32(IIS) dirname('/123') returns '\' (DIRECTORY_SEPARATOR)
if ($name == DIRECTORY_SEPARATOR) {
$name = self::URL_SEPARATOR;
}
return $name;
}

/**
Expand All @@ -395,7 +406,7 @@ protected function _basename($path) {
* @author Dmitry (dio) Levashov
**/
protected function _joinPath($dir, $name) {
return $dir.DIRECTORY_SEPARATOR.$name;
return $dir.self::URL_SEPARATOR.$name;
}

/**
Expand All @@ -409,25 +420,25 @@ protected function _normpath($path) {
if (empty($path)) {
$path = '.';
}
// path must be start with /
$path = preg_replace('|^\.\/?|', '/', $path);
$path = preg_replace('/^([^\/])/', "/$1", $path);
// path must be start with / (URL_SEPARATOR)
$path = preg_replace('|^\.\/?|', self::URL_SEPARATOR, $path);
$path = preg_replace('/^([^\/])/', self::URL_SEPARATOR."$1", $path);

if (strpos($path, '/') === 0) {
if (strpos($path, self::URL_SEPARATOR) === 0) {
$initial_slashes = true;
} else {
$initial_slashes = false;
}

if (($initial_slashes)
&& (strpos($path, '//') === 0)
&& (strpos($path, '///') === false)) {
&& (strpos($path, self::URL_SEPARATOR.self::URL_SEPARATOR) === 0)
&& (strpos($path, self::URL_SEPARATOR.self::URL_SEPARATOR.self::URL_SEPARATOR) === false)) {
$initial_slashes = 2;
}

$initial_slashes = (int) $initial_slashes;

$comps = explode('/', $path);
$comps = explode(self::URL_SEPARATOR, $path);
$new_comps = array();
foreach ($comps as $comp) {
if (in_array($comp, array('', '.'))) {
Expand All @@ -443,9 +454,9 @@ protected function _normpath($path) {
}
}
$comps = $new_comps;
$path = implode('/', $comps);
$path = implode(self::URL_SEPARATOR, $comps);
if ($initial_slashes) {
$path = str_repeat('/', $initial_slashes) . $path;
$path = str_repeat(self::URL_SEPARATOR, $initial_slashes) . $path;
}

return $path ? $path : '.';
Expand All @@ -470,7 +481,8 @@ protected function _relpath($path) {
* @author Dmitry (dio) Levashov
**/
protected function _abspath($path) {
return $path == $this->separator ? $this->root : $this->root.$this->separator.$path;
// ugly hack with DIRECTORY_SEPARATOR
return ($path == self::URL_SEPARATOR or $path == DIRECTORY_SEPARATOR)? $this->root : $this->_joinPath($this->root, $path);
}

/**
Expand All @@ -481,7 +493,7 @@ protected function _abspath($path) {
* @author Dmitry (dio) Levashov
**/
protected function _path($path) {
return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path));
return $this->rootName.($path == $this->root ? '' : $this->_joinPath( '', $this->_relpath($path)));
}

/**
Expand All @@ -493,7 +505,7 @@ protected function _path($path) {
* @author Dmitry (dio) Levashov
**/
protected function _inpath($path, $parent) {
return $path == $parent || strpos($path, $parent.'/') === 0;
return $path == $parent || strpos($path, $parent.self::URL_SEPARATOR) === 0;
}

/***************** file stat ********************/
Expand Down Expand Up @@ -630,7 +642,7 @@ protected function _subdirs($path) {

if (preg_match('/\s|\'|\"/', $path)) {
foreach (ftp_nlist($this->connect, $path) as $p) {
if (($stat = $this->stat($path.'/'.$p)) && $stat['mime'] == 'directory') {
if (($stat = $this->stat($this->_joinPath( '', $p)) && $stat['mime'] == 'directory')) {
return true;
}
}
Expand Down Expand Up @@ -673,7 +685,7 @@ protected function _scandir($path) {

foreach (ftp_rawlist($this->connect, $path) as $str) {
if (($stat = $this->parseRaw($str))) {
$files[] = $path.DIRECTORY_SEPARATOR.$stat['name'];
$files[] = $this->_joinPath($path, $stat['name']);
}
}

Expand Down Expand Up @@ -726,8 +738,8 @@ protected function _fclose($fp, $path='') {
* @author Dmitry (dio) Levashov
**/
protected function _mkdir($path, $name) {
$path = $path.'/'.$name;
if (ftp_mkdir($this->connect, $path) === false) {
$path = $this->_joinPath($path, $name);
if (ftp_mkdir($this->connect, $this->_normpath($path)) === false) {
return false;
}

Expand All @@ -745,7 +757,7 @@ protected function _mkdir($path, $name) {
**/
protected function _mkfile($path, $name) {
if ($this->tmp) {
$path = $path.'/'.$name;
$path = $this->_joinPath($path, $name);
$local = $this->tmp.DIRECTORY_SEPARATOR.md5($path);
$res = touch($local) && ftp_put($this->connect, $path, $local, FTP_ASCII);
@unlink($local);
Expand Down Expand Up @@ -780,7 +792,7 @@ protected function _copy($source, $targetDir, $name) {

if ($this->tmp) {
$local = $this->tmp.DIRECTORY_SEPARATOR.md5($source);
$target = $targetDir.DIRECTORY_SEPARATOR.$name;
$target = $this->_joinPath($targetDir, $name);

if (ftp_get($this->connect, $local, $source, FTP_BINARY)
&& ftp_put($this->connect, $target, $local, $this->ftpMode($target))) {
Expand All @@ -803,7 +815,7 @@ protected function _copy($source, $targetDir, $name) {
* @author Dmitry (dio) Levashov
**/
protected function _move($source, $targetDir, $name) {
$target = $targetDir.DIRECTORY_SEPARATOR.$name;
$target = $this->_joinPath($targetDir, $name);
return ftp_rename($this->connect, $source, $target) ? $target : false;
}

Expand Down Expand Up @@ -841,7 +853,7 @@ protected function _rmdir($path) {
* @author Dmitry (dio) Levashov
**/
protected function _save($fp, $dir, $name, $stat) {
$path = $dir.'/'.$name;
$path = $this->_joinPath($dir, $name);
return ftp_fput($this->connect, $path, $fp, $this->ftpMode($path))
? $path
: false;
Expand Down Expand Up @@ -978,7 +990,7 @@ protected function _extract($path, $arc)
return false;
}

$remoteDirectory = dirname($path);
$remoteDirectory = $this->_dirname($path);
chdir($tmpDir);
$command = escapeshellcmd($arc['cmd'] . ' ' . $arc['argc'] . ' "' . $basename . '"');
$descriptorspec = array(
Expand Down Expand Up @@ -1012,31 +1024,36 @@ protected function _extract($path, $arc)
$name = substr($name, 0, strlen($name) - strlen($m[0]));
}

$test = dirname($path) . DIRECTORY_SEPARATOR . $name;
$test = $this->_dirname($path) . DIRECTORY_SEPARATOR . $name;
if ($this->stat($test)) {
$name = $this->uniqueName(dirname($path), $name, '-', false);
$name = $this->uniqueName($this->_dirname($path), $name, '-', false);
}

$newPath = dirname($path) . DIRECTORY_SEPARATOR . $name;
$newPath = $this->_joinPath($this->_dirname($path), $name);

$success = $this->_mkdir(dirname($path), $name);
$success = $this->_mkdir($this->_dirname($path), $name);
foreach ($filesToProcess as $filename) {
if (!$success) {
break;
}
$targetPath = $newPath . DIRECTORY_SEPARATOR . $filename;

if (is_dir($filename)) {
$success = $this->_mkdir($newPath, $filename);
} else {
$targetPath = $this->_joinPath($newPath, $filename);
$success = ftp_put($this->connect, $targetPath, $filename, FTP_BINARY);
}
}
unset($filename);

} else {
$filename = $filesToProcess[0];
$newPath = $remoteDirectory . DIRECTORY_SEPARATOR . $filename;
$success = ftp_put($this->connect, $newPath, $filename, FTP_BINARY);
if (is_dir($filename)) {
$success = $this->_mkdir($remoteDirectory, $filename);
} else {
$newPath = $this->_joinPath($remoteDirectory, $filename);
$success = ftp_put($this->connect, $newPath, $filename, FTP_BINARY);
}
}

// return to initial directory
Expand Down Expand Up @@ -1116,7 +1133,7 @@ protected function _archive($dir, $files, $name, $arc)
$return_value = proc_close($process);
}

$remoteArchiveFile = $dir . DIRECTORY_SEPARATOR . $name;
$remoteArchiveFile = $this->_joinPath($dir, $name);

// upload archive
if (!ftp_put($this->connect, $remoteArchiveFile, $path, FTP_BINARY)) {
Expand Down Expand Up @@ -1196,7 +1213,7 @@ protected function ftp_scan_dir($remote_directory)
case 'd' :
break;
default:
$remote_file_path = $remote_directory . DIRECTORY_SEPARATOR . $info[8];
$remote_file_path = $this->_joinPath($remote_directory, $info[8]);
$item = array();
$item['path'] = $remote_file_path;
$item['type'] = 'f'; // normal file
Expand Down Expand Up @@ -1224,7 +1241,8 @@ private function ftp_download_files($remote_directory, array $files, $dest_local
foreach ($contents as $item) {
$drop = true;
foreach ($files as $file) {
if ($remote_directory . DIRECTORY_SEPARATOR . $file == $item['path'] || strstr($item['path'], $remote_directory . DIRECTORY_SEPARATOR . $file . DIRECTORY_SEPARATOR)) {
$path = $this->_joinPath($remote_directory, $file);
if ( $this->_inpath($item['path'], $path) ) {
$drop = false;
break;
}
Expand Down Expand Up @@ -1308,16 +1326,16 @@ private static function listFilesInDirectory($dir, $omitSymlinks, $prefix = '')
}
foreach($files as $file) {
if(!in_array($file, $excludes)) {
$path = $dir.DIRECTORY_SEPARATOR.$file;
$path = $dir.self::URL_SEPARATOR.$file;
if(is_link($path)) {
if($omitSymlinks) {
continue;
} else {
$result[] = $prefix.$file;
}
} else if(is_dir($path)) {
$result[] = $prefix.$file.DIRECTORY_SEPARATOR;
$subs = elFinderVolumeFTP::listFilesInDirectory($path, $omitSymlinks, $prefix.$file.DIRECTORY_SEPARATOR);
$result[] = $prefix.$file.self::URL_SEPARATOR;
$subs = elFinderVolumeFTP::listFilesInDirectory($path, $omitSymlinks, end($result));
if($subs) {
$result = array_merge($result, $subs);
}
Expand Down
4 changes: 2 additions & 2 deletions php/elFinderVolumeFTPIIS.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ protected function cacheDir($path) {
}
foreach (ftp_rawlist($this->connect, $path) as $raw) {
if (($stat = $this->parseRaw($raw))) {
$p = $path.DIRECTORY_SEPARATOR.$stat['name'];
$p = $this->_joinPath($path, $stat['name']);
// $files[] = $stat;
$this->dirsCache[$path][] = $p;
//$stat['name'] = $p;
Expand Down Expand Up @@ -118,7 +118,7 @@ protected function ftp_scan_dir($remote_directory)
$items = array();
foreach ($buff as $str) {
$info = preg_split("/\s+/", $str, 9);
$remote_file_path = $remote_directory . DIRECTORY_SEPARATOR . join(" ", array_slice($info, 3, 9));
$remote_file_path = $this->_joinPath($remote_directory, join(" ", array_slice($info, 3, 9)));
$item = array();
$item['type'] = $info[2] == '<DIR>' ? 'd' : 'f';
$item['path'] = $remote_file_path;
Expand Down
2 changes: 1 addition & 1 deletion php/elFinderVolumeLocalFileSystem.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ protected function _abspath($path) {
* @author Dmitry (dio) Levashov
**/
protected function _path($path) {
return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path));
return $this->rootName.($path == $this->root ? '' : DIRECTORY_SEPARATOR.$this->_relpath($path));
}

/**
Expand Down

0 comments on commit 1a8f873

Please sign in to comment.