From 79a6d89bccf4c5d4ce934c88bc544988c47b8e98 Mon Sep 17 00:00:00 2001 From: Luke Policinski Date: Wed, 19 Feb 2014 21:23:39 +0000 Subject: [PATCH 01/75] Feature Added : Ability to drag and drop in Chrome --- apps/files/ajax/upload.php | 26 ++++++++++++++++++-------- apps/files/js/file-upload.js | 3 ++- apps/files/js/filelist.js | 32 ++++++++++++++++++++++++++++---- lib/private/files/view.php | 11 +++++++++++ 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 145f40c50d..b2aa7a9920 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -103,22 +103,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) diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index f962a7044a..ae6fdc654e 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -327,7 +327,8 @@ $(document).ready(function() { // noone set update parameters, we set the minimum data.formData = { requesttoken: oc_requesttoken, - dir: $('#dir').val() + dir: $('#dir').val(), + file_directory: data.files[0]['relativePath'], }; } }, diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index d6cffde05d..2631812c2e 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -879,7 +879,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']} ]; }; } @@ -935,7 +936,7 @@ $(document).ready(function() { var file = result[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')); @@ -956,10 +957,33 @@ $(document).ready(function() { size += parseInt(file.size); data.context.attr('data-size', size); data.context.find('td.filesize').text(humanFileSize(size)); - - } else { + } + else { + // only append new file if uploaded into the current folder if (file.directory !== FileList.getCurrentDirectory()) { + + file_directory = file.directory.replace('/','').replace(/\/$/, "").split('/'); + + if (file_directory.length == 1) { + file_directory = file_directory[0]; + + // Get the directory + if ($('tr[data-file="'+file_directory+'"]').length == 0) + { + FileList.addDir(file_directory, 0, new Date(), false); + } + } + else { + file_directory = file_directory[0]; + } + + // update folder size + var size = parseInt($('tr[data-file="'+file_directory+'"]').attr('data-size')); + size += parseInt(file.size); + $('tr[data-file="'+file_directory+'"]').attr('data-size', size); + $('tr[data-file="'+file_directory+'"]').find('td.filesize').text(humanFileSize(size)); + return; } diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 530aa8f751..7977272ee1 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -617,10 +617,21 @@ class View { } public function fromTmpFile($tmpFile, $path) { + if (Filesystem::isValidPath($path)) { + + // Get directory that the file is going into + $file_path = \OC_User::getHome(\OC_User::getUser()) . '/files'.substr($path, 0, strrpos($path,'/')); + + // Create the directories if any + if(empty($file_path) === false) { + mkdir($file_path, 0770, true); + } + if (!$tmpFile) { debug_print_backtrace(); } + $source = fopen($tmpFile, 'r'); if ($source) { $this->file_put_contents($path, $source); From b01492fecd5019a09cd7b1265a9cef43fc42616f Mon Sep 17 00:00:00 2001 From: Luke Policinski Date: Wed, 19 Feb 2014 21:28:32 +0000 Subject: [PATCH 02/75] Feature Added : Ability to drag and drop in Chrome --- apps/files/ajax/upload.php | 4 ++-- apps/files/js/filelist.js | 12 ++++++------ lib/private/files/view.php | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index b2aa7a9920..d189386e05 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -107,12 +107,12 @@ $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' diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 2631812c2e..17846c23b7 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -936,7 +936,7 @@ $(document).ready(function() { var file = result[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')); @@ -962,12 +962,12 @@ $(document).ready(function() { // only append new file if uploaded into the current folder if (file.directory !== FileList.getCurrentDirectory()) { - + file_directory = file.directory.replace('/','').replace(/\/$/, "").split('/'); - + if (file_directory.length == 1) { file_directory = file_directory[0]; - + // Get the directory if ($('tr[data-file="'+file_directory+'"]').length == 0) { @@ -977,13 +977,13 @@ $(document).ready(function() { else { file_directory = file_directory[0]; } - + // update folder size var size = parseInt($('tr[data-file="'+file_directory+'"]').attr('data-size')); size += parseInt(file.size); $('tr[data-file="'+file_directory+'"]').attr('data-size', size); $('tr[data-file="'+file_directory+'"]').find('td.filesize').text(humanFileSize(size)); - + return; } diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 7977272ee1..ddf8c3038b 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -617,21 +617,21 @@ class View { } public function fromTmpFile($tmpFile, $path) { - + if (Filesystem::isValidPath($path)) { - + // Get directory that the file is going into $file_path = \OC_User::getHome(\OC_User::getUser()) . '/files'.substr($path, 0, strrpos($path,'/')); - + // Create the directories if any if(empty($file_path) === false) { mkdir($file_path, 0770, true); } - + if (!$tmpFile) { debug_print_backtrace(); } - + $source = fopen($tmpFile, 'r'); if ($source) { $this->file_put_contents($path, $source); From 089052b13af7a5e27d225ab345616511f4eaf2a9 Mon Sep 17 00:00:00 2001 From: Luke Policinski Date: Thu, 20 Feb 2014 20:18:27 +0000 Subject: [PATCH 03/75] Fixed issue with drag and drop not in the root directory, for folders and files --- apps/files/js/filelist.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 17846c23b7..64315c0362 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -958,10 +958,9 @@ $(document).ready(function() { data.context.attr('data-size', size); data.context.find('td.filesize').text(humanFileSize(size)); } - else { - + else { // only append new file if uploaded into the current folder - if (file.directory !== FileList.getCurrentDirectory()) { + if (file.directory != '/' && file.directory !== FileList.getCurrentDirectory()) { file_directory = file.directory.replace('/','').replace(/\/$/, "").split('/'); @@ -977,12 +976,14 @@ $(document).ready(function() { else { file_directory = file_directory[0]; } + + file_directory = FileList.findFileEl(file_directory); // update folder size - var size = parseInt($('tr[data-file="'+file_directory+'"]').attr('data-size')); + var size = parseInt(file_directory.attr('data-size')); size += parseInt(file.size); - $('tr[data-file="'+file_directory+'"]').attr('data-size', size); - $('tr[data-file="'+file_directory+'"]').find('td.filesize').text(humanFileSize(size)); + file_directory.attr('data-size', size); + file_directory.find('td.filesize').text(humanFileSize(size)); return; } From 9c8596e95b81f9d5ddcd7132ac0134b0ffed67e5 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 1 Apr 2014 15:43:27 +0200 Subject: [PATCH 04/75] Keep cached urls with different hostnames or baseurls seperate --- lib/private/route/cachingrouter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/route/cachingrouter.php b/lib/private/route/cachingrouter.php index ad25372391..63bfd3e053 100644 --- a/lib/private/route/cachingrouter.php +++ b/lib/private/route/cachingrouter.php @@ -31,7 +31,7 @@ class CachingRouter extends Router { * @return string */ public function generate($name, $parameters = array(), $absolute = false) { - $key = $name . json_encode($parameters) . $absolute; + $key = $this->context->getHost() . $this->context->getBaseUrl() . $name . json_encode($parameters) . $absolute; if ($this->cache->hasKey($key)) { return $this->cache->get($key); } else { From c926e98ea96f4782bc75b97e4db5996dacd6e0d4 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Tue, 1 Apr 2014 17:18:03 +0200 Subject: [PATCH 05/75] fix log in input sizing caused by core input field switch to px --- core/css/styles.css | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/core/css/styles.css b/core/css/styles.css index 8a12057529..f750c72077 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -402,14 +402,32 @@ input[type="submit"].enabled { } /* Icons for username and password fields to better recognize them */ -#adminlogin, #adminpass, #user, #password { width:11.7em!important; padding-left:1.8em; } -#adminlogin+label+img, #adminpass-icon, #user+label+img, #password-icon { - position:absolute; left:1.25em; top:1.65em; - -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; filter:alpha(opacity=30); opacity:.3; +#adminlogin, #adminpass, #user, #password { + width: 223px !important; + padding-left: 36px !important; +} +#adminlogin+label+img, +#adminpass-icon, +#user+label+img, +#password-icon { + position: absolute; + left: 1.25em; + top: 1.65em; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; + filter: alpha(opacity=30); + opacity: .3; +} +#adminpass-icon, #password-icon { + top: 1.1em; +} +input[name="password-clone"] { + padding-left: 1.8em; + width: 11.7em !important; +} +input[name="adminpass-clone"] { + padding-left: 1.8em; + width: 11.7em !important; } -#adminpass-icon, #password-icon { top:1.1em; } -input[name="password-clone"] { padding-left:1.8em; width:11.7em !important; } -input[name="adminpass-clone"] { padding-left:1.8em; width:11.7em !important; } /* General new input field look */ #body-login input[type="text"], @@ -456,7 +474,7 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; } #body-login form input[type="checkbox"]+label { position: relative; margin: 0; - font-size: 1em; + font-size: 13px; padding: 14px; padding-left: 28px; margin-left: -28px; @@ -610,11 +628,13 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; } /* Log in and install button */ #body-login input { - font-size: 1.5em; + font-size: 20px; + margin: 5px; + padding: 12px 10px 8px; } #body-login input[type="text"], #body-login input[type="password"] { - width: 13em; + width: 249px; } #body-login input.login { width: auto; @@ -624,7 +644,7 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; } padding: 10px 20px; /* larger log in and installation buttons */ } #remember_login { - margin: 18px 5px 0 18px; + margin: 24px 5px 0 16px !important; vertical-align: text-bottom; } From 0c441724bc3031e50715169e9fd5541b347b2878 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Tue, 1 Apr 2014 17:21:05 +0200 Subject: [PATCH 06/75] make infield labels use less space so pasting in is easier --- core/css/styles.css | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/core/css/styles.css b/core/css/styles.css index f750c72077..7af80e31ff 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -466,9 +466,14 @@ input[name="adminpass-clone"] { p.infield { position:relative; } label.infield { cursor:text !important; top:1.05em; left:.85em; } #body-login form label.infield { /* labels are ellipsized when too long, keep them short */ - position:absolute; width:90%; padding-left:1.4em; - font-size:19px; color:#aaa; - white-space:nowrap; overflow:hidden; text-overflow:ellipsis; + position: absolute; + width: auto; + margin-left: 26px; + font-size: 19px; + color: #aaa; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } #body-login #databaseField .infield { padding-left:0; } #body-login form input[type="checkbox"]+label { From 51fbf0bcbc2c3c68f7b4b36128304f4ab9df98e7 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 7 Apr 2014 13:27:18 +0200 Subject: [PATCH 07/75] add delimiter between host and baseurl --- lib/private/route/cachingrouter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/route/cachingrouter.php b/lib/private/route/cachingrouter.php index 63bfd3e053..766c67c73a 100644 --- a/lib/private/route/cachingrouter.php +++ b/lib/private/route/cachingrouter.php @@ -31,7 +31,7 @@ class CachingRouter extends Router { * @return string */ public function generate($name, $parameters = array(), $absolute = false) { - $key = $this->context->getHost() . $this->context->getBaseUrl() . $name . json_encode($parameters) . $absolute; + $key = $this->context->getHost() . '#' . $this->context->getBaseUrl() . $name . json_encode($parameters) . $absolute; if ($this->cache->hasKey($key)) { return $this->cache->get($key); } else { From 6d373e97c32ec51bd649eeafdfcc3596067776f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 7 Apr 2014 23:02:49 +0200 Subject: [PATCH 08/75] remove unused exit() --- apps/files/ajax/upload.php | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 38175fa500..a5ce7b257d 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -196,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)))); } From 971a311feec6c4c2de905bdbbe71c2cf60296cb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 7 Apr 2014 23:03:19 +0200 Subject: [PATCH 09/75] adding parentId to file info array --- apps/files/lib/helper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php index b765fdaf3e..f9515d6715 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 From d15a4719d2bc58827d7cbe616ab25aaf376c8293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 7 Apr 2014 23:04:08 +0200 Subject: [PATCH 10/75] fix folder upload in js --- apps/files/js/filelist.js | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 69c97e8b32..4a59508330 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1103,33 +1103,38 @@ $(document).ready(function() { size += parseInt(file.size); data.context.attr('data-size', size); data.context.find('td.filesize').text(humanFileSize(size)); - } - else { + } else { // only append new file if uploaded into the current folder - if (file.directory != '/' && file.directory !== FileList.getCurrentDirectory()) { + if (file.directory !== '/' && file.directory !== FileList.getCurrentDirectory()) { - file_directory = file.directory.replace('/','').replace(/\/$/, "").split('/'); + var fileDirectory = file.directory.replace('/','').replace(/\/$/, "").split('/'); - if (file_directory.length == 1) { - file_directory = file_directory[0]; + if (fileDirectory.length === 1) { + fileDirectory = fileDirectory[0]; // Get the directory - if ($('tr[data-file="'+file_directory+'"]').length == 0) - { - FileList.addDir(file_directory, 0, new Date(), false); + if ($('tr[data-file="'+fileDirectory+'"]').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 { - file_directory = file_directory[0]; + } else { + fileDirectory = fileDirectory[0]; } - file_directory = FileList.findFileEl(file_directory); + fileDirectory = FileList.findFileEl(fileDirectory); // update folder size - var size = parseInt(file_directory.attr('data-size')); + var size = parseInt(fileDirectory.attr('data-size')); size += parseInt(file.size); - file_directory.attr('data-size', size); - file_directory.find('td.filesize').text(humanFileSize(size)); + fileDirectory.attr('data-size', size); + fileDirectory.find('td.filesize').text(humanFileSize(size)); return; } From 7dd00746556aa4be26e41a6f3b66095a29b02c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 7 Apr 2014 23:17:35 +0200 Subject: [PATCH 11/75] fixing mkdir code to respect external file systems as well --- lib/private/files/view.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 0dce90aec4..519ed250b1 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -633,11 +633,11 @@ class View { if (Filesystem::isValidPath($path)) { // Get directory that the file is going into - $file_path = \OC_User::getHome(\OC_User::getUser()) . '/files'.substr($path, 0, strrpos($path,'/')); + $filePath = dirname($path); // Create the directories if any - if(empty($file_path) === false) { - mkdir($file_path, 0770, true); + if (!$this->file_exists($filePath)) { + $this->mkdir($filePath); } if (!$tmpFile) { From 68b7822cf50a670619659ae2082633f4c62fb5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 7 Apr 2014 23:45:35 +0200 Subject: [PATCH 12/75] js style fixes according to our jshintrc rules --- apps/files/js/filelist.js | 114 +++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 58 deletions(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 4a59508330..ceaaed264a 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, SVGSupport */ +/* global procesSelection, dragOptions, folderDropOptions, SVGSupport */ window.FileList = { appName: t('files', 'Files'), isEmpty: true, @@ -228,7 +228,7 @@ window.FileList = { linkUrl = Files.getDownloadUrl(name, FileList.getCurrentDirectory()); } td.append(''); - var link_elem = $('').attr({ + var linkElem = $('').attr({ "class": "name", "href": linkUrl }); @@ -244,19 +244,19 @@ window.FileList = { basename = name; extension = false; } - var name_span=$('').addClass('nametext').text(basename); - link_elem.append(name_span); + var nameSpan=$('').addClass('nametext').text(basename); + linkElem.append(nameSpan); if (extension) { - name_span.append($('').addClass('extension').text(extension)); + nameSpan.append($('').addClass('extension').text(extension)); } // dirs can show the number of uploaded files if (type === 'dir') { - link_elem.append($('').attr({ + linkElem.append($('').attr({ 'class': 'uploadtext', 'currentUploads': 0 })); } - td.append(link_elem); + td.append(linkElem); tr.append(td); // size column @@ -266,7 +266,7 @@ window.FileList = { } else { simpleSize = t('files', 'Pending'); } - var lastModifiedTime = Math.round(mtime / 1000); + td = $('').attr({ "class": "filesize", "style": 'color:rgb(' + sizeColor + ',' + sizeColor + ',' + sizeColor + ')' @@ -453,8 +453,6 @@ window.FileList = { }); }, reloadCallback: function(result) { - var $controls = $('#controls'); - delete this._reloadCall; this.hideMask(); @@ -822,10 +820,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 = ''+humanFileSize(summary.totalSize)+''; + var fileSize = ''; + if (!isNaN(summary.totalSize)) { + fileSize = ''+humanFileSize(summary.totalSize)+''; } var $summary = $(''+info+''+fileSize+''); @@ -911,7 +908,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); @@ -949,13 +945,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'); }); } }, @@ -991,9 +987,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'); @@ -1021,7 +1017,7 @@ $(document).ready(function() { return [ {name: 'dir', value: dir}, {name: 'requesttoken', value: oc_requesttoken}, - {name: 'file_directory', value: data.files[0]['relativePath']} + {name: 'file_directory', value: data.files[0].relativePath} ]; }; } else { @@ -1032,7 +1028,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 @@ -1045,19 +1041,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); } } @@ -1066,7 +1062,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; @@ -1080,27 +1076,28 @@ $(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 { @@ -1131,8 +1128,8 @@ $(document).ready(function() { fileDirectory = FileList.findFileEl(fileDirectory); // update folder size - var size = parseInt(fileDirectory.attr('data-size')); - size += parseInt(file.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)); @@ -1140,7 +1137,7 @@ $(document).ready(function() { } // 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; } @@ -1152,37 +1149,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() { @@ -1212,8 +1212,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); } @@ -1222,8 +1221,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)); From 8bb27551bde2d5aa516f4df2918ca3ed0ccd18b0 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 20 Mar 2014 00:21:14 +0100 Subject: [PATCH 13/75] LDAP: make sure cache key for paged result cookie matches when limit or offset is null or 0 --- apps/user_ldap/lib/access.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 4d187bab8d..b8e7e9bb67 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -1184,7 +1184,7 @@ class Access extends LDAPUtility { } $offset -= $limit; //we work with cache here - $cachekey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' . $limit . '-' . $offset; + $cachekey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' . intval($limit) . '-' . intval($offset); $cookie = ''; if(isset($this->cookies[$cachekey])) { $cookie = $this->cookies[$cachekey]; @@ -1206,7 +1206,7 @@ class Access extends LDAPUtility { */ private function setPagedResultCookie($base, $filter, $limit, $offset, $cookie) { if(!empty($cookie)) { - $cachekey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' .$limit . '-' . $offset; + $cachekey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' .intval($limit) . '-' . intval($offset); $this->cookies[$cachekey] = $cookie; } } From 40f9875f11e1bd35dd96ebd8fc8cf718be49689c Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 20 Mar 2014 00:21:51 +0100 Subject: [PATCH 14/75] LDAP: fix user report i.e. count for LDAP servers with really many users --- apps/user_ldap/lib/access.php | 42 ++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index b8e7e9bb67..7640a5b1bc 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -659,7 +659,7 @@ class Access extends LDAPUtility { * @param string $filter */ public function countUsers($filter, $attr = array('dn'), $limit = null, $offset = null) { - return $this->count($filter, $this->connection->ldapBaseGroups, $attr, $limit, $offset); + return $this->count($filter, $this->connection->ldapBaseUsers, $attr, $limit, $offset); } /** @@ -775,22 +775,34 @@ class Access extends LDAPUtility { */ private function count($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) { \OCP\Util::writeLog('user_ldap', 'Count filter: '.print_r($filter, true), \OCP\Util::DEBUG); - $search = $this->executeSearch($filter, $base, $attr, $limit, $offset); - if($search === false) { - return false; - } - list($sr, $pagedSearchOK) = $search; - $cr = $this->connection->getConnectionResource(); - $counter = 0; - foreach($sr as $key => $res) { - $count = $this->ldap->countEntries($cr, $res); - if($count !== false) { - $counter += $count; - } + + if(is_null($limit)) { + //TODO replace 400 with $this->connection->ldapPagingSize; once PR 6221 is merged and move it to callee countUsers() + $limit = 400; } - $this->processPagedSearchStatus($sr, $filter, $base, $counter, $limit, + $counter = 0; + $cr = $this->connection->getConnectionResource(); + + do { + $search = $this->executeSearch($filter, $base, $attr, + $limit, $offset); + if($search === false) { + return $counter > 0 ? $counter : false; + } + list($sr, $pagedSearchOK) = $search; + + foreach($sr as $key => $res) { + $count = $this->ldap->countEntries($cr, $res); + if($count !== false) { + $counter += $count; + } + } + + $this->processPagedSearchStatus($sr, $filter, $base, $count, $limit, $offset, $pagedSearchOK, $skipHandling); + $offset += $limit; + } while($count === $limit); return $counter; } @@ -891,7 +903,7 @@ class Access extends LDAPUtility { //we slice the findings, when //a) paged search insuccessful, though attempted //b) no paged search, but limit set - if((!$this->pagedSearchedSuccessful + if((!$this->getPagedSearchResultState() && $pagedSearchOK) || ( !$pagedSearchOK From 43402c56ddbe5e4041fdcdc0605d16badeadb69b Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 20 Mar 2014 09:14:41 +0100 Subject: [PATCH 15/75] initialize variable --- apps/user_ldap/lib/access.php | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 7640a5b1bc..1af993677c 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -782,6 +782,7 @@ class Access extends LDAPUtility { } $counter = 0; + $count = null; $cr = $this->connection->getConnectionResource(); do { From bdc418d1f99738d45b2a0e4fab07c974d5b58681 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 20 Mar 2014 10:59:58 +0100 Subject: [PATCH 16/75] var count is assigned in the inner loop so it must be checked inside there to be properly used as part of the exit condition of the outer loop --- apps/user_ldap/lib/access.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 1af993677c..d135ee5b73 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -786,6 +786,7 @@ class Access extends LDAPUtility { $cr = $this->connection->getConnectionResource(); do { + $continue = false; $search = $this->executeSearch($filter, $base, $attr, $limit, $offset); if($search === false) { @@ -798,12 +799,15 @@ class Access extends LDAPUtility { if($count !== false) { $counter += $count; } + if($count === $limit) { + $continue = true; + } } $this->processPagedSearchStatus($sr, $filter, $base, $count, $limit, $offset, $pagedSearchOK, $skipHandling); $offset += $limit; - } while($count === $limit); + } while($continue); return $counter; } From 2e5adadad7b779f0794a6ecddb2b0f51b9214b4a Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 20 Mar 2014 11:38:05 +0100 Subject: [PATCH 17/75] Put inner loop into own method, let's see whether it makes scrutinizer happier --- apps/user_ldap/lib/access.php | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index d135ee5b73..ce97aaff14 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -794,15 +794,8 @@ class Access extends LDAPUtility { } list($sr, $pagedSearchOK) = $search; - foreach($sr as $key => $res) { - $count = $this->ldap->countEntries($cr, $res); - if($count !== false) { - $counter += $count; - } - if($count === $limit) { - $continue = true; - } - } + $count = $this->countEntriesInSearchResults($sr, $limit, $continue); + $counter += $count; $this->processPagedSearchStatus($sr, $filter, $base, $count, $limit, $offset, $pagedSearchOK, $skipHandling); @@ -812,6 +805,22 @@ class Access extends LDAPUtility { return $counter; } + private function countEntriesInSearchResults($searchResults, $limit, + &$hasHitLimit) { + $cr = $this->connection->getConnectionResource(); + $count = 0; + + foreach($searchResults as $res) { + $count = intval($this->ldap->countEntries($cr, $res)); + $counter += $count; + if($count === $limit) { + $hasHitLimit = true; + } + } + + return $counter; + } + /** * @brief executes an LDAP search * @param $filter the LDAP filter for the search From ee3368d2ad8c362e27d904bbb22c7b741b09cff8 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 9 Apr 2014 11:38:51 +0200 Subject: [PATCH 18/75] replace hardcoded limit of 400 with user controlled ldapPagingSize value --- apps/user_ldap/lib/access.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index ce97aaff14..0b3ff4aa15 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -777,8 +777,7 @@ class Access extends LDAPUtility { \OCP\Util::writeLog('user_ldap', 'Count filter: '.print_r($filter, true), \OCP\Util::DEBUG); if(is_null($limit)) { - //TODO replace 400 with $this->connection->ldapPagingSize; once PR 6221 is merged and move it to callee countUsers() - $limit = 400; + $limit = $this->connection->ldapPagingSize; } $counter = 0; From 2fc9e27ceddf9d632d79916a71f9100138bb685f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 9 Apr 2014 22:16:41 +0200 Subject: [PATCH 19/75] use FileList.findFileEl --- apps/files/js/filelist.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 8ee89aad3e..9c749bb8f3 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1098,7 +1098,8 @@ $(document).ready(function() { fileDirectory = fileDirectory[0]; // Get the directory - if ($('tr[data-file="'+fileDirectory+'"]').length === 0) { + var fd = FileList.findFileEl(fileDirectory); + if (fd.length === 0) { var dir = { name: fileDirectory, type: 'dir', From e8be2ac55492a7e4f141d3bb7e6698783bef454c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 9 Apr 2014 23:32:12 +0200 Subject: [PATCH 20/75] In cases folder drag and drop is not supported a proper message is displayed --- apps/files/js/file-upload.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 46a5320840..070314a118 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -242,11 +242,18 @@ 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 + 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 From 0edacf372c5b2e1f1b64210ceff5e757494c959b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 10 Apr 2014 18:07:36 +0200 Subject: [PATCH 21/75] fix single file upload in firefox --- apps/files/js/file-upload.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 070314a118..516812563a 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -333,11 +333,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(), - file_directory: data.files[0]['relativePath'] + file_directory: fileDirectory }; } }, From 9e9c109390c265cdb63b5788365ce74034009a6c Mon Sep 17 00:00:00 2001 From: Volkan Gezer Date: Thu, 10 Apr 2014 21:54:25 +0200 Subject: [PATCH 22/75] Expiration date is hidden smoothly From now on, it is hidden smoothly as the other fields do. --- core/js/share.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/js/share.js b/core/js/share.js index ef71cc7999..19d71a6cbd 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -480,15 +480,16 @@ OC.Share={ $('#emailPrivateLink #email').hide(); $('#emailPrivateLink #emailButton').hide(); $('#allowPublicUploadWrapper').hide(); + $('#expirationDate').hide(); }, dirname:function(path) { return path.replace(/\\/g,'/').replace(/\/[^\/]*$/, ''); }, showExpirationDate:function(date) { $('#expirationCheckbox').attr('checked', true); - $('#expirationDate').before('
'); $('#expirationDate').val(date); - $('#expirationDate').show(); + $('#expirationDate').show('blind'); + $('#expirationDate').css('display','block'); $('#expirationDate').datepicker({ dateFormat : 'dd-mm-yy' }); @@ -558,7 +559,7 @@ $(document).ready(function() { OC.Share.itemShares[shareType].splice(index, 1); OC.Share.updateIcon(itemType, itemSource); if (typeof OC.Share.statuses[itemSource] === 'undefined') { - $('#expiration').hide(); + $('#expiration').hide('blind'); } }); return false; @@ -618,7 +619,7 @@ $(document).ready(function() { OC.Share.itemShares[OC.Share.SHARE_TYPE_LINK] = false; OC.Share.updateIcon(itemType, itemSource); if (typeof OC.Share.statuses[itemSource] === 'undefined') { - $('#expiration').hide(); + $('#expiration').hide('blind'); } }); } @@ -710,7 +711,7 @@ $(document).ready(function() { if (!result || result.status !== 'success') { OC.dialogs.alert(t('core', 'Error unsetting expiration date'), t('core', 'Error')); } - $('#expirationDate').hide(); + $('#expirationDate').hide('blind'); }); } }); From 07ea57465ba23dd31dae943b44f4c04ccabb5e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 11 Apr 2014 14:54:13 +0200 Subject: [PATCH 23/75] drop folder support on public shared folders --- apps/files_sharing/js/public.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 9ce8985f1f..ae2412f6a3 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 }; }); From 6343391e580b0a686f2b2ee2b0b43ca675473be8 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Fri, 11 Apr 2014 20:38:27 +0200 Subject: [PATCH 24/75] Change from showHTML to show There is no need to use `showHTML` here. --- apps/files/js/files.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files/js/files.js b/apps/files/js/files.js index ac10191618..9f38263bef 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -135,7 +135,7 @@ var Files = { return; } if (initStatus === '1') { // encryption tried to init but failed - OC.Notification.showHtml(t('files', 'Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files.')); + OC.Notification.show(t('files', 'Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files.')); return; } if (encryptedFiles === '1') { From df67a04385e64d2e14a7c0385289904d04b53301 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Sun, 13 Apr 2014 11:51:03 +0200 Subject: [PATCH 25/75] Move security headers to base.php Some headers were currently only added to the templates but not to other components (e.g. SabreDAV / JSON / etc...) The migration to base.php ensures that the headers are served to all requests passing base.php --- lib/base.php | 31 +++++++++++++++++++++++++++++++ lib/private/template.php | 26 +------------------------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/lib/base.php b/lib/base.php index 6ea77aa7a5..34baba69d4 100644 --- a/lib/base.php +++ b/lib/base.php @@ -213,6 +213,36 @@ class OC { } } + /* + * This function adds some security related headers to all requests + * served via base.php + * The implementation of this function as to happen here to ensure that + * all third-party components (e.g. SabreDAV) also benefit from this + * headers + */ + public static function addSecurityHeaders() { + header('X-XSS-Protection: 1; mode=block'); // Enforce browser based XSS filters + header('X-Content-Type-Options: nosniff'); // Disable sniffing the content type for IE + + // iFrame Restriction Policy + $xFramePolicy = OC_Config::getValue('xframe_restriction', true); + if($xFramePolicy) { + header('X-Frame-Options: Sameorigin'); // Disallow iFraming from other domains + } + + // Content Security Policy + // If you change the standard policy, please also change it in config.sample.php + $policy = OC_Config::getValue('custom_csp_policy', + 'default-src \'self\'; ' + .'script-src \'self\' \'unsafe-eval\'; ' + .'style-src \'self\' \'unsafe-inline\'; ' + .'frame-src *; ' + .'img-src *; ' + .'font-src \'self\' data:; ' + .'media-src *'); + header('Content-Security-Policy:'.$policy); + } + public static function checkSSL() { // redirect to https site if configured if (OC_Config::getValue("forcessl", false)) { @@ -512,6 +542,7 @@ class OC { self::checkConfig(); self::checkInstalled(); self::checkSSL(); + self::addSecurityHeaders(); $errors = OC_Util::checkServer(); if (count($errors) > 0) { diff --git a/lib/private/template.php b/lib/private/template.php index c6851c6cc8..b7db569095 100644 --- a/lib/private/template.php +++ b/lib/private/template.php @@ -64,31 +64,7 @@ class OC_Template extends \OC\Template\Base { $this->path = $path; parent::__construct($template, $requesttoken, $l10n, $themeDefaults); - - // Some headers to enhance security - header('X-XSS-Protection: 1; mode=block'); // Enforce browser based XSS filters - header('X-Content-Type-Options: nosniff'); // Disable sniffing the content type for IE - - // iFrame Restriction Policy - $xFramePolicy = OC_Config::getValue('xframe_restriction', true); - if($xFramePolicy) { - header('X-Frame-Options: Sameorigin'); // Disallow iFraming from other domains - } - - // Content Security Policy - // If you change the standard policy, please also change it in config.sample.php - $policy = OC_Config::getValue('custom_csp_policy', - 'default-src \'self\'; ' - .'script-src \'self\' \'unsafe-eval\'; ' - .'style-src \'self\' \'unsafe-inline\'; ' - .'frame-src *; ' - .'img-src *; ' - .'font-src \'self\' data:; ' - .'media-src *'); - header('Content-Security-Policy:'.$policy); // Standard - - } - +} /** * autodetect the formfactor of the used device * default -> the normal desktop browser interface From a2a850dd91664cbfeba50186d5219d90d62eadd2 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Sun, 13 Apr 2014 11:52:31 +0200 Subject: [PATCH 26/75] Fix indentation --- lib/private/template.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/private/template.php b/lib/private/template.php index b7db569095..610d5fbc8e 100644 --- a/lib/private/template.php +++ b/lib/private/template.php @@ -64,7 +64,8 @@ class OC_Template extends \OC\Template\Base { $this->path = $path; parent::__construct($template, $requesttoken, $l10n, $themeDefaults); -} + } + /** * autodetect the formfactor of the used device * default -> the normal desktop browser interface From b04d95b1160673dbaa80ce214f22e931e8c93178 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Sun, 13 Apr 2014 12:48:16 +0200 Subject: [PATCH 27/75] Remove uneeded usages of nosniff --- lib/private/json.php | 2 -- lib/public/appframework/http/jsonresponse.php | 1 - tests/lib/appframework/http/JSONResponseTest.php | 7 ------- 3 files changed, 10 deletions(-) diff --git a/lib/private/json.php b/lib/private/json.php index 4ccdb490a6..34f81c3b8c 100644 --- a/lib/private/json.php +++ b/lib/private/json.php @@ -119,8 +119,6 @@ class OC_JSON{ * Encode and print $data in json format */ public static function encodedPrint($data, $setContentType=true) { - // Disable mimesniffing, don't move this to setContentTypeHeader! - header( 'X-Content-Type-Options: nosniff' ); if($setContentType) { self::setContentTypeHeader(); } diff --git a/lib/public/appframework/http/jsonresponse.php b/lib/public/appframework/http/jsonresponse.php index 6628c4514d..6d029b7464 100644 --- a/lib/public/appframework/http/jsonresponse.php +++ b/lib/public/appframework/http/jsonresponse.php @@ -49,7 +49,6 @@ class JSONResponse extends Response { public function __construct($data=array(), $statusCode=Http::STATUS_OK) { $this->data = $data; $this->setStatus($statusCode); - $this->addHeader('X-Content-Type-Options', 'nosniff'); $this->addHeader('Content-type', 'application/json; charset=utf-8'); } diff --git a/tests/lib/appframework/http/JSONResponseTest.php b/tests/lib/appframework/http/JSONResponseTest.php index b9b7c7d638..fbaae1b922 100644 --- a/tests/lib/appframework/http/JSONResponseTest.php +++ b/tests/lib/appframework/http/JSONResponseTest.php @@ -79,13 +79,6 @@ class JSONResponseTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $this->json->render()); } - - public function testShouldHaveXContentHeaderByDefault() { - $headers = $this->json->getHeaders(); - $this->assertEquals('nosniff', $headers['X-Content-Type-Options']); - } - - public function testConstructorAllowsToSetData() { $data = array('hi'); $code = 300; From 387d46cb988ba2e617de9ede0ff6fb8430e59758 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Sun, 13 Apr 2014 12:54:26 +0200 Subject: [PATCH 28/75] Typo + Line breaks --- lib/base.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/base.php b/lib/base.php index 34baba69d4..5fb7b0b467 100644 --- a/lib/base.php +++ b/lib/base.php @@ -214,11 +214,9 @@ class OC { } /* - * This function adds some security related headers to all requests - * served via base.php - * The implementation of this function as to happen here to ensure that - * all third-party components (e.g. SabreDAV) also benefit from this - * headers + * This function adds some security related headers to all requests served via base.php + * The implementation of this function as hto happen here to ensure that all third-party + * components (e.g. SabreDAV) also benefit from this headers. */ public static function addSecurityHeaders() { header('X-XSS-Protection: 1; mode=block'); // Enforce browser based XSS filters From fa8814902e9012880179e61ea846a7d85e3079f8 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Sun, 13 Apr 2014 13:47:08 +0100 Subject: [PATCH 29/75] Adjust logic for deciding if trashbin empty Any error in opening the trashbin directory returns 'true' for isEmpty. An error is prevented by checking if the directory exists before trying to open it. --- apps/files_trashbin/lib/trashbin.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 7b14a4ec08..bf8d465e5d 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -921,13 +921,11 @@ class Trashbin { public static function isEmpty($user) { $view = new \OC\Files\View('/' . $user . '/files_trashbin'); - $dh = $view->opendir('/files'); - if (!$dh) { - return false; - } - while ($file = readdir($dh)) { - if ($file !== '.' and $file !== '..') { - return false; + if ($view->is_dir('/files') && $dh = $view->opendir('/files')) { + while ($file = readdir($dh)) { + if ($file !== '.' and $file !== '..') { + return false; + } } } return true; From 869e7a51f0ed5b24c1ee0714112edb71e7dd1b62 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Sun, 13 Apr 2014 14:46:37 +0100 Subject: [PATCH 30/75] Prevent error in files_trashbin `glob` can return FALSE when the directory is empty, instead of an empty array, causing an error at `foreach`. "Note: On some systems it is impossible to distinguish between empty match and an error." See http://www.php.net/manual/en/function.glob.php -> Return Values --- apps/files_trashbin/lib/trashbin.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index bf8d465e5d..9b931333b7 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -824,13 +824,15 @@ class Trashbin { $matches = glob($escapedVersionsName . '*'); } - foreach ($matches as $ma) { - if ($timestamp) { - $parts = explode('.v', substr($ma, 0, $offset)); - $versions[] = (end($parts)); - } else { - $parts = explode('.v', $ma); - $versions[] = (end($parts)); + if (is_array($matches)) { + foreach ($matches as $ma) { + if ($timestamp) { + $parts = explode('.v', substr($ma, 0, $offset)); + $versions[] = (end($parts)); + } else { + $parts = explode('.v', $ma); + $versions[] = (end($parts)); + } } } return $versions; From eeee9eacea333035e22ef3ed938e36f56bc762cd Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Sun, 13 Apr 2014 16:17:13 +0100 Subject: [PATCH 31/75] Prevent error from cache update on deleted files --- lib/private/files/storage/local.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/private/files/storage/local.php b/lib/private/files/storage/local.php index 571bf7f97c..ff2949d33b 100644 --- a/lib/private/files/storage/local.php +++ b/lib/private/files/storage/local.php @@ -305,7 +305,11 @@ if (\OC_Util::runningOnWindows()) { * @return bool */ public function hasUpdated($path, $time) { - return $this->filemtime($path) > $time; + if ($this->file_exists($path)) { + return $this->filemtime($path) > $time; + } else { + return true; + } } /** From 8bb003868c9f319e387bf464a035a3b2fd123531 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Sun, 13 Apr 2014 16:49:23 +0100 Subject: [PATCH 32/75] Fix user_ldap default setting value --- apps/user_ldap/templates/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 0a111225a7..03f2b8db09 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -37,7 +37,7 @@

-

+

t('Special Attributes'));?>

From c123dc7de4d9dde46bd31dbf6211704f1b4bb82d Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Mon, 14 Apr 2014 10:15:31 +0200 Subject: [PATCH 33/75] Fix typo Thanks @DeepDiver1975 --- lib/base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/base.php b/lib/base.php index 5fb7b0b467..7098f480e2 100644 --- a/lib/base.php +++ b/lib/base.php @@ -215,7 +215,7 @@ class OC { /* * This function adds some security related headers to all requests served via base.php - * The implementation of this function as hto happen here to ensure that all third-party + * The implementation of this function has to happen here to ensure that all third-party * components (e.g. SabreDAV) also benefit from this headers. */ public static function addSecurityHeaders() { From 2bda3f9ae0893e94bd07a9c8916adcf06aa4a597 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Mon, 14 Apr 2014 20:16:52 +0200 Subject: [PATCH 34/75] Use direct link instead of JS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to our CSP policy this link won’t work as it it considered as inline Javascript. This commit replaces the link with a static link to the files app. Reimplementation of #8067 - fixes #7742 --- lib/private/files.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/private/files.php b/lib/private/files.php index bfe6d3c02d..e6135c4329 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -231,7 +231,7 @@ class OC_Files { OC_Template::printErrorPage( $l->t('ZIP download is turned off.'), $l->t('Files need to be downloaded one by one.') - . '
' . $l->t('Back to Files') . '' + . '
' . $l->t('Back to Files') . '' ); exit; } @@ -258,8 +258,7 @@ class OC_Files { OC_Template::printErrorPage( $l->t('Selected files too large to generate zip file.'), $l->t('Please download the files separately in smaller chunks or kindly ask your administrator.') - .'
' - . $l->t('Back to Files') . '' + . '
' . $l->t('Back to Files') . '' ); exit; } From 91d40f5033a4b8d30147a0f9673375f7aeea4271 Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Mon, 14 Apr 2014 21:49:46 +0300 Subject: [PATCH 35/75] remove unneeded LOWER. Fixes #8202 --- lib/private/user/database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/user/database.php b/lib/private/user/database.php index 15e6643dfb..994a47011e 100644 --- a/lib/private/user/database.php +++ b/lib/private/user/database.php @@ -121,7 +121,7 @@ class OC_User_Database extends OC_User_Backend { */ public function setDisplayName($uid, $displayName) { if ($this->userExists($uid)) { - $query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `displayname` = ? WHERE LOWER(`uid`) = ?'); + $query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `displayname` = ? WHERE LOWER(`uid`) = LOWER(?)'); $query->execute(array($displayName, $uid)); return true; } else { From 7f77b08098426801bfede696a88671efc1f82d83 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 15 Apr 2014 15:48:02 +0200 Subject: [PATCH 36/75] Sort parameters and cast to int --- lib/private/route/cachingrouter.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/private/route/cachingrouter.php b/lib/private/route/cachingrouter.php index 766c67c73a..6412ceb041 100644 --- a/lib/private/route/cachingrouter.php +++ b/lib/private/route/cachingrouter.php @@ -31,7 +31,8 @@ class CachingRouter extends Router { * @return string */ public function generate($name, $parameters = array(), $absolute = false) { - $key = $this->context->getHost() . '#' . $this->context->getBaseUrl() . $name . json_encode($parameters) . $absolute; + sort($parameters); + $key = $this->context->getHost() . '#' . $this->context->getBaseUrl() . $name . json_encode($parameters) . intval($absolute); if ($this->cache->hasKey($key)) { return $this->cache->get($key); } else { From 02726acbc8bfd436dff97eaff575eb2572ecd48b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 15 Apr 2014 16:26:12 +0200 Subject: [PATCH 37/75] adding checks and log messages regarding the assets folder --- lib/private/templatelayout.php | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/private/templatelayout.php b/lib/private/templatelayout.php index af17adb11c..0c0c8d9c8d 100644 --- a/lib/private/templatelayout.php +++ b/lib/private/templatelayout.php @@ -66,7 +66,7 @@ class OC_TemplateLayout extends OC_Template { } $versionParameter = '?v=' . md5(implode(OC_Util::getVersion())); - $useAssetPipeline = OC_Config::getValue('asset-pipeline.enabled', false); + $useAssetPipeline = $this->isAssetPipelineEnabled(); if ($useAssetPipeline) { $this->append( 'jsfiles', OC_Helper::linkToRoute('js_config') . $versionParameter); @@ -179,4 +179,33 @@ class OC_TemplateLayout extends OC_Template { sort($files); return hash('md5', implode('', $files)); } + + /** + * @return bool + */ + private function isAssetPipelineEnabled() { + // asset management enabled? + $useAssetPipeline = OC_Config::getValue('asset-pipeline.enabled', false); + if (!$useAssetPipeline) { + return false; + } + + // assets folder exists? + $assetDir = \OC::$SERVERROOT . '/assets'; + if (!is_dir($assetDir)) { + if (!mkdir($assetDir)) { + \OCP\Util::writeLog('assets', + "Folder <$assetDir> does not exist and/or could not be generated.", \OCP\Util::ERROR); + return false; + } + } + + // assets folder can be accessed? + if (!touch($assetDir."/.oc")) { + \OCP\Util::writeLog('assets', + "Folder <$assetDir> could not be accessed.", \OCP\Util::ERROR); + return false; + } + return $useAssetPipeline; + } } From 30168169b973eb1ca909a9a811b72d28588e1100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 15 Apr 2014 16:56:45 +0200 Subject: [PATCH 38/75] Flush the Buffer Early - right after head --- core/templates/layout.base.php | 2 +- core/templates/layout.guest.php | 2 +- core/templates/layout.user.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/templates/layout.base.php b/core/templates/layout.base.php index b3e2f4da91..c519388fa3 100644 --- a/core/templates/layout.base.php +++ b/core/templates/layout.base.php @@ -30,7 +30,7 @@ ?> - + diff --git a/core/templates/layout.guest.php b/core/templates/layout.guest.php index 5788d1d5bd..1f89e3f040 100644 --- a/core/templates/layout.guest.php +++ b/core/templates/layout.guest.php @@ -32,7 +32,7 @@ ?> - +