diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000000000000000000000000000000000000..f40dd22b5fda8b2d899ee0bcea5adaf124b6d822
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,28 @@
+{
+	"camelCase": true,
+	"eqeqeq": true,
+	"immed": true,
+	"latedef": false,
+	"noarg": true,
+	"nonbsp": true,
+	"undef": true,
+	"unused": true,
+	"trailing": true,
+	"maxparams": 5,
+	"curly": true,
+	"jquery": true,
+	"maxlen": 80,
+	"indent": 4,
+	"browser": true,
+	"globals": {
+		"console": true,
+		"it": true,
+		"itx": true,
+		"expect": true,
+		"describe": true,
+		"beforeEach": true,
+		"afterEach": true,
+		"sinon": true,
+		"fakeServer": true
+	}
+}
diff --git a/apps/files/js/admin.js b/apps/files/js/admin.js
index bfa966706351e27b941e561b93c8a279f5c22e58..f735079fcbe5178cefe1805cec623e0483aa4eb8 100644
--- a/apps/files/js/admin.js
+++ b/apps/files/js/admin.js
@@ -1,3 +1,13 @@
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
 function switchPublicFolder()
 {
 	var publicEnable = $('#publicEnable').is(':checked');
@@ -10,7 +20,7 @@ function switchPublicFolder()
 $(document).ready(function(){
 	switchPublicFolder(); // Execute the function after loading DOM tree
 	$('#publicEnable').click(function(){
-			switchPublicFolder(); // To get rid of onClick()
+		switchPublicFolder(); // To get rid of onClick()
 	});
 
 	$('#allowZipDownload').bind('change', function() {
diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js
index 149e4a9666ba8cfbf180207ffa72001c63a8bf5e..f962a7044a853796451a0f415be288d952e52837 100644
--- a/apps/files/js/file-upload.js
+++ b/apps/files/js/file-upload.js
@@ -1,3 +1,13 @@
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
 /**
  * The file upload code uses several hooks to interact with blueimps jQuery file upload library:
  * 1. the core upload handling hooks are added when initializing the plugin,
@@ -8,6 +18,8 @@
  *    - TODO music upload button
  */
 
+/* global OC, t, n */
+
 /**
  * Function that will allow us to know if Ajax uploads are supported
  * @link https://github.com/New-Bamboo/example-ajax-upload/blob/master/public/index.html
diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js
index f36457f01a8529f9570d232550062296560c5216..9a69d7b368869138bf05948894de9e0f28dbdad7 100644
--- a/apps/files/js/fileactions.js
+++ b/apps/files/js/fileactions.js
@@ -1,3 +1,15 @@
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+/* global OC, FileList	*/
+/* global trashBinApp */
 var FileActions = {
 	actions: {},
 	defaults: {},
@@ -45,8 +57,9 @@ var FileActions = {
 		return filteredActions;
 	},
 	getDefault: function (mime, type, permissions) {
+		var mimePart;
 		if (mime) {
-			var mimePart = mime.substr(0, mime.indexOf('/'));
+			mimePart = mime.substr(0, mime.indexOf('/'));
 		}
 		var name = false;
 		if (mime && FileActions.defaults[mime]) {
@@ -141,13 +154,14 @@ var FileActions = {
 		parent.parent().children().last().find('.action.delete').remove();
 		if (actions['Delete']) {
 			var img = FileActions.icons['Delete'];
+			var html;
 			if (img.call) {
 				img = img(file);
 			}
 			if (typeof trashBinApp !== 'undefined' && trashBinApp) {
-				var html = '<a href="#" original-title="' + t('files', 'Delete permanently') + '" class="action delete delete-icon" />';
+				html = '<a href="#" original-title="' + t('files', 'Delete permanently') + '" class="action delete delete-icon" />';
 			} else {
-				var html = '<a href="#" class="action delete delete-icon" />';
+				html = '<a href="#" class="action delete delete-icon" />';
 			}
 			var element = $(html);
 			element.data('action', actions['Delete']);
@@ -174,10 +188,11 @@ var FileActions = {
 };
 
 $(document).ready(function () {
+	var downloadScope;
 	if ($('#allowZipDownload').val() == 1) {
-		var downloadScope = 'all';
+		downloadScope = 'all';
 	} else {
-		var downloadScope = 'file';
+		downloadScope = 'file';
 	}
 
 	if (typeof disableDownloadActions == 'undefined' || !disableDownloadActions) {
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 23b31e72467ad3106c75726358dd469711bc1694..81c52e2a863d8ccb31c98ac9e9a701b12de57d9e 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -1,4 +1,16 @@
-var FileList={
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+/* global OC, t, n, FileList, FileActions, Files */
+/* global procesSelection, dragOptions, SVGSupport, replaceSVG */
+window.FileList={
 	useUndo:true,
 	postProcessList: function() {
 		$('#fileList tr').each(function() {
@@ -191,6 +203,7 @@ var FileList={
 		return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
 	},
 	setCurrentDir: function(targetDir, changeUrl) {
+		var url;
 		$('#dir').val(targetDir);
 		if (changeUrl !== false) {
 			if (window.history.pushState && changeUrl !== false) {
@@ -834,7 +847,7 @@ $(document).ready(function() {
 					{name: 'requesttoken', value: oc_requesttoken}
 				];
 			};
-		} 
+		}
 
 	});
 	file_upload_start.on('fileuploadadd', function(e, data) {
diff --git a/apps/files/js/files.js b/apps/files/js/files.js
index 06f37da4b5ca96f44fc2ebdb981d542cbfab7c84..a535700c1b33949beb5c5a5d20fc6a08e539a6bc 100644
--- a/apps/files/js/files.js
+++ b/apps/files/js/files.js
@@ -1,4 +1,16 @@
-Files={
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+/* global OC, t, n, FileList, FileActions */
+/* global getURLParameter, isPublic */
+var Files = {
 	// file space size sync
 	_updateStorageStatistics: function() {
 		Files._updateStorageStatisticsTimeout = null;
@@ -68,17 +80,25 @@ Files={
 		return fileName;
 	},
 
-	isFileNameValid:function (name) {
-		if (name === '.') {
-			throw t('files', '\'.\' is an invalid file name.');
-		} else if (name.length === 0) {
+	/**
+	 * Checks whether the given file name is valid.
+	 * @param name file name to check
+	 * @return true if the file name is valid.
+	 * Throws a string exception with an error message if
+	 * the file name is not valid
+	 */
+	isFileNameValid: function (name) {
+		var trimmedName = name.trim();
+		if (trimmedName === '.' || trimmedName === '..') {
+			throw t('files', '"{name}" is an invalid file name.', {name: name});
+		} else if (trimmedName.length === 0) {
 			throw t('files', 'File name cannot be empty.');
 		}
-
 		// check for invalid characters
-		var invalid_characters = ['\\', '/', '<', '>', ':', '"', '|', '?', '*'];
+		var invalid_characters =
+			['\\', '/', '<', '>', ':', '"', '|', '?', '*', '\n'];
 		for (var i = 0; i < invalid_characters.length; i++) {
-			if (name.indexOf(invalid_characters[i]) !== -1) {
+			if (trimmedName.indexOf(invalid_characters[i]) !== -1) {
 				throw t('files', "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed.");
 			}
 		}
@@ -655,10 +675,10 @@ function procesSelection() {
 		var totalSize = 0;
 		for(var i=0; i<selectedFiles.length; i++) {
 			totalSize+=selectedFiles[i].size;
-		};
+		}
 		for(var i=0; i<selectedFolders.length; i++) {
 			totalSize+=selectedFolders[i].size;
-		};
+		}
 		$('#headerSize').text(humanFileSize(totalSize));
 		var selection = '';
 		if (selectedFolders.length > 0) {
@@ -770,10 +790,11 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) {
 		}
 		img.src = previewURL;
 	});
-}
+};
 
 function getUniqueName(name) {
 	if (FileList.findFileEl(name).exists()) {
+		var numMatch;
 		var parts=name.split('.');
 		var extension = "";
 		if (parts.length > 1) {
@@ -807,7 +828,7 @@ function checkTrashStatus() {
 
 function onClickBreadcrumb(e) {
 	var $el = $(e.target).closest('.crumb'),
-		$targetDir = $el.data('dir');
+		$targetDir = $el.data('dir'),
 		isPublic = !!$('#isPublic').val();
 
 	if ($targetDir !== undefined && !isPublic) {
diff --git a/apps/files/js/upgrade.js b/apps/files/js/upgrade.js
index 02d57fc9e6ccbe746f73b913e20e965ead6b2bf1..714adf824a1841e6a56e10822b2a436c6ad27670 100644
--- a/apps/files/js/upgrade.js
+++ b/apps/files/js/upgrade.js
@@ -1,3 +1,14 @@
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+/* global OC */
 $(document).ready(function () {
 	var eventSource, total, bar = $('#progressbar');
 	console.log('start');
diff --git a/apps/files/js/upload.js b/apps/files/js/upload.js
index 9d9f61f600eef9cd6a960d10e2f02bbe901edd37..617cf4b1c1d4555f584547a309f473a7eff91b8c 100644
--- a/apps/files/js/upload.js
+++ b/apps/files/js/upload.js
@@ -1,3 +1,14 @@
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+/* global OC */
 function Upload(fileSelector) {
 	if ($.support.xhrFileUpload) {
 		return new XHRUpload(fileSelector.target.files);
diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js
index e185cf2f654f9fa349db84f9aa95e3063d0c7a7f..8bbc1d3d141b533dff6f59da3da395bf1e3129da 100644
--- a/apps/files/tests/js/fileactionsSpec.js
+++ b/apps/files/tests/js/fileactionsSpec.js
@@ -18,7 +18,10 @@
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
+
+/* global OC, FileActions, FileList */
 describe('FileActions tests', function() {
+	var $filesTable;
 	beforeEach(function() {
 		// init horrible parameters
 		var $body = $('body');
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index 61e026c0725abc697a783b76cf32cd2b0c5f5388..c26e65fc4ded9e1b47071a22b26fca5210a859af 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -18,6 +18,8 @@
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
+
+/* global OC, FileList */
 describe('FileList tests', function() {
 	beforeEach(function() {
 		// init horrible parameters
diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js
index 9d0a2e4f9d7cf01974a1b82ee934d5c8144a5d90..018c8ef0f3cff215a718a9491e9fbad12a47c1b2 100644
--- a/apps/files/tests/js/filesSpec.js
+++ b/apps/files/tests/js/filesSpec.js
@@ -18,6 +18,8 @@
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
+
+/* global Files */
 describe('Files tests', function() {
 	describe('File name validation', function() {
 		it('Validates correct file names', function() {
@@ -36,12 +38,14 @@ describe('Files tests', function() {
 				'und Ümläüte sind auch willkommen'
 			];
 			for ( var i = 0; i < fileNames.length; i++ ) {
+				var error = false;
 				try {
 					expect(Files.isFileNameValid(fileNames[i])).toEqual(true);
 				}
 				catch (e) {
-					fail();
+					error = e;
 				}
+				expect(error).toEqual(false);
 			}
 		});
 		it('Detects invalid file names', function() {
@@ -69,7 +73,7 @@ describe('Files tests', function() {
 				var threwException = false;
 				try {
 					Files.isFileNameValid(fileNames[i]);
-					fail();
+					console.error('Invalid file name not detected:', fileNames[i]);
 				}
 				catch (e) {
 					threwException = true;