summaryrefslogtreecommitdiffstats
path: root/apps/files
diff options
context:
space:
mode:
authorJan-Christoph Borchardt <hey@jancborchardt.net>2014-01-29 10:55:44 +0100
committerJan-Christoph Borchardt <hey@jancborchardt.net>2014-01-29 10:55:44 +0100
commit13ed59c1cf2598f28c415c0c2459b5a4495ff5ef (patch)
tree890efcfe462f19468e2aa05ca1a22049edc21ab6 /apps/files
parentc767ebcc03c604f3141af4c286ad099fdf64c561 (diff)
parentcf2c061f1f2577b3a995d9e2423c93589d7df2b3 (diff)
downloadnextcloud-server-13ed59c1cf2598f28c415c0c2459b5a4495ff5ef.tar.gz
nextcloud-server-13ed59c1cf2598f28c415c0c2459b5a4495ff5ef.zip
merge master into mobile-style
Diffstat (limited to 'apps/files')
-rw-r--r--apps/files/appinfo/remote.php1
-rw-r--r--apps/files/css/files.css41
-rw-r--r--apps/files/css/upload.css12
-rw-r--r--apps/files/index.php2
-rw-r--r--apps/files/js/fileactions.js5
-rw-r--r--apps/files/js/filelist.js14
-rw-r--r--apps/files/js/files.js42
-rw-r--r--apps/files/templates/admin.php2
-rw-r--r--apps/files/templates/index.php2
-rw-r--r--apps/files/tests/js/fileactionsSpec.js61
-rw-r--r--apps/files/tests/js/filelistSpec.js63
-rw-r--r--apps/files/tests/js/filesSpec.js81
12 files changed, 288 insertions, 38 deletions
diff --git a/apps/files/appinfo/remote.php b/apps/files/appinfo/remote.php
index 9f290796205..ef22fe92188 100644
--- a/apps/files/appinfo/remote.php
+++ b/apps/files/appinfo/remote.php
@@ -52,6 +52,7 @@ $server->addPlugin(new OC_Connector_Sabre_FilesPlugin());
$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin());
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin());
$server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin());
+$server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav'));
// And off we go!
$server->exec();
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index 1c48d61c4e8..ca3b8500669 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -3,7 +3,7 @@
See the COPYING-README file. */
/* FILE MENU */
-.actions { padding:.3em; height:2em; width: 100%; }
+.actions { padding:5px; height:32px; width: 100%; }
.actions input, .actions button, .actions .button { margin:0; float:left; }
.actions .button a { color: #555; }
.actions .button a:hover, .actions .button a:active { color: #333; }
@@ -33,9 +33,9 @@
#new>ul {
display: none;
position: fixed;
- min-width: 7em;
+ min-width: 112px;
z-index: 10;
- padding: .5em;
+ padding: 8px;
padding-bottom: 0;
margin-top: 14px;
margin-left: -1px;
@@ -46,7 +46,7 @@
border-top-left-radius: 0;
box-shadow:0 2px 7px rgba(170,170,170,.4);
}
-#new>ul>li { height:36px; margin:.3em; padding-left:3em; padding-bottom:0.1em;
+#new>ul>li { height:36px; margin:5px; padding-left:48px; padding-bottom:2px;
background-repeat:no-repeat; cursor:pointer; }
#new>ul>li>p { cursor:pointer; padding-top: 7px; padding-bottom: 7px;}
@@ -73,7 +73,7 @@
min-width: 600px;
}
-#filestable tbody tr { background-color:#fff; height:2.5em; }
+#filestable tbody tr { background-color:#fff; height:40px; }
#filestable tbody tr:hover, tbody tr:active {
background-color: rgb(240,240,240);
}
@@ -88,7 +88,7 @@ span.extension, span.uploading, td.date { color:#999; }
span.extension { text-transform:lowercase; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; }
tr:hover span.extension { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; color:#777; }
table tr.mouseOver td { background-color:#eee; }
-table th { height:2em; padding:0 .5em; color:#999; }
+table th { height:24px; padding:0 8px; color:#999; }
table th .name {
position: absolute;
left: 55px;
@@ -111,15 +111,15 @@ table th#headerName {
height: 50px;
}
table th#headerSize, table td.filesize {
- min-width: 3em;
- padding: 0 1em;
+ min-width: 48px;
+ padding: 0 16px;
text-align: right;
}
table th#headerDate, table td.date {
-moz-box-sizing: border-box;
box-sizing: border-box;
position: relative;
- min-width: 11em;
+ min-width: 176px;
}
/* Multiselect bar */
@@ -147,7 +147,7 @@ table.multiselect #headerName {
position: relative;
width: 9999px; /* when we use 100%, the styling breaks on mobile … table styling */
}
-table td.selection, table th.selection, table td.fileaction { width:2em; text-align:center; }
+table td.selection, table th.selection, table td.fileaction { width:32px; text-align:center; }
table td.filename a.name {
position:relative; /* Firefox needs to explicitly have this default set … */
-moz-box-sizing: border-box;
@@ -165,8 +165,8 @@ table td.filename input.filename {
margin-left: 2px;
cursor: text;
}
-table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:.2em .5em .5em .3em; }
-table td.filename .nametext, .uploadtext, .modified { float:left; padding:.3em 0; }
+table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:3px 8px 8px 3px; }
+table td.filename .nametext, .uploadtext, .modified { float:left; padding:14px 0; }
#modified {
position: absolute;
@@ -186,8 +186,8 @@ table td.filename .nametext {
text-overflow: ellipsis;
max-width: 800px;
}
-table td.filename .uploadtext { font-weight:normal; margin-left:.5em; }
-table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; }
+table td.filename .uploadtext { font-weight:normal; margin-left:8px; }
+table td.filename form { font-size:14px; margin-left:48px; margin-right:48px; }
.ie8 input[type="checkbox"]{
padding: 0;
@@ -222,6 +222,11 @@ table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; }
width: 50px;
z-index: 5;
}
+#fileList tr td.filename>input[type="checkbox"]{
+ /* sometimes checkbox height is bigger (KDE/Qt), so setting to absolute
+ * to prevent it to increase the height */
+ position: absolute;
+}
#fileList tr td.filename>input[type="checkbox"] + label {
left: 0;
}
@@ -255,11 +260,11 @@ table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; }
right: 0;
}
-#fileList img.move2trash { display:inline; margin:-.5em 0; padding:1em .5em 1em .5em !important; float:right; }
+#fileList img.move2trash { display:inline; margin:-8px 0; padding:16px 8px 16px 8px !important; float:right; }
#fileList a.action.delete {
position: absolute;
right: 0;
- padding: 9px 14px 19px !important;
+ padding: 28px 14px 19px !important;
}
a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; }
@@ -277,13 +282,13 @@ a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; }
}
.selectedActions a img {
position:relative;
- top:.3em;
+ top:5px;
}
#fileList a.action {
display: inline;
- margin: -.5em 0;
+ margin: -8px 0;
padding: 18px 8px !important;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
diff --git a/apps/files/css/upload.css b/apps/files/css/upload.css
index ef043569094..06b4d4655fe 100644
--- a/apps/files/css/upload.css
+++ b/apps/files/css/upload.css
@@ -5,7 +5,7 @@
height: 36px;
width: 39px;
padding: 0 !important; /* override default control bar button padding */
- margin-left: .2em;
+ margin-left: 3px;
overflow: hidden;
vertical-align: top;
}
@@ -18,9 +18,6 @@
margin: -5px -3px;
cursor: pointer;
z-index: 10;
- background-image: url('%webroot%/core/img/actions/upload.svg');
- background-repeat: no-repeat;
- background-position: center;
opacity: .65;
}
.file_upload_target { display:none; }
@@ -33,7 +30,7 @@
height: 44px;
margin: -5px -3px;
padding: 0;
- font-size: 1em;
+ font-size: 16px;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0;
z-index: 20;
cursor: pointer;
@@ -119,11 +116,6 @@
.oc-dialog .fileexists .conflict input[type='checkbox'] {
float: left;
}
-.oc-dialog .fileexists .toggle {
- background-image: url('%webroot%/core/img/actions/triangle-e.png');
- width: 16px;
- height: 16px;
-}
.oc-dialog .fileexists #allfileslabel {
float:right;
}
diff --git a/apps/files/index.php b/apps/files/index.php
index 8f6838aa0d9..2ce8fdb065f 100644
--- a/apps/files/index.php
+++ b/apps/files/index.php
@@ -63,7 +63,6 @@ $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;
- $freeSpace = 0;
} else {
if ($isIE8){
// after the redirect above, the URL will have a format
@@ -77,7 +76,6 @@ if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we ne
else{
$files = \OCA\Files\Helper::getFiles($dir);
}
- $freeSpace = \OC\Files\Filesystem::free_space($dir);
$needUpgrade = false;
}
diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js
index 74bb711ef3d..eb59e71a030 100644
--- a/apps/files/js/fileactions.js
+++ b/apps/files/js/fileactions.js
@@ -173,7 +173,10 @@ $(document).ready(function () {
FileActions.register(downloadScope, 'Download', OC.PERMISSION_READ, function () {
return OC.imagePath('core', 'actions/download');
}, function (filename) {
- window.location = OC.filePath('files', 'ajax', 'download.php') + '?files=' + encodeURIComponent(filename) + '&dir=' + encodeURIComponent($('#dir').val());
+ var url = FileList.getDownloadUrl(filename);
+ if (url) {
+ OC.redirect(url);
+ }
});
}
$('#fileList tr').each(function () {
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 66968ab54c7..63fd0f4ce05 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -780,6 +780,20 @@ var FileList={
$('#fileList tr.searchresult').each(function(i,e) {
$(e).removeClass("searchresult");
});
+ },
+
+ /**
+ * Returns the download URL of the given file
+ * @param filename file name of the file
+ * @param dir optional directory in which the file name is, defaults to the current directory
+ */
+ getDownloadUrl: function(filename, dir) {
+ var params = {
+ files: filename,
+ dir: dir || FileList.getCurrentDirectory(),
+ download: null
+ };
+ return OC.filePath('files', 'ajax', 'download.php') + '?' + OC.buildQueryString(params);
}
};
diff --git a/apps/files/js/files.js b/apps/files/js/files.js
index b5633ae01aa..d794a1584de 100644
--- a/apps/files/js/files.js
+++ b/apps/files/js/files.js
@@ -493,7 +493,7 @@ var createDragShadow = function(event) {
var dir=$('#dir').val();
$(selectedFiles).each(function(i,elem) {
- var newtr = $('<tr/>').attr('data-dir', dir).attr('data-filename', elem.name);
+ var newtr = $('<tr/>').attr('data-dir', dir).attr('data-filename', elem.name).attr('data-origin', elem.origin);
newtr.append($('<td/>').addClass('filename').text(elem.name));
newtr.append($('<td/>').addClass('size').text(humanFileSize(elem.size)));
tbody.append(newtr);
@@ -511,13 +511,30 @@ var createDragShadow = function(event) {
};
//options for file drag/drop
+//start&stop handlers needs some cleaning up
var dragOptions={
revert: 'invalid', revertDuration: 300,
opacity: 0.7, zIndex: 100, appendTo: 'body', cursorAt: { left: 24, top: 18 },
helper: createDragShadow, cursor: 'move',
- stop: function(event, ui) {
- $('#fileList tr td.filename').addClass('ui-draggable');
- }
+ start: function(event, ui){
+ var $selectedFiles = $('td.filename input:checkbox:checked');
+ if($selectedFiles.length > 1){
+ $selectedFiles.parents('tr').fadeTo(250, 0.2);
+ }
+ else{
+ $(this).fadeTo(250, 0.2);
+ }
+ },
+ stop: function(event, ui) {
+ var $selectedFiles = $('td.filename input:checkbox:checked');
+ if($selectedFiles.length > 1){
+ $selectedFiles.parents('tr').fadeTo(250, 1);
+ }
+ else{
+ $(this).fadeTo(250, 1);
+ }
+ $('#fileList tr td.filename').addClass('ui-draggable');
+ }
};
// sane browsers support using the distance option
if ( $('html.ie').length === 0) {
@@ -525,6 +542,7 @@ if ( $('html.ie').length === 0) {
}
var folderDropOptions={
+ hoverClass: "canDrop",
drop: function( event, ui ) {
//don't allow moving a file into a selected folder
if ($(event.target).parents('tr').find('td input:first').prop('checked') === true) {
@@ -537,6 +555,11 @@ var folderDropOptions={
$(files).each(function(i,row) {
var dir = $(row).data('dir');
var file = $(row).data('filename');
+ //slapdash selector, tracking down our original element that the clone budded off of.
+ var origin = $('tr[data-id=' + $(row).data('origin') + ']');
+ var td = origin.children('td.filename');
+ var oldBackgroundImage = td.css('background-image');
+ td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')');
$.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: dir+'/'+target }, function(result) {
if (result) {
if (result.status === 'success') {
@@ -559,6 +582,7 @@ var folderDropOptions={
} else {
OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error'));
}
+ td.css('background-image', oldBackgroundImage);
});
});
},
@@ -583,6 +607,11 @@ var crumbDropOptions={
$(files).each(function(i,row) {
var dir = $(row).data('dir');
var file = $(row).data('filename');
+ //slapdash selector, tracking down our original element that the clone budded off of.
+ var origin = $('tr[data-id=' + $(row).data('origin') + ']');
+ var td = origin.children('td.filename');
+ var oldBackgroundImage = td.css('background-image');
+ td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')');
$.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: target }, function(result) {
if (result) {
if (result.status === 'success') {
@@ -597,6 +626,7 @@ var crumbDropOptions={
} else {
OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error'));
}
+ td.css('background-image', oldBackgroundImage);
});
});
},
@@ -663,7 +693,8 @@ function getSelectedFilesTrash(property) {
mime:$(element).data('mime'),
type:$(element).data('type'),
size:$(element).data('size'),
- etag:$(element).data('etag')
+ etag:$(element).data('etag'),
+ origin: $(element).data('id')
};
if (property) {
files.push(file[property]);
@@ -783,3 +814,4 @@ function onClickBreadcrumb(e) {
FileList.changeDirectory(decodeURIComponent($targetDir));
}
}
+
diff --git a/apps/files/templates/admin.php b/apps/files/templates/admin.php
index 697fc52526a..a5afd55fbc3 100644
--- a/apps/files/templates/admin.php
+++ b/apps/files/templates/admin.php
@@ -5,7 +5,7 @@
<h2><?php p($l->t('File handling')); ?></h2>
<?php if($_['uploadChangable']):?>
<label for="maxUploadSize"><?php p($l->t( 'Maximum upload size' )); ?> </label>
- <input name='maxUploadSize' id="maxUploadSize" value='<?php p($_['uploadMaxFilesize']) ?>'/>
+ <input type="text" name='maxUploadSize' id="maxUploadSize" value='<?php p($_['uploadMaxFilesize']) ?>'/>
<?php if($_['displayMaxPossibleUploadSize']):?>
(<?php p($l->t('max. possible: ')); p($_['maxPossibleUploadSize']) ?>)
<?php endif;?>
diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php
index 5188ca56281..ff78f0ca551 100644
--- a/apps/files/templates/index.php
+++ b/apps/files/templates/index.php
@@ -29,7 +29,7 @@
<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir">
<input type="file" id="file_upload_start" name='files[]'
data-url="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" />
- <a href="#" class="svg"></a>
+ <a href="#" class="svg icon icon-upload"></a>
</div>
<?php if ($_['trash']): ?>
<input id="trash" type="button" value="<?php p($l->t('Deleted files'));?>" class="button" <?php $_['trashEmpty'] ? p('disabled') : '' ?> />
diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js
new file mode 100644
index 00000000000..23f7b58dcd9
--- /dev/null
+++ b/apps/files/tests/js/fileactionsSpec.js
@@ -0,0 +1,61 @@
+/**
+* ownCloud
+*
+* @author Vincent Petry
+* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+describe('FileActions tests', function() {
+ beforeEach(function() {
+ // init horrible parameters
+ var $body = $('body');
+ $body.append('<input type="hidden" id="dir" value="/subdir"></input>');
+ $body.append('<input type="hidden" id="permissions" value="31"></input>');
+ // dummy files table
+ $filesTable = $body.append('<table id="filestable"></table>');
+ });
+ afterEach(function() {
+ $('#dir, #permissions, #filestable').remove();
+ });
+ it('calling display() sets file actions', function() {
+ // note: download_url is actually the link target, not the actual download URL...
+ var $tr = FileList.addFile('testName.txt', 1234, new Date(), false, false, {download_url: 'test/download/url'});
+
+ // no actions before call
+ expect($tr.find('.action[data-action=Download]').length).toEqual(0);
+ expect($tr.find('.action[data-action=Rename]').length).toEqual(0);
+ expect($tr.find('.action.delete').length).toEqual(0);
+
+ FileActions.display($tr.find('td.filename'), true);
+
+ // actions defined after cal
+ expect($tr.find('.action[data-action=Download]').length).toEqual(1);
+ expect($tr.find('.action[data-action=Rename]').length).toEqual(1);
+ expect($tr.find('.action.delete').length).toEqual(1);
+ });
+ it('redirects to download URL when clicking download', function() {
+ var redirectStub = sinon.stub(OC, 'redirect');
+ // note: download_url is actually the link target, not the actual download URL...
+ var $tr = FileList.addFile('test download File.txt', 1234, new Date(), false, false, {download_url: 'test/download/url'});
+ FileActions.display($tr.find('td.filename'), true);
+
+ $tr.find('.action[data-action=Download]').click();
+
+ expect(redirectStub.calledOnce).toEqual(true);
+ expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?files=test%20download%20File.txt&dir=%2Fsubdir&download');
+ redirectStub.restore();
+ });
+});
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
new file mode 100644
index 00000000000..61e026c0725
--- /dev/null
+++ b/apps/files/tests/js/filelistSpec.js
@@ -0,0 +1,63 @@
+/**
+* ownCloud
+*
+* @author Vincent Petry
+* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+describe('FileList tests', function() {
+ beforeEach(function() {
+ // init horrible parameters
+ var $body = $('body');
+ $body.append('<input type="hidden" id="dir" value="/subdir"></input>');
+ $body.append('<input type="hidden" id="permissions" value="31"></input>');
+ // dummy files table
+ $body.append('<table id="filestable"></table>');
+ });
+ afterEach(function() {
+ $('#dir, #permissions, #filestable').remove();
+ });
+ it('generates file element with correct attributes when calling addFile', function() {
+ var lastMod = new Date(10000);
+ // note: download_url is actually the link target, not the actual download URL...
+ var $tr = FileList.addFile('testName.txt', 1234, lastMod, false, false, {download_url: 'test/download/url'});
+
+ expect($tr).toBeDefined();
+ expect($tr[0].tagName.toLowerCase()).toEqual('tr');
+ expect($tr.find('a:first').attr('href')).toEqual('test/download/url');
+ expect($tr.attr('data-type')).toEqual('file');
+ expect($tr.attr('data-file')).toEqual('testName.txt');
+ expect($tr.attr('data-size')).toEqual('1234');
+ expect($tr.attr('data-permissions')).toEqual('31');
+ //expect($tr.attr('data-mime')).toEqual('plain/text');
+ });
+ it('generates dir element with correct attributes when calling addDir', function() {
+ var lastMod = new Date(10000);
+ var $tr = FileList.addDir('testFolder', 1234, lastMod, false);
+
+ expect($tr).toBeDefined();
+ expect($tr[0].tagName.toLowerCase()).toEqual('tr');
+ expect($tr.attr('data-type')).toEqual('dir');
+ expect($tr.attr('data-file')).toEqual('testFolder');
+ expect($tr.attr('data-size')).toEqual('1234');
+ expect($tr.attr('data-permissions')).toEqual('31');
+ //expect($tr.attr('data-mime')).toEqual('httpd/unix-directory');
+ });
+ it('returns correct download URL', function() {
+ expect(FileList.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?files=some%20file.txt&dir=%2Fsubdir&download');
+ expect(FileList.getDownloadUrl('some file.txt', '/anotherpath/abc')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?files=some%20file.txt&dir=%2Fanotherpath%2Fabc&download');
+ });
+});
diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js
new file mode 100644
index 00000000000..9d0a2e4f9d7
--- /dev/null
+++ b/apps/files/tests/js/filesSpec.js
@@ -0,0 +1,81 @@
+/**
+* ownCloud
+*
+* @author Vincent Petry
+* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+describe('Files tests', function() {
+ describe('File name validation', function() {
+ it('Validates correct file names', function() {
+ var fileNames = [
+ 'boringname',
+ 'something.with.extension',
+ 'now with spaces',
+ '.a',
+ '..a',
+ '.dotfile',
+ 'single\'quote',
+ ' spaces before',
+ 'spaces after ',
+ 'allowed chars including the crazy ones $%&_-^@!,()[]{}=;#',
+ '汉字也能用',
+ 'und Ümläüte sind auch willkommen'
+ ];
+ for ( var i = 0; i < fileNames.length; i++ ) {
+ try {
+ expect(Files.isFileNameValid(fileNames[i])).toEqual(true);
+ }
+ catch (e) {
+ fail();
+ }
+ }
+ });
+ it('Detects invalid file names', function() {
+ var fileNames = [
+ '',
+ ' ',
+ '.',
+ '..',
+ 'back\\slash',
+ 'sl/ash',
+ 'lt<lt',
+ 'gt>gt',
+ 'col:on',
+ 'double"quote',
+ 'pi|pe',
+ 'dont?ask?questions?',
+ 'super*star',
+ 'new\nline',
+ ' ..',
+ '.. ',
+ '. ',
+ ' .'
+ ];
+ for ( var i = 0; i < fileNames.length; i++ ) {
+ var threwException = false;
+ try {
+ Files.isFileNameValid(fileNames[i]);
+ fail();
+ }
+ catch (e) {
+ threwException = true;
+ }
+ expect(threwException).toEqual(true);
+ }
+ });
+ });
+});