diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php
index 062de5a2523b37f96f2bc1603fa68c55dd425285..e1f75ae91d0c8dd69d6f4063e5317deab8cd2759 100644
--- a/apps/files/ajax/newfile.php
+++ b/apps/files/ajax/newfile.php
@@ -10,7 +10,7 @@ global $eventSource;
 
 // Get the params
 $dir = isset( $_REQUEST['dir'] ) ? '/'.trim((string)$_REQUEST['dir'], '/\\') : '';
-$filename = isset( $_REQUEST['filename'] ) ? trim((string)$_REQUEST['filename'], '/\\') : '';
+$fileName = isset( $_REQUEST['filename'] ) ? trim((string)$_REQUEST['filename'], '/\\') : '';
 
 $l10n = \OC::$server->getL10N('files');
 
@@ -18,23 +18,14 @@ $result = array(
 	'success' 	=> false,
 	'data'		=> NULL
 );
-$trimmedFileName = trim($filename);
 
-if($trimmedFileName === '') {
-	$result['data'] = array('message' => (string)$l10n->t('File name cannot be empty.'));
+try {
+	\OC\Files\Filesystem::getView()->verifyPath($dir, $fileName);
+} catch (\OCP\Files\InvalidPathException $ex) {
+	$result['data'] = [
+		'message' => $ex->getMessage()];
 	OCP\JSON::error($result);
-	exit();
-}
-if($trimmedFileName === '.' || $trimmedFileName === '..') {
-	$result['data'] = array('message' => (string)$l10n->t('"%s" is an invalid file name.', $trimmedFileName));
-	OCP\JSON::error($result);
-	exit();
-}
-
-if(!OCP\Util::isValidFileName($filename)) {
-	$result['data'] = array('message' => (string)$l10n->t("Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed."));
-	OCP\JSON::error($result);
-	exit();
+	return;
 }
 
 if (!\OC\Files\Filesystem::file_exists($dir . '/')) {
@@ -46,12 +37,12 @@ if (!\OC\Files\Filesystem::file_exists($dir . '/')) {
 	exit();
 }
 
-$target = $dir.'/'.$filename;
+$target = $dir.'/'.$fileName;
 
 if (\OC\Files\Filesystem::file_exists($target)) {
 	$result['data'] = array('message' => (string)$l10n->t(
 			'The name %s is already used in the folder %s. Please choose a different name.',
-			array($filename, $dir))
+			array($fileName, $dir))
 		);
 	OCP\JSON::error($result);
 	exit();
diff --git a/apps/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php
index e5e038b715cd24a7c0a6f43387f318a088b9b912..3a252c5ba3c928c4abb813dbebfe9cf2eec68f05 100644
--- a/apps/files/ajax/newfolder.php
+++ b/apps/files/ajax/newfolder.php
@@ -9,7 +9,7 @@ OCP\JSON::callCheck();
 
 // Get the params
 $dir = isset($_POST['dir']) ? (string)$_POST['dir'] : '';
-$foldername = isset($_POST['foldername']) ?(string) $_POST['foldername'] : '';
+$folderName = isset($_POST['foldername']) ?(string) $_POST['foldername'] : '';
 
 $l10n = \OC::$server->getL10N('files');
 
@@ -18,16 +18,13 @@ $result = array(
 	'data'		=> NULL
 	);
 
-if(trim($foldername) === '') {
-	$result['data'] = array('message' => $l10n->t('Folder name cannot be empty.'));
+try {
+	\OC\Files\Filesystem::getView()->verifyPath($dir, $folderName);
+} catch (\OCP\Files\InvalidPathException $ex) {
+	$result['data'] = [
+		'message' => $ex->getMessage()];
 	OCP\JSON::error($result);
-	exit();
-}
-
-if(!OCP\Util::isValidFileName($foldername)) {
-	$result['data'] = array('message' => (string)$l10n->t("Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed."));
-	OCP\JSON::error($result);
-	exit();
+	return;
 }
 
 if (!\OC\Files\Filesystem::file_exists($dir . '/')) {
@@ -39,12 +36,12 @@ if (!\OC\Files\Filesystem::file_exists($dir . '/')) {
 	exit();
 }
 
-$target = $dir . '/' . $foldername;
+$target = $dir . '/' . $folderName;
 		
 if (\OC\Files\Filesystem::file_exists($target)) {
 	$result['data'] = array('message' => $l10n->t(
 			'The name %s is already used in the folder %s. Please choose a different name.',
-			array($foldername, $dir))
+			array($folderName, $dir))
 		);
 	OCP\JSON::error($result);
 	exit();
@@ -52,9 +49,9 @@ if (\OC\Files\Filesystem::file_exists($target)) {
 
 if(\OC\Files\Filesystem::mkdir($target)) {
 	if ( $dir !== '/') {
-		$path = $dir.'/'.$foldername;
+		$path = $dir.'/'.$folderName;
 	} else {
-		$path = '/'.$foldername;
+		$path = '/'.$folderName;
 	}
 	$meta = \OC\Files\Filesystem::getFileInfo($path);
 	$meta['type'] = 'dir'; // missing ?!
diff --git a/apps/files/js/files.js b/apps/files/js/files.js
index 314b8bf39c6734844c45358a939848d03b315a28..e63c3cad52eef7cd47b2c98919d8c068c142f2e4 100644
--- a/apps/files/js/files.js
+++ b/apps/files/js/files.js
@@ -102,14 +102,6 @@
 			} else if (trimmedName.length === 0) {
 				throw t('files', 'File name cannot be empty.');
 			}
-			// check for invalid characters
-			var invalidCharacters =
-				['\\', '/', '<', '>', ':', '"', '|', '?', '*', '\n'];
-			for (var i = 0; i < invalidCharacters.length; i++) {
-				if (trimmedName.indexOf(invalidCharacters[i]) !== -1) {
-					throw t('files', "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed.");
-				}
-			}
 			return true;
 		},
 		displayStorageWarnings: function() {
diff --git a/apps/files/tests/js/fileUploadSpec.js b/apps/files/tests/js/fileUploadSpec.js
index 2b4341ef1c345ad67d7a0d59126124763c5dd432..49b7265ced1eefc2443bc2d3911b602d72ad572e 100644
--- a/apps/files/tests/js/fileUploadSpec.js
+++ b/apps/files/tests/js/fileUploadSpec.js
@@ -110,18 +110,5 @@ describe('OC.Upload tests', function() {
 				'Not enough free space, you are uploading 5 kB but only 1000 B is left'
 			);
 		});
-		it('does not add file if it has invalid characters', function() {
-			var result;
-			testFile.name = 'stars*stars.txt';
-
-			result = addFile(testFile);
-
-			expect(result).toEqual(false);
-			expect(failStub.calledOnce).toEqual(true);
-			expect(failStub.getCall(0).args[1].textStatus).toEqual('invalidcharacters');
-			expect(failStub.getCall(0).args[1].errorThrown.substr(0, 12)).toEqual(
-				'Invalid name'
-			);
-		});
 	});
 });
diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js
index 4f8d5a29318ee97776c7ef880d9053a0d08e472c..f20ba03e2f1e90c850f18185ed745cfe9b53230f 100644
--- a/apps/files/tests/js/filesSpec.js
+++ b/apps/files/tests/js/filesSpec.js
@@ -55,16 +55,6 @@ describe('OCA.Files.Files tests', function() {
 				'     ',
 				'.',
 				'..',
-				'back\\slash',
-				'sl/ash',
-				'lt<lt',
-				'gt>gt',
-				'col:on',
-				'double"quote',
-				'pi|pe',
-				'dont?ask?questions?',
-				'super*star',
-				'new\nline',
 				' ..',
 				'.. ',
 				'. ',
diff --git a/lib/private/connector/sabre/exception/invalidpath.php b/lib/private/connector/sabre/exception/invalidpath.php
new file mode 100644
index 0000000000000000000000000000000000000000..ecf28f377b0c167c5de717d287b6114135399e0a
--- /dev/null
+++ b/lib/private/connector/sabre/exception/invalidpath.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Copyright (c) 2015 Thomas Müller <deepdiver@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file. */
+
+namespace OC\Connector\Sabre\Exception;
+
+use Sabre\DAV\Exception;
+
+class InvalidPath extends Exception {
+
+	const NS_OWNCLOUD = 'http://owncloud.org/ns';
+
+	/**
+	 * @var bool
+	 */
+	private $retry;
+
+	/**
+	 * @param string $message
+	 * @param bool $retry
+	 */
+	public function __construct($message, $retry = false) {
+		parent::__construct($message);
+		$this->retry = $retry;
+	}
+
+	/**
+	 * Returns the HTTP status code for this exception
+	 *
+	 * @return int
+	 */
+	public function getHTTPCode() {
+
+		return 400;
+
+	}
+
+	/**
+	 * This method allows the exception to include additional information
+	 * into the WebDAV error response
+	 *
+	 * @param \Sabre\DAV\Server $server
+	 * @param \DOMElement $errorNode
+	 * @return void
+	 */
+	public function serialize(\Sabre\DAV\Server $server,\DOMElement $errorNode) {
+
+		// set ownCloud namespace
+		$errorNode->setAttribute('xmlns:o', self::NS_OWNCLOUD);
+
+		// adding the retry node
+		$error = $errorNode->ownerDocument->createElementNS('o:','o:retry', var_export($this->retry, true));
+		$errorNode->appendChild($error);
+
+		// adding the message node
+		$error = $errorNode->ownerDocument->createElementNS('o:','o:reason', $this->getMessage());
+		$errorNode->appendChild($error);
+	}
+
+}
diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php
index 7ef6eea768e516c7deb546b4b5389e6b21400f9f..8f0642d794a7a92bf88d3b784fe19b6656a6875e 100644
--- a/lib/private/connector/sabre/file.php
+++ b/lib/private/connector/sabre/file.php
@@ -66,17 +66,15 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
 			throw new \Sabre\DAV\Exception\ServiceUnavailable("Encryption is disabled");
 		}
 
-		$fileName = basename($this->info->getPath());
-		if (!\OCP\Util::isValidFileName($fileName)) {
-			throw new \Sabre\DAV\Exception\BadRequest();
-		}
+		// verify path of the target
+		$this->verifyPath();
 
 		// chunked handling
 		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
 			return $this->createFileChunked($data);
 		}
 
-		list($storage,) = $this->fileView->resolvePath($this->path);
+		list($storage) = $this->fileView->resolvePath($this->path);
 		$needsPartFile = $this->needsPartFile($storage) && (strlen($this->path) > 1);
 
 		if ($needsPartFile) {
@@ -329,5 +327,5 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
 		// and/or add method on Storage called "needsPartFile()"
 		return !$storage->instanceOfStorage('OCA\Files_Sharing\External\Storage') &&
 			!$storage->instanceOfStorage('OC\Files\Storage\OwnCloud');
-	}	
+	}
 }
