FileManger stuff

This commit is contained in:
Serghey Rodin 2015-10-05 23:32:25 +03:00
parent b6dd534b60
commit 52db853acf
11 changed files with 417 additions and 131 deletions

54
bin/v-check-fs-permission Executable file
View file

@ -0,0 +1,54 @@
#!/bin/bash
# info: open file
# options: USER FILE
#
# The function opens/reads files on the file system
user=$1
src_file=$2
# Checking arguments
if [ -z "$src_file" ]; then
echo "Usage: USER FILE"
exit 1
fi
# Checking vesta user
if [ ! -e "$VESTA/data/users/$user" ]; then
echo "Error: vesta user $user doesn't exist"
exit 3
fi
# Checking user homedir
homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :)
if [ -z $homedir ]; then
echo "Error: user home directory doesn't exist"
exit 12
fi
# Checking path
if [ ! -z "$src_file" ]; then
rpath=$(readlink -f "$src_file")
if [ -z "$(echo $rpath |egrep "^/tmp|^$homedir")" ]; then
echo "Error: invalid source path $src_file"
exit 2
fi
fi
# Reading file
#sudo -u $user cat "$src_file" 2>/dev/null
#if [ $? -ne 0 ]; then
# echo "Error: file $src_file was not opened"
# exit 3
#fi
# Checking if file has readable permission
if [[ ! -r $src_file ]]
then
# echo "File is readable"
#else
echo "Cannot read file"
fi
# Exiting
exit

View file

@ -2787,3 +2787,56 @@ form#vstobjects.suspended {
text-align: right;
width: 140px;
}
.description {
font-weight: normal;
line-height: 25px;
padding-bottom: 20px;
margin-left: 50px;
}
.description ul{
margin-top: 15px;
list-style: none;
padding-left: 0;
}
.description li{
margin: 10px 0;
}
.description a {
line-height: 30px;
text-decoration: underline;
color: #2c9491;
}
.description a.purchase {
color: #86A307;
background-color: #9fbf0c;
border-radius: 3px;
color: #fff;
font-size: 13px;
font-weight: bold;
padding: 7px;
text-transform: capitalize;
text-decoration: none;
}
.description a.purchase:hover {
background-color: #c0e60f;
color: #555;
}
.description .licence {
padding: 20px 0;
color: #2c9491;
}
.description .licence input {
margin-left: 17px;
width: 137px;
}
.description span {
font-style: italic;
line-height: 45px;
padding-top: 20px;
}

View file

