diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php
index b21a9dfba2ed256e077233d94272201c9516c2ff..a5ce7b257da3db8de85ac94fc19f95b500b0d29c 100644
--- a/apps/files/ajax/upload.php
+++ b/apps/files/ajax/upload.php
@@ -111,22 +111,32 @@ if ($maxUploadFileSize >= 0 and $totalSize > $maxUploadFileSize) {
 }
 
 $result = array();
+$directory = '';
 if (strpos($dir, '..') === false) {
 	$fileCount = count($files['name']);
 	for ($i = 0; $i < $fileCount; $i++) {
+
+		// Get the files directory
+		if(isset($_POST['file_directory']) === true) {
+			$directory = '/'.$_POST['file_directory'];
+		}
+
 		// $path needs to be normalized - this failed within drag'n'drop upload to a sub-folder
 		if (isset($_POST['resolution']) && $_POST['resolution']==='autorename') {
 			// append a number in brackets like 'filename (2).ext'
-			$target = OCP\Files::buildNotExistingFileName(stripslashes($dir), $files['name'][$i]);
+			$target = OCP\Files::buildNotExistingFileName(stripslashes($dir.$directory), $files['name'][$i]);
 		} else {
-			$target = \OC\Files\Filesystem::normalizePath(stripslashes($dir).'/'.$files['name'][$i]);
+			$target = \OC\Files\Filesystem::normalizePath(stripslashes($dir.$directory).'/'.$files['name'][$i]);
 		}
-
-		$directory = \OC\Files\Filesystem::normalizePath(stripslashes($dir));
-		if (isset($public_directory)) {
-			// If we are uploading from the public app,
-			// we want to send the relative path in the ajax request.
-			$directory = $public_directory;
+		
+		if(empty($directory) === true)
+		{
+			$directory = \OC\Files\Filesystem::normalizePath(stripslashes($dir));
+			if (isset($public_directory)) {
+				// If we are uploading from the public app,
+				// we want to send the relative path in the ajax request.
+				$directory = $public_directory;
+			}
 		}
 
 		if ( ! \OC\Files\Filesystem::file_exists($target)
@@ -186,7 +196,6 @@ if (strpos($dir, '..') === false) {
 
 if ($error === false) {
 	OCP\JSON::encodedPrint($result);
-	exit();
 } else {
 	OCP\JSON::error(array(array('data' => array_merge(array('message' => $error, 'code' => $errorCode), $storageStats))));
 }
diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js
index e5d1eacbd149f2ad52db522e66ed71f0f701086e..3879aa658888c17ed53acfaaef1cdc0601c34169 100644
--- a/apps/files/js/file-upload.js
+++ b/apps/files/js/file-upload.js
@@ -242,11 +242,19 @@ OC.Upload = {
 						data.errorThrown = errorMessage;
 					}
 
-					if (file.type === '' && file.size === 4096) {
-						data.textStatus = 'dirorzero';
-						data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes',
-							{filename: file.name}
-						);
+					// in case folder drag and drop is not supported file will point to a directory
+					// http://stackoverflow.com/a/20448357
+					if (!file.type && file.size%4096 === 0 && file.size <= 102400) {
+						try {
+							reader = new FileReader();
+							reader.readAsBinaryString(f);
+						} catch (NS_ERROR_FILE_ACCESS_DENIED) {
+							//file is a directory
+							data.textStatus = 'dirorzero';
+							data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes',
+								{filename: file.name}
+							);
+						}
 					}
 
 					// add size
@@ -326,10 +334,15 @@ OC.Upload = {
 				submit: function(e, data) {
 					OC.Upload.rememberUpload(data);
 					if ( ! data.formData ) {
+						var fileDirectory = '';
+						if(typeof data.files[0].relativePath !== 'undefined') {
+							fileDirectory = data.files[0].relativePath;
+						}
 						// noone set update parameters, we set the minimum
 						data.formData = {
 							requesttoken: oc_requesttoken,
-									 dir: $('#dir').val()
+							dir: $('#dir').val(),
+							file_directory: fileDirectory
 						};
 					}
 				},
@@ -683,3 +696,4 @@ $(document).ready(function() {
 	OC.Upload.init();
 });
 
+
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 506741eb6eabee9d6498d3f9a15596d12591b55d..9c749bb8f347835e0524a08a875d2b51df956d2f 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -9,7 +9,7 @@
  */
 
 /* global OC, t, n, FileList, FileActions, Files, BreadCrumb */
-/* global procesSelection, dragOptions */
+/* global procesSelection, dragOptions, folderDropOptions */
 window.FileList = {
 	appName: t('files', 'Files'),
 	isEmpty: true,
@@ -212,7 +212,7 @@ window.FileList = {
 			linkUrl = Files.getDownloadUrl(name, FileList.getCurrentDirectory());
 		}
 		td.append('<input id="select-' + fileData.id + '" type="checkbox" /><label for="select-' + fileData.id + '"></label>');
-		var link_elem = $('<a></a>').attr({
+		var linkElem = $('<a></a>').attr({
 			"class": "name",
 			"href": linkUrl
 		});
@@ -228,19 +228,19 @@ window.FileList = {
 			basename = name;
 			extension = false;
 		}
-		var name_span=$('<span></span>').addClass('nametext').text(basename);
-		link_elem.append(name_span);
+		var nameSpan=$('<span></span>').addClass('nametext').text(basename);
+		linkElem.append(nameSpan);
 		if (extension) {
-			name_span.append($('<span></span>').addClass('extension').text(extension));
+			nameSpan.append($('<span></span>').addClass('extension').text(extension));
 		}
 		// dirs can show the number of uploaded files
 		if (type === 'dir') {
-			link_elem.append($('<span></span>').attr({
+			linkElem.append($('<span></span>').attr({
 				'class': 'uploadtext',
 				'currentUploads': 0
 			}));
 		}
-		td.append(link_elem);
+		td.append(linkElem);
 		tr.append(td);
 
 		// size column
@@ -250,7 +250,7 @@ window.FileList = {
 		} else {
 			simpleSize = t('files', 'Pending');
 		}
-		var lastModifiedTime = Math.round(mtime / 1000);
+
 		td = $('<td></td>').attr({
 			"class": "filesize",
 			"style": 'color:rgb(' + sizeColor + ',' + sizeColor + ',' + sizeColor + ')'
@@ -437,8 +437,6 @@ window.FileList = {
 		});
 	},
 	reloadCallback: function(result) {
-		var $controls = $('#controls');
-
 		delete this._reloadCall;
 		this.hideMask();
 
@@ -810,10 +808,9 @@ window.FileList = {
 			var info = t('files', '{dirs} and {files}', infoVars);
 
 			// don't show the filesize column, if filesize is NaN (e.g. in trashbin)
-			if (isNaN(summary.totalSize)) {
-				var fileSize = '';
-			} else {
-				var fileSize = '<td class="filesize">'+humanFileSize(summary.totalSize)+'</td>';
+			var fileSize = '';
+			if (!isNaN(summary.totalSize)) {
+				fileSize = '<td class="filesize">'+humanFileSize(summary.totalSize)+'</td>';
 			}
 
 			var $summary = $('<tr class="summary" data-file="undefined"><td><span class="info">'+info+'</span></td>'+fileSize+'<td></td></tr>');
@@ -899,7 +896,6 @@ window.FileList = {
 		}
 	},
 	updateEmptyContent: function() {
-		var $fileList = $('#fileList');
 		var permissions = $('#permissions').val();
 		var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0;
 		$('#emptycontent').toggleClass('hidden', !isCreatable || !FileList.isEmpty);
@@ -937,13 +933,13 @@ window.FileList = {
 	},
 	scrollTo:function(file) {
 		//scroll to and highlight preselected file
-		var $scrolltorow = FileList.findFileEl(file);
-		if ($scrolltorow.exists()) {
-			$scrolltorow.addClass('searchresult');
-			$(window).scrollTop($scrolltorow.position().top);
+		var $scrollToRow = FileList.findFileEl(file);
+		if ($scrollToRow.exists()) {
+			$scrollToRow.addClass('searchresult');
+			$(window).scrollTop($scrollToRow.position().top);
 			//remove highlight when hovered over
-			$scrolltorow.one('hover', function() {
-				$scrolltorow.removeClass('searchresult');
+			$scrollToRow.one('hover', function() {
+				$scrollToRow.removeClass('searchresult');
 			});
 		}
 	},
@@ -979,9 +975,9 @@ $(document).ready(function() {
 	FileList.initialize();
 
 	// handle upload events
-	var file_upload_start = $('#file_upload_start');
+	var fileUploadStart = $('#file_upload_start');
 
-	file_upload_start.on('fileuploaddrop', function(e, data) {
+	fileUploadStart.on('fileuploaddrop', function(e, data) {
 		OC.Upload.log('filelist handle fileuploaddrop', e, data);
 
 		var dropTarget = $(e.originalEvent.target).closest('tr, .crumb');
@@ -1008,7 +1004,8 @@ $(document).ready(function() {
 			data.formData = function(form) {
 				return [
 					{name: 'dir', value: dir},
-					{name: 'requesttoken', value: oc_requesttoken}
+					{name: 'requesttoken', value: oc_requesttoken},
+					{name: 'file_directory', value: data.files[0].relativePath}
 				];
 			};
 		} else {
@@ -1019,7 +1016,7 @@ $(document).ready(function() {
 			}
 		}
 	});
-	file_upload_start.on('fileuploadadd', function(e, data) {
+	fileUploadStart.on('fileuploadadd', function(e, data) {
 		OC.Upload.log('filelist handle fileuploadadd', e, data);
 
 		//finish delete if we are uploading a deleted file
@@ -1032,19 +1029,19 @@ $(document).ready(function() {
 			// add to existing folder
 
 			// update upload counter ui
-			var uploadtext = data.context.find('.uploadtext');
-			var currentUploads = parseInt(uploadtext.attr('currentUploads'));
+			var uploadText = data.context.find('.uploadtext');
+			var currentUploads = parseInt(uploadText.attr('currentUploads'), 10);
 			currentUploads += 1;
-			uploadtext.attr('currentUploads', currentUploads);
+			uploadText.attr('currentUploads', currentUploads);
 
 			var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads);
 			if (currentUploads === 1) {
 				var img = OC.imagePath('core', 'loading.gif');
 				data.context.find('td.filename').attr('style','background-image:url('+img+')');
-				uploadtext.text(translatedText);
-				uploadtext.show();
+				uploadText.text(translatedText);
+				uploadText.show();
 			} else {
-				uploadtext.text(translatedText);
+				uploadText.text(translatedText);
 			}
 		}
 
@@ -1053,7 +1050,7 @@ $(document).ready(function() {
 	 * when file upload done successfully add row to filelist
 	 * update counter when uploading to sub folder
 	 */
-	file_upload_start.on('fileuploaddone', function(e, data) {
+	fileUploadStart.on('fileuploaddone', function(e, data) {
 		OC.Upload.log('filelist handle fileuploaddone', e, data);
 
 		var response;
@@ -1067,38 +1064,69 @@ $(document).ready(function() {
 
 		if (typeof result[0] !== 'undefined' && result[0].status === 'success') {
 			var file = result[0];
+			var size = 0;
 
 			if (data.context && data.context.data('type') === 'dir') {
 
 				// update upload counter ui
-				var uploadtext = data.context.find('.uploadtext');
-				var currentUploads = parseInt(uploadtext.attr('currentUploads'));
+				var uploadText = data.context.find('.uploadtext');
+				var currentUploads = parseInt(uploadText.attr('currentUploads'), 10);
 				currentUploads -= 1;
-				uploadtext.attr('currentUploads', currentUploads);
+				uploadText.attr('currentUploads', currentUploads);
 				var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads);
 				if (currentUploads === 0) {
 					var img = OC.imagePath('core', 'filetypes/folder');
 					data.context.find('td.filename').attr('style','background-image:url('+img+')');
-					uploadtext.text(translatedText);
-					uploadtext.hide();
+					uploadText.text(translatedText);
+					uploadText.hide();
 				} else {
-					uploadtext.text(translatedText);
+					uploadText.text(translatedText);
 				}
 
 				// update folder size
-				var size = parseInt(data.context.data('size'));
-				size += parseInt(file.size);
+				size = parseInt(data.context.data('size'), 10);
+				size += parseInt(file.size, 10);
 				data.context.attr('data-size', size);
 				data.context.find('td.filesize').text(humanFileSize(size));
-
 			} else {
 				// only append new file if uploaded into the current folder
-				if (file.directory !== FileList.getCurrentDirectory()) {
+				if (file.directory !== '/' && file.directory !== FileList.getCurrentDirectory()) {
+
+					var fileDirectory = file.directory.replace('/','').replace(/\/$/, "").split('/');
+
+					if (fileDirectory.length === 1) {
+						fileDirectory = fileDirectory[0];
+
+						// Get the directory 
+						var fd = FileList.findFileEl(fileDirectory);
+						if (fd.length === 0) {
+							var dir = {
+								name: fileDirectory,
+								type: 'dir',
+								mimetype: 'httpd/unix-directory',
+								permissions: file.permissions,
+								size: 0,
+								id: file.parentId
+							};
+							FileList.add(dir, {insert: true});
+						}
+					} else {
+						fileDirectory = fileDirectory[0];
+					}
+					
+					fileDirectory = FileList.findFileEl(fileDirectory);
+
+					// update folder size
+					size = parseInt(fileDirectory.attr('data-size'), 10);
+					size += parseInt(file.size, 10);
+					fileDirectory.attr('data-size', size);
+					fileDirectory.find('td.filesize').text(humanFileSize(size));
+
 					return;
 				}
 
 				// add as stand-alone row to filelist
-				var size=t('files', 'Pending');
+				size = t('files', 'Pending');
 				if (data.files[0].size>=0) {
 					size=data.files[0].size;
 				}
@@ -1110,37 +1138,40 @@ $(document).ready(function() {
 			}
 		}
 	});
-	file_upload_start.on('fileuploadstop', function(e, data) {
+	fileUploadStart.on('fileuploadstop', function(e, data) {
 		OC.Upload.log('filelist handle fileuploadstop', e, data);
 
 		//if user pressed cancel hide upload chrome
 		if (data.errorThrown === 'abort') {
 			//cleanup uploading to a dir
-			var uploadtext = $('tr .uploadtext');
+			var uploadText = $('tr .uploadtext');
 			var img = OC.imagePath('core', 'filetypes/folder');
-			uploadtext.parents('td.filename').attr('style','background-image:url('+img+')');
-			uploadtext.fadeOut();
-			uploadtext.attr('currentUploads', 0);
+			uploadText.parents('td.filename').attr('style','background-image:url('+img+')');
+			uploadText.fadeOut();
+			uploadText.attr('currentUploads', 0);
 		}
 	});
-	file_upload_start.on('fileuploadfail', function(e, data) {
+	fileUploadStart.on('fileuploadfail', function(e, data) {
 		OC.Upload.log('filelist handle fileuploadfail', e, data);
 
 		//if user pressed cancel hide upload chrome
 		if (data.errorThrown === 'abort') {
 			//cleanup uploading to a dir
-			var uploadtext = $('tr .uploadtext');
+			var uploadText = $('tr .uploadtext');
 			var img = OC.imagePath('core', 'filetypes/folder');
-			uploadtext.parents('td.filename').attr('style','background-image:url('+img+')');
-			uploadtext.fadeOut();
-			uploadtext.attr('currentUploads', 0);
+			uploadText.parents('td.filename').attr('style','background-image:url('+img+')');
+			uploadText.fadeOut();
+			uploadText.attr('currentUploads', 0);
 		}
 	});
 
 	$('#notification').hide();
 	$('#notification:first-child').on('click', '.replace', function() {
 		OC.Notification.hide(function() {
-			FileList.replace($('#notification > span').attr('data-oldName'), $('#notification > span').attr('data-newName'), $('#notification > span').attr('data-isNewFile'));
+			FileList.replace(
+				$('#notification > span').attr('data-oldName'),
+				$('#notification > span').attr('data-newName'),
+				$('#notification > span').attr('data-isNewFile'));
 		});
 	});
 	$('#notification:first-child').on('click', '.suggest', function() {
@@ -1170,8 +1201,7 @@ $(document).ready(function() {
 
 	function parseHashQuery() {
 		var hash = window.location.hash,
-			pos = hash.indexOf('?'),
-			query;
+			pos = hash.indexOf('?');
 		if (pos >= 0) {
 			return hash.substr(pos + 1);
 		}
@@ -1180,8 +1210,7 @@ $(document).ready(function() {
 
 	function parseCurrentDirFromUrl() {
 		var query = parseHashQuery(),
-			params,
-			dir = '/';
+			params;
 		// try and parse from URL hash first
 		if (query) {
 			params = OC.parseQueryString(decodeQuery(query));
diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php
index b765fdaf3e3ac234653b688bb2a6a516412a49ec..f9515d671572a1884668da34112b75e694284541 100644
--- a/apps/files/lib/helper.php
+++ b/apps/files/lib/helper.php
@@ -73,13 +73,14 @@ class Helper
 	/**
 	 * Formats the file info to be returned as JSON to the client.
 	 *
-	 * @param \OCP\Files\FileInfo file info
+	 * @param \OCP\Files\FileInfo $i
 	 * @return array formatted file info
 	 */
 	public static function formatFileInfo($i) {
 		$entry = array();
 
 		$entry['id'] = $i['fileid'];
+		$entry['parentId'] = $i['parent'];
 		$entry['date'] = \OCP\Util::formatDate($i['mtime']);
 		$entry['mtime'] = $i['mtime'] * 1000;
 		// only pick out the needed attributes
diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js
index 9ce8985f1fd28e381e9a45ae515c0648a714d302..ae2412f6a3b6fd027cfdc840efa8405705a5a717 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -62,11 +62,17 @@ $(document).ready(function() {
 
 	var file_upload_start = $('#file_upload_start');
 	file_upload_start.on('fileuploadadd', function(e, data) {
+		var fileDirectory = '';
+		if(typeof data.files[0].relativePath !== 'undefined') {
+			fileDirectory = data.files[0].relativePath;
+		}
+
 		// Add custom data to the upload handler
 		data.formData = {
 			requesttoken: $('#publicUploadRequestToken').val(),
 			dirToken: $('#dirToken').val(),
-			subdir: $('input#dir').val()
+			subdir: $('input#dir').val(),
+			file_directory: fileDirectory
 		};
 	});
 
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index 94be71148651a11f87c2941995246fcc92532d52..519ed250b1f4def20c9eb15a151ec7b5056d33d0 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -629,10 +629,21 @@ class View {
 	}
 
 	public function fromTmpFile($tmpFile, $path) {
+
 		if (Filesystem::isValidPath($path)) {
+
+			// Get directory that the file is going into
+			$filePath = dirname($path);
+
+			// Create the directories if any
+			if (!$this->file_exists($filePath)) {
+				$this->mkdir($filePath);
+			}
+
 			if (!$tmpFile) {
 				debug_print_backtrace();
 			}
+
 			$source = fopen($tmpFile, 'r');
 			if ($source) {
 				$this->file_put_contents($path, $source);