diff --git a/lib/private/connector/sabre/node.php b/lib/private/connector/sabre/node.php
index 8fee6a4eb4e75af7b0446e95109e39b0d561cccf..cdabf26a3fbfcfb607194038142e41825e3c32a4 100644
--- a/lib/private/connector/sabre/node.php
+++ b/lib/private/connector/sabre/node.php
@@ -1,28 +1,40 @@
 <?php
-
 /**
- * ownCloud
+ * @author Arthur Schiwon <blizzz@owncloud.com>
+ * @author Bart Visscher <bartv@thisnet.nl>
+ * @author Björn Schießle <schiessle@owncloud.com>
+ * @author Jakob Sack <mail@jakobsack.de>
+ * @author Jörn Friedrich Dreyer <jfd@butonic.de>
+ * @author Klaas Freitag <freitag@owncloud.com>
+ * @author Markus Goetz <markus@woboq.com>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Robin Appelman <icewind@owncloud.com>
+ * @author Sam Tuke <mail@samtuke.com>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Vincent Petry <pvince81@owncloud.com>
  *
- * @author Jakob Sack
- * @copyright 2011 Jakob Sack kde@jakobsack.de
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
  *
- * This library is distributed in the hope that it will be useful,
+ * 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.
+ * 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 library.  If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
  *
  */
 
 namespace OC\Connector\Sabre;
 