@ -3,6 +3,17 @@ session_start();
include($_SERVER['DOCUMENT_ROOT']."/inc/main.php");
/*
if (empty($panel)) {
$command = VESTA_CMD."v-list-user '".$user."' 'json'";
exec ($command, $output, $return_var);
if ( $return_var > 0 ) {
header("Location: /error/");
exit;
}
$panel = json_decode(implode('', $output), true);
}
*/
/*
// Check user session
if ((!isset($_SESSION['user'])) && (!defined('NO_AUTH_REQUIRED'))) {
$_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
@ -23,13 +34,15 @@ if ((!isset($_SESSION['user'])) && (!defined('NO_AUTH_REQUIRED'))) {
<script src="/js/cheef-editor/ace/mode-ruby.js"></script>
<script src="/js/cheef-editor/jquery-ace.min.js"></script>
<div id="message" style="display:none; position: absoulte;background-color: green; color: white; padding: 10px;"></div>
<div id="error-message" style="display:none; position: absoulte;background-color: red; color: white; padding: 10px;"></div>
<?php
if (!empty($_REQUEST['path'])) {
$content = '';
$path = $_REQUEST['path'];
if (is_readable($path)) {
$image = getimagesize($path) ? true : false;
if ($image) {
@ -49,8 +62,16 @@ if ((!isset($_SESSION['user'])) && (!defined('NO_AUTH_REQUIRED'))) {
}
}
$content = file_get_contents($path);
$content = $content;
// $content = file_get_contents($path);
// v-open-fs-file
exec (VESTA_CMD . "v-open-fs-file {$user} {$path}", $content, $return_var);
if ($return_var != 0) {
print 'Error while opening file'; // todo: handle this more styled
exit;
}
$content = implode("\n", $content);
}
}
else {
@ -59,18 +80,78 @@ if ((!isset($_SESSION['user'])) && (!defined('NO_AUTH_REQUIRED'))) {
?>
<form method="post">
<form id="edit-file-form" method="post">
<!-- input id="do-backup" type="button" onClick="javascript:void(0);" name="save" value="backup (ctrl+F2)" class="backup" / -->
<input type="submit" name="save" value="Save" class="save" />
<textarea name="contents" class="editor" id="editor" rows="4" style="display:none;width: 100%; height: 100%;"><?php echo $content ?></textarea>
</form>
<script>
$('.editor').ace({ theme: 'twilight', lang: 'ruby' });
var dcrt = $('#editor').data('ace');
var editor = dcrt.editor.ace;
editor.gotoLine(0);
editor.focus();
<script type="text/javascript" src="/js/hotkeys.js"></script>
<script type="text/javascript">
$('.editor').ace({ theme: 'twilight', lang: 'ruby' });
var dcrt = $('#editor').data('ace');
var editor = dcrt.editor.ace;
editor.gotoLine(0);
editor.focus();
var makeBackup = function() {
var params = {
action: 'backup',
path: '<?= $path ?>'
};
$.ajax({url: "/file_manager/fm_api.php",
method: "POST",
data: params,
dataType: 'JSON',
success: function(reply) {
var fadeTimeout = 3000;
if (reply.result) {
$('#message').text('File backed up as ' + reply.filename);
clearTimeout(window.msg_tmt);
$('#message').show();
window.msg_tmt = setTimeout(function() {$('#message').fadeOut();}, fadeTimeout);
}
else {
$('#error-message').text(reply.message);
clearTimeout(window.errmsg_tmt);
$('#error-message').show();
window.errmsg_tmt = setTimeout(function() {$('#error-message').fadeOut();}, fadeTimeout);
}
}
});
}
$('#do-backup').on('click', function(evt) {
evt.preventDefault();
makeBackup();
});
//
// Shortcuts
//
shortcut.add("Ctrl+s",function() {
var inp = $('<input>').attr({'type': 'hidden', 'name': 'save'}).val('Save');
$('#edit-file-form').append(inp);
$('#edit-file-form').submit();
},{
'type': 'keydown',
'propagate': false,
'disable_in_input': false,
'target': document
});
shortcut.add("Ctrl+F2",function() {
makeBackup();
},{
'type': 'keydown',
'propagate': false,
'disable_in_input': false,
'target': document
});
</script>

View file

@ -97,6 +97,10 @@ switch ($_REQUEST['action']) {
$item = $_REQUEST['item'];
print json_encode($fm->packItem($item, $dir, $target_dir, $filename));
break;
case 'backup':
$path = $_REQUEST['path'];
print json_encode($fm->backupItem($path));
break;
default:
//print json_encode($fm->init());
break;

View file

@ -207,6 +207,47 @@ class FileManager {
}
}
function backupItem($item) {
$src_item = $this->formatFullPath($item);
$dst_item_name = $item . '~' . date('Ymd_His');
$dst_item = $this->formatFullPath($dst_item_name);
//print VESTA_CMD . "v-add-fs-archive {$this->user} {$item} {$dst_item}";die();
exec (VESTA_CMD . "v-copy-fs-file {$this->user} {$src_item} {$dst_item}", $output, $return_var);
$error = self::check_return_code($return_var, $output);
if (empty($error)) {
return array(
'result' => true,
'filename' => $dst_item_name
);
}
else {
return array(
'result' => false,
'message' => $error
);
}
$error = self::check_return_code($return_var, $output);
if (empty($error)) {
return array(
'result' => true
);
}
else {
return array(
'result' => false,
'message' => $error
);
}
}
function unpackItem($item, $dir, $target_dir, $filename) {
$item = $this->formatFullPath($item);
$dst_item = $this->formatFullPath($target_dir);

View file

@ -1,25 +1,38 @@
<?php
include($_SERVER['DOCUMENT_ROOT']."/inc/main.php");
// todo: set in session?
if (empty($panel)) {
$command = VESTA_CMD."v-list-user '".$user."' 'json'";
exec ($command, $output, $return_var);
if ( $return_var > 0 ) {
header("Location: /error/");
exit;
}
$panel = json_decode(implode('', $output), true);
}
// Define a destination
$targetFolder = '/home/admin/'; // Relative to the root
//$targetFolder = '/home/admin/'; // Relative to the root
$targetFolder = $panel[$user]['HOME']; // Relative to the root
$verifyToken = md5('unique_salt' . $_POST['timestamp']);
if (!empty($_FILES) && $_POST['token'] == $verifyToken) {
$tempFile = $_FILES['Filedata']['tmp_name'];
$targetPath = $targetFolder;
$targetFile = rtrim($targetPath,'/') . '/' . $_FILES['Filedata']['name'];
$tempFile = $_FILES['Filedata']['tmp_name'];
$targetPath = $targetFolder;
$targetFile = rtrim($targetPath,'/') . '/' . $_FILES['Filedata']['name'];
// Validate the file type
//$fileTypes = array('jpg','jpeg','gif','png'); // File extensions
//$fileParts = pathinfo($_FILES['Filedata']['name']);
exec (VESTA_CMD . "v-copy-fs-file {$user} {$tempFile} {$targetFile}", $output, $return_var);
//if (in_array($fileParts['extension'],$fileTypes)) {
move_uploaded_file($tempFile,$targetFile);
echo '1';
//} else {
// echo 'Invalid file type.';
// }
$error = self::check_return_code($return_var, $output);
if ($return_var != 0) {
echo '0';
} else {
echo '1';
}
}
?>

View file

@ -56,7 +56,7 @@ FM.EDITABLE_MIMETYPES = [
'application/epp+xml',
'application/javascript',
'application/json',
'application/jsonml+json ',
'application/jsonml+json ',
'application/lost+xml',
'application/marc',
'application/msword',
@ -219,9 +219,9 @@ FM.setSecondInactive = function(index, box) {
}
FM.goBackwards = function() {
if (FM.isPopupOpened()) {
return;
}
if (FM.isPopupOpened()) {
return;
}
var tab = FM.getTabLetter(FM.CURRENT_TAB);
var box = FM['TAB_' + tab];
@ -234,12 +234,12 @@ FM.goBackwards = function() {
}
FM.goToTop = function() {
if (FM.isPopupOpened()) {
return;
}
if (FM.isPopupOpened()) {
return;
}
if (FM.isPopupOpened()) {
return;
}
if (FM.isPopupOpened()) {
return;
}
var tab = FM.getTabLetter(FM.CURRENT_TAB);
var index = 0;
@ -248,9 +248,9 @@ FM.goToTop = function() {
}
FM.goToBottom = function() {
if (FM.isPopupOpened()) {
return;
}
if (FM.isPopupOpened()) {
return;
}
var tab = FM.getTabLetter(FM.CURRENT_TAB);
var index = $(FM.CURRENT_TAB).find('.dir').length - 1;
@ -258,9 +258,9 @@ FM.goToBottom = function() {
}
FM.goUp = function() {
if (FM.isPopupOpened()) {
return;
}
if (FM.isPopupOpened()) {
return;
}
var tab = FM.getTabLetter(FM.CURRENT_TAB);
var index = FM['CURRENT_' + tab + '_LINE'];
index -= 1;
@ -275,9 +275,9 @@ FM.goUp = function() {
}
FM.goDown = function() {
if (FM.isPopupOpened()) {
return;
}
if (FM.isPopupOpened()) {
return;
}
var tab = FM.getTabLetter(FM.CURRENT_TAB);
var index = FM['CURRENT_' + tab + '_LINE'];
@ -295,27 +295,27 @@ FM.goDown = function() {
// reloads provided tab
// reloads opposite tab if its needed
FM.openAndSync = function(dir, box, callback) {
var tab = FM.getTabLetter(box);
var tab = FM.getTabLetter(box);
var opposite_tab = 'A';
if (tab == 'A') {
opposite_tab = 'B';
}
var opposite_tab = 'A';
if (tab == 'A') {
opposite_tab = 'B';
}
var oppositeSyncNeeded = false;
var oppositeSyncNeeded = false;
if (FM.TAB_A_CURRENT_PATH == FM.TAB_B_CURRENT_PATH) {
oppositeSyncNeeded = true;
}
if (FM.TAB_A_CURRENT_PATH == FM.TAB_B_CURRENT_PATH) {
oppositeSyncNeeded = true;
}
if (oppositeSyncNeeded) {
FM.open(dir, FM['TAB_' + opposite_tab], callback);
return FM.open(dir, box, callback);
}
else {
return FM.open(dir, box, callback);
}
if (oppositeSyncNeeded) {
FM.open(dir, FM['TAB_' + opposite_tab], callback);
return FM.open(dir, box, callback);
}
else {
return FM.open(dir, box, callback);
}
}
@ -691,11 +691,11 @@ FM.generate_listing = function(reply, box) {
////////
/*if (FM['CURRENT_'+tab+'_LINE'] > -1 && $(box).find('.dir:eq(' + FM['CURRENT_'+tab+'_LINE'] + ')').lrngth > 0) {
}
else {
FM['CURRENT_'+tab+'_LINE'] = -1;
}*/
FM['CURRENT_'+tab+'_LINE'] = -1;
}
else {
FM['CURRENT_'+tab+'_LINE'] = -1;
}*/
FM['CURRENT_'+tab+'_LINE'] = -1;
}
FM.toggleCheck = function(uid) {
@ -958,9 +958,9 @@ FM.toggleAllItemsSelected = function() {
}
FM.selectCurrentElementAndGoToNext = function () {
if (FM.isPopupOpened()) {
return;
}
if (FM.isPopupOpened()) {
return;
}
var tab = FM.getTabLetter(FM.CURRENT_TAB);
var box = FM['TAB_' + tab];
@ -1106,7 +1106,7 @@ FM.unpackItem = function() {
var tpl = Tpl.get('popup_unpack', 'FM');
tpl.set(':FILENAME', src.name);
tpl.set(':DST_DIRNAME', dst + '/' + src.name + '_extracted');
tpl.set(':DST_DIRNAME', dst + '/' + src.name);
FM.popupOpen(tpl.finalize());
}
@ -1151,9 +1151,9 @@ FM.packItem = function() {
FM.switchTab = function() {
if (FM.isPopupOpened()) {
return;
}
if (FM.isPopupOpened()) {
return;
}
if (FM.CURRENT_TAB == FM.TAB_A) {
FM.setTabActive(FM.TAB_B);
@ -1264,12 +1264,12 @@ FM.renameItems = function() {
}
FM.isPopupOpened = function() {
return $('#popup').length > 0 ? true : false;
return $('#popup').length > 0 ? true : false;
}
FM.popupOpen = function(html) {
FM.popupClose();
//$('#popup').flayer_close();
FM.popupClose();
//$('#popup').flayer_close();
$('<div>').attr('id', 'popup').html(html).flayer({
afterStart: function(elm) {
elm.find('input[type="text"]:first').focus();
@ -1601,11 +1601,11 @@ FM.displayError = function(msg) {
}
FM.triggerRefreshActionTrick = function() {
// reload-in-time
$('#reload-in-time').remove();
FM.Env.RELOAD_IN_TIME = true;
var tpl = Tpl.get('reload_in_time', 'FM');
//tpl.set(':TIME_LEFT', FM.RELOAD_IN_TIME_SECONDS + 1);
// reload-in-time
$('#reload-in-time').remove();
FM.Env.RELOAD_IN_TIME = true;
var tpl = Tpl.get('reload_in_time', 'FM');
//tpl.set(':TIME_LEFT', FM.RELOAD_IN_TIME_SECONDS + 1);
$('body').append(tpl.finalize());
@ -1614,14 +1614,14 @@ FM.triggerRefreshActionTrick = function() {
var timeleft = FM.RELOAD_IN_TIME_SECONDS;
FM.Env.reload_in_time_interval =
setInterval(function() {
if (timeleft <= 0) {
clearInterval(FM.Env.reload_in_time_interval);
$('#reload-in-time').remove();
FM.Env.RELOAD_IN_TIME = false;
}
//ref.text(timeleft);
timeleft -= 1;
}, 1000);
if (timeleft <= 0) {
clearInterval(FM.Env.reload_in_time_interval);
$('#reload-in-time').remove();
FM.Env.RELOAD_IN_TIME = false;
}
//ref.text(timeleft);
timeleft -= 1;
}, 1000);
}
@ -1808,7 +1808,7 @@ $(document).ready(function() {
shortcut.add("Esc",function() {
FM.Env.RELOAD_IN_TIME = false;
FM.Env.RELOAD_IN_TIME = false;
$('#reload-in-time').remove();
if (FM.isPopupOpened()) {
return FM.handlePopupCancel();
@ -1839,14 +1839,14 @@ $(document).ready(function() {
});
shortcut.add("Left",function() {
if (!FM.isPopupOpened()) {
FM.setTabActive(FM.TAB_A);
if (!FM.isPopupOpened()) {
FM.setTabActive(FM.TAB_A);
var tab = FM.getTabLetter(FM.CURRENT_TAB);
if (FM['CURRENT_' + tab + '_LINE'] == -1) {
FM.setActive(0, FM.CURRENT_TAB);
}
}
var tab = FM.getTabLetter(FM.CURRENT_TAB);
if (FM['CURRENT_' + tab + '_LINE'] == -1) {
FM.setActive(0, FM.CURRENT_TAB);
}
}
},{
'type': 'keydown',
'propagate': false,
@ -1855,14 +1855,14 @@ $(document).ready(function() {
});
shortcut.add("Right",function() {
if (!FM.isPopupOpened()) {
FM.setTabActive(FM.TAB_B);
if (!FM.isPopupOpened()) {
FM.setTabActive(FM.TAB_B);
var tab = FM.getTabLetter(FM.CURRENT_TAB);
if (FM['CURRENT_' + tab + '_LINE'] == -1) {
FM.setActive(0, FM.CURRENT_TAB);
}
}
var tab = FM.getTabLetter(FM.CURRENT_TAB);
if (FM['CURRENT_' + tab + '_LINE'] == -1) {
FM.setActive(0, FM.CURRENT_TAB);
}
}
},{
'type': 'keydown',
@ -2000,14 +2000,14 @@ $(document).ready(function() {
'target': document
});
shortcut.add("F5",function() {
if (FM.Env.RELOAD_IN_TIME == true) {
location.reload();
return;
}
else {
FM.copyItems();
FM.triggerRefreshActionTrick();
}
if (FM.Env.RELOAD_IN_TIME == true) {
location.reload();
return;
}
else {
FM.copyItems();
FM.triggerRefreshActionTrick();
}
},{
'type': 'keydown',
'propagate': false,
@ -2043,8 +2043,8 @@ $(document).ready(function() {
});
/*shortcut.add("Y",function() {
if (FM.Env.RELOAD_IN_TIME == true) {
location.reload();
}
location.reload();
}
},{
'type': 'keydown',
'propagate': false,
@ -2053,9 +2053,9 @@ $(document).ready(function() {
});*/
shortcut.add("u",function() {
var tab_letter = FM.getTabLetter(FM.CURRENT_TAB);
$('#file_upload_'+tab_letter).trigger('click');
shortcut.add("u",function() {
var tab_letter = FM.getTabLetter(FM.CURRENT_TAB);
$('#file_upload_'+tab_letter).trigger('click');
},{
'type': 'keydown',
'propagate': false,

View file

@ -3,9 +3,12 @@
define('NO_AUTH_REQUIRED',true);
// Main include
include($_SERVER['DOCUMENT_ROOT']."/inc/main.php");
//echo $_SESSION['request_uri'];
$TAB = 'LOGIN';

View file

@ -684,8 +684,21 @@
<td>
<select class="vst-list" name="v_filemanager">
<option value='no'><?php print __('no'); ?></option>
<option value='yes'><?php print __('yes'); ?></option>
</select>
<br><br>
<div class="filemanager description" style="display:none">
Web Filemanager is a commercial module. By purchasing it you not only get powerfull filemanagement tool but also help VestaCP get better and stronger.<br>
You can see the bref video review of the module functionality.<br>
<span>(to try it free for a week please use "TMKE765" as a licence key)</span>
<div class="licence">
To activate filemanager insert licence key: <input type="text" class="vst-input" name="v_filemanager_licence" /><br>
</div>
<ul>
<li><a class="purchase" href="read.com">get monthly licence 3$/month</a></li>
<li><a class="purchase" href="read.com">get forever licence 50$</a></li>
</ul>
</div>
</td>
</tr>
</table>
@ -700,7 +713,7 @@
<input type="submit" class="button" name="save" value="<?php print __('Save');?>">
</td>
<td class="step-top">
<input type="button" class="button" value="<?php print __('Back');?>" onclick="<?php echo $back ?>">
<input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="<?php echo $back ?>">
</td>
</tr>
</table>
@ -709,3 +722,15 @@
</table>
</form>
</div>
<script>
$(document).ready(function(){
$('select[name=v_filemanager]').change(function(){
if($(this).val() == 'yes'){
$('.filemanager.description').show();
} else {
$('.filemanager.description').hide();
}
});
});
</script>

View file

@ -475,6 +475,8 @@
FM['CURRENT_A_LINE'] = 0;
}
FM.preselectedItems.A = [];
/*FM.setTabActive(FM.TAB_A, 'skip_highlights');
$(".listing-left .selected, .listing-left .ui-selectee").each(function(i, o) {
if (!$(o).hasClass('ui-selected')) {
@ -539,6 +541,8 @@
FM['CURRENT_B_LINE'] = 0;
}
FM.preselectedItems.B = [];
},
unselected: function (event, ui) {
FM.setTabActive(FM.TAB_B, 'skip_highlights');

View file

@ -1,7 +1,17 @@
<?php
include($_SERVER['DOCUMENT_ROOT']."/inc/main.php");
if (!empty($_REQUEST['path'])) {
$path = $_REQUEST['path'];
if (is_readable($path) && !empty($_REQUEST['raw'])) {
//print file_get_contents($path);
exec (VESTA_CMD . "v-check-fs-permission {$user} {$path}", $content, $return_var);
if ($return_var != 0) {
print 'Error while opening file'; // todo: handle this more styled
exit;
}
header('content-type: image/jpeg');
print file_get_contents($path);
exit;
@ -11,22 +21,20 @@ else {
die('File not found');
}
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>fotorama</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/fotorama/4.6.2/fotorama.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/fotorama/4.6.2/fotorama.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/fotorama/4.6.2/fotorama.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/fotorama/4.6.2/fotorama.js"></script>
</head>
<body>
<div style="background-color: #eee; /*display: inline-block; vertical-align: middle;*/ height: 100%; text-align: center; /*position: absolute; /*top: 50%; left: 50%; margin-top: -50px; margin-left: -50px; /*data-maxheight="100%" data-maxwidth="100%" */"
class="fotoram" data-fit="scaledown" data-allowfullscreen="true" data-nav="false">
<img src="/view/file/?path=<?=$path?>&raw=true" style="background: #3A6F9A; vertical-align: middle; /*max-height: 25px; max-width: 160px;*/" />
class="fotoram" data-fit="scaledown" data-allowfullscreen="true" data-nav="false">
<img src="/view/file/?path=<?=$path?>&raw=true" style="background: #3A6F9A; vertical-align: middle; /*max-height: 25px; max-width: 160px;*/" />
</div>
</body>
</html>