diff --git a/ifm.php b/ifm.php index f588dbd..af93fe0 100644 --- a/ifm.php +++ b/ifm.php @@ -861,15 +861,29 @@ function IFM() { self.showModal( '
\ \ \
'); + $('#extractFileButton').on( 'click', function() { + var t = $('input[name=extractTargetLocation]:checked').val(); + if( t == "custom" ) t = $('#extractCustomLocation').val(); + self.extractFile( self.JSEncode( name ), t ); + self.hideModal(); + return false; + }); + $('#extractCancelButton').on( 'click', function() { + self.hideModal(); + return false; + }); + $('#extractCustomLocation').on( 'click', function(e) { + $(e.target).prev().children().first().prop( 'checked', true ); + }); }; this.extractFile = function(name, t) { @@ -1608,39 +1622,24 @@ ifm.init(); echo json_encode( array( "status" => "ERROR", "message" => "No permission to extract files" ) ); else { $this->chDirIfNecessary( $d['dir'] ); - if( ! file_exists( $d['filename'] ) || substr( $d['filename'],-4 ) != ".zip" ) + if( ! file_exists( $d['filename'] ) || substr( $d['filename'],-4 ) != ".zip" ) { echo json_encode( array( "status" => "ERROR","message" => "No valid zip file found" ) ); - else { - if( ! isset( $d['targetdir'] ) ) - $d['targetdir'] = ""; - if( strpos( $d['targetdir'], "/" ) !== false ) - echo json_encode( array( "status" => "ERROR","message" => "Target directory must not contain slashes" ) ); - else { - switch( $d['targetdir'] ){ - case "": - if( $this->unzip( $_POST["filename"] ) ) - echo json_encode( array( "status" => "OK","message" => "File successfully extracted." ) ); - else - echo json_encode( array( "status" => "ERROR","message" => "File could not be extracted" ) ); - break; - default: - if( ! mkdir( $d['targetdir'] ) ) - echo json_encode( array( "status" => "ERROR","message" => "Could not create target directory" ) ); - else { - chdir( $d['targetdir'] ); - if( ! $this->unzip( "../" . $d["filename"] ) ) { - chdir( ".." ); - rmdir( $d['targetdir'] ); - echo json_encode( array( "status" => "ERROR","message" => "Could not extract file" ) ); - } - else { - chdir( ".." ); - echo json_encode( array( "status" => "OK","message" => "File successfully extracted" ) ); - } - } - break; - } - } + exit( 1 ); + } + if( ! isset( $d['targetdir'] ) || trim( $d['targetdir'] ) == "" ) + $d['targetdir'] = "./"; + if( ! $this->isPathValid( $d['targetdir'] ) ) { + echo json_encode( array( "status" => "ERROR","message" => "Target directory is not valid." ) ); + exit( 1 ); + } + if( ! is_dir( $d['targetdir'] ) && ! mkdir( $d['targetdir'], 0777, true ) ) { + echo json_encode( array( "status" => "ERROR","message" => "Could not create target directory." ) ); + exit( 1 ); + } + if( ! $this->unzip( $d['filename'], $d['targetdir'] ) ) { + echo json_encode( array( "status" => "ERROR","message" => "File could not be extracted" ) ); + } else { + echo json_encode( array( "status" => "OK","message" => "File successfully extracted." ) ); } } } @@ -1903,15 +1902,25 @@ ifm.init(); } private function isPathValid( $dir ) { - $rpDir = realpath( $dir ); - $rpConfig = realpath( IFMConfig::root_dir ); + /** + * This function is also used to check non-existent paths, but the PHP realpath function returns false for + * nonexistent paths. Hence we need to check the path manually in the following lines. + */ + $tmp_d = $dir; + $tmp_missing_parts = array(); + while( realpath( $tmp_d ) === false ) { + $tmp_i = pathinfo( $tmp_d ); + array_push( $tmp_missing_parts, $tmp_i['filename'] ); + $tmp_d = dirname( $tmp_d ); + } + $rpDir = $this->pathCombine( realpath( $tmp_d ), implode( "/", array_reverse( $tmp_missing_parts ) ) ); + $rpConfig = ( IFMConfig::root_dir == "" ) ? realpath( dirname( __FILE__ ) ) : 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 ) ) { + elseif( 0 === strpos( $rpDir, $rpConfig ) ) return true; - } else return false; } @@ -1996,11 +2005,11 @@ ifm.init(); } // unzip an archive - private function unzip( $file ) { + private function unzip( $file, $destination="./" ) { $zip = new ZipArchive; $res = $zip->open( $file ); if( $res === true ) { - $zip->extractTo( './' ); + $zip->extractTo( $destination ); $zip->close(); return true; } else { diff --git a/src/ifm.js b/src/ifm.js index 1d0cc7f..206defd 100644 --- a/src/ifm.js +++ b/src/ifm.js @@ -395,13 +395,27 @@ function IFM() { \
./
\
./'+targetDirSuggestion+'
\ -
\ +
\ \ \ '); + $('#extractFileButton').on( 'click', function() { + var t = $('input[name=extractTargetLocation]:checked').val(); + if( t == "custom" ) t = $('#extractCustomLocation').val(); + self.extractFile( self.JSEncode( name ), t ); + self.hideModal(); + return false; + }); + $('#extractCancelButton').on( 'click', function() { + self.hideModal(); + return false; + }); + $('#extractCustomLocation').on( 'click', function(e) { + $(e.target).prev().children().first().prop( 'checked', true ); + }); }; this.extractFile = function(name, t) { diff --git a/src/main.php b/src/main.php index eae3cab..7cbdae6 100644 --- a/src/main.php +++ b/src/main.php @@ -408,39 +408,24 @@ class IFM { echo json_encode( array( "status" => "ERROR", "message" => "No permission to extract files" ) ); else { $this->chDirIfNecessary( $d['dir'] ); - if( ! file_exists( $d['filename'] ) || substr( $d['filename'],-4 ) != ".zip" ) + if( ! file_exists( $d['filename'] ) || substr( $d['filename'],-4 ) != ".zip" ) { echo json_encode( array( "status" => "ERROR","message" => "No valid zip file found" ) ); - else { - if( ! isset( $d['targetdir'] ) ) - $d['targetdir'] = ""; - if( strpos( $d['targetdir'], "/" ) !== false ) - echo json_encode( array( "status" => "ERROR","message" => "Target directory must not contain slashes" ) ); - else { - switch( $d['targetdir'] ){ - case "": - if( $this->unzip( $_POST["filename"] ) ) - echo json_encode( array( "status" => "OK","message" => "File successfully extracted." ) ); - else - echo json_encode( array( "status" => "ERROR","message" => "File could not be extracted" ) ); - break; - default: - if( ! mkdir( $d['targetdir'] ) ) - echo json_encode( array( "status" => "ERROR","message" => "Could not create target directory" ) ); - else { - chdir( $d['targetdir'] ); - if( ! $this->unzip( "../" . $d["filename"] ) ) { - chdir( ".." ); - rmdir( $d['targetdir'] ); - echo json_encode( array( "status" => "ERROR","message" => "Could not extract file" ) ); - } - else { - chdir( ".." ); - echo json_encode( array( "status" => "OK","message" => "File successfully extracted" ) ); - } - } - break; - } - } + exit( 1 ); + } + if( ! isset( $d['targetdir'] ) || trim( $d['targetdir'] ) == "" ) + $d['targetdir'] = "./"; + if( ! $this->isPathValid( $d['targetdir'] ) ) { + echo json_encode( array( "status" => "ERROR","message" => "Target directory is not valid." ) ); + exit( 1 ); + } + if( ! is_dir( $d['targetdir'] ) && ! mkdir( $d['targetdir'], 0777, true ) ) { + echo json_encode( array( "status" => "ERROR","message" => "Could not create target directory." ) ); + exit( 1 ); + } + if( ! $this->unzip( $d['filename'], $d['targetdir'] ) ) { + echo json_encode( array( "status" => "ERROR","message" => "File could not be extracted" ) ); + } else { + echo json_encode( array( "status" => "OK","message" => "File successfully extracted." ) ); } } } @@ -703,15 +688,25 @@ class IFM { } private function isPathValid( $dir ) { - $rpDir = realpath( $dir ); - $rpConfig = realpath( IFMConfig::root_dir ); + /** + * This function is also used to check non-existent paths, but the PHP realpath function returns false for + * nonexistent paths. Hence we need to check the path manually in the following lines. + */ + $tmp_d = $dir; + $tmp_missing_parts = array(); + while( realpath( $tmp_d ) === false ) { + $tmp_i = pathinfo( $tmp_d ); + array_push( $tmp_missing_parts, $tmp_i['filename'] ); + $tmp_d = dirname( $tmp_d ); + } + $rpDir = $this->pathCombine( realpath( $tmp_d ), implode( "/", array_reverse( $tmp_missing_parts ) ) ); + $rpConfig = ( IFMConfig::root_dir == "" ) ? realpath( dirname( __FILE__ ) ) : 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 ) ) { + elseif( 0 === strpos( $rpDir, $rpConfig ) ) return true; - } else return false; } @@ -796,11 +791,11 @@ class IFM { } // unzip an archive - private function unzip( $file ) { + private function unzip( $file, $destination="./" ) { $zip = new ZipArchive; $res = $zip->open( $file ); if( $res === true ) { - $zip->extractTo( './' ); + $zip->extractTo( $destination ); $zip->close(); return true; } else {