diff --git a/ifm.php b/ifm.php index 023f233..4c9ccbe 100644 --- a/ifm.php +++ b/ifm.php @@ -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 @@ -174,7 +175,7 @@ error_reporting( E_ALL ); ini_set( 'display_errors', 'OFF' ); class IFM { - const VERSION = '2.3.1'; + const VERSION = '2.4.0'; public function __construct() { session_start(); @@ -306,6 +307,8 @@ class IFM { .icon-file-code:before { content: '\f1c9'; } /* '' */ .icon-sliders:before { content: '\f1de'; } /* '' */ .icon-trash:before { content: '\f1f8'; } /* '' */ + ").appendTo("head")},d.prototype.buildStyle=function(){var e=".node-"+this.elementId+"{";return this.options.color&&(e+="color:"+this.options.color+";"),this.options.backColor&&(e+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(e+="border:1px solid "+this.options.borderColor+";"):e+="border:none;",e+="}",this.options.onhoverColor&&(e+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+e},d.prototype.template={list:'',item:'
  • ',indent:'',icon:'',link:'',badge:''},d.prototype.css=".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}",d.prototype.getNode=function(e){return this.nodes[e]},d.prototype.getParent=function(e){var t=this.identifyNode(e);return this.nodes[t.parentId]},d.prototype.getSiblings=function(e){var t=this.identifyNode(e),o=this.getParent(t),s=o?o.nodes:this.tree;return s.filter(function(e){return e.nodeId!==t.nodeId})},d.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},d.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},d.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},d.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},d.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},d.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},d.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},d.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},d.prototype.selectNode=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.setSelectedState(e,!0,t)},this)),this.render()},d.prototype.unselectNode=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.setSelectedState(e,!1,t)},this)),this.render()},d.prototype.toggleNodeSelected=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.toggleSelectedState(e,t)},this)),this.render()},d.prototype.collapseAll=function(t){var o=this.findNodes("true","g","state.expanded");this.forEachIdentifier(o,t,e.proxy(function(e,t){this.setExpandedState(e,!1,t)},this)),this.render()},d.prototype.collapseNode=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.setExpandedState(e,!1,t)},this)),this.render()},d.prototype.expandAll=function(t){if(t=e.extend({},i.options,t),t&&t.levels)this.expandLevels(this.tree,t.levels,t);else{var o=this.findNodes("false","g","state.expanded");this.forEachIdentifier(o,t,e.proxy(function(e,t){this.setExpandedState(e,!0,t)},this))}this.render()},d.prototype.expandNode=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.setExpandedState(e,!0,t),e.nodes&&t&&t.levels&&this.expandLevels(e.nodes,t.levels-1,t)},this)),this.render()},d.prototype.expandLevels=function(t,o,s){s=e.extend({},i.options,s),e.each(t,e.proxy(function(e,t){this.setExpandedState(t,o>0?!0:!1,s),t.nodes&&this.expandLevels(t.nodes,o-1,s)},this))},d.prototype.revealNode=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){for(var o=this.getParent(e);o;)this.setExpandedState(o,!0,t),o=this.getParent(o)},this)),this.render()},d.prototype.toggleNodeExpanded=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.toggleExpandedState(e,t)},this)),this.render()},d.prototype.checkAll=function(t){var o=this.findNodes("false","g","state.checked");this.forEachIdentifier(o,t,e.proxy(function(e,t){this.setCheckedState(e,!0,t)},this)),this.render()},d.prototype.checkNode=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.setCheckedState(e,!0,t)},this)),this.render()},d.prototype.uncheckAll=function(t){var o=this.findNodes("true","g","state.checked");this.forEachIdentifier(o,t,e.proxy(function(e,t){this.setCheckedState(e,!1,t)},this)),this.render()},d.prototype.uncheckNode=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.setCheckedState(e,!1,t)},this)),this.render()},d.prototype.toggleNodeChecked=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.toggleCheckedState(e,t)},this)),this.render()},d.prototype.disableAll=function(t){var o=this.findNodes("false","g","state.disabled");this.forEachIdentifier(o,t,e.proxy(function(e,t){this.setDisabledState(e,!0,t)},this)),this.render()},d.prototype.disableNode=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.setDisabledState(e,!0,t)},this)),this.render()},d.prototype.enableAll=function(t){var o=this.findNodes("true","g","state.disabled");this.forEachIdentifier(o,t,e.proxy(function(e,t){this.setDisabledState(e,!1,t)},this)),this.render()},d.prototype.enableNode=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.setDisabledState(e,!1,t)},this)),this.render()},d.prototype.toggleNodeDisabled=function(t,o){this.forEachIdentifier(t,o,e.proxy(function(e,t){this.setDisabledState(e,!e.state.disabled,t)},this)),this.render()},d.prototype.forEachIdentifier=function(t,o,s){o=e.extend({},i.options,o),t instanceof Array||(t=[t]),e.each(t,e.proxy(function(e,t){s(this.identifyNode(t),o)},this))},d.prototype.identifyNode=function(e){return"number"==typeof e?this.nodes[e]:e},d.prototype.search=function(t,o){o=e.extend({},i.searchOptions,o),this.clearSearch({render:!1});var s=[];if(t&&t.length>0){o.exactMatch&&(t="^"+t+"$");var n="g";o.ignoreCase&&(n+="i"),s=this.findNodes(t,n),e.each(s,function(e,t){t.searchResult=!0})}return o.revealResults?this.revealNode(s):this.render(),this.$element.trigger("searchComplete",e.extend(!0,{},s)),s},d.prototype.clearSearch=function(t){t=e.extend({},{render:!0},t);var o=e.each(this.findNodes("true","g","searchResult"),function(e,t){t.searchResult=!1});t.render&&this.render(),this.$element.trigger("searchCleared",e.extend(!0,{},o))},d.prototype.findNodes=function(t,o,s){o=o||"g",s=s||"text";var n=this;return e.grep(this.nodes,function(e){var i=n.getNodeValue(e,s);return"string"==typeof i?i.match(new RegExp(t,o)):void 0})},d.prototype.getNodeValue=function(e,t){var o=t.indexOf(".");if(o>0){var n=e[t.substring(0,o)],i=t.substring(o+1,t.length);return this.getNodeValue(n,i)}return e.hasOwnProperty(t)?e[t].toString():s};var r=function(e){t.console&&t.console.error(e)};e.fn[n]=function(t,o){var s;return this.each(function(){var i=e.data(this,n);"string"==typeof t?i?e.isFunction(i[t])&&"_"!==t.charAt(0)?(o instanceof Array||(o=[o]),s=i[t].apply(i,o)):r("No such method : "+t):r("Not initialized, can not call method : "+t):"boolean"==typeof t?s=i:e.data(this,n,new d(this,e.extend(!0,{},t)))}),s||this}}(jQuery,window,document); + + @@ -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 + * @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 ) == "" )