+use OC\Connector\Sabre\Exception\InvalidPath;
+
+
 abstract class Node implements \Sabre\DAV\INode {
 	/**
 	 * Allow configuring the method used to generate Etags
@@ -103,9 +115,8 @@ abstract class Node implements \Sabre\DAV\INode {
 		list($parentPath,) = \Sabre\HTTP\URLUtil::splitPath($this->path);
 		list(, $newName) = \Sabre\HTTP\URLUtil::splitPath($name);
 
-		if (!\OCP\Util::isValidFileName($newName)) {
-			throw new \Sabre\DAV\Exception\BadRequest();
-		}
+		// verify path of the target
+		$this->verifyPath();
 
 		$newPath = $parentPath . '/' . $newName;
 
@@ -230,4 +241,13 @@ abstract class Node implements \Sabre\DAV\INode {
 		}
 		return $p;
 	}
+
+	protected function verifyPath() {
+		try {
+			$fileName = basename($this->info->getPath());
+			$this->fileView->verifyPath($this->path, $fileName);
+		} catch (\OCP\Files\InvalidPathException $ex) {
+			throw new InvalidPath($ex->getMessage());
+		}
+	}
 }
diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php
index 5edd949eeaf843055719c485afe493d69d99b625..3705aa8058604f15d5c514fa79f560c917121253 100644
--- a/lib/private/connector/sabre/objecttree.php
+++ b/lib/private/connector/sabre/objecttree.php
@@ -8,9 +8,11 @@
 
 namespace OC\Connector\Sabre;
 
+use OC\Connector\Sabre\Exception\InvalidPath;
 use OC\Files\FileInfo;
 use OC\Files\Filesystem;
 use OC\Files\Mount\MoveableMount;
+use OC_Connector_Sabre_Exception_InvalidPath;
 use OCP\Files\StorageInvalidException;
 use OCP\Files\StorageNotAvailableException;
 
@@ -185,8 +187,10 @@ class ObjectTree extends \Sabre\DAV\Tree {
 			}
 
 			$fileName = basename($destinationPath);
-			if (!\OCP\Util::isValidFileName($fileName)) {
-				throw new \Sabre\DAV\Exception\BadRequest();
+			try {
+				$this->fileView->verifyPath($destinationDir, $fileName);
+			} catch (\OCP\Files\InvalidPathException $ex) {
+				throw new InvalidPath($ex->getMessage());
 			}
 
 			$renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php
index edd756cbf1e59fb58f473f6872e92da41736b340..8549d5a1fadfba8bf5111503dfdc072864299a33 100644
--- a/lib/private/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -8,8 +8,14 @@
 
 namespace OC\Files\Storage;
 
+use OC\Files\Cache\Cache;
+use OC\Files\Cache\Scanner;
+use OC\Files\Cache\Storage;
 use OC\Files\Filesystem;
 use OC\Files\Cache\Watcher;
+use OCP\Files\InvalidCharacterInPathException;
+use OCP\Files\InvalidPathException;
+use OCP\Files\ReservedWordException;
 
 /**
  * Storage backend class for providing common filesystem operation methods
@@ -25,7 +31,6 @@ use OC\Files\Cache\Watcher;
 abstract class Common implements \OC\Files\Storage\Storage {
 	protected $cache;
 	protected $scanner;
-	protected $permissioncache;
 	protected $watcher;
 	protected $storageCache;
 
@@ -303,7 +308,7 @@ abstract class Common implements \OC\Files\Storage\Storage {
 			$storage = $this;
 		}
 		if (!isset($this->cache)) {
-			$this->cache = new \OC\Files\Cache\Cache($storage);
+			$this->cache = new Cache($storage);
 		}
 		return $this->cache;
 	}
@@ -313,7 +318,7 @@ abstract class Common implements \OC\Files\Storage\Storage {
 			$storage = $this;
 		}
 		if (!isset($this->scanner)) {
-			$this->scanner = new \OC\Files\Cache\Scanner($storage);
+			$this->scanner = new Scanner($storage);
 		}
 		return $this->scanner;
 	}
@@ -323,7 +328,7 @@ abstract class Common implements \OC\Files\Storage\Storage {
 			$storage = $this;
 		}
 		if (!isset($this->watcher)) {
-			$this->watcher = new \OC\Files\Cache\Watcher($storage);
+			$this->watcher = new Watcher($storage);
 			$this->watcher->setPolicy(\OC::$server->getConfig()->getSystemValue('filesystem_check_changes', Watcher::CHECK_ONCE));
 		}
 		return $this->watcher;
@@ -334,7 +339,7 @@ abstract class Common implements \OC\Files\Storage\Storage {
 			$storage = $this;
 		}
 		if (!isset($this->storageCache)) {
-			$this->storageCache = new \OC\Files\Cache\Storage($storage);
+			$this->storageCache = new Storage($storage);
 		}
 		return $this->storageCache;
 	}
@@ -451,4 +456,60 @@ abstract class Common implements \OC\Files\Storage\Storage {
 		return [];
 	}
 
+	/**
+	 * @inheritdoc
+	 */
+	public function verifyPath($path, $fileName) {
+		// NOTE: $path will remain unverified for now
+		if (\OC_Util::runningOnWindows()) {
+			$this->verifyWindowsPath($fileName);
+		} else {
+			$this->verifyPosixPath($fileName);
+		}
+	}
+
+	/**
+	 * https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
+	 * @param string $fileName
+	 * @throws InvalidPathException
+	 */
+	protected function verifyWindowsPath($fileName) {
+		$fileName = trim($fileName);
+		$this->scanForInvalidCharacters($fileName, "\\/<>:\"|?*");
+		$reservedNames = ['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9'];
+		if (in_array(strtoupper($fileName), $reservedNames)) {
+			throw new ReservedWordException();
+		}
+	}
+
+	/**
+	 * @param string $fileName
+	 * @throws InvalidPathException
+	 */
+	protected function verifyPosixPath($fileName) {
+		$fileName = trim($fileName);
+		$this->scanForInvalidCharacters($fileName, "\\/");
+		$reservedNames = ['*'];
+		if (in_array($fileName, $reservedNames)) {
+			throw new ReservedWordException();
+		}
+	}
+
+	/**
+	 * @param string $fileName
+	 * @param string $invalidChars
+	 * @throws InvalidPathException
+	 */
+	private function scanForInvalidCharacters($fileName, $invalidChars) {
+		foreach(str_split($invalidChars) as $char) {
+			if (strpos($fileName, $char) !== false) {
+				throw new InvalidCharacterInPathException();
+			}
+		}
+
+		$sanitizedFileName = filter_var($fileName, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
+		if($sanitizedFileName !== $fileName) {
+			throw new InvalidCharacterInPathException();
+		}
+	}
 }
diff --git a/lib/private/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php
index ea9de2873611bb582e20905de227e28327492d27..9208a7f7774276385100122693c18658571b0243 100644
--- a/lib/private/files/storage/wrapper/wrapper.php
+++ b/lib/private/files/storage/wrapper/wrapper.php
@@ -8,6 +8,8 @@
 
 namespace OC\Files\Storage\Wrapper;
 
+use OCP\Files\InvalidPathException;
+
 class Wrapper implements \OC\Files\Storage\Storage {
 	/**
 	 * @var \OC\Files\Storage\Storage $storage
@@ -477,4 +479,14 @@ class Wrapper implements \OC\Files\Storage\Storage {
 	public function getDirectDownload($path) {
 		return $this->storage->getDirectDownload($path);
 	}
+
+	/**
+	 * @param string $path the path of the target folder
+	 * @param string $fileName the name of the file itself
+	 * @return void
+	 * @throws InvalidPathException
+	 */
+	public function verifyPath($path, $fileName) {
+		$this->storage->verifyPath($path, $fileName);
+	}
 }
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index 4f9a4001d697809d0ba5987d847ae24ff06d13a0..f14209fd925e6e0cc9ac268514229dfe59fd5eac 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -11,6 +11,9 @@ namespace OC\Files;
 
 use OC\Files\Cache\Updater;
 use OC\Files\Mount\MoveableMount;
+use OCP\Files\InvalidCharacterInPathException;
+use OCP\Files\InvalidPathException;
+use OCP\Files\ReservedWordException;
 
 /**
  * Class to provide access to ownCloud filesystem via a "view", and methods for
@@ -29,11 +32,10 @@ use OC\Files\Mount\MoveableMount;
  * \OC\Files\Storage\Storage object
  */
 class View {
+	/** @var string */
 	private $fakeRoot = '';
 
-	/**
-	 * @var \OC\Files\Cache\Updater
-	 */
+	/** @var \OC\Files\Cache\Updater */
 	protected $updater;
 
 	/**
@@ -116,7 +118,7 @@ class View {
 	 * get the mountpoint of the storage object for a path
 	 * ( note: because a storage is not always mounted inside the fakeroot, the
 	 * returned mountpoint is relative to the absolute root of the filesystem
-	 * and doesn't take the chroot into account )
+	 * and does not take the chroot into account )
 	 *
 	 * @param string $path
 	 * @return string
@@ -129,7 +131,7 @@ class View {
 	 * get the mountpoint of the storage object for a path
 	 * ( note: because a storage is not always mounted inside the fakeroot, the
 	 * returned mountpoint is relative to the absolute root of the filesystem
-	 * and doesn't take the chroot into account )
+	 * and does not take the chroot into account )
 	 *
 	 * @param string $path
 	 * @return \OCP\Files\Mount\IMountPoint
@@ -1532,7 +1534,45 @@ class View {
 	/**
 	 * @return Updater
 	 */
-	public function getUpdater(){
+	public function getUpdater() {
 		return $this->updater;
 	}
+
+	/**
+	 * @param string $path
+	 * @param string $fileName
+	 * @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 ($trimmed === '.' || $trimmed === '..') {
+			throw new InvalidPathException($l10n->t('Dot files are not allowed'));
+		}
+
+		// 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'));
+		} catch (InvalidCharacterInPathException $ex) {
+			throw new InvalidPathException($l10n->t('File name contains at least one invalid characters'));
+		}
+	}
 }
diff --git a/lib/private/l10n.php b/lib/private/l10n.php
index 4e9316c333e561954b48df11eed4a65d628b651c..4fd4a617be8d27571d542834b0b57922763345f7 100644
--- a/lib/private/l10n.php
+++ b/lib/private/l10n.php
@@ -79,6 +79,48 @@ class OC_L10N implements \OCP\IL10N {
 		$this->lang = $lang;
 	}
 
+	/**
+	 * @param $app
+	 * @return string
+	 */
+	public static function setLanguageFromRequest($app = null) {
+		if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+			if (is_array($app)) {
+				$available = $app;
+			} else {
+				$available = self::findAvailableLanguages($app);
+			}
+
+			// E.g. make sure that 'de' is before 'de_DE'.
+			sort($available);
+
+			$preferences = preg_split('/,\s*/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
+			foreach ($preferences as $preference) {
+				list($preferred_language) = explode(';', $preference);
+				$preferred_language = str_replace('-', '_', $preferred_language);
+				foreach ($available as $available_language) {
+					if ($preferred_language === strtolower($available_language)) {
+						if (is_null($app)) {
+							self::$language = $available_language;
+						}
+						return $available_language;
+					}
+				}
+				foreach ($available as $available_language) {
+					if (substr($preferred_language, 0, 2) === $available_language) {
+						if (is_null($app)) {
+							self::$language = $available_language;
+						}
+						return $available_language;
+					}
+				}
+			}
+		}
+
+		// Last try: English
+		return 'en';
+	}
+
 	/**
 	 * @param $transFile
 	 * @param bool $mergeTranslations
@@ -403,41 +445,7 @@ class OC_L10N implements \OCP\IL10N {
 			return $default_language;
 		}
 
-		if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
-			if(is_array($app)) {
-				$available = $app;
-			} else {
-				$available = self::findAvailableLanguages($app);
-			}
-
-			// E.g. make sure that 'de' is before 'de_DE'.
-			sort($available);
-
-			$preferences = preg_split('/,\s*/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
-			foreach($preferences as $preference) {
-				list($preferred_language) = explode(';', $preference);
-				$preferred_language = str_replace('-', '_', $preferred_language);
-				foreach($available as $available_language) {
-					if ($preferred_language === strtolower($available_language)) {
-						if (is_null($app)) {
-							self::$language = $available_language;
-						}
-						return $available_language;
-					}
-				}
-				foreach($available as $available_language) {
-					if (substr($preferred_language, 0, 2) === $available_language) {
-						if (is_null($app)) {
-							self::$language = $available_language;
-						}
-						return $available_language;
-					}
-				}
-			}
-		}
-
-		// Last try: English
-		return 'en';
+		return self::setLanguageFromRequest($app);
 	}
 
 	/**
diff --git a/lib/private/util.php b/lib/private/util.php
index c6ad7cb5768d098826af38816b5420e9c1cc0824..62bbf5cf2aa35198b64a60f02ccd19c1155fa66b 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -1416,6 +1416,7 @@ class OC_Util {
 	 *
 	 * @param string $file file name to check
 	 * @return bool true if the file name is valid, false otherwise
+	 * @deprecated use \OC\Files\View::verifyPath()
 	 */
 	public static function isValidFileName($file) {
 		$trimmed = trim($file);
diff --git a/lib/public/files/invalidcharacterinpathexception.php b/lib/public/files/invalidcharacterinpathexception.php
new file mode 100644
index 0000000000000000000000000000000000000000..4ae2eb01c196f86bef94295bf8d7f757b48a1632
--- /dev/null
+++ b/lib/public/files/invalidcharacterinpathexception.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/InvalidCharacterInPathException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for invalid path
+ */
+class InvalidCharacterInPathException extends InvalidPathException {
+
+}
diff --git a/lib/public/files/reservedwordexception.php b/lib/public/files/reservedwordexception.php
new file mode 100644
index 0000000000000000000000000000000000000000..25c618a8dedf1f315aa5a8be64c641fca98115b2
--- /dev/null
+++ b/lib/public/files/reservedwordexception.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/ReservedWordException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for invalid path
+ */
+class ReservedWordException extends InvalidPathException {
+
+}
diff --git a/lib/public/files/storage.php b/lib/public/files/storage.php
index 3e6559c28f7354f233286aceba44f65d9af967ae..388ba5fa6ac534fbb97dade8fe8cb5b48722e0d0 100644
--- a/lib/public/files/storage.php
+++ b/lib/public/files/storage.php
@@ -28,6 +28,7 @@
 // use OCP namespace for all classes that are considered public.
 // This means that they should be used by apps instead of the internal ownCloud classes
 namespace OCP\Files;
+use OCP\Files\InvalidPathException;
 
 /**
  * Provide a common interface to all different storage options
@@ -345,4 +346,12 @@ interface Storage {
 	 * @return array|false
 	 */
 	public function getDirectDownload($path);
+
+	/**
+	 * @param string $path the path of the target folder
+	 * @param string $fileName the name of the file itself
+	 * @return void
+	 * @throws InvalidPathException
+	 */
+	public function verifyPath($path, $fileName);
 }
diff --git a/lib/public/util.php b/lib/public/util.php
index e6e14a26e01e08bbdbcd15a81f6d9b2060ee4d05..aa6cd5ba012316ec94c8357d1f9add6ff0bce8cc 100644
--- a/lib/public/util.php
+++ b/lib/public/util.php
@@ -497,6 +497,7 @@ class Util {
 	 * Returns whether the given file name is valid
 	 * @param string $file file name to check
 	 * @return bool true if the file name is valid, false otherwise
+	 * @deprecated use \OC\Files\View::verifyPath()
 	 */
 	public static function isValidFileName($file) {
 		return \OC_Util::isValidFileName($file);
diff --git a/ocs/v1.php b/ocs/v1.php
index b0f3e5e2b9025651f18aa8fed130dcf312736922..86631f39686b26430ec6c3254f3f6e01ade8b4d9 100644
--- a/ocs/v1.php
+++ b/ocs/v1.php
@@ -39,8 +39,8 @@ try {
 	// load all apps to get all api routes properly setup
 	OC_App::loadApps();
 
-	// api calls always will return English
-	\OC_L10N::forceLanguage('en');
+	// force language as given in the http request
+	\OC_L10N::setLanguageFromRequest();
 
 	OC::$server->getRouter()->match('/ocs'.\OC::$server->getRequest()->getRawPathInfo());
 } catch (ResourceNotFoundException $e) {
diff --git a/remote.php b/remote.php
index 80173441e90a11b11392f7d9bfb7ec9e448f24f0..101b19a807d84946db112fbd40dc82fd6cd085ad 100644
--- a/remote.php
+++ b/remote.php
@@ -29,6 +29,9 @@ try {
 		exit;
 	}
 
+	// force language as given in the http request
+	\OC_L10N::setLanguageFromRequest();
+
 	$file=ltrim($file, '/');
 
 	$parts=explode('/', $file, 2);
diff --git a/tests/lib/connector/sabre/directory.php b/tests/lib/connector/sabre/directory.php
index e7fbd1d27b6f481581dd0263c0adf6d3d75c6e7b..2550f2bcef107c6b615dafb58d308270e8cd885a 100644
--- a/tests/lib/connector/sabre/directory.php
+++ b/tests/lib/connector/sabre/directory.php
@@ -8,7 +8,9 @@
  */
 class Test_OC_Connector_Sabre_Directory extends \Test\TestCase {
 
+	/** @var OC\Files\View | PHPUnit_Framework_MockObject_MockObject */
 	private $view;
+	/** @var OC\Files\FileInfo | PHPUnit_Framework_MockObject_MockObject */
 	private $info;
 
 	protected function setUp() {
diff --git a/tests/lib/connector/sabre/exception/invalidpathtest.php b/tests/lib/connector/sabre/exception/invalidpathtest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d2d58887d6217907ca4672931d578942e269c503
--- /dev/null
+++ b/tests/lib/connector/sabre/exception/invalidpathtest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Test\Connector\Sabre\Exception;
+
+use OC\Connector\Sabre\Exception\InvalidPath;
+
+/**
+ * Copyright (c) 2015 Thomas Müller <deepdiver@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+class InvalidPathTest extends \Test\TestCase {
+
+	public function testSerialization() {
+
+		// create xml doc
+		$DOM = new \DOMDocument('1.0','utf-8');
+		$DOM->formatOutput = true;
+		$error = $DOM->createElementNS('DAV:','d:error');
+		$error->setAttribute('xmlns:s', \Sabre\DAV\Server::NS_SABREDAV);
+		$DOM->appendChild($error);
+
+		// serialize the exception
+		$message = "1234567890";
+		$retry = false;
+		$expectedXml = <<<EOD
+<?xml version="1.0" encoding="utf-8"?>
+<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:o="http://owncloud.org/ns">
+  <o:retry xmlns:o="o:">false</o:retry>
+  <o:reason xmlns:o="o:">1234567890</o:reason>
+</d:error>
+
+EOD;
+
+		$ex = new InvalidPath($message, $retry);
+		$server = $this->getMock('Sabre\DAV\Server');
+		$ex->serialize($server, $error);
+
+		// assert
+		$xml = $DOM->saveXML();
+		$this->assertEquals($expectedXml, $xml);
+	}
+}
diff --git a/tests/lib/connector/sabre/file.php b/tests/lib/connector/sabre/file.php
index 2ef5fd794be5c7d5a53fb007d40ca24fb2dc9714..f2812e390ac740c9b8df5e7602ea1998b9d38026 100644
--- a/tests/lib/connector/sabre/file.php
+++ b/tests/lib/connector/sabre/file.php
@@ -6,7 +6,12 @@
  * See the COPYING-README file.
  */
 
-class Test_OC_Connector_Sabre_File extends \Test\TestCase {
+namespace Test\Connector\Sabre;
+
+
+use OC_Connector_Sabre_File;
+
+class File extends \Test\TestCase {
 
 	/**
 	 * @expectedException \Sabre\DAV\Exception
@@ -93,7 +98,7 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase {
 	}
 
 	/**
-	 * @expectedException \Sabre\DAV\Exception\BadRequest
+	 * @expectedException \OC\Connector\Sabre\Exception\InvalidPath
 	 */
 	public function testSimplePutInvalidChars() {
 		// setup
@@ -104,9 +109,9 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase {
 
 		$view->expects($this->any())
 			->method('getRelativePath')
-			->will($this->returnValue('/super*star.txt'));
+			->will($this->returnValue('/*'));
 
-		$info = new \OC\Files\FileInfo('/super*star.txt', null, null, array(
+		$info = new \OC\Files\FileInfo('/*', null, null, array(
 			'permissions' => \OCP\Constants::PERMISSION_ALL
 		), null);
 		$file = new \OC\Connector\Sabre\File($view, $info);
@@ -117,7 +122,7 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase {
 
 	/**
 	 * Test setting name with setName() with invalid chars
-	 * @expectedException \Sabre\DAV\Exception\BadRequest
+	 * @expectedException \OC\Connector\Sabre\Exception\InvalidPath
 	 */
 	public function testSetNameInvalidChars() {
 		// setup
@@ -125,9 +130,9 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase {
 
 		$view->expects($this->any())
 			->method('getRelativePath')
-			->will($this->returnValue('/super*star.txt'));
+			->will($this->returnValue('/*'));
 
-		$info = new \OC\Files\FileInfo('/super*star.txt', null, null, array(
+		$info = new \OC\Files\FileInfo('/*', null, null, array(
 			'permissions' => \OCP\Constants::PERMISSION_ALL
 		), null);
 		$file = new \OC\Connector\Sabre\File($view, $info);
diff --git a/tests/lib/connector/sabre/node.php b/tests/lib/connector/sabre/node.php
index e1ae05b21709b3ac8699923489cd6e4af534af66..3b3a6107813ccec145e9705f63114cf5f289f78b 100644
--- a/tests/lib/connector/sabre/node.php
+++ b/tests/lib/connector/sabre/node.php
@@ -9,9 +9,6 @@
 
 namespace Test\Connector\Sabre;
 
-use OC\Files\FileInfo;
-use OC\Files\View;
-
 class Node extends \Test\TestCase {
 	public function davPermissionsProvider() {
 		return array(
diff --git a/tests/lib/connector/sabre/objecttree.php b/tests/lib/connector/sabre/objecttree.php
index 0709aa89c63c2a4088508f9d7f7f91df9c7114f1..d2702027b0dfe089681cbf84661d74cb75e34042 100644
--- a/tests/lib/connector/sabre/objecttree.php
+++ b/tests/lib/connector/sabre/objecttree.php
@@ -47,29 +47,29 @@ class ObjectTree extends \Test\TestCase {
 	 * @dataProvider moveFailedProvider
 	 * @expectedException \Sabre\DAV\Exception\Forbidden
 	 */
-	public function testMoveFailed($source, $dest, $updatables, $deletables) {
-		$this->moveTest($source, $dest, $updatables, $deletables);
+	public function testMoveFailed($source, $destination, $updatables, $deletables) {
+		$this->moveTest($source, $destination, $updatables, $deletables);
 	}
 
 	/**
 	 * @dataProvider moveSuccessProvider
 	 */
-	public function testMoveSuccess($source, $dest, $updatables, $deletables) {
-		$this->moveTest($source, $dest, $updatables, $deletables);
+	public function testMoveSuccess($source, $destination, $updatables, $deletables) {
+		$this->moveTest($source, $destination, $updatables, $deletables);
 		$this->assertTrue(true);
 	}
 
 	/**
 	 * @dataProvider moveFailedInvalidCharsProvider
-	 * @expectedException \Sabre\DAV\Exception\BadRequest
+	 * @expectedException \OC\Connector\Sabre\Exception\InvalidPath
 	 */
-	public function testMoveFailedInvalidChars($source, $dest, $updatables, $deletables) {
-		$this->moveTest($source, $dest, $updatables, $deletables);
+	public function testMoveFailedInvalidChars($source, $destination, $updatables, $deletables) {
+		$this->moveTest($source, $destination, $updatables, $deletables);
 	}
 
 	function moveFailedInvalidCharsProvider() {
 		return array(
-			array('a/b', 'a/c*', array('a' => false, 'a/b' => true, 'a/c*' => false), array()),
+			array('a/b', 'a/*', array('a' => false, 'a/b' => true, 'a/c*' => false), array()),
 		);
 	}
 
@@ -94,10 +94,10 @@ class ObjectTree extends \Test\TestCase {
 
 	/**
 	 * @param $source
-	 * @param $dest
+	 * @param $destination
 	 * @param $updatables
 	 */
-	private function moveTest($source, $dest, $updatables, $deletables) {
+	private function moveTest($source, $destination, $updatables, $deletables) {
 		$view = new TestDoubleFileView($updatables, $deletables);
 
 		$info = new FileInfo('', null, null, array(), null);
@@ -115,7 +115,7 @@ class ObjectTree extends \Test\TestCase {
 		/** @var $objectTree \OC\Connector\Sabre\ObjectTree */
 		$mountManager = \OC\Files\Filesystem::getMountManager();
 		$objectTree->init($rootDir, $view, $mountManager);
-		$objectTree->move($source, $dest);
+		$objectTree->move($source, $destination);
 	}
 
 	/**
diff --git a/tests/lib/files/pathverificationtest.php b/tests/lib/files/pathverificationtest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1a802a48f5718cde799783ac0c5868f603c17ea8
--- /dev/null
+++ b/tests/lib/files/pathverificationtest.php
@@ -0,0 +1,223 @@
+<?php
+/**
+ * Copyright (c) 2015 Thomas Müller <deepdiver@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file. */
+
+namespace Test\Files;
+
+use OC\Files\Storage\Local;
+use OC\Files\View;
+
+class PathVerification extends \Test\TestCase {
+
+	/**
+	 * @var \OC\Files\View
+	 */
+	private $view;
+
+	protected function setUp() {
+		parent::setUp();
+		$this->view = new View();
+	}
+
+	/**
+	 * @dataProvider providesEmptyFiles
+	 * @expectedException \OCP\Files\InvalidPathException
+	 * @expectedExceptionMessage Empty filename is not allowed
+	 */
+	public function testPathVerificationEmptyFileName($fileName) {
+		$this->view->verifyPath('', $fileName);
+	}
+
+	public function providesEmptyFiles() {
+		return [
+			[''],
+			[' '],
+		];
+	}
+
+	/**
+	 * @dataProvider providesDotFiles
+	 * @expectedException \OCP\Files\InvalidPathException
+	 * @expectedExceptionMessage Dot files are not allowed
+	 */
+	public function testPathVerificationDotFiles($fileName) {
+		$this->view->verifyPath('', $fileName);
+	}
+
+	public function providesDotFiles() {
+		return [
+			['.'],
+			['..'],
+			[' .'],
+			[' ..'],
+			['. '],
+			['.. '],
+			[' . '],
+			[' .. '],
+		];
+	}
+
+	/**
+	 * @dataProvider providesAstralPlane
+	 * @expectedException \OCP\Files\InvalidPathException
+	 * @expectedExceptionMessage 4-byte characters are not supported in file names
+	 */
+	public function testPathVerificationAstralPlane($fileName) {
+		$this->view->verifyPath('', $fileName);
+	}
+
+	public function providesAstralPlane() {
+		return [
+			// this is the monkey emoji - http://en.wikipedia.org/w/index.php?title=%F0%9F%90%B5&redirect=no
+			['🐵'],
+		];
+	}
+
+	/**
+	 * @dataProvider providesInvalidCharsWindows
+	 * @expectedException \OCP\Files\InvalidCharacterInPathException
+	 */
+	public function testPathVerificationInvalidCharsWindows($fileName) {
+		$storage = new Local(['datadir' => '']);
+
+		$fileName = " 123{$fileName}456 ";
+		\Test_Helper::invokePrivate($storage, 'verifyWindowsPath', [$fileName]);
+	}
+
+	public function providesInvalidCharsWindows() {
+		return [
+			[\chr(0)],
+			[\chr(1)],
+			[\chr(2)],
+			[\chr(3)],
+			[\chr(4)],
+			[\chr(5)],
+			[\chr(6)],
+			[\chr(7)],
+			[\chr(8)],
+			[\chr(9)],
+			[\chr(10)],
+			[\chr(11)],
+			[\chr(12)],
+			[\chr(13)],
+			[\chr(14)],
+			[\chr(15)],
+			[\chr(16)],
+			[\chr(17)],
+			[\chr(18)],
+			[\chr(19)],
+			[\chr(20)],
+			[\chr(21)],
+			[\chr(22)],
+			[\chr(23)],
+			[\chr(24)],
+			[\chr(25)],
+			[\chr(26)],
+			[\chr(27)],
+			[\chr(28)],
+			[\chr(29)],
+			[\chr(30)],
+			[\chr(31)],
+			['<'],
+			['>'],
+			[':'],
+			['"'],
+			['/'],
+			['\\'],
+			['|'],
+			['?'],
+			['*'],
+		];
+	}
+
+	/**
+	 * @dataProvider providesInvalidCharsPosix
+	 * @expectedException \OCP\Files\InvalidCharacterInPathException
+	 */
+	public function testPathVerificationInvalidCharsPosix($fileName) {
+		$storage = new Local(['datadir' => '']);
+
+		$fileName = " 123{$fileName}456 ";
+		\Test_Helper::invokePrivate($storage, 'verifyWindowsPath', [$fileName]);
+	}
+
+	public function providesInvalidCharsPosix() {
+		return [
+			[\chr(0)],
+			[\chr(1)],
+			[\chr(2)],
+			[\chr(3)],
+			[\chr(4)],
+			[\chr(5)],
+			[\chr(6)],
+			[\chr(7)],
+			[\chr(8)],
+			[\chr(9)],
+			[\chr(10)],
+			[\chr(11)],
+			[\chr(12)],
+			[\chr(13)],
+			[\chr(14)],
+			[\chr(15)],
+			[\chr(16)],
+			[\chr(17)],
+			[\chr(18)],
+			[\chr(19)],
+			[\chr(20)],
+			[\chr(21)],
+			[\chr(22)],
+			[\chr(23)],
+			[\chr(24)],
+			[\chr(25)],
+			[\chr(26)],
+			[\chr(27)],
+			[\chr(28)],
+			[\chr(29)],
+			[\chr(30)],
+			[\chr(31)],
+			['/'],
+			['\\'],
+		];
+	}
+
+	/**
+	 * @dataProvider providesReservedNamesWindows
+	 * @expectedException \OCP\Files\ReservedWordException
+	 */
+	public function testPathVerificationReservedNamesWindows($fileName) {
+		$storage = new Local(['datadir' => '']);
+
+		\Test_Helper::invokePrivate($storage, 'verifyWindowsPath', [$fileName]);
+	}
+
+	public function providesReservedNamesWindows() {
+		return [
+			[' CON '],
+			['prn '],
+			['AUX'],
+			['NUL'],
+			['COM1'],
+			['COM2'],
+			['COM3'],
+			['COM4'],
+			['COM5'],
+			['COM6'],
+			['COM7'],
+			['COM8'],
+			['COM9'],
+			['LPT1'],
+			['LPT2'],
+			['LPT3'],
+			['LPT4'],
+			['LPT5'],
+			['LPT6'],
+			['LPT7'],
+			['LPT8'],
+			['LPT9']
+		];
+	}
+
+}