Signed-off-by: Joas Schilling <coding@schilljs.com>tags/v11.0RC2
@@ -131,25 +131,14 @@ class Scanner extends BasicEmitter implements IScanner { | |||
* @throws \OCP\Lock\LockedException | |||
*/ | |||
public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true) { | |||
if (!\OC::$server->getDatabaseConnection()->supports4ByteText()) { | |||
// verify database - e.g. mysql only 3-byte chars | |||
if (preg_match('%(?: | |||
\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | |||
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | |||
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 | |||
)%xs', $file)) { | |||
// 4-byte characters are not supported in file names | |||
if ($file !== '') { | |||
try { | |||
$this->storage->verifyPath(dirname($file), basename($file)); | |||
} catch (\Exception $e) { | |||
return null; | |||
} | |||
} | |||
try { | |||
$this->storage->verifyPath(dirname($file), basename($file)); | |||
} catch (\Exception $e) { | |||
return null; | |||
} | |||
// only proceed if $file is not a partial file nor a blacklisted file | |||
if (!self::isPartialFile($file) and !Filesystem::isFileBlacklisted($file)) { | |||
@@ -45,8 +45,10 @@ use OC\Files\Cache\Scanner; | |||
use OC\Files\Cache\Updater; | |||
use OC\Files\Filesystem; | |||
use OC\Files\Cache\Watcher; | |||
use OCP\Files\EmptyFileNameException; | |||
use OCP\Files\FileNameTooLongException; | |||
use OCP\Files\InvalidCharacterInPathException; | |||
use OCP\Files\InvalidDirectoryException; | |||
use OCP\Files\InvalidPathException; | |||
use OCP\Files\ReservedWordException; | |||
use OCP\Files\Storage\ILockingStorage; | |||
@@ -487,8 +489,31 @@ abstract class Common implements Storage, ILockingStorage { | |||
/** | |||
* @inheritdoc | |||
* @throws InvalidPathException | |||
*/ | |||
public function verifyPath($path, $fileName) { | |||
// verify empty and dot files | |||
$trimmed = trim($fileName); | |||
if ($trimmed === '') { | |||
throw new EmptyFileNameException(); | |||
} | |||
if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) { | |||
throw new InvalidDirectoryException(); | |||
} | |||
if (!\OC::$server->getDatabaseConnection()->supports4ByteText()) { | |||
// verify database - e.g. mysql only 3-byte chars | |||
if (preg_match('%(?: | |||
\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | |||
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | |||
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 | |||
)%xs', $fileName)) { | |||
throw new InvalidCharacterInPathException(); | |||
} | |||
} | |||
if (isset($fileName[255])) { | |||
throw new FileNameTooLongException(); | |||
} |
@@ -53,8 +53,10 @@ use OC\Files\Storage\Storage; | |||
use OC\User\User; | |||
use OCP\Constants; | |||
use OCP\Files\Cache\ICacheEntry; | |||
use OCP\Files\EmptyFileNameException; | |||
use OCP\Files\FileNameTooLongException; | |||
use OCP\Files\InvalidCharacterInPathException; | |||
use OCP\Files\InvalidDirectoryException; | |||
use OCP\Files\InvalidPathException; | |||
use OCP\Files\Mount\IMountPoint; | |||
use OCP\Files\NotFoundException; | |||
@@ -1788,39 +1790,25 @@ class View { | |||
* @throws InvalidPathException | |||
*/ | |||
public function verifyPath($path, $fileName) { | |||
$l10n = \OC::$server->getL10N('lib'); | |||
// verify empty and dot files | |||
$trimmed = trim($fileName); | |||
if ($trimmed === '') { | |||
throw new InvalidPathException($l10n->t('Empty filename is not allowed')); | |||
} | |||
if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) { | |||
throw new InvalidPathException($l10n->t('Dot files are not allowed')); | |||
} | |||
if (!\OC::$server->getDatabaseConnection()->supports4ByteText()) { | |||
// verify database - e.g. mysql only 3-byte chars | |||
if (preg_match('%(?: | |||
\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | |||
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | |||
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 | |||
)%xs', $fileName)) { | |||
throw new InvalidPathException($l10n->t('4-byte characters are not supported in file names')); | |||
} | |||
} | |||
try { | |||
/** @type \OCP\Files\Storage $storage */ | |||
list($storage, $internalPath) = $this->resolvePath($path); | |||
$storage->verifyPath($internalPath, $fileName); | |||
} catch (ReservedWordException $ex) { | |||
throw new InvalidPathException($l10n->t('File name is a reserved word')); | |||
$l = \OC::$server->getL10N('lib'); | |||
throw new InvalidPathException($l->t('File name is a reserved word')); | |||
} catch (InvalidCharacterInPathException $ex) { | |||
throw new InvalidPathException($l10n->t('File name contains at least one invalid character')); | |||
$l = \OC::$server->getL10N('lib'); | |||
throw new InvalidPathException($l->t('File name contains at least one invalid character')); | |||
} catch (FileNameTooLongException $ex) { | |||
throw new InvalidPathException($l10n->t('File name is too long')); | |||
$l = \OC::$server->getL10N('lib'); | |||
throw new InvalidPathException($l->t('File name is too long')); | |||
} catch (InvalidDirectoryException $ex) { | |||
$l = \OC::$server->getL10N('lib'); | |||
throw new InvalidPathException($l->t('Dot files are not allowed')); | |||
} catch (EmptyFileNameException $ex) { | |||
$l = \OC::$server->getL10N('lib'); | |||
throw new InvalidPathException($l->t('Empty filename is not allowed')); | |||
} | |||
} | |||
@@ -0,0 +1,31 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
namespace OCP\Files; | |||
/** | |||
* Class EmptyFileNameException | |||
* | |||
* @package OCP\Files | |||
* @since 9.2.0 | |||
*/ | |||
class EmptyFileNameException extends InvalidPathException { | |||
} |
@@ -0,0 +1,31 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
namespace OCP\Files; | |||
/** | |||
* Class InvalidDirectoryException | |||
* | |||
* @package OCP\Files | |||
* @since 9.2.0 | |||
*/ | |||
class InvalidDirectoryException extends InvalidPathException { | |||
} |
@@ -86,7 +86,7 @@ class PathVerificationTest extends \Test\TestCase { | |||
if (!$connection->supports4ByteText()) { | |||
$this->expectException(InvalidPathException::class); | |||
$this->expectExceptionMessage('4-byte characters are not supported in file names'); | |||
$this->expectExceptionMessage('File name contains at least one invalid character'); | |||
} | |||
$this->view->verifyPath('', $fileName); |