mirror of
https://github.com/misterunknown/ifm.git
synced 2025-09-01 03:41:43 +02:00
added copy and move functionality for files and directories, disable logging for every keystroke
This commit is contained in:
@@ -27,6 +27,7 @@ class IFMConfig {
|
||||
const createdir = 1; // allow to create directorys
|
||||
const createfile = 1; // allow to create files
|
||||
const zipnload = 1; // allow to zip and download directorys
|
||||
const copymove = 1; // allow to copy and move files and directories
|
||||
|
||||
// view controls
|
||||
const multiselect = 1; // implement multiselect of files and directories
|
||||
|
80
src/ifm.js
80
src/ifm.js
@@ -104,7 +104,7 @@ function IFM() {
|
||||
if( self.config.showgroup > 0 )
|
||||
newRow += '<td class="hidden-xs hidden-sm hidden-md">' + data[i].group + '</td>';
|
||||
// actions
|
||||
if( self.inArray( 1, [self.config.edit, self.config.rename, self.config.delete, self.config.extract] ) ) {
|
||||
if( self.inArray( 1, [self.config.edit, self.config.rename, self.config.delete, self.config.extract, self.config.copymove] ) ) {
|
||||
newRow += '<td>';
|
||||
if( data[i].name.toLowerCase().substr(-4) == ".zip" && self.config.extract == 1 ) {
|
||||
newRow += '<a tabindex="0" onclick="ifm.extractFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-archive" title="extract"></span></a>';
|
||||
@@ -112,6 +112,9 @@ function IFM() {
|
||||
newRow += '<a tabindex="0" onclick="ifm.editFile(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-pencil" title="edit"></span></a>';
|
||||
}
|
||||
if( data[i].name != ".." && data[i].name != "." ) {
|
||||
if( self.config.copymove == 1 ) {
|
||||
newRow += '<a tabindex="0" onclick="ifm.copyMoveDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-folder-open-empty" title="copy/move"></span></a>';
|
||||
}
|
||||
if( self.config.rename == 1 )
|
||||
newRow += '<a tabindex="0" onclick="ifm.renameFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-terminal" title="rename"></span></a>';
|
||||
if( self.config.delete == 1 )
|
||||
@@ -140,7 +143,6 @@ function IFM() {
|
||||
};
|
||||
|
||||
this.changeDirectory = function( newdir, options={} ) {
|
||||
console.log( "changeDirectory, newdir="+newdir );
|
||||
config = { absolute: false, pushState: true };
|
||||
jQuery.extend( config, options );
|
||||
if( ! config.absolute ) newdir = self.pathCombine( self.currentDir, newdir );
|
||||
@@ -385,6 +387,78 @@ function IFM() {
|
||||
});
|
||||
};
|
||||
|
||||
this.copyMove = function( source, destination, action ) {
|
||||
var id=self.generateGuid();
|
||||
self.task_add(action.charAt(0).toUpperCase()+action.slice(1)+" "+source+" to "+destination, id);
|
||||
$.ajax({
|
||||
url: self.IFM_SCFN,
|
||||
type: "POST",
|
||||
data: ({
|
||||
dir: self.currentDir,
|
||||
api: "copyMove",
|
||||
action: action,
|
||||
filename: source,
|
||||
destination: destination
|
||||
}),
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if( data.status == "OK" ) {
|
||||
self.showMessage( data.message, "s" );
|
||||
} else {
|
||||
self.showMessage( data.message, "e" );
|
||||
}
|
||||
self.refreshFileTable();
|
||||
},
|
||||
error: function() {
|
||||
self.showMessage( "General error occured.", "e" );
|
||||
},
|
||||
complete: function() {
|
||||
self.task_done(id);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.copyMoveDialog = function(name) {
|
||||
self.showModal( '<form id="copyMoveFile"><fieldset>\
|
||||
<div class="modal-body">\
|
||||
<label>Select destination:</label>\
|
||||
<div id="copyMoveTree"><span class="icon icon-spin5"></span></div>\
|
||||
</div>\
|
||||
<div class="modal-footer">\
|
||||
<button type="button" class="btn btn-default" id="copyButton">copy</button>\
|
||||
<button type="button" class="btn btn-default" id="moveButton">move</button>\
|
||||
<button type="button" class="btn btn-default" id="cancelButton">cancel</button>\
|
||||
</div>\
|
||||
</fieldset></form>');
|
||||
$.ajax({
|
||||
url: ifm.IFM_SCFN,
|
||||
type: "POST",
|
||||
data: ({
|
||||
api: "getFolderTree",
|
||||
dir: ifm.currentDir
|
||||
}),
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
$('#copyMoveTree').treeview({data: data, levels: 0, expandIcon: "icon icon-folder-empty", collapseIcon: "icon icon-folder-open-empty"});
|
||||
},
|
||||
error: function() { self.hideModal(); self.showMessage( "Error while fetching the folder tree.", "e" ) }
|
||||
});
|
||||
$('#copyButton').on( 'click', function(e) {
|
||||
self.copyMove( name, $('#copyMoveTree .node-selected').data('path'), 'copy' );
|
||||
self.hideModal();
|
||||
return false;
|
||||
});
|
||||
$('#moveButton').on( 'click', function(e) {
|
||||
self.copyMove( name, $('#copyMoveTree .node-selected').data('path'), 'move' );
|
||||
self.hideModal();
|
||||
return false;
|
||||
});
|
||||
$('#cancelButton').on( 'click', function(e) {
|
||||
self.hideModal();
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
this.extractFileDialog = function(name) {
|
||||
var targetDirSuggestion="";
|
||||
if(name.lastIndexOf(".") > 1)
|
||||
@@ -819,8 +893,6 @@ function IFM() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
console.log( "key: "+e.key );
|
||||
}
|
||||
|
||||
// initialization
|
||||
|
1
src/includes/bootstrap-treeview.min.css
vendored
Normal file
1
src/includes/bootstrap-treeview.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}
|
1
src/includes/bootstrap-treeview.min.js
vendored
Normal file
1
src/includes/bootstrap-treeview.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
109
src/main.php
109
src/main.php
@@ -35,6 +35,7 @@ class IFM {
|
||||
<style type="text/css">';?> @@@src/includes/bootstrap.min.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/includes/ekko-lightbox.min.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/includes/fontello-embedded.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/includes/bootstrap-treeview.min.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/style.css@@@ <?php print '</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -113,6 +114,7 @@ class IFM {
|
||||
<script>';?> @@@src/includes/bootstrap.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/includes/bootstrap-notify.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/includes/ekko-lightbox.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/includes/bootstrap-treeview.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/ifm.js@@@ <?php print '</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -146,11 +148,17 @@ class IFM {
|
||||
case "downloadFile": $this->downloadFile( $_REQUEST ); break;
|
||||
case "extractFile": $this->extractFile( $_REQUEST ); break;
|
||||
case "uploadFile": $this->uploadFile( $_REQUEST ); break;
|
||||
case "copyMove": $this->copyMove( $_REQUEST ); break;
|
||||
case "changePermissions": $this->changePermissions( $_REQUEST ); break;
|
||||
case "zipnload": $this->zipnload( $_REQUEST); break;
|
||||
case "remoteUpload": $this->remoteUpload( $_REQUEST ); break;
|
||||
case "deleteMultipleFiles": $this->deleteMultipleFiles( $_REQUEST ); break;
|
||||
default: echo json_encode(array("status"=>"ERROR", "message"=>"No valid api action given")); break;
|
||||
case "getFolderTree":
|
||||
echo json_encode( array_merge( array( 0 => array( "text" => "/ [root]", "nodes" => array(), "dataAttributes" => array( "path" => realpath( IFMConfig::root_dir ) ) ) ), $this->getFolderTreeRecursive( IFMConfig::root_dir ) ) );
|
||||
break;
|
||||
default:
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No valid api action given" ) );
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
print json_encode(array("status"=>"ERROR", "message"=>"No valid working directory"));
|
||||
@@ -248,6 +256,58 @@ class IFM {
|
||||
echo json_encode( array_merge( $dirs, $files ) );
|
||||
}
|
||||
|
||||
private function getFolderTreeRecursive( $start_dir ) {
|
||||
$ret = array();
|
||||
$start_dir = realpath( $start_dir );
|
||||
if( $handle = opendir( $start_dir ) ) {
|
||||
while (false !== ( $result = readdir( $handle ) ) ) {
|
||||
if( is_dir( $this->pathCombine( $start_dir, $result ) ) && $result != "." && $result != ".." ) {
|
||||
array_push( $ret, array( "text" => $result, "dataAttributes" => array( "path" => $this->pathCombine( $start_dir, $result ) ), "nodes" => $this->getFolderTreeRecursive( $this->pathCombine( $start_dir, $result ) ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
sort( $ret );
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private function copyMove( $d ) {
|
||||
if( IFMConfig::copymove != 1 ) {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No permission to copy or move files." ) );
|
||||
exit( 1 );
|
||||
}
|
||||
$this->chDirIfNecessary( $d['dir'] );
|
||||
if( ! isset( $d['destination'] ) || ! $this->isPathValid( realpath( $d['destination'] ) ) ) {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No valid destination directory given." ) );
|
||||
exit( 1 );
|
||||
}
|
||||
if( ! file_exists( $d['filename'] ) ) {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No valid filename given." ) );
|
||||
exit( 1 );
|
||||
}
|
||||
if( $d['action'] == "copy" ) {
|
||||
if( $this->copyr( $d['filename'], $d['destination'] ) ) {
|
||||
echo json_encode( array( "status" => "OK", "message" => "File(s) were successfully copied." ) );
|
||||
exit( 0 );
|
||||
} else {
|
||||
$err = error_get_last();
|
||||
echo json_encode( array( "status" => "ERROR", "message" => $err['message'] ) );
|
||||
exit( 1 );
|
||||
}
|
||||
} elseif( $d['action'] == "move" ) {
|
||||
if( rename( $d['filename'], $this->pathCombine( $d['destination'], basename( $d['filename'] ) ) ) ) {
|
||||
echo json_encode( array( "status" => "OK", "message" => "File(s) were successfully moved." ) );
|
||||
exit( 0 );
|
||||
} else {
|
||||
$err = error_get_last();
|
||||
echo json_encode( array( "status" => "ERROR", "message" => $err['message'] ) );
|
||||
exit( 1 );
|
||||
}
|
||||
} else {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No valid action given." ) );
|
||||
exit( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// creates a directory
|
||||
private function createDir($w, $dn) {
|
||||
if( $dn == "" ) {
|
||||
@@ -788,6 +848,53 @@ class IFM {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file, or recursively copy a folder and its contents
|
||||
*
|
||||
* @author Aidan Lister <aidan@php.net>
|
||||
* @version 1.0.1
|
||||
* @link http://aidanlister.com/2004/04/recursively-copying-directories-in-php/
|
||||
* @param string $source Source path
|
||||
* @param string $dest Destination path
|
||||
* @return bool Returns TRUE on success, FALSE on failure
|
||||
*/
|
||||
private function copyr( $source, $dest )
|
||||
{
|
||||
// Check for symlinks
|
||||
if (is_link($source)) {
|
||||
return symlink(readlink($source), $dest);
|
||||
}
|
||||
|
||||
// Simple copy for a file
|
||||
if (is_file($source)) {
|
||||
$dest = ( is_dir( $dest ) ) ? $this->pathCombine( $dest, basename( $source ) ) : $dest;
|
||||
return copy($source, $dest);
|
||||
} else {
|
||||
$dest = $this->pathCombine( $dest, basename( $source ) );
|
||||
}
|
||||
|
||||
// Make destination directory
|
||||
if (!is_dir($dest)) {
|
||||
mkdir($dest);
|
||||
}
|
||||
|
||||
// Loop through the folder
|
||||
$dir = dir($source);
|
||||
while (false !== $entry = $dir->read()) {
|
||||
// Skip pointers
|
||||
if ($entry == '.' || $entry == '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Deep copy directories
|
||||
$this->copyr("$source/$entry", "$dest/$entry");
|
||||
}
|
||||
|
||||
// Clean up
|
||||
$dir->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
// combines two parts to a valid path
|
||||
private function pathCombine( $a, $b ) {
|
||||
if( trim( $a ) == "" && trim( $b ) == "" )
|
||||
|
Reference in New Issue
Block a user