1
0
mirror of https://github.com/misterunknown/ifm.git synced 2025-08-12 11:04:01 +02:00

Merge pull request #30 from misterunknown/issue-26

Issue 26
This commit is contained in:
Marco Dickert
2017-03-20 12:45:43 +01:00
committed by GitHub
4 changed files with 142 additions and 66 deletions

104
ifm.php
View File

@@ -34,14 +34,40 @@ class IFMConfig {
const showfilesize = 1; // show filesize? const showfilesize = 1; // show filesize?
const showowner = 1; // show file owner? const showowner = 1; // show file owner?
const showgroup = 1; // show file group? const showgroup = 1; // show file group?
const showpath = 0; // show real path of directory (not only root)?
const showpermissions = 2; // show permissions 0 -> not; 1 -> octal, 2 -> human readable const showpermissions = 2; // show permissions 0 -> not; 1 -> octal, 2 -> human readable
const showhtdocs = 1; // show .htaccess and .htpasswd const showhtdocs = 1; // show .htaccess and .htpasswd
const showhiddenfiles = 1; // show files beginning with a dot (e.g. ".bashrc") const showhiddenfiles = 1; // show files beginning with a dot (e.g. ".bashrc")
const showpath = 0; // show absolute path
// general config /*
authentication
This provides a super simple authentication functionality. At the moment only one user can be
configured. The credential information can be either set inline or read from a file. The
password has to be a hash generated by PHPs password_hash function. The default credentials are
admin:admin.
If you specify a file it should only contain one line, with the credentials in the following
format:
<username>:<passwordhash>
examples:
const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC';
const auth_source = 'file;/path/to/file';
*/
const auth = 0; const auth = 0;
const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC'; const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC';
/*
root_dir - set a custom root directory instead of the script location
This option is highly experimental and should only be set if you definitely know what you do.
Settings this option may cause black holes or other unwanted things. Use with special care.
default setting:
const root_dir = "";
*/
const root_dir = "";
const defaulttimezone = "Europe/Berlin"; // set default timezone const defaulttimezone = "Europe/Berlin"; // set default timezone
// development tools // development tools
@@ -350,7 +376,7 @@ div.footer div.panel-body { padding: 5px !important; }
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon" id="currentDirLabel">Content of <span id="docroot">'; <span class="input-group-addon" id="currentDirLabel">Content of <span id="docroot">';
if( IFMConfig::showpath == 1 ) print $this->getScriptRoot().'/'; else print '/'; print ( IFMConfig::showpath == 1 ) ? realpath( IFMConfig::root_dir ) : "/";
print '</span></span><input class="form-control" id="currentDir" aria-describedby="currentDirLabel" type="text"> print '</span></span><input class="form-control" id="currentDir" aria-describedby="currentDirLabel" type="text">
</div> </div>
</div> </div>
@@ -440,6 +466,7 @@ function IFM() {
this.IFM_SCFN = "<?=basename($_SERVER['SCRIPT_NAME'])?>"; this.IFM_SCFN = "<?=basename($_SERVER['SCRIPT_NAME'])?>";
this.config = jQuery.parseJSON('<?php echo json_encode(IFMConfig::getConstants()); ?>'); // serialize the PHP config array, so we can use it in JS too this.config = jQuery.parseJSON('<?php echo json_encode(IFMConfig::getConstants()); ?>'); // serialize the PHP config array, so we can use it in JS too
this.isDocroot = <?php echo realpath( IFMConfig::root_dir ) == dirname( __FILE__ ) ? "true" : "false"; ?>;
this.editor = null; // global ace editor this.editor = null; // global ace editor
this.fileChanged = false; // flag for check if file was changed already this.fileChanged = false; // flag for check if file was changed already
this.currentDir = ""; // this is the global variable for the current directory; it is used for AJAX requests this.currentDir = ""; // this is the global variable for the current directory; it is used for AJAX requests
@@ -497,16 +524,20 @@ function IFM() {
else if( self.config.edit == 1 && data[i].name.toLowerCase().substr(-4) != ".zip" ) else if( self.config.edit == 1 && data[i].name.toLowerCase().substr(-4) != ".zip" )
newRow += ' data-eaction="edit"'; newRow += ' data-eaction="edit"';
newRow += '><td><a tabindex="0"'; newRow += '><td><a tabindex="0"';
var guid = self.generateGuid();
if(data[i].type=="file") { if(data[i].type=="file") {
newRow += ' href="'+self.pathCombine(ifm.currentDir,data[i].name)+'"'; if( self.isDocroot ) {
if( data[i].icon.indexOf( 'file-image' ) !== -1 ) newRow += ' href="'+self.pathCombine(ifm.currentDir,data[i].name)+'"';
newRow += ' data-toggle="tooltip" title="<img src=\''+self.pathCombine(self.currentDir,data[i].name)+'\' class=\'imgpreview\'>"'; if( data[i].icon.indexOf( 'file-image' ) !== -1 )
newRow += ' data-toggle="tooltip" title="<img src=\''+self.pathCombine(self.currentDir,data[i].name)+'\' class=\'imgpreview\'"';
} else {
newRow += ' onclick="$(\'#d_'+guid+'\').submit();"';
}
} else { } else {
newRow += ' onclick="ifm.changeDirectory(\''+data[i].name+'\')"'; newRow += ' onclick="ifm.changeDirectory(\''+data[i].name+'\')"';
} }
newRow += '><span class="'+data[i].icon+'"></span> ' + ( data[i].name == '..' ? '[ up ]' : data[i].name ) + '</a></td>'; newRow += '><span class="'+data[i].icon+'"></span> ' + ( data[i].name == '..' ? '[ up ]' : data[i].name ) + '</a></td>';
if( ( data[i].type != "dir" && self.config.download == 1 ) || ( data[i].type == "dir" && self.config.zipnload == 1 ) ) { if( ( data[i].type != "dir" && self.config.download == 1 ) || ( data[i].type == "dir" && self.config.zipnload == 1 ) ) {
var guid = self.generateGuid();
newRow += '<td><form id="d_' + guid + '">'; newRow += '<td><form id="d_' + guid + '">';
newRow += '<input type="hidden" name="dir" value="' + self.currentDir + '">'; newRow += '<input type="hidden" name="dir" value="' + self.currentDir + '">';
newRow += '<input type="hidden" name="filename" value="' + ( data[i].name == '..' ? '.' : data[i].name ) + '">'; newRow += '<input type="hidden" name="filename" value="' + ( data[i].name == '..' ? '.' : data[i].name ) + '">';
@@ -1287,9 +1318,9 @@ ifm.init();
private function handleRequest() { private function handleRequest() {
if($_REQUEST["api"] == "getRealpath") { if($_REQUEST["api"] == "getRealpath") {
if( isset( $_REQUEST["dir"] ) && $_REQUEST["dir"] != "" ) if( isset( $_REQUEST["dir"] ) && $_REQUEST["dir"] != "" )
$this->getRealpath( $_REQUEST["dir"] ); echo json_encode( array( "realpath" => $this->getValidDir( $_REQUEST["dir"] ) ) );
else else
echo json_encode(array("realpath"=>"")); echo json_encode( array( "realpath" => "" ) );
} }
elseif( $_REQUEST["api"] == "getFiles" ) { elseif( $_REQUEST["api"] == "getFiles" ) {
if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) ) if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) )
@@ -1321,6 +1352,11 @@ ifm.init();
public function run() { public function run() {
if ( $this->checkAuth() ) { if ( $this->checkAuth() ) {
// go to our root_dir
if( ! is_dir( realpath( IFMConfig::root_dir ) ) || ! is_readable( realpath( IFMConfig::root_dir ) ) )
die( "Cannot access root_dir.");
else
chdir( IFMConfig::root_dir );
if ( ! isset($_REQUEST['api']) ) { if ( ! isset($_REQUEST['api']) ) {
$this->getApplication(); $this->getApplication();
} else { } else {
@@ -1831,14 +1867,6 @@ ifm.init();
</html>'; </html>';
} }
private function getValidDir($dir) {
if( $this->getScriptRoot() != substr( realpath( $dir ), 0, strlen( $this->getScriptRoot() ) ) ) {
return "";
} else {
return ( file_exists( realpath( $dir ) ) ) ? substr( realpath( $dir ), strlen( $this->getScriptRoot() ) + 1 ) : "";
}
}
private function filePermsDecode( $perms ) { private function filePermsDecode( $perms ) {
$oct = str_split( strrev( decoct( $perms ) ), 1 ); $oct = str_split( strrev( decoct( $perms ) ), 1 );
$masks = array( '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' ); $masks = array( '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' );
@@ -1851,17 +1879,36 @@ ifm.init();
); );
} }
private function isPathValid($p) { private function getValidDir( $dir ) {
if( $p == "" ) { if( ! $this->isPathValid( $dir ) || ! is_dir( $dir ) ) {
return true; return "";
} elseif( str_replace( "\\", "/", $this->getScriptRoot() ) == str_replace( "\\", "/", substr( realpath( dirname( $p ) ), 0, strlen( $this->getScriptRoot() ) ) ) ) { } else {
return true; $rpDir = realpath( $dir );
$rpConfig = realpath( IFMConfig::root_dir );
if( $rpConfig == "/" )
return $rpDir;
elseif( $rpDir == $rpConfig )
return "";
else
return substr( $rpDir, strlen( $rpConfig ) + 1 );
} }
return false; }
private function isPathValid( $dir ) {
$rpDir = realpath( $dir );
$rpConfig = realpath( IFMConfig::root_dir );
if( ! is_string( $rpDir ) || ! is_string( $rpConfig ) ) // can happen if open_basedir is in effect
return false;
elseif( $rpDir == $rpConfig )
return true;
elseif( 0 === strpos( $rpDir, $rpConfig ) ) {
return true;
}
else
return false;
} }
private function getScriptRoot() { private function getScriptRoot() {
//return realpath( substr( $_SERVER["SCRIPT_FILENAME"], 0, strrpos( $_SERVER["SCRIPT_FILENAME"], "/" ) ) );
return dirname( $_SERVER["SCRIPT_FILENAME"] ); return dirname( $_SERVER["SCRIPT_FILENAME"] );
} }
@@ -1886,15 +1933,6 @@ ifm.init();
} }
} }
private function getRealpath($dir) {
if( $this->getScriptRoot() != substr( realpath( $_POST["dir"] ), 0, strlen( $this->getScriptRoot() ) ) ) {
echo json_encode( array( "realpath" => "" ) );
} else {
$rp = substr( realpath( $_POST["dir"] ), strlen( $this->getScriptRoot() ) + 1 );
if( $rp == false ) $rp = "";
echo json_encode( array( "realpath" => $rp ) );
}
}
private function rec_rmdir( $path ) { private function rec_rmdir( $path ) {
if( !is_dir( $path ) ) { if( !is_dir( $path ) ) {
return -1; return -1;

View File

@@ -34,14 +34,40 @@ class IFMConfig {
const showfilesize = 1; // show filesize? const showfilesize = 1; // show filesize?
const showowner = 1; // show file owner? const showowner = 1; // show file owner?
const showgroup = 1; // show file group? const showgroup = 1; // show file group?
const showpath = 0; // show real path of directory (not only root)?
const showpermissions = 2; // show permissions 0 -> not; 1 -> octal, 2 -> human readable const showpermissions = 2; // show permissions 0 -> not; 1 -> octal, 2 -> human readable
const showhtdocs = 1; // show .htaccess and .htpasswd const showhtdocs = 1; // show .htaccess and .htpasswd
const showhiddenfiles = 1; // show files beginning with a dot (e.g. ".bashrc") const showhiddenfiles = 1; // show files beginning with a dot (e.g. ".bashrc")
const showpath = 0; // show absolute path
// general config /*
authentication
This provides a super simple authentication functionality. At the moment only one user can be
configured. The credential information can be either set inline or read from a file. The
password has to be a hash generated by PHPs password_hash function. The default credentials are
admin:admin.
If you specify a file it should only contain one line, with the credentials in the following
format:
<username>:<passwordhash>
examples:
const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC';
const auth_source = 'file;/path/to/file';
*/
const auth = 0; const auth = 0;
const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC'; const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC';
/*
root_dir - set a custom root directory instead of the script location
This option is highly experimental and should only be set if you definitely know what you do.
Settings this option may cause black holes or other unwanted things. Use with special care.
default setting:
const root_dir = "";
*/
const root_dir = "";
const defaulttimezone = "Europe/Berlin"; // set default timezone const defaulttimezone = "Europe/Berlin"; // set default timezone
// development tools // development tools

View File

@@ -5,6 +5,7 @@ function IFM() {
this.IFM_SCFN = "<?=basename($_SERVER['SCRIPT_NAME'])?>"; this.IFM_SCFN = "<?=basename($_SERVER['SCRIPT_NAME'])?>";
this.config = jQuery.parseJSON('<?php echo json_encode(IFMConfig::getConstants()); ?>'); // serialize the PHP config array, so we can use it in JS too this.config = jQuery.parseJSON('<?php echo json_encode(IFMConfig::getConstants()); ?>'); // serialize the PHP config array, so we can use it in JS too
this.isDocroot = <?php echo realpath( IFMConfig::root_dir ) == dirname( __FILE__ ) ? "true" : "false"; ?>;
this.editor = null; // global ace editor this.editor = null; // global ace editor
this.fileChanged = false; // flag for check if file was changed already this.fileChanged = false; // flag for check if file was changed already
this.currentDir = ""; // this is the global variable for the current directory; it is used for AJAX requests this.currentDir = ""; // this is the global variable for the current directory; it is used for AJAX requests
@@ -62,16 +63,20 @@ function IFM() {
else if( self.config.edit == 1 && data[i].name.toLowerCase().substr(-4) != ".zip" ) else if( self.config.edit == 1 && data[i].name.toLowerCase().substr(-4) != ".zip" )
newRow += ' data-eaction="edit"'; newRow += ' data-eaction="edit"';
newRow += '><td><a tabindex="0"'; newRow += '><td><a tabindex="0"';
var guid = self.generateGuid();
if(data[i].type=="file") { if(data[i].type=="file") {
newRow += ' href="'+self.pathCombine(ifm.currentDir,data[i].name)+'"'; if( self.isDocroot ) {
if( data[i].icon.indexOf( 'file-image' ) !== -1 ) newRow += ' href="'+self.pathCombine(ifm.currentDir,data[i].name)+'"';
newRow += ' data-toggle="tooltip" title="<img src=\''+self.pathCombine(self.currentDir,data[i].name)+'\' class=\'imgpreview\'>"'; if( data[i].icon.indexOf( 'file-image' ) !== -1 )
newRow += ' data-toggle="tooltip" title="<img src=\''+self.pathCombine(self.currentDir,data[i].name)+'\' class=\'imgpreview\'"';
} else {
newRow += ' onclick="$(\'#d_'+guid+'\').submit();"';
}
} else { } else {
newRow += ' onclick="ifm.changeDirectory(\''+data[i].name+'\')"'; newRow += ' onclick="ifm.changeDirectory(\''+data[i].name+'\')"';
} }
newRow += '><span class="'+data[i].icon+'"></span> ' + ( data[i].name == '..' ? '[ up ]' : data[i].name ) + '</a></td>'; newRow += '><span class="'+data[i].icon+'"></span> ' + ( data[i].name == '..' ? '[ up ]' : data[i].name ) + '</a></td>';
if( ( data[i].type != "dir" && self.config.download == 1 ) || ( data[i].type == "dir" && self.config.zipnload == 1 ) ) { if( ( data[i].type != "dir" && self.config.download == 1 ) || ( data[i].type == "dir" && self.config.zipnload == 1 ) ) {
var guid = self.generateGuid();
newRow += '<td><form id="d_' + guid + '">'; newRow += '<td><form id="d_' + guid + '">';
newRow += '<input type="hidden" name="dir" value="' + self.currentDir + '">'; newRow += '<input type="hidden" name="dir" value="' + self.currentDir + '">';
newRow += '<input type="hidden" name="filename" value="' + ( data[i].name == '..' ? '.' : data[i].name ) + '">'; newRow += '<input type="hidden" name="filename" value="' + ( data[i].name == '..' ? '.' : data[i].name ) + '">';

View File

@@ -54,7 +54,7 @@ class IFM {
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon" id="currentDirLabel">Content of <span id="docroot">'; <span class="input-group-addon" id="currentDirLabel">Content of <span id="docroot">';
if( IFMConfig::showpath == 1 ) print $this->getScriptRoot().'/'; else print '/'; print ( IFMConfig::showpath == 1 ) ? realpath( IFMConfig::root_dir ) : "/";
print '</span></span><input class="form-control" id="currentDir" aria-describedby="currentDirLabel" type="text"> print '</span></span><input class="form-control" id="currentDir" aria-describedby="currentDirLabel" type="text">
</div> </div>
</div> </div>
@@ -126,9 +126,9 @@ class IFM {
private function handleRequest() { private function handleRequest() {
if($_REQUEST["api"] == "getRealpath") { if($_REQUEST["api"] == "getRealpath") {
if( isset( $_REQUEST["dir"] ) && $_REQUEST["dir"] != "" ) if( isset( $_REQUEST["dir"] ) && $_REQUEST["dir"] != "" )
$this->getRealpath( $_REQUEST["dir"] ); echo json_encode( array( "realpath" => $this->getValidDir( $_REQUEST["dir"] ) ) );
else else
echo json_encode(array("realpath"=>"")); echo json_encode( array( "realpath" => "" ) );
} }
elseif( $_REQUEST["api"] == "getFiles" ) { elseif( $_REQUEST["api"] == "getFiles" ) {
if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) ) if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) )
@@ -160,6 +160,11 @@ class IFM {
public function run() { public function run() {
if ( $this->checkAuth() ) { if ( $this->checkAuth() ) {
// go to our root_dir
if( ! is_dir( realpath( IFMConfig::root_dir ) ) || ! is_readable( realpath( IFMConfig::root_dir ) ) )
die( "Cannot access root_dir.");
else
chdir( IFMConfig::root_dir );
if ( ! isset($_REQUEST['api']) ) { if ( ! isset($_REQUEST['api']) ) {
$this->getApplication(); $this->getApplication();
} else { } else {
@@ -670,14 +675,6 @@ class IFM {
</html>'; </html>';
} }
private function getValidDir($dir) {
if( $this->getScriptRoot() != substr( realpath( $dir ), 0, strlen( $this->getScriptRoot() ) ) ) {
return "";
} else {
return ( file_exists( realpath( $dir ) ) ) ? substr( realpath( $dir ), strlen( $this->getScriptRoot() ) + 1 ) : "";
}
}
private function filePermsDecode( $perms ) { private function filePermsDecode( $perms ) {
$oct = str_split( strrev( decoct( $perms ) ), 1 ); $oct = str_split( strrev( decoct( $perms ) ), 1 );
$masks = array( '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' ); $masks = array( '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' );
@@ -690,17 +687,36 @@ class IFM {
); );
} }
private function isPathValid($p) { private function getValidDir( $dir ) {
if( $p == "" ) { if( ! $this->isPathValid( $dir ) || ! is_dir( $dir ) ) {
return true; return "";
} elseif( str_replace( "\\", "/", $this->getScriptRoot() ) == str_replace( "\\", "/", substr( realpath( dirname( $p ) ), 0, strlen( $this->getScriptRoot() ) ) ) ) { } else {
return true; $rpDir = realpath( $dir );
$rpConfig = realpath( IFMConfig::root_dir );
if( $rpConfig == "/" )
return $rpDir;
elseif( $rpDir == $rpConfig )
return "";
else
return substr( $rpDir, strlen( $rpConfig ) + 1 );
} }
return false; }
private function isPathValid( $dir ) {
$rpDir = realpath( $dir );
$rpConfig = realpath( IFMConfig::root_dir );
if( ! is_string( $rpDir ) || ! is_string( $rpConfig ) ) // can happen if open_basedir is in effect
return false;
elseif( $rpDir == $rpConfig )
return true;
elseif( 0 === strpos( $rpDir, $rpConfig ) ) {
return true;
}
else
return false;
} }
private function getScriptRoot() { private function getScriptRoot() {
//return realpath( substr( $_SERVER["SCRIPT_FILENAME"], 0, strrpos( $_SERVER["SCRIPT_FILENAME"], "/" ) ) );
return dirname( $_SERVER["SCRIPT_FILENAME"] ); return dirname( $_SERVER["SCRIPT_FILENAME"] );
} }
@@ -725,15 +741,6 @@ class IFM {
} }
} }
private function getRealpath($dir) {
if( $this->getScriptRoot() != substr( realpath( $_POST["dir"] ), 0, strlen( $this->getScriptRoot() ) ) ) {
echo json_encode( array( "realpath" => "" ) );
} else {
$rp = substr( realpath( $_POST["dir"] ), strlen( $this->getScriptRoot() ) + 1 );
if( $rp == false ) $rp = "";
echo json_encode( array( "realpath" => $rp ) );
}
}
private function rec_rmdir( $path ) { private function rec_rmdir( $path ) {
if( !is_dir( $path ) ) { if( !is_dir( $path ) ) {
return -1; return -1;