diff options
Diffstat (limited to 'apps')
41 files changed, 1166 insertions, 563 deletions
diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php index c50e96b2429..f1b713b5534 100644 --- a/apps/files/ajax/list.php +++ b/apps/files/ajax/list.php @@ -10,35 +10,38 @@ OCP\JSON::checkLoggedIn(); // Load the files $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; + +if (!\OC\Files\Filesystem::is_dir($dir . '/')) { + header("HTTP/1.0 404 Not Found"); + exit(); +} + $doBreadcrumb = isset($_GET['breadcrumb']); $data = array(); +$baseUrl = OCP\Util::linkTo('files', 'index.php') . '?dir='; + +$permissions = \OCA\files\lib\Helper::getDirPermissions($dir); // Make breadcrumb if($doBreadcrumb) { - $breadcrumb = array(); - $pathtohere = "/"; - foreach( explode( "/", $dir ) as $i ) { - if( $i != "" ) { - $pathtohere .= "$i/"; - $breadcrumb[] = array( "dir" => $pathtohere, "name" => $i ); - } - } - - $breadcrumbNav = new OCP\Template( "files", "part.breadcrumb", "" ); - $breadcrumbNav->assign( "breadcrumb", $breadcrumb, false ); + $breadcrumb = \OCA\files\lib\Helper::makeBreadcrumb($dir); + + $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); + $breadcrumbNav->assign('breadcrumb', $breadcrumb, false); + $breadcrumbNav->assign('baseURL', $baseUrl); $data['breadcrumb'] = $breadcrumbNav->fetchPage(); } // make filelist -$files = array(); -foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $i ) { - $i["date"] = OCP\Util::formatDate($i["mtime"] ); - $files[] = $i; -} - -$list = new OCP\Template( "files", "part.list", "" ); -$list->assign( "files", $files, false ); -$data = array('files' => $list->fetchPage()); +$files = \OCA\files\lib\Helper::getFiles($dir); + +$list = new OCP\Template("files", "part.list", ""); +$list->assign('files', $files, false); +$list->assign('baseURL', $baseUrl, false); +$list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); +$list->assign('isPublic', false); +$data['files'] = $list->fetchPage(); +$data['permissions'] = $permissions; OCP\JSON::success(array('data' => $data)); diff --git a/apps/files/ajax/rawlist.php b/apps/files/ajax/rawlist.php index f568afad4da..9ccd4cc299a 100644 --- a/apps/files/ajax/rawlist.php +++ b/apps/files/ajax/rawlist.php @@ -11,22 +11,54 @@ OCP\JSON::checkLoggedIn(); // Load the files $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; -$mimetype = isset($_GET['mimetype']) ? $_GET['mimetype'] : ''; +$mimetypes = isset($_GET['mimetypes']) ? json_decode($_GET['mimetypes'], true) : ''; + +// Clean up duplicates from array and deal with non-array requests +if (is_array($mimetypes)) { + $mimetypes = array_unique($mimetypes); +} elseif (is_null($mimetypes)) { + $mimetypes = array($_GET['mimetypes']); +} // make filelist $files = array(); // If a type other than directory is requested first load them. -if($mimetype && strpos($mimetype, 'httpd/unix-directory') === false) { - foreach( \OC\Files\Filesystem::getDirectoryContent( $dir, 'httpd/unix-directory' ) as $i ) { - $i["date"] = OCP\Util::formatDate($i["mtime"] ); - $i['mimetype_icon'] = $i['type'] == 'dir' ? \mimetype_icon('dir'): \mimetype_icon($i['mimetype']); - $files[] = $i; +if($mimetypes && !in_array('httpd/unix-directory', $mimetypes)) { + foreach( \OC\Files\Filesystem::getDirectoryContent( $dir, 'httpd/unix-directory' ) as $file ) { + $file['directory'] = $dir; + $file['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($file['mimetype']); + $file["date"] = OCP\Util::formatDate($file["mtime"]); + $file['mimetype_icon'] = \OCA\files\lib\Helper::determineIcon($file); + $files[] = $file; } } -foreach( \OC\Files\Filesystem::getDirectoryContent( $dir, $mimetype ) as $i ) { - $i["date"] = OCP\Util::formatDate($i["mtime"] ); - $i['mimetype_icon'] = $i['type'] == 'dir' ? \mimetype_icon('dir'): \mimetype_icon($i['mimetype']); - $files[] = $i; + +if (is_array($mimetypes) && count($mimetypes)) { + foreach ($mimetypes as $mimetype) { + foreach( \OC\Files\Filesystem::getDirectoryContent( $dir, $mimetype ) as $file ) { + $file['directory'] = $dir; + $file['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($file['mimetype']); + $file["date"] = OCP\Util::formatDate($file["mtime"]); + $file['mimetype_icon'] = \OCA\files\lib\Helper::determineIcon($file); + $files[] = $file; + } + } +} else { + foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $file ) { + $file['directory'] = $dir; + $file['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($file['mimetype']); + $file["date"] = OCP\Util::formatDate($file["mtime"]); + $file['mimetype_icon'] = \OCA\files\lib\Helper::determineIcon($file); + $files[] = $file; + } } -OCP\JSON::success(array('data' => $files)); +// Sort by name +usort($files, function ($a, $b) { + if ($a['name'] === $b['name']) { + return 0; + } + return ($a['name'] < $b['name']) ? -1 : 1; +}); + +OC_JSON::success(array('data' => $files)); diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 8053649bd55..41d9808c56b 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -336,3 +336,25 @@ table.dragshadow td.size { text-align: center; margin-left: -200px; } +.mask { + z-index: 50; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: white; + background-repeat: no-repeat no-repeat; + background-position: 50%; + opacity: 0.7; + filter: alpha(opacity=70); + transition: opacity 100ms; + -moz-transition: opacity 100ms; + -o-transition: opacity 100ms; + -ms-transition: opacity 100ms; + -webkit-transition: opacity 100ms; +} +.mask.transparent{ + opacity: 0; +} + diff --git a/apps/files/index.php b/apps/files/index.php index f1e120c872c..d46d8e32eef 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -41,79 +41,58 @@ if (!\OC\Files\Filesystem::is_dir($dir . '/')) { exit(); } -function fileCmp($a, $b) { - if ($a['type'] == 'dir' and $b['type'] != 'dir') { - return -1; - } elseif ($a['type'] != 'dir' and $b['type'] == 'dir') { - return 1; - } else { - return strnatcasecmp($a['name'], $b['name']); +$isIE8 = false; +preg_match('/MSIE (.*?);/', $_SERVER['HTTP_USER_AGENT'], $matches); +if (count($matches) > 0 && $matches[1] <= 8){ + $isIE8 = true; +} + +// if IE8 and "?dir=path" was specified, reformat the URL to use a hash like "#?dir=path" +if ($isIE8 && isset($_GET['dir'])){ + if ($dir === ''){ + $dir = '/'; } + header('Location: ' . OCP\Util::linkTo('files', 'index.php') . '#?dir=' . \OCP\Util::encodePath($dir)); + exit(); } +$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 - $content = array(); $needUpgrade = true; $freeSpace = 0; } else { - $content = \OC\Files\Filesystem::getDirectoryContent($dir); + 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\lib\Helper::getFiles($dir); + } $freeSpace = \OC\Files\Filesystem::free_space($dir); $needUpgrade = false; } -foreach ($content as $i) { - $i['date'] = OCP\Util::formatDate($i['mtime']); - if ($i['type'] == 'file') { - $fileinfo = pathinfo($i['name']); - $i['basename'] = $fileinfo['filename']; - if (!empty($fileinfo['extension'])) { - $i['extension'] = '.' . $fileinfo['extension']; - } else { - $i['extension'] = ''; - } - } - $i['directory'] = $dir; - $i['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($i['mimetype']); - $files[] = $i; -} - -usort($files, "fileCmp"); // Make breadcrumb -$breadcrumb = array(); -$pathtohere = ''; -foreach (explode('/', $dir) as $i) { - if ($i != '') { - $pathtohere .= '/' . $i; - $breadcrumb[] = array('dir' => $pathtohere, 'name' => $i); - } -} +$breadcrumb = \OCA\files\lib\Helper::makeBreadcrumb($dir); // make breadcrumb und filelist markup $list = new OCP\Template('files', 'part.list', ''); $list->assign('files', $files); $list->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir='); $list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); -$list->assign('disableSharing', false); $list->assign('isPublic', false); $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', $breadcrumb); $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir='); -$permissions = OCP\PERMISSION_READ; -if (\OC\Files\Filesystem::isCreatable($dir . '/')) { - $permissions |= OCP\PERMISSION_CREATE; -} -if (\OC\Files\Filesystem::isUpdatable($dir . '/')) { - $permissions |= OCP\PERMISSION_UPDATE; -} -if (\OC\Files\Filesystem::isDeletable($dir . '/')) { - $permissions |= OCP\PERMISSION_DELETE; -} -if (\OC\Files\Filesystem::isSharable($dir . '/')) { - $permissions |= OCP\PERMISSION_SHARE; -} +$permissions = \OCA\files\lib\Helper::getDirPermissions($dir); if ($needUpgrade) { OCP\Util::addscript('files', 'upgrade'); @@ -153,5 +132,7 @@ if ($needUpgrade) { $tmpl->assign('isPublic', false); $tmpl->assign('publicUploadEnabled', $publicUploadEnabled); $tmpl->assign("encryptedFiles", \OCP\Util::encryptedFiles()); + $tmpl->assign('disableSharing', false); + $tmpl->assign('ajaxLoad', $ajaxLoad); $tmpl->printPage(); } diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 970aad1f978..6a53bebfcc0 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -1,155 +1,196 @@ -$(document).ready(function() { - var file_upload_param = { - dropZone: $('#content'), // restrict dropZone to content div - //singleFileUploads is on by default, so the data.files array will always have length 1 - add: function(e, data) { +/** + * Function that will allow us to know if Ajax uploads are supported + * @link https://github.com/New-Bamboo/example-ajax-upload/blob/master/public/index.html + * also see article @link http://blog.new-bamboo.co.uk/2012/01/10/ridiculously-simple-ajax-uploads-with-formdata + */ +function supportAjaxUploadWithProgress() { + return supportFileAPI() && supportAjaxUploadProgressEvents() && supportFormData(); - if(data.files[0].type === '' && data.files[0].size == 4096) - { - data.textStatus = 'dirorzero'; - data.errorThrown = t('files','Unable to upload your file as it is a directory or has 0 bytes'); - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - return true; //don't upload this file but go on with next in queue - } + // Is the File API supported? + function supportFileAPI() { + var fi = document.createElement('INPUT'); + fi.type = 'file'; + return 'files' in fi; + }; - var totalSize=0; - $.each(data.originalFiles, function(i,file){ - totalSize+=file.size; - }); + // Are progress events supported? + function supportAjaxUploadProgressEvents() { + var xhr = new XMLHttpRequest(); + return !! (xhr && ('upload' in xhr) && ('onprogress' in xhr.upload)); + }; - if(totalSize>$('#max_upload').val()){ - data.textStatus = 'notenoughspace'; - data.errorThrown = t('files','Not enough space available'); - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - return false; //don't upload anything - } + // Is FormData supported? + function supportFormData() { + return !! window.FormData; + } +} + +$(document).ready(function() { - // start the actual file upload - var jqXHR = data.submit(); + if ( $('#file_upload_start').length ) { + var file_upload_param = { + dropZone: $('#content'), // restrict dropZone to content div + //singleFileUploads is on by default, so the data.files array will always have length 1 + add: function(e, data) { - // remember jqXHR to show warning to user when he navigates away but an upload is still in progress - if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { - var dirName = data.context.data('file'); - if(typeof uploadingFiles[dirName] === 'undefined') { - uploadingFiles[dirName] = {}; + if(data.files[0].type === '' && data.files[0].size == 4096) + { + data.textStatus = 'dirorzero'; + data.errorThrown = t('files','Unable to upload your file as it is a directory or has 0 bytes'); + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + return true; //don't upload this file but go on with next in queue } - uploadingFiles[dirName][data.files[0].name] = jqXHR; - } else { - uploadingFiles[data.files[0].name] = jqXHR; - } - //show cancel button - if($('html.lte9').length === 0 && data.dataType !== 'iframe') { - $('#uploadprogresswrapper input.stop').show(); - } - }, - /** - * called after the first add, does NOT have the data param - * @param e - */ - start: function(e) { - //IE < 10 does not fire the necessary events for the progress bar. - if($('html.lte9').length > 0) { - return; - } - $('#uploadprogressbar').progressbar({value:0}); - $('#uploadprogressbar').fadeIn(); - }, - fail: function(e, data) { - if (typeof data.textStatus !== 'undefined' && data.textStatus !== 'success' ) { - if (data.textStatus === 'abort') { - $('#notification').text(t('files', 'Upload cancelled.')); - } else { - // HTTP connection problem - $('#notification').text(data.errorThrown); + var totalSize=0; + $.each(data.originalFiles, function(i,file){ + totalSize+=file.size; + }); + + if(totalSize>$('#max_upload').val()){ + data.textStatus = 'notenoughspace'; + data.errorThrown = t('files','Not enough space available'); + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + return false; //don't upload anything } - $('#notification').fadeIn(); - //hide notification after 5 sec - setTimeout(function() { - $('#notification').fadeOut(); - }, 5000); - } - delete uploadingFiles[data.files[0].name]; - }, - progress: function(e, data) { - // TODO: show nice progress bar in file row - }, - progressall: function(e, data) { - //IE < 10 does not fire the necessary events for the progress bar. - if($('html.lte9').length > 0) { - return; - } - var progress = (data.loaded/data.total)*100; - $('#uploadprogressbar').progressbar('value',progress); - }, - /** - * called for every successful upload - * @param e - * @param data - */ - done:function(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); - if(typeof result[0] !== 'undefined' && result[0].status === 'success') { - var filename = result[0].originalname; + // start the actual file upload + var jqXHR = data.submit(); - // delete jqXHR reference + // remember jqXHR to show warning to user when he navigates away but an upload is still in progress if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { var dirName = data.context.data('file'); - delete uploadingFiles[dirName][filename]; - if ($.assocArraySize(uploadingFiles[dirName]) == 0) { - delete uploadingFiles[dirName]; + if(typeof uploadingFiles[dirName] === 'undefined') { + uploadingFiles[dirName] = {}; } + uploadingFiles[dirName][data.files[0].name] = jqXHR; } else { - delete uploadingFiles[filename]; + uploadingFiles[data.files[0].name] = jqXHR; } - var file = result[0]; - } else { - data.textStatus = 'servererror'; - data.errorThrown = t('files', result.data.message); - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - } - }, - /** - * called after last upload - * @param e - * @param data - */ - stop: function(e, data) { - if(data.dataType !== 'iframe') { - $('#uploadprogresswrapper input.stop').hide(); - } + }, + submit: function(e, data) { + if ( ! data.formData ) { + // noone set update parameters, we set the minimum + data.formData = { + requesttoken: oc_requesttoken, + dir: $('#dir').val() + }; + } + }, + /** + * called after the first add, does NOT have the data param + * @param e + */ + start: function(e) { + }, + fail: function(e, data) { + if (typeof data.textStatus !== 'undefined' && data.textStatus !== 'success' ) { + if (data.textStatus === 'abort') { + $('#notification').text(t('files', 'Upload cancelled.')); + } else { + // HTTP connection problem + $('#notification').text(data.errorThrown); + } + $('#notification').fadeIn(); + //hide notification after 5 sec + setTimeout(function() { + $('#notification').fadeOut(); + }, 5000); + } + delete uploadingFiles[data.files[0].name]; + }, + /** + * called for every successful upload + * @param e + * @param data + */ + done:function(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); + + if(typeof result[0] !== 'undefined' && result[0].status === 'success') { + var filename = result[0].originalname; - //IE < 10 does not fire the necessary events for the progress bar. - if($('html.lte9').length > 0) { - return; + // delete jqXHR reference + if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { + var dirName = data.context.data('file'); + delete uploadingFiles[dirName][filename]; + if ($.assocArraySize(uploadingFiles[dirName]) == 0) { + delete uploadingFiles[dirName]; + } + } else { + delete uploadingFiles[filename]; + } + var file = result[0]; + } else { + data.textStatus = 'servererror'; + data.errorThrown = t('files', result.data.message); + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + } + }, + /** + * called after last upload + * @param e + * @param data + */ + stop: function(e, data) { } + }; - $('#uploadprogressbar').progressbar('value',100); - $('#uploadprogressbar').fadeOut(); - } - }; - var file_upload_handler = function() { - $('#file_upload_start').fileupload(file_upload_param); - }; + // 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) { + //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) { + $('#uploadprogresswrapper input.stop').show(); + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); + }); + fileupload.on('fileuploadprogress', function(e, data) { + //TODO progressbar in row + }); + fileupload.on('fileuploadprogressall', function(e, data) { + var progress = (data.loaded / data.total) * 100; + $('#uploadprogressbar').progressbar('value', progress); + }); + fileupload.on('fileuploadstop', function(e, data) { + $('#uploadprogresswrapper input.stop').fadeOut(); + $('#uploadprogressbar').fadeOut(); + + }); + fileupload.on('fileuploadfail', function(e, data) { + //if user pressed cancel hide upload progress bar and cancel button + if (data.errorThrown === 'abort') { + $('#uploadprogresswrapper input.stop').fadeOut(); + $('#uploadprogressbar').fadeOut(); + } + }); - if ( document.getElementById('data-upload-form') ) { - $(file_upload_handler); + } else { + console.log('skipping file progress because your browser is broken'); + } } + $.assocArraySize = function(obj) { // http://stackoverflow.com/a/6700/11236 var size = 0, key; @@ -351,5 +392,4 @@ $(document).ready(function() { $('#new>a').click(); }); }); - window.file_upload_param = file_upload_param; }); diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 097fe521aa6..330fe86f6b3 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -196,13 +196,12 @@ FileActions.register('all', 'Rename', OC.PERMISSION_UPDATE, function () { FileList.rename(filename); }); - FileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename) { - var dir = $('#dir').val(); + var dir = $('#dir').val() || '/'; if (dir !== '/') { dir = dir + '/'; } - window.location = OC.linkTo('files', 'index.php') + '?dir=' + encodeURIComponent(dir + filename); + FileList.changeDirectory(dir + filename); }); FileActions.setDefault('dir', 'Open'); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 29be5e0d362..b50d46c98d3 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1,7 +1,28 @@ var FileList={ useUndo:true, + postProcessList: function(){ + $('#fileList tr').each(function(){ + //little hack to set unescape filenames in attribute + $(this).attr('data-file',decodeURIComponent($(this).attr('data-file'))); + }); + }, update:function(fileListHtml) { - $('#fileList').empty().html(fileListHtml); + var $fileList = $('#fileList'), + permissions = $('#permissions').val(), + isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; + $fileList.empty().html(fileListHtml); + $('#emptycontent').toggleClass('hidden', !isCreatable || $fileList.find('tr').length > 0); + $fileList.find('tr').each(function () { + FileActions.display($(this).children('td.filename')); + }); + $fileList.trigger(jQuery.Event("fileActionsReady")); + FileList.postProcessList(); + // "Files" might not be loaded in extending apps + if (window.Files){ + Files.setupDragAndDrop(); + } + FileList.updateFileSummary(); + $fileList.trigger(jQuery.Event("updated")); }, createRow:function(type, name, iconurl, linktarget, size, lastModified, permissions){ var td, simpleSize, basename, extension; @@ -134,20 +155,109 @@ var FileList={ FileActions.display(tr.find('td.filename')); return tr; }, - refresh:function(data) { - var result = jQuery.parseJSON(data.responseText); + /** + * @brief Changes the current directory and reload the file list. + * @param targetDir target directory (non URL encoded) + * @param changeUrl false if the URL must not be changed (defaults to true) + */ + changeDirectory: function(targetDir, changeUrl, force){ + var $dir = $('#dir'), + url, + currentDir = $dir.val() || '/'; + targetDir = targetDir || '/'; + if (!force && currentDir === targetDir){ + return; + } + FileList.setCurrentDir(targetDir, changeUrl); + FileList.reload(); + }, + linkTo: function(dir){ + return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); + }, + setCurrentDir: function(targetDir, changeUrl){ + $('#dir').val(targetDir); + if (changeUrl !== false){ + if (window.history.pushState && changeUrl !== false){ + url = FileList.linkTo(targetDir); + window.history.pushState({dir: targetDir}, '', url); + } + // use URL hash for IE8 + else{ + window.location.hash = '?dir='+ encodeURIComponent(targetDir).replace(/%2F/g, '/'); + } + } + }, + /** + * @brief Reloads the file list using ajax call + */ + reload: function(){ + FileList.showMask(); + if (FileList._reloadCall){ + FileList._reloadCall.abort(); + } + FileList._reloadCall = $.ajax({ + url: OC.filePath('files','ajax','list.php'), + data: { + dir : $('#dir').val(), + breadcrumb: true + }, + error: function(result){ + FileList.reloadCallback(result); + }, + success: function(result) { + FileList.reloadCallback(result); + } + }); + }, + reloadCallback: function(result){ + var $controls = $('#controls'); + + delete FileList._reloadCall; + FileList.hideMask(); + + if (!result || result.status === 'error') { + OC.Notification.show(result.data.message); + return; + } + + if (result.status === 404){ + // go back home + FileList.changeDirectory('/'); + return; + } + + if (result.data.permissions){ + FileList.setDirectoryPermissions(result.data.permissions); + } + if(typeof(result.data.breadcrumb) != 'undefined'){ - updateBreadcrumb(result.data.breadcrumb); + $controls.find('.crumb').remove(); + $controls.prepend(result.data.breadcrumb); + + var width = $(window).width(); + Files.initBreadCrumbs(); + Files.resizeBreadcrumbs(width, true); + + // in case svg is not supported by the browser we need to execute the fallback mechanism + if(!SVGSupport()) { + replaceSVG(); + } } + FileList.update(result.data.files); - resetFileActionPanel(); + }, + setDirectoryPermissions: function(permissions){ + var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; + $('#permissions').val(permissions); + $('.creatable').toggleClass('hidden', !isCreatable); + $('.notCreatable').toggleClass('hidden', isCreatable); }, remove:function(name){ $('tr').filterAttr('data-file',name).find('td.filename').draggable('destroy'); $('tr').filterAttr('data-file',name).remove(); FileList.updateFileSummary(); if($('tr[data-file]').length==0){ - $('#emptycontent').show(); + $('#emptycontent').removeClass('hidden'); } }, insertElement:function(name,type,element){ @@ -177,7 +287,7 @@ var FileList={ }else{ $('#fileList').append(element); } - $('#emptycontent').hide(); + $('#emptycontent').addClass('hidden'); FileList.updateFileSummary(); }, loadingDone:function(name, id){ @@ -508,6 +618,31 @@ var FileList={ $connector.show(); } } + }, + showMask: function(){ + // in case one was shown before + var $mask = $('#content .mask'); + if ($mask.length){ + return; + } + + $mask = $('<div class="mask transparent"></div>'); + + $mask.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); + $mask.css('background-repeat', 'no-repeat'); + $('#content').append($mask); + + // block UI, but only make visible in case loading takes longer + FileList._maskTimeout = window.setTimeout(function(){ + // reset opacity + $mask.removeClass('transparent'); + }, 250); + }, + hideMask: function(){ + var $mask = $('#content .mask').remove(); + if (FileList._maskTimeout){ + window.clearTimeout(FileList._maskTimeout); + } } }; @@ -629,8 +764,8 @@ $(document).ready(function(){ } // update folder size - var size = parseInt(data.context.data('size')); - size += parseInt(file.size) ; + var size = parseInt(data.context.data('size')); + size += parseInt(file.size); data.context.attr('data-size', size); data.context.find('td.filesize').text(humanFileSize(size)); @@ -710,5 +845,55 @@ $(document).ready(function(){ $(window).trigger('beforeunload'); }); + function parseHashQuery(){ + var hash = window.location.hash, + pos = hash.indexOf('?'), + query; + if (pos >= 0){ + return hash.substr(pos + 1); + } + return ''; + } + + function parseCurrentDirFromUrl(){ + var query = parseHashQuery(), + params, + dir = '/'; + // try and parse from URL hash first + if (query){ + params = OC.parseQueryString(query); + } + // else read from query attributes + if (!params){ + params = OC.parseQueryString(location.search); + } + return (params && params.dir) || '/'; + } + + // fallback to hashchange when no history support + if (!window.history.pushState){ + $(window).on('hashchange', function(){ + FileList.changeDirectory(parseCurrentDirFromUrl(), false); + }); + } + window.onpopstate = function(e){ + var targetDir; + if (e.state && e.state.dir){ + targetDir = e.state.dir; + } + else{ + // read from URL + targetDir = parseCurrentDirFromUrl(); + } + if (targetDir){ + FileList.changeDirectory(targetDir, false); + } + } + + if (parseInt($('#ajaxLoad').val(), 10) === 1){ + // need to initially switch the dir to the one from the hash (IE8) + FileList.changeDirectory(parseCurrentDirFromUrl(), false, true); + } + FileList.createFileSummary(); }); diff --git a/apps/files/js/files.js b/apps/files/js/files.js index d729077ea72..c2418cfa751 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -94,29 +94,106 @@ Files={ OC.Notification.show(t('files_encryption', 'Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files.')); return; } + }, + + setupDragAndDrop: function(){ + var $fileList = $('#fileList'); + + //drag/drop of files + $fileList.find('tr td.filename').each(function(i,e){ + if ($(e).parent().data('permissions') & OC.PERMISSION_DELETE) { + $(e).draggable(dragOptions); + } + }); + + $fileList.find('tr[data-type="dir"] td.filename').each(function(i,e){ + if ($(e).parent().data('permissions') & OC.PERMISSION_CREATE){ + $(e).droppable(folderDropOptions); + } + }); + }, + + lastWidth: 0, + + initBreadCrumbs: function () { + Files.lastWidth = 0; + Files.breadcrumbs = []; + + // initialize with some extra space + Files.breadcrumbsWidth = 64; + if ( document.getElementById("navigation") ) { + Files.breadcrumbsWidth += $('#navigation').get(0).offsetWidth; + } + Files.hiddenBreadcrumbs = 0; + + $.each($('.crumb'), function(index, breadcrumb) { + Files.breadcrumbs[index] = breadcrumb; + Files.breadcrumbsWidth += $(breadcrumb).get(0).offsetWidth; + }); + + $.each($('#controls .actions>div'), function(index, action) { + Files.breadcrumbsWidth += $(action).get(0).offsetWidth; + }); + + // event handlers for breadcrumb items + $('#controls .crumb a').on('click', onClickBreadcrumb); + }, + + resizeBreadcrumbs: function (width, firstRun) { + 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('<span>...</span>'); + Files.breadcrumbsWidth += $(Files.breadcrumbs[1]).get(0).offsetWidth; + Files.hiddenBreadcrumbs = 2; + } + var i = Files.hiddenBreadcrumbs; + while (width < Files.breadcrumbsWidth && i > 1 && i < Files.breadcrumbs.length - 1) { + Files.breadcrumbsWidth -= $(Files.breadcrumbs[i]).get(0).offsetWidth; + $(Files.breadcrumbs[i]).hide(); + Files.hiddenBreadcrumbs = i; + i++ + } + } else if (width > Files.lastWidth && Files.hiddenBreadcrumbs > 0) { + var i = Files.hiddenBreadcrumbs; + while (width > Files.breadcrumbsWidth && i > 0) { + if (Files.hiddenBreadcrumbs == 1) { + Files.breadcrumbsWidth -= $(Files.breadcrumbs[1]).get(0).offsetWidth; + $(Files.breadcrumbs[1]).find('span').remove(); + $(Files.breadcrumbs[1]).find('a').show(); + Files.breadcrumbsWidth += $(Files.breadcrumbs[1]).get(0).offsetWidth; + } else { + $(Files.breadcrumbs[i]).show(); + Files.breadcrumbsWidth += $(Files.breadcrumbs[i]).get(0).offsetWidth; + if (Files.breadcrumbsWidth > width) { + Files.breadcrumbsWidth -= $(Files.breadcrumbs[i]).get(0).offsetWidth; + $(Files.breadcrumbs[i]).hide(); + break; + } + } + i--; + Files.hiddenBreadcrumbs = i; + } + } + Files.lastWidth = width; + } } }; $(document).ready(function() { + // FIXME: workaround for trashbin app + if (window.trashBinApp){ + return; + } Files.displayEncryptionWarning(); Files.bindKeyboardShortcuts(document, jQuery); - $('#fileList tr').each(function(){ - //little hack to set unescape filenames in attribute - $(this).attr('data-file',decodeURIComponent($(this).attr('data-file'))); - }); + + FileList.postProcessList(); + Files.setupDragAndDrop(); $('#file_action_panel').attr('activeAction', false); - //drag/drop of files - $('#fileList tr td.filename').each(function(i,e){ - if ($(e).parent().data('permissions') & OC.PERMISSION_DELETE) { - $(e).draggable(dragOptions); - } - }); - $('#fileList tr[data-type="dir"] td.filename').each(function(i,e){ - if ($(e).parent().data('permissions') & OC.PERMISSION_CREATE){ - $(e).droppable(folderDropOptions); - } - }); $('div.crumb:not(.last)').droppable(crumbDropOptions); $('ul#apps>li:first-child').data('dir',''); if($('div.crumb').length){ @@ -268,72 +345,15 @@ $(document).ready(function() { //do a background scan if needed scanFiles(); - var lastWidth = 0; - var breadcrumbs = []; - var breadcrumbsWidth = 0; - if ( document.getElementById("navigation") ) { - breadcrumbsWidth = $('#navigation').get(0).offsetWidth; - } - var hiddenBreadcrumbs = 0; - - $.each($('.crumb'), function(index, breadcrumb) { - breadcrumbs[index] = breadcrumb; - breadcrumbsWidth += $(breadcrumb).get(0).offsetWidth; - }); - - - $.each($('#controls .actions>div'), function(index, action) { - breadcrumbsWidth += $(action).get(0).offsetWidth; - }); - - function resizeBreadcrumbs(firstRun) { - var width = $(this).width(); - if (width != lastWidth) { - if ((width < lastWidth || firstRun) && width < breadcrumbsWidth) { - if (hiddenBreadcrumbs == 0) { - breadcrumbsWidth -= $(breadcrumbs[1]).get(0).offsetWidth; - $(breadcrumbs[1]).find('a').hide(); - $(breadcrumbs[1]).append('<span>...</span>'); - breadcrumbsWidth += $(breadcrumbs[1]).get(0).offsetWidth; - hiddenBreadcrumbs = 2; - } - var i = hiddenBreadcrumbs; - while (width < breadcrumbsWidth && i > 1 && i < breadcrumbs.length - 1) { - breadcrumbsWidth -= $(breadcrumbs[i]).get(0).offsetWidth; - $(breadcrumbs[i]).hide(); - hiddenBreadcrumbs = i; - i++ - } - } else if (width > lastWidth && hiddenBreadcrumbs > 0) { - var i = hiddenBreadcrumbs; - while (width > breadcrumbsWidth && i > 0) { - if (hiddenBreadcrumbs == 1) { - breadcrumbsWidth -= $(breadcrumbs[1]).get(0).offsetWidth; - $(breadcrumbs[1]).find('span').remove(); - $(breadcrumbs[1]).find('a').show(); - breadcrumbsWidth += $(breadcrumbs[1]).get(0).offsetWidth; - } else { - $(breadcrumbs[i]).show(); - breadcrumbsWidth += $(breadcrumbs[i]).get(0).offsetWidth; - if (breadcrumbsWidth > width) { - breadcrumbsWidth -= $(breadcrumbs[i]).get(0).offsetWidth; - $(breadcrumbs[i]).hide(); - break; - } - } - i--; - hiddenBreadcrumbs = i; - } - } - lastWidth = width; - } - } + Files.initBreadCrumbs(); $(window).resize(function() { - resizeBreadcrumbs(false); + var width = $(this).width(); + Files.resizeBreadcrumbs(width, false); }); - resizeBreadcrumbs(true); + var width = $(this).width(); + Files.resizeBreadcrumbs(width, true); // display storage warnings setTimeout ( "Files.displayStorageWarnings()", 100 ); @@ -415,10 +435,6 @@ function boolOperationFinished(data, callback) { } } -function updateBreadcrumb(breadcrumbHtml) { - $('p.nav').empty().html(breadcrumbHtml); -} - var createDragShadow = function(event){ //select dragged file var isDragSelected = $(event.target).parents('tr').find('td input:first').prop('checked'); @@ -681,3 +697,9 @@ function checkTrashStatus() { } }); } + +function onClickBreadcrumb(e){ + var $el = $(e.target).closest('.crumb'); + e.preventDefault(); + FileList.changeDirectory(decodeURIComponent($el.data('dir'))); +} diff --git a/apps/files/l10n/lt_LT.php b/apps/files/l10n/lt_LT.php index 0530adc2ae2..83ed8e8688f 100644 --- a/apps/files/l10n/lt_LT.php +++ b/apps/files/l10n/lt_LT.php @@ -2,6 +2,8 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Nepavyko perkelti %s - failas su tokiu pavadinimu jau egzistuoja", "Could not move %s" => "Nepavyko perkelti %s", +"Unable to set upload directory." => "Nepavyksta nustatyti įkėlimų katalogo.", +"Invalid Token" => "Netinkamas ženklas", "No file was uploaded. Unknown error" => "Failai nebuvo įkelti dėl nežinomos priežasties", "There is no error, the file uploaded with success" => "Failas įkeltas sėkmingai, be klaidų", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Įkeliamas failas yra didesnis nei leidžia upload_max_filesize php.ini faile:", @@ -31,19 +33,22 @@ $TRANSLATIONS = array( "cancel" => "atšaukti", "replaced {new_name} with {old_name}" => "pakeiskite {new_name} į {old_name}", "undo" => "anuliuoti", -"_%n folder_::_%n folders_" => array("","",""), -"_%n file_::_%n files_" => array("","",""), -"_Uploading %n file_::_Uploading %n files_" => array("","",""), +"_%n folder_::_%n folders_" => array("%n aplankas","%n aplankai","%n aplankų"), +"_%n file_::_%n files_" => array("%n failas","%n failai","%n failų"), +"{dirs} and {files}" => "{dirs} ir {files}", +"_Uploading %n file_::_Uploading %n files_" => array("Įkeliamas %n failas","Įkeliami %n failai","Įkeliama %n failų"), "files uploading" => "įkeliami failai", "'.' is an invalid file name." => "'.' yra neleidžiamas failo pavadinime.", "File name cannot be empty." => "Failo pavadinimas negali būti tuščias.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Neleistinas pavadinimas, '\\', '/', '<', '>', ':', '\"', '|', '?' ir '*' yra neleidžiami.", "Your storage is full, files can not be updated or synced anymore!" => "Jūsų visa vieta serveryje užimta", "Your storage is almost full ({usedSpacePercent}%)" => "Jūsų vieta serveryje beveik visa užimta ({usedSpacePercent}%)", +"Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Šifravimas buvo išjungtas, bet Jūsų failai vis dar užšifruoti. Prašome eiti į asmeninius nustatymus ir iššifruoti savo failus.", "Your download is being prepared. This might take some time if the files are big." => "Jūsų atsisiuntimas yra paruošiamas. tai gali užtrukti jei atsisiunčiamas didelis failas.", "Name" => "Pavadinimas", "Size" => "Dydis", "Modified" => "Pakeista", +"%s could not be renamed" => "%s negali būti pervadintas", "Upload" => "Įkelti", "File handling" => "Failų tvarkymas", "Maximum upload size" => "Maksimalus įkeliamo failo dydis", diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php index 7135ef9f656..3c13b8ea6e2 100644 --- a/apps/files/lib/helper.php +++ b/apps/files/lib/helper.php @@ -17,4 +17,120 @@ class Helper 'maxHumanFilesize' => $maxHumanFilesize, 'usedSpacePercent' => (int)$storageInfo['relative']); } + + public static function determineIcon($file) { + if($file['type'] === 'dir') { + $dir = $file['directory']; + $absPath = \OC\Files\Filesystem::getView()->getAbsolutePath($dir.'/'.$file['name']); + $mount = \OC\Files\Filesystem::getMountManager()->find($absPath); + if (!is_null($mount)) { + $sid = $mount->getStorageId(); + if (!is_null($sid)) { + $sid = explode(':', $sid); + if ($sid[0] === 'shared') { + return \OC_Helper::mimetypeIcon('dir-shared'); + } + if ($sid[0] !== 'local') { + return \OC_Helper::mimetypeIcon('dir-external'); + } + } + } + return \OC_Helper::mimetypeIcon('dir'); + } + + if($file['isPreviewAvailable']) { + $relativePath = substr($file['path'], 6); + return \OC_Helper::previewIcon($relativePath); + } + return \OC_Helper::mimetypeIcon($file['mimetype']); + } + + /** + * Comparator function to sort files alphabetically and have + * the directories appear first + * @param array $a file + * @param array $b file + * @return -1 if $a must come before $b, 1 otherwise + */ + public static function fileCmp($a, $b) { + if ($a['type'] === 'dir' and $b['type'] !== 'dir') { + return -1; + } elseif ($a['type'] !== 'dir' and $b['type'] === 'dir') { + return 1; + } else { + return strnatcasecmp($a['name'], $b['name']); + } + } + + /** + * Retrieves the contents of the given directory and + * returns it as a sorted array. + * @param string $dir path to the directory + * @return array of files + */ + public static function getFiles($dir) { + $content = \OC\Files\Filesystem::getDirectoryContent($dir); + $files = array(); + + foreach ($content as $i) { + $i['date'] = \OCP\Util::formatDate($i['mtime']); + if ($i['type'] === 'file') { + $fileinfo = pathinfo($i['name']); + $i['basename'] = $fileinfo['filename']; + if (!empty($fileinfo['extension'])) { + $i['extension'] = '.' . $fileinfo['extension']; + } else { + $i['extension'] = ''; + } + } + $i['directory'] = $dir; + $i['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($i['mimetype']); + $i['icon'] = \OCA\files\lib\Helper::determineIcon($i); + $files[] = $i; + } + + usort($files, array('\OCA\files\lib\Helper', 'fileCmp')); + + return $files; + } + + /** + * Splits the given path into a breadcrumb structure. + * @param string $dir path to process + * @return array where each entry is a hash of the absolute + * directory path and its name + */ + public static function makeBreadcrumb($dir){ + $breadcrumb = array(); + $pathtohere = ''; + foreach (explode('/', $dir) as $i) { + if ($i !== '') { + $pathtohere .= '/' . $i; + $breadcrumb[] = array('dir' => $pathtohere, 'name' => $i); + } + } + return $breadcrumb; + } + + /** + * Returns the numeric permissions for the given directory. + * @param string $dir directory without trailing slash + * @return numeric permissions + */ + public static function getDirPermissions($dir){ + $permissions = \OCP\PERMISSION_READ; + if (\OC\Files\Filesystem::isCreatable($dir . '/')) { + $permissions |= \OCP\PERMISSION_CREATE; + } + if (\OC\Files\Filesystem::isUpdatable($dir . '/')) { + $permissions |= \OCP\PERMISSION_UPDATE; + } + if (\OC\Files\Filesystem::isDeletable($dir . '/')) { + $permissions |= \OCP\PERMISSION_DELETE; + } + if (\OC\Files\Filesystem::isSharable($dir . '/')) { + $permissions |= \OCP\PERMISSION_SHARE; + } + return $permissions; + } } diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index 29cb457cd5a..bd991c3fcb0 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -1,8 +1,7 @@ <!--[if IE 8]><style>input[type="checkbox"]{padding:0;}table td{position:static !important;}</style><![endif]--> <div id="controls"> <?php print_unescaped($_['breadcrumb']); ?> - <?php if ($_['isCreatable']):?> - <div class="actions <?php if (isset($_['files']) and count($_['files'])==0):?>emptyfolder<?php endif; ?>"> + <div class="actions creatable <?php if (!$_['isCreatable']):?>hidden<?php endif; ?> <?php if (isset($_['files']) and count($_['files'])==0):?>emptycontent<?php endif; ?>"> <div id="new" class="button"> <a><?php p($l->t('New'));?></a> <ul> @@ -16,29 +15,23 @@ </div> <div id="upload" class="button" title="<?php p($l->t('Upload') . ' max. '.$_['uploadMaxHumanFilesize']) ?>"> - <form data-upload-id='1' - id="data-upload-form" - class="file_upload_form" - action="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" - method="post" - enctype="multipart/form-data" - target="file_upload_target_1"> <?php if($_['uploadMaxFilesize'] >= 0):?> <input type="hidden" name="MAX_FILE_SIZE" id="max_upload" value="<?php p($_['uploadMaxFilesize']) ?>"> <?php endif;?> <!-- Send the requesttoken, this is needed for older IE versions because they don't send the CSRF token via HTTP header in this case --> - <input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>" id="requesttoken"> <input type="hidden" class="max_human_file_size" value="(max <?php p($_['uploadMaxHumanFilesize']); ?>)"> <input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir"> - <input type="file" id="file_upload_start" name='files[]'/> + <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> - </form> </div> <?php if ($_['trash'] ): ?> - <input id="trash" type="button" value="<?php p($l->t('Deleted files'));?>" class="button" <?php $_['trashEmpty'] ? p('disabled') : '' ?>></input> + <div id="trash" class="button" <?php $_['trashEmpty'] ? p('disabled') : '' ?>> + <a><?php p($l->t('Deleted files'));?></a> + </div> <?php endif; ?> <div id="uploadprogresswrapper"> <div id="uploadprogressbar"></div> @@ -48,16 +41,15 @@ </div> </div> <div id="file_action_panel"></div> - <?php elseif( !$_['isPublic'] ):?> - <div class="actions"><input type="button" disabled value="<?php p($l->t('You don’t have write permissions here.'))?>"></div> - <input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir"> - <?php endif;?> + <div class="notCreatable notPublic <?php if ($_['isCreatable'] or $_['isPublic'] ):?>hidden<?php endif; ?>"> + <div class="actions"><input type="button" disabled value="<?php p($l->t('You don’t have write permissions here.'))?>"></div> + </div> <input type="hidden" name="permissions" value="<?php p($_['permissions']); ?>" id="permissions"> </div> -<?php if (isset($_['files']) and $_['isCreatable'] and count($_['files'])==0):?> - <div id="emptycontent"><?php p($l->t('Nothing in here. Upload something!'))?></div> -<?php endif; ?> +<div id="emptycontent" <?php if (!isset($_['files']) or !$_['isCreatable'] or count($_['files']) > 0 or !$_['ajaxLoad']):?>class="hidden"<?php endif; ?>><?php p($l->t('Nothing in here. Upload something!'))?></div> + +<input type="hidden" id="disableSharing" data-status="<?php p($_['disableSharing']); ?>"></input> <table id="filestable" data-allow-public-upload="<?php p($_['publicUploadEnabled'])?>" data-preview-x="36" data-preview-y="36"> <thead> @@ -82,7 +74,7 @@ <th id="headerDate"> <span id="modified"><?php p($l->t( 'Modified' )); ?></span> <?php if ($_['permissions'] & OCP\PERMISSION_DELETE): ?> -<!-- NOTE: Temporary fix to allow unsharing of files in root of Shared folder --> +<!-- NOTE: Temporary fix to allow unsharing of files in root of Shared folder --> <?php if ($_['dir'] == '/Shared'): ?> <span class="selectedActions"><a href="" class="delete-selected"> <?php p($l->t('Unshare'))?> @@ -120,6 +112,7 @@ </div> <!-- config hints for javascript --> +<input type="hidden" name="ajaxLoad" id="ajaxLoad" value="<?php p($_['ajaxLoad']); ?>" /> <input type="hidden" name="allowZipDownload" id="allowZipDownload" value="<?php p($_['allowZipDownload']); ?>" /> <input type="hidden" name="usedSpacePercent" id="usedSpacePercent" value="<?php p($_['usedSpacePercent']); ?>" /> <input type="hidden" name="encryptedFiles" id="encryptedFiles" value="<?php $_['encryptedFiles'] ? p('1') : p('0'); ?>" /> diff --git a/apps/files/templates/part.list.php b/apps/files/templates/part.list.php index 4076c1bb331..1e4d4d11c98 100644 --- a/apps/files/templates/part.list.php +++ b/apps/files/templates/part.list.php @@ -1,7 +1,7 @@ -<input type="hidden" id="disableSharing" data-status="<?php p($_['disableSharing']); ?>"> +<?php $totalfiles = 0; +$totaldirs = 0; +$totalsize = 0; ?> <?php foreach($_['files'] as $file): - //strlen('files/') => 6 - $relativePath = substr($file['path'], 6); // the bigger the file, the darker the shade of grey; megabytes*2 $simple_size_color = intval(160-$file['size']/(1024*1024)*2); if($simple_size_color<0) $simple_size_color = 0; @@ -22,26 +22,7 @@ <?php else: ?> <td class="filename svg" <?php endif; ?> - <?php if($file['type'] == 'dir'): ?> - style="background-image:url(<?php print_unescaped(OCP\mimetype_icon('dir')); ?>)" - <?php else: ?> - <?php if($_['isPublic']): ?> - <?php - $relativePath = substr($relativePath, strlen($_['sharingroot'])); - ?> - <?php if($file['isPreviewAvailable']): ?> - style="background-image:url(<?php print_unescaped(OCP\publicPreview_icon($relativePath, $_['sharingtoken'])); ?>)" - <?php else: ?> - style="background-image:url(<?php print_unescaped(OCP\mimetype_icon($file['mimetype'])); ?>)" - <?php endif; ?> - <?php else: ?> - <?php if($file['isPreviewAvailable']): ?> - style="background-image:url(<?php print_unescaped(OCP\preview_icon($relativePath)); ?>)" - <?php else: ?> - style="background-image:url(<?php print_unescaped(OCP\mimetype_icon($file['mimetype'])); ?>)" - <?php endif; ?> - <?php endif; ?> - <?php endif; ?> + style="background-image:url(<?php print_unescaped($file['icon']); ?>)" > <?php if(!isset($_['readonly']) || !$_['readonly']): ?> <input id="select-<?php p($file['fileid']); ?>" type="checkbox" /> diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 90a9984e27f..5b62b84e223 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -25,7 +25,9 @@ if (!OC_Config::getValue('maintenance', false)) { // App manager related hooks OCA\Encryption\Helper::registerAppHooks(); - stream_wrapper_register('crypt', 'OCA\Encryption\Stream'); + if(!in_array('crypt', stream_get_wrappers())) { + stream_wrapper_register('crypt', 'OCA\Encryption\Stream'); + } // check if we are logged in if (OCP\User::isLoggedIn()) { diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 85169e6a1d0..d9221c6e828 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -44,17 +44,22 @@ class Hooks { \OC_Util::setupFS($params['uid']);
}
- $util = new Util($view, $params['uid']);
-
- //check if all requirements are met
- if(!$util->ready() && (!Helper::checkRequirements() || !Helper::checkConfiguration())) {
- $error_msg = $l->t("Missing requirements.");
- $hint = $l->t('Please make sure that PHP 5.3.3 or newer is installed and that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled.');
- \OC_App::disable('files_encryption');
- \OCP\Util::writeLog('Encryption library', $error_msg . ' ' . $hint, \OCP\Util::ERROR);
- \OCP\Template::printErrorPage($error_msg, $hint);
+ $privateKey = \OCA\Encryption\Keymanager::getPrivateKey($view, $params['uid']);
+
+ // if no private key exists, check server configuration
+ if(!$privateKey) {
+ //check if all requirements are met
+ if(!Helper::checkRequirements() || !Helper::checkConfiguration()) {
+ $error_msg = $l->t("Missing requirements.");
+ $hint = $l->t('Please make sure that PHP 5.3.3 or newer is installed and that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled.');
+ \OC_App::disable('files_encryption');
+ \OCP\Util::writeLog('Encryption library', $error_msg . ' ' . $hint, \OCP\Util::ERROR);
+ \OCP\Template::printErrorPage($error_msg, $hint);
+ }
}
+ $util = new Util($view, $params['uid']);
+
// setup user, if user not ready force relogin
if (Helper::setupUser($util, $params['password']) === false) {
return false;
@@ -73,7 +78,7 @@ class Hooks { $userView = new \OC_FilesystemView('/' . $params['uid']);
- // Set legacy encryption key if it exists, to support
+ // Set legacy encryption key if it exists, to support
// depreciated encryption system
if (
$userView->file_exists('encryption.key')
@@ -249,7 +254,7 @@ class Hooks { $params['run'] = false;
$params['error'] = $l->t('Following users are not set up for encryption:') . ' ' . join(', ' , $notConfigured);
}
-
+
}
/**
@@ -260,7 +265,7 @@ class Hooks { // NOTE: $params has keys:
// [itemType] => file
// itemSource -> int, filecache file ID
- // [parent] =>
+ // [parent] =>
// [itemTarget] => /13
// shareWith -> string, uid of user being shared to
// fileTarget -> path of file being shared
@@ -301,13 +306,13 @@ class Hooks { // NOTE: parent is folder but shared was a file!
// we try to rebuild the missing path
// some examples we face here
- // user1 share folder1 with user2 folder1 has
- // the following structure
+ // user1 share folder1 with user2 folder1 has
+ // the following structure
// /folder1/subfolder1/subsubfolder1/somefile.txt
// user2 re-share subfolder2 with user3
// user3 re-share somefile.txt user4
- // so our path should be
- // /Shared/subfolder1/subsubfolder1/somefile.txt
+ // so our path should be
+ // /Shared/subfolder1/subsubfolder1/somefile.txt
// while user3 is sharing
if ($params['itemType'] === 'file') {
diff --git a/apps/files_encryption/l10n/lt_LT.php b/apps/files_encryption/l10n/lt_LT.php index 9fbf7b29604..4ededb716f4 100644 --- a/apps/files_encryption/l10n/lt_LT.php +++ b/apps/files_encryption/l10n/lt_LT.php @@ -6,12 +6,34 @@ $TRANSLATIONS = array( "Could not disable recovery key. Please check your recovery key password!" => "Neišėjo išjungti jūsų atkūrimo rakto. Prašome jį patikrinti!", "Password successfully changed." => "Slaptažodis sėkmingai pakeistas", "Could not change the password. Maybe the old password was not correct." => "Slaptažodis nebuvo pakeistas. Gali būti, kad buvo neteisingai suvestas senasis.", +"Private key password successfully updated." => "Privataus rakto slaptažodis buvo sėkmingai atnaujintas.", +"Could not update the private key password. Maybe the old password was not correct." => "Nepavyko atnaujinti privataus rakto slaptažodžio. Gali būti, kad buvo neteisingai suvestas senasis.", +"Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "Jūsų privatus raktas yra netinkamas! Panašu, kad Jūsų slaptažodis buvo pakeistas išorėje ownCloud sistemos (pvz. Jūsų organizacijos kataloge). Galite atnaujinti savo privataus rakto slaptažodį savo asmeniniuose nustatymuose, kad atkurti prieigą prie savo šifruotų failų.", +"Missing requirements." => "Trūkstami laukai.", +"Please make sure that PHP 5.3.3 or newer is installed and that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Prašome įsitikinti, kad PHP 5.3.3 ar naujesnė yra įdiegta ir kad OpenSSL kartu su PHP plėtiniu yra šjungti ir teisingai sukonfigūruoti. Kol kas šifravimo programa bus išjungta.", +"Following users are not set up for encryption:" => "Sekantys naudotojai nenustatyti šifravimui:", "Saving..." => "Saugoma...", +"Your private key is not valid! Maybe the your password was changed from outside." => "Jūsų privatus raktas yra netinkamas! Galbūt Jūsų slaptažodis buvo pakeistas iš išorės?", +"You can unlock your private key in your " => "Galite atrakinti savo privatų raktą savo", +"personal settings" => "asmeniniai nustatymai", "Encryption" => "Šifravimas", +"Enable recovery key (allow to recover users files in case of password loss):" => "Įjunkite atkūrimo raktą, (leisti atkurti naudotojų failus praradus slaptažodį):", +"Recovery key password" => "Atkūrimo rakto slaptažodis", "Enabled" => "Įjungta", "Disabled" => "Išjungta", +"Change recovery key password:" => "Pakeisti atkūrimo rakto slaptažodį:", +"Old Recovery key password" => "Senas atkūrimo rakto slaptažodis", +"New Recovery key password" => "Naujas atkūrimo rakto slaptažodis", "Change Password" => "Pakeisti slaptažodį", -"File recovery settings updated" => "Failų atstatymo nustatymai pakeisti", +"Your private key password no longer match your log-in password:" => "Privatus rakto slaptažodis daugiau neatitinka Jūsų prisijungimo slaptažodžio:", +"Set your old private key password to your current log-in password." => "Nustatyti Jūsų privataus rakto slaptažodį į Jūsų dabartinį prisijungimo.", +" If you don't remember your old password you can ask your administrator to recover your files." => "Jei nepamenate savo seno slaptažodžio, galite paprašyti administratoriaus atkurti Jūsų failus.", +"Old log-in password" => "Senas prisijungimo slaptažodis", +"Current log-in password" => "Dabartinis prisijungimo slaptažodis", +"Update Private Key Password" => "Atnaujinti privataus rakto slaptažodį", +"Enable password recovery:" => "Įjungti slaptažodžio atkūrimą:", +"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "Įjungus šią funkciją jums bus suteiktas pakartotinis priėjimas prie Jūsų šifruotų failų pamiršus slaptažodį.", +"File recovery settings updated" => "Failų atkūrimo nustatymai pakeisti", "Could not update file recovery" => "Neišėjo atnaujinti failų atkūrimo" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/apps/files_encryption/l10n/uk.php b/apps/files_encryption/l10n/uk.php index 680beddfe68..e4fb053a71a 100644 --- a/apps/files_encryption/l10n/uk.php +++ b/apps/files_encryption/l10n/uk.php @@ -1,6 +1,7 @@ <?php $TRANSLATIONS = array( "Saving..." => "Зберігаю...", -"Encryption" => "Шифрування" +"Encryption" => "Шифрування", +"Change Password" => "Змінити Пароль" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index cd4db05fb9b..df4d35cab0b 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -201,10 +201,11 @@ class Util { if (false === $this->recoveryEnabledForUser()) { // create database configuration - $sql = 'INSERT INTO `*PREFIX*encryption` (`uid`,`mode`,`recovery_enabled`) VALUES (?,?,?)'; + $sql = 'INSERT INTO `*PREFIX*encryption` (`uid`,`mode`,`recovery_enabled`,`migration_status`) VALUES (?,?,?,?)'; $args = array( $this->userId, 'server-side', + 0, 0 ); $query = \OCP\DB::prepare($sql); @@ -329,72 +330,73 @@ class Util { $this->view->is_dir($directory) && $handle = $this->view->opendir($directory) ) { - - while (false !== ($file = readdir($handle))) { - - if ( - $file !== "." - && $file !== ".." - ) { - - $filePath = $directory . '/' . $this->view->getRelativePath('/' . $file); - $relPath = \OCA\Encryption\Helper::stripUserFilesPath($filePath); - - // If the path is a directory, search - // its contents - if ($this->view->is_dir($filePath)) { - - $this->findEncFiles($filePath, $found); - - // If the path is a file, determine - // its encryption status - } elseif ($this->view->is_file($filePath)) { - - // Disable proxies again, some- - // where they got re-enabled :/ - \OC_FileProxy::$enabled = false; - - $isEncryptedPath = $this->isEncryptedPath($filePath); - // If the file is encrypted - // NOTE: If the userId is - // empty or not set, file will - // detected as plain - // NOTE: This is inefficient; - // scanning every file like this - // will eat server resources :( - if ( - Keymanager::getFileKey($this->view, $this->userId, $relPath) - && $isEncryptedPath - ) { - - $found['encrypted'][] = array( - 'name' => $file, - 'path' => $filePath - ); - - // If the file uses old - // encryption system - } elseif (Crypt::isLegacyEncryptedContent($isEncryptedPath, $relPath)) { - - $found['legacy'][] = array( - 'name' => $file, - 'path' => $filePath - ); - - // If the file is not encrypted - } else { - - $found['plain'][] = array( - 'name' => $file, - 'path' => $relPath - ); + if(is_resource($handle)) { + while (false !== ($file = readdir($handle))) { + + if ( + $file !== "." + && $file !== ".." + ) { + + $filePath = $directory . '/' . $this->view->getRelativePath('/' . $file); + $relPath = \OCA\Encryption\Helper::stripUserFilesPath($filePath); + + // If the path is a directory, search + // its contents + if ($this->view->is_dir($filePath)) { + + $this->findEncFiles($filePath, $found); + + // If the path is a file, determine + // its encryption status + } elseif ($this->view->is_file($filePath)) { + + // Disable proxies again, some- + // where they got re-enabled :/ + \OC_FileProxy::$enabled = false; + + $isEncryptedPath = $this->isEncryptedPath($filePath); + // If the file is encrypted + // NOTE: If the userId is + // empty or not set, file will + // detected as plain + // NOTE: This is inefficient; + // scanning every file like this + // will eat server resources :( + if ( + Keymanager::getFileKey($this->view, $this->userId, $relPath) + && $isEncryptedPath + ) { + + $found['encrypted'][] = array( + 'name' => $file, + 'path' => $filePath + ); + + // If the file uses old + // encryption system + } elseif (Crypt::isLegacyEncryptedContent($isEncryptedPath, $relPath)) { + + $found['legacy'][] = array( + 'name' => $file, + 'path' => $filePath + ); + + // If the file is not encrypted + } else { + + $found['plain'][] = array( + 'name' => $file, + 'path' => $relPath + ); + + } } } } - } \OC_FileProxy::$enabled = true; diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 2d7bcd4ac37..c08a266b48c 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -183,17 +183,20 @@ class AmazonS3 extends \OC\Files\Storage\Common { } $dh = $this->opendir($path); - while (($file = readdir($dh)) !== false) { - if ($file === '.' || $file === '..') { - continue; - } - if ($this->is_dir($path . '/' . $file)) { - $this->rmdir($path . '/' . $file); - } else { - $this->unlink($path . '/' . $file); + if(is_resource($dh)) { + while (($file = readdir($dh)) !== false) { + if ($file === '.' || $file === '..') { + continue; + } + + if ($this->is_dir($path . '/' . $file)) { + $this->rmdir($path . '/' . $file); + } else { + $this->unlink($path . '/' . $file); + } } - } + } try { $result = $this->connection->deleteObject(array( @@ -464,15 +467,17 @@ class AmazonS3 extends \OC\Files\Storage\Common { } $dh = $this->opendir($path1); - while (($file = readdir($dh)) !== false) { - if ($file === '.' || $file === '..') { - continue; + if(is_resource($dh)) { + while (($file = readdir($dh)) !== false) { + if ($file === '.' || $file === '..') { + continue; + } + + $source = $path1 . '/' . $file; + $target = $path2 . '/' . $file; + $this->copy($source, $target); } - - $source = $path1 . '/' . $file; - $target = $path2 . '/' . $file; - $this->copy($source, $target); - } + } } return true; diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index 1935740cd2e..659959e662e 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -378,7 +378,7 @@ class OC_Mount_Config { } $result = array(); $handle = opendir($path); - if ( ! $handle) { + if(!is_resource($handle)) { return array(); } while (false !== ($file = readdir($handle))) { diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php index 215bdcda6c2..b63b5885de1 100644 --- a/apps/files_external/lib/google.php +++ b/apps/files_external/lib/google.php @@ -206,14 +206,16 @@ class Google extends \OC\Files\Storage\Common { public function rmdir($path) { if (trim($path, '/') === '') { $dir = $this->opendir($path); - while (($file = readdir($dh)) !== false) { - if (!\OC\Files\Filesystem::isIgnoredDir($file)) { - if (!$this->unlink($path.'/'.$file)) { - return false; + if(is_resource($dir)) { + while (($file = readdir($dir)) !== false) { + if (!\OC\Files\Filesystem::isIgnoredDir($file)) { + if (!$this->unlink($path.'/'.$file)) { + return false; + } } } + closedir($dir); } - closedir($dir); $this->driveFiles = array(); return true; } else { diff --git a/apps/files_external/lib/irods.php b/apps/files_external/lib/irods.php index b8191db2f2e..6d4f66e856e 100644 --- a/apps/files_external/lib/irods.php +++ b/apps/files_external/lib/irods.php @@ -56,7 +56,7 @@ class iRODS extends \OC\Files\Storage\StreamWrapper{ } else { throw new \Exception(); } - + } public static function login( $params ) { @@ -138,11 +138,13 @@ class iRODS extends \OC\Files\Storage\StreamWrapper{ private function collectionMTime($path) { $dh = $this->opendir($path); $lastCTime = $this->filemtime($path); - while (($file = readdir($dh)) !== false) { - if ($file != '.' and $file != '..') { - $time = $this->filemtime($file); - if ($time > $lastCTime) { - $lastCTime = $time; + if(is_resource($dh)) { + while (($file = readdir($dh)) !== false) { + if ($file != '.' and $file != '..') { + $time = $this->filemtime($file); + if ($time > $lastCTime) { + $lastCTime = $time; + } } } } diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index 8e7a28fba1a..ecd4dae0484 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -99,11 +99,13 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ private function shareMTime() { $dh=$this->opendir(''); $lastCtime=0; - while (($file = readdir($dh)) !== false) { - if ($file!='.' and $file!='..') { - $ctime=$this->filemtime($file); - if ($ctime>$lastCtime) { - $lastCtime=$ctime; + if(is_resource($dh)) { + while (($file = readdir($dh)) !== false) { + if ($file!='.' and $file!='..') { + $ctime=$this->filemtime($file); + if ($ctime>$lastCtime) { + $lastCtime=$ctime; + } } } } diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 357c6fdf540..acabc9a5c10 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -7,8 +7,6 @@ function fileDownloadPath(dir, file) { return url; } -var form_data; - $(document).ready(function() { $('#data-upload-form').tipsy({gravity:'ne', fade:true}); @@ -50,19 +48,20 @@ $(document).ready(function() { }); } - // Add some form data to the upload handler - file_upload_param.formData = { - MAX_FILE_SIZE: $('#uploadMaxFilesize').val(), - requesttoken: $('#publicUploadRequestToken').val(), - dirToken: $('#dirToken').val(), - appname: 'files_sharing', - subdir: $('input#dir').val() - }; + var file_upload_start = $('#file_upload_start'); + file_upload_start.on('fileuploadadd', function(e, data) { + // Add custom data to the upload handler + data.formData = { + requesttoken: $('#publicUploadRequestToken').val(), + dirToken: $('#dirToken').val(), + subdir: $('input#dir').val() + }; + }); - // Add Uploadprogress Wrapper to controls bar - $('#controls').append($('#additional_controls div#uploadprogresswrapper')); + // Add Uploadprogress Wrapper to controls bar + $('#controls').append($('#additional_controls div#uploadprogresswrapper')); - // Cancel upload trigger - $('#cancel_upload_button').click(Files.cancelUploads); + // Cancel upload trigger + $('#cancel_upload_button').click(Files.cancelUploads); }); diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 3be89a39fa0..03ed02f41ef 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -4,7 +4,7 @@ $(document).ready(function() { if (typeof OC.Share !== 'undefined' && typeof FileActions !== 'undefined' && !disableSharing) { - $('#fileList').one('fileActionsReady',function(){ + $('#fileList').on('fileActionsReady',function(){ OC.Share.loadIcons('file'); }); diff --git a/apps/files_sharing/l10n/lt_LT.php b/apps/files_sharing/l10n/lt_LT.php index 5d0e58e2fb2..90ae6a39a07 100644 --- a/apps/files_sharing/l10n/lt_LT.php +++ b/apps/files_sharing/l10n/lt_LT.php @@ -1,7 +1,14 @@ <?php $TRANSLATIONS = array( +"The password is wrong. Try again." => "Netinka slaptažodis: Bandykite dar kartą.", "Password" => "Slaptažodis", "Submit" => "Išsaugoti", +"Sorry, this link doesn’t seem to work anymore." => "Atleiskite, panašu, kad nuoroda yra neveiksni.", +"Reasons might be:" => "Galimos priežastys:", +"the item was removed" => "elementas buvo pašalintas", +"the link expired" => "baigėsi nuorodos galiojimo laikas", +"sharing is disabled" => "dalinimasis yra išjungtas", +"For more info, please ask the person who sent this link." => "Dėl tikslesnės informacijos susisiekite su asmeniu atsiuntusiu nuorodą.", "%s shared the folder %s with you" => "%s pasidalino su jumis %s aplanku", "%s shared the file %s with you" => "%s pasidalino su jumis %s failu", "Download" => "Atsisiųsti", diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index d91acbbb2bd..257da89c84e 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -221,7 +221,8 @@ class Shared extends \OC\Files\Storage\Common { public function filemtime($path) { if ($path == '' || $path == '/') { $mtime = 0; - if ($dh = $this->opendir($path)) { + $dh = $this->opendir($path); + if(is_resource($dh)) { while (($filename = readdir($dh)) !== false) { $tempmtime = $this->filemtime($filename); if ($tempmtime > $mtime) { diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index ec6b4e815f8..6d3a07a9d0b 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -19,6 +19,20 @@ function fileCmp($a, $b) { } } +function determineIcon($file, $sharingRoot, $sharingToken) { + // for folders we simply reuse the files logic + if($file['type'] == 'dir') { + return \OCA\files\lib\Helper::determineIcon($file); + } + + $relativePath = substr($file['path'], 6); + $relativePath = substr($relativePath, strlen($sharingRoot)); + if($file['isPreviewAvailable']) { + return OCP\publicPreview_icon($relativePath, $sharingToken); + } + return OCP\mimetype_icon($file['mimetype']); +} + if (isset($_GET['t'])) { $token = $_GET['t']; $linkItem = OCP\Share::getShareByToken($token); @@ -133,6 +147,7 @@ if (isset($path)) { $tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path)); $tmpl->assign('fileTarget', basename($linkItem['file_target'])); $tmpl->assign('dirToken', $linkItem['token']); + $tmpl->assign('disableSharing', true); $allowPublicUploadEnabled = (bool) ($linkItem['permissions'] & OCP\PERMISSION_CREATE); if (\OCP\App::isEnabled('files_encryption')) { $allowPublicUploadEnabled = false; @@ -176,6 +191,7 @@ if (isset($path)) { } $i['directory'] = $getPath; $i['permissions'] = OCP\PERMISSION_READ; + $i['icon'] = determineIcon($i, $basePath, $token); $files[] = $i; } usort($files, "fileCmp"); @@ -191,7 +207,6 @@ if (isset($path)) { } $list = new OCP\Template('files', 'part.list', ''); $list->assign('files', $files); - $list->assign('disableSharing', true); $list->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path='); $list->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download&path='); diff --git a/apps/files_trashbin/ajax/list.php b/apps/files_trashbin/ajax/list.php new file mode 100644 index 00000000000..e72e67b01d7 --- /dev/null +++ b/apps/files_trashbin/ajax/list.php @@ -0,0 +1,51 @@ +<?php + +// only need filesystem apps +$RUNTIME_APPTYPES=array('filesystem'); + +// Init owncloud + + +OCP\JSON::checkLoggedIn(); + +// Load the files +$dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; +$doBreadcrumb = isset( $_GET['breadcrumb'] ) ? true : false; +$data = array(); + +// Make breadcrumb +if($doBreadcrumb) { + $breadcrumb = \OCA\files_trashbin\lib\Helper::makeBreadcrumb($dir); + + $breadcrumbNav = new OCP\Template('files_trashbin', 'part.breadcrumb', ''); + $breadcrumbNav->assign('breadcrumb', $breadcrumb, false); + $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php') . '?dir='); + $breadcrumbNav->assign('home', OCP\Util::linkTo('files', 'index.php')); + + $data['breadcrumb'] = $breadcrumbNav->fetchPage(); +} + +// make filelist +$files = \OCA\files_trashbin\lib\Helper::getTrashFiles($dir); + +if ($files === null){ + header("HTTP/1.0 404 Not Found"); + exit(); +} + +$dirlisting = false; +if ($dir && $dir !== '/') { + $dirlisting = true; +} + +$encodedDir = \OCP\Util::encodePath($dir); +$list = new OCP\Template('files_trashbin', 'part.list', ''); +$list->assign('files', $files, false); +$list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir='.$encodedDir); +$list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); +$list->assign('dirlisting', $dirlisting); +$list->assign('disableDownloadActions', true); +$data['files'] = $list->fetchPage(); + +OCP\JSON::success(array('data' => $data)); + diff --git a/apps/files_trashbin/index.php b/apps/files_trashbin/index.php index 0baeab1de97..9f17448a757 100644 --- a/apps/files_trashbin/index.php +++ b/apps/files_trashbin/index.php @@ -10,91 +10,52 @@ OCP\Util::addScript('files_trashbin', 'disableDefaultActions'); OCP\Util::addScript('files', 'fileactions'); $tmpl = new OCP\Template('files_trashbin', 'index', 'user'); -$user = \OCP\User::getUser(); -$view = new OC_Filesystemview('/'.$user.'/files_trashbin/files'); - OCP\Util::addStyle('files', 'files'); OCP\Util::addScript('files', 'filelist'); +// filelist overrides +OCP\Util::addScript('files_trashbin', 'filelist'); +OCP\Util::addscript('files', 'files'); $dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : ''; -$result = array(); -if ($dir) { - $dirlisting = true; - $dirContent = $view->opendir($dir); - $i = 0; - while(($entryName = readdir($dirContent)) !== false) { - if (!\OC\Files\Filesystem::isIgnoredDir($entryName)) { - $pos = strpos($dir.'/', '/', 1); - $tmp = substr($dir, 0, $pos); - $pos = strrpos($tmp, '.d'); - $timestamp = substr($tmp, $pos+2); - $result[] = array( - 'id' => $entryName, - 'timestamp' => $timestamp, - 'mime' => $view->getMimeType($dir.'/'.$entryName), - 'type' => $view->is_dir($dir.'/'.$entryName) ? 'dir' : 'file', - 'location' => $dir, - ); - } - } - closedir($dirContent); - -} else { - $dirlisting = false; - $query = \OC_DB::prepare('SELECT `id`,`location`,`timestamp`,`type`,`mime` FROM `*PREFIX*files_trash` WHERE `user` = ?'); - $result = $query->execute(array($user))->fetchAll(); +$isIE8 = false; +preg_match('/MSIE (.*?);/', $_SERVER['HTTP_USER_AGENT'], $matches); +if (count($matches) > 0 && $matches[1] <= 8){ + $isIE8 = true; } -$files = array(); -foreach ($result as $r) { - $i = array(); - $i['name'] = $r['id']; - $i['date'] = OCP\Util::formatDate($r['timestamp']); - $i['timestamp'] = $r['timestamp']; - $i['mimetype'] = $r['mime']; - $i['type'] = $r['type']; - if ($i['type'] === 'file') { - $fileinfo = pathinfo($r['id']); - $i['basename'] = $fileinfo['filename']; - $i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : ''; +// if IE8 and "?dir=path" was specified, reformat the URL to use a hash like "#?dir=path" +if ($isIE8 && isset($_GET['dir'])){ + if ($dir === ''){ + $dir = '/'; } - $i['directory'] = $r['location']; - if ($i['directory'] === '/') { - $i['directory'] = ''; - } - $i['permissions'] = OCP\PERMISSION_READ; - $i['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($r['mime']); - $files[] = $i; + header('Location: ' . OCP\Util::linkTo('files_trashbin', 'index.php') . '#?dir=' . \OCP\Util::encodePath($dir)); + exit(); } -function fileCmp($a, $b) { - if ($a['type'] === 'dir' and $b['type'] !== 'dir') { - return -1; - } elseif ($a['type'] !== 'dir' and $b['type'] === 'dir') { - return 1; - } else { - return strnatcasecmp($a['name'], $b['name']); - } +$ajaxLoad = false; + +if (!$isIE8){ + $files = \OCA\files_trashbin\lib\Helper::getTrashFiles($dir); +} +else{ + $files = array(); + $ajaxLoad = true; } -usort($files, "fileCmp"); - -// Make breadcrumb -$pathtohere = ''; -$breadcrumb = array(); -foreach (explode('/', $dir) as $i) { - if ($i !== '') { - if ( preg_match('/^(.+)\.d[0-9]+$/', $i, $match) ) { - $name = $match[1]; - } else { - $name = $i; - } - $pathtohere .= '/' . $i; - $breadcrumb[] = array('dir' => $pathtohere, 'name' => $name); - } +// Redirect if directory does not exist +if ($files === null){ + header('Location: ' . OCP\Util::linkTo('files_trashbin', 'index.php')); + exit(); } +$dirlisting = false; +if ($dir && $dir !== '/') { + $dirlisting = true; +} + +$breadcrumb = \OCA\files_trashbin\lib\Helper::makeBreadcrumb($dir); + $breadcrumbNav = new OCP\Template('files_trashbin', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', $breadcrumb); $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php') . '?dir='); @@ -106,7 +67,6 @@ $list->assign('files', $files); $encodedDir = \OCP\Util::encodePath($dir); $list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir='.$encodedDir); $list->assign('downloadURL', OCP\Util::linkTo('files_trashbin', 'download.php') . '?file='.$encodedDir); -$list->assign('disableSharing', true); $list->assign('dirlisting', $dirlisting); $list->assign('disableDownloadActions', true); @@ -114,6 +74,8 @@ $tmpl->assign('dirlisting', $dirlisting); $tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage()); $tmpl->assign('fileList', $list->fetchPage()); $tmpl->assign('files', $files); -$tmpl->assign('dir', \OC\Files\Filesystem::normalizePath($view->getAbsolutePath())); +$tmpl->assign('dir', $dir); +$tmpl->assign('disableSharing', true); +$tmpl->assign('ajaxLoad', true); $tmpl->printPage(); diff --git a/apps/files_trashbin/js/filelist.js b/apps/files_trashbin/js/filelist.js new file mode 100644 index 00000000000..cd5a67ddfe0 --- /dev/null +++ b/apps/files_trashbin/js/filelist.js @@ -0,0 +1,24 @@ +// override reload with own ajax call +FileList.reload = function(){ + FileList.showMask(); + if (FileList._reloadCall){ + FileList._reloadCall.abort(); + } + $.ajax({ + url: OC.filePath('files_trashbin','ajax','list.php'), + data: { + dir : $('#dir').val(), + breadcrumb: true + }, + error: function(result) { + FileList.reloadCallback(result); + }, + success: function(result) { + FileList.reloadCallback(result); + } + }); +} + +FileList.linkTo = function(dir){ + return OC.linkTo('files_trashbin', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); +} diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index 40c0bdb3829..d73eadb6011 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -171,9 +171,15 @@ $(document).ready(function() { action(filename); } } + + // event handlers for breadcrumb items + $('#controls').delegate('.crumb:not(.home) a', 'click', onClickBreadcrumb); }); - FileActions.actions.dir = {}; + FileActions.actions.dir = { + // only keep 'Open' action for navigation + 'Open': FileActions.actions.dir.Open + }; }); function processSelection(){ @@ -246,3 +252,9 @@ function disableActions() { $(".action").css("display", "none"); $(":input:checkbox").css("display", "none"); } +function onClickBreadcrumb(e){ + var $el = $(e.target).closest('.crumb'); + e.preventDefault(); + FileList.changeDirectory(decodeURIComponent($el.data('dir'))); +} + diff --git a/apps/files_trashbin/l10n/lt_LT.php b/apps/files_trashbin/l10n/lt_LT.php index c4a12ff2175..0a51290f4d9 100644 --- a/apps/files_trashbin/l10n/lt_LT.php +++ b/apps/files_trashbin/l10n/lt_LT.php @@ -8,8 +8,9 @@ $TRANSLATIONS = array( "Delete permanently" => "Ištrinti negrįžtamai", "Name" => "Pavadinimas", "Deleted" => "Ištrinti", -"_%n folder_::_%n folders_" => array("","",""), -"_%n file_::_%n files_" => array("","",""), +"_%n folder_::_%n folders_" => array("","","%n aplankų"), +"_%n file_::_%n files_" => array("","","%n failų"), +"restored" => "atstatyta", "Nothing in here. Your trash bin is empty!" => "Nieko nėra. Jūsų šiukšliadėžė tuščia!", "Restore" => "Atstatyti", "Delete" => "Ištrinti", diff --git a/apps/files_trashbin/lib/helper.php b/apps/files_trashbin/lib/helper.php new file mode 100644 index 00000000000..098fc0b54b7 --- /dev/null +++ b/apps/files_trashbin/lib/helper.php @@ -0,0 +1,97 @@ +<?php + +namespace OCA\files_trashbin\lib; + +class Helper +{ + /** + * Retrieves the contents of a trash bin directory. + * @param string $dir path to the directory inside the trashbin + * or empty to retrieve the root of the trashbin + * @return array of files + */ + public static function getTrashFiles($dir){ + $result = array(); + $user = \OCP\User::getUser(); + + if ($dir && $dir !== '/') { + $view = new \OC_Filesystemview('/'.$user.'/files_trashbin/files'); + $dirContent = $view->opendir($dir); + if ($dirContent === false){ + return null; + } + if(is_resource($dirContent)){ + while(($entryName = readdir($dirContent)) !== false) { + if (!\OC\Files\Filesystem::isIgnoredDir($entryName)) { + $pos = strpos($dir.'/', '/', 1); + $tmp = substr($dir, 0, $pos); + $pos = strrpos($tmp, '.d'); + $timestamp = substr($tmp, $pos+2); + $result[] = array( + 'id' => $entryName, + 'timestamp' => $timestamp, + 'mime' => $view->getMimeType($dir.'/'.$entryName), + 'type' => $view->is_dir($dir.'/'.$entryName) ? 'dir' : 'file', + 'location' => $dir, + ); + } + } + closedir($dirContent); + } + } else { + $query = \OC_DB::prepare('SELECT `id`,`location`,`timestamp`,`type`,`mime` FROM `*PREFIX*files_trash` WHERE `user` = ?'); + $result = $query->execute(array($user))->fetchAll(); + } + + $files = array(); + foreach ($result as $r) { + $i = array(); + $i['name'] = $r['id']; + $i['date'] = \OCP\Util::formatDate($r['timestamp']); + $i['timestamp'] = $r['timestamp']; + $i['mimetype'] = $r['mime']; + $i['type'] = $r['type']; + if ($i['type'] === 'file') { + $fileinfo = pathinfo($r['id']); + $i['basename'] = $fileinfo['filename']; + $i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : ''; + } + $i['directory'] = $r['location']; + if ($i['directory'] === '/') { + $i['directory'] = ''; + } + $i['permissions'] = \OCP\PERMISSION_READ; + $i['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($r['mime']); + $i['icon'] = \OCA\files\lib\Helper::determineIcon($i); + $files[] = $i; + } + + usort($files, array('\OCA\files\lib\Helper', 'fileCmp')); + + return $files; + } + + /** + * Splits the given path into a breadcrumb structure. + * @param string $dir path to process + * @return array where each entry is a hash of the absolute + * directory path and its name + */ + public static function makeBreadcrumb($dir){ + // Make breadcrumb + $pathtohere = ''; + $breadcrumb = array(); + foreach (explode('/', $dir) as $i) { + if ($i !== '') { + if ( preg_match('/^(.+)\.d[0-9]+$/', $i, $match) ) { + $name = $match[1]; + } else { + $name = $i; + } + $pathtohere .= '/' . $i; + $breadcrumb[] = array('dir' => $pathtohere, 'name' => $name); + } + } + return $breadcrumb; + } +} diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php index 88c32b1f3eb..82ba0608834 100644 --- a/apps/files_trashbin/templates/index.php +++ b/apps/files_trashbin/templates/index.php @@ -5,10 +5,14 @@ </div> <div id='notification'></div> -<?php if (isset($_['files']) && count($_['files']) === 0 && $_['dirlisting'] === false):?> +<?php if (isset($_['files']) && count($_['files']) === 0 && $_['dirlisting'] === false && !$_['ajaxLoad']):?> <div id="emptycontent"><?php p($l->t('Nothing in here. Your trash bin is empty!'))?></div> <?php endif; ?> +<input type="hidden" name="ajaxLoad" id="ajaxLoad" value="<?php p($_['ajaxLoad']); ?>" /> +<input type="hidden" id="disableSharing" data-status="<?php p($_['disableSharing']); ?>"></input> +<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir"> + <table id="filestable"> <thead> <tr> diff --git a/apps/files_trashbin/templates/part.breadcrumb.php b/apps/files_trashbin/templates/part.breadcrumb.php index 8ecab58e5c8..4acc298adbe 100644 --- a/apps/files_trashbin/templates/part.breadcrumb.php +++ b/apps/files_trashbin/templates/part.breadcrumb.php @@ -1,11 +1,11 @@ -<div class="crumb"> +<div class="crumb home"> <a href="<?php print_unescaped($_['home']); ?>"> <img src="<?php print_unescaped(OCP\image_path('core', 'places/home.svg'));?>" class="svg" /> </a> </div> <?php if(count($_["breadcrumb"])):?> <div class="crumb svg" - data-dir='<?php print_unescaped($_['baseURL']); ?>'> + data-dir='/'> <a href="<?php p($_['baseURL']); ?>"><?php p($l->t("Deleted Files")); ?></a> </div> <?php endif;?> diff --git a/apps/files_trashbin/templates/part.list.php b/apps/files_trashbin/templates/part.list.php index f7cc6b01bbb..78709d986ae 100644 --- a/apps/files_trashbin/templates/part.list.php +++ b/apps/files_trashbin/templates/part.list.php @@ -1,4 +1,3 @@ -<input type="hidden" id="disableSharing" data-status="<?php p($_['disableSharing']); ?>"> <?php foreach($_['files'] as $file): $relative_deleted_date = OCP\relative_modified_date($file['timestamp']); // the older the file, the brighter the shade of grey; days*14 @@ -12,7 +11,7 @@ data-permissions='<?php p($file['permissions']); ?>' <?php if ( $_['dirlisting'] ): ?> id="<?php p($file['directory'].'/'.$file['name']);?>" - data-file="<?php p($file['directory'].'/'.$file['name']);?>" + data-file="<?php p($name);?>" data-timestamp='' data-dirlisting=1 <?php else: ?> diff --git a/apps/files_versions/l10n/lt_LT.php b/apps/files_versions/l10n/lt_LT.php index 4e1af5fcc29..3afcfbe3b5f 100644 --- a/apps/files_versions/l10n/lt_LT.php +++ b/apps/files_versions/l10n/lt_LT.php @@ -2,6 +2,9 @@ $TRANSLATIONS = array( "Could not revert: %s" => "Nepavyko atstatyti: %s", "Versions" => "Versijos", +"Failed to revert {file} to revision {timestamp}." => "Nepavyko atstatyti {file} į būseną {timestamp}.", +"More versions..." => "Daugiau versijų...", +"No other versions available" => "Nėra daugiau versijų", "Restore" => "Atstatyti" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/apps/user_ldap/l10n/es_AR.php b/apps/user_ldap/l10n/es_AR.php index b31f41e3dfb..2436df8de77 100644 --- a/apps/user_ldap/l10n/es_AR.php +++ b/apps/user_ldap/l10n/es_AR.php @@ -75,8 +75,10 @@ $TRANSLATIONS = array( "By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "Por defecto, el nombre de usuario interno es creado a partir del atributo UUID. Esto asegura que el nombre de usuario es único y no es necesaria una conversión de caracteres. El nombre de usuario interno sólo se pueden usar estos caracteres: [ a-zA-Z0-9_.@- ]. El resto de caracteres son sustituidos por su correspondiente en ASCII o simplemente omitidos. En caso colisiones, se agregará o incrementará un número. El nombre de usuario interno es usado para identificar un usuario. Es también el nombre predeterminado para el directorio personal del usuario en ownCloud. También es parte de las URLs remotas, por ejemplo, para los servicios *DAV. Con esta opción, se puede cambiar el comportamiento por defecto. Para conseguir un comportamiento similar a versiones anteriores a ownCloud 5, ingresá el atributo del nombre mostrado en el campo siguiente. Dejalo vacío para el comportamiento por defecto. Los cambios solo tendrán efecto en los nuevos usuarios LDAP mapeados (agregados).", "Internal Username Attribute:" => "Atributo Nombre Interno de usuario:", "Override UUID detection" => "Sobrescribir la detección UUID", +"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "Por defecto, el atributo UUID es detectado automáticamente. Este atributo es usado para identificar de manera certera usuarios y grupos LDAP. Además, el nombre de usuario interno será creado en base al UUID, si no fue especificado otro comportamiento más arriba. Podés sobrescribir la configuración y pasar un atributo de tu elección. Tenés que asegurarte que el atributo de tu elección sea accesible por los usuarios y grupos y que sea único. Dejalo en blanco para usar el comportamiento por defecto. Los cambios tendrán efecto sólo en los nuevos usuarios y grupos de LDAP mapeados (agregados).", "UUID Attribute:" => "Atributo UUID:", "Username-LDAP User Mapping" => "Asignación del Nombre de usuario de un usuario LDAP", +"Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." => "Los usuarios son usados para almacenar y asignar datos (metadatos). Con el fin de identificar de forma precisa y reconocer usuarios, a cada usuario de LDAP se será asignado un nombre de usuario interno. Esto requiere un mapeo entre el nombre de usuario y el usuario del LDAP. El nombre de usuario creado es mapeado respecto al UUID del usuario en el LDAP. De forma adicional, el DN es dejado en caché para reducir la interacción entre el LDAP, pero no es usado para la identificación. Si el DN cambia, los cambios van a ser aplicados. El nombre de usuario interno es usado en todos los lugares. Vaciar los mapeos, deja restos por todas partes. Vaciar los mapeos, no es sensible a configuración, ¡afecta a todas las configuraciones del LDAP! Nunca limpies los mapeos en un entorno de producción, solamente en fase de desarrollo o experimental.", "Clear Username-LDAP User Mapping" => "Borrar la asignación de los Nombres de usuario de los usuarios LDAP", "Clear Groupname-LDAP Group Mapping" => "Borrar la asignación de los Nombres de grupo de los grupos de LDAP", "Test Configuration" => "Probar configuración", diff --git a/apps/user_ldap/l10n/lt_LT.php b/apps/user_ldap/l10n/lt_LT.php index 7e8b389af7f..2c3b938fcfe 100644 --- a/apps/user_ldap/l10n/lt_LT.php +++ b/apps/user_ldap/l10n/lt_LT.php @@ -2,6 +2,7 @@ $TRANSLATIONS = array( "Deletion failed" => "Ištrinti nepavyko", "Error" => "Klaida", +"Host" => "Mazgas", "Password" => "Slaptažodis", "Group Filter" => "Grupės filtras", "Port" => "Prievadas", diff --git a/apps/user_webdavauth/l10n/lt_LT.php b/apps/user_webdavauth/l10n/lt_LT.php index 90fc2d5ac3e..41a7fa9502d 100644 --- a/apps/user_webdavauth/l10n/lt_LT.php +++ b/apps/user_webdavauth/l10n/lt_LT.php @@ -1,5 +1,7 @@ <?php $TRANSLATIONS = array( -"WebDAV Authentication" => "WebDAV autorizavimas" +"WebDAV Authentication" => "WebDAV autentikacija", +"Address: " => "Adresas:", +"The user credentials will be sent to this address. This plugin checks the response and will interpret the HTTP statuscodes 401 and 403 as invalid credentials, and all other responses as valid credentials." => "Naudotojo duomenys bus nusiųsti šiuo adresu. Šis įskiepis patikrins gautą atsakymą ir interpretuos HTTP būsenos kodą 401 ir 403 kaip negaliojančius duomenis, ir visus kitus gautus atsakymus kaip galiojančius duomenis. " ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/apps/user_webdavauth/l10n/uk.php b/apps/user_webdavauth/l10n/uk.php index fcde044ec75..dff8b308c5d 100644 --- a/apps/user_webdavauth/l10n/uk.php +++ b/apps/user_webdavauth/l10n/uk.php @@ -1,5 +1,6 @@ <?php $TRANSLATIONS = array( -"WebDAV Authentication" => "Аутентифікація WebDAV" +"WebDAV Authentication" => "Аутентифікація WebDAV", +"Address: " => "Адреса:" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; |