From 1291303c5a312fad9f01fbaf22cc21e3b9b3675d Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Sun, 2 Mar 2014 22:30:24 +0100 Subject: Replace OC.Router.generate() with OC.generateUrl() --- apps/files/js/filelist.js | 4 +++- apps/files/js/files.js | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'apps/files/js') diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 550c10dba3e..c3c7f4c2b9b 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -137,7 +137,9 @@ window.FileList={ var download_url = null; if (!param.download_url) { - download_url = OC.Router.generate('download', { file: $('#dir').val()+'/'+name }); + download_url = OC.generateUrl( + '/download{file}', + { file: $('#dir').val()+'/'+name }); } else { download_url = param.download_url; } diff --git a/apps/files/js/files.js b/apps/files/js/files.js index f4546120702..c93862e85d8 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -780,9 +780,9 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) { if ( $('#isPublic').length ) { urlSpec.t = $('#dirToken').val(); - previewURL = OC.Router.generate('core_ajax_public_preview', urlSpec); + previewURL = OC.generateUrl('/publicpreview.png?') + $.param(urlSpec); } else { - previewURL = OC.Router.generate('core_ajax_preview', urlSpec); + previewURL = OC.generateUrl('/core/preview.png?') + $.param(urlSpec); } previewURL = previewURL.replace('(', '%28'); previewURL = previewURL.replace(')', '%29'); -- cgit v1.2.3 From 9f087a2070c1115eeb6bd0d961f7629e19eceefc Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Sun, 2 Mar 2014 23:41:14 +0100 Subject: fixing download url in files app --- apps/files/js/filelist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apps/files/js') diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index c3c7f4c2b9b..d6a4ae99764 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -138,7 +138,7 @@ window.FileList={ var download_url = null; if (!param.download_url) { download_url = OC.generateUrl( - '/download{file}', + 'apps/files/download{file}', { file: $('#dir').val()+'/'+name }); } else { download_url = param.download_url; -- cgit v1.2.3 From 2e73c957e5b3ae4030e41520088fb078354ae8b1 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 4 Mar 2014 16:42:40 +0100 Subject: don't allow to create a file or folder named 'Shared' in the root folder, also exclude all combinations of lower and upper case letters --- apps/files/ajax/move.php | 2 +- apps/files/js/file-upload.js | 34 ++++++++++++++--------------- apps/files/js/filelist.js | 9 +++----- apps/files/js/files.js | 7 ++++-- apps/files/tests/js/filesSpec.js | 35 ++++++++++++++++++++++++++++++ lib/private/connector/sabre/directory.php | 4 ++-- lib/private/connector/sabre/objecttree.php | 3 +++ 7 files changed, 66 insertions(+), 28 deletions(-) (limited to 'apps/files/js') diff --git a/apps/files/ajax/move.php b/apps/files/ajax/move.php index 93063e52eb0..04a260265c2 100644 --- a/apps/files/ajax/move.php +++ b/apps/files/ajax/move.php @@ -18,7 +18,7 @@ if(\OC\Files\Filesystem::file_exists($target . '/' . $file)) { exit; } -if ($dir != '' || $file != 'Shared') { +if ($target != '' || strtolower($file) != 'shared') { $targetFile = \OC\Files\Filesystem::normalizePath($target . '/' . $file); $sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) { diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index f962a7044a8..aa85644cefb 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -82,7 +82,7 @@ OC.Upload = { */ isProcessing:function() { var count = 0; - + jQuery.each(this._uploads,function(i, data) { if (data.state() === 'pending') { count++; @@ -208,13 +208,13 @@ $(document).ready(function() { add: function(e, data) { OC.Upload.log('add', e, data); var that = $(this); - + // we need to collect all data upload objects before starting the upload so we can check their existence // and set individual conflict actions. unfortunately there is only one variable that we can use to identify // the selection a data upload is part of, so we have to collect them in data.originalFiles // turning singleFileUploads off is not an option because we want to gracefully handle server errors like // already exists - + // create a container where we can store the data objects if ( ! data.originalFiles.selection ) { // initialize selection and remember number of files to upload @@ -225,34 +225,34 @@ $(document).ready(function() { }; } var selection = data.originalFiles.selection; - + // add uploads if ( selection.uploads.length < selection.filesToUpload ) { // remember upload selection.uploads.push(data); } - + //examine file var file = data.files[0]; try { // FIXME: not so elegant... need to refactor that method to return a value - Files.isFileNameValid(file.name); + Files.isFileNameValid(file.name, FileList.getCurrentDirectory()); } catch (errorMessage) { data.textStatus = 'invalidcharacters'; 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} ); } - + // add size selection.totalBytes += file.size; - + // check PHP upload limit if (selection.totalBytes > $('#upload_limit').val()) { data.textStatus = 'sizeexceedlimit'; @@ -270,7 +270,7 @@ $(document).ready(function() { 'size2': humanFileSize($('#free_space').val()) }); } - + // end upload for whole selection on error if (data.errorThrown) { // trigger fileupload fail @@ -281,12 +281,12 @@ $(document).ready(function() { // check existing files when all is collected if ( selection.uploads.length >= selection.filesToUpload ) { - + //remove our selection hack: delete data.originalFiles.selection; var callbacks = { - + onNoConflicts: function (selection) { $.each(selection.uploads, function(i, upload) { upload.submit(); @@ -309,7 +309,7 @@ $(document).ready(function() { }; OC.Upload.checkExistingFiles(selection, callbacks); - + } return true; // continue adding files @@ -439,7 +439,7 @@ $(document).ready(function() { }); fileupload.on('fileuploadstop', function(e, data) { OC.Upload.log('progress handle fileuploadstop', e, data); - + $('#uploadprogresswrapper input.stop').fadeOut(); $('#uploadprogressbar').fadeOut(); Files.updateStorageStatistics(); @@ -531,7 +531,7 @@ $(document).ready(function() { if ($(this).children('p').length === 0) { return; } - + $('#new .error').tipsy('hide'); $('#new li').each(function(i,element) { @@ -545,7 +545,7 @@ $(document).ready(function() { var text=$(this).children('p').text(); $(this).data('text',text); $(this).children('p').remove(); - + // add input field var form = $('
'); var input = $(''); @@ -562,7 +562,7 @@ $(document).ready(function() { throw t('files', 'URL cannot be empty'); } else if (type !== 'web' && !Files.isFileNameValid(filename)) { // Files.isFileNameValid(filename) throws an exception itself - } else if ($('#dir').val() === '/' && filename === 'Shared') { + } else if (FileList.getCurrentDirectory() === '/' && filename.toLowerCase() === 'shared') { throw t('files', 'In the home folder \'Shared\' is a reserved filename'); } else if (FileList.inList(filename)) { throw t('files', '{new_name} already exists', {new_name: filename}); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 550c10dba3e..020ee275b7d 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -419,15 +419,12 @@ window.FileList={ len = input.val().length; } input.selectRange(0, len); - var checkInput = function () { var filename = input.val(); if (filename !== oldname) { - if (!Files.isFileNameValid(filename)) { - // Files.isFileNameValid(filename) throws an exception itself - } else if($('#dir').val() === '/' && filename === 'Shared') { - throw t('files','In the home folder \'Shared\' is a reserved filename'); - } else if (FileList.inList(filename)) { + // Files.isFileNameValid(filename) throws an exception itself + Files.isFileNameValid(filename, FileList.getCurrentDirectory()); + if (FileList.inList(filename)) { throw t('files', '{new_name} already exists', {new_name: filename}); } } diff --git a/apps/files/js/files.js b/apps/files/js/files.js index f4546120702..48e5771ae8a 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -87,9 +87,12 @@ var Files = { * Throws a string exception with an error message if * the file name is not valid */ - isFileNameValid: function (name) { + isFileNameValid: function (name, root) { var trimmedName = name.trim(); - if (trimmedName === '.' || trimmedName === '..') { + if (trimmedName === '.' + || trimmedName === '..' + || (root === '/' && trimmedName.toLowerCase() === 'shared')) + { throw t('files', '"{name}" is an invalid file name.', {name: name}); } else if (trimmedName.length === 0) { throw t('files', 'File name cannot be empty.'); diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js index 018c8ef0f3c..95bf87e03ec 100644 --- a/apps/files/tests/js/filesSpec.js +++ b/apps/files/tests/js/filesSpec.js @@ -48,6 +48,41 @@ describe('Files tests', function() { expect(error).toEqual(false); } }); + it('Validates correct file names do not create Shared folder in root', function() { + // create shared file in subfolder + var error = false; + try { + expect(Files.isFileNameValid('shared', '/foo')).toEqual(true); + expect(Files.isFileNameValid('Shared', '/foo')).toEqual(true); + } + catch (e) { + error = e; + } + expect(error).toEqual(false); + + // create shared file in root + var threwException = false; + try { + Files.isFileNameValid('Shared', '/'); + console.error('Invalid file name not detected'); + } + catch (e) { + threwException = true; + } + expect(threwException).toEqual(true); + + // create shared file in root + var threwException = false; + try { + Files.isFileNameValid('shared', '/'); + console.error('Invalid file name not detected'); + } + catch (e) { + threwException = true; + } + expect(threwException).toEqual(true); + + }); it('Detects invalid file names', function() { var fileNames = [ '', diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index 02d1a9f4ba2..3ed9e94d69b 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -50,7 +50,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createFile($name, $data = null) { - if ($name === 'Shared' && empty($this->path)) { + if (strtolower($name) === 'shared' && empty($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } @@ -86,7 +86,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createDirectory($name) { - if ($name === 'Shared' && empty($this->path)) { + if (strtolower($name) === 'shared' && empty($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php index d2fa425b22c..accf020daa2 100644 --- a/lib/private/connector/sabre/objecttree.php +++ b/lib/private/connector/sabre/objecttree.php @@ -94,6 +94,9 @@ class ObjectTree extends \Sabre_DAV_ObjectTree { } if ($sourceDir !== $destinationDir) { // for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir + if (ltrim($destinationDir, '/') === '' && strtolower($sourceNode->getName()) === 'shared') { + throw new \Sabre_DAV_Exception_Forbidden(); + } if (!$fs->isUpdatable($sourceDir)) { throw new \Sabre_DAV_Exception_Forbidden(); } -- cgit v1.2.3 From 1ab10cb4f7e085f957198e05e727c81b2c9b27a9 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 5 Mar 2014 18:46:55 +0100 Subject: Do not set #dir when on public.php Fix #7571 --- apps/files/js/filelist.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'apps/files/js') diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 550c10dba3e..9a64035d72a 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1156,9 +1156,9 @@ $(document).ready(function() { // need to initially switch the dir to the one from the hash (IE8) FileList.changeDirectory(parseCurrentDirFromUrl(), false, true); } - } - FileList.setCurrentDir(parseCurrentDirFromUrl(), false); + FileList.setCurrentDir(parseCurrentDirFromUrl(), false); + } FileList.createFileSummary(); }); -- cgit v1.2.3 From 07f78c824833bfcb3233f881286dc625d81e44f6 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 6 Mar 2014 13:49:57 +0100 Subject: Added unit tests for "add()" method for file upload - Added OC.Upload.init() to make the code testable - Added unit tests for the add() method of the uploader with some error cases --- apps/files/js/file-upload.js | 1003 +++++++++++++++++---------------- apps/files/tests/js/fileUploadSpec.js | 127 +++++ 2 files changed, 631 insertions(+), 499 deletions(-) create mode 100644 apps/files/tests/js/fileUploadSpec.js (limited to 'apps/files/js') diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index aa85644cefb..b9c4dc941f7 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -177,549 +177,554 @@ OC.Upload = { checkExistingFiles: function (selection, callbacks) { // TODO check filelist before uploading and show dialog on conflicts, use callbacks callbacks.onNoConflicts(selection); - } -}; - -$(document).ready(function() { - - if ( $('#file_upload_start').exists() ) { - - var file_upload_param = { - dropZone: $('#content'), // restrict dropZone to content div - autoUpload: false, - sequentialUploads: true, - //singleFileUploads is on by default, so the data.files array will always have length 1 - /** - * on first add of every selection - * - check all files of originalFiles array with files in dir - * - on conflict show dialog - * - skip all -> remember as single skip action for all conflicting files - * - replace all -> remember as single replace action for all conflicting files - * - choose -> show choose dialog - * - mark files to keep - * - when only existing -> remember as single skip action - * - when only new -> remember as single replace action - * - when both -> remember as single autorename action - * - start uploading selection - * @param {object} e - * @param {object} data - * @returns {boolean} - */ - add: function(e, data) { - OC.Upload.log('add', e, data); - var that = $(this); - - // we need to collect all data upload objects before starting the upload so we can check their existence - // and set individual conflict actions. unfortunately there is only one variable that we can use to identify - // the selection a data upload is part of, so we have to collect them in data.originalFiles - // turning singleFileUploads off is not an option because we want to gracefully handle server errors like - // already exists - - // create a container where we can store the data objects - if ( ! data.originalFiles.selection ) { - // initialize selection and remember number of files to upload - data.originalFiles.selection = { - uploads: [], - filesToUpload: data.originalFiles.length, - totalBytes: 0 - }; - } - var selection = data.originalFiles.selection; - - // add uploads - if ( selection.uploads.length < selection.filesToUpload ) { - // remember upload - selection.uploads.push(data); - } - - //examine file - var file = data.files[0]; - try { - // FIXME: not so elegant... need to refactor that method to return a value - Files.isFileNameValid(file.name, FileList.getCurrentDirectory()); - } - catch (errorMessage) { - data.textStatus = 'invalidcharacters'; - 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} - ); - } + init: function() { + if ( $('#file_upload_start').exists() ) { + + var file_upload_param = { + dropZone: $('#content'), // restrict dropZone to content div + autoUpload: false, + sequentialUploads: true, + //singleFileUploads is on by default, so the data.files array will always have length 1 + /** + * on first add of every selection + * - check all files of originalFiles array with files in dir + * - on conflict show dialog + * - skip all -> remember as single skip action for all conflicting files + * - replace all -> remember as single replace action for all conflicting files + * - choose -> show choose dialog + * - mark files to keep + * - when only existing -> remember as single skip action + * - when only new -> remember as single replace action + * - when both -> remember as single autorename action + * - start uploading selection + * @param {object} e + * @param {object} data + * @returns {boolean} + */ + add: function(e, data) { + OC.Upload.log('add', e, data); + var that = $(this); + + // we need to collect all data upload objects before starting the upload so we can check their existence + // and set individual conflict actions. unfortunately there is only one variable that we can use to identify + // the selection a data upload is part of, so we have to collect them in data.originalFiles + // turning singleFileUploads off is not an option because we want to gracefully handle server errors like + // already exists + + // create a container where we can store the data objects + if ( ! data.originalFiles.selection ) { + // initialize selection and remember number of files to upload + data.originalFiles.selection = { + uploads: [], + filesToUpload: data.originalFiles.length, + totalBytes: 0 + }; + } + var selection = data.originalFiles.selection; - // add size - selection.totalBytes += file.size; + // add uploads + if ( selection.uploads.length < selection.filesToUpload ) { + // remember upload + selection.uploads.push(data); + } - // check PHP upload limit - if (selection.totalBytes > $('#upload_limit').val()) { - data.textStatus = 'sizeexceedlimit'; - data.errorThrown = t('files', 'Total file size {size1} exceeds upload limit {size2}', { - 'size1': humanFileSize(selection.totalBytes), - 'size2': humanFileSize($('#upload_limit').val()) - }); - } + //examine file + var file = data.files[0]; + try { + // FIXME: not so elegant... need to refactor that method to return a value + Files.isFileNameValid(file.name, FileList.getCurrentDirectory()); + } + catch (errorMessage) { + data.textStatus = 'invalidcharacters'; + data.errorThrown = errorMessage; + } - // check free space - if (selection.totalBytes > $('#free_space').val()) { - data.textStatus = 'notenoughspace'; - data.errorThrown = t('files', 'Not enough free space, you are uploading {size1} but only {size2} is left', { - 'size1': humanFileSize(selection.totalBytes), - 'size2': humanFileSize($('#free_space').val()) - }); - } + 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} + ); + } - // end upload for whole selection on error - if (data.errorThrown) { - // trigger fileupload fail - var fu = that.data('blueimp-fileupload') || that.data('fileupload'); - fu._trigger('fail', e, data); - return false; //don't upload anything - } + // add size + selection.totalBytes += file.size; - // check existing files when all is collected - if ( selection.uploads.length >= selection.filesToUpload ) { + // check PHP upload limit + if (selection.totalBytes > $('#upload_limit').val()) { + data.textStatus = 'sizeexceedlimit'; + data.errorThrown = t('files', 'Total file size {size1} exceeds upload limit {size2}', { + 'size1': humanFileSize(selection.totalBytes), + 'size2': humanFileSize($('#upload_limit').val()) + }); + } - //remove our selection hack: - delete data.originalFiles.selection; + // check free space + if (selection.totalBytes > $('#free_space').val()) { + data.textStatus = 'notenoughspace'; + data.errorThrown = t('files', 'Not enough free space, you are uploading {size1} but only {size2} is left', { + 'size1': humanFileSize(selection.totalBytes), + 'size2': humanFileSize($('#free_space').val()) + }); + } - var callbacks = { + // end upload for whole selection on error + if (data.errorThrown) { + // trigger fileupload fail + var fu = that.data('blueimp-fileupload') || that.data('fileupload'); + fu._trigger('fail', e, data); + return false; //don't upload anything + } - onNoConflicts: function (selection) { - $.each(selection.uploads, function(i, upload) { - upload.submit(); - }); - }, - onSkipConflicts: function (selection) { - //TODO mark conflicting files as toskip - }, - onReplaceConflicts: function (selection) { - //TODO mark conflicting files as toreplace - }, - onChooseConflicts: function (selection) { - //TODO mark conflicting files as chosen - }, - onCancel: function (selection) { - $.each(selection.uploads, function(i, upload) { - upload.abort(); - }); - } - }; + // check existing files when all is collected + if ( selection.uploads.length >= selection.filesToUpload ) { + + //remove our selection hack: + delete data.originalFiles.selection; + + var callbacks = { + + onNoConflicts: function (selection) { + $.each(selection.uploads, function(i, upload) { + upload.submit(); + }); + }, + onSkipConflicts: function (selection) { + //TODO mark conflicting files as toskip + }, + onReplaceConflicts: function (selection) { + //TODO mark conflicting files as toreplace + }, + onChooseConflicts: function (selection) { + //TODO mark conflicting files as chosen + }, + onCancel: function (selection) { + $.each(selection.uploads, function(i, upload) { + upload.abort(); + }); + } + }; - OC.Upload.checkExistingFiles(selection, callbacks); + OC.Upload.checkExistingFiles(selection, callbacks); - } + } - return true; // continue adding files - }, - /** - * called after the first add, does NOT have the data param - * @param {object} e - */ - start: function(e) { - OC.Upload.log('start', e, null); - }, - submit: function(e, data) { - OC.Upload.rememberUpload(data); - if ( ! data.formData ) { - // noone set update parameters, we set the minimum - data.formData = { - requesttoken: oc_requesttoken, - dir: $('#dir').val() - }; - } - }, - fail: function(e, data) { - OC.Upload.log('fail', e, data); - if (typeof data.textStatus !== 'undefined' && data.textStatus !== 'success' ) { - if (data.textStatus === 'abort') { - OC.Notification.show(t('files', 'Upload cancelled.')); - } else { - // HTTP connection problem - OC.Notification.show(data.errorThrown); - if (data.result) { - var result = JSON.parse(data.result); - if (result && result[0] && result[0].data && result[0].data.code === 'targetnotfound') { - // abort upload of next files if any - OC.Upload.cancelUploads(); + return true; // continue adding files + }, + /** + * called after the first add, does NOT have the data param + * @param {object} e + */ + start: function(e) { + OC.Upload.log('start', e, null); + }, + submit: function(e, data) { + OC.Upload.rememberUpload(data); + if ( ! data.formData ) { + // noone set update parameters, we set the minimum + data.formData = { + requesttoken: oc_requesttoken, + dir: $('#dir').val() + }; + } + }, + fail: function(e, data) { + OC.Upload.log('fail', e, data); + if (typeof data.textStatus !== 'undefined' && data.textStatus !== 'success' ) { + if (data.textStatus === 'abort') { + OC.Notification.show(t('files', 'Upload cancelled.')); + } else { + // HTTP connection problem + OC.Notification.show(data.errorThrown); + if (data.result) { + var result = JSON.parse(data.result); + if (result && result[0] && result[0].data && result[0].data.code === 'targetnotfound') { + // abort upload of next files if any + OC.Upload.cancelUploads(); + } } } + //hide notification after 10 sec + setTimeout(function() { + OC.Notification.hide(); + }, 10000); } - //hide notification after 10 sec - setTimeout(function() { - OC.Notification.hide(); - }, 10000); - } - OC.Upload.deleteUpload(data); - }, - /** - * called for every successful upload - * @param {object} e - * @param {object} data - */ - done:function(e, data) { - OC.Upload.log('done', e, data); - // handle different responses (json or body from iframe for ie) - var response; - if (typeof data.result === 'string') { - response = data.result; - } else { - //fetch response from iframe - response = data.result[0].body.innerText; - } - var result=$.parseJSON(response); - - delete data.jqXHR; - - if (result.status === 'error' && result.data && result.data.message){ - data.textStatus = 'servererror'; - data.errorThrown = result.data.message; - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - } else if (typeof result[0] === 'undefined') { - data.textStatus = 'servererror'; - data.errorThrown = t('files', 'Could not get result from server.'); - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - } else if (result[0].status === 'existserror') { - //show "file already exists" dialog - var original = result[0]; - var replacement = data.files[0]; - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - OC.dialogs.fileexists(data, original, replacement, OC.Upload, fu); - } else if (result[0].status !== 'success') { - //delete data.jqXHR; - data.textStatus = 'servererror'; - data.errorThrown = result[0].data.message; // error message has been translated on server - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); + OC.Upload.deleteUpload(data); + }, + /** + * called for every successful upload + * @param {object} e + * @param {object} data + */ + done:function(e, data) { + OC.Upload.log('done', e, data); + // handle different responses (json or body from iframe for ie) + var response; + if (typeof data.result === 'string') { + response = data.result; + } else { + //fetch response from iframe + response = data.result[0].body.innerText; + } + var result=$.parseJSON(response); + + delete data.jqXHR; + + if (result.status === 'error' && result.data && result.data.message){ + data.textStatus = 'servererror'; + data.errorThrown = result.data.message; + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + } else if (typeof result[0] === 'undefined') { + data.textStatus = 'servererror'; + data.errorThrown = t('files', 'Could not get result from server.'); + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + } else if (result[0].status === 'existserror') { + //show "file already exists" dialog + var original = result[0]; + var replacement = data.files[0]; + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + OC.dialogs.fileexists(data, original, replacement, OC.Upload, fu); + } else if (result[0].status !== 'success') { + //delete data.jqXHR; + data.textStatus = 'servererror'; + data.errorThrown = result[0].data.message; // error message has been translated on server + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + } + }, + /** + * called after last upload + * @param {object} e + * @param {object} data + */ + stop: function(e, data) { + OC.Upload.log('stop', e, data); } - }, - /** - * called after last upload - * @param {object} e - * @param {object} data - */ - stop: function(e, data) { - OC.Upload.log('stop', e, data); - } - }; + }; + + // initialize jquery fileupload (blueimp) + var fileupload = $('#file_upload_start').fileupload(file_upload_param); + window.file_upload_param = fileupload; + + if (supportAjaxUploadWithProgress()) { + + // add progress handlers + fileupload.on('fileuploadadd', function(e, data) { + OC.Upload.log('progress handle fileuploadadd', e, data); + //show cancel button + //if (data.dataType !== 'iframe') { //FIXME when is iframe used? only for ie? + // $('#uploadprogresswrapper input.stop').show(); + //} + }); + // add progress handlers + fileupload.on('fileuploadstart', function(e, data) { + OC.Upload.log('progress handle fileuploadstart', e, data); + $('#uploadprogresswrapper input.stop').show(); + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); + }); + fileupload.on('fileuploadprogress', function(e, data) { + OC.Upload.log('progress handle fileuploadprogress', e, data); + //TODO progressbar in row + }); + fileupload.on('fileuploadprogressall', function(e, data) { + OC.Upload.log('progress handle fileuploadprogressall', e, data); + var progress = (data.loaded / data.total) * 100; + $('#uploadprogressbar').progressbar('value', progress); + }); + fileupload.on('fileuploadstop', function(e, data) { + OC.Upload.log('progress handle fileuploadstop', e, data); - // initialize jquery fileupload (blueimp) - var fileupload = $('#file_upload_start').fileupload(file_upload_param); - window.file_upload_param = fileupload; - - if (supportAjaxUploadWithProgress()) { - - // add progress handlers - fileupload.on('fileuploadadd', function(e, data) { - OC.Upload.log('progress handle fileuploadadd', e, data); - //show cancel button - //if (data.dataType !== 'iframe') { //FIXME when is iframe used? only for ie? - // $('#uploadprogresswrapper input.stop').show(); - //} - }); - // add progress handlers - fileupload.on('fileuploadstart', function(e, data) { - OC.Upload.log('progress handle fileuploadstart', e, data); - $('#uploadprogresswrapper input.stop').show(); - $('#uploadprogressbar').progressbar({value:0}); - $('#uploadprogressbar').fadeIn(); - }); - fileupload.on('fileuploadprogress', function(e, data) { - OC.Upload.log('progress handle fileuploadprogress', e, data); - //TODO progressbar in row - }); - fileupload.on('fileuploadprogressall', function(e, data) { - OC.Upload.log('progress handle fileuploadprogressall', e, data); - var progress = (data.loaded / data.total) * 100; - $('#uploadprogressbar').progressbar('value', progress); - }); - fileupload.on('fileuploadstop', function(e, data) { - OC.Upload.log('progress handle fileuploadstop', e, data); - - $('#uploadprogresswrapper input.stop').fadeOut(); - $('#uploadprogressbar').fadeOut(); - Files.updateStorageStatistics(); - }); - fileupload.on('fileuploadfail', function(e, data) { - OC.Upload.log('progress handle fileuploadfail', e, data); - //if user pressed cancel hide upload progress bar and cancel button - if (data.errorThrown === 'abort') { $('#uploadprogresswrapper input.stop').fadeOut(); $('#uploadprogressbar').fadeOut(); - } - }); - - } else { - console.log('skipping file progress because your browser is broken'); - } - } + Files.updateStorageStatistics(); + }); + fileupload.on('fileuploadfail', function(e, data) { + OC.Upload.log('progress handle fileuploadfail', e, data); + //if user pressed cancel hide upload progress bar and cancel button + if (data.errorThrown === 'abort') { + $('#uploadprogresswrapper input.stop').fadeOut(); + $('#uploadprogressbar').fadeOut(); + } + }); - $.assocArraySize = function(obj) { - // http://stackoverflow.com/a/6700/11236 - var size = 0, key; - for (key in obj) { - if (obj.hasOwnProperty(key)) { - size++; + } else { + console.log('skipping file progress because your browser is broken'); } } - return size; - }; - // warn user not to leave the page while upload is in progress - $(window).on('beforeunload', function(e) { - if (OC.Upload.isProcessing()) { - return t('files', 'File upload is in progress. Leaving the page now will cancel the upload.'); - } - }); + $.assocArraySize = function(obj) { + // http://stackoverflow.com/a/6700/11236 + var size = 0, key; + for (key in obj) { + if (obj.hasOwnProperty(key)) { + size++; + } + } + return size; + }; - //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) - if (navigator.userAgent.search(/konqueror/i) === -1) { - $('#file_upload_start').attr('multiple', 'multiple'); - } + // warn user not to leave the page while upload is in progress + $(window).on('beforeunload', function(e) { + if (OC.Upload.isProcessing()) { + return t('files', 'File upload is in progress. Leaving the page now will cancel the upload.'); + } + }); - //if the breadcrumb is to long, start by replacing foldernames with '...' except for the current folder - var crumb=$('div.crumb').first(); - while($('div.controls').height() > 40 && crumb.next('div.crumb').length > 0) { - crumb.children('a').text('...'); - crumb = crumb.next('div.crumb'); - } - //if that isn't enough, start removing items from the breacrumb except for the current folder and it's parent - var crumb = $('div.crumb').first(); - var next = crumb.next('div.crumb'); - while($('div.controls').height()>40 && next.next('div.crumb').length > 0) { - crumb.remove(); - crumb = next; - next = crumb.next('div.crumb'); - } - //still not enough, start shorting down the current folder name - var crumb=$('div.crumb>a').last(); - while($('div.controls').height() > 40 && crumb.text().length > 6) { - var text=crumb.text(); - text = text.substr(0,text.length-6)+'...'; - crumb.text(text); - } + //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) + if (navigator.userAgent.search(/konqueror/i) === -1) { + $('#file_upload_start').attr('multiple', 'multiple'); + } - $(document).click(function(ev) { - // do not close when clicking in the dropdown - if ($(ev.target).closest('#new').length){ - return; + //if the breadcrumb is to long, start by replacing foldernames with '...' except for the current folder + var crumb=$('div.crumb').first(); + while($('div.controls').height() > 40 && crumb.next('div.crumb').length > 0) { + crumb.children('a').text('...'); + crumb = crumb.next('div.crumb'); } - $('#new>ul').hide(); - $('#new').removeClass('active'); - if ($('#new .error').length > 0) { - $('#new .error').tipsy('hide'); + //if that isn't enough, start removing items from the breacrumb except for the current folder and it's parent + var crumb = $('div.crumb').first(); + var next = crumb.next('div.crumb'); + while($('div.controls').height()>40 && next.next('div.crumb').length > 0) { + crumb.remove(); + crumb = next; + next = crumb.next('div.crumb'); } - $('#new li').each(function(i,element) { - if ($(element).children('p').length === 0) { - $(element).children('form').remove(); - $(element).append('

'+$(element).data('text')+'

'); - } - }); - }); - $('#new').click(function(event) { - event.stopPropagation(); - }); - $('#new>a').click(function() { - $('#new>ul').toggle(); - $('#new').toggleClass('active'); - }); - $('#new li').click(function() { - if ($(this).children('p').length === 0) { - return; + //still not enough, start shorting down the current folder name + var crumb=$('div.crumb>a').last(); + while($('div.controls').height() > 40 && crumb.text().length > 6) { + var text=crumb.text(); + text = text.substr(0,text.length-6)+'...'; + crumb.text(text); } - $('#new .error').tipsy('hide'); - - $('#new li').each(function(i,element) { - if ($(element).children('p').length === 0) { - $(element).children('form').remove(); - $(element).append('

'+$(element).data('text')+'

'); + $(document).click(function(ev) { + // do not close when clicking in the dropdown + if ($(ev.target).closest('#new').length){ + return; } + $('#new>ul').hide(); + $('#new').removeClass('active'); + if ($('#new .error').length > 0) { + $('#new .error').tipsy('hide'); + } + $('#new li').each(function(i,element) { + if ($(element).children('p').length === 0) { + $(element).children('form').remove(); + $(element).append('

'+$(element).data('text')+'

'); + } + }); }); - - var type=$(this).data('type'); - var text=$(this).children('p').text(); - $(this).data('text',text); - $(this).children('p').remove(); - - // add input field - var form = $('
'); - var input = $(''); - var newName = $(this).attr('data-newname') || ''; - if (newName) { - input.val(newName); - } - form.append(input); - $(this).append(form); - var lastPos; - var checkInput = function () { - var filename = input.val(); - if (type === 'web' && filename.length === 0) { - throw t('files', 'URL cannot be empty'); - } else if (type !== 'web' && !Files.isFileNameValid(filename)) { - // Files.isFileNameValid(filename) throws an exception itself - } else if (FileList.getCurrentDirectory() === '/' && filename.toLowerCase() === 'shared') { - throw t('files', 'In the home folder \'Shared\' is a reserved filename'); - } else if (FileList.inList(filename)) { - throw t('files', '{new_name} already exists', {new_name: filename}); - } else { - return true; + $('#new').click(function(event) { + event.stopPropagation(); + }); + $('#new>a').click(function() { + $('#new>ul').toggle(); + $('#new').toggleClass('active'); + }); + $('#new li').click(function() { + if ($(this).children('p').length === 0) { + return; } - }; - // verify filename on typing - input.keyup(function(event) { - try { - checkInput(); - input.tipsy('hide'); - input.removeClass('error'); - } catch (error) { - input.attr('title', error); - input.tipsy({gravity: 'w', trigger: 'manual'}); - input.tipsy('show'); - input.addClass('error'); - } - }); + $('#new .error').tipsy('hide'); - input.focus(); - // pre select name up to the extension - lastPos = newName.lastIndexOf('.'); - if (lastPos === -1) { - lastPos = newName.length; - } - input.selectRange(0, lastPos); - form.submit(function(event) { - event.stopPropagation(); - event.preventDefault(); - try { - checkInput(); - var newname = input.val(); - if (FileList.lastAction) { - FileList.lastAction(); + $('#new li').each(function(i,element) { + if ($(element).children('p').length === 0) { + $(element).children('form').remove(); + $(element).append('

'+$(element).data('text')+'

'); } - var name = getUniqueName(newname); - if (newname !== name) { - FileList.checkName(name, newname, true); - var hidden = true; + }); + + var type=$(this).data('type'); + var text=$(this).children('p').text(); + $(this).data('text',text); + $(this).children('p').remove(); + + // add input field + var form = $('
'); + var input = $(''); + var newName = $(this).attr('data-newname') || ''; + if (newName) { + input.val(newName); + } + form.append(input); + $(this).append(form); + var lastPos; + var checkInput = function () { + var filename = input.val(); + if (type === 'web' && filename.length === 0) { + throw t('files', 'URL cannot be empty'); + } else if (type !== 'web' && !Files.isFileNameValid(filename)) { + // Files.isFileNameValid(filename) throws an exception itself + } else if (FileList.getCurrentDirectory() === '/' && filename.toLowerCase() === 'shared') { + throw t('files', 'In the home folder \'Shared\' is a reserved filename'); + } else if (FileList.inList(filename)) { + throw t('files', '{new_name} already exists', {new_name: filename}); } else { - var hidden = false; + return true; } - switch(type) { - case 'file': - $.post( - OC.filePath('files', 'ajax', 'newfile.php'), - {dir:$('#dir').val(), filename:name}, - function(result) { - if (result.status === 'success') { - var date = new Date(); - // TODO: ideally addFile should be able to receive - // all attributes and set them automatically, - // and also auto-load the preview - var tr = FileList.addFile(name, 0, date, false, hidden); - tr.attr('data-size', result.data.size); - tr.attr('data-mime', result.data.mime); - tr.attr('data-id', result.data.id); - tr.attr('data-etag', result.data.etag); - tr.find('.filesize').text(humanFileSize(result.data.size)); - var path = getPathForPreview(name); - Files.lazyLoadPreview(path, result.data.mime, function(previewpath) { - tr.find('td.filename').attr('style','background-image:url('+previewpath+')'); - }, null, null, result.data.etag); - FileActions.display(tr.find('td.filename'), true); - } else { - OC.dialogs.alert(result.data.message, t('core', 'Could not create file')); + }; + + // verify filename on typing + input.keyup(function(event) { + try { + checkInput(); + input.tipsy('hide'); + input.removeClass('error'); + } catch (error) { + input.attr('title', error); + input.tipsy({gravity: 'w', trigger: 'manual'}); + input.tipsy('show'); + input.addClass('error'); + } + }); + + input.focus(); + // pre select name up to the extension + lastPos = newName.lastIndexOf('.'); + if (lastPos === -1) { + lastPos = newName.length; + } + input.selectRange(0, lastPos); + form.submit(function(event) { + event.stopPropagation(); + event.preventDefault(); + try { + checkInput(); + var newname = input.val(); + if (FileList.lastAction) { + FileList.lastAction(); + } + var name = getUniqueName(newname); + if (newname !== name) { + FileList.checkName(name, newname, true); + var hidden = true; + } else { + var hidden = false; + } + switch(type) { + case 'file': + $.post( + OC.filePath('files', 'ajax', 'newfile.php'), + {dir:$('#dir').val(), filename:name}, + function(result) { + if (result.status === 'success') { + var date = new Date(); + // TODO: ideally addFile should be able to receive + // all attributes and set them automatically, + // and also auto-load the preview + var tr = FileList.addFile(name, 0, date, false, hidden); + tr.attr('data-size', result.data.size); + tr.attr('data-mime', result.data.mime); + tr.attr('data-id', result.data.id); + tr.attr('data-etag', result.data.etag); + tr.find('.filesize').text(humanFileSize(result.data.size)); + var path = getPathForPreview(name); + Files.lazyLoadPreview(path, result.data.mime, function(previewpath) { + tr.find('td.filename').attr('style','background-image:url('+previewpath+')'); + }, null, null, result.data.etag); + FileActions.display(tr.find('td.filename'), true); + } else { + OC.dialogs.alert(result.data.message, t('core', 'Could not create file')); + } } - } - ); - break; - case 'folder': - $.post( - OC.filePath('files','ajax','newfolder.php'), - {dir:$('#dir').val(), foldername:name}, - function(result) { - if (result.status === 'success') { - var date=new Date(); - FileList.addDir(name, 0, date, hidden); - var tr = FileList.findFileEl(name); - tr.attr('data-id', result.data.id); - } else { - OC.dialogs.alert(result.data.message, t('core', 'Could not create folder')); + ); + break; + case 'folder': + $.post( + OC.filePath('files','ajax','newfolder.php'), + {dir:$('#dir').val(), foldername:name}, + function(result) { + if (result.status === 'success') { + var date=new Date(); + FileList.addDir(name, 0, date, hidden); + var tr = FileList.findFileEl(name); + tr.attr('data-id', result.data.id); + } else { + OC.dialogs.alert(result.data.message, t('core', 'Could not create folder')); + } } + ); + break; + case 'web': + if (name.substr(0,8) !== 'https://' && name.substr(0,7) !== 'http://') { + name = 'http://' + name; } - ); - break; - case 'web': - if (name.substr(0,8) !== 'https://' && name.substr(0,7) !== 'http://') { - name = 'http://' + name; - } - var localName=name; - if (localName.substr(localName.length-1,1)==='/') {//strip / - localName=localName.substr(0,localName.length-1); - } - if (localName.indexOf('/')) {//use last part of url - localName=localName.split('/').pop(); - } else { //or the domain - localName=(localName.match(/:\/\/(.[^\/]+)/)[1]).replace('www.',''); - } - localName = getUniqueName(localName); - //IE < 10 does not fire the necessary events for the progress bar. - if ($('html.lte9').length === 0) { - $('#uploadprogressbar').progressbar({value:0}); - $('#uploadprogressbar').fadeIn(); - } - - var eventSource=new OC.EventSource(OC.filePath('files','ajax','newfile.php'),{dir:$('#dir').val(),source:name,filename:localName}); - eventSource.listen('progress',function(progress) { + var localName=name; + if (localName.substr(localName.length-1,1)==='/') {//strip / + localName=localName.substr(0,localName.length-1); + } + if (localName.indexOf('/')) {//use last part of url + localName=localName.split('/').pop(); + } else { //or the domain + localName=(localName.match(/:\/\/(.[^\/]+)/)[1]).replace('www.',''); + } + localName = getUniqueName(localName); //IE < 10 does not fire the necessary events for the progress bar. if ($('html.lte9').length === 0) { - $('#uploadprogressbar').progressbar('value',progress); + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); } - }); - eventSource.listen('success',function(data) { - var mime = data.mime; - var size = data.size; - var id = data.id; - $('#uploadprogressbar').fadeOut(); - var date = new Date(); - FileList.addFile(localName, size, date, false, hidden); - var tr = FileList.findFileEl(localName); - tr.data('mime', mime).data('id', id); - tr.attr('data-id', id); - var path = $('#dir').val()+'/'+localName; - Files.lazyLoadPreview(path, mime, function(previewpath) { - tr.find('td.filename').attr('style', 'background-image:url('+previewpath+')'); - }, null, null, data.etag); - FileActions.display(tr.find('td.filename'), true); - }); - eventSource.listen('error',function(error) { - $('#uploadprogressbar').fadeOut(); - var message = (error && error.message) || t('core', 'Error fetching URL'); - OC.Notification.show(message); - //hide notification after 10 sec - setTimeout(function() { - OC.Notification.hide(); - }, 10000); - }); - break; + + var eventSource=new OC.EventSource(OC.filePath('files','ajax','newfile.php'),{dir:$('#dir').val(),source:name,filename:localName}); + eventSource.listen('progress',function(progress) { + //IE < 10 does not fire the necessary events for the progress bar. + if ($('html.lte9').length === 0) { + $('#uploadprogressbar').progressbar('value',progress); + } + }); + eventSource.listen('success',function(data) { + var mime = data.mime; + var size = data.size; + var id = data.id; + $('#uploadprogressbar').fadeOut(); + var date = new Date(); + FileList.addFile(localName, size, date, false, hidden); + var tr = FileList.findFileEl(localName); + tr.data('mime', mime).data('id', id); + tr.attr('data-id', id); + var path = $('#dir').val()+'/'+localName; + Files.lazyLoadPreview(path, mime, function(previewpath) { + tr.find('td.filename').attr('style', 'background-image:url('+previewpath+')'); + }, null, null, data.etag); + FileActions.display(tr.find('td.filename'), true); + }); + eventSource.listen('error',function(error) { + $('#uploadprogressbar').fadeOut(); + var message = (error && error.message) || t('core', 'Error fetching URL'); + OC.Notification.show(message); + //hide notification after 10 sec + setTimeout(function() { + OC.Notification.hide(); + }, 10000); + }); + break; + } + var li=form.parent(); + form.remove(); + /* workaround for IE 9&10 click event trap, 2 lines: */ + $('input').first().focus(); + $('#content').focus(); + li.append('

'+li.data('text')+'

'); + $('#new>a').click(); + } catch (error) { + input.attr('title', error); + input.tipsy({gravity: 'w', trigger: 'manual'}); + input.tipsy('show'); + input.addClass('error'); } - var li=form.parent(); - form.remove(); - /* workaround for IE 9&10 click event trap, 2 lines: */ - $('input').first().focus(); - $('#content').focus(); - li.append('

'+li.data('text')+'

'); - $('#new>a').click(); - } catch (error) { - input.attr('title', error); - input.tipsy({gravity: 'w', trigger: 'manual'}); - input.tipsy('show'); - input.addClass('error'); - } + }); }); - }); - window.file_upload_param = file_upload_param; + window.file_upload_param = file_upload_param; + return file_upload_param; + } +}; + +$(document).ready(function() { + OC.Upload.init(); }); + diff --git a/apps/files/tests/js/fileUploadSpec.js b/apps/files/tests/js/fileUploadSpec.js new file mode 100644 index 00000000000..2b4341ef1c3 --- /dev/null +++ b/apps/files/tests/js/fileUploadSpec.js @@ -0,0 +1,127 @@ +/** +* ownCloud +* +* @author Vincent Petry +* @copyright 2014 Vincent Petry +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU AFFERO GENERAL PUBLIC LICENSE for more details. +* +* You should have received a copy of the GNU Affero General Public +* License along with this library. If not, see . +* +*/ + +/* global OC */ +describe('OC.Upload tests', function() { + var $dummyUploader; + var testFile; + + beforeEach(function() { + testFile = { + name: 'test.txt', + size: 5000, // 5 KB + type: 'text/plain', + lastModifiedDate: new Date() + }; + // need a dummy button because file-upload checks on it + $('#testArea').append( + '' + + '' + // 10 MB + '' // 50 MB + ); + $dummyUploader = $('#file_upload_start'); + }); + afterEach(function() { + delete window.file_upload_param; + $dummyUploader = undefined; + }); + describe('Adding files for upload', function() { + var params; + var failStub; + + beforeEach(function() { + params = OC.Upload.init(); + failStub = sinon.stub(); + $dummyUploader.on('fileuploadfail', failStub); + }); + afterEach(function() { + params = undefined; + failStub = undefined; + }); + + /** + * Add file for upload + * @param file file data + */ + function addFile(file) { + return params.add.call( + $dummyUploader[0], + {}, + { + originalFiles: {}, + files: [file] + }); + } + + it('adds file when size is below limits', function() { + var result = addFile(testFile); + expect(result).toEqual(true); + }); + it('adds file when free space is unknown', function() { + var result; + $('#free_space').val(-2); + + result = addFile(testFile); + + expect(result).toEqual(true); + expect(failStub.notCalled).toEqual(true); + }); + it('does not add file if it exceeds upload limit', function() { + var result; + $('#upload_limit').val(1000); + + result = addFile(testFile); + + expect(result).toEqual(false); + expect(failStub.calledOnce).toEqual(true); + expect(failStub.getCall(0).args[1].textStatus).toEqual('sizeexceedlimit'); + expect(failStub.getCall(0).args[1].errorThrown).toEqual( + 'Total file size 5 kB exceeds upload limit 1000 B' + ); + }); + it('does not add file if it exceeds free space', function() { + var result; + $('#free_space').val(1000); + + result = addFile(testFile); + + expect(result).toEqual(false); + expect(failStub.calledOnce).toEqual(true); + expect(failStub.getCall(0).args[1].textStatus).toEqual('notenoughspace'); + expect(failStub.getCall(0).args[1].errorThrown).toEqual( + 'Not enough free space, you are uploading 5 kB but only 1000 B is left' + ); + }); + it('does not add file if it has invalid characters', function() { + var result; + testFile.name = 'stars*stars.txt'; + + result = addFile(testFile); + + expect(result).toEqual(false); + expect(failStub.calledOnce).toEqual(true); + expect(failStub.getCall(0).args[1].textStatus).toEqual('invalidcharacters'); + expect(failStub.getCall(0).args[1].errorThrown.substr(0, 12)).toEqual( + 'Invalid name' + ); + }); + }); +}); -- cgit v1.2.3 From 0dcac65aa1eb14adc4d3693b6a2c99cbf6ea2425 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 6 Mar 2014 13:50:53 +0100 Subject: Fixed upload issue when free space is not known --- apps/files/js/file-upload.js | 4 +++- lib/private/helper.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'apps/files/js') diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index b9c4dc941f7..b7b8f6fdeb6 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -206,6 +206,7 @@ OC.Upload = { add: function(e, data) { OC.Upload.log('add', e, data); var that = $(this); + var freeSpace; // we need to collect all data upload objects before starting the upload so we can check their existence // and set individual conflict actions. unfortunately there is only one variable that we can use to identify @@ -261,7 +262,8 @@ OC.Upload = { } // check free space - if (selection.totalBytes > $('#free_space').val()) { + freeSpace = $('#free_space').val(); + if (freeSpace >= 0 && selection.totalBytes > freeSpace) { data.textStatus = 'notenoughspace'; data.errorThrown = t('files', 'Not enough free space, you are uploading {size1} but only {size2} is left', { 'size1': humanFileSize(selection.totalBytes), diff --git a/lib/private/helper.php b/lib/private/helper.php index d8c4650f666..b9956d5ec1c 100644 --- a/lib/private/helper.php +++ b/lib/private/helper.php @@ -839,7 +839,7 @@ class OC_Helper { * @return int number of bytes representing */ public static function maxUploadFilesize($dir, $freeSpace = null) { - if (is_null($freeSpace)){ + if (is_null($freeSpace) || $freeSpace < 0){ $freeSpace = self::freeSpace($dir); } return min($freeSpace, self::uploadLimit()); -- cgit v1.2.3 From e7d571511408f44c6caffe31e13289d245590954 Mon Sep 17 00:00:00 2001 From: IchEben Date: Fri, 7 Mar 2014 17:45:24 +0100 Subject: only initialise upload dropZone if public upload is allowed --- apps/files/js/file-upload.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apps/files/js') diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index b7b8f6fdeb6..ea4061c9b0b 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -180,7 +180,7 @@ OC.Upload = { }, init: function() { - if ( $('#file_upload_start').exists() ) { + if ( $('#file_upload_start').exists() && $('#file_upload_start').is(':visible')) { var file_upload_param = { dropZone: $('#content'), // restrict dropZone to content div -- cgit v1.2.3 From ea8705bac8ae10b0c3c11258e83d8fb80ee616e9 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Mon, 17 Mar 2014 20:15:10 +0100 Subject: additional class is added to the file actions called e.g. 'action-share', 'action-rename' in order to allow proper translations of the action's display name an additional parameter has been added to the register function --- apps/files/js/fileactions.js | 37 ++++++++++++++++++++++++++----------- apps/files_versions/js/versions.js | 3 ++- 2 files changed, 28 insertions(+), 12 deletions(-) (limited to 'apps/files/js') diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 9a69d7b3688..a7d1fa9d8a2 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -15,21 +15,33 @@ var FileActions = { defaults: {}, icons: {}, currentFile: null, - register: function (mime, name, permissions, icon, action) { + register: function (mime, name, permissions, icon, action, displayName) { if (!FileActions.actions[mime]) { FileActions.actions[mime] = {}; } if (!FileActions.actions[mime][name]) { FileActions.actions[mime][name] = {}; } + if (!displayName) { + displayName = t('files', name); + } FileActions.actions[mime][name]['action'] = action; FileActions.actions[mime][name]['permissions'] = permissions; + FileActions.actions[mime][name]['displayName'] = displayName; FileActions.icons[name] = icon; }, setDefault: function (mime, name) { FileActions.defaults[mime] = name; }, get: function (mime, type, permissions) { + var actions = this.getActions(mime, type, permissions); + var filteredActions = {}; + $.each(actions, function (name, action) { + filteredActions[name] = action.action; + }); + return filteredActions; + }, + getActions: function (mime, type, permissions) { var actions = {}; if (FileActions.actions.all) { actions = $.extend(actions, FileActions.actions.all); @@ -51,7 +63,7 @@ var FileActions = { var filteredActions = {}; $.each(actions, function (name, action) { if (action.permissions & permissions) { - filteredActions[name] = action.action; + filteredActions[name] = action; } }); return filteredActions; @@ -82,7 +94,7 @@ var FileActions = { */ display: function (parent, triggerEvent) { FileActions.currentFile = parent; - var actions = FileActions.get(FileActions.getCurrentMimeType(), FileActions.getCurrentType(), FileActions.getCurrentPermissions()); + var actions = FileActions.getActions(FileActions.getCurrentMimeType(), FileActions.getCurrentType(), FileActions.getCurrentPermissions()); var file = FileActions.getCurrentFile(); var nameLinks; if (FileList.findFileEl(file).data('renaming')) { @@ -105,15 +117,16 @@ var FileActions = { event.data.actionFunc(file); }; - var addAction = function (name, action) { + var addAction = function (name, action, displayName) { // NOTE: Temporary fix to prevent rename action in root of Shared directory if (name === 'Rename' && $('#dir').val() === '/Shared') { return true; } if ((name === 'Download' || action !== defaultAction) && name !== 'Delete') { + var img = FileActions.icons[name], - actionText = t('files', name), + actionText = displayName, actionContainer = 'a.name>span.fileactions'; if (name === 'Rename') { @@ -125,7 +138,7 @@ var FileActions = { if (img.call) { img = img(file); } - var html = ''; + var html = ''; if (img) { html += ''; } @@ -133,8 +146,7 @@ var FileActions = { var element = $(html); element.data('action', name); - //alert(element); - element.on('click', {a: null, elem: parent, actionFunc: actions[name]}, actionHandler); + element.on('click', {a: null, elem: parent, actionFunc: actions[name].action}, actionHandler); parent.find(actionContainer).append(element); } @@ -142,12 +154,15 @@ var FileActions = { $.each(actions, function (name, action) { if (name !== 'Share') { - addAction(name, action); + displayName = action.displayName; + ah = action.action; + + addAction(name, ah, displayName); } }); if(actions.Share && !($('#dir').val() === '/' && file === 'Shared')){ - // t('files', 'Share') - addAction('Share', actions.Share); + displayName = t('files', 'Share'); + addAction('Share', actions.Share, displayName); } // remove the existing delete action diff --git a/apps/files_versions/js/versions.js b/apps/files_versions/js/versions.js index 4adf14745de..b452bc25b13 100644 --- a/apps/files_versions/js/versions.js +++ b/apps/files_versions/js/versions.js @@ -11,7 +11,7 @@ $(document).ready(function(){ // Add versions button to 'files/index.php' FileActions.register( 'file' - , t('files_versions', 'Versions') + , 'Versions' , OC.PERMISSION_UPDATE , function() { // Specify icon for hitory button @@ -36,6 +36,7 @@ $(document).ready(function(){ createVersionsDropdown(filename, file); } } + , t('files_versions', 'Versions') ); } -- cgit v1.2.3 From 6b9ae27b90ee5649fcab2417ebaf14e87559756e Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 18 Mar 2014 17:14:38 +0100 Subject: drop file cache migration OC5 -> OC6 --- apps/files/ajax/upgrade.php | 44 ------- apps/files/index.php | 135 ++++++++++----------- apps/files/js/upgrade.js | 28 ----- apps/files/templates/upgrade.php | 4 - core/ajax/update.php | 9 -- core/command/upgrade.php | 9 -- lib/private/files/cache/legacy.php | 139 --------------------- lib/private/files/cache/upgrade.php | 235 ------------------------------------ lib/private/updater.php | 43 ------- 9 files changed, 62 insertions(+), 584 deletions(-) delete mode 100644 apps/files/ajax/upgrade.php delete mode 100644 apps/files/js/upgrade.js delete mode 100644 apps/files/templates/upgrade.php delete mode 100644 lib/private/files/cache/legacy.php delete mode 100644 lib/private/files/cache/upgrade.php (limited to 'apps/files/js') diff --git a/apps/files/ajax/upgrade.php b/apps/files/ajax/upgrade.php deleted file mode 100644 index 7237b02c0b0..00000000000 --- a/apps/files/ajax/upgrade.php +++ /dev/null @@ -1,44 +0,0 @@ -hasItems()) { - OC_Hook::connect('\OC\Files\Cache\Upgrade', 'migrate_path', $listener, 'upgradePath'); - - OC_DB::beginTransaction(); - $upgrade = new \OC\Files\Cache\Upgrade($legacy); - $count = $legacy->getCount(); - $eventSource->send('total', $count); - $upgrade->upgradePath('/' . $user . '/files'); - OC_DB::commit(); -} -\OC\Files\Cache\Upgrade::upgradeDone($user); -$eventSource->send('done', true); -$eventSource->close(); - -class UpgradeListener { - /** - * @var OC_EventSource $eventSource - */ - private $eventSource; - - private $count = 0; - private $lastSend = 0; - - public function __construct($eventSource) { - $this->eventSource = $eventSource; - } - - public function upgradePath($path) { - $this->count++; - if ($this->count > ($this->lastSend + 5)) { - $this->lastSend = $this->count; - $this->eventSource->send('count', $this->count); - } - } -} diff --git a/apps/files/index.php b/apps/files/index.php index ad7a2e210ed..c66cd40fb56 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -62,22 +62,17 @@ if ($isIE8 && isset($_GET['dir'])){ $ajaxLoad = false; $files = array(); $user = OC_User::getUser(); -if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we need to upgrade the cache - $needUpgrade = true; -} else { - if ($isIE8){ - // after the redirect above, the URL will have a format - // like "files#?dir=path" which means that no path was given - // (dir is not set). In that specific case, we don't return any - // files because the client will take care of switching the dir - // to the one from the hash, then ajax-load the initial file list - $files = array(); - $ajaxLoad = true; - } - else{ - $files = \OCA\Files\Helper::getFiles($dir); - } - $needUpgrade = false; +if ($isIE8){ + // after the redirect above, the URL will have a format + // like "files#?dir=path" which means that no path was given + // (dir is not set). In that specific case, we don't return any + // files because the client will take care of switching the dir + // to the one from the hash, then ajax-load the initial file list + $files = array(); + $ajaxLoad = true; +} +else{ + $files = \OCA\Files\Helper::getFiles($dir); } $config = \OC::$server->getConfig(); @@ -97,62 +92,56 @@ $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir $permissions = $dirInfo->getPermissions(); -if ($needUpgrade) { - OCP\Util::addscript('files', 'upgrade'); - $tmpl = new OCP\Template('files', 'upgrade', 'user'); - $tmpl->printPage(); -} else { - // information about storage capacities - $storageInfo=OC_Helper::getStorageInfo($dir); - $freeSpace=$storageInfo['free']; - $uploadLimit=OCP\Util::uploadLimit(); - $maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); - $publicUploadEnabled = $config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'); - // if the encryption app is disabled, than everything is fine (INIT_SUCCESSFUL status code) - $encryptionInitStatus = 2; - if (OC_App::isEnabled('files_encryption')) { - $session = new \OCA\Encryption\Session(new \OC\Files\View('/')); - $encryptionInitStatus = $session->getInitialized(); - } - - $trashEnabled = \OCP\App::isEnabled('files_trashbin'); - $trashEmpty = true; - if ($trashEnabled) { - $trashEmpty = \OCA\Files_Trashbin\Trashbin::isEmpty($user); - } +// information about storage capacities +$storageInfo=OC_Helper::getStorageInfo($dir); +$freeSpace=$storageInfo['free']; +$uploadLimit=OCP\Util::uploadLimit(); +$maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); +$publicUploadEnabled = $config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'); +// if the encryption app is disabled, than everything is fine (INIT_SUCCESSFUL status code) +$encryptionInitStatus = 2; +if (OC_App::isEnabled('files_encryption')) { + $session = new \OCA\Encryption\Session(new \OC\Files\View('/')); + $encryptionInitStatus = $session->getInitialized(); +} - $isCreatable = \OC\Files\Filesystem::isCreatable($dir . '/'); - $fileHeader = (!isset($files) or count($files) > 0); - $emptyContent = ($isCreatable and !$fileHeader) or $ajaxLoad; - - OCP\Util::addscript('files', 'fileactions'); - OCP\Util::addscript('files', 'files'); - OCP\Util::addscript('files', 'keyboardshortcuts'); - $tmpl = new OCP\Template('files', 'index', 'user'); - $tmpl->assign('fileList', $list->fetchPage()); - $tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage()); - $tmpl->assign('dir', $dir); - $tmpl->assign('isCreatable', $isCreatable); - $tmpl->assign('permissions', $permissions); - $tmpl->assign('files', $files); - $tmpl->assign('trash', $trashEnabled); - $tmpl->assign('trashEmpty', $trashEmpty); - $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); // minimium of freeSpace and uploadLimit - $tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); - $tmpl->assign('freeSpace', $freeSpace); - $tmpl->assign('uploadLimit', $uploadLimit); // PHP upload limit - $tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); - $tmpl->assign('usedSpacePercent', (int)$storageInfo['relative']); - $tmpl->assign('isPublic', false); - $tmpl->assign('publicUploadEnabled', $publicUploadEnabled); - $tmpl->assign("encryptedFiles", \OCP\Util::encryptedFiles()); - $tmpl->assign("mailNotificationEnabled", $config->getAppValue('core', 'shareapi_allow_mail_notification', 'yes')); - $tmpl->assign("allowShareWithLink", $config->getAppValue('core', 'shareapi_allow_links', 'yes')); - $tmpl->assign("encryptionInitStatus", $encryptionInitStatus); - $tmpl->assign('disableSharing', false); - $tmpl->assign('ajaxLoad', $ajaxLoad); - $tmpl->assign('emptyContent', $emptyContent); - $tmpl->assign('fileHeader', $fileHeader); - - $tmpl->printPage(); +$trashEnabled = \OCP\App::isEnabled('files_trashbin'); +$trashEmpty = true; +if ($trashEnabled) { + $trashEmpty = \OCA\Files_Trashbin\Trashbin::isEmpty($user); } + +$isCreatable = \OC\Files\Filesystem::isCreatable($dir . '/'); +$fileHeader = (!isset($files) or count($files) > 0); +$emptyContent = ($isCreatable and !$fileHeader) or $ajaxLoad; + +OCP\Util::addscript('files', 'fileactions'); +OCP\Util::addscript('files', 'files'); +OCP\Util::addscript('files', 'keyboardshortcuts'); +$tmpl = new OCP\Template('files', 'index', 'user'); +$tmpl->assign('fileList', $list->fetchPage()); +$tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage()); +$tmpl->assign('dir', $dir); +$tmpl->assign('isCreatable', $isCreatable); +$tmpl->assign('permissions', $permissions); +$tmpl->assign('files', $files); +$tmpl->assign('trash', $trashEnabled); +$tmpl->assign('trashEmpty', $trashEmpty); +$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); // minimium of freeSpace and uploadLimit +$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); +$tmpl->assign('freeSpace', $freeSpace); +$tmpl->assign('uploadLimit', $uploadLimit); // PHP upload limit +$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); +$tmpl->assign('usedSpacePercent', (int)$storageInfo['relative']); +$tmpl->assign('isPublic', false); +$tmpl->assign('publicUploadEnabled', $publicUploadEnabled); +$tmpl->assign("encryptedFiles", \OCP\Util::encryptedFiles()); +$tmpl->assign("mailNotificationEnabled", $config->getAppValue('core', 'shareapi_allow_mail_notification', 'yes')); +$tmpl->assign("allowShareWithLink", $config->getAppValue('core', 'shareapi_allow_links', 'yes')); +$tmpl->assign("encryptionInitStatus", $encryptionInitStatus); +$tmpl->assign('disableSharing', false); +$tmpl->assign('ajaxLoad', $ajaxLoad); +$tmpl->assign('emptyContent', $emptyContent); +$tmpl->assign('fileHeader', $fileHeader); + +$tmpl->printPage(); diff --git a/apps/files/js/upgrade.js b/apps/files/js/upgrade.js deleted file mode 100644 index 714adf824a1..00000000000 --- a/apps/files/js/upgrade.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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'); - bar.progressbar({value: 0}); - eventSource = new OC.EventSource(OC.filePath('files', 'ajax', 'upgrade.php')); - eventSource.listen('total', function (count) { - total = count; - console.log(count + ' files needed to be migrated'); - }); - eventSource.listen('count', function (count) { - bar.progressbar({value: (count / total) * 100}); - console.log(count); - }); - eventSource.listen('done', function () { - document.location.reload(); - }); -}); diff --git a/apps/files/templates/upgrade.php b/apps/files/templates/upgrade.php deleted file mode 100644 index e03f086e47d..00000000000 --- a/apps/files/templates/upgrade.php +++ /dev/null @@ -1,4 +0,0 @@ -
- t('Upgrading filesystem cache...'));?> -
-
diff --git a/core/ajax/update.php b/core/ajax/update.php index d6af84e95b1..2a0cbb2036d 100644 --- a/core/ajax/update.php +++ b/core/ajax/update.php @@ -16,15 +16,6 @@ if (OC::checkUpgrade(false)) { $updater->listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource, $l) { $eventSource->send('success', (string)$l->t('Updated database')); }); - $updater->listen('\OC\Updater', 'filecacheStart', function () use ($eventSource, $l) { - $eventSource->send('success', (string)$l->t('Updating filecache, this may take really long...')); - }); - $updater->listen('\OC\Updater', 'filecacheDone', function () use ($eventSource, $l) { - $eventSource->send('success', (string)$l->t('Updated filecache')); - }); - $updater->listen('\OC\Updater', 'filecacheProgress', function ($out) use ($eventSource, $l) { - $eventSource->send('success', (string)$l->t('... %d%% done ...', array('percent' => $out))); - }); $updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource) { $eventSource->send('failure', $message); $eventSource->close(); diff --git a/core/command/upgrade.php b/core/command/upgrade.php index 6e5681b26df..cfccfb5d2f0 100644 --- a/core/command/upgrade.php +++ b/core/command/upgrade.php @@ -59,15 +59,6 @@ class Upgrade extends Command { $updater->listen('\OC\Updater', 'dbUpgrade', function () use($output) { $output->writeln('Updated database'); }); - $updater->listen('\OC\Updater', 'filecacheStart', function () use($output) { - $output->writeln('Updating filecache, this may take really long...'); - }); - $updater->listen('\OC\Updater', 'filecacheDone', function () use($output) { - $output->writeln('Updated filecache'); - }); - $updater->listen('\OC\Updater', 'filecacheProgress', function ($out) use($output) { - $output->writeln('... ' . $out . '% done ...'); - }); $updater->listen('\OC\Updater', 'failure', function ($message) use($output) { $output->writeln($message); diff --git a/lib/private/files/cache/legacy.php b/lib/private/files/cache/legacy.php deleted file mode 100644 index 4d5f58741e9..00000000000 --- a/lib/private/files/cache/legacy.php +++ /dev/null @@ -1,139 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -namespace OC\Files\Cache; - -/** - * Provide read only support for the old filecache - */ -class Legacy { - private $user; - - private $cacheHasItems = null; - - /** - * @param string $user - */ - public function __construct($user) { - $this->user = $user; - } - - /** - * get the numbers of items in the legacy cache - * - * @return int - */ - function getCount() { - $sql = 'SELECT COUNT(`id`) AS `count` FROM `*PREFIX*fscache` WHERE `user` = ?'; - $result = \OC_DB::executeAudited($sql, array($this->user)); - if ($row = $result->fetchRow()) { - return $row['count']; - } else { - return 0; - } - } - - /** - * check if a legacy cache is present and holds items - * - * @return bool - */ - function hasItems() { - if (!is_null($this->cacheHasItems)) { - return $this->cacheHasItems; - } - try { - $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*fscache` WHERE `user` = ?',1); - } catch (\Exception $e) { - $this->cacheHasItems = false; - return false; - } - try { - $result = $query->execute(array($this->user)); - } catch (\Exception $e) { - $this->cacheHasItems = false; - return false; - } - - if ($result === false || property_exists($result, 'error_message_prefix')) { - $this->cacheHasItems = false; - return false; - } - - $this->cacheHasItems = (bool)$result->fetchRow(); - return $this->cacheHasItems; - } - - /** - * get an item from the legacy cache - * - * @param string $path - * @return array - */ - function get($path) { - if (is_numeric($path)) { - $sql = 'SELECT * FROM `*PREFIX*fscache` WHERE `id` = ?'; - } else { - $sql = 'SELECT * FROM `*PREFIX*fscache` WHERE `path` = ?'; - } - $result = \OC_DB::executeAudited($sql, array($path)); - $data = $result->fetchRow(); - $data['etag'] = $this->getEtag($data['path'], $data['user']); - return $data; - } - - /** - * Get the ETag for the given path - * - * @param type $path - * @return string - */ - function getEtag($path, $user = null) { - static $query = null; - - $pathDetails = explode('/', $path, 4); - if((!$user) && !isset($pathDetails[1])) { - //no user!? Too odd, return empty string. - return ''; - } else if(!$user) { - //guess user from path, if no user passed. - $user = $pathDetails[1]; - } - - if(!isset($pathDetails[3]) || is_null($pathDetails[3])) { - $relativePath = ''; - } else { - $relativePath = $pathDetails[3]; - } - - if(is_null($query)){ - $query = \OC_DB::prepare('SELECT `propertyvalue` FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = \'{DAV:}getetag\''); - } - $result = \OC_DB::executeAudited($query,array($user, '/' . $relativePath)); - if ($row = $result->fetchRow()) { - return trim($row['propertyvalue'], '"'); - } else { - return ''; - } - } - - /** - * get all child items of an item from the legacy cache - * - * @param int $id - * @return array - */ - function getChildren($id) { - $result = \OC_DB::executeAudited('SELECT * FROM `*PREFIX*fscache` WHERE `parent` = ?', array($id)); - $data = $result->fetchAll(); - foreach ($data as $i => $item) { - $data[$i]['etag'] = $this->getEtag($item['path'], $item['user']); - } - return $data; - } -} diff --git a/lib/private/files/cache/upgrade.php b/lib/private/files/cache/upgrade.php deleted file mode 100644 index e3a46896cbf..00000000000 --- a/lib/private/files/cache/upgrade.php +++ /dev/null @@ -1,235 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -namespace OC\Files\Cache; - -class Upgrade { - /** - * @var Legacy $legacy - */ - private $legacy; - - private $numericIds = array(); - - private $mimeTypeIds = array(); - - /** - * @param Legacy $legacy - */ - public function __construct($legacy) { - $this->legacy = $legacy; - } - - /** - * Preform a upgrade a path and it's childs - * - * @param string $path - * @param bool $mode - */ - function upgradePath($path, $mode = Scanner::SCAN_RECURSIVE) { - if (!$this->legacy->hasItems()) { - return; - } - \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $path); - if ($row = $this->legacy->get($path)) { - $data = $this->getNewData($row); - if ($data) { - $this->insert($data); - $this->upgradeChilds($data['id'], $mode); - } - } - } - - /** - * upgrade all child elements of an item - * - * @param int $id - * @param bool $mode - */ - function upgradeChilds($id, $mode = Scanner::SCAN_RECURSIVE) { - $children = $this->legacy->getChildren($id); - foreach ($children as $child) { - $childData = $this->getNewData($child); - \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $child['path']); - if ($childData) { - $this->insert($childData); - if ($mode == Scanner::SCAN_RECURSIVE) { - $this->upgradeChilds($child['id']); - } - } - } - } - - /** - * insert data into the new cache - * - * @param array $data the data for the new cache - */ - function insert($data) { - static $insertQuery = null; - if(is_null($insertQuery)) { - $insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache` - ( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` ) - VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); - } - if (!$this->inCache($data['storage'], $data['path_hash'], $data['id'])) { - \OC_DB::executeAudited($insertQuery, array($data['id'], $data['storage'], - $data['path'], $data['path_hash'], $data['parent'], $data['name'], - $data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted'], $data['etag'])); - } - } - - /** - * check if an item is already in the new cache - * - * @param string $storage - * @param string $pathHash - * @param string $id - * @return bool - */ - function inCache($storage, $pathHash, $id) { - static $query = null; - if(is_null($query)) { - $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE (`storage` = ? AND `path_hash` = ?) OR `fileid` = ?'); - } - $result = \OC_DB::executeAudited($query, array($storage, $pathHash, $id)); - return (bool)$result->fetchRow(); - } - - /** - * get the new data array from the old one - * - * @param array $data the data from the old cache - * Example data array - * Array - * ( - * [id] => 418 - * [path] => /tina/files/picture.jpg //relative to datadir - * [path_hash] => 66d4547e372888deed80b24fec9b192b - * [parent] => 234 - * [name] => picture.jpg - * [user] => tina - * [size] => 1265283 - * [ctime] => 1363909709 - * [mtime] => 1363909709 - * [mimetype] => image/jpeg - * [mimepart] => image - * [encrypted] => 0 - * [versioned] => 0 - * [writable] => 1 - * ) - * - * @return array - */ - function getNewData($data) { - //Make sure there is a path, otherwise we can do nothing. - if(!isset($data['path'])) { - return false; - } - $newData = $data; - /** - * @var \OC\Files\Storage\Storage $storage - * @var string $internalPath; - */ - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($data['path']); - if ($storage) { - $newData['etag'] = $data['etag']; - $newData['path_hash'] = md5($internalPath); - $newData['path'] = $internalPath; - $newData['storage'] = $this->getNumericId($storage); - $newData['parent'] = ($internalPath === '') ? -1 : $data['parent']; - $newData['permissions'] = ($data['writable']) ? \OCP\PERMISSION_ALL : \OCP\PERMISSION_READ; - $newData['storage_object'] = $storage; - $newData['mimetype'] = $this->getMimetypeId($newData['mimetype'], $storage); - $newData['mimepart'] = $this->getMimetypeId($newData['mimepart'], $storage); - return $newData; - } else { - \OC_Log::write('core', 'Unable to migrate data from old cache for '.$data['path'].' because the storage was not found', \OC_Log::ERROR); - return false; - } - } - - /** - * get the numeric storage id - * - * @param \OC\Files\Storage\Storage $storage - * @return int - */ - function getNumericId($storage) { - $storageId = $storage->getId(); - if (!isset($this->numericIds[$storageId])) { - $cache = $storage->getCache(); - $this->numericIds[$storageId] = $cache->getNumericStorageId(); - } - return $this->numericIds[$storageId]; - } - - /** - * get the numeric id for a mimetype - * - * @param string $mimetype - * @param \OC\Files\Storage\Storage $storage - * @return int - */ - function getMimetypeId($mimetype, $storage) { - if (!isset($this->mimeTypeIds[$mimetype])) { - $cache = new Cache($storage); - $this->mimeTypeIds[$mimetype] = $cache->getMimetypeId($mimetype); - } - return $this->mimeTypeIds[$mimetype]; - } - - /** - * check if a cache upgrade is required for $user - * - * @param string $user - * @return bool - */ - static function needUpgrade($user) { - $cacheVersion = (int)\OCP\Config::getUserValue($user, 'files', 'cache_version', 4); - if ($cacheVersion < 5) { - $legacy = new \OC\Files\Cache\Legacy($user); - if ($legacy->hasItems()) { - return true; - } - self::upgradeDone($user); - } - - return false; - } - - /** - * mark the filecache as upgrade - * - * @param string $user - */ - static function upgradeDone($user) { - \OCP\Config::setUserValue($user, 'files', 'cache_version', 5); - } - - /** - * Does a "silent" upgrade, i.e. without an Event-Source as triggered - * on User-Login via Ajax. This method is called within the regular - * ownCloud upgrade. - * - * @param string $user a User ID - */ - public static function doSilentUpgrade($user) { - if(!self::needUpgrade($user)) { - return; - } - $legacy = new \OC\Files\Cache\Legacy($user); - if ($legacy->hasItems()) { - \OC_DB::beginTransaction(); - $upgrade = new \OC\Files\Cache\Upgrade($legacy); - $upgrade->upgradePath('/' . $user . '/files'); - \OC_DB::commit(); - } - \OC\Files\Cache\Upgrade::upgradeDone($user); - } -} diff --git a/lib/private/updater.php b/lib/private/updater.php index dd8dc84e804..1354f3fd2f8 100644 --- a/lib/private/updater.php +++ b/lib/private/updater.php @@ -16,9 +16,6 @@ use OC\Hooks\BasicEmitter; * - maintenanceStart() * - maintenanceEnd() * - dbUpgrade() - * - filecacheStart() - * - filecacheProgress(int $percentage) - * - filecacheDone() * - failure(string $message) */ class Updater extends BasicEmitter { @@ -122,9 +119,6 @@ class Updater extends BasicEmitter { \OC_DB::updateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml'); $this->emit('\OC\Updater', 'dbUpgrade'); - // do a file cache upgrade for users with files - // this can take loooooooooooooooooooooooong - $this->upgradeFileCache(); } catch (\Exception $exception) { $this->emit('\OC\Updater', 'failure', array($exception->getMessage())); } @@ -142,42 +136,5 @@ class Updater extends BasicEmitter { $this->emit('\OC\Updater', 'maintenanceEnd'); } - private function upgradeFileCache() { - try { - $query = \OC_DB::prepare(' - SELECT DISTINCT `user` - FROM `*PREFIX*fscache` - '); - $result = $query->execute(); - } catch (\Exception $e) { - return; - } - $users = $result->fetchAll(); - if (count($users) == 0) { - return; - } - $step = 100 / count($users); - $percentCompleted = 0; - $lastPercentCompletedOutput = 0; - $startInfoShown = false; - foreach ($users as $userRow) { - $user = $userRow['user']; - \OC\Files\Filesystem::initMountPoints($user); - \OC\Files\Cache\Upgrade::doSilentUpgrade($user); - if (!$startInfoShown) { - //We show it only now, because otherwise Info about upgraded apps - //will appear between this and progress info - $this->emit('\OC\Updater', 'filecacheStart'); - $startInfoShown = true; - } - $percentCompleted += $step; - $out = floor($percentCompleted); - if ($out != $lastPercentCompletedOutput) { - $this->emit('\OC\Updater', 'filecacheProgress', array($out)); - $lastPercentCompletedOutput = $out; - } - } - $this->emit('\OC\Updater', 'filecacheDone'); - } } -- cgit v1.2.3 From 76961ce0727d08ef3d12bd445798df221f5d2063 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 18 Mar 2014 17:54:21 +0100 Subject: fixing javascript error where $(Files.breadcrumbs[1]).get(0) returns undefined - happens on resize to a very small width --- apps/files/js/files.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'apps/files/js') diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 1186a72a44f..1137364db4a 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -196,11 +196,14 @@ var Files = { if (width !== Files.lastWidth) { if ((width < Files.lastWidth || firstRun) && width < Files.breadcrumbsWidth) { if (Files.hiddenBreadcrumbs === 0) { - Files.breadcrumbsWidth -= $(Files.breadcrumbs[1]).get(0).offsetWidth; - $(Files.breadcrumbs[1]).find('a').hide(); - $(Files.breadcrumbs[1]).append('...'); - Files.breadcrumbsWidth += $(Files.breadcrumbs[1]).get(0).offsetWidth; - Files.hiddenBreadcrumbs = 2; + bc = $(Files.breadcrumbs[1]).get(0); + if (typeof bc != 'undefined') { + Files.breadcrumbsWidth -= bc.offsetWidth; + $(Files.breadcrumbs[1]).find('a').hide(); + $(Files.breadcrumbs[1]).append('...'); + Files.breadcrumbsWidth += bc.offsetWidth; + Files.hiddenBreadcrumbs = 2; + } } var i = Files.hiddenBreadcrumbs; while (width < Files.breadcrumbsWidth && i > 1 && i < Files.breadcrumbs.length - 1) { -- cgit v1.2.3 From fa28c089fa3ffb72e97ca0f89cbfade3d0a8a8a5 Mon Sep 17 00:00:00 2001 From: Oskar Hollmann Date: Wed, 19 Mar 2014 22:09:09 +0100 Subject: Fix: 'Upload button tooltip doesn't disappear' Fixes issue #7461. Tipsy tooltip must be hidden when the upload starts. Otherwise it covers the progress bar and stays in DOM. --- apps/files/js/file-upload.js | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 apps/files/js/file-upload.js (limited to 'apps/files/js') diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js old mode 100644 new mode 100755 index ea4061c9b0b..c668bbf397d --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -320,6 +320,7 @@ OC.Upload = { */ start: function(e) { OC.Upload.log('start', e, null); + $('#upload').tipsy('hide'); // otherwise "Upload max." covers progress bar }, submit: function(e, data) { OC.Upload.rememberUpload(data); -- cgit v1.2.3 From 90839b784f748b18a2a5fae4cc3f80bd1df7b355 Mon Sep 17 00:00:00 2001 From: Oskar Hollmann Date: Wed, 19 Mar 2014 23:05:03 +0100 Subject: Comment moved to prevent 'Line is too long' warning. --- apps/files/js/file-upload.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'apps/files/js') diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index c668bbf397d..371c83e742c 100755 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -320,7 +320,8 @@ OC.Upload = { */ start: function(e) { OC.Upload.log('start', e, null); - $('#upload').tipsy('hide'); // otherwise "Upload max." covers progress bar + //hide the tooltip otherwise it covers the progress bar + $('#upload').tipsy('hide'); }, submit: function(e, data) { OC.Upload.rememberUpload(data); -- cgit v1.2.3 From 5747e0e3f98d3c299b0bd46bb77ca7bf6b170312 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Thu, 20 Mar 2014 13:26:21 +0100 Subject: remove executable flag for file-upload.js --- apps/files/js/file-upload.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 apps/files/js/file-upload.js (limited to 'apps/files/js') diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js old mode 100755 new mode 100644 -- cgit v1.2.3 From f88b24d53237ce50c2c4b4d696700dcdf59bb437 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Thu, 27 Mar 2014 14:48:35 +0100 Subject: enable SVG->PNG fallback for newly uploaded files and folders --- apps/files/js/filelist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apps/files/js') diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 503bf681139..cda4e823a73 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -71,7 +71,7 @@ window.FileList={ }); // filename td td = $('').attr({ - "class": "filename", + "class": "filename svg", "style": 'background-image:url('+iconurl+'); background-size: 32px;' }); var rand = Math.random().toString(16).slice(2); -- cgit v1.2.3