mirror of
https://github.com/nextcloud/server.git
synced 2026-04-22 06:37:56 -04:00
commit
8dd9dedee8
22 changed files with 948 additions and 63 deletions
|
|
@ -23,7 +23,9 @@
|
|||
#new>ul>li>p { cursor:pointer; }
|
||||
#new>ul>li>form>input { padding:0.3em; margin:-0.3em; }
|
||||
|
||||
#upload {
|
||||
#trash { height:17px; margin:0 0 0 1em; z-index:1010; position:absolute; right:13.5em; }
|
||||
|
||||
#upload {
|
||||
height:27px; padding:0; margin-left:0.2em; overflow:hidden;
|
||||
}
|
||||
#upload a {
|
||||
|
|
@ -109,6 +111,7 @@ table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; }
|
|||
}
|
||||
#fileList .fileactions a.action img { position:relative; top:.2em; }
|
||||
#fileList a.action { display:inline; margin:-.5em 0; padding:1em .5em 1em .5em !important; }
|
||||
#fileList img.move2trash { display:inline; margin:-.5em 0; padding:1em .5em 1em .5em !important; float:right; }
|
||||
a.action.delete { float:right; }
|
||||
a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; }
|
||||
.selectedActions { display:none; float:right; }
|
||||
|
|
|
|||
|
|
@ -131,9 +131,10 @@ if ($needUpgrade) {
|
|||
$tmpl->assign('isCreatable', \OC\Files\Filesystem::isCreatable($dir . '/'));
|
||||
$tmpl->assign('permissions', $permissions);
|
||||
$tmpl->assign('files', $files);
|
||||
$tmpl->assign('trash', \OCP\App::isEnabled('files_trashbin'));
|
||||
$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
|
||||
$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
|
||||
$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
|
||||
$tmpl->assign('usedSpacePercent', (int)$storageInfo['relative']);
|
||||
$tmpl->printPage();
|
||||
}
|
||||
}
|
||||
|
|
@ -147,15 +147,19 @@ $(document).ready(function () {
|
|||
} else {
|
||||
var downloadScope = 'file';
|
||||
}
|
||||
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());
|
||||
});
|
||||
|
||||
|
||||
if (typeof disableDownloadActions == 'undefined' || !disableDownloadActions) {
|
||||
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());
|
||||
});
|
||||
}
|
||||
|
||||
$('#fileList tr').each(function(){
|
||||
FileActions.display($(this).children('td.filename'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
FileActions.register('all', 'Delete', OC.PERMISSION_DELETE, function () {
|
||||
|
|
@ -185,6 +189,7 @@ FileActions.register('all', 'Rename', OC.PERMISSION_UPDATE, function () {
|
|||
FileList.rename(filename);
|
||||
});
|
||||
|
||||
|
||||
FileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename) {
|
||||
window.location = OC.linkTo('files', 'index.php') + '?dir=' + encodeURIComponent($('#dir').val()).replace(/%2F/g, '/') + '/' + encodeURIComponent(filename);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -271,65 +271,39 @@ var FileList={
|
|||
}
|
||||
},
|
||||
do_delete:function(files){
|
||||
if(files.substr){
|
||||
files=[files];
|
||||
}
|
||||
for (var i in files) {
|
||||
var deleteAction = $('tr').filterAttr('data-file',files[i]).children("td.date").children(".action.delete");
|
||||
var oldHTML = deleteAction[0].outerHTML;
|
||||
var newHTML = '<img class="move2trash" data-action="Delete" title="'+t('files', 'perform delete operation')+'" src="'+ OC.imagePath('core', 'loading.gif') +'"></a>';
|
||||
deleteAction[0].outerHTML = newHTML;
|
||||
}
|
||||
// Finish any existing actions
|
||||
if (FileList.lastAction) {
|
||||
FileList.lastAction();
|
||||
}
|
||||
|
||||
FileList.prepareDeletion(files);
|
||||
|
||||
if (!FileList.useUndo) {
|
||||
FileList.lastAction();
|
||||
} else {
|
||||
// NOTE: Temporary fix to change the text to unshared for files in root of Shared folder
|
||||
if ($('#dir').val() == '/Shared') {
|
||||
OC.Notification.showHtml(t('files', 'unshared {files}', {'files': escapeHTML(files)})+'<span class="undo">'+t('files', 'undo')+'</span>');
|
||||
} else {
|
||||
OC.Notification.showHtml(t('files', 'deleted {files}', {'files': escapeHTML(files)})+'<span class="undo">'+t('files', 'undo')+'</span>');
|
||||
}
|
||||
}
|
||||
},
|
||||
finishDelete:function(ready,sync){
|
||||
if(!FileList.deleteCanceled && FileList.deleteFiles){
|
||||
var fileNames=JSON.stringify(FileList.deleteFiles);
|
||||
$.ajax({
|
||||
url: OC.filePath('files', 'ajax', 'delete.php'),
|
||||
async:!sync,
|
||||
type:'post',
|
||||
data: {dir:$('#dir').val(),files:fileNames},
|
||||
complete: function(data){
|
||||
boolOperationFinished(data, function(){
|
||||
OC.Notification.hide();
|
||||
$.each(FileList.deleteFiles,function(index,file){
|
||||
FileList.remove(file);
|
||||
var fileNames = JSON.stringify(files);
|
||||
$.post(OC.filePath('files', 'ajax', 'delete.php'),
|
||||
{dir:$('#dir').val(),files:fileNames},
|
||||
function(result){
|
||||
if (result.status == 'success') {
|
||||
$.each(files,function(index,file){
|
||||
var files = $('tr').filterAttr('data-file',file);
|
||||
files.hide();
|
||||
files.find('input[type="checkbox"]').removeAttr('checked');
|
||||
files.removeClass('selected');
|
||||
});
|
||||
FileList.deleteCanceled=true;
|
||||
FileList.deleteFiles=null;
|
||||
FileList.lastAction = null;
|
||||
if(ready){
|
||||
ready();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
prepareDeletion:function(files){
|
||||
if(files.substr){
|
||||
files=[files];
|
||||
}
|
||||
$.each(files,function(index,file){
|
||||
var files = $('tr').filterAttr('data-file',file);
|
||||
files.hide();
|
||||
files.find('input[type="checkbox"]').removeAttr('checked');
|
||||
files.removeClass('selected');
|
||||
});
|
||||
procesSelection();
|
||||
FileList.deleteCanceled=false;
|
||||
FileList.deleteFiles=files;
|
||||
FileList.lastAction = function() {
|
||||
FileList.finishDelete(null, true);
|
||||
};
|
||||
procesSelection();
|
||||
} else {
|
||||
$.each(files,function(index,file) {
|
||||
var deleteAction = $('tr').filterAttr('data-file',file).children("td.date").children(".move2trash");
|
||||
deleteAction[0].outerHTML = oldHTML;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,11 @@ $(document).ready(function() {
|
|||
$(this).parent().children('#file_upload_start').trigger('click');
|
||||
return false;
|
||||
});
|
||||
|
||||
// Show trash bin
|
||||
$('#trash a').live('click', function() {
|
||||
window.location=OC.filePath('files_trashbin', '', 'index.php');
|
||||
});
|
||||
|
||||
var lastChecked;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@
|
|||
<a href="#" class="svg" onclick="return false;"></a>
|
||||
</form>
|
||||
</div>
|
||||
<?php if ($_['trash'] ): ?>
|
||||
<div id="trash" class="button">
|
||||
<a><?php echo $l->t('Trash');?></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div id="uploadprogresswrapper">
|
||||
<div id="uploadprogressbar"></div>
|
||||
<input type="button" class="stop" style="display:none"
|
||||
|
|
@ -42,7 +47,6 @@
|
|||
onclick="javascript:Files.cancelUploads();"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="file_action_panel"></div>
|
||||
<?php else:?>
|
||||
|
|
|
|||
45
apps/files_trashbin/ajax/undelete.php
Normal file
45
apps/files_trashbin/ajax/undelete.php
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
if(!OCP\User::isLoggedIn()) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$files = $_REQUEST['files'];
|
||||
$dirlisting = $_REQUEST['dirlisting'];
|
||||
$list = explode(';', $files);
|
||||
|
||||
$error = array();
|
||||
$success = array();
|
||||
|
||||
$i = 0;
|
||||
foreach ($list as $file) {
|
||||
if ( $dirlisting=='0') {
|
||||
$delimiter = strrpos($file, '.d');
|
||||
$filename = substr($file, 0, $delimiter);
|
||||
$timestamp = substr($file, $delimiter+2);
|
||||
} else {
|
||||
$path_parts = pathinfo($file);
|
||||
$filename = $path_parts['basename'];
|
||||
$timestamp = null;
|
||||
}
|
||||
|
||||
if ( !OCA_Trash\Trashbin::restore($file, $filename, $timestamp) ) {
|
||||
$error[] = $filename;
|
||||
} else {
|
||||
$success[$i]['filename'] = $file;
|
||||
$success[$i]['timestamp'] = $timestamp;
|
||||
$i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( $error ) {
|
||||
$filelist = '';
|
||||
foreach ( $error as $e ) {
|
||||
$filelist .= $e.', ';
|
||||
}
|
||||
OCP\JSON::error(array("data" => array("message" => "Couldn't restore ".rtrim($filelist,', '), "success" => $success, "error" => $error)));
|
||||
} else {
|
||||
OCP\JSON::success(array("data" => array("success" => $success)));
|
||||
}
|
||||
|
||||
7
apps/files_trashbin/appinfo/app.php
Normal file
7
apps/files_trashbin/appinfo/app.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
OC::$CLASSPATH['OCA_Trash\Hooks'] = 'apps/files_trashbin/lib/hooks.php';
|
||||
OC::$CLASSPATH['OCA_Trash\Trashbin'] = 'apps/files_trashbin/lib/trash.php';
|
||||
|
||||
|
||||
OCP\Util::connectHook('OC_Filesystem', 'delete', "OCA_Trash\Hooks", "remove_hook");
|
||||
92
apps/files_trashbin/appinfo/database.xml
Normal file
92
apps/files_trashbin/appinfo/database.xml
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<database>
|
||||
|
||||
<name>*dbname*</name>
|
||||
<create>true</create>
|
||||
<overwrite>false</overwrite>
|
||||
|
||||
<charset>utf8</charset>
|
||||
|
||||
<table>
|
||||
|
||||
<name>*dbprefix*files_trash</name>
|
||||
|
||||
<declaration>
|
||||
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>50</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>user</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>50</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>timestamp</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>12</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>location</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>200</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>type</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>4</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>mime</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>30</length>
|
||||
</field>
|
||||
|
||||
<index>
|
||||
<name>id_index</name>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
|
||||
<index>
|
||||
<name>timestamp_index</name>
|
||||
<field>
|
||||
<name>timestamp</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
|
||||
<index>
|
||||
<name>user_index</name>
|
||||
<field>
|
||||
<name>user</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
|
||||
</declaration>
|
||||
|
||||
</table>
|
||||
|
||||
</database>
|
||||
14
apps/files_trashbin/appinfo/info.xml
Normal file
14
apps/files_trashbin/appinfo/info.xml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0"?>
|
||||
<info>
|
||||
<id>files_trashbin</id>
|
||||
<name>Trash</name>
|
||||
<description>Trash bin</description>
|
||||
<licence>AGPL</licence>
|
||||
<author>Bjoern Schiessle</author>
|
||||
<shipped>true</shipped>
|
||||
<require>4.9</require>
|
||||
<default_enable/>
|
||||
<types>
|
||||
<filesystem/>
|
||||
</types>
|
||||
</info>
|
||||
1
apps/files_trashbin/appinfo/version
Normal file
1
apps/files_trashbin/appinfo/version
Normal file
|
|
@ -0,0 +1 @@
|
|||
0.1
|
||||
51
apps/files_trashbin/download.php
Normal file
51
apps/files_trashbin/download.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud - trash bin
|
||||
*
|
||||
* @author Bjoern Schiessle
|
||||
* @copyright 2013 Bjoern Schiessle schiessle@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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Check if we are a user
|
||||
OCP\User::checkLoggedIn();
|
||||
|
||||
$filename = $_GET["file"];
|
||||
|
||||
$view = new OC_FilesystemView('/'.\OCP\User::getUser().'/files_trashbin');
|
||||
|
||||
if(!$view->file_exists($filename)) {
|
||||
header("HTTP/1.0 404 Not Found");
|
||||
$tmpl = new OCP\Template( '', '404', 'guest' );
|
||||
$tmpl->assign('file', $filename);
|
||||
$tmpl->printPage();
|
||||
exit;
|
||||
}
|
||||
|
||||
$ftype=$view->getMimeType( $filename );
|
||||
|
||||
header('Content-Type:'.$ftype);if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) {
|
||||
header( 'Content-Disposition: attachment; filename="' . rawurlencode( basename($filename) ) . '"' );
|
||||
} else {
|
||||
header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode( basename($filename) )
|
||||
. '; filename="' . rawurlencode( basename($filename) ) . '"' );
|
||||
}
|
||||
OCP\Response::disableCaching();
|
||||
header('Content-Length: '. $view->filesize($filename));
|
||||
|
||||
OC_Util::obEnd();
|
||||
$view->readfile( $filename );
|
||||
100
apps/files_trashbin/index.php
Normal file
100
apps/files_trashbin/index.php
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
// Check if we are a user
|
||||
OCP\User::checkLoggedIn();
|
||||
|
||||
OCP\Util::addScript('files_trashbin', 'trash');
|
||||
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');
|
||||
|
||||
OCP\Util::addStyle('files', 'files');
|
||||
OCP\Util::addScript('files', 'filelist');
|
||||
|
||||
$dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : '';
|
||||
|
||||
if ($dir) {
|
||||
$dirlisting = true;
|
||||
$view = new \OC_FilesystemView('/'.\OCP\User::getUser().'/files_trashbin');
|
||||
$fullpath = \OCP\Config::getSystemValue('datadirectory').$view->getAbsolutePath($dir);
|
||||
$dirContent = opendir($fullpath);
|
||||
$i = 0;
|
||||
while($entryName = readdir($dirContent)) {
|
||||
if ( $entryName != '.' && $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($fullpath);
|
||||
|
||||
} 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();
|
||||
}
|
||||
|
||||
$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;
|
||||
$files[] = $i;
|
||||
}
|
||||
|
||||
// Make breadcrumb
|
||||
$breadcrumb = array(array('dir' => '', 'name' => 'Trash'));
|
||||
$pathtohere = '';
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
$breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '');
|
||||
$breadcrumbNav->assign('breadcrumb', $breadcrumb, false);
|
||||
$breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php') . '?dir=', false);
|
||||
|
||||
$list = new OCP\Template('files_trashbin', 'part.list', '');
|
||||
$list->assign('files', $files, false);
|
||||
$list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir='.$dir, false);
|
||||
$list->assign('downloadURL', OCP\Util::linkTo('files_trashbin', 'download.php') . '?file='.$dir, false);
|
||||
$list->assign('disableSharing', true);
|
||||
$list->assign('dirlisting', $dirlisting);
|
||||
$list->assign('disableDownloadActions', true);
|
||||
$tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage(), false);
|
||||
$tmpl->assign('fileList', $list->fetchPage(), false);
|
||||
$tmpl->assign('files', $files);
|
||||
$tmpl->assign('dir', OC_Filesystem::normalizePath($view->getAbsolutePath()));
|
||||
|
||||
$tmpl->printPage();
|
||||
3
apps/files_trashbin/js/disableDefaultActions.js
Normal file
3
apps/files_trashbin/js/disableDefaultActions.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
/* disable download and sharing actions */
|
||||
var disableDownloadActions = true;
|
||||
var disableSharing = true;
|
||||
158
apps/files_trashbin/js/trash.js
Normal file
158
apps/files_trashbin/js/trash.js
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
|
||||
$(document).ready(function() {
|
||||
|
||||
if (typeof FileActions !== 'undefined') {
|
||||
FileActions.register('all', 'Restore', OC.PERMISSION_READ, OC.imagePath('core', 'actions/undelete.png'), function(filename) {
|
||||
var tr=$('tr').filterAttr('data-file', filename);
|
||||
var spinner = '<img class="move2trash" title="'+t('files_trashbin', 'perform restore operation')+'" src="'+ OC.imagePath('core', 'loader.gif') +'"></a>';
|
||||
var undeleteAction = $('tr').filterAttr('data-file',filename).children("td.date");
|
||||
undeleteAction[0].innerHTML = undeleteAction[0].innerHTML+spinner;
|
||||
$.post(OC.filePath('files_trashbin','ajax','undelete.php'),
|
||||
{files:tr.attr('data-file'), dirlisting:tr.attr('data-dirlisting') },
|
||||
function(result){
|
||||
for (var i = 0; i < result.data.success.length; i++) {
|
||||
var row = document.getElementById(result.data.success[i].filename);
|
||||
row.parentNode.removeChild(row);
|
||||
}
|
||||
if (result.status != 'success') {
|
||||
OC.dialogs.alert(result.data.message, 'Error');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
// Sets the select_all checkbox behaviour :
|
||||
$('#select_all').click(function() {
|
||||
if($(this).attr('checked')){
|
||||
// Check all
|
||||
$('td.filename input:checkbox').attr('checked', true);
|
||||
$('td.filename input:checkbox').parent().parent().addClass('selected');
|
||||
}else{
|
||||
// Uncheck all
|
||||
$('td.filename input:checkbox').attr('checked', false);
|
||||
$('td.filename input:checkbox').parent().parent().removeClass('selected');
|
||||
}
|
||||
processSelection();
|
||||
});
|
||||
|
||||
$('td.filename input:checkbox').live('change',function(event) {
|
||||
if (event.shiftKey) {
|
||||
var last = $(lastChecked).parent().parent().prevAll().length;
|
||||
var first = $(this).parent().parent().prevAll().length;
|
||||
var start = Math.min(first, last);
|
||||
var end = Math.max(first, last);
|
||||
var rows = $(this).parent().parent().parent().children('tr');
|
||||
for (var i = start; i < end; i++) {
|
||||
$(rows).each(function(index) {
|
||||
if (index == i) {
|
||||
var checkbox = $(this).children().children('input:checkbox');
|
||||
$(checkbox).attr('checked', 'checked');
|
||||
$(checkbox).parent().parent().addClass('selected');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
var selectedCount=$('td.filename input:checkbox:checked').length;
|
||||
$(this).parent().parent().toggleClass('selected');
|
||||
if(!$(this).attr('checked')){
|
||||
$('#select_all').attr('checked',false);
|
||||
}else{
|
||||
if(selectedCount==$('td.filename input:checkbox').length){
|
||||
$('#select_all').attr('checked',true);
|
||||
}
|
||||
}
|
||||
processSelection();
|
||||
});
|
||||
|
||||
$('.undelete').click('click',function(event) {
|
||||
var spinner = '<img class="move2trash" title="'+t('files_trashbin', 'perform undelete operation')+'" src="'+ OC.imagePath('core', 'loader.gif') +'"></a>';
|
||||
var files=getSelectedFiles('file');
|
||||
var fileslist=files.join(';');
|
||||
var dirlisting=getSelectedFiles('dirlisting')[0];
|
||||
|
||||
for (var i in files) {
|
||||
var undeleteAction = $('tr').filterAttr('data-file',files[i]).children("td.date");
|
||||
undeleteAction[0].innerHTML = undeleteAction[0].innerHTML+spinner;
|
||||
}
|
||||
|
||||
$.post(OC.filePath('files_trashbin','ajax','undelete.php'),
|
||||
{files:fileslist, dirlisting:dirlisting},
|
||||
function(result){
|
||||
for (var i = 0; i < result.data.success.length; i++) {
|
||||
var row = document.getElementById(result.data.success[i].filename);
|
||||
row.parentNode.removeChild(row);
|
||||
}
|
||||
if (result.status != 'success') {
|
||||
OC.dialogs.alert(result.data.message, 'Error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
function processSelection(){
|
||||
var selected=getSelectedFiles();
|
||||
var selectedFiles=selected.filter(function(el){return el.type=='file'});
|
||||
var selectedFolders=selected.filter(function(el){return el.type=='dir'});
|
||||
if(selectedFiles.length==0 && selectedFolders.length==0) {
|
||||
$('#headerName>span.name').text(t('files','Name'));
|
||||
$('#modified').text(t('files','Deleted'));
|
||||
$('table').removeClass('multiselect');
|
||||
$('.selectedActions').hide();
|
||||
}
|
||||
else {
|
||||
$('.selectedActions').show();
|
||||
var selection='';
|
||||
if(selectedFolders.length>0){
|
||||
if(selectedFolders.length==1){
|
||||
selection+=t('files','1 folder');
|
||||
}else{
|
||||
selection+=t('files','{count} folders',{count: selectedFolders.length});
|
||||
}
|
||||
if(selectedFiles.length>0){
|
||||
selection+=' & ';
|
||||
}
|
||||
}
|
||||
if(selectedFiles.length>0){
|
||||
if(selectedFiles.length==1){
|
||||
selection+=t('files','1 file');
|
||||
}else{
|
||||
selection+=t('files','{count} files',{count: selectedFiles.length});
|
||||
}
|
||||
}
|
||||
$('#headerName>span.name').text(selection);
|
||||
$('#modified').text('');
|
||||
$('table').addClass('multiselect');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get a list of selected files
|
||||
* @param string property (option) the property of the file requested
|
||||
* @return array
|
||||
*
|
||||
* possible values for property: name, mime, size and type
|
||||
* if property is set, an array with that property for each file is returnd
|
||||
* if it's ommited an array of objects with all properties is returned
|
||||
*/
|
||||
function getSelectedFiles(property){
|
||||
var elements=$('td.filename input:checkbox:checked').parent().parent();
|
||||
var files=[];
|
||||
elements.each(function(i,element){
|
||||
var file={
|
||||
name:$(element).attr('data-filename'),
|
||||
file:$(element).attr('data-file'),
|
||||
timestamp:$(element).attr('data-timestamp'),
|
||||
type:$(element).attr('data-type'),
|
||||
dirlisting:$(element).attr('data-dirlisting')
|
||||
};
|
||||
if(property){
|
||||
files.push(file[property]);
|
||||
}else{
|
||||
files.push(file);
|
||||
}
|
||||
});
|
||||
return files;
|
||||
}
|
||||
45
apps/files_trashbin/lib/hooks.php
Normal file
45
apps/files_trashbin/lib/hooks.php
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud - trash bin
|
||||
*
|
||||
* @author Bjoern Schiessle
|
||||
* @copyright 2013 Bjoern Schiessle schiessle@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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class contains all hooks.
|
||||
*/
|
||||
|
||||
namespace OCA_Trash;
|
||||
|
||||
class Hooks {
|
||||
|
||||
/**
|
||||
* @brief Copy files to trash bin
|
||||
* @param array
|
||||
*
|
||||
* This function is connected to the delete signal of OC_Filesystem
|
||||
* to copy the file to the trash bin
|
||||
*/
|
||||
public static function remove_hook($params) {
|
||||
|
||||
if ( \OCP\App::isEnabled('files_trashbin') ) {
|
||||
$path = $params['path'];
|
||||
Trashbin::move2trash($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
264
apps/files_trashbin/lib/trash.php
Normal file
264
apps/files_trashbin/lib/trash.php
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud - trash bin
|
||||
*
|
||||
* @author Bjoern Schiessle
|
||||
* @copyright 2013 Bjoern Schiessle schiessle@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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA_Trash;
|
||||
|
||||
class Trashbin {
|
||||
|
||||
const DEFAULT_RETENTION_OBLIGATION=180; // how long do we keep files in the trash bin if no other value is defined in the config file (unit: days)
|
||||
/**
|
||||
* move file to the trash bin
|
||||
*
|
||||
* @param $file_path path to the deleted file/directory relative to the files root directory
|
||||
*/
|
||||
public static function move2trash($file_path) {
|
||||
$user = \OCP\User::getUser();
|
||||
$view = new \OC_FilesystemView('/'. $user);
|
||||
if (!$view->is_dir('files_trashbin')) {
|
||||
$view->mkdir('files_trashbin');
|
||||
$view->mkdir("versions_trashbin");
|
||||
}
|
||||
|
||||
$path_parts = pathinfo($file_path);
|
||||
|
||||
$deleted = $path_parts['basename'];
|
||||
$location = $path_parts['dirname'];
|
||||
$timestamp = time();
|
||||
$mime = $view->getMimeType('files'.$file_path);
|
||||
|
||||
if ( $view->is_dir('files'.$file_path) ) {
|
||||
$type = 'dir';
|
||||
} else {
|
||||
$type = 'file';
|
||||
}
|
||||
|
||||
self::copy_recursive($file_path, 'files_trashbin/'.$deleted.'.d'.$timestamp, $view);
|
||||
|
||||
if ( $view->file_exists('files_trashbin/'.$deleted.'.d'.$timestamp) ) {
|
||||
$query = \OC_DB::prepare("INSERT INTO *PREFIX*files_trash (id,timestamp,location,type,mime,user) VALUES (?,?,?,?,?,?)");
|
||||
$result = $query->execute(array($deleted, $timestamp, $location, $type, $mime, $user));
|
||||
if ( !$result ) { // if file couldn't be added to the database than also don't store it in the trash bin.
|
||||
$view->deleteAll('files_trashbin/'.$deleted.'.d'.$timestamp);
|
||||
\OC_Log::write('files_trashbin', 'trash bin database couldn\'t be updated', \OC_log::ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( \OCP\App::isEnabled('files_versions') ) {
|
||||
if ( $view->is_dir('files_versions'.$file_path) ) {
|
||||
$view->rename('files_versions'.$file_path, 'versions_trashbin/'. $deleted.'.d'.$timestamp);
|
||||
} else if ( $versions = \OCA_Versions\Storage::getVersions($file_path) ) {
|
||||
foreach ($versions as $v) {
|
||||
$view->rename('files_versions'.$v['path'].'.v'.$v['version'], 'versions_trashbin/'. $deleted.'.v'.$v['version'].'.d'.$timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
\OC_Log::write('files_trashbin', 'Couldn\'t move '.$file_path.' to the trash bin' , \OC_log::ERROR);
|
||||
}
|
||||
|
||||
self::expire();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* restore files from trash bin
|
||||
* @param $file path to the deleted file
|
||||
* @param $filename name of the file
|
||||
* @param $timestamp time when the file was deleted
|
||||
*/
|
||||
public static function restore($file, $filename, $timestamp) {
|
||||
|
||||
$user = \OCP\User::getUser();
|
||||
$view = new \OC_FilesystemView('/'.$user);
|
||||
|
||||
if ( $timestamp ) {
|
||||
$query = \OC_DB::prepare('SELECT location,type FROM *PREFIX*files_trash WHERE user=? AND id=? AND timestamp=?');
|
||||
$result = $query->execute(array($user,$filename,$timestamp))->fetchAll();
|
||||
if ( count($result) != 1 ) {
|
||||
\OC_Log::write('files_trashbin', 'trash bin database inconsistent!', \OC_Log::ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// if location no longer exists, restore file in the root directory
|
||||
$location = $result[0]['location'];
|
||||
if ( $result[0]['location'] != '/' &&
|
||||
(!$view->is_dir('files'.$result[0]['location']) ||
|
||||
!$view->isUpdatable('files'.$result[0]['location'])) ) {
|
||||
$location = '';
|
||||
}
|
||||
} else {
|
||||
$path_parts = pathinfo($filename);
|
||||
$result[] = array(
|
||||
'location' => $path_parts['dirname'],
|
||||
'type' => $view->is_dir('/files_trashbin/'.$file) ? 'dir' : 'files',
|
||||
);
|
||||
$location = '';
|
||||
}
|
||||
|
||||
$source = \OC_Filesystem::normalizePath('files_trashbin/'.$file);
|
||||
$target = \OC_Filesystem::normalizePath('files/'.$location.'/'.$filename);
|
||||
|
||||
// we need a extension in case a file/dir with the same name already exists
|
||||
$ext = self::getUniqueExtension($location, $filename, $view);
|
||||
$mtime = $view->filemtime($source);
|
||||
if( $view->rename($source, $target.$ext) ) {
|
||||
$view->touch($target.$ext, $mtime);
|
||||
// if versioning app is enabled, copy versions from the trash bin back to the original location
|
||||
if ( \OCP\App::isEnabled('files_versions') ) {
|
||||
if ( $result[0]['type'] == 'dir' ) {
|
||||
$view->rename(\OC_Filesystem::normalizePath('versions_trashbin/'. $file), \OC_Filesystem::normalizePath('files_versions/'.$location.'/'.$filename.$ext));
|
||||
} else if ( $versions = self::getVersionsFromTrash($file, $timestamp) ) {
|
||||
foreach ($versions as $v) {
|
||||
if ($timestamp ) {
|
||||
$view->rename('versions_trashbin/'.$filename.'.v'.$v.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v);
|
||||
} else {
|
||||
$view->rename('versions_trashbin/'.$file.'.v'.$v, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $timestamp ) {
|
||||
$query = \OC_DB::prepare('DELETE FROM *PREFIX*files_trash WHERE user=? AND id=? AND timestamp=?');
|
||||
$query->execute(array($user,$filename,$timestamp));
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
\OC_Log::write('files_trashbin', 'Couldn\'t restore file from trash bin, '.$filename , \OC_log::ERROR);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* clean up the trash bin
|
||||
*/
|
||||
private static function expire() {
|
||||
|
||||
$view = new \OC_FilesystemView('/'.\OCP\User::getUser());
|
||||
$user = \OCP\User::getUser();
|
||||
|
||||
$query = \OC_DB::prepare('SELECT location,type,id,timestamp FROM *PREFIX*files_trash WHERE user=?');
|
||||
$result = $query->execute(array($user))->fetchAll();
|
||||
|
||||
$retention_obligation = \OC_Config::getValue('trashbin_retention_obligation', self::DEFAULT_RETENTION_OBLIGATION);
|
||||
|
||||
$limit = time() - ($retention_obligation * 86400);
|
||||
|
||||
foreach ( $result as $r ) {
|
||||
$timestamp = $r['timestamp'];
|
||||
$filename = $r['id'];
|
||||
if ( $r['timestamp'] < $limit ) {
|
||||
$view->unlink('files_trashbin/'.$filename.'.d'.$timestamp);
|
||||
if ($r['type'] == 'dir') {
|
||||
$view->unlink('versions_trashbin/'.$filename.'.d'.$timestamp);
|
||||
} else if ( $versions = self::getVersionsFromTrash($filename, $timestamp) ) {
|
||||
foreach ($versions as $v) {
|
||||
$view->unlink('versions_trashbin/'.$filename.'.v'.$v.'.d'.$timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$query = \OC_DB::prepare('DELETE FROM *PREFIX*files_trash WHERE user=? AND timestamp<?');
|
||||
$query->execute(array($user,$limit));
|
||||
}
|
||||
|
||||
/**
|
||||
* recursive copy to copy a whole directory
|
||||
*
|
||||
* @param $source source path, relative to the users files directory
|
||||
* @param $destination destination path relative to the users root directoy
|
||||
* @param $view file view for the users root directory
|
||||
*/
|
||||
private static function copy_recursive( $source, $destination, $view ) {
|
||||
if ( $view->is_dir( 'files'.$source ) ) {
|
||||
$view->mkdir( $destination );
|
||||
$view->touch($destination, $view->filemtime('files'.$source));
|
||||
foreach ( \OC_Files::getDirectoryContent($source) as $i ) {
|
||||
$pathDir = $source.'/'.$i['name'];
|
||||
if ( $view->is_dir('files'.$pathDir) ) {
|
||||
self::copy_recursive($pathDir, $destination.'/'.$i['name'], $view);
|
||||
} else {
|
||||
$view->copy( 'files'.$pathDir, $destination . '/' . $i['name'] );
|
||||
$view->touch($destination . '/' . $i['name'], $view->filemtime('files'.$pathDir));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$view->copy( 'files'.$source, $destination );
|
||||
$view->touch($destination, $view->filemtime('files'.$source));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find all versions which belong to the file we want to restore
|
||||
* @param $filename name of the file which should be restored
|
||||
* @param $timestamp timestamp when the file was deleted
|
||||
*/
|
||||
private static function getVersionsFromTrash($filename, $timestamp) {
|
||||
$view = new \OC_FilesystemView('/'.\OCP\User::getUser().'/versions_trashbin');
|
||||
$versionsName = \OCP\Config::getSystemValue('datadirectory').$view->getAbsolutePath($filename);
|
||||
$versions = array();
|
||||
|
||||
if ($timestamp ) {
|
||||
// fetch for old versions
|
||||
$matches = glob( $versionsName.'.v*.d'.$timestamp );
|
||||
$offset = -strlen($timestamp)-2;
|
||||
} else {
|
||||
$matches = glob( $versionsName.'.v*' );
|
||||
}
|
||||
|
||||
foreach( $matches as $ma ) {
|
||||
if ( $timestamp ) {
|
||||
$parts = explode( '.v', substr($ma, 0, $offset) );
|
||||
$versions[] = ( end( $parts ) );
|
||||
} else {
|
||||
$parts = explode( '.v', $ma );
|
||||
$versions[] = ( end( $parts ) );
|
||||
}
|
||||
}
|
||||
return $versions;
|
||||
}
|
||||
|
||||
/**
|
||||
* find unique extension for restored file if a file with the same name already exists
|
||||
* @param $location where the file should be restored
|
||||
* @param $filename name of the file
|
||||
* @param $view filesystem view relative to users root directory
|
||||
* @return string with unique extension
|
||||
*/
|
||||
private static function getUniqueExtension($location, $filename, $view) {
|
||||
$ext = '';
|
||||
if ( $view->file_exists('files'.$location.'/'.$filename) ) {
|
||||
$tmpext = '.restored';
|
||||
$ext = $tmpext;
|
||||
$i = 1;
|
||||
while ( $view->file_exists('files'.$location.'/'.$filename.$ext) ) {
|
||||
$ext = $tmpext.$i;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
return $ext;
|
||||
}
|
||||
|
||||
}
|
||||
34
apps/files_trashbin/templates/index.php
Normal file
34
apps/files_trashbin/templates/index.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<!--[if IE 8]><style>input[type="checkbox"]{padding:0;}table td{position:static !important;}</style><![endif]-->
|
||||
<div id="controls">
|
||||
<?php echo($_['breadcrumb']); ?>
|
||||
<div id="file_action_panel"></div>
|
||||
</div>
|
||||
<div id='notification'></div>
|
||||
|
||||
<?php if (isset($_['files']) && count($_['files'])==0):?>
|
||||
<div id="emptyfolder"><?php echo $l->t('Nothing in here. Your trash bin is empty!')?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th id='headerName'>
|
||||
<input type="checkbox" id="select_all" />
|
||||
<span class='name'><?php echo $l->t( 'Name' ); ?></span>
|
||||
<span class='selectedActions'>
|
||||
<a href="" class="undelete">
|
||||
<img class="svg" alt="<?php echo $l->t( 'Restore' ); ?>"
|
||||
src="<?php echo OCP\image_path("core", "actions/undelete.png"); ?>" />
|
||||
<?php echo $l->t('Restore')?>
|
||||
</a>
|
||||
</span>
|
||||
</th>
|
||||
<th id="headerDate">
|
||||
<span id="modified"><?php echo $l->t( 'Deleted' ); ?></span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="fileList">
|
||||
<?php echo($_['fileList']); ?>
|
||||
</tbody>
|
||||
</table>
|
||||
76
apps/files_trashbin/templates/part.list.php
Normal file
76
apps/files_trashbin/templates/part.list.php
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<input type="hidden" id="disableSharing" data-status="<?php echo $_['disableSharing']; ?>">
|
||||
<?php foreach($_['files'] as $file):
|
||||
$simple_file_size = OCP\simple_file_size($file['size']);
|
||||
// the bigger the file, the darker the shade of grey; megabytes*2
|
||||
$simple_size_color = intval(200-$file['size']/(1024*1024)*2);
|
||||
if($simple_size_color<0) $simple_size_color = 0;
|
||||
$relative_deleted_date = OCP\relative_modified_date($file['timestamp']);
|
||||
// the older the file, the brighter the shade of grey; days*14
|
||||
$relative_date_color = round((time()-$file['mtime'])/60/60/24*14);
|
||||
if($relative_date_color>200) $relative_date_color = 200;
|
||||
$name = str_replace('+', '%20', urlencode($file['name']));
|
||||
$name = str_replace('%2F', '/', $name);
|
||||
$directory = str_replace('+', '%20', urlencode($file['directory']));
|
||||
$directory = str_replace('%2F', '/', $directory); ?>
|
||||
<tr data-filename="<?php echo $file['name'];?>"
|
||||
data-type="<?php echo ($file['type'] == 'dir')?'dir':'file'?>"
|
||||
data-mime="<?php echo $file['mimetype']?>"
|
||||
data-permissions='<?php echo $file['permissions']; ?>'
|
||||
<?php if ( $_['dirlisting'] ): ?>
|
||||
id="<?php echo $file['directory'].'/'.$file['name'];?>"
|
||||
data-file="<?php echo $file['directory'].'/'.$file['name'];?>"
|
||||
data-timestamp=''
|
||||
data-dirlisting=1
|
||||
<?php else: ?>
|
||||
id="<?php echo $file['name'].'.d'.$file['timestamp'];?>"
|
||||
data-file="<?php echo $file['name'].'.d'.$file['timestamp'];?>"
|
||||
data-timestamp='<?php echo $file['timestamp'];?>'
|
||||
data-dirlisting=0
|
||||
<?php endif; ?>>
|
||||
<td class="filename svg"
|
||||
<?php if($file['type'] == 'dir'): ?>
|
||||
style="background-image:url(<?php echo OCP\mimetype_icon('dir'); ?>)"
|
||||
<?php else: ?>
|
||||
style="background-image:url(<?php echo OCP\mimetype_icon($file['mimetype']); ?>)"
|
||||
<?php endif; ?>
|
||||
>
|
||||
<?php if(!isset($_['readonly']) || !$_['readonly']): ?><input type="checkbox" /><?php endif; ?>
|
||||
<?php if($file['type'] == 'dir'): ?>
|
||||
<?php if( $_['dirlisting'] ): ?>
|
||||
<a class="name" href="<?php echo $_['baseURL'].'/'.$name; ?>" title="">
|
||||
<?php else: ?>
|
||||
<a class="name" href="<?php echo $_['baseURL'].'/'.$name.'.d'.$file['timestamp']; ?>" title="">
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<?php if( $_['dirlisting'] ): ?>
|
||||
<a class="name" href="<?php echo $_['downloadURL'].'/'.$name; ?>" title="">
|
||||
<?php else: ?>
|
||||
<a class="name" href="<?php echo $_['downloadURL'].'/'.$name.'.d'.$file['timestamp'];?>" title="">
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
<span class="nametext">
|
||||
<?php if($file['type'] == 'dir'):?>
|
||||
<?php echo htmlspecialchars($file['name']);?>
|
||||
<?php else:?>
|
||||
<?php echo htmlspecialchars($file['basename']);?><span
|
||||
class='extension'><?php echo $file['extension'];?></span>
|
||||
<?php endif;?>
|
||||
</span>
|
||||
<?php if($file['type'] == 'dir'):?>
|
||||
<span class="uploadtext" currentUploads="0">
|
||||
</span>
|
||||
<?php endif;?>
|
||||
</a>
|
||||
</td>
|
||||
<td class="date">
|
||||
<span class="modified"
|
||||
title="<?php echo $file['date']; ?>"
|
||||
style="color:rgb(<?php echo $relative_date_color.','
|
||||
.$relative_date_color.','
|
||||
.$relative_date_color ?>)">
|
||||
<?php echo $relative_deleted_date; ?>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach;
|
||||
|
||||
|
|
@ -12,5 +12,5 @@ OCP\Util::addscript('files_versions', 'versions');
|
|||
// Listen to write signals
|
||||
OCP\Util::connectHook('OC_Filesystem', 'write', "OCA_Versions\Hooks", "write_hook");
|
||||
// Listen to delete and rename signals
|
||||
OCP\Util::connectHook('OC_Filesystem', 'delete', "OCA_Versions\Hooks", "remove_hook");
|
||||
OCP\Util::connectHook('OC_Filesystem', 'post-delete', "OCA_Versions\Hooks", "remove_hook");
|
||||
OCP\Util::connectHook('OC_Filesystem', 'rename', "OCA_Versions\Hooks", "rename_hook");
|
||||
|
|
@ -102,6 +102,9 @@ $CONFIG = array(
|
|||
/* Password to use for sendmail mail, depends on mail_smtpauth if this is used */
|
||||
"mail_smtppassword" => "",
|
||||
|
||||
/* How long should ownCloud keep deleted files in the trash bin, default value: 180 days */
|
||||
'trashbin_retention_obligation' => 180,
|
||||
|
||||
/* Check 3rdparty apps for malicious code fragments */
|
||||
"appcodechecker" => "",
|
||||
|
||||
|
|
|
|||
BIN
core/img/actions/undelete.png
Normal file
BIN
core/img/actions/undelete.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 624 B |
Loading…
Reference in a new issue