diff --git a/ifm.php b/ifm.php index af3c93c..35adfb4 100644 --- a/ifm.php +++ b/ifm.php @@ -34,14 +34,40 @@ class IFMConfig { const showfilesize = 1; // show filesize? const showowner = 1; // show file owner? 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 showhtdocs = 1; // show .htaccess and .htpasswd 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: + : + + examples: + const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC'; + const auth_source = 'file;/path/to/file'; + */ const auth = 0; 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 // development tools @@ -350,7 +376,7 @@ div.footer div.panel-body { padding: 5px !important; }
Content of '; - if( IFMConfig::showpath == 1 ) print $this->getScriptRoot().'/'; else print '/'; + print ( IFMConfig::showpath == 1 ) ? realpath( IFMConfig::root_dir ) : "/"; print '
@@ -440,6 +466,7 @@ function IFM() { this.IFM_SCFN = ""; this.config = jQuery.parseJSON(''); // serialize the PHP config array, so we can use it in JS too + this.isDocroot = ; this.editor = null; // global ace editor 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 @@ -497,16 +524,20 @@ function IFM() { else if( self.config.edit == 1 && data[i].name.toLowerCase().substr(-4) != ".zip" ) newRow += ' data-eaction="edit"'; newRow += '>"'; + if( self.isDocroot ) { + newRow += ' href="'+self.pathCombine(ifm.currentDir,data[i].name)+'"'; + if( data[i].icon.indexOf( 'file-image' ) !== -1 ) + newRow += ' data-toggle="tooltip" title=" ' + ( data[i].name == '..' ? '[ up ]' : data[i].name ) + ''; if( ( data[i].type != "dir" && self.config.download == 1 ) || ( data[i].type == "dir" && self.config.zipnload == 1 ) ) { - var guid = self.generateGuid(); newRow += '
'; newRow += ''; newRow += ''; @@ -1287,9 +1318,9 @@ ifm.init(); private function handleRequest() { if($_REQUEST["api"] == "getRealpath") { if( isset( $_REQUEST["dir"] ) && $_REQUEST["dir"] != "" ) - $this->getRealpath( $_REQUEST["dir"] ); + echo json_encode( array( "realpath" => $this->getValidDir( $_REQUEST["dir"] ) ) ); else - echo json_encode(array("realpath"=>"")); + echo json_encode( array( "realpath" => "" ) ); } elseif( $_REQUEST["api"] == "getFiles" ) { if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) ) @@ -1321,6 +1352,11 @@ ifm.init(); public function run() { 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']) ) { $this->getApplication(); } else { @@ -1831,14 +1867,6 @@ ifm.init(); '; } - 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 ) { $oct = str_split( strrev( decoct( $perms ) ), 1 ); $masks = array( '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' ); @@ -1851,17 +1879,36 @@ ifm.init(); ); } - private function isPathValid($p) { - if( $p == "" ) { - return true; - } elseif( str_replace( "\\", "/", $this->getScriptRoot() ) == str_replace( "\\", "/", substr( realpath( dirname( $p ) ), 0, strlen( $this->getScriptRoot() ) ) ) ) { - return true; + private function getValidDir( $dir ) { + if( ! $this->isPathValid( $dir ) || ! is_dir( $dir ) ) { + return ""; + } else { + $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() { - //return realpath( substr( $_SERVER["SCRIPT_FILENAME"], 0, strrpos( $_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 ) { if( !is_dir( $path ) ) { return -1; diff --git a/src/config.php b/src/config.php index 7ef1022..8fc1a34 100644 --- a/src/config.php +++ b/src/config.php @@ -34,14 +34,40 @@ class IFMConfig { const showfilesize = 1; // show filesize? const showowner = 1; // show file owner? 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 showhtdocs = 1; // show .htaccess and .htpasswd 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: + : + + examples: + const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC'; + const auth_source = 'file;/path/to/file'; + */ const auth = 0; 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 // development tools diff --git a/src/ifm.js b/src/ifm.js index 109e908..c0a830e 100644 --- a/src/ifm.js +++ b/src/ifm.js @@ -5,6 +5,7 @@ function IFM() { this.IFM_SCFN = ""; this.config = jQuery.parseJSON(''); // serialize the PHP config array, so we can use it in JS too + this.isDocroot = ; this.editor = null; // global ace editor 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 @@ -62,16 +63,20 @@ function IFM() { else if( self.config.edit == 1 && data[i].name.toLowerCase().substr(-4) != ".zip" ) newRow += ' data-eaction="edit"'; newRow += '>"'; + if( self.isDocroot ) { + newRow += ' href="'+self.pathCombine(ifm.currentDir,data[i].name)+'"'; + if( data[i].icon.indexOf( 'file-image' ) !== -1 ) + newRow += ' data-toggle="tooltip" title=" ' + ( data[i].name == '..' ? '[ up ]' : data[i].name ) + ''; if( ( data[i].type != "dir" && self.config.download == 1 ) || ( data[i].type == "dir" && self.config.zipnload == 1 ) ) { - var guid = self.generateGuid(); newRow += ''; newRow += ''; newRow += ''; diff --git a/src/main.php b/src/main.php index 648fd85..3ad1221 100644 --- a/src/main.php +++ b/src/main.php @@ -54,7 +54,7 @@ class IFM {
Content of '; - if( IFMConfig::showpath == 1 ) print $this->getScriptRoot().'/'; else print '/'; + print ( IFMConfig::showpath == 1 ) ? realpath( IFMConfig::root_dir ) : "/"; print '
@@ -126,9 +126,9 @@ class IFM { private function handleRequest() { if($_REQUEST["api"] == "getRealpath") { if( isset( $_REQUEST["dir"] ) && $_REQUEST["dir"] != "" ) - $this->getRealpath( $_REQUEST["dir"] ); + echo json_encode( array( "realpath" => $this->getValidDir( $_REQUEST["dir"] ) ) ); else - echo json_encode(array("realpath"=>"")); + echo json_encode( array( "realpath" => "" ) ); } elseif( $_REQUEST["api"] == "getFiles" ) { if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) ) @@ -160,6 +160,11 @@ class IFM { public function run() { 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']) ) { $this->getApplication(); } else { @@ -670,14 +675,6 @@ class IFM { '; } - 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 ) { $oct = str_split( strrev( decoct( $perms ) ), 1 ); $masks = array( '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' ); @@ -690,17 +687,36 @@ class IFM { ); } - private function isPathValid($p) { - if( $p == "" ) { - return true; - } elseif( str_replace( "\\", "/", $this->getScriptRoot() ) == str_replace( "\\", "/", substr( realpath( dirname( $p ) ), 0, strlen( $this->getScriptRoot() ) ) ) ) { - return true; + private function getValidDir( $dir ) { + if( ! $this->isPathValid( $dir ) || ! is_dir( $dir ) ) { + return ""; + } else { + $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() { - //return realpath( substr( $_SERVER["SCRIPT_FILENAME"], 0, strrpos( $_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 ) { if( !is_dir( $path ) ) { return -1;